{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","node_modules/imagesloaded/imagesloaded.js","node_modules/imagesloaded/node_modules/eventie/eventie.js","node_modules/imagesloaded/node_modules/wolfy87-eventemitter/EventEmitter.js","node_modules/lodash/index.js","node_modules/promise/index.js","node_modules/promise/lib/core.js","node_modules/promise/lib/done.js","node_modules/promise/lib/es6-extensions.js","node_modules/promise/lib/finally.js","node_modules/promise/lib/index.js","node_modules/promise/lib/node-extensions.js","node_modules/promise/lib/synchronous.js","node_modules/promise/node_modules/asap/browser-asap.js","node_modules/promise/node_modules/asap/browser-raw.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/BootBarnExpress/components/BootBarnExpressRefinementWizard.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/Lob/AddressAutocomplete/AddressAutocompleteDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/Lob/AddressVerification/AddressVerificationDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/ajax.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/alert.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/app.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bonus-products-view.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/AddToCartOptions.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/AddToCartOptionsStoreSearch.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/LocalDeliveryDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/LocationSearch.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/ProductLineItemHelper.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/ShopYourStoreDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/bopis/components/StoreSearch.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/captcha.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/compare-widget.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/CarouselVideo.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/CookieNotification.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/EmailForm.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/EmailSignup.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/GiftCardBalanceInquiryComponent.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/GiftCardBalanceInquiryDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/Globale.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/ImageGallery/SlickAndImgViewer2.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/ImageGallery/Swiper.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/LoadingIndicator.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/NavigationController.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/OrderStatusForm.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/Recaptcha.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/RecentlyViewedProducts.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/RelevantProductRecommendations.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/components/SameDayShippingCountdown.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/cookieprivacy.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/countdown.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/countries.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/dialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/findMoreStores.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/giftcard.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/giftcert.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/helpers/GiftCardBalanceInquiryHelper.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/helpers/RequestHelper.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/jquery-ext.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/lazyloadPageElements.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/login.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/loginDialog.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/minicart.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/page.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/Authentication/EmailAddressCapture.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/account.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/bootbarnexpress.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/bootfinder.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/cart.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/cart_echo.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/categorylanding.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/ApplePay.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/GiftCardPaymentPanel.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/LoyaltyCredit.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/PaymentVoucherPaymentPanel.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/RewardsCredit.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/address.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/billing.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/formPrepare.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/index.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/multiship.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/opcaddress.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/opcaddress_enhanced.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/opcpayment.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout/shipping.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/checkout_echo.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/compare.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/content.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/onepcheckout.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/onepcheckout_groups.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/orderconfirmation.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/addToCart.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/availability.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/image.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/index.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/productSet.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/requestGift.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/variant.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/product/video.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/registry.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/search.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/storefront.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/pages/storelocator.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/popup.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/product-tile.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/productRotate3d.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/progress.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/quantityStepper.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/quickview.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/rating.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/register.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/searchbar.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/searchplaceholder.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/size-refinements.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/slickSliderHelpers.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/sliders.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/storeinventory/cart.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/storeinventory/index.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/storeinventory/product.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/style-counts.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/tls.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/tooltip.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/util.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/validator.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/watermark.js","../../Temp/Cartridges/app_storefront_core/cartridge/js/wishlist.js","../../Temp/Cartridges/app_storefront_countryoutfitters/cartridge/js/ImageConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/data/StateToZipCodeMap.json","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/data/ZipCodeToStateMap.json","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/AddressVerification/AddressVerificationHelper.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/DataLayerConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/Geolocation/GeolocationHelper.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/ImageConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/RefinementConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/RegexPatterns.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/SiteConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/TemplateConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/ValidationConstants.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient.js","../../Temp/Cartridges/bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper.js","../../Temp/Cartridges/bootbarn_rsp/cartridge/js/ImageConstants.js","../../Temp/Cartridges/int_shoppay_sfra/cartridge/client/default/js/cart/initShopPayCart.js","../../Temp/Cartridges/int_shoppay_sfra/cartridge/client/default/js/helpers/shoppayHelper.js","../../Temp/Cartridges/int_svs/cartridge/scripts/GiftCardConstants.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1dA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC/jYA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzkBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3sFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1kCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACj/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/qBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClgDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACt4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3mBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACx4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClyEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3iBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;;ACAA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1sBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"app.js","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})","/*!\n * imagesLoaded v3.2.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( window, factory ) { 'use strict';\n  // universal module definition\n\n  /*global define: false, module: false, require: false */\n\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD\n    define( [\n      'eventEmitter/EventEmitter',\n      'eventie/eventie'\n    ], function( EventEmitter, eventie ) {\n      return factory( window, EventEmitter, eventie );\n    });\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory(\n      window,\n      require('wolfy87-eventemitter'),\n      require('eventie')\n    );\n  } else {\n    // browser global\n    window.imagesLoaded = factory(\n      window,\n      window.EventEmitter,\n      window.eventie\n    );\n  }\n\n})( window,\n\n// --------------------------  factory -------------------------- //\n\nfunction factory( window, EventEmitter, eventie ) {\n\n'use strict';\n\nvar $ = window.jQuery;\nvar console = window.console;\n\n// -------------------------- helpers -------------------------- //\n\n// extend objects\nfunction extend( a, b ) {\n  for ( var prop in b ) {\n    a[ prop ] = b[ prop ];\n  }\n  return a;\n}\n\nvar objToString = Object.prototype.toString;\nfunction isArray( obj ) {\n  return objToString.call( obj ) == '[object Array]';\n}\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n  var ary = [];\n  if ( isArray( obj ) ) {\n    // use object if already an array\n    ary = obj;\n  } else if ( typeof obj.length == 'number' ) {\n    // convert nodeList to array\n    for ( var i=0; i < obj.length; i++ ) {\n      ary.push( obj[i] );\n    }\n  } else {\n    // array of single index\n    ary.push( obj );\n  }\n  return ary;\n}\n\n  // -------------------------- imagesLoaded -------------------------- //\n\n  /**\n   * @param {Array, Element, NodeList, String} elem\n   * @param {Object or Function} options - if function, use as callback\n   * @param {Function} onAlways - callback function\n   */\n  function ImagesLoaded( elem, options, onAlways ) {\n    // coerce ImagesLoaded() without new, to be new ImagesLoaded()\n    if ( !( this instanceof ImagesLoaded ) ) {\n      return new ImagesLoaded( elem, options, onAlways );\n    }\n    // use elem as selector string\n    if ( typeof elem == 'string' ) {\n      elem = document.querySelectorAll( elem );\n    }\n\n    this.elements = makeArray( elem );\n    this.options = extend( {}, this.options );\n\n    if ( typeof options == 'function' ) {\n      onAlways = options;\n    } else {\n      extend( this.options, options );\n    }\n\n    if ( onAlways ) {\n      this.on( 'always', onAlways );\n    }\n\n    this.getImages();\n\n    if ( $ ) {\n      // add jQuery Deferred object\n      this.jqDeferred = new $.Deferred();\n    }\n\n    // HACK check async to allow time to bind listeners\n    var _this = this;\n    setTimeout( function() {\n      _this.check();\n    });\n  }\n\n  ImagesLoaded.prototype = new EventEmitter();\n\n  ImagesLoaded.prototype.options = {};\n\n  ImagesLoaded.prototype.getImages = function() {\n    this.images = [];\n\n    // filter & find items if we have an item selector\n    for ( var i=0; i < this.elements.length; i++ ) {\n      var elem = this.elements[i];\n      this.addElementImages( elem );\n    }\n  };\n\n  /**\n   * @param {Node} element\n   */\n  ImagesLoaded.prototype.addElementImages = function( elem ) {\n    // filter siblings\n    if ( elem.nodeName == 'IMG' ) {\n      this.addImage( elem );\n    }\n    // get background image on element\n    if ( this.options.background === true ) {\n      this.addElementBackgroundImages( elem );\n    }\n\n    // find children\n    // no non-element nodes, #143\n    var nodeType = elem.nodeType;\n    if ( !nodeType || !elementNodeTypes[ nodeType ] ) {\n      return;\n    }\n    var childImgs = elem.querySelectorAll('img');\n    // concat childElems to filterFound array\n    for ( var i=0; i < childImgs.length; i++ ) {\n      var img = childImgs[i];\n      this.addImage( img );\n    }\n\n    // get child background images\n    if ( typeof this.options.background == 'string' ) {\n      var children = elem.querySelectorAll( this.options.background );\n      for ( i=0; i < children.length; i++ ) {\n        var child = children[i];\n        this.addElementBackgroundImages( child );\n      }\n    }\n  };\n\n  var elementNodeTypes = {\n    1: true,\n    9: true,\n    11: true\n  };\n\n  ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n    var style = getStyle( elem );\n    // get url inside url(\"...\")\n    var reURL = /url\\(['\"]*([^'\"\\)]+)['\"]*\\)/gi;\n    var matches = reURL.exec( style.backgroundImage );\n    while ( matches !== null ) {\n      var url = matches && matches[1];\n      if ( url ) {\n        this.addBackground( url, elem );\n      }\n      matches = reURL.exec( style.backgroundImage );\n    }\n  };\n\n  // IE8\n  var getStyle = window.getComputedStyle || function( elem ) {\n    return elem.currentStyle;\n  };\n\n  /**\n   * @param {Image} img\n   */\n  ImagesLoaded.prototype.addImage = function( img ) {\n    var loadingImage = new LoadingImage( img );\n    this.images.push( loadingImage );\n  };\n\n  ImagesLoaded.prototype.addBackground = function( url, elem ) {\n    var background = new Background( url, elem );\n    this.images.push( background );\n  };\n\n  ImagesLoaded.prototype.check = function() {\n    var _this = this;\n    this.progressedCount = 0;\n    this.hasAnyBroken = false;\n    // complete if no images\n    if ( !this.images.length ) {\n      this.complete();\n      return;\n    }\n\n    function onProgress( image, elem, message ) {\n      // HACK - Chrome triggers event before object properties have changed. #83\n      setTimeout( function() {\n        _this.progress( image, elem, message );\n      });\n    }\n\n    for ( var i=0; i < this.images.length; i++ ) {\n      var loadingImage = this.images[i];\n      loadingImage.once( 'progress', onProgress );\n      loadingImage.check();\n    }\n  };\n\n  ImagesLoaded.prototype.progress = function( image, elem, message ) {\n    this.progressedCount++;\n    this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;\n    // progress event\n    this.emit( 'progress', this, image, elem );\n    if ( this.jqDeferred && this.jqDeferred.notify ) {\n      this.jqDeferred.notify( this, image );\n    }\n    // check if completed\n    if ( this.progressedCount == this.images.length ) {\n      this.complete();\n    }\n\n    if ( this.options.debug && console ) {\n      console.log( 'progress: ' + message, image, elem );\n    }\n  };\n\n  ImagesLoaded.prototype.complete = function() {\n    var eventName = this.hasAnyBroken ? 'fail' : 'done';\n    this.isComplete = true;\n    this.emit( eventName, this );\n    this.emit( 'always', this );\n    if ( this.jqDeferred ) {\n      var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';\n      this.jqDeferred[ jqMethod ]( this );\n    }\n  };\n\n  // --------------------------  -------------------------- //\n\n  function LoadingImage( img ) {\n    this.img = img;\n  }\n\n  LoadingImage.prototype = new EventEmitter();\n\n  LoadingImage.prototype.check = function() {\n    // If complete is true and browser supports natural sizes,\n    // try to check for image status manually.\n    var isComplete = this.getIsImageComplete();\n    if ( isComplete ) {\n      // report based on naturalWidth\n      this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n      return;\n    }\n\n    // If none of the checks above matched, simulate loading on detached element.\n    this.proxyImage = new Image();\n    eventie.bind( this.proxyImage, 'load', this );\n    eventie.bind( this.proxyImage, 'error', this );\n    // bind to image as well for Firefox. #191\n    eventie.bind( this.img, 'load', this );\n    eventie.bind( this.img, 'error', this );\n    this.proxyImage.src = this.img.src;\n  };\n\n  LoadingImage.prototype.getIsImageComplete = function() {\n    return this.img.complete && this.img.naturalWidth !== undefined;\n  };\n\n  LoadingImage.prototype.confirm = function( isLoaded, message ) {\n    this.isLoaded = isLoaded;\n    this.emit( 'progress', this, this.img, message );\n  };\n\n  // ----- events ----- //\n\n  // trigger specified handler for event type\n  LoadingImage.prototype.handleEvent = function( event ) {\n    var method = 'on' + event.type;\n    if ( this[ method ] ) {\n      this[ method ]( event );\n    }\n  };\n\n  LoadingImage.prototype.onload = function() {\n    this.confirm( true, 'onload' );\n    this.unbindEvents();\n  };\n\n  LoadingImage.prototype.onerror = function() {\n    this.confirm( false, 'onerror' );\n    this.unbindEvents();\n  };\n\n  LoadingImage.prototype.unbindEvents = function() {\n    eventie.unbind( this.proxyImage, 'load', this );\n    eventie.unbind( this.proxyImage, 'error', this );\n    eventie.unbind( this.img, 'load', this );\n    eventie.unbind( this.img, 'error', this );\n  };\n\n  // -------------------------- Background -------------------------- //\n\n  function Background( url, element ) {\n    this.url = url;\n    this.element = element;\n    this.img = new Image();\n  }\n\n  // inherit LoadingImage prototype\n  Background.prototype = new LoadingImage();\n\n  Background.prototype.check = function() {\n    eventie.bind( this.img, 'load', this );\n    eventie.bind( this.img, 'error', this );\n    this.img.src = this.url;\n    // check if image is already complete\n    var isComplete = this.getIsImageComplete();\n    if ( isComplete ) {\n      this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n      this.unbindEvents();\n    }\n  };\n\n  Background.prototype.unbindEvents = function() {\n    eventie.unbind( this.img, 'load', this );\n    eventie.unbind( this.img, 'error', this );\n  };\n\n  Background.prototype.confirm = function( isLoaded, message ) {\n    this.isLoaded = isLoaded;\n    this.emit( 'progress', this, this.element, message );\n  };\n\n  // -------------------------- jQuery -------------------------- //\n\n  ImagesLoaded.makeJQueryPlugin = function( jQuery ) {\n    jQuery = jQuery || window.jQuery;\n    if ( !jQuery ) {\n      return;\n    }\n    // set local variable\n    $ = jQuery;\n    // $().imagesLoaded()\n    $.fn.imagesLoaded = function( options, callback ) {\n      var instance = new ImagesLoaded( this, options, callback );\n      return instance.jqDeferred.promise( $(this) );\n    };\n  };\n  // try making plugin\n  ImagesLoaded.makeJQueryPlugin();\n\n  // --------------------------  -------------------------- //\n\n  return ImagesLoaded;\n\n});\n","/*!\n * eventie v1.0.6\n * event binding helper\n *   eventie.bind( elem, 'click', myFn )\n *   eventie.unbind( elem, 'click', myFn )\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true */\n/*global define: false, module: false */\n\n( function( window ) {\n\n'use strict';\n\nvar docElem = document.documentElement;\n\nvar bind = function() {};\n\nfunction getIEEvent( obj ) {\n  var event = window.event;\n  // add event.target\n  event.target = event.target || event.srcElement || obj;\n  return event;\n}\n\nif ( docElem.addEventListener ) {\n  bind = function( obj, type, fn ) {\n    obj.addEventListener( type, fn, false );\n  };\n} else if ( docElem.attachEvent ) {\n  bind = function( obj, type, fn ) {\n    obj[ type + fn ] = fn.handleEvent ?\n      function() {\n        var event = getIEEvent( obj );\n        fn.handleEvent.call( fn, event );\n      } :\n      function() {\n        var event = getIEEvent( obj );\n        fn.call( obj, event );\n      };\n    obj.attachEvent( \"on\" + type, obj[ type + fn ] );\n  };\n}\n\nvar unbind = function() {};\n\nif ( docElem.removeEventListener ) {\n  unbind = function( obj, type, fn ) {\n    obj.removeEventListener( type, fn, false );\n  };\n} else if ( docElem.detachEvent ) {\n  unbind = function( obj, type, fn ) {\n    obj.detachEvent( \"on\" + type, obj[ type + fn ] );\n    try {\n      delete obj[ type + fn ];\n    } catch ( err ) {\n      // can't delete window object properties\n      obj[ type + fn ] = undefined;\n    }\n  };\n}\n\nvar eventie = {\n  bind: bind,\n  unbind: unbind\n};\n\n// ----- module definition ----- //\n\nif ( typeof define === 'function' && define.amd ) {\n  // AMD\n  define( eventie );\n} else if ( typeof exports === 'object' ) {\n  // CommonJS\n  module.exports = eventie;\n} else {\n  // browser global\n  window.eventie = eventie;\n}\n\n})( window );\n","/*!\n * EventEmitter v4.2.11 - git.io/ee\n * Unlicense - http://unlicense.org/\n * Oliver Caldwell - http://oli.me.uk/\n * @preserve\n */\n\n;(function () {\n    'use strict';\n\n    /**\n     * Class for managing events.\n     * Can be extended to provide event functionality in other classes.\n     *\n     * @class EventEmitter Manages event registering and emitting.\n     */\n    function EventEmitter() {}\n\n    // Shortcuts to improve speed and size\n    var proto = EventEmitter.prototype;\n    var exports = this;\n    var originalGlobalValue = exports.EventEmitter;\n\n    /**\n     * Finds the index of the listener for the event in its storage array.\n     *\n     * @param {Function[]} listeners Array of listeners to search through.\n     * @param {Function} listener Method to look for.\n     * @return {Number} Index of the specified listener, -1 if not found\n     * @api private\n     */\n    function indexOfListener(listeners, listener) {\n        var i = listeners.length;\n        while (i--) {\n            if (listeners[i].listener === listener) {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n\n    /**\n     * Alias a method while keeping the context correct, to allow for overwriting of target method.\n     *\n     * @param {String} name The name of the target method.\n     * @return {Function} The aliased method\n     * @api private\n     */\n    function alias(name) {\n        return function aliasClosure() {\n            return this[name].apply(this, arguments);\n        };\n    }\n\n    /**\n     * Returns the listener array for the specified event.\n     * Will initialise the event object and listener arrays if required.\n     * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.\n     * Each property in the object response is an array of listener functions.\n     *\n     * @param {String|RegExp} evt Name of the event to return the listeners from.\n     * @return {Function[]|Object} All listener functions for the event.\n     */\n    proto.getListeners = function getListeners(evt) {\n        var events = this._getEvents();\n        var response;\n        var key;\n\n        // Return a concatenated array of all matching events if\n        // the selector is a regular expression.\n        if (evt instanceof RegExp) {\n            response = {};\n            for (key in events) {\n                if (events.hasOwnProperty(key) && evt.test(key)) {\n                    response[key] = events[key];\n                }\n            }\n        }\n        else {\n            response = events[evt] || (events[evt] = []);\n        }\n\n        return response;\n    };\n\n    /**\n     * Takes a list of listener objects and flattens it into a list of listener functions.\n     *\n     * @param {Object[]} listeners Raw listener objects.\n     * @return {Function[]} Just the listener functions.\n     */\n    proto.flattenListeners = function flattenListeners(listeners) {\n        var flatListeners = [];\n        var i;\n\n        for (i = 0; i < listeners.length; i += 1) {\n            flatListeners.push(listeners[i].listener);\n        }\n\n        return flatListeners;\n    };\n\n    /**\n     * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.\n     *\n     * @param {String|RegExp} evt Name of the event to return the listeners from.\n     * @return {Object} All listener functions for an event in an object.\n     */\n    proto.getListenersAsObject = function getListenersAsObject(evt) {\n        var listeners = this.getListeners(evt);\n        var response;\n\n        if (listeners instanceof Array) {\n            response = {};\n            response[evt] = listeners;\n        }\n\n        return response || listeners;\n    };\n\n    /**\n     * Adds a listener function to the specified event.\n     * The listener will not be added if it is a duplicate.\n     * If the listener returns true then it will be removed after it is called.\n     * If you pass a regular expression as the event name then the listener will be added to all events that match it.\n     *\n     * @param {String|RegExp} evt Name of the event to attach the listener to.\n     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.addListener = function addListener(evt, listener) {\n        var listeners = this.getListenersAsObject(evt);\n        var listenerIsWrapped = typeof listener === 'object';\n        var key;\n\n        for (key in listeners) {\n            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {\n                listeners[key].push(listenerIsWrapped ? listener : {\n                    listener: listener,\n                    once: false\n                });\n            }\n        }\n\n        return this;\n    };\n\n    /**\n     * Alias of addListener\n     */\n    proto.on = alias('addListener');\n\n    /**\n     * Semi-alias of addListener. It will add a listener that will be\n     * automatically removed after its first execution.\n     *\n     * @param {String|RegExp} evt Name of the event to attach the listener to.\n     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.addOnceListener = function addOnceListener(evt, listener) {\n        return this.addListener(evt, {\n            listener: listener,\n            once: true\n        });\n    };\n\n    /**\n     * Alias of addOnceListener.\n     */\n    proto.once = alias('addOnceListener');\n\n    /**\n     * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.\n     * You need to tell it what event names should be matched by a regex.\n     *\n     * @param {String} evt Name of the event to create.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.defineEvent = function defineEvent(evt) {\n        this.getListeners(evt);\n        return this;\n    };\n\n    /**\n     * Uses defineEvent to define multiple events.\n     *\n     * @param {String[]} evts An array of event names to define.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.defineEvents = function defineEvents(evts) {\n        for (var i = 0; i < evts.length; i += 1) {\n            this.defineEvent(evts[i]);\n        }\n        return this;\n    };\n\n    /**\n     * Removes a listener function from the specified event.\n     * When passed a regular expression as the event name, it will remove the listener from all events that match it.\n     *\n     * @param {String|RegExp} evt Name of the event to remove the listener from.\n     * @param {Function} listener Method to remove from the event.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.removeListener = function removeListener(evt, listener) {\n        var listeners = this.getListenersAsObject(evt);\n        var index;\n        var key;\n\n        for (key in listeners) {\n            if (listeners.hasOwnProperty(key)) {\n                index = indexOfListener(listeners[key], listener);\n\n                if (index !== -1) {\n                    listeners[key].splice(index, 1);\n                }\n            }\n        }\n\n        return this;\n    };\n\n    /**\n     * Alias of removeListener\n     */\n    proto.off = alias('removeListener');\n\n    /**\n     * Adds listeners in bulk using the manipulateListeners method.\n     * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.\n     * You can also pass it a regular expression to add the array of listeners to all events that match it.\n     * Yeah, this function does quite a bit. That's probably a bad thing.\n     *\n     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.\n     * @param {Function[]} [listeners] An optional array of listener functions to add.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.addListeners = function addListeners(evt, listeners) {\n        // Pass through to manipulateListeners\n        return this.manipulateListeners(false, evt, listeners);\n    };\n\n    /**\n     * Removes listeners in bulk using the manipulateListeners method.\n     * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n     * You can also pass it an event name and an array of listeners to be removed.\n     * You can also pass it a regular expression to remove the listeners from all events that match it.\n     *\n     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.\n     * @param {Function[]} [listeners] An optional array of listener functions to remove.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.removeListeners = function removeListeners(evt, listeners) {\n        // Pass through to manipulateListeners\n        return this.manipulateListeners(true, evt, listeners);\n    };\n\n    /**\n     * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.\n     * The first argument will determine if the listeners are removed (true) or added (false).\n     * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n     * You can also pass it an event name and an array of listeners to be added/removed.\n     * You can also pass it a regular expression to manipulate the listeners of all events that match it.\n     *\n     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.\n     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.\n     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {\n        var i;\n        var value;\n        var single = remove ? this.removeListener : this.addListener;\n        var multiple = remove ? this.removeListeners : this.addListeners;\n\n        // If evt is an object then pass each of its properties to this method\n        if (typeof evt === 'object' && !(evt instanceof RegExp)) {\n            for (i in evt) {\n                if (evt.hasOwnProperty(i) && (value = evt[i])) {\n                    // Pass the single listener straight through to the singular method\n                    if (typeof value === 'function') {\n                        single.call(this, i, value);\n                    }\n                    else {\n                        // Otherwise pass back to the multiple function\n                        multiple.call(this, i, value);\n                    }\n                }\n            }\n        }\n        else {\n            // So evt must be a string\n            // And listeners must be an array of listeners\n            // Loop over it and pass each one to the multiple method\n            i = listeners.length;\n            while (i--) {\n                single.call(this, evt, listeners[i]);\n            }\n        }\n\n        return this;\n    };\n\n    /**\n     * Removes all listeners from a specified event.\n     * If you do not specify an event then all listeners will be removed.\n     * That means every event will be emptied.\n     * You can also pass a regex to remove all events that match it.\n     *\n     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.removeEvent = function removeEvent(evt) {\n        var type = typeof evt;\n        var events = this._getEvents();\n        var key;\n\n        // Remove different things depending on the state of evt\n        if (type === 'string') {\n            // Remove all listeners for the specified event\n            delete events[evt];\n        }\n        else if (evt instanceof RegExp) {\n            // Remove all events matching the regex.\n            for (key in events) {\n                if (events.hasOwnProperty(key) && evt.test(key)) {\n                    delete events[key];\n                }\n            }\n        }\n        else {\n            // Remove all listeners in all events\n            delete this._events;\n        }\n\n        return this;\n    };\n\n    /**\n     * Alias of removeEvent.\n     *\n     * Added to mirror the node API.\n     */\n    proto.removeAllListeners = alias('removeEvent');\n\n    /**\n     * Emits an event of your choice.\n     * When emitted, every listener attached to that event will be executed.\n     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.\n     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.\n     * So they will not arrive within the array on the other side, they will be separate.\n     * You can also pass a regular expression to emit to all events that match it.\n     *\n     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n     * @param {Array} [args] Optional array of arguments to be passed to each listener.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.emitEvent = function emitEvent(evt, args) {\n        var listenersMap = this.getListenersAsObject(evt);\n        var listeners;\n        var listener;\n        var i;\n        var key;\n        var response;\n\n        for (key in listenersMap) {\n            if (listenersMap.hasOwnProperty(key)) {\n                listeners = listenersMap[key].slice(0);\n                i = listeners.length;\n\n                while (i--) {\n                    // If the listener returns true then it shall be removed from the event\n                    // The function is executed either with a basic call or an apply if there is an args array\n                    listener = listeners[i];\n\n                    if (listener.once === true) {\n                        this.removeListener(evt, listener.listener);\n                    }\n\n                    response = listener.listener.apply(this, args || []);\n\n                    if (response === this._getOnceReturnValue()) {\n                        this.removeListener(evt, listener.listener);\n                    }\n                }\n            }\n        }\n\n        return this;\n    };\n\n    /**\n     * Alias of emitEvent\n     */\n    proto.trigger = alias('emitEvent');\n\n    /**\n     * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.\n     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.\n     *\n     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n     * @param {...*} Optional additional arguments to be passed to each listener.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.emit = function emit(evt) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        return this.emitEvent(evt, args);\n    };\n\n    /**\n     * Sets the current value to check against when executing listeners. If a\n     * listeners return value matches the one set here then it will be removed\n     * after execution. This value defaults to true.\n     *\n     * @param {*} value The new value to check for when executing listeners.\n     * @return {Object} Current instance of EventEmitter for chaining.\n     */\n    proto.setOnceReturnValue = function setOnceReturnValue(value) {\n        this._onceReturnValue = value;\n        return this;\n    };\n\n    /**\n     * Fetches the current value to check against when executing listeners. If\n     * the listeners return value matches this one then it should be removed\n     * automatically. It will return true by default.\n     *\n     * @return {*|Boolean} The current value to check for or the default, true.\n     * @api private\n     */\n    proto._getOnceReturnValue = function _getOnceReturnValue() {\n        if (this.hasOwnProperty('_onceReturnValue')) {\n            return this._onceReturnValue;\n        }\n        else {\n            return true;\n        }\n    };\n\n    /**\n     * Fetches the events object and creates one if required.\n     *\n     * @return {Object} The events storage object.\n     * @api private\n     */\n    proto._getEvents = function _getEvents() {\n        return this._events || (this._events = {});\n    };\n\n    /**\n     * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.\n     *\n     * @return {Function} Non conflicting EventEmitter class.\n     */\n    EventEmitter.noConflict = function noConflict() {\n        exports.EventEmitter = originalGlobalValue;\n        return EventEmitter;\n    };\n\n    // Expose the class either via AMD, CommonJS or the global object\n    if (typeof define === 'function' && define.amd) {\n        define(function () {\n            return EventEmitter;\n        });\n    }\n    else if (typeof module === 'object' && module.exports){\n        module.exports = EventEmitter;\n    }\n    else {\n        exports.EventEmitter = EventEmitter;\n    }\n}.call(this));\n","/**\n * @license\n * lodash 3.10.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern -d -o ./index.js`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n;(function() {\n\n  /** Used as a safe reference for `undefined` in pre-ES5 environments. */\n  var undefined;\n\n  /** Used as the semantic version number. */\n  var VERSION = '3.10.1';\n\n  /** Used to compose bitmasks for wrapper metadata. */\n  var BIND_FLAG = 1,\n      BIND_KEY_FLAG = 2,\n      CURRY_BOUND_FLAG = 4,\n      CURRY_FLAG = 8,\n      CURRY_RIGHT_FLAG = 16,\n      PARTIAL_FLAG = 32,\n      PARTIAL_RIGHT_FLAG = 64,\n      ARY_FLAG = 128,\n      REARG_FLAG = 256;\n\n  /** Used as default options for `_.trunc`. */\n  var DEFAULT_TRUNC_LENGTH = 30,\n      DEFAULT_TRUNC_OMISSION = '...';\n\n  /** Used to detect when a function becomes hot. */\n  var HOT_COUNT = 150,\n      HOT_SPAN = 16;\n\n  /** Used as the size to enable large array optimizations. */\n  var LARGE_ARRAY_SIZE = 200;\n\n  /** Used to indicate the type of lazy iteratees. */\n  var LAZY_FILTER_FLAG = 1,\n      LAZY_MAP_FLAG = 2;\n\n  /** Used as the `TypeError` message for \"Functions\" methods. */\n  var FUNC_ERROR_TEXT = 'Expected a function';\n\n  /** Used as the internal argument placeholder. */\n  var PLACEHOLDER = '__lodash_placeholder__';\n\n  /** `Object#toString` result references. */\n  var argsTag = '[object Arguments]',\n      arrayTag = '[object Array]',\n      boolTag = '[object Boolean]',\n      dateTag = '[object Date]',\n      errorTag = '[object Error]',\n      funcTag = '[object Function]',\n      mapTag = '[object Map]',\n      numberTag = '[object Number]',\n      objectTag = '[object Object]',\n      regexpTag = '[object RegExp]',\n      setTag = '[object Set]',\n      stringTag = '[object String]',\n      weakMapTag = '[object WeakMap]';\n\n  var arrayBufferTag = '[object ArrayBuffer]',\n      float32Tag = '[object Float32Array]',\n      float64Tag = '[object Float64Array]',\n      int8Tag = '[object Int8Array]',\n      int16Tag = '[object Int16Array]',\n      int32Tag = '[object Int32Array]',\n      uint8Tag = '[object Uint8Array]',\n      uint8ClampedTag = '[object Uint8ClampedArray]',\n      uint16Tag = '[object Uint16Array]',\n      uint32Tag = '[object Uint32Array]';\n\n  /** Used to match empty string literals in compiled template source. */\n  var reEmptyStringLeading = /\\b__p \\+= '';/g,\n      reEmptyStringMiddle = /\\b(__p \\+=) '' \\+/g,\n      reEmptyStringTrailing = /(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g;\n\n  /** Used to match HTML entities and HTML characters. */\n  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,\n      reUnescapedHtml = /[&<>\"'`]/g,\n      reHasEscapedHtml = RegExp(reEscapedHtml.source),\n      reHasUnescapedHtml = RegExp(reUnescapedHtml.source);\n\n  /** Used to match template delimiters. */\n  var reEscape = /<%-([\\s\\S]+?)%>/g,\n      reEvaluate = /<%([\\s\\S]+?)%>/g,\n      reInterpolate = /<%=([\\s\\S]+?)%>/g;\n\n  /** Used to match property names within property paths. */\n  var reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?\\1)\\]/,\n      reIsPlainProp = /^\\w*$/,\n      rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g;\n\n  /**\n   * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns)\n   * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern).\n   */\n  var reRegExpChars = /^[:!,]|[\\\\^$.*+?()[\\]{}|\\/]|(^[0-9a-fA-Fnrtuvx])|([\\n\\r\\u2028\\u2029])/g,\n      reHasRegExpChars = RegExp(reRegExpChars.source);\n\n  /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */\n  var reComboMark = /[\\u0300-\\u036f\\ufe20-\\ufe23]/g;\n\n  /** Used to match backslashes in property paths. */\n  var reEscapeChar = /\\\\(\\\\)?/g;\n\n  /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */\n  var reEsTemplate = /\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g;\n\n  /** Used to match `RegExp` flags from their coerced string values. */\n  var reFlags = /\\w*$/;\n\n  /** Used to detect hexadecimal string values. */\n  var reHasHexPrefix = /^0[xX]/;\n\n  /** Used to detect host constructors (Safari > 5). */\n  var reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n  /** Used to detect unsigned integer values. */\n  var reIsUint = /^\\d+$/;\n\n  /** Used to match latin-1 supplementary letters (excluding mathematical operators). */\n  var reLatin1 = /[\\xc0-\\xd6\\xd8-\\xde\\xdf-\\xf6\\xf8-\\xff]/g;\n\n  /** Used to ensure capturing order of template delimiters. */\n  var reNoMatch = /($^)/;\n\n  /** Used to match unescaped characters in compiled string literals. */\n  var reUnescapedString = /['\\n\\r\\u2028\\u2029\\\\]/g;\n\n  /** Used to match words to create compound words. */\n  var reWords = (function() {\n    var upper = '[A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde]',\n        lower = '[a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff]+';\n\n    return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');\n  }());\n\n  /** Used to assign default `context` object properties. */\n  var contextProps = [\n    'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',\n    'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',\n    'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite',\n    'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',\n    'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap'\n  ];\n\n  /** Used to make template sourceURLs easier to identify. */\n  var templateCounter = -1;\n\n  /** Used to identify `toStringTag` values of typed arrays. */\n  var typedArrayTags = {};\n  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\n  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\n  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\n  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\n  typedArrayTags[uint32Tag] = true;\n  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =\n  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\n  typedArrayTags[dateTag] = typedArrayTags[errorTag] =\n  typedArrayTags[funcTag] = typedArrayTags[mapTag] =\n  typedArrayTags[numberTag] = typedArrayTags[objectTag] =\n  typedArrayTags[regexpTag] = typedArrayTags[setTag] =\n  typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;\n\n  /** Used to identify `toStringTag` values supported by `_.clone`. */\n  var cloneableTags = {};\n  cloneableTags[argsTag] = cloneableTags[arrayTag] =\n  cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =\n  cloneableTags[dateTag] = cloneableTags[float32Tag] =\n  cloneableTags[float64Tag] = cloneableTags[int8Tag] =\n  cloneableTags[int16Tag] = cloneableTags[int32Tag] =\n  cloneableTags[numberTag] = cloneableTags[objectTag] =\n  cloneableTags[regexpTag] = cloneableTags[stringTag] =\n  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\n  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\n  cloneableTags[errorTag] = cloneableTags[funcTag] =\n  cloneableTags[mapTag] = cloneableTags[setTag] =\n  cloneableTags[weakMapTag] = false;\n\n  /** Used to map latin-1 supplementary letters to basic latin letters. */\n  var deburredLetters = {\n    '\\xc0': 'A',  '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n    '\\xe0': 'a',  '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n    '\\xc7': 'C',  '\\xe7': 'c',\n    '\\xd0': 'D',  '\\xf0': 'd',\n    '\\xc8': 'E',  '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n    '\\xe8': 'e',  '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n    '\\xcC': 'I',  '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n    '\\xeC': 'i',  '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n    '\\xd1': 'N',  '\\xf1': 'n',\n    '\\xd2': 'O',  '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n    '\\xf2': 'o',  '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n    '\\xd9': 'U',  '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n    '\\xf9': 'u',  '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n    '\\xdd': 'Y',  '\\xfd': 'y', '\\xff': 'y',\n    '\\xc6': 'Ae', '\\xe6': 'ae',\n    '\\xde': 'Th', '\\xfe': 'th',\n    '\\xdf': 'ss'\n  };\n\n  /** Used to map characters to HTML entities. */\n  var htmlEscapes = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#39;',\n    '`': '&#96;'\n  };\n\n  /** Used to map HTML entities to characters. */\n  var htmlUnescapes = {\n    '&amp;': '&',\n    '&lt;': '<',\n    '&gt;': '>',\n    '&quot;': '\"',\n    '&#39;': \"'\",\n    '&#96;': '`'\n  };\n\n  /** Used to determine if values are of the language type `Object`. */\n  var objectTypes = {\n    'function': true,\n    'object': true\n  };\n\n  /** Used to escape characters for inclusion in compiled regexes. */\n  var regexpEscapes = {\n    '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34',\n    '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39',\n    'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46',\n    'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66',\n    'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78'\n  };\n\n  /** Used to escape characters for inclusion in compiled string literals. */\n  var stringEscapes = {\n    '\\\\': '\\\\',\n    \"'\": \"'\",\n    '\\n': 'n',\n    '\\r': 'r',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  /** Detect free variable `exports`. */\n  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;\n\n  /** Detect free variable `module`. */\n  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;\n\n  /** Detect free variable `global` from Node.js. */\n  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;\n\n  /** Detect free variable `self`. */\n  var freeSelf = objectTypes[typeof self] && self && self.Object && self;\n\n  /** Detect free variable `window`. */\n  var freeWindow = objectTypes[typeof window] && window && window.Object && window;\n\n  /** Detect the popular CommonJS extension `module.exports`. */\n  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;\n\n  /**\n   * Used as a reference to the global object.\n   *\n   * The `this` value is used if it's the global object to avoid Greasemonkey's\n   * restricted `window` object, otherwise the `window` object is used.\n   */\n  var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * The base implementation of `compareAscending` which compares values and\n   * sorts them in ascending order without guaranteeing a stable sort.\n   *\n   * @private\n   * @param {*} value The value to compare.\n   * @param {*} other The other value to compare.\n   * @returns {number} Returns the sort order indicator for `value`.\n   */\n  function baseCompareAscending(value, other) {\n    if (value !== other) {\n      var valIsNull = value === null,\n          valIsUndef = value === undefined,\n          valIsReflexive = value === value;\n\n      var othIsNull = other === null,\n          othIsUndef = other === undefined,\n          othIsReflexive = other === other;\n\n      if ((value > other && !othIsNull) || !valIsReflexive ||\n          (valIsNull && !othIsUndef && othIsReflexive) ||\n          (valIsUndef && othIsReflexive)) {\n        return 1;\n      }\n      if ((value < other && !valIsNull) || !othIsReflexive ||\n          (othIsNull && !valIsUndef && valIsReflexive) ||\n          (othIsUndef && valIsReflexive)) {\n        return -1;\n      }\n    }\n    return 0;\n  }\n\n  /**\n   * The base implementation of `_.findIndex` and `_.findLastIndex` without\n   * support for callback shorthands and `this` binding.\n   *\n   * @private\n   * @param {Array} array The array to search.\n   * @param {Function} predicate The function invoked per iteration.\n   * @param {boolean} [fromRight] Specify iterating from right to left.\n   * @returns {number} Returns the index of the matched value, else `-1`.\n   */\n  function baseFindIndex(array, predicate, fromRight) {\n    var length = array.length,\n        index = fromRight ? length : -1;\n\n    while ((fromRight ? index-- : ++index < length)) {\n      if (predicate(array[index], index, array)) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  /**\n   * The base implementation of `_.indexOf` without support for binary searches.\n   *\n   * @private\n   * @param {Array} array The array to search.\n   * @param {*} value The value to search for.\n   * @param {number} fromIndex The index to search from.\n   * @returns {number} Returns the index of the matched value, else `-1`.\n   */\n  function baseIndexOf(array, value, fromIndex) {\n    if (value !== value) {\n      return indexOfNaN(array, fromIndex);\n    }\n    var index = fromIndex - 1,\n        length = array.length;\n\n    while (++index < length) {\n      if (array[index] === value) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  /**\n   * The base implementation of `_.isFunction` without support for environments\n   * with incorrect `typeof` results.\n   *\n   * @private\n   * @param {*} value The value to check.\n   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n   */\n  function baseIsFunction(value) {\n    // Avoid a Chakra JIT bug in compatibility modes of IE 11.\n    // See https://github.com/jashkenas/underscore/issues/1621 for more details.\n    return typeof value == 'function' || false;\n  }\n\n  /**\n   * Converts `value` to a string if it's not one. An empty string is returned\n   * for `null` or `undefined` values.\n   *\n   * @private\n   * @param {*} value The value to process.\n   * @returns {string} Returns the string.\n   */\n  function baseToString(value) {\n    return value == null ? '' : (value + '');\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimLeft` to get the index of the first character\n   * of `string` that is not found in `chars`.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @param {string} chars The characters to find.\n   * @returns {number} Returns the index of the first character not found in `chars`.\n   */\n  function charsLeftIndex(string, chars) {\n    var index = -1,\n        length = string.length;\n\n    while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}\n    return index;\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimRight` to get the index of the last character\n   * of `string` that is not found in `chars`.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @param {string} chars The characters to find.\n   * @returns {number} Returns the index of the last character not found in `chars`.\n   */\n  function charsRightIndex(string, chars) {\n    var index = string.length;\n\n    while (index-- && chars.indexOf(string.charAt(index)) > -1) {}\n    return index;\n  }\n\n  /**\n   * Used by `_.sortBy` to compare transformed elements of a collection and stable\n   * sort them in ascending order.\n   *\n   * @private\n   * @param {Object} object The object to compare.\n   * @param {Object} other The other object to compare.\n   * @returns {number} Returns the sort order indicator for `object`.\n   */\n  function compareAscending(object, other) {\n    return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);\n  }\n\n  /**\n   * Used by `_.sortByOrder` to compare multiple properties of a value to another\n   * and stable sort them.\n   *\n   * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise,\n   * a value is sorted in ascending order if its corresponding order is \"asc\", and\n   * descending if \"desc\".\n   *\n   * @private\n   * @param {Object} object The object to compare.\n   * @param {Object} other The other object to compare.\n   * @param {boolean[]} orders The order to sort by for each property.\n   * @returns {number} Returns the sort order indicator for `object`.\n   */\n  function compareMultiple(object, other, orders) {\n    var index = -1,\n        objCriteria = object.criteria,\n        othCriteria = other.criteria,\n        length = objCriteria.length,\n        ordersLength = orders.length;\n\n    while (++index < length) {\n      var result = baseCompareAscending(objCriteria[index], othCriteria[index]);\n      if (result) {\n        if (index >= ordersLength) {\n          return result;\n        }\n        var order = orders[index];\n        return result * ((order === 'asc' || order === true) ? 1 : -1);\n      }\n    }\n    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n    // that causes it, under certain circumstances, to provide the same value for\n    // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n    // for more details.\n    //\n    // This also ensures a stable sort in V8 and other engines.\n    // See https://code.google.com/p/v8/issues/detail?id=90 for more details.\n    return object.index - other.index;\n  }\n\n  /**\n   * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.\n   *\n   * @private\n   * @param {string} letter The matched letter to deburr.\n   * @returns {string} Returns the deburred letter.\n   */\n  function deburrLetter(letter) {\n    return deburredLetters[letter];\n  }\n\n  /**\n   * Used by `_.escape` to convert characters to HTML entities.\n   *\n   * @private\n   * @param {string} chr The matched character to escape.\n   * @returns {string} Returns the escaped character.\n   */\n  function escapeHtmlChar(chr) {\n    return htmlEscapes[chr];\n  }\n\n  /**\n   * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes.\n   *\n   * @private\n   * @param {string} chr The matched character to escape.\n   * @param {string} leadingChar The capture group for a leading character.\n   * @param {string} whitespaceChar The capture group for a whitespace character.\n   * @returns {string} Returns the escaped character.\n   */\n  function escapeRegExpChar(chr, leadingChar, whitespaceChar) {\n    if (leadingChar) {\n      chr = regexpEscapes[chr];\n    } else if (whitespaceChar) {\n      chr = stringEscapes[chr];\n    }\n    return '\\\\' + chr;\n  }\n\n  /**\n   * Used by `_.template` to escape characters for inclusion in compiled string literals.\n   *\n   * @private\n   * @param {string} chr The matched character to escape.\n   * @returns {string} Returns the escaped character.\n   */\n  function escapeStringChar(chr) {\n    return '\\\\' + stringEscapes[chr];\n  }\n\n  /**\n   * Gets the index at which the first occurrence of `NaN` is found in `array`.\n   *\n   * @private\n   * @param {Array} array The array to search.\n   * @param {number} fromIndex The index to search from.\n   * @param {boolean} [fromRight] Specify iterating from right to left.\n   * @returns {number} Returns the index of the matched `NaN`, else `-1`.\n   */\n  function indexOfNaN(array, fromIndex, fromRight) {\n    var length = array.length,\n        index = fromIndex + (fromRight ? 0 : -1);\n\n    while ((fromRight ? index-- : ++index < length)) {\n      var other = array[index];\n      if (other !== other) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  /**\n   * Checks if `value` is object-like.\n   *\n   * @private\n   * @param {*} value The value to check.\n   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n   */\n  function isObjectLike(value) {\n    return !!value && typeof value == 'object';\n  }\n\n  /**\n   * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a\n   * character code is whitespace.\n   *\n   * @private\n   * @param {number} charCode The character code to inspect.\n   * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.\n   */\n  function isSpace(charCode) {\n    return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||\n      (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));\n  }\n\n  /**\n   * Replaces all `placeholder` elements in `array` with an internal placeholder\n   * and returns an array of their indexes.\n   *\n   * @private\n   * @param {Array} array The array to modify.\n   * @param {*} placeholder The placeholder to replace.\n   * @returns {Array} Returns the new array of placeholder indexes.\n   */\n  function replaceHolders(array, placeholder) {\n    var index = -1,\n        length = array.length,\n        resIndex = -1,\n        result = [];\n\n    while (++index < length) {\n      if (array[index] === placeholder) {\n        array[index] = PLACEHOLDER;\n        result[++resIndex] = index;\n      }\n    }\n    return result;\n  }\n\n  /**\n   * An implementation of `_.uniq` optimized for sorted arrays without support\n   * for callback shorthands and `this` binding.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\n   * @param {Function} [iteratee] The function invoked per iteration.\n   * @returns {Array} Returns the new duplicate-value-free array.\n   */\n  function sortedUniq(array, iteratee) {\n    var seen,\n        index = -1,\n        length = array.length,\n        resIndex = -1,\n        result = [];\n\n    while (++index < length) {\n      var value = array[index],\n          computed = iteratee ? iteratee(value, index, array) : value;\n\n      if (!index || seen !== computed) {\n        seen = computed;\n        result[++resIndex] = value;\n      }\n    }\n    return result;\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace\n   * character of `string`.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @returns {number} Returns the index of the first non-whitespace character.\n   */\n  function trimmedLeftIndex(string) {\n    var index = -1,\n        length = string.length;\n\n    while (++index < length && isSpace(string.charCodeAt(index))) {}\n    return index;\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace\n   * character of `string`.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @returns {number} Returns the index of the last non-whitespace character.\n   */\n  function trimmedRightIndex(string) {\n    var index = string.length;\n\n    while (index-- && isSpace(string.charCodeAt(index))) {}\n    return index;\n  }\n\n  /**\n   * Used by `_.unescape` to convert HTML entities to characters.\n   *\n   * @private\n   * @param {string} chr The matched character to unescape.\n   * @returns {string} Returns the unescaped character.\n   */\n  function unescapeHtmlChar(chr) {\n    return htmlUnescapes[chr];\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Create a new pristine `lodash` function using the given `context` object.\n   *\n   * @static\n   * @memberOf _\n   * @category Utility\n   * @param {Object} [context=root] The context object.\n   * @returns {Function} Returns a new `lodash` function.\n   * @example\n   *\n   * _.mixin({ 'foo': _.constant('foo') });\n   *\n   * var lodash = _.runInContext();\n   * lodash.mixin({ 'bar': lodash.constant('bar') });\n   *\n   * _.isFunction(_.foo);\n   * // => true\n   * _.isFunction(_.bar);\n   * // => false\n   *\n   * lodash.isFunction(lodash.foo);\n   * // => false\n   * lodash.isFunction(lodash.bar);\n   * // => true\n   *\n   * // using `context` to mock `Date#getTime` use in `_.now`\n   * var mock = _.runInContext({\n   *   'Date': function() {\n   *     return { 'getTime': getTimeMock };\n   *   }\n   * });\n   *\n   * // or creating a suped-up `defer` in Node.js\n   * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;\n   */\n  function runInContext(context) {\n    // Avoid issues with some ES3 environments that attempt to use values, named\n    // after built-in constructors like `Object`, for the creation of literals.\n    // ES5 clears this up by stating that literals must use built-in constructors.\n    // See https://es5.github.io/#x11.1.5 for more details.\n    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;\n\n    /** Native constructor references. */\n    var Array = context.Array,\n        Date = context.Date,\n        Error = context.Error,\n        Function = context.Function,\n        Math = context.Math,\n        Number = context.Number,\n        Object = context.Object,\n        RegExp = context.RegExp,\n        String = context.String,\n        TypeError = context.TypeError;\n\n    /** Used for native method references. */\n    var arrayProto = Array.prototype,\n        objectProto = Object.prototype,\n        stringProto = String.prototype;\n\n    /** Used to resolve the decompiled source of functions. */\n    var fnToString = Function.prototype.toString;\n\n    /** Used to check objects for own properties. */\n    var hasOwnProperty = objectProto.hasOwnProperty;\n\n    /** Used to generate unique IDs. */\n    var idCounter = 0;\n\n    /**\n     * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n     * of values.\n     */\n    var objToString = objectProto.toString;\n\n    /** Used to restore the original `_` reference in `_.noConflict`. */\n    var oldDash = root._;\n\n    /** Used to detect if a method is native. */\n    var reIsNative = RegExp('^' +\n      fnToString.call(hasOwnProperty).replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&')\n      .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n    );\n\n    /** Native method references. */\n    var ArrayBuffer = context.ArrayBuffer,\n        clearTimeout = context.clearTimeout,\n        parseFloat = context.parseFloat,\n        pow = Math.pow,\n        propertyIsEnumerable = objectProto.propertyIsEnumerable,\n        Set = getNative(context, 'Set'),\n        setTimeout = context.setTimeout,\n        splice = arrayProto.splice,\n        Uint8Array = context.Uint8Array,\n        WeakMap = getNative(context, 'WeakMap');\n\n    /* Native method references for those with the same name as other `lodash` methods. */\n    var nativeCeil = Math.ceil,\n        nativeCreate = getNative(Object, 'create'),\n        nativeFloor = Math.floor,\n        nativeIsArray = getNative(Array, 'isArray'),\n        nativeIsFinite = context.isFinite,\n        nativeKeys = getNative(Object, 'keys'),\n        nativeMax = Math.max,\n        nativeMin = Math.min,\n        nativeNow = getNative(Date, 'now'),\n        nativeParseInt = context.parseInt,\n        nativeRandom = Math.random;\n\n    /** Used as references for `-Infinity` and `Infinity`. */\n    var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,\n        POSITIVE_INFINITY = Number.POSITIVE_INFINITY;\n\n    /** Used as references for the maximum length and index of an array. */\n    var MAX_ARRAY_LENGTH = 4294967295,\n        MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,\n        HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;\n\n    /**\n     * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n     * of an array-like value.\n     */\n    var MAX_SAFE_INTEGER = 9007199254740991;\n\n    /** Used to store function metadata. */\n    var metaMap = WeakMap && new WeakMap;\n\n    /** Used to lookup unminified function names. */\n    var realNames = {};\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a `lodash` object which wraps `value` to enable implicit chaining.\n     * Methods that operate on and return arrays, collections, and functions can\n     * be chained together. Methods that retrieve a single value or may return a\n     * primitive value will automatically end the chain returning the unwrapped\n     * value. Explicit chaining may be enabled using `_.chain`. The execution of\n     * chained methods is lazy, that is, execution is deferred until `_#value`\n     * is implicitly or explicitly called.\n     *\n     * Lazy evaluation allows several methods to support shortcut fusion. Shortcut\n     * fusion is an optimization strategy which merge iteratee calls; this can help\n     * to avoid the creation of intermediate data structures and greatly reduce the\n     * number of iteratee executions.\n     *\n     * Chaining is supported in custom builds as long as the `_#value` method is\n     * directly or indirectly included in the build.\n     *\n     * In addition to lodash methods, wrappers have `Array` and `String` methods.\n     *\n     * The wrapper `Array` methods are:\n     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,\n     * `splice`, and `unshift`\n     *\n     * The wrapper `String` methods are:\n     * `replace` and `split`\n     *\n     * The wrapper methods that support shortcut fusion are:\n     * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,\n     * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,\n     * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,\n     * and `where`\n     *\n     * The chainable wrapper methods are:\n     * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,\n     * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,\n     * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`,\n     * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`,\n     * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`,\n     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,\n     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,\n     * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`,\n     * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`,\n     * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,\n     * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,\n     * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`,\n     * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`,\n     * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`,\n     * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`,\n     * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`,\n     * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`\n     *\n     * The wrapper methods that are **not** chainable by default are:\n     * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`,\n     * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`,\n     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`,\n     * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`,\n     * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,\n     * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`,\n     * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`,\n     * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`,\n     * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`,\n     * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`,\n     * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`,\n     * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`,\n     * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`,\n     * `unescape`, `uniqueId`, `value`, and `words`\n     *\n     * The wrapper method `sample` will return a wrapped value when `n` is provided,\n     * otherwise an unwrapped value is returned.\n     *\n     * @name _\n     * @constructor\n     * @category Chain\n     * @param {*} value The value to wrap in a `lodash` instance.\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var wrapped = _([1, 2, 3]);\n     *\n     * // returns an unwrapped value\n     * wrapped.reduce(function(total, n) {\n     *   return total + n;\n     * });\n     * // => 6\n     *\n     * // returns a wrapped value\n     * var squares = wrapped.map(function(n) {\n     *   return n * n;\n     * });\n     *\n     * _.isArray(squares);\n     * // => false\n     *\n     * _.isArray(squares.value());\n     * // => true\n     */\n    function lodash(value) {\n      if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {\n        if (value instanceof LodashWrapper) {\n          return value;\n        }\n        if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {\n          return wrapperClone(value);\n        }\n      }\n      return new LodashWrapper(value);\n    }\n\n    /**\n     * The function whose prototype all chaining wrappers inherit from.\n     *\n     * @private\n     */\n    function baseLodash() {\n      // No operation performed.\n    }\n\n    /**\n     * The base constructor for creating `lodash` wrapper objects.\n     *\n     * @private\n     * @param {*} value The value to wrap.\n     * @param {boolean} [chainAll] Enable chaining for all wrapper methods.\n     * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.\n     */\n    function LodashWrapper(value, chainAll, actions) {\n      this.__wrapped__ = value;\n      this.__actions__ = actions || [];\n      this.__chain__ = !!chainAll;\n    }\n\n    /**\n     * An object environment feature flags.\n     *\n     * @static\n     * @memberOf _\n     * @type Object\n     */\n    var support = lodash.support = {};\n\n    /**\n     * By default, the template delimiters used by lodash are like those in\n     * embedded Ruby (ERB). Change the following template settings to use\n     * alternative delimiters.\n     *\n     * @static\n     * @memberOf _\n     * @type Object\n     */\n    lodash.templateSettings = {\n\n      /**\n       * Used to detect `data` property values to be HTML-escaped.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'escape': reEscape,\n\n      /**\n       * Used to detect code to be evaluated.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'evaluate': reEvaluate,\n\n      /**\n       * Used to detect `data` property values to inject.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'interpolate': reInterpolate,\n\n      /**\n       * Used to reference the data object in the template text.\n       *\n       * @memberOf _.templateSettings\n       * @type string\n       */\n      'variable': '',\n\n      /**\n       * Used to import variables into the compiled template.\n       *\n       * @memberOf _.templateSettings\n       * @type Object\n       */\n      'imports': {\n\n        /**\n         * A reference to the `lodash` function.\n         *\n         * @memberOf _.templateSettings.imports\n         * @type Function\n         */\n        '_': lodash\n      }\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.\n     *\n     * @private\n     * @param {*} value The value to wrap.\n     */\n    function LazyWrapper(value) {\n      this.__wrapped__ = value;\n      this.__actions__ = [];\n      this.__dir__ = 1;\n      this.__filtered__ = false;\n      this.__iteratees__ = [];\n      this.__takeCount__ = POSITIVE_INFINITY;\n      this.__views__ = [];\n    }\n\n    /**\n     * Creates a clone of the lazy wrapper object.\n     *\n     * @private\n     * @name clone\n     * @memberOf LazyWrapper\n     * @returns {Object} Returns the cloned `LazyWrapper` object.\n     */\n    function lazyClone() {\n      var result = new LazyWrapper(this.__wrapped__);\n      result.__actions__ = arrayCopy(this.__actions__);\n      result.__dir__ = this.__dir__;\n      result.__filtered__ = this.__filtered__;\n      result.__iteratees__ = arrayCopy(this.__iteratees__);\n      result.__takeCount__ = this.__takeCount__;\n      result.__views__ = arrayCopy(this.__views__);\n      return result;\n    }\n\n    /**\n     * Reverses the direction of lazy iteration.\n     *\n     * @private\n     * @name reverse\n     * @memberOf LazyWrapper\n     * @returns {Object} Returns the new reversed `LazyWrapper` object.\n     */\n    function lazyReverse() {\n      if (this.__filtered__) {\n        var result = new LazyWrapper(this);\n        result.__dir__ = -1;\n        result.__filtered__ = true;\n      } else {\n        result = this.clone();\n        result.__dir__ *= -1;\n      }\n      return result;\n    }\n\n    /**\n     * Extracts the unwrapped value from its lazy wrapper.\n     *\n     * @private\n     * @name value\n     * @memberOf LazyWrapper\n     * @returns {*} Returns the unwrapped value.\n     */\n    function lazyValue() {\n      var array = this.__wrapped__.value(),\n          dir = this.__dir__,\n          isArr = isArray(array),\n          isRight = dir < 0,\n          arrLength = isArr ? array.length : 0,\n          view = getView(0, arrLength, this.__views__),\n          start = view.start,\n          end = view.end,\n          length = end - start,\n          index = isRight ? end : (start - 1),\n          iteratees = this.__iteratees__,\n          iterLength = iteratees.length,\n          resIndex = 0,\n          takeCount = nativeMin(length, this.__takeCount__);\n\n      if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) {\n        return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__);\n      }\n      var result = [];\n\n      outer:\n      while (length-- && resIndex < takeCount) {\n        index += dir;\n\n        var iterIndex = -1,\n            value = array[index];\n\n        while (++iterIndex < iterLength) {\n          var data = iteratees[iterIndex],\n              iteratee = data.iteratee,\n              type = data.type,\n              computed = iteratee(value);\n\n          if (type == LAZY_MAP_FLAG) {\n            value = computed;\n          } else if (!computed) {\n            if (type == LAZY_FILTER_FLAG) {\n              continue outer;\n            } else {\n              break outer;\n            }\n          }\n        }\n        result[resIndex++] = value;\n      }\n      return result;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a cache object to store key/value pairs.\n     *\n     * @private\n     * @static\n     * @name Cache\n     * @memberOf _.memoize\n     */\n    function MapCache() {\n      this.__data__ = {};\n    }\n\n    /**\n     * Removes `key` and its value from the cache.\n     *\n     * @private\n     * @name delete\n     * @memberOf _.memoize.Cache\n     * @param {string} key The key of the value to remove.\n     * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.\n     */\n    function mapDelete(key) {\n      return this.has(key) && delete this.__data__[key];\n    }\n\n    /**\n     * Gets the cached value for `key`.\n     *\n     * @private\n     * @name get\n     * @memberOf _.memoize.Cache\n     * @param {string} key The key of the value to get.\n     * @returns {*} Returns the cached value.\n     */\n    function mapGet(key) {\n      return key == '__proto__' ? undefined : this.__data__[key];\n    }\n\n    /**\n     * Checks if a cached value for `key` exists.\n     *\n     * @private\n     * @name has\n     * @memberOf _.memoize.Cache\n     * @param {string} key The key of the entry to check.\n     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n     */\n    function mapHas(key) {\n      return key != '__proto__' && hasOwnProperty.call(this.__data__, key);\n    }\n\n    /**\n     * Sets `value` to `key` of the cache.\n     *\n     * @private\n     * @name set\n     * @memberOf _.memoize.Cache\n     * @param {string} key The key of the value to cache.\n     * @param {*} value The value to cache.\n     * @returns {Object} Returns the cache object.\n     */\n    function mapSet(key, value) {\n      if (key != '__proto__') {\n        this.__data__[key] = value;\n      }\n      return this;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     *\n     * Creates a cache object to store unique values.\n     *\n     * @private\n     * @param {Array} [values] The values to cache.\n     */\n    function SetCache(values) {\n      var length = values ? values.length : 0;\n\n      this.data = { 'hash': nativeCreate(null), 'set': new Set };\n      while (length--) {\n        this.push(values[length]);\n      }\n    }\n\n    /**\n     * Checks if `value` is in `cache` mimicking the return signature of\n     * `_.indexOf` by returning `0` if the value is found, else `-1`.\n     *\n     * @private\n     * @param {Object} cache The cache to search.\n     * @param {*} value The value to search for.\n     * @returns {number} Returns `0` if `value` is found, else `-1`.\n     */\n    function cacheIndexOf(cache, value) {\n      var data = cache.data,\n          result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];\n\n      return result ? 0 : -1;\n    }\n\n    /**\n     * Adds `value` to the cache.\n     *\n     * @private\n     * @name push\n     * @memberOf SetCache\n     * @param {*} value The value to cache.\n     */\n    function cachePush(value) {\n      var data = this.data;\n      if (typeof value == 'string' || isObject(value)) {\n        data.set.add(value);\n      } else {\n        data.hash[value] = true;\n      }\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a new array joining `array` with `other`.\n     *\n     * @private\n     * @param {Array} array The array to join.\n     * @param {Array} other The other array to join.\n     * @returns {Array} Returns the new concatenated array.\n     */\n    function arrayConcat(array, other) {\n      var index = -1,\n          length = array.length,\n          othIndex = -1,\n          othLength = other.length,\n          result = Array(length + othLength);\n\n      while (++index < length) {\n        result[index] = array[index];\n      }\n      while (++othIndex < othLength) {\n        result[index++] = other[othIndex];\n      }\n      return result;\n    }\n\n    /**\n     * Copies the values of `source` to `array`.\n     *\n     * @private\n     * @param {Array} source The array to copy values from.\n     * @param {Array} [array=[]] The array to copy values to.\n     * @returns {Array} Returns `array`.\n     */\n    function arrayCopy(source, array) {\n      var index = -1,\n          length = source.length;\n\n      array || (array = Array(length));\n      while (++index < length) {\n        array[index] = source[index];\n      }\n      return array;\n    }\n\n    /**\n     * A specialized version of `_.forEach` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array} Returns `array`.\n     */\n    function arrayEach(array, iteratee) {\n      var index = -1,\n          length = array.length;\n\n      while (++index < length) {\n        if (iteratee(array[index], index, array) === false) {\n          break;\n        }\n      }\n      return array;\n    }\n\n    /**\n     * A specialized version of `_.forEachRight` for arrays without support for\n     * callback shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array} Returns `array`.\n     */\n    function arrayEachRight(array, iteratee) {\n      var length = array.length;\n\n      while (length--) {\n        if (iteratee(array[length], length, array) === false) {\n          break;\n        }\n      }\n      return array;\n    }\n\n    /**\n     * A specialized version of `_.every` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {boolean} Returns `true` if all elements pass the predicate check,\n     *  else `false`.\n     */\n    function arrayEvery(array, predicate) {\n      var index = -1,\n          length = array.length;\n\n      while (++index < length) {\n        if (!predicate(array[index], index, array)) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n    /**\n     * A specialized version of `baseExtremum` for arrays which invokes `iteratee`\n     * with one argument: (value).\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {Function} comparator The function used to compare values.\n     * @param {*} exValue The initial extremum value.\n     * @returns {*} Returns the extremum value.\n     */\n    function arrayExtremum(array, iteratee, comparator, exValue) {\n      var index = -1,\n          length = array.length,\n          computed = exValue,\n          result = computed;\n\n      while (++index < length) {\n        var value = array[index],\n            current = +iteratee(value);\n\n        if (comparator(current, computed)) {\n          computed = current;\n          result = value;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * A specialized version of `_.filter` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {Array} Returns the new filtered array.\n     */\n    function arrayFilter(array, predicate) {\n      var index = -1,\n          length = array.length,\n          resIndex = -1,\n          result = [];\n\n      while (++index < length) {\n        var value = array[index];\n        if (predicate(value, index, array)) {\n          result[++resIndex] = value;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * A specialized version of `_.map` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array} Returns the new mapped array.\n     */\n    function arrayMap(array, iteratee) {\n      var index = -1,\n          length = array.length,\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = iteratee(array[index], index, array);\n      }\n      return result;\n    }\n\n    /**\n     * Appends the elements of `values` to `array`.\n     *\n     * @private\n     * @param {Array} array The array to modify.\n     * @param {Array} values The values to append.\n     * @returns {Array} Returns `array`.\n     */\n    function arrayPush(array, values) {\n      var index = -1,\n          length = values.length,\n          offset = array.length;\n\n      while (++index < length) {\n        array[offset + index] = values[index];\n      }\n      return array;\n    }\n\n    /**\n     * A specialized version of `_.reduce` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @param {boolean} [initFromArray] Specify using the first element of `array`\n     *  as the initial value.\n     * @returns {*} Returns the accumulated value.\n     */\n    function arrayReduce(array, iteratee, accumulator, initFromArray) {\n      var index = -1,\n          length = array.length;\n\n      if (initFromArray && length) {\n        accumulator = array[++index];\n      }\n      while (++index < length) {\n        accumulator = iteratee(accumulator, array[index], index, array);\n      }\n      return accumulator;\n    }\n\n    /**\n     * A specialized version of `_.reduceRight` for arrays without support for\n     * callback shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @param {boolean} [initFromArray] Specify using the last element of `array`\n     *  as the initial value.\n     * @returns {*} Returns the accumulated value.\n     */\n    function arrayReduceRight(array, iteratee, accumulator, initFromArray) {\n      var length = array.length;\n      if (initFromArray && length) {\n        accumulator = array[--length];\n      }\n      while (length--) {\n        accumulator = iteratee(accumulator, array[length], length, array);\n      }\n      return accumulator;\n    }\n\n    /**\n     * A specialized version of `_.some` for arrays without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {boolean} Returns `true` if any element passes the predicate check,\n     *  else `false`.\n     */\n    function arraySome(array, predicate) {\n      var index = -1,\n          length = array.length;\n\n      while (++index < length) {\n        if (predicate(array[index], index, array)) {\n          return true;\n        }\n      }\n      return false;\n    }\n\n    /**\n     * A specialized version of `_.sum` for arrays without support for callback\n     * shorthands and `this` binding..\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {number} Returns the sum.\n     */\n    function arraySum(array, iteratee) {\n      var length = array.length,\n          result = 0;\n\n      while (length--) {\n        result += +iteratee(array[length]) || 0;\n      }\n      return result;\n    }\n\n    /**\n     * Used by `_.defaults` to customize its `_.assign` use.\n     *\n     * @private\n     * @param {*} objectValue The destination object property value.\n     * @param {*} sourceValue The source object property value.\n     * @returns {*} Returns the value to assign to the destination object.\n     */\n    function assignDefaults(objectValue, sourceValue) {\n      return objectValue === undefined ? sourceValue : objectValue;\n    }\n\n    /**\n     * Used by `_.template` to customize its `_.assign` use.\n     *\n     * **Note:** This function is like `assignDefaults` except that it ignores\n     * inherited property values when checking if a property is `undefined`.\n     *\n     * @private\n     * @param {*} objectValue The destination object property value.\n     * @param {*} sourceValue The source object property value.\n     * @param {string} key The key associated with the object and source values.\n     * @param {Object} object The destination object.\n     * @returns {*} Returns the value to assign to the destination object.\n     */\n    function assignOwnDefaults(objectValue, sourceValue, key, object) {\n      return (objectValue === undefined || !hasOwnProperty.call(object, key))\n        ? sourceValue\n        : objectValue;\n    }\n\n    /**\n     * A specialized version of `_.assign` for customizing assigned values without\n     * support for argument juggling, multiple sources, and `this` binding `customizer`\n     * functions.\n     *\n     * @private\n     * @param {Object} object The destination object.\n     * @param {Object} source The source object.\n     * @param {Function} customizer The function to customize assigned values.\n     * @returns {Object} Returns `object`.\n     */\n    function assignWith(object, source, customizer) {\n      var index = -1,\n          props = keys(source),\n          length = props.length;\n\n      while (++index < length) {\n        var key = props[index],\n            value = object[key],\n            result = customizer(value, source[key], key, object, source);\n\n        if ((result === result ? (result !== value) : (value === value)) ||\n            (value === undefined && !(key in object))) {\n          object[key] = result;\n        }\n      }\n      return object;\n    }\n\n    /**\n     * The base implementation of `_.assign` without support for argument juggling,\n     * multiple sources, and `customizer` functions.\n     *\n     * @private\n     * @param {Object} object The destination object.\n     * @param {Object} source The source object.\n     * @returns {Object} Returns `object`.\n     */\n    function baseAssign(object, source) {\n      return source == null\n        ? object\n        : baseCopy(source, keys(source), object);\n    }\n\n    /**\n     * The base implementation of `_.at` without support for string collections\n     * and individual key arguments.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {number[]|string[]} props The property names or indexes of elements to pick.\n     * @returns {Array} Returns the new array of picked elements.\n     */\n    function baseAt(collection, props) {\n      var index = -1,\n          isNil = collection == null,\n          isArr = !isNil && isArrayLike(collection),\n          length = isArr ? collection.length : 0,\n          propsLength = props.length,\n          result = Array(propsLength);\n\n      while(++index < propsLength) {\n        var key = props[index];\n        if (isArr) {\n          result[index] = isIndex(key, length) ? collection[key] : undefined;\n        } else {\n          result[index] = isNil ? undefined : collection[key];\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Copies properties of `source` to `object`.\n     *\n     * @private\n     * @param {Object} source The object to copy properties from.\n     * @param {Array} props The property names to copy.\n     * @param {Object} [object={}] The object to copy properties to.\n     * @returns {Object} Returns `object`.\n     */\n    function baseCopy(source, props, object) {\n      object || (object = {});\n\n      var index = -1,\n          length = props.length;\n\n      while (++index < length) {\n        var key = props[index];\n        object[key] = source[key];\n      }\n      return object;\n    }\n\n    /**\n     * The base implementation of `_.callback` which supports specifying the\n     * number of arguments to provide to `func`.\n     *\n     * @private\n     * @param {*} [func=_.identity] The value to convert to a callback.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param {number} [argCount] The number of arguments to provide to `func`.\n     * @returns {Function} Returns the callback.\n     */\n    function baseCallback(func, thisArg, argCount) {\n      var type = typeof func;\n      if (type == 'function') {\n        return thisArg === undefined\n          ? func\n          : bindCallback(func, thisArg, argCount);\n      }\n      if (func == null) {\n        return identity;\n      }\n      if (type == 'object') {\n        return baseMatches(func);\n      }\n      return thisArg === undefined\n        ? property(func)\n        : baseMatchesProperty(func, thisArg);\n    }\n\n    /**\n     * The base implementation of `_.clone` without support for argument juggling\n     * and `this` binding `customizer` functions.\n     *\n     * @private\n     * @param {*} value The value to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @param {Function} [customizer] The function to customize cloning values.\n     * @param {string} [key] The key of `value`.\n     * @param {Object} [object] The object `value` belongs to.\n     * @param {Array} [stackA=[]] Tracks traversed source objects.\n     * @param {Array} [stackB=[]] Associates clones with source counterparts.\n     * @returns {*} Returns the cloned value.\n     */\n    function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {\n      var result;\n      if (customizer) {\n        result = object ? customizer(value, key, object) : customizer(value);\n      }\n      if (result !== undefined) {\n        return result;\n      }\n      if (!isObject(value)) {\n        return value;\n      }\n      var isArr = isArray(value);\n      if (isArr) {\n        result = initCloneArray(value);\n        if (!isDeep) {\n          return arrayCopy(value, result);\n        }\n      } else {\n        var tag = objToString.call(value),\n            isFunc = tag == funcTag;\n\n        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n          result = initCloneObject(isFunc ? {} : value);\n          if (!isDeep) {\n            return baseAssign(result, value);\n          }\n        } else {\n          return cloneableTags[tag]\n            ? initCloneByTag(value, tag, isDeep)\n            : (object ? value : {});\n        }\n      }\n      // Check for circular references and return its corresponding clone.\n      stackA || (stackA = []);\n      stackB || (stackB = []);\n\n      var length = stackA.length;\n      while (length--) {\n        if (stackA[length] == value) {\n          return stackB[length];\n        }\n      }\n      // Add the source value to the stack of traversed objects and associate it with its clone.\n      stackA.push(value);\n      stackB.push(result);\n\n      // Recursively populate clone (susceptible to call stack limits).\n      (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {\n        result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.create` without support for assigning\n     * properties to the created object.\n     *\n     * @private\n     * @param {Object} prototype The object to inherit from.\n     * @returns {Object} Returns the new object.\n     */\n    var baseCreate = (function() {\n      function object() {}\n      return function(prototype) {\n        if (isObject(prototype)) {\n          object.prototype = prototype;\n          var result = new object;\n          object.prototype = undefined;\n        }\n        return result || {};\n      };\n    }());\n\n    /**\n     * The base implementation of `_.delay` and `_.defer` which accepts an index\n     * of where to slice the arguments to provide to `func`.\n     *\n     * @private\n     * @param {Function} func The function to delay.\n     * @param {number} wait The number of milliseconds to delay invocation.\n     * @param {Object} args The arguments provide to `func`.\n     * @returns {number} Returns the timer id.\n     */\n    function baseDelay(func, wait, args) {\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      return setTimeout(function() { func.apply(undefined, args); }, wait);\n    }\n\n    /**\n     * The base implementation of `_.difference` which accepts a single array\n     * of values to exclude.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {Array} values The values to exclude.\n     * @returns {Array} Returns the new array of filtered values.\n     */\n    function baseDifference(array, values) {\n      var length = array ? array.length : 0,\n          result = [];\n\n      if (!length) {\n        return result;\n      }\n      var index = -1,\n          indexOf = getIndexOf(),\n          isCommon = indexOf == baseIndexOf,\n          cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null,\n          valuesLength = values.length;\n\n      if (cache) {\n        indexOf = cacheIndexOf;\n        isCommon = false;\n        values = cache;\n      }\n      outer:\n      while (++index < length) {\n        var value = array[index];\n\n        if (isCommon && value === value) {\n          var valuesIndex = valuesLength;\n          while (valuesIndex--) {\n            if (values[valuesIndex] === value) {\n              continue outer;\n            }\n          }\n          result.push(value);\n        }\n        else if (indexOf(values, value, 0) < 0) {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.forEach` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array|Object|string} Returns `collection`.\n     */\n    var baseEach = createBaseEach(baseForOwn);\n\n    /**\n     * The base implementation of `_.forEachRight` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array|Object|string} Returns `collection`.\n     */\n    var baseEachRight = createBaseEach(baseForOwnRight, true);\n\n    /**\n     * The base implementation of `_.every` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {boolean} Returns `true` if all elements pass the predicate check,\n     *  else `false`\n     */\n    function baseEvery(collection, predicate) {\n      var result = true;\n      baseEach(collection, function(value, index, collection) {\n        result = !!predicate(value, index, collection);\n        return result;\n      });\n      return result;\n    }\n\n    /**\n     * Gets the extremum value of `collection` invoking `iteratee` for each value\n     * in `collection` to generate the criterion by which the value is ranked.\n     * The `iteratee` is invoked with three arguments: (value, index|key, collection).\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {Function} comparator The function used to compare values.\n     * @param {*} exValue The initial extremum value.\n     * @returns {*} Returns the extremum value.\n     */\n    function baseExtremum(collection, iteratee, comparator, exValue) {\n      var computed = exValue,\n          result = computed;\n\n      baseEach(collection, function(value, index, collection) {\n        var current = +iteratee(value, index, collection);\n        if (comparator(current, computed) || (current === exValue && current === result)) {\n          computed = current;\n          result = value;\n        }\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.fill` without an iteratee call guard.\n     *\n     * @private\n     * @param {Array} array The array to fill.\n     * @param {*} value The value to fill `array` with.\n     * @param {number} [start=0] The start position.\n     * @param {number} [end=array.length] The end position.\n     * @returns {Array} Returns `array`.\n     */\n    function baseFill(array, value, start, end) {\n      var length = array.length;\n\n      start = start == null ? 0 : (+start || 0);\n      if (start < 0) {\n        start = -start > length ? 0 : (length + start);\n      }\n      end = (end === undefined || end > length) ? length : (+end || 0);\n      if (end < 0) {\n        end += length;\n      }\n      length = start > end ? 0 : (end >>> 0);\n      start >>>= 0;\n\n      while (start < length) {\n        array[start++] = value;\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.filter` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {Array} Returns the new filtered array.\n     */\n    function baseFilter(collection, predicate) {\n      var result = [];\n      baseEach(collection, function(value, index, collection) {\n        if (predicate(value, index, collection)) {\n          result.push(value);\n        }\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,\n     * without support for callback shorthands and `this` binding, which iterates\n     * over `collection` using the provided `eachFunc`.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {Function} predicate The function invoked per iteration.\n     * @param {Function} eachFunc The function to iterate over `collection`.\n     * @param {boolean} [retKey] Specify returning the key of the found element\n     *  instead of the element itself.\n     * @returns {*} Returns the found element or its key, else `undefined`.\n     */\n    function baseFind(collection, predicate, eachFunc, retKey) {\n      var result;\n      eachFunc(collection, function(value, key, collection) {\n        if (predicate(value, key, collection)) {\n          result = retKey ? key : value;\n          return false;\n        }\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.flatten` with added support for restricting\n     * flattening and specifying the start index.\n     *\n     * @private\n     * @param {Array} array The array to flatten.\n     * @param {boolean} [isDeep] Specify a deep flatten.\n     * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.\n     * @param {Array} [result=[]] The initial result value.\n     * @returns {Array} Returns the new flattened array.\n     */\n    function baseFlatten(array, isDeep, isStrict, result) {\n      result || (result = []);\n\n      var index = -1,\n          length = array.length;\n\n      while (++index < length) {\n        var value = array[index];\n        if (isObjectLike(value) && isArrayLike(value) &&\n            (isStrict || isArray(value) || isArguments(value))) {\n          if (isDeep) {\n            // Recursively flatten arrays (susceptible to call stack limits).\n            baseFlatten(value, isDeep, isStrict, result);\n          } else {\n            arrayPush(result, value);\n          }\n        } else if (!isStrict) {\n          result[result.length] = value;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `baseForIn` and `baseForOwn` which iterates\n     * over `object` properties returned by `keysFunc` invoking `iteratee` for\n     * each property. Iteratee functions may exit iteration early by explicitly\n     * returning `false`.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {Function} keysFunc The function to get the keys of `object`.\n     * @returns {Object} Returns `object`.\n     */\n    var baseFor = createBaseFor();\n\n    /**\n     * This function is like `baseFor` except that it iterates over properties\n     * in the opposite order.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {Function} keysFunc The function to get the keys of `object`.\n     * @returns {Object} Returns `object`.\n     */\n    var baseForRight = createBaseFor(true);\n\n    /**\n     * The base implementation of `_.forIn` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     */\n    function baseForIn(object, iteratee) {\n      return baseFor(object, iteratee, keysIn);\n    }\n\n    /**\n     * The base implementation of `_.forOwn` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     */\n    function baseForOwn(object, iteratee) {\n      return baseFor(object, iteratee, keys);\n    }\n\n    /**\n     * The base implementation of `_.forOwnRight` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     */\n    function baseForOwnRight(object, iteratee) {\n      return baseForRight(object, iteratee, keys);\n    }\n\n    /**\n     * The base implementation of `_.functions` which creates an array of\n     * `object` function property names filtered from those provided.\n     *\n     * @private\n     * @param {Object} object The object to inspect.\n     * @param {Array} props The property names to filter.\n     * @returns {Array} Returns the new array of filtered property names.\n     */\n    function baseFunctions(object, props) {\n      var index = -1,\n          length = props.length,\n          resIndex = -1,\n          result = [];\n\n      while (++index < length) {\n        var key = props[index];\n        if (isFunction(object[key])) {\n          result[++resIndex] = key;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `get` without support for string paths\n     * and default values.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array} path The path of the property to get.\n     * @param {string} [pathKey] The key representation of path.\n     * @returns {*} Returns the resolved value.\n     */\n    function baseGet(object, path, pathKey) {\n      if (object == null) {\n        return;\n      }\n      if (pathKey !== undefined && pathKey in toObject(object)) {\n        path = [pathKey];\n      }\n      var index = 0,\n          length = path.length;\n\n      while (object != null && index < length) {\n        object = object[path[index++]];\n      }\n      return (index && index == length) ? object : undefined;\n    }\n\n    /**\n     * The base implementation of `_.isEqual` without support for `this` binding\n     * `customizer` functions.\n     *\n     * @private\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @param {Function} [customizer] The function to customize comparing values.\n     * @param {boolean} [isLoose] Specify performing partial comparisons.\n     * @param {Array} [stackA] Tracks traversed `value` objects.\n     * @param {Array} [stackB] Tracks traversed `other` objects.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     */\n    function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {\n      if (value === other) {\n        return true;\n      }\n      if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {\n        return value !== value && other !== other;\n      }\n      return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);\n    }\n\n    /**\n     * A specialized version of `baseIsEqual` for arrays and objects which performs\n     * deep comparisons and tracks traversed objects enabling objects with circular\n     * references to be compared.\n     *\n     * @private\n     * @param {Object} object The object to compare.\n     * @param {Object} other The other object to compare.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Function} [customizer] The function to customize comparing objects.\n     * @param {boolean} [isLoose] Specify performing partial comparisons.\n     * @param {Array} [stackA=[]] Tracks traversed `value` objects.\n     * @param {Array} [stackB=[]] Tracks traversed `other` objects.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n      var objIsArr = isArray(object),\n          othIsArr = isArray(other),\n          objTag = arrayTag,\n          othTag = arrayTag;\n\n      if (!objIsArr) {\n        objTag = objToString.call(object);\n        if (objTag == argsTag) {\n          objTag = objectTag;\n        } else if (objTag != objectTag) {\n          objIsArr = isTypedArray(object);\n        }\n      }\n      if (!othIsArr) {\n        othTag = objToString.call(other);\n        if (othTag == argsTag) {\n          othTag = objectTag;\n        } else if (othTag != objectTag) {\n          othIsArr = isTypedArray(other);\n        }\n      }\n      var objIsObj = objTag == objectTag,\n          othIsObj = othTag == objectTag,\n          isSameTag = objTag == othTag;\n\n      if (isSameTag && !(objIsArr || objIsObj)) {\n        return equalByTag(object, other, objTag);\n      }\n      if (!isLoose) {\n        var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n            othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n        if (objIsWrapped || othIsWrapped) {\n          return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);\n        }\n      }\n      if (!isSameTag) {\n        return false;\n      }\n      // Assume cyclic values are equal.\n      // For more information on detecting circular references see https://es5.github.io/#JO.\n      stackA || (stackA = []);\n      stackB || (stackB = []);\n\n      var length = stackA.length;\n      while (length--) {\n        if (stackA[length] == object) {\n          return stackB[length] == other;\n        }\n      }\n      // Add `object` and `other` to the stack of traversed objects.\n      stackA.push(object);\n      stackB.push(other);\n\n      var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);\n\n      stackA.pop();\n      stackB.pop();\n\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.isMatch` without support for callback\n     * shorthands and `this` binding.\n     *\n     * @private\n     * @param {Object} object The object to inspect.\n     * @param {Array} matchData The propery names, values, and compare flags to match.\n     * @param {Function} [customizer] The function to customize comparing objects.\n     * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n     */\n    function baseIsMatch(object, matchData, customizer) {\n      var index = matchData.length,\n          length = index,\n          noCustomizer = !customizer;\n\n      if (object == null) {\n        return !length;\n      }\n      object = toObject(object);\n      while (index--) {\n        var data = matchData[index];\n        if ((noCustomizer && data[2])\n              ? data[1] !== object[data[0]]\n              : !(data[0] in object)\n            ) {\n          return false;\n        }\n      }\n      while (++index < length) {\n        data = matchData[index];\n        var key = data[0],\n            objValue = object[key],\n            srcValue = data[1];\n\n        if (noCustomizer && data[2]) {\n          if (objValue === undefined && !(key in object)) {\n            return false;\n          }\n        } else {\n          var result = customizer ? customizer(objValue, srcValue, key) : undefined;\n          if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {\n            return false;\n          }\n        }\n      }\n      return true;\n    }\n\n    /**\n     * The base implementation of `_.map` without support for callback shorthands\n     * and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array} Returns the new mapped array.\n     */\n    function baseMap(collection, iteratee) {\n      var index = -1,\n          result = isArrayLike(collection) ? Array(collection.length) : [];\n\n      baseEach(collection, function(value, key, collection) {\n        result[++index] = iteratee(value, key, collection);\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.matches` which does not clone `source`.\n     *\n     * @private\n     * @param {Object} source The object of property values to match.\n     * @returns {Function} Returns the new function.\n     */\n    function baseMatches(source) {\n      var matchData = getMatchData(source);\n      if (matchData.length == 1 && matchData[0][2]) {\n        var key = matchData[0][0],\n            value = matchData[0][1];\n\n        return function(object) {\n          if (object == null) {\n            return false;\n          }\n          return object[key] === value && (value !== undefined || (key in toObject(object)));\n        };\n      }\n      return function(object) {\n        return baseIsMatch(object, matchData);\n      };\n    }\n\n    /**\n     * The base implementation of `_.matchesProperty` which does not clone `srcValue`.\n     *\n     * @private\n     * @param {string} path The path of the property to get.\n     * @param {*} srcValue The value to compare.\n     * @returns {Function} Returns the new function.\n     */\n    function baseMatchesProperty(path, srcValue) {\n      var isArr = isArray(path),\n          isCommon = isKey(path) && isStrictComparable(srcValue),\n          pathKey = (path + '');\n\n      path = toPath(path);\n      return function(object) {\n        if (object == null) {\n          return false;\n        }\n        var key = pathKey;\n        object = toObject(object);\n        if ((isArr || !isCommon) && !(key in object)) {\n          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n          if (object == null) {\n            return false;\n          }\n          key = last(path);\n          object = toObject(object);\n        }\n        return object[key] === srcValue\n          ? (srcValue !== undefined || (key in object))\n          : baseIsEqual(srcValue, object[key], undefined, true);\n      };\n    }\n\n    /**\n     * The base implementation of `_.merge` without support for argument juggling,\n     * multiple sources, and `this` binding `customizer` functions.\n     *\n     * @private\n     * @param {Object} object The destination object.\n     * @param {Object} source The source object.\n     * @param {Function} [customizer] The function to customize merged values.\n     * @param {Array} [stackA=[]] Tracks traversed source objects.\n     * @param {Array} [stackB=[]] Associates values with source counterparts.\n     * @returns {Object} Returns `object`.\n     */\n    function baseMerge(object, source, customizer, stackA, stackB) {\n      if (!isObject(object)) {\n        return object;\n      }\n      var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),\n          props = isSrcArr ? undefined : keys(source);\n\n      arrayEach(props || source, function(srcValue, key) {\n        if (props) {\n          key = srcValue;\n          srcValue = source[key];\n        }\n        if (isObjectLike(srcValue)) {\n          stackA || (stackA = []);\n          stackB || (stackB = []);\n          baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);\n        }\n        else {\n          var value = object[key],\n              result = customizer ? customizer(value, srcValue, key, object, source) : undefined,\n              isCommon = result === undefined;\n\n          if (isCommon) {\n            result = srcValue;\n          }\n          if ((result !== undefined || (isSrcArr && !(key in object))) &&\n              (isCommon || (result === result ? (result !== value) : (value === value)))) {\n            object[key] = result;\n          }\n        }\n      });\n      return object;\n    }\n\n    /**\n     * A specialized version of `baseMerge` for arrays and objects which performs\n     * deep merges and tracks traversed objects enabling objects with circular\n     * references to be merged.\n     *\n     * @private\n     * @param {Object} object The destination object.\n     * @param {Object} source The source object.\n     * @param {string} key The key of the value to merge.\n     * @param {Function} mergeFunc The function to merge values.\n     * @param {Function} [customizer] The function to customize merged values.\n     * @param {Array} [stackA=[]] Tracks traversed source objects.\n     * @param {Array} [stackB=[]] Associates values with source counterparts.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {\n      var length = stackA.length,\n          srcValue = source[key];\n\n      while (length--) {\n        if (stackA[length] == srcValue) {\n          object[key] = stackB[length];\n          return;\n        }\n      }\n      var value = object[key],\n          result = customizer ? customizer(value, srcValue, key, object, source) : undefined,\n          isCommon = result === undefined;\n\n      if (isCommon) {\n        result = srcValue;\n        if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {\n          result = isArray(value)\n            ? value\n            : (isArrayLike(value) ? arrayCopy(value) : []);\n        }\n        else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n          result = isArguments(value)\n            ? toPlainObject(value)\n            : (isPlainObject(value) ? value : {});\n        }\n        else {\n          isCommon = false;\n        }\n      }\n      // Add the source value to the stack of traversed objects and associate\n      // it with its merged value.\n      stackA.push(srcValue);\n      stackB.push(result);\n\n      if (isCommon) {\n        // Recursively merge objects and arrays (susceptible to call stack limits).\n        object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);\n      } else if (result === result ? (result !== value) : (value === value)) {\n        object[key] = result;\n      }\n    }\n\n    /**\n     * The base implementation of `_.property` without support for deep paths.\n     *\n     * @private\n     * @param {string} key The key of the property to get.\n     * @returns {Function} Returns the new function.\n     */\n    function baseProperty(key) {\n      return function(object) {\n        return object == null ? undefined : object[key];\n      };\n    }\n\n    /**\n     * A specialized version of `baseProperty` which supports deep paths.\n     *\n     * @private\n     * @param {Array|string} path The path of the property to get.\n     * @returns {Function} Returns the new function.\n     */\n    function basePropertyDeep(path) {\n      var pathKey = (path + '');\n      path = toPath(path);\n      return function(object) {\n        return baseGet(object, path, pathKey);\n      };\n    }\n\n    /**\n     * The base implementation of `_.pullAt` without support for individual\n     * index arguments and capturing the removed elements.\n     *\n     * @private\n     * @param {Array} array The array to modify.\n     * @param {number[]} indexes The indexes of elements to remove.\n     * @returns {Array} Returns `array`.\n     */\n    function basePullAt(array, indexes) {\n      var length = array ? indexes.length : 0;\n      while (length--) {\n        var index = indexes[length];\n        if (index != previous && isIndex(index)) {\n          var previous = index;\n          splice.call(array, index, 1);\n        }\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.random` without support for argument juggling\n     * and returning floating-point numbers.\n     *\n     * @private\n     * @param {number} min The minimum possible value.\n     * @param {number} max The maximum possible value.\n     * @returns {number} Returns the random number.\n     */\n    function baseRandom(min, max) {\n      return min + nativeFloor(nativeRandom() * (max - min + 1));\n    }\n\n    /**\n     * The base implementation of `_.reduce` and `_.reduceRight` without support\n     * for callback shorthands and `this` binding, which iterates over `collection`\n     * using the provided `eachFunc`.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {*} accumulator The initial value.\n     * @param {boolean} initFromCollection Specify using the first or last element\n     *  of `collection` as the initial value.\n     * @param {Function} eachFunc The function to iterate over `collection`.\n     * @returns {*} Returns the accumulated value.\n     */\n    function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {\n      eachFunc(collection, function(value, index, collection) {\n        accumulator = initFromCollection\n          ? (initFromCollection = false, value)\n          : iteratee(accumulator, value, index, collection);\n      });\n      return accumulator;\n    }\n\n    /**\n     * The base implementation of `setData` without support for hot loop detection.\n     *\n     * @private\n     * @param {Function} func The function to associate metadata with.\n     * @param {*} data The metadata.\n     * @returns {Function} Returns `func`.\n     */\n    var baseSetData = !metaMap ? identity : function(func, data) {\n      metaMap.set(func, data);\n      return func;\n    };\n\n    /**\n     * The base implementation of `_.slice` without an iteratee call guard.\n     *\n     * @private\n     * @param {Array} array The array to slice.\n     * @param {number} [start=0] The start position.\n     * @param {number} [end=array.length] The end position.\n     * @returns {Array} Returns the slice of `array`.\n     */\n    function baseSlice(array, start, end) {\n      var index = -1,\n          length = array.length;\n\n      start = start == null ? 0 : (+start || 0);\n      if (start < 0) {\n        start = -start > length ? 0 : (length + start);\n      }\n      end = (end === undefined || end > length) ? length : (+end || 0);\n      if (end < 0) {\n        end += length;\n      }\n      length = start > end ? 0 : ((end - start) >>> 0);\n      start >>>= 0;\n\n      var result = Array(length);\n      while (++index < length) {\n        result[index] = array[index + start];\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.some` without support for callback shorthands\n     * and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {boolean} Returns `true` if any element passes the predicate check,\n     *  else `false`.\n     */\n    function baseSome(collection, predicate) {\n      var result;\n\n      baseEach(collection, function(value, index, collection) {\n        result = predicate(value, index, collection);\n        return !result;\n      });\n      return !!result;\n    }\n\n    /**\n     * The base implementation of `_.sortBy` which uses `comparer` to define\n     * the sort order of `array` and replaces criteria objects with their\n     * corresponding values.\n     *\n     * @private\n     * @param {Array} array The array to sort.\n     * @param {Function} comparer The function to define sort order.\n     * @returns {Array} Returns `array`.\n     */\n    function baseSortBy(array, comparer) {\n      var length = array.length;\n\n      array.sort(comparer);\n      while (length--) {\n        array[length] = array[length].value;\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.sortByOrder` without param guards.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n     * @param {boolean[]} orders The sort orders of `iteratees`.\n     * @returns {Array} Returns the new sorted array.\n     */\n    function baseSortByOrder(collection, iteratees, orders) {\n      var callback = getCallback(),\n          index = -1;\n\n      iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });\n\n      var result = baseMap(collection, function(value) {\n        var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });\n        return { 'criteria': criteria, 'index': ++index, 'value': value };\n      });\n\n      return baseSortBy(result, function(object, other) {\n        return compareMultiple(object, other, orders);\n      });\n    }\n\n    /**\n     * The base implementation of `_.sum` without support for callback shorthands\n     * and `this` binding.\n     *\n     * @private\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {number} Returns the sum.\n     */\n    function baseSum(collection, iteratee) {\n      var result = 0;\n      baseEach(collection, function(value, index, collection) {\n        result += +iteratee(value, index, collection) || 0;\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.uniq` without support for callback shorthands\n     * and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {Function} [iteratee] The function invoked per iteration.\n     * @returns {Array} Returns the new duplicate-value-free array.\n     */\n    function baseUniq(array, iteratee) {\n      var index = -1,\n          indexOf = getIndexOf(),\n          length = array.length,\n          isCommon = indexOf == baseIndexOf,\n          isLarge = isCommon && length >= LARGE_ARRAY_SIZE,\n          seen = isLarge ? createCache() : null,\n          result = [];\n\n      if (seen) {\n        indexOf = cacheIndexOf;\n        isCommon = false;\n      } else {\n        isLarge = false;\n        seen = iteratee ? [] : result;\n      }\n      outer:\n      while (++index < length) {\n        var value = array[index],\n            computed = iteratee ? iteratee(value, index, array) : value;\n\n        if (isCommon && value === value) {\n          var seenIndex = seen.length;\n          while (seenIndex--) {\n            if (seen[seenIndex] === computed) {\n              continue outer;\n            }\n          }\n          if (iteratee) {\n            seen.push(computed);\n          }\n          result.push(value);\n        }\n        else if (indexOf(seen, computed, 0) < 0) {\n          if (iteratee || isLarge) {\n            seen.push(computed);\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.values` and `_.valuesIn` which creates an\n     * array of `object` property values corresponding to the property names\n     * of `props`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array} props The property names to get values for.\n     * @returns {Object} Returns the array of property values.\n     */\n    function baseValues(object, props) {\n      var index = -1,\n          length = props.length,\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = object[props[index]];\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,\n     * and `_.takeWhile` without support for callback shorthands and `this` binding.\n     *\n     * @private\n     * @param {Array} array The array to query.\n     * @param {Function} predicate The function invoked per iteration.\n     * @param {boolean} [isDrop] Specify dropping elements instead of taking them.\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Array} Returns the slice of `array`.\n     */\n    function baseWhile(array, predicate, isDrop, fromRight) {\n      var length = array.length,\n          index = fromRight ? length : -1;\n\n      while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}\n      return isDrop\n        ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))\n        : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));\n    }\n\n    /**\n     * The base implementation of `wrapperValue` which returns the result of\n     * performing a sequence of actions on the unwrapped `value`, where each\n     * successive action is supplied the return value of the previous.\n     *\n     * @private\n     * @param {*} value The unwrapped value.\n     * @param {Array} actions Actions to peform to resolve the unwrapped value.\n     * @returns {*} Returns the resolved value.\n     */\n    function baseWrapperValue(value, actions) {\n      var result = value;\n      if (result instanceof LazyWrapper) {\n        result = result.value();\n      }\n      var index = -1,\n          length = actions.length;\n\n      while (++index < length) {\n        var action = actions[index];\n        result = action.func.apply(action.thisArg, arrayPush([result], action.args));\n      }\n      return result;\n    }\n\n    /**\n     * Performs a binary search of `array` to determine the index at which `value`\n     * should be inserted into `array` in order to maintain its sort order.\n     *\n     * @private\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {boolean} [retHighest] Specify returning the highest qualified index.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     */\n    function binaryIndex(array, value, retHighest) {\n      var low = 0,\n          high = array ? array.length : low;\n\n      if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {\n        while (low < high) {\n          var mid = (low + high) >>> 1,\n              computed = array[mid];\n\n          if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {\n            low = mid + 1;\n          } else {\n            high = mid;\n          }\n        }\n        return high;\n      }\n      return binaryIndexBy(array, value, identity, retHighest);\n    }\n\n    /**\n     * This function is like `binaryIndex` except that it invokes `iteratee` for\n     * `value` and each element of `array` to compute their sort ranking. The\n     * iteratee is invoked with one argument; (value).\n     *\n     * @private\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @param {boolean} [retHighest] Specify returning the highest qualified index.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     */\n    function binaryIndexBy(array, value, iteratee, retHighest) {\n      value = iteratee(value);\n\n      var low = 0,\n          high = array ? array.length : 0,\n          valIsNaN = value !== value,\n          valIsNull = value === null,\n          valIsUndef = value === undefined;\n\n      while (low < high) {\n        var mid = nativeFloor((low + high) / 2),\n            computed = iteratee(array[mid]),\n            isDef = computed !== undefined,\n            isReflexive = computed === computed;\n\n        if (valIsNaN) {\n          var setLow = isReflexive || retHighest;\n        } else if (valIsNull) {\n          setLow = isReflexive && isDef && (retHighest || computed != null);\n        } else if (valIsUndef) {\n          setLow = isReflexive && (retHighest || isDef);\n        } else if (computed == null) {\n          setLow = false;\n        } else {\n          setLow = retHighest ? (computed <= value) : (computed < value);\n        }\n        if (setLow) {\n          low = mid + 1;\n        } else {\n          high = mid;\n        }\n      }\n      return nativeMin(high, MAX_ARRAY_INDEX);\n    }\n\n    /**\n     * A specialized version of `baseCallback` which only supports `this` binding\n     * and specifying the number of arguments to provide to `func`.\n     *\n     * @private\n     * @param {Function} func The function to bind.\n     * @param {*} thisArg The `this` binding of `func`.\n     * @param {number} [argCount] The number of arguments to provide to `func`.\n     * @returns {Function} Returns the callback.\n     */\n    function bindCallback(func, thisArg, argCount) {\n      if (typeof func != 'function') {\n        return identity;\n      }\n      if (thisArg === undefined) {\n        return func;\n      }\n      switch (argCount) {\n        case 1: return function(value) {\n          return func.call(thisArg, value);\n        };\n        case 3: return function(value, index, collection) {\n          return func.call(thisArg, value, index, collection);\n        };\n        case 4: return function(accumulator, value, index, collection) {\n          return func.call(thisArg, accumulator, value, index, collection);\n        };\n        case 5: return function(value, other, key, object, source) {\n          return func.call(thisArg, value, other, key, object, source);\n        };\n      }\n      return function() {\n        return func.apply(thisArg, arguments);\n      };\n    }\n\n    /**\n     * Creates a clone of the given array buffer.\n     *\n     * @private\n     * @param {ArrayBuffer} buffer The array buffer to clone.\n     * @returns {ArrayBuffer} Returns the cloned array buffer.\n     */\n    function bufferClone(buffer) {\n      var result = new ArrayBuffer(buffer.byteLength),\n          view = new Uint8Array(result);\n\n      view.set(new Uint8Array(buffer));\n      return result;\n    }\n\n    /**\n     * Creates an array that is the composition of partially applied arguments,\n     * placeholders, and provided arguments into a single array of arguments.\n     *\n     * @private\n     * @param {Array|Object} args The provided arguments.\n     * @param {Array} partials The arguments to prepend to those provided.\n     * @param {Array} holders The `partials` placeholder indexes.\n     * @returns {Array} Returns the new array of composed arguments.\n     */\n    function composeArgs(args, partials, holders) {\n      var holdersLength = holders.length,\n          argsIndex = -1,\n          argsLength = nativeMax(args.length - holdersLength, 0),\n          leftIndex = -1,\n          leftLength = partials.length,\n          result = Array(leftLength + argsLength);\n\n      while (++leftIndex < leftLength) {\n        result[leftIndex] = partials[leftIndex];\n      }\n      while (++argsIndex < holdersLength) {\n        result[holders[argsIndex]] = args[argsIndex];\n      }\n      while (argsLength--) {\n        result[leftIndex++] = args[argsIndex++];\n      }\n      return result;\n    }\n\n    /**\n     * This function is like `composeArgs` except that the arguments composition\n     * is tailored for `_.partialRight`.\n     *\n     * @private\n     * @param {Array|Object} args The provided arguments.\n     * @param {Array} partials The arguments to append to those provided.\n     * @param {Array} holders The `partials` placeholder indexes.\n     * @returns {Array} Returns the new array of composed arguments.\n     */\n    function composeArgsRight(args, partials, holders) {\n      var holdersIndex = -1,\n          holdersLength = holders.length,\n          argsIndex = -1,\n          argsLength = nativeMax(args.length - holdersLength, 0),\n          rightIndex = -1,\n          rightLength = partials.length,\n          result = Array(argsLength + rightLength);\n\n      while (++argsIndex < argsLength) {\n        result[argsIndex] = args[argsIndex];\n      }\n      var offset = argsIndex;\n      while (++rightIndex < rightLength) {\n        result[offset + rightIndex] = partials[rightIndex];\n      }\n      while (++holdersIndex < holdersLength) {\n        result[offset + holders[holdersIndex]] = args[argsIndex++];\n      }\n      return result;\n    }\n\n    /**\n     * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function.\n     *\n     * @private\n     * @param {Function} setter The function to set keys and values of the accumulator object.\n     * @param {Function} [initializer] The function to initialize the accumulator object.\n     * @returns {Function} Returns the new aggregator function.\n     */\n    function createAggregator(setter, initializer) {\n      return function(collection, iteratee, thisArg) {\n        var result = initializer ? initializer() : {};\n        iteratee = getCallback(iteratee, thisArg, 3);\n\n        if (isArray(collection)) {\n          var index = -1,\n              length = collection.length;\n\n          while (++index < length) {\n            var value = collection[index];\n            setter(result, value, iteratee(value, index, collection), collection);\n          }\n        } else {\n          baseEach(collection, function(value, key, collection) {\n            setter(result, value, iteratee(value, key, collection), collection);\n          });\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Creates a `_.assign`, `_.defaults`, or `_.merge` function.\n     *\n     * @private\n     * @param {Function} assigner The function to assign values.\n     * @returns {Function} Returns the new assigner function.\n     */\n    function createAssigner(assigner) {\n      return restParam(function(object, sources) {\n        var index = -1,\n            length = object == null ? 0 : sources.length,\n            customizer = length > 2 ? sources[length - 2] : undefined,\n            guard = length > 2 ? sources[2] : undefined,\n            thisArg = length > 1 ? sources[length - 1] : undefined;\n\n        if (typeof customizer == 'function') {\n          customizer = bindCallback(customizer, thisArg, 5);\n          length -= 2;\n        } else {\n          customizer = typeof thisArg == 'function' ? thisArg : undefined;\n          length -= (customizer ? 1 : 0);\n        }\n        if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n          customizer = length < 3 ? undefined : customizer;\n          length = 1;\n        }\n        while (++index < length) {\n          var source = sources[index];\n          if (source) {\n            assigner(object, source, customizer);\n          }\n        }\n        return object;\n      });\n    }\n\n    /**\n     * Creates a `baseEach` or `baseEachRight` function.\n     *\n     * @private\n     * @param {Function} eachFunc The function to iterate over a collection.\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new base function.\n     */\n    function createBaseEach(eachFunc, fromRight) {\n      return function(collection, iteratee) {\n        var length = collection ? getLength(collection) : 0;\n        if (!isLength(length)) {\n          return eachFunc(collection, iteratee);\n        }\n        var index = fromRight ? length : -1,\n            iterable = toObject(collection);\n\n        while ((fromRight ? index-- : ++index < length)) {\n          if (iteratee(iterable[index], index, iterable) === false) {\n            break;\n          }\n        }\n        return collection;\n      };\n    }\n\n    /**\n     * Creates a base function for `_.forIn` or `_.forInRight`.\n     *\n     * @private\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new base function.\n     */\n    function createBaseFor(fromRight) {\n      return function(object, iteratee, keysFunc) {\n        var iterable = toObject(object),\n            props = keysFunc(object),\n            length = props.length,\n            index = fromRight ? length : -1;\n\n        while ((fromRight ? index-- : ++index < length)) {\n          var key = props[index];\n          if (iteratee(iterable[key], key, iterable) === false) {\n            break;\n          }\n        }\n        return object;\n      };\n    }\n\n    /**\n     * Creates a function that wraps `func` and invokes it with the `this`\n     * binding of `thisArg`.\n     *\n     * @private\n     * @param {Function} func The function to bind.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @returns {Function} Returns the new bound function.\n     */\n    function createBindWrapper(func, thisArg) {\n      var Ctor = createCtorWrapper(func);\n\n      function wrapper() {\n        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n        return fn.apply(thisArg, arguments);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a `Set` cache object to optimize linear searches of large arrays.\n     *\n     * @private\n     * @param {Array} [values] The values to cache.\n     * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.\n     */\n    function createCache(values) {\n      return (nativeCreate && Set) ? new SetCache(values) : null;\n    }\n\n    /**\n     * Creates a function that produces compound words out of the words in a\n     * given string.\n     *\n     * @private\n     * @param {Function} callback The function to combine each word.\n     * @returns {Function} Returns the new compounder function.\n     */\n    function createCompounder(callback) {\n      return function(string) {\n        var index = -1,\n            array = words(deburr(string)),\n            length = array.length,\n            result = '';\n\n        while (++index < length) {\n          result = callback(result, array[index], index);\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function that produces an instance of `Ctor` regardless of\n     * whether it was invoked as part of a `new` expression or by `call` or `apply`.\n     *\n     * @private\n     * @param {Function} Ctor The constructor to wrap.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createCtorWrapper(Ctor) {\n      return function() {\n        // Use a `switch` statement to work with class constructors.\n        // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist\n        // for more details.\n        var args = arguments;\n        switch (args.length) {\n          case 0: return new Ctor;\n          case 1: return new Ctor(args[0]);\n          case 2: return new Ctor(args[0], args[1]);\n          case 3: return new Ctor(args[0], args[1], args[2]);\n          case 4: return new Ctor(args[0], args[1], args[2], args[3]);\n          case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);\n          case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);\n          case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n        }\n        var thisBinding = baseCreate(Ctor.prototype),\n            result = Ctor.apply(thisBinding, args);\n\n        // Mimic the constructor's `return` behavior.\n        // See https://es5.github.io/#x13.2.2 for more details.\n        return isObject(result) ? result : thisBinding;\n      };\n    }\n\n    /**\n     * Creates a `_.curry` or `_.curryRight` function.\n     *\n     * @private\n     * @param {boolean} flag The curry bit flag.\n     * @returns {Function} Returns the new curry function.\n     */\n    function createCurry(flag) {\n      function curryFunc(func, arity, guard) {\n        if (guard && isIterateeCall(func, arity, guard)) {\n          arity = undefined;\n        }\n        var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity);\n        result.placeholder = curryFunc.placeholder;\n        return result;\n      }\n      return curryFunc;\n    }\n\n    /**\n     * Creates a `_.defaults` or `_.defaultsDeep` function.\n     *\n     * @private\n     * @param {Function} assigner The function to assign values.\n     * @param {Function} customizer The function to customize assigned values.\n     * @returns {Function} Returns the new defaults function.\n     */\n    function createDefaults(assigner, customizer) {\n      return restParam(function(args) {\n        var object = args[0];\n        if (object == null) {\n          return object;\n        }\n        args.push(customizer);\n        return assigner.apply(undefined, args);\n      });\n    }\n\n    /**\n     * Creates a `_.max` or `_.min` function.\n     *\n     * @private\n     * @param {Function} comparator The function used to compare values.\n     * @param {*} exValue The initial extremum value.\n     * @returns {Function} Returns the new extremum function.\n     */\n    function createExtremum(comparator, exValue) {\n      return function(collection, iteratee, thisArg) {\n        if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {\n          iteratee = undefined;\n        }\n        iteratee = getCallback(iteratee, thisArg, 3);\n        if (iteratee.length == 1) {\n          collection = isArray(collection) ? collection : toIterable(collection);\n          var result = arrayExtremum(collection, iteratee, comparator, exValue);\n          if (!(collection.length && result === exValue)) {\n            return result;\n          }\n        }\n        return baseExtremum(collection, iteratee, comparator, exValue);\n      };\n    }\n\n    /**\n     * Creates a `_.find` or `_.findLast` function.\n     *\n     * @private\n     * @param {Function} eachFunc The function to iterate over a collection.\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new find function.\n     */\n    function createFind(eachFunc, fromRight) {\n      return function(collection, predicate, thisArg) {\n        predicate = getCallback(predicate, thisArg, 3);\n        if (isArray(collection)) {\n          var index = baseFindIndex(collection, predicate, fromRight);\n          return index > -1 ? collection[index] : undefined;\n        }\n        return baseFind(collection, predicate, eachFunc);\n      };\n    }\n\n    /**\n     * Creates a `_.findIndex` or `_.findLastIndex` function.\n     *\n     * @private\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new find function.\n     */\n    function createFindIndex(fromRight) {\n      return function(array, predicate, thisArg) {\n        if (!(array && array.length)) {\n          return -1;\n        }\n        predicate = getCallback(predicate, thisArg, 3);\n        return baseFindIndex(array, predicate, fromRight);\n      };\n    }\n\n    /**\n     * Creates a `_.findKey` or `_.findLastKey` function.\n     *\n     * @private\n     * @param {Function} objectFunc The function to iterate over an object.\n     * @returns {Function} Returns the new find function.\n     */\n    function createFindKey(objectFunc) {\n      return function(object, predicate, thisArg) {\n        predicate = getCallback(predicate, thisArg, 3);\n        return baseFind(object, predicate, objectFunc, true);\n      };\n    }\n\n    /**\n     * Creates a `_.flow` or `_.flowRight` function.\n     *\n     * @private\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new flow function.\n     */\n    function createFlow(fromRight) {\n      return function() {\n        var wrapper,\n            length = arguments.length,\n            index = fromRight ? length : -1,\n            leftIndex = 0,\n            funcs = Array(length);\n\n        while ((fromRight ? index-- : ++index < length)) {\n          var func = funcs[leftIndex++] = arguments[index];\n          if (typeof func != 'function') {\n            throw new TypeError(FUNC_ERROR_TEXT);\n          }\n          if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') {\n            wrapper = new LodashWrapper([], true);\n          }\n        }\n        index = wrapper ? -1 : length;\n        while (++index < length) {\n          func = funcs[index];\n\n          var funcName = getFuncName(func),\n              data = funcName == 'wrapper' ? getData(func) : undefined;\n\n          if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {\n            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);\n          } else {\n            wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);\n          }\n        }\n        return function() {\n          var args = arguments,\n              value = args[0];\n\n          if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {\n            return wrapper.plant(value).value();\n          }\n          var index = 0,\n              result = length ? funcs[index].apply(this, args) : value;\n\n          while (++index < length) {\n            result = funcs[index].call(this, result);\n          }\n          return result;\n        };\n      };\n    }\n\n    /**\n     * Creates a function for `_.forEach` or `_.forEachRight`.\n     *\n     * @private\n     * @param {Function} arrayFunc The function to iterate over an array.\n     * @param {Function} eachFunc The function to iterate over a collection.\n     * @returns {Function} Returns the new each function.\n     */\n    function createForEach(arrayFunc, eachFunc) {\n      return function(collection, iteratee, thisArg) {\n        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))\n          ? arrayFunc(collection, iteratee)\n          : eachFunc(collection, bindCallback(iteratee, thisArg, 3));\n      };\n    }\n\n    /**\n     * Creates a function for `_.forIn` or `_.forInRight`.\n     *\n     * @private\n     * @param {Function} objectFunc The function to iterate over an object.\n     * @returns {Function} Returns the new each function.\n     */\n    function createForIn(objectFunc) {\n      return function(object, iteratee, thisArg) {\n        if (typeof iteratee != 'function' || thisArg !== undefined) {\n          iteratee = bindCallback(iteratee, thisArg, 3);\n        }\n        return objectFunc(object, iteratee, keysIn);\n      };\n    }\n\n    /**\n     * Creates a function for `_.forOwn` or `_.forOwnRight`.\n     *\n     * @private\n     * @param {Function} objectFunc The function to iterate over an object.\n     * @returns {Function} Returns the new each function.\n     */\n    function createForOwn(objectFunc) {\n      return function(object, iteratee, thisArg) {\n        if (typeof iteratee != 'function' || thisArg !== undefined) {\n          iteratee = bindCallback(iteratee, thisArg, 3);\n        }\n        return objectFunc(object, iteratee);\n      };\n    }\n\n    /**\n     * Creates a function for `_.mapKeys` or `_.mapValues`.\n     *\n     * @private\n     * @param {boolean} [isMapKeys] Specify mapping keys instead of values.\n     * @returns {Function} Returns the new map function.\n     */\n    function createObjectMapper(isMapKeys) {\n      return function(object, iteratee, thisArg) {\n        var result = {};\n        iteratee = getCallback(iteratee, thisArg, 3);\n\n        baseForOwn(object, function(value, key, object) {\n          var mapped = iteratee(value, key, object);\n          key = isMapKeys ? mapped : key;\n          value = isMapKeys ? value : mapped;\n          result[key] = value;\n        });\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function for `_.padLeft` or `_.padRight`.\n     *\n     * @private\n     * @param {boolean} [fromRight] Specify padding from the right.\n     * @returns {Function} Returns the new pad function.\n     */\n    function createPadDir(fromRight) {\n      return function(string, length, chars) {\n        string = baseToString(string);\n        return (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string);\n      };\n    }\n\n    /**\n     * Creates a `_.partial` or `_.partialRight` function.\n     *\n     * @private\n     * @param {boolean} flag The partial bit flag.\n     * @returns {Function} Returns the new partial function.\n     */\n    function createPartial(flag) {\n      var partialFunc = restParam(function(func, partials) {\n        var holders = replaceHolders(partials, partialFunc.placeholder);\n        return createWrapper(func, flag, undefined, partials, holders);\n      });\n      return partialFunc;\n    }\n\n    /**\n     * Creates a function for `_.reduce` or `_.reduceRight`.\n     *\n     * @private\n     * @param {Function} arrayFunc The function to iterate over an array.\n     * @param {Function} eachFunc The function to iterate over a collection.\n     * @returns {Function} Returns the new each function.\n     */\n    function createReduce(arrayFunc, eachFunc) {\n      return function(collection, iteratee, accumulator, thisArg) {\n        var initFromArray = arguments.length < 3;\n        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))\n          ? arrayFunc(collection, iteratee, accumulator, initFromArray)\n          : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);\n      };\n    }\n\n    /**\n     * Creates a function that wraps `func` and invokes it with optional `this`\n     * binding of, partial application, and currying.\n     *\n     * @private\n     * @param {Function|string} func The function or method name to reference.\n     * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param {Array} [partials] The arguments to prepend to those provided to the new function.\n     * @param {Array} [holders] The `partials` placeholder indexes.\n     * @param {Array} [partialsRight] The arguments to append to those provided to the new function.\n     * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.\n     * @param {Array} [argPos] The argument positions of the new function.\n     * @param {number} [ary] The arity cap of `func`.\n     * @param {number} [arity] The arity of `func`.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {\n      var isAry = bitmask & ARY_FLAG,\n          isBind = bitmask & BIND_FLAG,\n          isBindKey = bitmask & BIND_KEY_FLAG,\n          isCurry = bitmask & CURRY_FLAG,\n          isCurryBound = bitmask & CURRY_BOUND_FLAG,\n          isCurryRight = bitmask & CURRY_RIGHT_FLAG,\n          Ctor = isBindKey ? undefined : createCtorWrapper(func);\n\n      function wrapper() {\n        // Avoid `arguments` object use disqualifying optimizations by\n        // converting it to an array before providing it to other functions.\n        var length = arguments.length,\n            index = length,\n            args = Array(length);\n\n        while (index--) {\n          args[index] = arguments[index];\n        }\n        if (partials) {\n          args = composeArgs(args, partials, holders);\n        }\n        if (partialsRight) {\n          args = composeArgsRight(args, partialsRight, holdersRight);\n        }\n        if (isCurry || isCurryRight) {\n          var placeholder = wrapper.placeholder,\n              argsHolders = replaceHolders(args, placeholder);\n\n          length -= argsHolders.length;\n          if (length < arity) {\n            var newArgPos = argPos ? arrayCopy(argPos) : undefined,\n                newArity = nativeMax(arity - length, 0),\n                newsHolders = isCurry ? argsHolders : undefined,\n                newHoldersRight = isCurry ? undefined : argsHolders,\n                newPartials = isCurry ? args : undefined,\n                newPartialsRight = isCurry ? undefined : args;\n\n            bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);\n            bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);\n\n            if (!isCurryBound) {\n              bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);\n            }\n            var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],\n                result = createHybridWrapper.apply(undefined, newData);\n\n            if (isLaziable(func)) {\n              setData(result, newData);\n            }\n            result.placeholder = placeholder;\n            return result;\n          }\n        }\n        var thisBinding = isBind ? thisArg : this,\n            fn = isBindKey ? thisBinding[func] : func;\n\n        if (argPos) {\n          args = reorder(args, argPos);\n        }\n        if (isAry && ary < args.length) {\n          args.length = ary;\n        }\n        if (this && this !== root && this instanceof wrapper) {\n          fn = Ctor || createCtorWrapper(func);\n        }\n        return fn.apply(thisBinding, args);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates the padding required for `string` based on the given `length`.\n     * The `chars` string is truncated if the number of characters exceeds `length`.\n     *\n     * @private\n     * @param {string} string The string to create padding for.\n     * @param {number} [length=0] The padding length.\n     * @param {string} [chars=' '] The string used as padding.\n     * @returns {string} Returns the pad for `string`.\n     */\n    function createPadding(string, length, chars) {\n      var strLength = string.length;\n      length = +length;\n\n      if (strLength >= length || !nativeIsFinite(length)) {\n        return '';\n      }\n      var padLength = length - strLength;\n      chars = chars == null ? ' ' : (chars + '');\n      return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength);\n    }\n\n    /**\n     * Creates a function that wraps `func` and invokes it with the optional `this`\n     * binding of `thisArg` and the `partials` prepended to those provided to\n     * the wrapper.\n     *\n     * @private\n     * @param {Function} func The function to partially apply arguments to.\n     * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.\n     * @param {*} thisArg The `this` binding of `func`.\n     * @param {Array} partials The arguments to prepend to those provided to the new function.\n     * @returns {Function} Returns the new bound function.\n     */\n    function createPartialWrapper(func, bitmask, thisArg, partials) {\n      var isBind = bitmask & BIND_FLAG,\n          Ctor = createCtorWrapper(func);\n\n      function wrapper() {\n        // Avoid `arguments` object use disqualifying optimizations by\n        // converting it to an array before providing it `func`.\n        var argsIndex = -1,\n            argsLength = arguments.length,\n            leftIndex = -1,\n            leftLength = partials.length,\n            args = Array(leftLength + argsLength);\n\n        while (++leftIndex < leftLength) {\n          args[leftIndex] = partials[leftIndex];\n        }\n        while (argsLength--) {\n          args[leftIndex++] = arguments[++argsIndex];\n        }\n        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n        return fn.apply(isBind ? thisArg : this, args);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a `_.ceil`, `_.floor`, or `_.round` function.\n     *\n     * @private\n     * @param {string} methodName The name of the `Math` method to use when rounding.\n     * @returns {Function} Returns the new round function.\n     */\n    function createRound(methodName) {\n      var func = Math[methodName];\n      return function(number, precision) {\n        precision = precision === undefined ? 0 : (+precision || 0);\n        if (precision) {\n          precision = pow(10, precision);\n          return func(number * precision) / precision;\n        }\n        return func(number);\n      };\n    }\n\n    /**\n     * Creates a `_.sortedIndex` or `_.sortedLastIndex` function.\n     *\n     * @private\n     * @param {boolean} [retHighest] Specify returning the highest qualified index.\n     * @returns {Function} Returns the new index function.\n     */\n    function createSortedIndex(retHighest) {\n      return function(array, value, iteratee, thisArg) {\n        var callback = getCallback(iteratee);\n        return (iteratee == null && callback === baseCallback)\n          ? binaryIndex(array, value, retHighest)\n          : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest);\n      };\n    }\n\n    /**\n     * Creates a function that either curries or invokes `func` with optional\n     * `this` binding and partially applied arguments.\n     *\n     * @private\n     * @param {Function|string} func The function or method name to reference.\n     * @param {number} bitmask The bitmask of flags.\n     *  The bitmask may be composed of the following flags:\n     *     1 - `_.bind`\n     *     2 - `_.bindKey`\n     *     4 - `_.curry` or `_.curryRight` of a bound function\n     *     8 - `_.curry`\n     *    16 - `_.curryRight`\n     *    32 - `_.partial`\n     *    64 - `_.partialRight`\n     *   128 - `_.rearg`\n     *   256 - `_.ary`\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param {Array} [partials] The arguments to be partially applied.\n     * @param {Array} [holders] The `partials` placeholder indexes.\n     * @param {Array} [argPos] The argument positions of the new function.\n     * @param {number} [ary] The arity cap of `func`.\n     * @param {number} [arity] The arity of `func`.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {\n      var isBindKey = bitmask & BIND_KEY_FLAG;\n      if (!isBindKey && typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      var length = partials ? partials.length : 0;\n      if (!length) {\n        bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);\n        partials = holders = undefined;\n      }\n      length -= (holders ? holders.length : 0);\n      if (bitmask & PARTIAL_RIGHT_FLAG) {\n        var partialsRight = partials,\n            holdersRight = holders;\n\n        partials = holders = undefined;\n      }\n      var data = isBindKey ? undefined : getData(func),\n          newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];\n\n      if (data) {\n        mergeData(newData, data);\n        bitmask = newData[1];\n        arity = newData[9];\n      }\n      newData[9] = arity == null\n        ? (isBindKey ? 0 : func.length)\n        : (nativeMax(arity - length, 0) || 0);\n\n      if (bitmask == BIND_FLAG) {\n        var result = createBindWrapper(newData[0], newData[2]);\n      } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {\n        result = createPartialWrapper.apply(undefined, newData);\n      } else {\n        result = createHybridWrapper.apply(undefined, newData);\n      }\n      var setter = data ? baseSetData : setData;\n      return setter(result, newData);\n    }\n\n    /**\n     * A specialized version of `baseIsEqualDeep` for arrays with support for\n     * partial deep comparisons.\n     *\n     * @private\n     * @param {Array} array The array to compare.\n     * @param {Array} other The other array to compare.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Function} [customizer] The function to customize comparing arrays.\n     * @param {boolean} [isLoose] Specify performing partial comparisons.\n     * @param {Array} [stackA] Tracks traversed `value` objects.\n     * @param {Array} [stackB] Tracks traversed `other` objects.\n     * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n     */\n    function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {\n      var index = -1,\n          arrLength = array.length,\n          othLength = other.length;\n\n      if (arrLength != othLength && !(isLoose && othLength > arrLength)) {\n        return false;\n      }\n      // Ignore non-index properties.\n      while (++index < arrLength) {\n        var arrValue = array[index],\n            othValue = other[index],\n            result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;\n\n        if (result !== undefined) {\n          if (result) {\n            continue;\n          }\n          return false;\n        }\n        // Recursively compare arrays (susceptible to call stack limits).\n        if (isLoose) {\n          if (!arraySome(other, function(othValue) {\n                return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);\n              })) {\n            return false;\n          }\n        } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n    /**\n     * A specialized version of `baseIsEqualDeep` for comparing objects of\n     * the same `toStringTag`.\n     *\n     * **Note:** This function only supports comparing values with tags of\n     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n     *\n     * @private\n     * @param {Object} object The object to compare.\n     * @param {Object} other The other object to compare.\n     * @param {string} tag The `toStringTag` of the objects to compare.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function equalByTag(object, other, tag) {\n      switch (tag) {\n        case boolTag:\n        case dateTag:\n          // Coerce dates and booleans to numbers, dates to milliseconds and booleans\n          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.\n          return +object == +other;\n\n        case errorTag:\n          return object.name == other.name && object.message == other.message;\n\n        case numberTag:\n          // Treat `NaN` vs. `NaN` as equal.\n          return (object != +object)\n            ? other != +other\n            : object == +other;\n\n        case regexpTag:\n        case stringTag:\n          // Coerce regexes to strings and treat strings primitives and string\n          // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.\n          return object == (other + '');\n      }\n      return false;\n    }\n\n    /**\n     * A specialized version of `baseIsEqualDeep` for objects with support for\n     * partial deep comparisons.\n     *\n     * @private\n     * @param {Object} object The object to compare.\n     * @param {Object} other The other object to compare.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Function} [customizer] The function to customize comparing values.\n     * @param {boolean} [isLoose] Specify performing partial comparisons.\n     * @param {Array} [stackA] Tracks traversed `value` objects.\n     * @param {Array} [stackB] Tracks traversed `other` objects.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n      var objProps = keys(object),\n          objLength = objProps.length,\n          othProps = keys(other),\n          othLength = othProps.length;\n\n      if (objLength != othLength && !isLoose) {\n        return false;\n      }\n      var index = objLength;\n      while (index--) {\n        var key = objProps[index];\n        if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {\n          return false;\n        }\n      }\n      var skipCtor = isLoose;\n      while (++index < objLength) {\n        key = objProps[index];\n        var objValue = object[key],\n            othValue = other[key],\n            result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;\n\n        // Recursively compare objects (susceptible to call stack limits).\n        if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {\n          return false;\n        }\n        skipCtor || (skipCtor = key == 'constructor');\n      }\n      if (!skipCtor) {\n        var objCtor = object.constructor,\n            othCtor = other.constructor;\n\n        // Non `Object` object instances with different constructors are not equal.\n        if (objCtor != othCtor &&\n            ('constructor' in object && 'constructor' in other) &&\n            !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n              typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n    /**\n     * Gets the appropriate \"callback\" function. If the `_.callback` method is\n     * customized this function returns the custom method, otherwise it returns\n     * the `baseCallback` function. If arguments are provided the chosen function\n     * is invoked with them and its result is returned.\n     *\n     * @private\n     * @returns {Function} Returns the chosen function or its result.\n     */\n    function getCallback(func, thisArg, argCount) {\n      var result = lodash.callback || callback;\n      result = result === callback ? baseCallback : result;\n      return argCount ? result(func, thisArg, argCount) : result;\n    }\n\n    /**\n     * Gets metadata for `func`.\n     *\n     * @private\n     * @param {Function} func The function to query.\n     * @returns {*} Returns the metadata for `func`.\n     */\n    var getData = !metaMap ? noop : function(func) {\n      return metaMap.get(func);\n    };\n\n    /**\n     * Gets the name of `func`.\n     *\n     * @private\n     * @param {Function} func The function to query.\n     * @returns {string} Returns the function name.\n     */\n    function getFuncName(func) {\n      var result = func.name,\n          array = realNames[result],\n          length = array ? array.length : 0;\n\n      while (length--) {\n        var data = array[length],\n            otherFunc = data.func;\n        if (otherFunc == null || otherFunc == func) {\n          return data.name;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Gets the appropriate \"indexOf\" function. If the `_.indexOf` method is\n     * customized this function returns the custom method, otherwise it returns\n     * the `baseIndexOf` function. If arguments are provided the chosen function\n     * is invoked with them and its result is returned.\n     *\n     * @private\n     * @returns {Function|number} Returns the chosen function or its result.\n     */\n    function getIndexOf(collection, target, fromIndex) {\n      var result = lodash.indexOf || indexOf;\n      result = result === indexOf ? baseIndexOf : result;\n      return collection ? result(collection, target, fromIndex) : result;\n    }\n\n    /**\n     * Gets the \"length\" property value of `object`.\n     *\n     * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n     * that affects Safari on at least iOS 8.1-8.3 ARM64.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {*} Returns the \"length\" value.\n     */\n    var getLength = baseProperty('length');\n\n    /**\n     * Gets the propery names, values, and compare flags of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the match data of `object`.\n     */\n    function getMatchData(object) {\n      var result = pairs(object),\n          length = result.length;\n\n      while (length--) {\n        result[length][2] = isStrictComparable(result[length][1]);\n      }\n      return result;\n    }\n\n    /**\n     * Gets the native function at `key` of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {string} key The key of the method to get.\n     * @returns {*} Returns the function if it's native, else `undefined`.\n     */\n    function getNative(object, key) {\n      var value = object == null ? undefined : object[key];\n      return isNative(value) ? value : undefined;\n    }\n\n    /**\n     * Gets the view, applying any `transforms` to the `start` and `end` positions.\n     *\n     * @private\n     * @param {number} start The start of the view.\n     * @param {number} end The end of the view.\n     * @param {Array} transforms The transformations to apply to the view.\n     * @returns {Object} Returns an object containing the `start` and `end`\n     *  positions of the view.\n     */\n    function getView(start, end, transforms) {\n      var index = -1,\n          length = transforms.length;\n\n      while (++index < length) {\n        var data = transforms[index],\n            size = data.size;\n\n        switch (data.type) {\n          case 'drop':      start += size; break;\n          case 'dropRight': end -= size; break;\n          case 'take':      end = nativeMin(end, start + size); break;\n          case 'takeRight': start = nativeMax(start, end - size); break;\n        }\n      }\n      return { 'start': start, 'end': end };\n    }\n\n    /**\n     * Initializes an array clone.\n     *\n     * @private\n     * @param {Array} array The array to clone.\n     * @returns {Array} Returns the initialized clone.\n     */\n    function initCloneArray(array) {\n      var length = array.length,\n          result = new array.constructor(length);\n\n      // Add array properties assigned by `RegExp#exec`.\n      if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n        result.index = array.index;\n        result.input = array.input;\n      }\n      return result;\n    }\n\n    /**\n     * Initializes an object clone.\n     *\n     * @private\n     * @param {Object} object The object to clone.\n     * @returns {Object} Returns the initialized clone.\n     */\n    function initCloneObject(object) {\n      var Ctor = object.constructor;\n      if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {\n        Ctor = Object;\n      }\n      return new Ctor;\n    }\n\n    /**\n     * Initializes an object clone based on its `toStringTag`.\n     *\n     * **Note:** This function only supports cloning values with tags of\n     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n     *\n     * @private\n     * @param {Object} object The object to clone.\n     * @param {string} tag The `toStringTag` of the object to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @returns {Object} Returns the initialized clone.\n     */\n    function initCloneByTag(object, tag, isDeep) {\n      var Ctor = object.constructor;\n      switch (tag) {\n        case arrayBufferTag:\n          return bufferClone(object);\n\n        case boolTag:\n        case dateTag:\n          return new Ctor(+object);\n\n        case float32Tag: case float64Tag:\n        case int8Tag: case int16Tag: case int32Tag:\n        case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n          var buffer = object.buffer;\n          return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);\n\n        case numberTag:\n        case stringTag:\n          return new Ctor(object);\n\n        case regexpTag:\n          var result = new Ctor(object.source, reFlags.exec(object));\n          result.lastIndex = object.lastIndex;\n      }\n      return result;\n    }\n\n    /**\n     * Invokes the method at `path` on `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path of the method to invoke.\n     * @param {Array} args The arguments to invoke the method with.\n     * @returns {*} Returns the result of the invoked method.\n     */\n    function invokePath(object, path, args) {\n      if (object != null && !isKey(path, object)) {\n        path = toPath(path);\n        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n        path = last(path);\n      }\n      var func = object == null ? object : object[path];\n      return func == null ? undefined : func.apply(object, args);\n    }\n\n    /**\n     * Checks if `value` is array-like.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n     */\n    function isArrayLike(value) {\n      return value != null && isLength(getLength(value));\n    }\n\n    /**\n     * Checks if `value` is a valid array-like index.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n     * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n     */\n    function isIndex(value, length) {\n      value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;\n      length = length == null ? MAX_SAFE_INTEGER : length;\n      return value > -1 && value % 1 == 0 && value < length;\n    }\n\n    /**\n     * Checks if the provided arguments are from an iteratee call.\n     *\n     * @private\n     * @param {*} value The potential iteratee value argument.\n     * @param {*} index The potential iteratee index or key argument.\n     * @param {*} object The potential iteratee object argument.\n     * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.\n     */\n    function isIterateeCall(value, index, object) {\n      if (!isObject(object)) {\n        return false;\n      }\n      var type = typeof index;\n      if (type == 'number'\n          ? (isArrayLike(object) && isIndex(index, object.length))\n          : (type == 'string' && index in object)) {\n        var other = object[index];\n        return value === value ? (value === other) : (other !== other);\n      }\n      return false;\n    }\n\n    /**\n     * Checks if `value` is a property name and not a property path.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @param {Object} [object] The object to query keys on.\n     * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n     */\n    function isKey(value, object) {\n      var type = typeof value;\n      if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {\n        return true;\n      }\n      if (isArray(value)) {\n        return false;\n      }\n      var result = !reIsDeepProp.test(value);\n      return result || (object != null && value in toObject(object));\n    }\n\n    /**\n     * Checks if `func` has a lazy counterpart.\n     *\n     * @private\n     * @param {Function} func The function to check.\n     * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.\n     */\n    function isLaziable(func) {\n      var funcName = getFuncName(func);\n      if (!(funcName in LazyWrapper.prototype)) {\n        return false;\n      }\n      var other = lodash[funcName];\n      if (func === other) {\n        return true;\n      }\n      var data = getData(other);\n      return !!data && func === data[0];\n    }\n\n    /**\n     * Checks if `value` is a valid array-like length.\n     *\n     * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n     */\n    function isLength(value) {\n      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n    }\n\n    /**\n     * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` if suitable for strict\n     *  equality comparisons, else `false`.\n     */\n    function isStrictComparable(value) {\n      return value === value && !isObject(value);\n    }\n\n    /**\n     * Merges the function metadata of `source` into `data`.\n     *\n     * Merging metadata reduces the number of wrappers required to invoke a function.\n     * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`\n     * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`\n     * augment function arguments, making the order in which they are executed important,\n     * preventing the merging of metadata. However, we make an exception for a safe\n     * common case where curried functions have `_.ary` and or `_.rearg` applied.\n     *\n     * @private\n     * @param {Array} data The destination metadata.\n     * @param {Array} source The source metadata.\n     * @returns {Array} Returns `data`.\n     */\n    function mergeData(data, source) {\n      var bitmask = data[1],\n          srcBitmask = source[1],\n          newBitmask = bitmask | srcBitmask,\n          isCommon = newBitmask < ARY_FLAG;\n\n      var isCombo =\n        (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||\n        (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||\n        (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);\n\n      // Exit early if metadata can't be merged.\n      if (!(isCommon || isCombo)) {\n        return data;\n      }\n      // Use source `thisArg` if available.\n      if (srcBitmask & BIND_FLAG) {\n        data[2] = source[2];\n        // Set when currying a bound function.\n        newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;\n      }\n      // Compose partial arguments.\n      var value = source[3];\n      if (value) {\n        var partials = data[3];\n        data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);\n        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);\n      }\n      // Compose partial right arguments.\n      value = source[5];\n      if (value) {\n        partials = data[5];\n        data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);\n        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);\n      }\n      // Use source `argPos` if available.\n      value = source[7];\n      if (value) {\n        data[7] = arrayCopy(value);\n      }\n      // Use source `ary` if it's smaller.\n      if (srcBitmask & ARY_FLAG) {\n        data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);\n      }\n      // Use source `arity` if one is not provided.\n      if (data[9] == null) {\n        data[9] = source[9];\n      }\n      // Use source `func` and merge bitmasks.\n      data[0] = source[0];\n      data[1] = newBitmask;\n\n      return data;\n    }\n\n    /**\n     * Used by `_.defaultsDeep` to customize its `_.merge` use.\n     *\n     * @private\n     * @param {*} objectValue The destination object property value.\n     * @param {*} sourceValue The source object property value.\n     * @returns {*} Returns the value to assign to the destination object.\n     */\n    function mergeDefaults(objectValue, sourceValue) {\n      return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults);\n    }\n\n    /**\n     * A specialized version of `_.pick` which picks `object` properties specified\n     * by `props`.\n     *\n     * @private\n     * @param {Object} object The source object.\n     * @param {string[]} props The property names to pick.\n     * @returns {Object} Returns the new object.\n     */\n    function pickByArray(object, props) {\n      object = toObject(object);\n\n      var index = -1,\n          length = props.length,\n          result = {};\n\n      while (++index < length) {\n        var key = props[index];\n        if (key in object) {\n          result[key] = object[key];\n        }\n      }\n      return result;\n    }\n\n    /**\n     * A specialized version of `_.pick` which picks `object` properties `predicate`\n     * returns truthy for.\n     *\n     * @private\n     * @param {Object} object The source object.\n     * @param {Function} predicate The function invoked per iteration.\n     * @returns {Object} Returns the new object.\n     */\n    function pickByCallback(object, predicate) {\n      var result = {};\n      baseForIn(object, function(value, key, object) {\n        if (predicate(value, key, object)) {\n          result[key] = value;\n        }\n      });\n      return result;\n    }\n\n    /**\n     * Reorder `array` according to the specified indexes where the element at\n     * the first index is assigned as the first element, the element at\n     * the second index is assigned as the second element, and so on.\n     *\n     * @private\n     * @param {Array} array The array to reorder.\n     * @param {Array} indexes The arranged array indexes.\n     * @returns {Array} Returns `array`.\n     */\n    function reorder(array, indexes) {\n      var arrLength = array.length,\n          length = nativeMin(indexes.length, arrLength),\n          oldArray = arrayCopy(array);\n\n      while (length--) {\n        var index = indexes[length];\n        array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;\n      }\n      return array;\n    }\n\n    /**\n     * Sets metadata for `func`.\n     *\n     * **Note:** If this function becomes hot, i.e. is invoked a lot in a short\n     * period of time, it will trip its breaker and transition to an identity function\n     * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)\n     * for more details.\n     *\n     * @private\n     * @param {Function} func The function to associate metadata with.\n     * @param {*} data The metadata.\n     * @returns {Function} Returns `func`.\n     */\n    var setData = (function() {\n      var count = 0,\n          lastCalled = 0;\n\n      return function(key, value) {\n        var stamp = now(),\n            remaining = HOT_SPAN - (stamp - lastCalled);\n\n        lastCalled = stamp;\n        if (remaining > 0) {\n          if (++count >= HOT_COUNT) {\n            return key;\n          }\n        } else {\n          count = 0;\n        }\n        return baseSetData(key, value);\n      };\n    }());\n\n    /**\n     * A fallback implementation of `Object.keys` which creates an array of the\n     * own enumerable property names of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     */\n    function shimKeys(object) {\n      var props = keysIn(object),\n          propsLength = props.length,\n          length = propsLength && object.length;\n\n      var allowIndexes = !!length && isLength(length) &&\n        (isArray(object) || isArguments(object));\n\n      var index = -1,\n          result = [];\n\n      while (++index < propsLength) {\n        var key = props[index];\n        if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Converts `value` to an array-like object if it's not one.\n     *\n     * @private\n     * @param {*} value The value to process.\n     * @returns {Array|Object} Returns the array-like object.\n     */\n    function toIterable(value) {\n      if (value == null) {\n        return [];\n      }\n      if (!isArrayLike(value)) {\n        return values(value);\n      }\n      return isObject(value) ? value : Object(value);\n    }\n\n    /**\n     * Converts `value` to an object if it's not one.\n     *\n     * @private\n     * @param {*} value The value to process.\n     * @returns {Object} Returns the object.\n     */\n    function toObject(value) {\n      return isObject(value) ? value : Object(value);\n    }\n\n    /**\n     * Converts `value` to property path array if it's not one.\n     *\n     * @private\n     * @param {*} value The value to process.\n     * @returns {Array} Returns the property path array.\n     */\n    function toPath(value) {\n      if (isArray(value)) {\n        return value;\n      }\n      var result = [];\n      baseToString(value).replace(rePropName, function(match, number, quote, string) {\n        result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n      });\n      return result;\n    }\n\n    /**\n     * Creates a clone of `wrapper`.\n     *\n     * @private\n     * @param {Object} wrapper The wrapper to clone.\n     * @returns {Object} Returns the cloned wrapper.\n     */\n    function wrapperClone(wrapper) {\n      return wrapper instanceof LazyWrapper\n        ? wrapper.clone()\n        : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array of elements split into groups the length of `size`.\n     * If `collection` can't be split evenly, the final chunk will be the remaining\n     * elements.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to process.\n     * @param {number} [size=1] The length of each chunk.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the new array containing chunks.\n     * @example\n     *\n     * _.chunk(['a', 'b', 'c', 'd'], 2);\n     * // => [['a', 'b'], ['c', 'd']]\n     *\n     * _.chunk(['a', 'b', 'c', 'd'], 3);\n     * // => [['a', 'b', 'c'], ['d']]\n     */\n    function chunk(array, size, guard) {\n      if (guard ? isIterateeCall(array, size, guard) : size == null) {\n        size = 1;\n      } else {\n        size = nativeMax(nativeFloor(size) || 1, 1);\n      }\n      var index = 0,\n          length = array ? array.length : 0,\n          resIndex = -1,\n          result = Array(nativeCeil(length / size));\n\n      while (index < length) {\n        result[++resIndex] = baseSlice(array, index, (index += size));\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array with all falsey values removed. The values `false`, `null`,\n     * `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to compact.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * _.compact([0, 1, false, 2, '', 3]);\n     * // => [1, 2, 3]\n     */\n    function compact(array) {\n      var index = -1,\n          length = array ? array.length : 0,\n          resIndex = -1,\n          result = [];\n\n      while (++index < length) {\n        var value = array[index];\n        if (value) {\n          result[++resIndex] = value;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array of unique `array` values not included in the other\n     * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {...Array} [values] The arrays of values to exclude.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * _.difference([1, 2, 3], [4, 2]);\n     * // => [1, 3]\n     */\n    var difference = restParam(function(array, values) {\n      return (isObjectLike(array) && isArrayLike(array))\n        ? baseDifference(array, baseFlatten(values, false, true))\n        : [];\n    });\n\n    /**\n     * Creates a slice of `array` with `n` elements dropped from the beginning.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {number} [n=1] The number of elements to drop.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.drop([1, 2, 3]);\n     * // => [2, 3]\n     *\n     * _.drop([1, 2, 3], 2);\n     * // => [3]\n     *\n     * _.drop([1, 2, 3], 5);\n     * // => []\n     *\n     * _.drop([1, 2, 3], 0);\n     * // => [1, 2, 3]\n     */\n    function drop(array, n, guard) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (guard ? isIterateeCall(array, n, guard) : n == null) {\n        n = 1;\n      }\n      return baseSlice(array, n < 0 ? 0 : n);\n    }\n\n    /**\n     * Creates a slice of `array` with `n` elements dropped from the end.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {number} [n=1] The number of elements to drop.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.dropRight([1, 2, 3]);\n     * // => [1, 2]\n     *\n     * _.dropRight([1, 2, 3], 2);\n     * // => [1]\n     *\n     * _.dropRight([1, 2, 3], 5);\n     * // => []\n     *\n     * _.dropRight([1, 2, 3], 0);\n     * // => [1, 2, 3]\n     */\n    function dropRight(array, n, guard) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (guard ? isIterateeCall(array, n, guard) : n == null) {\n        n = 1;\n      }\n      n = length - (+n || 0);\n      return baseSlice(array, 0, n < 0 ? 0 : n);\n    }\n\n    /**\n     * Creates a slice of `array` excluding elements dropped from the end.\n     * Elements are dropped until `predicate` returns falsey. The predicate is\n     * bound to `thisArg` and invoked with three arguments: (value, index, array).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that match the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.dropRightWhile([1, 2, 3], function(n) {\n     *   return n > 1;\n     * });\n     * // => [1]\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': true },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': false }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');\n     * // => ['barney', 'fred']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.dropRightWhile(users, 'active', false), 'user');\n     * // => ['barney']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.dropRightWhile(users, 'active'), 'user');\n     * // => ['barney', 'fred', 'pebbles']\n     */\n    function dropRightWhile(array, predicate, thisArg) {\n      return (array && array.length)\n        ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)\n        : [];\n    }\n\n    /**\n     * Creates a slice of `array` excluding elements dropped from the beginning.\n     * Elements are dropped until `predicate` returns falsey. The predicate is\n     * bound to `thisArg` and invoked with three arguments: (value, index, array).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.dropWhile([1, 2, 3], function(n) {\n     *   return n < 3;\n     * });\n     * // => [3]\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': false },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': true }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');\n     * // => ['fred', 'pebbles']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.dropWhile(users, 'active', false), 'user');\n     * // => ['pebbles']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.dropWhile(users, 'active'), 'user');\n     * // => ['barney', 'fred', 'pebbles']\n     */\n    function dropWhile(array, predicate, thisArg) {\n      return (array && array.length)\n        ? baseWhile(array, getCallback(predicate, thisArg, 3), true)\n        : [];\n    }\n\n    /**\n     * Fills elements of `array` with `value` from `start` up to, but not\n     * including, `end`.\n     *\n     * **Note:** This method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to fill.\n     * @param {*} value The value to fill `array` with.\n     * @param {number} [start=0] The start position.\n     * @param {number} [end=array.length] The end position.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = [1, 2, 3];\n     *\n     * _.fill(array, 'a');\n     * console.log(array);\n     * // => ['a', 'a', 'a']\n     *\n     * _.fill(Array(3), 2);\n     * // => [2, 2, 2]\n     *\n     * _.fill([4, 6, 8], '*', 1, 2);\n     * // => [4, '*', 8]\n     */\n    function fill(array, value, start, end) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {\n        start = 0;\n        end = length;\n      }\n      return baseFill(array, value, start, end);\n    }\n\n    /**\n     * This method is like `_.find` except that it returns the index of the first\n     * element `predicate` returns truthy for instead of the element itself.\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {number} Returns the index of the found element, else `-1`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': false },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': true }\n     * ];\n     *\n     * _.findIndex(users, function(chr) {\n     *   return chr.user == 'barney';\n     * });\n     * // => 0\n     *\n     * // using the `_.matches` callback shorthand\n     * _.findIndex(users, { 'user': 'fred', 'active': false });\n     * // => 1\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.findIndex(users, 'active', false);\n     * // => 0\n     *\n     * // using the `_.property` callback shorthand\n     * _.findIndex(users, 'active');\n     * // => 2\n     */\n    var findIndex = createFindIndex();\n\n    /**\n     * This method is like `_.findIndex` except that it iterates over elements\n     * of `collection` from right to left.\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {number} Returns the index of the found element, else `-1`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': true },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': false }\n     * ];\n     *\n     * _.findLastIndex(users, function(chr) {\n     *   return chr.user == 'pebbles';\n     * });\n     * // => 2\n     *\n     * // using the `_.matches` callback shorthand\n     * _.findLastIndex(users, { 'user': 'barney', 'active': true });\n     * // => 0\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.findLastIndex(users, 'active', false);\n     * // => 2\n     *\n     * // using the `_.property` callback shorthand\n     * _.findLastIndex(users, 'active');\n     * // => 0\n     */\n    var findLastIndex = createFindIndex(true);\n\n    /**\n     * Gets the first element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @alias head\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {*} Returns the first element of `array`.\n     * @example\n     *\n     * _.first([1, 2, 3]);\n     * // => 1\n     *\n     * _.first([]);\n     * // => undefined\n     */\n    function first(array) {\n      return array ? array[0] : undefined;\n    }\n\n    /**\n     * Flattens a nested array. If `isDeep` is `true` the array is recursively\n     * flattened, otherwise it is only flattened a single level.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to flatten.\n     * @param {boolean} [isDeep] Specify a deep flatten.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * _.flatten([1, [2, 3, [4]]]);\n     * // => [1, 2, 3, [4]]\n     *\n     * // using `isDeep`\n     * _.flatten([1, [2, 3, [4]]], true);\n     * // => [1, 2, 3, 4]\n     */\n    function flatten(array, isDeep, guard) {\n      var length = array ? array.length : 0;\n      if (guard && isIterateeCall(array, isDeep, guard)) {\n        isDeep = false;\n      }\n      return length ? baseFlatten(array, isDeep) : [];\n    }\n\n    /**\n     * Recursively flattens a nested array.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to recursively flatten.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * _.flattenDeep([1, [2, 3, [4]]]);\n     * // => [1, 2, 3, 4]\n     */\n    function flattenDeep(array) {\n      var length = array ? array.length : 0;\n      return length ? baseFlatten(array, true) : [];\n    }\n\n    /**\n     * Gets the index at which the first occurrence of `value` is found in `array`\n     * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons. If `fromIndex` is negative, it is used as the offset\n     * from the end of `array`. If `array` is sorted providing `true` for `fromIndex`\n     * performs a faster binary search.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to search.\n     * @param {*} value The value to search for.\n     * @param {boolean|number} [fromIndex=0] The index to search from or `true`\n     *  to perform a binary search on a sorted array.\n     * @returns {number} Returns the index of the matched value, else `-1`.\n     * @example\n     *\n     * _.indexOf([1, 2, 1, 2], 2);\n     * // => 1\n     *\n     * // using `fromIndex`\n     * _.indexOf([1, 2, 1, 2], 2, 2);\n     * // => 3\n     *\n     * // performing a binary search\n     * _.indexOf([1, 1, 2, 2], 2, true);\n     * // => 2\n     */\n    function indexOf(array, value, fromIndex) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return -1;\n      }\n      if (typeof fromIndex == 'number') {\n        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;\n      } else if (fromIndex) {\n        var index = binaryIndex(array, value);\n        if (index < length &&\n            (value === value ? (value === array[index]) : (array[index] !== array[index]))) {\n          return index;\n        }\n        return -1;\n      }\n      return baseIndexOf(array, value, fromIndex || 0);\n    }\n\n    /**\n     * Gets all but the last element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.initial([1, 2, 3]);\n     * // => [1, 2]\n     */\n    function initial(array) {\n      return dropRight(array, 1);\n    }\n\n    /**\n     * Creates an array of unique values that are included in all of the provided\n     * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @returns {Array} Returns the new array of shared values.\n     * @example\n     * _.intersection([1, 2], [4, 2], [2, 1]);\n     * // => [2]\n     */\n    var intersection = restParam(function(arrays) {\n      var othLength = arrays.length,\n          othIndex = othLength,\n          caches = Array(length),\n          indexOf = getIndexOf(),\n          isCommon = indexOf == baseIndexOf,\n          result = [];\n\n      while (othIndex--) {\n        var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : [];\n        caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null;\n      }\n      var array = arrays[0],\n          index = -1,\n          length = array ? array.length : 0,\n          seen = caches[0];\n\n      outer:\n      while (++index < length) {\n        value = array[index];\n        if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {\n          var othIndex = othLength;\n          while (--othIndex) {\n            var cache = caches[othIndex];\n            if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) {\n              continue outer;\n            }\n          }\n          if (seen) {\n            seen.push(value);\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    });\n\n    /**\n     * Gets the last element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {*} Returns the last element of `array`.\n     * @example\n     *\n     * _.last([1, 2, 3]);\n     * // => 3\n     */\n    function last(array) {\n      var length = array ? array.length : 0;\n      return length ? array[length - 1] : undefined;\n    }\n\n    /**\n     * This method is like `_.indexOf` except that it iterates over elements of\n     * `array` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to search.\n     * @param {*} value The value to search for.\n     * @param {boolean|number} [fromIndex=array.length-1] The index to search from\n     *  or `true` to perform a binary search on a sorted array.\n     * @returns {number} Returns the index of the matched value, else `-1`.\n     * @example\n     *\n     * _.lastIndexOf([1, 2, 1, 2], 2);\n     * // => 3\n     *\n     * // using `fromIndex`\n     * _.lastIndexOf([1, 2, 1, 2], 2, 2);\n     * // => 1\n     *\n     * // performing a binary search\n     * _.lastIndexOf([1, 1, 2, 2], 2, true);\n     * // => 3\n     */\n    function lastIndexOf(array, value, fromIndex) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return -1;\n      }\n      var index = length;\n      if (typeof fromIndex == 'number') {\n        index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;\n      } else if (fromIndex) {\n        index = binaryIndex(array, value, true) - 1;\n        var other = array[index];\n        if (value === value ? (value === other) : (other !== other)) {\n          return index;\n        }\n        return -1;\n      }\n      if (value !== value) {\n        return indexOfNaN(array, index, true);\n      }\n      while (index--) {\n        if (array[index] === value) {\n          return index;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * Removes all provided values from `array` using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * **Note:** Unlike `_.without`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {...*} [values] The values to remove.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = [1, 2, 3, 1, 2, 3];\n     *\n     * _.pull(array, 2, 3);\n     * console.log(array);\n     * // => [1, 1]\n     */\n    function pull() {\n      var args = arguments,\n          array = args[0];\n\n      if (!(array && array.length)) {\n        return array;\n      }\n      var index = 0,\n          indexOf = getIndexOf(),\n          length = args.length;\n\n      while (++index < length) {\n        var fromIndex = 0,\n            value = args[index];\n\n        while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {\n          splice.call(array, fromIndex, 1);\n        }\n      }\n      return array;\n    }\n\n    /**\n     * Removes elements from `array` corresponding to the given indexes and returns\n     * an array of the removed elements. Indexes may be specified as an array of\n     * indexes or as individual arguments.\n     *\n     * **Note:** Unlike `_.at`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {...(number|number[])} [indexes] The indexes of elements to remove,\n     *  specified as individual indexes or arrays of indexes.\n     * @returns {Array} Returns the new array of removed elements.\n     * @example\n     *\n     * var array = [5, 10, 15, 20];\n     * var evens = _.pullAt(array, 1, 3);\n     *\n     * console.log(array);\n     * // => [5, 15]\n     *\n     * console.log(evens);\n     * // => [10, 20]\n     */\n    var pullAt = restParam(function(array, indexes) {\n      indexes = baseFlatten(indexes);\n\n      var result = baseAt(array, indexes);\n      basePullAt(array, indexes.sort(baseCompareAscending));\n      return result;\n    });\n\n    /**\n     * Removes all elements from `array` that `predicate` returns truthy for\n     * and returns an array of the removed elements. The predicate is bound to\n     * `thisArg` and invoked with three arguments: (value, index, array).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * **Note:** Unlike `_.filter`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the new array of removed elements.\n     * @example\n     *\n     * var array = [1, 2, 3, 4];\n     * var evens = _.remove(array, function(n) {\n     *   return n % 2 == 0;\n     * });\n     *\n     * console.log(array);\n     * // => [1, 3]\n     *\n     * console.log(evens);\n     * // => [2, 4]\n     */\n    function remove(array, predicate, thisArg) {\n      var result = [];\n      if (!(array && array.length)) {\n        return result;\n      }\n      var index = -1,\n          indexes = [],\n          length = array.length;\n\n      predicate = getCallback(predicate, thisArg, 3);\n      while (++index < length) {\n        var value = array[index];\n        if (predicate(value, index, array)) {\n          result.push(value);\n          indexes.push(index);\n        }\n      }\n      basePullAt(array, indexes);\n      return result;\n    }\n\n    /**\n     * Gets all but the first element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @alias tail\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.rest([1, 2, 3]);\n     * // => [2, 3]\n     */\n    function rest(array) {\n      return drop(array, 1);\n    }\n\n    /**\n     * Creates a slice of `array` from `start` up to, but not including, `end`.\n     *\n     * **Note:** This method is used instead of `Array#slice` to support node\n     * lists in IE < 9 and to ensure dense arrays are returned.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to slice.\n     * @param {number} [start=0] The start position.\n     * @param {number} [end=array.length] The end position.\n     * @returns {Array} Returns the slice of `array`.\n     */\n    function slice(array, start, end) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {\n        start = 0;\n        end = length;\n      }\n      return baseSlice(array, start, end);\n    }\n\n    /**\n     * Uses a binary search to determine the lowest index at which `value` should\n     * be inserted into `array` in order to maintain its sort order. If an iteratee\n     * function is provided it is invoked for `value` and each element of `array`\n     * to compute their sort ranking. The iteratee is bound to `thisArg` and\n     * invoked with one argument; (value).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     * @example\n     *\n     * _.sortedIndex([30, 50], 40);\n     * // => 1\n     *\n     * _.sortedIndex([4, 4, 5, 5], 5);\n     * // => 2\n     *\n     * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };\n     *\n     * // using an iteratee function\n     * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {\n     *   return this.data[word];\n     * }, dict);\n     * // => 1\n     *\n     * // using the `_.property` callback shorthand\n     * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');\n     * // => 1\n     */\n    var sortedIndex = createSortedIndex();\n\n    /**\n     * This method is like `_.sortedIndex` except that it returns the highest\n     * index at which `value` should be inserted into `array` in order to\n     * maintain its sort order.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     * @example\n     *\n     * _.sortedLastIndex([4, 4, 5, 5], 5);\n     * // => 4\n     */\n    var sortedLastIndex = createSortedIndex(true);\n\n    /**\n     * Creates a slice of `array` with `n` elements taken from the beginning.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {number} [n=1] The number of elements to take.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.take([1, 2, 3]);\n     * // => [1]\n     *\n     * _.take([1, 2, 3], 2);\n     * // => [1, 2]\n     *\n     * _.take([1, 2, 3], 5);\n     * // => [1, 2, 3]\n     *\n     * _.take([1, 2, 3], 0);\n     * // => []\n     */\n    function take(array, n, guard) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (guard ? isIterateeCall(array, n, guard) : n == null) {\n        n = 1;\n      }\n      return baseSlice(array, 0, n < 0 ? 0 : n);\n    }\n\n    /**\n     * Creates a slice of `array` with `n` elements taken from the end.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {number} [n=1] The number of elements to take.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.takeRight([1, 2, 3]);\n     * // => [3]\n     *\n     * _.takeRight([1, 2, 3], 2);\n     * // => [2, 3]\n     *\n     * _.takeRight([1, 2, 3], 5);\n     * // => [1, 2, 3]\n     *\n     * _.takeRight([1, 2, 3], 0);\n     * // => []\n     */\n    function takeRight(array, n, guard) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (guard ? isIterateeCall(array, n, guard) : n == null) {\n        n = 1;\n      }\n      n = length - (+n || 0);\n      return baseSlice(array, n < 0 ? 0 : n);\n    }\n\n    /**\n     * Creates a slice of `array` with elements taken from the end. Elements are\n     * taken until `predicate` returns falsey. The predicate is bound to `thisArg`\n     * and invoked with three arguments: (value, index, array).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.takeRightWhile([1, 2, 3], function(n) {\n     *   return n > 1;\n     * });\n     * // => [2, 3]\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': true },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': false }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');\n     * // => ['pebbles']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.takeRightWhile(users, 'active', false), 'user');\n     * // => ['fred', 'pebbles']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.takeRightWhile(users, 'active'), 'user');\n     * // => []\n     */\n    function takeRightWhile(array, predicate, thisArg) {\n      return (array && array.length)\n        ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)\n        : [];\n    }\n\n    /**\n     * Creates a slice of `array` with elements taken from the beginning. Elements\n     * are taken until `predicate` returns falsey. The predicate is bound to\n     * `thisArg` and invoked with three arguments: (value, index, array).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.takeWhile([1, 2, 3], function(n) {\n     *   return n < 3;\n     * });\n     * // => [1, 2]\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': false },\n     *   { 'user': 'fred',    'active': false},\n     *   { 'user': 'pebbles', 'active': true }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');\n     * // => ['barney']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.takeWhile(users, 'active', false), 'user');\n     * // => ['barney', 'fred']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.takeWhile(users, 'active'), 'user');\n     * // => []\n     */\n    function takeWhile(array, predicate, thisArg) {\n      return (array && array.length)\n        ? baseWhile(array, getCallback(predicate, thisArg, 3))\n        : [];\n    }\n\n    /**\n     * Creates an array of unique values, in order, from all of the provided arrays\n     * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @returns {Array} Returns the new array of combined values.\n     * @example\n     *\n     * _.union([1, 2], [4, 2], [2, 1]);\n     * // => [1, 2, 4]\n     */\n    var union = restParam(function(arrays) {\n      return baseUniq(baseFlatten(arrays, false, true));\n    });\n\n    /**\n     * Creates a duplicate-free version of an array, using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons, in which only the first occurence of each element\n     * is kept. Providing `true` for `isSorted` performs a faster search algorithm\n     * for sorted arrays. If an iteratee function is provided it is invoked for\n     * each element in the array to generate the criterion by which uniqueness\n     * is computed. The `iteratee` is bound to `thisArg` and invoked with three\n     * arguments: (value, index, array).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias unique\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {boolean} [isSorted] Specify the array is sorted.\n     * @param {Function|Object|string} [iteratee] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the new duplicate-value-free array.\n     * @example\n     *\n     * _.uniq([2, 1, 2]);\n     * // => [2, 1]\n     *\n     * // using `isSorted`\n     * _.uniq([1, 1, 2], true);\n     * // => [1, 2]\n     *\n     * // using an iteratee function\n     * _.uniq([1, 2.5, 1.5, 2], function(n) {\n     *   return this.floor(n);\n     * }, Math);\n     * // => [1, 2.5]\n     *\n     * // using the `_.property` callback shorthand\n     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 1 }, { 'x': 2 }]\n     */\n    function uniq(array, isSorted, iteratee, thisArg) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      if (isSorted != null && typeof isSorted != 'boolean') {\n        thisArg = iteratee;\n        iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted;\n        isSorted = false;\n      }\n      var callback = getCallback();\n      if (!(iteratee == null && callback === baseCallback)) {\n        iteratee = callback(iteratee, thisArg, 3);\n      }\n      return (isSorted && getIndexOf() == baseIndexOf)\n        ? sortedUniq(array, iteratee)\n        : baseUniq(array, iteratee);\n    }\n\n    /**\n     * This method is like `_.zip` except that it accepts an array of grouped\n     * elements and creates an array regrouping the elements to their pre-zip\n     * configuration.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array of grouped elements to process.\n     * @returns {Array} Returns the new array of regrouped elements.\n     * @example\n     *\n     * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);\n     * // => [['fred', 30, true], ['barney', 40, false]]\n     *\n     * _.unzip(zipped);\n     * // => [['fred', 'barney'], [30, 40], [true, false]]\n     */\n    function unzip(array) {\n      if (!(array && array.length)) {\n        return [];\n      }\n      var index = -1,\n          length = 0;\n\n      array = arrayFilter(array, function(group) {\n        if (isArrayLike(group)) {\n          length = nativeMax(group.length, length);\n          return true;\n        }\n      });\n      var result = Array(length);\n      while (++index < length) {\n        result[index] = arrayMap(array, baseProperty(index));\n      }\n      return result;\n    }\n\n    /**\n     * This method is like `_.unzip` except that it accepts an iteratee to specify\n     * how regrouped values should be combined. The `iteratee` is bound to `thisArg`\n     * and invoked with four arguments: (accumulator, value, index, group).\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array of grouped elements to process.\n     * @param {Function} [iteratee] The function to combine regrouped values.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the new array of regrouped elements.\n     * @example\n     *\n     * var zipped = _.zip([1, 2], [10, 20], [100, 200]);\n     * // => [[1, 10, 100], [2, 20, 200]]\n     *\n     * _.unzipWith(zipped, _.add);\n     * // => [3, 30, 300]\n     */\n    function unzipWith(array, iteratee, thisArg) {\n      var length = array ? array.length : 0;\n      if (!length) {\n        return [];\n      }\n      var result = unzip(array);\n      if (iteratee == null) {\n        return result;\n      }\n      iteratee = bindCallback(iteratee, thisArg, 4);\n      return arrayMap(result, function(group) {\n        return arrayReduce(group, iteratee, undefined, true);\n      });\n    }\n\n    /**\n     * Creates an array excluding all provided values using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {Array} array The array to filter.\n     * @param {...*} [values] The values to exclude.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * _.without([1, 2, 1, 3], 1, 2);\n     * // => [3]\n     */\n    var without = restParam(function(array, values) {\n      return isArrayLike(array)\n        ? baseDifference(array, values)\n        : [];\n    });\n\n    /**\n     * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)\n     * of the provided arrays.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @returns {Array} Returns the new array of values.\n     * @example\n     *\n     * _.xor([1, 2], [4, 2]);\n     * // => [1, 4]\n     */\n    function xor() {\n      var index = -1,\n          length = arguments.length;\n\n      while (++index < length) {\n        var array = arguments[index];\n        if (isArrayLike(array)) {\n          var result = result\n            ? arrayPush(baseDifference(result, array), baseDifference(array, result))\n            : array;\n        }\n      }\n      return result ? baseUniq(result) : [];\n    }\n\n    /**\n     * Creates an array of grouped elements, the first of which contains the first\n     * elements of the given arrays, the second of which contains the second elements\n     * of the given arrays, and so on.\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {...Array} [arrays] The arrays to process.\n     * @returns {Array} Returns the new array of grouped elements.\n     * @example\n     *\n     * _.zip(['fred', 'barney'], [30, 40], [true, false]);\n     * // => [['fred', 30, true], ['barney', 40, false]]\n     */\n    var zip = restParam(unzip);\n\n    /**\n     * The inverse of `_.pairs`; this method returns an object composed from arrays\n     * of property names and values. Provide either a single two dimensional array,\n     * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names\n     * and one of corresponding values.\n     *\n     * @static\n     * @memberOf _\n     * @alias object\n     * @category Array\n     * @param {Array} props The property names.\n     * @param {Array} [values=[]] The property values.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * _.zipObject([['fred', 30], ['barney', 40]]);\n     * // => { 'fred': 30, 'barney': 40 }\n     *\n     * _.zipObject(['fred', 'barney'], [30, 40]);\n     * // => { 'fred': 30, 'barney': 40 }\n     */\n    function zipObject(props, values) {\n      var index = -1,\n          length = props ? props.length : 0,\n          result = {};\n\n      if (length && !values && !isArray(props[0])) {\n        values = [];\n      }\n      while (++index < length) {\n        var key = props[index];\n        if (values) {\n          result[key] = values[index];\n        } else if (key) {\n          result[key[0]] = key[1];\n        }\n      }\n      return result;\n    }\n\n    /**\n     * This method is like `_.zip` except that it accepts an iteratee to specify\n     * how grouped values should be combined. The `iteratee` is bound to `thisArg`\n     * and invoked with four arguments: (accumulator, value, index, group).\n     *\n     * @static\n     * @memberOf _\n     * @category Array\n     * @param {...Array} [arrays] The arrays to process.\n     * @param {Function} [iteratee] The function to combine grouped values.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the new array of grouped elements.\n     * @example\n     *\n     * _.zipWith([1, 2], [10, 20], [100, 200], _.add);\n     * // => [111, 222]\n     */\n    var zipWith = restParam(function(arrays) {\n      var length = arrays.length,\n          iteratee = length > 2 ? arrays[length - 2] : undefined,\n          thisArg = length > 1 ? arrays[length - 1] : undefined;\n\n      if (length > 2 && typeof iteratee == 'function') {\n        length -= 2;\n      } else {\n        iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined;\n        thisArg = undefined;\n      }\n      arrays.length = length;\n      return unzipWith(arrays, iteratee, thisArg);\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a `lodash` object that wraps `value` with explicit method\n     * chaining enabled.\n     *\n     * @static\n     * @memberOf _\n     * @category Chain\n     * @param {*} value The value to wrap.\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'age': 36 },\n     *   { 'user': 'fred',    'age': 40 },\n     *   { 'user': 'pebbles', 'age': 1 }\n     * ];\n     *\n     * var youngest = _.chain(users)\n     *   .sortBy('age')\n     *   .map(function(chr) {\n     *     return chr.user + ' is ' + chr.age;\n     *   })\n     *   .first()\n     *   .value();\n     * // => 'pebbles is 1'\n     */\n    function chain(value) {\n      var result = lodash(value);\n      result.__chain__ = true;\n      return result;\n    }\n\n    /**\n     * This method invokes `interceptor` and returns `value`. The interceptor is\n     * bound to `thisArg` and invoked with one argument; (value). The purpose of\n     * this method is to \"tap into\" a method chain in order to perform operations\n     * on intermediate results within the chain.\n     *\n     * @static\n     * @memberOf _\n     * @category Chain\n     * @param {*} value The value to provide to `interceptor`.\n     * @param {Function} interceptor The function to invoke.\n     * @param {*} [thisArg] The `this` binding of `interceptor`.\n     * @returns {*} Returns `value`.\n     * @example\n     *\n     * _([1, 2, 3])\n     *  .tap(function(array) {\n     *    array.pop();\n     *  })\n     *  .reverse()\n     *  .value();\n     * // => [2, 1]\n     */\n    function tap(value, interceptor, thisArg) {\n      interceptor.call(thisArg, value);\n      return value;\n    }\n\n    /**\n     * This method is like `_.tap` except that it returns the result of `interceptor`.\n     *\n     * @static\n     * @memberOf _\n     * @category Chain\n     * @param {*} value The value to provide to `interceptor`.\n     * @param {Function} interceptor The function to invoke.\n     * @param {*} [thisArg] The `this` binding of `interceptor`.\n     * @returns {*} Returns the result of `interceptor`.\n     * @example\n     *\n     * _('  abc  ')\n     *  .chain()\n     *  .trim()\n     *  .thru(function(value) {\n     *    return [value];\n     *  })\n     *  .value();\n     * // => ['abc']\n     */\n    function thru(value, interceptor, thisArg) {\n      return interceptor.call(thisArg, value);\n    }\n\n    /**\n     * Enables explicit method chaining on the wrapper object.\n     *\n     * @name chain\n     * @memberOf _\n     * @category Chain\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 40 }\n     * ];\n     *\n     * // without explicit chaining\n     * _(users).first();\n     * // => { 'user': 'barney', 'age': 36 }\n     *\n     * // with explicit chaining\n     * _(users).chain()\n     *   .first()\n     *   .pick('user')\n     *   .value();\n     * // => { 'user': 'barney' }\n     */\n    function wrapperChain() {\n      return chain(this);\n    }\n\n    /**\n     * Executes the chained sequence and returns the wrapped result.\n     *\n     * @name commit\n     * @memberOf _\n     * @category Chain\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var array = [1, 2];\n     * var wrapped = _(array).push(3);\n     *\n     * console.log(array);\n     * // => [1, 2]\n     *\n     * wrapped = wrapped.commit();\n     * console.log(array);\n     * // => [1, 2, 3]\n     *\n     * wrapped.last();\n     * // => 3\n     *\n     * console.log(array);\n     * // => [1, 2, 3]\n     */\n    function wrapperCommit() {\n      return new LodashWrapper(this.value(), this.__chain__);\n    }\n\n    /**\n     * Creates a new array joining a wrapped array with any additional arrays\n     * and/or values.\n     *\n     * @name concat\n     * @memberOf _\n     * @category Chain\n     * @param {...*} [values] The values to concatenate.\n     * @returns {Array} Returns the new concatenated array.\n     * @example\n     *\n     * var array = [1];\n     * var wrapped = _(array).concat(2, [3], [[4]]);\n     *\n     * console.log(wrapped.value());\n     * // => [1, 2, 3, [4]]\n     *\n     * console.log(array);\n     * // => [1]\n     */\n    var wrapperConcat = restParam(function(values) {\n      values = baseFlatten(values);\n      return this.thru(function(array) {\n        return arrayConcat(isArray(array) ? array : [toObject(array)], values);\n      });\n    });\n\n    /**\n     * Creates a clone of the chained sequence planting `value` as the wrapped value.\n     *\n     * @name plant\n     * @memberOf _\n     * @category Chain\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var array = [1, 2];\n     * var wrapped = _(array).map(function(value) {\n     *   return Math.pow(value, 2);\n     * });\n     *\n     * var other = [3, 4];\n     * var otherWrapped = wrapped.plant(other);\n     *\n     * otherWrapped.value();\n     * // => [9, 16]\n     *\n     * wrapped.value();\n     * // => [1, 4]\n     */\n    function wrapperPlant(value) {\n      var result,\n          parent = this;\n\n      while (parent instanceof baseLodash) {\n        var clone = wrapperClone(parent);\n        if (result) {\n          previous.__wrapped__ = clone;\n        } else {\n          result = clone;\n        }\n        var previous = clone;\n        parent = parent.__wrapped__;\n      }\n      previous.__wrapped__ = value;\n      return result;\n    }\n\n    /**\n     * Reverses the wrapped array so the first element becomes the last, the\n     * second element becomes the second to last, and so on.\n     *\n     * **Note:** This method mutates the wrapped array.\n     *\n     * @name reverse\n     * @memberOf _\n     * @category Chain\n     * @returns {Object} Returns the new reversed `lodash` wrapper instance.\n     * @example\n     *\n     * var array = [1, 2, 3];\n     *\n     * _(array).reverse().value()\n     * // => [3, 2, 1]\n     *\n     * console.log(array);\n     * // => [3, 2, 1]\n     */\n    function wrapperReverse() {\n      var value = this.__wrapped__;\n\n      var interceptor = function(value) {\n        return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse();\n      };\n      if (value instanceof LazyWrapper) {\n        var wrapped = value;\n        if (this.__actions__.length) {\n          wrapped = new LazyWrapper(this);\n        }\n        wrapped = wrapped.reverse();\n        wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });\n        return new LodashWrapper(wrapped, this.__chain__);\n      }\n      return this.thru(interceptor);\n    }\n\n    /**\n     * Produces the result of coercing the unwrapped value to a string.\n     *\n     * @name toString\n     * @memberOf _\n     * @category Chain\n     * @returns {string} Returns the coerced string value.\n     * @example\n     *\n     * _([1, 2, 3]).toString();\n     * // => '1,2,3'\n     */\n    function wrapperToString() {\n      return (this.value() + '');\n    }\n\n    /**\n     * Executes the chained sequence to extract the unwrapped value.\n     *\n     * @name value\n     * @memberOf _\n     * @alias run, toJSON, valueOf\n     * @category Chain\n     * @returns {*} Returns the resolved unwrapped value.\n     * @example\n     *\n     * _([1, 2, 3]).value();\n     * // => [1, 2, 3]\n     */\n    function wrapperValue() {\n      return baseWrapperValue(this.__wrapped__, this.__actions__);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array of elements corresponding to the given keys, or indexes,\n     * of `collection`. Keys may be specified as individual arguments or as arrays\n     * of keys.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {...(number|number[]|string|string[])} [props] The property names\n     *  or indexes of elements to pick, specified individually or in arrays.\n     * @returns {Array} Returns the new array of picked elements.\n     * @example\n     *\n     * _.at(['a', 'b', 'c'], [0, 2]);\n     * // => ['a', 'c']\n     *\n     * _.at(['barney', 'fred', 'pebbles'], 0, 2);\n     * // => ['barney', 'pebbles']\n     */\n    var at = restParam(function(collection, props) {\n      return baseAt(collection, baseFlatten(props));\n    });\n\n    /**\n     * Creates an object composed of keys generated from the results of running\n     * each element of `collection` through `iteratee`. The corresponding value\n     * of each key is the number of times the key was returned by `iteratee`.\n     * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.countBy([4.3, 6.1, 6.4], function(n) {\n     *   return Math.floor(n);\n     * });\n     * // => { '4': 1, '6': 2 }\n     *\n     * _.countBy([4.3, 6.1, 6.4], function(n) {\n     *   return this.floor(n);\n     * }, Math);\n     * // => { '4': 1, '6': 2 }\n     *\n     * _.countBy(['one', 'two', 'three'], 'length');\n     * // => { '3': 2, '5': 1 }\n     */\n    var countBy = createAggregator(function(result, value, key) {\n      hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);\n    });\n\n    /**\n     * Checks if `predicate` returns truthy for **all** elements of `collection`.\n     * The predicate is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias all\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {boolean} Returns `true` if all elements pass the predicate check,\n     *  else `false`.\n     * @example\n     *\n     * _.every([true, 1, null, 'yes'], Boolean);\n     * // => false\n     *\n     * var users = [\n     *   { 'user': 'barney', 'active': false },\n     *   { 'user': 'fred',   'active': false }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.every(users, { 'user': 'barney', 'active': false });\n     * // => false\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.every(users, 'active', false);\n     * // => true\n     *\n     * // using the `_.property` callback shorthand\n     * _.every(users, 'active');\n     * // => false\n     */\n    function every(collection, predicate, thisArg) {\n      var func = isArray(collection) ? arrayEvery : baseEvery;\n      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {\n        predicate = undefined;\n      }\n      if (typeof predicate != 'function' || thisArg !== undefined) {\n        predicate = getCallback(predicate, thisArg, 3);\n      }\n      return func(collection, predicate);\n    }\n\n    /**\n     * Iterates over elements of `collection`, returning an array of all elements\n     * `predicate` returns truthy for. The predicate is bound to `thisArg` and\n     * invoked with three arguments: (value, index|key, collection).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias select\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the new filtered array.\n     * @example\n     *\n     * _.filter([4, 5, 6], function(n) {\n     *   return n % 2 == 0;\n     * });\n     * // => [4, 6]\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': true },\n     *   { 'user': 'fred',   'age': 40, 'active': false }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');\n     * // => ['barney']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.filter(users, 'active', false), 'user');\n     * // => ['fred']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.filter(users, 'active'), 'user');\n     * // => ['barney']\n     */\n    function filter(collection, predicate, thisArg) {\n      var func = isArray(collection) ? arrayFilter : baseFilter;\n      predicate = getCallback(predicate, thisArg, 3);\n      return func(collection, predicate);\n    }\n\n    /**\n     * Iterates over elements of `collection`, returning the first element\n     * `predicate` returns truthy for. The predicate is bound to `thisArg` and\n     * invoked with three arguments: (value, index|key, collection).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias detect\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {*} Returns the matched element, else `undefined`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'age': 36, 'active': true },\n     *   { 'user': 'fred',    'age': 40, 'active': false },\n     *   { 'user': 'pebbles', 'age': 1,  'active': true }\n     * ];\n     *\n     * _.result(_.find(users, function(chr) {\n     *   return chr.age < 40;\n     * }), 'user');\n     * // => 'barney'\n     *\n     * // using the `_.matches` callback shorthand\n     * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');\n     * // => 'pebbles'\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.result(_.find(users, 'active', false), 'user');\n     * // => 'fred'\n     *\n     * // using the `_.property` callback shorthand\n     * _.result(_.find(users, 'active'), 'user');\n     * // => 'barney'\n     */\n    var find = createFind(baseEach);\n\n    /**\n     * This method is like `_.find` except that it iterates over elements of\n     * `collection` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {*} Returns the matched element, else `undefined`.\n     * @example\n     *\n     * _.findLast([1, 2, 3, 4], function(n) {\n     *   return n % 2 == 1;\n     * });\n     * // => 3\n     */\n    var findLast = createFind(baseEachRight, true);\n\n    /**\n     * Performs a deep comparison between each element in `collection` and the\n     * source object, returning the first element that has equivalent property\n     * values.\n     *\n     * **Note:** This method supports comparing arrays, booleans, `Date` objects,\n     * numbers, `Object` objects, regexes, and strings. Objects are compared by\n     * their own, not inherited, enumerable properties. For comparing a single\n     * own or inherited property value see `_.matchesProperty`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {Object} source The object of property values to match.\n     * @returns {*} Returns the matched element, else `undefined`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': true },\n     *   { 'user': 'fred',   'age': 40, 'active': false }\n     * ];\n     *\n     * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');\n     * // => 'barney'\n     *\n     * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');\n     * // => 'fred'\n     */\n    function findWhere(collection, source) {\n      return find(collection, baseMatches(source));\n    }\n\n    /**\n     * Iterates over elements of `collection` invoking `iteratee` for each element.\n     * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection). Iteratee functions may exit iteration early\n     * by explicitly returning `false`.\n     *\n     * **Note:** As with other \"Collections\" methods, objects with a \"length\" property\n     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`\n     * may be used for object iteration.\n     *\n     * @static\n     * @memberOf _\n     * @alias each\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array|Object|string} Returns `collection`.\n     * @example\n     *\n     * _([1, 2]).forEach(function(n) {\n     *   console.log(n);\n     * }).value();\n     * // => logs each value from left to right and returns the array\n     *\n     * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {\n     *   console.log(n, key);\n     * });\n     * // => logs each value-key pair and returns the object (iteration order is not guaranteed)\n     */\n    var forEach = createForEach(arrayEach, baseEach);\n\n    /**\n     * This method is like `_.forEach` except that it iterates over elements of\n     * `collection` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @alias eachRight\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array|Object|string} Returns `collection`.\n     * @example\n     *\n     * _([1, 2]).forEachRight(function(n) {\n     *   console.log(n);\n     * }).value();\n     * // => logs each value from right to left and returns the array\n     */\n    var forEachRight = createForEach(arrayEachRight, baseEachRight);\n\n    /**\n     * Creates an object composed of keys generated from the results of running\n     * each element of `collection` through `iteratee`. The corresponding value\n     * of each key is an array of the elements responsible for generating the key.\n     * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.groupBy([4.2, 6.1, 6.4], function(n) {\n     *   return Math.floor(n);\n     * });\n     * // => { '4': [4.2], '6': [6.1, 6.4] }\n     *\n     * _.groupBy([4.2, 6.1, 6.4], function(n) {\n     *   return this.floor(n);\n     * }, Math);\n     * // => { '4': [4.2], '6': [6.1, 6.4] }\n     *\n     * // using the `_.property` callback shorthand\n     * _.groupBy(['one', 'two', 'three'], 'length');\n     * // => { '3': ['one', 'two'], '5': ['three'] }\n     */\n    var groupBy = createAggregator(function(result, value, key) {\n      if (hasOwnProperty.call(result, key)) {\n        result[key].push(value);\n      } else {\n        result[key] = [value];\n      }\n    });\n\n    /**\n     * Checks if `value` is in `collection` using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n     * for equality comparisons. If `fromIndex` is negative, it is used as the offset\n     * from the end of `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @alias contains, include\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {*} target The value to search for.\n     * @param {number} [fromIndex=0] The index to search from.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.\n     * @returns {boolean} Returns `true` if a matching element is found, else `false`.\n     * @example\n     *\n     * _.includes([1, 2, 3], 1);\n     * // => true\n     *\n     * _.includes([1, 2, 3], 1, 2);\n     * // => false\n     *\n     * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');\n     * // => true\n     *\n     * _.includes('pebbles', 'eb');\n     * // => true\n     */\n    function includes(collection, target, fromIndex, guard) {\n      var length = collection ? getLength(collection) : 0;\n      if (!isLength(length)) {\n        collection = values(collection);\n        length = collection.length;\n      }\n      if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {\n        fromIndex = 0;\n      } else {\n        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);\n      }\n      return (typeof collection == 'string' || !isArray(collection) && isString(collection))\n        ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)\n        : (!!length && getIndexOf(collection, target, fromIndex) > -1);\n    }\n\n    /**\n     * Creates an object composed of keys generated from the results of running\n     * each element of `collection` through `iteratee`. The corresponding value\n     * of each key is the last element responsible for generating the key. The\n     * iteratee function is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * var keyData = [\n     *   { 'dir': 'left', 'code': 97 },\n     *   { 'dir': 'right', 'code': 100 }\n     * ];\n     *\n     * _.indexBy(keyData, 'dir');\n     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }\n     *\n     * _.indexBy(keyData, function(object) {\n     *   return String.fromCharCode(object.code);\n     * });\n     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }\n     *\n     * _.indexBy(keyData, function(object) {\n     *   return this.fromCharCode(object.code);\n     * }, String);\n     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }\n     */\n    var indexBy = createAggregator(function(result, value, key) {\n      result[key] = value;\n    });\n\n    /**\n     * Invokes the method at `path` of each element in `collection`, returning\n     * an array of the results of each invoked method. Any additional arguments\n     * are provided to each invoked method. If `methodName` is a function it is\n     * invoked for, and `this` bound to, each element in `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Array|Function|string} path The path of the method to invoke or\n     *  the function invoked per iteration.\n     * @param {...*} [args] The arguments to invoke the method with.\n     * @returns {Array} Returns the array of results.\n     * @example\n     *\n     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');\n     * // => [[1, 5, 7], [1, 2, 3]]\n     *\n     * _.invoke([123, 456], String.prototype.split, '');\n     * // => [['1', '2', '3'], ['4', '5', '6']]\n     */\n    var invoke = restParam(function(collection, path, args) {\n      var index = -1,\n          isFunc = typeof path == 'function',\n          isProp = isKey(path),\n          result = isArrayLike(collection) ? Array(collection.length) : [];\n\n      baseEach(collection, function(value) {\n        var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);\n        result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);\n      });\n      return result;\n    });\n\n    /**\n     * Creates an array of values by running each element in `collection` through\n     * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three\n     * arguments: (value, index|key, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * Many lodash methods are guarded to work as iteratees for methods like\n     * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.\n     *\n     * The guarded methods are:\n     * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,\n     * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,\n     * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,\n     * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,\n     * `sum`, `uniq`, and `words`\n     *\n     * @static\n     * @memberOf _\n     * @alias collect\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the new mapped array.\n     * @example\n     *\n     * function timesThree(n) {\n     *   return n * 3;\n     * }\n     *\n     * _.map([1, 2], timesThree);\n     * // => [3, 6]\n     *\n     * _.map({ 'a': 1, 'b': 2 }, timesThree);\n     * // => [3, 6] (iteration order is not guaranteed)\n     *\n     * var users = [\n     *   { 'user': 'barney' },\n     *   { 'user': 'fred' }\n     * ];\n     *\n     * // using the `_.property` callback shorthand\n     * _.map(users, 'user');\n     * // => ['barney', 'fred']\n     */\n    function map(collection, iteratee, thisArg) {\n      var func = isArray(collection) ? arrayMap : baseMap;\n      iteratee = getCallback(iteratee, thisArg, 3);\n      return func(collection, iteratee);\n    }\n\n    /**\n     * Creates an array of elements split into two groups, the first of which\n     * contains elements `predicate` returns truthy for, while the second of which\n     * contains elements `predicate` returns falsey for. The predicate is bound\n     * to `thisArg` and invoked with three arguments: (value, index|key, collection).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the array of grouped elements.\n     * @example\n     *\n     * _.partition([1, 2, 3], function(n) {\n     *   return n % 2;\n     * });\n     * // => [[1, 3], [2]]\n     *\n     * _.partition([1.2, 2.3, 3.4], function(n) {\n     *   return this.floor(n) % 2;\n     * }, Math);\n     * // => [[1.2, 3.4], [2.3]]\n     *\n     * var users = [\n     *   { 'user': 'barney',  'age': 36, 'active': false },\n     *   { 'user': 'fred',    'age': 40, 'active': true },\n     *   { 'user': 'pebbles', 'age': 1,  'active': false }\n     * ];\n     *\n     * var mapper = function(array) {\n     *   return _.pluck(array, 'user');\n     * };\n     *\n     * // using the `_.matches` callback shorthand\n     * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);\n     * // => [['pebbles'], ['barney', 'fred']]\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.map(_.partition(users, 'active', false), mapper);\n     * // => [['barney', 'pebbles'], ['fred']]\n     *\n     * // using the `_.property` callback shorthand\n     * _.map(_.partition(users, 'active'), mapper);\n     * // => [['fred'], ['barney', 'pebbles']]\n     */\n    var partition = createAggregator(function(result, value, key) {\n      result[key ? 0 : 1].push(value);\n    }, function() { return [[], []]; });\n\n    /**\n     * Gets the property value of `path` from all elements in `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Array|string} path The path of the property to pluck.\n     * @returns {Array} Returns the property values.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 40 }\n     * ];\n     *\n     * _.pluck(users, 'user');\n     * // => ['barney', 'fred']\n     *\n     * var userIndex = _.indexBy(users, 'user');\n     * _.pluck(userIndex, 'age');\n     * // => [36, 40] (iteration order is not guaranteed)\n     */\n    function pluck(collection, path) {\n      return map(collection, property(path));\n    }\n\n    /**\n     * Reduces `collection` to a value which is the accumulated result of running\n     * each element in `collection` through `iteratee`, where each successive\n     * invocation is supplied the return value of the previous. If `accumulator`\n     * is not provided the first element of `collection` is used as the initial\n     * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:\n     * (accumulator, value, index|key, collection).\n     *\n     * Many lodash methods are guarded to work as iteratees for methods like\n     * `_.reduce`, `_.reduceRight`, and `_.transform`.\n     *\n     * The guarded methods are:\n     * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`,\n     * and `sortByOrder`\n     *\n     * @static\n     * @memberOf _\n     * @alias foldl, inject\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {*} Returns the accumulated value.\n     * @example\n     *\n     * _.reduce([1, 2], function(total, n) {\n     *   return total + n;\n     * });\n     * // => 3\n     *\n     * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {\n     *   result[key] = n * 3;\n     *   return result;\n     * }, {});\n     * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)\n     */\n    var reduce = createReduce(arrayReduce, baseEach);\n\n    /**\n     * This method is like `_.reduce` except that it iterates over elements of\n     * `collection` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @alias foldr\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {*} Returns the accumulated value.\n     * @example\n     *\n     * var array = [[0, 1], [2, 3], [4, 5]];\n     *\n     * _.reduceRight(array, function(flattened, other) {\n     *   return flattened.concat(other);\n     * }, []);\n     * // => [4, 5, 2, 3, 0, 1]\n     */\n    var reduceRight = createReduce(arrayReduceRight, baseEachRight);\n\n    /**\n     * The opposite of `_.filter`; this method returns the elements of `collection`\n     * that `predicate` does **not** return truthy for.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Array} Returns the new filtered array.\n     * @example\n     *\n     * _.reject([1, 2, 3, 4], function(n) {\n     *   return n % 2 == 0;\n     * });\n     * // => [1, 3]\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': false },\n     *   { 'user': 'fred',   'age': 40, 'active': true }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');\n     * // => ['barney']\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.pluck(_.reject(users, 'active', false), 'user');\n     * // => ['fred']\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.reject(users, 'active'), 'user');\n     * // => ['barney']\n     */\n    function reject(collection, predicate, thisArg) {\n      var func = isArray(collection) ? arrayFilter : baseFilter;\n      predicate = getCallback(predicate, thisArg, 3);\n      return func(collection, function(value, index, collection) {\n        return !predicate(value, index, collection);\n      });\n    }\n\n    /**\n     * Gets a random element or `n` random elements from a collection.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to sample.\n     * @param {number} [n] The number of elements to sample.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {*} Returns the random sample(s).\n     * @example\n     *\n     * _.sample([1, 2, 3, 4]);\n     * // => 2\n     *\n     * _.sample([1, 2, 3, 4], 2);\n     * // => [3, 1]\n     */\n    function sample(collection, n, guard) {\n      if (guard ? isIterateeCall(collection, n, guard) : n == null) {\n        collection = toIterable(collection);\n        var length = collection.length;\n        return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;\n      }\n      var index = -1,\n          result = toArray(collection),\n          length = result.length,\n          lastIndex = length - 1;\n\n      n = nativeMin(n < 0 ? 0 : (+n || 0), length);\n      while (++index < n) {\n        var rand = baseRandom(index, lastIndex),\n            value = result[rand];\n\n        result[rand] = result[index];\n        result[index] = value;\n      }\n      result.length = n;\n      return result;\n    }\n\n    /**\n     * Creates an array of shuffled values, using a version of the\n     * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to shuffle.\n     * @returns {Array} Returns the new shuffled array.\n     * @example\n     *\n     * _.shuffle([1, 2, 3, 4]);\n     * // => [4, 1, 3, 2]\n     */\n    function shuffle(collection) {\n      return sample(collection, POSITIVE_INFINITY);\n    }\n\n    /**\n     * Gets the size of `collection` by returning its length for array-like\n     * values or the number of own enumerable properties for objects.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to inspect.\n     * @returns {number} Returns the size of `collection`.\n     * @example\n     *\n     * _.size([1, 2, 3]);\n     * // => 3\n     *\n     * _.size({ 'a': 1, 'b': 2 });\n     * // => 2\n     *\n     * _.size('pebbles');\n     * // => 7\n     */\n    function size(collection) {\n      var length = collection ? getLength(collection) : 0;\n      return isLength(length) ? length : keys(collection).length;\n    }\n\n    /**\n     * Checks if `predicate` returns truthy for **any** element of `collection`.\n     * The function returns as soon as it finds a passing value and does not iterate\n     * over the entire collection. The predicate is bound to `thisArg` and invoked\n     * with three arguments: (value, index|key, collection).\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias any\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {boolean} Returns `true` if any element passes the predicate check,\n     *  else `false`.\n     * @example\n     *\n     * _.some([null, 0, 'yes', false], Boolean);\n     * // => true\n     *\n     * var users = [\n     *   { 'user': 'barney', 'active': true },\n     *   { 'user': 'fred',   'active': false }\n     * ];\n     *\n     * // using the `_.matches` callback shorthand\n     * _.some(users, { 'user': 'barney', 'active': false });\n     * // => false\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.some(users, 'active', false);\n     * // => true\n     *\n     * // using the `_.property` callback shorthand\n     * _.some(users, 'active');\n     * // => true\n     */\n    function some(collection, predicate, thisArg) {\n      var func = isArray(collection) ? arraySome : baseSome;\n      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {\n        predicate = undefined;\n      }\n      if (typeof predicate != 'function' || thisArg !== undefined) {\n        predicate = getCallback(predicate, thisArg, 3);\n      }\n      return func(collection, predicate);\n    }\n\n    /**\n     * Creates an array of elements, sorted in ascending order by the results of\n     * running each element in a collection through `iteratee`. This method performs\n     * a stable sort, that is, it preserves the original sort order of equal elements.\n     * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n     * (value, index|key, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the new sorted array.\n     * @example\n     *\n     * _.sortBy([1, 2, 3], function(n) {\n     *   return Math.sin(n);\n     * });\n     * // => [3, 1, 2]\n     *\n     * _.sortBy([1, 2, 3], function(n) {\n     *   return this.sin(n);\n     * }, Math);\n     * // => [3, 1, 2]\n     *\n     * var users = [\n     *   { 'user': 'fred' },\n     *   { 'user': 'pebbles' },\n     *   { 'user': 'barney' }\n     * ];\n     *\n     * // using the `_.property` callback shorthand\n     * _.pluck(_.sortBy(users, 'user'), 'user');\n     * // => ['barney', 'fred', 'pebbles']\n     */\n    function sortBy(collection, iteratee, thisArg) {\n      if (collection == null) {\n        return [];\n      }\n      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {\n        iteratee = undefined;\n      }\n      var index = -1;\n      iteratee = getCallback(iteratee, thisArg, 3);\n\n      var result = baseMap(collection, function(value, key, collection) {\n        return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };\n      });\n      return baseSortBy(result, compareAscending);\n    }\n\n    /**\n     * This method is like `_.sortBy` except that it can sort by multiple iteratees\n     * or property names.\n     *\n     * If a property name is provided for an iteratee the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If an object is provided for an iteratee the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees\n     *  The iteratees to sort by, specified as individual values or arrays of values.\n     * @returns {Array} Returns the new sorted array.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'fred',   'age': 48 },\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 42 },\n     *   { 'user': 'barney', 'age': 34 }\n     * ];\n     *\n     * _.map(_.sortByAll(users, ['user', 'age']), _.values);\n     * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]\n     *\n     * _.map(_.sortByAll(users, 'user', function(chr) {\n     *   return Math.floor(chr.age / 10);\n     * }), _.values);\n     * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]\n     */\n    var sortByAll = restParam(function(collection, iteratees) {\n      if (collection == null) {\n        return [];\n      }\n      var guard = iteratees[2];\n      if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {\n        iteratees.length = 1;\n      }\n      return baseSortByOrder(collection, baseFlatten(iteratees), []);\n    });\n\n    /**\n     * This method is like `_.sortByAll` except that it allows specifying the\n     * sort orders of the iteratees to sort by. If `orders` is unspecified, all\n     * values are sorted in ascending order. Otherwise, a value is sorted in\n     * ascending order if its corresponding order is \"asc\", and descending if \"desc\".\n     *\n     * If a property name is provided for an iteratee the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If an object is provided for an iteratee the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n     * @param {boolean[]} [orders] The sort orders of `iteratees`.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.\n     * @returns {Array} Returns the new sorted array.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'fred',   'age': 48 },\n     *   { 'user': 'barney', 'age': 34 },\n     *   { 'user': 'fred',   'age': 42 },\n     *   { 'user': 'barney', 'age': 36 }\n     * ];\n     *\n     * // sort by `user` in ascending order and by `age` in descending order\n     * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values);\n     * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]\n     */\n    function sortByOrder(collection, iteratees, orders, guard) {\n      if (collection == null) {\n        return [];\n      }\n      if (guard && isIterateeCall(iteratees, orders, guard)) {\n        orders = undefined;\n      }\n      if (!isArray(iteratees)) {\n        iteratees = iteratees == null ? [] : [iteratees];\n      }\n      if (!isArray(orders)) {\n        orders = orders == null ? [] : [orders];\n      }\n      return baseSortByOrder(collection, iteratees, orders);\n    }\n\n    /**\n     * Performs a deep comparison between each element in `collection` and the\n     * source object, returning an array of all elements that have equivalent\n     * property values.\n     *\n     * **Note:** This method supports comparing arrays, booleans, `Date` objects,\n     * numbers, `Object` objects, regexes, and strings. Objects are compared by\n     * their own, not inherited, enumerable properties. For comparing a single\n     * own or inherited property value see `_.matchesProperty`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to search.\n     * @param {Object} source The object of property values to match.\n     * @returns {Array} Returns the new filtered array.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },\n     *   { 'user': 'fred',   'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }\n     * ];\n     *\n     * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');\n     * // => ['barney']\n     *\n     * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');\n     * // => ['fred']\n     */\n    function where(collection, source) {\n      return filter(collection, baseMatches(source));\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Gets the number of milliseconds that have elapsed since the Unix epoch\n     * (1 January 1970 00:00:00 UTC).\n     *\n     * @static\n     * @memberOf _\n     * @category Date\n     * @example\n     *\n     * _.defer(function(stamp) {\n     *   console.log(_.now() - stamp);\n     * }, _.now());\n     * // => logs the number of milliseconds it took for the deferred function to be invoked\n     */\n    var now = nativeNow || function() {\n      return new Date().getTime();\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The opposite of `_.before`; this method creates a function that invokes\n     * `func` once it is called `n` or more times.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {number} n The number of calls before `func` is invoked.\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new restricted function.\n     * @example\n     *\n     * var saves = ['profile', 'settings'];\n     *\n     * var done = _.after(saves.length, function() {\n     *   console.log('done saving!');\n     * });\n     *\n     * _.forEach(saves, function(type) {\n     *   asyncSave({ 'type': type, 'complete': done });\n     * });\n     * // => logs 'done saving!' after the two async saves have completed\n     */\n    function after(n, func) {\n      if (typeof func != 'function') {\n        if (typeof n == 'function') {\n          var temp = n;\n          n = func;\n          func = temp;\n        } else {\n          throw new TypeError(FUNC_ERROR_TEXT);\n        }\n      }\n      n = nativeIsFinite(n = +n) ? n : 0;\n      return function() {\n        if (--n < 1) {\n          return func.apply(this, arguments);\n        }\n      };\n    }\n\n    /**\n     * Creates a function that accepts up to `n` arguments ignoring any\n     * additional arguments.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to cap arguments for.\n     * @param {number} [n=func.length] The arity cap.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * _.map(['6', '8', '10'], _.ary(parseInt, 1));\n     * // => [6, 8, 10]\n     */\n    function ary(func, n, guard) {\n      if (guard && isIterateeCall(func, n, guard)) {\n        n = undefined;\n      }\n      n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);\n      return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);\n    }\n\n    /**\n     * Creates a function that invokes `func`, with the `this` binding and arguments\n     * of the created function, while it is called less than `n` times. Subsequent\n     * calls to the created function return the result of the last `func` invocation.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {number} n The number of calls at which `func` is no longer invoked.\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new restricted function.\n     * @example\n     *\n     * jQuery('#add').on('click', _.before(5, addContactToList));\n     * // => allows adding up to 4 contacts to the list\n     */\n    function before(n, func) {\n      var result;\n      if (typeof func != 'function') {\n        if (typeof n == 'function') {\n          var temp = n;\n          n = func;\n          func = temp;\n        } else {\n          throw new TypeError(FUNC_ERROR_TEXT);\n        }\n      }\n      return function() {\n        if (--n > 0) {\n          result = func.apply(this, arguments);\n        }\n        if (n <= 1) {\n          func = undefined;\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function that invokes `func` with the `this` binding of `thisArg`\n     * and prepends any additional `_.bind` arguments to those provided to the\n     * bound function.\n     *\n     * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,\n     * may be used as a placeholder for partially applied arguments.\n     *\n     * **Note:** Unlike native `Function#bind` this method does not set the \"length\"\n     * property of bound functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to bind.\n     * @param {*} thisArg The `this` binding of `func`.\n     * @param {...*} [partials] The arguments to be partially applied.\n     * @returns {Function} Returns the new bound function.\n     * @example\n     *\n     * var greet = function(greeting, punctuation) {\n     *   return greeting + ' ' + this.user + punctuation;\n     * };\n     *\n     * var object = { 'user': 'fred' };\n     *\n     * var bound = _.bind(greet, object, 'hi');\n     * bound('!');\n     * // => 'hi fred!'\n     *\n     * // using placeholders\n     * var bound = _.bind(greet, object, _, '!');\n     * bound('hi');\n     * // => 'hi fred!'\n     */\n    var bind = restParam(function(func, thisArg, partials) {\n      var bitmask = BIND_FLAG;\n      if (partials.length) {\n        var holders = replaceHolders(partials, bind.placeholder);\n        bitmask |= PARTIAL_FLAG;\n      }\n      return createWrapper(func, bitmask, thisArg, partials, holders);\n    });\n\n    /**\n     * Binds methods of an object to the object itself, overwriting the existing\n     * method. Method names may be specified as individual arguments or as arrays\n     * of method names. If no method names are provided all enumerable function\n     * properties, own and inherited, of `object` are bound.\n     *\n     * **Note:** This method does not set the \"length\" property of bound functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Object} object The object to bind and assign the bound methods to.\n     * @param {...(string|string[])} [methodNames] The object method names to bind,\n     *  specified as individual method names or arrays of method names.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var view = {\n     *   'label': 'docs',\n     *   'onClick': function() {\n     *     console.log('clicked ' + this.label);\n     *   }\n     * };\n     *\n     * _.bindAll(view);\n     * jQuery('#docs').on('click', view.onClick);\n     * // => logs 'clicked docs' when the element is clicked\n     */\n    var bindAll = restParam(function(object, methodNames) {\n      methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);\n\n      var index = -1,\n          length = methodNames.length;\n\n      while (++index < length) {\n        var key = methodNames[index];\n        object[key] = createWrapper(object[key], BIND_FLAG, object);\n      }\n      return object;\n    });\n\n    /**\n     * Creates a function that invokes the method at `object[key]` and prepends\n     * any additional `_.bindKey` arguments to those provided to the bound function.\n     *\n     * This method differs from `_.bind` by allowing bound functions to reference\n     * methods that may be redefined or don't yet exist.\n     * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)\n     * for more details.\n     *\n     * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic\n     * builds, may be used as a placeholder for partially applied arguments.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Object} object The object the method belongs to.\n     * @param {string} key The key of the method.\n     * @param {...*} [partials] The arguments to be partially applied.\n     * @returns {Function} Returns the new bound function.\n     * @example\n     *\n     * var object = {\n     *   'user': 'fred',\n     *   'greet': function(greeting, punctuation) {\n     *     return greeting + ' ' + this.user + punctuation;\n     *   }\n     * };\n     *\n     * var bound = _.bindKey(object, 'greet', 'hi');\n     * bound('!');\n     * // => 'hi fred!'\n     *\n     * object.greet = function(greeting, punctuation) {\n     *   return greeting + 'ya ' + this.user + punctuation;\n     * };\n     *\n     * bound('!');\n     * // => 'hiya fred!'\n     *\n     * // using placeholders\n     * var bound = _.bindKey(object, 'greet', _, '!');\n     * bound('hi');\n     * // => 'hiya fred!'\n     */\n    var bindKey = restParam(function(object, key, partials) {\n      var bitmask = BIND_FLAG | BIND_KEY_FLAG;\n      if (partials.length) {\n        var holders = replaceHolders(partials, bindKey.placeholder);\n        bitmask |= PARTIAL_FLAG;\n      }\n      return createWrapper(key, bitmask, object, partials, holders);\n    });\n\n    /**\n     * Creates a function that accepts one or more arguments of `func` that when\n     * called either invokes `func` returning its result, if all `func` arguments\n     * have been provided, or returns a function that accepts one or more of the\n     * remaining `func` arguments, and so on. The arity of `func` may be specified\n     * if `func.length` is not sufficient.\n     *\n     * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,\n     * may be used as a placeholder for provided arguments.\n     *\n     * **Note:** This method does not set the \"length\" property of curried functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to curry.\n     * @param {number} [arity=func.length] The arity of `func`.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Function} Returns the new curried function.\n     * @example\n     *\n     * var abc = function(a, b, c) {\n     *   return [a, b, c];\n     * };\n     *\n     * var curried = _.curry(abc);\n     *\n     * curried(1)(2)(3);\n     * // => [1, 2, 3]\n     *\n     * curried(1, 2)(3);\n     * // => [1, 2, 3]\n     *\n     * curried(1, 2, 3);\n     * // => [1, 2, 3]\n     *\n     * // using placeholders\n     * curried(1)(_, 3)(2);\n     * // => [1, 2, 3]\n     */\n    var curry = createCurry(CURRY_FLAG);\n\n    /**\n     * This method is like `_.curry` except that arguments are applied to `func`\n     * in the manner of `_.partialRight` instead of `_.partial`.\n     *\n     * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic\n     * builds, may be used as a placeholder for provided arguments.\n     *\n     * **Note:** This method does not set the \"length\" property of curried functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to curry.\n     * @param {number} [arity=func.length] The arity of `func`.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Function} Returns the new curried function.\n     * @example\n     *\n     * var abc = function(a, b, c) {\n     *   return [a, b, c];\n     * };\n     *\n     * var curried = _.curryRight(abc);\n     *\n     * curried(3)(2)(1);\n     * // => [1, 2, 3]\n     *\n     * curried(2, 3)(1);\n     * // => [1, 2, 3]\n     *\n     * curried(1, 2, 3);\n     * // => [1, 2, 3]\n     *\n     * // using placeholders\n     * curried(3)(1, _)(2);\n     * // => [1, 2, 3]\n     */\n    var curryRight = createCurry(CURRY_RIGHT_FLAG);\n\n    /**\n     * Creates a debounced function that delays invoking `func` until after `wait`\n     * milliseconds have elapsed since the last time the debounced function was\n     * invoked. The debounced function comes with a `cancel` method to cancel\n     * delayed invocations. Provide an options object to indicate that `func`\n     * should be invoked on the leading and/or trailing edge of the `wait` timeout.\n     * Subsequent calls to the debounced function return the result of the last\n     * `func` invocation.\n     *\n     * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked\n     * on the trailing edge of the timeout only if the the debounced function is\n     * invoked more than once during the `wait` timeout.\n     *\n     * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)\n     * for details over the differences between `_.debounce` and `_.throttle`.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to debounce.\n     * @param {number} [wait=0] The number of milliseconds to delay.\n     * @param {Object} [options] The options object.\n     * @param {boolean} [options.leading=false] Specify invoking on the leading\n     *  edge of the timeout.\n     * @param {number} [options.maxWait] The maximum time `func` is allowed to be\n     *  delayed before it is invoked.\n     * @param {boolean} [options.trailing=true] Specify invoking on the trailing\n     *  edge of the timeout.\n     * @returns {Function} Returns the new debounced function.\n     * @example\n     *\n     * // avoid costly calculations while the window size is in flux\n     * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n     *\n     * // invoke `sendMail` when the click event is fired, debouncing subsequent calls\n     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {\n     *   'leading': true,\n     *   'trailing': false\n     * }));\n     *\n     * // ensure `batchLog` is invoked once after 1 second of debounced calls\n     * var source = new EventSource('/stream');\n     * jQuery(source).on('message', _.debounce(batchLog, 250, {\n     *   'maxWait': 1000\n     * }));\n     *\n     * // cancel a debounced call\n     * var todoChanges = _.debounce(batchLog, 1000);\n     * Object.observe(models.todo, todoChanges);\n     *\n     * Object.observe(models, function(changes) {\n     *   if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {\n     *     todoChanges.cancel();\n     *   }\n     * }, ['delete']);\n     *\n     * // ...at some point `models.todo` is changed\n     * models.todo.completed = true;\n     *\n     * // ...before 1 second has passed `models.todo` is deleted\n     * // which cancels the debounced `todoChanges` call\n     * delete models.todo;\n     */\n    function debounce(func, wait, options) {\n      var args,\n          maxTimeoutId,\n          result,\n          stamp,\n          thisArg,\n          timeoutId,\n          trailingCall,\n          lastCalled = 0,\n          maxWait = false,\n          trailing = true;\n\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      wait = wait < 0 ? 0 : (+wait || 0);\n      if (options === true) {\n        var leading = true;\n        trailing = false;\n      } else if (isObject(options)) {\n        leading = !!options.leading;\n        maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);\n        trailing = 'trailing' in options ? !!options.trailing : trailing;\n      }\n\n      function cancel() {\n        if (timeoutId) {\n          clearTimeout(timeoutId);\n        }\n        if (maxTimeoutId) {\n          clearTimeout(maxTimeoutId);\n        }\n        lastCalled = 0;\n        maxTimeoutId = timeoutId = trailingCall = undefined;\n      }\n\n      function complete(isCalled, id) {\n        if (id) {\n          clearTimeout(id);\n        }\n        maxTimeoutId = timeoutId = trailingCall = undefined;\n        if (isCalled) {\n          lastCalled = now();\n          result = func.apply(thisArg, args);\n          if (!timeoutId && !maxTimeoutId) {\n            args = thisArg = undefined;\n          }\n        }\n      }\n\n      function delayed() {\n        var remaining = wait - (now() - stamp);\n        if (remaining <= 0 || remaining > wait) {\n          complete(trailingCall, maxTimeoutId);\n        } else {\n          timeoutId = setTimeout(delayed, remaining);\n        }\n      }\n\n      function maxDelayed() {\n        complete(trailing, timeoutId);\n      }\n\n      function debounced() {\n        args = arguments;\n        stamp = now();\n        thisArg = this;\n        trailingCall = trailing && (timeoutId || !leading);\n\n        if (maxWait === false) {\n          var leadingCall = leading && !timeoutId;\n        } else {\n          if (!maxTimeoutId && !leading) {\n            lastCalled = stamp;\n          }\n          var remaining = maxWait - (stamp - lastCalled),\n              isCalled = remaining <= 0 || remaining > maxWait;\n\n          if (isCalled) {\n            if (maxTimeoutId) {\n              maxTimeoutId = clearTimeout(maxTimeoutId);\n            }\n            lastCalled = stamp;\n            result = func.apply(thisArg, args);\n          }\n          else if (!maxTimeoutId) {\n            maxTimeoutId = setTimeout(maxDelayed, remaining);\n          }\n        }\n        if (isCalled && timeoutId) {\n          timeoutId = clearTimeout(timeoutId);\n        }\n        else if (!timeoutId && wait !== maxWait) {\n          timeoutId = setTimeout(delayed, wait);\n        }\n        if (leadingCall) {\n          isCalled = true;\n          result = func.apply(thisArg, args);\n        }\n        if (isCalled && !timeoutId && !maxTimeoutId) {\n          args = thisArg = undefined;\n        }\n        return result;\n      }\n      debounced.cancel = cancel;\n      return debounced;\n    }\n\n    /**\n     * Defers invoking the `func` until the current call stack has cleared. Any\n     * additional arguments are provided to `func` when it is invoked.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to defer.\n     * @param {...*} [args] The arguments to invoke the function with.\n     * @returns {number} Returns the timer id.\n     * @example\n     *\n     * _.defer(function(text) {\n     *   console.log(text);\n     * }, 'deferred');\n     * // logs 'deferred' after one or more milliseconds\n     */\n    var defer = restParam(function(func, args) {\n      return baseDelay(func, 1, args);\n    });\n\n    /**\n     * Invokes `func` after `wait` milliseconds. Any additional arguments are\n     * provided to `func` when it is invoked.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to delay.\n     * @param {number} wait The number of milliseconds to delay invocation.\n     * @param {...*} [args] The arguments to invoke the function with.\n     * @returns {number} Returns the timer id.\n     * @example\n     *\n     * _.delay(function(text) {\n     *   console.log(text);\n     * }, 1000, 'later');\n     * // => logs 'later' after one second\n     */\n    var delay = restParam(function(func, wait, args) {\n      return baseDelay(func, wait, args);\n    });\n\n    /**\n     * Creates a function that returns the result of invoking the provided\n     * functions with the `this` binding of the created function, where each\n     * successive invocation is supplied the return value of the previous.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {...Function} [funcs] Functions to invoke.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * var addSquare = _.flow(_.add, square);\n     * addSquare(1, 2);\n     * // => 9\n     */\n    var flow = createFlow();\n\n    /**\n     * This method is like `_.flow` except that it creates a function that\n     * invokes the provided functions from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @alias backflow, compose\n     * @category Function\n     * @param {...Function} [funcs] Functions to invoke.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * var addSquare = _.flowRight(square, _.add);\n     * addSquare(1, 2);\n     * // => 9\n     */\n    var flowRight = createFlow(true);\n\n    /**\n     * Creates a function that memoizes the result of `func`. If `resolver` is\n     * provided it determines the cache key for storing the result based on the\n     * arguments provided to the memoized function. By default, the first argument\n     * provided to the memoized function is coerced to a string and used as the\n     * cache key. The `func` is invoked with the `this` binding of the memoized\n     * function.\n     *\n     * **Note:** The cache is exposed as the `cache` property on the memoized\n     * function. Its creation may be customized by replacing the `_.memoize.Cache`\n     * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)\n     * method interface of `get`, `has`, and `set`.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to have its output memoized.\n     * @param {Function} [resolver] The function to resolve the cache key.\n     * @returns {Function} Returns the new memoizing function.\n     * @example\n     *\n     * var upperCase = _.memoize(function(string) {\n     *   return string.toUpperCase();\n     * });\n     *\n     * upperCase('fred');\n     * // => 'FRED'\n     *\n     * // modifying the result cache\n     * upperCase.cache.set('fred', 'BARNEY');\n     * upperCase('fred');\n     * // => 'BARNEY'\n     *\n     * // replacing `_.memoize.Cache`\n     * var object = { 'user': 'fred' };\n     * var other = { 'user': 'barney' };\n     * var identity = _.memoize(_.identity);\n     *\n     * identity(object);\n     * // => { 'user': 'fred' }\n     * identity(other);\n     * // => { 'user': 'fred' }\n     *\n     * _.memoize.Cache = WeakMap;\n     * var identity = _.memoize(_.identity);\n     *\n     * identity(object);\n     * // => { 'user': 'fred' }\n     * identity(other);\n     * // => { 'user': 'barney' }\n     */\n    function memoize(func, resolver) {\n      if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      var memoized = function() {\n        var args = arguments,\n            key = resolver ? resolver.apply(this, args) : args[0],\n            cache = memoized.cache;\n\n        if (cache.has(key)) {\n          return cache.get(key);\n        }\n        var result = func.apply(this, args);\n        memoized.cache = cache.set(key, result);\n        return result;\n      };\n      memoized.cache = new memoize.Cache;\n      return memoized;\n    }\n\n    /**\n     * Creates a function that runs each argument through a corresponding\n     * transform function.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to wrap.\n     * @param {...(Function|Function[])} [transforms] The functions to transform\n     * arguments, specified as individual functions or arrays of functions.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * function doubled(n) {\n     *   return n * 2;\n     * }\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * var modded = _.modArgs(function(x, y) {\n     *   return [x, y];\n     * }, square, doubled);\n     *\n     * modded(1, 2);\n     * // => [1, 4]\n     *\n     * modded(5, 10);\n     * // => [25, 20]\n     */\n    var modArgs = restParam(function(func, transforms) {\n      transforms = baseFlatten(transforms);\n      if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      var length = transforms.length;\n      return restParam(function(args) {\n        var index = nativeMin(args.length, length);\n        while (index--) {\n          args[index] = transforms[index](args[index]);\n        }\n        return func.apply(this, args);\n      });\n    });\n\n    /**\n     * Creates a function that negates the result of the predicate `func`. The\n     * `func` predicate is invoked with the `this` binding and arguments of the\n     * created function.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} predicate The predicate to negate.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * function isEven(n) {\n     *   return n % 2 == 0;\n     * }\n     *\n     * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));\n     * // => [1, 3, 5]\n     */\n    function negate(predicate) {\n      if (typeof predicate != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      return function() {\n        return !predicate.apply(this, arguments);\n      };\n    }\n\n    /**\n     * Creates a function that is restricted to invoking `func` once. Repeat calls\n     * to the function return the value of the first call. The `func` is invoked\n     * with the `this` binding and arguments of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new restricted function.\n     * @example\n     *\n     * var initialize = _.once(createApplication);\n     * initialize();\n     * initialize();\n     * // `initialize` invokes `createApplication` once\n     */\n    function once(func) {\n      return before(2, func);\n    }\n\n    /**\n     * Creates a function that invokes `func` with `partial` arguments prepended\n     * to those provided to the new function. This method is like `_.bind` except\n     * it does **not** alter the `this` binding.\n     *\n     * The `_.partial.placeholder` value, which defaults to `_` in monolithic\n     * builds, may be used as a placeholder for partially applied arguments.\n     *\n     * **Note:** This method does not set the \"length\" property of partially\n     * applied functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to partially apply arguments to.\n     * @param {...*} [partials] The arguments to be partially applied.\n     * @returns {Function} Returns the new partially applied function.\n     * @example\n     *\n     * var greet = function(greeting, name) {\n     *   return greeting + ' ' + name;\n     * };\n     *\n     * var sayHelloTo = _.partial(greet, 'hello');\n     * sayHelloTo('fred');\n     * // => 'hello fred'\n     *\n     * // using placeholders\n     * var greetFred = _.partial(greet, _, 'fred');\n     * greetFred('hi');\n     * // => 'hi fred'\n     */\n    var partial = createPartial(PARTIAL_FLAG);\n\n    /**\n     * This method is like `_.partial` except that partially applied arguments\n     * are appended to those provided to the new function.\n     *\n     * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic\n     * builds, may be used as a placeholder for partially applied arguments.\n     *\n     * **Note:** This method does not set the \"length\" property of partially\n     * applied functions.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to partially apply arguments to.\n     * @param {...*} [partials] The arguments to be partially applied.\n     * @returns {Function} Returns the new partially applied function.\n     * @example\n     *\n     * var greet = function(greeting, name) {\n     *   return greeting + ' ' + name;\n     * };\n     *\n     * var greetFred = _.partialRight(greet, 'fred');\n     * greetFred('hi');\n     * // => 'hi fred'\n     *\n     * // using placeholders\n     * var sayHelloTo = _.partialRight(greet, 'hello', _);\n     * sayHelloTo('fred');\n     * // => 'hello fred'\n     */\n    var partialRight = createPartial(PARTIAL_RIGHT_FLAG);\n\n    /**\n     * Creates a function that invokes `func` with arguments arranged according\n     * to the specified indexes where the argument value at the first index is\n     * provided as the first argument, the argument value at the second index is\n     * provided as the second argument, and so on.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to rearrange arguments for.\n     * @param {...(number|number[])} indexes The arranged argument indexes,\n     *  specified as individual indexes or arrays of indexes.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var rearged = _.rearg(function(a, b, c) {\n     *   return [a, b, c];\n     * }, 2, 0, 1);\n     *\n     * rearged('b', 'c', 'a')\n     * // => ['a', 'b', 'c']\n     *\n     * var map = _.rearg(_.map, [1, 0]);\n     * map(function(n) {\n     *   return n * 3;\n     * }, [1, 2, 3]);\n     * // => [3, 6, 9]\n     */\n    var rearg = restParam(function(func, indexes) {\n      return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes));\n    });\n\n    /**\n     * Creates a function that invokes `func` with the `this` binding of the\n     * created function and arguments from `start` and beyond provided as an array.\n     *\n     * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to apply a rest parameter to.\n     * @param {number} [start=func.length-1] The start position of the rest parameter.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var say = _.restParam(function(what, names) {\n     *   return what + ' ' + _.initial(names).join(', ') +\n     *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);\n     * });\n     *\n     * say('hello', 'fred', 'barney', 'pebbles');\n     * // => 'hello fred, barney, & pebbles'\n     */\n    function restParam(func, start) {\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);\n      return function() {\n        var args = arguments,\n            index = -1,\n            length = nativeMax(args.length - start, 0),\n            rest = Array(length);\n\n        while (++index < length) {\n          rest[index] = args[start + index];\n        }\n        switch (start) {\n          case 0: return func.call(this, rest);\n          case 1: return func.call(this, args[0], rest);\n          case 2: return func.call(this, args[0], args[1], rest);\n        }\n        var otherArgs = Array(start + 1);\n        index = -1;\n        while (++index < start) {\n          otherArgs[index] = args[index];\n        }\n        otherArgs[start] = rest;\n        return func.apply(this, otherArgs);\n      };\n    }\n\n    /**\n     * Creates a function that invokes `func` with the `this` binding of the created\n     * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).\n     *\n     * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to spread arguments over.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var say = _.spread(function(who, what) {\n     *   return who + ' says ' + what;\n     * });\n     *\n     * say(['fred', 'hello']);\n     * // => 'fred says hello'\n     *\n     * // with a Promise\n     * var numbers = Promise.all([\n     *   Promise.resolve(40),\n     *   Promise.resolve(36)\n     * ]);\n     *\n     * numbers.then(_.spread(function(x, y) {\n     *   return x + y;\n     * }));\n     * // => a Promise of 76\n     */\n    function spread(func) {\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      return function(array) {\n        return func.apply(this, array);\n      };\n    }\n\n    /**\n     * Creates a throttled function that only invokes `func` at most once per\n     * every `wait` milliseconds. The throttled function comes with a `cancel`\n     * method to cancel delayed invocations. Provide an options object to indicate\n     * that `func` should be invoked on the leading and/or trailing edge of the\n     * `wait` timeout. Subsequent calls to the throttled function return the\n     * result of the last `func` call.\n     *\n     * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked\n     * on the trailing edge of the timeout only if the the throttled function is\n     * invoked more than once during the `wait` timeout.\n     *\n     * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)\n     * for details over the differences between `_.throttle` and `_.debounce`.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to throttle.\n     * @param {number} [wait=0] The number of milliseconds to throttle invocations to.\n     * @param {Object} [options] The options object.\n     * @param {boolean} [options.leading=true] Specify invoking on the leading\n     *  edge of the timeout.\n     * @param {boolean} [options.trailing=true] Specify invoking on the trailing\n     *  edge of the timeout.\n     * @returns {Function} Returns the new throttled function.\n     * @example\n     *\n     * // avoid excessively updating the position while scrolling\n     * jQuery(window).on('scroll', _.throttle(updatePosition, 100));\n     *\n     * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes\n     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {\n     *   'trailing': false\n     * }));\n     *\n     * // cancel a trailing throttled call\n     * jQuery(window).on('popstate', throttled.cancel);\n     */\n    function throttle(func, wait, options) {\n      var leading = true,\n          trailing = true;\n\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      if (options === false) {\n        leading = false;\n      } else if (isObject(options)) {\n        leading = 'leading' in options ? !!options.leading : leading;\n        trailing = 'trailing' in options ? !!options.trailing : trailing;\n      }\n      return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing });\n    }\n\n    /**\n     * Creates a function that provides `value` to the wrapper function as its\n     * first argument. Any additional arguments provided to the function are\n     * appended to those provided to the wrapper function. The wrapper is invoked\n     * with the `this` binding of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @category Function\n     * @param {*} value The value to wrap.\n     * @param {Function} wrapper The wrapper function.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var p = _.wrap(_.escape, function(func, text) {\n     *   return '<p>' + func(text) + '</p>';\n     * });\n     *\n     * p('fred, barney, & pebbles');\n     * // => '<p>fred, barney, &amp; pebbles</p>'\n     */\n    function wrap(value, wrapper) {\n      wrapper = wrapper == null ? identity : wrapper;\n      return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,\n     * otherwise they are assigned by reference. If `customizer` is provided it is\n     * invoked to produce the cloned values. If `customizer` returns `undefined`\n     * cloning is handled by the method instead. The `customizer` is bound to\n     * `thisArg` and invoked with two argument; (value [, index|key, object]).\n     *\n     * **Note:** This method is loosely based on the\n     * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).\n     * The enumerable properties of `arguments` objects and objects created by\n     * constructors other than `Object` are cloned to plain `Object` objects. An\n     * empty object is returned for uncloneable values such as functions, DOM nodes,\n     * Maps, Sets, and WeakMaps.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @param {Function} [customizer] The function to customize cloning values.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {*} Returns the cloned value.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney' },\n     *   { 'user': 'fred' }\n     * ];\n     *\n     * var shallow = _.clone(users);\n     * shallow[0] === users[0];\n     * // => true\n     *\n     * var deep = _.clone(users, true);\n     * deep[0] === users[0];\n     * // => false\n     *\n     * // using a customizer callback\n     * var el = _.clone(document.body, function(value) {\n     *   if (_.isElement(value)) {\n     *     return value.cloneNode(false);\n     *   }\n     * });\n     *\n     * el === document.body\n     * // => false\n     * el.nodeName\n     * // => BODY\n     * el.childNodes.length;\n     * // => 0\n     */\n    function clone(value, isDeep, customizer, thisArg) {\n      if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {\n        isDeep = false;\n      }\n      else if (typeof isDeep == 'function') {\n        thisArg = customizer;\n        customizer = isDeep;\n        isDeep = false;\n      }\n      return typeof customizer == 'function'\n        ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1))\n        : baseClone(value, isDeep);\n    }\n\n    /**\n     * Creates a deep clone of `value`. If `customizer` is provided it is invoked\n     * to produce the cloned values. If `customizer` returns `undefined` cloning\n     * is handled by the method instead. The `customizer` is bound to `thisArg`\n     * and invoked with two argument; (value [, index|key, object]).\n     *\n     * **Note:** This method is loosely based on the\n     * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).\n     * The enumerable properties of `arguments` objects and objects created by\n     * constructors other than `Object` are cloned to plain `Object` objects. An\n     * empty object is returned for uncloneable values such as functions, DOM nodes,\n     * Maps, Sets, and WeakMaps.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to deep clone.\n     * @param {Function} [customizer] The function to customize cloning values.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {*} Returns the deep cloned value.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney' },\n     *   { 'user': 'fred' }\n     * ];\n     *\n     * var deep = _.cloneDeep(users);\n     * deep[0] === users[0];\n     * // => false\n     *\n     * // using a customizer callback\n     * var el = _.cloneDeep(document.body, function(value) {\n     *   if (_.isElement(value)) {\n     *     return value.cloneNode(true);\n     *   }\n     * });\n     *\n     * el === document.body\n     * // => false\n     * el.nodeName\n     * // => BODY\n     * el.childNodes.length;\n     * // => 20\n     */\n    function cloneDeep(value, customizer, thisArg) {\n      return typeof customizer == 'function'\n        ? baseClone(value, true, bindCallback(customizer, thisArg, 1))\n        : baseClone(value, true);\n    }\n\n    /**\n     * Checks if `value` is greater than `other`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.\n     * @example\n     *\n     * _.gt(3, 1);\n     * // => true\n     *\n     * _.gt(3, 3);\n     * // => false\n     *\n     * _.gt(1, 3);\n     * // => false\n     */\n    function gt(value, other) {\n      return value > other;\n    }\n\n    /**\n     * Checks if `value` is greater than or equal to `other`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`.\n     * @example\n     *\n     * _.gte(3, 1);\n     * // => true\n     *\n     * _.gte(3, 3);\n     * // => true\n     *\n     * _.gte(1, 3);\n     * // => false\n     */\n    function gte(value, other) {\n      return value >= other;\n    }\n\n    /**\n     * Checks if `value` is classified as an `arguments` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isArguments(function() { return arguments; }());\n     * // => true\n     *\n     * _.isArguments([1, 2, 3]);\n     * // => false\n     */\n    function isArguments(value) {\n      return isObjectLike(value) && isArrayLike(value) &&\n        hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');\n    }\n\n    /**\n     * Checks if `value` is classified as an `Array` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isArray([1, 2, 3]);\n     * // => true\n     *\n     * _.isArray(function() { return arguments; }());\n     * // => false\n     */\n    var isArray = nativeIsArray || function(value) {\n      return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;\n    };\n\n    /**\n     * Checks if `value` is classified as a boolean primitive or object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isBoolean(false);\n     * // => true\n     *\n     * _.isBoolean(null);\n     * // => false\n     */\n    function isBoolean(value) {\n      return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);\n    }\n\n    /**\n     * Checks if `value` is classified as a `Date` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isDate(new Date);\n     * // => true\n     *\n     * _.isDate('Mon April 23 2012');\n     * // => false\n     */\n    function isDate(value) {\n      return isObjectLike(value) && objToString.call(value) == dateTag;\n    }\n\n    /**\n     * Checks if `value` is a DOM element.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.\n     * @example\n     *\n     * _.isElement(document.body);\n     * // => true\n     *\n     * _.isElement('<body>');\n     * // => false\n     */\n    function isElement(value) {\n      return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);\n    }\n\n    /**\n     * Checks if `value` is empty. A value is considered empty unless it is an\n     * `arguments` object, array, string, or jQuery-like collection with a length\n     * greater than `0` or an object with own enumerable properties.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {Array|Object|string} value The value to inspect.\n     * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n     * @example\n     *\n     * _.isEmpty(null);\n     * // => true\n     *\n     * _.isEmpty(true);\n     * // => true\n     *\n     * _.isEmpty(1);\n     * // => true\n     *\n     * _.isEmpty([1, 2, 3]);\n     * // => false\n     *\n     * _.isEmpty({ 'a': 1 });\n     * // => false\n     */\n    function isEmpty(value) {\n      if (value == null) {\n        return true;\n      }\n      if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||\n          (isObjectLike(value) && isFunction(value.splice)))) {\n        return !value.length;\n      }\n      return !keys(value).length;\n    }\n\n    /**\n     * Performs a deep comparison between two values to determine if they are\n     * equivalent. If `customizer` is provided it is invoked to compare values.\n     * If `customizer` returns `undefined` comparisons are handled by the method\n     * instead. The `customizer` is bound to `thisArg` and invoked with three\n     * arguments: (value, other [, index|key]).\n     *\n     * **Note:** This method supports comparing arrays, booleans, `Date` objects,\n     * numbers, `Object` objects, regexes, and strings. Objects are compared by\n     * their own, not inherited, enumerable properties. Functions and DOM nodes\n     * are **not** supported. Provide a customizer function to extend support\n     * for comparing other values.\n     *\n     * @static\n     * @memberOf _\n     * @alias eq\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @param {Function} [customizer] The function to customize value comparisons.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     * @example\n     *\n     * var object = { 'user': 'fred' };\n     * var other = { 'user': 'fred' };\n     *\n     * object == other;\n     * // => false\n     *\n     * _.isEqual(object, other);\n     * // => true\n     *\n     * // using a customizer callback\n     * var array = ['hello', 'goodbye'];\n     * var other = ['hi', 'goodbye'];\n     *\n     * _.isEqual(array, other, function(value, other) {\n     *   if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {\n     *     return true;\n     *   }\n     * });\n     * // => true\n     */\n    function isEqual(value, other, customizer, thisArg) {\n      customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;\n      var result = customizer ? customizer(value, other) : undefined;\n      return  result === undefined ? baseIsEqual(value, other, customizer) : !!result;\n    }\n\n    /**\n     * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,\n     * `SyntaxError`, `TypeError`, or `URIError` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an error object, else `false`.\n     * @example\n     *\n     * _.isError(new Error);\n     * // => true\n     *\n     * _.isError(Error);\n     * // => false\n     */\n    function isError(value) {\n      return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;\n    }\n\n    /**\n     * Checks if `value` is a finite primitive number.\n     *\n     * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite).\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.\n     * @example\n     *\n     * _.isFinite(10);\n     * // => true\n     *\n     * _.isFinite('10');\n     * // => false\n     *\n     * _.isFinite(true);\n     * // => false\n     *\n     * _.isFinite(Object(10));\n     * // => false\n     *\n     * _.isFinite(Infinity);\n     * // => false\n     */\n    function isFinite(value) {\n      return typeof value == 'number' && nativeIsFinite(value);\n    }\n\n    /**\n     * Checks if `value` is classified as a `Function` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isFunction(_);\n     * // => true\n     *\n     * _.isFunction(/abc/);\n     * // => false\n     */\n    function isFunction(value) {\n      // The use of `Object#toString` avoids issues with the `typeof` operator\n      // in older versions of Chrome and Safari which return 'function' for regexes\n      // and Safari 8 equivalents which return 'object' for typed array constructors.\n      return isObject(value) && objToString.call(value) == funcTag;\n    }\n\n    /**\n     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n     * @example\n     *\n     * _.isObject({});\n     * // => true\n     *\n     * _.isObject([1, 2, 3]);\n     * // => true\n     *\n     * _.isObject(1);\n     * // => false\n     */\n    function isObject(value) {\n      // Avoid a V8 JIT bug in Chrome 19-20.\n      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n      var type = typeof value;\n      return !!value && (type == 'object' || type == 'function');\n    }\n\n    /**\n     * Performs a deep comparison between `object` and `source` to determine if\n     * `object` contains equivalent property values. If `customizer` is provided\n     * it is invoked to compare values. If `customizer` returns `undefined`\n     * comparisons are handled by the method instead. The `customizer` is bound\n     * to `thisArg` and invoked with three arguments: (value, other, index|key).\n     *\n     * **Note:** This method supports comparing properties of arrays, booleans,\n     * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions\n     * and DOM nodes are **not** supported. Provide a customizer function to extend\n     * support for comparing other values.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {Object} object The object to inspect.\n     * @param {Object} source The object of property values to match.\n     * @param {Function} [customizer] The function to customize value comparisons.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n     * @example\n     *\n     * var object = { 'user': 'fred', 'age': 40 };\n     *\n     * _.isMatch(object, { 'age': 40 });\n     * // => true\n     *\n     * _.isMatch(object, { 'age': 36 });\n     * // => false\n     *\n     * // using a customizer callback\n     * var object = { 'greeting': 'hello' };\n     * var source = { 'greeting': 'hi' };\n     *\n     * _.isMatch(object, source, function(value, other) {\n     *   return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined;\n     * });\n     * // => true\n     */\n    function isMatch(object, source, customizer, thisArg) {\n      customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;\n      return baseIsMatch(object, getMatchData(source), customizer);\n    }\n\n    /**\n     * Checks if `value` is `NaN`.\n     *\n     * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)\n     * which returns `true` for `undefined` and other non-numeric values.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n     * @example\n     *\n     * _.isNaN(NaN);\n     * // => true\n     *\n     * _.isNaN(new Number(NaN));\n     * // => true\n     *\n     * isNaN(undefined);\n     * // => true\n     *\n     * _.isNaN(undefined);\n     * // => false\n     */\n    function isNaN(value) {\n      // An `NaN` primitive is the only value that is not equal to itself.\n      // Perform the `toStringTag` check first to avoid errors with some host objects in IE.\n      return isNumber(value) && value != +value;\n    }\n\n    /**\n     * Checks if `value` is a native function.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a native function, else `false`.\n     * @example\n     *\n     * _.isNative(Array.prototype.push);\n     * // => true\n     *\n     * _.isNative(_);\n     * // => false\n     */\n    function isNative(value) {\n      if (value == null) {\n        return false;\n      }\n      if (isFunction(value)) {\n        return reIsNative.test(fnToString.call(value));\n      }\n      return isObjectLike(value) && reIsHostCtor.test(value);\n    }\n\n    /**\n     * Checks if `value` is `null`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n     * @example\n     *\n     * _.isNull(null);\n     * // => true\n     *\n     * _.isNull(void 0);\n     * // => false\n     */\n    function isNull(value) {\n      return value === null;\n    }\n\n    /**\n     * Checks if `value` is classified as a `Number` primitive or object.\n     *\n     * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified\n     * as numbers, use the `_.isFinite` method.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isNumber(8.4);\n     * // => true\n     *\n     * _.isNumber(NaN);\n     * // => true\n     *\n     * _.isNumber('8.4');\n     * // => false\n     */\n    function isNumber(value) {\n      return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);\n    }\n\n    /**\n     * Checks if `value` is a plain object, that is, an object created by the\n     * `Object` constructor or one with a `[[Prototype]]` of `null`.\n     *\n     * **Note:** This method assumes objects created by the `Object` constructor\n     * have no inherited enumerable properties.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     * }\n     *\n     * _.isPlainObject(new Foo);\n     * // => false\n     *\n     * _.isPlainObject([1, 2, 3]);\n     * // => false\n     *\n     * _.isPlainObject({ 'x': 0, 'y': 0 });\n     * // => true\n     *\n     * _.isPlainObject(Object.create(null));\n     * // => true\n     */\n    function isPlainObject(value) {\n      var Ctor;\n\n      // Exit early for non `Object` objects.\n      if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) ||\n          (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {\n        return false;\n      }\n      // IE < 9 iterates inherited properties before own properties. If the first\n      // iterated property is an object's own property then there are no inherited\n      // enumerable properties.\n      var result;\n      // In most environments an object's own properties are iterated before\n      // its inherited properties. If the last iterated property is an object's\n      // own property then there are no inherited enumerable properties.\n      baseForIn(value, function(subValue, key) {\n        result = key;\n      });\n      return result === undefined || hasOwnProperty.call(value, result);\n    }\n\n    /**\n     * Checks if `value` is classified as a `RegExp` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isRegExp(/abc/);\n     * // => true\n     *\n     * _.isRegExp('/abc/');\n     * // => false\n     */\n    function isRegExp(value) {\n      return isObject(value) && objToString.call(value) == regexpTag;\n    }\n\n    /**\n     * Checks if `value` is classified as a `String` primitive or object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isString('abc');\n     * // => true\n     *\n     * _.isString(1);\n     * // => false\n     */\n    function isString(value) {\n      return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);\n    }\n\n    /**\n     * Checks if `value` is classified as a typed array.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n     * @example\n     *\n     * _.isTypedArray(new Uint8Array);\n     * // => true\n     *\n     * _.isTypedArray([]);\n     * // => false\n     */\n    function isTypedArray(value) {\n      return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];\n    }\n\n    /**\n     * Checks if `value` is `undefined`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n     * @example\n     *\n     * _.isUndefined(void 0);\n     * // => true\n     *\n     * _.isUndefined(null);\n     * // => false\n     */\n    function isUndefined(value) {\n      return value === undefined;\n    }\n\n    /**\n     * Checks if `value` is less than `other`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.\n     * @example\n     *\n     * _.lt(1, 3);\n     * // => true\n     *\n     * _.lt(3, 3);\n     * // => false\n     *\n     * _.lt(3, 1);\n     * // => false\n     */\n    function lt(value, other) {\n      return value < other;\n    }\n\n    /**\n     * Checks if `value` is less than or equal to `other`.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`.\n     * @example\n     *\n     * _.lte(1, 3);\n     * // => true\n     *\n     * _.lte(3, 3);\n     * // => true\n     *\n     * _.lte(3, 1);\n     * // => false\n     */\n    function lte(value, other) {\n      return value <= other;\n    }\n\n    /**\n     * Converts `value` to an array.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {Array} Returns the converted array.\n     * @example\n     *\n     * (function() {\n     *   return _.toArray(arguments).slice(1);\n     * }(1, 2, 3));\n     * // => [2, 3]\n     */\n    function toArray(value) {\n      var length = value ? getLength(value) : 0;\n      if (!isLength(length)) {\n        return values(value);\n      }\n      if (!length) {\n        return [];\n      }\n      return arrayCopy(value);\n    }\n\n    /**\n     * Converts `value` to a plain object flattening inherited enumerable\n     * properties of `value` to own properties of the plain object.\n     *\n     * @static\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {Object} Returns the converted plain object.\n     * @example\n     *\n     * function Foo() {\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.assign({ 'a': 1 }, new Foo);\n     * // => { 'a': 1, 'b': 2 }\n     *\n     * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n     * // => { 'a': 1, 'b': 2, 'c': 3 }\n     */\n    function toPlainObject(value) {\n      return baseCopy(value, keysIn(value));\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Recursively merges own enumerable properties of the source object(s), that\n     * don't resolve to `undefined` into the destination object. Subsequent sources\n     * overwrite property assignments of previous sources. If `customizer` is\n     * provided it is invoked to produce the merged values of the destination and\n     * source properties. If `customizer` returns `undefined` merging is handled\n     * by the method instead. The `customizer` is bound to `thisArg` and invoked\n     * with five arguments: (objectValue, sourceValue, key, object, source).\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @param {Function} [customizer] The function to customize assigned values.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var users = {\n     *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]\n     * };\n     *\n     * var ages = {\n     *   'data': [{ 'age': 36 }, { 'age': 40 }]\n     * };\n     *\n     * _.merge(users, ages);\n     * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }\n     *\n     * // using a customizer callback\n     * var object = {\n     *   'fruits': ['apple'],\n     *   'vegetables': ['beet']\n     * };\n     *\n     * var other = {\n     *   'fruits': ['banana'],\n     *   'vegetables': ['carrot']\n     * };\n     *\n     * _.merge(object, other, function(a, b) {\n     *   if (_.isArray(a)) {\n     *     return a.concat(b);\n     *   }\n     * });\n     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }\n     */\n    var merge = createAssigner(baseMerge);\n\n    /**\n     * Assigns own enumerable properties of source object(s) to the destination\n     * object. Subsequent sources overwrite property assignments of previous sources.\n     * If `customizer` is provided it is invoked to produce the assigned values.\n     * The `customizer` is bound to `thisArg` and invoked with five arguments:\n     * (objectValue, sourceValue, key, object, source).\n     *\n     * **Note:** This method mutates `object` and is based on\n     * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign).\n     *\n     * @static\n     * @memberOf _\n     * @alias extend\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @param {Function} [customizer] The function to customize assigned values.\n     * @param {*} [thisArg] The `this` binding of `customizer`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });\n     * // => { 'user': 'fred', 'age': 40 }\n     *\n     * // using a customizer callback\n     * var defaults = _.partialRight(_.assign, function(value, other) {\n     *   return _.isUndefined(value) ? other : value;\n     * });\n     *\n     * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });\n     * // => { 'user': 'barney', 'age': 36 }\n     */\n    var assign = createAssigner(function(object, source, customizer) {\n      return customizer\n        ? assignWith(object, source, customizer)\n        : baseAssign(object, source);\n    });\n\n    /**\n     * Creates an object that inherits from the given `prototype` object. If a\n     * `properties` object is provided its own enumerable properties are assigned\n     * to the created object.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} prototype The object to inherit from.\n     * @param {Object} [properties] The properties to assign to the object.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * function Shape() {\n     *   this.x = 0;\n     *   this.y = 0;\n     * }\n     *\n     * function Circle() {\n     *   Shape.call(this);\n     * }\n     *\n     * Circle.prototype = _.create(Shape.prototype, {\n     *   'constructor': Circle\n     * });\n     *\n     * var circle = new Circle;\n     * circle instanceof Circle;\n     * // => true\n     *\n     * circle instanceof Shape;\n     * // => true\n     */\n    function create(prototype, properties, guard) {\n      var result = baseCreate(prototype);\n      if (guard && isIterateeCall(prototype, properties, guard)) {\n        properties = undefined;\n      }\n      return properties ? baseAssign(result, properties) : result;\n    }\n\n    /**\n     * Assigns own enumerable properties of source object(s) to the destination\n     * object for all destination properties that resolve to `undefined`. Once a\n     * property is set, additional values of the same property are ignored.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });\n     * // => { 'user': 'barney', 'age': 36 }\n     */\n    var defaults = createDefaults(assign, assignDefaults);\n\n    /**\n     * This method is like `_.defaults` except that it recursively assigns\n     * default properties.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });\n     * // => { 'user': { 'name': 'barney', 'age': 36 } }\n     *\n     */\n    var defaultsDeep = createDefaults(merge, mergeDefaults);\n\n    /**\n     * This method is like `_.find` except that it returns the key of the first\n     * element `predicate` returns truthy for instead of the element itself.\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {string|undefined} Returns the key of the matched element, else `undefined`.\n     * @example\n     *\n     * var users = {\n     *   'barney':  { 'age': 36, 'active': true },\n     *   'fred':    { 'age': 40, 'active': false },\n     *   'pebbles': { 'age': 1,  'active': true }\n     * };\n     *\n     * _.findKey(users, function(chr) {\n     *   return chr.age < 40;\n     * });\n     * // => 'barney' (iteration order is not guaranteed)\n     *\n     * // using the `_.matches` callback shorthand\n     * _.findKey(users, { 'age': 1, 'active': true });\n     * // => 'pebbles'\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.findKey(users, 'active', false);\n     * // => 'fred'\n     *\n     * // using the `_.property` callback shorthand\n     * _.findKey(users, 'active');\n     * // => 'barney'\n     */\n    var findKey = createFindKey(baseForOwn);\n\n    /**\n     * This method is like `_.findKey` except that it iterates over elements of\n     * a collection in the opposite order.\n     *\n     * If a property name is provided for `predicate` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `predicate` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to search.\n     * @param {Function|Object|string} [predicate=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {string|undefined} Returns the key of the matched element, else `undefined`.\n     * @example\n     *\n     * var users = {\n     *   'barney':  { 'age': 36, 'active': true },\n     *   'fred':    { 'age': 40, 'active': false },\n     *   'pebbles': { 'age': 1,  'active': true }\n     * };\n     *\n     * _.findLastKey(users, function(chr) {\n     *   return chr.age < 40;\n     * });\n     * // => returns `pebbles` assuming `_.findKey` returns `barney`\n     *\n     * // using the `_.matches` callback shorthand\n     * _.findLastKey(users, { 'age': 36, 'active': true });\n     * // => 'barney'\n     *\n     * // using the `_.matchesProperty` callback shorthand\n     * _.findLastKey(users, 'active', false);\n     * // => 'fred'\n     *\n     * // using the `_.property` callback shorthand\n     * _.findLastKey(users, 'active');\n     * // => 'pebbles'\n     */\n    var findLastKey = createFindKey(baseForOwnRight);\n\n    /**\n     * Iterates over own and inherited enumerable properties of an object invoking\n     * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked\n     * with three arguments: (value, key, object). Iteratee functions may exit\n     * iteration early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.forIn(new Foo, function(value, key) {\n     *   console.log(key);\n     * });\n     * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed)\n     */\n    var forIn = createForIn(baseFor);\n\n    /**\n     * This method is like `_.forIn` except that it iterates over properties of\n     * `object` in the opposite order.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.forInRight(new Foo, function(value, key) {\n     *   console.log(key);\n     * });\n     * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c'\n     */\n    var forInRight = createForIn(baseForRight);\n\n    /**\n     * Iterates over own enumerable properties of an object invoking `iteratee`\n     * for each property. The `iteratee` is bound to `thisArg` and invoked with\n     * three arguments: (value, key, object). Iteratee functions may exit iteration\n     * early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.forOwn(new Foo, function(value, key) {\n     *   console.log(key);\n     * });\n     * // => logs 'a' and 'b' (iteration order is not guaranteed)\n     */\n    var forOwn = createForOwn(baseForOwn);\n\n    /**\n     * This method is like `_.forOwn` except that it iterates over properties of\n     * `object` in the opposite order.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.forOwnRight(new Foo, function(value, key) {\n     *   console.log(key);\n     * });\n     * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b'\n     */\n    var forOwnRight = createForOwn(baseForOwnRight);\n\n    /**\n     * Creates an array of function property names from all enumerable properties,\n     * own and inherited, of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @alias methods\n     * @category Object\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns the new array of property names.\n     * @example\n     *\n     * _.functions(_);\n     * // => ['after', 'ary', 'assign', ...]\n     */\n    function functions(object) {\n      return baseFunctions(object, keysIn(object));\n    }\n\n    /**\n     * Gets the property value at `path` of `object`. If the resolved value is\n     * `undefined` the `defaultValue` is used in its place.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path of the property to get.\n     * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.\n     * @returns {*} Returns the resolved value.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n     *\n     * _.get(object, 'a[0].b.c');\n     * // => 3\n     *\n     * _.get(object, ['a', '0', 'b', 'c']);\n     * // => 3\n     *\n     * _.get(object, 'a.b.c', 'default');\n     * // => 'default'\n     */\n    function get(object, path, defaultValue) {\n      var result = object == null ? undefined : baseGet(object, toPath(path), path + '');\n      return result === undefined ? defaultValue : result;\n    }\n\n    /**\n     * Checks if `path` is a direct property.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path to check.\n     * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.\n     * @example\n     *\n     * var object = { 'a': { 'b': { 'c': 3 } } };\n     *\n     * _.has(object, 'a');\n     * // => true\n     *\n     * _.has(object, 'a.b.c');\n     * // => true\n     *\n     * _.has(object, ['a', 'b', 'c']);\n     * // => true\n     */\n    function has(object, path) {\n      if (object == null) {\n        return false;\n      }\n      var result = hasOwnProperty.call(object, path);\n      if (!result && !isKey(path)) {\n        path = toPath(path);\n        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n        if (object == null) {\n          return false;\n        }\n        path = last(path);\n        result = hasOwnProperty.call(object, path);\n      }\n      return result || (isLength(object.length) && isIndex(path, object.length) &&\n        (isArray(object) || isArguments(object)));\n    }\n\n    /**\n     * Creates an object composed of the inverted keys and values of `object`.\n     * If `object` contains duplicate values, subsequent values overwrite property\n     * assignments of previous values unless `multiValue` is `true`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to invert.\n     * @param {boolean} [multiValue] Allow multiple values per key.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Object} Returns the new inverted object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': 2, 'c': 1 };\n     *\n     * _.invert(object);\n     * // => { '1': 'c', '2': 'b' }\n     *\n     * // with `multiValue`\n     * _.invert(object, true);\n     * // => { '1': ['a', 'c'], '2': ['b'] }\n     */\n    function invert(object, multiValue, guard) {\n      if (guard && isIterateeCall(object, multiValue, guard)) {\n        multiValue = undefined;\n      }\n      var index = -1,\n          props = keys(object),\n          length = props.length,\n          result = {};\n\n      while (++index < length) {\n        var key = props[index],\n            value = object[key];\n\n        if (multiValue) {\n          if (hasOwnProperty.call(result, value)) {\n            result[value].push(key);\n          } else {\n            result[value] = [key];\n          }\n        }\n        else {\n          result[value] = key;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array of the own enumerable property names of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects. See the\n     * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)\n     * for more details.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.keys(new Foo);\n     * // => ['a', 'b'] (iteration order is not guaranteed)\n     *\n     * _.keys('hi');\n     * // => ['0', '1']\n     */\n    var keys = !nativeKeys ? shimKeys : function(object) {\n      var Ctor = object == null ? undefined : object.constructor;\n      if ((typeof Ctor == 'function' && Ctor.prototype === object) ||\n          (typeof object != 'function' && isArrayLike(object))) {\n        return shimKeys(object);\n      }\n      return isObject(object) ? nativeKeys(object) : [];\n    };\n\n    /**\n     * Creates an array of the own and inherited enumerable property names of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.keysIn(new Foo);\n     * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n     */\n    function keysIn(object) {\n      if (object == null) {\n        return [];\n      }\n      if (!isObject(object)) {\n        object = Object(object);\n      }\n      var length = object.length;\n      length = (length && isLength(length) &&\n        (isArray(object) || isArguments(object)) && length) || 0;\n\n      var Ctor = object.constructor,\n          index = -1,\n          isProto = typeof Ctor == 'function' && Ctor.prototype === object,\n          result = Array(length),\n          skipIndexes = length > 0;\n\n      while (++index < length) {\n        result[index] = (index + '');\n      }\n      for (var key in object) {\n        if (!(skipIndexes && isIndex(key, length)) &&\n            !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The opposite of `_.mapValues`; this method creates an object with the\n     * same values as `object` and keys generated by running each own enumerable\n     * property of `object` through `iteratee`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns the new mapped object.\n     * @example\n     *\n     * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {\n     *   return key + value;\n     * });\n     * // => { 'a1': 1, 'b2': 2 }\n     */\n    var mapKeys = createObjectMapper(true);\n\n    /**\n     * Creates an object with the same keys as `object` and values generated by\n     * running each own enumerable property of `object` through `iteratee`. The\n     * iteratee function is bound to `thisArg` and invoked with three arguments:\n     * (value, key, object).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n     *  per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Object} Returns the new mapped object.\n     * @example\n     *\n     * _.mapValues({ 'a': 1, 'b': 2 }, function(n) {\n     *   return n * 3;\n     * });\n     * // => { 'a': 3, 'b': 6 }\n     *\n     * var users = {\n     *   'fred':    { 'user': 'fred',    'age': 40 },\n     *   'pebbles': { 'user': 'pebbles', 'age': 1 }\n     * };\n     *\n     * // using the `_.property` callback shorthand\n     * _.mapValues(users, 'age');\n     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n     */\n    var mapValues = createObjectMapper();\n\n    /**\n     * The opposite of `_.pick`; this method creates an object composed of the\n     * own and inherited enumerable properties of `object` that are not omitted.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {Function|...(string|string[])} [predicate] The function invoked per\n     *  iteration or property names to omit, specified as individual property\n     *  names or arrays of property names.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'user': 'fred', 'age': 40 };\n     *\n     * _.omit(object, 'age');\n     * // => { 'user': 'fred' }\n     *\n     * _.omit(object, _.isNumber);\n     * // => { 'user': 'fred' }\n     */\n    var omit = restParam(function(object, props) {\n      if (object == null) {\n        return {};\n      }\n      if (typeof props[0] != 'function') {\n        var props = arrayMap(baseFlatten(props), String);\n        return pickByArray(object, baseDifference(keysIn(object), props));\n      }\n      var predicate = bindCallback(props[0], props[1], 3);\n      return pickByCallback(object, function(value, key, object) {\n        return !predicate(value, key, object);\n      });\n    });\n\n    /**\n     * Creates a two dimensional array of the key-value pairs for `object`,\n     * e.g. `[[key1, value1], [key2, value2]]`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the new array of key-value pairs.\n     * @example\n     *\n     * _.pairs({ 'barney': 36, 'fred': 40 });\n     * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)\n     */\n    function pairs(object) {\n      object = toObject(object);\n\n      var index = -1,\n          props = keys(object),\n          length = props.length,\n          result = Array(length);\n\n      while (++index < length) {\n        var key = props[index];\n        result[index] = [key, object[key]];\n      }\n      return result;\n    }\n\n    /**\n     * Creates an object composed of the picked `object` properties. Property\n     * names may be specified as individual arguments or as arrays of property\n     * names. If `predicate` is provided it is invoked for each property of `object`\n     * picking the properties `predicate` returns truthy for. The predicate is\n     * bound to `thisArg` and invoked with three arguments: (value, key, object).\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {Function|...(string|string[])} [predicate] The function invoked per\n     *  iteration or property names to pick, specified as individual property\n     *  names or arrays of property names.\n     * @param {*} [thisArg] The `this` binding of `predicate`.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'user': 'fred', 'age': 40 };\n     *\n     * _.pick(object, 'user');\n     * // => { 'user': 'fred' }\n     *\n     * _.pick(object, _.isString);\n     * // => { 'user': 'fred' }\n     */\n    var pick = restParam(function(object, props) {\n      if (object == null) {\n        return {};\n      }\n      return typeof props[0] == 'function'\n        ? pickByCallback(object, bindCallback(props[0], props[1], 3))\n        : pickByArray(object, baseFlatten(props));\n    });\n\n    /**\n     * This method is like `_.get` except that if the resolved value is a function\n     * it is invoked with the `this` binding of its parent object and its result\n     * is returned.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path of the property to resolve.\n     * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.\n     * @returns {*} Returns the resolved value.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };\n     *\n     * _.result(object, 'a[0].b.c1');\n     * // => 3\n     *\n     * _.result(object, 'a[0].b.c2');\n     * // => 4\n     *\n     * _.result(object, 'a.b.c', 'default');\n     * // => 'default'\n     *\n     * _.result(object, 'a.b.c', _.constant('default'));\n     * // => 'default'\n     */\n    function result(object, path, defaultValue) {\n      var result = object == null ? undefined : object[path];\n      if (result === undefined) {\n        if (object != null && !isKey(path, object)) {\n          path = toPath(path);\n          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n          result = object == null ? undefined : object[last(path)];\n        }\n        result = result === undefined ? defaultValue : result;\n      }\n      return isFunction(result) ? result.call(object) : result;\n    }\n\n    /**\n     * Sets the property value of `path` on `object`. If a portion of `path`\n     * does not exist it is created.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to augment.\n     * @param {Array|string} path The path of the property to set.\n     * @param {*} value The value to set.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n     *\n     * _.set(object, 'a[0].b.c', 4);\n     * console.log(object.a[0].b.c);\n     * // => 4\n     *\n     * _.set(object, 'x[0].y.z', 5);\n     * console.log(object.x[0].y.z);\n     * // => 5\n     */\n    function set(object, path, value) {\n      if (object == null) {\n        return object;\n      }\n      var pathKey = (path + '');\n      path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);\n\n      var index = -1,\n          length = path.length,\n          lastIndex = length - 1,\n          nested = object;\n\n      while (nested != null && ++index < length) {\n        var key = path[index];\n        if (isObject(nested)) {\n          if (index == lastIndex) {\n            nested[key] = value;\n          } else if (nested[key] == null) {\n            nested[key] = isIndex(path[index + 1]) ? [] : {};\n          }\n        }\n        nested = nested[key];\n      }\n      return object;\n    }\n\n    /**\n     * An alternative to `_.reduce`; this method transforms `object` to a new\n     * `accumulator` object which is the result of running each of its own enumerable\n     * properties through `iteratee`, with each invocation potentially mutating\n     * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked\n     * with four arguments: (accumulator, value, key, object). Iteratee functions\n     * may exit iteration early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Array|Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [accumulator] The custom accumulator value.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {*} Returns the accumulated value.\n     * @example\n     *\n     * _.transform([2, 3, 4], function(result, n) {\n     *   result.push(n *= n);\n     *   return n % 2 == 0;\n     * });\n     * // => [4, 9]\n     *\n     * _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) {\n     *   result[key] = n * 3;\n     * });\n     * // => { 'a': 3, 'b': 6 }\n     */\n    function transform(object, iteratee, accumulator, thisArg) {\n      var isArr = isArray(object) || isTypedArray(object);\n      iteratee = getCallback(iteratee, thisArg, 4);\n\n      if (accumulator == null) {\n        if (isArr || isObject(object)) {\n          var Ctor = object.constructor;\n          if (isArr) {\n            accumulator = isArray(object) ? new Ctor : [];\n          } else {\n            accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);\n          }\n        } else {\n          accumulator = {};\n        }\n      }\n      (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {\n        return iteratee(accumulator, value, index, object);\n      });\n      return accumulator;\n    }\n\n    /**\n     * Creates an array of the own enumerable property values of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property values.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.values(new Foo);\n     * // => [1, 2] (iteration order is not guaranteed)\n     *\n     * _.values('hi');\n     * // => ['h', 'i']\n     */\n    function values(object) {\n      return baseValues(object, keys(object));\n    }\n\n    /**\n     * Creates an array of the own and inherited enumerable property values\n     * of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects.\n     *\n     * @static\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property values.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.valuesIn(new Foo);\n     * // => [1, 2, 3] (iteration order is not guaranteed)\n     */\n    function valuesIn(object) {\n      return baseValues(object, keysIn(object));\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Checks if `n` is between `start` and up to but not including, `end`. If\n     * `end` is not specified it is set to `start` with `start` then set to `0`.\n     *\n     * @static\n     * @memberOf _\n     * @category Number\n     * @param {number} n The number to check.\n     * @param {number} [start=0] The start of the range.\n     * @param {number} end The end of the range.\n     * @returns {boolean} Returns `true` if `n` is in the range, else `false`.\n     * @example\n     *\n     * _.inRange(3, 2, 4);\n     * // => true\n     *\n     * _.inRange(4, 8);\n     * // => true\n     *\n     * _.inRange(4, 2);\n     * // => false\n     *\n     * _.inRange(2, 2);\n     * // => false\n     *\n     * _.inRange(1.2, 2);\n     * // => true\n     *\n     * _.inRange(5.2, 4);\n     * // => false\n     */\n    function inRange(value, start, end) {\n      start = +start || 0;\n      if (end === undefined) {\n        end = start;\n        start = 0;\n      } else {\n        end = +end || 0;\n      }\n      return value >= nativeMin(start, end) && value < nativeMax(start, end);\n    }\n\n    /**\n     * Produces a random number between `min` and `max` (inclusive). If only one\n     * argument is provided a number between `0` and the given number is returned.\n     * If `floating` is `true`, or either `min` or `max` are floats, a floating-point\n     * number is returned instead of an integer.\n     *\n     * @static\n     * @memberOf _\n     * @category Number\n     * @param {number} [min=0] The minimum possible value.\n     * @param {number} [max=1] The maximum possible value.\n     * @param {boolean} [floating] Specify returning a floating-point number.\n     * @returns {number} Returns the random number.\n     * @example\n     *\n     * _.random(0, 5);\n     * // => an integer between 0 and 5\n     *\n     * _.random(5);\n     * // => also an integer between 0 and 5\n     *\n     * _.random(5, true);\n     * // => a floating-point number between 0 and 5\n     *\n     * _.random(1.2, 5.2);\n     * // => a floating-point number between 1.2 and 5.2\n     */\n    function random(min, max, floating) {\n      if (floating && isIterateeCall(min, max, floating)) {\n        max = floating = undefined;\n      }\n      var noMin = min == null,\n          noMax = max == null;\n\n      if (floating == null) {\n        if (noMax && typeof min == 'boolean') {\n          floating = min;\n          min = 1;\n        }\n        else if (typeof max == 'boolean') {\n          floating = max;\n          noMax = true;\n        }\n      }\n      if (noMin && noMax) {\n        max = 1;\n        noMax = false;\n      }\n      min = +min || 0;\n      if (noMax) {\n        max = min;\n        min = 0;\n      } else {\n        max = +max || 0;\n      }\n      if (floating || min % 1 || max % 1) {\n        var rand = nativeRandom();\n        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max);\n      }\n      return baseRandom(min, max);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the camel cased string.\n     * @example\n     *\n     * _.camelCase('Foo Bar');\n     * // => 'fooBar'\n     *\n     * _.camelCase('--foo-bar');\n     * // => 'fooBar'\n     *\n     * _.camelCase('__foo_bar__');\n     * // => 'fooBar'\n     */\n    var camelCase = createCompounder(function(result, word, index) {\n      word = word.toLowerCase();\n      return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word);\n    });\n\n    /**\n     * Capitalizes the first character of `string`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to capitalize.\n     * @returns {string} Returns the capitalized string.\n     * @example\n     *\n     * _.capitalize('fred');\n     * // => 'Fred'\n     */\n    function capitalize(string) {\n      string = baseToString(string);\n      return string && (string.charAt(0).toUpperCase() + string.slice(1));\n    }\n\n    /**\n     * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n     * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to deburr.\n     * @returns {string} Returns the deburred string.\n     * @example\n     *\n     * _.deburr('déjà vu');\n     * // => 'deja vu'\n     */\n    function deburr(string) {\n      string = baseToString(string);\n      return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');\n    }\n\n    /**\n     * Checks if `string` ends with the given target string.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to search.\n     * @param {string} [target] The string to search for.\n     * @param {number} [position=string.length] The position to search from.\n     * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.\n     * @example\n     *\n     * _.endsWith('abc', 'c');\n     * // => true\n     *\n     * _.endsWith('abc', 'b');\n     * // => false\n     *\n     * _.endsWith('abc', 'b', 2);\n     * // => true\n     */\n    function endsWith(string, target, position) {\n      string = baseToString(string);\n      target = (target + '');\n\n      var length = string.length;\n      position = position === undefined\n        ? length\n        : nativeMin(position < 0 ? 0 : (+position || 0), length);\n\n      position -= target.length;\n      return position >= 0 && string.indexOf(target, position) == position;\n    }\n\n    /**\n     * Converts the characters \"&\", \"<\", \">\", '\"', \"'\", and \"\\`\", in `string` to\n     * their corresponding HTML entities.\n     *\n     * **Note:** No other characters are escaped. To escape additional characters\n     * use a third-party library like [_he_](https://mths.be/he).\n     *\n     * Though the \">\" character is escaped for symmetry, characters like\n     * \">\" and \"/\" don't need escaping in HTML and have no special meaning\n     * unless they're part of a tag or unquoted attribute value.\n     * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)\n     * (under \"semi-related fun fact\") for more details.\n     *\n     * Backticks are escaped because in Internet Explorer < 9, they can break out\n     * of attribute values or HTML comments. See [#59](https://html5sec.org/#59),\n     * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and\n     * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)\n     * for more details.\n     *\n     * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)\n     * to reduce XSS vectors.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to escape.\n     * @returns {string} Returns the escaped string.\n     * @example\n     *\n     * _.escape('fred, barney, & pebbles');\n     * // => 'fred, barney, &amp; pebbles'\n     */\n    function escape(string) {\n      // Reset `lastIndex` because in IE < 9 `String#replace` does not.\n      string = baseToString(string);\n      return (string && reHasUnescapedHtml.test(string))\n        ? string.replace(reUnescapedHtml, escapeHtmlChar)\n        : string;\n    }\n\n    /**\n     * Escapes the `RegExp` special characters \"\\\", \"/\", \"^\", \"$\", \".\", \"|\", \"?\",\n     * \"*\", \"+\", \"(\", \")\", \"[\", \"]\", \"{\" and \"}\" in `string`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to escape.\n     * @returns {string} Returns the escaped string.\n     * @example\n     *\n     * _.escapeRegExp('[lodash](https://lodash.com/)');\n     * // => '\\[lodash\\]\\(https:\\/\\/lodash\\.com\\/\\)'\n     */\n    function escapeRegExp(string) {\n      string = baseToString(string);\n      return (string && reHasRegExpChars.test(string))\n        ? string.replace(reRegExpChars, escapeRegExpChar)\n        : (string || '(?:)');\n    }\n\n    /**\n     * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the kebab cased string.\n     * @example\n     *\n     * _.kebabCase('Foo Bar');\n     * // => 'foo-bar'\n     *\n     * _.kebabCase('fooBar');\n     * // => 'foo-bar'\n     *\n     * _.kebabCase('__foo_bar__');\n     * // => 'foo-bar'\n     */\n    var kebabCase = createCompounder(function(result, word, index) {\n      return result + (index ? '-' : '') + word.toLowerCase();\n    });\n\n    /**\n     * Pads `string` on the left and right sides if it's shorter than `length`.\n     * Padding characters are truncated if they can't be evenly divided by `length`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to pad.\n     * @param {number} [length=0] The padding length.\n     * @param {string} [chars=' '] The string used as padding.\n     * @returns {string} Returns the padded string.\n     * @example\n     *\n     * _.pad('abc', 8);\n     * // => '  abc   '\n     *\n     * _.pad('abc', 8, '_-');\n     * // => '_-abc_-_'\n     *\n     * _.pad('abc', 3);\n     * // => 'abc'\n     */\n    function pad(string, length, chars) {\n      string = baseToString(string);\n      length = +length;\n\n      var strLength = string.length;\n      if (strLength >= length || !nativeIsFinite(length)) {\n        return string;\n      }\n      var mid = (length - strLength) / 2,\n          leftLength = nativeFloor(mid),\n          rightLength = nativeCeil(mid);\n\n      chars = createPadding('', rightLength, chars);\n      return chars.slice(0, leftLength) + string + chars;\n    }\n\n    /**\n     * Pads `string` on the left side if it's shorter than `length`. Padding\n     * characters are truncated if they exceed `length`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to pad.\n     * @param {number} [length=0] The padding length.\n     * @param {string} [chars=' '] The string used as padding.\n     * @returns {string} Returns the padded string.\n     * @example\n     *\n     * _.padLeft('abc', 6);\n     * // => '   abc'\n     *\n     * _.padLeft('abc', 6, '_-');\n     * // => '_-_abc'\n     *\n     * _.padLeft('abc', 3);\n     * // => 'abc'\n     */\n    var padLeft = createPadDir();\n\n    /**\n     * Pads `string` on the right side if it's shorter than `length`. Padding\n     * characters are truncated if they exceed `length`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to pad.\n     * @param {number} [length=0] The padding length.\n     * @param {string} [chars=' '] The string used as padding.\n     * @returns {string} Returns the padded string.\n     * @example\n     *\n     * _.padRight('abc', 6);\n     * // => 'abc   '\n     *\n     * _.padRight('abc', 6, '_-');\n     * // => 'abc_-_'\n     *\n     * _.padRight('abc', 3);\n     * // => 'abc'\n     */\n    var padRight = createPadDir(true);\n\n    /**\n     * Converts `string` to an integer of the specified radix. If `radix` is\n     * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,\n     * in which case a `radix` of `16` is used.\n     *\n     * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E)\n     * of `parseInt`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} string The string to convert.\n     * @param {number} [radix] The radix to interpret `value` by.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {number} Returns the converted integer.\n     * @example\n     *\n     * _.parseInt('08');\n     * // => 8\n     *\n     * _.map(['6', '08', '10'], _.parseInt);\n     * // => [6, 8, 10]\n     */\n    function parseInt(string, radix, guard) {\n      // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`.\n      // Chrome fails to trim leading <BOM> whitespace characters.\n      // See https://code.google.com/p/v8/issues/detail?id=3109 for more details.\n      if (guard ? isIterateeCall(string, radix, guard) : radix == null) {\n        radix = 0;\n      } else if (radix) {\n        radix = +radix;\n      }\n      string = trim(string);\n      return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));\n    }\n\n    /**\n     * Repeats the given string `n` times.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to repeat.\n     * @param {number} [n=0] The number of times to repeat the string.\n     * @returns {string} Returns the repeated string.\n     * @example\n     *\n     * _.repeat('*', 3);\n     * // => '***'\n     *\n     * _.repeat('abc', 2);\n     * // => 'abcabc'\n     *\n     * _.repeat('abc', 0);\n     * // => ''\n     */\n    function repeat(string, n) {\n      var result = '';\n      string = baseToString(string);\n      n = +n;\n      if (n < 1 || !string || !nativeIsFinite(n)) {\n        return result;\n      }\n      // Leverage the exponentiation by squaring algorithm for a faster repeat.\n      // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.\n      do {\n        if (n % 2) {\n          result += string;\n        }\n        n = nativeFloor(n / 2);\n        string += string;\n      } while (n);\n\n      return result;\n    }\n\n    /**\n     * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the snake cased string.\n     * @example\n     *\n     * _.snakeCase('Foo Bar');\n     * // => 'foo_bar'\n     *\n     * _.snakeCase('fooBar');\n     * // => 'foo_bar'\n     *\n     * _.snakeCase('--foo-bar');\n     * // => 'foo_bar'\n     */\n    var snakeCase = createCompounder(function(result, word, index) {\n      return result + (index ? '_' : '') + word.toLowerCase();\n    });\n\n    /**\n     * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the start cased string.\n     * @example\n     *\n     * _.startCase('--foo-bar');\n     * // => 'Foo Bar'\n     *\n     * _.startCase('fooBar');\n     * // => 'Foo Bar'\n     *\n     * _.startCase('__foo_bar__');\n     * // => 'Foo Bar'\n     */\n    var startCase = createCompounder(function(result, word, index) {\n      return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1));\n    });\n\n    /**\n     * Checks if `string` starts with the given target string.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to search.\n     * @param {string} [target] The string to search for.\n     * @param {number} [position=0] The position to search from.\n     * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.\n     * @example\n     *\n     * _.startsWith('abc', 'a');\n     * // => true\n     *\n     * _.startsWith('abc', 'b');\n     * // => false\n     *\n     * _.startsWith('abc', 'b', 1);\n     * // => true\n     */\n    function startsWith(string, target, position) {\n      string = baseToString(string);\n      position = position == null\n        ? 0\n        : nativeMin(position < 0 ? 0 : (+position || 0), string.length);\n\n      return string.lastIndexOf(target, position) == position;\n    }\n\n    /**\n     * Creates a compiled template function that can interpolate data properties\n     * in \"interpolate\" delimiters, HTML-escape interpolated data properties in\n     * \"escape\" delimiters, and execute JavaScript in \"evaluate\" delimiters. Data\n     * properties may be accessed as free variables in the template. If a setting\n     * object is provided it takes precedence over `_.templateSettings` values.\n     *\n     * **Note:** In the development build `_.template` utilizes\n     * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)\n     * for easier debugging.\n     *\n     * For more information on precompiling templates see\n     * [lodash's custom builds documentation](https://lodash.com/custom-builds).\n     *\n     * For more information on Chrome extension sandboxes see\n     * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The template string.\n     * @param {Object} [options] The options object.\n     * @param {RegExp} [options.escape] The HTML \"escape\" delimiter.\n     * @param {RegExp} [options.evaluate] The \"evaluate\" delimiter.\n     * @param {Object} [options.imports] An object to import into the template as free variables.\n     * @param {RegExp} [options.interpolate] The \"interpolate\" delimiter.\n     * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.\n     * @param {string} [options.variable] The data object variable name.\n     * @param- {Object} [otherOptions] Enables the legacy `options` param signature.\n     * @returns {Function} Returns the compiled template function.\n     * @example\n     *\n     * // using the \"interpolate\" delimiter to create a compiled template\n     * var compiled = _.template('hello <%= user %>!');\n     * compiled({ 'user': 'fred' });\n     * // => 'hello fred!'\n     *\n     * // using the HTML \"escape\" delimiter to escape data property values\n     * var compiled = _.template('<b><%- value %></b>');\n     * compiled({ 'value': '<script>' });\n     * // => '<b>&lt;script&gt;</b>'\n     *\n     * // using the \"evaluate\" delimiter to execute JavaScript and generate HTML\n     * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');\n     * compiled({ 'users': ['fred', 'barney'] });\n     * // => '<li>fred</li><li>barney</li>'\n     *\n     * // using the internal `print` function in \"evaluate\" delimiters\n     * var compiled = _.template('<% print(\"hello \" + user); %>!');\n     * compiled({ 'user': 'barney' });\n     * // => 'hello barney!'\n     *\n     * // using the ES delimiter as an alternative to the default \"interpolate\" delimiter\n     * var compiled = _.template('hello ${ user }!');\n     * compiled({ 'user': 'pebbles' });\n     * // => 'hello pebbles!'\n     *\n     * // using custom template delimiters\n     * _.templateSettings.interpolate = /{{([\\s\\S]+?)}}/g;\n     * var compiled = _.template('hello {{ user }}!');\n     * compiled({ 'user': 'mustache' });\n     * // => 'hello mustache!'\n     *\n     * // using backslashes to treat delimiters as plain text\n     * var compiled = _.template('<%= \"\\\\<%- value %\\\\>\" %>');\n     * compiled({ 'value': 'ignored' });\n     * // => '<%- value %>'\n     *\n     * // using the `imports` option to import `jQuery` as `jq`\n     * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';\n     * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });\n     * compiled({ 'users': ['fred', 'barney'] });\n     * // => '<li>fred</li><li>barney</li>'\n     *\n     * // using the `sourceURL` option to specify a custom sourceURL for the template\n     * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });\n     * compiled(data);\n     * // => find the source of \"greeting.jst\" under the Sources tab or Resources panel of the web inspector\n     *\n     * // using the `variable` option to ensure a with-statement isn't used in the compiled template\n     * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });\n     * compiled.source;\n     * // => function(data) {\n     * //   var __t, __p = '';\n     * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';\n     * //   return __p;\n     * // }\n     *\n     * // using the `source` property to inline compiled templates for meaningful\n     * // line numbers in error messages and a stack trace\n     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\\\n     *   var JST = {\\\n     *     \"main\": ' + _.template(mainText).source + '\\\n     *   };\\\n     * ');\n     */\n    function template(string, options, otherOptions) {\n      // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)\n      // and Laura Doktorova's doT.js (https://github.com/olado/doT).\n      var settings = lodash.templateSettings;\n\n      if (otherOptions && isIterateeCall(string, options, otherOptions)) {\n        options = otherOptions = undefined;\n      }\n      string = baseToString(string);\n      options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);\n\n      var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),\n          importsKeys = keys(imports),\n          importsValues = baseValues(imports, importsKeys);\n\n      var isEscaping,\n          isEvaluating,\n          index = 0,\n          interpolate = options.interpolate || reNoMatch,\n          source = \"__p += '\";\n\n      // Compile the regexp to match each delimiter.\n      var reDelimiters = RegExp(\n        (options.escape || reNoMatch).source + '|' +\n        interpolate.source + '|' +\n        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +\n        (options.evaluate || reNoMatch).source + '|$'\n      , 'g');\n\n      // Use a sourceURL for easier debugging.\n      var sourceURL = '//# sourceURL=' +\n        ('sourceURL' in options\n          ? options.sourceURL\n          : ('lodash.templateSources[' + (++templateCounter) + ']')\n        ) + '\\n';\n\n      string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {\n        interpolateValue || (interpolateValue = esTemplateValue);\n\n        // Escape characters that can't be included in string literals.\n        source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);\n\n        // Replace delimiters with snippets.\n        if (escapeValue) {\n          isEscaping = true;\n          source += \"' +\\n__e(\" + escapeValue + \") +\\n'\";\n        }\n        if (evaluateValue) {\n          isEvaluating = true;\n          source += \"';\\n\" + evaluateValue + \";\\n__p += '\";\n        }\n        if (interpolateValue) {\n          source += \"' +\\n((__t = (\" + interpolateValue + \")) == null ? '' : __t) +\\n'\";\n        }\n        index = offset + match.length;\n\n        // The JS engine embedded in Adobe products requires returning the `match`\n        // string in order to produce the correct `offset` value.\n        return match;\n      });\n\n      source += \"';\\n\";\n\n      // If `variable` is not specified wrap a with-statement around the generated\n      // code to add the data object to the top of the scope chain.\n      var variable = options.variable;\n      if (!variable) {\n        source = 'with (obj) {\\n' + source + '\\n}\\n';\n      }\n      // Cleanup code by stripping empty strings.\n      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)\n        .replace(reEmptyStringMiddle, '$1')\n        .replace(reEmptyStringTrailing, '$1;');\n\n      // Frame code as the function body.\n      source = 'function(' + (variable || 'obj') + ') {\\n' +\n        (variable\n          ? ''\n          : 'obj || (obj = {});\\n'\n        ) +\n        \"var __t, __p = ''\" +\n        (isEscaping\n           ? ', __e = _.escape'\n           : ''\n        ) +\n        (isEvaluating\n          ? ', __j = Array.prototype.join;\\n' +\n            \"function print() { __p += __j.call(arguments, '') }\\n\"\n          : ';\\n'\n        ) +\n        source +\n        'return __p\\n}';\n\n      var result = attempt(function() {\n        return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);\n      });\n\n      // Provide the compiled function's source by its `toString` method or\n      // the `source` property as a convenience for inlining compiled templates.\n      result.source = source;\n      if (isError(result)) {\n        throw result;\n      }\n      return result;\n    }\n\n    /**\n     * Removes leading and trailing whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to trim.\n     * @param {string} [chars=whitespace] The characters to trim.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {string} Returns the trimmed string.\n     * @example\n     *\n     * _.trim('  abc  ');\n     * // => 'abc'\n     *\n     * _.trim('-_-abc-_-', '_-');\n     * // => 'abc'\n     *\n     * _.map(['  foo  ', '  bar  '], _.trim);\n     * // => ['foo', 'bar']\n     */\n    function trim(string, chars, guard) {\n      var value = string;\n      string = baseToString(string);\n      if (!string) {\n        return string;\n      }\n      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {\n        return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);\n      }\n      chars = (chars + '');\n      return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);\n    }\n\n    /**\n     * Removes leading whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to trim.\n     * @param {string} [chars=whitespace] The characters to trim.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {string} Returns the trimmed string.\n     * @example\n     *\n     * _.trimLeft('  abc  ');\n     * // => 'abc  '\n     *\n     * _.trimLeft('-_-abc-_-', '_-');\n     * // => 'abc-_-'\n     */\n    function trimLeft(string, chars, guard) {\n      var value = string;\n      string = baseToString(string);\n      if (!string) {\n        return string;\n      }\n      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {\n        return string.slice(trimmedLeftIndex(string));\n      }\n      return string.slice(charsLeftIndex(string, (chars + '')));\n    }\n\n    /**\n     * Removes trailing whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to trim.\n     * @param {string} [chars=whitespace] The characters to trim.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {string} Returns the trimmed string.\n     * @example\n     *\n     * _.trimRight('  abc  ');\n     * // => '  abc'\n     *\n     * _.trimRight('-_-abc-_-', '_-');\n     * // => '-_-abc'\n     */\n    function trimRight(string, chars, guard) {\n      var value = string;\n      string = baseToString(string);\n      if (!string) {\n        return string;\n      }\n      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {\n        return string.slice(0, trimmedRightIndex(string) + 1);\n      }\n      return string.slice(0, charsRightIndex(string, (chars + '')) + 1);\n    }\n\n    /**\n     * Truncates `string` if it's longer than the given maximum string length.\n     * The last characters of the truncated string are replaced with the omission\n     * string which defaults to \"...\".\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to truncate.\n     * @param {Object|number} [options] The options object or maximum string length.\n     * @param {number} [options.length=30] The maximum string length.\n     * @param {string} [options.omission='...'] The string to indicate text is omitted.\n     * @param {RegExp|string} [options.separator] The separator pattern to truncate to.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {string} Returns the truncated string.\n     * @example\n     *\n     * _.trunc('hi-diddly-ho there, neighborino');\n     * // => 'hi-diddly-ho there, neighbo...'\n     *\n     * _.trunc('hi-diddly-ho there, neighborino', 24);\n     * // => 'hi-diddly-ho there, n...'\n     *\n     * _.trunc('hi-diddly-ho there, neighborino', {\n     *   'length': 24,\n     *   'separator': ' '\n     * });\n     * // => 'hi-diddly-ho there,...'\n     *\n     * _.trunc('hi-diddly-ho there, neighborino', {\n     *   'length': 24,\n     *   'separator': /,? +/\n     * });\n     * // => 'hi-diddly-ho there...'\n     *\n     * _.trunc('hi-diddly-ho there, neighborino', {\n     *   'omission': ' [...]'\n     * });\n     * // => 'hi-diddly-ho there, neig [...]'\n     */\n    function trunc(string, options, guard) {\n      if (guard && isIterateeCall(string, options, guard)) {\n        options = undefined;\n      }\n      var length = DEFAULT_TRUNC_LENGTH,\n          omission = DEFAULT_TRUNC_OMISSION;\n\n      if (options != null) {\n        if (isObject(options)) {\n          var separator = 'separator' in options ? options.separator : separator;\n          length = 'length' in options ? (+options.length || 0) : length;\n          omission = 'omission' in options ? baseToString(options.omission) : omission;\n        } else {\n          length = +options || 0;\n        }\n      }\n      string = baseToString(string);\n      if (length >= string.length) {\n        return string;\n      }\n      var end = length - omission.length;\n      if (end < 1) {\n        return omission;\n      }\n      var result = string.slice(0, end);\n      if (separator == null) {\n        return result + omission;\n      }\n      if (isRegExp(separator)) {\n        if (string.slice(end).search(separator)) {\n          var match,\n              newEnd,\n              substring = string.slice(0, end);\n\n          if (!separator.global) {\n            separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');\n          }\n          separator.lastIndex = 0;\n          while ((match = separator.exec(substring))) {\n            newEnd = match.index;\n          }\n          result = result.slice(0, newEnd == null ? end : newEnd);\n        }\n      } else if (string.indexOf(separator, end) != end) {\n        var index = result.lastIndexOf(separator);\n        if (index > -1) {\n          result = result.slice(0, index);\n        }\n      }\n      return result + omission;\n    }\n\n    /**\n     * The inverse of `_.escape`; this method converts the HTML entities\n     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their\n     * corresponding characters.\n     *\n     * **Note:** No other HTML entities are unescaped. To unescape additional HTML\n     * entities use a third-party library like [_he_](https://mths.be/he).\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to unescape.\n     * @returns {string} Returns the unescaped string.\n     * @example\n     *\n     * _.unescape('fred, barney, &amp; pebbles');\n     * // => 'fred, barney, & pebbles'\n     */\n    function unescape(string) {\n      string = baseToString(string);\n      return (string && reHasEscapedHtml.test(string))\n        ? string.replace(reEscapedHtml, unescapeHtmlChar)\n        : string;\n    }\n\n    /**\n     * Splits `string` into an array of its words.\n     *\n     * @static\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The string to inspect.\n     * @param {RegExp|string} [pattern] The pattern to match words.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Array} Returns the words of `string`.\n     * @example\n     *\n     * _.words('fred, barney, & pebbles');\n     * // => ['fred', 'barney', 'pebbles']\n     *\n     * _.words('fred, barney, & pebbles', /[^, ]+/g);\n     * // => ['fred', 'barney', '&', 'pebbles']\n     */\n    function words(string, pattern, guard) {\n      if (guard && isIterateeCall(string, pattern, guard)) {\n        pattern = undefined;\n      }\n      string = baseToString(string);\n      return string.match(pattern || reWords) || [];\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Attempts to invoke `func`, returning either the result or the caught error\n     * object. Any additional arguments are provided to `func` when it is invoked.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Function} func The function to attempt.\n     * @returns {*} Returns the `func` result or error object.\n     * @example\n     *\n     * // avoid throwing errors for invalid selectors\n     * var elements = _.attempt(function(selector) {\n     *   return document.querySelectorAll(selector);\n     * }, '>_>');\n     *\n     * if (_.isError(elements)) {\n     *   elements = [];\n     * }\n     */\n    var attempt = restParam(function(func, args) {\n      try {\n        return func.apply(undefined, args);\n      } catch(e) {\n        return isError(e) ? e : new Error(e);\n      }\n    });\n\n    /**\n     * Creates a function that invokes `func` with the `this` binding of `thisArg`\n     * and arguments of the created function. If `func` is a property name the\n     * created callback returns the property value for a given element. If `func`\n     * is an object the created callback returns `true` for elements that contain\n     * the equivalent object properties, otherwise it returns `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias iteratee\n     * @category Utility\n     * @param {*} [func=_.identity] The value to convert to a callback.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.\n     * @returns {Function} Returns the callback.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 40 }\n     * ];\n     *\n     * // wrap to create custom callback shorthands\n     * _.callback = _.wrap(_.callback, function(callback, func, thisArg) {\n     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(func);\n     *   if (!match) {\n     *     return callback(func, thisArg);\n     *   }\n     *   return function(object) {\n     *     return match[2] == 'gt'\n     *       ? object[match[1]] > match[3]\n     *       : object[match[1]] < match[3];\n     *   };\n     * });\n     *\n     * _.filter(users, 'age__gt36');\n     * // => [{ 'user': 'fred', 'age': 40 }]\n     */\n    function callback(func, thisArg, guard) {\n      if (guard && isIterateeCall(func, thisArg, guard)) {\n        thisArg = undefined;\n      }\n      return isObjectLike(func)\n        ? matches(func)\n        : baseCallback(func, thisArg);\n    }\n\n    /**\n     * Creates a function that returns `value`.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {*} value The value to return from the new function.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var object = { 'user': 'fred' };\n     * var getter = _.constant(object);\n     *\n     * getter() === object;\n     * // => true\n     */\n    function constant(value) {\n      return function() {\n        return value;\n      };\n    }\n\n    /**\n     * This method returns the first argument provided to it.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {*} value Any value.\n     * @returns {*} Returns `value`.\n     * @example\n     *\n     * var object = { 'user': 'fred' };\n     *\n     * _.identity(object) === object;\n     * // => true\n     */\n    function identity(value) {\n      return value;\n    }\n\n    /**\n     * Creates a function that performs a deep comparison between a given object\n     * and `source`, returning `true` if the given object has equivalent property\n     * values, else `false`.\n     *\n     * **Note:** This method supports comparing arrays, booleans, `Date` objects,\n     * numbers, `Object` objects, regexes, and strings. Objects are compared by\n     * their own, not inherited, enumerable properties. For comparing a single\n     * own or inherited property value see `_.matchesProperty`.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Object} source The object of property values to match.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': true },\n     *   { 'user': 'fred',   'age': 40, 'active': false }\n     * ];\n     *\n     * _.filter(users, _.matches({ 'age': 40, 'active': false }));\n     * // => [{ 'user': 'fred', 'age': 40, 'active': false }]\n     */\n    function matches(source) {\n      return baseMatches(baseClone(source, true));\n    }\n\n    /**\n     * Creates a function that compares the property value of `path` on a given\n     * object to `value`.\n     *\n     * **Note:** This method supports comparing arrays, booleans, `Date` objects,\n     * numbers, `Object` objects, regexes, and strings. Objects are compared by\n     * their own, not inherited, enumerable properties.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Array|string} path The path of the property to get.\n     * @param {*} srcValue The value to match.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney' },\n     *   { 'user': 'fred' }\n     * ];\n     *\n     * _.find(users, _.matchesProperty('user', 'fred'));\n     * // => { 'user': 'fred' }\n     */\n    function matchesProperty(path, srcValue) {\n      return baseMatchesProperty(path, baseClone(srcValue, true));\n    }\n\n    /**\n     * Creates a function that invokes the method at `path` on a given object.\n     * Any additional arguments are provided to the invoked method.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Array|string} path The path of the method to invoke.\n     * @param {...*} [args] The arguments to invoke the method with.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': { 'b': { 'c': _.constant(2) } } },\n     *   { 'a': { 'b': { 'c': _.constant(1) } } }\n     * ];\n     *\n     * _.map(objects, _.method('a.b.c'));\n     * // => [2, 1]\n     *\n     * _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');\n     * // => [1, 2]\n     */\n    var method = restParam(function(path, args) {\n      return function(object) {\n        return invokePath(object, path, args);\n      };\n    });\n\n    /**\n     * The opposite of `_.method`; this method creates a function that invokes\n     * the method at a given path on `object`. Any additional arguments are\n     * provided to the invoked method.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Object} object The object to query.\n     * @param {...*} [args] The arguments to invoke the method with.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var array = _.times(3, _.constant),\n     *     object = { 'a': array, 'b': array, 'c': array };\n     *\n     * _.map(['a[2]', 'c[0]'], _.methodOf(object));\n     * // => [2, 0]\n     *\n     * _.map([['a', '2'], ['c', '0']], _.methodOf(object));\n     * // => [2, 0]\n     */\n    var methodOf = restParam(function(object, args) {\n      return function(path) {\n        return invokePath(object, path, args);\n      };\n    });\n\n    /**\n     * Adds all own enumerable function properties of a source object to the\n     * destination object. If `object` is a function then methods are added to\n     * its prototype as well.\n     *\n     * **Note:** Use `_.runInContext` to create a pristine `lodash` function to\n     * avoid conflicts caused by modifying the original.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Function|Object} [object=lodash] The destination object.\n     * @param {Object} source The object of functions to add.\n     * @param {Object} [options] The options object.\n     * @param {boolean} [options.chain=true] Specify whether the functions added\n     *  are chainable.\n     * @returns {Function|Object} Returns `object`.\n     * @example\n     *\n     * function vowels(string) {\n     *   return _.filter(string, function(v) {\n     *     return /[aeiou]/i.test(v);\n     *   });\n     * }\n     *\n     * _.mixin({ 'vowels': vowels });\n     * _.vowels('fred');\n     * // => ['e']\n     *\n     * _('fred').vowels().value();\n     * // => ['e']\n     *\n     * _.mixin({ 'vowels': vowels }, { 'chain': false });\n     * _('fred').vowels();\n     * // => ['e']\n     */\n    function mixin(object, source, options) {\n      if (options == null) {\n        var isObj = isObject(source),\n            props = isObj ? keys(source) : undefined,\n            methodNames = (props && props.length) ? baseFunctions(source, props) : undefined;\n\n        if (!(methodNames ? methodNames.length : isObj)) {\n          methodNames = false;\n          options = source;\n          source = object;\n          object = this;\n        }\n      }\n      if (!methodNames) {\n        methodNames = baseFunctions(source, keys(source));\n      }\n      var chain = true,\n          index = -1,\n          isFunc = isFunction(object),\n          length = methodNames.length;\n\n      if (options === false) {\n        chain = false;\n      } else if (isObject(options) && 'chain' in options) {\n        chain = options.chain;\n      }\n      while (++index < length) {\n        var methodName = methodNames[index],\n            func = source[methodName];\n\n        object[methodName] = func;\n        if (isFunc) {\n          object.prototype[methodName] = (function(func) {\n            return function() {\n              var chainAll = this.__chain__;\n              if (chain || chainAll) {\n                var result = object(this.__wrapped__),\n                    actions = result.__actions__ = arrayCopy(this.__actions__);\n\n                actions.push({ 'func': func, 'args': arguments, 'thisArg': object });\n                result.__chain__ = chainAll;\n                return result;\n              }\n              return func.apply(object, arrayPush([this.value()], arguments));\n            };\n          }(func));\n        }\n      }\n      return object;\n    }\n\n    /**\n     * Reverts the `_` variable to its previous value and returns a reference to\n     * the `lodash` function.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @returns {Function} Returns the `lodash` function.\n     * @example\n     *\n     * var lodash = _.noConflict();\n     */\n    function noConflict() {\n      root._ = oldDash;\n      return this;\n    }\n\n    /**\n     * A no-operation function that returns `undefined` regardless of the\n     * arguments it receives.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @example\n     *\n     * var object = { 'user': 'fred' };\n     *\n     * _.noop(object) === undefined;\n     * // => true\n     */\n    function noop() {\n      // No operation performed.\n    }\n\n    /**\n     * Creates a function that returns the property value at `path` on a\n     * given object.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Array|string} path The path of the property to get.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': { 'b': { 'c': 2 } } },\n     *   { 'a': { 'b': { 'c': 1 } } }\n     * ];\n     *\n     * _.map(objects, _.property('a.b.c'));\n     * // => [2, 1]\n     *\n     * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');\n     * // => [1, 2]\n     */\n    function property(path) {\n      return isKey(path) ? baseProperty(path) : basePropertyDeep(path);\n    }\n\n    /**\n     * The opposite of `_.property`; this method creates a function that returns\n     * the property value at a given path on `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {Object} object The object to query.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var array = [0, 1, 2],\n     *     object = { 'a': array, 'b': array, 'c': array };\n     *\n     * _.map(['a[2]', 'c[0]'], _.propertyOf(object));\n     * // => [2, 0]\n     *\n     * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));\n     * // => [2, 0]\n     */\n    function propertyOf(object) {\n      return function(path) {\n        return baseGet(object, toPath(path), path + '');\n      };\n    }\n\n    /**\n     * Creates an array of numbers (positive and/or negative) progressing from\n     * `start` up to, but not including, `end`. If `end` is not specified it is\n     * set to `start` with `start` then set to `0`. If `end` is less than `start`\n     * a zero-length range is created unless a negative `step` is specified.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {number} [start=0] The start of the range.\n     * @param {number} end The end of the range.\n     * @param {number} [step=1] The value to increment or decrement by.\n     * @returns {Array} Returns the new array of numbers.\n     * @example\n     *\n     * _.range(4);\n     * // => [0, 1, 2, 3]\n     *\n     * _.range(1, 5);\n     * // => [1, 2, 3, 4]\n     *\n     * _.range(0, 20, 5);\n     * // => [0, 5, 10, 15]\n     *\n     * _.range(0, -4, -1);\n     * // => [0, -1, -2, -3]\n     *\n     * _.range(1, 4, 0);\n     * // => [1, 1, 1]\n     *\n     * _.range(0);\n     * // => []\n     */\n    function range(start, end, step) {\n      if (step && isIterateeCall(start, end, step)) {\n        end = step = undefined;\n      }\n      start = +start || 0;\n      step = step == null ? 1 : (+step || 0);\n\n      if (end == null) {\n        end = start;\n        start = 0;\n      } else {\n        end = +end || 0;\n      }\n      // Use `Array(length)` so engines like Chakra and V8 avoid slower modes.\n      // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details.\n      var index = -1,\n          length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = start;\n        start += step;\n      }\n      return result;\n    }\n\n    /**\n     * Invokes the iteratee function `n` times, returning an array of the results\n     * of each invocation. The `iteratee` is bound to `thisArg` and invoked with\n     * one argument; (index).\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {number} n The number of times to invoke `iteratee`.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {Array} Returns the array of results.\n     * @example\n     *\n     * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false));\n     * // => [3, 6, 4]\n     *\n     * _.times(3, function(n) {\n     *   mage.castSpell(n);\n     * });\n     * // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2`\n     *\n     * _.times(3, function(n) {\n     *   this.cast(n);\n     * }, mage);\n     * // => also invokes `mage.castSpell(n)` three times\n     */\n    function times(n, iteratee, thisArg) {\n      n = nativeFloor(n);\n\n      // Exit early to avoid a JSC JIT bug in Safari 8\n      // where `Array(0)` is treated as `Array(1)`.\n      if (n < 1 || !nativeIsFinite(n)) {\n        return [];\n      }\n      var index = -1,\n          result = Array(nativeMin(n, MAX_ARRAY_LENGTH));\n\n      iteratee = bindCallback(iteratee, thisArg, 1);\n      while (++index < n) {\n        if (index < MAX_ARRAY_LENGTH) {\n          result[index] = iteratee(index);\n        } else {\n          iteratee(index);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Generates a unique ID. If `prefix` is provided the ID is appended to it.\n     *\n     * @static\n     * @memberOf _\n     * @category Utility\n     * @param {string} [prefix] The value to prefix the ID with.\n     * @returns {string} Returns the unique ID.\n     * @example\n     *\n     * _.uniqueId('contact_');\n     * // => 'contact_104'\n     *\n     * _.uniqueId();\n     * // => '105'\n     */\n    function uniqueId(prefix) {\n      var id = ++idCounter;\n      return baseToString(prefix) + id;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Adds two numbers.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {number} augend The first number to add.\n     * @param {number} addend The second number to add.\n     * @returns {number} Returns the sum.\n     * @example\n     *\n     * _.add(6, 4);\n     * // => 10\n     */\n    function add(augend, addend) {\n      return (+augend || 0) + (+addend || 0);\n    }\n\n    /**\n     * Calculates `n` rounded up to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {number} n The number to round up.\n     * @param {number} [precision=0] The precision to round up to.\n     * @returns {number} Returns the rounded up number.\n     * @example\n     *\n     * _.ceil(4.006);\n     * // => 5\n     *\n     * _.ceil(6.004, 2);\n     * // => 6.01\n     *\n     * _.ceil(6040, -2);\n     * // => 6100\n     */\n    var ceil = createRound('ceil');\n\n    /**\n     * Calculates `n` rounded down to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {number} n The number to round down.\n     * @param {number} [precision=0] The precision to round down to.\n     * @returns {number} Returns the rounded down number.\n     * @example\n     *\n     * _.floor(4.006);\n     * // => 4\n     *\n     * _.floor(0.046, 2);\n     * // => 0.04\n     *\n     * _.floor(4060, -2);\n     * // => 4000\n     */\n    var floor = createRound('floor');\n\n    /**\n     * Gets the maximum value of `collection`. If `collection` is empty or falsey\n     * `-Infinity` is returned. If an iteratee function is provided it is invoked\n     * for each value in `collection` to generate the criterion by which the value\n     * is ranked. The `iteratee` is bound to `thisArg` and invoked with three\n     * arguments: (value, index, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {*} Returns the maximum value.\n     * @example\n     *\n     * _.max([4, 2, 8, 6]);\n     * // => 8\n     *\n     * _.max([]);\n     * // => -Infinity\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 40 }\n     * ];\n     *\n     * _.max(users, function(chr) {\n     *   return chr.age;\n     * });\n     * // => { 'user': 'fred', 'age': 40 }\n     *\n     * // using the `_.property` callback shorthand\n     * _.max(users, 'age');\n     * // => { 'user': 'fred', 'age': 40 }\n     */\n    var max = createExtremum(gt, NEGATIVE_INFINITY);\n\n    /**\n     * Gets the minimum value of `collection`. If `collection` is empty or falsey\n     * `Infinity` is returned. If an iteratee function is provided it is invoked\n     * for each value in `collection` to generate the criterion by which the value\n     * is ranked. The `iteratee` is bound to `thisArg` and invoked with three\n     * arguments: (value, index, collection).\n     *\n     * If a property name is provided for `iteratee` the created `_.property`\n     * style callback returns the property value of the given element.\n     *\n     * If a value is also provided for `thisArg` the created `_.matchesProperty`\n     * style callback returns `true` for elements that have a matching property\n     * value, else `false`.\n     *\n     * If an object is provided for `iteratee` the created `_.matches` style\n     * callback returns `true` for elements that have the properties of the given\n     * object, else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {*} Returns the minimum value.\n     * @example\n     *\n     * _.min([4, 2, 8, 6]);\n     * // => 2\n     *\n     * _.min([]);\n     * // => Infinity\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36 },\n     *   { 'user': 'fred',   'age': 40 }\n     * ];\n     *\n     * _.min(users, function(chr) {\n     *   return chr.age;\n     * });\n     * // => { 'user': 'barney', 'age': 36 }\n     *\n     * // using the `_.property` callback shorthand\n     * _.min(users, 'age');\n     * // => { 'user': 'barney', 'age': 36 }\n     */\n    var min = createExtremum(lt, POSITIVE_INFINITY);\n\n    /**\n     * Calculates `n` rounded to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {number} n The number to round.\n     * @param {number} [precision=0] The precision to round to.\n     * @returns {number} Returns the rounded number.\n     * @example\n     *\n     * _.round(4.006);\n     * // => 4\n     *\n     * _.round(4.006, 2);\n     * // => 4.01\n     *\n     * _.round(4060, -2);\n     * // => 4100\n     */\n    var round = createRound('round');\n\n    /**\n     * Gets the sum of the values in `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @category Math\n     * @param {Array|Object|string} collection The collection to iterate over.\n     * @param {Function|Object|string} [iteratee] The function invoked per iteration.\n     * @param {*} [thisArg] The `this` binding of `iteratee`.\n     * @returns {number} Returns the sum.\n     * @example\n     *\n     * _.sum([4, 6]);\n     * // => 10\n     *\n     * _.sum({ 'a': 4, 'b': 6 });\n     * // => 10\n     *\n     * var objects = [\n     *   { 'n': 4 },\n     *   { 'n': 6 }\n     * ];\n     *\n     * _.sum(objects, function(object) {\n     *   return object.n;\n     * });\n     * // => 10\n     *\n     * // using the `_.property` callback shorthand\n     * _.sum(objects, 'n');\n     * // => 10\n     */\n    function sum(collection, iteratee, thisArg) {\n      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {\n        iteratee = undefined;\n      }\n      iteratee = getCallback(iteratee, thisArg, 3);\n      return iteratee.length == 1\n        ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee)\n        : baseSum(collection, iteratee);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // Ensure wrappers are instances of `baseLodash`.\n    lodash.prototype = baseLodash.prototype;\n\n    LodashWrapper.prototype = baseCreate(baseLodash.prototype);\n    LodashWrapper.prototype.constructor = LodashWrapper;\n\n    LazyWrapper.prototype = baseCreate(baseLodash.prototype);\n    LazyWrapper.prototype.constructor = LazyWrapper;\n\n    // Add functions to the `Map` cache.\n    MapCache.prototype['delete'] = mapDelete;\n    MapCache.prototype.get = mapGet;\n    MapCache.prototype.has = mapHas;\n    MapCache.prototype.set = mapSet;\n\n    // Add functions to the `Set` cache.\n    SetCache.prototype.push = cachePush;\n\n    // Assign cache to `_.memoize`.\n    memoize.Cache = MapCache;\n\n    // Add functions that return wrapped values when chaining.\n    lodash.after = after;\n    lodash.ary = ary;\n    lodash.assign = assign;\n    lodash.at = at;\n    lodash.before = before;\n    lodash.bind = bind;\n    lodash.bindAll = bindAll;\n    lodash.bindKey = bindKey;\n    lodash.callback = callback;\n    lodash.chain = chain;\n    lodash.chunk = chunk;\n    lodash.compact = compact;\n    lodash.constant = constant;\n    lodash.countBy = countBy;\n    lodash.create = create;\n    lodash.curry = curry;\n    lodash.curryRight = curryRight;\n    lodash.debounce = debounce;\n    lodash.defaults = defaults;\n    lodash.defaultsDeep = defaultsDeep;\n    lodash.defer = defer;\n    lodash.delay = delay;\n    lodash.difference = difference;\n    lodash.drop = drop;\n    lodash.dropRight = dropRight;\n    lodash.dropRightWhile = dropRightWhile;\n    lodash.dropWhile = dropWhile;\n    lodash.fill = fill;\n    lodash.filter = filter;\n    lodash.flatten = flatten;\n    lodash.flattenDeep = flattenDeep;\n    lodash.flow = flow;\n    lodash.flowRight = flowRight;\n    lodash.forEach = forEach;\n    lodash.forEachRight = forEachRight;\n    lodash.forIn = forIn;\n    lodash.forInRight = forInRight;\n    lodash.forOwn = forOwn;\n    lodash.forOwnRight = forOwnRight;\n    lodash.functions = functions;\n    lodash.groupBy = groupBy;\n    lodash.indexBy = indexBy;\n    lodash.initial = initial;\n    lodash.intersection = intersection;\n    lodash.invert = invert;\n    lodash.invoke = invoke;\n    lodash.keys = keys;\n    lodash.keysIn = keysIn;\n    lodash.map = map;\n    lodash.mapKeys = mapKeys;\n    lodash.mapValues = mapValues;\n    lodash.matches = matches;\n    lodash.matchesProperty = matchesProperty;\n    lodash.memoize = memoize;\n    lodash.merge = merge;\n    lodash.method = method;\n    lodash.methodOf = methodOf;\n    lodash.mixin = mixin;\n    lodash.modArgs = modArgs;\n    lodash.negate = negate;\n    lodash.omit = omit;\n    lodash.once = once;\n    lodash.pairs = pairs;\n    lodash.partial = partial;\n    lodash.partialRight = partialRight;\n    lodash.partition = partition;\n    lodash.pick = pick;\n    lodash.pluck = pluck;\n    lodash.property = property;\n    lodash.propertyOf = propertyOf;\n    lodash.pull = pull;\n    lodash.pullAt = pullAt;\n    lodash.range = range;\n    lodash.rearg = rearg;\n    lodash.reject = reject;\n    lodash.remove = remove;\n    lodash.rest = rest;\n    lodash.restParam = restParam;\n    lodash.set = set;\n    lodash.shuffle = shuffle;\n    lodash.slice = slice;\n    lodash.sortBy = sortBy;\n    lodash.sortByAll = sortByAll;\n    lodash.sortByOrder = sortByOrder;\n    lodash.spread = spread;\n    lodash.take = take;\n    lodash.takeRight = takeRight;\n    lodash.takeRightWhile = takeRightWhile;\n    lodash.takeWhile = takeWhile;\n    lodash.tap = tap;\n    lodash.throttle = throttle;\n    lodash.thru = thru;\n    lodash.times = times;\n    lodash.toArray = toArray;\n    lodash.toPlainObject = toPlainObject;\n    lodash.transform = transform;\n    lodash.union = union;\n    lodash.uniq = uniq;\n    lodash.unzip = unzip;\n    lodash.unzipWith = unzipWith;\n    lodash.values = values;\n    lodash.valuesIn = valuesIn;\n    lodash.where = where;\n    lodash.without = without;\n    lodash.wrap = wrap;\n    lodash.xor = xor;\n    lodash.zip = zip;\n    lodash.zipObject = zipObject;\n    lodash.zipWith = zipWith;\n\n    // Add aliases.\n    lodash.backflow = flowRight;\n    lodash.collect = map;\n    lodash.compose = flowRight;\n    lodash.each = forEach;\n    lodash.eachRight = forEachRight;\n    lodash.extend = assign;\n    lodash.iteratee = callback;\n    lodash.methods = functions;\n    lodash.object = zipObject;\n    lodash.select = filter;\n    lodash.tail = rest;\n    lodash.unique = uniq;\n\n    // Add functions to `lodash.prototype`.\n    mixin(lodash, lodash);\n\n    /*------------------------------------------------------------------------*/\n\n    // Add functions that return unwrapped values when chaining.\n    lodash.add = add;\n    lodash.attempt = attempt;\n    lodash.camelCase = camelCase;\n    lodash.capitalize = capitalize;\n    lodash.ceil = ceil;\n    lodash.clone = clone;\n    lodash.cloneDeep = cloneDeep;\n    lodash.deburr = deburr;\n    lodash.endsWith = endsWith;\n    lodash.escape = escape;\n    lodash.escapeRegExp = escapeRegExp;\n    lodash.every = every;\n    lodash.find = find;\n    lodash.findIndex = findIndex;\n    lodash.findKey = findKey;\n    lodash.findLast = findLast;\n    lodash.findLastIndex = findLastIndex;\n    lodash.findLastKey = findLastKey;\n    lodash.findWhere = findWhere;\n    lodash.first = first;\n    lodash.floor = floor;\n    lodash.get = get;\n    lodash.gt = gt;\n    lodash.gte = gte;\n    lodash.has = has;\n    lodash.identity = identity;\n    lodash.includes = includes;\n    lodash.indexOf = indexOf;\n    lodash.inRange = inRange;\n    lodash.isArguments = isArguments;\n    lodash.isArray = isArray;\n    lodash.isBoolean = isBoolean;\n    lodash.isDate = isDate;\n    lodash.isElement = isElement;\n    lodash.isEmpty = isEmpty;\n    lodash.isEqual = isEqual;\n    lodash.isError = isError;\n    lodash.isFinite = isFinite;\n    lodash.isFunction = isFunction;\n    lodash.isMatch = isMatch;\n    lodash.isNaN = isNaN;\n    lodash.isNative = isNative;\n    lodash.isNull = isNull;\n    lodash.isNumber = isNumber;\n    lodash.isObject = isObject;\n    lodash.isPlainObject = isPlainObject;\n    lodash.isRegExp = isRegExp;\n    lodash.isString = isString;\n    lodash.isTypedArray = isTypedArray;\n    lodash.isUndefined = isUndefined;\n    lodash.kebabCase = kebabCase;\n    lodash.last = last;\n    lodash.lastIndexOf = lastIndexOf;\n    lodash.lt = lt;\n    lodash.lte = lte;\n    lodash.max = max;\n    lodash.min = min;\n    lodash.noConflict = noConflict;\n    lodash.noop = noop;\n    lodash.now = now;\n    lodash.pad = pad;\n    lodash.padLeft = padLeft;\n    lodash.padRight = padRight;\n    lodash.parseInt = parseInt;\n    lodash.random = random;\n    lodash.reduce = reduce;\n    lodash.reduceRight = reduceRight;\n    lodash.repeat = repeat;\n    lodash.result = result;\n    lodash.round = round;\n    lodash.runInContext = runInContext;\n    lodash.size = size;\n    lodash.snakeCase = snakeCase;\n    lodash.some = some;\n    lodash.sortedIndex = sortedIndex;\n    lodash.sortedLastIndex = sortedLastIndex;\n    lodash.startCase = startCase;\n    lodash.startsWith = startsWith;\n    lodash.sum = sum;\n    lodash.template = template;\n    lodash.trim = trim;\n    lodash.trimLeft = trimLeft;\n    lodash.trimRight = trimRight;\n    lodash.trunc = trunc;\n    lodash.unescape = unescape;\n    lodash.uniqueId = uniqueId;\n    lodash.words = words;\n\n    // Add aliases.\n    lodash.all = every;\n    lodash.any = some;\n    lodash.contains = includes;\n    lodash.eq = isEqual;\n    lodash.detect = find;\n    lodash.foldl = reduce;\n    lodash.foldr = reduceRight;\n    lodash.head = first;\n    lodash.include = includes;\n    lodash.inject = reduce;\n\n    mixin(lodash, (function() {\n      var source = {};\n      baseForOwn(lodash, function(func, methodName) {\n        if (!lodash.prototype[methodName]) {\n          source[methodName] = func;\n        }\n      });\n      return source;\n    }()), false);\n\n    /*------------------------------------------------------------------------*/\n\n    // Add functions capable of returning wrapped and unwrapped values when chaining.\n    lodash.sample = sample;\n\n    lodash.prototype.sample = function(n) {\n      if (!this.__chain__ && n == null) {\n        return sample(this.value());\n      }\n      return this.thru(function(value) {\n        return sample(value, n);\n      });\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The semantic version number.\n     *\n     * @static\n     * @memberOf _\n     * @type string\n     */\n    lodash.VERSION = VERSION;\n\n    // Assign default placeholders.\n    arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {\n      lodash[methodName].placeholder = lodash;\n    });\n\n    // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.\n    arrayEach(['drop', 'take'], function(methodName, index) {\n      LazyWrapper.prototype[methodName] = function(n) {\n        var filtered = this.__filtered__;\n        if (filtered && !index) {\n          return new LazyWrapper(this);\n        }\n        n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0);\n\n        var result = this.clone();\n        if (filtered) {\n          result.__takeCount__ = nativeMin(result.__takeCount__, n);\n        } else {\n          result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });\n        }\n        return result;\n      };\n\n      LazyWrapper.prototype[methodName + 'Right'] = function(n) {\n        return this.reverse()[methodName](n).reverse();\n      };\n    });\n\n    // Add `LazyWrapper` methods that accept an `iteratee` value.\n    arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {\n      var type = index + 1,\n          isFilter = type != LAZY_MAP_FLAG;\n\n      LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {\n        var result = this.clone();\n        result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type });\n        result.__filtered__ = result.__filtered__ || isFilter;\n        return result;\n      };\n    });\n\n    // Add `LazyWrapper` methods for `_.first` and `_.last`.\n    arrayEach(['first', 'last'], function(methodName, index) {\n      var takeName = 'take' + (index ? 'Right' : '');\n\n      LazyWrapper.prototype[methodName] = function() {\n        return this[takeName](1).value()[0];\n      };\n    });\n\n    // Add `LazyWrapper` methods for `_.initial` and `_.rest`.\n    arrayEach(['initial', 'rest'], function(methodName, index) {\n      var dropName = 'drop' + (index ? '' : 'Right');\n\n      LazyWrapper.prototype[methodName] = function() {\n        return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);\n      };\n    });\n\n    // Add `LazyWrapper` methods for `_.pluck` and `_.where`.\n    arrayEach(['pluck', 'where'], function(methodName, index) {\n      var operationName = index ? 'filter' : 'map',\n          createCallback = index ? baseMatches : property;\n\n      LazyWrapper.prototype[methodName] = function(value) {\n        return this[operationName](createCallback(value));\n      };\n    });\n\n    LazyWrapper.prototype.compact = function() {\n      return this.filter(identity);\n    };\n\n    LazyWrapper.prototype.reject = function(predicate, thisArg) {\n      predicate = getCallback(predicate, thisArg, 1);\n      return this.filter(function(value) {\n        return !predicate(value);\n      });\n    };\n\n    LazyWrapper.prototype.slice = function(start, end) {\n      start = start == null ? 0 : (+start || 0);\n\n      var result = this;\n      if (result.__filtered__ && (start > 0 || end < 0)) {\n        return new LazyWrapper(result);\n      }\n      if (start < 0) {\n        result = result.takeRight(-start);\n      } else if (start) {\n        result = result.drop(start);\n      }\n      if (end !== undefined) {\n        end = (+end || 0);\n        result = end < 0 ? result.dropRight(-end) : result.take(end - start);\n      }\n      return result;\n    };\n\n    LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) {\n      return this.reverse().takeWhile(predicate, thisArg).reverse();\n    };\n\n    LazyWrapper.prototype.toArray = function() {\n      return this.take(POSITIVE_INFINITY);\n    };\n\n    // Add `LazyWrapper` methods to `lodash.prototype`.\n    baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n      var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),\n          retUnwrapped = /^(?:first|last)$/.test(methodName),\n          lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];\n\n      if (!lodashFunc) {\n        return;\n      }\n      lodash.prototype[methodName] = function() {\n        var args = retUnwrapped ? [1] : arguments,\n            chainAll = this.__chain__,\n            value = this.__wrapped__,\n            isHybrid = !!this.__actions__.length,\n            isLazy = value instanceof LazyWrapper,\n            iteratee = args[0],\n            useLazy = isLazy || isArray(value);\n\n        if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {\n          // Avoid lazy use if the iteratee has a \"length\" value other than `1`.\n          isLazy = useLazy = false;\n        }\n        var interceptor = function(value) {\n          return (retUnwrapped && chainAll)\n            ? lodashFunc(value, 1)[0]\n            : lodashFunc.apply(undefined, arrayPush([value], args));\n        };\n\n        var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined },\n            onlyLazy = isLazy && !isHybrid;\n\n        if (retUnwrapped && !chainAll) {\n          if (onlyLazy) {\n            value = value.clone();\n            value.__actions__.push(action);\n            return func.call(value);\n          }\n          return lodashFunc.call(undefined, this.value())[0];\n        }\n        if (!retUnwrapped && useLazy) {\n          value = onlyLazy ? value : new LazyWrapper(this);\n          var result = func.apply(value, args);\n          result.__actions__.push(action);\n          return new LodashWrapper(result, chainAll);\n        }\n        return this.thru(interceptor);\n      };\n    });\n\n    // Add `Array` and `String` methods to `lodash.prototype`.\n    arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {\n      var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],\n          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',\n          retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);\n\n      lodash.prototype[methodName] = function() {\n        var args = arguments;\n        if (retUnwrapped && !this.__chain__) {\n          return func.apply(this.value(), args);\n        }\n        return this[chainName](function(value) {\n          return func.apply(value, args);\n        });\n      };\n    });\n\n    // Map minified function names to their real names.\n    baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n      var lodashFunc = lodash[methodName];\n      if (lodashFunc) {\n        var key = lodashFunc.name,\n            names = realNames[key] || (realNames[key] = []);\n\n        names.push({ 'name': methodName, 'func': lodashFunc });\n      }\n    });\n\n    realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }];\n\n    // Add functions to the lazy wrapper.\n    LazyWrapper.prototype.clone = lazyClone;\n    LazyWrapper.prototype.reverse = lazyReverse;\n    LazyWrapper.prototype.value = lazyValue;\n\n    // Add chaining functions to the `lodash` wrapper.\n    lodash.prototype.chain = wrapperChain;\n    lodash.prototype.commit = wrapperCommit;\n    lodash.prototype.concat = wrapperConcat;\n    lodash.prototype.plant = wrapperPlant;\n    lodash.prototype.reverse = wrapperReverse;\n    lodash.prototype.toString = wrapperToString;\n    lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;\n\n    // Add function aliases to the `lodash` wrapper.\n    lodash.prototype.collect = lodash.prototype.map;\n    lodash.prototype.head = lodash.prototype.first;\n    lodash.prototype.select = lodash.prototype.filter;\n    lodash.prototype.tail = lodash.prototype.rest;\n\n    return lodash;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // Export lodash.\n  var _ = runInContext();\n\n  // Some AMD build optimizers like r.js check for condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // Expose lodash to the global object when an AMD loader is present to avoid\n    // errors in cases where lodash is loaded by a script tag and not intended\n    // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for\n    // more details.\n    root._ = _;\n\n    // Define as an anonymous module so, through path mapping, it can be\n    // referenced as the \"underscore\" module.\n    define(function() {\n      return _;\n    });\n  }\n  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.\n  else if (freeExports && freeModule) {\n    // Export for Node.js or RingoJS.\n    if (moduleExports) {\n      (freeModule.exports = _)._ = _;\n    }\n    // Export for Rhino with CommonJS support.\n    else {\n      freeExports._ = _;\n    }\n  }\n  else {\n    // Export for a browser or Rhino.\n    root._ = _;\n  }\n}.call(this));\n","'use strict';\n\nmodule.exports = require('./lib')\n","'use strict';\n\nvar asap = require('asap/raw');\n\nfunction noop() {}\n\n// States:\n//\n// 0 - pending\n// 1 - fulfilled with _value\n// 2 - rejected with _value\n// 3 - adopted the state of another promise, _value\n//\n// once the state is no longer pending (0) it is immutable\n\n// All `_` prefixed properties will be reduced to `_{random number}`\n// at build time to obfuscate them and discourage their use.\n// We don't use symbols or Object.defineProperty to fully hide them\n// because the performance isn't good enough.\n\n\n// to avoid using try/catch inside critical functions, we\n// extract them to here.\nvar LAST_ERROR = null;\nvar IS_ERROR = {};\nfunction getThen(obj) {\n  try {\n    return obj.then;\n  } catch (ex) {\n    LAST_ERROR = ex;\n    return IS_ERROR;\n  }\n}\n\nfunction tryCallOne(fn, a) {\n  try {\n    return fn(a);\n  } catch (ex) {\n    LAST_ERROR = ex;\n    return IS_ERROR;\n  }\n}\nfunction tryCallTwo(fn, a, b) {\n  try {\n    fn(a, b);\n  } catch (ex) {\n    LAST_ERROR = ex;\n    return IS_ERROR;\n  }\n}\n\nmodule.exports = Promise;\n\nfunction Promise(fn) {\n  if (typeof this !== 'object') {\n    throw new TypeError('Promises must be constructed via new');\n  }\n  if (typeof fn !== 'function') {\n    throw new TypeError('Promise constructor\\'s argument is not a function');\n  }\n  this._40 = 0;\n  this._65 = 0;\n  this._55 = null;\n  this._72 = null;\n  if (fn === noop) return;\n  doResolve(fn, this);\n}\nPromise._37 = null;\nPromise._87 = null;\nPromise._61 = noop;\n\nPromise.prototype.then = function(onFulfilled, onRejected) {\n  if (this.constructor !== Promise) {\n    return safeThen(this, onFulfilled, onRejected);\n  }\n  var res = new Promise(noop);\n  handle(this, new Handler(onFulfilled, onRejected, res));\n  return res;\n};\n\nfunction safeThen(self, onFulfilled, onRejected) {\n  return new self.constructor(function (resolve, reject) {\n    var res = new Promise(noop);\n    res.then(resolve, reject);\n    handle(self, new Handler(onFulfilled, onRejected, res));\n  });\n}\nfunction handle(self, deferred) {\n  while (self._65 === 3) {\n    self = self._55;\n  }\n  if (Promise._37) {\n    Promise._37(self);\n  }\n  if (self._65 === 0) {\n    if (self._40 === 0) {\n      self._40 = 1;\n      self._72 = deferred;\n      return;\n    }\n    if (self._40 === 1) {\n      self._40 = 2;\n      self._72 = [self._72, deferred];\n      return;\n    }\n    self._72.push(deferred);\n    return;\n  }\n  handleResolved(self, deferred);\n}\n\nfunction handleResolved(self, deferred) {\n  asap(function() {\n    var cb = self._65 === 1 ? deferred.onFulfilled : deferred.onRejected;\n    if (cb === null) {\n      if (self._65 === 1) {\n        resolve(deferred.promise, self._55);\n      } else {\n        reject(deferred.promise, self._55);\n      }\n      return;\n    }\n    var ret = tryCallOne(cb, self._55);\n    if (ret === IS_ERROR) {\n      reject(deferred.promise, LAST_ERROR);\n    } else {\n      resolve(deferred.promise, ret);\n    }\n  });\n}\nfunction resolve(self, newValue) {\n  // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure\n  if (newValue === self) {\n    return reject(\n      self,\n      new TypeError('A promise cannot be resolved with itself.')\n    );\n  }\n  if (\n    newValue &&\n    (typeof newValue === 'object' || typeof newValue === 'function')\n  ) {\n    var then = getThen(newValue);\n    if (then === IS_ERROR) {\n      return reject(self, LAST_ERROR);\n    }\n    if (\n      then === self.then &&\n      newValue instanceof Promise\n    ) {\n      self._65 = 3;\n      self._55 = newValue;\n      finale(self);\n      return;\n    } else if (typeof then === 'function') {\n      doResolve(then.bind(newValue), self);\n      return;\n    }\n  }\n  self._65 = 1;\n  self._55 = newValue;\n  finale(self);\n}\n\nfunction reject(self, newValue) {\n  self._65 = 2;\n  self._55 = newValue;\n  if (Promise._87) {\n    Promise._87(self, newValue);\n  }\n  finale(self);\n}\nfunction finale(self) {\n  if (self._40 === 1) {\n    handle(self, self._72);\n    self._72 = null;\n  }\n  if (self._40 === 2) {\n    for (var i = 0; i < self._72.length; i++) {\n      handle(self, self._72[i]);\n    }\n    self._72 = null;\n  }\n}\n\nfunction Handler(onFulfilled, onRejected, promise){\n  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;\n  this.onRejected = typeof onRejected === 'function' ? onRejected : null;\n  this.promise = promise;\n}\n\n/**\n * Take a potentially misbehaving resolver function and make sure\n * onFulfilled and onRejected are only called once.\n *\n * Makes no guarantees about asynchrony.\n */\nfunction doResolve(fn, promise) {\n  var done = false;\n  var res = tryCallTwo(fn, function (value) {\n    if (done) return;\n    done = true;\n    resolve(promise, value);\n  }, function (reason) {\n    if (done) return;\n    done = true;\n    reject(promise, reason);\n  });\n  if (!done && res === IS_ERROR) {\n    done = true;\n    reject(promise, LAST_ERROR);\n  }\n}\n","'use strict';\n\nvar Promise = require('./core.js');\n\nmodule.exports = Promise;\nPromise.prototype.done = function (onFulfilled, onRejected) {\n  var self = arguments.length ? this.then.apply(this, arguments) : this;\n  self.then(null, function (err) {\n    setTimeout(function () {\n      throw err;\n    }, 0);\n  });\n};\n","'use strict';\n\n//This file contains the ES6 extensions to the core Promises/A+ API\n\nvar Promise = require('./core.js');\n\nmodule.exports = Promise;\n\n/* Static Functions */\n\nvar TRUE = valuePromise(true);\nvar FALSE = valuePromise(false);\nvar NULL = valuePromise(null);\nvar UNDEFINED = valuePromise(undefined);\nvar ZERO = valuePromise(0);\nvar EMPTYSTRING = valuePromise('');\n\nfunction valuePromise(value) {\n  var p = new Promise(Promise._61);\n  p._65 = 1;\n  p._55 = value;\n  return p;\n}\nPromise.resolve = function (value) {\n  if (value instanceof Promise) return value;\n\n  if (value === null) return NULL;\n  if (value === undefined) return UNDEFINED;\n  if (value === true) return TRUE;\n  if (value === false) return FALSE;\n  if (value === 0) return ZERO;\n  if (value === '') return EMPTYSTRING;\n\n  if (typeof value === 'object' || typeof value === 'function') {\n    try {\n      var then = value.then;\n      if (typeof then === 'function') {\n        return new Promise(then.bind(value));\n      }\n    } catch (ex) {\n      return new Promise(function (resolve, reject) {\n        reject(ex);\n      });\n    }\n  }\n  return valuePromise(value);\n};\n\nPromise.all = function (arr) {\n  var args = Array.prototype.slice.call(arr);\n\n  return new Promise(function (resolve, reject) {\n    if (args.length === 0) return resolve([]);\n    var remaining = args.length;\n    function res(i, val) {\n      if (val && (typeof val === 'object' || typeof val === 'function')) {\n        if (val instanceof Promise && val.then === Promise.prototype.then) {\n          while (val._65 === 3) {\n            val = val._55;\n          }\n          if (val._65 === 1) return res(i, val._55);\n          if (val._65 === 2) reject(val._55);\n          val.then(function (val) {\n            res(i, val);\n          }, reject);\n          return;\n        } else {\n          var then = val.then;\n          if (typeof then === 'function') {\n            var p = new Promise(then.bind(val));\n            p.then(function (val) {\n              res(i, val);\n            }, reject);\n            return;\n          }\n        }\n      }\n      args[i] = val;\n      if (--remaining === 0) {\n        resolve(args);\n      }\n    }\n    for (var i = 0; i < args.length; i++) {\n      res(i, args[i]);\n    }\n  });\n};\n\nPromise.reject = function (value) {\n  return new Promise(function (resolve, reject) {\n    reject(value);\n  });\n};\n\nPromise.race = function (values) {\n  return new Promise(function (resolve, reject) {\n    values.forEach(function(value){\n      Promise.resolve(value).then(resolve, reject);\n    });\n  });\n};\n\n/* Prototype Methods */\n\nPromise.prototype['catch'] = function (onRejected) {\n  return this.then(null, onRejected);\n};\n","'use strict';\n\nvar Promise = require('./core.js');\n\nmodule.exports = Promise;\nPromise.prototype['finally'] = function (f) {\n  return this.then(function (value) {\n    return Promise.resolve(f()).then(function () {\n      return value;\n    });\n  }, function (err) {\n    return Promise.resolve(f()).then(function () {\n      throw err;\n    });\n  });\n};\n","'use strict';\n\nmodule.exports = require('./core.js');\nrequire('./done.js');\nrequire('./finally.js');\nrequire('./es6-extensions.js');\nrequire('./node-extensions.js');\nrequire('./synchronous.js');\n","'use strict';\n\n// This file contains then/promise specific extensions that are only useful\n// for node.js interop\n\nvar Promise = require('./core.js');\nvar asap = require('asap');\n\nmodule.exports = Promise;\n\n/* Static Functions */\n\nPromise.denodeify = function (fn, argumentCount) {\n  if (\n    typeof argumentCount === 'number' && argumentCount !== Infinity\n  ) {\n    return denodeifyWithCount(fn, argumentCount);\n  } else {\n    return denodeifyWithoutCount(fn);\n  }\n};\n\nvar callbackFn = (\n  'function (err, res) {' +\n  'if (err) { rj(err); } else { rs(res); }' +\n  '}'\n);\nfunction denodeifyWithCount(fn, argumentCount) {\n  var args = [];\n  for (var i = 0; i < argumentCount; i++) {\n    args.push('a' + i);\n  }\n  var body = [\n    'return function (' + args.join(',') + ') {',\n    'var self = this;',\n    'return new Promise(function (rs, rj) {',\n    'var res = fn.call(',\n    ['self'].concat(args).concat([callbackFn]).join(','),\n    ');',\n    'if (res &&',\n    '(typeof res === \"object\" || typeof res === \"function\") &&',\n    'typeof res.then === \"function\"',\n    ') {rs(res);}',\n    '});',\n    '};'\n  ].join('');\n  return Function(['Promise', 'fn'], body)(Promise, fn);\n}\nfunction denodeifyWithoutCount(fn) {\n  var fnLength = Math.max(fn.length - 1, 3);\n  var args = [];\n  for (var i = 0; i < fnLength; i++) {\n    args.push('a' + i);\n  }\n  var body = [\n    'return function (' + args.join(',') + ') {',\n    'var self = this;',\n    'var args;',\n    'var argLength = arguments.length;',\n    'if (arguments.length > ' + fnLength + ') {',\n    'args = new Array(arguments.length + 1);',\n    'for (var i = 0; i < arguments.length; i++) {',\n    'args[i] = arguments[i];',\n    '}',\n    '}',\n    'return new Promise(function (rs, rj) {',\n    'var cb = ' + callbackFn + ';',\n    'var res;',\n    'switch (argLength) {',\n    args.concat(['extra']).map(function (_, index) {\n      return (\n        'case ' + (index) + ':' +\n        'res = fn.call(' + ['self'].concat(args.slice(0, index)).concat('cb').join(',') + ');' +\n        'break;'\n      );\n    }).join(''),\n    'default:',\n    'args[argLength] = cb;',\n    'res = fn.apply(self, args);',\n    '}',\n    \n    'if (res &&',\n    '(typeof res === \"object\" || typeof res === \"function\") &&',\n    'typeof res.then === \"function\"',\n    ') {rs(res);}',\n    '});',\n    '};'\n  ].join('');\n\n  return Function(\n    ['Promise', 'fn'],\n    body\n  )(Promise, fn);\n}\n\nPromise.nodeify = function (fn) {\n  return function () {\n    var args = Array.prototype.slice.call(arguments);\n    var callback =\n      typeof args[args.length - 1] === 'function' ? args.pop() : null;\n    var ctx = this;\n    try {\n      return fn.apply(this, arguments).nodeify(callback, ctx);\n    } catch (ex) {\n      if (callback === null || typeof callback == 'undefined') {\n        return new Promise(function (resolve, reject) {\n          reject(ex);\n        });\n      } else {\n        asap(function () {\n          callback.call(ctx, ex);\n        })\n      }\n    }\n  }\n};\n\nPromise.prototype.nodeify = function (callback, ctx) {\n  if (typeof callback != 'function') return this;\n\n  this.then(function (value) {\n    asap(function () {\n      callback.call(ctx, null, value);\n    });\n  }, function (err) {\n    asap(function () {\n      callback.call(ctx, err);\n    });\n  });\n};\n","'use strict';\n\nvar Promise = require('./core.js');\n\nmodule.exports = Promise;\nPromise.enableSynchronous = function () {\n  Promise.prototype.isPending = function() {\n    return this.getState() == 0;\n  };\n\n  Promise.prototype.isFulfilled = function() {\n    return this.getState() == 1;\n  };\n\n  Promise.prototype.isRejected = function() {\n    return this.getState() == 2;\n  };\n\n  Promise.prototype.getValue = function () {\n    if (this._65 === 3) {\n      return this._55.getValue();\n    }\n\n    if (!this.isFulfilled()) {\n      throw new Error('Cannot get a value of an unfulfilled promise.');\n    }\n\n    return this._55;\n  };\n\n  Promise.prototype.getReason = function () {\n    if (this._65 === 3) {\n      return this._55.getReason();\n    }\n\n    if (!this.isRejected()) {\n      throw new Error('Cannot get a rejection reason of a non-rejected promise.');\n    }\n\n    return this._55;\n  };\n\n  Promise.prototype.getState = function () {\n    if (this._65 === 3) {\n      return this._55.getState();\n    }\n    if (this._65 === -1 || this._65 === -2) {\n      return 0;\n    }\n\n    return this._65;\n  };\n};\n\nPromise.disableSynchronous = function() {\n  Promise.prototype.isPending = undefined;\n  Promise.prototype.isFulfilled = undefined;\n  Promise.prototype.isRejected = undefined;\n  Promise.prototype.getValue = undefined;\n  Promise.prototype.getReason = undefined;\n  Promise.prototype.getState = undefined;\n};\n","\"use strict\";\n\n// rawAsap provides everything we need except exception management.\nvar rawAsap = require(\"./raw\");\n// RawTasks are recycled to reduce GC churn.\nvar freeTasks = [];\n// We queue errors to ensure they are thrown in right order (FIFO).\n// Array-as-queue is good enough here, since we are just dealing with exceptions.\nvar pendingErrors = [];\nvar requestErrorThrow = rawAsap.makeRequestCallFromTimer(throwFirstError);\n\nfunction throwFirstError() {\n    if (pendingErrors.length) {\n        throw pendingErrors.shift();\n    }\n}\n\n/**\n * Calls a task as soon as possible after returning, in its own event, with priority\n * over other events like animation, reflow, and repaint. An error thrown from an\n * event will not interrupt, nor even substantially slow down the processing of\n * other events, but will be rather postponed to a lower priority event.\n * @param {{call}} task A callable object, typically a function that takes no\n * arguments.\n */\nmodule.exports = asap;\nfunction asap(task) {\n    var rawTask;\n    if (freeTasks.length) {\n        rawTask = freeTasks.pop();\n    } else {\n        rawTask = new RawTask();\n    }\n    rawTask.task = task;\n    rawAsap(rawTask);\n}\n\n// We wrap tasks with recyclable task objects.  A task object implements\n// `call`, just like a function.\nfunction RawTask() {\n    this.task = null;\n}\n\n// The sole purpose of wrapping the task is to catch the exception and recycle\n// the task object after its single use.\nRawTask.prototype.call = function () {\n    try {\n        this.task.call();\n    } catch (error) {\n        if (asap.onerror) {\n            // This hook exists purely for testing purposes.\n            // Its name will be periodically randomized to break any code that\n            // depends on its existence.\n            asap.onerror(error);\n        } else {\n            // In a web browser, exceptions are not fatal. However, to avoid\n            // slowing down the queue of pending tasks, we rethrow the error in a\n            // lower priority turn.\n            pendingErrors.push(error);\n            requestErrorThrow();\n        }\n    } finally {\n        this.task = null;\n        freeTasks[freeTasks.length] = this;\n    }\n};\n","\"use strict\";\n\n// Use the fastest means possible to execute a task in its own turn, with\n// priority over other events including IO, animation, reflow, and redraw\n// events in browsers.\n//\n// An exception thrown by a task will permanently interrupt the processing of\n// subsequent tasks. The higher level `asap` function ensures that if an\n// exception is thrown by a task, that the task queue will continue flushing as\n// soon as possible, but if you use `rawAsap` directly, you are responsible to\n// either ensure that no exceptions are thrown from your task, or to manually\n// call `rawAsap.requestFlush` if an exception is thrown.\nmodule.exports = rawAsap;\nfunction rawAsap(task) {\n    if (!queue.length) {\n        requestFlush();\n        flushing = true;\n    }\n    // Equivalent to push, but avoids a function call.\n    queue[queue.length] = task;\n}\n\nvar queue = [];\n// Once a flush has been requested, no further calls to `requestFlush` are\n// necessary until the next `flush` completes.\nvar flushing = false;\n// `requestFlush` is an implementation-specific method that attempts to kick\n// off a `flush` event as quickly as possible. `flush` will attempt to exhaust\n// the event queue before yielding to the browser's own event loop.\nvar requestFlush;\n// The position of the next task to execute in the task queue. This is\n// preserved between calls to `flush` so that it can be resumed if\n// a task throws an exception.\nvar index = 0;\n// If a task schedules additional tasks recursively, the task queue can grow\n// unbounded. To prevent memory exhaustion, the task queue will periodically\n// truncate already-completed tasks.\nvar capacity = 1024;\n\n// The flush function processes all tasks that have been scheduled with\n// `rawAsap` unless and until one of those tasks throws an exception.\n// If a task throws an exception, `flush` ensures that its state will remain\n// consistent and will resume where it left off when called again.\n// However, `flush` does not make any arrangements to be called again if an\n// exception is thrown.\nfunction flush() {\n    while (index < queue.length) {\n        var currentIndex = index;\n        // Advance the index before calling the task. This ensures that we will\n        // begin flushing on the next task the task throws an error.\n        index = index + 1;\n        queue[currentIndex].call();\n        // Prevent leaking memory for long chains of recursive calls to `asap`.\n        // If we call `asap` within tasks scheduled by `asap`, the queue will\n        // grow, but to avoid an O(n) walk for every task we execute, we don't\n        // shift tasks off the queue after they have been executed.\n        // Instead, we periodically shift 1024 tasks off the queue.\n        if (index > capacity) {\n            // Manually shift all values starting at the index back to the\n            // beginning of the queue.\n            for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) {\n                queue[scan] = queue[scan + index];\n            }\n            queue.length -= index;\n            index = 0;\n        }\n    }\n    queue.length = 0;\n    index = 0;\n    flushing = false;\n}\n\n// `requestFlush` is implemented using a strategy based on data collected from\n// every available SauceLabs Selenium web driver worker at time of writing.\n// https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593\n\n// Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that\n// have WebKitMutationObserver but not un-prefixed MutationObserver.\n// Must use `global` or `self` instead of `window` to work in both frames and web\n// workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.\n\n/* globals self */\nvar scope = typeof global !== \"undefined\" ? global : self;\nvar BrowserMutationObserver = scope.MutationObserver || scope.WebKitMutationObserver;\n\n// MutationObservers are desirable because they have high priority and work\n// reliably everywhere they are implemented.\n// They are implemented in all modern browsers.\n//\n// - Android 4-4.3\n// - Chrome 26-34\n// - Firefox 14-29\n// - Internet Explorer 11\n// - iPad Safari 6-7.1\n// - iPhone Safari 7-7.1\n// - Safari 6-7\nif (typeof BrowserMutationObserver === \"function\") {\n    requestFlush = makeRequestCallFromMutationObserver(flush);\n\n// MessageChannels are desirable because they give direct access to the HTML\n// task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera\n// 11-12, and in web workers in many engines.\n// Although message channels yield to any queued rendering and IO tasks, they\n// would be better than imposing the 4ms delay of timers.\n// However, they do not work reliably in Internet Explorer or Safari.\n\n// Internet Explorer 10 is the only browser that has setImmediate but does\n// not have MutationObservers.\n// Although setImmediate yields to the browser's renderer, it would be\n// preferrable to falling back to setTimeout since it does not have\n// the minimum 4ms penalty.\n// Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and\n// Desktop to a lesser extent) that renders both setImmediate and\n// MessageChannel useless for the purposes of ASAP.\n// https://github.com/kriskowal/q/issues/396\n\n// Timers are implemented universally.\n// We fall back to timers in workers in most engines, and in foreground\n// contexts in the following browsers.\n// However, note that even this simple case requires nuances to operate in a\n// broad spectrum of browsers.\n//\n// - Firefox 3-13\n// - Internet Explorer 6-9\n// - iPad Safari 4.3\n// - Lynx 2.8.7\n} else {\n    requestFlush = makeRequestCallFromTimer(flush);\n}\n\n// `requestFlush` requests that the high priority event queue be flushed as\n// soon as possible.\n// This is useful to prevent an error thrown in a task from stalling the event\n// queue if the exception handled by Node.js’s\n// `process.on(\"uncaughtException\")` or by a domain.\nrawAsap.requestFlush = requestFlush;\n\n// To request a high priority event, we induce a mutation observer by toggling\n// the text of a text node between \"1\" and \"-1\".\nfunction makeRequestCallFromMutationObserver(callback) {\n    var toggle = 1;\n    var observer = new BrowserMutationObserver(callback);\n    var node = document.createTextNode(\"\");\n    observer.observe(node, {characterData: true});\n    return function requestCall() {\n        toggle = -toggle;\n        node.data = toggle;\n    };\n}\n\n// The message channel technique was discovered by Malte Ubl and was the\n// original foundation for this library.\n// http://www.nonblocking.io/2011/06/windownexttick.html\n\n// Safari 6.0.5 (at least) intermittently fails to create message ports on a\n// page's first load. Thankfully, this version of Safari supports\n// MutationObservers, so we don't need to fall back in that case.\n\n// function makeRequestCallFromMessageChannel(callback) {\n//     var channel = new MessageChannel();\n//     channel.port1.onmessage = callback;\n//     return function requestCall() {\n//         channel.port2.postMessage(0);\n//     };\n// }\n\n// For reasons explained above, we are also unable to use `setImmediate`\n// under any circumstances.\n// Even if we were, there is another bug in Internet Explorer 10.\n// It is not sufficient to assign `setImmediate` to `requestFlush` because\n// `setImmediate` must be called *by name* and therefore must be wrapped in a\n// closure.\n// Never forget.\n\n// function makeRequestCallFromSetImmediate(callback) {\n//     return function requestCall() {\n//         setImmediate(callback);\n//     };\n// }\n\n// Safari 6.0 has a problem where timers will get lost while the user is\n// scrolling. This problem does not impact ASAP because Safari 6.0 supports\n// mutation observers, so that implementation is used instead.\n// However, if we ever elect to use timers in Safari, the prevalent work-around\n// is to add a scroll event listener that calls for a flush.\n\n// `setTimeout` does not call the passed callback if the delay is less than\n// approximately 7 in web workers in Firefox 8 through 18, and sometimes not\n// even then.\n\nfunction makeRequestCallFromTimer(callback) {\n    return function requestCall() {\n        // We dispatch a timeout with a specified delay of 0 for engines that\n        // can reliably accommodate that request. This will usually be snapped\n        // to a 4 milisecond delay, but once we're flushing, there's no delay\n        // between events.\n        var timeoutHandle = setTimeout(handleTimer, 0);\n        // However, since this timer gets frequently dropped in Firefox\n        // workers, we enlist an interval handle that will try to fire\n        // an event 20 times per second until it succeeds.\n        var intervalHandle = setInterval(handleTimer, 50);\n\n        function handleTimer() {\n            // Whichever timer succeeds will cancel both timers and\n            // execute the callback.\n            clearTimeout(timeoutHandle);\n            clearInterval(intervalHandle);\n            callback();\n        }\n    };\n}\n\n// This is for `asap.js` only.\n// Its name will be periodically randomized to break any code that depends on\n// its existence.\nrawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;\n\n// ASAP was originally a nextTick shim included in Q. This was factored out\n// into this ASAP package. It was later adapted to RSVP which made further\n// amendments. These decisions, particularly to marginalize MessageChannel and\n// to capture the MutationObserver implementation in a closure, were integrated\n// back into ASAP proper.\n// https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js\n","'use strict';\n\nvar _ = require('lodash');\nvar dialog = require('../../dialog');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar util = require('../../util');\n\nexports.initialize = initialize;\n\nvar options;\nvar dataBuffer;\n\nvar $container;\nvar StepsConfiguration;\n\nfunction initialize($containerParameter, optionsParameter) {\n\tdataBuffer = {};\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\t\n\t$container = $containerParameter;\n\n\tif (options && options.Bopis && options.Bopis.Enabled) {\n\t\tif (options.Bopis.SelectedLocations && options.Bopis.StepConfiguration) {\n\t\t\tStepsConfiguration = options.Bopis.StepConfiguration;\n\t\t\t\n\t\t\tif (!options.Bopis.IsLocationSearchFiltered && window.location.search.indexOf('prefn2') < 0) {\n\t\t\t\t$container.addClass('open');\n\t\t\t\t$('body').addClass('scroll-lock');\n\t\t\t}\n\t\t\t\n\t\t\tbuildStepPlaceholders(0);\n\t\t\tif (StepsConfiguration[0].Type == 'Category') {\n\t\t\t\tbuildStepWithCategories(0);\n\t\t\t} else if (StepsConfiguration[0].Type == 'Refinement') {\n\t\t\t\tbuildStepWithSizes(0);\n\t\t\t}\n\n\t\t\t$(document).off('click.SelectNewFilters').on('click.SelectNewFilters', '.callout-selected-location .select-new-filters', function(event) {\n\t\t\t\t$container.addClass('open');\n\t\t\t\t$('body').addClass('scroll-lock');\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.SeeMoreSizes').on('click.SeeMoreSizes', '[step] a.see-more-sizes', function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t$container.find('[step][refinement=\"size\"] .refinementValues').toggleClass('hidden');\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.SearchCategory').on('click.SearchCategory', '[step] a.selectable:not(.placeholder)', function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar step = parseInt($this.closest('[step]').attr('step'), 10);\n\t\t\t\tvar stepConfiguration = StepsConfiguration[step + 1];\n\t\t\t\tvar categoryId;\n\t\t\t\tif ($this.attr('category-id')) {\n\t\t\t\t\tcategoryId = $this.attr('category-id');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$container.find('[step=\"' + step + '\"] a').removeClass('selected');\n\t\t\t\tif ((step + 2) <= StepsConfiguration.length) {\n\t\t\t\t\tfor (var stepIndex = step + 2; stepIndex < StepsConfiguration.length; stepIndex++) {\n\t\t\t\t\t\tbuildStepPlaceholder(stepIndex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$this.addClass('selected');\n\t\t\t\t\n\t\t\t\tvar selectedCategory = $container.find('.steps a[category-id].selected').last().attr('category-id');\n\t\t\t\tvar selectedSize = $container.find('.steps a[refinement-value].selected').last().attr('refinement-value');\n\t\t\t\tvar selectedLength = $container.find('.steps a[refinement-length].selected').last().attr('refinement-length');\n\t\t\t\tvar selectedWidth = $container.find('.steps a[refinement-width].selected').last().attr('refinement-width');\n\t\t\t\t\n\t\t\t\tif (categoryId) {\n\t\t\t\t\tif (stepConfiguration.Type == 'Category') {\n\t\t\t\t\t\tbuildStepWithCategories(step + 1, categoryId);\n\t\t\t\t\t} else if (stepConfiguration.Type == 'Refinement') {\n\t\t\t\t\t\tbuildStepWithSizes(step + 1, categoryId);\n\t\t\t\t\t}\n\t\t\t\t} else if (selectedLength && selectedWidth) {\n\t\t\t\t\tupdateProductCountForCategoryAndSize(step + 1, selectedCategory, selectedLength + ' ' + selectedWidth);\n\t\t\t\t} else if (selectedLength && dataBuffer['WidthsByLength'] && dataBuffer['WidthsByLength'][selectedLength]) {\n\t\t\t\t\tvar selectedSizes = '';\n\t\t\t\t\tfor (var widthForLengthKey in dataBuffer['WidthsByLength'][selectedLength]) {\n\t\t\t\t\t\tvar widthForLength = dataBuffer['WidthsByLength'][selectedLength][widthForLengthKey];\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (selectedSizes) {\n\t\t\t\t\t\t\tselectedSizes += '|';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tselectedSizes += selectedLength + ' ' + widthForLength;\n\t\t\t\t\t}\n\t\t\t\t\tupdateProductCountForCategoryAndSize(step + 1, selectedCategory, selectedSizes);\n\t\t\t\t} else if (selectedSize) {\n\t\t\t\t\t$container.find('[step][refinement=\"width\"]').remove();\n\t\t\t\t\tupdateProductCountForCategoryAndSize(step + 1, selectedCategory, selectedSize);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$container.find('.btn.reset').removeAttr('disabled');\n\t\t\t\tvar allStepsHaveSelectedValue = true;\n\t\t\t\t$container.find('[step]').each(function() {\n\t\t\t\t\tif ($(this).find('.selectable.selected').length < 1) {\n\t\t\t\t\t\tallStepsHaveSelectedValue = false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (allStepsHaveSelectedValue) {\n\t\t\t\t\t$container.find('.btn.apply').removeAttr('disabled');\n\t\t\t\t} else {\n\t\t\t\t\t$container.find('.btn.apply').attr('disabled', 'disabled');\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.SearchLength').on('click.SearchLength', '[step] a.selectable[refinement-length]:not(.placeholder)', function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar step = parseInt($this.closest('[step]').attr('step'), 10);\n\t\t\t\tvar stepConfiguration = StepsConfiguration[step + 1];\n\t\t\t\tvar selectedCategory = $container.find('.steps a[category-id].selected').last().attr('category-id');\n\t\t\t\tvar selectedLength = $container.find('.steps a[refinement-length].selected').last().attr('refinement-length');\n\t\t\t\t\n\t\t\t\tbuildStepWithWidths(step + 1, selectedCategory, selectedLength);\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.Apply').on('click.Apply', '.btn.apply', function(event) {\n\t\t\t\t$container.removeClass('open');\n\t\t\t\t\n\t\t\t\t$('body').loading({\n\t\t\t\t\tContent: '<h6>Hold Your Horses!</h6><p>Your selections are loading...</p>',\n\t\t\t\t\tCssClass: 'bootbarnexpress',\n\t\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tvar $selectedCategory = $container.find('.steps a[category-id].selected').last();\n\t\t\t\tvar selectedCategory = $selectedCategory.attr('category-id');\n\t\t\t\tvar selectedCategoryUrl = $selectedCategory.attr('category-url');\n\t\t\t\tvar selectedSize = $container.find('.steps a[refinement-value].selected').last().attr('refinement-value');\n\t\t\t\tvar selectedLength = $container.find('.steps a[refinement-length].selected').last().attr('refinement-length');\n\t\t\t\tvar selectedWidth = $container.find('.steps a[refinement-width].selected').last().attr('refinement-width');\n\t\t\t\tvar selectedLocation = options.Bopis.SelectedLocations[0].StoreId;\n\t\t\t\t\n\t\t\t\tif (selectedLocation && selectedCategoryUrl) {\n\t\t\t\t\tvar url = window.location.origin + selectedCategoryUrl;\n\t\t\t\t\turl = util.appendParamToURL(url, 'prefn1', 'availableStores');\n\t\t\t\t\turl = util.appendParamToURL(url, 'prefv1', selectedLocation);\n\t\t\t\t\n\t\t\t\t\tif (selectedLength && selectedWidth) {\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefn2', 'size');\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefv2', selectedLength + ' ' + selectedWidth);\n\t\t\t\t\t} else if (selectedLength && dataBuffer['WidthsByLength'] && dataBuffer['WidthsByLength'][selectedLength]) {\n\t\t\t\t\t\tvar selectedSizes = '';\n\t\t\t\t\t\tfor (var widthForLengthKey in dataBuffer['WidthsByLength'][selectedLength]) {\n\t\t\t\t\t\t\tvar widthForLength = dataBuffer['WidthsByLength'][selectedLength][widthForLengthKey];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (selectedSizes) {\n\t\t\t\t\t\t\t\tselectedSizes += '|';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tselectedSizes += selectedLength + ' ' + widthForLength;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefn2', 'size');\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefv2', selectedSizes);\n\t\t\t\t\t} else if (selectedSize) {\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefn2', 'size');\n\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefv2', selectedSize);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.Reset').on('click.Reset', '.btn.reset', function(event) {\n\t\t\t\t$container.find('.steps').html('');\n\t\t\t\tbuildStepPlaceholders(0);\n\t\t\t\tbuildStepWithCategories(0);\n\t\t\t\t$container.find('.btn.apply, .btn.reset').attr('disabled', 'disabled');\n\t\t\t});\n\t\t\t\n\t\t\t$container.off('click.Close').on('click.Close', '.close', function(event) {\n\t\t\t\t$container.removeClass('open');\n\t\t\t\t$('body').removeClass('scroll-lock');\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction buildStepWithCategories(step, categoryIdParameter) {\n\tvar categoryId = categoryIdParameter || 'root';\n\t$container.find('.product-count-container').loading({\n\t\tIsImageShown: false\n\t});\n\tvar $step = $container.find('[step=\"' + step + '\"]');\n\tif ($step.length < 1) {\n\t\t$container.find('.steps').append('<div step=\"' + step + '\"></div>');\n\t\t$step = $container.find('[step=\"' + step + '\"]');\n\t}\n\t$step.loading({\n\t\tIsImageShown: false,\n        Content: '<p>Your selections are loading...</p>',\n\t\tCssClass: 'bootbarnexpress',\n\t\tBackgroundColor: 'transparent'\n\t});\n\tif ($step.find('h5').length > 0) {\n\t\t$step.find('.loading-indicator-container').css('margin-top', $step.find('h5').innerHeight());\n\t}\n\n\t$.ajax({\n        method: 'GET',\n        url: Urls.BootBarnExpress.GetSubCategoriesForCategoryId,\n        contentType: 'application/json',\n        data: {\n\t        cgid: categoryId,\n            prefn1: 'availableStores',\n            prefv1: options.Bopis.SelectedLocations[0].StoreId\n\t    },\n        dataType: 'json',\n        success: function(data) {\n            $container.attr('state', 'result');\n            \n            if (data && data.ProductCount) {\n            \t$container.find('.product-count').html(data.ProductCount.toLocaleString('en'));\n            }\n            \n            if (data && data.Categories) {\n            \tvar stepHtml;\n            \tif (StepsConfiguration[step] && StepsConfiguration[step].Header) {\n            \t\tstepHtml = '<h5>' + StepsConfiguration[step].Header + '</h5>';\n            \t} else {\n            \t\tstepHtml = '';\n            \t}\n            \tfor (var categoryKey in data.Categories) {\n            \t\tvar category = data.Categories[categoryKey];\t\t\n            \t\tstepHtml += '<a category-id=\"' + category.Id + '\" category-url=\"' + category.Url + '\" class=\"selectable\">' + category.Name + '</a>';\n            \t}\n            \t\n        \t\t$step.html(stepHtml).show().loading('destroy');\n        \t\tscrollToStep($step);\n            \t\n                if (options.successCallback) {\n                \toptions.successCallback(inquiryResult);\n                }\n            } else {\n                $container.attr('result-count', '0');\n                $step.show().loading('destroy');\n                \n                if (options.errorCallback) {\n                \toptions.errorCallback();\n                }\n            }\n            \n            $container.find('.product-count-container').loading('destroy');\n        },\n        error: function() {\n            if (options.errorCallback) {\n            \toptions.errorCallback();\n            }\n            \n            $step.show().loading('destroy');\n            $container.find('.product-count-container').loading('destroy');\n        }\n    });\t\n}\n\nfunction buildStepWithSizes(step, categoryIdParameter) {\n\tvar categoryId = categoryIdParameter || 'root';\n\t$container.find('.product-count-container').loading({\n\t\tIsImageShown: false\n\t});\n\tvar $step = $container.find('[step=\"' + step + '\"]');\n\tif ($step.length < 1) {\n\t\t$container.find('.steps').append('<div step=\"' + step + '\"></div>');\n\t\t$step = $container.find('[step=\"' + step + '\"]');\n\t}\n\t$step.loading({\n\t\tIsImageShown: false,\n        Content: '<p>Your selections are loading...</p>',\n\t\tCssClass: 'bootbarnexpress',\n\t\tBackgroundColor: 'transparent'\n\t});\n\tif ($step.find('h5').length > 0) {\n\t\t$step.find('.loading-indicator-container').css('margin-top', $step.find('h5').innerHeight());\n\t}\n\tdataBuffer['WidthsByLength'] = {};\n\n\t$.ajax({\n\t\tmethod: 'GET',\n\t\turl: Urls.BootBarnExpress.GetSortedRefinementValuesForRefinementId,\n\t\tcontentType: 'application/json',\n\t\tdata: {\n            cgid: categoryId,\n            refinementId: StepsConfiguration[step - 1].Refinement || 'size',\n            prefn1: 'availableStores',\n            prefv1: options.Bopis.SelectedLocations[0].StoreId\n\t\t},\n\t\tdataType: 'json',\n\t\tsuccess: function(data) {\n            $container.attr('state', 'result');\n            \n            if (data && data.ProductCount) {\n            \t$container.find('.product-count').html(data.ProductCount.toLocaleString('en'));\n            }\n            \n            if (data && data.RefinementValues) {\n            \tvar popularSizesHtml = '';\n\t\t\t\tvar hideRefinementValues = '';\n\t\t\t\tvar hasWidths = false;\n            \tif (data.PopularSizes && data.PopularSizes.length > 0) {\n            \t\tpopularSizesHtml = '<h6>Most Popular</h6>';\n            \t\t\n            \t\tvar parsedPopularSizeRefinementValues = parseSizeRefinementValuesIntoLengthAndWidth(data.PopularSizes);\n            \t\tif (parsedPopularSizeRefinementValues && parsedPopularSizeRefinementValues.Lengths && parsedPopularSizeRefinementValues.Lengths.length > 0) {\n            \t\t\tfor (var refinementKey in parsedPopularSizeRefinementValues.Lengths) {\n\t\t            \t\tvar refinementValue = parsedPopularSizeRefinementValues.Lengths[refinementKey];\n\t\t\t\t\t\t\tvar refinementAttribute;\n\t\t            \t\tif (parsedPopularSizeRefinementValues.WidthsByLength[refinementValue]) {\n\t\t\t\t\t\t\t\trefinementAttribute = 'refinement-length';\n\t\t\t\t\t\t\t\thasWidths = true;\n\t\t            \t\t} else {\n\t\t\t\t\t\t\t\trefinementAttribute = 'refinement-value';\n\t\t\t\t\t\t\t}\n\t\t            \t\t\n\t\t            \t\tpopularSizesHtml += '<a ' + refinementAttribute + '=\"' + refinementValue + '\" class=\"selectable\">' + refinementValue + '</a>';\n\t\t            \t}\n            \t\t} else {\n\t\t            \tfor (var refinementKey in data.PopularSizes) {\n\t\t            \t\tvar refinementValue = data.PopularSizes[refinementKey];\n\t\t            \t\tpopularSizesHtml += '<a refinement-value=\"' + refinementValue.value + '\" class=\"selectable\">' + refinementValue.displayValue + '</a>';\n\t\t            \t}\n            \t\t}\n\t            \tpopularSizesHtml = '<div class=\"popularSizes\">' + popularSizesHtml + '</div>' + '<a class=\"see-more-sizes\">See More Sizes</a>';\n\t            \thideRefinementValues = ' hidden';\n            \t}\n            \tvar sizesHeaderHtml;\n            \tvar refinementValuesHtml = '';\n            \t\n            \tvar parsedSizeRefinementValues = parseSizeRefinementValuesIntoLengthAndWidth(data.RefinementValues);\n            \tif (parsedSizeRefinementValues && parsedSizeRefinementValues.Lengths && parsedSizeRefinementValues.Lengths.length > 0) {\n            \t\tsizesHeaderHtml = '<h5>Filter By Size</h5>';\n            \t\t\n            \t\tif (parsedSizeRefinementValues.WidthsByLength && parsedSizeRefinementValues.WidthsByLength.length > 0) {\n            \t\t\tdataBuffer['WidthsByLength'] = parsedSizeRefinementValues.WidthsByLength;\n            \t\t}\n            \t\t\n            \t\tfor (var refinementKey in parsedSizeRefinementValues.Lengths) {\n            \t\t\tvar refinementValue = parsedSizeRefinementValues.Lengths[refinementKey];\n            \t\t\tvar refinementAttribute = 'refinement-length';\n            \t\t\tif (parsedSizeRefinementValues.WidthsByLength[refinementValue] && parsedSizeRefinementValues.WidthsByLength[refinementValue].length == 1) {\n\t            \t\t\trefinementValue += ' ' + parsedSizeRefinementValues.WidthsByLength[refinementValue][0];\n\t\t\t\t\t\t\trefinementAttribute = 'refinement-value';\n\t            \t\t} else if (parsedSizeRefinementValues.WidthsByLength[refinementValue]) {\n\t\t\t\t\t\t\trefinementAttribute = 'refinement-length';\n\t\t\t\t\t\t\thasWidths = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trefinementAttribute = 'refinement-value';\n\t\t\t\t\t\t}\n            \t\t\t\n\t            \t\trefinementValuesHtml += '<a ' + refinementAttribute + '=\"' + refinementValue + '\" class=\"selectable\">' + refinementValue + '</a>';\n\t            \t}\n            \t} else {\n            \t\tsizesHeaderHtml = '<h5>Filter By Size</h5>';\n            \t\t\n\t            \tfor (var refinementKey in data.RefinementValues) {\n\t            \t\tvar refinementValue = data.RefinementValues[refinementKey];\n\t            \t\trefinementValuesHtml += '<a refinement-value=\"' + refinementValue.value + '\" class=\"selectable\">' + refinementValue.displayValue + '</a>';\n\t            \t}\n            \t}\n            \t\n            \tvar stepHtml = sizesHeaderHtml + popularSizesHtml + '<div class=\"refinementValues' + hideRefinementValues + '\">' + refinementValuesHtml + '</div>';\n\n\t\t\t\tif (hasWidths) {\n\t\t\t\t\t$container.find('[step][refinement=\"width\"]').show();\n\t\t\t\t} else {\n\t\t\t\t\t$container.find('[step][refinement=\"width\"]').hide();\n\t\t\t\t}\n\n        \t\t$step.html(stepHtml).show().loading('destroy');\n        \t\t$step.attr('refinement', 'size');\n        \t\tscrollToStep($step);\n            \t\n                if (options.successCallback) {\n                \toptions.successCallback(inquiryResult);\n                }\n            } else {\n                $container.attr('result-count', '0');\n                \n                if (options.errorCallback) {\n                \toptions.errorCallback();\n                }\n            }\n            \n            $container.find('.product-count-container').loading('destroy');\n        },\n        error: function() {\n            if (options.errorCallback) {\n            \toptions.errorCallback();\n            }\n            \n            $container.find('.product-count-container').loading('destroy');\n        }\n    });\n}\n\nfunction buildStepWithWidths(step, categoryIdParameter, lengthParameter) {\n\tvar categoryId = categoryIdParameter || 'root';\n\t$container.find('.product-count-container').loading({\n\t\tIsImageShown: false\n\t});\n\tvar $step = $container.find('[step=\"' + step + '\"]');\n\tif ($step.length < 1) {\n\t\t$container.find('.steps').append('<div step=\"' + step + '\"></div>');\n\t\t$step = $container.find('[step=\"' + step + '\"]');\n\t}\n\t\n\tvar refinementValuesHtml = '';\n\tvar widthType;\n\tfor (var refinementValueKey in dataBuffer['WidthsByLength'][lengthParameter]) {\n\t\tvar refinementValue = dataBuffer['WidthsByLength'][lengthParameter][refinementValueKey];\n\t\tvar refinementValueDisplay = refinementValue == 'D' ? refinementValue + '&nbsp;<span class=\"width-note\">(REG)</span>' : refinementValue;\n\t\trefinementValuesHtml += '<a refinement-width=\"' + refinementValue + '\" class=\"selectable\">' + refinementValueDisplay + '</a>';\n\t\t\n\t\tif (!widthType) {\n\t\t\tvar widthParsedAsInteger = parseInt(refinementValue, 10);\n\t\t\t\n\t\t\tif (widthParsedAsInteger == refinementValue) {\n\t\t\t\twidthType = 'pants';\n\t\t\t}\n\t\t}\n\t}\n\n\tvar widthsHeaderHtml;\n\tvar widthTypeLabel;\n\tif (widthType == 'pants') {\n\t\twidthTypeLabel = 'Inseam';\n\t} else {\n\t\twidthTypeLabel = 'Width';\n\t}\n\twidthsHeaderHtml = '<h5>Filter By ' + widthTypeLabel + '</h5>';\n\tvar stepHtml = widthsHeaderHtml + '<div class=\"refinementValues\">' + refinementValuesHtml + '</div>';\n\t\n\t$step.html(stepHtml).show();\n\t$step.attr('refinement', 'width');\n\tscrollToStep($step);\n}\n\nfunction buildStepPlaceholders(step) {\n\tfor (var stepIndex = step; stepIndex < options.Bopis.StepConfiguration.length; stepIndex++) {\n\t\tvar $step = $container.find('[step=\"' + stepIndex + '\"]');\n\t\tif ($step.length < 1) {\n\t\t\t$container.find('.steps').append('<div step=\"' + stepIndex + '\"></div>');\n\t\t\t$step = $container.find('[step=\"' + stepIndex + '\"]');\n\t\t}\n\t\tbuildStepPlaceholder(stepIndex, $step);\n\t}\n}\n\nfunction buildStepPlaceholder(step, $step) {\n\tvar stepConfiguration = options.Bopis.StepConfiguration[step];\n\n\tif (!$step) {\n\t\tvar $step = $container.find('[step=\"' + step + '\"]');\n\t\tif ($step.length < 1) {\n\t\t\t$container.find('.steps').append('<div step=\"' + step + '\"></div>');\n\t\t\t$step = $container.find('[step=\"' + step + '\"]');\n\t\t}\n\t}\n\n\tif (stepConfiguration.Refinement) {\n\t\t$step.attr('refinement', stepConfiguration.Refinement);\n\t}\n\n\tif (stepConfiguration && stepConfiguration.Placeholder) {\n\t\tvar stepHeaderHtml = '';\n\t\tif (stepConfiguration.Placeholder.Header) {\n\t\t\tstepHeaderHtml = '<h5 class=\"placeholder\">' + stepConfiguration.Placeholder.Header + '</h5>';\n\t\t} else if (stepConfiguration.Header) {\n\t\t\tstepHeaderHtml = '<h5 class=\"placeholder\">' + stepConfiguration.Header + '</h5>';\n\t\t}\n\n\t\tvar refinementValuesHtml = '';\n\t\tif (stepConfiguration.Placeholder.Values) {\n\t\t\tfor (var refinementKey in stepConfiguration.Placeholder.Values) {\n\t\t\t\trefinementValuesHtml += '<a refinement-value=\"' + stepConfiguration.Placeholder.Values[refinementKey] + '\" class=\"placeholder selectable\">' + stepConfiguration.Placeholder.Values[refinementKey] + '</a>';\n\t\t\t}\n\t\t} else if (stepConfiguration.Placeholder.Text) {\n\t\t\trefinementValuesHtml += '<p class=\"placeholder\">' + stepConfiguration.Placeholder.Text + '</p>';\n\t\t}\n\t\t\n\t\tif (stepConfiguration.Refinement == 'size') {\n\t\t\trefinementValuesHtml = '<div class=\"popularSizes\"><h6 class=\"placeholder\">Most Popular</h6>' + refinementValuesHtml + '</div><a class=\"see-more-sizes placeholder\">See More Sizes</a>';\n\t\t} else {\n\t\t\trefinementValuesHtml = '<div class=\"refinementValues\">' + refinementValuesHtml + '</div>';\n\t\t}\n\n\t\t$step.html(stepHeaderHtml + refinementValuesHtml);\n\t} else {\n\t\t$step.html('').hide();\n\t}\n}\n\nfunction updateProductCountForCategoryAndSize(step, selectedCategory, selectedSize) {\n\t$container.find('.product-count-container').loading({\n\t\tIsImageShown: false\n\t});\n\t\n\t$.ajax({\n        method: 'GET',\n        url: Urls.BootBarnExpress.GetSortedRefinementValuesForRefinementId,\n        contentType: 'application/json',\n        data: {\n            cgid: selectedCategory,\n            prefn1: 'availableStores',\n            prefv1: options.Bopis.SelectedLocations[0].StoreId,\n            prefn2: 'size',\n            prefv2: selectedSize\n        },\n        dataType: 'json',\n        success: function(data) {\n            if (data && data.ProductCount) {\n            \t$container.find('.product-count').html(data.ProductCount.toLocaleString('en'));\n            }\n            \n\t\t\tif (options.successCallback) {\n            \toptions.successCallback(inquiryResult);\n            }\n            \n            $container.find('.product-count-container').loading('destroy');\n        },\n        error: function() {\n        \tif (options.errorCallback) {\n            \toptions.errorCallback();\n            }\n        \t\n        \t$container.find('.product-count-container').loading('destroy');\n        }\n    });\n}\n\nfunction parseSizeRefinementValuesIntoLengthAndWidth(refinementValues) {\n\tvar sizeRefinementValuesLengths = [];\n\tvar sizeRefinementValuesWidths = [];\n\tvar sizeRefinementValuesWidthsByLength = [];\n\t\n\tif (refinementValues) {\n\t\tfor (var refinementKey in refinementValues) {\n\t\t\tvar refinementValue = refinementValues[refinementKey];\n\t\t\t\n\t\t\tvar splitRefinementValue = refinementValue.value.split(' ');\n\t\t\tif (splitRefinementValue && 'length' in splitRefinementValue && splitRefinementValue.length > 1) {\n\t\t\t\tvar sizeRefinementValueWidth = splitRefinementValue.pop();\n\t\t\t\tvar sizeRefinementValueLength = splitRefinementValue.join(' ');\n\t\t\t\t\n\t\t\t\tif (!sizeRefinementValuesWidthsByLength[sizeRefinementValueLength]) {\n\t\t\t\t\tsizeRefinementValuesWidthsByLength[sizeRefinementValueLength] = [];\n\t\t\t\t}\n\t\t\t\tsizeRefinementValuesWidthsByLength[sizeRefinementValueLength].push(sizeRefinementValueWidth);\n\t\t\t\t\n\t\t\t\tif (sizeRefinementValuesLengths.indexOf(sizeRefinementValueLength) < 0) {\n\t\t\t\t\tsizeRefinementValuesLengths.push(sizeRefinementValueLength);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (sizeRefinementValuesWidths.indexOf(sizeRefinementValueWidth) < 0) {\n\t\t\t\t\tsizeRefinementValuesWidths.push(sizeRefinementValueWidth);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsizeRefinementValuesLengths.push(refinementValue.value);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tvar payload = {\n\t\tLengths: sizeRefinementValuesLengths,\n\t\tWidths: sizeRefinementValuesWidths,\n\t\tWidthsByLength: sizeRefinementValuesWidthsByLength\n\t}\n\t\n\treturn payload;\n}\n\nfunction scrollToStep($step) {\n\t$container.find('.modal-body').animate({\n\t\tscrollTop: $step.position().top\n\t});\n}","'use strict';\n\nvar _ = require('lodash');\nvar AddressVerificationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/AddressVerification/AddressVerificationHelper');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nvar options;\nvar dataBuffer;\nvar templates;\n\nfunction initialize(optionsParameter, addressData) {\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\tdataBuffer = $.extend({}, addressData);\n\n\tif (addressData && addressData.$field && addressData.$form) {\n\t\ttemplates = {};\n\t\ttemplates.container = _.template($('#template-address-autocomplete-container').html(), TemplateConstants.Lodash.Settings);\n\t\ttemplates.address = _.template($('#template-address-autocomplete-item').html(), TemplateConstants.Lodash.Settings);\n\n\t\tvar addressSuggestionsHtml = '';\n\t\tif (addressData && addressData.InquiryResult && addressData.InquiryResult.suggestions && addressData.InquiryResult.suggestions.length > 0) {\n\t\t\tfor (var addressSuggestionKey in addressData.InquiryResult.suggestions) {\n\t\t\t\tvar addressSuggestion = addressData.InquiryResult.suggestions[addressSuggestionKey];\n\t\t\t\taddressSuggestionsHtml += templates.address({ Address: buildAddressHtmlFromAddressObject(AddressVerificationHelper.BuildAddressObjectFromAddressAutocompleteSuggestion(addressSuggestion)) });\n\t\t\t}\n\t\t}\n\n\t\tvar $fieldContainer = addressData.$field.parent();\n\t\tif ($fieldContainer.find('.address-autocomplete-dialog').length > 0) {\n\t\t\t$fieldContainer.find('.address-autocomplete-dialog').remove();\n\t\t}\n\n\t\tvar addressSuggestionsContainerHtml = templates.container({ Addresses: addressSuggestionsHtml });\n\t\t$fieldContainer.prepend(addressSuggestionsContainerHtml);\n\n\t\taddressData.$form.off('click.AddressAutocompleteSelect').on('click.AddressAutocompleteSelect', '.address-autocomplete-dialog li', function(event) {\n\t\t\tvar $this = $(this);\n\n\t\t\taddressData.$form.find('.address-autocomplete-dialog').remove();\n\t\t\t$(document).trigger('SetAddressFromAddressAutocomplete', {\n\t\t\t\t$form: addressData.$form,\n\t\t\t\t$field: addressData.$field,\n\t\t\t\tAddress: AddressVerificationHelper.BuildAddressObjectFromAddressAutocompleteSuggestion(addressData.InquiryResult.suggestions[$this.index()])\n\t\t\t});\n\t\t});\n\n\t\t$(document).off('click.AddressAutocompleteClose').on('click.AddressAutocompleteClose', function(event) {\n\t\t\tvar $target = $(event.currentTarget);\n\n\t\t\tif ($target.closest('.address-autocomplete-dialog').length == 0) {\n\t\t\t\t$('.address-autocomplete-dialog').remove();\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction buildAddressHtmlFromAddressObject(addressObject) {\n\tvar addressArray = [];\n\tif (addressObject.PrimaryLine) {\n\t\taddressArray[addressArray.length] = addressObject.PrimaryLine;\n\t}\n\tif (addressObject.City || addressObject.StateCode || addressObject.PostalCode) {\n\t\tvar addressLine = '';\n\t\tif (addressObject.City) {\n\t\t\taddressLine += addressObject.City + ', ';\n\t\t}\n\t\tif (addressObject.StateCode) {\n\t\t\taddressLine += addressObject.StateCode;\n\t\t\tif (addressObject.PostalCode) {\n\t\t\t\taddressLine += ' ';\n\t\t\t}\n\t\t}\n\t\tif (addressObject.PostalCode) {\n\t\t\taddressLine += addressObject.PostalCode;\n\t\t}\n\n\t\taddressArray[addressArray.length] = addressLine;\n\t}\n\n\treturn addressArray.join('<br/>');\n}\n\nexports.initialize = initialize;","'use strict';\n\nvar _ = require('lodash');\nvar dialog = require('../../dialog');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nvar options;\nvar dataBuffer;\nvar templates;\n\nfunction initialize(optionsParameter, addressType, addressData) {\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\tdataBuffer = $.extend({}, addressData);\n\ttemplates = {};\n\ttemplates.address = _.template($('#template-address-verification-address').html(), TemplateConstants.Lodash.Settings);\n\n\tdialog.open({\n\t\thtml: $('#dialog-address-verification').html(),\n\t\toptions: {\n\t\t\tdialogClass: 'dialog-address-verification',\n\t\t\twidth: 320,\n\t\t\tdraggable: false,\n\t\t\tresizable: false,\n\t\t\topen: function(event, ui) {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar $addresses = $this.find('.addresses');\n\t\t\t\t$addresses.html('');\n\t\t\t\t$this.closest('.ui-dialog').attr('status', dataBuffer.Status);\n\n\t\t\t\tvar addressRecommendedHtml;\n\t\t\t\tif (dataBuffer.Status == 'deliverable' && !dataBuffer.Match) {\n\t\t\t\t\taddressRecommendedHtml = templates.address({\n\t\t\t\t\t\tAddressType: addressType,\n\t\t\t\t\t\tAction: 'recommended',\n\t\t\t\t\t\tClass: 'selected',\n\t\t\t\t\t\tChecked: 'checked',\n\t\t\t\t\t\tHeader: 'Recommended Address',\n\t\t\t\t\t\tAddress: buildAddressHtmlFromAddressObject(dataBuffer.AddressVerified)\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tvar addressEnteredHtml;\n\t\t\t\taddressEnteredHtml = templates.address({\n\t\t\t\t\tAddressType: addressType,\n\t\t\t\t\tAction: 'entered',\n\t\t\t\t\tClass: !addressRecommendedHtml ? 'selected' : '',\n\t\t\t\t\tChecked: !addressRecommendedHtml ? 'checked' : '',\n\t\t\t\t\tHeader: 'Address as Entered',\n\t\t\t\t\tAddress: buildAddressHtmlFromAddressObject(dataBuffer.AddressOriginal)\n\t\t\t\t});\n\n\t\t\t\tif (addressRecommendedHtml) {\n\t\t\t\t\t$addresses.append(addressRecommendedHtml);\n\t\t\t\t}\n\t\t\t\tif (addressEnteredHtml) {\n\t\t\t\t\t$addresses.append(addressEnteredHtml);\n\t\t\t\t}\n\n\t\t\t\t$this.find('.address-type').text(addressType);\n\t\t\t\t$this.find('h3:visible').focus(); // ADA compliance - add focus to first element in modal to help screen readers\n\t\t\t\t\n\t\t\t\t$this.off('click.AddressSelect').on('click.AddressSelect', '.address-container .radio-large', function(event) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tvar $addressContainer = $(this).closest('.address-container');\n\n\t\t\t\t\t$this.find('.address-container').removeClass('selected');\n\t\t\t\t\t$addressContainer.addClass('selected');\n\t\t\t\t\t$addressContainer.find('input').prop('checked', true);\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.AddressUse').on('click.AddressUse', '.address-use', function(event) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tvar addressToUse = $(this).closest('.address-container').find('input').val();\n\t\t\t\t\tvar addressObject;\n\t\t\t\t\tif (addressToUse == 'recommended') {\n\t\t\t\t\t\taddressObject = dataBuffer.AddressVerified;\n\t\t\t\t\t} else if (addressToUse == 'entered') {\n\t\t\t\t\t\taddressObject = dataBuffer.AddressOriginal;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (addressObject) {\n\t\t\t\t\t\t$(document).trigger('SetAddressFromAddressVerification', $.extend(addressObject, { AddressType: addressType }));\n\t\t\t\t\t}\n\t\t\t\t\t$this.dialog('close');\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.AddressContinue').on('click.AddressContinue', '.address-continue', function(event) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t$(document).trigger('SetAddressFromAddressVerification', $.extend(dataBuffer.AddressOriginal, { AddressType: addressType }));\n\t\t\t\t\t$this.dialog('close');\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t$this.off('click.AddressEdit').on('click.AddressEdit', '.address-edit', function(event) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t$this.dialog('close');\n\t\t\t\t\tvar $focusElement = $('#billingAddressForm').find('input[name=\"dwfrm_billingaddress_address1\"]');\n\t\t\t\t\tif (addressType == 'shipping') {\n\t\t\t\t\t\t$focusElement = $('#shippingAddressForm').find('input[name=\"dwfrm_shippingaddress_address1\"]');\n\t\t\t\t\t}\n\t\t\t\t\t$focusElement.focus();\n\t\t\t\t});\n            },\n            close: function(event, ui) {\n\t\t\t\tvar $this = $(this);\n\t\t\t\t$this.off('click.SelectAddress');\n\t\t\t\t$this.off('click.UseEnteredAddress');\n\t\t\t\t$this.off('click.UseRecommendedAddress');\n\t\t\t\t$this.off('click.EditShippingAddress');\n            }\n\t\t}\n\t});\n}\n\nfunction buildAddressHtmlFromAddressObject(addressObject) {\n\tvar addressArray = [];\n\tif (addressObject.PrimaryLine) {\n\t\taddressArray[addressArray.length] = addressObject.PrimaryLine;\n\t}\n\tif (addressObject.SecondaryLine) {\n\t\taddressArray[addressArray.length] = addressObject.SecondaryLine;\n\t}\n\tif (addressObject.City || addressObject.StateCode || addressObject.PostalCode) {\n\t\tvar addressLine = '';\n\t\tif (addressObject.City) {\n\t\t\taddressLine += addressObject.City + ', ';\n\t\t}\n\t\tif (addressObject.StateCode) {\n\t\t\taddressLine += addressObject.StateCode;\n\t\t\tif (addressObject.PostalCode) {\n\t\t\t\taddressLine += ' ';\n\t\t\t}\n\t\t}\n\t\tif (addressObject.PostalCode) {\n\t\t\taddressLine += addressObject.PostalCode;\n\t\t}\n\n\t\taddressArray[addressArray.length] = addressLine;\n\t}\n\n\treturn addressArray.join('<br/>');\n}\n\nexports.initialize = initialize;","'use strict';\n\nvar progress = require('./progress'),\n    util = require('./util');\n\nvar currentRequests = [];\n\n/**\n * @function\n * @description Ajax request to get json response\n * @param {Boolean} async  Asynchronous or not\n * @param {String} url URI for the request\n * @param {Object} data Name/Value pair data request\n * @param {Function} callback  Callback function to be called\n */\nvar getJson = function (options) {\n    options.url = util.toAbsoluteUrl(options.url);\n    // return if no url exists or url matches a current request\n    if (!options.url || currentRequests[options.url]) {\n        return;\n    }\n\n    currentRequests[options.url] = true;\n\n    // make the server call\n    $.ajax({\n        dataType: 'json',\n        url: options.url,\n        async: (typeof options.async === 'undefined' || options.async === null) ? true : options.async,\n        data: options.data || {}\n    })\n    // success\n    .done(function (response) {\n        if (options.callback) {\n            options.callback(response);\n        }\n    })\n    // failed\n    .fail(function (xhr, textStatus) {\n        if (textStatus === 'parsererror') {\n            window.alert(Resources.BAD_RESPONSE);\n        }\n        if (options.callback) {\n            options.callback(null);\n        }\n    })\n    // executed on success or fail\n    .always(function () {\n        // remove current request from hash\n        if (currentRequests[options.url]) {\n            delete currentRequests[options.url];\n        }\n    });\n};\n/**\n * @function\n * @description ajax request to load html response in a given container\n * @param {String} url URI for the request\n * @param {Object} data Name/Value pair data request\n * @param {Function} callback  Callback function to be called\n * @param {Object} target Selector or element that will receive content\n */\nvar load = function (options) {\n    options.url = util.toAbsoluteUrl(options.url);\n    // return if no url exists or url matches a current request\n    if (!options.url || currentRequests[options.url]) {\n        return;\n    }\n\n    currentRequests[options.url] = true;\n\n    // make the server call\n    $.ajax({\n        dataType: 'html',\n        url: util.appendParamToURL(options.url, 'format', 'ajax'),\n        data: options.data,\n        xhrFields: {\n            withCredentials: true\n        }\n    })\n    .done(function (response) {\n        // success\n        if (options.target) {\n            $(options.target).empty().html(response);\n        }\n        if (options.callback) {\n            options.callback(response);\n        }\n    })\n    .fail(function (xhr, textStatus) {\n        // failed\n        if (textStatus === 'parsererror') {\n            window.alert(Resources.BAD_RESPONSE);\n        }\n        options.callback(null, textStatus);\n    })\n    .always(function () {\n        progress.hide();\n        // remove current request from hash\n        if (currentRequests[options.url]) {\n            delete currentRequests[options.url];\n        }\n    });\n};\n\nexports.getJson = getJson;\nexports.load = load;\n","'use strict';\n\n/**\n * @function\n * @description Initializes the alert widget\n */\nexports.init = function(options) {\n    var type = options.type ? options.type : 'alert-primary';\n    var timer = options.timer ? options.timer : 5000;\n    var alertElement = '<div class=\"alert ' + type + '\"><div class=\"alert-content\">' + options.content + '</div></div>';\n\n    $('body').append(alertElement).fadeIn('slow');\n    var alertTimer = setTimeout(function() {\n        $('.alert').fadeOut('slow').remove();\n    }, timer);\n\n    $('body').on('click', '.alert', function() {\n        $(this).fadeOut('slow').remove();\n    });\n};\n","/**\n *    (c) 2009-2014 Demandware Inc.\n *    Subject to standard usage terms and conditions\n *    For all details and documentation:\n *    https://bitbucket.com/demandware/sitegenesis\n */\n\n'use strict';\n\nvar countries = require('./countries'),\n    dialog = require('./dialog'),\n    minicart = require('./minicart'),\n    page = require('./page'),\n    rating = require('./rating'),\n    searchplaceholder = require('./searchplaceholder'),\n    //tooltip = require('./tooltip'),\n    util = require('./util'),\n    validator = require('./validator'),\n    tls = require('./tls'),\n  \tTPromise = require('promise'),\n  \tajax = require('./ajax'),\n  \trotate3d = require('./productRotate3d.js'),\n    count_down = require('./countdown'),\n    lazyloadPageElements = require('./lazyloadPageElements'),\n    cookieNotification = require('./components/CookieNotification'),\n    navigation = require('./components/NavigationController'),\n    emailForm = require('./components/EmailForm'),\n\tslickHelpers = require('./slickSliderHelpers'),\n\tquantityStepper = require('./quantityStepper'),\n\twishlist = require('./wishlist'),\n\tloginDialog = require('./loginDialog'),\n\tlogin = require('./login'),\n\tregister = require('./register'),\n\talert = require('./alert'),\n\tGlobale = require('./components/Globale'),\n\tsearchbar = require('./searchbar'),\n\tsliders = require('./sliders');\n\nvar EmailSignup = require('./components/EmailSignup');\nvar giftCardBalanceInquiryHelper = require('./helpers/GiftCardBalanceInquiryHelper');\nvar GoogleTagManagerClient = require('../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar RequestHelper = require('../../../app_storefront_core/cartridge/js/helpers/RequestHelper');\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\n// if jQuery has not been loaded, load from google cdn\nif (!window.jQuery) {\n    var s = document.createElement('script');\n    s.setAttribute('src', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js');\n    s.setAttribute('type', 'text/javascript');\n    document.getElementsByTagName('head')[0].appendChild(s);\n}\n\nrequire('./jquery-ext')();\nrequire('./cookieprivacy')();\nrequire('./captcha')();\nrequire('./watermark')();\n\nvar dataBuffer = {};\nvar siteName;\n\nvar $sliderMobile;\nvar $navSecondary;\nvar $navUtilities;\nvar $navUl;\nvar $topBannerBar;\nvar $topBannerBarInner;\nvar $navigation;\nvar $topBannerInnerLinks;\nvar $selectSort;\nvar $secondaryHead;\nvar $searchResultContainer;\nvar $productContainerImage;\nvar $productDetail;\nvar $sectionCheckout;\nvar $mainInnerAlt;\nvar $sectionErrorFigure;\nvar $sectionErrorBox;\nvar $footerMenuItems;\nvar $promoMessages;\n\nfunction initializeEvents() {\n\tcookieNotification.initialize();\n\tvar controlKeys = ['8', '13', '46', '45', '36', '35', '38', '37', '40', '39'];\n\tvar $win = $(window);\n\tvar $doc = $(document);\n\t$doc.on('app.resize', function () {\n\t\tresizeDeviceHelper();\n\t});\n\t$win.on('load resize', function () {\n\t\tresizeDeviceHelper();\n\t});\n\t\n\t$(document).off('CategoryHeaderSliders.Initialize').on('CategoryHeaderSliders.Initialize', function(event) {\n\t\tsliders.initializeCategorySliders('.cat-header-content.cat-header-slider:not(.slick-initialized)');\n\t});\n\n\t$(document).off('PostAjaxAuthenticationActions.Initialize').on('PostAjaxAuthenticationActions.Initialize', function(event, options) {\n\t\tvar data = options.results;\n\t\tvar isAccountDialog = options.isAccountDialog;\n\t\tif (isAccountDialog) {\n\t\t\tvar customerFirstName = data.customerFirstName ? ', ' + data.customerFirstName + '.' : '.';\n\t\t\tvar alertMessage;\n\t\t\tif (options.displayMessage == 'login') {\n\t\t\t\talertMessage = 'Welcome back' + customerFirstName;\n\t\t\t}\n\t\t\tif (options.displayMessage == 'register') {\n\t\t\t\talertMessage = 'Thanks for creating an account' + customerFirstName;\n\t\t\t}\n\t\t\t\n\t\t\tif (SitePreferences.WISHLIST_ENABLED) { // Future-forward: in case we ever implement login/register dialogs other than with wishlist\n\t\t\t\t/**** Wishlist icon updates ****/\n\t\t\t\tvar wishlistItems = data.controllerResults && data.controllerResults.allWishlistItems ? data.controllerResults.allWishlistItems : data.allWishlistItems ? data.allWishlistItems : null;\n\t\t\t\tvar returnedResult = data.controllerResults && data.controllerResults.result ? data.controllerResults.result : data.result ? data.result : null;\n\t\t\t\tif (wishlistItems != null) {\n\t\t\t\t\twindow.localStorage.WishlistProductIDs = JSON.stringify(wishlistItems);\n\t\t\t\t\twishlist.renderAllWishlistButtons();\n\t\t\t\t\tif (returnedResult == 'complete') {\n\t\t\t\t\t\talertMessage += ' This item is already saved to your Wishlist.';\n\t\t\t\t\t} else {\n\t\t\t\t\t\talertMessage += ' An item has been added to your Wishlist.';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**** Selected store updates ****/\n\t\t\tvar storeFromProfile = data.storeFromProfile ? data.storeFromProfile : null;\n\t\t\tvar addToCartOptionsStoreId = $('.bopis-add-to-cart-options-store-selector .selected-store').length > 0 ? $('.bopis-add-to-cart-options-store-selector .selected-store').attr('store-id') : null;\n\t\t\tvar navStoresDropdownStoreId = $('.stores-dropdown .current-store .map.store').length > 0 ? $('.stores-dropdown .current-store .map.store').attr('data-id') : null;\n\t\t\tvar storeID;\n\n\t\t\tvar isProductPage = $('.pt_product-details').length;\n\t\t\tvar isCategory = $('.pt_product-search-result').length;\n\t\t\tif (isProductPage) {\n\t\t\t\tstoreID = addToCartOptionsStoreId ? addToCartOptionsStoreId : storeFromProfile ? storeFromProfile : null;\n\t\t\t\tif (storeID) {\n\t\t\t\t\t// Redraw the \"My Store\" piece on the PDP\n\t\t\t\t\t$(document).trigger('Bopis.StoreSearch.Select', storeID);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isCategory) {\n\t\t\t\tstoreID = navStoresDropdownStoreId ? navStoresDropdownStoreId : storeFromProfile ? storeFromProfile : null;\n\t\t\t}\n\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\tif (isCategory) {\n\t\t\t\t\tif (storeID) {\n\t\t\t\t\t\t// Make sure to update the store number in customer profile when on the PLP\n\t\t\t\t\t\t$(document).trigger('Bopis.AssignStoreToProfile', storeID);\n\t\t\t\t\t} \n\t\t\t\t}\n\t\t\t\tif (storeID) {\n\t\t\t\t\t// Redraw the selected store pieces in nav, Shop Your Store on PLP, My Account store drop-down, and store search modal\n\t\t\t\t\t$(document).trigger('Bopis.SelectedStore.Refresh', storeID);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**** Minicart update ****/\n\t\t\tif (data.cartQuantity) {\n\t\t\t\tvar $miniCartElm = $('.mini-cart .minicart-quantity').length > 0 ? $('.mini-cart .minicart-quantity') : $('.mini-cart .btn-minicart .btn-minicart-qty');\n\t\t\t\t$miniCartElm.html(data.cartQuantity);\n\t\t\t}\n\n\t\t\t/**** My Account navigation update ****/\n\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\t$('.login-dropdown .user-panel .form-login').addClass('d-none');\n\t\t\t\t$('.login-dropdown .login-dropdown-customer-menu').removeClass('d-none');\n\t\t\t} else {\n\t\t\t\tvar profileName = data.customerFirstName ? ' ' + data.customerFirstName : '';\n\t\t\t\t$('.mobile-account-main.first-name a').first().find('span').html('Hello' + profileName);\n\t\t\t}\n\n\t\t\t/**** Client Window > Customer object update ****/\n\t\t\tCustomer.authenticated = true;\n\t\t\tCustomer.registered = true;\n\t\t\t\n\t\t\t/**** Close the account dialog ****/\n\t\t\tdialog.close();\n\n\t\t\t/**** Show the alert ****/\n\t\t\talert.init({\n\t\t\t\ttype: 'alert-primary',\n\t\t\t\ttimer: 3000,\n\t\t\t\tcontent: alertMessage\n\t\t\t});\n\t\t} else {\n\t\t\twindow.location.href = data.registerDialogContinueUrl ? data.registerDialogContinueUrl : data.loginDialogContinueUrl ? data.loginDialogContinueUrl : location.reload();\n\t\t}\n\t});\n\n\t// Dom-Ready Sliders\n\tsliders.init('.barn-slider', {dots: false, breakpoints: {0: {slidesToShow: 1}, 1024: {slidesToShow: 2}}});\n\tif (SitePreferences.CONTENT_SLOT_SLIDER == 'swiperJS') {\n\t\tsliders.init('.collections-content.has-slider .curated', {loop: false, dots: false, breakpoints: {0: {slidesToShow: 1}, 768: {slidesToShow: 3}}});\n\t} else {\n\t\tsliders.init('.collections-content.has-slider .curated', {breakpoints: {0: {slidesToShow: 1}, 768: {slidesToShow: 3}}});\n\t}\n\tsliders.init('.section-offers.tiles .section-body', {dots: false, breakpoints: {0: {slidesToShow: 1}, 480: {slidesToShow: 3}, 768: {slidesToShow: 4}}});\n\tsliders.init('.section-offers.section-brands .brand-list', {dots: false, breakpoints: {0: {slidesToShow: 4}, 480: {slidesToShow: 3}, 768: {slidesToShow: 6}}});\n\n\tif ($(document).find('.jumbotron-mobile').length > 0 && window.innerWidth <= 767) {\n\t\tvar jumbotronExpandedCookie = getCookie('jumbotronExpandedCookie');\n\t\tif (jumbotronExpandedCookie == 'true' && $('#jumbotron-current-offers-icon').hasClass('fa-angle-down')) {\n\t\t\t$('.jumbotron-mobile').toggleClass('active');\n\t\t\t$('#jumbotron-current-offers-icon').removeClass('fa-angle-down');\n\t\t\t$('#jumbotron-current-offers-icon').addClass('fa-angle-up');\n\t\t} else if(jumbotronExpandedCookie == 'false' && $('#jumbotron-current-offers-icon').hasClass('fa-angle-up')) {\n\t\t\t$('.jumbotron-mobile').toggleClass('active');\n\t\t\t$('#jumbotron-current-offers-icon').removeClass('fa-angle-up');\n\t\t\t$('#jumbotron-current-offers-icon').addClass('fa-angle-down');\n\t\t}\n\t}\n\t\t\n\tif(window.innerWidth > 767 ) {\n\t\t$('.mobile-only .guest-checkout-form').remove();\n\t} else {\n\t\t$('.mobile-hidden .guest-checkout-form').remove();\n\t}\n\t\n\t\n\t$('#guest_checkout_optin:checkbox').change(function() {\n\t\tif ($('#guest_checkout_optin').prop(\"checked\")) {\n\t\t\t$('.optin-input').addClass('checked');\n\t\t} else {\n\t\t\t$('.optin-input').removeClass('checked');\n\t\t}\n\t});\n\n\t// selected states for account navigation\n\tif ($(document).find('.pt_account, .pt_order, .pt_customer-service, .pt_wish-list').length > 0) {\n\t\tvar currentPage = window.location.origin + window.location.pathname;\n\t\tvar isOnTopLevelPage = false;\n\t\t$('#secondary nav a')\n\t\t\t.removeClass('is-active')\n\t\t\t.each(function(index, value) {\n\t\t\t\tif (value.href === currentPage) {\n\t\t\t\t\t$(this).addClass('is-active');\n\t\t\t\t\tisOnTopLevelPage = true;\n\t\t\t\t}\n\t\t});\n\t\tif (!isOnTopLevelPage) {\n\t\t\t$('#secondary nav a').each(function(index, value) {\n\t\t\t\tif (value.href === document.referrer) {\n\t\t\t\t\t$(this).addClass('is-active');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Document.Ready(): ADA Compliance Fixes ---\n\t$(document).trigger('SlickSliderAccessibilityMods');\n\t// This work-around will have to do until we can contact the vendor to fix their tags.\n\tvar adaTagIntervalCounter = 0;\n\tvar adaTagInterval = setInterval(function(){ \n\t\tif (!$('img[src*=\"arttrk.com\"]').is('[alt]')) {\n\t\t\t$('img[src*=\"arttrk.com\"]').attr('alt','Tracking pixel');\n\t\t}\n\t\tif (!$('#fileUploadForm input#fileSelector').is('[aria-label]')) {\n\t\t\t$('#fileUploadForm input#fileSelector').attr('aria-label', 'Select file to upload');\n\t\t}\t\n\t\tif (adaTagIntervalCounter > 9 || ($('img[src*=\"arttrk.com\"]').is('[alt]') && $('#fileUploadForm input#fileSelector').is('[aria-label]'))) {\n\t\t\tclearInterval(adaTagInterval);\n\t\t}\n\t\tadaTagIntervalCounter++;\n\t}, 1000); // 1000 ms = start after 1sec \n\t// Skip link for product recommendations container\n\t$(document).off('click.Skip.Recommendations').on('click.Skip.Recommendations','.skip-product-recommendations-container', function(e) {\n\t\t$(this).siblings('.product-recommendations-container-dive').focus();\n\t});\n\n\t$(document).off('click.Zoom.Skip.Section').on('click.Zoom.Skip.Section','.product-image-container-mobile .skip-to-next', function(e) {\n\t\te.preventDefault();\n\t\tvar isSkipToWishlistButton = $(this).attr('href').indexOf('pdp-wishlist-button-container') > -1;\n\t\tif (isSkipToWishlistButton) {\n\t\t\t$('#pdp-wishlist-button-container .wishlist-item-status-button').addClass('focus-visible-indicator').focus();\n\t\t} else {\n\t\t\twindow.location = $(this).attr('href');\n\t\t}\n\t});\n\n\t// --- Initialize Events: ADA Compliance Keyboard Tab Visual Indicator ---\n\t$(document).on('keyup', function (event) {\n\t\tif (event.which === SiteConstants.KeyCodes.Tab) {\n\t\t\t$(':focus').addClass('focus-visible-indicator');\n\t\t\tif ($(':focus').hasClass('visually-hidden')) {\n\t\t\t\t// Get the innards of the current focus element and copy them into the hidden-element-memo that is then prepended to the <body>\n\t\t\t\tvar htmlText = $(':focus').html();\n\t\t\t\tvar $hiddenElementMemo = $('<div/>', {\"class\": \"hidden-element-memo\"}).html(htmlText);\n\t\t\t\t$('body').prepend($hiddenElementMemo);\n\n\t\t\t\t// Clear memo after 3 seconds if it has not already been cleared\n\t\t\t\tsetTimeout(function() { \n\t\t\t\t\t$('.hidden-element-memo').remove();\n\t\t\t\t}, 3000); // 3000 ms = start after 1sec \n\t\t\t}\n\t\t}\n\t}).on('keydown keypress mousemove', function (event) {\n\t\t$('.focus-visible-indicator').removeClass('focus-visible-indicator');\n\t\t$('.hidden-element-memo').remove();\n\t});\n\n\t$(document).on('init.Slider.Aria', '.slider', function(event, slick) {\n\t\t$(this).find('.slick-list').removeAttr('aria-live');\n\t}).on('click.Slider.Aria keyup.Slider.Aria', function(event) {\n\t\tif (event.target.matches('.slider, .slider *')) {\n\t\t\tif (!$(event.target).closest('.slider').find('.slick-list').attr('aria-live')) {\n\t\t\t\t$(event.target).closest('.slider').find('.slick-list').attr('aria-live', 'polite');\n\t\t\t}\n\t\t} else {\n\t\t\t$('.slider').find('.slick-list').removeAttr('aria-live');\n\t\t}\n\t});\n\n    $.fn.hasAttr = function(name) {\n\t\treturn this.attr(name) !== undefined;\n\t};\n\t\n\tfunction CheckloginCreate() {\n\t\tvar loginCreateCount = $(\".login-create-account\").length;\n\t\tif(loginCreateCount == 0) {\n\t\t$(\".order-confirmation-details\").addClass(\"fullWidth\");\n\t\t}else {\n\t\t\t$(\".order-confirmation-details\").removeClass(\"fullWidth\");\n\t\t}\n\t}\n\t\n\t// set customer birthday\n\t$(document).on('click','#dwfrm_birthday button.confirm', function(event){\n\t\tevent.preventDefault();\n\t\tvar email = $('.credential-list--email').text().trim();\n\t\tvar birthdayField = $('#dwfrm_birthday');\n\t\tvar birthmonth = birthdayField.find('.birthmonth select');\n\t\tvar birthday = birthdayField.find('.birthday select');\n\t\tvar birthyear = birthdayField.find('.birthyear select');\n\t\tvar month, day, year, birthdate;\n\t\t\n\t\tif (!birthmonth.val()) {\n\t\t\tbirthmonth.addClass('error-red');\n\t\t} else {\n\t\t\tbirthmonth.removeClass('error-red');\n\t\t\tmonth = birthmonth.find(\"option:selected\").text();\n\t\t}\n\t\t\n\t\tif (!birthday.val()) {\n\t\t\tbirthday.addClass('error-red');\n\t\t} else {\n\t\t\tbirthday.removeClass('error-red');\n\t\t\tday = birthday.find(\"option:selected\").text();\n\t\t}\n\n\t\tif (!birthyear.val()) {\n\t\t\tbirthyear.addClass('error-red');\n\t\t} else {\n\t\t\tbirthyear.removeClass('error-red');\n\t\t\tyear = birthyear.find(\"option:selected\").text();\n\t\t}\n\t\t\n\t\tif (birthdayField.find('.error-red').length > 0){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tbirthdate = month + '/' + day + '/' + year;\n\t\t\n\t\t$.ajax({\n\t\t\ttype: 'post',\n\t\t\turl: Urls.setBirthday,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\temail: email,\n\t\t\t\tmonth: month,\n\t\t\t\tday: day,\n\t\t\t\tyear: year\n\t\t\t}),\n\t\t\tsuccess: function (data) {\n\t\t\t\t$('#dwfrm_birthday').remove();\n\t\t\t\t$('.credential-list--birthdate').text(birthdate);\n\t\t\t\t\n\t\t\t\tif(SitePreferences.CORDIAL_ENABLED){\t\t\t\t\n\t\t\t\t\tvar auth_data = {\n\t\t\t\t\t\temail: email\n\t\t\t\t\t}\n\t\t\t\t\tvar contact_data = {\n\t\t\t\t\t    'channels': {\n\t\t\t\t\t        'email': {\n\t\t\t\t\t            'address': email\n\t\t\t\t\t        }\n\t\t\t\t\t    },\n\t\t\t\t\t    'birthday': birthdate\n\t\t\t\t\t};\n\t\n\t\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\t\tcrdl('contact', auth_data, contact_data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t\n\tif(siteName == SiteConstants.SiteIds.BootBarnUS && SitePreferences.PINTEREST_ENABLED){\t\n\t\tif ($(document).find('.pt_product-details').length > 0) {\n\t\t\tsetTimeout(function(){   \t\n\t\t\t\tvar thisItem = JSON.parse($('.productCardMetadata.pdp-browse').attr('data-product-gtm-json'));\n\t\t\t\tvar productID = thisItem[\"id\"];\n\t\t\t\tvar dateTime = Math.floor(Date.now() / 1000);\n\t\t\t\tvar eventID = 'pdp-' + productID + '-' + dateTime;\n\n\t\t\t  \tpintrk('track', 'pagevisit', {\n\t\t\t  \t\tevent_id: eventID,\n\t\t\t  \t\tline_items: [\n\t\t\t  \t\t\t{\n\t\t\t\t\t  \t\tproduct_name: thisItem[\"name\"].replace(/\\\\/g, \"\"),\n\t\t\t\t\t  \t\tproduct_id: productID,\n\t\t\t\t\t  \t\tproduct_category: thisItem[\"category\"].replace(/\\\\/g, \"\"),\n\t\t\t\t\t  \t\tproduct_price: thisItem[\"price\"],\n\t\t\t\t\t  \t\tproduct_brand: thisItem[\"brand\"]\n\t\t\t  \t\t\t}\n\t\t\t  \t\t]\n\t\t\t  \t});\n\t\t\t}, 3000);\t\t\t\t\t\n\t\t}\n\t\t\n\t\t// checkout event created on confirmation\t\n\t\tif ($(document).find('.order-confirmation-details').length > 0) {\n\t\t\tvar orderID = $('.orderdetails .sectionheader h3').text().replace('Order Number:','').trim();\n\t\t\tvar dateTime = Math.floor(Date.now() / 1000);\n\t\t\tvar eventID = 'checkout-' + orderID + '-' + dateTime;\n\t\t\tvar currency = 'USD';\n\t\t\t\n\t\t\tvar items = [];\n\t\t\t$('.order-item').each(function(index, el) {\n\t\t\t\tvar _this = $(this);\n\t\t\t\titems[index] = {};\n\t\t\t\t_this.find('.productCardMetadata').each(function(key, v) {\n\t\t\t\t\tvar thisItem = JSON.parse($(this).attr('data-product-gtm-json'));\n\t\t\t\t\tvar currency = thisItem[\"currency\"];\n\t\t\t\t\tvar product = {};\t\n\t\t\t\t\tproduct.product_name = thisItem[\"id\"];\n\t\t\t\t\tproduct.product_variant_id = thisItem[\"skuid\"];\n\t\t\t\t\tproduct.product_name = thisItem[\"name\"].replace(/\\\\/g, \"\");\n\t\t\t\t\tproduct.product_brand = thisItem[\"brand\"];\n\t\t\t\t\tproduct.product_quantity = thisItem[\"quantity\"];\n\t\t\t\t\tproduct.product_price = thisItem[\"price\"];\n\t\t\t\t\titems[index]= product;\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tpintrk('track', 'checkout', {\n\t\t\t\tevent_id: eventID,\n\t\t\t\tvalue: parseFloat($('.orderdetails .total .order-total').text().replace('$','')).toFixed(2),\n\t\t\t\torder_quantity: Math.round($('.orderdetails span.item-count').data('count')),\n\t\t\t\tcurrency: currency,\n\t\t\t\torder_id: orderID,\n\t\t\t\tline_items: items\n\t\t\t});\n\t\t}\n\t}\n\t\n\t// CORDIAL ACCOUNT SIGN-UP, BROWSE, CART, ORDER\n\tif(SitePreferences.CORDIAL_ENABLED){\n\t\t// homepage browse\n\t\tif ($(document).find('[content-slot-id=\"homepage-01\"]').length > 0) {\t\t\n\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\tcrdl('event', 'homepage_browse');\n\t\t\t}\t\t\n\t\t}\n\t\t\n\t\t// plp browse\n\t\tif ($(document).find('.pt_product-search-result').length > 0) {\n\t\t\tvar maxTiles = 10;\n\t\t\tvar products = [];\n\t\t\t$('.product-tile').each(function(i) {\n\t\t\t\tif (i < maxTiles) {\n\t\t\t\t\tvar product = $(this).attr('data-itemid');\n\t\t\t\t\tproducts.push(product);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tvar properties = {\n\t\t\t    \"category\": $('#categoryTitle').text().replace(/\\\\/g, \"\").trim(),\n\t\t\t    \"url\": $(location).attr(\"href\").split(\"?utm\")[0].split(\"#utm\")[0].split(\"&utm\")[0],\n\t\t\t    \"products\": products\n\t\t\t};\n\t\t\t\n\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\tcrdl('event', 'category_browse', properties);\n\t\t\t}\t\t\n\t\t}\n\t\t\n\t\t// pdp browse\n\t\tif ($(document).find('.pt_product-details').length > 0) {\n\t\t\tsetTimeout(function(){   \t\n\t\t\t\tvar thisItem = JSON.parse($('.productCardMetadata.pdp-browse').attr('data-product-gtm-json'));\n\t\t\t  \tvar images = [];\n\t\t\t\t$('.product-primary-image [class*=\"-slide\"]').each(function () {\n\t\t\t\t\tvar image = $(this).find('a').attr('href');\n\t\t\t\t\tif (!image || image == undefined || image == null) {\n\t\t\t\t\t\timage = $(this).find('img').attr('src');\n\t\t\t\t\t}\n\t\t\t\t\tif (images.indexOf(image) === -1) {\n\t\t\t\t\t\timages.push(image);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t  \tvar properties = {\n\t\t\t\t\t\"productID\": thisItem[\"id\"],\n\t\t\t\t\t\"productName\": thisItem[\"name\"].replace(/\\\\/g, \"\"),\n\t\t\t\t\t\"category\": thisItem[\"category\"].replace(/\\\\/g, \"\"),\n\t\t\t\t\t\"price\": thisItem[\"price\"],\n\t\t\t\t\t\"images\": images,\n\t\t\t  \t\t\"url\": $(location).attr(\"href\").split(\"?utm\")[0].split(\"#utm\")[0].split(\"&utm\")[0],\n\t\t\t\t\t\"attr\": {\n\t\t\t            \"manufacturer\": thisItem[\"brand\"]\n\t\t\t        },\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t  \t\tcrdl('event', 'product_browse', properties); \n\t\t\t\t}\n\t\t\t}, 3000);\t\t\t\t\t\n\t\t}\n\t\t\n\t\t// add Cordial contact from checkout\n\t\t$('#submitBilling').on('click', function(e){\n\t    \te.preventDefault();\n\t    \tif ($('.bill-address-fields .field.error').length == 0) {\n\t\t\t\tvar email = $('#dwfrm_billingaddress_email').val().trim();\n\t\t\t\tvar firstName = $('#dwfrm_billingaddress_firstName').val();\n\t\t\t\tvar lastName = $('#dwfrm_billingaddress_lastName').val();\n\t\t\t\tvar phone = $('#dwfrm_billingaddress_phone').val();\n\t\t\t\tvar zip = $('#dwfrm_billingaddress_postal').val();\n\t\t\t\tvar country = $('#dwfrm_billingaddress_country').val();\n\t\t\t\tvar state = $('#dwfrm_billingaddress_states_state').val();\n\t\t\t\tvar city = $('#dwfrm_billingaddress_city').val();\n\t\t\t\t\t\t\n\t\t\t\tif ($('input#newslettersignup').is(':checked')){\n\t\t\t\t\tvar auth_data = {\n\t\t\t\t\t\temail: email\n\t\t\t\t\t}\n\t\t\t\t\tvar contact_data = {\n\t\t\t\t\t    'channels': {\n\t\t\t\t\t        'email': {\n\t\t\t\t\t            'address': email,\n\t\t\t\t\t            'subscribeStatus': 'subscribed'\n\t\t\t\t\t        }\n\t\t\t\t\t    },\n\t\t\t\t\t\t'first_name': firstName,\n\t\t\t\t\t\t'last_name': lastName,\n\t\t\t\t\t\t'phone': phone,\n\t\t\t\t\t\t'postal_code': zip,\n\t\t\t\t\t\t'signup_source': 'checkout',\n\t\t\t\t\t\t'welcome_signup': true,\n\t\t\t\t\t\t'geo_location': {\n\t\t\t\t\t\t    'postal_code': zip,\n\t\t\t\t\t\t    'country': country,\n\t\t\t\t\t\t    'state': state,\n\t\t\t\t\t\t    'city': city\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tvar properties = {\n\t\t\t\t\t    \"signup_source\": 'checkout',\n\t\t\t\t\t    \"welcome_signup\": true\n\t\t\t\t\t};\n\t\t\n\t\t\t\t\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\t\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\t\t\tcrdl([\n\t\t\t\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t\t\t\t['event', 'email_signup', properties]\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).catch();\n\t\t\t\t}\n\t    \t}\n\t\t});\n\t\t\n\t\t// update Cart when qty change or removal in cart\n\t\tfunction cordialUpdateCart() {\n\t\t\tsetTimeout(function(){\n\t\t\t\tvar items = [];\n\t\t\t\t$('.order-item').each(function(index, el) {\n\t\t\t\t\tvar _this = $(this);\n\t\t\t\t\titems[index] = {};\n\t\t\t\t\t_this.find('.productCardMetadata').each(function(key, v) {\n\t\t\t\t\t\tvar thisItem = JSON.parse($(this).attr('data-product-gtm-json'));\n\t\t\t\t\t\tvar product = {};\t\n\t\t\t\t\t\tproduct.productID = thisItem[\"id\"];\n\t\t\t\t\t\tproduct.sku = thisItem[\"skuid\"];\n\t\t\t\t\t\tproduct.category = thisItem[\"category\"].replace(/\\\\/g, \"\");\n\t\t\t\t\t\tproduct.name = thisItem[\"name\"].replace(/\\\\/g, \"\");\n\t\t\t\t\t\tproduct.qty = thisItem[\"quantity\"];\n\t\t\t\t\t\tproduct.itemPrice = thisItem[\"price\"];\n\t\t\t\t\t\tproduct.images = [_this.find('img').attr('src')];\n\t\t\t\t\t\tproduct.url = window.location.origin + _this.find('.name').find('a').attr('href').split(\"?utm\")[0].split(\"#utm\")[0].split(\"&utm\")[0];\n\t\t\t\t\t\tproduct.attr = {'manufacturer': thisItem[\"brand\"], 'color': thisItem[\"color\"], 'size': thisItem[\"size\"] };\n\t\t\t\t\t\titems[index]= product;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tvar cart_data = items;\n\t\t\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['cart', 'clear'],\n\t\t\t\t\t\t['cartitem', 'add' , cart_data], \n\t\t\t\t\t\t['event', 'cart']\n\t\t\t\t\t]); \n\t\t\t\t}\n\t\t\t}, 3000);\n\t\t}\n\t\t\n\t\tfunction cordialClearCart() {\n\t\t\tsetTimeout(function(){\n\t\t\t\tvar properties = {\n\t\t\t\t    'status': 'empty'\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['cart', 'clear'],\n\t\t\t\t\t\t['event', 'cart', properties]\n\t\t\t\t\t]); \n\t\t\t\t}\n\t\t\t}, 3000);\n\t\t}\n\t\t\n\t\tif ($(document).find('.pt_cart').length > 0 || $(document).find('.pt_onepcheckout').length > 0) {\n\t\t\tif($('.order-item').length > 0){\n\t\t\t\tcordialUpdateCart();\n\t\t    } else {\t\t    \t\n\t\t    \tcordialClearCart();\n\t\t    }\n\t\t}\n\t\t\n\t\t$('body').on('change', 'input.opc-qty', function(event) {\n\t\t\tcordialUpdateCart();\n\t\t});\n\t\t\n\t\t$('body').on('click', '.cart-change', function(event) {\n\t\t\tsetTimeout(function(){\n\t\t\t\tif($('.order-item').length == 0){\n\t\t\t\t\tcordialClearCart();\n\t\t\t    } else {\n\t\t\t    \tcordialUpdateCart();\n\t\t\t    }\t\n\t    \t}, 2000);\n\t\t});\n\t\t\n\t\t// order event created on confirmation; myaccount signup\t\n\t\tif ($(document).find('.order-confirmation-details').length > 0) {\n\t\t\tvar orderID = $('.order-history-info span.value').first().text().trim();\n\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\tvar orderID = $('.orderdetails .sectionheader h3').text().replace('Order Number:','').trim();\n\t\t\t}\n\t\t\tvar email = $('.order-billing-email').text().trim();\n\t\t\tvar shippingName = $('.order-shipping-name').text().trim();\n\t\t\tvar shippingAddress2 = $('.order-shipping-address2').text().trim();\n\t\t\tvar shippingAddress3 = $('.order-shipping-address3').text().trim();\n\t\t\tvar shippingAddress = $('.order-shipping-address1').text().trim();\n\t\t\tif(shippingAddress2) { \n\t\t\t\tshippingAddress += \", \" + shippingAddress2;\n\t\t\t}\n\t\t\tif(shippingAddress3) { \n\t\t\t\tshippingAddress += \", \" + shippingAddress3;\n\t\t\t}\n\t\t\tvar shippingCity = $('.order-shipping-geo .city').text().trim().replace(',','');\n\t\t\tvar shippingState = $('.order-shipping-geo .state').text().trim();\n\t\t\tvar shippingZip = $('.order-shipping-geo .zip').text().trim();\n\t\t\tvar shippingCountry = $('.order-shipping-country').text().trim();\n\t\t\tvar billingName = $('.order-billing-name').text().trim();\n\t\t\tvar billingAddress2 = $('.order-billing-address2').text().trim();\n\t\t\tvar billingAddress3 = $('.order-billing-address3').text().trim();\n\t\t\tvar billingAddress = $('.order-billing-address1').text().trim();\n\t\t\tif(billingAddress2) { \n\t\t\t\tbillingAddress += \", \" + billingAddress2;\n\t\t\t}\n\t\t\tif(billingAddress3) { \n\t\t\t\tbillingAddress += \", \" + billingAddress3;\n\t\t\t}\n\t\t\tvar billingCity = $('.order-billing-geo .city').text().trim().replace(',','');\n\t\t\tvar billingState = $('.order-billing-geo .state').text().trim();\n\t\t\tvar billingZip = $('.order-billing-geo .zip').text().trim();\n\t\t\tvar billingCountry = $('.order-billing-country').text().trim();\n\t\t\tvar billingPhone = $('.order-billing-phone').text().replace('Phone:','').trim();\n\t\t\t\n\t\t\tvar name = billingName.split(' ');\n\t\t\tvar firstName = name[0];\n\t\t\tvar lastName = name[name.length-1];\n\t\t\t\n\t\t\tvar items = [];\n\t\t\t$('.order-item').each(function(index, el) {\n\t\t\t\tvar _this = $(this);\n\t\t\t\titems[index] = {};\n\t\t\t\t_this.find('.productCardMetadata').each(function(key, v) {\n\t\t\t\t\tvar thisItem = JSON.parse($(this).attr('data-product-gtm-json'));\n\t\t\t\t\tvar product = {};\t\n\t\t\t\t\tproduct.productID = thisItem[\"id\"];\n\t\t\t\t\tproduct.sku = thisItem[\"skuid\"];\n\t\t\t\t\tproduct.category = thisItem[\"category\"].replace(/\\\\/g, \"\");\n\t\t\t\t\tproduct.name = thisItem[\"name\"].replace(/\\\\/g, \"\");\n\t\t\t\t\tproduct.qty = thisItem[\"quantity\"];\n\t\t\t\t\tproduct.itemPrice = thisItem[\"price\"];\n\t\t\t\t\tproduct.images = [_this.find('img').attr('src')];\n\t\t\t\t\tproduct.url = window.location.origin + _this.find('.name').find('a').attr('href');\n\t\t\t\t\tproduct.attr = {'manufacturer': thisItem[\"brand\"], 'color': thisItem[\"color\"], 'size': thisItem[\"size\"] };\n\t\t\t\t\titems[index]= product;\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tvar order_data = {\n\t\t\t  \"orderID\": orderID,\n\t\t\t  \"shippingAddress\": {\n\t\t\t    \"name\": shippingName,\n\t\t\t    \"address\": shippingAddress,\n\t\t\t    \"city\": shippingCity,\n\t\t\t    \"state\": shippingState,\n\t\t\t    \"postalCode\": shippingZip,\n\t\t\t    \"country\": shippingCountry\n\t\t\t  },\n\t\t\t  \"billingAddress\": {\n\t\t\t\t\"name\": billingName,\n\t\t\t\t\"address\": billingAddress,\n\t\t\t\t\"city\": billingCity,\n\t\t\t\t\"state\": billingState,\n\t\t\t\t\"postalCode\": billingZip,\n\t\t\t\t\"country\": billingCountry\n\t\t\t  },\n\t\t\t  \"items\": items\n\t\t\t};\n\t\t\t\n\t\t\tvar properties = {\n\t\t\t    \"orderID\": orderID\n\t\t\t};\n\t\t\t\t\t\t\n\t\t\tvar auth_data = {\n\t\t\t\temail: email\n\t\t\t}\n\t\t\tvar contact_data = {\n\t\t\t    'channels': {\n\t\t\t        'email': {\n\t\t\t            'address': email\n\t\t\t        }\n\t\t\t    },\n\t\t\t    'first_name': firstName,\n\t\t\t\t'last_name': lastName,\n\t\t\t\t'phone': billingPhone,\n\t\t\t\t'postal_code': billingZip,\n\t\t\t\t'source_create': 'order',\n\t\t\t\t'geo_location': {\n\t\t\t\t    'postal_code': billingZip,\n\t\t\t\t    'country': billingCountry,\n\t\t\t\t    'state': billingState,\n\t\t\t\t    'city': billingCity\n\t\t\t\t}\n\t\t\t};\t\t\t\t\n\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\t\n\t\t\t\tcrdl([\n\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t['cart', 'clear'],\n\t\t\t\t\t['order', 'add', order_data],\n\t\t\t\t\t['event', 'order', properties]\n\t\t\t\t]);\n\t\t\t}\n\t\t\t\n\t\t\t// create Cordial contact on confirmation page\n\t\t\t$(document).on('click','.largebutton[name=\"dwfrm_profile_confirm\"]', function(){\n\t\t\t\tvar password = $('.password-holder .password').val();\n\t\t\t\tvar passwordConfirm = $('.password-holder .password-confirm').val();\n\t\t\t\tvar formValidation = true;\n\t\t\t\tvar signupEvent = \"\";\n\n\t\t\t\tvar regexPassword = /^(?=.*?[A-z])(?=.*?[0-9])(?=.*?[#?!\\=\\/\\,\\.\\~\\`\\(\\)\\{\\}\\[\\]\\\\@_$%^&*-]).{6,15}$/g;\n\t\t\t\tif ( String(password).match(regexPassword) == null ) {\n\t\t\t\t\tformValidation = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (password !== passwordConfirm) {\n\t\t\t\t\tformValidation = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!password || !passwordConfirm) {\n\t\t\t\t\tformValidation = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (formValidation && $('#RegistrationForm .field.error').length == 0){\t\t\t\t\t\n\t\t\t\t\tvar auth_data = {\n\t\t\t\t\t\temail: email\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar contact_data = {\n\t\t\t\t\t    'channels': {\n\t\t\t\t\t        'email': {\n\t\t\t\t\t            'address': email\n\t\t\t\t\t        }\n\t\t\t\t\t    },\n\t\t\t\t\t\t'first_name': firstName,\n\t\t\t\t\t\t'last_name': lastName,\n\t\t\t\t\t\t'phone': billingPhone,\n\t\t\t\t\t\t'postal_code': billingZip,\n\t\t\t\t\t\t'source_create': 'myaccount',\n\t\t\t\t\t\t'geo_location': {\n\t\t\t\t\t\t    'postal_code': billingZip,\n\t\t\t\t\t\t    'country': billingCountry,\n\t\t\t\t\t\t    'state': billingState,\n\t\t\t\t\t\t    'city': billingCity\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tvar loginProperties = {\n\t\t\t\t\t    \"email\": email\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif ($('input#newslettersignup').is(':checked')){\t\t\t\t\t\n\t\t\t\t\t\tvar contact_data = {\n\t\t\t\t\t\t    'channels': {\n\t\t\t\t\t\t        'email': {\n\t\t\t\t\t\t            'address': email,\n\t\t\t\t\t\t            'subscribeStatus': 'subscribed'\n\t\t\t\t\t\t        }\n\t\t\t\t\t\t    },\n\t\t\t\t\t\t\t'first_name': firstName,\n\t\t\t\t\t\t\t'last_name': lastName,\n\t\t\t\t\t\t\t'phone': billingPhone,\n\t\t\t\t\t\t\t'postal_code': billingZip,\n\t\t\t\t\t\t\t'signup_source': 'myaccount',\n\t\t\t\t\t\t\t'source_create': 'myaccount',\n\t\t\t\t\t\t\t'welcome_signup': true,\n\t\t\t\t\t\t\t'geo_location': {\n\t\t\t\t\t\t\t    'postal_code': billingZip,\n\t\t\t\t\t\t\t    'country': billingCountry,\n\t\t\t\t\t\t\t    'state': billingState,\n\t\t\t\t\t\t\t    'city': billingCity\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar properties = {\n\t\t\t\t\t\t    \"signup_source\": 'myaccount',\n\t\t\t\t\t\t    \"page\": 'confirmation',\n\t\t\t\t\t\t    \"welcome_signup\": true\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t\tsignupEvent = ['event', 'email_signup', properties];\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\t\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\t\t\tcrdl([\t\t\t\t\n\t\t\t\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t\t\t\t['event', 'account_create'],\n\t\t\t\t\t\t\t\t['event', 'login', loginProperties],\n\t\t\t\t\t\t\t\tsignupEvent\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).catch();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\t// Password Reset - No Account\n\t\tif ($(document).find('.reset-password .no-account').length > 0) {\n\t\t\tvar email = $('.no-account').text();\n\t\n\t\t\tvar auth_data = {\n\t\t\t\temail: email\n\t\t\t}\n\t\t\tvar contact_data = {\n\t\t\t    'channels': {\n\t\t\t        'email': {\n\t\t\t            'address': email\n\t\t\t        }\n\t\t\t    }\n\t\t\t};\n\t\t\t\n\t\t\tvar properties = {\n\t\t\t    \"email\": email\n\t\t\t};\n\n\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\tcrdl([\n\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t['event', 'reset-password-no-account', properties]\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Password Reset Confirmation\n\t\tif ($(document).find('#password-reset-confirm').length > 0) {\n\t\t\tvar email = $('#password-reset-confirm').attr('data-email');\n\t\t\tvar passwordEvent = \"reset-password\";\n\t\t\t\n\t\t\tif ($(document).find('.noAccount').length > 0) {\n\t\t\t\tvar passwordEvent = \"reset-password-no-account\";\n\t\t\t}\n\t\t\t\n\t\t\tvar auth_data = {\n\t\t\t\temail: email\n\t\t\t}\n\t\t\tvar contact_data = {\n\t\t\t    'channels': {\n\t\t\t        'email': {\n\t\t\t            'address': email\n\t\t\t        }\n\t\t\t    }\n\t\t\t};\n\t\t\t\n\t\t\tvar properties = {\n\t\t\t    \"email\": email\n\t\t\t};\n\n\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\tcrdl([\n\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t['event', passwordEvent, properties]\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t}\n\t//END CORDIAL\n\n\t\n\t// Reloading login page after unsuccessful attempt w/ error messaging,\n\t// and retaining username if 'Remember me' was checked\n\tif (window.location.href.indexOf('retry') >= 0) {\n        $('.login-dialog-error .invalid-login').removeClass('d-none');\n\t\tif (window.location.href.indexOf('=') >= 0) {\n\t\t\tvar username = window.location.href.split('=')[1];\n\t\t\t$('input[name*=\"dwfrm_login_username\"]').val(username);\n\t\t\t$('input[name*=\"dwfrm_login_rememberme\"]').prop('checked', true);\n\t\t}\n\t}\n\t \n\t// Make this my store click delegation\n\t$(document).on('click','.assign-store-container .assign-store', function(e){\n\t\te.preventDefault();\n\t\tvar storeID = $(this).parents('.store').data('id');\n\t\t$.ajax({\n\t\t\turl : Urls.assignStoreId,\n\t\t\tdata : { store_id : storeID },\n\t\t\tmethod : \"POST\",\n\t\t\tdataType : \"JSON\",\n\t\t\tsuccess : function(data) {\n\t\t\t\tif ( 'success' in data && data['success'] == true ) {\n\t\t\t\t\tlocation.reload();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t\n\t$(document).on('click', '.review', function(e){\n\t\tif (typeof $BV !== 'undefined') {\n\t\t\tvar productID = $(this).data('product-id');\n\t\t\tvar campaignID = $(this).data('campaign-id');\n\t\t\tif (typeof productID !== 'undefined') {\n\t\t\t\tproductID = productID.toString();\n\t\t\t\tif (productID.length > 0) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\n\t\t\t\t\tif (typeof $BV !== 'undefined') {\n\t\t\t\t\t\t$BV.ui(\"rr\", \"submit_review\", {productId: productID, campaignId: campaignID});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t\n\t//BazaarVoice - click on pdp inline rating scrolls down to reviews tab\n\t$(document).off('click.ScrollToReviews').on('click.ScrollToReviews', '.pdp-main .rating-container', '.bv-content-pagination-buttons-item .bv-content-btn', function(e) {\n\t\te.preventDefault();\n\t\tvar scrollTop = $('.product-reviews-container').offset().top - 10;\n\t\t\n\t\t$('html, body').animate({\n\t        scrollTop: scrollTop\n\t    }, 250);\n\t});\n\n\t//BazaarVoice syndication message\n\tsetInterval(function() {\n\t\tif(siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\tif($('#BVRRContainer').length){\n\t\t\t\t$('.bv-content-item').each(function(){\n\t\t\t\t\tvar originPost = $(this).find('.bv-content-reference-data .bv-origin-post');\n\t\t\t\t\tif(originPost.length < 1){\n\t\t\t\t    \tvar referenceMsg = $(this).find('.bv-badge-syndicated').text();\n\t\t\t\t    \t$(this).find('.bv-content-reference-data').append('<span class=\"bv-origin-post\">' + referenceMsg + '</span>');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, 500);\n\t\n\t//BazaarVoice - hide empty inline ratings and reviews\n\tif (pageContext && 'type' in pageContext && pageContext.type == 'product') {  \n\t\tsetTimeout(function() {\n\t    \tvar reviewCount = $('.bv_numReviews_component_container .bv_text').first().text().replace(/[()]/g,\"\");\n\t    \tif(parseInt(reviewCount) == 0 || $('.rating-container .img-separator').length){\n\t    \t\t$('.rating-container').hide();\n\t    \t\t$('.product-reviews-container').hide();\n\t    \t}\n\t    }, 2500);\n\t}\n\t\n\t//BazaarVoice - injecting stylesheet that overrides v2 shadow dom elements\n\tfunction addStyle(styles) {\n\t\tvar css = document.createElement('style');\n\t\tcss.type = 'text/css';\n\t  \n\t\tif (css.styleSheet){\n\t\t\tcss.styleSheet.cssText = styles;\n\t\t} else {\n\t\t\tcss.appendChild(document.createTextNode(styles));\n\t\t}\n\t\t\n\t\tvar bvElement = document.querySelector('div[data-bv-show=\"reviews\"]');\n\t\tif (bvElement && bvElement.shadowRoot) {\n\t\t\tbvElement.shadowRoot.appendChild(css);\n\t\t}\n\t}\n     \n    var styles = '.jsQeHX.WwxUI, .hRrcFz.WwxUI, .iFcEcv, .cXVdAC, .jsBsQs h3, .jqkdD, .gPsONF, .dVMqmv, .edZJjR, .hkyTvk, .dYLjyG, .fyeCcH, .fFNqWB, .lpnWEu, .dmcWUN { display: none !important }';\n    styles += '.bv_rating_content2, .bv_rating_content3, div[role=\"presentation\"] { display: none; flex: none }';\n\tstyles += '.cAtgnP { height: 100%; margin: 0 10px; padding-top: 10px }';\n\tstyles += '.jsQeHX.jsBsQs { margin: -20px 0 5px }';\n\tstyles += '.lTfDK, .eUaoSK, .jdEYYu, .gpRfFu { padding: 0px 16px; border-radius: unset }';\n\tstyles += '.jYCRe { border-radius: unset }';\n\tstyles += '.eUaoSK:focus { border-color: #393939 }';\n\tstyles += '.jTsSWZ { top: 2px }';  \n\tstyles += '.grdlqX.jHUsCh { color: #393939 }';\n\tstyles += '.ewPPY { border-bottom: none }';\n\tstyles += '.jOJVrV, .hiOSWf, .hiOSWf:hover { color: #ffffff; border-radius: unset }';\n\tstyles += 'div[itemprop=\"reviewRating\"], .gaVmkF, .isujDp { display: inline-flex; vertical-align: top; padding: 6px 12px 0 0 }';\n\tstyles += '.dpKFPg .gaVmkF { padding: 3px 12px 0 0 }';\n\tstyles += '@media (max-width: 767px) { div[itemprop=\"reviewRating\"], .gaVmkF, .isujDp { display: block; overflow: hidden }}';\n\tstyles += '.eGdSeJ, .eDeQCM, .bmAjQc { border-radius: unset }';\n\tstyles += '.gCFpGN { border-color: #7a7a7a; border-radius: unset }';\n\tstyles += '#reviews_container { margin-bottom: 25px }';\n\tstyles += 'div[data-bv-v=\"contentItem\"], .eYSWxm, .iDMzsn, .kuAUQn { border-top: 1px solid #d2d2d0; border-bottom: none; padding: 5px }';\n\tstyles += '.isujDp, .ijcDoa { display: inline; width: auto }';\n\tstyles += '.ljNKOA, .eDZdDN { padding: 5px 0 0 }';\n\tstyles += '.kiucBp { width: 14px; height: 14px }';\n\tstyles += 'div[data-bv-v=\"contentHeader\"], .hXbnlk, .kMYzbs, .hvfaWI, .hsSPAB, .hjojyB { width: 100%; padding: 0px }';\n\tstyles += 'h3.fXHeKf, h3.fCOyrM, h3.iCmYvO, h3.kCKagG, h3.beXXjZ, h3.eLoCMw { display: inline; font-size: 15px; font-weight: bold; margin: 0}';\n\tstyles += 'h3.kCKagG { line-height: 30px }';\n\tstyles += '@media (max-width: 767px) { h3.fXHeKf, h3.fCOyrM { line-height: 20px }}';\n\tstyles += '@media (max-width: 767px) { h3.iCmYvO { line-height: 20px; display: block; padding: 4px 0 }}';\t\n\tstyles += '.jPLiFm { margin: 10px 0px }';\n\tstyles += '.fktUhc { margin-top: 0px }';\n\tstyles += '.bSBrrQ { display: flex; align-items: center; margin-bottom: 18px }';\n\tstyles += '.bSBrrQ .DGfVS, .bSBrrQ .eDQqsO, .bSBrrQ .fqoJXd, .bSBrrQ button { display: inline; font-style: normal !important }';\n\tstyles += '.bSBrrQ .DGfVS h3, .bSBrrQ .eDQqsO h3, .bSBrrQ .fqoJX h3 { display: inline; margin-right: 10px; font-weight: normal }';\n\tstyles += '.hYfEUK { width: auto; margin-right: 10px }';\n\tstyles += '.bSBrrQ button { display: inline-flex; width: auto; font-weight: unset !important; margin-right: 10px }';\n\tstyles += '.bSBrrQ button meta { display: inline; }';\n\tstyles += '.bSBrrQ .ftAYOi, .bSBrrQ .dxQtDU, .bSBrrQ .bNKApu, .bSBrrQ .dxQtDU { display: inline; min-width: unset; max-width: unset }';\n\tstyles += '.bSBrrQ .dxQtDU, .bSBrrQ .jWGhqr { font-style: italic }';\n\tstyles += '@media (max-width: 767px) { .bSBrrQ button { width: auto; font-style: unset !important; margin-right: 10px }}';\n\tstyles += '.BdbdY, .hcnLga, .ktOlkc { margin: 15px 0px 10px }';\n\tstyles += '.BdbdY div, .hcnLga div, .ktOlkc div { padding: 5px 10px; border-radius: unset }';\n\tstyles += 'li[role=\"presentation\"] { display: inline-flex }';\n\tstyles += 'li[role=\"presentation\"] button { height: 40px; width: 40px; border-radius: unset }';\n\tstyles += 'li[role=\"presentation\"] a { height: 40px; width: 40px; border-radius: unset; padding-top: 10px }';\n\tstyles += 'li[role=\"presentation\"] a:hover { background-color: #efefef }';\n\tstyles += '.gocwuF { border-radius: unset; margin-bottom: 0 }';\n\tstyles += '.kxUynv, .kndPnx { border-radius: unset; margin-bottom: 5px }';\n\tstyles += 'div[data-bv-v=\"contentSummary\"], .bBuIFZ, .EFCyH, .kyNJgB { margin: 0; padding: 0 }';\n\tstyles += '@media (max-width: 767px) { .EFCyH { padding: 2px 2px 0px; }}';\n\tstyles += '.kssGoV { background: none }';\n\tstyles += '.jruHEc { margin: 0px }';\n\tstyles += '.PNCvp { color: #ffffff }';\n\tstyles += '.hQzHbm { height: 500px }';\n\tstyles += '.hQzHbm .cAtgnP { margin: 0; padding-top: 0 }';\n\tstyles += '.hQzHbm .hquDrt { height: calc(95vh) }';\n\tstyles += '.hQzHbm div[data-bv-v=\"contentItem\"] { border: none; padding: 5px }';\n\tstyles += '.hQzHbm .icytl { font-size: 20px }';\n\tstyles += '.hQzHbm .icytl svg { width: 20px; height: 20px }';\n\tstyles += '.hQzHbm h3.kCKagG, .hQzHbm h3.beXXjZ, .hQzHbm h3.eLoCMw { font-size: 20px; line-height: 25px }';\n\n\tif (pageContext && 'type' in pageContext && pageContext.type == 'product') {  \n\t\tsetTimeout(function() {\n\t\t\taddStyle(styles)\n\t\t}, 2500);\n\t}\n    \n    /*//BazaarVoice add Review/Reviews text to inline ratings count \n\tsetTimeout(function() {\n    \tvar reviewCount = $('.bv_numReviews_component_container .bv_text').first().text().replace(/[()]/g,\"\");\n    \tvar reviewText = parseInt(reviewCount) > 1 ? Resources.REVIEWS : Resources.REVIEW_TEXT;\n    \t$('.bv_numReviews_component_container .bv_text').text('(' + reviewCount + ' ' + reviewText + ')');\n    }, 3000);\n\n\tsetInterval(function() {\n\t\tCheckloginCreate();\n\t}, 2000);*/\n\t\n\t$('.section-group .section-body:last').append($('.section-reviews'));\n\n\t$(\".pt_customer-service #secondary .nav-title\").click(function() {\n\t\t$(this).toggleClass('active');\n\t\t$(\".pt_customer-service #secondary #customer-service-nav\").slideToggle();\n\t});\t\n\n\tsearchbar.init();\n\t\t\n\tif (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\tvar btn = $('#back-to-top'),\n\t\tscroll_position = 2100;\n\t\t\n\t\tif (window.innerWidth <= 767) {\n\t\t\tscroll_position = 2771;\n\t\t}\n\t\t\n\t\tif (window.innerWidth > 767) {\n    \t\t$('#main').prepend('<div class=\"menu-hover-overlay\" style=\"display:none;\"></div>');\n\t    \t\n\t    \t$('.has-dropdown.nav-menu').hover(\n\t\t\t\tfunction() {\n\t\t\t\t\t$('#wrapper').addClass('menu-active');\n\t\t\t\t},\n\t\t\t\tfunction() {\n\t\t\t\t\t$('#wrapper').removeClass('menu-active');\n\t\t\t\t}\n    \t    );\n    \t}\n\t\t\n\t\t$(window).scroll(function() {\n\t\t  if ($(window).scrollTop() > scroll_position) {\n\t\t    btn.addClass('show');\n\t\t  } else {\n\t\t    btn.removeClass('show');\n\t\t  }\n\t\t});\n\n\t\tbtn.on('click', function(e) {\n\t\t  e.preventDefault();\n\t\t  $('html, body').animate({scrollTop:0}, scroll_position);\n\t\t});\n\n\t\tif($('.homepage-03 .content-asset-body').length >= 1) {\n\t\t\tvar slot_position = $('.homepage-03 .content-asset-body').attr('slot-position').trim();\n\t\t\tif(slot_position != '3'){\n\t\t\t\tvar promo_slot = $('.shell.homepage-03').html(),\n\t\t\t\tbefore_this_slot = '.homepage-0' + parseInt(slot_position, 10);\n\t\t\t\t$('.shell.homepage-03').remove();\n\t\t\t\t\n\t\t\t\tif(slot_position > 3 && slot_position < 8){\n\t\t\t\t\tbefore_this_slot = '.homepage-0' + (parseInt(slot_position, 10) + 1);\t\t\t\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tif(slot_position > 7){\n\t\t\t\t\t$('.shell' + before_this_slot).after('<div class=\"shell homepage-03\">' + promo_slot + '</div>');\n\t\t\t\t} else {\n\t\t\t\t\t$('.shell' + before_this_slot).before('<div class=\"shell homepage-03\">' + promo_slot + '</div>');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar brands_count = $('.brand').length;\n\tvar styles_count = $('.style').length;\n\tvar toestyle_count = $('.toe-style').length;\n\n\tif(brands_count < 16) {\n\t\t$('.pt_content .viewallbrands').hide();\n\t}\n\n\tif(styles_count < 8) {\n\t\t$('.pt_content .viewallstyles').hide();\n\t}\n\n\tif(toestyle_count < 8) {\n\t\t$('.pt_content .viewalltoes').hide();\n\t}\n\n\t$(document).on('click','.ca-header-contact-info',function(event) {\n\t\tif(window.innerWidth > 767) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t});\n\t\n\t/*if(window.innerWidth < 767 ) {\n\t\tif(siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\t$('.product-listing-1x4 .grid-tile').each(function(){\n\t\t\t\t$(this).find('.product-content').before('<div class=\"savings-bar\"></div>');\n\t\t\t    if($(this).find('.product-sales-price').length !== 0){\n\t\t\t    \tvar $promoMsg = $(this).find('.product-sales-price').text().trim().replace('You Save:', 'Save');\n\t\t\t    \t$(this).find('.savings-bar').css('background-color','#E3ECEE').text($promoMsg).show();\n\t\t\t    }\t\n\t\t\t});\n\t\t}\n\t}*/\n\n\tif(window.innerWidth < 767 ) {\n\t\tif(brands_count > 8) {\n\t\t\t$('.pt_content .viewallbrands').show();\n\t\t}\n\n\t\t$('.pt_content .style:nth-child(n+9)').css({'display':'none'});\n\t\t$('.pt_content .toe-style:nth-child(n+9)').css({'display':'none'});\n\n\t\tif ($('.top-banner-bar').attr('data-header-for') != 'bootbarn_us') {\n\t\t\t$('.pt_storefront .list-review-products li .offer-list').slideUp();\n\t\t\t$('.pt_storefront .offer-head h2').addClass('close');\n\t\t}\n\t} else {\n\t\t$('.pt_content .style:nth-child(n+9)').css({'display':'block'});\n\t\t$('.pt_content .toe-style:nth-child(n+9)').css({'display':'block'});\n\t}\n\n\t$(document).on('click','.pt_content .viewallbrands',function(event) {\n\t\tevent.preventDefault();\n\t\tif($('.pt_content .viewallbrands').hasClass(\"expanded\")) {\n\t\t\t$('.pt_content .viewallbrands').removeClass(\"expanded\");\n\t\t\t$('.pt_content .brand:nth-child(n+9)').css({'display':'none'});\n\t\t\t$('.pt_content .viewallbrands').html(Resources.SHOWMOREBRANDS);\n\t\t} else {\n\t\t\t$('.pt_content .viewallbrands').addClass(\"expanded\");\n\t\t\t$('.pt_content .brand:nth-child(n+9)').css({'display':'block'});\n\t\t\t$('.pt_content .viewallbrands').html(Resources.CLOSE);\n\t\t}\n\t});\n\n\t$(document).on('click','.pt_content .viewallstyles',function(event) {\n\t\tevent.preventDefault();\n\t\tif($('.pt_content .viewallstyles').hasClass(\"expanded\")) {\n\t\t\t$('.pt_content .viewallstyles').removeClass(\"expanded\");\n\t\t\t$('.pt_content .style:nth-child(n+9)').css({'display':'none'});\n\t\t\t$('.pt_content .viewallstyles').html(Resources.SHOWMORESTYLE);\n\t\t} else {\n\t\t\t$('.pt_content .viewallstyles').addClass(\"expanded\");\n\t\t\t$('.pt_content .style:nth-child(n+9)').css({'display':'block'});\n\t\t\t$('.pt_content .viewallstyles').html(Resources.CLOSE);\n\t\t}\n\t});\n\n\t$(document).on('click','.pt_content .viewalltoes',function(event) {\n\t\tevent.preventDefault();\n\t\tif($('.pt_content .viewalltoes').hasClass(\"expanded\")) {\n\t\t\t$('.pt_content .viewalltoes').removeClass(\"expanded\");\n\t\t\t$('.pt_content .toe-style:nth-child(n+9)').css({'display':'none'});\n\t\t\t$('.pt_content .viewalltoes').html(Resources.SHOWMORETOE);\n\t\t} else {\n\t\t\t$('.pt_content .viewalltoes').addClass(\"expanded\");\n\t\t\t$('.pt_content .toe-style:nth-child(n+9)').css({'display':'block'});\n\t\t\t$('.pt_content .viewalltoes').html(Resources.CLOSE);\n\t\t}\n\t});\n\n\t$(document).on('click', '.swatch-list .swatch:not(.selected) [class*=\"swatch-im\"]', function() {\n\t\tvar $parentBlock = $(this).closest('.slide, .swatch-list');\n\t\tvar $mainImg = $parentBlock.find('.product-image img:first');\n\t\tvar swatchData = $(this).data('thumb');\n\t\t\n\t\tif (swatchData) {\n\t\t\t$mainImg.attr('alt', swatchData.alt);\n\t\t\t$mainImg.attr('title', swatchData.title);\n\t\t\t$mainImg.attr('src', swatchData.src);\n\t\t\t\n\t\t\t$parentBlock.find('.swatch').removeClass('selected');\n\t\t\t$(this).closest('.swatch').addClass('selected');\n\t\t} else {\n\t\t\twindow.location.href = $(this).closest('.swatch').attr('href');\n\t\t}\n\t});\n\t\n\t$(document).on('click','.yes-alts button.altButton', function(e){\n\t\te.preventDefault();\n\t\tvar altHiddenCount = $(this).closest('.yes-alts ul.swatch-list').find('.hidden-content').length;\n\t\tvar altHiddenToggle = '+ ' + altHiddenCount;\n\t\t$(this).text( $(this).text().indexOf('+') >= 0 ? \"- Less\" : altHiddenToggle);\n\t\t$(this).closest('.yes-alts ul.swatch-list').find('.hidden-content').toggle();\n\t});\n\n\t//Terms and Conditions Popup on Checkout\n\t$(document).off('click', '[dialog-content]').on('click', '[dialog-content]', function(event) {\n        event.preventDefault();\n        \n        var $this = $(event.currentTarget);\n        var $contentContainer = $($this.attr('dialog-content'));\n        \n        dialog.open({\n            html: $contentContainer.html(),\n            options: {\n                title: $contentContainer.attr('title'),\n                dialogClass: 'fixed checkout-terms' + ($contentContainer.attr('dialog-class') ? ' ' + $contentContainer.attr('dialog-class') : ''),\n                draggable: false,\n                open: function(event, ui) {\n                \tvar $this = $(this);\n                \t\n\t            \t$('body').addClass('dialog-open');\n\t            \t$this.scrollTop(0);\n\t            \temailForm.initialize($this);\n\t            },\n\t            close: function(event, ui) {\n\t            \t$('body').removeClass('dialog-open');\n\t            }\n            }\n        });\n\t});\n\n\t//Page Top functionality for popup content in terms and conditions\n\t$(document).off('click', '.ui-dialog [href=\"#pgTop\"]').on('click', '.ui-dialog [href=\"#pgTop\"]', function(event) {\n    \tevent.preventDefault();\n    \t\n    \tvar $this = $(event.currentTarget);\n    \t$this.closest('.ui-dialog-content').scrollTop(0);\n    });\n\n\t$('.video-play-btn')\n\t.on('click', function(e) {\n\t\tvar $this = $(this);\n\t\tvar $video = $this.closest('.video');\n\t\tvar $iframe = $video.find('iframe');\n\t\tvar originalSRC = $video.find('iframe').attr('src').replace('?autoplay=1','');\n\t\tvar videoHtml = $(this).next('iframe').prop('outerHTML');\n\t\tvideoHtml = videoHtml.replace(/src=\".+?\"/, 'src=\"' + originalSRC + '?autoplay=1\"');\n\t\tdialog.open({\n            html:(videoHtml),\n            options: {\n            \twidth: 560,\n                dialogClass: 'videopopup',\n                title: $video.find('.video-caption').text(),\n                close: function() {\n                \t$('.ui-dialog').find('iframe').attr('src', '');\n                }\n            },\n\t\t});\n\n\t\te.preventDefault();\n\t})\n\n\t\n\t//Prepare for touch/menu\n\tif (util.isTouchDevice()) {\n\t\t$('body').addClass('touchDevice');\n\t}\n\tif(window.navigator.platform.match(\"i(Win)\")){\n\t\t$('body').addClass('isWin')\n\t}\n\t\n\tif (siteName != SiteConstants.SiteIds.BootBarnUS && siteName != SiteConstants.SiteIds.SheplersUS) {\n\t\tif(window.innerWidth < 767) {\n\t\t\tif ($('.header-banner').children().length == 0) {\n\t\t\t$('.top-banner').addClass('no-top');\n\t\t\t}\n\t\t}\n\t}\n\t\n    $('body')\n        .on('keydown', 'textarea[data-character-limit]', function (e) {\n            var text = $.trim($(this).val()),\n                charsLimit = $(this).data('character-limit'),\n                charsUsed = text.length;\n\n            if ((charsUsed >= charsLimit) && (controlKeys.indexOf(e.which.toString()) < 0)) {\n                e.preventDefault();\n            }\n        })\n        .on('change keyup mouseup', 'textarea[data-character-limit]', function () {\n            var text = $.trim($(this).val()),\n                charsLimit = $(this).data('character-limit'),\n                charsUsed = text.length,\n                charsRemain = charsLimit - charsUsed;\n\n            if (charsRemain < 0) {\n                $(this).val(text.slice(0, charsRemain));\n                charsRemain = 0;\n            }\n\n            $(this).next('div.char-count').find('.char-remain-count').html(charsRemain);\n        })\n        .on('click','.pt_storefront .offer-head h2',function(event) {\n        \tevent.preventDefault();\n        \tif(window.innerWidth < 767 && $('.top-banner-bar').attr('data-header-for') != 'bootbarn_us') {\n\t        \t$(this)\n\t        \t\t.toggleClass('close')\n\t        \t\t.closest('li')\n\t        \t\t.find('.offer-list')\n\t        \t\t.slideToggle(200);\n\t\t\t} else if ($('.top-banner-bar').attr('data-header-for') == 'bootbarn_us') {\n\t\t\t\t$(this)\n\t\t\t\t\t.toggleClass('active')\n\t\t\t\t\t.closest('li')\n\t\t\t\t\t.toggleClass('active')\n\t\t\t\t\t.find('.offer-list')\n\t\t\t\t\t.toggleClass('active')\n\t\t\t\t\t.slideToggle(200);\n\t\t\t}\n\t\t})\n\t\t.on('click', '.footer-item .content-asset h3', function(event) {\n\t\t\tevent.preventDefault();\n\t\t\t\n\t\t\tif(window.innerWidth < 1025) {\n\t\t\t\t$(this)\n\t\t\t\t\t.toggleClass('active')\n\t\t\t\t\t.closest('.footer-item')\n\t\t\t\t\t.siblings()\n\t\t\t\t\t.find('.active')\n\t\t\t\t\t.removeClass('active');\n\n\t\t\t\t$(this)\n\t\t\t\t\t.next()\n\t\t\t\t\t.stop()\n\t\t\t\t\t.slideToggle()\n\t\t\t\t\t.closest('.footer-item')\n\t\t\t\t\t.siblings()\n\t\t\t\t\t.find('.menu-footer')\n\t\t\t\t\t.slideUp();\n\t\t\t}\n\t\t})\n\t\t.on('click', '.btn-expand', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tvar element = $(this).attr('href');\n\t\t\t\n\t\t\tif($('.sticky-menu').length > 0) {\n\t\t\t\tvar element = element  +  \".search-mobile\";\n\t\t\t}\n\t\t\t\n\t\t\t$(element).toggleClass('show');\n\t\t\t\n            if($('.sticky-menu').length > 0) { \n                $('#main').toggleClass('search-open');\n            }\n\n\t\t\tif($('.menu-toggle').hasClass('active')) {\n\t\t\t\tnavigation.CloseNavigation();\n\t\t\t}\n\n\t\t\tif($('#mini-cart').hasClass('active')) {\n\t\t\t\t$('#mini-cart .mini-cart-link').removeClass('active');\n\t\t\t\t$('#mini-cart').removeClass('active');\n\t\t\t}\n\t\t\t\n\t\t\tif($('.second-mobnav').hasClass('active')) {\t\t\t\t\n\t\t\t\t$('.second-mobnav').removeClass('active')\n\t\t\t\t$('#second-mobnav').slideUp();\n\t\t\t}\n\t\t\t\n\t\t\tif (element == '#search' || element == '#search.search-mobile') {\n\t\t\t\t$(document).trigger('SearchBar.Expand');\n            }\n\t\t})\n\t\t.on('click', '.btn-location-redirect', function(event){\n\t\t\tevent.preventDefault();\n\t\t\tvar linkRedirectStore = $(this).find('span').attr('loc-link');\n\t\t\tif (linkRedirectStore != null) {\n\t\t\t\tlocation.href = linkRedirectStore;\n\t\t\t}\n\t\t})\n\t\t.on('click', '.btn-location', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tif($('#mini-cart').hasClass('active')) {\n\t\t\t\t$('#mini-cart .mini-cart-link').removeClass('active');\n\t\t\t\t$('#mini-cart').removeClass('active');\n\t\t\t}\n\n\t\t\t$('#navigation')\n\t\t\t\t.stop()\n\t\t\t\t.slideToggle();\n\n\t\t\tnavigation.CloseNavigation();\n\t\t\t\n\t\t\tvar element = $(this).attr('href');\n\n\t\t\t$(element)\n\t\t\t\t.find('.nav-secondary-dropdown')\n\t\t\t\t.stop()\n\t\t\t\t.slideToggle()\n\t\t\t\t.parent()\n\t\t\t\t.siblings()\n\t\t\t\t.find('.nav-secondary-dropdown')\n\t\t\t\t.slideUp();\n\t\t})\n\t\t.on('click', '.jumbotron-current-offers', function (event) {\n\t\t\t$('.jumbotron-mobile').toggleClass('active');\n\t\t\tif($('#jumbotron-current-offers-icon').hasClass('fa-angle-up')) {\n\t\t\t\t$('#jumbotron-current-offers-icon').removeClass('fa-angle-up');\n\t\t\t\t$('#jumbotron-current-offers-icon').addClass('fa-angle-down');\n\t\t\t\tsetCookie('jumbotronExpandedCookie', false, 2);\n\t\t\t} else {\n\t\t\t\t$('#jumbotron-current-offers-icon').removeClass('fa-angle-down');\n\t\t\t\t$('#jumbotron-current-offers-icon').addClass('fa-angle-up');\n\t\t\t\tsetCookie('jumbotronExpandedCookie', true, 2);\n\t\t\t}\n\t\t})\n\t\t.on('click', '.second-mobnav', function (event) {\n\t\t\tevent.preventDefault();\n\t\t\t\n\t\t\t$(this).toggleClass('active');\n\t\t\t\n\t\t\t$('#second-mobnav')\n\t\t\t.stop()\n\t\t\t.slideToggle(150);\n\t\t\t\n\t\t\tif($('.menu-toggle').hasClass('active')) {\n\t\t\t\t$('.menu-toggle').removeClass('active');\n\t\t\t\t$('html').removeClass('menu-active');\n\t\t\t}\n\t\t\t \n\t\t\tif($('#mini-cart').hasClass('active')) {\n\t\t\t\t$('#mini-cart .mini-cart-link').removeClass('active');\n\t\t\t\t$('#mini-cart').removeClass('active');\n\t\t\t}\n\t\t\t$(document).trigger('SearchBar.Hide');\n\t\t})\n\t\t\n\t\t.on('click', '.accordion > a', function (event) {\n\t\t\tvar $container = $(this).closest('.accordion');\n\t\t\t$container.find('ul').slideToggle('fast');\n\t\t})\n/*\n\t\t.on('touchstart', function(event)  {\n    \t\tif (!$(event.target).closest('#navigation').length && !$(event.target).is('#navigation') && $win.width() > 767 )  {\n    \t\t    $('.level-2').stop().slideUp(400);\n    \t\t}  \n    \t})\n*/\n\t\t\n\t\t.on('mouseover', '#mini-cart', function () {\n\t\t\tif(window.innerWidth > 1024) {\n\t\t\t\t$(this)\n\t\t\t\t\t.find('.mini-cart-link')\n\t\t\t\t\t.addClass('active');\n\n\t\t\t\t$(this)\n\t\t\t\t\t.addClass('active');\n\t\t\t}\n\n\t\t\tif($('#navigation').hasAttr('style')) {\n\t\t\t\t$('.menu-toggle').removeClass('active');\n\t\t\t}\n\t\t\t$(document).trigger('SearchBar.Hide');\n\t\t})\n\t\t.on('mouseleave', '#mini-cart', function () {\n\t\t\tvar $this = $(this);\n\n\t\t\tif(window.innerWidth > 1024) {\n\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t$this\n\t\t\t\t\t\t.find('.mini-cart-link')\n\t\t\t\t\t\t.removeClass('active');\n\n\t\t\t\t\t$this\n\t\t\t\t\t\t.removeClass('active');\n\t\t\t\t}, 1000);\n\t\t\t}\n\t\t})\n\t\t.on('click', '.edit-search-query', function () {\n\t\t\t$('.category-popup-list-stores').dialog('close');\n\t\t\t$('.grid-page-storeselector-popup').dialog('open');\n\t\t})\n\t\t.on('click', '.popup-list-stores input[name=\"apply\"]', function () {\n\t\t\tif (!$('input[name=\"store\"]:checked').val()) {\n\t\t\t\talert('Select one of stores');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\ttype: 'get',\n\t\t\t\turl: Urls.setDefaultStore,\n\t\t\t\tdata: {\n\t\t\t\t\tstoreId: $('input[name=\"store\"]:checked').val()\n\t\t\t\t},\n\n\t\t\t\tsuccess: function (data) {\n\t\t\t\t\t$('.category-popup-list-stores').dialog('close');\n\t\t\t\t\tdocument.location.reload();\n\t\t\t\t}\n\t\t\t});\n\t\t})\n\t\t\n\t\t.on('click', '.pt_product-search-result .category-slot a', function(event) {\n\t\t\tvar refinementValue = $(event.target).closest('[data-link-attribute-value]').data('link-attribute-value');\n\t\t\tvar isRefinementLink = refinementValue != undefined;\n\n\t\t\tif (isRefinementLink) {\t\n\t\t\t\tvar $sidebarRefinement = $('#refinements-inner').find('#field-' + refinementValue);\n\t\t\t\tvar urlRefinementData = getUrlRefinementData();\n\n\t\t\t\tif ($sidebarRefinement.length > 0) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t$sidebarRefinement.trigger('click');\n\t\t\t\t} else if (urlRefinementData.hasRefinements) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tvar refinementId = $(event.target).closest('[data-link-attribute-id]').data('link-attribute-id');\n\t\t\t\t\tvar refinementIsAlreadySelected = false;\n\t\t\t\t\tvar redirectUrl;\n\n\t\t\t\t\tfor (var refinement in urlRefinementData.parameters) {\n\t\t\t\t\t\tif (urlRefinementData.parameters[refinement] === refinementValue) {\n\t\t\t\t\t\t\trefinementIsAlreadySelected = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!refinementIsAlreadySelected) {\n\t\t\t\t\t\tredirectUrl = window.location.href + '&prefn' + urlRefinementData.newRefinementStartNumber + '=' + refinementId + '&prefv' + urlRefinementData.newRefinementStartNumber + '=' + refinementValue;\n\t\t\t\t\t\twindow.location.href = redirectUrl;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t$(document).on('click', '.thumb-link, .name-link', function(event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar $container = $this.closest('.accordion, .section-offers, .tiles, .cat-header-content.cat-header-slider').first();\n\t\t\tif ($container.length > 0) {\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tif ($container.find('.product-tile').length > 0) {\n\t\t\t\t\tvar containerId = $container.attr('content-slot-id') || $container.attr('id');\n\t\n\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\tpromotion_name: containerId\n\t\t\t\t\t}\n\n\t\t\t\t\tvar pageType;\n\t\t\t\t\tvar $wrapper = $this.closest('.add-to-cart-modal');\n\t\t\t\t\tif ($wrapper.length > 0) {\n\t\t\t\t\t\tpageType = 'addtocartmodal';\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!pageType) {\n\t\t\t\t\t\t$wrapper = $('#wrapper');\n\t\t\t\t\t\tif ($wrapper.length > 0) {\n\t\t\t\t\t\t\tif (pageContext && pageContext.type) {\n\t\t\t\t\t\t\t\tswitch (pageContext.type) {\n\t\t\t\t\t\t\t\t\tcase 'storefront':\n\t\t\t\t\t\t\t\t\tpageType = 'Homepage';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'search':\n\t\t\t\t\t\t\t\t\tpageType = 'PLP';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'product':\n\t\t\t\t\t\t\t\t\tpageType = 'PDP';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'cart':\n\t\t\t\t\t\t\t\t\tpageType = 'Cart';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'onepcheckout':\n\t\t\t\t\t\t\t\t\tcase 'onepcheckout_groups':\n\t\t\t\t\t\t\t\t\tpageType = 'Checkout';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'orderconfirmation':\n\t\t\t\t\t\t\t\t\tpageType = 'Order Confirmation';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'customerservice':\n\t\t\t\t\t\t\t\t\tpageType = 'Customer Service';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'account':\n\t\t\t\t\t\t\t\t\tpageType = 'Account';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'content':\n\t\t\t\t\t\t\t\t\tpageType = 'Content Page';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\n\t\t\t\t\t\t\t\t\tcase 'error':\n\t\t\t\t\t\t\t\t\tpageType = 'Error Page';\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pageType) {\n\t\t\t\t\t\tdataObject.promotion_id = pageType;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar redirectHandler = function() {\n\t\t\t\t\t\tlocation.href = $this.attr('href');\n\t\t\t\t\t};\n\t\n\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('SelectPromotion', dataObject, { Container: $this.closest('.product-tile') }).then(redirectHandler).catch(redirectHandler);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t$(document).on('click', '[content-asset-id] a, [content-asset-id] button', function(event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar isLink = $this.attr('href') && $this.attr('href').length > 0 && $this.attr('href').indexOf('//') >= 0;\n\t\t\tvar isClose = $this.attr('class') && $this.attr('class').length > 0 && $this.attr('class').indexOf('close') >= 0;\n\n\t\t\tif ($this.closest('.product-tile').length == 0 && !isClose) {\n\t\t\t\tvar $container = $this.closest('[content-asset-id]').first();\n\t\t\t\tif ($container.length > 0) {\n\t\t\t\t\tif (isLink) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\n\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\tcontent_type: 'content',\n\t\t\t\t\t\titem_id: $container.attr('content-asset-id')\n\t\t\t\t\t}\n\n\t\t\t\t\tvar redirectHandler = function() {\n\t\t\t\t\t\tif (isLink) {\n\t\t\t\t\t\t\tlocation.href = $this.attr('href');\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\n\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('SelectContent', dataObject).then(redirectHandler).catch(redirectHandler);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\taddPromotionDataLayers();\n\t\t$(document).off('GoogleTagManager.AddPromotionDataLayers').on('GoogleTagManager.AddPromotionDataLayers', function(event) {\n\t\t\taddPromotionDataLayers();\n\t\t});\n\t\t\n\t\t/**\n\t\t * Add class to content slot refinements if they're currently active\n\t\t * and remove any static refinements if they're not found in the sidebar\n\t\t * to prevent empty search results.\n\t\t */\n\t\tif ($('body').find('.pt_product-search-result .category-slot a').length > 0) {\n\t\t\tvar $slotLink = $('body').find('.pt_product-search-result .category-slot a');\n\t\t\tvar urlRefinementData = getUrlRefinementData();\n\t\t\tvar sidebarRefinements = getSidebarRefinements();\n\t\t\t$slotLink.each(function(index, value) {\n\t\t\t\tvar linkRefinementType = $(value).data('link-attribute-value');\n\t\t\t\tfor (var refinement in urlRefinementData.parameters) {\n\t\t\t\t\tif (refinement.match(/^\\prefv/)) {\n\t\t\t\t\t\tvar refinementValues = urlRefinementData.parameters[refinement].split('%7C');\n\t\t\t\t\t\tfor (var index = 0; index < refinementValues.length; index++) {\n\t\t\t\t\t\t\tif (refinementValues[index] === linkRefinementType) {\n\t\t\t\t\t\t\t\t$(value).addClass('refinement-active');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (linkRefinementType != undefined) {\n\t\t\t\t\tvar foundInSidebar = false;\n\t\t\t\t\tfor (var index = 0; index < sidebarRefinements.length; index++) {\n\t\t\t\t\t\tif (sidebarRefinements[index] === linkRefinementType) {\n\t\t\t\t\t\t\tvar foundInSidebar = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!foundInSidebar) {\n\t\t\t\t\t\t$(value).closest('li').remove();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t$slotLink.closest('.section-block').removeClass('hidden');\n\t\t}\n\n\t\t/**\n\t\t * helper function to get a list of existing refinements from the URL\n\t\t */\n\t\tfunction getUrlRefinementData() {\n\t\t\tvar refinements = location.search.substr(1).split('&');\n\t\t\tvar urlRefinementData = {\n\t\t\t\tnewRefinementStartNumber: 1,\n\t\t\t\tparameters: {},\n\t\t\t\thasRefinements: false\n\t\t\t};\n\t\t\tif (refinements.length > 0) {\n\t\t\t\tfor (var index = 0; index < refinements.length; index++) {\n\t\t\t\t\tvar parameter = refinements[index].split('=');\n\t\t\t\t\tif (parameter[0].match(/^\\prefn/)) {\n\t\t\t\t\t\turlRefinementData.newRefinementStartNumber++;\n\t\t\t\t\t\turlRefinementData.hasRefinements = true;\n\t\t\t\t\t\turlRefinementData.parameters[parameter[0]] = parameter[1];\n\t\t\t\t\t}\n\t\t\t\t\tif (parameter[0].match(/^\\prefv/)) {\n\t\t\t\t\t\turlRefinementData.parameters[parameter[0]] = parameter[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn urlRefinementData;\n\t\t}\n\n\t\t/**\n\t\t * helper function to get a list of refinement names present in refinement sidebar\n\t\t */\n\t\tfunction getSidebarRefinements() {\n\t\t\tvar sidebarRefinementList = [];\n\t\t\t$('#secondary.refinements .checkbox input').each(function(index, value) {\n\t\t\t\tif ($(value).attr('id').match(/^field/)) {\n\t\t\t\t\tvar refinementName = $(value).attr('id').split('-')[1];\n\t\t\t\t\tsidebarRefinementList.push(refinementName);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn sidebarRefinementList;\n\t\t}\n \n    \t//ready #navigation for interaction (arrests odd initial interaction on touch devices)\n    \t$(\"#navigation\").addClass(\"hoverReady\");\n\n\t\t// Switch show text\n\t\t$('.switch input').change(function () {\n\t\t\tif($(this).prop('checked')) {\n\t\t\t\t$(this)\n\t\t\t\t\t.closest('.result-options')\n\t\t\t\t\t.addClass('show-info');\n\t\t\t} else {\n\t\t\t\t$(this)\n\t\t\t\t\t.closest('.result-options')\n\t\t\t\t\t.removeClass('show-info');\n\t\t\t}\n\t\t});\n\n\t\tif($('body').find('.result-options .switch input[name=\"field-true\"]').prop('checked')) {\n\t\t\tvar toggleBtn = $('body').find('.result-options .switch input[name=\"field-switch\"]');\n\n\t\t\tif(!toggleBtn.prop('checked')) {\n\t\t\t\ttoggleBtn.closest('.result-options').addClass('show-info');\n\t\t\t\ttoggleBtn.closest('.result-options').find('input[name=\"field-switch\"]').attr('checked', 'checked');\n\t\t\t} else {\n\t\t\t\ttoggleBtn.closest('.result-options').removeClass('show-info');\n\t\t\t\ttoggleBtn.closest('.result-options').find('input[name=\"field-switch\"]').removeAttr('checked');\n\t\t\t}\n\t\t}\n\n\t\t$('.swatches > li > ul').on('click', 'a', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this)\n\t\t\t\t.toggleClass('current')\n\t\t\t\t.parent()\n\t\t\t\t.siblings()\n\t\t\t\t.find('.current')\n\t\t\t\t.removeClass('current');\n\t\t});\n\n\t\t// Generic slider init\n\t\tsliders.init('.slider .slides');\n\t\t\n\t\t$('.service-toggle-item').on('click', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this).toggleClass('active');\n\n\t\t\t$(this).next('.customer-service-inner').toggleClass('open');\n\t\t\t$(this).next('.customer-service-inner').slideToggle();\n\t\t});\n\n\t\t$('.top-brands .category-head').on('click', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this).toggleClass('active');\n\n\t\t\t$(this).next('.category-body').toggleClass('open');\n\t\t\t$(this).next('.category-body').slideToggle();\n\t\t});\n\n\t\t$(document).on('update', '.slider-products-primary', function() {\n    \t\tsliders.init('.slider-products-primary .slides', {breakpoints: {0: {slidesToShow: 1, dots: true}, 768: {slidesToShow: 3}, 1024: {slidesToShow: 4}}});\n\t\t});\n\n\t\t// make sure slider gets initialized for product recommendations when dynamically added\n\t\tif ($('.pt_product-details').length > 0 || $('.no-hits-banner').length > 0) {\n\t\t\tsliders.initializeRecommendationSlider();\n\t\t}\n\n\t\t$(document).off('EinsteinProductRecommendations.Initialize').on('EinsteinProductRecommendations.Initialize', function() {\n\t\t\tsliders.initializeRecommendationSlider();\n\t\t});\n\n\t\t$(document).on('init-slider', '.slider-products-primary', function() {\n\t\t\tif (pageContext.site !== SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\tvar showMobileDots = siteName == SiteConstants.SiteIds.CountryOutfittersUS ? false : true;\n\t\t\t\tsliders.init('.product-recommendations .slider-products-primary .slides:not(.slick-slider):not(.swiper-full-wrapper):has(li)', {loop: false, breakpoints: {0: {slidesToShow: 1, dots: showMobileDots, arrows: true}, 768: {slidesToShow: 3, dots: false, arrows: true}, 1024: {slidesToShow: 4, dots: false, arrows: true}}}, true);\n\t\t\t\tsliders.init('.last-visited .slider-products-primary .slides:not(.slick-slider):not(.swiper-full-wrapper):has(li)', {loop: false, breakpoints: {0: {slidesToShow: 1, dots: showMobileDots, arrows: true}, 768: {slidesToShow: 3, dots: false, arrows: true},  1024: {slidesToShow: 4, dots: false, arrows: true}}});\n\t\t\t} else {\n\t\t\t\tsliders.init('.product-recommendations .slider-products-primary .slides:not(.slick-slider):not(.swiper-full-wrapper):has(li)', {loop: false, breakpoints: {0: {slidesToShow: 1, dots: true, arrows: true}, 768: {slidesToShow: 3, dots: false, arrows: true}}}, true);\n\t\t\t\tsliders.init('.last-visited .slider-products-primary .slides:not(.slick-slider):not(.swiper-full-wrapper):has(li)', {loop: false, breakpoints: {0: {slidesToShow: 1, dots: true, arrows: true}, 768: {slidesToShow: 4, dots: false, arrows: true}}});\n\t\t\t}\n\t\t});\n\n\t\tsliders.init('.slider-filmstrip .slides', {loop: true});\n\n\t\tsliders.initializeCategorySliders('.cat-header-content.cat-header-slider:not(.slick-initialized)');\n\n\t\t// Waypoints\n\t\t$('.waypoint').on('click', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tvar element = $(this).attr('href');\n\n\t\t\t$('html, body').animate({\n\t\t\t\tscrollTop: $(element).offset().top\n\t\t\t}, 1000);\n\t\t});\n\n\t\t// Btn Expand Alt\n\t\t$('.btn-expand-alt').on('click', function(event) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar element = $(this).attr('href');\n\n\n\t\t\tif ($(element).hasClass('grid-page-storeselector-popup')) {\n\t\t\t\t$(element).dialog('open');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$(element)\n\t\t\t\t.toggleClass('show');\n\t\t});\n\n\t\t$('.grid-page-storeselector-popup').dialog({\n\t\t\twidth: 450,\n\t\t\tautoOpen: false,\n\t\t\tmodal: true,\n\t\t\tresizable: false\n\t\t});\n\n\t\t// Sidebar Close\n\t\t$('#secondary .close, #sort-by .close, .popup-close').on('click', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this)\n\t\t\t\t.closest('.show')\n\t\t\t\t.removeClass('show');\n\t\t});\n\n\t\t$('.message .close').on('click', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this)\n\t\t\t\t.parent()\n\t\t\t\t.slideUp();\n\t\t});\n\n\t\tif ($('#GlobaleFreeShippingBannerContainer').length > 0) {\n\t\t\tvar globaleFreeShippingBannerObserver = new MutationObserver(function(mutations, observer) {\n\t\t\t\tfor (var mutationKey in mutations) {\n\t\t\t\t\tvar mutation = mutations[mutationKey];\n\t\t\t\t\tif (mutation.type === 'childList') {\n\t\t\t\t\t\tresizeDeviceHelper();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tglobaleFreeShippingBannerObserver.observe(document.getElementById('GlobaleFreeShippingBannerContainer'), {attributes: false, childList: true, subtree: true });\n\t\t}\n\n\t\t// Back to Top button\n\t\tfunction topButtonToggle() {\n\t\t\tvar $scrollTop = $win.scrollTop();\n\t\t\tif ($scrollTop >  100 ) {\n\t\t\t\t$('body').addClass('btn-go-top-active');\n\t\t\t\t$( '.btn-go-top' ).addClass('active');\n\t\t\t} else {\n\t\t\t\t$('body').removeClass('btn-go-top-active');\n\t\t\t\t$( '.btn-go-top' ).removeClass('active');\n\t\t\t}\n\t\t}\n\t\t\n\t\t$win.on('scroll', function () {\n\t\t\ttopButtonToggle();\n\t\t\t$(document).trigger('SearchBar.ScrollTop');\n\t\t});\n\n\t\t$win.on('load', function() {\n\t\t\taccordionMobile();\n\t\t\taccordionMobileAlt();\n\n\t\t\t// Disabled per BOOT-3517\n\t\t\t// $( '<span class=\"btn-go-top\"><i class=\"fa fa-angle-up\" aria-hidden=\"true\"></i><span>Top</span></span>' ).insertBefore($('.footer:not(.footer-mobile)'));\n\t\t\t// topButtonToggle();\n\t\t});\n\n\t\t$doc.on('click', '.btn-go-top', function(e){\n\t\t\t$('html, body').animate({scrollTop: 0},800);\n\t\t\te.preventDefault();\n\t\t})\n\n\t\t// Read More / Less\n\t\t$doc.on('click', '.section-offers-text .read-more', function(e) {\n\t\t\te.preventDefault();\n\t\t\t$(this).parents('.section-body').first().addClass('expand');\n\t\t\treturn false;\n\t\t});\n\n\t\t$doc.on('click', '.section-offers-text .read-less', function(e) {\n\t\t\te.preventDefault();\n\t\t\t$(this).parents('.section-body').first().removeClass('expand');\n\t\t\treturn false;\n\t\t});\n\t\t\n\t\t\n\t\t// Accordion\n\t\tfunction accordionMobile() {\n\t\t\t$('.offer .offer-head h6').on('click', function (e) {\n\t\t\t\tif(event.target.nodeName == \"H6\"){\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t$(this).find('.chevron-collapse').click();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t$('.offer .offer-head h6 .chevron-collapse').on('click', function (event) {\n\t\t\t\tif (window.innerWidth > 1024) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t\tvar $this = $(this)\n\t\t\t\tvar $parent = $this.closest('.offer')\n\n\t\t\t\tif ($parent.hasClass(\"active\")) {\n\t\t\t\t\t$parent.removeClass('active').find('.offer-body').slideUp();\n\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$parent.addClass('active').find('.offer-body').slideDown();\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t\t$win.resize(function() {\n\t\t\t\tif(window.innerWidth > 1024) {\n\t\t\t\t\t$('.offer .offer-body').show();\n\t\t\t\t} else {\n\t\t\t\t\t$('.offer .offer-body').hide()\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tfunction accordionMobileAlt() {\n\t\t\t$('.accordion-mobile .accordion-mobile-head').on('click', function (event) {\n\t\t\t\tif (window.innerWidth > 1024) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tvar $this = $(this),\n\t\t\t\t\t$parent = $this.closest('.accordion-mobile');\n\n\t\t\t\t$this\n\t\t\t\t.toggleClass('active')\n\t\t\t\t.next()\n\t\t\t\t.stop()\n\t\t\t\t.slideToggle();\n\t\t\t});\n\t\t};\n\n\t\t// Accordion\n\t\t$(document).on('click', '.accordion-section .accordion-head', function(event) {\n\t\t\tevent.preventDefault();\n\t\t\tvar $this = $(this);\n\t\t\tvar $container = $this.closest('.accordion');\n\t\t\t$this.toggleClass('active');\n\t\t\t$this.next('.accordion-body').stop().slideToggle(400);\n\n\t\t\tif ($this.hasClass('active') && $container.find('.slides').length > 0 && $container.find('.slick-initialized').length > 0) {\n\t\t\t\t$container.find('.slides').slick('refresh');\n\t\t\t}\n\t\t});\n\n\t\t$(document).on('click', '.section-offers.content-columns .section-column h6.column-title', function(event) {\n\t\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS && window.innerWidth < 768) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t$(this).toggleClass('active');\n\t\t\t\t$(this).next('.column-content').stop().slideToggle();\n\t\t\t}\n\t\t});\n\n\t\t// Rotate Text\n\t\tfunction rotateText($element, duration) {\n\t\t\tvar lengthSlider = $element.find('.rotate-element').length;\n\t\t\tvar $rotateElement = $element.find('.rotate-element');\n\t\t\t\n\t\t\tif (lengthSlider > 0) {\n\t\t\t\tvar interval = setInterval(function () {\n\t\t\t\t\tvar $rotateElementActive \t= $element.find('.active');\n\t\t\t\t\tvar $nextElement = $rotateElementActive.next();\n\t\n\t\t\t\t\tif($nextElement.index() === -1) {\n\t\t\t\t\t\t$nextElement = $element.find('.rotate-element:first-child');\n\t\n\t\t\t\t\t\t$nextElement\n\t\t\t\t\t\t\t.addClass('active')\n\t\t\t\t\t\t\t.siblings()\n\t\t\t\t\t\t\t.removeClass('active');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$nextElement\n\t\t\t\t\t\t\t.addClass('active')\n\t\t\t\t\t\t\t.siblings()\n\t\t\t\t\t\t\t.removeClass('active');\n\t\t\t\t\t}\n\t\t\t\t}, duration);\n\t\t\t}\n\t\t}\n\t\trotateText($('.top-banner-message'), $('.top-banner-message').data('duration'));\n\n   \tif (window.innerWidth <= 767) {\n   \t\t$('.refinement h3.toggle.expanded:not(.selected), .refinement .refinement-body.toggle-content.expanded:not(.selected)').removeClass('expanded');\n   \t}\n   \n    // add generic toggle functionality\n    $('.toggle:not(.disabled)').not('.expanded').next('.toggle-content').hide();\n    $('.toggle:not(.disabled)').click(function () {\n        $(this).toggleClass('expanded').next('.toggle-content').toggle();\n    });\n\n    // subscribe email box\n    var $subscribeEmail = $('.subscribe-email');\n    if ($subscribeEmail.length > 0)    {\n        $subscribeEmail.focus(function () {\n            var val = $(this.val());\n            if (val.length > 0 && val !== Resources.SUBSCRIBE_EMAIL_DEFAULT) {\n                return; // do not animate when contains non-default value\n            }\n\n            $(this).animate({color: '#999999'}, 500, 'linear', function () {\n                $(this).val('').css('color', '#333333');\n            });\n        }).blur(function () {\n            var val = $.trim($(this.val()));\n            if (val.length > 0) {\n                return; // do not animate when contains value\n            }\n            $(this).val(Resources.SUBSCRIBE_EMAIL_DEFAULT)\n                .css('color', '#999999')\n                .animate({color: '#333333'}, 500, 'linear');\n        });\n    }\n\n    $('.privacy-policy').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href'),\n            options: {\n                height: 600\n            }\n        });\n    });\n\n\t$(\"#Mapmobile area\").click(function () {\n\t\t$(\"#store-name\").removeClass('storeheading');\n\t\tvar value = $(this).attr(\"href\");\n\t\tvar valueName = value.replace('#','');\n\t\t$('html,body').animate({\n\t\t\tscrollTop: $(\"a[name=\"+ valueName +\"]\").offset().top - 200\n\t\t})\n\t});\n    \n    $( \".user-info\" ).hover(\n    \t  function() {\n    \t\t $(this).addClass('active');\n    \t  },\n    \t  function() {\n    \t\t $(this).removeClass('active');\n    \t  }\n\n    );\n\n    var storesMediaQuery = matchMedia('(max-width: 1024px)');\n\tstoresMediaQuery.addListener(mobileStores);\n\t$(mobileStores);\n\n    $(document).on('click', '.detail-toggle-item', function(e) {\n        e.preventDefault();\n        \n        $(this).toggleClass('active');\n        $('.discount-details-entry').toggleClass('open').animate({ 'height': 'toggle', 'opacity': 'toggle' }, 250, null, function() {\n        \t\n        });\n    });\n\n\t// add show/hide password functionality\n\t$(document).on('click', '[data-action=\"toggle-password-visibility\"]', function(e) {\n\t\te.preventDefault();\n\t\tvar $button = $(e.target);\n\t\tvar $passwordInput = $button.closest('.password-holder').find('input');\n\t\tvar passwordInputType = $passwordInput.attr('type');\n\t\tif (passwordInputType === 'password') {\n\t\t\t$button.addClass('password-visibility--visible');\n\t\t\t$button.removeClass('password-visibility--invisible');\n\t\t\t$passwordInput.attr('type', 'text').focus();\n\t\t} else {\n\t\t\t$button.addClass('password-visibility--invisible');\n\t\t\t$button.removeClass('password-visibility--visible');\n\t\t\t$passwordInput.attr('type', 'password').focus();\n\t\t}\n\t});\n\t\n\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\tif ($('.cs-rewards-program').length >= 1) {\n\t\t\tif ($('.customer-rewards-number').length == 0) {\t\n\t\t\t\tBreadPayments.on(\"CARD:RECEIVE_APPLICATION_RESULT\", function(cardResult){\n\t\t\t\t\t// Handle Application Result\n\t\t\t\t\tswitch(cardResult.result){\n\t\t\t\t\t\tcase 'APPROVED':\n\t\t\t\t\t\tcase 'PENDING':\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t$.ajax({\n\t\t\t\t\t\t\t\ttype: 'post',\n\t\t\t\t\t\t\t\turl: Urls.createRewardsAccount,\n\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\t\t\t\t\temailAddress: cardResult.emailAddress,\n\t\t\t\t\t\t\t\t\tphoneNumber: cardResult.mobilePhone\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tsuccess: function (data) {\n\t\t\t\t\t\t\t\t\tconsole.log('Rewards account created.');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// BOOT-5363: show/hide total savings message based on promotion callout messages\n\t$('.product-tile').each(function() {\n\t\tvar $tile = $(this);\n\t\tif ($tile.find('.hide-total-savings').length > 0) {\n\t\t\t$tile.find('.product-total-savings').addClass('d-none');\n\t\t}\n\t});\n\tif($('.product-detail').find('.hide-total-savings').length > 0) {\n\t\t$('.product-total-savings').addClass('d-none');\n\t}\n}\n\n/**\n * @private\n * @function\n * @description Adds class ('js') to html for css targeting and loads js specific styles.\n */\nfunction initializeDom() {\n    // add class to html for css targeting\n    $('html').addClass('js');\n    // load js specific styles\n    util.limitCharacters();\n\n    // DOM EVENT FOR HEADER STORE LOCATOR\n\t$('.stores-near-content .list-stores').delegate( 'a.make-this-mystore', 'click',function(e){\n\t\te.preventDefault();\n\t\tvar postCode = $(this).attr('data-postalcode');\n\t\t$('a.ico-crosshairs-use-my-location').data('postalcode',postCode);\n\t\theaderNavStoreSearch();\n\t});\n\n}\n\n// Resize Helper\nfunction resizeDeviceHelper() {\n\tvar countryOutfitters = 'country_outfitters_us';\n\tvar bootBarn = 'bootbarn_us';\n\tvar sliderMobileSwiper;\n\n\t$('html').removeClass('size-mobile size-tablet size-desktop');\n\tif (window.innerWidth <= 767) {\n\t\t$('html').addClass('size-mobile');\n\t} else if (window.innerWidth <= 1024) {\n\t\t$('html').addClass('size-tablet');\n\t} else {\n\t\t$('html').addClass('size-desktop');\n\t}\n\t\n\tvar $navigationContainer = $('#navigation');\n\t\n\tif (!$('.second-mobnav').hasClass('active')) {\n\t\t$('.nav-utilities').hide();\n\t}\n\t\n\t$('.nav-utilities, #navigation').removeClass('preload');\n\t$('#nav-utils').removeClass('loadhide');\n\t\n\tif ((siteName != bootBarn && window.innerWidth <= 1024) || window.innerWidth <= 767) {\n\t\tif (siteName != SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t$navSecondary.insertAfter($navUl);\n\t\t}\n\n\t\t$sectionErrorFigure.insertBefore($sectionErrorBox);\n\t\t$navUtilities.insertAfter($topBannerInnerLinks);\n\t\tif ($sliderMobile.length > 0) {\n\t\t\tsliderMobileSwiper = sliders.init('.slider-mobile', {dots: true, loop: true});\n\t\t}\n\n\t\tvar image = $(\".slider-single-image img\");\n\t\t$.removeData(image, 'elevateZoom');\n\t\t$('.zoomContainer').remove();\n\t\t\n\t\tif($('.section-offers.all-on-sale').length){\n\t\t\tsetTimeout(function(){\n\t\t\t\t$('.section-offers.all-on-sale .chevron-collapse').each(function(){\n\t\t\t\t\t$(this).click();\n\t\t\t\t});\n\t\t\t}, 13);\n\t\t\t\n\t\t}\n\t\t$('.accordion-mobile').each(function () {\n\t\t\tvar accMobile = $(this);\n\n\t\t\tif (!accMobile.hasClass('active')) {\n\t\t\t\taccMobile.find('.accordion-mobile-body').hide();\n\t\t\t}\n\t\t});\n\t} else {\n\t\t$navUl.find('.has-dropdown.active').removeClass('active');\n\n\t\t$navUtilities.insertBefore($topBannerBarInner);\n\t\tif (siteName != SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t$navSecondary.prependTo($topBannerBar);\n\t\t}\n\n\t\t$sectionErrorFigure.insertAfter($sectionErrorBox);\n\t\t$navigation.removeAttr('style');\n\n\t\tif ($sliderMobile.length > 0) {\n\t\t\tif ($sliderMobile.find('.swiper-initialized').length > 0) {\n\t\t\t\tsliderMobileSwiper.destroy();\n\t\t\t}\n\t\t\tif ($sliderMobile.find('.slick-initialized').length > 0) {\n\t\t\t\t$sliderMobile.slick('unslick');\n\t\t\t}\n\t\t}\n\t\t$('.accordion-mobile-body').show();\n\t\t\n\t\t$('html').removeClass('menu-active');\n\t\t$('.menu-toggle').removeClass('active');\n\t\t$('#navigation .level-2').hide();\n\t}\n\t\n\tresizeLayoutHelper();\n}\n\nfunction resizeLayoutHelper() {\n\tvar newMarginTop = 0;\n\tvar innerWidthThreshold;\t\n\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\tinnerWidthThreshold = 1023;\n\t} else {\n\t\tinnerWidthThreshold = 767;\n\t}\n\tif (window.innerWidth <= innerWidthThreshold) {\n\t\tnewMarginTop = parseFloat($('.header-wrapper').outerHeight());\n\t}\n\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\tif (!$('html').hasClass('menu-active')) {\n\t\t\t$('#main').css('margin-top', newMarginTop);\n\t\t}\n\t} else {\n\t\tif (!$('html').hasClass('menu-active')) {\n\t\t\t$('#wrapper').css('margin-top', newMarginTop);\n\t\t}\n\t}\n\tif (!$('html').hasClass('initialized')) {\n\t\t$('html').addClass('initialized');\n\t}\n}\n\nfunction usemylocation(storeid) {\n\tvar t_url = Urls.usecurrentlocation;\n\tif (storeid === undefined) {\n\t\tstoreid = 'getall';\n\t}\n\n\t$.ajax({\n\t   url: t_url,\n\t   type: 'POST',\n\t   data: { 'source' : 'ajax' },\n\t   dataType: 'json',\n\t   error: function() {\n\t\t   console.log('error');\n\t   },\n\t   success: function(dataJson) {\n\t      if( 'stores' in dataJson && dataJson['stores'].length > 0 ) {\n\t    \t  \tif(storeid == 'getall') {\n\t    \t  \t\t$('.stores-near-content .stores-near-body ul.list-stores').html('');\n\t    \t  \t}\n\t\t\t\t$('div.stores-near-actions a.go-to-findstore').html(Resources.FIND_MORE_STORES);\n\t\t\t\tif ( dataJson['stores'].length == 1 ) {\n\t\t\t\t\t$('.stores-near-content').slideUp();\n\t\t\t\t}\n\t\t\t\tdataJson['stores'].forEach(function(element, index){\n\t\t\t\t\tvar store = element;\n\t\t\t\t\tvar htmlDisplay = '';\n\t\t\t\t\tvar storePhoneNumber = ('' + element['phone']).replace(/\\D/g,'');\n\t\t\t\t\tvar postalCodeVal = ( typeof element['postalCode'] != 'undefined' ? element['postalCode']  : '' );\n\n\t\t\t\t\tif(storeid == 'getall') {\n\t\t\t\t\t\tif(index == 0) {\n\t\t\t\t\t\t\thtmlDisplay += '<span class=\"red store-name-value\">'+element['name']+'</span>';\n\t\t\t\t\t\t\thtmlDisplay += element['address1'];\n\t\t\t\t\t\t\thtmlDisplay += '<br/>'+ ( typeof element['city'] != 'undefined' ? element['city'] +', ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += ( typeof element['stateCode'] != 'undefined' ? element['stateCode'] +' ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += postalCodeVal;\n\t\t\t\t\t\t\thtmlDisplay += '<br /><a href=\"tel:'+storePhoneNumber+'\">'+store['phone']+'</a>';\n\t\t\t\t\t\t\thtmlDisplay += '<span>'+unescape(store['storeHours'])+'</span>';\n\t\t\t\t\t\t\t$('.stores-dropdown .current-store address').html(htmlDisplay);\n\t\t\t\t\t\t\t$('.stores-dropdown .current-store').slideDown();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thtmlDisplay += '<li><h5><span>'+element['name']+'</span><a href=\"#\" class=\"make-this-mystore\" id=\"' + element['ID'] + '\" data-postalcode=\"'+postalCodeVal+'\">'+Resources.MAKE_THIS_MYSTORE+'</a></h5>';\n\t\t\t\t\t\t\thtmlDisplay += '<address>'+element['address1'];\n\t\t\t\t\t\t\thtmlDisplay += '<br/>'+ ( typeof element['city'] != 'undefined' ? element['city'] +', ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += ( typeof element['stateCode'] != 'undefined' ? element['stateCode'] +' ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += postalCodeVal;\n\t\t\t\t\t\t\thtmlDisplay += '<br /><a href=\"tel:'+storePhoneNumber+'\">'+store['phone']+'</a>';\n\t\t\t\t\t\t\thtmlDisplay += '/<address>' + unescape(store['storeHours']);\n\t\t\t\t\t\t\thtmlDisplay += '</li>';\n\t\t\t\t\t\t\t$('.stores-near-content .stores-near-body ul.list-stores').append($(htmlDisplay));\n\t\t\t\t\t\t\t$('.stores-near-content').slideDown();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif(storeid == element['ID']) {\n\t\t\t\t\t\t\thtmlDisplay += '<span class=\"red store-name-value\">'+element['name']+'</span>';\n\t\t\t\t\t\t\thtmlDisplay += element['address1'];\n\t\t\t\t\t\t\thtmlDisplay += '<br/>'+ ( typeof element['city'] != 'undefined' ? element['city'] +', ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += ( typeof element['stateCode'] != 'undefined' ? element['stateCode'] +' ' : '' );\n\t\t\t\t\t\t\thtmlDisplay += postalCodeVal;\n\t\t\t\t\t\t\thtmlDisplay += '<br /><a href=\"tel:'+storePhoneNumber+'\">'+store['phone']+'</a>';\n\t\t\t\t\t\t\thtmlDisplay += '<span>'+unescape(store['storeHours'])+'</span>';\n\t\t\t\t\t\t\t$('.stores-dropdown .current-store address').html(htmlDisplay);\n\t\t\t\t\t\t\t$('.stores-dropdown .current-store').slideDown();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t$('.stores-near-content').slideUp();\n\t\t\t\t$('div.stores-near-actions a.go-to-findstore').html(Resources.FIND_STORES);\n\t\t\t\t$('.stores-dropdown .current-store').slideUp();\n\t\t\t\tif ( $('.stores-dropdown h3.no_results').length == 0 ) {\n\t\t\t\t\t$('.stores-dropdown').prepend('<h3 class=\"no_results\">'+Resources.NO_STORE_RESULTS+'</h3>');\n\t\t\t\t} else {\n\t\t\t\t\t$('.stores-dropdown h3.no_results').fadeIn();\n\t\t\t\t}\n\t\t\t\t$('.stores-dropdown h3.no_results').show().delay(2000).fadeOut();\n\t\t  }\n\t   }\n\t});\n}\n\n\n/** \n *\n * Moves customer specific stores info in main header to mobile utility header.\n * This is needed because the store info is part of a remote include in another spot on desktop. \n *\n */\nfunction mobileStores() {\t\n\tvar $mobileStoreMetadata = $('#mobile-storeMetadata');\n\tvar $mobileStoreBannerText = $('#mobile-banner-store-text');\n\t\n\tif ($mobileStoreMetadata !== undefined && $mobileStoreMetadata != null && $mobileStoreMetadata.length  > 0){\n\t\tif ($mobileStoreBannerText !== undefined && $mobileStoreBannerText != null && $mobileStoreBannerText.length  > 0){\n\t\t\tvar isOpen = $mobileStoreMetadata.data('is-open');\n\t\t\tif (isOpen){\n\t\t\t\tvar storeName = $mobileStoreMetadata.data('store-name');\n\t\t\t\tvar openUntil =  $mobileStoreMetadata.data('open-until');\n\t\t\t\tvar closingTime =  $mobileStoreMetadata.data('closing-time');\n\t\t\t\tvar bannerText = storeName + ' &#8226; ' + openUntil + ' ' + closingTime;\n\t\t\t\t$mobileStoreBannerText.html(bannerText);\t\n\t\t\t} else {\n\t\t\t\tvar closedText =  $mobileStoreMetadata.data('closed-text');\n\t\t\t\t$mobileStoreBannerText.html(closedText);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction setCookie(cname, cvalue, exdays) {\n\tvar d = new Date();\n\td.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));\n\tvar expires = \"expires=\"+d.toUTCString();\n\tdocument.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n  }\n  \n  function getCookie(cname) {\n\tvar name = cname + \"=\";\n\tvar ca = document.cookie.split(';');\n\tfor(var i = 0; i < ca.length; i++) {\n\t  var c = ca[i];\n\t  while (c.charAt(0) == ' ') {\n\t\tc = c.substring(1);\n\t  }\n\t  if (c.indexOf(name) == 0) {\n\t\treturn c.substring(name.length, c.length);\n\t  }\n\t}\n\treturn \"\";\n  }\n\n\n\nfunction addPromotionDataLayers() {\n\tvar $containers = $('.accordion:visible, .section-offers:visible, .cat-header-content.cat-header-slider:visible');\n\tif ($containers.length > 0) {\n\t\t$containers.each(function() {\n\t\t\tvar $container = $(this);\n\t\t\tif ($container.attr('data-layer-added') != 'true' && $container.find('.product-tile').length > 0) {\n\t\t\t\tvar containerId = $container.attr('content-slot-id') || $container.attr('id');\n\n\t\t\t\tvar dataObject = {\n\t\t\t\t\tpromotion_name: containerId\n\t\t\t\t}\n\n\t\t\t\tvar pageType;\n\t\t\t\tvar $wrapper = $container.closest('.add-to-cart-modal');\n\t\t\t\tif ($wrapper.length > 0) {\n\t\t\t\t\tpageType = 'addtocartmodal';\n\t\t\t\t}\n\n\t\t\t\tif (!pageType) {\n\t\t\t\t\t$wrapper = $('#wrapper');\n\t\t\t\t\tif ($wrapper.length > 0) {\n\t\t\t\t\t\tif (pageContext && pageContext.type) {\n\t\t\t\t\t\t\tswitch (pageContext.type) {\n\t\t\t\t\t\t\t\tcase 'storefront':\n\t\t\t\t\t\t\t\tpageType = 'Homepage';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'search':\n\t\t\t\t\t\t\t\tpageType = 'PLP';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'product':\n\t\t\t\t\t\t\t\tpageType = 'PDP';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'cart':\n\t\t\t\t\t\t\t\tpageType = 'Cart';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'onepcheckout':\n\t\t\t\t\t\t\t\tcase 'onepcheckout_groups':\n\t\t\t\t\t\t\t\tpageType = 'Checkout';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'orderconfirmation':\n\t\t\t\t\t\t\t\tpageType = 'Order Confirmation';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'customerservice':\n\t\t\t\t\t\t\t\tpageType = 'Customer Service';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'account':\n\t\t\t\t\t\t\t\tpageType = 'Account';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'content':\n\t\t\t\t\t\t\t\tpageType = 'Content Page';\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 'error':\n\t\t\t\t\t\t\t\tpageType = 'Error Page';\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pageType) {\n\t\t\t\t\tdataObject.promotion_id = pageType;\n\t\t\t\t}\n\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ViewPromotion', dataObject, { Container: $container });\n\t\t\t\t$container.attr('data-layer-added', true);\n\t\t\t}\n\t\t});\n\t}\n}\n\nvar pages = {\n\tstorefront: require('./pages/storefront'),\n\taccount: require('./pages/account'),\n\tbootbarnexpress: require('./pages/bootbarnexpress'),\n\tbootfinder: require('./pages/bootfinder'),\n    cart: require('./pages/cart'),\n\tcart_echo: require('./pages/cart_echo'),\n    checkout: require('./pages/checkout'),\n\tcheckout_echo: require('../../../app_storefront_core/cartridge/js/pages/checkout_echo'),\n    compare: require('./pages/compare'),\n    product: require('./pages/product'),\n    registry: require('./pages/registry'),\n    search: require('./pages/search'),\n    storelocator: require('./pages/storelocator'),\n    onepcheckout: require('./pages/onepcheckout'),\n    onepcheckout_groups: require('./pages/onepcheckout_groups'),\n\torderconfirmation: require('./pages/orderconfirmation'),\n    categorylanding: require('./pages/categorylanding'),\n    content: require('./pages/content'),\n    authentication_EmailAddressCapture: require('./pages/Authentication/EmailAddressCapture') \n};\n\nvar lastScrollTop = 0; \nvar scrollDelta = 100;\nvar fixedHeaderLimit = 800;\nvar headerWrapper = $('.header-wrapper');\n\nvar app = {\n    init: function () {\n\t\t$.extend(page, window.pageContext);\n\n    \t$sliderMobile = $('.slider-mobile');\n\t\t$navSecondary \t\t\t= $('.nav-secondary');\n\t\t$navUtilities \t\t\t= $('.nav-utilities');\n\t\t$navUl \t\t\t\t\t= $('#navigation > ul');\n\t\t$topBannerBar \t\t\t= $('.top-banner-bar');\n\t\t$topBannerBarInner\t\t= $('.top-banner-bar-inner');\n\t\t$navigation \t\t\t= $('#navigation');\n\t\t$topBannerInnerLinks \t= $('.top-banner-inner-links');\n\t\t$selectSort \t\t\t= $('#sort-by');\n\t\t$secondaryHead \t\t\t= $('#secondary .refinements-head');\n\t\t$searchResultContainer \t= $('#search-result');\n\t\t$productContainerImage\t= $('#pdpMain .product-image-container');\n\t\t$productDetail\t\t\t= $('#pdpMain .product-detail');\n\t\t$sectionCheckout \t\t= $('.section-checkout');\n\t\t$mainInnerAlt\t\t\t= $('.main-inner-alt');\n\t\t$sectionErrorFigure \t= $('.section-error figure');\n\t\t$sectionErrorBox \t\t= $('.section-error .box');\n\t\t$footerMenuItems\t\t= $('.footer-item .content-asset');\n\t\t$promoMessages\t\t= $productContainerImage.find('.promo-messages');\n    \tsiteName = pageContext.site || '';\n    \twindow.sgDialog = require('./dialog');\n    \twindow.sgUtil = require('./util');\n    \t\n        if (document.cookie.length === 0) {\n            $('<div/>').addClass('browser-compatibility-alert cookies').append($('<p/>').addClass('browser-error').html(Resources.COOKIES_DISABLED)).appendTo('#browser-check');\n            $('.browser-compatibility-alert.cookies').prepend('<i class=\"fa fa-exclamation-triangle fa-3x pull-left\"></i>');\n        }\n        initializeDom();\n        initializeEvents();\n        \n\t\tlogin.init(page.options);\n\t\tregister.init();\n        navigation.Initialize();\n        countries.init();\n        //tooltip.init();\n        minicart.init();\n        validator.init();\n        rating.init();\n        searchplaceholder.init();\n\t\trotate3d.init();\n        count_down.init();\n        lazyloadPageElements.init();\n        giftCardBalanceInquiryHelper.initializeAllFoundComponents();\n\t\tslickHelpers.init();\n\t\tif (pageContext && 'type' in pageContext && pageContext.type != 'cart' && pageContext.type != 'onepcheckout' && pageContext.type != 'onepcheckout_groups') {\n            quantityStepper.init();\n        }\n\t\twishlist.init();\n\t\tGlobale.initialize();\n\t\t\n        // execute page specific initializations\n        \n        var ns = page.ns;\n        if (ns && pages[ns] && pages[ns].init) {\n            pages[ns].init(page.options || {});\n        }\n\n        GoogleTagManagerClient.PushDataLayerForPage(page);\n        EmailSignup.Initialize(page);\n        \n        // Check TLS status if indicated by site preference\n        if (SitePreferences.CHECK_TLS === true) {\n            tls.getUserAgent();\n\t\t}\n\n        // Initialize Sticky header events\n        $(window).scroll(function(event){\n\t\t\tif ((siteName == SiteConstants.SiteIds.BootBarnUS || siteName == SiteConstants.SiteIds.SheplersUS) && window.innerWidth <= 1023) {\n\t\t\t\tif ($(window).scrollTop() > fixedHeaderLimit) {\n\t\t\t\t\theaderWrapper.addClass('header-fixed');\n\t\t\t\t} else {\n\t\t\t\t\theaderWrapper.removeClass('header-fixed');\n\t\t\t\t}\n\n\t\t\t\tvar nowScrollTop = $(this).scrollTop();\n\t\t\t\tif(Math.abs(lastScrollTop - nowScrollTop) >= scrollDelta){\n\t\t\t\t\tif (nowScrollTop > lastScrollTop){\n\t\t\t\t\t\tif (headerWrapper.hasClass('header-fixed-active')) {\n\t\t\t\t\t\t\theaderWrapper.removeClass('header-fixed-active');\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ($(window).scrollTop() > fixedHeaderLimit) {\n\t\t\t\t\t\t\tif (!headerWrapper.hasClass('header-fixed-active')) {\n\t\t\t\t\t\t\t\theaderWrapper.addClass('header-fixed-active');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\theaderWrapper.removeClass('header-fixed-active');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlastScrollTop = nowScrollTop;\n\t\t \t\t}\n\t\t\t}\n\n\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS && $('html').hasClass('size-tablet') && window.innerWidth == 1024) {\n\t\t\t\tvar nowScrollTop = $(this).scrollTop();\n\t\t\t\tif(Math.abs(nowScrollTop) > 300) {\n\t\t\t\t\tif ($('#navigation .has-dropdown').hasClass('active')) {\n\t\t\t\t\t\t$('#navigation .has-dropdown').removeClass('active');\n\t\t\t\t\t\t$('html').removeClass('menu-active');\n\t\t\t\t\t\t$('.header-wrapper .top-banner').removeClass('nav-active');\n\t\t\t\t\t\t$('html').removeClass('desktop-nav-active');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( $(\".top-banner-inner .primary-logo a img.mobile-logo[src*=sheplers_us]\").length ) {\n\t            if ( $(\".second-mobnav\").length > 0 && $(\".second-mobnav\").is(\":visible\") ) {\n\t                var st = $(this).scrollTop();\n\t                \n\t                if (st > 0) {\n\t                    $(\".top-banner-bar .shell\").hide();\n\t                    $(\".top-banner div.top-banner-inner\").css(\"margin-top\",\"0px\");\n\t                    $(\".top-banner div.top-banner-bar .header-search\").attr(\"style\",\"top:55px !important\");\n\t                } else {\n\t                    $(\".top-banner-bar .shell\").show();\n\t                    $(\".top-banner div.top-banner-inner\").css(\"margin-top\",\"25px\");\n\t                    $(\".top-banner div.top-banner-bar .header-search\").attr(\"style\",\"top:80px !important\");\n\t                }\n\t            } else {\n\t            \t\t$(\".top-banner-bar .shell\").show();\n\t            \t\t$(\".top-banner div.top-banner-inner\").css(\"margin-top\",\"0px\");\n\t            \t\t$(\".top-banner div.top-banner-bar .header-search\").attr(\"style\",\"top:80px !important\");\n\t            \t\tif ( $(\".top-banner-bar-aside #second-mobnav\").length ) {\n\t            \t\t\t$(\".top-banner-bar-aside #second-mobnav\").show();\n\t            \t\t}\n\t            }\n\t\t\t}\n        });\n\n\t\tresizeDeviceHelper();\n    }\n};\n\n// general extension functions\n(function () {\n    String.format = function () {\n        var s = arguments[0];\n        var i, len = arguments.length - 1;\n        for (i = 0; i < len; i++) {\n            var reg = new RegExp('\\\\{' + i + '\\\\}', 'gm');\n            s = s.replace(reg, arguments[i + 1]);\n        }\n        return s;\n    };\n})();\n\n// initialize app\n$(document).ready(function () {\n    app.init();\n});\n\n(function () {\n String.format = function () {\n     var s = arguments[0];\n     var i, len = arguments.length - 1;\n     for (i = 0; i < len; i++) {\n         var reg = new RegExp('\\\\{' + i + '\\\\}', 'gm');\n         s = s.replace(reg, arguments[i + 1]);\n     }\n     return s;\n };\n})();\n","'use strict';\n\nvar dialog = require('./dialog'),\n    page = require('./page'),\n    util = require('./util');\n\nvar selectedList = [];\nvar maxItems = 1;\nvar bliUUID = '';\n\n/**\n * @private\n * @function\n * description Gets a list of bonus products related to a promoted product\n */\nfunction getBonusProducts() {\n    var bonusproducts = [];\n\n    var i, len;\n    for (i = 0, len = selectedList.length; i < len; i++) {\n        var p = {\n            pid: selectedList[i].pid,\n            qty: selectedList[i].qty,\n            options: {}\n        };\n        var a, alen, bp = selectedList[i];\n        if (bp.options) {\n            for (a = 0, alen = bp.options.length; a < alen; a++) {\n                var opt = bp.options[a];\n                p.options = {optionName:opt.name, optionValue:opt.value};\n            }\n        }\n        bonusproducts.push({product:p});\n    }\n    return {bonusproducts: bonusproducts};\n}\n\nvar selectedItemTemplate = function (data) {\n    var attributes = '';\n    for (var attrID in data.attributes) {\n        var attr = data.attributes[attrID];\n        attributes += '<li data-attribute-id=\"' + attrID + '\">\\n';\n        attributes += '<span class=\"display-name\">' + attr.displayName + '</span>: ';\n        attributes += '<span class=\"display-value\">' + attr.displayValue + '</span>\\n';\n        attributes += '</li>';\n    }\n    attributes += '<li class=\"item-qty\">\\n';\n    attributes += '<span class=\"display-name\">Qty</span>: ';\n    attributes += '<span class=\"display-value\">' + data.qty + '</span>';\n    return [\n        '<li class=\"selected-bonus-item\" data-uuid=\"' + data.uuid + '\" data-pid=\"' + data.pid + '\">',\n        '<i class=\"remove-link fa fa-remove\" title=\"Remove this product\" href=\"#\"></i>',\n        '<div class=\"item-name\">' + data.name + '</div>',\n        '<ul class=\"item-attributes\">',\n        attributes,\n        '<ul>',\n        '<li>'\n    ].join('\\n');\n};\n\n// hide swatches that are not selected or not part of a Product Variation Group\nvar hideSwatches = function () {\n    $('.bonus-product-item:not([data-producttype=\"master\"]) .swatches li').not('.selected').not('.variation-group-value').hide();\n    // prevent unselecting the selected variant\n    $('.bonus-product-item .swatches .selected').on('click', function () {\n        return false;\n    });\n};\n\n/**\n * @private\n * @function\n * @description Updates the summary page with the selected bonus product\n */\nfunction updateSummary() {\n    var $bonusProductList = $('#bonus-product-list');\n    if (!selectedList.length) {\n        $bonusProductList.find('li.selected-bonus-item').remove();\n    } else {\n        var ulList = $bonusProductList.find('ul.selected-bonus-items').first();\n        var i, len;\n        for (i = 0, len = selectedList.length; i < len; i++) {\n            var item = selectedList[i];\n            var li = selectedItemTemplate(item);\n            $(li).appendTo(ulList);\n        }\n    }\n\n    // get remaining item count\n    var remain = maxItems - selectedList.length;\n    $bonusProductList.find('.bonus-items-available').text(remain);\n    if (remain <= 0) {\n        $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n    } else {\n        $bonusProductList.find('.select-bonus-item').removeAttr('disabled');\n    }\n    $(document).trigger('update-summary');\n}\n\nfunction initializeGrid () {\n    var $bonusProduct = $('#bonus-product-dialog'),\n        $bonusProductList = $('#bonus-product-list'),\n        bliData = $bonusProductList.data('line-item-detail');\n    maxItems = bliData.maxItems;\n    bliUUID = bliData.uuid;\n\n    if (bliData.itemCount >= maxItems) {\n        $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n    }\n\n    var cartItems = $bonusProductList.find('.selected-bonus-item');\n    cartItems.each(function () {\n        var ci = $(this);\n        var product = {\n            uuid: ci.data('uuid'),\n            pid: ci.data('pid'),\n            qty: ci.find('.item-qty').text(),\n            name: ci.find('.item-name').html(),\n            attributes: {}\n        };\n        var attributes = ci.find('ul.item-attributes li');\n        attributes.each(function () {\n            var li = $(this);\n            product.attributes[li.data('attributeId')] = {\n                displayName:li.children('.display-name').html(),\n                displayValue:li.children('.display-value').html()\n            };\n        });\n        selectedList.push(product);\n    });\n\n    $bonusProductList.on('click', '.bonus-product-item a[href].swatchanchor', function (e) {\n        e.preventDefault();\n        var url = this.href,\n            $this = $(this);\n        url = util.appendParamsToUrl(url, {\n            'source': 'bonus',\n            'format': 'ajax'\n        });\n        $.ajax({\n            url: url,\n            success: function (response) {\n                $this.closest('.bonus-product-item').empty().html(response);\n                hideSwatches();\n            }\n        });\n    })\n    .on('change', '.input-text', function () {\n        $bonusProductList.find('.select-bonus-item').removeAttr('disabled');\n        $(this).closest('.bonus-product-form').find('.quantity-error').text('');\n    })\n    .on('click', '.select-bonus-item', function (e) {\n        e.preventDefault();\n        if (selectedList.length >= maxItems) {\n            $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n            $bonusProductList.find('.bonus-items-available').text('0');\n            return;\n        }\n\n        var form = $(this).closest('.bonus-product-form'),\n            detail = $(this).closest('.product-detail'),\n            uuid = form.find('input[name=\"productUUID\"]').val(),\n            qtyVal = form.find('input[name=\"Quantity\"]').val(),\n            qty = (isNaN(qtyVal)) ? 1 : (+qtyVal);\n\n        if (qty > maxItems) {\n            $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n            form.find('.quantity-error').text(Resources.BONUS_PRODUCT_TOOMANY);\n            return;\n        }\n\n        var product = {\n            uuid: uuid,\n            pid: form.find('input[name=\"pid\"]').val(),\n            qty: qty,\n            name: detail.find('.product-name').text(),\n            attributes: detail.find('.product-variations').data('attributes'),\n            options: []\n        };\n\n        var optionSelects = form.find('.product-option');\n\n        optionSelects.each(function () {\n            product.options.push({\n                name: this.name,\n                value: $(this).val(),\n                display: $(this).children(':selected').first().html()\n            });\n        });\n        selectedList.push(product);\n        updateSummary();\n    })\n    .on('click', '.remove-link', function (e) {\n        e.preventDefault();\n        var container = $(this).closest('.selected-bonus-item');\n        if (!container.data('uuid')) { return; }\n\n        var uuid = container.data('uuid');\n        var i, len = selectedList.length;\n        for (i = 0; i < len; i++) {\n            if (selectedList[i].uuid === uuid) {\n                selectedList.splice(i, 1);\n                break;\n            }\n        }\n        updateSummary();\n    })\n    .on('click', '.add-to-cart-bonus', function (e) {\n        e.preventDefault();\n        var url = util.appendParamsToUrl(Urls.addBonusProduct, {bonusDiscountLineItemUUID: bliUUID});\n        var bonusProducts = getBonusProducts();\n        if (bonusProducts.bonusproducts[0].product.qty > maxItems) {\n            bonusProducts.bonusproducts[0].product.qty = maxItems;\n        }\n        // make the server call\n        $.ajax({\n            type: 'POST',\n            dataType: 'json',\n            cache: false,\n            contentType: 'application/json',\n            url: url,\n            data: JSON.stringify(bonusProducts)\n        })\n        .done(function () {\n            // success\n            page.refresh();\n        })\n        .fail(function (xhr, textStatus) {\n            // failed\n            if (textStatus === 'parsererror') {\n                window.alert(Resources.BAD_RESPONSE);\n            } else {\n                window.alert(Resources.SERVER_CONNECTION_ERROR);\n            }\n        })\n        .always(function () {\n            $bonusProduct.dialog('close');\n        });\n    })\n    .on('click', '#more-bonus-products', function (e) {\n        e.preventDefault();\n        var uuid = $('#bonus-product-list').data().lineItemDetail.uuid;\n\n        //get the next page of choice of bonus products\n        var lineItemDetail = JSON.parse($('#bonus-product-list').attr('data-line-item-detail'));\n        lineItemDetail.pageStart = lineItemDetail.pageStart + lineItemDetail.pageSize;\n        $('#bonus-product-list').attr('data-line-item-detail', JSON.stringify(lineItemDetail));\n\n        var url = util.appendParamsToUrl(Urls.getBonusProducts, {\n            bonusDiscountLineItemUUID: uuid,\n            format: 'ajax',\n            lazyLoad: 'true',\n            pageStart: lineItemDetail.pageStart,\n            pageSize: $('#bonus-product-list').data().lineItemDetail.pageSize,\n            bonusProductsTotal: $('#bonus-product-list').data().lineItemDetail.bpTotal\n        });\n\n        $.ajax({\n            type: 'GET',\n            cache: false,\n            contentType: 'application/json',\n            url: url\n        })\n        .done(function (data) {\n            //add the new page to DOM and remove 'More' link if it is the last page of results\n            $('#more-bonus-products').before(data);\n            if ((lineItemDetail.pageStart + lineItemDetail.pageSize) >= $('#bonus-product-list').data().lineItemDetail.bpTotal) {\n                $('#more-bonus-products').remove();\n            }\n        })\n        .fail(function (xhr, textStatus) {\n            if (textStatus === 'parsererror') {\n                window.alert(Resources.BAD_RESPONSE);\n            } else {\n                window.alert(Resources.SERVER_CONNECTION_ERROR);\n            }\n        });\n    });\n}\n\nvar bonusProductsView = {\n    /**\n     * @function\n     * @description Open the list of bonus products selection dialog\n     */\n    show: function (url) {\n        var $bonusProduct = $('#bonus-product-dialog');\n        // create the dialog\n        dialog.open({\n            target: $bonusProduct,\n            url: url,\n            options: {\n                width: 795,\n                title: Resources.BONUS_PRODUCTS\n            },\n            callback: function () {\n                initializeGrid();\n                hideSwatches();\n            }\n        });\n    },\n    /**\n     * @function\n     * @description Open bonus product promo prompt dialog\n     */\n    loadBonusOption: function () {\n        var    self = this,\n            bonusDiscountContainer = document.querySelector('.bonus-discount-container');\n        if (!bonusDiscountContainer) { return; }\n\n        // get the html from minicart, then trash it\n        var bonusDiscountContainerHtml = bonusDiscountContainer.outerHTML;\n        bonusDiscountContainer.parentNode.removeChild(bonusDiscountContainer);\n\n        dialog.open({\n            html: bonusDiscountContainerHtml,\n            options: {\n                width: 400,\n                title: Resources.BONUS_PRODUCT,\n                buttons: [{\n                    text: Resources.SELECT_BONUS_PRODUCTS,\n                    click: function () {\n                        var uuid = $('.bonus-product-promo').data('lineitemid'),\n                            url = util.appendParamsToUrl(Urls.getBonusProducts, {\n                                bonusDiscountLineItemUUID: uuid,\n                                source: 'bonus',\n                                format: 'ajax',\n                                lazyLoad: 'false',\n                                pageStart: 0,\n                                pageSize: 10,\n                                bonusProductsTotal: -1\n                            });\n                        $(this).dialog('close');\n                        self.show(url);\n                    }\n                }, {\n                    text: Resources.NO_THANKS,\n                    click: function () {\n                        $(this).dialog('close');\n                    }\n                }]\n            },\n            callback: function () {\n                // show hide promo details\n                $('.show-promo-details').on('click', function () {\n                    $('.promo-details').toggleClass('visible');\n                });\n            }\n        });\n    }\n};\n\nmodule.exports = bonusProductsView;\n","'use strict';\n\nvar _ = require('lodash');\nvar addToCartOptionsStoreSearch = require('./AddToCartOptionsStoreSearch');\nvar dialog = require('../../dialog');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar LocalDeliveryDialog = require('./LocalDeliveryDialog');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar util = require('../../util');\nvar tooltip = require('../../tooltip');\n\nexports.initialize = initialize;\n\nvar options;\nvar optionsStoreSearch;\nvar optionsLocalDelivery;\nvar dataBuffer;\nvar storeSearch;\nvar localDeliveryStoreSearch;\n\nvar resultContainerTemplate;\nvar resultItemTemplate;\nvar localDeliveryDecorator;\n\nvar $container;\nvar $storeSearchButton;\nvar $storeSearchButtonContainer;\nvar $addToCartOptions;\nvar $bopisButton;\n\nfunction initialize($containerParameter, optionsParameter) {\n\tdataBuffer = {};\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\n\tvar selectedSize;\n\tvar $selectedSizeInDropdown = $('div.product-variations .size.size-options li.selected');\n\tvar $selectedLength = $('div.product-variations .length.length-options li.selected');\n\tvar $selectedWidth = $('div.product-variations .width.width-options li.selected');\n\tif ($selectedLength.length && $selectedWidth.length) {\n\t\tselectedSize = $selectedLength.find('[data-length-name]').attr('data-length-name') + ' ' + $selectedWidth.find('[data-width-name]').attr('data-width-name');\n\t} else if ($selectedSizeInDropdown.length > 0) {\n\t\tselectedSize = $selectedSizeInDropdown.find('[data-size-name]').attr('data-size-name');\n\t} else {\n\t\tselectedSize = util.getPreferenceValueFromWindowLocation('size');\n\t}\n\tstoreSearch = new addToCartOptionsStoreSearch();\n\tlocalDeliveryStoreSearch = new addToCartOptionsStoreSearch();\n\toptionsStoreSearch = Object.assign(options);\n\toptionsLocalDelivery = Object.assign({\n\t\tLocalDeliveryOnly: true,\n\t\tEvents: {\n\t\t\tSelectStore: 'Bopis.LocalDelivery.StoreSelect'\n\t\t},\n\t\tFunctions: {\n\t\t\tClose: function() {\n\t\t\t\t$('.dialog-bopis-options').removeClass('hidden');\n\t\t\t\t$('.ui-widget-overlay').removeClass('hidden');\n\t\t\t\t$('.bopis-local-delivery-store-search-container').removeClass('show');\n\t\t\t}\n\t\t},\n\t}, options);\n\n\tresultContainerTemplate = _.template($('#template-bopis-result-container').html(), TemplateConstants.Lodash.Settings);\n\tresultItemTemplate = _.template($('#template-bopis-result-item').html(), TemplateConstants.Lodash.Settings);\n\tlocalDeliveryDecorator = _.template($('#template-bopis-localdelivery-decorator').html(), TemplateConstants.Lodash.Settings);\n\n\t$container = $containerParameter;\n\t$storeSearchButton = $container.find('.btn.store-search');\n\t$storeSearchButtonContainer = $container.find('.btn-store-search-container');\n\t$bopisButton = $container.find('.btn.bopis');\n\n\t$addToCartOptions = $container.find('.bopis-add-to-cart-options');\n\t$addToCartOptions.attr('state', 'form');\n\tinitializeTooltips(selectedSize);\n\n\t$(document).off('click.SearchByStore.Display').on('click.SearchByStore.Display', '.bopis-add-to-cart-options-container .search-store:not(.disabled)', function(event) {\n\t\tevent.preventDefault();\n\t\tevent.stopImmediatePropagation();\n\n\t\tvar sizeSelected = $('div.product-variations .size.size-options li.selected').length;\n\t\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\t\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\t\tvar colorSelected = $('div.product-variations .color.color-options li.selected').length;\n\t\tvar isSizeSelected = (sizeSelected || (lengthSelected && widthSelected)) && colorSelected;\n\n\t\tif (options.StoreUIVersion != '2024Redesign') {\n\t\t\tif (!isSizeSelected && !colorSelected) {\n\t\t\t\tdialog.open({\n\t\t\t\t\thtml: 'Please select a size and color.',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tdialogClass: 'dialog-alert',\n\t\t\t\t\t\tdraggable: false\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t} else if (!isSizeSelected) {\n\t\t\t\tdialog.open({\n\t\t\t\t\thtml: 'Please select a size',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tdialogClass: 'dialog-alert',\n\t\t\t\t\t\tdraggable: false\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t} else if (!colorSelected) {\n\t\t\t\tdialog.open({\n\t\t\t\t\thtml: 'Please select a color',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tdialogClass: 'dialog-alert',\n\t\t\t\t\t\tdraggable: false\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif ($container.find('input[name=\"AddToCartOption\"]:checked').val() == 'delivery') {\n\t\t\tlocalDeliveryStoreSearch.initialize($('.bopis-local-delivery-store-search-container'), optionsLocalDelivery);\n\t\t} else {\n\t\t\tstoreSearch.initialize($('.bopis-add-to-cart-store-search-container'), optionsStoreSearch);\n\t\t}\n    });\n\n\t$(document).off('click.SearchByZipCode.Display').on('click.SearchByZipCode.Display', '.bopis-add-to-cart-options .search-zipcode:not(.disabled)', function (event) {\n\t\tevent.preventDefault();\n\t\tevent.stopImmediatePropagation();\n\n\t\tlocalDeliveryStoreSearch.initialize($('.bopis-local-delivery-store-search-container'), optionsLocalDelivery);\n    });\n\n\t$(document).off('Bopis.LocalDelivery.StoreSelect').on('Bopis.LocalDelivery.StoreSelect', function (event, store) {\n\t\t$.ajax({\n\t\t\tmethod: 'GET',\n\t\t\turl: Urls.Bopis.GetLocalDeliveryFormData,\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(localDeliveryFormData) {\n\t\t\t\tLocalDeliveryDialog.initialize(optionsLocalDelivery, store, localDeliveryFormData);\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tLocalDeliveryDialog.initialize(optionsLocalDelivery, store);\n\t\t\t}\n\t\t});\n\t});\n\n\t$(document).off('Bopis.LocalDelivery.Display').on('Bopis.LocalDelivery.Display', function (event, data) {\n\t\tvar $storeData = $container.find('.selected-store[store-data]');\n\t\tif ($storeData.length > 0) {\n\t\t\tif (data) {\n\t\t\t\toptionsLocalDelivery = $.extend(optionsLocalDelivery, data);\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'GET',\n\t\t\t\turl: Urls.Bopis.GetLocalDeliveryFormData,\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(localDeliveryFormData) {\n\t\t\t\t\tLocalDeliveryDialog.initialize(optionsLocalDelivery, JSON.parse($storeData.attr('store-data')), localDeliveryFormData);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tLocalDeliveryDialog.initialize(optionsLocalDelivery, JSON.parse($storeData.attr('store-data')));\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t\n\t$(document).off('Bopis.StoreSearch.Select').on('Bopis.StoreSearch.Select', function (event, storeId) {\n\t\tdataBuffer['SelectedLocation'] = storeId;\n\t\tredraw(true);\n\t});\n\n\t$(document).off('click.Store.Select').on('click.Store.Select', '.bopis-add-to-cart-options-container .select-store', function(event) {\n\t\tdataBuffer['SelectedLocation'] = $(this).closest('[store-id]').attr('store-id');\n\t\tredraw(true);\n\t});\n\n\t$(document).off('ProductDetailPage.Variant.AddToCartOptions').on('ProductDetailPage.Variant.AddToCartOptions', function() {\n\t\tredraw();\n\t});\n\n\tdataBuffer['SelectedLocation'] = options.SelectedLocations;\n}\n\nfunction redraw(saveSelectedLocation) {\n\tvar selectedColor;\n\tvar $selectedColorInSwatch = $('div.product-variations .color.color-options li.selected');;\n\tif ($selectedColorInSwatch.length > 0) {\n\t\tselectedColor = $selectedColorInSwatch.find('[data-color-name]').attr('data-color-id');\n\t} else {\n\t\tselectedColor = util.getPreferenceValueFromWindowLocation('color');\n\t}\n\n\tvar selectedSize;\n\tvar $selectedSizeInDropdown = $('div.product-variations .size.size-options li.selected');\n\tvar $selectedLength = $('div.product-variations .length.length-options li.selected');\n\tvar $selectedWidth = $('div.product-variations .width.width-options li.selected');\n\tif ($selectedLength.length && $selectedWidth.length) {\n\t\tselectedSize = $selectedLength.find('[data-length-name]').attr('data-length-name') + ' ' + $selectedWidth.find('[data-width-name]').attr('data-width-name');\n\t} else if ($selectedSizeInDropdown.length > 0) {\n\t\tselectedSize = $selectedSizeInDropdown.find('[data-size-name]').attr('data-size-name');\n\t} else {\n\t\tselectedSize = util.getPreferenceValueFromWindowLocation('size');\n\t}\n\t\n\tvar payload = {\n\t\tChannel: options.Channel,\n\t\tProductId: options.ProductId,\n\t\tSelectedLocation: dataBuffer['SelectedLocation'],\n\t\tSaveSelectedLocation: !!saveSelectedLocation,\n\t\tSelectedOption: $container.find('input[name=\"AddToCartOption\"]:checked').val()\n\t}\n\tpayload['dwvar_' + options.ProductId + '_color'] = selectedColor;\n\tpayload['dwvar_' + options.ProductId + '_size'] = selectedSize;\n\n\t$.ajax({\n\t\tmethod: 'GET',\n\t\turl: Urls.Bopis.AddToCartOptions,\n\t\tcontentType: 'application/json',\n\t\tdata: payload,\n\t\tdataType: 'html',\n\t\tsuccess: function(data) {\n\t\t\t$container.html($(data).children());\n\t\t\t$addToCartOptions = $container.find('.bopis-add-to-cart-options');\n\t\t\tinitializeTooltips(selectedSize);\n\t\t},\n\t\terror: function() {\n\t\t\t\n\t\t}\n\t});\n}\n\nfunction initializeTooltips(selectedSize) {\n\tif (!selectedSize) {\n\t\t$addToCartOptions.find('label.disabled > span').each(function(index, element) {\n\t\t\tvar $this = $(this);\n\n\t\t\ttooltip.init({\n\t\t\t\titems: $this,\n\t\t\t\ttooltipClass: 'tooltip-select-size',\n\t\t\t\tcontent: 'Select a size to<br />see availability'\n\t\t\t}, $this);\n\t\t});\n\t}\n\n\tvar localDeliveryRadius;\n\tvar $storeData = $container.find('.selected-store[store-data]');\n\tif ($storeData && $storeData.length > 0) {\n\t\tvar storeData = JSON.parse($storeData.first().attr('store-data'));\n\t\tif (storeData && storeData.location && storeData.location.local_delivery_vendor && storeData.location.local_delivery_radius) {\n\t\t\tlocalDeliveryRadius = storeData.location.local_delivery_radius;\n\t\t}\n\t}\n\n\t$('.add-to-cart-options-tooltip').find('.delivery-radius').html(localDeliveryRadius);\n\ttooltip.init({\n\t\titems: '.add-to-cart-options-tooltip',\n\t\ttooltipClass: 'add-to-cart-options-tooltip'\n\t}, $('.add-to-cart-options-tooltip'));\n}","'use strict';\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar GeolocationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/Geolocation/GeolocationHelper');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar tooltip = require('../../tooltip');\nvar ValidationSettings = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ZipCodeToStateMap = require('../../../../../bc_sheplersbootbarn_core/cartridge/data/ZipCodeToStateMap.json');\n\nmodule.exports = AddToCartOptionsStoreSearch;\n\nfunction AddToCartOptionsStoreSearch() {\n\tthis.options;\n\tthis.validator;\n\tthis.loaded;\n\tthis.dataBuffer;\n\n\tthis.resultContainerTemplate;\n\tthis.resultItemTemplate;\n\tthis.localDeliveryDecorator;\n\n\tthis.$container;\n\tthis.$form;\n\tthis.$result;\n\tthis.$formInputPostalCode;\n\tthis.$formInputRadius;\n\tthis.$storeSearchButton;\n\tthis.$storeSearchButtonContainer;\n\tthis.$bopisButton;\n\tthis.$errorMessage;\n\tthis.$inputTooltip;\n\n\tthis.initialize = function($containerParameter, optionsParameter) {\n\t\tvar self = this;\n\t\tif (!this.dataBuffer) {\n\t\t\tthis.dataBuffer = {};\n\t\t}\n\t\tif (!this.loaded) {\n\t\t\tthis.loaded = {};\n\t\t}\n\t\tthis.options = $.extend({\n\t\t\tsuccessCallback: null,\n\t\t\terrorCallback: null\n\t\t}, optionsParameter);\n\n\t\tthis.resultContainerTemplate = _.template($('#template-bopis-result-container-addtocartoptions').html(), TemplateConstants.Lodash.Settings);\n\t\tthis.resultItemTemplate = _.template($('#template-bopis-result-item-addtocartoptions').html(), TemplateConstants.Lodash.Settings);\n\t\tthis.localDeliveryDecorator = _.template($('#template-bopis-localdelivery-decorator').html(), TemplateConstants.Lodash.Settings);\n\n\t\tthis.$container = $containerParameter;\n\t\tthis.$form = this.$container.find('form');\n\t\tthis.$result = this.$container.find('.result');\n\t\tthis.$formInputPostalCode = this.$form.find('input[name$=\"_postalCode\"]');\n\t\tthis.$formInputRadius = this.$form.find('[name$=\"_radius\"]');\n\t\tthis.$storeSearchButton = this.$container.find('.btn.store-search');\n\t\tthis.$storeSearchButtonContainer = this.$container.find('.btn-store-search-container');\n\t\tthis.$bopisButton = this.$container.find('.btn.bopis');\n\t\tthis.$errorMessage = this.$form.find('span.error');\n\t\tthis.$inputTooltip = this.$formInputPostalCode.parent();\n\t\tthis.$container.find('.btn.store-select').addClass('disabled');\n\t\t$('html').addClass('scroll-lock');\n\n\t\tif (this.options && this.options.LocalDelivery && this.options.LocalDelivery.Radius) {\n\t\t\tthis.$container.find('.delivery-radius').html(this.options.LocalDelivery.Radius);\n\t\t}\n\t\tthis.$container.attr('state', 'form');\n\t\tthis.validator = this.$form.validate(ValidationSettings.Global);\n\t\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n\t\tthis.$formInputPostalCode.rules('add', ValidationRules.ZipCode);\n\n\t\tthis.$container.addClass('show');\n\t\tif (this.$container.attr('state') === 'form' && this.validator.checkForm() && !this.$storeSearchButton.hasClass('ready')) {\n\t\t\tthis.$storeSearchButton.addClass('ready');\n\t\t}\n\n\t\tthis.$form.off('click.apply').on('click.apply', '.btn.store-search:not([loading])', function (event) {\n\t\t\tevent.preventDefault();\n\t\t\tself.$storeSearchButtonContainer.loading();\n\t\t\tself.search();\n\t\t});\n\n\t\tthis.$container.off('click.apply').on('click.apply', '.btn.bopis:not([loading])', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tvar selectedLocation = self.dataBuffer['StoresDisplayed'][$('input[name=\"Bopis_StoreSearch_StoreId\"]:checked').val()];\n\t\t\tif (selectedLocation) {\n\t\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', { bopis: true, shippingOption: 'pickup', channel: self.options.Channel });\n\t\t\t} else {\n\t\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', { channel: self.options.Channel });\n\t\t\t}\n\t\t});\n\n\t\tthis.$formInputPostalCode.off('keydown.BopisStoreSearch.ValidationCheck').on('keydown.BopisStoreSearch.ValidationCheck', function (event) {\n\t\t\tif (self.$formInputPostalCode.val().length == 5 && parseInt(event.key, 10) == event.key && !window.getSelection().toString()) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t});\n\n\t\tthis.$formInputPostalCode.off('change.BopisStoreSearch.ValidationCheck').on('change.BopisStoreSearch.ValidationCheck', function (event) {\n\t\t\tif (self.$formInputPostalCode.val().length > 5) {\n\t\t\t\tself.$formInputPostalCode.val(self.$formInputPostalCode.val().substr(0, 5));\n\t\t\t}\n\t\t});\n\n\t\tthis.$formInputPostalCode.off('keyup.BopisStoreSearch.ValidationCheck, change.BopisStoreSearch.ValidationCheck').on('keyup.BopisStoreSearch.ValidationCheck, change.BopisStoreSearch.ValidationCheck', function (event) {\n\t\t\tevent.stopImmediatePropagation();\n\n\t\t\tif (self.$container.attr('state') === 'form') {\n\t\t\t\tif (self.validator.checkForm() && !self.$storeSearchButton.hasClass('ready')) {\n\t\t\t\t\tself.$storeSearchButton.addClass('ready');\n\t\t\t\t} else if (!self.validator.checkForm() && self.$storeSearchButton.hasClass('ready')) {\n\t\t\t\t\tself.$storeSearchButton.removeClass('ready');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (self.$container.attr('state') === 'result') {\n\t\t\t\tself.$container.attr('state', 'form');\n\t\t\t\tself.$formInputPostalCode.val('');\n\t\t\t}\n\t\t});\n\n\t\t$(document).off('mousedown.BopisStoreSearch.ValidationClear').on('mousedown.BopisStoreSearch.ValidationClear', function (event) {\n\t\t\tif (self.validator && $(event.target).closest(self.$container).length == 0) {\n\t\t\t\tself.validator.resetForm();\n\t\t\t\tself.$errorMessage.html('').hide();\n\t\t\t}\n\t\t});\n\n\t\t$(document).off('Bopis.StoreSearch.Reset').on('Bopis.StoreSearch.Reset', function (event) {\n\t\t\tself.reset();\n\t\t});\n\n\t\tthis.$container.off('click.BopisStoreSearch.Selection').on('click.BopisStoreSearch.Selection', 'input[name=\"Bopis_StoreSearch_StoreId\"]', function (event) {\n\t\t\tvar bopisStore = $('input[name=\"Bopis_StoreSearch_StoreId\"]:checked').val();\n\n\t\t\tif (!self.$bopisButton.hasClass('ready')) {\n\t\t\t\tself.$bopisButton.addClass('ready');\n\t\t\t}\n\n\t\t\t$('.product-add-to-cart button').attr('disabled', 'disabled').addClass('hidden');\n\n\t\t\tif (bopisStore) {\n\t\t\t\tself.$bopisButton.attr('state', 'pickup');\n\t\t\t} else {\n\t\t\t\tself.$bopisButton.attr('state', 'ship');\n\t\t\t}\n\t\t});\n\n\t\tthis.$container.off('click.BopisStoreSearch.NoResultsShip').on('click.BopisStoreSearch.NoResultsShip', '.btn.no-results-ship', function (event) {\n\t\t\t$('html').removeClass('scroll-lock');\n\t\t\tself.close();\n\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', { channel: self.options.Channel });\n\t\t});\n\n\t\tthis.$container.off('click.BopisAddToCartOptionsStoreSearch.Select').on('click.BopisAddToCartOptionsStoreSearch.Select', 'li[store]', function (event) {\n\t\t\tevent.preventDefault();\n\t\t\t\n\t\t\tvar $this = $(this);\n\t\t\t$this.find('input').prop('checked', true);\n\t\t\tself.$container.find('.btn.store-select').removeClass('disabled');\n\t\t});\n\n\t\tthis.$container.off('click.BopisAddToCartOptionsStoreSearch.Confirm').on('click.BopisAddToCartOptionsStoreSearch.Confirm', '.btn.store-select:not(.disabled)', function (event) {\n\t\t\tvar store = $(this).closest('input[store]').attr('store');\n\t\t\tvar store = self.$container.find('input[name=\"bopis-store\"]:checked').val();\n\t\t\tvar eventName = 'Bopis.StoreSearch.Select';\n\n\t\t\tif (self.options.Events && self.options.Events.SelectStore) {\n\t\t\t\teventName = self.options.Events.SelectStore;\n\t\t\t\tstore = self.dataBuffer['StoresDisplayed'][store];\n\t\t\t}\n\t\t\t$('html').removeClass('scroll-lock');\n\t\t\t$(document).trigger(eventName, store);\n\t\t\tself.close();\n\t\t});\n\n\t\tthis.$container.off('click.BopisAddToCartOptionsStoreSearch.Close').on('click.BopisAddToCartOptionsStoreSearch.Close', '.close', function (event) {\n\t\t\t$('html').removeClass('scroll-lock');\n\t\t\tself.close();\n\t\t});\n\n\t\tthis.$container.off('click.UseMyLocation').on('click.UseMyLocation', '.use-my-location', function (event) {\n\t\t\tevent.preventDefault();\n\t\t\t\n\t\t\tGeolocationHelper.GetPosition().then(function(position) {\n\t\t\t\tself.search(true, position);\n\t\t\t}).catch();\n\t\t});\n\n\t\tthis.reset();\n\t\tif (this.options.StoreUIVersion == '2024Redesign' && this.$formInputPostalCode.val()) {\n\t\t\tthis.search();\n\t\t}\n\t}\n\n\tthis.reset = function() {\n\t\tthis.$container.attr('result-count', '0');\n\t\tthis.$result.html('');\n\t}\n\n\tthis.close = function() {\n\t\t$('html').removeClass('scroll-lock');\n\t\tif (this.options.Functions && this.options.Functions.Close) {\n\t\t\tthis.options.Functions.Close();\n\t\t} else {\n\t\t\t$('.bopis-add-to-cart-store-search-container').removeClass('show');\n\t\t}\n\t}\n\n\tthis.search = function(isByGeolocation, position) {\n\t\tvar self = this;\n\t\tvar colorSelected = $('div.product-variations .color.color-options li.selected').length;\n\t\tvar sizeSelected = $('div.product-variations .size.size-options li.selected');\n\t\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\t\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\t\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\n\t\tif (this.options.StoreUIVersion != '2024Redesign') {\n\t\t\tif (!isSizeSelected && !colorSelected) {\n\t\t\t\tthis.$errorMessage.html('Please select a size and color.').show();\n\t\t\t\treturn false;\n\t\t\t} else if (!isSizeSelected) {\n\t\t\t\tthis.$errorMessage.html('Please select a size.').show();\n\t\t\t\treturn false;\n\t\t\t} else if (!colorSelected) {\n\t\t\t\tthis.$errorMessage.html('Please select a color.').show();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tthis.$errorMessage.html('').hide();\n\t\tthis.$storeSearchButton.removeAttr('disabled');\n\n\t\tvar geolocationPosition;\n\t\tif (isByGeolocation && position && position.coords) {\n\t\t\tgeolocationPosition = {\n\t\t\t\tcoords: {\n\t\t\t\t\taccuracy: position.coords.accuracy,\n\t\t\t\t\tlatitude: position.coords.latitude,\n\t\t\t\t\tlongitude: position.coords.longitude\n\t\t\t\t},\n\t\t\t\ttimestamp: position.timestamp\n\t\t\t}\n\t\t}\n\n\t\tvar isValid = isByGeolocation || this.validator.valid();\n\t\tif (Urls && Urls.Bopis.GetStoreInventoryForProductForPostalCode && isValid) {\n\t\t\tthis.$result.html('');\n\t\t\tthis.$result.loading();\n\n\t\t\tthis.loaded['LocationData'] = false;\n\t\t\tthis.loaded['InventoryData'] = false;\n\t\t\tthis.dataBuffer['LocationData'] = null;\n\t\t\tthis.dataBuffer['InventoryData'] = null;\n\n\t\t\tvar getLocationUrl;\n\t\t\tvar getLocationData;\n\t\t\tif (isByGeolocation) {\n\t\t\t\tgetLocationUrl = Urls.Bopis.GetLocationsForGeolocationPosition;\n\t\t\t\tgetLocationData = {\n\t\t\t\t\tChannel: this.options.Channel,\n\t\t\t\t\tSource: this.options.Source,\n\t\t\t\t\tGeolocationPosition: geolocationPosition,\n\t\t\t\t\tRadius: parseFloat(this.$formInputRadius.val()) || 3000\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgetLocationUrl = Urls.Bopis.GetLocationsForPostalCode;\n\t\t\t\tgetLocationData = {\n\t\t\t\t\tChannel: this.options.Channel,\n\t\t\t\t\tSource: this.options.Source,\n\t\t\t\t\tPostalCode: this.$formInputPostalCode.val(),\n\t\t\t\t\tRadius: parseFloat(this.$formInputRadius.val()) || 3000\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'POST',\n\t\t\t\turl: getLocationUrl,\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify(getLocationData),\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tvar locationData;\n\t\t\t\t\tif (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data && data.InquiryResult.data.length > 0) {\n\t\t\t\t\t\tlocationData = data.InquiryResult.data;\n\n\t\t\t\t\t\tif (locationData && locationData.length > 0) {\n\t\t\t\t\t\t\tlocationData = locationData.sort(function(left, right) {\n\t\t\t\t\t\t\t\treturn left.distance - right.distance;\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tself.dataBuffer['LocationData'] = locationData;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tself.loaded['LocationData'] = true;\n\t\t\t\t\tself.render();\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tif (self.options.errorCallback) {\n\t\t\t\t\t\tself.options.errorCallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tvar productId = $('.product-add-to-cart input[name=\"pid\"]').val();\n\t\t\tvar getStoreInventoryUrl;\n\t\t\tvar getStoreInventoryData;\n\t\t\tif (isByGeolocation) {\n\t\t\t\tgetStoreInventoryUrl = Urls.Bopis.GetStoreInventoryForProductForGeolocationPosition;\n\t\t\t\tgetStoreInventoryData = {\n\t\t\t\t\tChannel: this.options.Channel,\n\t\t\t\t\tSource: this.options.Source,\n\t\t\t\t\tProductId: productId,\n\t\t\t\t\tGeolocationPosition: geolocationPosition,\n\t\t\t\t\tStoreSearchRadius: parseFloat(this.$formInputRadius.val()) || 3000,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgetStoreInventoryUrl = Urls.Bopis.GetStoreInventoryForProductForPostalCode;\n\t\t\t\tgetStoreInventoryData = {\n\t\t\t\t\tChannel: this.options.Channel,\n\t\t\t\t\tSource: this.options.Source,\n\t\t\t\t\tProductId: productId,\n\t\t\t\t\tPostalCode: this.$formInputPostalCode.val(),\n\t\t\t\t\tStoreSearchRadius: parseFloat(this.$formInputRadius.val()) || 3000,\n\t\t\t\t\tSavePostalCode: true\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'POST',\n\t\t\t\turl: getStoreInventoryUrl,\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify(getStoreInventoryData),\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data && data.InquiryResult.data.length > 0 && data.InquiryResult.data[0].inventory_supplies) {\n\t\t\t\t\t\tvar inquiryResult = data.InquiryResult.data[0].inventory_supplies;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (inquiryResult && inquiryResult.length > 0) {\n\t\t\t\t\t\t\tself.dataBuffer['InventoryData'] = [];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfor (var inventoryRecordElement in inquiryResult) {\n\t\t\t\t\t\t\t\tvar inventoryRecord = inquiryResult[inventoryRecordElement];\n\t\t\t\t\t\t\t\tself.dataBuffer['InventoryData'][inventoryRecord.location.code] = inventoryRecord;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tself.loaded['InventoryData'] = true;\n\t\t\t\t\tself.render();\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tif (self.$result.attr('loading')) {\n\t\t\t\t\t\tself.$result.loading('destroy');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (self.options.errorCallback) {\n\t\t\t\t\t\tself.options.errorCallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tthis.render = function() {\n\t\tif (this.loaded['LocationData'] && this.loaded['InventoryData']) {\n\t\t\tif (this.$storeSearchButtonContainer.attr('loading')) {\n\t\t\t\tthis.$storeSearchButtonContainer.loading('destroy');\n\t\t\t}\n\t\t\tif (this.$result.attr('loading')) {\n\t\t\t\tthis.$result.loading('destroy');\n\t\t\t}\n\n\t\t\tthis.$container.attr('state', 'result');\n\t\t\tif (this.dataBuffer['LocationData'] && this.dataBuffer['LocationData'].length > 0) {\n\t\t\t\tthis.dataBuffer['StoresDisplayed'] = [];\n\n\t\t\t\tvar $addToCartOptions = $('.bopis-add-to-cart-options');\n\t\t\t\tvar quantitySourceType;\n\t\t\t\tvar dropshipLeadDays;\n\t\t\t\tif ($addToCartOptions.length > 0) {\n\t\t\t\t\tquantitySourceType = $addToCartOptions.attr('quantity-source-type');\n\t\t\t\t\tdropshipLeadDays = parseInt($addToCartOptions.attr('dropship-lead-days'), 10);\n\t\t\t\t}\n\t\t\t\tvar quantitySourceTypeOffset = 0;\n\t\t\t\tif (quantitySourceType == 'WHS') {\n\t\t\t\t\tquantitySourceTypeOffset = -1;\n\t\t\t\t}\n\n\t\t\t\tvar storeListHtml = '';\n\t\t\t\tvar isStoreSelected = false;\n\t\t\t\tvar status = '';\n\t\t\t\tvar statusDisplay = '';\n\t\t\t\tvar isLocalDeliverySupported = false;\n\t\t\t\tvar localDeliveryHtml = '';\n\t\t\t\tvar storesDisplayedCount = 0;\n\t\t\t\tvar selectedStoreAttribute;\n\t\t\t\tvar quantityAvailable = false;\n\t\t\t\tfor (var locationKey in this.dataBuffer['LocationData']) {\n\t\t\t\t\tvar location = this.dataBuffer['LocationData'][locationKey];\n\n\t\t\t\t\tvar inventoryRecord;\n\t\t\t\t\tif (this.dataBuffer['InventoryData'] && this.dataBuffer['InventoryData'][location.code]) {\n\t\t\t\t\t\tinventoryRecord = this.dataBuffer['InventoryData'][location.code];\n\t\t\t\t\t}\n\n\t\t\t\t\tstatus = 'unavailable';\n\t\t\t\t\tstatusDisplay = 'Unavailable';\n\t\t\t\t\tisLocalDeliverySupported = false;\n\t\t\t\t\tlocalDeliveryHtml = '';\n\t\t\t\t\tif (inventoryRecord && inventoryRecord.detail && inventoryRecord.detail.quantity > 0 && !this.dataBuffer['StoresDisplayed'][inventoryRecord.location.code] && (!this.options.LocalDeliveryOnly || (inventoryRecord.location.local_delivery_enabled && this.isLocationInLocalDeliveryRadius(inventoryRecord.location)))) {\n\t\t\t\t\t\tif (this.options && this.options.SelectedLocations == inventoryRecord.location.code) {\n\t\t\t\t\t\t\tisStoreSelected = true;\n\t\t\t\t\t\t\tselectedStoreAttribute ='checked';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselectedStoreAttribute = '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (this.options.LocalDelivery.Enabled && this.isLocationInLocalDeliveryRadius(inventoryRecord.location) && inventoryRecord.location.local_delivery_enabled) {\n\t\t\t\t\t\t\tlocalDeliveryHtml = this.localDeliveryDecorator();\n\t\t\t\t\t\t\tisLocalDeliverySupported = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isLocalDeliverySupported && inventoryRecord.detail && inventoryRecord.detail.quantity > 0) {\n\t\t\t\t\t\t\tif (this.options.LocalDeliveryOnly) {\n\t\t\t\t\t\t\t\tstatusDisplay = 'Same-Day Delivery<br/>Available';\n\t\t\t\t\t\t\t\tstatus = 'available';\n\t\t\t\t\t\t\t} else if (!this.options.LocalDeliveryOnly) {\n\t\t\t\t\t\t\t\t// statusDisplay = 'Pickup & Same-Day<br/>Delivery Available';\n\t\t\t\t\t\t\t\tstatusDisplay = 'Available Today';\n\t\t\t\t\t\t\t\tstatus = 'available';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!this.options.LocalDeliveryOnly && inventoryRecord.detail && inventoryRecord.detail.quantity > 0) {\n\t\t\t\t\t\t\tstatusDisplay = 'Available Today';\n\t\t\t\t\t\t\tstatus = 'available';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tquantityAvailable = inventoryRecord.detail.quantity;\n\t\t\t\t\t} else if (!this.options.LocalDeliveryOnly && pageContext.site != SiteConstants.SiteIds.BootBarnRspUS) {\n\t\t\t\t\t\tstatusDisplay = 'Arrives in ' + (this.options.ShippingMethods.ShipToStore.DayRangeStart + dropshipLeadDays + quantitySourceTypeOffset) + '-' + (this.options.ShippingMethods.ShipToStore.DayRangeEnd + dropshipLeadDays + quantitySourceTypeOffset) + '<br/>Business Days';\n\t\t\t\t\t\tstatus = 'available';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tquantityAvailable = false\n\t\t\t\t\t}\n\n\t\t\t\t\tvar locationName;\n\t\t\t\t\tif (this.options && this.options.StoreUIVersion == '2024Redesign') {\n\t\t\t\t\t\tlocationName = '<strong>' + location.StoreInfo.Name + ' - ' + location.StoreInfo.StoreId + '</strong>';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlocationName = '<strong>' + location.StoreInfo.Name + '</strong>';\n\t\t\t\t\t}\n\t\t\t\t\tif (this.options && this.options.AgentStoreID == location.code) {\n\t\t\t\t\t\tlocationName += '<br/>(Your Store)';\n\t\t\t\t\t}\n\n\t\t\t\t\tstoreListHtml += this.resultItemTemplate({\n\t\t\t\t\t\tStoreId: location.code,\n\t\t\t\t\t\tQuantityAvailable: quantityAvailable,\n\t\t\t\t\t\tHtml: '<span class=\"store-name\">' + locationName + '</span><br/>' + location.StoreInfo.Address1 + '<br/>' + location.StoreInfo.City + ', ' + location.StoreInfo.StateCodeParsed + ', ' + location.StoreInfo.PostalCode.substr(0, 5),\n\t\t\t\t\t\tSelected: selectedStoreAttribute,\n\t\t\t\t\t\tLocalDelivery: localDeliveryHtml,\n\t\t\t\t\t\tStatus: status,\n\t\t\t\t\t\tStatusDisplay: statusDisplay\n\t\t\t\t\t});\n\n\t\t\t\t\tstoresDisplayedCount += 1;\n\t\t\t\t\tthis.dataBuffer['StoresDisplayed'][location.code] = inventoryRecord ? inventoryRecord : { location: location };\n\t\t\t\t}\n\n\t\t\t\tvar resultHtml = this.resultContainerTemplate({\n\t\t\t\t\tHtml: storeListHtml\n\t\t\t\t});\n\n\t\t\t\tif (isStoreSelected) {\n\t\t\t\t\tthis.$bopisButton.addClass('ready');\n\t\t\t\t}\n\n\t\t\t\tif (storesDisplayedCount > 0) {\n\t\t\t\t\tthis.$result.html(resultHtml);\n\t\t\t\t\tthis.$container.attr('result-count', storesDisplayedCount);\n\t\t\t\t\tthis.$container.find('.result-container').show();\n\t\t\t\t\tthis.$container.find('.result-empty').hide();\n\t\t\t\t} else {\n\t\t\t\t\tthis.$container.attr('result-count', 0);\n\t\t\t\t\tthis.$container.find('.result-container').hide();\n\t\t\t\t\tthis.$container.find('.result-empty').show();\n\t\t\t\t}\n\n\t\t\t\ttooltip.init({\n\t\t\t\t\titems: '.tooltip'\n\t\t\t\t}, this.$result);\n\n\t\t\t\tif (this.options.successCallback) {\n\t\t\t\t\tthis.options.successCallback(inquiryResult);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$('.product-add-to-cart button').removeAttr('disabled').removeClass('hidden');\n\t\t\t\tthis.reset();\t\t\t\t\t\t\n\t\t\t\tthis.$result.closest('.result-container').hide();\n\t\t\t\tthis.$container.find('.result-empty').show();\n\n\t\t\t\tif (this.options.errorCallback) {\n\t\t\t\t\tthis.options.errorCallback();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tthis.isLocationInLocalDeliveryRadius = function(location) {\n\t\tvar localDeliveryRadius;\n\t\tif (this.options && this.options.LocalDelivery) {\n\t\t\tif (location.local_delivery_vendor && location.local_delivery_vendor == 'GoLocal') {\n\t\t\t\tlocalDeliveryRadius = this.options.LocalDelivery.RadiusForGoLocal;\n\t\t\t} else {\n\t\t\t\tlocalDeliveryRadius = this.options.LocalDelivery.RadiusForRoadie;\n\t\t\t}\n\t\t}\t\n\n\t\tif (localDeliveryRadius && location && location.distance && localDeliveryRadius >= location.distance) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n}","'use strict';\n\nvar _ = require('lodash');\nvar addToCartOptionsStoreSearch = require('./AddToCartOptionsStoreSearch');\nvar dialog = require('../../dialog');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar tooltip = require('../../tooltip');\nvar ValidationSettings = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ZipCodeToStateMap = require('../../../../../bc_sheplersbootbarn_core/cartridge/data/ZipCodeToStateMap.json');\n\nexports.initialize = initialize;\nexports.remove = remove;\n\nvar options;\nvar optionsLocalDelivery;\nvar validator;\nvar dataBuffer;\nvar localDeliveryStoreSearch;\nvar localDeliveryRadius;\n\nfunction initialize(optionsParameter, selectedLocation, localDeliveryFormData) {\n\tdataBuffer = {};\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\n\tif (selectedLocation && selectedLocation.location && selectedLocation.location.local_delivery_vendor && selectedLocation.location.local_delivery_vendor == 'GoLocal') {\n\t\tlocalDeliveryRadius = options.LocalDelivery.RadiusForGoLocal;\n\t} else if (selectedLocation && selectedLocation.location && selectedLocation.location.local_delivery_vendor && selectedLocation.location.local_delivery_vendor == 'Roadie') {\n\t\tlocalDeliveryRadius = options.LocalDelivery.RadiusForRoadie;\n\t}\n\n\tbuildAddressHtmlForLocation(selectedLocation.location);\n\t$('#dialog-bopis-options').find('.delivery-radius').html(localDeliveryRadius);\n\tvar $optionalMessage = $('#dialog-bopis-options header .optional-message');\n\t\n\tif (options.OptionalMessage) {\n\t\tif ($optionalMessage.length == 0) {\n\t\t\t$('#dialog-bopis-options header').append('<p class=\"optional-message\">' + options.OptionalMessage + '</p>')\n\t\t}\n\t} else if ($optionalMessage.length > 0) {\n\t\t$optionalMessage.remove();\n\t}\n\t\n\tlocalDeliveryStoreSearch = new addToCartOptionsStoreSearch();\n\toptionsLocalDelivery = Object.assign(options, {\n\t\tLocalDeliveryOnly: true,\n\t\tEvents: {\n\t\t\tSelectStore: 'Bopis.StoreSearchSelectLocalDelivery'\n\t\t},\n\t\tFunctions: {\n\t\t\tClose: function() {\n\t\t\t\t$('.dialog-bopis-options').removeClass('hidden');\n\t\t\t\t$('.ui-widget-overlay').removeClass('hidden');\n\t\t\t\t$('.bopis-local-delivery-store-search-container').removeClass('show');\n\t\t\t}\n\t\t}\n\t});\n\n\tGoogleTagManagerClient.PushDataLayerForEvent('roadieFormDisplay');\n\tdialog.open({\n\t\thtml: $('#dialog-bopis-options').html(),\n\t\toptions: {\n\t\t\tdialogClass: 'dialog-bopis-options',\n\t\t\twidth: 320,\n\t\t\tdraggable: false,\n\t\t\tresizable: false,\n\t\t\topen: function(event, ui) {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar $addressForm = $this.find('form.bopis-delivery-address');\n\t\t\t\tappendCSRFToken($addressForm);\n\t\t\t\t\n\t\t\t\tif (localDeliveryFormData) {\n\t\t\t\t\t$addressForm.find('input[name=\"email\"]').val(localDeliveryFormData.Email || '');\n\t\t\t\t\t$addressForm.find('input[name=\"phone\"]').val(localDeliveryFormData.Phone || '');\n\t\t\t\t\t$addressForm.find('input[name=\"firstName\"]').val(localDeliveryFormData.FirstName || '');\n\t\t\t\t\t$addressForm.find('input[name=\"lastName\"]').val(localDeliveryFormData.LastName || '');\n\t\t\t\t\t$addressForm.find('input[name=\"address1\"]').val(localDeliveryFormData.Address1 || '');\n\t\t\t\t\t$addressForm.find('input[name=\"address2\"]').val(localDeliveryFormData.Address2 || '');\n\t\t\t\t\t$addressForm.find('input[name=\"address3\"]').val(localDeliveryFormData.Address3 || '');\n\t\t\t\t\t$addressForm.find('input[name=\"city\"]').val(localDeliveryFormData.City || '');\n\t\t\t\t\t$addressForm.find('select[name=\"stateCode\"] option[value=\"' + localDeliveryFormData.State + '\"]').prop('selected', true);\n\t\t\t\t\t$addressForm.find('input[name=\"postalCode\"]').val(localDeliveryFormData.PostalCode || '');\n\t\t\t\t\t$addressForm.find('textarea[name=\"deliveryNote\"]').val(localDeliveryFormData.DeliveryNote || '');\n\t\t\t\t}\n\n\t\t\t\tvar addressValidator = $addressForm.validate(ValidationSettings.Global);\n\t\t\t\t$.validator.addMethod('requiredExcludingPunctuation', ValidationHelper.ValidateRequiredExcludingPunctuation, Resources.INVALID_VALUE);\n\t\t\t\t$.validator.addMethod('postOfficeBox', ValidationHelper.ValidateAddressForPostOfficeBox, Resources.INVALID_ADDRESS_POBOX);\n\t\t\t\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n\t\t\t\t$.validator.addMethod('stateCodeForCaliforniaStateLine', ValidationHelper.ValidateStateCodeForCaliforniaStateLine, Resources.INVALID_CALIFORNIA_STATE_LINE_LOCAL_DELIVERY);\n\t\t\t\t\n\t\t\t\t$addressForm.find('input[name=\"address1\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBox);\n\t\t\t\t$addressForm.find('input[name=\"address2\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBox);\n\t\t\t\t$addressForm.find('input[name=\"address3\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBox);\n\t\t\t\t$addressForm.find('select[name=\"stateCode\"]').rules('add', ValidationRules.StateCodeForCaliforniaStateLine);\n\t\t\t    $addressForm.find('input[name=\"postalCode\"]').rules('add', ValidationRules.ZipCode);\n\t\t\t\t$addressForm.find('input.required, select.required').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t\t\t\t$addressForm.find('input[name=\"email\"]').rules('add', ValidationRules.Email);\n\t\t\t\t$this.attr('local-delivery-vendor', $('#dialog-bopis-options').attr('local-delivery-vendor'));\n\t\t\t\t$this.attr('local-delivery-radius', isLocalDeliveryValid(selectedLocation));\n\t\t\t\t$this.attr('store-state', selectedLocation.location.postal_address.province_or_state);\n\t\t\t\t\n\t\t\t\t$this.off('click.SelectDeliveryOption').on('click.SelectDeliveryOption', '.delivery-option label', function (event) {\n\t\t\t\t\tvar deliveryOption = $(this).find('input').val();\n\n\t\t\t\t\tif (deliveryOption == 'pickup') {\n\t\t\t\t\t\t$this.find('.address-form').hide();\n\t\t\t\t\t} else if (deliveryOption == 'delivery') {\n\t\t\t\t\t\t$this.find('.address-form').show();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.Apply').on('click.Apply', '.btn.bopis-option:not([loading])', function (event) {\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t$this.find('.ui-dialog-footer .error').remove();\n\n\t\t\t\t\tvar selectedBopisOption;\n\t\t\t\t\tif (options && options.Mode == 'AddToCartOptions') {\n\t\t\t\t\t\tselectedBopisOption = 'delivery';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselectedBopisOption = $this.find('input[name=\"bopis-option\"]:checked').val();\n\t\t\t\t\t}\n\t\t\t\t\tvar eventData = {bopis: true, bopisStore: selectedLocation.location.code, shippingOption: selectedBopisOption, channel: options.Channel, quantityAvailable: selectedLocation.detail.quantity};\n\t\t\t\t\tif (selectedBopisOption == 'delivery') {\n\t\t\t\t\t\tvar deliveryAddressObject = {};\n\t\t\t\t\t\tvar $deliveryAddressForm = $this.find('.bopis-delivery-address');\n\t\t\t\t\t\tvar deliveryAddressArray = $deliveryAddressForm.serializeArray();\n\t\t\t\t\t\t$(deliveryAddressArray).each(function(index, element) {\n\t\t\t\t\t\t\tif (element.value != 'disabled' && $deliveryAddressForm.find('[name=\"' + element.name + '\"]').attr('type') != 'hidden') {\n\t\t\t\t\t\t\t\tdeliveryAddressObject[element.name] = element.value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\teventData.deliveryAddress = JSON.stringify(deliveryAddressObject);\n\t\t\t\t\t\t$deliveryAddressForm.find('input[type=\"hidden\"]').each(function () {\n\t\t\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\t\t\teventData[$this.attr('name')] = $this.val();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (selectedBopisOption != 'delivery' || $addressForm.valid()) {\n\t\t\t\t\t\tif (selectedBopisOption == 'delivery') {\n\t\t\t\t\t\t\t$.ajax({\n\t\t\t\t\t            method: 'POST',\n\t\t\t\t\t            url: Urls.Bopis.ValidatePostalCodeForLocations,\n\t\t\t\t\t            contentType: 'application/json',\n\t\t\t\t\t            data: JSON.stringify({\n\t\t\t\t\t                PostalCode: $addressForm.find('input[name=\"postalCode\"]').val(),\n\t\t\t\t\t                Locations: [selectedLocation.location.code]\n\t\t\t\t\t            }),\n\t\t\t\t\t            dataType: 'json',\n\t\t\t\t\t            success: function(data) {\n\t\t\t\t\t            \tif (data) {\n\t\t\t\t\t\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForEvent('roadieFormSubmit');\n\t\t\t\t\t            \t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', eventData);\n\t\t\t\t\t            \t} else {\n\t\t\t\t\t            \t\tvar errorMessage = '<div class=\"error\">The zip code you entered is different than the one you searched with, and the selected location is not in range. Please update your address and try again.</div>'\n\n\t\t\t\t\t            \t\t$this.find('.ui-dialog-footer').prepend(errorMessage);\n\t\t\t\t\t            \t}\n\t\t\t\t\t            }\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', eventData);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.ChangeZip').on('click.ChangeZip', '.btn.change-zip', function (event) {\n\t\t\t\t\t$(document).trigger('Bopis.StoreSearch.Reset');\n\t\t\t\t\tdialog.close();\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.ChangeStore').on('click.ChangeStore', '.btn.change-store', function (event) {\n\t\t\t\t\tdialog.close();\n\t\t\t\t});\n\n\t\t\t\t$this.off('click.SearchStore').on('click.SearchStore', '.search-store', function (event) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopImmediatePropagation();\n\n\t\t\t\t\t$('.dialog-bopis-options').addClass('hidden');\n\t\t\t\t\t$('.ui-widget-overlay').addClass('hidden');\n\t\t\t\t\t\n\t\t\t\t\tlocalDeliveryStoreSearch.initialize($('.bopis-local-delivery-store-search-container'), optionsLocalDelivery);\n\t\t\t\t});\n            },\n            close: function(event, ui) {\n\n            }\n\t\t}\n\t});\n\n\t$(document).off('Bopis.StoreSearchSelectLocalDelivery').on('Bopis.StoreSearchSelectLocalDelivery', function (event, store) {\n\t\tbuildAddressHtmlForLocation(store.location);\n\t\t$('.dialog-bopis-options').removeClass('hidden');\n\t\t$('.ui-widget-overlay').removeClass('hidden');\n\t\t$('.bopis-local-delivery-store-search-container').removeClass('show');\n\t\t$('.dialog-bopis-options').find('.dialog-content').attr('local-delivery-radius', isLocalDeliveryValid(store));\n\t\t$('.dialog-bopis-options').find('.dialog-content').attr('store-state', store.location.postal_address.province_or_state);\n\t});\n}\n\nfunction remove() {\n\tvalidator.destroy();\n\t$('.product-add-to-cart button').removeAttr('disabled').removeClass('hidden');\n}\n\nfunction buildAddressHtmlForLocation(location) {\n\tvar locationHtml;\n\tif (options && options.Mode == 'AddToCartOptions') {\n\t\tlocationHtml = '<p class=\"selected-location-name\">' + location.postal_address.name + '</p>' + \n\t\t\t\t\t\t\t\t'<p class=\"selected-location-address\">' + location.postal_address.address_line1 + '<br/>' +\n\t\t\t\t\t\t\t\tlocation.postal_address.city + ', ' + location.postal_address.province_or_state + '</p>' +\n\t\t\t\t\t\t\t\t'<a class=\"search-store\">Change Store</a>';\n\t} else {\n\t\tlocationHtml = location.postal_address.address_line1 + '<br/>' +\n\t\tlocation.postal_address.city + ', ' + location.postal_address.province_or_state;\n\t}\n\n\t$('.ui-dialog.dialog-bopis-options').find('.selected-location-details').html(locationHtml);\n\t$('#dialog-bopis-options').find('.selected-location-details').html(locationHtml);\n}\n\nfunction isLocalDeliveryValid(record) {\n\tif (options.LocalDelivery && options.LocalDelivery.Enabled && isLocationInLocalDeliveryRadius(record.location) && record.location.local_delivery_enabled && record.detail && record.detail.quantity > 0) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction isLocationInLocalDeliveryRadius(location) {\n\tif (localDeliveryRadius && location.distance && localDeliveryRadius >= location.distance) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction appendCSRFToken($form) {\n\t$.ajax({\n\t\tmethod: 'get',\n\t\turl: Urls.CSRFToken.Get,\n\t\tdataType: 'json',\n\t\tsuccess: function(response) {\n\t\t\t$form.append('<input type=\"hidden\" name=\"' + response.name + '\" value=\"' + response.token + '\"/>');\n\t\t}\n\t});\n}","'use strict';\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar GeolocationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/Geolocation/GeolocationHelper');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar ValidationSettings = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\n\nmodule.exports = LocationSearch;\n\nfunction LocationSearch() {\n\tthis.$container;\n\tthis.$form;\n\tthis.dataBuffer;\n\tthis.options;\n\tthis.validator;\n\t\n\tthis.resultContainerTemplate = _.template($('#template-bopis-result-container').html(), TemplateConstants.Lodash.Settings);\n\tthis.resultItemTemplate = _.template($('#template-bopis-result-item').html(), TemplateConstants.Lodash.Settings);\n\n\tthis.$result;\n\tthis.$formInputPostalCode;\n\tthis.$formInputRadius;\n\tthis.$storeSearchButton;\n\tthis.$storeSelectButton;\n\tthis.$bopisButton;\n\tthis.$errorMessage;\n\t\n\tthis.initialize = function ($container, options) {\n\t\tvar self = this;\n\t\tthis.$container = $container;\n\t\tthis.$form = $container.find('form');\n\t\tthis.options = $.extend({\n\t\t\tsuccessCallback: null,\n\t\t\terrorCallback: null\n\t\t}, options);\n\t\tthis.dataBuffer = {\n\t\t\tlimit: this.options && this.options.Bopis && this.options.Bopis.StoreSearchLimit ? this.options.Bopis.StoreSearchLimit : 5\n\t\t};\n\t\tthis.$result = this.$container.find('.result');\n\t\tthis.$formInputPostalCode = this.$form.find('input[name$=\"_postalCode\"]');\n\t\tthis.$formInputRadius = this.$form.find('[name$=\"_radius\"]');\n\t\tthis.$storeSearchButton = this.$container.find('.btn.store-search');\n\t\tthis.$storeSelectButton = this.$container.find('.btn.store-select');\n\t\tthis.$bopisButton = this.$container.find('.btn.bopis');\n\t    this.$errorMessage = this.$form.find('span.error');\n\t\t$('html').addClass('scroll-lock');\n\n\t\tif (this.options.DefaultZipCode) {\n\t\t\tthis.$formInputPostalCode.val(this.options.DefaultZipCode);\n\t\t}\n\n\t    this.$container.attr('state', 'form');\n\t    this.validator = this.$form.validate(ValidationSettings.Global);\n\t\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n\t    this.$formInputPostalCode.rules('add', ValidationRules.ZipCode);\n\t\n\t    if (this.validator.checkForm() && this.$container.attr('state') === 'form' && !this.$storeSearchButton.hasClass('ready')) {\n\t\t\tthis.$storeSearchButton.addClass('ready').removeAttr('disabled');\n\t    }\n\t\tthis.$container.show();\n\t    \n\t    this.$form.off('click.Apply').on('click.Apply', '.btn.store-search:not([loading])', '.btn.store-search:not([loading])', function (event) {\n\t    \tevent.preventDefault();\n\t    \t$('.bopis-store-search').attr('state', 'form');\n\t    \tself.$container.trigger('LocationSearch.FormSubmit');\n\t    });\n\t    \n\t    this.$container.off('click.DialogClose').on('click.DialogClose', '.close', function (event) {\n\t    \tevent.preventDefault();\n\t\t\t$('html').removeClass('scroll-lock');\n\t    \t$('.bopis-store-search').attr('state', 'form');\n\t\t\t$('.location-search-dialog').hide();\n\t    });\n\t    \n\t    this.$container.off('LocationSearch.FormSubmit').on('LocationSearch.FormSubmit', function (event) {\n\t\t\tevent.preventDefault();\n\n\t        self.$errorMessage.html('').hide();\n\t        if (Urls && Urls.Bopis.GetLocationsForPostalCode && self.validator.valid() && self.$formInputPostalCode.val()) {\n\t\t\t\tself.dataBuffer.loadMore = 'postalCode';\n\t\t\t\tself.dataBuffer.offset = 0;\n\t\t\t\tself.$storeSearchButton.loading();\n\t\t\t\tself.$result.html('');\n\t\t\t\tself.$result.loading();\n\t\t\t\tself.getStoreListForPostalCode(self.$formInputPostalCode.val());\n\t\t\t}\n\t\t});\n\t    \n\t    this.$container.off('click.SelectStore').on('click.SelectStore', '.btn.select-store:not([loading])', function (event) {\n\t\t\t$('html').removeClass('scroll-lock');\n\t\t\t$(this).loading({\n\t\t\t\tContent: '<h6>Hold Your Horses!</h6><p>Your selections are loading...</p>',\n\t\t\t\tCssClass: 'bootbarnexpress',\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\t    });\n\n\t\tthis.$container.off('click.SelectStore').on('click.SelectStore', '.btn.set-my-store:not([loading])', function (event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar $storeInput = $this.closest('li').find('input');\n\t\t\tvar storeId;\n\t\t\t$('html').removeClass('scroll-lock');\n\t\t\tif ($storeInput && $storeInput.length > 0) {\n\t\t\t\tstoreId = $storeInput.val();\n\t\t\t}\n\n\t\t\tif (storeId) {\n\t\t\t\tself.updateStoreDetails(storeId);\n\t\t\t}\n\t    });\n\t    \n\t    this.$formInputPostalCode.off('keypress.LocationSearch.FormSubmit').on('keypress.LocationSearch.FormSubmit', function (event) {\n\t    \tif (event.key == 'Enter') {\n\t    \t\tself.$container.trigger('LocationSearch.FormSubmit');\n\t    \t\treturn false;\n\t    \t}\n\t    });\n\t    \n\t    this.$formInputPostalCode.off('keydown.LocationSearch.ValidationCheck').on('keydown.LocationSearch.ValidationCheck', function (event) {\n\t    \tif (self.$formInputPostalCode.val().length == 5 && parseInt(event.key, 10) == event.key && !window.getSelection().toString()) {\n\t    \t\tevent.preventDefault();\n\t    \t}\n\t    \t\n\t    \t$(document).find('.bopis-store-search').attr('state', 'form');\n\t    });\n\t    \n\t    \n\t    this.$formInputPostalCode.off('change.LocationSearch.ValidationCheck').on('change.LocationSearch.ValidationCheck', function (event) {\n\t    \tif (self.$formInputPostalCode.val().length > 5) {\n\t    \t\tself.$formInputPostalCode.val(self.$formInputPostalCode.val().substr(0, 5));\n\t    \t}\n\t    \t\n\t    \t$(document).find('.bopis-store-search').attr('state', 'form');\n\t    });\n\t    \n\t    this.$formInputPostalCode.off('keyup.LocationSearch.ValidationCheck, change.LocationSearch.ValidationCheck').on('keyup.LocationSearch.ValidationCheck, change.LocationSearch.ValidationCheck', function (event) {\n\t    \tevent.stopImmediatePropagation();\n\t    \t\n\t\t\tif ($container.attr('state') === 'form') {\n\t\t\t\tif (self.validator.checkForm() && !self.$storeSearchButton.hasClass('ready')) {\n\t\t\t\t\tself.$storeSearchButton.addClass('ready').removeAttr('disabled');\n\t\t\t\t} else if (!self.validator.checkForm() && self.$storeSearchButton.hasClass('ready')) {\n\t\t\t\t\tself.$storeSearchButton.removeClass('ready').attr('disabled', 'disabled');\n\t\t\t\t}\n\t\t\t}\n\t    });\n\t    \n\t    $(document).off('mousedown.LocationSearch.ValidationClear').on('mousedown.LocationSearch.ValidationClear', function (event) {\n\t        if (self.validator && $(event.target).closest(self.$container).length == 0) {\n\t            self.$errorMessage.html('').hide();\n\t        }\n\t    });\n\t \n\t    this.$container.off('click.LocationSearch.Reset').on('click.LocationSearch.Reset', '.reset', function (event) {\n\t    \tself.$formInputPostalCode.val('');\n\t        self.$container.attr('state', 'form');\n\t        self.$storeSearchButton.removeClass('ready').attr('disabled', 'disabled');\n\t        $('.product-add-to-cart button').removeAttr('disabled');\n\t        self.$bopisButton.removeClass('ready');\n\t    });\n   \n\t    this.$container.off('click.LocationSearch.Selection').on('click.LocationSearch.Selection', 'input[name=\"Bopis_StoreSearch_StoreId\"]', function (event) {\n\t        var bopisStore = $('input[name=\"Bopis_StoreSearch_StoreId\"]:checked').val();\n\t        \n\t        if (!self.$bopisButton.hasClass('ready')) {\n\t        \tself.$bopisButton.addClass('ready');\n\t        }\n\n\t\t\tif (self.$storeSelectButton.length > 0) {\n\t\t\t\tself.$storeSelectButton.attr('href', Urls.storeLandingPage + '?Store=' + bopisStore).addClass('ready');; \n\t\t\t}\n\t        \n\t        $('.product-add-to-cart button').attr('disabled', 'disabled');\n\t        \n\t        if (bopisStore) {\n\t        \tself.$bopisButton.attr('state', 'pickup');\n\t        } else {\n\t        \tself.$bopisButton.attr('state', 'ship');\n\t        }\n\t    });\n\n\t\tthis.$container.off('click.UseMyLocation').on('click.UseMyLocation', '.use-my-location', function (event) {\n\t\t\tevent.preventDefault();\n\t\t\tself.geolocationSearch();\n\t\t});\n\n\t\t$(document).off('LocationSearch.GeolocationSearch').on('LocationSearch.GeolocationSearch', function (event) {\n\t\t\tself.geolocationSearch();\n\t\t});\n\n\t\tthis.$container.off('click.LoadMore').on('click.LoadMore', '.load-more', function (event) {\n\t\t\tevent.preventDefault();\n\n\t\t\t$(this).loading({ IsLabelShown: false });\n\t\t\tself.dataBuffer.offset += self.dataBuffer.limit;\n\t\t\tif (self.dataBuffer.loadMore == 'geolocationPosition') {\n\t\t\t\tself.getStoreListForGeolocationPosition(self.dataBuffer.geolocationPosition, true);\n\t\t\t} else if (self.dataBuffer.loadMore == 'postalCode') {\n\t\t\t\tself.getStoreListForPostalCode(self.$formInputPostalCode.val(), true);\n\t\t\t}\n\t\t});\n\t}\n\n\tthis.geolocationSearch = function() {\n\t\tvar self = this;\n\t\tself.dataBuffer.loadMore = 'geolocationPosition';\n\t\tself.dataBuffer.offset = 0;\n\t\tthis.$result.html('');\n\t\tthis.$result.loading();\n\t\tGeolocationHelper.GetPosition().then(function(position) {\n\t\t\tself.dataBuffer.geolocationPosition = position;\n\t\t\tself.getStoreListForGeolocationPosition(self.dataBuffer.geolocationPosition);\n\t\t}).catch(function() {\n\t\t\tif (self.$result.attr('loading')) {\n\t\t\t\tself.$result.loading('destroy');\n\t\t\t}\n\t\t});\n\t}\n\n\tthis.remove = function() {\n\t\tthis.validator.destroy();\n\t\t$('.product-add-to-cart button').removeAttr('disabled');\n\t}\n\t\n\tthis.getStoreListForGeolocationPosition = function(position, isLoadMore) {\n\t\tvar self = this;\n\t\tvar geolocationPosition;\n\t\tif (position && position.coords) {\n\t\t\tgeolocationPosition = {\n\t\t\t\tcoords: {\n\t\t\t\t\taccuracy: position.coords.accuracy,\n\t\t\t\t\tlatitude: position.coords.latitude,\n\t\t\t\t\tlongitude: position.coords.longitude\n\t\t\t\t},\n\t\t\t\ttimestamp: position.timestamp\n\t\t\t};\n\t\t}\n\t\t$.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.Bopis.GetLocationsForGeolocationPosition,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\tChannel: this.options.Channel,\n\t\t\t\tSource: this.options.Source,\n\t\t\t\tGeolocationPosition: geolocationPosition,\n\t\t\t\tRadius: parseFloat(this.$formInputRadius.val()) || 3000,\n\t\t\t\tLimit: this.dataBuffer.limit,\n\t\t\t\tOffset: this.dataBuffer.offset\n\t\t\t}),\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\tself.renderStoreList(data, isLoadMore);\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\t\n\t\t\t}\n\t\t});\t\t\n\t}\n\n\tthis.getStoreListForPostalCode = function(postalCode, isLoadMore) {\n\t\tvar self = this;\n\t\t$.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.Bopis.GetStoresByCityStatePostalSearchKeyAjax,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\tChannel: self.options.Channel,\n\t\t\t\tSource: self.options.Source,\n\t\t\t\tSearchKey: postalCode,\n\t\t\t\tRadius: self.$formInputRadius.val() || 3000,\n\t\t\t\tLimit: self.dataBuffer.limit,\n\t\t\t\tOffset: self.dataBuffer.offset\n\t\t\t}),\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\tself.renderStoreList(data, isLoadMore);\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tif (self.options.errorCallback) {\n\t\t\t\t\tself.options.errorCallback();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tthis.renderStoreList = function(data, isLoadMore) {\n\t\tvar locationData;\n\t\tif (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data && data.InquiryResult.data.length > 0) {\n\t\t\tlocationData = data.InquiryResult.data;\n\t\t}\n\n\t\tthis.$container.attr('state', 'result');\n\t\tif (locationData && locationData.length > 0) {\n\t\t\tvar locationsDisplayed = 0;\n\t\t\tlocationData = locationData.sort(function(left, right) {\n\t\t\t\treturn left.distance - right.distance;\n\t\t\t});\n\t\t\t\n\t\t\tthis.dataBuffer['StoresDisplayed'] = [];\n\t\t\tthis.$container.attr('result-count', locationData.length);\n\t\t\t\n\t\t\tvar storeListHtml = '';\n\t\t\tfor (var locationElement in locationData) {\n\t\t\t\tvar location = locationData[locationElement];\n\t\t\t\t\n\t\t\t\tif (location && !this.dataBuffer['StoresDisplayed'][location.code]) {\n\t\t\t\t\tvar storePhone = '';\n\t\t\t\t\tvar storeOpenUntil = '';\n\t\t\t\t\tif (location.StoreInfo) {\n\t\t\t\t\t\tif (location.StoreInfo.Phone) {\n\t\t\t\t\t\t\tstorePhone = location.StoreInfo.Phone;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (location.StoreInfo.OpenUntil) {\n\t\t\t\t\t\t\tstoreOpenUntil = location.StoreInfo.OpenUntil;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar locationName;\n\t\t\t\t\tif (this.options && this.options.StoreUIVersion == '2024Redesign') {\n\t\t\t\t\t\tlocationName = '<strong>' + location.StoreInfo.Name + ' - ' + location.StoreInfo.StoreId + '</strong>';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlocationName = '<strong>' + location.StoreInfo.Name + '</strong>';\n\t\t\t\t\t}\n\t\t\t\t\tif (this.options && this.options.AgentStoreID == location.code) {\n\t\t\t\t\t\tlocationName += '<br/>(Your Store)';\n\t\t\t\t\t}\n\t\t\t\t\tvar html = locationName + '<br/>' +\n\t\t\t\t\t\t\t\tlocation.StoreInfo.Address1 + '<br />' + \n\t\t\t\t\t\t\t\tlocation.StoreInfo.City + ', ' + location.StoreInfo.StateCodeParsed + ' ' + location.StoreInfo.PostalCode.substr(0, 5) + '<br />' +\n\t\t\t\t\t\t\t\tstorePhone;\n\t\t\t\t\tif (pageContext.siteId == SiteConstants.BootBarnRspUS && storeOpenUntil) {\n\t\t\t\t\t\thtml += '<br />' + storeOpenUntil;\n\t\t\t\t\t}\n\n\t\t\t\t\tstoreListHtml += this.resultItemTemplate({\n\t\t\t\t\t\tStoreId: location.code,\n\t\t\t\t\t\tDistance: location.StoreInfo.Distance.toFixed(1) + '<br/>mi',\n\t\t\t\t\t\tSelected: '',\n\t\t\t\t\t\tLandingCategory: this.options.LandingCategory,\n\t\t\t\t\t\tStatusDisplay: storeOpenUntil,\n\t\t\t\t\t\tHtml: html\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tlocationsDisplayed++;\n\t\t\t\tif (locationsDisplayed >= this.dataBuffer.limit) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis.dataBuffer['StoresDisplayed'][location.code] = true;\n\t\t\t}\n\t\t\t\n\t\t\tvar resultHtml = this.resultContainerTemplate({\n\t\t\t\tHtml: storeListHtml\n\t\t\t});\n\t\t\tif (pageContext.siteId == SiteConstants.BootBarnRspUS && data.InquiryResult.meta.page < data.InquiryResult.meta.pages) {\n\t\t\t\tresultHtml += '<a href=\"#\" class=\"load-more\">Load More</a>';\n\t\t\t}\n\t\t\tif (this.$storeSearchButton.attr('loading')) {\n\t\t\t\tthis.$storeSearchButton.loading('destroy');\n\t\t\t}\n\t\t\tif (this.$result.attr('loading')) {\n\t\t\t\tthis.$result.loading('destroy');\n\t\t\t}\n\t\t\tif (isLoadMore) {\n\t\t\t\tthis.$result.find('.load-more').remove();\n\t\t\t\tthis.$result.append(resultHtml);\n\t\t\t} else {\n\t\t\t\tthis.$result.html(resultHtml);\n\t\t\t}\n\t\t} else if (!isLoadMore) {\n\t\t\tthis.$container.attr('result-count', '0');\n\t\t\tthis.$result.html('');\n\t\t}\n\t}\n\n\tthis.updateStoreDetails = function(storeId) {\n\t\tif (storeId) {\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'POST',\n\t\t\t\turl: Urls.Stores.SetMyStore,\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\tStoreId: storeId\n\t\t\t\t}),\n\t\t\t\tdataType: 'html',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t$('.my-store-panel').replaceWith(data);\n\t\t\t\t\t$('.my-store-modal').hide();\n\t\t\t\t\t$('.location-search-dialog').hide();\n\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\turl: Urls.Stores.GetMyStorePanel,\n\t\t\t\t\t\tdataType: 'html',\n\t\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t\t$('.my-store-panel').replaceWith(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\turl: Urls.Stores.GetMyStoreModal,\n\t\t\t\t\t\tdataType: 'html',\n\t\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t\t$('.my-store-modal').replaceWith(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\turl: Urls.getStoresPanel,\n\t\t\t\t\t\tdataType: 'html',\n\t\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t\t$('#location').html(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$(document).trigger('ShopMyStore.Update', storeId);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\t$('.my-store-modal').hide();\n\t\t\t\t\t$('.location-search-dialog').hide();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tthis.assignStoreId = function(storeId) {\n\t\tif (storeId) {\n\t\t\t$.ajax({\n\t\t\t\turl : Urls.assignStoreId,\n\t\t\t\tdata : { store_id : storeId },\n\t\t\t\tmethod : \"POST\",\n\t\t\t\tdataType : \"JSON\",\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tif ('success' in data && data['success'] == true) {\n\t\t\t\t\t\t// TODO: any follow-up needed client-side?\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\t\n\treturn this;\n}\n","'use strict';\n\nexports.ValidateProductLineItems = validateProductLineItems;\n\nvar options;\nvar buffer = {};\n\nfunction validateProductLineItems($bopisProductLineItems, optionsParameter) {\n\tif (optionsParameter) {\n\t\toptions = optionsParameter;\n\t}\n\t\n\tbuffer['TotalCount'] = $bopisProductLineItems.length;\n\tbuffer['LoadedCount'] = 0;\n\tbuffer['ProductLineItems'] = {};\n\t\n\t$bopisProductLineItems.each(function(index, element) {\n\t\tvar $this = $(this);\n\t\tvar uuid = $this.attr('uuid');\n\t\tvar productId = $this.attr('sku');\n\t\tvar storeId = $this.attr('store');\n\t\tvar quantityRequested = $this.closest('.order-item').find('.qty-edit input[type=\"text\"]').val();\n\t\t\n\t\t$.ajax({\n            method: 'POST',\n            url: Urls.Bopis.GetStoreInventoryForProductForStore,\n            contentType: 'application/json',\n            async: true,\n            data: JSON.stringify({\n                ProductId: productId,\n                StoreId: storeId\n            }),\n            dataType: 'json',\n            success: function(data) {\n                var inquiryResult;\n                if (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data[0].inventory_supplies) {\n                    inquiryResult = data.InquiryResult.data[0].inventory_supplies;\n                }\n                \n                if (inquiryResult && inquiryResult && inquiryResult.length > 0) {\n                \tbuffer['ProductLineItems'][uuid] = {\n                \t\tQuantityRequested: parseInt(quantityRequested, 10),\n                \t\tInquiryResult: inquiryResult\n                \t};\n                \t\n                    buffer['LoadedCount'] += 1;\n                    validateProductLineItemsSuccess();\n                } else {\n                \t$result.html('');\n                    \n                    if (options && options.ErrorCallback) {\n                    \toptions.errorCallback();\n                    }\n                }\n            },\n            error: function() {\n                if (options && options.ErrorCallback) {\n                \toptions.errorCallback();\n                }\n            }\n        });\n\t});\n\t\n\treturn false;\n}\n\nfunction validateProductLineItemsSuccess() {\n\tif (buffer['LoadedCount'] == buffer['TotalCount']) {\n\t\tvar isBopisInventoryValid = true;\n\t\tfor (var productLineItemUUID in buffer['ProductLineItems']) {\n\t\t\tvar productLineItem\t= buffer['ProductLineItems'][productLineItemUUID];\n\t\t\t\n\t\t\tif (productLineItem.QuantityRequested > productLineItem.InquiryResult[0].detail.quantity) {\n\t\t\t\tisBopisInventoryValid = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (options && options.SuccessEvent) {\n\t\t\t$(document).trigger(options.SuccessEvent, {\n\t\t\t\tSubmitPaymentForBopis: true,\n\t\t\t\tIsBopisInventoryValid: isBopisInventoryValid\n\t\t\t});\n\t\t}\n\t}\n}","'use strict';\n\nvar dialog = require('../../dialog');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar loadingIndicator = require('../../components/LoadingIndicator');\n\nexports.initialize = initialize;\n\nvar options;\nvar dataBuffer;\n\nfunction initialize(optionsParameter) {\n\tdataBuffer = {};\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\n\t$('#shop-your-store-dialog').find('.store-name').text(options.StoreName);\n\t$('#shop-your-store-dialog').find('.category-links a').each(function(index, element) {\n\t\tvar $this = $(this);\n\t\tvar href = $this.attr('href');\n\t\tif (href.indexOf('?') > -1) {\n\t\t\thref = href.substr(0, href.indexOf('?'));\n\t\t}\n\t\t$this.attr('href', href + '?prefn1=availableStores&prefv1=' + options.StoreId + '&shopmystore=true');\n\t})\n\t\n\t// GoogleTagManagerClient.PushDataLayerForEvent('roadieFormDisplay');\n\tdialog.open({\n\t\thtml: $('#shop-your-store-dialog').html(),\n\t\toptions: {\n\t\t\tdialogClass: 'shop-your-store-dialog',\n\t\t\twidth: 380,\n\t\t\tdraggable: false,\n\t\t\tresizable: false,\n\t\t\topen: function(event, ui) {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar $shopYourStoreToggle = $this.find('.shop-my-store-toggle .checkbox-toggle');\n\t\t\t\tdataBuffer['toggleTimer'] = setInterval(function() {\n\t\t\t\t\t$shopYourStoreToggle.click();\n\t\t\t\t}, 2000);\n            },\n            close: function(event, ui) {\n\t\t\t\tclearInterval(dataBuffer['toggleTimer']);\n\t\t\t\t$(this).find('.shop-my-store-toggle .checkbox-toggle input').prop('checked', false);\n            }\n\t\t}\n\t});\n}","'use strict';\n\nvar _ = require('lodash');\nvar dialog = require('../../dialog');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar LocalDeliveryDialog = require('./LocalDeliveryDialog');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar tooltip = require('../../tooltip');\nvar ValidationSettings = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ZipCodeToStateMap = require('../../../../../bc_sheplersbootbarn_core/cartridge/data/ZipCodeToStateMap.json');\n\nexports.initialize = initialize;\nexports.search = search;\nexports.remove = remove;\n\nvar options;\nvar validator;\nvar dataBuffer;\n\nvar resultContainerTemplate;\nvar resultItemTemplate;\nvar localDeliveryDecorator;\n\nvar $container;\nvar $form;\nvar $result;\nvar $formInputPostalCode;\nvar $storeSearchButton;\nvar $storeSearchButtonContainer;\nvar $bopisButton;\nvar $errorMessage;\nvar $inputTooltip;\n\nfunction initialize($containerParameter, optionsParameter) {\n\tdataBuffer = {};\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\n\tresultContainerTemplate = _.template($('#template-bopis-result-container').html(), TemplateConstants.Lodash.Settings);\n\tresultItemTemplate = _.template($('#template-bopis-result-item').html(), TemplateConstants.Lodash.Settings);\n\tlocalDeliveryDecorator = _.template($('#template-bopis-localdelivery-decorator').html(), TemplateConstants.Lodash.Settings);\n\n\t$container = $containerParameter;\n\t$form = $container.find('form');\n\t$result = $container.find('.result');\n\t$formInputPostalCode = $form.find('input[name$=\"_postalCode\"]');\n\t$storeSearchButton = $container.find('.btn.store-search');\n\t$storeSearchButtonContainer = $container.find('.btn-store-search-container');\n\t$bopisButton = $container.find('.btn.bopis');\n    $errorMessage = $form.find('span.error');\n\t$inputTooltip = $formInputPostalCode.parent();\n\n    if (options && options.IsVariantSelected) {\n\t\t$('.btn.store-search').removeAttr('disabled');\n\t\t$inputTooltip.removeClass('tooltip');\n    }\n\n\ttooltip.init({\n\t\titems: '.store-search-tooltip',\n\t\ttooltipClass: 'store-search-tooltip'\n\t}, $('.store-search-tooltip'));\n\n    $container.attr('state', 'form');\n    validator = $form.validate(ValidationSettings.Global);\n\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n    $formInputPostalCode.rules('add', ValidationRules.ZipCode);\n\n\tif ($container.attr('state') === 'form' && validator.checkForm() && !$storeSearchButton.hasClass('ready')) {\n\t\t$storeSearchButton.addClass('ready');\n    }\n\n    $form.off('click.apply').on('click.apply', '.btn.store-search:not([loading])', function (event) {\n\t\tevent.preventDefault();\n\t\tsearch();\n\t});\n\n    $container.off('click.apply').on('click.apply', '.btn.bopis:not([loading])', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar selectedLocation = dataBuffer['StoresDisplayed'][$('input[name=\"Bopis_StoreSearch_StoreId\"]:checked').val()];\n\t\tif (selectedLocation) {\n\t\t\tif (options.LocalDelivery.Enabled) {\n\t\t\t\tLocalDeliveryDialog.initialize(options, selectedLocation);\n\t\t\t} else {\n\t\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', { bopis: true, shippingOption: 'pickup', channel: options.Channel });\n\t\t\t}\n\t\t} else {\n\t\t\t$(document).trigger('ProductDetailPage.Bopis.AddToCart', { channel: options.Channel });\n\t\t}\n\t});\n\n    $formInputPostalCode.off('keydown.BopisStoreSearch.ValidationCheck').on('keydown.BopisStoreSearch.ValidationCheck', function (event) {\n    \tif ($formInputPostalCode.val().length == 5 && parseInt(event.key, 10) == event.key && !window.getSelection().toString()) {\n    \t\tevent.preventDefault();\n    \t}\n    });\n\n    $formInputPostalCode.off('change.BopisStoreSearch.ValidationCheck').on('change.BopisStoreSearch.ValidationCheck', function (event) {\n    \tif ($formInputPostalCode.val().length > 5) {\n    \t\t$formInputPostalCode.val($formInputPostalCode.val().substr(0, 5));\n    \t}\n    });\n\n    $formInputPostalCode.off('keyup.BopisStoreSearch.ValidationCheck, change.BopisStoreSearch.ValidationCheck').on('keyup.BopisStoreSearch.ValidationCheck, change.BopisStoreSearch.ValidationCheck', function (event) {\n    \tevent.stopImmediatePropagation();\n\n\t\tif ($container.attr('state') === 'form') {\n\t\t\tif (validator.checkForm() && !$storeSearchButton.hasClass('ready')) {\n\t\t\t\t$storeSearchButton.addClass('ready');\n\t\t\t} else if (!validator.checkForm() && $storeSearchButton.hasClass('ready')) {\n\t\t\t\t$storeSearchButton.removeClass('ready');\n\t\t\t}\n\t\t}\n\n    \tif ($container.attr('state') === 'result') {\n\t\t\t$container.attr('state', 'form');\n        \t$formInputPostalCode.val('');\n        }\n    });\n\n    $(document).off('mousedown.BopisStoreSearch.ValidationClear').on('mousedown.BopisStoreSearch.ValidationClear', function (event) {\n        if (validator && $(event.target).closest($container).length == 0) {\n            validator.resetForm();\n            $errorMessage.html('').hide();\n        }\n    });\n\n    $(document).off('Bopis.StoreSearch.Reset').on('Bopis.StoreSearch.Reset', function (event) {\n\t\treset();\n    });\n\n    $container.off('click.BopisStoreSearch.Reset').on('click.BopisStoreSearch.Reset', '.reset', function (event) {\n\t\treset();\n    });\n\n    $(document).off('ProductDetailPage.Variant.StoreSearch').on('ProductDetailPage.Variant.StoreSearch', function (event) {\n        if (options.SelectedLocations) {\n\t\t\tvar sizeSelected = $('div.product-variations .size.size-options li.selected');\n\t\t\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\t\t\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\t\t\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\t\t\tvar isColorSelected = $('div.product-variations .color.color-options li.selected').length;\n\n\t\t\tif (isSizeSelected && isColorSelected) {\n\t\t\t\tsearch();\n\t\t\t}\n\t\t}\n    });\n\n    $container.off('click.BopisStoreSearch.Selection').on('click.BopisStoreSearch.Selection', 'input[name=\"Bopis_StoreSearch_StoreId\"]', function (event) {\n        var bopisStore = $('input[name=\"Bopis_StoreSearch_StoreId\"]:checked').val();\n\n        if (!$bopisButton.hasClass('ready')) {\n        \t$bopisButton.addClass('ready');\n        }\n\n        $('.product-add-to-cart button').attr('disabled', 'disabled').addClass('hidden');\n\n        if (bopisStore) {\n        \t$bopisButton.attr('state', 'pickup');\n        } else {\n        \t$bopisButton.attr('state', 'ship');\n        }\n    });\n}\n\nfunction reset() {\n\t$formInputPostalCode.val('');\n    $container.attr('state', 'form');\n    $storeSearchButton.removeClass('ready');\n    $('.product-add-to-cart button').removeAttr('disabled').removeClass('hidden');\n    $bopisButton.removeClass('ready');\n}\n\nfunction search() {\n\tvar sizeSelected = $('div.product-variations .size.size-options li.selected');\n\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\tvar isColorSelected = $('div.product-variations .color.color-options li.selected').length;\n\n    if (!isSizeSelected && !isColorSelected) {\n    \t$errorMessage.html('Please select a size and color first.').show();\n    \treturn false;\n    } else if (!isSizeSelected) {\n    \t$errorMessage.html('Please select a size first.').show();\n    \treturn false;\n    } else if (!isColorSelected) {\n    \t$errorMessage.html('Please select a color first.').show();\n    \treturn false;\n    } else {\n    \t$errorMessage.html('').hide();\n    \t$storeSearchButton.removeAttr('disabled');\n    }\n\n    if (Urls && Urls.Bopis.GetStoreInventoryForProductForPostalCode && validator.valid()) {\n        $storeSearchButtonContainer.loading({\n            IsImageShown: false,\n\t\t\tLabel: Resources.Loading.Loading,\n\t\t\tBackgroundColor: $storeSearchButton.css('background-color')\n        });\n\n\t\t$.ajax({\n            method: 'POST',\n            url: Urls.Bopis.GetStoreInventoryForProductForPostalCode,\n            contentType: 'application/json',\n            data: JSON.stringify({\n\t\t\t\tChannel: options.Channel,\n\t\t\t\tSource: options.Source,\n                ProductId: $('.product-add-to-cart input[name=\"pid\"]').val(),\n                PostalCode: $formInputPostalCode.val()\n            }),\n            dataType: 'json',\n            success: function(data) {\n\t\t\t\tif ($storeSearchButtonContainer.attr('loading')) {\n                \t$storeSearchButtonContainer.loading('destroy');\n\t\t\t\t}\n                $('.product-add-to-cart button').attr('disabled', 'disabled').addClass('hidden');\n\n                var inquiryResult;\n                if (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data && data.InquiryResult.data.length > 0 && data.InquiryResult.data[0].inventory_supplies) {\n                    inquiryResult = data.InquiryResult.data[0].inventory_supplies;\n                }\n\n                $container.attr('state', 'result');\n                if (inquiryResult && inquiryResult.length > 0) {\n                \tdataBuffer['StoresDisplayed'] = [];\n                    $container.attr('result-count', inquiryResult.length);\n\n                    var storeListHtml = '';\n                    var isStoreSelected = false;\n                    var selectedStoreAttribute;\n                    for (var inventoryRecordElement in inquiryResult) {\n                    \tvar inventoryRecord = inquiryResult[inventoryRecordElement];\n\n                    \tif (inventoryRecord.detail && inventoryRecord.detail.quantity > 0 && !dataBuffer['StoresDisplayed'][inventoryRecord.location.code]) {\n                    \t\tif (options && options.SelectedLocations == inventoryRecord.location.code) {\n                    \t\t\tisStoreSelected = true;\n                    \t\t\tselectedStoreAttribute ='checked';\n                    \t\t} else {\n                    \t\t\tselectedStoreAttribute = '';\n                    \t\t}\n\n                    \t\tvar localDeliveryHtml = '';\n                    \t\tif (options.LocalDelivery.Enabled && isLocationInLocalDeliveryRadius(inventoryRecord.location) && inventoryRecord.location.local_delivery_enabled) {\n                    \t\t\tlocalDeliveryHtml = localDeliveryDecorator();\n                    \t\t}\n\n\t\t\t\t\t\t\tvar labelPrefix;\n\t\t\t\t\t\t\tif (options && options.IsStoreHoliday) {\n\t\t\t\t\t\t\t\tlabelPrefix = 'Available At ';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabelPrefix = 'Available TODAY At ';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (inventoryRecord.location.postal_address.namePrefix) {\n\t\t\t\t\t\t\t\tlabelPrefix += '<span class=\"nowrap\">' + inventoryRecord.location.postal_address.namePrefix + '</span> ';\n\t\t\t\t\t\t\t}\n\n                        \tstoreListHtml += resultItemTemplate({\n                        \t\tStoreId: inventoryRecord.location.code,\n                        \t\tQuantityAvailable: inventoryRecord.detail.quantity,\n\t                        \tHtml: labelPrefix + inventoryRecord.location.postal_address.name + ',<br/>' + inventoryRecord.location.postal_address.address_line1 + ', ' + inventoryRecord.location.postal_address.city + ', ' + inventoryRecord.location.postal_address.province_or_state,\n\t                        \tSelected: selectedStoreAttribute,\n\t                        \tLocalDelivery: localDeliveryHtml\n\t                        });\n                    \t}\n\n                    \tdataBuffer['StoresDisplayed'][inventoryRecord.location.code] = inventoryRecord;\n                    }\n                    storeListHtml += resultItemTemplate({\n                    \tStoreId: '',\n                    \tQuantityAvailable: '',\n                    \tHtml: 'Ship Instead',\n                    \tSelected: '',\n                    \tLocalDelivery: ''\n                    });\n\n                    var resultHtml = resultContainerTemplate({\n                    \tHtml: storeListHtml\n                    });\n\n                    if (isStoreSelected) {\n                    \t$bopisButton.addClass('ready');\n                    }\n\n                    $result.html(resultHtml);\n\n\t\t\t\t\ttooltip.init({\n\t\t\t        \titems: '.tooltip'\n                \t}, $result);\n\n                    if (options.successCallback) {\n                    \toptions.successCallback(inquiryResult);\n                    }\n                } else {\n\t\t\t\t\t$('.product-add-to-cart button').removeAttr('disabled').removeClass('hidden');\n                    $container.attr('result-count', '0');\n                \t$result.html('');\n\n                    if (options.errorCallback) {\n                    \toptions.errorCallback();\n                    }\n                }\n            },\n            error: function() {\n\t\t\t\tif ($storeSearchButtonContainer.attr('loading')) {\n            \t\t$storeSearchButtonContainer.loading('destroy');\n\t\t\t\t}\n\n                if (options.errorCallback) {\n                \toptions.errorCallback();\n                }\n            }\n        });\n\t}\n}\n\nfunction remove() {\n\tvalidator.destroy();\n\t$('.product-add-to-cart button').removeAttr('disabled').removeClass('hidden');\n}\n\nfunction isLocationInLocalDeliveryRadius(location) {\n\tvar localDeliveryRadius;\n\tif (location.local_delivery_vendor && location.local_delivery_vendor == 'GoLocal') {\n\t\tlocalDeliveryRadius = options.LocalDelivery.RadiusForGoLocal;\n\t} else {\n\t\tlocalDeliveryRadius = options.LocalDelivery.RadiusForRoadie;\n\t}\t\n\n\tif (localDeliveryRadius && location && location.distance && localDeliveryRadius >= location.distance) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}","'use strict';\n\nvar dialog = require('./dialog');\nvar util = require('./util');\nvar SessionAttributes = window.SessionAttributes;\n\n/**\n * @function captcha    Used to display/control the scrim containing the simulated captcha code\n **/\nmodule.exports = function () {\n\t/**\n\t * if the session.privacy.ratelimited element is present then show the notification\n\t * NOTE: You will probably want to replace this with a call to an actual CAPTCHA system to replace the simple one here\n\t */\n\tif (SessionAttributes.SHOW_CAPTCHA) {\n\t\tdialog.open({\n\t\t\thtml: '<p>' + Resources.PASSWORD_TIP_1 + '</p><p>' + Resources.PASSWORD_TIP_2 + '</p>',\n\t\t\toptions: {\n\t\t\t\ttitle: Resources.ARE_YOU_HUMAN,\n\t\t\t\tcloseOnEscape: false,\n\t\t\t\tdialogClass: 'no-close password-error',\n\t\t\t\twidth: 400,\n\t\t\t\tbuttons: [{\n\t\t\t\t\ttext: Resources.OK,\n\t\t\t\t\tclick: function () {\n\t\t\t\t\t\tvar url = util.appendParamsToUrl(Urls.rateLimiterReset, {format: 'ajax'});\n\t\t\t\t\t\t$.ajax({\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t});\n\t\t\t\t\t\t$(this).dialog('close');\n\t\t\t\t\t}\n\t\t\t\t}]\n\t\t\t}\n\t\t});\n\t}\n};\n","'use strict';\n\nvar page = require('./page'),\n    util = require('./util'),\n    TPromise = require('promise');\n\nvar _currentCategory = '',\n    MAX_ACTIVE = 6;\n\n/**\n * @private\n * @function\n * @description Verifies the number of elements in the compare container and updates it with sequential classes for ui targeting\n */\nfunction refreshContainer() {\n    var $compareContainer = $('.compare-items');\n    var $compareItems = $compareContainer.find('.compare-item');\n    var numActive = $compareItems.filter('.active').length;\n\n    if (numActive < 2) {\n        $('#compare-items-button').attr('disabled', 'disabled');\n    } else {\n        $('#compare-items-button').removeAttr('disabled');\n    }\n\n    $compareContainer.toggle(numActive > 0);\n}\n/**\n * @private\n * @function\n * @description Adds an item to the compare container and refreshes it\n */\nfunction addToList(data) {\n    // get the first compare-item not currently active\n    var $item = $('.compare-items .compare-item').not('.active').first(),\n        $productTile = $('#' + data.uuid);\n\n    if ($item.length === 0) {\n        if ($productTile.length > 0) {\n            $productTile.find('.compare-check')[0].checked = false;\n        }\n        window.alert(Resources.COMPARE_ADD_FAIL);\n        return;\n    }\n\n    // if already added somehow, return\n    if ($('[data-uuid=\"' + data.uuid + '\"]').length > 0) {\n        return;\n    }\n    // set as active item\n    $item.addClass('active')\n        .attr('data-uuid', data.uuid)\n        .attr('data-itemid', data.itemid)\n        .data('uuid', data.uuid)\n        .data('itemid', data.itemid)\n        .append($(data.img).clone().addClass('compare-item-image'));\n}\n/**\n * @private\n * @function\n * description Removes an item from the compare container and refreshes it\n */\nfunction removeFromList($item) {\n    if ($item.length === 0) { return; }\n    // remove class, data and id from item\n    $item.removeClass('active')\n        .removeAttr('data-uuid')\n        .removeAttr('data-itemid')\n        .data('uuid', '')\n        .data('itemid', '')\n        // remove the image\n        .find('.compare-item-image').remove();\n}\n\nfunction addProductAjax(args) {\n    var promise = new TPromise(function (resolve, reject) {\n        $.ajax({\n            url: Urls.compareAdd,\n            data: {\n                pid: args.itemid,\n                category: _currentCategory\n            },\n            dataType: 'json'\n        }).done(function (response) {\n            if (!response || !response.success) {\n                reject(new Error(Resources.COMPARE_ADD_FAIL));\n            } else {\n                resolve(response);\n            }\n        }).fail(function (jqxhr, status, err) {\n            reject(new Error(err));\n        });\n    });\n    return promise;\n}\n\nfunction removeProductAjax(args) {\n    var promise = new TPromise(function (resolve, reject) {\n        $.ajax({\n            url: Urls.compareRemove,\n            data: {\n                pid: args.itemid,\n                category: _currentCategory\n            },\n            dataType: 'json'\n        }).done(function (response) {\n            if (!response || !response.success) {\n                reject(new Error(Resources.COMPARE_REMOVE_FAIL));\n            } else {\n                resolve(response);\n            }\n        }).fail(function (jqxhr, status, err) {\n            reject(new Error(err));\n        });\n    });\n    return promise;\n}\n\nfunction shiftImages() {\n    return new TPromise(function (resolve) {\n        var $items = $('.compare-items .compare-item');\n        $items.each(function (i, item) {\n            var $item = $(item);\n            // last item\n            if (i === $items.length - 1) {\n                return removeFromList($item);\n            }\n            var $next = $items.eq(i + 1);\n            if ($next.hasClass('active')) {\n                // remove its own image\n                $next.find('.compare-item-image').detach().appendTo($item);\n                $item.addClass('active')\n                    .attr('data-uuid', $next.data('uuid'))\n                    .attr('data-itemid', $next.data('itemid'))\n                    .data('uuid', $next.data('uuid'))\n                    .data('itemid', $next.data('itemid'));\n            }\n        });\n        resolve();\n    });\n}\n\n/**\n * @function\n * @description Adds product to the compare table\n */\nfunction addProduct(args) {\n    var promise;\n    var $items = $('.compare-items .compare-item');\n    var $cb = $(args.cb);\n    var numActive = $items.filter('.active').length;\n    if (numActive === MAX_ACTIVE) {\n        if (!window.confirm(Resources.COMPARE_CONFIRMATION)) {\n            $cb[0].checked = false;\n            return;\n        }\n\n        // remove product using id\n        var $firstItem = $items.first();\n        promise = removeItem($firstItem).then(function () {\n            return shiftImages();\n        });\n    } else {\n        promise = TPromise.resolve(0);\n    }\n    return promise.then(function () {\n        return addProductAjax(args).then(function () {\n            addToList(args);\n            if ($cb && $cb.length > 0) { $cb[0].checked = true; }\n            refreshContainer();\n        });\n    }).then(null, function () {\n        if ($cb && $cb.length > 0) { $cb[0].checked = false; }\n    });\n}\n\n/**\n * @function\n * @description Removes product from the compare table\n * @param {object} args - the arguments object should have the following properties: itemid, uuid and cb (checkbox)\n */\nfunction removeProduct(args) {\n    var $cb = args.cb ? $(args.cb) : null;\n    return removeProductAjax(args).then(function () {\n        var $item = $('[data-uuid=\"' + args.uuid + '\"]');\n        removeFromList($item);\n        if ($cb && $cb.length > 0) { $cb[0].checked = false; }\n        refreshContainer();\n    }, function () {\n        if ($cb && $cb.length > 0) { $cb[0].checked = true; }\n    });\n}\n\nfunction removeItem($item) {\n    var uuid = $item.data('uuid'),\n        $productTile = $('#' + uuid);\n    return removeProduct({\n        itemid: $item.data('itemid'),\n        uuid: uuid,\n        cb: ($productTile.length === 0) ? null : $productTile.find('.compare-check')\n    });\n}\n\n/**\n * @private\n * @function\n * @description Initializes the DOM-Object of the compare container\n */\nfunction initializeDom() {\n    var $compareContainer = $('.compare-items');\n    _currentCategory = $compareContainer.data('category') || '';\n    var $active = $compareContainer.find('.compare-item').filter('.active');\n    $active.each(function () {\n        var $productTile = $('#' +  $(this).data('uuid'));\n        if ($productTile.length === 0) {return;}\n        $productTile.find('.compare-check')[0].checked = true;\n    });\n    // set container state\n    refreshContainer();\n}\n\n/**\n * @private\n * @function\n * @description Initializes the events on the compare container\n */\nfunction initializeEvents() {\n    // add event to buttons to remove products\n    $('.compare-item').on('click', '.compare-item-remove', function () {\n        removeItem($(this).closest('.compare-item'));\n    });\n\n    // Button to go to compare page\n    $('#compare-items-button').on('click', function () {\n        page.redirect(util.appendParamToURL(Urls.compareShow, 'category', _currentCategory));\n    });\n\n    // Button to clear all compared items\n    // rely on refreshContainer to take care of hiding the container\n    $('#clear-compared-items').on('click', function () {\n        $('.compare-items .active').each(function () {\n            removeItem($(this));\n        });\n    });\n}\n\nexports.init = function () {\n    initializeDom();\n    initializeEvents();\n};\n\nexports.addProduct = addProduct;\nexports.removeProduct = removeProduct;\n","'use strict';\n\nvar dialog = require('../../js/dialog');\n\nvar openCarouselVideoModal = function(event) {\n    var $videoElement = $('[data-carousel-video-element]').wrap('<div class=\"video-container\"></div>').parent();\n    \n    dialog.open({\n        html: $videoElement[0].outerHTML,\n        options: {\n            dialogClass: 'fixed carousel-video-modal',\n            width: '100%',\n            height: '100%',\n\t\t\tdraggable: false,\n\t\t\tresizable: false,\n            open: function(event, ui) {\n                var $this = $(this);\n                $this.find('.carousel-video-element')[0].play();\n            },\n            close: function(event, ui) {\n                var $this = $(this);\n                $this.find('.carousel-video-element')[0].pause();\n            }\n        }\n    });\n}\n\nfunction initialize() {\n\t$(document).off('click.CarouselVideo.Play').on('click.CarouselVideo.Play', '.product-primary-image [data-carousel-video]', openCarouselVideoModal);\n\n\t$(document).off('click.CarouselVideo.Catch').on('click.CarouselVideo.Catch', '.product-primary-image .carousel-video-link', function(event) {\n\t\tevent.preventDefault();\n\t});\n}\n\nmodule.exports.init = initialize;\n","'use strict';\n\nexports.initialize = initialize;\n\nfunction initialize() {\n\t$(document).off('click.HeaderBanner.Close').on('click.HeaderBanner.Close', '.header-banner .close', function(event) {\n\t\tevent.preventDefault();\n\t\tvar $this = $(this);\n\t\t\n\t\tvar contentAssetId = $this.closest('[content-asset-id]').attr('content-asset-id');\n\t\tif (contentAssetId) {\n\t\t\tacknowledge(contentAssetId, 'Yes', function() {\n\t\t\t\t$('.header-banner').hide();\n\t\t\t\t$(document).trigger('app.resize');\n\t\t\t});\n\t\t}\n\t});\n\n\t$(document).off('click.CookieNotification.Yes').on('click.CookieNotification.Yes', '.notification.cpra-cookie-notification .actions .yes', function(event) {\n\t\tevent.preventDefault();\n\t\tvar $this = $(this);\n\t\t\n\t\t$this.closest('.notification').addClass('hidden');\n\t\tacknowledge('Cookies', 'Yes');\n\t});\n\t\n\t$(document).off('click.CookieNotification.No').on('click.CookieNotification.No', '.notification.cpra-cookie-notification .actions .no', function(event) {\n\t\tevent.preventDefault();\n\t\tvar $this = $(this);\n\t\t\n\t\twindow.location.href = $this.attr('href');\n\t\tacknowledge('Cookies', 'No');\n\t});\n}\n\nfunction acknowledge(notification, acknowledgement, callbackSuccessParameter, callbackErrorParameter) {\n\tvar callbackSuccess = callbackSuccessParameter || function() { };\n\tvar callbackError = callbackErrorParameter || function() { };\n\n\tif (notification && acknowledgement) {\n\t\t$.ajax({\n\t\t\turl: Urls.CookieNotification.Acknowledge,\n\t\t\ttype: 'POST',\n\t\t\tdata: {\n\t\t\t\tNotification: notification,\n\t\t\t\tAcknowledgement: acknowledgement\n\t\t\t},\n\t\t\tdataType: 'json',\n\t\t\tsuccess: callbackSuccess,\n\t\t\terror: callbackError\n\t\t});\n\t}\n}","'use strict';\n\nvar dialog = require('../dialog');\n\nvar ValidationSettings = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\n\nexports.initialize = initialize;\n\nfunction initialize($container) {\n\t$container.find('[email-form]').each(function (index, element) {\n\t\tvar $form = $(element);\n\t\tvar formType = $form.attr('email-form');\n\t\tappendCSRFToken($form);\n\n\t\tif (formType && typeof handlers[formType] == 'function') {\n\t\t\thandlers[formType]($form);\n\t\t}\n\t});\n}\n\nvar handlers = {\n\t'cpra': function($form) {\n\t\tvar $requiredFields = $form.find('input.required');\n\t\tvar $formNameFirst = $form.find('input[name$=\"name_first\"]');\n\t\tvar $formNameLast = $form.find('input[name$=\"name_last\"]');\n\t\tvar $formEmail = $form.find('input[name$=\"email\"]');\n\t\tvar $formPhone = $form.find('input[name$=\"phone\"]');\n\t\tvar $formRequestType = $form.find('input[name$=\"requestType\"]');\n\t\t\n\t\tvar formValidator = $form.validate(ValidationSettings.Global);\n\t\t$.validator.addMethod('requiredExcludingPunctuation', ValidationHelper.ValidateRequiredExcludingPunctuation, Resources.INVALID_VALUE);\n\t\t$requiredFields.rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t\t$formEmail.rules('add', ValidationRules.Email);\n\t\t$form.find('span.error').remove();\n\t\t\n\t\t$form.find('input[type=\"submit\"]').on('click', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (formValidator.form()) {\n\t\t\t\tvar data = {\n\t\t\t\t\t'form_type': $form.attr('email-form'),\n\t\t\t\t\t'name_first': $formNameFirst.val(),\n\t\t\t\t\t'name_last': $formNameLast.val(),\n\t\t\t\t\t'email': $formEmail.val(),\n\t\t\t\t\t'phone': $formPhone.val(),\n//\t\t\t\t\t'request_type': $formRequestType.filter(':checked').map(function() { return this.value; }).get().join(' and ')\n\t\t\t\t\t'request_type': $formRequestType.val()\n\t\t\t\t}\n\n\t\t\t\t$form.find('input[type=\"hidden\"]').each(function () {\n\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\tdata[$this.attr('name')] = $this.val();\n\t\t\t\t});\n\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: Urls.EmailForm.Send,\n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\tdata: data,\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\tif (data && data.EmailSent) {\n\t\t\t\t\t\t\tvar $successContent = $('.content.cpra-form-success');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdialog.open({\n\t\t\t\t\t            html: $successContent.html(),\n\t\t\t\t\t            options: {\n\t\t\t\t\t                title: $successContent.attr('title'),\n\t\t\t\t\t                dialogClass: 'fixed checkout-terms' + ($successContent.attr('dialog-class') ? ' ' + $successContent.attr('dialog-class') : ''),\n\t\t\t\t\t                draggable: false,\n\t\t\t\t\t                open: function(event, ui) {\n\t\t\t\t\t                \tvar $this = $(this);\n\t\t\t\t\t        \n\t\t\t\t\t\t            \t$('body').addClass('dialog-open');\n\t\t\t\t\t\t            \t$this.scrollTop(0);\n\t\t\t\t\t\t            },\n\t\t\t\t\t\t            close: function(event, ui) {\n\t\t\t\t\t\t            \t$('body').removeClass('dialog-open');\n\t\t\t\t\t\t            }\n\t\t\t\t\t            }\n\t\t\t\t\t        });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar $errorContent = $('.content.cpra-form-error');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdialog.open({\n\t\t\t\t\t            html: $errorContent.html(),\n\t\t\t\t\t            options: {\n\t\t\t\t\t                title: $errorContent.attr('title'),\n\t\t\t\t\t                dialogClass: 'fixed checkout-terms' + ($errorContent.attr('dialog-class') ? ' ' + $errorContent.attr('dialog-class') : ''),\n\t\t\t\t\t                draggable: false,\n\t\t\t\t\t                open: function(event, ui) {\n\t\t\t\t\t                \tvar $this = $(this);\n\t\t\t\t\t        \n\t\t\t\t\t\t            \t$('body').addClass('dialog-open');\n\t\t\t\t\t\t            \t$this.scrollTop(0);\n\t\t\t\t\t\t            },\n\t\t\t\t\t\t            close: function(event, ui) {\n\t\t\t\t\t\t            \t$('body').removeClass('dialog-open');\n\t\t\t\t\t\t            }\n\t\t\t\t\t            }\n\t\t\t\t\t        });\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tvar $errorContent = $('.content.cpra-form-error');\n\t\t\t\t\t\t\n\t\t\t\t\t\tdialog.open({\n\t\t\t\t            html: $errorContent.html(),\n\t\t\t\t            options: {\n\t\t\t\t                title: $errorContent.attr('title'),\n\t\t\t\t                dialogClass: 'fixed checkout-terms' + ($errorContent.attr('dialog-class') ? ' ' + $errorContent.attr('dialog-class') : ''),\n\t\t\t\t                draggable: false,\n\t\t\t\t                open: function(event, ui) {\n\t\t\t\t                \tvar $this = $(this);\n\t\t\t\t        \n\t\t\t\t\t            \t$('body').addClass('dialog-open');\n\t\t\t\t\t            \t$this.scrollTop(0);\n\t\t\t\t\t            },\n\t\t\t\t\t            close: function(event, ui) {\n\t\t\t\t\t            \t$('body').removeClass('dialog-open');\n\t\t\t\t\t            }\n\t\t\t\t            }\n\t\t\t\t        });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction appendCSRFToken($form) {\n\t$.ajax({\n\t\tmethod: 'get',\n\t\turl: Urls.CSRFToken.Get,\n\t\tdataType: 'json',\n\t\tsuccess: function(response) {\n\t\t\t$form.append('<input type=\"hidden\" name=\"' + response.name + '\" value=\"' + response.token + '\"/>');\n\t\t}\n\t});\n}","'use strict';\n\nvar Recaptcha = require('../components/Recaptcha');\nvar RequestHelper = require('../../../../app_storefront_core/cartridge/js/helpers/RequestHelper');\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\n\nexports.Initialize = initialize;\n\nvar $footerEmailForm;\nvar validator;\nvar dataBuffer = {};\nvar options = {};\nvar loaded = {};\n\n\nfunction initialize(page) {\n\tif (page && page.options) {\n\t\toptions = page.options;\n\t}\n\n\tvar footerEmailFormSelector;\n\tif (page.site == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\tfooterEmailFormSelector = 'form#email-alert-signup';\n\t} else if (page.site == SiteConstants.SiteIds.BootBarnUS) {\n\t\tfooterEmailFormSelector = 'form#bootbarn-footer-email-alert-signup';\n\t} else {\n\t\tfooterEmailFormSelector = 'form#footer-email-signup';\n\t}\n\t\n\t$footerEmailForm = $(footerEmailFormSelector);\n\tif ($footerEmailForm.length > 0) {\t\t\n\t\tvar $validatorErrorMessage = $footerEmailForm.find('span.error');\n\t\t\n\t\t$footerEmailForm.on('submit', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForFooterEmailSignup) {\n\t\t\t\tsubmitEmailSignup();\n\t\t\t}\t\t\t\n\t\t});\n\t\t\n\t\t$(document).off('mousedown.EmailSignUp.ValidationClear').on('mousedown.EmailSignUp.ValidationClear', function(event) {\n\t\t\tif (validator && $(event.target).closest(footerEmailFormSelector).parent().length == 0) {\n\t\t\t\tvalidator.resetForm();\n\t\t\t\t$validatorErrorMessage.removeClass('signup-success').html('').hide();\n\t        }\n\t    });\n\n\t\t$(document).on('Global.EmailSignup', function (event, data) {\n\t\t\tif (options && options.Recaptcha && options.Recaptcha.EnabledForFooterEmailSignup) {\n\t\t\t\tsubmitEmailSignup();\n\t\t\t}\n\t\t});\n\n\t\tif (options && options.Recaptcha && options.Recaptcha.EnabledForFooterEmailSignup && options.Recaptcha.GoogleSiteKey) {\n\t\t\tRecaptcha.initialize();\n\t\t\trenderRecaptchaForEmailSignup();\n\t\t\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\t\t\tif (!loaded.Recaptcha) {\n\t\t\t\t\tloaded.Recaptcha = true;\n\t\t\t\t\trenderRecaptchaForEmailSignup();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction submitEmailSignup() {\n\tvar $emailAddress = $footerEmailForm.find('input#email-alert-address');\t\t\n\tvalidator = $footerEmailForm.validate();\n\t$emailAddress.rules('add', ValidationRules.Email);\n\tvalidator.form();\n\n\tif (validator.valid()) {\n\t\tif(SitePreferences.CORDIAL_ENABLED){\n\t\t\tvar auth_data = {\n\t\t\t\temail: $emailAddress.val()\n\t\t\t}\n\t\t\tvar contact_data = {\n\t\t\t\t'channels': {\n\t\t\t\t\t'email': {\n\t\t\t\t\t\t'address': $emailAddress.val(),\n\t\t\t\t\t\t'subscribeStatus': 'subscribed'\t\t\t\t            \n\t\t\t\t\t}\n\t\t\t\t},\t\t\t\t    \n\t\t\t\t'signup_source': 'footer',\n\t\t\t\t'welcome_signup': true\n\t\t\t};\n\t\t\t\n\t\t\tvar properties = {\n\t\t\t\t\"signup_source\": 'footer',\n\t\t\t\t\"welcome_signup\": true\n\t\t\t};\n\n\t\t\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t\t['event', 'email_signup', properties]\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t}).catch();\n\t\t}\n\t\tif (SitePreferences.RETENTION_COM_ENABLED) {\n\t\t\tgeq.suppress();\n\t\t}\n\n\t\tif ($('#email-alert-address.valid').length > 0 && $('#email-alert-address').val() != '') {\n\t\t\t$('input#email-alert-address').val('');\n\t\t\t$('.signup-success').show();\n\t\t}\n\t\tsetTimeout(function() {\n\t\t\t$('.signup-success').hide();\n\t\t}, 5000);\n\t}\n}\n\nfunction renderRecaptchaForEmailSignup() {\n    if (loaded.Recaptcha && $footerEmailForm.length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForFooterEmailSignup && options.Recaptcha.GoogleSiteKey) {\n        if (dataBuffer.EmailSignupRecaptcha) {\n            grecaptcha.reset(dataBuffer.EmailSignupRecaptcha);\n        }\n        dataBuffer.EmailSignupRecaptcha = grecaptcha.render('footer-email-alert-signup-submit', {\n            'sitekey': options.Recaptcha.GoogleSiteKey,\n            'callback': emailSignup,\n            'badge': 'inline'\n        });\n    }\n}","'use strict';\n\nvar loadingIndicator = require('./LoadingIndicator');\nvar ReturnCodes = require('../../../../int_svs/cartridge/scripts/GiftCardConstants').ReturnCodes;\nvar ValidationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\n\nexports.initialize = initialize;\nexports.remove = remove;\n\nvar giftCardBalanceInquiryValidator;\n\nfunction initialize($container, optionsParameter) {\n\tvar options = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\t\n\tvar $giftCardBalanceInquiryComponent = $container.find('.gift-card-balance-inquiry-component');\n\t\n\tvar $giftCardBalanceInquiryForm = $giftCardBalanceInquiryComponent.find('form');\n\tvar $giftCardBalanceInquiryResult = $giftCardBalanceInquiryComponent.find('.balance-inquiry-result');\n\tvar $giftCardBalanceInquiryResultAmount = $giftCardBalanceInquiryComponent.find('.amount');\n\tvar $giftCardBalanceInquiryCardNumber = $giftCardBalanceInquiryForm.find('input[name$=\"giftCard_number\"]');\n    var $giftCardBalanceInquiryPinNumber = $giftCardBalanceInquiryForm.find('input[name$=\"giftCard_pin\"]');\n    var $giftCardBalanceInquiryErrorMessage = $giftCardBalanceInquiryForm.find('span.error');\n\t\n    $container.attr('balance-inquiry-state', 'form');\n\t\n    $giftCardBalanceInquiryComponent.off('click.apply').on('click.apply', '.btn.balance-inquiry:not([loading])', function (event) {\n\t\tevent.preventDefault();\n\n\t\t$giftCardBalanceInquiryErrorMessage.html('').hide();\n        giftCardBalanceInquiryValidator = $giftCardBalanceInquiryForm.validate();\n\t\t$.validator.addMethod('giftCardNumberLength', ValidationHelper.ValidateGiftCardNumberLength, Resources.Validation.Messages.GiftCard.Number.Length);\n\t\t$.validator.addMethod('giftCardNumberValues', ValidationHelper.ValidateGiftCardNumberValues, Resources.Validation.Messages.GiftCard.Number.Values);\n\t\t$giftCardBalanceInquiryCardNumber.rules('add', ValidationRules.GiftCard.Number);\n\t\t$giftCardBalanceInquiryPinNumber.rules('add', ValidationRules.GiftCard.Pin);\n        giftCardBalanceInquiryValidator.form();\n\n        if (Urls && Urls.GiftCard.BalanceInquiry && giftCardBalanceInquiryValidator.valid()) {\n            var $this = $(this);\n\n            $this.loading({\n                IsImageShown: false,\n                Label: Resources.Loading.Loading\n            });\n\n\t\t\tvar giftCardBalanceInquiryCardNumber = $giftCardBalanceInquiryCardNumber.val().match(/(\\d)/g);\n\t\t\tif (giftCardBalanceInquiryCardNumber && giftCardBalanceInquiryCardNumber.length) {\n\t\t\t\tgiftCardBalanceInquiryCardNumber = giftCardBalanceInquiryCardNumber.join('');\n\t\t\t}\n\n            $.ajax({\n                method: 'POST',\n                url: Urls.GiftCard.BalanceInquiry,\n                contentType: 'application/json',\n                data: JSON.stringify({\n                    cardNumber: giftCardBalanceInquiryCardNumber,\n                    pin: $giftCardBalanceInquiryPinNumber.val()\n                }),\n                dataType: 'json',\n                success: function (data) {\n                    $this.loading('destroy');\n\n                    var inquiryResult;\n                    if (data && data.ServiceSuccessfullyCalled && data.InquiryResult) {\n                        inquiryResult = data.InquiryResult;\n                    }\n\n                    if (inquiryResult && inquiryResult.ReturnCode.ReturnCode == ReturnCodes.Approval) {\n                        $container.attr('balance-inquiry-state', 'result');\n                        \n                        $giftCardBalanceInquiryResultAmount.text(inquiryResult.BalanceAmount.AmountFormatted);\n                        \n                        if (options.successCallback) {\n                        \toptions.successCallback(inquiryResult);\n                        }\n                    } else {\n                    \tif (inquiryResult.ReturnCode.ReturnDescription == 'Invalid Message') {\n                    \t\tinquiryResult.ReturnCode.ReturnDescription = Resources.Error.Generic;\t\n                    \t}\n                    \t\n                        $giftCardBalanceInquiryErrorMessage.html(inquiryResult.ReturnCode.ReturnDescription || Resources.Error.Generic).show();\n                        \n                        if (options.errorCallback) {\n                        \toptions.errorCallback();\n                        }\n                    }\n                }\n            });\n\t\t}\n\t});\n    \n    $giftCardBalanceInquiryCardNumber.off('keydown.GiftCardBalanceInquiry.ValidationClear, change.GiftCardBalanceInquiry.ValidationClear').on('keydown.GiftCardBalanceInquiry.ValidationClear, change.GiftCardBalanceInquiry.ValidationClear', function (event) {\n\t\tif ($container.attr('balance-inquiry-state') === 'result') {\n\t\t\t$container.attr('balance-inquiry-state', 'form');\n        \t$giftCardBalanceInquiryPinNumber.val('');\n        \t$giftCardBalanceInquiryResultAmount.text('');\n        }\n    });\n    \n    $(document).off('mousedown.GiftCardBalanceInquiry.ValidationClear').on('mousedown.GiftCardBalanceInquiry.ValidationClear', function (event) {\n        if (giftCardBalanceInquiryValidator && $(event.target).closest('.gift-card-balance-inquiry-component').parent().length == 0) {\n            giftCardBalanceInquiryValidator.resetForm();\n            $giftCardBalanceInquiryErrorMessage.html('').hide();\n        }\n    });\n}\n\nfunction remove() {\n\tgiftCardBalanceInquiryValidator.destroy();\n}","'use strict';\n\nvar dialog = require('../dialog');\n\nexports.initialize = initialize;\n\nfunction initialize() {\n    dialog.open({\n        html: $('#dialog-content-gift-card-balance-inquiry').html(),\n        options: {\n            title: 'Gift Card Balance Check',\n            dialogClass: 'gift-card-balance-inquiry',\n            resizable: false,\n            draggable: false\n        }\n    });\n}\n","'use strict';\n\nvar loadingIndicator = require('./LoadingIndicator');\n\nexports.initialize = initialize;\n\nvar options;\nvar dataBuffer;\nvar loadingIndicatorSettings = {\n    IsLabelShown: false,\n    CssClass: 'fullscreen',\n    BackgroundColor: 'transparent'\n};\n\nfunction initialize(optionsParameter) {\n\toptions = $.extend({\n\t\tsuccessCallback: null,\n\t\terrorCallback: null\n\t}, optionsParameter);\n\tdataBuffer = {\n\t\tinitialized: false\n\t};\n\n\t$(document).off('click.GlobaleInitialize').on('click.GlobaleInitialize', '.country-selector', function(event) {\n\t\tif ($('div#globale-script-loader-data').length > 0 && !dataBuffer.initialized) {\n\t\t\tdataBuffer.initialized = true;\n\t\t\tevent.preventDefault();\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t\t$('body').append('<script type=\"text/javascript\" id=\"globale-script-loader\" src=\"' + Urls.Globale.ScriptLoader + '\"></script>');\n\t\t}\n\t});\n\n\t$(document).off('Globale.Initialized').on('Globale.Initialized', function(event) {\n\t\tif (dataBuffer.initialized && $('.pt_checkout_globale').length == 0) {\n\t\t\tdataBuffer.showShippingSwitcherInterval = setInterval(showShippingSwitcher, 250);\n\t\t}\n\t});\n}\n\nfunction showShippingSwitcher() {\n\tif (GlobalE && GlobalE.ShippingSwitcher && GlobalE.ShippingSwitcher.Show && typeof GlobalE.ShippingSwitcher.Show == 'function') {\n\t\tif ($('body').attr('loading')) {\n\t\t\t$('body').loading('destroy');\n\t\t}\n\t\tclearInterval(dataBuffer.showShippingSwitcherInterval);\n\t\tGlobalE.ShippingSwitcher.Show();\n\t}\n}","'use strict';\n\nexports.initialize = initialize;\n\nvar ImageConstants;\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar carouselVideo = require('./../CarouselVideo');\n\nvar singleImageSlickOptions;\nvar productThumbnailSlickOptions;\n\nvar html = [];\nvar data = [];\nvar loaded = [];\nvar options;\n\nvar $singleImageSlides;\nvar $thumbnailImageContainer;\nvar $thumbnailImageSlides;\n\nfunction initialize(params) {\n\tif (params) {\n    \toptions = params;\n\t}\n    var $pdpMain = $('#pdpMain');\n\n\tif (pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\tImageConstants = require('../../../../../app_storefront_countryoutfitters/cartridge/js/ImageConstants');\n\t} else if (pageContext.isstoresite) {\n\t\tImageConstants = require('../../../../../bootbarn_rsp/cartridge/js/ImageConstants');\n\t} else { \n\t\tImageConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ImageConstants');\n\t}\n\tsingleImageSlickOptions = ImageConstants.SlickSlider.Options.Single;\n\tproductThumbnailSlickOptions = ImageConstants.SlickSlider.Options.Thumbnail;\n\n    $singleImageSlides = $('.slider-single-image .slides');\n    $thumbnailImageContainer = $('.product-thumbnails-container');\n\t$thumbnailImageSlides = $thumbnailImageContainer.find('.slides');\n\n    $pdpMain.off('click.Variant.Leaflet.Zoom.In').on('click.Variant.Leaflet.Zoom.In', '.custom.leaflet-control-zoom-in', function (e) {\n\t\tvar $slides = $('.slider-single-image .slides');\n\t\tvar slick = $slides.slick('getSlick');\n\t\t$slides.find('[data-slick-index=\"' + slick.currentSlide + '\"] img.high-resolution').imgViewer2('getMap').zoomIn();\n    });\n    \n    $pdpMain.off('click.Variant.Leaflet.Zoom.Out').on('click.Variant.Leaflet.Zoom.Out', '.custom.leaflet-control-zoom-out', function (e) {\n\t\tvar $slides = $('.slider-single-image .slides');\n\t\tvar slick = $slides.slick('getSlick');\n\t\t$slides.find('[data-slick-index=\"' + slick.currentSlide + '\"] img.high-resolution').imgViewer2('getMap').zoomOut();\n    });\n\t\n\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS || pageContext.site === SiteConstants.SiteIds.BootBarnUS || pageContext.options.StoreUIVersion == '2024Redesign') {\n\t\t$(window).off('resize.PDP.Slider.Primary').on('resize.PDP.Slider.Primary', function (event) {\n\t\t\tif (data['mapResizeTimer']) {\n\t\t\t\tclearTimeout(data['mapResizeTimer']);\n\t\t\t}\n\t\t\tdata['mapResizeTimer'] = setTimeout(mapResizeTimerHandler, 250);\n\t\t});\n\t}\n\t\n\t$singleImageSlides.on('init', function(event, slick) {\n\t\t// if (pageContext.site === SiteConstants.SiteIds.SheplersUS || pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\tvar $initialSlide = $singleImageSlides.find('.slick-slide.slick-active');\n\t\t\tdata['singleImageSlidesInitialSlide'] = $initialSlide.attr('data-slick-index');\n\t\t\tdata['singleImageSlidesCurrentSlide'] = data['singleImageSlidesInitialSlide'];\n\n\t\t\tinitializeImageViewerOnSlide($initialSlide);\n\t\t\t// setTimeout(function(){resizeSliderToMatchSlide($initialSlide);}, 250);\n\t\t// }\n\t});\n\t\n\t$singleImageSlides.on('beforeChange', function(event, slick, currentSlide, nextSlide) {\n\t\tif (nextSlide != data['singleImageSlidesCurrentSlide']) {\n\t\t\t$thumbnailImageSlides.find('.slick-current').removeClass('slick-current');\n\t\t\t$thumbnailImageSlides.find('.slide[data-slick-index=\"' + nextSlide + '\"]').addClass('slick-current');\n\t\t\tsetThumbnailPageBySlide(nextSlide + 1);\n\n\t\t\t// var $currentSlide = $singleImageSlides.find('[data-slick-index=\"' + currentSlide + '\"]');\n\t\t\t// removeImageViewerOnSlide($currentSlide);\n\n\t\t\tvar $nextSlide = $singleImageSlides.find('[data-slick-index=\"' + nextSlide + '\"]');\n\t\t\t// turn off zoom on video slide\n\t\t\tif (!$nextSlide.hasClass('carousel-video-slide')) {\n\t\t\t\tinitializeImageViewerOnSlide($nextSlide);\n\t\t\t}\n\t\t\t// initializeSlidesToSide($nextSlide);\n\n\t\t\tdata['singleImageSlidesCurrentSlide'] = nextSlide;\n\t\t}\n\t});\n\n    var singleImageSlickOptions = ImageConstants.SlickSlider.Options.Single;\n    if (pageContext.site === SiteConstants.SiteIds.SheplersUS || pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n    \tsingleImageSlickOptions.dots = true;\n\t\tsingleImageSlickOptions.responsive[0].settings.arrows = false;\n\t}\n\n\t$singleImageSlides.not('.slick-initialized').slick(singleImageSlickOptions);\n\n    var productThumbnailSlickOptions = ImageConstants.SlickSlider.Options.Thumbnail;\n    if (pageContext.site === SiteConstants.SiteIds.SheplersUS || pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\tproductThumbnailSlickOptions.vertical = true;\n\t}\n\t$thumbnailImageSlides.not('.slick-initialized').slick(productThumbnailSlickOptions);\n\n\tdata['thumbnailsCurrentPage'] = 1;\n\tdata['thumbnailsMaximumSlide'] = $thumbnailImageSlides.find('.slide').length;\n\tdata['thumbnailsMaximumPage'] = Math.ceil(data['thumbnailsMaximumSlide'] / productThumbnailSlickOptions.slidesToShow);\n\n\tif (data['thumbnailsMaximumPage'] <= 1) {\n\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.next').addClass('disable');\n\t} else {\n\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.next').removeClass('disable');\n\t}\n\n\t$('.product-thumbnails-container .product-thumbnails-arrow').on('click', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar pageDelta = 0;\n\t\tif ($this.hasClass('next')) {\n\t\t\tpageDelta = 1;\n\t\t} else if ($this.hasClass('previous')) {\n\t\t\tpageDelta = -1;\n\t\t}\n\n\t\tsetThumbnailPage(data['thumbnailsCurrentPage'] + pageDelta);\n\t});\n\n\t$('.product-thumbnails .slide a').on('click', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $currentSlide = $this.closest('.slick-track').find('.slick-current');\n\t\tvar currentSlide = $currentSlide.data('slick-index');\n\t\tvar $nextSlide = $this.closest('.slide');\n\t\tvar nextSlide = $nextSlide.data('slick-index');\n\n\t\t$thumbnailImageSlides.find('.slick-current').removeClass('slick-current');\n\t\t$nextSlide.addClass('slick-current');\n\t\t$singleImageSlides.slick('slickGoTo', nextSlide);\n\t});\n\n\tcarouselVideo.init();\n}\n\nfunction initializeSlidesToSide($slide) {\n\tvar $leftSlide = $slide.prev();\n\tif ($leftSlide.length > 0) {\n\t\tinitializeImageViewerOnSlide($leftSlide);\n\t}\n\n\tvar $rightSlide = $slide.next();\n\tif ($rightSlide.length > 0) {\n\t\tinitializeImageViewerOnSlide($rightSlide);\n\t}\n}\n\nfunction setThumbnailPageBySlide(selectedSlide) {\n\tif (selectedSlide >= 1 && selectedSlide <= data['thumbnailsMaximumSlide']) {\n\t\tsetThumbnailPage(Math.ceil(selectedSlide / ImageConstants.SlickSlider.Options.Thumbnail.slidesToShow));\n\t}\n}\n\nfunction setThumbnailPage(selectedPage) {\n\tif (selectedPage >= 1 && selectedPage <= data['thumbnailsMaximumPage']) {\n\t\tif (pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\tvar offsetX = $thumbnailImageSlides.find('.slick-track').offset().left - $thumbnailImageSlides.find('.slick-track .slide[data-slick-index=\"' + (selectedPage * ImageConstants.SlickSlider.Options.Thumbnail.slidesToShow - ImageConstants.SlickSlider.Options.Thumbnail.slidesToShow) + '\"]').offset().left + 'px';\n\t\t\t$thumbnailImageSlides.find('.slick-track').css('transform', 'translate3d(' + offsetX + ', 0, 0)');\n\t\t} else {\n\t\t\tvar offsetY = $thumbnailImageSlides.find('.slick-track').offset().top - $thumbnailImageSlides.find('.slick-track .slide[data-slick-index=\"' + (selectedPage * ImageConstants.SlickSlider.Options.Thumbnail.slidesToShow - ImageConstants.SlickSlider.Options.Thumbnail.slidesToShow) + '\"]').offset().top + 'px';\n\t\t\t$thumbnailImageSlides.find('.slick-track').css('transform', 'translate3d(0, ' + offsetY + ', 0)');\n\t\t}\n\n\t\tif (selectedPage > 1) {\n\t\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.previous').removeClass('disable');\n\t\t} else {\n\t\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.previous').addClass('disable');\n\t\t}\n\n\t\tif (selectedPage < data['thumbnailsMaximumPage']) {\n\t\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.next').removeClass('disable');\n\t\t} else {\n\t\t\t$thumbnailImageContainer.find('.product-thumbnails-arrow.next').addClass('disable');\n\t\t}\n\n\t\tdata['thumbnailsCurrentPage'] = selectedPage;\n\t}\n}\n\nfunction removeImageViewerOnSlide($slide) {\n\tif ($slide.find('img.high-resolution').length > 0) {\n\t\t$slide.find('img').removeClass('high-resolution').imgViewer2('destroy');\n\t}\n}\n\nfunction initializeImageViewerOnSlide($slideToInitialize) {\n\tif ($slideToInitialize.find('img.high-resolution').length == 0) {\n\t\t$slideToInitialize.find('img').attr('src', $slideToInitialize.find('a.zoomedImage').attr('href')).addClass('high-resolution').imgViewer2({\n\t\t\tzoomMax: 4,\n\t\t\tdragable: false,\n\t\t\tonReady: function() {\n\t\t\t\tvar imgViewer2 = this;\n\t\t\t\tvar map = this.map;\n\n\t\t\t\timgViewer2.setZoom(1);\n\t\t\t\tif (map && map.tap) {\n\t\t\t\t\tmap.tap.disable();\n\t\t\t\t}\n\t\t\t\tif (map && map.dragging) {\n\t\t\t\t\tmap.dragging.disable();\n\t\t\t\t}\n\n\t\t\t\t$(map.getContainer()).off('wheel').on('wheel', function(event) {\n\t\t\t\t\tvar wheelScrollAnimationTargetDelta = 0;\n\n\t\t\t\t\tif (data['wheelScrollAnimation']) {\n\t\t\t\t\t\twheelScrollAnimationTargetDelta = data['wheelScrollAnimationTarget'] - $(window).scrollTop();\n\t\t\t\t\t\tdata['wheelScrollAnimation'].stop();\n\t\t\t\t\t}\n\n\t\t\t\t\tvar zoomLevel = imgViewer2.getZoom();\n\t\t\t\t\tvar zoomMaximum = $slideToInitialize.find('img.high-resolution').imgViewer2('option', 'zoomMax');\n\t\t\t\t\tif ((zoomLevel == 1 && event.originalEvent.deltaY > 0) || (zoomLevel > (zoomMaximum - 0.5)) && event.originalEvent.deltaY < 0) {\n\t\t\t\t\t\tdata['wheelScrollAnimationTarget'] = $(window).scrollTop() + event.originalEvent.deltaY + wheelScrollAnimationTargetDelta;\n\t\t\t\t\t\tdata['wheelScrollAnimation'] = $('html, body').animate({\n\t\t\t\t\t\t\tscrollTop: data['wheelScrollAnimationTarget']\n\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\tduration: 'fast',\n\t\t\t\t\t\t\tcomplete: function() { \n\t\t\t\t\t\t\t\tdata['wheelScrollAnimation'] = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tmap.on('zoom', function(event) {\n\t\t\t\t\tvar zoomLevel = imgViewer2.getZoom();\n\n\t\t\t\t\tif (zoomLevel > 1.05) {\n\t\t\t\t\t\t$slideToInitialize.find('img.high-resolution').imgViewer2('option', 'dragable', true);\n\n\t\t\t\t\t\tif (map && map.tap) {\n\t\t\t\t\t\t\tmap.tap.enable();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (map && map.dragging) {\n\t\t\t\t\t\t\tmap.dragging.enable();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'draggable', false, true);\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'swipe', false, true);\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'touchMove', false, true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$slideToInitialize.find('img.high-resolution').imgViewer2('option', 'dragable', false);\n\n\t\t\t\t\t\tif (map && map.tap) {\n\t\t\t\t\t\t\tmap.tap.disable();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (map && map.dragging) {\n\t\t\t\t\t\t\tmap.dragging.disable();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'draggable', true, true);\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'swipe', true, true);\n\t\t\t\t\t\t$('.slider-single-image .slides').slick('slickSetOption', 'touchMove', true, true);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t} else {\n\t\tvar slideImageMap = $slideToInitialize.find('img.high-resolution').imgViewer2('getMap');\n\t\tif (slideImageMap) {\n\t\t\tslideImageMap.invalidateSize();\n\t\t}\n\t}\n}\n\nfunction mapResizeTimerHandler() {\n\tif (data['singleImageSlidesInitialSlide'] != undefined) {\n\t\tvar $initialSlide = $('.slider-single-image .slides').find('[data-slick-index=\"' + data['singleImageSlidesInitialSlide'] + '\"]');\n\t\tresizeSliderToMatchSlide($initialSlide);\n\n        var slick = $singleImageSlides.slick('getSlick');\n        var $currentSlide = $singleImageSlides.find('[data-slick-index=\"' + slick.currentSlide + '\"]');\n\t\tvar currentSlideImageMap = $currentSlide.find('img.high-resolution').imgViewer2('getMap');\n\t\tif (currentSlideImageMap) {\n\t\t\tcurrentSlideImageMap.invalidateSize();\n\t\t}\n\t}\n}\n\nfunction resizeSliderToMatchSlide($slide) {\n\tvar $slideTrack = $slide.closest('.slick-track');\n\t$slideTrack.css('height', 'auto');\n\n\tvar $slideImage = $slide.find('.slide-image > img');\n\tvar slideImageHeight = $slide.height();\n\tvar slideImageWidth = $slide.width();\n\tvar slideAspectRatio = slideImageWidth / slideImageHeight;\n\n\t$slideTrack.css('height', slideImageHeight);\n\t$slideTrack.find('.slick-slide').not($slide).each(function() {\n\t\tvar $this = $(this);\n\t\tvar $thisImage = $this.find('.slide-image > img');\n\t\tvar thisImageAspectRatio = $thisImage.width() / $thisImage.height();\n\n\t\tif ($thisImage.height() > slideImageHeight && thisImageAspectRatio <= slideAspectRatio) {\n\t\t\t$this.addClass('constrain-height');\n\t\t}\n\t});\n}","'use strict';\n\nvar carouselVideo = require('../CarouselVideo');\n\n// Global vars\nvar options;\nvar isMobile = window.innerWidth <= 767;\n\nexports.initialize = initialize;\n\nfunction initialize(params) {\n\tif (params) {\n\t\toptions = params;\n\t}\n\tvar thumbGallerySwiper, largeSwiper,\n\t\tthumbGalleryBreakpoints = options && options.thumbGalleryBreakpoints ? options.thumbGalleryBreakpoints : null,\n\t\tthumbGalleryBreakpointSettings = thumbGalleryBreakpoints ? (isMobile ? thumbGalleryBreakpoints['0'] : thumbGalleryBreakpoints['768']) : null,\n\t\tenableThumbGalleryForCurrentBreakpoint = thumbGalleryBreakpointSettings && thumbGalleryBreakpointSettings.enabled,\n\t\tisThumbnailsElm = $('.thumbs-product-swiper').length > 0;\n\n\t// Check to see if we have any thumbnails at all\n\tif (isThumbnailsElm) {\n\t\t// Initialize thumbnails gallery and assign instance to 'thumbGallerySwiper'\n\t\tif (enableThumbGalleryForCurrentBreakpoint) {\n\t\t\tthumbGallerySwiper = thumbGallerySwiperInit(options);\n\t\t\t// Thumbnail slider modifications - can only make mods after thumbs gallery slider has been initialized.\n\t\t\t// No default arrow navigation exists for thumbnails gallery in swiper, so we add our own.\n\t\t\tthumbGalleryNavigation(options, thumbGallerySwiper, thumbGalleryBreakpointSettings);\n\t\t\tif (isMobile) {\n\t\t\t\t$('.product-image-container-mobile').addClass('swiper-thumbs-mobile-edits');\n\t\t\t}\n\t\t} else {\n\t\t\t$('.thumbs-product-swiper').addClass('d-none');\n\t\t}\n\t\t// Initialize PDP main image swiper and pass in thumbnails gallery if it exists\n\t\tlargeSwiper = largeSwiperInit(options, thumbGallerySwiper);\n\t} else {\n\t\tlargeSwiper = largeSwiperInit(options, null);\n\t}\n\n\tif (options.zoom) {\n\t\t$('#pdpMain').off('click.Variant.Swiper.Zoom.In').on('click.Variant.Swiper.Zoom.In', '.custom.leaflet-control-zoom-in', function (e) {\n\t\t\tlargeSwiper.zoom.in();\n\t\t});\n\t\t\n\t\t$('#pdpMain').off('click.Variant.Swiper.Zoom.Out').on('click.Variant.Swiper.Zoom.Out', '.custom.leaflet-control-zoom-out', function (e) {\n\t\t\tlargeSwiper.zoom.out();\n\t\t});\n\t}\n\n\tcarouselVideo.init();\n}\n\nfunction thumbGallerySwiperInit(options) {\n\t// Thumbnails swiper options\n\tvar thumbnailsSwiperOptions = {\n\t\tdirection: isMobile ? 'horizontal' :'vertical',\n\t\tslidesPerView: 7,\n\t\tslidesPerGroup: 7,\n\t\tloop: false,\n\t\tslideToClickedSlide: true,\n\t\tallowTouchMove: true,\n\t\ta11y: {\n            enabled: true,\n            firstSlideMessage: 'This is the first slide',\n            lastSlideMessage: 'This is the last slide'\n        },\n\t\tkeyboard: {\n\t\t\tenabled: true,\n\t\t\tpageUpDown: true\n\t\t}\n\t};\n\n\tif (options.thumbGalleryScrollDirection) {\n\t\tthumbnailsSwiperOptions.direction = isMobile ? 'horizontal' : options.thumbGalleryScrollDirection;\n\t}\n\n\t// Initiate thumbnails swiper\n\treturn new Swiper ('.thumbs-product-swiper', thumbnailsSwiperOptions);\n}\n\nfunction largeSwiperInit(options, thumbnailsSwiper) {\n\tvar largeSwiperOptions;\n\tvar mobileDots = options.breakpoints && options.breakpoints['0'] && options.breakpoints['0'].dots ? options.breakpoints['0'].dots : true;\n\tvar desktopDots = options.breakpoints && options.breakpoints['768'] && options.breakpoints['768'].dots ? options.breakpoints['768'].dots : false;\n\n\t// Large product swiper options\n\tlargeSwiperOptions = {\n\t\tslidesPerView: 1,\n\t\tcenteredSlides: true,\n\t\tloop: false,\n\t\ta11y: {\n            enabled: true,\n            firstSlideMessage: 'This is the first slide',\n            lastSlideMessage: 'This is the last slide'\n        },\n\t\tkeyboard: {\n\t\t\tenabled: true,\n\t\t\tpageUpDown: true\n\t\t},\n\t\tbreakpoints: {\n\t\t\t0: {\n\t\t\t\tpagination: {\n\t\t\t\t\tenabled: mobileDots,\n\t\t\t\t\tel: '.swiper-pagination',\n\t\t\t\t\tclickable: true\n\t\t\t\t}\n\t\t\t},\n\t\t\t768: {\n\t\t\t\tpagination: {\n\t\t\t\t\tenabled: desktopDots,\n\t\t\t\t\tel: '.swiper-pagination',\n\t\t\t\t\tclickable: true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tif (desktopDots || mobileDots) {\n\t\tvar modifierClass;\n\t\tif (!desktopDots && mobileDots) {\n\t\t\tmodifierClass = 'swiper-paginated-mobile-';\n\t\t}\n\t\tif (desktopDots && !mobileDots) {\n\t\t\tmodifierClass = 'swiper-paginated-desktop-';\n\t\t}\n\t\tif (desktopDots && mobileDots) {\n\t\t\tmodifierClass = 'swiper-paginated-both-';\n\t\t}\n\t\tif (modifierClass) {\n\t\t\tlargeSwiperOptions.containerModifierClass = modifierClass;\n\t\t}\n\t}\n\n\tif (options.zoom) {\n\t\tlargeSwiperOptions.zoom = {\n\t\t\tmaxRatio: 3,\n\t\t\tminRatio: 1\n\t\t}\n\t}\n\n\tif (thumbnailsSwiper) {\n\t\tlargeSwiperOptions.thumbs = {\n\t\t\tswiper: thumbnailsSwiper\n\t\t}\n\t}\n\n\t// Initiate large product swiper\n\treturn new Swiper ('.large-product-swiper', largeSwiperOptions);\n}\n\nfunction thumbGalleryNavigation(options, swiperInstance, breakpointSettings) {\n\tvar $swiperThumbnailsDomElement = $('.thumbs-product-swiper');\n\tif (!$swiperThumbnailsDomElement || !swiperInstance || !breakpointSettings || $swiperThumbnailsDomElement.find('.swiper-slide').length < 8) {\n\t\treturn;\n\t} else {\n\t\tvar addNavigation = breakpointSettings ? (breakpointSettings.arrows ? breakpointSettings.arrows : false) : null,\n\t\t\tisVertical = $swiperThumbnailsDomElement.hasClass('swiper-vertical'),\n\t\t\tisHorizontal = $swiperThumbnailsDomElement.hasClass('swiper-horizontal'),\n\t\t\tthumbGallerySlides = $swiperThumbnailsDomElement.find('.swiper-slide'),\n\t\t\tthumbsDirectionClass = isVertical ? 'thumbs-vertical' : 'thumbs-horizontal', \n\t\t\t$thumbnailsNavigation = $('<div />', { 'class': 'thumbs-product-navigation' }),\n\t\t\tcarets;\n\n\t\t\tif (addNavigation) {\n\t\t\t\tif (isVertical) {\n\t\t\t\t\tcarets = '<i class=\"fa-solid fa-angle-up d-none\"></i><i class=\"fa-solid fa-angle-down\"></i>';\n\t\t\t\t}\n\t\t\t\tif (isHorizontal) {\n\t\t\t\t\tcarets = '<i class=\"fa-solid fa-angle-left d-none\"></i><i class=\"fa-solid fa-angle-right\"></i>';\n\t\t\t\t}\n\t\t\t\t$thumbnailsNavigation.html(carets).addClass(thumbsDirectionClass).insertBefore($swiperThumbnailsDomElement);\n\t\t\t\tvar prevIcons = '.thumbs-product-navigation .fa-angle-up, .thumbs-product-navigation .fa-angle-left';\n\t\t\t\tvar nextIcons = '.thumbs-product-navigation .fa-angle-down, .thumbs-product-navigation .fa-angle-right';\n\t\t\t\t$(document).on('click', prevIcons, function() {\n\t\t\t\t\tswiperInstance.slidePrev(500);\n\t\t\t\t\tvar prevIconsFirstVisibleIndex = thumbGallerySlides.index($swiperThumbnailsDomElement.find('.swiper-slide-visible:first'));\n\t\t\t\t\tvar prevIconsLastVisibleIndex = thumbGallerySlides.index($swiperThumbnailsDomElement.find('.swiper-slide-visible:last'));\n\t\t\t\t\tif (prevIconsFirstVisibleIndex == 0) {\n\t\t\t\t\t\t$(prevIcons).addClass('d-none');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(prevIcons).removeClass('d-none');\n\t\t\t\t\t}\n\t\t\t\t\tif (prevIconsLastVisibleIndex < 7) {\n\t\t\t\t\t\t$(nextIcons).removeClass('d-none');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(nextIcons).addClass('d-none');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$(document).on('click', nextIcons, function() {\n\t\t\t\t\tswiperInstance.slideNext(500);\n\t\t\t\t\tvar nextIconsLastVisibleIndex = thumbGallerySlides.index($swiperThumbnailsDomElement.find('.swiper-slide-visible:last'));\n\t\t\t\t\tif (nextIconsLastVisibleIndex == (thumbGallerySlides.length - 1)) {\n\t\t\t\t\t\t$(nextIcons).addClass('d-none');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(nextIcons).removeClass('d-none');\n\t\t\t\t\t}\n\t\t\t\t\tif (nextIconsLastVisibleIndex > 6) {\n\t\t\t\t\t\t$(prevIcons).removeClass('d-none');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(prevIcons).addClass('d-none');\n\t\t\t\t\t}\n\t\t\t\t});\t\n\t\t\t}\n\t}\n}\n","'use strict';\n\nvar _ = require('lodash');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\n$.widget('bootbarn.loading', {\n    options: {\n        IsImageShown: true,\n        IsLabelShown: true,\n        Label: Resources.Loading.Loading,\n        Content: '',\n        CssClass: '',\n        BackgroundColor: null\n    },\n\n    _create: function() {\n        this.element.attr('loading', 'loading');\n\n        var loadingIndicatorTemplate = _.template($('#template-loading-indicator').html(), TemplateConstants.Lodash.Settings);\n        var $loadingIndicatorContainer = $(loadingIndicatorTemplate({\n        \tContent: this.options.Content\n        }));\n        var $loadingIndicator = $loadingIndicatorContainer.find('.loading-indicator');\n        $loadingIndicatorContainer.css('background-color', this.options.BackgroundColor ? this.options.BackgroundColor : this.element.css('background-color'));\n\n        if (this.options.CssClass) {\n            $loadingIndicatorContainer.addClass(this.options.CssClass);\n        }\n        \n        if (this.options.IsLabelShown && !this.options.Content) {\n            $loadingIndicator.addClass('label');\n            $loadingIndicator.attr('label', this.options.Label);\n        }\n\n        if (this.options.IsImageShown) {\n            $loadingIndicator.addClass('image');\n        }\n\n\t\t$loadingIndicatorContainer.appendTo(this.element);\n\t},\n    \n    _destroy: function() {\n\t\tthis.element.removeAttr('loading').find('.loading-indicator-container').remove();\n    }\n});\n","'use strict';\n\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nexports.Initialize = initialize;\nexports.CloseNavigation = closeNavigation;\n\nvar navDataBuffer = {};\n\nfunction initialize() {\n\tvar siteName = $('.top-banner-bar').data('header-for') || \"\";\n\tvar $navSecondary = $('.nav-secondary');\n\t\n\t$('.nav-secondary-dropdown').parent().addClass('has-dropdown');\n\tif (siteName == SiteConstants.SiteIds.BootBarnUS) {\n\t\tif (window.innerWidth < 1024) {\n\t\t\t$navSecondary.find('li#location').removeClass('has-dropdown');\n\t\t}\n\t}\n\n\t// BootBarn 2020 Full width nav drop down helper\n\tif ($('.top-banner-bar').data('header-for') == 'bootbarn_us') {\n\t\t// main nav hover effects\t\t\n\t\t$('html #navigation .has-dropdown').hover(function () {\n\t\t\tif (!$('html').hasClass('size-mobile')) {\n\t\t\t\t$(this).addClass('active');\n\t\t\t\t$(this).closest('.top-banner').addClass('nav-active');\n\t\t\t\t$('html').addClass('desktop-nav-active');\n\t\t\t\t$('.nav-cover').show();\n\t\t\t}\n\t\t}, function () {\n\t\t\tif (!$('html').hasClass('size-mobile')) {\n\t\t\t\t$('.nav-cover').hide();\n\t\t\t\t$('.top-banner').removeClass('nav-active');\n\t\t\t\t$('html').removeClass('desktop-nav-active');\n\t\t\t\t$(this).removeClass('active');\n\t\t\t}\n\t\t});\n\t}\n\t\n\tif ($navSecondary.find('#location-display-caption').length > 0 && $navSecondary.find('#location-display-caption').hasClass('no-store-to-display')) {\n\t\tif ($navSecondary.find('#location-display-caption').parents('#location').length > 0) {\n\t\t\t$navSecondary.find('#location-display-caption').parents('#location').removeClass('has-dropdown');\n\t\t}\n\t}\t\n\t\n\t// collision detection and adjustment for if menu off-screen\n\t// this is bound to document and .size-desktop to avoid iOS issue with first tap triggering mouseover instead of click - dan@redvan\n\t$(document).on('mouseover', 'html.size-desktop #navigation .has-dropdown > a', function(event) {\n\t\tnavigationCollisionDetection($(event.currentTarget));\n\t});\n\t\n\t$('body').on('click', '#navigation .has-dropdown > a, .nav-secondary .has-dropdown > a', function(event) {\n\t\tevent.preventDefault();\n\t\t\n\t\tvar $this = $(this);\n\t\tvar $parent = $this.closest('.has-dropdown');\n\t\tvar $container = $parent.closest('#navigation, .nav-secondary');\n\t\t\n\t\tif ($('html').hasClass('size-mobile')) {\n\t\t\tvar $scrollingContainer = $('#navigation');\n\t\t\tvar offsetOpenMenu = 0;\n\t\t\tvar scrollTopNew = 0;\n\t\t\t\n\t\t\tif ($('#navigation .has-dropdown.active').first().length > 0 && ($('#navigation .has-dropdown.active').first().offset().top < $this.offset().top)) {\n\t\t\t\toffsetOpenMenu = $('#navigation .has-dropdown.active').first().find('.level-2, .nav-secondary-dropdown').outerHeight();\n\t\t\t}\n\t\t\t\n\t\t\tscrollTopNew = $this.offset().top - $scrollingContainer.offset().top + $scrollingContainer.scrollTop() - offsetOpenMenu;\n\n\t\t\t$scrollingContainer.animate({\n\t\t\t\tscrollTop: scrollTopNew\n\t\t\t}, 150);\n\t\t}\n\t\t\n\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS && $('html').hasClass('size-tablet')) {\n\t\t\tif ($parent.hasClass('active')) {\n\t\t\t\t$parent.removeClass('active');\n\t\t\t} else if (!$parent.hasClass('active')) {\n\t\t\t\t$('#navigation .has-dropdown').removeClass('active');\n\t\t\t\t$parent.addClass('active');\n\t\t\t}\n\t\t}\n\n\t\tif ((!$('html').hasClass('size-desktop') && pageContext.site !== SiteConstants.SiteIds.SheplersUS) || ($('html').hasClass('size-mobile') && pageContext.site === SiteConstants.SiteIds.SheplersUS)) {\n\t\t\t//close other header menus\n\t\t\tif (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\t\t$('.top-banner-bar .nav-secondary .has-dropdown .nav-secondary-dropdown').hide();\n\t\t\t} else {\n\t\t\t\t$('.top-banner-bar .nav-secondary .has-dropdown .nav-secondary-dropdown').stop().slideUp(150);\n\t\t\t}\n\n\t\t\tif ($parent.hasClass('active')) {\n\t\t\t\tif (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\t\t\t$parent.removeClass('active').find('.level-2, .nav-secondary-dropdown').hide();\n\t\t\t\t} else {\n\t\t\t\t\t$parent.removeClass('active').find('.level-2, .nav-secondary-dropdown').stop().slideUp(150);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\t\t\t$('#navigation .has-dropdown.active').removeClass('active').find('.level-2, .nav-secondary-dropdown').hide();\n\t\t\t\t\t$parent.addClass('active').find('.level-2, .nav-secondary-dropdown').show();\n\t\t\t\t} else {\n\t\t\t\t\t$('#navigation .has-dropdown.active').removeClass('active').find('.level-2, .nav-secondary-dropdown').stop().slideUp(150);\n\t\t\t\t\t$parent.addClass('active').find('.level-2, .nav-secondary-dropdown').stop().slideDown(150);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ($('#navigation .has-dropdown.active:not(.accordion)').length > 0) {\n\t\t\t\t$container.attr('active-menu-level', '1');\n\t\t\t} else {\n\t\t\t\t$container.removeAttr('active-menu-level');\n\t\t\t}\n\t\t\t\n\t\t\tif ($('#navigation .has-dropdown.active').length > 0) {\n\t\t\t\t$('.menu-toggle').addClass('active');\n\t\t\t\t$('html').addClass('menu-active');\n\n\t\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS && $('html').hasClass('size-tablet') && window.innerWidth == 1024) {\n\t\t\t\t\t$(this).closest('.top-banner').addClass('nav-active');\n\t\t\t\t\t$('html').addClass('desktop-nav-active');\n\t\t\t\t}\n\t\t\t} else if (window.innerWidth >= 1024) {\n\t\t\t\t$('.menu-toggle').removeClass('active');\n\t\t\t\t$('html').removeClass('menu-active');\n\n\t\t\t\tif (siteName == SiteConstants.SiteIds.BootBarnUS && $('html').hasClass('size-tablet') && window.innerWidth == 1024) {\n\t\t\t\t\t$(this).closest('.top-banner').removeClass('nav-active');\n\t\t\t\t\t$('html').removeClass('desktop-nav-active');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!$('html').hasClass('size-mobile')) {\n\t\t\tnavigationCollisionDetection($this);\n\t\t}\n\t\t\n\t\treturn false;\n\t})\n\t.on('click', '.menu-toggle', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tif ($('html').hasClass('size-mobile') || $('html').hasClass('size-tablet')) {\n\t\t\tvar $html = $('html');\n\t\t\tvar $body = $('body');\n\t\t\tvar $container = $('#wrapper');\n\t\t\tvar headerWrapper = $('.header-wrapper');\n\t\t\tvar jumbotronContainer = headerWrapper.find('.jumbotron-ajax');\n\t\t\tvar logoAndLinks = headerWrapper.find('.logo-and-links-container');\n\t\t\tvar navFixedHeaderLimit = 800;\n\t\t\tvar topBannerBar = headerWrapper.find('.top-banner-bar');\n\t\n\t\t\tvar tobBannerInnerHeight = window.innerHeight - (parseFloat(topBannerBar.outerHeight()) + parseFloat(jumbotronContainer.outerHeight()));\n\t\t\tvar navContainerHeight = window.innerHeight - (parseFloat(topBannerBar.outerHeight()) + parseFloat(logoAndLinks.outerHeight()) + parseFloat(jumbotronContainer.outerHeight())); \n\t\n\t\t\tif (!$html.hasClass('menu-active')) {\n\t\t\t\tvar scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n\t\t\t\tnavDataBuffer['wrapperScrollTop'] = scrollTop;\n\t\t\t\tnavDataBuffer['wrapperMarginTop'] = $container.css('margin-top');\n\t\t\t\t$container.attr('buffer-scrollTop', scrollTop);\n\t\t\t\t\n\t\t\t\t$('.top-banner-inner').css('height', tobBannerInnerHeight);\n\t\t\t\t$('.top-banner-inner .navigation-and-jumbotron-container').css('height', navContainerHeight);\n\t\t\t\t\n\t\t\t\t$html.addClass('menu-active');\n\t\t\t\t$this.addClass('active');\n\t\t\t\t$this.attr('aria-label', $this.attr('data-close')); // Change the aria-label on the menu-toggle for screen readers\n\n\t\t\t\tif (window.innerWidth <= 1023 && scrollTop > navFixedHeaderLimit) {\n\t\t\t\t\t$('.header-wrapper').css('max-height', window.innerHeight);\n\t\t\t\t}\n\t\t\t\t$('.my-store-panel.mobile-only .show-store-search').focus();\n\t\t\t} else {\n\t\t\t\t$html.removeClass('menu-active');\n\t\t\t\t$this.removeClass('active');\n\t\t\t\t$this.attr('aria-label', $this.attr('data-open')); // Change the aria-label on the menu-toggle for screen readers\n\t\n\t\t\t\tif (navDataBuffer['wrapperScrollTop'] > 0) {\n\t\t\t\t\tdocument.body.scrollTop = document.documentElement.scrollTop = navDataBuffer['wrapperScrollTop'];\n\t\t\t\t}\n\t\t\t\t$('#navigation').removeAttr('active-menu-level');\n\t\n\t\t\t\t$('.top-banner-inner').css('height', '');\n\t\t\t\t$('.top-banner-inner .navigation-and-jumbotron-container').css('height', 'auto');\n\t\n\t\t\t\tif (window.innerWidth <= 1023) {\n\t\t\t\t\t$('.header-wrapper').css('transform', 'none');\n\t\t\t\t\t$('.header-wrapper').css('max-height', 'auto');\n\t\t\t\t\t$('html, body').animate({ scrollTop: 0 }, 300);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$('#navigation .level-2').hide();\n\t\t$('#navigation .level-1').slideDown();\n\t\t$('#navigation .active').removeClass('active');\t\t\t\n\t\t$('.nav-secondary-dropdown').slideUp(150);\n\n\t\tif ($('#mini-cart').hasClass('active')) {\n\t\t\t$('#mini-cart .mini-cart-link').removeClass('active');\n\t\t\t$('#mini-cart').removeClass('active');\n\t\t}\n\n\t\t$(document).trigger('SearchBar.Hide');\n\t\t\n\t\tif ($('.second-mobnav').hasClass('active')) {\t\t\t\t\n\t\t\t$('.second-mobnav').removeClass('active')\n\t\t\t$('#second-mobnav').stop().slideUp(150);\n\t\t}\n\t})\n\t.on('click.MenuItemToggle', '.menu-category li .menu-item-toggle', function (event) {\n\t\tevent.preventDefault();\n\t\tvar $parentLi = $(e.target).closest('li');\n\t\t$parentLi.siblings('li').removeClass('active').find('.menu-item-toggle').removeClass('fa-chevron-up active').addClass('fa-chevron-right');\n\t\t$parentLi.toggleClass('active');\n\t\t$(e.target).toggleClass('fa-chevron-right fa-chevron-up active');\n\t});\n\n\t/* --- ADA Compliance: Keyboard main menu navigation ---\n\t * ARROW DOWN: Will open flyouts; focus goes to first clickable link in flyout\n\t * ARROW UP: Will close flyouts; focus returns to the parent of the flyout\n\t * TAB: A focus indicator will show up at time of each tab\n\t * ENTER: By default, hitting enter will engage any link that has current focus\n\t */\n\t$(document).on('keyup', 'ul.menu-category li.has-dropdown', function (event) { \n\t\t// Down Arrow: If sub-menu has been opened...\n\t\tif (event.which === SiteConstants.KeyCodes.ArrowDown) {\n\t\t\t// BootBarn-specific nav features\n\t\t\tif ($('.top-banner-bar').data('header-for') == 'bootbarn_us') {\n\t\t\t\t$(this).trigger('mouseenter');\n\t\t\t}\n\t\t\t$(this).find('ul').find('a[href!=\"\"][href]').removeAttr('tabindex'); // Remove tabindex to allow natural tab flow of nav list\n\t\t\tvar navLinksPopulated = $(this).find('.level-2 ul:first-of-type li:first-of-type').find('a').filter(function(x, navLink) {\n\t\t\t\tif ($(navLink).attr('href') && $(navLink).attr('href').trim().length > 0) {\n\t\t\t\t\treturn navLink;\n\t\t\t\t}\n\t\t\t});\n\t\t\t$(navLinksPopulated[0]).focus().addClass('focus-visible-indicator'); // Focus on first populated <a> within opened sub-menu and add visual indicator\n\t\t\t$(this).attr('aria-expanded','true').addClass('active keyboard-activated'); // Update expanded attribute and add keyboard class\n\t\t}\n\t\t// Up Arrow: If sub-menu has been closed...\n\t\tif (event.which === SiteConstants.KeyCodes.ArrowUp) {\n\t\t\t// BootBarn-specific nav features\n\t\t\tif ($('.top-banner-bar').data('header-for') == 'bootbarn_us') {\n\t\t\t\t$(this).trigger('mouseleave');\n\t\t\t}\n\t\t\t$(this).find('ul').find('a[href!=\"\"][href]').attr('tabindex','-1'); // Add negative tabindex to skip nested anchors\n\t\t\t$(this).attr('aria-expanded','false').removeClass('active keyboard-activated').focus().addClass('focus-visible-indicator'); // Update expanded attribute, remove keyboard class and reposition focus indicator\n\t\t}\n\t\t// Tab: Keyboard logic for nav tabbing...\n\t\tif (event.which === SiteConstants.KeyCodes.Tab) {\n\t\t\tif (!$(document.activeElement).hasClass('keyboard-activated') && ($(document.activeElement).closest('li.has-dropdown') && !$(document.activeElement).closest('li.has-dropdown').hasClass('keyboard-activated'))) { // If user tabbed away from activated sub-menu, close the sub-menu\n\t\t\t\t// BootBarn-specific nav features\n\t\t\t\tif ($('.top-banner-bar').data('header-for') == 'bootbarn_us') {\n\t\t\t\t\t$('li.has-dropdown.keyboard-activated').trigger('mouseleave');\n\t\t\t\t}\n\t\t\t\t$('li.has-dropdown.keyboard-activated').find('ul').find('a[href!=\"\"][href]').attr('tabindex','-1'); // Add negative tabindex to skip nested anchors when submenu is closed\n\t\t\t\t$('li.has-dropdown.keyboard-activated').attr('aria-expanded','false').removeClass('active keyboard-activated'); // Update expanded attribute and remove keyboard class\n\t\t\t}\n\t\t}\n\t})\n\t.on('keydown', '.menu-toggle', function (event) { \n\t\tif (($('html').hasClass('size-mobile') || $('html').hasClass('size-tablet')) && event.which === SiteConstants.KeyCodes.Enter) {\n\t\t\t$('.my-store-panel.mobile-only a').focus().addClass('focus-visible-indicator');\n\t\t}\n\t})\n\t.on('mouseover', 'ul.menu-category li.has-dropdown', function (event) {\n\t\t$(this).attr('aria-expanded','true'); // CSS-expaned sub-menu occurs on hover. Use JS to update the expanded attribute for mouse users.\n\t})\n\t.on('mousemove', function (event) {\n\t\t$('.focus-visible-indicator').removeClass('focus-visible-indicator');\n\t\tif ($('li.has-dropdown.keyboard-activated')) {\n\t\t\tif ($('.top-banner-bar').data('header-for') == 'bootbarn_us') {\n\t\t\t\t$('li.has-dropdown.keyboard-activated').trigger('mouseleave');\n\t\t\t}\n\t\t\t$('li.has-dropdown.keyboard-activated').find('ul').find('a[href!=\"\"][href]').attr('tabindex','-1'); // Add negative tabindex to skip nested anchors when submenu is closed\n\t\t\t$('li.has-dropdown.keyboard-activated').attr('aria-expanded','false').removeClass('active keyboard-activated'); // Update expanded attribute and remove keyboard class\n\t\t}\n\t});\n\n\t/* --- Document Ready --- */\n\t$(document).ready(function() {\n\t\tvar adaSubMenuAttributes = {\n\t\t\t'role': 'menuitem',\n\t\t\t'aria-haspopup': 'true',\n\t\t\t'aria-expanded': 'false'\n\t\t}\n\t\t$('ul.menu-category.level-1 ul').attr('role','menu').attr('aria-label', function(n, x) {\n\t\t\treturn $(this).closest('li').find('.has-sub-menu').first().html();\n\t\t});\n\t\t$('ul.menu-category.level-1').find('a').filter(function(n, navLink) {\n\t\t\t// Add role=\"none\" to all list items, and then use specificity further down to override if needed\n\t\t\t$(navLink).parents('ul:not(.level-1)').find('li').attr('role','none');\n\t\t\t// Add tabindex=\"-1\" to all nested anchor tags to force tab order using arrow up and down events\n\t\t\t$(navLink).attr('tabindex','-1');\n\t\t\t// IF the href attribute is not empty, apply ADA attributes correctly for a menuitem\n\t\t\tif ($(navLink).attr('href') && $(navLink).attr('href').trim().length > 0) {\n\t\t\t\t$(navLink).attr('role','menuitem');\n\t\t\t// ELSE, if href attribute is empty, then ensure <a> gets skipped in keyboard navigation and screen readers\n\t\t\t} else {\n\t\t\t\t$(navLink).parent().attr(adaSubMenuAttributes);\n\t\t\t}\n\t\t});\n\t});\n\n\tif (siteName == SiteConstants.SiteIds.BootBarnUS && window.innerWidth == 1024) {\t\t\n\t\t$('body').on('click', function(e) {\n\t\t\tif ($('html').hasClass('size-tablet') && $('#navigation .has-dropdown').hasClass('active')) {\n\t\t\t\tif(e.target.id == '#navigation .has-dropdown') {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif( $(e.target).closest('#navigation .has-dropdown').length > 0 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t$('#navigation .has-dropdown').removeClass('active');\n\t\t\t\t$('html').removeClass('menu-active');\n\t\t\t\t$('.header-wrapper .top-banner').removeClass('nav-active');\n\t\t\t\t$('html').removeClass('desktop-nav-active');\n\t\t\t}\n\t\t});\n\t}\n\t\n\t\n\t$('body').on('click', '#navigation .level-3 > li > a.offer-primary', function(event) {\n\t\tif (siteName == SiteConstants.SiteIds.CountryOutfittersUS && $('html').hasClass('size-mobile')) {\n\t\t\tevent.preventDefault();\n\t\t\t\n\t\t\tvar $this = $(this);\n\t\t\tvar $parent = $this.closest('li');\n\t\t\tvar $container = $parent.closest('.level-2');\n\t\t\t\n\t\t\t$container.find('.level-3 li').not($parent).removeClass('active');\n\t\t\t$parent.toggleClass('active');\n\t\t}\n\t});\n}\n\nfunction navigationCollisionDetection($navigationEventTarget) {\n\tvar $container = $navigationEventTarget.closest('.has-dropdown');\n\t\n\t$container.removeClass('collision-right collision-both');\n\t\t\n\tvar $menu = $container.find('> .level-2');\n\t\n\tif ($menu.length > 0) {\n\t\tvar menuLeft = $menu.offset().left;\n\t\tvar menuRight = menuLeft + $menu.outerWidth();\n\t\t\n\t\tvar $boundaryContainer = $('.top-banner-inner');\n\t\t\n\t\tif ($boundaryContainer.find('> .shell').length > 0) {\n\t\t\t$boundaryContainer = $boundaryContainer.find('> .shell');\n\t\t}\n\t\t\n\t\tvar boundaryLeft = $boundaryContainer.offset().left;\n\t\tvar boundaryRight = boundaryLeft + $boundaryContainer.outerWidth();\n\t\t\n\t\tvar boundaryBuffer = 30;\n\n\t\tif (menuRight >= (boundaryRight + boundaryBuffer)) {\n\t\t\tvar buttonRight = $navigationEventTarget.offset().left + $navigationEventTarget.outerWidth();\n\t\t\t\n\t\t\tif (buttonRight - $menu.outerWidth() <= (boundaryLeft - boundaryBuffer)) {\n\t\t\t\t$container.addClass('collision-both');\n\t\t\t} else {\n\t\t\t\t$container.addClass('collision-right');\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction closeNavigation() {\n\t$('html').removeClass('menu-active');\n\t$('.menu-toggle').removeClass('active');\n\t$('#navigation .has-dropdown.active').removeClass('active').find('.level-2, .nav-secondary-dropdown').stop().slideUp(150);\n}","'use strict';\n\nvar ValidationSettings = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\n\nexports.initialize = initialize;\n\nfunction initialize($orderStatusForm) {\n\t$.validator.addMethod('orderNumber', ValidationHelper.ValidateOrderNumber, Resources.INVALID_ORDER_NUMBER);\n\t$.validator.addMethod('postalCode', ValidationHelper.ValidatePostalCode, Resources.INVALID_POSTAL_CODE);\n\t\n\tvar $orderStatusFormOrderNumber = $orderStatusForm.find('input[name$=\"_orderNumber\"]');\n\tvar $orderStatusFormOrderEmail = $orderStatusForm.find('input[name$=\"_orderEmail\"]');\n\tvar $orderStatusFormOrderPostalCode = $orderStatusForm.find('input[name$=\"_postalCode\"]');\n\t\n\tvar formValidator = $orderStatusForm.validate(ValidationSettings.Global);\n\t$orderStatusFormOrderNumber.rules('add', ValidationRules.OrderNumber);\n\t$orderStatusFormOrderEmail.rules('add', ValidationRules.Email);\n\t$orderStatusFormOrderPostalCode.rules('add', ValidationRules.PostalCode);\n}","'use strict';\n\nvar Promise = require('promise');\n\nexports.initialize = initialize;\nexports.verify = verify;\n\nfunction initialize() {\n\twindow.recaptchaLoaded = function () {\n\t\t$(document).trigger('Recaptcha.Loaded');\n\t};\n\n\twindow.emailSignup = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'Global.EmailSignup');\n\t};\n\n\twindow.accountLogin = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'Account.SubmitLogin');\n\t};\n\n\twindow.resetPassword = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'Account.ResetPassword');\n\t};\n\n\twindow.submitOPCPayment = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'Checkout.SubmitPayment');\n\t};\n\t\n\twindow.submitOPCPaymentPrivateLabel = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'Checkout.SubmitPaymentPrivateLabel');\n\t};\n\n\twindow.submitMerryMail = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'MerryMail.Send');\n\t};\n\t\n\twindow.submitRewardsCredit = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'RewardsCredit.Add');\n\t};\n\t\n\twindow.submitLoyaltyCredit = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'LoyaltyCredit.Add');\n\t};\n\t\n\twindow.submitGiftCard = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'GiftCard.Apply');\n\t};\n\n\twindow.submitPaymentVoucher = function (token) {\n\t\treturn verifyAndTriggerEvent(token, 'PaymentVoucher.Apply');\n\t};\n};\n\nfunction verifyAndTriggerEvent(token, eventName) {\n\treturn $.when(verify(token)).then(function(data, textStatus, xmlHttpRequest) {\n\t\treturn new Promise(function(resolve, reject) {\n\t\t\tif (data.success) {\n\t\t\t\t$(document).trigger(eventName);\n\t\t\t\tresolve();\t\n\t\t\t} else {\n\t\t\t\treject();\n\t\t\t}\n\t\t});\n\t});\t\n}\n\nfunction verify(token) {\n\treturn $.ajax({\n\t\tmethod: 'POST',\n\t\turl: Urls.verifyRecaptcha,\n\t\tcontentType: 'application/json',\n\t\tdata: JSON.stringify({\n\t\t\ttoken: token\n\t\t})\n\t});\n}","'use strict';\n\nvar loadingIndicator = require('./LoadingIndicator');\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nexports.initialize = initialize;\n\nvar productTileContainers = [];\n\nfunction initialize(options) {\n\tif (options.Url && options.Containers && options.Containers.length > 0) {\n\t\tfor (var index = 0; index < options.Containers.length; index++) {\n\t\t\tvar container = options.Containers[index];\n\t\t\t\n\t\t\tproductTileContainers[productTileContainers.length] = new ProductTileContainer(options.Url, container).load();\n\t\t}\n\t}\n}\n\nfunction ProductTileContainer(url, container, requestData) {\n\tvar $container;\n\tvar $containerBody;\n\tvar dataBuffer = {};\n\tvar htmlBuffer = {};\n\tvar currentHtmlBufferCount = 0;\n\tvar expectedHtmlBufferCount = 0;\n\n\tthis.load = function() {\n\t\t$container = $(container.Selector);\n\t\t$containerBody = $container.find('.accordion-body');\n\t\t$container.hide();\n\t\t\n\t\tif ($container.length > 0) {\n\t\t\t$containerBody.loading();\n\t\t\t$container.show();\n\t\t\t\t\t\t\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'POST',\n\t\t\t\turl: url,\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\taddProductId: container.addProductId,\n\t\t\t\t\texcludeProductId: container.excludeProductId\n\t\t\t\t}),\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (data && data.ProductIds && data.ProductIds.length > 0) {\n\t\t\t\t\t\tdataBuffer = data;\n\t\t\t\t\t\texpectedHtmlBufferCount = data.ProductIds.length;\n\n\t\t\t\t\t\tfor (var index = 0; index < data.ProductIds.length; index++) {\n\t\t\t\t\t\t\tgetProductHitTile(data.ProductIds[index]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(document).trigger('RecentlyViewedProducts.Done', $container);\n\t\t\t\t\t\t$container.hide();\n\t\t\t\t\t\tfinish();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\t$container.hide();\n\t\t\t\t\tfinish();\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t$(document).trigger('RecentlyViewedProducts.Done', $container);\n\t\t}\n\t}\n\n\tvar getProductHitTile = function(productId) {\n\t\tvar requestData = {\n\t\t\tpid: productId,\n\t\t\tshowswatches: 'true',\n\t\t\tshowpricing: 'true',\n\t\t\tshowpromotion: 'true',\n\t\t\tshowrating: 'true',\n\t\t\tshowbadges: 'false',\n\t\t\tshowaffirm: 'false',\n\t\t}\n\n\t\t$.ajax({\n\t\t\tmethod: 'GET',\n\t\t\turl: Urls.hitTile,\n\t\t\tdata: requestData,\n\t\t\tdataType: 'html',\n\t\t\tsuccess: function (data) {\n\t\t\t\tif (data) {\n\t\t\t\t\thtmlBuffer[productId] = '<li class=\"slide\">' + data + '</li>';\n\t\t\t\t}\n\t\t\t},\n\t\t\tcomplete: function () {\n\t\t\t\tcurrentHtmlBufferCount++;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t}\n\n\tvar render = function() {\n\t\tif (currentHtmlBufferCount == expectedHtmlBufferCount) {\n\t\t\tvar html = '';\n\n\t\t\tfor (var index = 0; index < dataBuffer.ProductIds.length; index++) {\n\t\t\t\tif (htmlBuffer[dataBuffer.ProductIds[index]]) {\n\t\t\t\t\thtml += htmlBuffer[dataBuffer.ProductIds[index]];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar $html = $(html);\n\t\t\tif (pageContext.site != SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\t\t\t$html.find('.product-tile').addClass('product');\n\t\t\t}\n\t\t\t$container.find('.slides').html($html);\n\t\t\t$container.find('.slider-products-primary').trigger('init-slider');\n\t\t\tfinish();\n\n\t\t\tif ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui) {\n\t\t\t    affirm.ui.refresh();\n\t\t\t}\n\t\t}\n\t}\n\n\tvar finish = function() {\n\t\t$containerBody.loading('destroy');\n\t\t$(document).trigger('RecentlyViewedProducts.Done', $container);\n\t\t$(document).trigger('Currency.Update', $container);\n\t}\n}","'use strict';\n\nvar loadingIndicator = require('./LoadingIndicator');\n\nexports.initialize = initialize;\n\nvar recommendationsContainers = [];\n\nfunction initialize(options) {\n\tif (options.Url && options.Containers && options.Containers.length > 0) {\n\t\tfor (var index = 0; index < options.Containers.length; index++) {\n\t\t\trecommendationsContainers[recommendationsContainers.length] = new RecommendationsContainer(options.Url, options.Containers[index]).load();\n\t\t}\n\t}\n}\n\nfunction RecommendationsContainer(url, container) {\n\tvar $container;\n\tvar $containerBody;\n\tvar dataBuffer = {};\n\tvar htmlBuffer = {};\n\tvar currentHtmlBufferCount = 0;\n\tvar expectedHtmlBufferCount = 0;\n\n\tthis.load = function() {\n\t\t$container = $(container.Selector);\n\t\t$containerBody = $container.find('.accordion-body');\n\t\t\n\t\t$container.hide();\n\t\t\n\t\tif ($container.length > 0 && container.ProductId && container.RelationType) {\n\t\t\t$containerBody.loading();\n\t\t\t$container.show();\n\t\t\t\n\t\t\tvar requestData = {\n\t\t\t\t'styles': container.ProductId,\n\t\t\t\t'relationtype': container.RelationType\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'GET',\n\t\t\t\turl: url,\n\t\t\t\tdata: requestData,\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (data && data.products && data.products.length > 0) {\n\t\t\t\t\t\tdataBuffer = data;\n\t\t\t\t\t\texpectedHtmlBufferCount = data.products.length;\n\n\t\t\t\t\t\tfor (var index = 0; index < data.products.length; index++) {\n\t\t\t\t\t\t\tgetProductHitTile((index + 1), data.products[index].productid);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$container.hide();\n\t\t\t\t\t\tfinish();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\t$container.hide();\n\t\t\t\t\tfinish();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tvar getProductHitTile = function(position, productId) {\n\t\tvar requestData = {\n\t\t\t'position': position,\n\t\t\t'pid': productId,\n\t\t\t'showswatches': 'true',\n\t\t\t'showpricing': 'true',\n\t\t\t'showpromotion': 'true',\n\t\t\t'showrating': 'true',\n\t\t\t'showbadges': 'false',\n\t\t\t'showaffirm': 'false',\n\t\t}\n\n\t\t$.ajax({\n\t\t\tmethod: 'GET',\n\t\t\turl: Urls.hitTile,\n\t\t\tdata: requestData,\n\t\t\tdataType: 'html',\n\t\t\tsuccess: function (data) {\n\t\t\t\tif (data) {\n\t\t\t\t\thtmlBuffer[productId] = '<li class=\"slide\">' + data + '</li>';\n\t\t\t\t}\n\t\t\t},\n\t\t\tcomplete: function () {\n\t\t\t\tcurrentHtmlBufferCount++;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t}\n\n\tvar render = function() {\n\t\tif (currentHtmlBufferCount == expectedHtmlBufferCount) {\n\t\t\tvar html = '';\n\n\t\t\tfor (var index = 0; index < dataBuffer.products.length; index++) {\n\t\t\t\tif (htmlBuffer[dataBuffer.products[index].productid]) {\n\t\t\t\t\thtml += htmlBuffer[dataBuffer.products[index].productid];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar $html = $(html);\n\t\t\t$html.find('.product-tile').addClass('product');\n\n\t\t\t$container.find('.slides').html($html);\n\t\t\t$container.find('.slider-products-primary').trigger('init-slider');\n\t\t\tfinish();\n\n\t\t\tif ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui) {\n\t\t\t    affirm.ui.refresh();\n\t\t\t}\n\t\t}\n\t}\n\n\tvar finish = function() {\n\t\t$containerBody.loading('destroy');\n\t\t$(document).trigger('RelevantProductRecommendations.Done', $container);\n\t\t$(document).trigger('Currency.Update', $container);\n\t}\n}","'use strict';\n\nvar _ = require('lodash');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nexports.initialize = initialize;\nexports.render = render;\n\nvar data;\nvar loaded;\nvar options;\nvar $container;\n\nfunction initialize($containerObject, optionsObject) {\n\tif (Urls && Urls.getSameDayShippingCountdownData && Urls.getSameDayShippingCountdownContentSlot) {\n\t\t$container = $containerObject;\n\t\toptions = optionsObject;\n\t\tdata = {};\n\t\tloaded = {\n\t\t\tContentSlot: false,\n\t\t\tData: false\n\t\t}\n\t\t\n\t\t$(document).off('SameDayShippingCountdown.Update').on('SameDayShippingCountdown.Update', update);\n\t\t\n\t\t$.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.getSameDayShippingCountdownData,\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function (response) {\n\t\t\t\tloaded.Data = true;\n\t\t\t\tdata.Response = response;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t\t\n\t\t$.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.getSameDayShippingCountdownContentSlot,\n\t\t\tdataType: 'html',\n\t\t\tsuccess: function (html) {\n\t\t\t\tloaded.ContentSlot = true;\n\t\t\t\tdata.Html = html;\n\t\t\t\trender();\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction render() {\n\tif (loaded && loaded.ContentSlot && loaded.Data && data) {\n\t\tvar countdownText = '';\n\t\t\n\t\tif (data.Response && data.Response.TimeLeft) {\n\t\t\tif (data.Response.TimeLeft.Hours > 0) {\n\t\t\t\tcountdownText += data.Response.TimeLeft.Hours + ' ' + (data.Response.TimeLeft.Hours > 1 ? Resources.HOURS_ABBREVIATED : Resources.HOUR_ABBREVIATED);\n\t\t\t}\n\t\t\t\n\t\t\tif (data.Response.TimeLeft.Minutes > 0) {\n\t\t\t\tif (countdownText != '') {\n\t\t\t\t\tcountdownText += ' ';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcountdownText += data.Response.TimeLeft.Minutes + ' ' + (data.Response.TimeLeft.Minutes > 1 ? Resources.MINUTES_ABBREVIATED : Resources.MINUTE_ABBREVIATED);\n\t\t\t}\n\t\t}\n\n\t\tif (data.Html) {\n\t\t\t$container.html(data.Html).find('input[name=\"initTime\"]').remove();\n\t\t}\n\t\t\n\t\tif (countdownText) {\n\t\t\t$container.html(_.template($container.html(), TemplateConstants.Lodash.Settings)({\n\t\t\t\tcountdown: countdownText\n\t\t\t}));\n\t\t\t\n\t\t\tupdate();\n\t\t} else {\n\t\t\t$(document).off('SameDayShippingCountdown.Update');\n\t\t}\n\t}\n};\n\nfunction update() {\n\tif ($container.html().replace(/<!--([^\\d]*)-->/g, '').trim().length > 0) {\n\t\tvar $selectedVariation = $('.product-variations .attribute-size .select-text [same-day-shipping]');\n\t\t\n\t\tif ($selectedVariation.length > 0) {\n\t\t\tif ($selectedVariation.attr('same-day-shipping').toLowerCase() == 'true') {\n\t\t\t\t$container.show();\n\t\t\t} else {\n\t\t\t\t$container.hide();\n\t\t\t}\n\t\t} else if (parseFloat(options.percentageOfVariantsFromWarehouse) >= parseFloat(options.sameDayShippingWindowWarehousePercentage)) {\n\t\t\t$container.show();\n\t\t} else {\n\t\t\t$container.hide();\n\t\t}\n\t}\n}","'use strict';\n\nvar dialog = require('./dialog');\n\n/**\n * @function cookieprivacy    Used to display/control the scrim containing the cookie privacy code\n **/\nmodule.exports = function () {\n    /**\n     * If we have not accepted cookies AND we're not on the Privacy Policy page, then show the notification\n     * NOTE: You will probably want to adjust the Privacy Page test to match your site's specific privacy / cookie page\n     */\n    if (SitePreferences.COOKIE_HINT === true && document.cookie.indexOf('dw_cookies_accepted') < 0) {\n        // check for privacy policy page\n        if ($('.privacy-policy').length === 0) {\n            dialog.open({\n                url: Urls.cookieHint,\n                options: {\n                    closeOnEscape: false,\n                    dialogClass: 'no-close',\n                    buttons: [{\n                        text: Resources.I_AGREE,\n                        click: function () {\n                            $(this).dialog('close');\n                            enableCookies();\n                        }\n                    }]\n                }\n            });\n        }\n    } else {\n        // Otherwise, we don't need to show the asset, just enable the cookies\n        enableCookies();\n    }\n\n    function enableCookies() {\n        if (document.cookie.indexOf('dw=1') < 0) {\n            document.cookie = 'dw=1; path=/';\n        }\n        if (document.cookie.indexOf('dw_cookies_accepted') < 0) {\n            document.cookie = 'dw_cookies_accepted=1; path=/';\n        }\n    }\n};\n","'use strict';\n\nexports.init = function init () {\n\n    $('.countdown-wrapper').each(function() {\n        var $this = $(this),\n          countdownStr = $this.data('countdown-date'),\n          countdownDate = new Date(countdownStr);\n\n        var ts = countdown(new Date(), countdownDate, countdown.DAYS | countdown.HOURS | countdown.MINUTES);\n        var showCountdown = ts.value > 0;\n\n        if (showCountdown) {\n          $this.find('.countdown-text').text(ts.toString());\n        }\n\n\n    });\n\n};\n","'use strict';\n\nexports.init = function init () {\n    $('.country-selector .current-country').on('click', function () {\n        $('.country-selector .selector').toggleClass('active');\n        $(this).toggleClass('selector-active');\n    });\n    // set currency first before reload\n    $('.country-selector .selector .locale').on('click', function (e) {\n        e.preventDefault();\n        var url = this.href;\n        var currency = this.getAttribute('data-currency');\n        $.ajax({\n            dataType: 'json',\n            url: Urls.setSessionCurrency,\n            data: {\n                format: 'ajax',\n                currencyMnemonic: currency\n            }\n        })\n        .done(function (response) {\n            if (!response.success) {\n                throw new Error('Unable to set currency');\n            }\n            window.location.href = url;\n        });\n    });\n};\n","'use strict';\n\nvar ajax = require('./ajax'),\n    util = require('./util'),\n    _ = require('lodash'),\n    imagesLoaded = require('imagesloaded');\n\nvar dialog = {\n    /**\n     * @function\n     * @description Appends a dialog to a given container (target)\n     * @param {Object} params  params.target can be an id selector or an jquery object\n     */\n    create: function (params) {\n        var $target, id;\n\n        if (_.isString(params.target)) {\n            if (params.target.charAt(0) === '#') {\n                $target = $(params.target);\n            } else {\n                $target = $('#' + params.target);\n            }\n        } else if (params.target instanceof jQuery) {\n            $target = params.target;\n        } else if ($('#dialog-container').length > 0) {\n            $target = $('#dialog-container');\n        } else {\n\t\t\t$target = $('<div id=\"dialog-container\"/>').appendTo('body');\n\t\t}\n\n        // if no element found, create one\n        if ($target.length === 0) {\n            if ($target.selector && $target.selector.charAt(0) === '#') {\n                id = $target.selector.substr(1);\n                $target = $('<div>').attr('id', id).addClass('dialog-content').appendTo('body');\n            }\n        }\n\n        if ((params.options != undefined && params.options != null) && (params.options.title == undefined || ('title' in params.options && params.options.title.length == 0))) {\n            params.options.dialogClass += ' ui-dialog-title-collapse';\n        }\n\n        // create the dialog\n        this.$container = $target;\n        this.$container.dialog(_.merge({}, this.settings, params.options || {}));\n\n        /* --- BOOT-5386 ---\n         * This is a workaround for a known jquery Dialog UI bug with the maxWidth option. By setting the Dialog width option to 100% and setting the CSS max-width\n         * to 800px, this allows the dialogs to be responsive width. This fix is necessary to create responsive Dialogs for smaller screens, but also be backwards \n         * compatible with existing dialogs on the site that have been previously set to the default size of 800px.\n         * https://stackoverflow.com/questions/16471890/responsive-jquery-ui-dialog-and-a-fix-for-maxwidth-bug\n         */\n        this.$container.parent().css(\"max-width\", \"800px\");\n    },\n    /**\n     * @function\n     * @description Opens a dialog using the given url (params.url) or html (params.html)\n     * @param {Object} params\n     * @param {Object} params.url should contain the url\n     * @param {String} params.html contains the html of the dialog content\n     */\n    open: function (params) {\n        // close any open dialog\n        this.close();\n        this.create(params);\n        this.replace(params);\n    },\n    /**\n     * @description populate the dialog with html content, then open it\n     **/\n    openWithContent: function (params) {\n        var content, position, callback;\n\n        if (!this.$container) { return; }\n        content = params.content || params.html;\n        if (!content) { return; }\n        this.$container.empty().html(content);\n        if (!this.$container.dialog('isOpen')) {\n            this.$container.dialog('open');\n        }\n\n        if (params.options) {\n            position = params.options.position;\n        }\n        if (!position) {\n            position = this.settings.position;\n        }\n        imagesLoaded(this.$container).on('done', function () {\n            this.$container.dialog('option', 'position', position);\n        }.bind(this));\n\n        callback = (typeof params.callback === 'function') ? params.callback : function () {};\n        callback();\n    },\n    /**\n     * @description Replace the content of current dialog\n     * @param {object} params\n     * @param {string} params.url - If the url property is provided, an ajax call is performed to get the content to replace\n     * @param {string} params.html - If no url property is provided, use html provided to replace\n     */\n    replace: function (params) {\n        if (!this.$container) {\n            return;\n        }\n        if (params.url) {\n            params.url = util.appendParamToURL(params.url, 'format', 'ajax');\n            ajax.load({\n                url: params.url,\n                data: params.data,\n                callback: function (response) {\n                    params.content = response;\n                    this.openWithContent(params);\n                }.bind(this)\n            });\n        } else if (params.html) {\n            this.openWithContent(params);\n        }\n    },\n    /**\n     * @function\n     * @description Closes the dialog\n     */\n    close: function () {\n        if (!this.$container) {\n            return;\n        }\n        this.$container.dialog('close');\n    },\n    /**\n     * @function\n     * @description Submits the dialog form with the given action\n     * @param {String} The action which will be triggered upon form submit\n     */\n    submit: function (action, callback) {\n        var $form = this.$container.find('form:first');\n        // set the action\n        $('<input/>').attr({\n            name: action,\n            type: 'hidden'\n        }).appendTo($form);\n        // serialize the form and get the post url\n        var data = $form.serialize();\n        var url = $form.attr('action');\n        // make sure the server knows this is an ajax request\n        if (data.indexOf('ajax') === -1) {\n            data += '&format=ajax';\n        }\n        // post the data and replace current content with response content\n        $.ajax({\n            type: 'POST',\n            url: url,\n            data: data,\n            dataType: 'html',\n            success: function (html) {\n                this.$container.html(html);\n                if (callback) {\n                    callback();\n                }\n            }.bind(this),\n            failure: function () {\n                window.alert(Resources.SERVER_ERROR);\n            }\n        });\n    },\n    exists: function () {\n        return this.$container && (this.$container.length > 0);\n    },\n    isActive: function () {\n        return this.exists() && (this.$container.children.length > 0);\n    },\n    settings: {\n        autoOpen: false,\n        height: 'auto',\n        modal: true,\n        overlay: {\n            opacity: 0.5,\n            background: 'black'\n        },\n        resizable: false,\n        title: '',\n        width: '100%',\n\t\topen: function(event, ui) {\n\t\t\t\n\t\t},\n        close: function () {\n            $(this).dialog('close');\n        },\n        position: {\n            my: 'center',\n            at: 'center',\n            of: window,\n            collision: 'flipfit'\n        }\n    }\n};\n\nmodule.exports = dialog;\n","'use strict';\n\nvar _ = require('lodash'),\n\tdialog = require('./dialog');\n\nvar $dialogContent,\n\tstate = {},\n\tready = {},\n\ttemplates = {},\n\thtml = {};\n\nvar templateSettings = { interpolate: /{{([\\s\\S]+?)}}/g };\n\nfunction initialize(options) {\n\tstate['options'] = options || {};\n\t\n\tloadTemplates();\n\tloadStores();\n\tloadStates();\n\t\n\topenDialog();\t\n}\n\nfunction openDialog() {\n\tready['dialog'] = false;\n\t\n\tdialog.open({\n\t\thtml: '<div class=\"dialog-loading\"></div>',\n\t\toptions: {\n\t\t\ttitle: Resources.FIND_MORE_STORES,\n\t\t\tdialogClass: 'dialog-find-more-stores',\n\t\t\tresizable: false,\n\t\t\tdraggable: false,\n\t\t\topen: function() {\n\t\t\t\t$dialogContent = $(this);\n\t\t\t\tready['dialog'] = true;\n\t\t\t\t\n\t\t\t\tevents();\n\t\t\t\trender();\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction events() {\n\t$dialogContent.off('click.findMoreStores.go').on('click.findMoreStores.go', '.search button', function () {\n\t\tloadStores(true);\n\t});\n\t\n\t$dialogContent.off('click.findMoreStores.submit').on('click.findMoreStores.submit', '.submit', function () {\n\t\tvar selectedStore = $dialogContent.find('.stores-list input:checked').val();\n\t\t\n\t\tif (selectedStore) {\n\t\t\t$(document).trigger('opc.SetShippingAddress', state['stores'].addresses[selectedStore]);\n\t\t\tdialog.close();\n\t\t}\n\t});\n}\n\nfunction loadStates() {\n\tready['states'] = false;\n\t\n\t$.ajax({ method: 'POST', url: Urls.getCountryStates, data: 'countryCode=US', dataType: 'json', success: function (data) {\t\t\n\t\tstate['states'] = JSON.parse(data.statesList);\n\t\tready['states'] = true;\n\t\t\t\t\n\t\trender();\n\t}});\n}\n\nfunction renderStates() {\n\thtml['states'] = '<option class=\"placeholder\"></option>';\n\t\n\tfor (var stateElement in state['states']) {\n\t\tvar stateOption = state.states[stateElement];\n\t\t\n\t\thtml['states'] += '<option value=\"' + stateOption.label + '\">' + stateOption.label + '</option>';\n\t}\n\t\n\t$dialogContent.find('select[name=\"StateCode\"]').html(html['states']);\n}\n\nfunction loadStores(update) {\n\tready['stores'] = false;\n\t\n\tvar payload = {};\n\t\n\tif ($dialogContent) {\n\t\tpayload.PostalCode = $dialogContent.find('.search [name=\"PostalCode\"]').val();\n\t\tpayload.StateCode = $dialogContent.find('.search [name=\"StateCode\"]').val();\n\t}\n\t\n\tpayload.storeQuery = state.options['storeQuery'] ? state.options['storeQuery'] : {};\n\t\n\t$.ajax({ method: 'POST', url: Urls.getMoreStoresAddressList, data: JSON.stringify(payload), contentType: 'application/json', dataType: 'json', success: function (data) {\t\t\n\t\tstate['stores'] = data;\n\t\tready['stores'] = true;\n\t\t\n\t\tif (update) {\n\t\t\trenderStores();\n\t\t} else {\n\t\t\trender();\n\t\t}\n\t}});\n}\n\nfunction renderStores() {\n\thtml['stores'] = '';\n\t\n\tif (state['stores'].addresses.length > 0) {\n\t\tvar index = 0;\n\t\tfor (var storeAddressesElement in state['stores'].addresses) {\n\t\t\tvar storeAddress = state['stores'].addresses[storeAddressesElement];\n\t\t\t\n\t\t\tvar streetAddress = storeAddress.address1;\n\t\t\tif (storeAddress.address2) {\n\t\t\t\tstreetAddress += storeAddress.address2;\n\t\t\t}\n\t\t\t\n\t\t\thtml['stores'] += templates['location']({\n\t\t\t\tid: index,\n\t\t\t\tname: storeAddress.fullName + ' ' + storeAddress.lastName,\n\t\t\t\taddress: streetAddress,\n\t\t\t\tcity: storeAddress.city,\n\t\t\t\tstate: storeAddress.stateCode,\n\t\t\t\tpostal: storeAddress.postalCode,\n\t\t\t\tphone: storeAddress.phone\n\t\t\t});\n\t\t\t\n\t\t\tindex++;\n\t\t}\n\t\t\n\t\t$dialogContent.find('.no-results').hide();\n\t\t$dialogContent.find('.stores-list').html(html['stores']).show();\n\t} else {\n\t\t$dialogContent.find('.no-results').show();\n\t\t$dialogContent.find('.stores-list').hide();\n\t}\n\t\n\t\n}\n\nfunction loadTemplates() {\n\ttemplates = {};\n\t\n\t$.ajax({ method: 'POST', url: Urls.getMoreStoresDialogTemplate, dataType: 'html', success: function (data) {\n\t\ttemplates['dialog'] = _.template(data, templateSettings);\n\t\trender();\n\t}});\n\t\n\t$.ajax({ method: 'POST', url: Urls.getMoreStoresLocationTemplate, dataType: 'html', success: function (data) {\n\t\ttemplates['location'] = _.template(data, templateSettings);\n\t\trender();\n\t}});\n}\n\nfunction render(update) {\n\tif (ready['dialog'] && ready['stores'] && ready['states'] && templates['dialog'] && templates['location']) {\n\t\t$dialogContent.html(templates['dialog']());\n\t\t\n\t\tif (state.options && state.options.view) {\n\t\t\t$dialogContent.attr('view', state.options.view);\n\t\t} else {\n\t\t\t$dialogContent.removeAttr('view');\n\t\t}\n\t\t\n\t\trenderStores();\n\t\trenderStates();\n\t}\t\n}\n\nexports.initialize = initialize;","'use strict';\n\nvar ajax = require('./ajax'),\n    util = require('./util');\n/**\n * @function\n * @description Load details to a given gift certificate\n * @param {String} id The ID of the gift certificate\n * @param {Function} callback A function to called\n */\nexports.checkBalance = function (id, callback) {\n    // load gift certificate details\n    var url = util.appendParamToURL(Urls.giftCardCheckBalance, 'giftCertificateID', id);\n\n    ajax.getJson({\n        url: url,\n        callback: callback\n    });\n};\n","'use strict';\n\nvar ajax = require('./ajax'),\n    minicart = require('./minicart'),\n    util = require('./util');\n\nvar setAddToCartHandler = function (e) {\n    e.preventDefault();\n    var form = $(this).closest('form');\n\n    var options = {\n        url: util.ajaxUrl(form.attr('action')),\n        method: 'POST',\n        cache: false,\n        data: form.serialize()\n    };\n    $.ajax(options).done(function (response) {\n        if (response.success) {\n            ajax.load({\n                url: Urls.minicartGC,\n                data: {lineItemId: response.result.lineItemId},\n                callback: function (response) {\n                    minicart.show(response);\n                    form.find('input,textarea').val('');\n                }\n            });\n        } else {\n            form.find('span.error').hide();\n            for (var id in response.errors.FormErrors) {\n                var $errorEl = $('#' + id).addClass('error').removeClass('valid').next('.error');\n                if (!$errorEl || $errorEl.length === 0) {\n                    $errorEl = $('<span for=\"' + id + '\" generated=\"true\" class=\"error\" style=\"\"></span>');\n                    $('#' + id).after($errorEl);\n                }\n                $errorEl.text(response.errors.FormErrors[id].replace(/\\\\'/g, '\\'')).show();\n            }\n        }\n    }).fail(function (xhr, textStatus) {\n        // failed\n        if (textStatus === 'parsererror') {\n            window.alert(Resources.BAD_RESPONSE);\n        } else {\n            window.alert(Resources.SERVER_CONNECTION_ERROR);\n        }\n    });\n};\n\nexports.init = function () {\n    $('#AddToBasketButton').on('click', setAddToCartHandler);\n};\n","'use strict';\n\nvar giftCardBalanceInquiryComponent = require('../components/GiftCardBalanceInquiryComponent');\n\nexports.initializeAllFoundComponents = initializeAllFoundComponents;\n\nfunction initializeAllFoundComponents($containerParameter) {\n\tvar $container = $containerParameter || $(document);\n\t\n\tvar $balanceInquiryComponents = $container.find('.gift-card-balance-inquiry-component');\n\tif ($balanceInquiryComponents.length > 0) {\n\t\t$balanceInquiryComponents.each(function() {\n\t\t\tgiftCardBalanceInquiryComponent.initialize($(this).parent());\n\t\t});\n\t}\n}","'use strict';\n\nexports.Validate = validate;\n\nfunction validate(action) {\n\treturn new Promise(function(resolve, reject) {\n\t\t$.ajax({\n\t\t\tmethod: 'post',\n\t\t\turl: Urls.Request.Validate,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\tAction: action\n\t\t\t}),\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\tif (data) {\n\t\t\t\t\tresolve(data);\n\t\t\t\t} else {\n\t\t\t\t\treject(data);\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function(data) {\n\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t} else {\n\t\t\t\t\treject(data);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}","'use strict';\n// jQuery extensions\n\nmodule.exports = function () {\n    // params\n    // toggleClass - required\n    // triggerSelector - optional. the selector for the element that triggers the event handler. defaults to the child elements of the list.\n    // eventName - optional. defaults to 'click'\n    $.fn.toggledList = function (options) {\n        if (!options.toggleClass) { return this; }\n        var list = this;\n        return list.on(options.eventName || 'click', options.triggerSelector || list.children(), function (e) {\n            e.preventDefault();\n            var classTarget = options.triggerSelector ? $(this).parent() : $(this);\n            classTarget.toggleClass(options.toggleClass);\n            // execute callback if exists\n            if (options.callback) {options.callback();}\n        });\n    };\n\n    $.fn.syncHeight = function () {\n\t\tthis.height('auto');\n        var arr = $.makeArray(this);\n        arr.sort(function (a, b) {\n            return $(a).height() - $(b).height();\n        });\n        return this.height($(arr[arr.length - 1]).height());\n    };\n\n\t$.fn.syncHeightToMinimum = function () {\n\t\tthis.height('auto');\n        var arr = $.makeArray(this);\n        arr.sort(function (a, b) {\n            return $(a).height() - $(b).height();\n        });\n        return this.height($(arr[0]).height());\n    };\n\n\t$.fn.syncHeightToAverage = function () {\n\t\tthis.height('auto');\n        var arr = $.makeArray(this);\n        arr.sort(function (a, b) {\n            return $(a).height() - $(b).height();\n        });\n        return this.height($(arr[parseInt(arr.length/2, 10)]).height());\n    };\n};\n","'use strict';\n\nvar _ = require('lodash');\nvar sliders = require('./sliders');\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nexports.init = function init () {\n\tslickSlideJumbotron();\n\n\t// $('.jumbotron-ajax').ready(function(){\n\t// \trenderJumbotronSlot();\n\t// });\n\t\n\tvar renderJumbotronSlot = function(){\n\t\tif (Urls && Urls.getJumbotronSlot) {\n\t\t\t$.ajax({ method: 'POST', url: Urls.getJumbotronSlot, dataType: 'html', success: function (data) {\n\t\t\t\tvar html = '';\n\t\t\t\tvar contentSlot;\n\t\t\t\tvar isJson = false;\n\t\t\t\t\n\t\t\t\tvar templateSettings = {\n\t\t\t    \tinterpolate: /{{([\\s\\S]+?)}}/g\n\t\t\t    };\n\t\t\t\t\n\t\t\t\tvar template = _.template($('#template-jumbotron').html(), templateSettings);\n\t\t\t\t\n\t\t\t\tvar dataPayload = data.substr(data.indexOf('{'), data.length);\n\t\t\t\t\n\t\t\t\tvar endPayloadIndex = dataPayload.length;\n\t\t\t\tif (dataPayload.indexOf('<!-- dwMarker') > 0) {\n\t\t\t\t\tendPayloadIndex = dataPayload.indexOf('<!-- dwMarker');\n\t\t\t\t}\n\t\t\t\tdataPayload = dataPayload.substr(0, endPayloadIndex);\n\t\t\t\t\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\tcontentSlot = JSON.parse(dataPayload);\n\t\t\t\t\tisJson = true;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.warn('ContentSlot template not set to JSON');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (contentSlot) {\n\t\t\t\t\tif (contentSlot.content) {\n\t\t\t\t\t\thtml = template({ jumbotron: buildContentSlotFromJSON(contentSlot) });\n\t\t\t\t\t}\n\t\t\t\t} else if (!isJson) {\n\t\t\t\t\thtml = template({ jumbotron: data });\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$('.jumbotron-ajax').addClass('active').html(html);\n\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t\t\t\tslickSlideJumbotron();\n\t\t\t\t}\n\t\t\t\t$(document).trigger('app.resize');\n\t\t\t}});\n\t\t}\n\t}\n\n\t//fishtag rigging content asset 'cat-global-header'\n\t//$('.cat-global-header').ready(function(){\n\t//\trenderFishtag();\n\t//});\n\t\n\tfunction renderFishtag(){\n\t\tif (Urls && Urls.getFishtag) {\n\t\t\t$.ajax({ method: 'POST', url: Urls.getFishtag, dataType: 'html', success: function(data){\n\t\t\t\tvar html = '';\n\t\t\t\tvar contentSlot;\n\t\t\t\tvar isJson = false;\n\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\tcontentSlot = JSON.parse(data.substr(data.indexOf('{'), data.length));\n\t\t\t\t\tisJson = true;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.warn('ContentSlot template not set to JSON');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (contentSlot && contentSlot.content) {\n\t\t\t\t\thtml = buildContentSlotFromJSON(contentSlot);\n\t\t\t\t} else if (!isJson) {\n\t\t\t\t\thtml = data;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$('.fishtag-slot').html(html);\n                rotateText($('.top-banner-message'), $('.top-banner-message').data('duration'));\n\t\t\t}});\n\t\t}\n\t}\n\t\n\tfunction buildContentSlotFromJSON(contentSlotJSON) {\n\t\tvar body = '';\n\t\t\n\t\tif (contentSlotJSON && contentSlotJSON.content) {\n\t\t\tfor (var contentSlotItem in contentSlotJSON.content) {\n\t\t\t\tbody += contentSlotJSON.content[contentSlotItem].body;\n\t\t\t}\n\t\t\n\t\t\tif (contentSlotJSON.countdownTo) {\n\t\t\t\tbody = '<div class=\"countdown-wrapper\" data-countdown-date=\"' + contentSlotJSON.countdownTo + '\">' + body + '</div>'; \n\t\t\t}\n\t\t}\n\t\t\n\t\treturn body;\n\t}\n\t\n\t// Rotate Text for fishtag\n\tfunction rotateText($element, duration) {\n\t\tvar lengthSlider \t\t\t= $element.find('.rotate-element').length;\n\t\tvar $rotateElement \t\t\t= $element.find('.rotate-element');\n\n\t\tsetInterval(function() {\n\t\t\tvar $rotateElementActive \t= $element.find('.active');\n\t\t\tvar $nextElement = $rotateElementActive.next();\n\n\t\t\tif($nextElement.index() === -1) {\n\t\t\t\t$nextElement = $element.find('.rotate-element:first-child');\n\n\t\t\t\t$nextElement\n\t\t\t\t\t.addClass('active')\n\t\t\t\t\t.siblings()\n\t\t\t\t\t.removeClass('active');\n\t\t\t} else {\n\t\t\t\t$nextElement\n\t\t\t\t\t.addClass('active')\n\t\t\t\t\t.siblings()\n\t\t\t\t\t.removeClass('active');\n\t\t\t}\n\t\t}, duration);\n\t}\n\n\tfunction slickSlideJumbotron() {\n\t\tvar slidesMobile = $('.gbcolumns').closest('[data-slides-mobile]').length > 0 ? parseInt($('.gbcolumns').closest('[data-slides-mobile]').attr('data-slides-mobile')) : 1;\n\t\tvar slidesDesktop = $('.gbcolumns').closest('[data-slides-desktop]').length > 0 ? parseInt($('.gbcolumns').closest('[data-slides-desktop]').attr('data-slides-desktop')) : 4;\n\t\n\t\tsliders.init('.gbcolumns', {dots: false, breakpoints: {0: {slidesToShow: slidesMobile, arrows: true}, 768: {slidesToShow: slidesDesktop}}});\n\t}\n}","'use strict';\n\n/* -------------------------\n * LOGIN\n * -------------------------\n */\n\nvar loadingIndicator = require('./components/LoadingIndicator');\nvar dialog = require('./dialog');\nvar loginDialog = require('./loginDialog');\nvar recaptcha = require('./components/Recaptcha');\nvar util = require('./util'); //util reference\nvar\tvalidator = require('./validator');\n\nvar GoogleTagManagerClient = require('../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TPromise = require('promise');\n\nvar dataBuffer = {};\nvar options = {};\nvar loaded = {};\nvar loadingIndicatorSettings = {\n    IsLabelShown: false,\n    CssClass: 'fullscreen',\n    BackgroundColor: 'transparent'\n};\nvar opcLoggedInCustomerAddresses = [];\n\n/**\n * @private\n * @function\n * @description init events for the loginPage\n */\nfunction initLoginEvents() {\n    //toggle the value of the rememberme checkbox\n    $(document).on('change', '.login-rememberme input', function () {\n        if ($(this).prop('checked')) {\n            $('#rememberme').val('true');\n        } else {\n            $('#rememberme').val('false');\n        }\n    });\n    $(document).on('click', '#optin-privacy-policy', function(e) { \n        e.preventDefault(); \n        location.href = Urls.privacyPage; \n    });\n    $(document).on('click', '#reward-learn-more', function(e) { \n        e.preventDefault(); \n        location.href = Urls.learnFAQ; \n    });\n    $(document).on('click', '.movetoaddr', function(e){\n        e.preventDefault();\n        $('html, body').animate({ \n            scrollTop: $('.billing-address-form').eq(0).offset().top\n        }, 1000);\n    });\n    $(document).on('click', '#attach-rewards-form label', function() {\n        $('#attach-rewards-form input').removeAttr('checked');\n        $(this).siblings('[name=\"attach-rewards-options\"]').attr('checked', 'checked');\n    });\n}\n\nfunction validateLoginForm($form, checkFields) {\t\n    if (!$form || !checkFields) { return false }\n\n    var $emailField = $form.find('input[name*=\"_username\"]');\t\n    var $passwordField = $form.find('input[name*=\"_password\"]');\n    var $passcodeField = $form.find('input[name*=\"_passcode\"]');\n    var emailValue = $emailField.length > 0 ? $emailField.val().trim() : null;\n\tvar passwordValue = $passwordField.length > 0 ? $passwordField.val().trim() : null;\n    var passcodeValue = $passcodeField.length > 0 ? $passcodeField.val().trim() : null;\n\tvar formValidation = true;\n\n    for (var i = 0; i < checkFields.length; i++) {\n        var currentField = checkFields[i];\n                \n        if (currentField.toUpperCase() == 'EMAIL' && (!emailValue || emailValue.length == 0)) {\n            formValidation = false;\n            $form.find('input[name*=\"_username\"]').addClass('error');\n        }\n        if (currentField.toUpperCase() == 'PASSWORD' && (!passwordValue || passwordValue.length == 0)) {\n            formValidation = false;\n            $form.find('input[name*=\"_password\"]').addClass('error');\n        }\n        if (currentField.toUpperCase() == 'PASSCODE' && (!passcodeValue || passcodeValue.length == 0)) {\n            formValidation = false;\n            $form.find('input[name*=\"_passcode\"]').addClass('error');\n        }\n    }\n\t\t\t\n\tif (!formValidation) {\n        $form.find('.login-dialog-error .invalid-missing-fields').removeClass('d-none');\n        return false;\n    } else {\n        $form.find('.login-dialog-error span').addClass('d-none');\n        return true;\n    }\n}\n\nfunction errorHandling(data, dialogTitle, dialogHtml) {\n    if (data && typeof data === 'object' && 'message' in data) {\n        console.log(data.message);\n    }\n    dialog.open({\n        html: dialogHtml,\n        options: {\n            title: dialogTitle,\n            draggable: false,\n            open: function(event, ui) {                                    \n                $('body').addClass('dialog-open');\n            },\n            close: function(event, ui) {\n                $('body').removeClass('dialog-open');\n            }\n        }\n    });\n}\n\n// Cordial tracking for loginPage and loginDialog\nfunction loginCordialAccountEvent($form, isLoginDialog) {\n    var username = $form.find('input[name*=\"_username\"]').val().trim();\n        \n    var auth_data = {\n        email: username\n    }\n        \n    var contact_data = {\n        'channels': {\n            'email': {\n                'address': username      \n            }\n        }\n    };\n    \n    var properties = {\n        \"email\": username,\n        \"loginType\": isLoginDialog ? \"login-dialog\" : \"login\"\n    };\n        \n    if (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n        crdl([\t\t\t\t\n            ['contact', auth_data, contact_data],\n            ['event', 'login', properties]\n        ]);\n    }\n}\n\n// Cordial password reset - no account event\nfunction passwordResetNoAccountCordialEvent(container) {\n    if (container && $(container).find('.reset-password .no-account').length > 0) {\n        var email = $('.no-account').text();\n\t\n\t\tvar auth_data = {\n\t\t\temail: email\n\t\t}\n\t\tvar contact_data = {\n\t\t\t'channels': {\n\t\t\t    'email': {\n\t\t\t        'address': email\n\t\t\t    }\n\t\t\t}\n\t\t};\n\t\t\t\n\t\tvar properties = {\n\t\t\t\"email\": email\n\t\t};\n\n\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\tcrdl([\n\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t['event', 'reset-password-no-account', properties]\n\t\t\t]);\n\t\t}\n\t}\n}\n\nfunction initializeRecaptchaForLogin() {\n\trenderRecaptchaForLogin();\n\t$(document).on('Account.SubmitLogin', function(event) {\n\t\t$('#accountLoginButton').click();\n\t});\n}\n\nfunction renderRecaptchaForLogin() {\n\tif (loaded.Recaptcha && $('#accountLoginButton').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForAccountLogin && options.Recaptcha.GoogleSiteKey) {\n\t\tdataBuffer.LoginRecaptcha = grecaptcha.render('accountLoginButton', {\n\t        'sitekey': options.Recaptcha.GoogleSiteKey,\n\t        'callback': accountLogin,\n\t        'badge': 'bottomleft'\n\t    });\n\t}\n}\n\nfunction renderRecaptchaForPasswordReset() {\n\tif (loaded.Recaptcha && $('#request-password-send-btn').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForPasswordReset && options.Recaptcha.GoogleSiteKey) {\n\t\tif (dataBuffer.ResetPasswordRecaptcha) {\n\t\t\tgrecaptcha.reset(dataBuffer.ResetPasswordRecaptcha);\n\t\t}\n\n\t\tdataBuffer.ResetPasswordRecaptcha = grecaptcha.render('request-password-send-btn', {\n\t        'sitekey': options.Recaptcha.GoogleSiteKey,\n\t        'callback': window.resetPassword,\n\t        'badge': 'bottomleft'\n\t    });\n\t}\n}\n\nvar updateCustomerDetails = function (form, name) {\n    var $form = $(form);\n \n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.onePageLogin),\n        data: $form.serialize() + '&' + name + '=' + name\n    }));\n }\n\nfunction showNotification(text, selector, msgType) {\n    var $selector = $(selector);\n\tif ($selector.length == 0) {\n        var $form = $('form.opc-login'),\n            $selector = $('<span/>', {'class': 'login-notification', 'tabindex': '0'}).wrap('<div class=\"formfield clearfix error-box\"><div class=\"form-row required\"><div class=\"field-wrapper\"></div></div></div>');\n\n        $selector.parent().parent().parent().insertBefore('form.opc-login .form-row-button');\n        $selector = $(selector);\n    }\n\n    $selector.removeClass('success error').addClass(msgType).text(text).focus();\n}\n \nfunction clearNotification(selector) {\n     if(selector.length){\n        $('.formfield.error-box').remove();\n\t\tselector.removeClass('success error');\n     }\n}\n \n// GTM and Cordial tagging for cart opc-login\nfunction opcLoginTagging($form, callback) {\n    var email =  $form.find('input[name*=\"username\"]').val();\n    var auth_data = {\n        email: email\n    }\n    var contact_data = {\n        'channels': {\n            'email': {\n                'address': email      \n            }\n        }\n    };\n    var properties = {\n        \"email\": email\n    };\n    GoogleTagManagerClient.PushDataLayerForDataLayerType('CustomerLogin', { method: 'cart' }).then(function() {\n        if (SitePreferences.CORDIAL_ENABLED) {\n            if (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n                crdl([\n                    ['contact', auth_data, contact_data],['event', 'login', properties]\n                ]);\n            }\n        }\n        if (callback) callback();\n    });\n}\n\nfunction passwordlessLoginSequence(isCheckoutLogin) {\n    if (!isCheckoutLogin) {\n        $('#otp-toggle-button').hide();\n    }\n    $('.login-dialog-signin-container, .login-dialog-register-message, #toggle-registration').hide();\n    $('.login-dialog-passcode-container').addClass('passcode-form-show');\n    $('.otp-passcode-field-container, .otp-resend-code-container').hide();\n    $('.otp-email-field-container').show();\n    $('.login-dialog-passcode-container input[name*=\"dwfrm_otplogin\"]').val(''); // clear previous form input values\n}\n\n/**\n * Login reporting - increments counters in custom object\n * @param {String} type - Either 'normal' for traditional login type, or 'passwordless' for new login type\n * @param {String} source - Source of login, which can be original, cart, cart-modal, or wishlist-modal\n */\nfunction trackLoginActions(type, source) {\n    if (!type || !source) {\n        return;\n    }\n\n    $.ajax({\n        type: 'POST',\n        url: Urls.loginTracking,\n        contentType: 'application/json',\n        data: JSON.stringify({\n            type: type,\n            source: source\n        }),\n        error: function(jqXHR, textStatus, errorThrown) {\n            console.log('Login-TrackActions: Error in incrementing login action counters. ERROR TEXT: '+textStatus+', ERROR THROWN: '+errorThrown+'.');\n        },\n        success: function(response) {\n            if (response) {}\n        }\n    });\n}\n\n/**\n * @private\n * @function\n * @description init login button event for the loginPage, loginDialog and checkout login\n */\nfunction initLoginButtons() {\n\t$(document).on('click', '#accountLoginButton', function(event) {\n\t\tevent.preventDefault();\n        var dialogHtml = '<p style=\"padding: 10px;\">Oops, something went wrong with login. Please try again later.</p>';\n        var $accountLoginButton = $(this);\n        var $accountLoginForm = $accountLoginButton.closest('form#dwfrm_login');\n        var formRememberMe = $accountLoginForm.find('input[name*=\"dwfrm_login_rememberme\"]').is(':checked');\n        var formUsername = formRememberMe ? '=' + $accountLoginForm.find('input[name*=\"dwfrm_login_username\"]').val() : '';\n        var formUrl = $accountLoginForm.attr('action');\n\n        // Clear previous form errors\n        $accountLoginForm.find('input').removeClass('error');\n        $accountLoginForm.find('.login-dialog-error span').addClass('d-none');\n\n        var isValidForm = validateLoginForm($accountLoginForm, ['email','password']);\n        var isLoginDialog = formUrl.indexOf('loginDialog') >= 0;\n        var formData = $accountLoginForm.serialize();\n\n        if (!isLoginDialog) {\n            $('[data-login-source]').attr('data-login-source', 'original'); // For reporting \n        }\n\t\t\n        // Using AJAX instead of default HTML button submit for login page and dialog\n        if (isValidForm) {        \n            $('body').loading(loadingIndicatorSettings);\n            $.ajax({\n                type: 'POST',\n                url: formUrl,\n                data: formData,\n                success: function(data, textStatus, jqXHR) {\n                    if (typeof data === 'object' && 'result' in data) {\n                        if (data.result == 'error') {\n                            $('body').loading('destroy');\n                            if (isLoginDialog) {\n                                $accountLoginForm.find('.login-dialog-error .invalid-login').removeClass('d-none');\n                            } else {\n                                window.location.href = data.loginDialogContinueUrl + '?retry';\n                            }\n                        } else if (data.result == 'success' || data.result == 'complete') {\n                            $('body').loading('destroy');\n                            // 'validateCustomer' property only returns in the data if this is a dialog. Otherwise, rewards validation happens through the URL using loginDialogContinueUrl. \n                            // If this is a rewards customer, and the cusomter account requires validation...\n                            if ('validateCustomer' in data && data.validateCustomer) {\n                                if (SitePreferences.CORDIAL_ENABLED) {\n                                    loginCordialAccountEvent($accountLoginForm, isLoginDialog);\n                                }\n                                var newAttributes = {\n                                    \"data-modal-type\": \"login\",\n                                    \"data-continue-url\": 'loginDialogContinueUrl' in data ? data.loginDialogContinueUrl : '',\n                                    \"data-first-name\": 'customerFirstName' in data ? data.customerFirstName : '',\n                                    \"data-store-number\": 'storeFromProfile' in data ? data.storeFromProfile : '',\n                                    \"data-cart-quantity\": 'cartQuantity' in data ? data.cartQuantity : ''\n                                }\n                                $('.login-dialog-validate-customer').html(data.validateCustomer);\n                                $('.login-dialog-validate-customer').addClass('validate-customer-show follow-account-dialog-path').attr(newAttributes);\n                                // Do this in two places: \n                                // (1) for login-dialog here because the element is only loaded into page via AJAX, \n                                // (2) init of page load for regular rewards verification pages through normal login flow\n                                initAddRulesForCodeInput();\n                            } else {\n                                // Fire the cordial login event\n                                if (SitePreferences.CORDIAL_ENABLED) {\n                                    loginCordialAccountEvent($accountLoginForm, isLoginDialog);\n                                }\n                                trackLoginActions('password', $('[data-login-source]').attr('data-login-source'));\n\n                                // Handle follow-up actions accordingly\n                                $(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: data, isAccountDialog: isLoginDialog, displayMessage: 'login' });\n                            }\n                        } else {\n                            $('body').loading('destroy');\n                            errorHandling(data, 'Login - Error', dialogHtml);\n                        }\n                    } else {\n                        $('body').loading('destroy');\n                        if (isLoginDialog) {\n                            errorHandling(data, 'Login - Error', dialogHtml);\n                        } else {\n                            window.location.href = location.href.split('?')[0]+'?retry';\n                        }\n                    }\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    $('body').loading('destroy');\n                    if (!isLoginDialog) {\n                        window.location.href = location.href.split('?')[0]+'?retry';\n                    }\n                }\n            });\n        }  \n\t});\n\n    $(document).on('click', '.opc-login-submit-button', function(event) {\n        event.preventDefault();\n        var $opcLoginButton = $(this);\n        var $opcLoginForm = $opcLoginButton.closest('form.opc-login');\n        var notificationSelector = $('.login-notification');\n\n        $('body').loading(loadingIndicatorSettings);\n\n        $('[data-login-source]').attr('data-login-source', 'cart'); // For reporting\n        $opcLoginForm.validate().form();\n        clearNotification(notificationSelector);\n        updateCustomerDetails($opcLoginForm, $(this).attr('name')).then(function (response) {\n            if (typeof response != 'object') {\n                try {\n                    response = JSON.parse(response);\n                } catch(e) {\n                    console.log(e);\n                    response = {};\n                }\n            }\n            if ('viewModel' in response && 'Customer' in response.viewModel && response.viewModel.Customer.authenticated == true) {\n                Customer.authenticated = response.viewModel.Customer.authenticated;\n                opcLoggedInCustomerAddresses = response.viewModel.Addresses;\n                if ('validateCustomer' in response) {\n                    $.ajax({\n                        type: 'GET',\n                        url: Urls.renderDialogTemplate,\n                        error: function(jqXHR, textStatus, errorThrown) {\n                            $('body').loading('destroy');\n                            console.log(errorThrown);\n                        },\n                        success: function(data) {\n                            if (data) {\n                                $('body').loading('destroy');\n                                opcLoginTagging($opcLoginForm);\n                                var opcLoginContinueUrl = $('#cart-items-form').length ? Urls.onePage : Urls.account;\n\n                                dialog.open({\n                                    html: data,\n                                    options: {\n                                        dialogClass: 'login-dialog',\n                                        draggable: false,\n                                        height: 600,\n                                        open: function() {\n                                            $('body').addClass('dialog-open');\n                                            $(this).scrollTop(0);\n                                            if (SitePreferences.CORDIAL_ENABLED) {\n                                                loginCordialAccountEvent($opcLoginForm, false);\n                                            }\n\n                                            $('.ui-dialog.login-dialog').css('height', '430px');\n                                            $('.ui-dialog.login-dialog .login-dialog-forms-container').css('margin', '0 -8px');\n                                            $('.login-dialog-passcode-container, .login-dialog-register-container').hide();\n\n                                            var newAttributes = {\n                                                \"data-modal-type\": \"login\",\n                                                \"data-continue-url\": opcLoginContinueUrl,\n                                                \"data-first-name\": 'customerFirstName' in response ? response.customerFirstName : '',\n                                                \"data-store-number\": 'storeFromProfile' in response ? response.storeFromProfile : '',\n                                                \"data-cart-quantity\": 'cartQuantity' in response ? response.cartQuantity : '',\n                                                \"data-opc-login\": true\n                                            }\n                                            $('.login-dialog-validate-customer').html(response.validateCustomer);\n                                            $('.login-dialog-validate-customer').addClass('validate-customer-show follow-account-dialog-path').attr(newAttributes);\n\n                                            initAddRulesForCodeInput();\n\n                                            var $passwordReset = $(this).find('.login-dialog-forms-container #password-reset-button');\n                                            $passwordReset.attr('data-target', $passwordReset.attr('data-target') + '?loginDialog=true');\n                                        },\n                                        close: function() {\n                                            $('body').removeClass('dialog-open');\n                                        }\n                                    }\n                                });\n                            }\n                        }\n                    });\n                } else {\n                    $('body').loading('destroy');\n                    opcLoginTagging($opcLoginForm);\n                    trackLoginActions('password', $('[data-login-source]').attr('data-login-source'));\n                    location.href = Urls.onePage;\n                }\n            } else {\n                $('body').loading('destroy');\n                $('.opc-login .field-wrapper input').addClass('error');\n                showNotification(Resources.PWD_EMAIL_ERROR, '.login-notification', 'error');\n            }\n        }.bind(this));    \n    });\n\n    $(document).on('click', '#otp-toggle-button', function(e) {\n\t\te.preventDefault();\n        var isAccountDialog = $(this).closest('.login-dialog-forms-container').length;\n        var isCheckoutLogin = $(this).hasClass('opc-passwordless-login');\n        if (isAccountDialog) {\n            passwordlessLoginSequence(false);\n        } else if (isCheckoutLogin) {\n            loginDialog.show(function() {\n                passwordlessLoginSequence(true);\n                $('.login-dialog-forms-container [data-login-source]').attr('data-login-source', 'cart-modal'); \n                $('.login-dialog-forms-container [data-passwordless-login-source]').attr('data-passwordless-login-source', 'cart-modal');\n            });\n        } else {\n            window.location.href = Urls.passwordlessLogin;\n        }\n\t});\n\n    $(document).on('click', '#otpCancelButton', function(e) {\n\t\te.preventDefault();\n        var isAccountDialog = $(this).closest('.login-dialog-forms-container').length;\n        var isCheckout = $('[data-login-source]').attr('data-login-source') != undefined && $('[data-login-source]').attr('data-login-source').indexOf('cart') > -1;\n        if (isAccountDialog) {\n            if (isCheckout) {\n                dialog.close();\n            } else {\n                var $otpHeader = $('form#dwfrm_otplogin .profile-header');\n                var $otpInstructions = $('form#dwfrm_otplogin .otp-instructions');\n                $('.login-dialog-signin-container, .login-dialog-register-message, #otp-toggle-button, #toggle-registration').show();\n                $('.login-dialog-passcode-container').removeClass('passcode-form-show');\n                $otpHeader.html($otpHeader.attr('data-email'));\n                $otpInstructions.html($otpInstructions.attr('data-email'));\n                $('#dwfrm_otplogin_username').show(); // don't clear previous email value for form validation\n                $('#otpContinueButton').show();\n                $('#dwfrm_otplogin_passcode').hide().val(''); // clear previous passcode value for form\n                $('#otpVerifyButton').hide();\n            }\n        } else {\n            window.location.href = Urls.account;\n        }\n\t});\n\n    $(document).on('click', '#otpContinueButton, .otp-resend-code', function(event) {\n        event.preventDefault();\n        var errorMessage = '<p style=\"padding: 10px;\">Sorry, we were unable to send a one-time passcode at this time. Please login using your credentials instead.</p>';\n        var $otpContinueButton = $(this);\n        var $otpLoginForm = $otpContinueButton.closest('form#dwfrm_otplogin');\n        var isResend = $(this).hasClass('otp-resend-code');\n\n        // Clear previous form errors\n        $otpLoginForm.find('input').removeClass('error');\n        $otpLoginForm.find('.login-dialog-error span').addClass('d-none');\n\n        var isValidForm = validateLoginForm($otpLoginForm, ['email']);\n        var emailAddress = $otpLoginForm.find('input[name*=\"_username\"]').val();\n\n        $('.login-dialog-passcode-container, .otp-login-form-container').attr('data-email', emailAddress);\n\n        // Using AJAX instead of default HTML button submit for login page and dialog\n        if (isValidForm) {\n            if (isResend) {\n                $('body').loading(loadingIndicatorSettings); \n            }     \n            $.ajax({\n                type: 'POST',\n                url: Urls.getPasscode,\n                data: {\n                    emailAddress: emailAddress\n                },\n                success: function(data, textStatus, jqXHR) {\n                    if (typeof data === 'string' && data.length == 0) { \n                        if (isResend) {\n                            $('body').loading('destroy'); \n                        } \n                        errorHandling(data, 'Passwordless Login - Error', errorMessage);\n                    } else {\n                        if (isResend) {\n                            $('body').loading('destroy'); \n                        }  \n                        if ((textStatus && textStatus != 'success') || (data && 'status' in data && data.status == 'ERROR')) {\n                            errorHandling(data, 'Passwordless Login - Error', errorMessage);\n                        }\n                        if (data && 'status' in data && (data.status == 'OK' ||  data.status == 'NOT_FOUND')) {\n                            $otpLoginForm.attr('data-usid', data.usid);\n                            var $otpHeader = $otpLoginForm.find('.profile-header');\n                            var $otpInstructions = $otpLoginForm.find('.otp-instructions');\n                            $otpHeader.html($otpHeader.attr('data-verify'));\n                            $otpInstructions.html($otpInstructions.attr('data-verify'));\n                            $otpInstructions.append('<span>'+emailAddress+'</span>');\n                            $('.otp-email-field-container, #otpContinueButton').hide();\n                            $('.otp-passcode-field-container').css('display', 'flex');\n                            $('#dwfrm_otplogin_passcode').show().val('').removeAttr('placeholder').attr('inputmode','numeric'); // clear previous passcode value from form\n                            $('#otpVerifyButton, .otp-resend-code-container').show();\n                        }    \n                    }\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    errorHandling(data, 'Passwordless Login - Error', errorMessage);\n                }\n            });\n        }\n    });\n\n    $(document).on('click', '#otpVerifyButton', function(event) {\n        event.preventDefault();\n        var errorMessage = '<p style=\"padding: 10px;\">Sorry, we were unable to send a passcode at this time. Please try again later.</p>';\n        var $otpVerifyButton = $(this);\n        var $otpLoginForm = $otpVerifyButton.closest('form#dwfrm_otplogin');\n        var formUrl = $otpLoginForm.attr('action');\n\n        // Clear previous form errors\n        $otpLoginForm.find('input').removeClass('error');\n        $otpLoginForm.find('.login-dialog-error span').addClass('d-none');\n\n        var isLoginDialog = formUrl.indexOf('loginDialog') >= 0;\n        var isValidForm = validateLoginForm($otpLoginForm, ['email','passcode']);\n        var formData = $otpLoginForm.serialize();\n        formData += '&usid=' + $otpLoginForm.attr('data-usid');\n        formData += '&' + $otpVerifyButton.attr('name') + '=' + $otpVerifyButton.attr('name');\n\n        // Using AJAX instead of default HTML button submit for login page and dialog\n        if (isValidForm) {   \n            $('body').loading(loadingIndicatorSettings);  \n            $.ajax({\n                type: 'POST',\n                url: formUrl,\n                data: formData,\n                success: function(data, textStatus, jqXHR) {\n                    $('body').loading('destroy');\n                    if (typeof data === 'object' && data.status != 'ERROR') {\n                        // 'validateCustomer' property only returns in the data if this is a dialog. Otherwise, rewards validation happens through the URL using loginDialogContinueUrl. \n                        // If this is a rewards customer, and the cusomter account requires validation...\n                        if ('validateCustomer' in data && data.validateCustomer) {\n                            if (SitePreferences.CORDIAL_ENABLED) {\n                                loginCordialAccountEvent($otpLoginForm, isLoginDialog);\n                            }\n                            var newAttributes = {\n                                \"data-modal-type\": \"login\",\n                                \"data-continue-url\": 'loginDialogContinueUrl' in data ? data.loginDialogContinueUrl : '',\n                                \"data-first-name\": 'customerFirstName' in data ? data.customerFirstName : '',\n                                \"data-store-number\": 'storeFromProfile' in data ? data.storeFromProfile : '',\n                                \"data-cart-quantity\": 'cartQuantity' in data ? data.cartQuantity : ''\n                            }\n                            $('.login-dialog-validate-customer, .otp-login-form-container').html(data.validateCustomer);\n                            $('.login-dialog-validate-customer, .otp-login-form-container').addClass('validate-customer-show follow-account-dialog-path').attr(newAttributes);\n                        } else {\n                            // Fire the cordial login event\n                            if (SitePreferences.CORDIAL_ENABLED) {\n                                loginCordialAccountEvent($otpLoginForm, isLoginDialog);\n                            }\n                            trackLoginActions('passwordless', $('[data-passwordless-login-source]').attr('data-passwordless-login-source'));\n\n                            // Pass this value to PostAjaxAuthenticationActions.Initialize for the isAccountDialog due to scope of BOOT-6100.\n                            // We are not using this ticket to prevent cart refresh for modal. Will need additional ticket with scope to change cart behavior.\n                            var isCartPasswordless = $('[data-passwordless-login-source]').attr('data-passwordless-login-source') == 'cart-modal' ? false : isLoginDialog;\n\n                            // Handle follow-up actions accordingly\n                            $(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: data, isAccountDialog: isCartPasswordless, displayMessage: 'login' });\n                        }    \n                    } else {\n                        var errorsFound;\n\t\t\t\t\t\tif (data.validationErrors) {\n\t\t\t\t\t\t\terrorsFound = JSON.parse(data.validationErrors);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (errorsFound && Object.keys(errorsFound).length > 0) {\n\t\t\t\t\t\t\tfor (var fieldName in errorsFound) {\n\t\t\t\t\t\t\t\t$(errorsFound[fieldName]).removeClass('d-none');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n                            if (data.responseData && data.responseData.ErrorCode == 401) {\n                                $('.invalid-wrong-passcode').removeClass('d-none');\n                            } else {\n\t\t\t\t\t\t\t    errorHandling(data, 'Passwordless Login - Error', errorMessage);\n                            }\n\t\t\t\t\t\t}\n                    }\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    $('body').loading('destroy');\n                    errorHandling(data, 'Passwordless Login - Error', errorMessage);\n                }\n            });\n        }\n    });\n}\n\nfunction callNextController(url, callback) {\n    $.ajax({\n        type: 'GET',\n        url: url,\n        contentType: 'application/json',\n        error: function(jqXHR, textStatus, errorThrown) {\n        },\n        success: function(response) {\n            if (response) {\n                if (callback) callback(response);\n            }\n        }\n    });\t\n}\n\n/**\n * @private\n * @function\n * @description register on-click event for rewards validation > send code button\n * @notes changed the button.on('click') to a document.on('click') for HTML that is dynamically loaded in page with AJAX well after initial page load\n */\nfunction initValidateRewardsAccount() {\t\n\t$(document).on('click', '#validate-account button#send-code', function(event) {\n\t\tevent.preventDefault();\n\n        var $validateAccountForm = $('#validate-account');\n        var isAccountDialog = $('.login-dialog-validate-customer').hasClass('follow-account-dialog-path');\n        var sendType = $validateAccountForm.find('input[name=validate-account]:checked').attr('id').indexOf('none') > -1 ? 'none' : 'other';\n\n\t\tif (sendType == \"none\") {\t\t\t\t\n\t\t\t$.ajax({\n\t\t\t\ttype: 'post',\n\t\t\t\turl: Urls.createRewardsAccount,\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\tfirstName: $('.customer-account .first-name').text(),\n\t\t\t\t\tlastName: $('.customer-account .last-name').text(),\n\t\t\t\t\temailAddress: $('.customer-account .email-address').text(),\n\t\t\t\t\tphoneNumber: $('.customer-account .phone-number').text(),\n\t\t\t\t\tzipCode: $('.customer-account .zip-code').text()\n\t\t\t\t}),\n\t\t\t\tsuccess: function (data) {\n\t\t\t\t\tconsole.log('Rewards account created.');\n\t\t\t\t\tinitVerificationDirection();\n\t\t\t\t}\n\t\t\t});\t\t\t\n\t\t} else {\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.sendValidationCode,\n\t\t\t\tdataType: 'JSON',\n\t\t\t\tmethod: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\t'sendMethod': $validateAccountForm.find('input[name=validate-account]:checked').val(),\n\t\t\t\t\t'sendTo': $validateAccountForm.find('input[name=validate-account]:checked').attr('data-value')\n\t\t\t\t},\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tvar resultStatus = 'status' in data && data.status != 'pending' ? true : 'result' in data && 'status' in data.result && data.result.status != 'pending' ? true : false;\n\t\t\t\t\tif (('error' in data && data.error) || resultStatus) {\n\t\t\t\t\t\t$('.further-info').hide();\n\t\t\t\t\t\t$('.verify-form').hide();\n\t\t\t\t\t\t$('.verify-fail').removeClass('hidden');\n\t\t\t\t\t}\t\n\t\t\t\t\t$('.account-recognized').hide();\n\t\t\t\t\tif (isAccountDialog) {\n\t\t\t\t\t\t$('.verify-account').removeClass('hidden').addClass('validate-customer-show');\t\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$('.verify-account').removeClass('hidden');\t\n\t\t\t\t\t}\t\t\t\n\t\t\t\t\t$('.' + sendType + '-method').removeClass('hidden');\n\t\t\t\t},\n\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t\n    $(document).on('click', '#attach-rewards-button', function(event) {\n        event.preventDefault();\n        var errorMessage = '<p style=\"padding: 10px;\">Sorry, we were unable to finalize your rewards account updates.</p>';\n        var $attachRewardsForm = $('#attach-rewards-form');\n        var $selectedOption = $attachRewardsForm.find('input[name=attach-rewards-options]:checked');\n        var submittedEmail = $('.login-dialog-passcode-container, .otp-login-form-container').attr('data-email');\n\n        if (!$selectedOption) {\n            $('.attach-rewards-form-errors').removeClass('d-none');\n            return;\n        }\n\n        $.ajax({\n            url: Urls.attachRewards,\n            dataType: 'JSON',\n            method: 'POST',\n            data: {\n                'option': $selectedOption.val(),\n                'email': submittedEmail\n            },\n            success : function(data) {\n                if (data && data.result && data.result == 'success') {\n                    console.log('Rewards attachment complete.');\n                    initVerificationDirection();\n                } else {\n                    errorHandling(data, 'Rewards Account - Error', errorMessage);\n                }\n            },\n            error: function(jqXHR, textStatus, errorThrown) {\n                errorHandling(data, 'Rewards Account - Error', errorMessage);\n            }\n        });\n    });\n}\n\n/**\n * @private\n * @function\n * @description register on-click event for rewards validation > verify code button\n */\nfunction initVerifyCodeSent() {   \n    $(document).on('click', '#verify-code button#verify-user', function(event) {\n        event.preventDefault();\n\n        var $verifyCodeForm = $('#verify-code');\n        if (!$verifyCodeForm.valid()) {\n            return false;\n        }\n\n        $.ajax({\n            url: Urls.verifySubmittedCode,\n            dataType: 'JSON',\n            method: 'POST',\n            data: {\n                'code':  $verifyCodeForm.find('input[name=enter-code]', '#verify-code').val(),\n                'sendTo': $('#validate-account').find('input[name=validate-account]:checked').attr('data-value')\n            },\n            success : function(data) {\n                if (('error' in data && data.error) || ('status' in data && data.status != 'approved')) {\n                    $('.further-info').hide();\n                    $('.verify-form').hide();\n                    $('.verify-fail').removeClass('hidden');\t\t\t\t\t\t\t\n                } else {\n                    console.log('Rewards verification complete.');\n                    initVerificationDirection();\n                }\n            },\n            complete: function(data, status, xhr) {\n                if (data.status == 302 && data.responseText) {\n                    location.href = data.responseText;\n                }\n            }\n        });\n    });\n}\n\n/**\n * @private\n * @function\n * @description directs the page load or the page redraw after rewards verification screen\n */\nfunction initVerificationDirection() {\n    var $validateDialog = $('.login-dialog-validate-customer');\n    var isAccountDialog = $('.login-dialog-validate-customer').hasClass('follow-account-dialog-path');\n    var dataModalType, dataNextControllerUrl, dataContinueUrl, dataFirstName, dataStore, dataCartQuantity, isOpcLogin;\n\n    if ($validateDialog.length) {\n        dataModalType = $validateDialog.attr('data-modal-type');\n        dataNextControllerUrl = $validateDialog.attr('data-next-controller-url');\n        dataContinueUrl = $validateDialog.attr('data-continue-url');\n        dataFirstName = $validateDialog.attr('data-first-name');\n        dataStore = $validateDialog.attr('data-store-number');\n        dataCartQuantity = $validateDialog.attr('data-cart-quantity');\n        isOpcLogin = $validateDialog.attr('data-opc-login') == 'true';\n\n        if (isOpcLogin) {\n            dialog.close();\n            location.href = Urls.onePage;\n        }\n        if (isAccountDialog) {\n            if (dataNextControllerUrl) {\n                callNextController(dataNextControllerUrl, function(response) {\n                    if (response && 'result' in response && (response.result == 'success' || response.result == 'complete')) {\n                        response.customerFirstName = dataFirstName;\n                        response.storeFromProfile = dataStore;\n                        response.cartQuantity = dataCartQuantity;\n                        // Handle follow-up actions accordingly\n                        $(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: response, isAccountDialog: isAccountDialog, displayMessage: dataModalType });\n                    }\n                });\n            } else {\n                if (dataContinueUrl) {\n                    location.href = dataContinueUrl;\n                } else {\n                    location.href = Urls.account;\n                }\n            }\n        }\n    } else {\n        location.href = Urls.account;\n    }\n}\n\n/**\n * @private\n * @function\n * @description add rules to code input field\n */\nfunction initAddRulesForCodeInput() {\n    $('form#verify-code').validate();\n    $('#verify-code #enter-code').rules('add', {\n        required: true,\n        digits: true,\n        minlength: 6,\n        messages: {\n            required: Resources.VALIDATE_CODE,\n            minlength: Resources.VALIDATE_CODE\n        },\n        normalizer: function(value) {\n            return $.trim(value);\n        }\n    });\n}\n\n/**\n * @private\n * @function\n * @description register on-click event for rewards validation > verify code > resend code link\n */\nfunction initResendValidationCode() {\n    $(document).on('click', '.verify-account a.resend-code', function(event) {\n        event.preventDefault();\t\t\n        if ($('.login-dialog-validate-customer').hasClass('follow-account-dialog-path')) {\n            $('.verify-account, .further-info span').addClass('hidden');\t\n            $('.account-recognized').css('left','-9999px').removeClass('hidden').show().addClass('validate-customer-show');\t\t\t\n        } else {\n            location.reload();\n        }\n    });\n}\n\n/**\n * @private\n * @function\n * @description register on-click events for reset-password flow\n */\nfunction initResetPasswordEvents() {\t\n    // Show reset password form\n\t$(document).on('click', '#password-reset-button', function(event) {\n        event.preventDefault();\n        var $resetPasswordButton = $(this);\n        var resetDialogUrl = $resetPasswordButton.attr('data-target');\n        var isLoginDialog = resetDialogUrl.indexOf('loginDialog') >= 0;\n\n        if (isLoginDialog) {\n            $('body').loading(loadingIndicatorSettings);\n            var dialogHtml = '<p style=\"padding: 10px;\">Oops, something went wrong with Password Reset. Please try again later.</p>';\n\n            $.ajax({\n                type: 'GET',\n                url: resetDialogUrl,\n                success: function(data, textStatus, jqXHR) {\n                    if (typeof data === 'object' && 'result' in data) {\n                        if (data.result == 'complete') {\n                            $('body').loading('destroy');\n                            // If we received HTML in the data for displaying the reset password form, then display it...\n                            if ('resetPasswordForm' in data && data.resetPasswordForm) {\n                                $('.login-dialog-reset-password').html(data.resetPasswordForm);\n                                $('.login-dialog-reset-password').addClass('reset-password-show');\n                                $('.login-dialog-reset-password').find('#PasswordResetForm').attr('action', $('.login-dialog-reset-password').find('#PasswordResetForm').attr('action') + '?loginDialog=true');\n\t\t\t\t\t\t\t\trenderRecaptchaForPasswordReset();\n                            } else {\n                                $('body').loading('destroy');\n                                errorHandling(data, 'Reset Password - Error', dialogHtml);\n                            }\n                        } else {\n                            $('body').loading('destroy');\n                            errorHandling(data, 'Reset Password - Error', dialogHtml);\n                        }\n                    } else {\n                        $('body').loading('destroy');\n                        if (isLoginDialog) {\n                            errorHandling(data, 'Reset Password - Error', dialogHtml);\n                        } else {\n                            window.location.href = location.href;\n                        }\n                    }\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    $('body').loading('destroy');\n                    if (!isLoginDialog) {\n                        window.location.href = location.href;\n                    }\n                }\n            });\n        } else if (SitePreferences.RESET_POPUP_ENABLED) {\n\t\t\tdialog.open({\n\t            url: resetDialogUrl,\n\t            options: {\n\t            \tdialogClass: 'resetpwdpopup',\n\t            \twidth: 385,\n\t                open: function () {\n\t\t\t\t\t\trenderRecaptchaForPasswordReset();\n\t                    $(\".reset-password-heading-close-btn, .ui-widget-overlay\").on('click',function(){\n\t                        $(\"button.ui-dialog-titlebar-close\").click();\n\t                    });\n\t                }\n\t            }\n\t\t\t});\n        } else {\n            window.location.href = resetDialogUrl;\n        }\n\t});\n\t\n    // Submit reset password form\n    $(document).on('click.ResetPassword', '#request-password-send-btn, [name$=\"_requestpassword_send\"]', function(event) {\n    \tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForPasswordReset) {\n\t\t\tresetPassword(event, $(this));\n\t\t}\n\t});\n    \n    $(document).on('Account.ResetPassword', function (event, data) {\n\t\tresetPassword(event, null, true);\n\t});\n}\n\nfunction resetPassword(event, $resetPasswordSendButton, isRecaptchaEvent) {\n\tif (!$resetPasswordSendButton) {\n\t\t$resetPasswordSendButton = $('#request-password-send-btn');\n\t}\n\n\tvar $resetPasswordSendForm = $resetPasswordSendButton.closest('form#PasswordResetForm');\n\tvar isLoginDialog = $resetPasswordSendForm.attr('action').indexOf('loginDialog') >= 0;\n\n\t// Try to prevent the form submission as quickly as possible before doing all of the other logic\n\tif (isLoginDialog || (SitePreferences.RESET_POPUP_ENABLED && dialog.isActive())) {\n\t\tevent.preventDefault();\n\t}\n\n\tvalidator.init();\n\tvar isValidForm = $resetPasswordSendForm.valid();\n\n\tif (isValidForm) {   \n\t\tif (isLoginDialog) {\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t\tvar dialogHtml = '<p style=\"padding: 10px;\">Oops, something went wrong with Password Reset. Please try again later.</p>';\n\t\t\tvar formData = $resetPasswordSendForm.serialize();\n\t\t\tformData += '&' + $resetPasswordSendButton.attr('name') + '=' + $resetPasswordSendButton.attr('name');  \n\n\t\t\t$.ajax({\n\t\t\t\ttype: 'POST',\n\t\t\t\turl: $resetPasswordSendForm.attr('action'),\n\t\t\t\tdata: formData,\n\t\t\t\tsuccess: function(data, textStatus, jqXHR) {\n\t\t\t\t\tif (typeof data === 'object' && 'result' in data) {\n\t\t\t\t\t\tif (data.result == 'complete') {\n\t\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\t\t// If reset password email was sent, show confirmation within the dialog\n\t\t\t\t\t\t\tif ('resetPasswordConfirmation' in data && data.resetPasswordConfirmation) {\n\t\t\t\t\t\t\t\t$('.login-dialog-reset-password').html(data.resetPasswordConfirmation);\n\t\t\t\t\t\t\t\t$('.login-dialog-reset-password').addClass('reset-password-show');\n\t\t\t\t\t\t\t\tpasswordResetNoAccountCordialEvent('.login-dialog-reset-password');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\t\t\terrorHandling(data, 'Reset Password - Error', dialogHtml);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\t\terrorHandling(data, 'Reset Password - Error', dialogHtml);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\tif (isLoginDialog) {\n\t\t\t\t\t\t\terrorHandling(data, 'Reset Password - Error', dialogHtml);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twindow.location.href = location.href;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\tif (!isLoginDialog) {\n\t\t\t\t\t\twindow.location.href = location.href;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else if (SitePreferences.RESET_POPUP_ENABLED && dialog.isActive()) {\n\t\t\tdialog.submit($resetPasswordSendButton.attr('name'), function() {\n\t\t\t\tpasswordResetNoAccountCordialEvent('.resetpwdpopup');\n\t\t\t});\n\t\t} else if (isRecaptchaEvent) {\n\t\t\t$resetPasswordSendForm.append('<input type=\"hidden\" name=\"' + $resetPasswordSendButton.attr('name') + '\" value=\"' + $resetPasswordSendButton.val() + '\"/>')\n\t\t\t$resetPasswordSendForm.submit();\n\t\t}\n\t}\n}\n\nmodule.exports = {\n    init: function (optionsParameter) {\n\t\toptions = optionsParameter;\n\n        initLoginEvents();\n\t\tif (options && options.Recaptcha && (options.Recaptcha.EnabledForAccountLogin || options.Recaptcha.EnabledForPasswordReset)) {\n\t\t\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\t\t\tif (!loaded.Recaptcha) {\n\t\t\t\t\tloaded.Recaptcha = true;\n\t\t\t\t\trenderRecaptchaForLogin();\n\t\t\t\t\trenderRecaptchaForPasswordReset();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\trecaptcha.initialize();\n\t\t\tinitializeRecaptchaForLogin();\n\t\t\trenderRecaptchaForPasswordReset();\n\t\t}\n\t\tinitLoginButtons();\n        initValidateRewardsAccount();\n        initVerifyCodeSent();\n        initResendValidationCode();\n        initAddRulesForCodeInput();\n        initResetPasswordEvents();\n    }\n};","'use strict';\n\nvar dialog = require('./dialog');\n\n/* -------------------------\n * LOGIN MODAL\n * -------------------------\n */\n\nvar loginDialog = {\n    /**\n     * @function\n     * @description Shows the account-login form in a dialog\n     */\n    show: function(callback, controller, action, productID, params, completeUrl) {\n        $.ajax({\n            type: 'POST',\n            url: Urls.loginDialog,\n            data: JSON.stringify({\n                controller: controller,\n                action: action,\n                passedQueryString: params\n            }),\n            contentType: 'application/json',\n            error: function(jqXHR, textStatus, errorThrown) {\n                console.log(errorThrown);\n            },\n            success: function(response) {\n\t\t\t\tif (response) {\n\n                    dialog.open({\n                        html: response,\n                        options: {\n                            dialogClass: 'login-dialog',\n                            draggable: false,\n                            open: function() {\n                                $('body').addClass('dialog-open');\n                                $(this).scrollTop(0);\n                                $(this).find('.login-dialog-forms-container').attr('data-controller', controller).attr('data-action', action).attr('data-product', productID);\n                                $(this).find('.login-dialog-forms-container form').each(function(i, form) {\n                                    var actionUrl = $(form).attr('action') + '?loginDialog=true';\n                                    $(form).attr('action', actionUrl);\n                                });\n                                $(this).find('.login-dialog-validate-customer').attr('data-next-controller-url', completeUrl);\n                                var $passwordReset = $(this).find('.login-dialog-forms-container #password-reset-button');\n                                $passwordReset.attr('data-target', $passwordReset.attr('data-target') + '?loginDialog=true');\n                                if (callback) {\n                                    callback();\n                                }\n                            },\n                            close: function() {\n                                $('body').removeClass('dialog-open');\n                            }\n                        }\n                    });\n                }\n\t\t\t}\n\t\t});\n    },\n    /**\n     * @function\n     * @description Closes the account-login dialog\n     */\n    close: function() {\n        dialog.close();\n    }\n}\n\nmodule.exports = loginDialog;","'use strict';\n\nvar util = require('./util'),\n    bonusProductsView = require('./bonus-products-view');\n\nvar timer = {\n    id: null,\n    clear: function () {\n        if (this.id) {\n            window.clearTimeout(this.id);\n            delete this.id;\n        }\n    },\n    start: function (duration, callback) {\n        this.id = setTimeout(callback, duration);\n    }\n};\n\nvar minicart = {\n    init: function () {\n        this.$el = $('#mini-cart');\n        this.$content = this.$el.find('.mini-cart-content');\n\n        $('.mini-cart-product').eq(0).find('.mini-cart-toggle').addClass('fa-caret-down');\n        $('.mini-cart-product').not(':first').addClass('collapsed')\n            .find('.mini-cart-toggle').addClass('fa-caret-right');\n\n        $('.mini-cart-toggle').on('click', function () {\n            $(this).toggleClass('fa-caret-down fa-caret-right');\n            $(this).closest('.mini-cart-product').toggleClass('collapsed');\n        });\n\n        // events\n        this.$el.find('.mini-cart-total').on('mouseenter', function () {\n            if (this.$content.not(':visible')) {\n                this.slide();\n            }\n        }.bind(this));\n\n        this.$content.on('mouseenter', function () {\n            timer.clear();\n        }).on('mouseleave', function () {\n            timer.clear();\n            timer.start(30, this.close.bind(this));\n        }.bind(this));\n        \n        $(document).on('minicart:update', function(){\n        \t//implement minicart update here\n        });\n    },\n    /**\n     * @function\n     * @description Shows the given content in the mini cart\n     * @param {String} A HTML string with the content which will be shown\n     */\n    show: function (html) {\n        this.$el.html(html);\n        util.scrollBrowser(0);\n        this.init();\n        this.slide();\n        bonusProductsView.loadBonusOption();\n    },\n    /**\n     * @function\n     * @description Slides down and show the contents of the mini cart\n     */\n    slide: function () {\n        timer.clear();\n        // show the item\n        this.$content.slideDown('slow');\n        // after a time out automatically close it\n        timer.start(6000, this.close.bind(this));\n    },\n    /**\n     * @function\n     * @description Closes the mini cart with given delay\n     * @param {Number} delay The delay in milliseconds\n     */\n    close: function (delay) {\n        timer.clear();\n        this.$content.slideUp(delay);\n    }\n};\n\nmodule.exports = minicart;\n","'use strict';\n\nvar util = require('./util');\n\nvar page = {\n    title: '',\n    type: '',\n    params: util.getQueryStringParams(window.location.search.substr(1)),\n    redirect: function (newURL) {\n        setTimeout(function () {\n            window.location.href = newURL;\n        }, 0);\n    },\n    refresh: function () {\n        setTimeout(function () {\n            window.location.assign(window.location.href);\n        }, 500);\n    }\n};\n\nmodule.exports = page;\n","'use strict';\n\nvar util = require('../../util');\n\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\n\nvar $authenticationContainer = $('.authentication-form-container');\nvar $authenticationForm = $authenticationContainer.closest('form');\nvar $authenticationEmailAddress = $authenticationForm.find('input[name=\"AuthenticationEmailAddress\"]');\nvar authenticationValidator;\n\nexports.init = function(options) {\n\t$authenticationContainer.on('click', 'input[type=\"submit\"]', function (event) {\n    \tevent.preventDefault();\n    \t\n\t    authenticationValidator = $authenticationForm.validate();\n\t    $authenticationEmailAddress.rules('add', ValidationRules.Email);\n\t    authenticationValidator.form();\n\t    \n\t    if (authenticationValidator.valid()) {\n\t    \t$('<input />').attr('type', 'hidden').attr('name', 'isMobile').attr('value', $('html.size-mobile').length > 0).appendTo($authenticationForm);\n\t    \t$authenticationForm.submit();\n\t    }\t\n    });\n};","'use strict';\n\nvar AddressAutocompleteDialog;\nvar AddressVerificationDialog;\nvar AddressVerificationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/js/AddressVerification/AddressVerificationHelper');\nvar\tdialog = require('../dialog');\nvar\tfindMoreStores = require('../findMoreStores');\nvar\torderStatusForm = require('../components/OrderStatusForm');\nvar\tgiftcert = require('../giftcert');\nvar\tpage = require('../page');\nvar recaptcha = require('../components/Recaptcha');\nvar\ttooltip = require('../tooltip');\nvar\tutil = require('../util');\nvar\tvalidator = require('../validator');\n\nvar PaymentMethodConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar dataBuffer = {};\nvar options = {};\nvar loaded = {};\n\n/**\n * @function\n * @description Initializes the events on the address form (apply, cancel, delete)\n * @param {Element} form The form which will be initialized\n */\nfunction initializeAddressForm() {\n    var $addressEditForm = $('#edit-address-form');\n\t$addressEditForm.on('click', '.submit-shipping', function (e) {\n        e.preventDefault();\n\n\t\tvar addressType = $addressEditForm.attr('address-type') ? $addressEditForm.attr('address-type') : 'saved';\n\t\tvar addressDeliverable = function () {\n\t\t\t$addressEditForm.submit();\n\t\t}\n\t\tvar addressNotDeliverable = function (addressVerifyData) {\n\t\t\tAddressVerificationDialog.initialize(options, addressType, addressVerifyData);\t\t\t\n\t\t}\n\t\tvar country = $addressEditForm.find('[id*=\"_country\"]').val();\n\t\tif (options && options.Lob && options.Lob.AddressVerification.Enabled && country.toUpperCase() == 'US' && $addressEditForm.find('.submit-shipping').attr('verified') != 'true') {\n\t\t\tAddressVerificationHelper.VerifyAddress($addressEditForm, options).then(addressDeliverable, addressNotDeliverable);\n\t\t} else {\n\t\t\taddressDeliverable();\n\t\t}\n    });\n\n\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\t$(document).on('keyup.AddressAutocomplete', '#edit-address-form input[type=\"text\"]', function (event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar formValidator = $addressEditForm.validate();\n\n\t\t\tif (event.keyCode == 8 || event.keyCode == 46) {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t} else if (!formValidator.checkForm() && ($this.attr('id').indexOf('_address1') >= 0 || $this.attr('id').indexOf('_address2') >= 0 || $this.attr('id').indexOf('_city') >= 0 || $this.attr('id').indexOf('_postal') >= 0)) {\n\t\t\t\tvar addressAutocompleteHandler = function (addressAutocompleteData) {\n\t\t\t\t\tAddressAutocompleteDialog.initialize(options, addressAutocompleteData);\n\t\t\t\t}\n\t\t\t\n\t\t\t\tAddressVerificationHelper.AutocompleteAddress($addressEditForm, $this, options).then(addressAutocompleteHandler);\n\t\t\t} else {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t}\n\t\t});\n\t\t\n\t\t$(document).on('SetAddressFromAddressAutocomplete', function (event, data) {\n\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog(data.$form, data.Address);\n\t\t});\n\t}\n\n\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\t$(document).on('SetAddressFromAddressVerification', function (event, addressData) {\n\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog($addressEditForm, addressData);\n\t\t\t$addressEditForm.submit();\n\t\t});\n\t}\n\n    validator.init();\n}\n/**\n * @private\n * @function\n * @description Toggles the list of Orders\n */\nfunction toggleFullOrder () {\n    $('.order-items')\n        .find('li.hidden:first')\n        .prev('li')\n        .append('<a class=\"toggle\">View All</a>')\n        .children('.toggle')\n        .click(function () {\n            $(this).parent().siblings('li.hidden').show();\n            $(this).remove();\n        });\n}\n/**\n * @private\n * @function\n * @description Binds the events on the address form (edit, create, delete)\n */\nfunction initAddressEvents() {\n    $(document).ready(function(){\n    \tif ( $('.address-field-container form select').length > 0 ) {\n        \t$('.address-field-container form select').each(function(){\n        \t\t$(this).selectmenu({});\n        \t});\n        }\n    \t\n    \t$(\"#dwfrm_profile_customer_berewarded\").on(\"click\",function(){\n        \tif ( $(this).is(':checked') ) {\n        \t\t$('.rewardsNumberContainer').slideDown();\n        \t} else {\n        \t\t$('.rewardsNumberContainer').slideUp();\n        \t}\n    \t});\n\n\t\tif ($('#edit-address-form').length > 0) {\n\t\t\tinitializeAddressForm();\n\t\t}\n    });\n    \n    $(window).on('load', function() {\n    \t$('#primary #edit-address-form input[name=\"dwfrm_profile_address_remove\"]').off('click');\n    \t$('#primary #edit-address-form input[name=\"dwfrm_profile_address_remove\"]').on('click', function(e){\n    \t\te.preventDefault();\n    \t\tvar $form = $(this).parents('form');\n            if (window.confirm(String.format(Resources.CONFIRM_DELETE, Resources.TITLE_ADDRESS))) {\n                var url = util.appendParamsToUrl(Urls.deleteAddress, {\n                    AddressID: $form.find('#addressid').val(),\n                    format: 'ajax'\n                });\n                $.ajax({\n                    url: url,\n                    method: 'POST',\n                    dataType: 'json'\n                }).done(function (data) {\n                    if (data.status.toLowerCase() === 'ok') {\n                        dialog.close();\n                        var qParams = util.getQueryStringParams(window.location.search.substr(1));\n                        if(qParams.cid !== null && qParams.cid == 'billing'){\n                        \tlocation.href = Urls.paymentsList;\n                        } else {\n                        \tlocation.href = Urls.addressesList;\n                        }                      \n                    } else if (data.message.length > 0) {\n                        window.alert(data.message);\n                        return false;\n                    } else {\n                        dialog.close();\n                        location.href = Urls.addressesList;\n                    }\n                });\n            }\n    \t});\n    });\n}\n/**\n * @private\n * @function\n * @description Binds the events of the payment methods list (delete card)\n */\nfunction initPaymentEvents() {\n\tvar $creditCardTypeSelect = $('select[id*=\"creditcard_type\"]');\n\t\n\t// Remove dialog payment add/edit implementation to use page redirect instead\n    /*$('.add-card').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href')\n        });\n    });*/\n\n\t$creditCardTypeSelect.off('change.CreditCardTypeDetection').on('change.CreditCardTypeDetection', function (e) {\n\t\tvar $this = $(this);\n\t\tvar paymentInstrumentType = $this.val();\n\t\tvar $allianceDataFieldDelta = $('input[name*=\"_owner\"], select[name*=\"_month\"], select[name*=\"_year\"], label.expiration-date');\n\t\tvar $allianceDataDisplayDelta = $('label.expiration-date');\n\t\t\n\t    switch (paymentInstrumentType) {\n\t\t\tcase PaymentMethodConstants.AllianceData:\n\t\t\t\t$allianceDataFieldDelta.removeClass('required').closest('.formfield').hide();\n\t\t\t\t$allianceDataDisplayDelta.hide();\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t$allianceDataFieldDelta.addClass('required').closest('.formfield').show();\n\t\t\t\t$allianceDataDisplayDelta.show();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t\n\t$('.cc-number-container input[type=\"text\"]').off('keyup.CreditCardTypeDetection').on('keyup.CreditCardTypeDetection', function (e) {\n\t\tvar selectedCreditCardType = util.getCreditCardType($(this).val());\n\t\t\n\t\tif (selectedCreditCardType) {\n\t\t\t$creditCardTypeSelect.val(selectedCreditCardType.PaymentCardDisplayKey);\n\t\t} else {\n\t\t\t$creditCardTypeSelect.val('');\n\t\t}\n\t\t\n\t\t$creditCardTypeSelect.trigger('change.CreditCardTypeDetection');\n\t});\n    \n    $creditCardTypeSelect.trigger('change.CreditCardTypeDetection');\n\t\n\tvar paymentList = $('.payment-list');\n    if (paymentList.length === 0) { return; }\n\t\n    $('form[name=\"payment-remove\"] button[type=\"submit\"]').on('click', function (e) {\n        e.preventDefault();\n        \n        // override form submission in order to prevent refresh issues\n        var $button = $(e.target);\n        \n        // confirm delete\n        if ($button.hasClass('delete')) {\n        \tif (!window.confirm(String.format(Resources.CONFIRM_DELETE, Resources.TITLE_CREDITCARD))) {\n        \t\treturn false;\n        \t}\n        }\n        \n        var $form = $(this).closest('form'); \n        \n        $('<input/>').attr({\n            type: 'hidden',\n            name: $button.attr('name'),\n            value: $button.attr('value') || 'delete card'\n        }).appendTo($form);\n        var data = $form.serialize();\n        $.ajax({\n            type: 'POST',\n            url: $form.attr('action'),\n            data: data\n        })\n        .done(function () {\n            page.redirect(Urls.paymentsList);\n        });\n    });\n}\n/**\n * @private\n * @function\n * @description init events for the loginPage\n */\nfunction initLoginPage() {\n    //o-auth binding for which icon is clicked\n    $('.oAuthIcon').bind('click', function () {\n        $('#OAuthProvider').val(this.id);\n    });\n    $('.btn-lookup-order').on('click', function (e) {\n        e.preventDefault();\n        $('div.check-order-content').slideDown();\n        $(this).slideUp();\n    });\n    $('#password-reset-rewards').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href'),\n            target : $(\".password-reset-dialog-container\"),\n            options: {\n            \tdialogClass: 'select-rewards-number-popup',\n            \twidth: 385,\n                open: function () {\n                    validator.init();\n                    var $requestPasswordForm = $('[name$=\"_requestpassword\"]'),\n                        $submit = $requestPasswordForm.find('[name$=\"_requestpassword_send\"]'),\n                    \t$resetPasswordForm = $('[name$=\"_resetpassword\"]');\n                    $($submit).on('click', function (e) {\n                        if (!$requestPasswordForm.valid()) {\n                            return;\n                        }\n                    });\n                    if ( $resetPasswordForm.length > 0 ) {\n                    \t$resetPasswordForm.find(\"button[type=submit]\").on('click', function (e) {\n                    \t\te.preventDefault();\n                    \t\tvar nameAttr = $(this).attr('name');\n                    \t\tdialog.submit(nameAttr);\n                    \t});\n                    }\n                    $(\".reset-password-heading-close-btn\").on('click',function(){\n                        $(\"button.ui-dialog-titlebar-close\").click();\n                    });\n                    execBarCodeGeneration();\n                }\n            }\n        });\n    });\n    if ( $('#password-reset-rewards').length > 0 ) {\n    \tvar ct = 0;\n    \twhile(ct < 2) {\n    \t\tct++;\n    \t\t$('#password-reset-rewards').click();\n    \t}\n    }\n}\n\n/**\n * @private\n * @function\n * @description Binds the events of the order, address and payment pages\n */\nfunction initializeEvents() {\n    toggleFullOrder();\n    initAddressEvents();\n    initPaymentEvents();\n    initLoginPage();\n\tinitCreateAccountEventHandlers();\n    if (util.isMobile()) {\n    \tutil.limitInputToLength('#CreditCardForm input[name*=\"_number\"]', 16);\n    }\n\n\tvar blurFields = \"#dwfrm_profile_customer_email, #dwfrm_profile_customer_emailconfirm, input[id*=dwfrm_profile_login_password_], input[id*=dwfrm_profile_login_passwordconfirm_]\";\n    $(blurFields).blur(function(){\n        if ( $(this).val() == '' ) {\n            if ( $(this).parents('.form-row').find( '.form-caption.error-message' ).length ) {\n                $(this).parents('.form-row').find( '.form-caption.error-message' ).html('');\n            }\n        }\n    });\n}\n\nfunction execBarCodeGeneration() {\n\tif ($('.rewardsregistrationconfirmation').length > 0) {\n\t\tvar barcodeNumber = \"\"+$('.rewardsregistrationconfirmation').find(\"[data-rewardsnumber]\").data('rewardsnumber');\n\t\tvar barcodeType = 'code128';\n\t\t\n\t\t$(\"#barcodeTarget\").barcode(barcodeNumber, barcodeType, {\n\t\t\tbarHeight:'75',\n\t\t\tbarWidth:'2',\n\t\t\tfontSize:'14',\n\t\t\tfontWeight:'bold',\n\t\t\toutput:'bmp'\n\t\t});\n\t}\n}\n\nfunction initRewardsPage() {\n\t$(window).on('load', function() {\n\t\texecBarCodeGeneration();\n\t});\n}\n\n$(window).on(\"message\", function(e) {\n    var data = e.originalEvent.data;\n    if(data == \"error\"){\n    \t$(\".menu-utility-user\").addClass(\"loginError\");\n    }\n});\n\nfunction renderOptions(optionParent, optionsStoreId) {\n\tvar options = '';\n\tvar statesList = JSON.parse($(optionsStoreId + ' option:selected').data('options').replace(/\\'/g, '\\\"'));\n\t\n\tstatesList.forEach(function(state){\n\t\toptions += '<option class=\"select-option\" label=\"'+state.label+'\" value=\"'+state.code+'\">'+state.label+'</option>';\n\t});\n\t$(optionParent).empty().append(options);\n\t\n\tif (statesList.length <= 1) {\n\t\t$(optionParent).parent().parent().parent().hide();\n\t\t$(optionParent + '_sbm').val($(optionParent).val()).attr('disabled', false);\n\t} else {\n\t\t$(optionParent).parent().parent().parent().show();\n\t\t$(optionParent + '_sbm').attr('disabled', true);\n\t}\n}\n\nfunction initRewardRegisterForm() {\n\t$(document).ready(function() {\n\t\tvar $rewardRegisterForm = $('#dwfrm_rewardsregistration');\n\t\tif ($rewardRegisterForm.length > 0) {\n\t\t\t$rewardRegisterForm.find('#dwfrm_rewardsregistration_rewardscustomer_phone').rules('add', {\n\t\t\t\tphone: true\n\t\t\t});\n\t\t\t$rewardRegisterForm.find('#dwfrm_rewardsregistration_rewardscustomeraddress_zipcode').rules('add', {\n\t\t\t\tpostal: true\n\t\t\t});\n\t\t\t$rewardRegisterForm.find('#dwfrm_rewardsregistration_rewardscustomer_email').rules('add', {\n\t\t\t\trequireEmailExtension: true\n\t\t\t});\n\t\t\t$rewardRegisterForm.find('#dwfrm_rewardsregistration_rewardscustomer_emailconfirm').rules('add', {\n\t\t\t\trequireEmailExtension: true,\n\t\t\t\tequalTo: '#dwfrm_rewardsregistration_rewardscustomer_email'\n\t\t\t});\n\n\t\t\t$rewardRegisterForm.on('keyup', '#dwfrm_rewardsregistration_rewardscustomer_email', function(event) {\n\t\t\t\tvar serverErrorMessage = $(event.target).closest('.form-row').find('.error-message');\n\t\t\t\tif (serverErrorMessage.length > 0) {\n\t\t\t\t\tserverErrorMessage.remove();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n}\n\nfunction initRewardsAttached() {\n\t$(window).on('load', function() {\n\t\tif ($('#rewardsCheckBalance #fieldRewardsNumber').val() != '') {\n\t\t\t$('#rewardsCheckBalance input[type=\"submit\"]').trigger('click');\n\t\t}\n\t});\n}\n\nfunction passBreadSetup(rewardsNumber) {\n\tBreadPayments.setup({\n\t\tloyaltyID: rewardsNumber,\n\t\tstoreNumber: util.isMobile() ? SitePreferences.PLCC_STORE_NUMBER_MOBILE : SitePreferences.PLCC_STORE_NUMBER_WEB,\n\t\texistingCardHolder: false,\n\t\tenv: SitePreferences.PLCC_ENVIRONMENT,\n\t});\n}\n\nfunction initDisplayRewardsData() {\n\t$.ajax({\n\t\turl: Urls.getRewardInfoForRegistered,\n\t\tdataType: 'JSON',\n\t\tmethod: 'POST',\n\t\tdata : {\n\t\t\t'csrf_token':  $('.account-overview input[name=\"csrf_token\"]').val(),\n\t\t\t'rewardsNumber': $('.attached-rewards-account .rewards-number').text(),\t\t\t\n\t\t\t'email': $('.attached-rewards-account.email-address').text(),\n\t\t\t'zipcode': $('.attached-rewards-account.zip-code').text(),\n\t\t\t'phone': $('.attached-rewards-account.phone-number').text()\n\t\t},\n\t\tsuccess : function(data) {\n\t\t\tif ('error' in data && data['error']) {\n\t\t\t\t$('.myaccount-contact-custserv').removeClass('hidden');\t\t\t\t\n\t\t\t} else {\t\t\t\n\t\t\t\tif (data.securityRisk) {\t\t\t\t\t\n\t\t\t\t\t$('.myaccount-contact-custserv').removeClass('hidden');\n\t\t\t\t} else {\n\t\t\t\t\t$('#active-rewards').removeClass('hidden');\n\t\t\t\t\t$('.attached-rewards-account.available-rewards').html(\"$\" + parseFloat(data.creditAmount).toFixed(0));\n\t\t\t\t\t$('.attached-rewards-account.current-points').html(data.pointBalance);\n\t\t\t\t}\t\t\n\t\t\t}\n\t\t\tif ($('#active-rewards').length >= 1) {\n\t\t\t\tpassBreadSetup(data.rewardsNumber);\n\t\t\t\tBreadPayments.registerPlacements([dashboardPlacement]);\n\t\t\t}\n\t\t},\n\t\tcomplete: function(data, status, xhr) {\n\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\tlocation.href = data.responseText;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initRewardCheckForm() {\n\t$(document).ready(function() {\n\t\t$('#rewardsSelect1').selectmenu();\n\t\t$('#rewardsSelect2').selectmenu();\n\t\t$('body').on('click', '#rewardsSelect1-menu .ui-menu-item-wrapper', function(){\n\t\t\tvar select1text = $(this).text();\n\t\t\t\n\t\t\tif (select1text == \"B Rewarded\" || select1text == \"Rewards Number\" ) {\n\t\t\t\t$('#rewardsCheckBalance .brewarded-number').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .rewards-number').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .email-address').addClass('hidden');\n\t\t\t\t$('#rewardsSelect1-button').addClass('hidden');\n\t\t\t}\n\t\t\t\n\t\t\tif (select1text == \"Email Address\") {\n\t\t\t\t$('#rewardsCheckBalance .email-address').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .brewarded-number').addClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .rewards-number').addClass('hidden');\n\t\t\t\t$('#rewardsSelect1-button').addClass('hidden');\n\t\t\t}\t\n\t\t});\n\t\t\n\t\t$('body').on('click', '#rewardsSelect2-menu .ui-menu-item-wrapper', function(){\n\t\t\tvar select2text = $(this).text();\n\t\t\t\n\t\t\tif (select2text == \"Zip Code\") {\n\t\t\t\t$('#rewardsCheckBalance .zip-code').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .phone-number').addClass('hidden');\n\t\t\t\t$('#rewardsSelect2-button').addClass('hidden');\n\t\t\t}\n\t\t\t\n\t\t\tif (select2text == \"Phone Number\") {\n\t\t\t\t$('#rewardsCheckBalance .phone-number').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .zip-code').addClass('hidden');\n\t\t\t\t$('#rewardsSelect2-button').addClass('hidden');\n\t\t\t}\t\n\t\t});\n\t\t\n\t\tvar $rewardCheckForm = $('#rewardsCheckBalance');\n\t\tif ($rewardCheckForm.length > 0) {\n\t\t\t$rewardCheckForm.find('#fieldRewardsNumber').rules('add', {\n\t\t\t\tpositivenumber: true\n\t\t\t});\n\t\t\t$rewardCheckForm.find('#fieldRewardsEmail').rules('add', {\n\t\t\t\trequireEmailExtension: true\n\t\t\t});\n\t\t\t$rewardCheckForm.find('#fieldRewardsZipcode').rules('add', {\n\t\t\t\tpostal: true\n\t\t\t});\n\t\t\t$rewardCheckForm.find('#fieldRewardsPhone').rules('add', {\n\t\t\t\tphone: true\n\t\t\t});\n\t\t\t\n\t\t\t$('#rewardsCheckBalance #resetRewardsInquiry').on('click',  function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t$('.ui-selectmenu-text').text('Select One');\n\t\t\t\t$('#rewardsSelect1-button').removeClass('hidden');\n\t\t\t\t$('#rewardsSelect2-button').removeClass('hidden');\n\t\t\t\t$('#rewardsCheckBalance .form-row').addClass('hidden').find('input.input-text').val('');\n\t\t\t\t$('#sendRewardsInquiry').attr('disabled', true);\n\t\t\t\t$('.rewards-results').html('');\n\t\t\t});\n\t\t\t\n\t\t\t$('#rewardsCheckBalance').on('change', 'input.input-text', function() {\n\t\t\t\tif ( $('#fieldRewardsNumber').val() || $('#fieldRewardsEmail').val() ) {\n\t\t\t\t\tif ( $('#fieldRewardsZipcode').val() || $('#fieldRewardsPhone').val() ){\t\t\t\t\t\n\t\t\t\t\t\t$('#sendRewardsInquiry').removeAttr('disabled');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t$rewardCheckForm.find('input#sendRewardsInquiry').on('click', function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tvar $resultsContainer = $('.rewards-results');\n\n\t\t\t\t$resultsContainer.html('');\n\n\t\t\t\tif (!$rewardCheckForm.valid()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\turl: Urls.getRewardInfo,\n\t\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t'csrf_token':  $rewardCheckForm.find('input[name=\"csrf_token\"]').val(),\n\t\t\t\t\t\t\t'rewardsNumber': $rewardCheckForm.find('#fieldRewardsNumber').val(),\n\t\t\t\t\t\t\t'email': $rewardCheckForm.find('#fieldRewardsEmail').val(),\n\t\t\t\t\t\t\t'zipcode': $rewardCheckForm.find('#fieldRewardsZipcode').val(),\n\t\t\t\t\t\t\t'phone': $rewardCheckForm.find('#fieldRewardsPhone').val()\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tif ('error' in data && data['error']) {\n\t\t\t\t\t\t\t\t$resultsContainer.append('<p class=\"error-block\">'+data['message']+'</p>');\n\t\t\t\t\t\t\t\t$('.rewards-contact-custserv').removeClass('hidden');\n\t\t\t\t\t\t\t} else {\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t$('#rewards-dashboard').show();\n\t\t\t\t\t\t\t\tif (data.securityRisk) {\n\t\t\t\t\t\t\t\t\t$('.rewards-contact-custserv').removeClass('hidden');\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$('.display-rewards').removeClass('hidden');\n\t\t\t\t\t\t\t\t\tif ( $('#goToCreditTwo').length < 1 ) {\n\t\t\t\t\t\t\t\t\t\trenderRewardCheckResults(data, $resultsContainer);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$('.rewards-details').hide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n}\n\nfunction renderRewardCheckResults(data, $resultsContainer) {\n\tvar rewardsCreditAmount = $('.available-rewards').data('credit');\n\tvar pointsRequired = $('.available-rewards').data('required');\n\tvar pointsNeeded = pointsRequired-data.pointBalance;\n\tvar pointsText = data.pointBalance == 1 ? ' PT ' : ' PTS ';\n\t\n\t$('#rewards-number').text(\"#\" + data.rewardsNumber).removeClass('loader');\n\t$('#rewards-earned').text(\"$\" + (Math.floor(parseFloat(data.pointsEarnedInLastYear/pointsRequired))*15).toFixed(2));\n\t$('.rewards-message div').removeClass('loader');\n\t$('#rewards-credit').show().html(\"$\" + parseFloat(data.creditAmount).toFixed(0)).removeClass('loader');\n\tif (data.creditAmount != 0){\t\t\n\t\t$('#rewards-expiration').show().find('span').text(data.creditExpirationDate);\t\t\n\t} else {\n\t\t$('.rewards-zero-message').show();\n\t}\n\t$('.available-points div').removeClass('loader');\n\t$('.points-accrued').removeClass('loader').html(data.pointBalance);\n\t\n\tpassBreadSetup(data.rewardsNumber);\n\tBreadPayments.registerPlacements([loyaltyPlacement]);\n}\n\nfunction initDisplayLoyaltyData() {\n\tif ($('.pt_account').length > 0) {\n\t\t$.ajax({\n\t\t\turl: Urls.loyaltyCheck,\n\t\t\tdataType: 'JSON',\n\t\t\tmethod: 'POST',\n\t\t\tdata: {\n\t\t\t\t'loyaltyNumber': $('.settings--loyalty').attr('data-number'),\n\t\t\t\t'loyaltyZip': $('.settings--loyalty').attr('data-zip')\n\t\t\t},\t\t\t\t\t\t\n\t\t\tsuccess : function(data) {\n\t\t\t\tif (('error' in data && data['error'])) {\n\t\t\t\t\t$('.loyalty-error').text(data.message);\n\t\t\t\t} else {\n\t\t\t\t\trenderLoyaltyInfo(data.status);\n\t\t\t\t}\n\t\t\t},\n\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction renderLoyaltyInfo(data) {\n\tvar optinStatus = data.optIn;\n\t\n\tif (optinStatus){\n\t\t$('.loyalty-number span.value').text(data.loyaltyMemberNumber);\n\t\t$('.current-points span.value').text(Math.floor(data.points));\n\t\t$('.available-rewards span.value').text(\"$\" + data.totalRewards);\n\t} else {\n\t\t$('.settings--loyalty').hide();\n\t}\n}\n\nfunction clearLoyaltyForm() {\n\t$('.check-my-balance').show();\n\t$('.my-balance').hide();\n\t$('.ui-selectmenu-text').text('Select One');\n\t$('#loyaltySelect1-button').removeClass('hidden');\n\t$('#loyaltySelect2-button').removeClass('hidden');\n\t$('#loyaltyCheckBalance .form-row').addClass('hidden').find('input.input-text').val('');\n\t$('#sendLoyaltyInquiry').attr('disabled', true);\n\t$('.loyalty-results span').text('');\n\t$('.loyalty-error').html('');\n}\n\nfunction initLoyaltyCheckForm() {\n\tif ($('.pt_loyalty').length > 0) {\n\t\t$('#loyaltySelect1').selectmenu();\n\t\t$('#loyaltySelect2').selectmenu();\n\t\t\n\t\t$('body').on('click', '#loyaltySelect1-menu .ui-menu-item-wrapper', function(){\n\t\t\tvar select1text = $(this).text();\n\t\t\t\n\t\t\tif (select1text == \"Loyalty Number\" ) {\n\t\t\t\t$('#loyaltyCheckBalance .brewarded-number').removeClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .loyalty-number').removeClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .email-address').addClass('hidden');\n\t\t\t\t$('#loyaltySelect1-button').addClass('hidden');\n\t\t\t}\n\t\t\t\n\t\t\tif (select1text == \"Email Address\") {\n\t\t\t\t$('#loyaltyCheckBalance .email-address').removeClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .brewarded-number').addClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .loyalty-number').addClass('hidden');\n\t\t\t\t$('#loyaltySelect1-button').addClass('hidden');\n\t\t\t}\t\n\t\t});\n\t\t\n\t\t$('body').on('click', '#loyaltySelect2-menu .ui-menu-item-wrapper', function(){\n\t\t\tvar select2text = $(this).text();\n\t\t\t\n\t\t\tif (select2text == \"Zip Code\") {\n\t\t\t\t$('#loyaltyCheckBalance .zip-code').removeClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .phone-number').addClass('hidden');\n\t\t\t\t$('#loyaltySelect2-button').addClass('hidden');\n\t\t\t}\n\t\t\t\n\t\t\tif (select2text == \"Phone Number\") {\n\t\t\t\t$('#loyaltyCheckBalance .phone-number').removeClass('hidden');\n\t\t\t\t$('#loyaltyCheckBalance .zip-code').addClass('hidden');\n\t\t\t\t$('#loyaltySelect2-button').addClass('hidden');\n\t\t\t}\t\n\t\t});\n\t\t\n\t\tvar $loyaltyCheckForm = $('#loyaltyCheckBalance');\n\t\tif ($loyaltyCheckForm.length > 0) {\n\t\t\t$loyaltyCheckForm.find('#fieldLoyaltyNumber').rules('add', {\n\t\t\t\tpositivenumber: true\n\t\t\t});\n\t\t\t$loyaltyCheckForm.find('#fieldLoyaltyEmail').rules('add', {\n\t\t\t\trequireEmailExtension: true\n\t\t\t});\n\t\t\t$loyaltyCheckForm.find('#fieldLoyaltyZipcode').rules('add', {\n\t\t\t\tpostal: true\n\t\t\t});\n\t\t\t$loyaltyCheckForm.find('#fieldLoyaltyPhone').rules('add', {\n\t\t\t\tphone: true\n\t\t\t});\n\t\t\t\n\t\t\t$('#loyaltyCheckBalance #resetLoyaltyInquiry').on('click',  function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearLoyaltyForm();\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tvar scrollMinus = 0;\n\t\t\tif ($('.voucher').length > 8 ){\n\t\t\t\tscrollMinus = 100;\n\t\t\t}\n\t\t\tif ($(window).width() < 767) {\n\t\t\t\tscrollMinus = 190;\n\t\t\t}\t\t\n\t\t\t\n\t\t\t$('.my-balance #startOverLoyalty').on('click',  function() {\t\t\t\t\t\t\n\t\t\t\tclearLoyaltyForm();\n\t\t\t\tif (scrollMinus > 0) {\n\t\t\t\t\t$('html,body').animate({scrollTop: $(\".tab\").offset().top - scrollMinus}, 200);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t$('#loyaltyCheckBalance').on('change', 'input.input-text', function() {\n\t\t\t\tif ( $('#fieldLoyaltyNumber').val() || $('#fieldLoyaltyEmail').val() ) {\n\t\t\t\t\tif ( $('#fieldLoyaltyZipcode').val() || $('#fieldLoyaltyPhone').val() ){\t\t\t\t\t\n\t\t\t\t\t\t$('#sendLoyaltyInquiry').removeAttr('disabled');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\n\t\t\t$loyaltyCheckForm.find('input#sendLoyaltyInquiry').on('click', function(event) {\n\t\t\t\tevent.preventDefault();\n\t\n\t\t\t\tif (!$loyaltyCheckForm.valid()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: Urls.loyaltyCheck,\n\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\t'loyaltyNumber': $loyaltyCheckForm.find('#fieldLoyaltyNumber').val(),\n\t\t\t\t\t\t'loyaltyEmail': $loyaltyCheckForm.find('#fieldLoyaltyEmail').val(),\n\t\t\t\t\t\t'loyaltyZip': $loyaltyCheckForm.find('#fieldLoyaltyZipcode').val(),\n\t\t\t\t\t\t'loyaltyPhone': $loyaltyCheckForm.find('#fieldLoyaltyPhone').val()\n\t\t\t\t\t},\t\t\t\t\t\t\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\tif (('error' in data && data['error'])) {\n\t\t\t\t\t\t\t$('.loyalty-error').text(data.message);\n\t\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\trenderLoyaltyCheckResults(data.status);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction renderLoyaltyCheckResults(data) {\n\tvar optinStatus = data.optIn;\n\tvar currentSite = '';\n\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n    \tcurrentSite = Resources.LoyaltyCredit.NotOptedInSHEP;\n    }\n\tif (pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS) {\n    \tcurrentSite = Resources.LoyaltyCredit.NotOptedInCO;\n    }\n\t\n\tif (optinStatus){\n\t\t$('.check-my-balance').hide();\n\t\t$('.my-balance').removeClass('hidden').show();\n\t\t$('.loyalty-number span').text(data.loyaltyMemberNumber);\n\t\t$('.current-points span').text(Math.floor(data.points));\n\t\t$('.available-rewards span').text(\"$\" + data.totalRewards);\n\t\tvar details = '';\n\t\tvar vouchers = data.rewardInfo;\n\t\t\n\t\tvouchers.forEach(function(voucher){\n\t\t\tdetails += '<div class=\"voucher\"><span class=\"reward-amount\">Reward Amount: <b>$'+voucher.rewardAmount+'</b></span><span class=\"expiration\">Expiration Date: <b>'+voucher.expirationDate+'</b></span></div>';\n\t\t});\n\t\t\n\t\t$('.details').html(details);\n\t} else {\n\t\t$('.loyalty-error').text(currentSite);\n\t}\n}\n\nfunction initLoyaltySocial() {\n\tvar handle = '';\n\t\n\t$('body').on('focus', '#fieldLoyaltySocialHandleInstagram', function() {\n\t\t$('.handle-error').text('');\n\t});\n\n\t$('body').on('click', '#updateInstagramHandle', function(){\n\t\t$('.handle-display').removeClass('show-handle').addClass('show-form');\n\t\t$('.form-display').removeClass('show-handle').addClass('show-form');\n\t});\n\t\n\t$('body').on('click', '#addInstagramHandle', function(){\n\t\tevent.preventDefault();\n\t\t\n\t\tvar formValidation = true;\n\t\tvar handle = $('#fieldLoyaltySocialHandleInstagram').val();\n\t\tvar regexHandle = /^@([a-zA-Z0-9]|[._](?![._])){2,30}$/;\n\t\tif (String(handle).match(regexHandle) == null ) {\n\t\t\tformValidation = false;\n\t\t}\n\n\t\tif (formValidation) {\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.loyaltyOptin,\n\t\t\t\tdataType: 'JSON',\n\t\t\t\tmethod: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\t'email': $('.settings--loyalty').attr('data-email'),\n\t\t\t\t\t'dwCustomerID': $('.settings--loyalty').attr('data-dwid'),\n\t\t\t\t\t'instaHandle': handle,\n\t\t\t\t\t'optStatus': $('.settings--loyalty').attr('data-optin')\n\t\t\t\t},\t\t\t\t\t\t\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tif (('error' in data && data['error'])) {\n\t\t\t\t\t\t$('.handle-error').text(data.message);\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t$('.handle-display').removeClass('show-form').addClass('show-handle');\n\t\t\t\t\t\t$('.handle-display .value').text(handle);\n\t\t\t\t\t\t$('.form-display').removeClass('show-form').addClass('show-handle');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t$('.handle-error').text('Please enter a valid social handle.');\n\t\t}\n\t});\n}\n\nfunction initAddressFormEvents() {\n\t$(document).ready(function(){\n\t\t$(document).on('change', '#dwfrm_profile_address_country', function(){\n\t\t\trenderOptions('#dwfrm_profile_address_states_state', '#dwfrm_profile_address_country');\n\t\t\tvar $initialState = $('#dwfrm_profile_address_states_state_sbm');\n\t\t\t\n\t\t\tif ($initialState.length > 0 && $initialState.val() != '') {\n\t\t\t\t$('#dwfrm_profile_address_states_state').val($initialState.val());\n\t\t\t}\n\t\t});\n\t\t$('#dwfrm_profile_address_country').trigger('change');\n\t\t\n\t\t$(document).on('click', '.find-more-stores a', function () {\n\t\t\tfindMoreStores.initialize({ view: 'account' });\n\t\t});\n\t\t\n\t\t$(document).on('opc.SetShippingAddress', function (e, address) {\n\t\t\tvar $closestStores = $('#closestStores');\n\t\t\tvar $makeThisMystore = $('#storeControls').find('[data-action=\"makethismystore\"]');\n\t\t\t\n\t\t\t$closestStores.find('option.find-more-stores').remove();\n\t\t\tif ($closestStores.find('option[value=\"' + address.storeId + '\"]').length == 0) {\n\t\t\t\t$closestStores.find('option').first().after('<option class=\"find-more-stores\" value=\"' + address.storeId + '\">' + address.firstName + ' - ' + address.labelText + '</option>');\n\t\t\t}\n\t\t\t\n\t\t\t$closestStores.val(address.storeId);\n\t\t\t$closestStores.trigger('change');\n\t\t\tif ($makeThisMystore.length > 0) {\n\t\t\t\t$makeThisMystore.trigger('click');\n\t\t\t}\n\t\t});\n\n\t\t$(document).on('click', '.address-tile .address-delete', function() {\n\t\t\tif (!confirm(String.format(Resources.CONFIRM_DELETE, Resources.TITLE_ADDRESS))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t});\n}\n\nfunction verifyAccountCode() {  \n\t// 'enter-code' rules will be applied to rewards verification page with this code. See loginDialog.js for the rules added after account dialog is opened.\t\n\t$('#verify-code').find('#enter-code').rules('add', {\n\t\trequired: true,\n\t\tdigits: true,\n\t\tminlength: 6,\n\t\tmessages: {\n\t\t\trequired: Resources.VALIDATE_CODE,\n\t\t\tminlength: Resources.VALIDATE_CODE\n\t\t},\n\t\tnormalizer: function(value) {\n\t\t\treturn $.trim(value);\n\t\t}\n\t});\n}\n\n/* On the Account registration (aka settings) page, hook up the event handler to update the hidden form field\n * for 'My Store Number' when the (dynamically populated) Closest Stores drop down is changed. \n * Also, set the value of the selected option in the drop down, or the value in 'My Store Number'\n * appropriately on load (based on if creating an Account or editing one. \n */\nfunction initCreateAccountEventHandlers(){\n\tvar $closestStores = $('#closestStores');\n\tvar $storeControls = $('#storeControls');\n\tif ($closestStores != undefined && $closestStores != null){\n\t\tvar lengthStores = $closestStores.find('option').length;\n\t\tif (lengthStores > 0) {\n\t\t\tvar storedValue = $('#dwfrm_profile_customer_myStoreNumber').val();\n\t\t\t$closestStores.on('change', function(e) {\n\t\t\t\tvar newValue = $(this).val();\n\t\t\t\t$('#dwfrm_profile_customer_myStoreNumber').val(newValue);\n\t\t\t\tupdateSelectedStorePreview($(e.target).find(':selected'));\n\n\t\t\t\tif (storedValue !== newValue) {\n\t\t\t\t\t$storeControls.removeClass('hidden');\n\t\t\t\t} else {\n\t\t\t\t\t$storeControls.addClass('hidden');\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tsetSelectedStoreDropdownOrMyStoreNumber();\n\t\t}\n\t\t$storeControls.on('click', 'a', function(e) {\n\t\t\te.preventDefault();\n\t\t\tvar storeId = $('#dwfrm_profile_customer_myStoreNumber').val();\n\t\t\t$.ajax({\n\t\t\t\turl : Urls.assignStoreId,\n\t\t\t\tdata : { store_id : storeId },\n\t\t\t\tmethod : \"POST\",\n\t\t\t\tdataType : \"JSON\",\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tif ( 'success' in data && data['success'] == true ) {\n\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\n/* Check and see if the profile has a value for 'My Store Number', which it might if on the Account Edit page.\n * If so, then set the store drop down to the store on the profile.\n * If not, then set the hidden form field for 'My Store Number' to the selected store in the drop down, which will be the first one when on the Create Account page.  \n */\nfunction setSelectedStoreDropdownOrMyStoreNumber() {\n\tvar $myStoreNumberSelected = $('#dwfrm_profile_customer_myStoreNumber');\n\tif ($myStoreNumberSelected != undefined && $myStoreNumberSelected != null){\n\t\tvar currentMyStoreValue = $myStoreNumberSelected.val(); \n\t\tif (currentMyStoreValue == undefined || currentMyStoreValue == null || currentMyStoreValue.length == 0){\n\t\t\t$myStoreNumberSelected.val($('#closestStores').val());\t\n\t\t} else {\n\t\t\t$('#closestStores option[value=' + currentMyStoreValue + ']').attr('selected','selected');\n\t\t\tupdateSelectedStorePreview($('#closestStores option[value=' + currentMyStoreValue + ']'));\n\t\t}\n        $('#storeSection').removeClass('hidden');\n\t}\n}\n\nfunction updateSelectedStorePreview($store) {\n\tif ($('#selectedStore').length > 0) {\n\t\t$('#selectedStore .name').text($store.data('name'));\n\t\t$('#selectedStore .address1').text($store.data('address1'));\n\t\tif ($store.data('address2') && $store.data('address2').length > 0) {\n\t\t\t$('#selectedStore .address2').text($store.data('address2')).removeClass('hidden');\n\t\t} else {\n\t\t\t$('#selectedStore .address2').text('').addClass('hidden');\n\t\t}\n\t\t\n\t\t$('#selectedStore .city').text($store.data('city'));\n\t\t$('#selectedStore .stateCode').text($store.data('statecode'));\n\t\t$('#selectedStore .postalCode').text($store.data('postalcode'));\n\t\t$('#selectedStore .countryCode').text($store.data('countrycode'));\n\t\t$('#selectedStore .phone').text($store.data('phone'));\n\t}\n}\n\n\n\nmodule.exports = {\n    init: function (optionsParameter) {\n\t\toptions = optionsParameter;\n\n\t\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\t\tAddressVerificationDialog = require('../Lob/AddressVerification/AddressVerificationDialog');\n\t\t}\n\n\t\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\t\tAddressAutocompleteDialog = require('../Lob/AddressAutocomplete/AddressAutocompleteDialog');\n\t\t}\n\n        initializeEvents();\n        giftcert.init();\n        initAddressFormEvents();\n        initRewardRegisterForm();\n        initRewardCheckForm();\n        initLoyaltyCheckForm();\n        if (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n        \tinitDisplayRewardsData();\n        }\n        if ((pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS || pageContext.site === SiteConstants.SiteIds.SheplersUS) && SitePreferences.LOYALTY_ENABLED) {\n        \tinitDisplayLoyaltyData();\n        \tinitLoyaltySocial();\n        }\n        initRewardsAttached();\n\t\tverifyAccountCode();\n        orderStatusForm.initialize($('#dwfrm_ordertrack'));      \n    },\n    initCartLogin: function () {\n        initLoginPage();\n        initRewardsPage();\n    }\n};","'use strict';\n\nvar bopis = require('../bopis/components/LocationSearch');\n\nexports.init = function (options) {\n\tvar bopisWaysToShop = new bopis();\n\tvar bopisFooter = new bopis();\n\t\n\tif ($('.waystoshop .bopis-store-search').length > 0) {\n\t\tbopisWaysToShop.initialize($('.waystoshop .bopis-store-search'), $.extend(options.Bopis, { Channel: options.Channel }));\n\t}\n\tif ($('.bopis-store-search-container .bopis-store-search').length > 0) {\n\t\tbopisFooter.initialize($('.bopis-store-search-container .bopis-store-search'), $.extend(options.Bopis, { Channel: options.Channel }));\n\t}\n};\n","'use strict';\n\nvar _ = require('lodash');\nvar GoogleTagManagerClient = require('../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar util = require('../util');\nvar ValidationSettings = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\n\nvar options;\nvar dataBuffer;\nvar $container;\nvar $step;\nvar templates;\nvar loadingIndicatorSettings;\n\nexports.init = function (optionsParameter) {\n\tif (optionsParameter) {\n\t\toptions = optionsParameter;\n\t} else {\n\t\toptions = {};\n\t}\n\t$container = $('.bootfinder');\n\t$step = $container.find('[step]');\n\tdataBuffer = {\n\t\tstep: 0,\n\t\tstepData: {}\n\t};\n\ttemplates = {\n\t\tsectionContainer: _.template($('#template-bootfinder-section-container').html(), TemplateConstants.Lodash.Settings),\n\t\tsection: _.template($('#template-bootfinder-section').html(), TemplateConstants.Lodash.Settings),\n\t\toption: _.template($('#template-bootfinder-option').html(), TemplateConstants.Lodash.Settings),\n\t\toptionImage: _.template($('#template-bootfinder-option-image').html(), TemplateConstants.Lodash.Settings),\n\t\tresults: _.template($('#template-bootfinder-results').html(), TemplateConstants.Lodash.Settings)\n\t}\n\tloadingIndicatorSettings = {\n\t\tIsLabelShown: false\n\t};\n\t\n\t$container.off('click.BootFinderStepDelta').on('click.BootFinderStepDelta', '[step-delta]', function(event) {\n\t\tvar $this = $(this);\n\t\tvar stepDelta = parseInt($this.attr('step-delta'), 10);\n\t\tdataBuffer.stepDelta = stepDelta;\n\t\tvar step = dataBuffer.step + dataBuffer.stepDelta;\n\t\tif (step >= 0 && step <= options.Configuration.Steps.length) {\n\t\t\tdataBuffer.step = step;\n\t\t}\n\t\trender();\n\t});\n\n\t// $container.off('click.BootFinderStepIndex').on('click.BootFinderStepIndex', '[step-index]', function(event) {\n\t// \tvar $this = $(this);\n\t// \tvar step = parseInt($this.attr('step-index'), 10);\n\t// \tif (step >= 0 && step <= options.Configuration.Steps.length) {\n\t// \t\tdataBuffer.step = step;\n\t// \t}\n\t// \trender();\n\t// });\n\n\t$container.off('click.BootFinderStepOptions').on('click.BootFinderStepOptions', '[step] .options .option', function(event) {\n\t\tvar $this = $(this);\n\t\tvar sectionIndex = parseInt($this.closest('[section]').attr('section'), 10);\n\t\tif ($this.hasClass('selected') && !options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].SelectRequired) {\n\t\t\t$this.removeClass('selected');\n\t\t\tif (dataBuffer.stepData[dataBuffer.step] && dataBuffer.stepData[dataBuffer.step][sectionIndex]) {\n\t\t\t\tvar selectedIndex = dataBuffer.stepData[dataBuffer.step][sectionIndex].indexOf($this.attr('value'));\n\t\t\t\tif (selectedIndex > -1) {\n\t\t\t\t\tdataBuffer.stepData[dataBuffer.step][sectionIndex].splice(selectedIndex, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'size' || options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'width') {\n\t\t\t\tupdateSizes(sectionIndex, options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex]);\n\t\t\t}\n\t\t} else {\n\t\t\tif (!options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].SelectMultiple) {\n\t\t\t\t$this.closest('.options').find('.option').removeClass('selected');\n\t\t\t}\n\t\t\tif (options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].SelectReset && (dataBuffer.step + 1) <= options.Configuration.Steps.length) {\n\t\t\t\tfor (var stepIndex = (dataBuffer.step + 1); stepIndex <= options.Configuration.Steps.length; stepIndex++) {\n\t\t\t\t\tdataBuffer.stepData[stepIndex] = {};\n\t\t\t\t}\n\t\t\t}\n\t\t\t$this.addClass('selected');\n\t\t\tif (!dataBuffer.stepData[dataBuffer.step]) {\n\t\t\t\tdataBuffer.stepData[dataBuffer.step] = {}\n\t\t\t}\n\t\t\tif (!dataBuffer.stepData[dataBuffer.step][sectionIndex] || !options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].SelectMultiple) {\n\t\t\t\tdataBuffer.stepData[dataBuffer.step][sectionIndex] = [];\n\t\t\t}\n\t\t\tvar sectionData = dataBuffer.stepData[dataBuffer.step][sectionIndex];\n\t\t\tsectionData[sectionData.length] = $this.attr('value');\n\t\t\tif (options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'size' || options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'width') {\n\t\t\t\tupdateSizes(sectionIndex, sectionData);\n\t\t\t}\n\t\t}\n\n\t\tif (!options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].SelectMultiple && $this.closest('.options').find('.selected').length > 0 && dataBuffer.step < (options.Configuration.Steps.length - 1)) {\n\t\t\tdataBuffer.stepDelta = 1;\n\t\t\tdataBuffer.step += dataBuffer.stepDelta;\n\t\t\trender();\n\t\t}\n\t});\n\n\t$container.off('click.BootFinderSendResultsEmail').on('click.BootFinderSendResultsEmail', '.send-results-email', function(event) {\n\t\tevent.preventDefault();\n\t\t\n\t\tvar $this = $(this);\n\t\tvar $form = $this.closest('form');\n\t\tif (dataBuffer.$emailForm && dataBuffer.$emailForm.valid()) {\n\t\t\tvar url = buildUrl();\n\t\t\turl = util.appendParamToURL(url, 'bootfinderemail');\n\n\t\t\tvar payload = {\n\t\t\t\temail: $form.find('input[type=\"email\"]').val(),\n\t\t\t\turl: url\n\t\t\t}\n\t\t\t$step.loading($.extend(loadingIndicatorSettings, {\n\t\t\t\tIsLabelShown: true,\n\t\t\t\tContent: 'Sending Email...'\n\t\t\t}));\n\t\t\t$.ajax({\n\t\t\t\ttype: 'post',\n\t\t\t\tdata: payload,\n\t\t\t\turl: buildUrl(Urls.BootFinder.SendResultsEmail),\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (data && data.success) {\n\t\t\t\t\t\t$step.find('.loading-indicator').find('.content').html('Email Sent!<br/>Loading Results...');\n\t\t\t\t\t\twindow.location = $('.view-results').attr('href');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$container.find('.validation-error-container').html('<span class=\"error\">An error occurred sending the email. Please try again.</span>');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t$container.off('click.BootFinderViewResults').on('click.BootFinderViewResults', '.view-results', function(event) {\n\t\tif (!$step.attr('loading')) {\n\t\t\t$step.loading($.extend(loadingIndicatorSettings, {\n\t\t\t\tContent: 'Loading Results...'\n\t\t\t}));\n\t\t\tvar url = buildUrl();\n\t\t\turl = util.appendParamToURL(url, 'bootfinderviewresults');\n\t\t\twindow.location = url;\n\t\t}\n\t});\n\n\t$(window).off('load.BootFinder resize.BootFinder').on('load.BootFinder resize.BootFinder', function(event) {\n\t\tif ($(window).outerWidth() <= 768) {\n\t\t\t$container.css('min-height', $(window).outerHeight() - $('.header-wrapper').height());\n\t\t} else {\n\t\t\t$container.css('min-height', 0);\n\t\t}\n\t});\n\n\tvar stepListHtml = '';\n\tfor (var stepIndex in options.Configuration.Steps) {\n\t\tstepListHtml += '<a step-index=\"' + stepIndex + '\"></a>';\n\t}\n\t$container.find('.step-list').html(stepListHtml);\n\trender();\n};\n\nfunction render() {\n\t$step.height($step.outerHeight());\n\t$step.html('');\n\t$step.loading(loadingIndicatorSettings);\n\t$('html').animate({ scrollTop: 0 }, 250);\n\tif (dataBuffer.step == (options.Configuration.Steps.length - 1)) {\n\t\t$container.find('.next').hide();\n\t\t$container.find('.view-results').show();\n\t} else {\n\t\t$container.find('.next').show();\n\t\t$container.find('.view-results').hide();\n\t}\n\trenderStep();\n\tsendDataLayer();\n\tif ($container.hasClass('results')) {\n\t\t$container.removeClass('results');\n\t}\n\n\t$container.find('.step-list a').removeClass('active');\n\t$container.find('.step-list a:nth-child(' + (dataBuffer.step + 1) + ')').addClass('active');\n\t$container.find('[step]').attr('step', dataBuffer.step);\n}\n\nfunction updateSizes(sectionIndex, sectionData) {\n\treturn getRefinementCountsForSection(sectionIndex, sectionData).then(function(data) {\n\t\tif (options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex] && options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'size') {\n\t\t\tvar $selectedLengths = $('[section=\"' + sectionIndex + '\"] .options').find('.option.selected');\n\t\t\tvar $widths = $('[section=\"' + (sectionIndex + 1) + '\"] .options .option');\n\t\t\tif ($selectedLengths && $selectedLengths.length > 0) {\n\t\t\t\t$widths.addClass('disabled');\n\t\t\t\t$selectedLengths.each(function() {\n\t\t\t\t\tvar selectedLength = $(this).attr('value');\n\t\t\t\t\t$widths.each(function() {\n\t\t\t\t\t\tvar width = $(this).attr('value');\n\t\t\t\t\t\tvar size = selectedLength + ' ' + width;\n\t\t\t\t\t\tif (dataBuffer.Refinements && dataBuffer.Refinements.size && dataBuffer.Refinements.size[size]) {\n\t\t\t\t\t\t\t$widths.filter('[value=\"' + width + '\"]').removeClass('disabled');\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t$widths.removeClass('disabled');\n\t\t\t}\n\t\t} else if (options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex] && options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex].Refinement == 'width') {\n\t\t\tvar $selectedWidths = $('[section=\"' + sectionIndex + '\"] .options').find('.option.selected');\n\t\t\tvar $lengths = $('[section=\"' + (sectionIndex - 1) + '\"] .options .option');\n\t\t\tif ($selectedWidths && $selectedWidths.length > 0) {\n\t\t\t\t$lengths.addClass('disabled');\n\t\t\t\t$selectedWidths.each(function() {\n\t\t\t\t\tvar selectedWidth = $(this).attr('value');\n\t\t\t\t\t$lengths.each(function() {\n\t\t\t\t\t\tvar length = $(this).attr('value');\n\t\t\t\t\t\tvar size = length + ' ' + selectedWidth;\n\t\t\t\t\t\tif (dataBuffer.Refinements && dataBuffer.Refinements.size && dataBuffer.Refinements.size[size]) {\n\t\t\t\t\t\t\t$lengths.filter('[value=\"' + length + '\"]').removeClass('disabled');\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t$lengths.removeClass('disabled');\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction renderStep() {\n\tvar step = options.Configuration.Steps[dataBuffer.step];\n\tvar stepData;\n\tif (dataBuffer.stepData && dataBuffer.stepData[dataBuffer.step]) {\n\t \tstepData = dataBuffer.stepData[dataBuffer.step];\n\t}\n\tdataBuffer.sectionRenderCount = 0;\n\tfor (var sectionIndex in step.Sections) {\n\t\tvar section = step.Sections[sectionIndex];\n\t\tvar columns = 1;\n\t\tif (section.Columns) {\n\t\t\tcolumns = section.Columns;\n\t\t}\n\t\t$container.find('[step]').append(templates.sectionContainer({\n\t\t\tSection: sectionIndex,\n\t\t\tColumns: columns\n\t\t}));\n\n\t\tvar optionsHtml = '';\n\t\tif (section.Options) {\n\t\t\tvar sectionOptions;\n\t\t\tif (typeof section.Options == 'object' && section.OptionsRelatedSelectionStep != undefined && section.OptionsRelatedSelectionSection != undefined && dataBuffer.stepData && dataBuffer.stepData[section.OptionsRelatedSelectionStep] && dataBuffer.stepData[section.OptionsRelatedSelectionStep][section.OptionsRelatedSelectionSection]) {\n\t\t\t\tvar optionsRelatedSelectionValue = dataBuffer.stepData[section.OptionsRelatedSelectionStep][section.OptionsRelatedSelectionSection];\n\t\t\t\tsectionOptions = section.Options[optionsRelatedSelectionValue];\n\t\t\t} else {\n\t\t\t\tsectionOptions = section.Options;\n\t\t\t}\n\t\t\tfor (var optionIndex in sectionOptions) {\n\t\t\t\tvar option = sectionOptions[optionIndex];\n\t\t\t\tif (option.Text) {\n\t\t\t\t\tvar cssClass = '';\n\t\t\t\t\tif (stepData && stepData[sectionIndex] && 'indexOf' in stepData[sectionIndex] && stepData[sectionIndex].indexOf(option.Text) > -1) {\n\t\t\t\t\t\tcssClass = 'selected';\n\t\t\t\t\t}\n\n\t\t\t\t\toptionsHtml += templates.option({\n\t\t\t\t\t\tImage: '',\n\t\t\t\t\t\tText: option.Text,\n\t\t\t\t\t\tValue: option.Text,\n\t\t\t\t\t\tCssClass: cssClass\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\trenderSection(sectionIndex, section.Header, section.Text, optionsHtml);\n\t\t} else if (section.Refinement && section.Refinement != 'width') {\n\t\t\tgetRefinementCountsForSection(sectionIndex, section).then(function(data) {\n\t\t\t\tvar optionsHtmlInner = '';\n\t\t\t\tif (data.Section.Refinement == 'size') {\n\t\t\t\t\tvar lengths = [];\n\t\t\t\t\tvar widths = [];\n\t\t\t\t\tvar widthRegex = / [\\w\\/]+/gi;\n\t\t\t\t\tfor (var refinementKey in data.Refinements) {\n\t\t\t\t\t\tvar refinementCount = data.Refinements[refinementKey];\n\t\t\t\t\t\tif (refinementCount) {\n\t\t\t\t\t\t\tvar widthRegexResult = refinementKey.match(widthRegex);\n\t\t\t\t\t\t\tvar length;\n\t\t\t\t\t\t\tvar width;\n\t\t\t\t\t\t\tif (widthRegexResult && widthRegexResult.length) {\n\t\t\t\t\t\t\t\twidth = widthRegexResult[widthRegexResult.length - 1].trim();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (width) {\n\t\t\t\t\t\t\t\tlength = refinementKey.replace(width, '').trim();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (length && lengths.indexOf(length) < 0) {\n\t\t\t\t\t\t\t\tlengths[lengths.length] = length;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (width && widths.indexOf(width) < 0) {\n\t\t\t\t\t\t\t\twidths[widths.length] = width;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlengths.sort(function(left, right) {\n\t\t\t\t\t\tvar leftValue = left.replace(/ *1\\/2/, '.5');\n\t\t\t\t\t\tvar rightValue = right.replace(/ *1\\/2/, '.5');\n\t\t\t\t\t\treturn parseFloat(leftValue) - parseFloat(rightValue);\n\t\t\t\t\t});\n\n\t\t\t\t\twidths.sort(function(left, right) {\n\t\t\t\t\t\tvar leftValue = parseInt(left, 10);\n\t\t\t\t\t\tvar rightValue = parseInt(right, 10);\n\t\t\t\t\t\tif (leftValue) {\n\t\t\t\t\t\t\tleftValue = ''.padStart(leftValue, left.replace(/\\d/g, '')[0]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tleftValue = left;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (rightValue) {\n\t\t\t\t\t\t\trightValue = ''.padStart(rightValue, right.replace(/\\d/g, '')[0]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trightValue = right;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar leftWidthDescription;\n\t\t\t\t\t\tif (options.WidthDescriptionConfiguration && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][left]) {\n\t\t\t\t\t\t\tleftWidthDescription = options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][left];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar rightWidthDescription;\n\t\t\t\t\t\tif (options.WidthDescriptionConfiguration && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][right]) {\n\t\t\t\t\t\t\trightWidthDescription = options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][right];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (leftWidthDescription == 'Medium' && rightWidthDescription != 'Medium') {\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t} else if (leftWidthDescription != 'Medium' && rightWidthDescription == 'Medium') {\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (leftWidthDescription == 'Wide' && rightWidthDescription != 'Wide') {\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t} else if (leftWidthDescription != 'Wide' && rightWidthDescription == 'Wide') {\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn leftValue.localeCompare(rightValue);\n\t\t\t\t\t});\n\n\t\t\t\t\tfor (var lengthIndex in lengths) {\n\t\t\t\t\t\tvar length = lengths[lengthIndex];\n\t\t\t\t\t\tvar cssClass = '';\n\t\t\t\t\t\tif (stepData && stepData[data.SectionIndex] && 'indexOf' in stepData[data.SectionIndex] && stepData[data.SectionIndex].indexOf(length) > -1) {\n\t\t\t\t\t\t\tcssClass = 'selected';\n\t\t\t\t\t\t}\n\t\t\t\t\t\toptionsHtmlInner += templates.option({\n\t\t\t\t\t\t\tImage: '',\n\t\t\t\t\t\t\tText: length,\n\t\t\t\t\t\t\tValue: length,\n\t\t\t\t\t\t\tCssClass: cssClass\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tdataBuffer.lengths = lengths;\n\t\t\t\t\trenderSection(data.SectionIndex, data.Section.Header, data.Section.Text, optionsHtmlInner);\n\n\t\t\t\t\tvar widthsHtml = '';\n\t\t\t\t\tvar widthSectionIndex = parseInt(data.SectionIndex, 10) + 1;\n\t\t\t\t\tfor (var widthIndex in widths) {\n\t\t\t\t\t\tvar width = widths[widthIndex];\n\t\t\t\t\t\tvar cssClass = '';\n\t\t\t\t\t\tif (stepData && stepData[widthSectionIndex] && 'indexOf' in stepData[widthSectionIndex] && stepData[widthSectionIndex].indexOf(width) > -1) {\n\t\t\t\t\t\t\tcssClass = 'selected';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar widthDescription = '';\n\t\t\t\t\t\tif (options.WidthDescriptionConfiguration && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'] && options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][width]) {\n\t\t\t\t\t\t\twidthDescription = ' (' + options.WidthDescriptionConfiguration[dataBuffer.stepData[0][0]]['Boot'][width] + ')';\n\t\t\t\t\t\t}\n\t\t\t\t\t\twidthsHtml += templates.option({\n\t\t\t\t\t\t\tImage: '',\n\t\t\t\t\t\t\tText: width + widthDescription,\n\t\t\t\t\t\t\tValue: width,\n\t\t\t\t\t\t\tCssClass: cssClass\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tdataBuffer.widths = widths;\n\t\t\t\t\t$container.find('[section=\"' + widthSectionIndex + '\"] .options').html(widthsHtml);\n\t\t\t\t\tupdateSizes(sectionIndex, options.Configuration.Steps[dataBuffer.step].Sections[sectionIndex]);\n\t\t\t\t} else {\n\t\t\t\t\tfor (var refinementKey in data.Refinements) {\n\t\t\t\t\t\tvar refinementCount = data.Refinements[refinementKey];\n\t\t\t\t\t\tif (refinementCount) {\n\t\t\t\t\t\t\tvar refinementText;\n\t\t\t\t\t\t\tif (dataBuffer.DisplayValues[data.Section.Refinement] && dataBuffer.DisplayValues[data.Section.Refinement][refinementKey]) {\n\t\t\t\t\t\t\t\trefinementText = dataBuffer.DisplayValues[data.Section.Refinement][refinementKey];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trefinementText = refinementKey;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar cssClass = '';\n\t\t\t\t\t\t\tif (stepData && stepData[data.SectionIndex] && 'indexOf' in stepData[data.SectionIndex] && stepData[data.SectionIndex].indexOf(refinementKey) > -1) {\n\t\t\t\t\t\t\t\tcssClass = 'selected';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar sectionImages;\n\t\t\t\t\t\t\tif (typeof section.Images == 'object' && section.ImagesRelatedSelectionStep != undefined && section.ImagesRelatedSelectionSection != undefined && dataBuffer.stepData && dataBuffer.stepData[section.ImagesRelatedSelectionStep] && dataBuffer.stepData[section.ImagesRelatedSelectionStep][section.ImagesRelatedSelectionSection]) {\n\t\t\t\t\t\t\t\tvar imagesRelatedSelectionValue = dataBuffer.stepData[section.ImagesRelatedSelectionStep][section.ImagesRelatedSelectionSection];\n\t\t\t\t\t\t\t\tsectionImages = section.Images[imagesRelatedSelectionValue];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsectionImages = section.Images;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar imageHtml = '';\n\t\t\t\t\t\t\tif (sectionImages && sectionImages[refinementKey]) {\n\t\t\t\t\t\t\t\timageHtml = templates.optionImage({\n\t\t\t\t\t\t\t\t\tImageUrl: sectionImages[refinementKey]\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\n\t\t\t\t\t\t\toptionsHtmlInner += templates.option({\n\t\t\t\t\t\t\t\tImage: imageHtml,\n\t\t\t\t\t\t\t\tText: refinementText,\n\t\t\t\t\t\t\t\tValue: refinementKey,\n\t\t\t\t\t\t\t\tCssClass: cssClass\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\trenderSection(data.SectionIndex, data.Section.Header, data.Section.Text, optionsHtmlInner);\n\t\t\t\t}\n\t\t\t}).catch();\n\t\t} else {\n\t\t\trenderSection(sectionIndex, section.Header, section.Text, optionsHtml);\n\t\t}\n\t}\n}\n\nfunction renderSection(index, header, textParameter, sectionOptions) {\n\tdataBuffer.sectionRenderCount++;\n\tvar text = '';\n\tif (textParameter) {\n\t\ttext = '<p>' + textParameter + '</p>';\n\t}\n\t$container.find('[section=\"' + index + '\"]').html(templates.section({\n\t\tHeader: header,\n\t\tText: text,\n\t\tOptions: sectionOptions\n\t}));\n\n\tif (dataBuffer.sectionRenderCount == options.Configuration.Steps[dataBuffer.step].Sections.length) {\n\t\tif ($step.attr('loading')) {\n\t\t\t$step.css('height', '');\n\t\t\t$step.loading('destroy');\n\t\t\t$('html').animate({ scrollTop: 0 }, 250);\n\t\t}\n\t\t$container.find('[step-delta]').removeClass('disabled');\n\t\tif (options.Configuration.Steps[dataBuffer.step].Sections[index].SelectRequired && $('.options').length != $('.options').find('.selected').length) {\n\t\t\t$container.find('.next').addClass('disabled');\n\t\t}\t\n\t\tif (dataBuffer.step == 0) {\n\t\t\t$container.find('.back').addClass('disabled');\n\t\t}\n\t\tif ($container.find('.option').length == 0) {\n\t\t\tif (dataBuffer.step < (options.Configuration.Steps.length - 1)) {\n\t\t\t\tdataBuffer.step += dataBuffer.stepDelta;\n\t\t\t\trender();\n\t\t\t} else {\n\t\t\t\t$('section header h2').text('No more options to choose from, click the View Results button!')\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction renderResults() {\n\tvar url = buildUrl();\n\turl = util.appendParamToURL(url, 'bootfinderviewresults');\n\n\t$container.find('[step]').html(templates.results({\n\t\tUrl: url\n\t}));\n\n\tdataBuffer.$emailForm = $container.find('form.email');\n\tdataBuffer.emailValidator = dataBuffer.$emailForm.validate(ValidationSettings.Global);\n\tdataBuffer.$emailForm.find('input[name=\"email\"]').rules('add', $.extend(ValidationRules.Email, {\n\t\trequired: true,\n\t\tmessages: {\n\t\t\trequired: $.validator.format('Please enter an email address.')\n\t\t}\n\t}));\n\tdataBuffer.$emailForm.find('input[name=\"useragreement\"]').rules('add', {\n\t\trequired: true,\n\t\tmessages: {\n\t\t\trequired: $.validator.format('Please agree to the terms and conditions.')\n\t\t}\n\t});\n\n\tif ($step.attr('loading')) {\n\t\t$step.css('height', '');\n\t\t$step.loading('destroy');\n\t\t$('html').animate({ scrollTop: 0 }, 250);\n\t}\n\t$container.find('[step-delta]').removeClass('disabled');\n\t$container.find('.next').addClass('disabled');\n}\n\nfunction buildUrl(urlParameter, includeAdditionalData) {\n\tvar url;\n\tif (dataBuffer && dataBuffer.stepData[options.Configuration.CategorySelectionStep] && dataBuffer.stepData[options.Configuration.CategorySelectionStep][options.Configuration.CategorySelectionSection]) {\n\t\tvar categorySelectionSection = options.Configuration.Steps[options.Configuration.CategorySelectionStep].Sections[options.Configuration.CategorySelectionSection];\n\t\tvar optionRelatedSelection = dataBuffer.stepData[categorySelectionSection.OptionsRelatedSelectionStep][categorySelectionSection.OptionsRelatedSelectionSection][0];\n\t\tvar categorySelection = dataBuffer.stepData[options.Configuration.CategorySelectionStep][options.Configuration.CategorySelectionSection][0];\n\n\t\tvar categorySelectionIndex;\n\t\tvar optionRelatedSelectionOptionIndex = 0;\n\t\tvar optionRelatedSelectionOptions = categorySelectionSection.Options[optionRelatedSelection];\n\t\twhile (!categorySelectionIndex && optionRelatedSelectionOptionIndex <= optionRelatedSelectionOptions.length) {\n\t\t\tif (optionRelatedSelectionOptions[optionRelatedSelectionOptionIndex] && optionRelatedSelectionOptions[optionRelatedSelectionOptionIndex].Text == categorySelection) {\n\t\t\t\tcategorySelectionIndex = optionRelatedSelectionOptionIndex;\n\t\t\t}\n\t\t\toptionRelatedSelectionOptionIndex++;\n\t\t}\n\n\t\tvar categorySelectionData = categorySelectionSection.Options[optionRelatedSelection][categorySelectionIndex];\n\t\tif (urlParameter) {\n\t\t\turl = urlParameter;\n\t\t} else {\n\t\t\turl = categorySelectionData.Url;\n\t\t}\n\t\tvar parameterIndex = 1;\n\t\tfor (var categorySelectionDataKey in categorySelectionData) {\n\t\t\tvar categorySelectionDataValue = categorySelectionData[categorySelectionDataKey];\n\t\t\tif (urlParameter && categorySelectionDataKey == 'cgid') {\n\t\t\t\turl = util.appendParamToURL(url, 'cgid', categorySelectionDataValue);\n\t\t\t} else if (categorySelectionDataKey != 'Text' && categorySelectionDataKey != 'Url' && categorySelectionDataKey != 'cgid') {\n\t\t\t\turl = util.appendParamToURL(url, 'prefn' + parameterIndex, categorySelectionDataKey);\n\t\t\t\turl = util.appendParamToURL(url, 'prefv' + parameterIndex, categorySelectionDataValue);\n\t\t\t\tparameterIndex++;\n\t\t\t}\n\t\t}\n\n\t\tfor (var stepIndexInner in options.Configuration.Steps) {\n\t\t\tif (stepIndexInner <= dataBuffer.step) {\n\t\t\t\tvar stepInner = options.Configuration.Steps[stepIndexInner];\n\t\t\t\tfor (var sectionIndexInner in stepInner.Sections) {\n\t\t\t\t\tvar sectionInner = stepInner.Sections[sectionIndexInner];\n\t\t\t\t\tif (sectionInner.Refinement && sectionInner.Refinement != 'width') {\n\t\t\t\t\t\tvar refinementValues;\n\t\t\t\t\t\tif (dataBuffer.stepData && dataBuffer.stepData[stepIndexInner] && dataBuffer.stepData[stepIndexInner][sectionIndexInner]) {\n\t\t\t\t\t\t\trefinementValues = dataBuffer.stepData[stepIndexInner][sectionIndexInner];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trefinementValues = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (sectionInner.Refinement == 'size') {\n\t\t\t\t\t\t\tvar widthSectionIndex = parseInt(sectionIndexInner, 10) + 1;\n\t\t\t\t\t\t\tvar selectedWidths = dataBuffer.stepData[stepIndexInner][widthSectionIndex];\n\t\t\t\t\t\t\tvar isDatabufferWidths = false;\n\t\t\t\t\t\t\tif (!selectedWidths || !selectedWidths.length) {\n\t\t\t\t\t\t\t\tselectedWidths = dataBuffer.widths;\n\t\t\t\t\t\t\t\tisDatabufferWidths = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar isDatabufferLengths = false;\n\t\t\t\t\t\t\tif (!refinementValues || !refinementValues.length) {\n\t\t\t\t\t\t\t\trefinementValues = dataBuffer.lengths;\n\t\t\t\t\t\t\t\tisDatabufferLengths = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar selectedSizes = [];\n\t\t\t\t\t\t\tif (!isDatabufferWidths || !isDatabufferLengths) {\n\t\t\t\t\t\t\t\tfor (var refinementIndex in refinementValues) {\n\t\t\t\t\t\t\t\t\tvar selectedLength = refinementValues[refinementIndex];\n\t\t\t\t\t\t\t\t\tfor (var widthIndex in selectedWidths) {\n\t\t\t\t\t\t\t\t\t\tvar selectedWidth = selectedWidths[widthIndex];\n\t\t\t\t\t\t\t\t\t\tvar selectedSize = selectedLength + ' ' + selectedWidth;\n\t\t\t\t\t\t\t\t\t\tif (selectedSizes.indexOf(selectedSize) < 0) {\n\t\t\t\t\t\t\t\t\t\t\tselectedSizes[selectedSizes.length] = selectedSize;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trefinementValues = selectedSizes;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (refinementValues && refinementValues.length > 0) {\n\t\t\t\t\t\t\tif (sectionInner.Refinement == 'Price') {\n\t\t\t\t\t\t\t\tif (dataBuffer.Thresholds && dataBuffer.Thresholds[sectionInner.Refinement] && dataBuffer.Thresholds[sectionInner.Refinement][refinementValues]) {\n\t\t\t\t\t\t\t\t\tvar threshold = dataBuffer.Thresholds[sectionInner.Refinement][refinementValues[0]];\n\t\t\t\t\t\t\t\t\turl = util.appendParamToURL(url, 'pmin', threshold.valueFrom);\n\t\t\t\t\t\t\t\t\turl = util.appendParamToURL(url, 'pmax', threshold.valueTo);\t\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefn' + parameterIndex, sectionInner.Refinement);\n\t\t\t\t\t\t\t\turl = util.appendParamToURL(url, 'prefv' + parameterIndex, refinementValues.join('|'));\n\t\t\t\t\t\t\t\tparameterIndex++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (includeAdditionalData) {\n\t\t\turl = util.appendParamToURL(url, 'displayvalues', 'Price');\n\t\t\turl = util.appendParamToURL(url, 'thresholds', 'Price');\n\t\t}\n\t}\n\n\treturn url;\n}\n\nfunction getRefinementCountsForSection(sectionIndex, section) {\n\tvar promise = new Promise(function(resolve, reject) {\n\t\t$.ajax({\n\t\t\ttype: 'get',\n\t\t\turl: buildUrl(Urls.getRefinementCounts, true),\n\t\t\tsuccess: function(data) {\n\t\t\t\tdataBuffer = $.extend(dataBuffer, data);\n\n\t\t\t\tvar payload = {\n\t\t\t\t\tSectionIndex: sectionIndex,\n\t\t\t\t\tSection: section\n\t\t\t\t};\n\t\t\t\tif (section && section.Refinement) {\n\t\t\t\t\tpayload.Refinements = data.Refinements[section.Refinement];\n\t\t\t\t}\n\t\t\t\tresolve(payload);\n\t\t\t}\n\t\t});\n\t});\n\n\treturn promise;\n}\n\nfunction sendDataLayer() {\n\tGoogleTagManagerClient.PushDataLayerForEvent('bootfinderquiz', {\n\t\tstep: dataBuffer.step,\n\t\tstepData: JSON.parse(JSON.stringify(dataBuffer.stepData))\n\t}, null, 'GoogleAnalytics4');\n}","'use strict';\n\nvar quantityStepper = require('../quantityStepper');\nvar account = require('./account');\nvar ApplePay = require('./checkout/ApplePay');\nvar bonusProductsView = require('../bonus-products-view');\nvar quickview = require('../quickview');\nvar cartStoreInventory = require('../storeinventory/cart');\nvar ajax = require('../ajax');\nvar util = require('../util');\nvar formPrepare = require('./checkout/formPrepare');\nvar page = require('../page');\nvar tooltip = require('../tooltip');\nvar TPromise = require('promise');\nvar CheckoutConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants');\nvar DataLayerConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/DataLayerConstants');\nvar GoogleTagManagerClient = require('../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar PaymentMethodConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar RequestHelper = require('../../../../app_storefront_core/cartridge/js/helpers/RequestHelper');\n\nvar isCartPage = false;\nvar dataBuffer = {};\nvar options;\n\n/**\n * @private\n * @function\n * @description Binds events to the cart page (edit item's details, bonus item's actions, coupon code entry)\n */ \nfunction initializeEvents() {\t\n    $(document).off('click', '#cart-table .item-edit-details a').on('click', '#cart-table .item-edit-details a', function (e) {\n        e.preventDefault();\n        \n        quickview.show({\n            url: e.target.href,\n            source: 'cart'\n        });\n    });\n    \n    $(document).off('click', '#cart-table .bonus-item-actions a, #cart-table .item-details .bonusproducts a').on('click', '#cart-table .bonus-item-actions a, #cart-table .item-details .bonusproducts a', function (e) {\n        e.preventDefault();\n        \n        bonusProductsView.show(this.href);\n    });\n    \n    $(document).off('keydown', 'form input[name$=\"_couponCode\"]').on('keydown', 'form input[name$=\"_couponCode\"]', function (e) {   \t\n    \tif (e.which === SiteConstants.KeyCodes.Enter) {\n    \t\te.preventDefault();\n    \t\t\n    \t\t$('.error.coupon-error').remove();\n    \t\tif ($(document.activeElement).val().length === 0 || e.which === SiteConstants.KeyCodes.Enter && $(this).val().length === 0) {\n\t\t\t\t$('<span/>', {\"class\":\"error coupon-error\", text : Resources.COUPON_ADD_ERROR}).insertAfter('.cart-coupon-code .pcode-coupon');\n\t\t\t\t\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\t $('button[name$=\"addCoupon\"]').trigger('click');\n\t\t\t}\n    \t}   \t \n    });\n\n    $(document).off('click', 'button[name$=\"deleteProduct\"]').on('click', 'button[name$=\"deleteProduct\"]', function (e) {\n    \te.preventDefault();\n    \t\n    \tupdateCart($(this).attr('name'));\n    });\n     \n    $(document).off('click', 'button[name$=\"addCoupon\"]').on('click', 'button[name$=\"addCoupon\"]', function (e) {\n\t   \te.preventDefault();\n\t   \t\n\t   \t$('.error.coupon-error').text('');\n\t   \tvar $form = $('form#cart-items-form');\n\t\tvar name = $(this).attr('name');\n\t\t\n\t\t(function() {\n\t\t\treturn TPromise.resolve($.ajax({\n\t            type: 'POST',\n\t            url: util.ajaxUrl(Urls.onePageSubmit),\n\t            data: $form.serialize() + '&' + name + '=' + name + '&respType=json'\n\t        }))\n\t\t}()).then(function (response) {\n\t\t\tif (response.success && response.success !== CheckoutConstants.ResponseCodes.AlreadyInBasket) {\t\t\t\t\n\t\t\t\tvar couponCode = $('.pcode-coupon input[name*=\"_couponCode\"]').val();\n\n\t\t\t\tvar dataObject = {\n\t\t\t\t\tcreative_name: couponCode,\n\t\t\t\t\tcreative_slot: 'couponcode',\n\t\t\t\t\tpromotion_id: response.Promotion && response.Promotion.ID ? response.Promotion.ID : '',\n\t\t\t\t\tpromotion_name: response.Promotion && response.Promotion.Name ? response.Promotion.Name : ''\n\t\t\t\t}\n\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('SelectPromotion', dataObject);\n\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t} else {1\n\t\t\t\tvar message = response.success == CheckoutConstants.ResponseCodes.AlreadyInBasket ? Resources.COUPON_ADD_ERROR_DUP : Resources.COUPON_ADD_ERROR;\n\t\t\t\t$('<span/>', {'class': 'error coupon-error', 'text': message}).insertAfter('.cart-coupon-code .pcode-coupon');\n\t\t\t}\n\t    }.bind(this));\n\t});\n\n    $(document).off('click', 'button[name$=\"deleteCoupon\"]').on('click', 'button[name$=\"deleteCoupon\"]', function (e) {\n    \te.preventDefault();\n    \t\n\t\tvar name = $(this).attr('name');\n\t\t(function(){\n\t\t\treturn TPromise.resolve($.ajax({\n\t            type: 'POST',\n\t            url: util.ajaxUrl(Urls.onePageSubmit),\n\t            data: $('form#cart-items-form').serialize() + '&' + name + '=' + name + '&respType=json'\n\t        }))\n\t\t}()).then(function (response) {\n\t\t\t$(document).trigger('Cart.Update');\n\t    }.bind(this));\n    });\n    \n    $(document).off('refresh-required').on('refresh-required', function(){\n    \tif ($('form#cart-items-form input[name$=\"_quantity\"]').length > 0) {\n            setTimeout( function(){ \n                $('form#cart-items-form input[name$=\"_quantity\"]:first').trigger('focus').trigger('blur');\n            }, 300);\n    \t}\n    });\n\n    $(document).on('focus', 'input[name^=\"dwfrm_guestcheckout_username_\"]', function () {\n\t\t$(this).removeClass('error');\n\t\t$('#dwfrm_guestcheckout span.error').remove();\n    });\n    \n    $(document).off('keydown', 'form input[name^=\"dwfrm_guestcheckout_username_\"]').on('keydown', 'input[name^=\"dwfrm_guestcheckout_username_\"]', function (e) {   \t\n    \tif (e.which === SiteConstants.KeyCodes.Enter) {\t\t\n    \t\te.preventDefault();\n    \t\t$('#dwfrm_guestcheckout span.error').remove();\n    \t\t\n    \t\tvar $form = $('form.guest-checkout');\n    \t\t$form.validate().form();\n    \t\t\n    \t\tvar email = $(document.activeElement).val();\n    \t\tvar isEmailValid = validateEmail(email);\n    \t\t\n    \t\tif ($form.valid() && isEmailValid && $('#dwfrm_guestcheckout span.error').length < 1 ) {\n    \t\t\trenderGuestCheckout(email)\n    \t\t} else {\n    \t\t\tif ($('input[name^=\"dwfrm_guestcheckout_username_\"].error').length == 0) {\n    \t\t\t\tinvalidateGuestCheckout();\n    \t\t\t}\n    \t\t}\n    \t}   \t \n    });\n    \n    $(document).off('click', 'button#guestCheckout').on('click', 'button#guestCheckout', function (e) {\n    \te.preventDefault();\n\t\t$('#dwfrm_guestcheckout span.error').remove();\n\t\t\n\t\tvar $form = $('form.guest-checkout');\n\t\t$form.validate().form();\n\t\t\n\t\tvar email = $('input[name^=\"dwfrm_guestcheckout_username_\"]').val();\n\t\tif ($('input[name^=\"dwfrm_guestcheckout_username_\"].valid').length > 0) {\n\t\t\tvar email = $('input[name^=\"dwfrm_guestcheckout_username_\"].valid').val();\n\t\t}\n\t\t\n\t\tvar isEmailValid = validateEmail(email);\n    \t\n\t\tif ($form.valid() && isEmailValid && $('#dwfrm_guestcheckout span.error').length < 1 ) {\t\t\t\n\t\t\trenderGuestCheckout(email);\n\t\t} else {\n\t\t\tif ($('input[name^=\"dwfrm_guestcheckout_username_\"].error').length == 0) {\n\t\t\t\tinvalidateGuestCheckout();\n\t\t\t}\n\t\t}\n    });\n   \n\t$(document).off('click', '.order-total-payments [payment-method] .remove').on('click', '.order-total-payments [payment-method] .remove', function (e) {\n\t\tvar paymentInstrumentUUID = $(e.currentTarget).closest('[payment-method').attr('uuid');\n\t\n\t\tif (paymentInstrumentUUID) {\n\t\t\tvar requestPayload = {\n\t\t\t\tUUID: paymentInstrumentUUID\n\t\t\t}\n\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.removePaymentInstrument,\n\t\t\t\ttype: 'POST',\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify(requestPayload),\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tupdateCart('dwfrm_cart_updateCart');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n    \n    $(document).on('Cart.Update', function (event, data) {\n    \tupdateCart('dwfrm_cart_updateCart', data);\n    });\n}\n\nfunction validateEmail(email) {\n\tvar isEmailValid = true;\n\t\n\tif (email.length == 0){\n\t\tisEmailValid = true;\n\t}\n\t\n\tvar regexEmail = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$/;\n\tif (email.length > 0 && email.match(regexEmail) == null) {\n\t\tisEmailValid = false;\n\t\tinvalidateGuestCheckout();\n\t}\n\t\n\treturn isEmailValid;\n}\n\nfunction invalidateGuestCheckout() {\n\t$('input[name^=\"dwfrm_guestcheckout_username_\"]').removeClass('valid').addClass('error');\n\t$('.guest-checkout .field-wrapper').append('<span class=\"error custom-guestcheckout-error\" style=\"display:block !important;\">' + Resources.VALIDATE_EMAIL + '</span>');\n}\n\nfunction renderGuestCheckout(email) {\n\t\n\tif(email.length > 0){\n\t\tvar optIn = false;\n\t\t\n\t\tif(SitePreferences.CORDIAL_ENABLED){\n\t\t\tvar signupEvent = '';\n\t\t\t\n\t\t\tvar auth_data = {\n\t\t\t\temail: email\n\t\t\t}\n\t\t\tvar contact_data = {\n\t\t\t\t'channels': {\n\t\t\t\t\t'email': {\n\t\t\t\t\t\t'address': email,\n\t\t\t\t\t\t'subscribeStatus': 'none'\n\t\t\t\t\t}\n\t\t\t\t},\t\t\t\t    \n\t\t\t\t'workflow_checkout_abandon': true\n\t\t\t};\n\t\t\t\n\t\t\tvar guestProperties = {\n\t\t\t\t'email': email,\n\t\t\t\t'workflow_checkout_abandon': true\n\t\t\t};\n\t\t\t\n\t\t\tif ($('#guest_checkout_optin').prop(\"checked\")) {\n\t\t\t\tvar auth_data = {\n\t\t\t\t\temail: email\n\t\t\t\t}\n\t\t\t\tvar contact_data = {\n\t\t\t\t\t'channels': {\n\t\t\t\t\t\t'email': {\n\t\t\t\t\t\t\t'address': email,\n\t\t\t\t\t\t\t'subscribeStatus': 'subscribed'\t\t\t\t            \n\t\t\t\t\t\t}\n\t\t\t\t\t},\t\t\t\t    \n\t\t\t\t\t'signup_source': 'checkout',\n\t\t\t\t\t'welcome_signup': true,\n\t\t\t\t\t'workflow_checkout_abandon': true\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tvar properties = {\n\t\t\t\t\t'signup_source': 'checkout',\n\t\t\t\t\t'welcome_signup': true,\n\t\t\t\t\t'workflow_checkout_abandon': true\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tvar signupEvent = ['event', 'email_signup', properties];\n\t\t\t}\n\t\t\t\n\t\t\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t\t['event', 'guest_checkout', guestProperties],\n\t\t\t\t\t\tsignupEvent\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t}).catch();\n\t\t}\n\t} else {\n\t\tvar optIn = $('#guest_checkout_optin').prop(\"checked\");\n\t}\n\t\n\t$.ajax({\n\t\turl: Urls.setEmailOnCart,\n\t\ttype: \"get\",\n\t\tdata: {email: email},\n\t\tsuccess: function (response) {\n\t\t\tvar data = JSON.parse(response);\n\t\t\t\t\n\t\t\tif (data.status == 'success') {\n\t\t\t\twindow.location.href = Urls.onePage + ((window.innerWidth < SiteConstants.Responsive.Widths.Mobile) ? '#addressinfo' : '');\n\t\t\t}\n\t\t},\n\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\tconsole.log(textStatus, errorThrown);\n\t\t}\n\t});\n\t\n\t$.ajax({\n\t\turl: Urls.setEmailOptin,\n\t\ttype: \"get\",\n\t\tdata: {optIn: optIn},\n\t\tsuccess: function (response) {\n\t\t\tvar data = JSON.parse(response);\n\t\t\t\t\n\t\t\tif (data.status == 'success') {\n\t\t\t\twindow.location.href = Urls.onePage + ((window.innerWidth < SiteConstants.Responsive.Widths.Mobile) ? '#addressinfo' : '');\n\t\t\t}\n\t\t},\n\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\tconsole.log(textStatus, errorThrown);\n\t\t}\n\t});\n}\n\nfunction triggerReactWebviewEvent() {\n\tif ('ReactNativeWebView' in window) {\n\t\twindow.ReactNativeWebView.postMessage(JSON.stringify({ action: 'cart-refresh' }));\n\t}\n}\n\nvar updateCartBuffer;\nvar updateCartXmlHttpRequestBuffer;\nfunction updateCart(triggerElementName, updateCartOptions, isCartPage) {\n\tif (updateCartXmlHttpRequestBuffer) {\n\t\tfor (var updateCartXmlHttpRequestKey in updateCartXmlHttpRequestBuffer) {\n\t\t\tvar updateCartXmlHttpRequest = updateCartXmlHttpRequestBuffer[updateCartXmlHttpRequestKey];\n\t\t\t\n\t\t\tif (updateCartXmlHttpRequest.readyState !== 4) { \n\t\t\t\tupdateCartXmlHttpRequest.abort();\n\t\t\t}\n\t\t}\n\t}\n\tupdateCartXmlHttpRequestBuffer = [];\n\tupdateCartBuffer = [];\n\n\tgetCartHtml(triggerElementName, updateCartOptions, isCartPage);\n\tif (!isCartPage) {\n\t\tgetOrderSummaryCalloutHtml(triggerElementName, updateCartOptions, isCartPage);\n\t}\n}\n\nfunction getCartHtml(triggerElementName, updateCartOptions, isCartPage) {\n    var form = $(\".update-cart-button\").parents('form');\n    updateCartBuffer['Cart'] = null;\n\n\tif (form.attr('action')) {\n\t\tif (isCartPage == undefined) {\n\t\t\tisCartPage = $('.pt_cart').length > 0;\n\t\t}\n\n\t\tupdateCartXmlHttpRequestBuffer['getCartHtml'] = $.ajax({\n\t        url : form.attr('action'),\n\t\t    type : \"POST\",\n\t        data : triggerElementName + '=' + triggerElementName + '&selectedPaymentMethod=' + $('input[name*=\"_selectedPaymentMethodID\"]').val() + '&format=ajax',\n\t\t    success : function (data) {\n\t\t    \tupdateCartBuffer['Cart'] = data;\n\t\t\t\tgetCartData(triggerElementName, updateCartOptions, isCartPage);\n\t\t\t\tupdateCartRender(triggerElementName, updateCartOptions, isCartPage);\n\t\t    }\n\t\t});\n\t}\n}\n\nfunction getOrderSummaryCalloutHtml(triggerElementName, updateCartOptions, isCartPage) {\n    updateCartBuffer['OrderSummaryCallout'] = null;\n\n\tupdateCartXmlHttpRequestBuffer['getOrderSummaryCalloutHtml'] = $.ajax({\n\t\turl: Urls.getOrderSummaryCalloutContentSlot,\n\t\tdataType: 'html',\n\t\tsuccess: function (data) {\n\t\t\tupdateCartBuffer['OrderSummaryCallout'] = data;\n\t\t\tupdateCartRender(triggerElementName, updateCartOptions, isCartPage);\n\t\t}\n\t});\n}\n\nfunction getCartData(triggerElementName, updateCartOptions, isCartPage) {\n\tupdateCartBuffer['CartData'] = null;\n\n\tupdateCartXmlHttpRequestBuffer['getCartData'] = $.ajax({\n\t    url : Urls.getCartData,\n\t\ttype : \"POST\",\n\t\tdata: {\n\t\t\tisCart: isCartPage\n\t\t},\n\t    success : function (data) {\n\t    \t$('[has-local-delivery-shipment]').attr('has-local-delivery-shipment', data.HasLocalDeliveryShipment || false);\n\t    \t$('[has-physical-shipment]').attr('has-physical-shipment', data.HasPhysicalShipment || false);\n\t\t\t$('[has-warehouse-shipment]').attr('has-warehouse-shipment', data.HasWarehouseShipment || false);\n\t\t\t$('[has-warehouse-shipment]').attr('has-shipping-methods', data.ShippingMethods ? data.ShippingMethods.join(' ') : false);\n\t    \t$('[has-gift-cards]').attr('has-gift-cards', data.HasGiftCards || false);\n\t    \t$('[has-gift-cards-only]').attr('has-gift-cards-only', data.HasGiftCardsOnly || false);\n\t\t\t$('[has-store-pickup-shipment]').attr('has-store-pickup-shipment', (data.Bopis && data.Bopis.HasStorePickupShipment) || false);\n\t\t\t$('[has-store-pickup-shipment-only]').attr('has-store-pickup-shipment-only', (data.Bopis && data.Bopis.HasStorePickupShipmentOnly) || false);\n\n\t\t\tif (data.Bopis && data.Bopis.HasStorePickupShipmentOnly) {\n\t\t\t\t$('#isShippingAddressSameAsBillingAddress').prop('checked', true);\n\t\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t\t\t}\n\n\t    \t$(document).trigger('CartData.Update', data);\n\n\t    \tupdateCartBuffer['CartData'] = data;\n\t    \tif (data.Bopis) {\n\t    \t\tupdateCartBuffer['Bopis'] = data.Bopis;\n\t    \t}\n\t    \t\n\t    \tif (!data.IsGlobaleValidOrInactive) {\n\t    \t\t$('.section-checkout').addClass('global-e-validation-error');\n\t    \t\t$('.section-checkout').find('.cart-errors').addClass('active');\n\t    \t} else {\n\t    \t\t$('.section-checkout').removeClass('global-e-validation-error');\n\t    \t\t$('.section-checkout').find('.cart-errors').removeClass('active');\n\t    \t}\n\n\t    \tif ((!data.OrderTotal || !data.OrderTotal.balanceAvailable) || (data.ShippingRestrictions && data.ShippingRestrictions.Status == 'shippingRestrictionsError')) {\n\t\t\t\tif (!isCartPage) {\n\t\t\t\t\t$('.payment-methods-section').hide();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (isCartPage) {\n\t\t\t\t\t$('.guest-checkout .error-form').remove();\n\t\t\t\t} else {\n\t\t\t\t\t$('.payment-methods-section').show();\n\t\t\t\t}\n\t\t\t}\n\t    \t\n\t    \thandleOrderTotal(triggerElementName, updateCartOptions, isCartPage);\n\t    }\n\t});\n}\n\nfunction handleOrderTotal(triggerElementName, updateCartOptions, isCartPage) {\n\tupdateCartBuffer['PaymentInstrumentHtml'] = null;\n\tvar removeAction = '<a class=\"remove\">Remove</a>';\n\tvar rewardsProgram = '';\n\tif (pageContext.site == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\trewardsProgram = 'Club CO';\n\t}\n\tif (pageContext.site == SiteConstants.SiteIds.SheplersUS) {\n\t\trewardsProgram = 'Sheplers';\n\t}\n\t\n\tif (updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length > 0) {\n\t\tupdateCartBuffer['PaymentInstrumentHtml'] = '';\n\t\n\t\tfor (var paymentInstrumentKey in updateCartBuffer['CartData'].OrderTotal.paymentInstruments) {\n\t\t\tvar paymentInstrument = updateCartBuffer['CartData'].OrderTotal.paymentInstruments[paymentInstrumentKey];\n\t\t\tvar paymentInstrumentUUIDAttribute = 'uuid=\"' + paymentInstrument.UUID + '\"';\n\t\t\t\n\t\t\tswitch (paymentInstrument.paymentMethod.Id) {\n\t\t\t\tcase PaymentMethodConstants.RewardsCredit:\n\t\t    \t\tupdateCartBuffer['PaymentInstrumentHtml'] += '<div ' + paymentInstrumentUUIDAttribute + ' payment-method=\"' + paymentInstrument.paymentMethod.Id + '\" allow-remove=\"' + paymentInstrument.allowRemove + '\">' +\n\t\t    \t\t\t'<span class=\"label\"><span class=\"name\">B Rewarded</span>&nbsp;<span class=\"number\">Reward</span></span>' +\n\t\t    \t\t\t'<span class=\"value\">' + paymentInstrument.amountDisplay + '</span>' +\n\t\t    \t\t'</div>';\n\t\t    \tbreak;\n\t\t    \t\n\t\t\t\tcase PaymentMethodConstants.LoyaltyCredit:\n\t\t    \t\tupdateCartBuffer['PaymentInstrumentHtml'] += '<div ' + paymentInstrumentUUIDAttribute + ' payment-method=\"' + paymentInstrument.paymentMethod.Id + '\" allow-remove=\"' + paymentInstrument.allowRemove + '\">' +\n\t\t    \t\t\t'<span class=\"label\"><span class=\"name\">'+rewardsProgram+'</span>&nbsp;<span class=\"number\">Reward</span></span>' +\n\t\t    \t\t\t'<span class=\"value\">' + paymentInstrument.amountDisplay + '</span>' +\n\t\t    \t\t'</div>';\n\t\t    \tbreak;\n\t\t\t\n\t\t\t\tdefault:\n\t\t    \t\tupdateCartBuffer['PaymentInstrumentHtml'] += '<div ' + paymentInstrumentUUIDAttribute + ' payment-method=\"' + paymentInstrument.paymentMethod.Id + '\" allow-remove=\"' + paymentInstrument.allowRemove + '\">' +\n\t\t    \t\t\t'<span class=\"label\"><span class=\"name\">' + paymentInstrument.paymentMethod.Name + '</span>&nbsp;<span class=\"number\">' + paymentInstrument.number + '</span>' + removeAction + '</span>' +\n\t\t    \t\t\t'<span class=\"value\">' + paymentInstrument.amountDisplay + '</span>' +\n\t\t    \t\t'</div>';\n\t\t    \tbreak;\n\t\t    }\n\t\t}\n\t} else {\n\t\t$(document).trigger('GiftCard.Clear');\n\t\t$(document).trigger('RewardsCredit.Clear');\n\t\t$(document).trigger('LoyaltyCredit.Clear');\n\t}\n\t\n\tif (updateCartBuffer['CartData'].OrderTotal.balance < updateCartBuffer['CartData'].OrderTotal.total) {\n\t\tupdateCartBuffer['BalanceDueHtml'] = '<span class=\"label\">Balance Due</span>' +\n\t\t\t'<span class=\"value\">' + updateCartBuffer['CartData'].OrderTotal.balanceDisplay + '</span>';\n\t}\n\t\n\tupdateCartRender(triggerElementName, updateCartOptions, isCartPage);\n}\n\nfunction updateCartRender(triggerElementName, updateCartOptions, isCartPage) {\n\tif (updateCartBuffer['Cart'] && (isCartPage || (updateCartBuffer['OrderSummaryCallout'] && updateCartBuffer['CartData']))) {\n\t\tvar $basketContainerHtml = $(updateCartBuffer['Cart']);\n\t\n\t\tif (updateCartBuffer['CartData'] && updateCartBuffer['CartData'].OrderTotal) {\n\t\t\t$basketContainerHtml.find('.order-total-price .value').html(updateCartBuffer['CartData'].OrderTotal.totalDisplay);\n\t    \t$('.payment-section .order-total-price .value').html(updateCartBuffer['CartData'].OrderTotal.totalDisplay);\n\t\t\n\t\t\tif (updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length > 0) {\n\t\t\t\t$basketContainerHtml.find('.order-totals-table').attr('payments-applied', updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length);\n\t    \t\t$('.payment-section').attr('payments-applied', updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length);\n\t    \t} else {\n\t    \t\t$basketContainerHtml.find('.order-totals-table').removeAttr('payments-applied');\n\t    \t\t$('.payment-section').removeAttr('payments-applied');\n\t    \t}\n\t\t\n\t\t\t$basketContainerHtml.find('.order-totals-table').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t    \t$('body').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t\t\t$('.payment-section').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t\t\n\t\t\tif (updateCartBuffer['CartData'].OrderTotal.balance > 0) {\n\t\t\t\t$('.payment-method-options').show();\n\t\t\t\t$('.payment-section-footer[data-method=\"PayPal\"] button').hide();\n\t\t\t} else {\n\t\t\t\t$('.payment-method-options').hide();\n\t\t\t\t$('.payment-section-footer[data-method=\"PayPal\"] button').show();\n\t\t\t}\n\t\t\n\t    \tif (updateCartBuffer['BalanceDueHtml']) {\t\n\t    \t\t$basketContainerHtml.find('.order-balance-due').html(updateCartBuffer['BalanceDueHtml']);\n\t    \t\t$('.payment-section .order-balance-due').html(updateCartBuffer['BalanceDueHtml']);    \t\t\n\t    \t} else {\n\t    \t\t$('.payment-section .order-balance-due').html('');\n\t    \t}\n\t    \t\n\t    \tif (updateCartBuffer['PaymentInstrumentHtml']) {\n\t    \t\t$basketContainerHtml.find('.order-total-payments').html(updateCartBuffer['PaymentInstrumentHtml']);\n\t    \t\t$('.payment-section .order-total-payments').html(updateCartBuffer['PaymentInstrumentHtml']);\n\t    \t} else {\n\t    \t\t$('.payment-section .order-total-payments').html('');\n\t    \t}\n\t\t}\n\n\t\t$('.basket-container').html($basketContainerHtml);\n\t\t\n\t\tif (updateCartBuffer['CartData']) {\n\t\t\tvar orderTotalForAffirm = updateCartBuffer['CartData'].OrderTotal.balance;\n\t\t\tif (!orderTotalForAffirm && updateCartBuffer['CartData'].OrderTotal.adjustedMerchandizeTotalPrice) {\n\t\t\t\torderTotalForAffirm = updateCartBuffer['CartData'].OrderTotal.adjustedMerchandizeTotalPrice;\n\t\t\t}\n\t\t\tif ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui && orderTotalForAffirm >= updateCartBuffer['CartData'].AffirmMinimumOrderTotal) {\n\t\t\t\t$('.affirm-product-modal').attr('data-amount', orderTotalForAffirm * 100);\n\t\t\t\taffirm.ui.refresh();\n\t\t\t} else {\n\t\t\t\t$('.affirm-product-modal').attr('data-amount', 5000);\n\t\t\t}\n\t\t}\n\n\t\tif ($('.basket-container').find('.product-availability-list .not-available').length > 0) {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').attr('disabled', 'disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t\t$('#submitOPCPayment').after('<div id=\"errorBoxOPC\" class=\"p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>' + Resources.Validation.Messages.Products.Availability + ':</b> ' + Resources.Validation.Messages.Products.AvailabilityExceeded + '</div>');\n\t\t} else if (updateCartBuffer['Bopis'] && updateCartBuffer['Bopis'].NumberOfBopisStoresInCart > updateCartBuffer['Bopis'].MaximumNumberOfBopisStoresInCart) {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').attr('disabled', 'disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t\t$('#submitOPCPayment').after('<div id=\"errorBoxOPC\" class=\"p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>' + Resources.Validation.Messages.General.CartLimit + ':</b> ' + Resources.Validation.Messages.Bopis.MaximumStoresExceeded + '</div>');\n\t\t} else {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').removeAttr('disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t}\n\t\t\n\t\tif (updateCartBuffer['OrderSummaryCallout']) {\t\n\t\t\t$('.callout-ordersummary').html(updateCartBuffer['OrderSummaryCallout']);\n\t\t}\n\t\t\n\t    if (SitePreferences.STORE_PICKUP) {\n\t        cartStoreInventory.init();\n\t    }\n\t    \n\t    account.initCartLogin();\n\t    checkCheckoutAccessibility();\n\n\t\tvar $cartMiniCartButton = $('.banner-cart-holder .btn-minicart');\n\t    if ($cartMiniCartButton.length > 0) {\n\t\t\t$.ajax({url : Urls.cartMiniCart, data : {desktop: '1'}, dataType: 'html', success : function(data) {\n\t            $('.banner-cart-holder').html(data);\n\t        }});\n\t\t\t\n\t    \t$.ajax({url : Urls.cartMiniCart, dataType: 'html', success : function(data) {\n\t    \t\tvar parentMiniCart = $(\".top-banner-inner-links #mini-cart\");\n\t    \t\t\n\t    \t\tif (parentMiniCart.length > 0) {\n\t    \t\t\tparentMiniCart.html(data);\n\t    \t\t}\n\t        }});\n\t\t}\n\t    \n        $.ajax({url: Urls.cartItemQuantity, data: {desktop: '1'}, dataType: 'html', success: function (data) {\n        \t$('.confirmation-message .item-count').html(data);\n\t        \n\t        var quantity = parseInt($('.confirmation-message .item-count').find('span').text(), 10);\n\t        if (!quantity) {\n\t            $('.checkout-buttons.mobile-only').hide();\t            \n\t\t\t}\n\t\t}});\n\t\t\n\t    \n\t    if (triggerElementName.indexOf('deleteProduct') > -1) {\n\t    \t$(document).trigger('refresh-required');\n\t    }\n\n\t\tif (!options || !options.EventTriggers || options.EventTriggers['update-summary']) {\n\t\t\t$(document).trigger('update-summary');\n\t\t}\n\t\t\n\t\tif (!options || !options.EventTriggers || options.EventTriggers['update-shipping']) {\n\t\t\t$(document).trigger('update-shipping');\n\t\t}\n\t    \n\t    $('[minimum-cart-total], [maximum-cart-total]').each(function(index, element) {\n\t    \tvar $this = $(this);\n\t    \tvar paymentMethodCartTotalMinimum = parseFloat($this.attr('minimum-cart-total'));\n\t    \tvar paymentMethodCartTotalMaximum = parseFloat($this.attr('maximum-cart-total'));\n\t    \n\t    \tvar isCartTotalMinimumValid = false;\n\t    \tif (isNaN(paymentMethodCartTotalMinimum) || updateCartBuffer['CartData'].OrderTotal.balance >= paymentMethodCartTotalMinimum) {\n\t    \t\tisCartTotalMinimumValid = true;\n\t    \t}\n\t    \t\n\t    \tvar isCartTotalMaximumValid = false;\n\t    \tif (isNaN(paymentMethodCartTotalMaximum) || updateCartBuffer['CartData'].OrderTotal.balance <= paymentMethodCartTotalMaximum) {\n\t    \t\tisCartTotalMaximumValid = true;\n\t    \t}\n\t    \t\n\t    \tif (isCartTotalMinimumValid && isCartTotalMaximumValid) {\n\t    \t\t$this.closest('.payment-method-option').attr('valid-for-balance-due', 'true');\n\t    \t} else {\n\t    \t\t$this.closest('.payment-method-option').attr('valid-for-balance-due', 'false');\n\t    \t}\n\t    });\n\t\t\n\t    if (updateCartBuffer['CartData'] && !updateCartBuffer['CartData'].HasPhysicalShipment && $('.single.shipping-address-type-selector input:checked').val() != SiteConstants.AddressTypes.Customer) {\n\t    \t$('.single.shipping-address-type-selector input[value=\"' + SiteConstants.AddressTypes.Customer + '\"]').click();\n\t    }\n\t\t\n\t\ttooltip.init({\n\t\t\titems: '.shipping-method-tooltip',\n\t\t\ttooltipClass: 'shipping-method-tooltip'\n\t\t}, $('[shipping-method]'));\n\n\t\ttooltip.init({\n\t\t\titems: '.tooltip'\n\t\t});\n\n\t\ttriggerReactWebviewEvent();\n\t\ttriggerSrFocus();\n\t\t$(document).trigger('QuantityStepper.TargetFocus');\n\t    $(document).trigger('Cart.UpdateSuccess');\n\t}\n}\n\nfunction triggerSrFocus() {\n\t$('[role=\"alert\"]:visible').last().focus().addClass('focus-visible-indicator');\n}\n\nfunction checkCheckoutAccessibility() {\n\tif ($('.order-item').length == 0) {\n\t\t$('.section-checkout > div').removeClass('active');\n\t\t$('.billing-address-form, .shipping-address-cont, .shipping-payment-cont').hide();\n\t\t$('.form-checkout.login-element, .section-checkout').addClass('empty-cart');\n\t}\n}\n\n/**\n * @description Make the AJAX request to get customer data\n * @param {Element} form The form element that contains the item quantity and ID data\n * @param {Element} Action name to apply to form\n * @returns {Promise}\n */\nvar updateCustomerDetails = function (form, name) {\n    var $form = $(form);\n\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.onePageLogin),\n        data: $form.serialize() + '&' + name + '=' + name\n    }));\n};\n\n/**\n * @description Make the AJAX request to reset customer password\n * @param {String} registered customer email\n * @returns {Promise}\n */\nvar resetCustomerPassword = function (email) {\n\treturn TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.resetOPCPass),\n        data: 'email='+ email\n    }));\n};\n\n/**\n * @description Make the AJAX request to reset customer password\n * @param {String} error message\n * @param {Element} element to add error after\n * @returns {Void}\n */\nvar showError = function(message, selector){\n\tvar $errorContainer = selector.closest('field-wrapper').next('.error');\n\n\tif (!$errorContainer.prop('defaultText') || $errorContainer.text() != message) {\n\t\tselector.prop('defaultText', $errorContainer.text());\n\t}\n\t\n\t$errorContainer.text(message).show();\n};\n\n/**\n * @description Make the AJAX request to reset customer password\n * @param {String} notification text\n * @param {Element} selector to apply message\n * @param {String} notification type: error or success\n * @returns {Void}\n */\nfunction showNotification(text, selector, msgType) {\n\tvar $selector = $(selector);\n\tif ($selector.length == 0) {\n\t\tvar $form = $('form.opc-login');\n\t\t$selector = $('<span/>', {'class': 'login-notification'}).wrap('<div class=\"formfield clearfix error-box\"><div class=\"form-row required\"><div class=\"field-wrapper\"></div></div></div>');\n\n\t\t$selector.parent().parent().parent().insertBefore('form.opc-login .form-row-button');\n\t\t$selector = $(selector);\n\t}\n\n\t$selector.removeClass('success error').addClass(msgType).text(text);\n};\n\n/**\n * @description Make the AJAX request to reset customer password\n * @param {Element} selector to clear notification type: error or success\n * @returns {Void}\n */\nfunction clearNotification(selector){\n\tif (selector.length) {\n\t\t$('.formfield.error-box').remove();\n\t\tselector.removeClass('success error');\n\t}\n};\n\nexports.updateCart = updateCart;\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\tif (options && options.isCartPage) {\n    \tisCartPage = true;\n    }\n    initializeEvents();\n    if (SitePreferences.STORE_PICKUP) {\n        cartStoreInventory.init();\n    }\n\tApplePay.initialize(options);\n    account.initCartLogin();\n\tquantityStepper.init(updateCart);\n    updateCart('dwfrm_cart_updateCart', null, options.isCartPage);\n};","'use strict';\n\nvar addToCart = require('./product/addToCart');\nvar quantityStepper = require('../quantityStepper');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar _ = require('lodash');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nvar html = {};\nvar options = {};\nvar data = {};\nvar templates = {};\n\nvar video;\nvar stream;\nvar barcodeDetector;\nvar barcodeDetectorInterval;\nvar barcodeScanInputAddProductTimer;\nvar barcodeScanInputFocusInterval;\nvar productSearchInputFocusInterval;\n\nvar $productFinder;\nvar $barcodeScanner;\nvar $barcodeScannerInputContainer;\nvar $barcodeScannerInput;\nvar $barcodeScannerErrorContainer;\nvar $barcodeScannerAddButton;\nvar $barcodeScannerAddButtonText;\nvar $barcodeScannerStartButton;\nvar $barcodeScannerStartButtonText;\nvar $barcodeScannerModal;\nvar $productSearch;\nvar $productSearchInputContainer;\nvar $productSearchInput;\nvar $productSearchErrorContainer;\nvar $productSearchSearchButton;\nvar $productSearchSearchButtonText;\nvar $productSearchResultsContainer;\nvar $productSearchResults;\nvar $productSearchResultsFooter;\nvar $productSearchResultsLoadMore;\n\nfunction initialize(options) {\n\t$productFinder = $('.product-finder');\n\t$barcodeScanner = $productFinder.find('.section.scan');\n\t$barcodeScannerInputContainer = $barcodeScanner.find('.input');\n\t$barcodeScannerInput = $barcodeScannerInputContainer.find('input');\n\t$barcodeScannerErrorContainer = $barcodeScanner.find('.error');\n\t$barcodeScannerAddButton = $barcodeScanner.find('.action.add');\n\t$barcodeScannerAddButtonText = $barcodeScannerAddButton.find('span');\n\t$barcodeScannerStartButton = $barcodeScanner.find('.action.start');\n\t$barcodeScannerStartButtonText = $barcodeScannerStartButton.find('span');\n\t$barcodeScannerModal = $barcodeScanner.find('.modal');\n\t$productSearch = $productFinder.find('.section.search');\n\t$productSearchInputContainer = $productSearch.find('.input');\n\t$productSearchInput = $productSearchInputContainer.find('input');\n\t$productSearchErrorContainer = $productSearch.find('.error');\n\t$productSearchSearchButton = $productSearch.find('.action.search');\n\t$productSearchSearchButtonText = $productSearchSearchButton.find('span');\n\t$productSearchResultsContainer = $productSearch.find('.results-container');\n\t$productSearchResults = $productSearchResultsContainer.find('.results');\n\t$productSearchResultsFooter = $productSearchResultsContainer.find('footer');\n\t$productSearchResultsLoadMore = $productSearchResultsContainer.find('.load-more');\n\n\tif (('BarcodeDetector' in window)) {\n\t\t$barcodeScanner.addClass('barcode-detector');\n\t}\n\n\tdata['ProductSearchPageSize'] = 5;\n\n    templates['variations'] = _.template($('#template-variations').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelector'] = _.template($('#template-variations-selector').html(), TemplateConstants.Lodash.Settings);\n\ttemplates['variationSelectorAttributeGuide'] = _.template($('#template-variations-attribute-guide').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdown'] = _.template($('#template-variations-selector-dropdown').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdownOption'] = _.template($('#template-variations-selector-dropdown-option').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdownOptionSelected'] = _.template($('#template-variations-selector-dropdown-option-selected').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatch'] = _.template($('#template-variations-selector-swatch').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatchOption'] = _.template($('#template-variations-selector-swatch-option').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatchOptionUnselectable'] = _.template($('#template-variations-selector-swatch-option-unselectable').html(), TemplateConstants.Lodash.Settings);\n\n\t// $(document).off('keyup.BarcodeScannerInput').on('keyup.BarcodeScannerInput', '.input', function(event) {\n\t// \tvar $this = $(this);\n\n\t// \t$barcodeScannerErrorContainer.html('');\n\t// \tif (barcodeScanInputAddProductTimer) {\n\t// \t\tclearTimeout(barcodeScanInputAddProductTimer);\n\t// \t}\n\n\t// \tbarcodeScanInputAddProductTimer = setTimeout(function() {\n\t// \t\taddProductWithUpc($this.val());\n\t// \t}, 250);\n\t// });\n\n\t$productFinder.off('click.Add').on('click.Add', '.action.add', function(event) {\n\t\tevent.preventDefault();\n\t\taddProductWithUpc($barcodeScannerInput.val());\n\t});\n\n\t$productFinder.off('click.OptionsToggle').on('click.OptionsToggle', '.action.options', function(event) {\n\t\t$(this).addClass('active');\n\t});\n\n\t$productFinder.off('click.ModeSet').on('click.ModeSet', '.options [set-mode]', function(event) {\n\t\t$barcodeScannerErrorContainer.html('');\n\t\t$productSearchErrorContainer.html('');\n\t\t$('.product-finder').attr('mode', $(this).attr('set-mode'));\n\t\t$('.action.options').removeClass('active');\n\t});\n\n\t$(document).off('click.OptionsClose').on('click.OptionsClose', function(event) {\n\t\tvar $target = $(event.target);\n\t\tif (!$target.hasClass('options') && $target.closest('.options').length == 0) {\n\t\t\t$('.action.options').removeClass('active');\n\t\t}\n\t});\n\n\t$barcodeScanner.off('click.KeyboardToggle').on('click.KeyboardToggle', '.options .keyboard', function(event) {\n\t\tif ($(this).hasClass('active')) {\n\t\t\t$(this).removeClass('active');\n\t\t\t$barcodeScannerInput.attr('inputmode', 'none');\n\t\t} else {\n\t\t\t$(this).addClass('active');\n\t\t\t$barcodeScannerInput.attr('inputmode', $barcodeScannerInput.attr('type'));\n\t\t}\n\t\t$('.action.options').removeClass('active');\n\t});\n\n\t$barcodeScanner.off('click.BarcodeScannerStart').on('click.BarcodeScannerStart', '.action.start', function(event) {\n\t\tif (!('BarcodeDetector' in window)) {\n\t\t\talert('Barcode Detector is not supported by this browser.');\n  \t\t} else {\n\t\t\t$('.section.scan').addClass('active');\n\n\t\t\tif (!barcodeDetector) {\n\t\t\t\tbarcodeDetector = new BarcodeDetector();\n\t\t\t}\n\n\t\t\tvideo = $barcodeScannerModal.find('video')[0];\n\t\t\tvideo.setAttribute('playsinline', '');\n\t\t\tvideo.setAttribute('autoplay', '');\n\t\t\tvideo.setAttribute('muted', '');\n\t\t\tvideo.style.width = '100%';\n\t\t\tvideo.style.height = '100%';\n\n\t\t\tvar constraints = {\n\t\t\t\taudio: false,\n\t\t\t\tvideo: {\n\t\t\t\t\tfacingMode: 'environment'\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tnavigator.mediaDevices.getUserMedia(constraints).then(function success(mediaStream) {\n\t\t\t\tstream = mediaStream;\n\t\t\t\tvideo.srcObject = stream;\n\t\t\t});\n\n\t\t\tvideo.onloadedmetadata = function(event) {\n\t\t\t\tbarcodeDetectorInterval = setInterval(detectBarcode, 500);\n\t\t\t};\n\t\t}\n\t});\n\n\t$(document).off('click.BarcodeScannerStop').on('click.BarcodeScannerStop', '.modal .close', function(event) {\n\t\tcloseBarcodeScanner();\n\t});\n\n\t$(document).off('paste.UPC').on('paste.UPC', function(event) {\n\t\tif (!$barcodeScannerInput.is(\":focus\") && $(event.target).closest('.product-finder').length > 0) {\n\t\t\tgetClipboardValue(event, this, function(upc) {\n\t\t\t\t$barcodeScannerErrorContainer.html('');\n\t\t\t\taddProductWithUpc(upc);\n\t\t\t});\n\t\t}\n\t});\n\n\t$productSearchInput.off('keyup.ProductSearchChange').on('keyup.ProductSearchChange', function(event) {\n\t\tupdateProductSearchAction();\n\t});\n\n\t$productSearch.off('click.ProductSearchStart').on('click.ProductSearchStart', '.action.search', function(event) {\n\t\tevent.preventDefault();\n\t\tvar query = $productSearchInput.val();\n\t\tif (query) {\n\t\t\tif ($productSearchInputContainer.attr('action') == 'search') {\n\t\t\t\t$productSearchResults.html('');\n\t\t\t\t$productSearch.removeClass('active');\n\t\t\t\tdata['ProductSearchPage'] = 1;\n\t\t\t\tsearchProductsWithQuery(query);\n\t\t\t} else {\n\t\t\t\tresetProductSearch();\n\t\t\t}\n\t\t}\n\t});\n\n\t$productSearch.off('click.ProductSearchLoadMore').on('click.ProductSearchLoadMore', '.load-more', function(event) {\n\t\tvar query = $productSearchInput.val();\n\t\tif (query) {\n\t\t\tdata['ProductSearchPage'] += 1;\n\t\t\tsearchProductsWithQuery(query);\n\t\t}\n\t});\n\n\t$productSearch.off('click.ProductSearchProductSelect').on('click.ProductSearchProductSelect', '.grid-tile .product-tile a', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $gridTile = $this.closest('.grid-tile');\n\t\tvar $productTile = $this.closest('.product-tile');\n\t\tif ($gridTile.find('.product-variations').length > 0) {\n\t\t\t$gridTile.find('.product-variations').remove();\n\t\t} else {\n\t\t\tgetStylesForProduct($productTile.data('itemid'));\n\t\t}\n\t});\n\n\t$productSearch.off('change.ProductSearchAttributeSelect').on('change.ProductSearchAttributeSelect', '.grid-tile .product-variations select', function(event) {\n\t\tvar $productTile = $(this).closest('.grid-tile').find('.product-tile');\n\t\tgetStylesForProduct($productTile.data('itemid'));\n\t});\n\n\t$productSearch.off('click.ProductSearchProductAdd').on('click.ProductSearchProductAdd', '.grid-tile .product-variations .btn.add', function(event) {\n\t\tvar $this = $(this);\n\t\tif ($this.attr('pid')) {\n\t\t\taddProductWithProductId($this.attr('pid'), $this);\n\t\t}\n\t});\n\n\t$productSearch.off('click.ProductSearchClose').on('click.ProductSearchClose', '.results-container .close', function(event) {\n\t\t$('body').removeClass('product-search');\n\t});\n\n\tif (!options || options.StoreUIVersion != '2024Redesign') {\n\t\tbarcodeScanInputFocusInterval = setInterval(function() {\n\t\t\tif (!$barcodeScannerInput.is(':visible:focus') && $barcodeScanner.find(':focus').length == 0) {\n\t\t\t\t$barcodeScannerInput.focus();\n\t\t\t}\n\t\t}, 500);\n\t\n\t\tproductSearchInputFocusInterval = setInterval(function() {\n\t\t\tif (!$productSearchInput.is(':visible:focus') && !$productSearch.hasClass('active') && $productSearch.find(':focus').length == 0) {\n\t\t\t\t$productSearchInput.focus();\n\t\t\t}\n\t\t}, 500);\n\n\t\t$(document).off('click.Checkout').on('click.Checkout', '.checkout .btn.btn-checkout', function (event) {\n\t\t\t$(this).loading({\n\t\t\t\tIsLabelShown: false,\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\t\t});\n\n\t\tquantityStepper.init(null, renderCart);\n\t\taddToCart();\n\t}\n}\n\nfunction updateProductSearchAction() {\n\tvar productSearchInputValue = $productSearchInput.val();\n\tif (productSearchInputValue) {\n\t\tproductSearchInputValue = productSearchInputValue.toLowerCase();\n\t}\n\tvar productSearchQueryValue = $productSearchInputContainer.attr('query');\n\tif (productSearchQueryValue) {\n\t\tproductSearchQueryValue = productSearchQueryValue.toLowerCase();\n\t}\n\n\tif (productSearchInputValue && productSearchQueryValue && productSearchInputValue == productSearchQueryValue) {\n\t\t$productSearchInputContainer.attr('action', 'reset');\n\t} else {\n\t\t$productSearchInputContainer.attr('action', 'search');\n\t}\n}\n\nfunction searchProductsWithQuery(query) {\n\t$productSearchErrorContainer.html('');\n\t$productSearchInputContainer.attr('query', query);\n\t$productSearchInputContainer.loading({\n\t\tIsImageShown: false,\n\t\tIsLabelShown: false\n\t});\n\t$productSearchSearchButton.loading({\n\t\tIsLabelShown: false,\n\t\tBackgroundColor: 'transparent'\n\t});\n\tif ($productSearchResultsLoadMore.is(':visible')) {\n\t\t$productSearchResultsLoadMore.loading({\n\t\t\tIsLabelShown: false,\n\t\t\tBackgroundColor: 'transparent'\n\t\t});\n\t}\n\t$productSearchInput.attr('disabled', 'disabled');\n\n\t$.ajax({\n\t\ttype: 'GET',\n\t\turl: Urls.Search.Show,\n\t\tdata: {\n\t\t\tformat: 'ajax',\n\t\t\tq: query,\n\t\t\t// prefn1: 'availableStores',\n\t\t\t// prefv1: options.AgentStoreID,\n\t\t\tstart: parseInt((data['ProductSearchPage'] - 1) * data['ProductSearchPageSize'], 10),\n\t\t\tsz: data['ProductSearchPageSize']\n\t\t},\n\t\tsuccess: function(response) {\n\t\t\tvar $html = $(response);\n\t\t\tvar $productGrid = $html.find('#search-result-items');\n\t\t\tvar $pagination = $html.find('.search-result-options .pagination[count]').first();\n\t\t\tvar productTileCount = $productGrid.find('.grid-tile').length + $('.section.search .results-container').find('.grid-tile').length;\n\t\t\tvar productTotalCount = 0;\n\t\t\tif ($pagination.length > 0) {\n\t\t\t\tproductTotalCount = parseInt($html.find('.search-result-options .pagination[count]').first().attr('count').replace(/\\D/g, ''), 10);\n\t\t\t}\n\n\t\t\tif (productTileCount > 0) {\n\t\t\t\t$productSearchResults.append($productGrid.html());\n\t\t\t\tif (productTileCount < productTotalCount) {\n\t\t\t\t\t$productSearchResultsFooter.show();\n\t\t\t\t} else {\n\t\t\t\t\t$productSearchResultsFooter.hide();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$productSearchResults.append($('<li class=\"no-results\">No products found for your search.</li>'));\n\t\t\t\t$productSearchResultsFooter.hide();\n\t\t\t}\n\t\t\t$productSearch.addClass('active');\n\t\t},\n\t\tcomplete: function(xhr) {\n\t\t\t$productSearchInputContainer.attr('upc', '');\n\t\t\t$productSearchInputContainer.loading('destroy');\n\t\t\t$productSearchSearchButton.loading('destroy');\n\t\t\tif ($productSearchResultsLoadMore.attr('loading')) {\n\t\t\t\t$productSearchResultsLoadMore.loading('destroy');\n\t\t\t}\n\t\t\t$productSearchInput.removeAttr('disabled');\n\t\t\tupdateProductSearchAction();\n\t\t}\n\t});\n}\n\nfunction getStylesForProduct(productId) {\n\tvar $productTile = $productSearchResults.find('.product-tile[data-itemid=\"' + productId + '\"]');\n\n\tif ($productTile.length > 0) {\n\t\tvar $gridTile = $productTile.closest('.grid-tile');\n\n\t\tif ($gridTile.length > 0) {\n\t\t\tvar isFirstLoad = false;\n\t\t\tvar $productVariations;\n\t\t\tif ($gridTile.find('.product-variations').length > 0) {\n\t\t\t\t$productVariations = $gridTile.find('.product-variations');\n\t\t\t} else {\n\t\t\t\tisFirstLoad = true;\n\t\t\t\t$productVariations = $gridTile.append('<div class=\"product-variations\"></div>').find('.product-variations');\n\t\t\t}\n\t\t\t$productVariations.loading({\n\t\t\t\tIsLabelShown: false,\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\t\t\tif ($gridTile.find('.btn.add').is(':visible')) {\n\t\t\t\t$gridTile.find('.btn.add').loading({\n\t\t\t\t\tIsLabelShown: false,\n\t\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t\t});\n\t\t\t}\n\t\t\tdata['attributeGuides'] = {};\n\n\t\t\tvar payload = {\n\t\t\t\tpid: $productTile.data('itemid')\n\t\t\t}\n\n\t\t\tif (!isFirstLoad) {\n\t\t\t\tvar $productVariationAttributesSelected = $productVariations.find('[attribute] option.selectable:checked');\n\t\t\t\t$productVariationAttributesSelected.each(function() {\n\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\tvar productVariationAttributeId = $this.closest('[attribute]').attr('attribute');\n\t\t\t\t\tvar productVariationAttributeValue = $this.val();\n\t\t\t\t\tpayload['dwvar_' + payload.pid + '_' + productVariationAttributeId] = productVariationAttributeValue;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t$.ajax({\n\t\t\t\tmethod: 'post',\n\t\t\t\turl: Urls.getVariationAttributes,\n\t\t\t\tdata: payload,\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(response) {\n\t\t\t\t\thtml['variationSelectors'] = '';\n\t\t\t\t\tfor (var variation in response.variations) {\n\t\t\t\t\t\tvar variationData = response.variations[variation];\n\t\t\t\t\t\tvar variationDataValueSelected = null;\n\t\t\t\t\t\t\n\t\t\t\t\t\thtml['variationSelectorWidgetOptions'] = '';\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\tfor (var variationValue in variationData.values) {\n\t\t\t\t\t\t\tvar variationDataValue = variationData.values[variationValue];\n\t\t\t\t\t\t\tvar variationDataValueTemplate;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar variationDataValuePayload = {\n\t\t\t\t\t\t\t\tattribute: variationDataValue.attribute,\n\t\t\t\t\t\t\t\tvalueId: variationDataValue.valueId,\n\t\t\t\t\t\t\t\tvalue: variationDataValue.value,\n\t\t\t\t\t\t\t\ttitle: variationDataValue.title,\n\t\t\t\t\t\t\t\ttext: variationDataValue.text,\n\t\t\t\t\t\t\t\tstock: variationDataValue.stock,\n\t\t\t\t\t\t\t\tshipping: variationDataValue.shipping,\n\t\t\t\t\t\t\t\tisSameDayShippingWindow: variationDataValue.isSameDayShippingWindow,\n\t\t\t\t\t\t\t\tquantitySourceType: variationDataValue.quantitySourceType,\n\t\t\t\t\t\t\t\thref: variationDataValue.href,\n\t\t\t\t\t\t\t\tselectable: variationDataValue.selectable ? 'selectable' : 'unselectable',\n\t\t\t\t\t\t\t\tselected: !isFirstLoad && variationDataValue.selected ? 'selected' : '',\n\t\t\t\t\t\t\t\tswatchImageUrl: variationDataValue.images.swatch.url,\n\t\t\t\t\t\t\t\tlargeSwatchImageUrl: variationDataValue.images.largeSwatch.url,\n\t\t\t\t\t\t\t\threfAttribute: variationDataValue.selectable ? 'href' : 'xhref'\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (variationData.type == 'swatch') {\n\t\t\t\t\t\t\t\tif (variationDataValue.selectable) {\n\t\t\t\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorSwatchOption'];\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tvariationDataValuePayload.imageLarge = JSON.stringify({\n\t\t\t\t\t\t\t\t\t\turl: variationDataValue.images.large.url,\n\t\t\t\t\t\t\t\t\t\ttitle: variationDataValue.images.large.title,\n\t\t\t\t\t\t\t\t\t\talt: variationDataValue.images.large.alt,\n\t\t\t\t\t\t\t\t\t\thires: variationDataValue.images.hires.url\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorSwatchOptionUnselectable'];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorDropdownOption'];\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (variationDataValue.selected) {\n\t\t\t\t\t\t\t\t\tvariationDataValueSelected = variationDataValue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\thtml['variationSelectorWidgetOptions'] += variationDataValueTemplate(variationDataValuePayload);\n\t\t\t\t\t\t}\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (variationData.type == 'swatch') {\n\t\t\t\t\t\t\thtml['variationSelectorWidget'] = templates['variationSelectorSwatch']({\n\t\t\t\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\t\t\t\toptions: html['variationSelectorWidgetOptions']\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar placeholder = variationData.label.placeholder;\n\t\t\t\t\t\t\tif (variationDataValueSelected) {\n\t\t\t\t\t\t\t\tplaceholder = templates['variationSelectorDropdownOptionSelected']({\n\t\t\t\t\t\t\t\t\ttext: variationDataValueSelected.text,\n\t\t\t\t\t\t\t\t\tstock: variationDataValueSelected.stock,\n\t\t\t\t\t\t\t\t\tshipping: variationDataValueSelected.shipping,\n\t\t\t\t\t\t\t\t\tisSameDayShippingWindow: variationDataValueSelected.isSameDayShippingWindow,\n\t\t\t\t\t\t\t\t\tquantitySourceType: variationDataValueSelected.quantitySourceType\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\thtml['variationSelectorWidget'] = templates['variationSelectorDropdown']({\n\t\t\t\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\t\t\t\ttext: placeholder,\n\t\t\t\t\t\t\t\toptions: html['variationSelectorWidgetOptions']\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thtml['attributeGuide'] = '';\n\t\t\t\t\t\tif (variationData.attributeGuide) {\n\t\t\t\t\t\t\tdata['attributeGuides'][variationData.productVariationAttribute] = variationData.attributeGuide;\n\t\t\t\t\t\t\thtml['attributeGuide'] = templates['variationSelectorAttributeGuide'](_.extend(variationData.attributeGuide, { Attribute: variationData.productVariationAttribute }));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thtml['variationSelector'] = templates['variationSelector']({\n\t\t\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\ttext: variationData.label.text,\n\t\t\t\t\t\t\t\tmessage: variationData.label.message\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tselector: html['variationSelectorWidget'],\n\t\t\t\t\t\t\tguide: html['attributeGuide']\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\thtml['variationSelectors'] += html['variationSelector'];\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\thtml['selectors'] = templates['variations']({\n\t\t\t\t\t\tselectors: html['variationSelectors']\n\t\t\t\t\t});\n\n\t\t\t\t\t$productVariations.html(html['selectors']).addClass('loaded');\n\t\t\t\t\tif (response.pid) {\n\t\t\t\t\t\t$gridTile.find('.btn.add').attr('pid', response.pid);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$gridTile.find('.btn.add').removeAttr('pid');\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcomplete: function(xhr) {\n\t\t\t\t\t$productVariations.loading('destroy');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction resetProductSearch() {\n\t$productSearch.removeClass('active');\n\t$productSearchInputContainer.attr('query', '');\n\t$productSearchInput.val('');\n\t$productSearchInput.focus();\n\tupdateProductSearchAction();\n}\n\nfunction addProductWithProductId(productId, $gridTileAddButton) {\n\tif ($gridTileAddButton) {\n\t\t$gridTileAddButton.loading({\n\t\t\tIsLabelShown: false,\n\t\t\tBackgroundColor: 'transparent'\n\t\t});\n\t}\n\t$productSearchErrorContainer.html('');\n\n\taddProduct({\n\t\tpayload: {\n\t\t\tpid: productId\n\t\t},\n\t\tcomplete: function(xhr) {\n\t\t\tif ($gridTileAddButton && $gridTileAddButton.attr('loading')) {\n\t\t\t\t$gridTileAddButton.loading('destroy');\n\t\t\t}\n\t\t\tresetProductSearch();\n\t\t\trenderCart();\n\t\t}\n\t});\n}\n\nfunction detectBarcode() {\n\tvar canvas = $barcodeScannerModal.find('canvas')[0];\n\tcanvas.width = video.videoWidth;\n\tcanvas.height = video.videoHeight;\n\n\tvar canvasContext = canvas.getContext('2d');\n\tcanvasContext.drawImage(video, 0, 0, canvas.width, canvas.height);\n\n\tvar barcodeDetector = new BarcodeDetector();\n\tbarcodeDetector.detect(canvasContext.getImageData(0, 0, canvas.width, canvas.height)).then(barcodes => {\n\t\t$barcodeScannerModal.addClass('scanned');\n\t\t\n\t\tbarcodes.forEach(function(barcode) {\n\t\t\tvar barcodeValue;\n\t\t\tif ('rawValue' in barcode) {\n\t\t\t\tbarcodeValue = barcode.rawValue;\n\t\t\t} else if ('rawData' in barcode) {\n\t\t\t\tbarcodeValue = barcode.rawData;\n\t\t\t}\n\t\t\t\n\t\t\tcloseBarcodeScanner();\n\t\t\taddProductWithUpc(barcodeValue);\n\t\t});\n\t}).catch(error => {\n\t\t// alert(error);\n\t});\n}\n\nfunction closeBarcodeScanner() {\n\t$('.section.scan').removeClass('active');\n\tif (barcodeDetectorInterval) {\n\t\tbarcodeDetectorInterval = clearInterval(barcodeDetectorInterval);\n\t}\n\tstream.getTracks().forEach(function(track) {\n\t\ttrack.stop();\n\t});\n\tvideo.srcObject = null;\n}\n\nfunction getClipboardValue(event, element, callback) {\n\tif (navigator.clipboard && navigator.clipboard.readText) {\n\t  \t// modern approach with Clipboard API\n\t  \tnavigator.clipboard.readText().then(callback);\n\t} else if (event.originalEvent && event.originalEvent.clipboardData) {\n\t  \t// OriginalEvent is a property from jQuery, normalizing the event object\n\t  \tcallback(event.originalEvent.clipboardData.getData('text'));\n\t} else if (event.clipboardData) {\n\t  \t// used in some browsers for clipboardData\n\t  \tcallback(event.clipboardData.getData('text/plain'));\n\t} else if (window.clipboardData) {\n\t  \t// Older clipboardData version for Internet Explorer only\n\t  \tcallback(window.clipboardData.getData('Text'));\n\t} else {\n\t  \t// Last resort fallback, using a timer\n\t  \tsetTimeout(function() {\n\t\t\tcallback(element.value)\n\t  \t}, 100);\n\t}\n}\n\nfunction addProductWithUpc(upc) {\n\t$barcodeScannerInputContainer.attr('upc', upc);\n\t$barcodeScannerInputContainer.loading({\n\t\tIsImageShown: false,\n\t\tIsLabelShown: false\n\t});\n\t$barcodeScannerAddButton.loading({\n\t\tIsLabelShown: false,\n\t\tBackgroundColor: 'transparent'\n\t});\n\t$barcodeScannerInput.val('');\n\t$barcodeScannerErrorContainer.html('');\n\t$barcodeScannerInput.attr('disabled', 'disabled');\n\n\taddProduct({\n\t\tpayload: {\n\t\t\tupc: upc\n\t\t},\n\t\tsuccess: function(response) {\n\t\t\tif (response && !response.IsProductInProductService) {\n\t\t\t\t$barcodeScannerErrorContainer.append('<p>Product not found in service!</p>');\t\n\t\t\t} else if (response && !response.IsProductInCatalog) {\n\t\t\t\t$barcodeScannerErrorContainer.append('<p>Product not found in catalog!</p>');\t\n\t\t\t}\n\t\t},\n\t\tcomplete: function(xhr) {\n\t\t\t$barcodeScannerInputContainer.attr('upc', '');\n\t\t\t$barcodeScannerInputContainer.loading('destroy');\n\t\t\t$barcodeScannerAddButton.loading('destroy');\n\t\t\t$barcodeScannerInput.removeAttr('disabled');\n\t\t\trenderCart();\n\t\t}\n\t});\n}\n\nfunction addProduct(parameters) {\n\tvar payload = $.extend(parameters.payload || {}, {\n\t\tformat: 'ajax',\n\t\tQuantity: 1,\n\t\tcartAction: 'add',\n\t\tcsrf_token: options.Token,\n\t\tchannel: 'Echo',\n\t\tbopis_store: '',\n\t\tbopis_quantity_available: '',\n\t\tbopis_shipping_option: ''\n\t});\n\n\tif (payload.pid || payload.upc) {\n\t\t$.ajax({\n\t\t\ttype: 'POST',\n\t\t\turl: Urls.addProduct,\n\t\t\tdata: payload,\n\t\t\tsuccess: function(response) {\n\t\t\t\tif (parameters.success && typeof parameters.success == 'function') {\n\t\t\t\t\tparameters.success(response);\n\t\t\t\t}\n\t\t\t},\n\t\t\tcomplete: function(xhr) {\n\t\t\t\tif (parameters.complete && typeof parameters.complete == 'function') {\n\t\t\t\t\tparameters.complete(xhr);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction renderCart() {\n\tif (options && options.StoreUIVersion == '2024Redesign') {\n\t\tlocation.reload();\n\t} else {\n\t\t$.ajax({\n\t\t\ttype: 'GET',\n\t\t\turl: Urls.Cart.GetCartBodyProductLineItems,\n\t\t\tsuccess: function(response) {\n\t\t\t\t$('#wrapper > .cart > form').html(response);\n\t\t\t}\n\t\t});\n\n\t\t$.ajax({\n\t\t\ttype: 'POST',\n\t\t\turl: Urls.getCartData,\n\t\t\tdata: {\n\t\t\t\tisCart: true\n\t\t\t},\n\t\t\tsuccess: function(response) {\n\t\t\t\tif (response && response.OrderTotal && response.OrderTotal.adjustedMerchandizeTotalPrice) {\n\t\t\t\t\t$('.order-subtotal .order-value').text(response.OrderTotal.adjustedMerchandizeTotalPriceDisplay);\n\t\t\t\t\t$('.order-totals-table').removeClass('hidden');\n\t\t\t\t} else {\n\t\t\t\t\t$('.order-totals-table').addClass('hidden');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tupdateCSRFToken();\n}\n\nfunction updateCSRFToken() {\n    $.ajax({\n    \tmethod: 'get',\n    \turl: Urls.CSRFToken.Get,\n\t\tdataType: 'json',\n    \tsuccess: function(response) {\n    \t\toptions.Token = response.token;\n    \t}\n    });\n}\n\nexports.renderCart = renderCart;\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\tinitialize(options);\n};","'use strict';\n\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar sizeRefinements = require('../size-refinements');\nvar sliders = require('../sliders');\nvar styleCounts = require('../style-counts');\nvar util = require('../util');\n\nexports.init = function(options) {\n\tstyleCounts.render(options.StyleCountCache);\n\tsizeRefinements.init();\n\tsliders.initializeCategorySliders('.main-content .category-landing-slider:not(.slick-initialized)');\n};","'use strict';\n\nexports.initialize = initialize;\n\nvar applePaySession;\nvar options = {};\nvar buffer = {};\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter || {};\n\n\t$('[payment-method-container=\"DW_APPLE_PAY\"]').attr('can-make-payments', 'ApplePaySession' in window && 'canMakePayments' in ApplePaySession && ApplePaySession.canMakePayments());\n\t$('[payment-method-group-container=\"DW_APPLE_PAY\"]').attr('can-make-payments', 'ApplePaySession' in window && 'canMakePayments' in ApplePaySession && ApplePaySession.canMakePayments());\n\t\n\tgetApplePayPaymentRequest();\n\t$(document).off('ApplePay.GetPaymentRequest').on('ApplePay.GetPaymentRequest Cart.UpdateSuccess', function(event) {\n\t\tgetApplePayPaymentRequest();\n\t});\n\n\t$(document).off('click.ApplePay').on('click.ApplePay', '.submit-applepay-button', function(event) {\n\t\tapplePaySession = new ApplePaySession(1, buffer['applePayRequest']);\n\t\tapplePaySession.onvalidatemerchant = validateMerchant;\n\t\tapplePaySession.onshippingcontactselected = shippingContactSelected;\n\t\tapplePaySession.onshippingmethodselected = shippingMethodSelected;\n\t\tapplePaySession.onpaymentmethodselected = paymentMethodSelected;\n\t\tapplePaySession.oncouponcodechanged = couponCodeChanged;\n\t\tapplePaySession.onpaymentauthorized = paymentAuthorized;\n\t\tapplePaySession.oncancel = cancel;\n\t\tapplePaySession.begin();\n\t});\n}\n\nfunction validateMerchant(event) {\n\tfetch(Urls.ApplePay.ValidateMerchant, getFetchOptions('POST', event))\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completeMerchantValidation(response);\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-ValidateMerchant', error);\n\t});\n}\n\nfunction shippingContactSelected(event) {\n\tfetch(Urls.ApplePay.ShippingContactSelected, getFetchOptions('POST', event))\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completeShippingContactSelection(response);\n\t\t$(document).trigger('Cart.Update');\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-ShippingContactSelected', error);\n\t});\n}\n\nfunction shippingMethodSelected(event) {\n\tfetch(Urls.ApplePay.ShippingMethodSelected, getFetchOptions('POST', event))\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completeShippingMethodSelection(response);\n\t\t$(document).trigger('Cart.Update');\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-ShippingMethodSelected', error);\n\t});\n}\n\nfunction paymentMethodSelected(event) {\n\tfetch(Urls.ApplePay.PaymentMethodSelected, getFetchOptions('POST', event))\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completePaymentMethodSelection(response);\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-PaymentMethodSelected', error);\n\t});\n}\n\nfunction couponCodeChanged(event) {\n\tfetch(Urls.ApplePay.CouponCodeChanged)\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completeCouponCodeChange(response);\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-CouponCodeChanged', error);\n\t});\n}\n\nfunction paymentAuthorized(event) {\n\tfetch(Urls.ApplePay.PaymentAuthorized, getFetchOptions('POST', event))\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(response) {\n\t\tapplePaySession.completePayment(response);\n\t})\n\t.then(function(response) {\n\t\tif (event.payment) {\n\t\t\tif (event.payment.billingContact) {\n\t\t\t\tvar billingAddressObject = {};\n\t\t\t\tbillingAddressObject.FirstName = event.payment.billingContact.givenName;\n\t\t\t\tbillingAddressObject.LastName = event.payment.billingContact.familyName;\n\t\t\t\tbillingAddressObject.PrimaryLine = event.payment.billingContact.addressLines[0] || '';\n\t\t\t\tbillingAddressObject.SecondaryLine = event.payment.billingContact.addressLines[1] || '';\n\t\t\t\tbillingAddressObject.StateCode = event.payment.billingContact.administrativeArea;\n\t\t\t\tbillingAddressObject.PostalCode = event.payment.billingContact.postalCode;\n\t\t\t\tbillingAddressObject.City = event.payment.billingContact.locality;\n\n\t\t\t\tif (event.payment.shippingContact && event.payment.shippingContact.phone) {\n\t\t\t\t\tbillingAddressObject.Phone = event.payment.shippingContact.phone.replace('+','');\n\t\t\t\t}\n\n\t\t\t\tif (options.isCheckoutPage) {\n\t\t\t\t\t$(document).trigger('SetAddressFromAddressVerification', $.extend(billingAddressObject, { AddressType: 'billing' }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (event.payment.shippingContact) {\n\t\t\t\tvar shippingAddressObject = {};\n\t\t\t\tshippingAddressObject.FirstName = event.payment.shippingContact.givenName;\n\t\t\t\tshippingAddressObject.LastName = event.payment.shippingContact.familyName;\n\t\t\t\tshippingAddressObject.PrimaryLine = event.payment.shippingContact.addressLines[0] || '';\n\t\t\t\tshippingAddressObject.SecondaryLine = event.payment.shippingContact.addressLines[1] || '';\n\t\t\t\tshippingAddressObject.StateCode = event.payment.shippingContact.administrativeArea;\n\t\t\t\tshippingAddressObject.PostalCode = event.payment.shippingContact.postalCode;\n\t\t\t\tshippingAddressObject.City = event.payment.shippingContact.locality;\n\n\t\t\t\tif (event.payment.shippingContact.phone) {\n\t\t\t\t\tshippingAddressObject.Phone = event.payment.shippingContact.phone.replace('+','');\n\t\t\t\t}\n\n\t\t\t\tif (options.isCheckoutPage) {\n\t\t\t\t\t$(document).trigger('SetAddressFromAddressVerification', $.extend(shippingAddressObject, { AddressType: 'shipping' }));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (options.isCheckoutPage) {\n\t\t\t$(document).trigger('Cart.Update');\n\t\t} else {\n\t\t\twindow.location = Urls.onePage;\n\t\t}\n\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-PaymentAuthorized', error);\n\t});\n}\n\nfunction cancel(event) {\n\tfetch(Urls.ApplePay.Cancel, getFetchOptions('POST'))\n\t.then(function() {\n\t\t// applePaySession.abort();\n\t\tif (options.isCheckoutPage) {\n\t\t\t$(document).trigger('Cart.Update');\n\t\t}\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-Cancel', error);\n\t});\n}\n\nfunction getApplePayPaymentRequest() {\n\tfetch(Urls.ApplePay.GetRequest)\n\t.then(function(response) { \n\t\treturn response.json();\n\t})\n\t.then(function(applePayRequest) {\n\t\tbuffer['applePayRequest'] = applePayRequest;\n\t})\n\t.catch(function(error) {\n\t\tconsole.error('ApplePay-GetRequest', error);\n\t});\n}\n\nfunction getFetchOptions(method, body) {\n\tvar fetchOptions = {\n\t\tcredentials: 'include'\n\t};\n\tif (method) {\n\t\tfetchOptions.method = method;\n\t}\n\tif (body) {\n\t\tfetchOptions.headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'Accept': 'application/json'\n\t\t}\n\t\tfetchOptions.body = JSON.stringify(filterEvent(body));\n\t}\n\n\treturn fetchOptions;\n}\n\nfunction filterEvent(event) {\n\tvar eventFiltered = {};\n\tfor (var property in event) {\n\t\tif (!Event.prototype.hasOwnProperty(property)) {\n\t\t\teventFiltered[property] = event[property];\n\t\t}\n\t}\n\treturn eventFiltered;\n}","'use strict';\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar giftCardBalanceInquiryDialog = require('../../components/GiftCardBalanceInquiryDialog');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar opcpayment = require('./opcpayment');\n\nexports.initialize = initialize;\n\nvar $giftCardPaymentContainer = $('[payment-method=\"SVS_Gift_Card\"]');\nvar $giftCardPaymentForm = $giftCardPaymentContainer.find('form');\nvar $giftCardPaymentCardNumber = $giftCardPaymentContainer.find('input[name$=\"giftCard_number\"]');\nvar $giftCardPaymentPinNumber = $giftCardPaymentContainer.find('input[name$=\"giftCard_pin\"]');\nvar $giftCardPaymentMessage = $giftCardPaymentContainer.find('.messages');\nvar $giftCardPaymentErrorMessage = $giftCardPaymentContainer.find('span.error');\nvar $giftCardPaymentApplied = $giftCardPaymentContainer.find('.form-giftcards-applied');\nvar $giftCardPaymentApplyButton = $giftCardPaymentContainer.find('.apply');\nvar giftCardValidator;\nvar giftCardRecaptcha;\nvar options = {};\nvar loaded = {};\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && $giftCardPaymentApplyButton.length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForGiftCards && options.Recaptcha.GoogleSiteKey) {\n\t\tgiftCardRecaptcha = grecaptcha.render('svs-gift-card-apply-button', {\n\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t        callback: submitGiftCard,\n\t        badge: 'bottomleft'\n\t    });\n\t}\n}\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter || {};\n\t\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n\t\n    $giftCardPaymentContainer.on('click', '.apply:not([loading])', function(event) {\n\t\tevent.preventDefault();\n\t\t\n        if (!options || !options.Recaptcha || !options.Recaptcha.EnabledForGiftCards || !options.Recaptcha.GoogleSiteKey) {\n            $(document).trigger('GiftCard.Apply');\n        }\n\t});\n\t\n\t$(document).on('GiftCard.Apply', function(event) {\t\t\n        event.preventDefault();\n\n        if (parseFloat($('[balance-due]').first().attr('balance-due')) <= 0) {\n            $giftCardPaymentErrorMessage.html(Resources.RewardsCredit.NoBalanceDue).show();\n            \n            if (giftCardRecaptcha != undefined) {\n\t\t\t\tgrecaptcha.reset(giftCardRecaptcha);\n\t\t\t}\n        } else {\n            $giftCardPaymentErrorMessage.html('').hide();\n            giftCardValidator = $giftCardPaymentForm.validate();\n\t\t\t$.validator.addMethod('giftCardNumberLength', ValidationHelper.ValidateGiftCardNumberLength, Resources.Validation.Messages.GiftCard.Number.Length);\n\t\t\t$.validator.addMethod('giftCardNumberValues', ValidationHelper.ValidateGiftCardNumberValues, Resources.Validation.Messages.GiftCard.Number.Values);\n            $giftCardPaymentCardNumber.rules('add', ValidationRules.GiftCard.Number);\n            $giftCardPaymentPinNumber.rules('add', ValidationRules.GiftCard.Pin);\n            giftCardValidator.form();\n\n            // Adding ADA compliance error messages for giftCardPayment section\n            if ($giftCardPaymentForm.find('.field.error').length > 0) {\n                $('.payment-declined').remove();\n                var giftCardPaymentFormErrorMessages = opcpayment.getErrorMessages($giftCardPaymentForm);\n                var giftCardPaymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', giftCardPaymentFormErrorMessages);\n                if (giftCardPaymentFormErrorBox) {\n                    $giftCardPaymentApplied.after(giftCardPaymentFormErrorBox);\n                }\n            }\n\n            if (Urls && Urls.GiftCard.Apply && giftCardValidator.valid()) {\n                var giftCardRowContainerHtml = _.template($('#template-gift-card-row-container').html(), TemplateConstants.Lodash.Settings)();\n                var $giftCardPaymentAppliedGiftCard = $(giftCardRowContainerHtml).appendTo($giftCardPaymentApplied);\n\n                $giftCardPaymentApplyButton.loading(options.LoadingIndicator || {\n                    IsImageShown: false,\n                    Label: Resources.Loading.Processing\n                });\n\t\t\t\tif (!options.LoadingIndicator) {\n\t\t\t\t\t$giftCardPaymentAppliedGiftCard.loading(options.LoadingIndicator || {\n\t\t\t\t\t\tLabel: Resources.Loading.GiftCard.Applying\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tvar giftCardPaymentCardNumber = $giftCardPaymentCardNumber.val().match(/(\\d)/g);\n\t\t\t\tif (giftCardPaymentCardNumber && giftCardPaymentCardNumber.length) {\n\t\t\t\t\tgiftCardPaymentCardNumber = giftCardPaymentCardNumber.join('');\n\t\t\t\t}\n\n                $.ajax({\n                    method: 'POST',\n                    url: Urls.GiftCard.Apply,\n                    contentType: 'application/json',\n                    data: JSON.stringify({\n                        number: giftCardPaymentCardNumber,\n                        pin: $giftCardPaymentPinNumber.val(),\n                        amount: null\n                    }),\n                    dataType: 'json',\n                    success: function (data) {\n\t\t\t\t\t\tif ($giftCardPaymentApplyButton.attr('loading')) {\n                        \t$giftCardPaymentApplyButton.loading('destroy');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ($giftCardPaymentAppliedGiftCard.attr('loading')) {\n                        \t$giftCardPaymentAppliedGiftCard.loading('destroy');\n\t\t\t\t\t\t}\n                        \n                        if (data.success) {\n                            $giftCardPaymentCardNumber.val('');\n                            $giftCardPaymentPinNumber.val('');\n                            \n                            if (data.amountApplied && data.amountApplied.value > 0) {\n                            \t$giftCardPaymentApplied.find('[data-id=\"' + data.id + '\"]').remove();                            \t\n                                $giftCardPaymentAppliedGiftCard.attr('data-id', data.id);\n\n                                var giftCardRowContentHtml = _.template($('#template-gift-card-row-content').html(), TemplateConstants.Lodash.Settings)({\n                                    cardNumber: data.number,\n                                    amountApplied: data.amountApplied.displayValue\n                                });\n\n                                $giftCardPaymentAppliedGiftCard.html(giftCardRowContentHtml);\n                            }\n                            \n                            if (data.message) {\n                            \t$giftCardPaymentErrorMessage.html(data.message).show();\n                            }\n\n\t\t\t\t\t\t\tif (options.StoreUIVersion == '2024Redesign') {\n\t\t\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t\t\t} else {\n                            \t$(document).trigger('Cart.Update');\n\t\t\t\t\t\t\t}\n                        } else {\n                        \tif (data.message == 'Invalid Message') {\n                        \t\tdata.message = Resources.Error.Generic;\t\n                        \t}\n                        \t\n                            $giftCardPaymentAppliedGiftCard.remove();\n                            $giftCardPaymentErrorMessage.html(data.message || Resources.Error.Generic).show();\n                        }\n                        \n\t\t\t\t\t\tif (giftCardRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(giftCardRecaptcha);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\t\tvalue: data.amountApplied.value,\n\t\t\t\t\t\t\tpayment_type: 'Gift Card SVS'\n\t\t\t\t\t\t}\n\t\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo', dataObject);\n                    },\n                    error: function() {\n\t\t\t\t\t\t$giftCardPaymentApplyButton.loading('destroy');\n\t\t\t\t\t\t$giftCardPaymentAppliedGiftCard.remove();\n\t\t\t\t\t\t$giftCardPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (giftCardRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(giftCardRecaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                });\n            } else {\n            \tif (giftCardRecaptcha != undefined) {\n\t\t\t\t\tgrecaptcha.reset(giftCardRecaptcha);\n\t\t\t\t}\t\n            }\n        }\n    });\n\n    $(document).off('mousedown.GiftCardPaymentPanel').on('mousedown.GiftCardPaymentPanel', function (event) {\n        if (giftCardValidator && $(event.target).closest($giftCardPaymentContainer).length == 0) {\n            giftCardValidator.resetForm();\n            $giftCardPaymentErrorMessage.html('').hide();\n        }\n    });\n\n    $(document).on('CartData.Update', function (event, data) {\n    \t$('[has-gift-cards]').attr('has-gift-cards', data.HasGiftCards || false);\n\t    $('[has-gift-cards-only]').attr('has-gift-cards-only', data.HasGiftCardsOnly || false);\n\t    \n\t    if (data.HasGiftCards && !data.AllowGiftCardPurchaseWithGiftCard) {\n\t    \t$giftCardPaymentMessage.html(Resources.GiftCard.GiftCardPurchaseWithGiftCardNotAllowed);\n\t    \t$giftCardPaymentContainer.attr('status', 'locked');\n\t    } else {\n\t    \t$giftCardPaymentMessage.html('');\n\t    \t$giftCardPaymentContainer.attr('status', 'active');\n\t    }\n    });\n    \n    $(document).on('GiftCard.Clear', function () {\n        $giftCardPaymentApplied.html('');\n        $('.order-balance-due').html('');\n    });\n\n    $giftCardPaymentContainer.on('click', '.remove:not([loading])', function (event) {\n        event.preventDefault();\n\n        var $giftCardRow = $(this).closest('.form-giftcard-applied');\n        $giftCardRow.loading(options.LoadingIndicator || {\n            Label: Resources.Loading.GiftCard.Removing\n        });\n        $giftCardPaymentErrorMessage.html('').hide();\n\n        $.ajax({\n            url : Urls.GiftCard.Remove,\n            type : 'POST',\n            contentType: 'application/json',\n            data: JSON.stringify({\n                id: $giftCardRow.data('id')\n            }),\n            dataType : 'json',\n            success : function(data) {\n            \t$giftCardRow.loading('destroy');\n            \t\n                if (data.success) {\n                    $giftCardRow.remove();\n\n                    if (options.StoreUIVersion == '2024Redesign') {\n\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t\t\t}\n                } else {\n                \t$giftCardPaymentErrorMessage.html(data.error || Resources.Error.Generic).show();\n                }\n            },\n            error: function() {\n\t\t\t\t$giftCardRow.loading('destroy');\n\t\t\t\t$giftCardPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t}\n        });\n    });\n\n    $(document).on('click.BalanceInquiry', '[payment-method=\"SVS_Gift_Card\"] .balance-inquiry a', function (event) {\n        event.preventDefault();\n        giftCardBalanceInquiryDialog.initialize();\n    });\n    \n    $(document).on('click', '.form-label.expander', function(){\n    \t$('form.svs-gift-card-information').slideToggle();\n    \t$giftCardPaymentContainer.toggleClass('svs-collapsed');\n    });\n}\n","'use strict';\n/* global Resources, Urls */\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar opcpayment = require('./opcpayment');\nvar util = require('../../util');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nexports.initialize = initialize;\n\nvar $loyaltyPaymentContainer = $('[payment-method=\"LOYALTY_CREDIT\"]');\nvar $loyaltyPaymentsForm = $loyaltyPaymentContainer.find('form');\nvar $loyaltyPaymentsApplied = $loyaltyPaymentContainer.find('.loyalty-applied');\nvar $loyaltyPaymentInput = $loyaltyPaymentContainer.find('#dwfrm_billing_loyalty_loyaltyNumber');\nvar $loyaltyPhoneNumberInput = $loyaltyPaymentContainer.find('#dwfrm_billing_loyalty_loyaltyPhoneNumber');\nvar $loyaltyZipCodeInput = $loyaltyPaymentContainer.find('#dwfrm_billing_loyalty_loyaltyZipCode');\nvar $loyaltyPaymentSecondaryContainer = $loyaltyPaymentContainer.find('.loyalty-secondary');\nvar $loyaltyPaymentSecondarySelect = $loyaltyPaymentContainer.find('#loyalty-secondary-select');\nvar $loyaltyPaymentErrorMessage = $loyaltyPaymentContainer.find('span.error');\nvar loyaltyCreditValidator;\nvar loyaltyCreditRowTemplate = _.template($('#template-loyalty-credit-row').html(), TemplateConstants.Lodash.Settings);\nvar loyaltyCreditRecaptcha;\nvar options = {};\nvar loaded = {};\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && $('#loyalty-credit-add-button').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForloyaltyCredit && options.Recaptcha.GoogleSiteKey) {\n\t\tloyaltyCreditRecaptcha = grecaptcha.render('loyalty-credit-add-button', {\n\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t        callback: submitLoyaltyCredit,\n\t        badge: 'bottomleft'\n\t    });\n\t}\n}\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter || {};\n\tvar currentSite = '';\n\tif ($(\".logo.shep\").length > 0){\n    \tcurrentSite = Resources.LoyaltyCredit.NotOptedInSHEP;\n    }\n\tif ($(\".logo.co\").length > 0){\n    \tcurrentSite = Resources.LoyaltyCredit.NotOptedInCO;\n    }\n\t\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n\t\n\tif ($(\".loyalty-row[status='applied']\").length > 0){\n\t\t$loyaltyPaymentsForm.hide();\n\t}\n\n\tif ($loyaltyPaymentSecondarySelect.closest('.opc-summary').length > 0) {\n\t\t$loyaltyPaymentSecondarySelect.selectmenu({\n\t\t\twidth: '100%',\n\t\t\tappendTo: '[payment-method=\"LOYALTY_CREDIT\"] .loyalty-secondary',\n\t\t\tchange: function(event, ui) {\n\t\t\t\t$loyaltyPaymentSecondaryContainer.attr('secondary', ui && ui.item && ui.item.value ? ui.item.value : '');\n\t\t\t}\n\t\t});\n\t}\n\t\n\t$loyaltyPaymentContainer.on('click', '.reset', function(event) {\n\t\tevent.preventDefault();\n\t\tresetSecondarySelect();\n\t});\n\n\t$loyaltyPaymentContainer.on('click', '.add', function(event) {\n\t\tevent.preventDefault();\n\t\t\n        if (!options || !options.Recaptcha || !options.Recaptcha.EnabledForRewardsCredit || !options.Recaptcha.GoogleSiteKey) {\n            $(document).trigger('LoyaltyCredit.Add'); \n        }\n\t});\n\t\n\t$(document).on('LoyaltyCredit.Add', function(event, data) {\n\t\tevent.preventDefault();\n\n\t\tif (parseFloat($('[balance-due]').first().attr('balance-due')) <= 0) {\n\t\t\t$loyaltyPaymentErrorMessage.html(Resources.LoyaltyCredit.NoBalanceDue).show();\n\t\t} else {\n\t\t\tvar loyaltySecondaryFactor = $loyaltyPaymentSecondaryContainer.attr('secondary');\n\t\t\tloyaltyCreditValidator = $loyaltyPaymentsForm.validate();\n            $loyaltyPaymentInput.rules('add', ValidationRules.LoyaltyCredit.Number);\n\n\t\t\tswitch (loyaltySecondaryFactor) {\n\t\t\t\tcase \"zipcode\":\n\t\t\t\t\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n\t\t\t\t\t$loyaltyZipCodeInput.rules('add', ValidationRules.ZipCode);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n            loyaltyCreditValidator.form();\n\n\t\t\t// Adding ADA compliance error messages for giftCardPayment section\n            if ($loyaltyPaymentsForm.find('.field.error').length > 0) {\n\t\t\t\t$('.payment-declined').remove();\n                var loyaltyPaymentFormErrorMessages = opcpayment.getErrorMessages($loyaltyPaymentsForm);\n                var loyaltyPaymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', loyaltyPaymentFormErrorMessages);\n                if (loyaltyPaymentFormErrorBox) {\n                    $loyaltyPaymentsApplied.after(loyaltyPaymentFormErrorBox);\n                }\n            }\n\t\t\t\n            if (Urls && Urls.checkLoyalty && loyaltyCreditValidator.valid()) {\n            \t$loyaltyPaymentsForm.hide();\n            \t\n\t\t\t\tvar $loyaltyCreditRow = $(loyaltyCreditRowTemplate());\n\t\t\t\t$loyaltyCreditRow = $loyaltyCreditRow.appendTo($loyaltyPaymentsApplied);\n\t\t\t\t$loyaltyCreditRow.attr('status', 'pending');\n\t\t\t\t$loyaltyCreditRow.find('.basketLoyaltyNumber').html(util.getMaskedNumber($loyaltyPaymentInput.val(), 4, 'xxxx... '));\n\t\n\t\t\t\t$loyaltyCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t\t\t$loyaltyCreditRow.find('.form-controls').loading({Label: Resources.Loading.LoyaltyCredit.Loading});\n\t\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: Urls.checkLoyalty,\n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcsrf_token:  $loyaltyPaymentContainer.find('input[name=\"csrf_token\"]').val(),\n\t\t\t\t\t\tloyaltyNumber: $loyaltyPaymentInput.val(),\n\t\t\t\t\t\tloyaltyPhoneNumber: $loyaltyPhoneNumberInput.val(),\n\t\t\t\t\t\tloyaltyZipCode: $loyaltyZipCodeInput.val()\n\t\t\t\t\t},\n\t\t\t\t\tdataType: 'json',\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t$loyaltyPaymentErrorMessage.html('').hide();\n\t\n\t\t\t\t\t\t$loyaltyCreditRow.find('.btn').loading('destroy');\n\t\t\t\t\t\t$loyaltyCreditRow.find('.form-controls').loading('destroy');\n\t\n\t\t\t\t\t\tif (data.error !== 'undefined' && data.error === true) {\n\t\t\t\t\t\t\t$loyaltyCreditRow.remove();\n\t\t\t\t\t\t\t$loyaltyPaymentsForm.show();\n\t\t\t\t\t\t\t$loyaltyPaymentErrorMessage.html(data.errorMsg).show();\n\t\t\t\t\t\t} else if (!data.optinStatus) {\n\t\t\t\t\t\t\t$loyaltyPaymentContainer.attr('has-loyaltynumber', 'false');\n\t\t\t\t\t\t\t$loyaltyCreditRow.attr('status', 'message');\n\t\t\t\t\t\t\t$loyaltyCreditRow.find('.message').html(currentSite);\n\t\t\t\t\t\t} else if (parseFloat(data.creditAmount) <= 0) {\n\t\t\t\t\t\t\t$loyaltyPaymentContainer.attr('has-loyaltynumber', 'true');\n\t\t\t\t\t\t\t$loyaltyCreditRow.attr('status', 'message');\n\t\t\t\t\t\t\t$loyaltyCreditRow.find('.message').html(Resources.LoyaltyCredit.NoBalanceAvailable);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$loyaltyPaymentContainer.attr('has-loyaltynumber', 'true');\n\t\t\t\t\t\t\t$loyaltyPaymentContainer.attr('data-loyalty', data.optIn);\n\t\t\t\t\t\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').html(data.creditAmountFormatted);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar details = '';\t\t\t\t\t\n\t\t\t\t\t\t\tvar vouchers = data.creditVouchers;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvouchers.reverse().forEach(function(voucher){\n\t\t\t\t\t\t\t\tdetails += '<div class=\"voucher\"><span class=\"reward-amount\"><b>$'+voucher.rewardAmount+'</b></span><span class=\"expiration\"><i>Expires '+voucher.expirationDate+'</i></span></div>';\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t$loyaltyCreditRow.find('.vouchers').html(details);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (loyaltyCreditRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(loyaltyCreditRecaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\t$loyaltyCreditRow.remove();\n\t\t\t\t\t\t$loyaltyPaymentsForm.show();\n\t\t\t\t\t\t$loyaltyPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (loyaltyCreditRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(loyaltyCreditRecaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n            }\n\t\t}\n\t});\n\n\t$loyaltyPaymentContainer.on('click', '.apply', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $loyaltyCreditRow = $(this).closest('.loyalty-row');\n\t\t\n\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').addClass('hide');\n\t\t$loyaltyCreditRow.find('.voucher').addClass('hide');\n\t\t$loyaltyCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t$loyaltyCreditRow.find('.form-controls').loading({Label: Resources.Loading.LoyaltyCredit.Applying});\n\n\t\t$.ajax({\n\t\t\turl: Urls.applyLoyalty,\n\t\t\ttype: 'POST',\n\t\t\tdata: {\n\t\t\t\tcsrf_token:  $loyaltyPaymentContainer.find('input[name=\"csrf_token\"]').val(),\n\t\t\t\tloyaltyNumber: $loyaltyPaymentInput.val(),\n\t\t\t\tloyaltyPhoneNumber: $loyaltyPhoneNumberInput.val(),\n\t\t\t\tloyaltyZipCode: $loyaltyZipCodeInput.val()\n\t\t\t},\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\t$loyaltyPaymentErrorMessage.html('').hide();\n\n\t\t\t\t$loyaltyCreditRow.find('.btn').loading('destroy');\n\t\t\t\t$loyaltyCreditRow.find('.form-controls').loading('destroy');\n\n\t\t\t\tif (data.error !== 'undefined' && data.error === true) {\n\t\t\t\t\t$loyaltyCreditRow.attr('status', 'message');\n\t\t\t\t\t$loyaltyPaymentInput.val('');\n\t\t\t\t\t$loyaltyCreditRow.remove();\n\t\t\t\t\t$loyaltyPaymentsForm.show();\n\t\t\t\t\t$loyaltyPaymentErrorMessage.html(data.errorMsg).show();\n\t\t\t\t} else {\n\t\t\t\t\t$loyaltyCreditRow.attr('status', 'applied');\n\t\t\t\t\t$loyaltyPaymentsForm.hide();\n\t\t\t\t\t$loyaltyCreditRow.find('.voucher').removeClass('hide');\n\t\t\t\t\t$loyaltyCreditRow.find('.basketLoyaltyNumber').html(util.getMaskedNumber(data.loyaltyNumber, 4, 'xxxx... '));\n\t\t\t\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').removeClass('hide').html(data.loyaltyCreditUsedFormatted).attr('label', Resources.LoyaltyCredit.RewardApplied);\n\n\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\tvalue: data.rewardsCreditUsed,\n\t\t\t\t\t\tpayment_type: 'Loyalty'\n\t\t\t\t\t}\n\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo', dataObject);\n\n\t\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\t$loyaltyCreditRow.attr('status', 'message');\n\t\t\t\t$loyaltyPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\tresetForm(true);\n\t\t\t},\n\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t$loyaltyPaymentContainer.on('click LoyaltyCredit.Remove', '.remove', function(event, data) {\n\t\tevent.preventDefault();\n\n\t\tvar $loyaltyCreditRow = $(this).closest('.loyalty-row');\n\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').addClass('hide');\n\t\t$loyaltyCreditRow.find('.voucher').addClass('hide');\n\t\t$loyaltyCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t$loyaltyCreditRow.find('.form-controls').loading({Label: Resources.Loading.LoyaltyCredit.Removing});\n\n\t\tvar payload = {\n\t\t\tloyaltyNumber: $('input#dwfrm_billing_loyalty_loyaltyNumber').val()\n\t\t}\n\n\t\tif (data && data.ResetSessionData) {\n\t\t\tpayload.resetSessionData = true\n\t\t}\n\n\t\t$.ajax({\n\t\t\turl: Urls.removeLoyalty,\n\t\t\ttype: 'POST',\n\t\t\tdataType: 'json',\n\t\t\tdata: payload,\n\t\t\tsuccess: function() {\n\t\t\t\t$loyaltyPaymentErrorMessage.html('').hide();\n\n\t\t\t\tif ($loyaltyCreditRow.find('.btn[loading]').length > 0) {\n\t\t\t\t\t$loyaltyCreditRow.find('.btn').loading('destroy');\n\t\t\t\t}\n\t\t\t\tif ($loyaltyCreditRow.find('.form-controls[loading]').length > 0) {\n\t\t\t\t\t$loyaltyCreditRow.find('.form-controls').loading('destroy');\n\t\t\t\t}\n\n\t\t\t\tif ($loyaltyPaymentContainer.attr('has-loyaltynumber') !== 'true') {\n\t\t\t\t\t$loyaltyPaymentInput.val('');\n\t\t\t\t\t$loyaltyPaymentsForm.show();\n\t\t\t\t\t$loyaltyCreditRow.attr('status', 'form');\n\t\t\t\t\t$loyaltyPaymentsApplied.html('');\n\t\t\t\t} else {\n\t\t\t\t\t$loyaltyCreditRow.attr('status', 'pending');\n\t\t\t\t\t$loyaltyCreditRow.find('.voucher').removeClass('hide');\n\t\t\t\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').removeClass('hide').attr('label', Resources.LoyaltyCredit.Reward);\n\t\t\t\t}\n\n\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t},\n            error: function() {\n\t\t\t\t$loyaltyCreditRow.find('.btn').loading('destroy');\n\t\t\t\t$loyaltyCreditRow.find('.form-controls').loading('destroy');\n\n\t\t\t\t$loyaltyPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t}\n\t\t});\n\t});\n\t\n\t$loyaltyPaymentContainer.on('click', '.change', function(event) {\n\t\tevent.preventDefault();\n\t\t\n\t\t$loyaltyPaymentContainer.attr('has-loyaltynumber', 'false');\n\t\tif ($loyaltyPaymentsApplied.find('.loyalty-row').attr('status') === 'applied') {\n\t\t\t$loyaltyPaymentContainer.find('.remove').trigger('LoyaltyCredit.Remove');\n\t\t}\n\t\tresetForm();\n\t});\n\n\t$(document).off('mousedown.LoyaltyCreditPaymentPanel').on('mousedown.LoyaltyCreditPaymentPanel', function (event) {\n        if (loyaltyCreditValidator && $(event.target).closest($loyaltyPaymentContainer).length == 0) {\n            loyaltyCreditValidator.resetForm();\n            $loyaltyPaymentErrorMessage.html('').hide();\n        }\n    });\n\t\n\t$(document).on('LoyaltyCredit.Clear', function(event) {\n\t\tevent.preventDefault();\n\t\tresetForm();\n\t});\n\n\t$loyaltyPaymentContainer.on('click', '.reset', function(event) {\n\t\tevent.preventDefault();\n\t\t$loyaltyPaymentsForm.show();\n\t\t$loyaltyPhoneNumberInput.val('');\n\t\t$loyaltyZipCodeInput.val('');\n\t});\n\t\n\tif ($loyaltyPaymentContainer.attr('has-loyaltynumber') === 'true' && $loyaltyPaymentsApplied.find('.loyalty-row').length == 0 && $('[checkout-mode]').attr('checkout-mode') != 'echo') {\n\t\t$(document).trigger('LoyaltyCredit.Add', { Registered: true });\n\t}\n}\n\nfunction resetForm(showErrorMessage) {\n\tif (loyaltyCreditValidator) {\n\t\tloyaltyCreditValidator.resetForm();\n\t}\n\t\n\tif (!showErrorMessage) {\n\t\t$loyaltyPaymentErrorMessage.html('').hide();\n\t}\n\t\n\tvar $loyaltyCreditRow = $loyaltyPaymentsApplied.find('.loyalty-row');\n\tif ($loyaltyPaymentContainer.attr('has-loyaltynumber') !== 'true') {\n\t\t$loyaltyPaymentInput.val('');\n\t\t$loyaltyPhoneNumberInput.val('');\n\t\t$loyaltyZipCodeInput.val('');\n\t\t\n\t\t$loyaltyPaymentsForm.show();\n\t\t$loyaltyPaymentsApplied.html('');\n\t} else {\n\t\t$loyaltyCreditRow.find('.basketLoyaltyAmount').attr('label', Resources.LoyaltyCredit.Reward);\n\t}\n\n\tresetSecondarySelect();\n}\n\nfunction resetSecondarySelect() {\n\t$loyaltyPaymentSecondarySelect.prop('selectedIndex', 0);\n\tif ($loyaltyPaymentSecondarySelect.closest('.opc-summary').length > 0) {\n\t\t$loyaltyPaymentSecondarySelect.selectmenu('refresh');\n\t}\n\t$loyaltyPaymentSecondaryContainer.attr('secondary', '');\n}","'use strict';\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\n\nexports.initialize = initialize;\n\nvar $paymentContainer = $('[payment-method=\"B2B_Payment_Voucher\"]');\nvar $paymentForm = $paymentContainer.find('form');\nvar $paymentVoucherNumber = $paymentContainer.find('input[name=\"paymentvouchercode\"]');\nvar $paymentMessage = $paymentContainer.find('.messages');\nvar $paymentErrorMessage = $paymentContainer.find('span.error');\nvar $paymentsApplied = $paymentContainer.find('.form-payments-applied');\nvar $paymentApplyButton = $paymentContainer.find('.apply');\nvar validator;\nvar recaptcha;\nvar options = {};\nvar loaded = {};\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && $paymentApplyButton.length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForPaymentVouchers && options.Recaptcha.GoogleSiteKey) {\n\t\trecaptcha = grecaptcha.render('payment-voucher-apply-button', {\n\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t        callback: submitPaymentVoucher,\n\t        badge: 'bottomleft'\n\t    });\n\t}\n}\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter || {};\n\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n\t\n    $paymentContainer.on('click', '.apply:not([loading])', function (event) {\n\t\tevent.preventDefault();\n\t\t\n        if (!options || !options.Recaptcha || !options.Recaptcha.EnabledForPaymentVouchers || !options.Recaptcha.GoogleSiteKey) {\n            $(document).trigger('PaymentVoucher.Apply');\n        }\n\t});\n\t\n\t$(document).on('PaymentVoucher.Apply', function(event) {\t\t\n        event.preventDefault();\n\n        if (parseFloat($('[balance-due]').first().attr('balance-due')) <= 0) {\n            $paymentErrorMessage.html(Resources.PaymentVoucher.NoBalanceDue).show();\n            \n            if (recaptcha != undefined) {\n\t\t\t\tgrecaptcha.reset(recaptcha);\n\t\t\t}\n        } else {\n            $paymentErrorMessage.html('').hide();\n            validator = $paymentForm.validate();\n            $paymentVoucherNumber.rules('add', ValidationRules.PaymentVoucher.Number);\n            validator.checkForm();\n\n            if (Urls && Urls.PaymentVoucher.Apply && validator.valid()) {\n                var rowContainerHtml = _.template($('#template-paymentvoucher-row-container').html(), TemplateConstants.Lodash.Settings)();\n                var $paymentApplied = $(rowContainerHtml).appendTo($paymentsApplied);\n\n                $paymentApplyButton.loading({\n                    IsImageShown: true,\n\t\t\t\t\tIsLabelShown: false\n                });\n                $paymentApplied.loading({\n                    Label: Resources.Loading.PaymentVoucher.Applying\n                });\n\n                $.ajax({\n                    method: 'POST',\n                    url: Urls.PaymentVoucher.Apply,\n                    contentType: 'application/json',\n                    data: JSON.stringify({\n                        number: $paymentVoucherNumber.val(),\n                        amount: null\n                    }),\n                    dataType: 'json',\n                    success: function (data) {\n                        $paymentApplyButton.loading('destroy');\n                        $paymentApplied.loading('destroy');\n                        \n                        if (data.success) {\n                            $paymentVoucherNumber.val('');\n                            \n                            if (data.amountApplied && data.amountApplied.value > 0) {\n                            \t$paymentsApplied.find('[data-id=\"' + data.id + '\"]').remove();                            \t\n                                $paymentApplied.attr('data-id', data.id);\n\n                                var rowContentHtml = _.template($('#template-paymentvoucher-row-content').html(), TemplateConstants.Lodash.Settings)({\n                                    paymentNumber: data.number,\n                                    amountApplied: data.amountApplied.displayValue\n                                });\n\n                                $paymentApplied.html(rowContentHtml);\n                            }\n                            \n                            if (data.message) {\n                            \t$paymentErrorMessage.html(data.message).show();\n                            }\n\n                            $(document).trigger('Cart.Update');\n                        } else {\n                        \tif (data.message == 'Invalid Message') {\n                        \t\tdata.message = Resources.Error.Generic;\t\n                        \t}\n                        \t\n                            $paymentApplied.remove();\n                            $paymentErrorMessage.html(data.message || Resources.Error.Generic).show();\n                        }\n                        \n\t\t\t\t\t\tif (recaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(recaptcha);\n\t\t\t\t\t\t}\n                    },\n                    error: function() {\n\t\t\t\t\t\t$paymentApplyButton.loading('destroy');\n\t\t\t\t\t\t$paymentApplied.remove();\n\t\t\t\t\t\t$paymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (recaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(recaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                });\n            } else {\n            \tif (recaptcha != undefined) {\n\t\t\t\t\tgrecaptcha.reset(recaptcha);\n\t\t\t\t}\t\n            }\n        }\n    });\n\n    $(document).off('mousedown.paymentPanel').on('mousedown.paymentPanel', function (event) {\n        if (validator && $(event.target).closest($paymentContainer).length == 0) {\n            validator.resetForm();\n            $paymentErrorMessage.html('').hide();\n        }\n    });\n\n    $(document).on('CartData.Update', function (event, data) {\n    \t$('[has-gift-cards]').attr('has-gift-cards', data.HasGiftCards || false);\n\t    $('[has-gift-cards-only]').attr('has-gift-cards-only', data.HasGiftCardsOnly || false);\n\t    \n\t    if (data.HasGiftCards && !data.AllowpurchaseWithGiftCard) {\n\t    \t$paymentMessage.html(Resources.GiftCard.purchaseWithGiftCardNotAllowed);\n\t    \t$paymentContainer.attr('status', 'locked');\n\t    } else {\n\t    \t$paymentMessage.html('');\n\t    \t$paymentContainer.attr('status', 'active');\n\t    }\n    });\n    \n    $(document).on('GiftCard.Clear', function () {\n        $paymentsApplied.html('');\n        $('.order-balance-due').html('');\n    });\n\n    $paymentContainer.on('click', '.remove:not([loading])', function (event) {\n        event.preventDefault();\n\n        var $row = $(this).closest('.form-payment-applied');\n        $row.loading({\n            Label: Resources.Loading.GiftCard.Removing\n        });\n        $paymentErrorMessage.html('').hide();\n\n        $.ajax({\n            url : Urls.PaymentVoucher.Remove,\n            type : 'POST',\n            contentType: 'application/json',\n            data: JSON.stringify({\n                id: $row.data('id')\n            }),\n            dataType : 'json',\n            success : function(data) {\n            \t$row.loading('destroy');\n            \t\n                if (data.success) {\n                    $row.remove();\n\n                    $(document).trigger('Cart.Update');\n                } else {\n                \t$paymentErrorMessage.html(data.error || Resources.Error.Generic).show();\n                }\n            },\n            error: function() {\n\t\t\t\t$row.loading('destroy');\n\t\t\t\t$paymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t}\n        });\n    });\n}\n","'use strict';\n/* global Resources, Urls */\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../../components/LoadingIndicator');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar opcpayment = require('./opcpayment');\nvar util = require('../../util');\n\nexports.initialize = initialize;\n\nvar $rewardsPaymentContainer = $('[payment-method=\"REWARDS_CREDIT\"][has-rewardsnumber]');\nvar $rewardsPaymentsForm = $rewardsPaymentContainer.find('form');\nvar $rewardsPaymentsApplied = $rewardsPaymentContainer.find('.rewards-applied');\nvar $rewardsPaymentInput = $rewardsPaymentContainer.find('#dwfrm_billing_rewards_rewardsNumber');\nvar $rewardsEmailInput = $rewardsPaymentContainer.find('#dwfrm_billing_rewards_rewardsEmail');\nvar $rewardsPhoneNumberInput = $rewardsPaymentContainer.find('#dwfrm_billing_rewards_rewardsPhoneNumber');\nvar $rewardsZipCodeInput = $rewardsPaymentContainer.find('#dwfrm_billing_rewards_rewardsZipCode');\nvar $rewardsPaymentSecondaryContainer = $rewardsPaymentContainer.find('.rewards-secondary');\nvar $rewardsPaymentSecondarySelect = $rewardsPaymentContainer.find('#rewards-secondary-select');\nvar $rewardsPaymentErrorMessage = $rewardsPaymentContainer.find('span.error');\nvar rewardsCreditValidator;\nvar rewardsCreditRowTemplate = _.template($('#template-rewards-credit-row').html(), TemplateConstants.Lodash.Settings);\nvar rewardsCreditRecaptcha;\nvar options = {};\nvar loaded = {};\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && $('#rewards-credit-add-button').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForRewardsCredit && options.Recaptcha.GoogleSiteKey) {\n\t\trewardsCreditRecaptcha = grecaptcha.render('rewards-credit-add-button', {\n\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t        callback: submitRewardsCredit,\n\t        badge: 'bottomleft'\n\t    });\n\t}\n}\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter || {};\n\t\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n\n\tif ($rewardsPaymentSecondarySelect.closest('.opc-summary').length > 0) {\n\t\t$rewardsPaymentSecondarySelect.selectmenu({\n\t\t\twidth: '100%',\n\t\t\tappendTo: '[payment-method=\"REWARDS_CREDIT\"] .rewards-secondary',\n\t\t\tchange: function(event, ui) {\n\t\t\t\t$rewardsPaymentSecondaryContainer.attr('secondary', ui && ui.item && ui.item.value ? ui.item.value : '');\n\t\t\t}\n\t\t});\n\t}\n\t\n\t$rewardsPaymentContainer.on('click', '.reset', function(event) {\n\t\tevent.preventDefault();\n\t\tresetSecondarySelect();\n\t});\n\n\t$rewardsPaymentContainer.on('click', '.add', function(event) {\n\t\tevent.preventDefault();\n\t\t\n        if (!options || !options.Recaptcha || !options.Recaptcha.EnabledForRewardsCredit || !options.Recaptcha.GoogleSiteKey) {\n            $(document).trigger('RewardsCredit.Add'); \n        }\n\t});\n\t\n\t$(document).on('RewardsCredit.Add', function(event, data) {\n\t\tevent.preventDefault();\n\n\t\tif (parseFloat($('[balance-due]').first().attr('balance-due')) <= 0) {\n\t\t\t$rewardsPaymentErrorMessage.html(Resources.RewardsCredit.NoBalanceDue).show();\n\t\t} else {\n\t\t\tvar rewardsSecondaryFactor = $rewardsPaymentSecondaryContainer.attr('secondary');\n\t\t\trewardsCreditValidator = $rewardsPaymentsForm.validate();\n            $rewardsPaymentInput.rules('add', ValidationRules.RewardsCredit.Number);\n\n\t\t\tswitch (rewardsSecondaryFactor) {\n\t\t\t\tcase \"zipcode\":\n\t\t\t\t\t$.validator.addMethod('zipCode', ValidationHelper.ValidateZipCode, Resources.INVALID_POSTAL_CODE);\n\t\t\t\t\t$rewardsZipCodeInput.rules('add', ValidationRules.ZipCode);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n            rewardsCreditValidator.form();\n\n\t\t\t// Adding ADA compliance error messages for giftCardPayment section\n            if ($rewardsPaymentsForm.find('.field.error').length > 0) {\n\t\t\t\t$('.payment-declined').remove();\n                var rewardsPaymentFormErrorMessages = opcpayment.getErrorMessages($rewardsPaymentsForm);\n                var rewardsPaymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', rewardsPaymentFormErrorMessages);\n                if (rewardsPaymentFormErrorBox) {\n                    $rewardsPaymentsApplied.after(rewardsPaymentFormErrorBox);\n                }\n            }\n\t\t\t\n            if (Urls && Urls.checkRewards && rewardsCreditValidator.valid()) {\n            \t$rewardsPaymentsForm.hide();\n            \t\n\t\t\t\tvar $rewardsCreditRow = $(rewardsCreditRowTemplate());\n\t\t\t\t$rewardsCreditRow = $rewardsCreditRow.appendTo($rewardsPaymentsApplied);\n\t\t\t\t$rewardsCreditRow.attr('status', 'pending');\n\t\t\t\t$rewardsCreditRow.find('.basketRewardNumber').html(util.getMaskedNumber($rewardsPaymentInput.val(), 4, 'xxxx... '));\n\t\n\t\t\t\t$rewardsCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t\t\t$rewardsCreditRow.find('.form-controls').loading({Label: Resources.Loading.RewardsCredit.Loading});\n\t\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: data && data.Registered ? Urls.checkRewardsForRegistered : Urls.checkRewards,\n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcsrf_token:  $rewardsPaymentContainer.find('input[name=\"csrf_token\"]').val(),\n\t\t\t\t\t\trewardsNumber: $rewardsPaymentInput.val(),\n\t\t\t\t\t\trewardsEmail: $rewardsEmailInput.val(),\n\t\t\t\t\t\trewardsPhoneNumber: $rewardsPhoneNumberInput.val(),\n\t\t\t\t\t\trewardsZipCode: $rewardsZipCodeInput.val()\n\t\t\t\t\t},\n\t\t\t\t\tdataType: 'json',\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t$rewardsPaymentErrorMessage.html('').hide();\n\t\n\t\t\t\t\t\tif ($rewardsCreditRow.find('.btn[loading]').length > 0) {\n\t\t\t\t\t\t\t$rewardsCreditRow.find('.btn').loading('destroy');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ($rewardsCreditRow.find('.form-controls[loading]').length > 0) {\n\t\t\t\t\t\t\t$rewardsCreditRow.find('.form-controls').loading('destroy');\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tif (data && data.error !== 'undefined' && data.error === true) {\n\t\t\t\t\t\t\t$rewardsCreditRow.remove();\n\t\t\t\t\t\t\t$rewardsPaymentsForm.show();\n\t\t\t\t\t\t\t$rewardsPaymentErrorMessage.html(data.errorMsg).show();\n\t\t\t\t\t\t} else if (data && parseFloat(data.creditAmount) <= 0) {\n\t\t\t\t\t\t\t$rewardsPaymentContainer.attr('has-rewardsnumber', 'true');\n\t\t\t\t\t\t\t$rewardsCreditRow.attr('status', 'message');\n\t\t\t\t\t\t\t$rewardsCreditRow.find('.message').html(Resources.RewardsCredit.NoBalanceAvailable);\n\t\t\t\t\t\t} else if (data && data.creditAmountFormatted) {\n\t\t\t\t\t\t\t$rewardsPaymentContainer.attr('has-rewardsnumber', 'true');\n\t\t\t\t\t\t\t$rewardsCreditRow.find('.basketRewardAmount').html(data.creditAmountFormatted.replace('.00', ''));\n\t\t\t\t\t\t\t$rewardsCreditRow.find('.expiration-date').html(data.creditExpirationDate);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (rewardsCreditRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(rewardsCreditRecaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\t$rewardsCreditRow.remove();\n\t\t\t\t\t\t$rewardsPaymentsForm.show();\n\t\t\t\t\t\t$rewardsPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (rewardsCreditRecaptcha != undefined) {\n\t\t\t\t\t\t\tgrecaptcha.reset(rewardsCreditRecaptcha);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n            }\n\t\t}\n\t});\n\n\t$rewardsPaymentContainer.on('click', '.apply', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $rewardsCreditRow = $(this).closest('.reward-row');\n\n\t\t$rewardsCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t$rewardsCreditRow.find('.form-controls').loading({Label: Resources.Loading.RewardsCredit.Applying});\n\n\t\t$.ajax({\n\t\t\turl: Urls.applyRewards,\n\t\t\ttype: 'POST',\n\t\t\tdata: {\n\t\t\t\tcsrf_token:  $rewardsPaymentContainer.find('input[name=\"csrf_token\"]').val(),\n\t\t\t\trewardsNumber: $rewardsPaymentInput.val(),\n\t\t\t\trewardsEmail: $rewardsEmailInput.val(),\n\t\t\t\trewardsPhoneNumber: $rewardsPhoneNumberInput.val(),\n\t\t\t\trewardsZipCode: $rewardsZipCodeInput.val()\n\t\t\t},\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\t$rewardsPaymentErrorMessage.html('').hide();\n\t\t\t\tif ($rewardsCreditRow.find('.btn[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.btn').loading('destroy');\n\t\t\t\t}\n\t\t\t\tif ($rewardsCreditRow.find('.form-controls[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.form-controls').loading('destroy');\n\t\t\t\t}\n\n\t\t\t\tif (data.error !== 'undefined' && data.error === true) {\n\t\t\t\t\t$rewardsCreditRow.attr('status', 'message');\n\t\t\t\t\t$rewardsPaymentInput.val('');\n\t\t\t\t\t$rewardsCreditRow.remove();\n\t\t\t\t\t$rewardsPaymentsForm.show();\n\t\t\t\t\t$rewardsPaymentErrorMessage.html(data.errorMsg).show();\n\t\t\t\t} else {\n\t\t\t\t\t$rewardsCreditRow.attr('status', 'applied');\n\t\t\t\t\t$rewardsCreditRow.find('.basketRewardNumber').html(util.getMaskedNumber(data.rewardsNumber, 4, 'xxxx... '));\n\t\t\t\t\t$rewardsCreditRow.find('.basketRewardAmount').html(data.rewardsCreditUsedFormatted).attr('label', Resources.RewardsCredit.RewardApplied);\n\t\t\t\t\t$rewardsCreditRow.find('.expiration-date').html(data.creditExpirationDate);\n\n\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\tvalue: data.rewardsCreditUsed,\n\t\t\t\t\t\tpayment_type: 'B Rewarded'\n\t\t\t\t\t}\n\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo', dataObject);\n\t\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\t$rewardsCreditRow.attr('status', 'message');\n\t\t\t\t$rewardsPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t\tresetForm(true);\n\t\t\t},\n\t\t\tcomplete: function(data, status, xhr) {\n\t\t\t\tif (data.status == 302 && data.responseText) {\n\t\t\t\t\tlocation.href = data.responseText;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t$rewardsPaymentContainer.on('click RewardsCredit.Remove', '.remove', function(event, data) {\n\t\tevent.preventDefault();\n\n\t\tvar $rewardsCreditRow = $(this).closest('.reward-row');\n\t\t$rewardsCreditRow.find('.btn').loading({IsLabelShown: false});\n\t\t$rewardsCreditRow.find('.form-controls').loading({Label: Resources.Loading.RewardsCredit.Removing});\n\n\t\tvar payload = {\n\t\t\trewardsNumber: $('input#dwfrm_billing_rewards_rewardsNumber').val()\n\t\t}\n\n\t\tif (data && data.ResetSessionData) {\n\t\t\tpayload.resetSessionData = true\n\t\t}\n\n\t\t$.ajax({\n\t\t\turl: Urls.removeRewards,\n\t\t\ttype: 'POST',\n\t\t\tdataType: 'json',\n\t\t\tdata: payload,\n\t\t\tsuccess: function() {\n\t\t\t\t$rewardsPaymentErrorMessage.html('').hide();\n\n\t\t\t\tif ($rewardsCreditRow.find('.btn[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.btn').loading('destroy');\n\t\t\t\t}\n\t\t\t\tif ($rewardsCreditRow.find('.form-controls[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.form-controls').loading('destroy');\n\t\t\t\t}\n\n\t\t\t\tif ($rewardsPaymentContainer.attr('has-rewardsnumber') !== 'true') {\n\t\t\t\t\t$rewardsPaymentInput.val('');\n\t\t\t\t\t$rewardsPaymentsForm.show();\n\t\t\t\t\t$rewardsCreditRow.attr('status', 'form');\n\t\t\t\t\t$rewardsPaymentsApplied.html('');\n\t\t\t\t} else {\n\t\t\t\t\t$rewardsCreditRow.attr('status', 'pending');\n\t\t\t\t\t$rewardsCreditRow.find('.basketRewardAmount').attr('label', Resources.RewardsCredit.Reward);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t},\n            error: function() {\n\t\t\t\tif ($rewardsCreditRow.find('.btn[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.btn').loading('destroy');\n\t\t\t\t}\n\t\t\t\tif ($rewardsCreditRow.find('.form-controls[loading]').length > 0) {\n\t\t\t\t\t$rewardsCreditRow.find('.form-controls').loading('destroy');\n\t\t\t\t}\n\n\t\t\t\t$rewardsPaymentErrorMessage.html(Resources.Error.Generic).show();\n\t\t\t}\n\t\t});\n\t});\n\t\n\t$rewardsPaymentContainer.on('click', '.change', function(event) {\n\t\tevent.preventDefault();\n\t\t\n\t\t$rewardsPaymentContainer.attr('has-rewardsnumber', 'false');\n\t\tif ($rewardsPaymentsApplied.find('.reward-row').attr('status') === 'applied') {\n\t\t\t$rewardsPaymentContainer.find('.remove').trigger('RewardsCredit.Remove');\n\t\t}\n\t\tresetForm();\n\t});\n\n\t$(document).off('mousedown.RewardsCreditPaymentPanel').on('mousedown.RewardsCreditPaymentPanel', function (event) {\n        if (rewardsCreditValidator && $(event.target).closest($rewardsPaymentContainer).length == 0) {\n            rewardsCreditValidator.resetForm();\n            $rewardsPaymentErrorMessage.html('').hide();\n        }\n    });\n\t\n\t$(document).on('RewardsCredit.Clear', function(event) {\n\t\tevent.preventDefault();\n\t\tresetForm();\n\t});\n\n\t$rewardsPaymentContainer.on('click', '.reset', function(event) {\n\t\tevent.preventDefault();\n\t\t$rewardsPaymentsForm.show();\n\t\t$rewardsPhoneNumberInput.val('');\n\t\t$rewardsZipCodeInput.val('');\n\t});\n\t\n\tif ($rewardsPaymentContainer.attr('has-rewardsnumber') === 'true' && $rewardsPaymentsApplied.find('.reward-row').length == 0 && $('[checkout-mode]').attr('checkout-mode') != 'echo') {\n\t\t$(document).trigger('RewardsCredit.Add', { Registered: true });\n\t}\n}\n\nfunction resetForm(showErrorMessage) {\n\tif (rewardsCreditValidator) {\n\t\trewardsCreditValidator.resetForm();\n\t}\n\t\n\tif (!showErrorMessage) {\n\t\t$rewardsPaymentErrorMessage.html('').hide();\n\t}\n\t\n\tvar $rewardsCreditRow = $rewardsPaymentsApplied.find('.reward-row');\n\tif ($rewardsPaymentContainer.attr('has-rewardsnumber') !== 'true') {\n\t\t$rewardsPaymentInput.val('');\n\t\t$rewardsPhoneNumberInput.val('');\n\t\t$rewardsZipCodeInput.val('');\n\t\t\n\t\t$rewardsPaymentsForm.show();\n\t\t$rewardsPaymentsApplied.html('');\n\t} else {\n\t\t$rewardsCreditRow.find('.basketRewardAmount').attr('label', Resources.RewardsCredit.Reward);\n\t}\n\n\tresetSecondarySelect();\n}\n\nfunction resetSecondarySelect() {\n\t$rewardsPaymentSecondarySelect.prop('selectedIndex', 0);\n\tif ($rewardsPaymentSecondarySelect.closest('.opc-summary').length > 0) {\n\t\t$rewardsPaymentSecondarySelect.selectmenu('refresh');\n\t}\n\t$rewardsPaymentSecondaryContainer.attr('secondary', '');\n}","'use strict';\n\nvar util = require('../../util');\nvar shipping = require('./shipping');\n\n/**\n * @function\n * @description Selects the first address from the list of addresses\n */\nexports.init = function () {\n    var $form = $('.address');\n    // select address from list\n    $('select[name$=\"_addressList\"]', $form).on('change', function () {\n        var selected = $(this).children(':selected').first();\n        var selectedAddress = $(selected).data('address');\n        if (!selectedAddress) { return; }\n        util.fillAddressFields(selectedAddress, $form);\n        shipping.updateShippingMethodList();\n        // re-validate the form\n        $form.validate().form();\n    });\n};\n","'use strict';\n\nvar ajax = require('../../ajax');\nvar formPrepare = require('./formPrepare');\nvar giftcard = require('../../giftcard');\nvar util = require('../../util');\n\nvar PaymentMethodConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\n\n/**\n * @function\n * @description Fills the Credit Card form with the passed data-parameter and clears the former cvn input\n * @param {Object} data The Credit Card data (holder, type, masked number, expiration month/year)\n */\nfunction setCCFields(data) {\n    var $creditCard = $('[data-method=\"' + PaymentMethodConstants.CreditCard + '\"]');\n    $creditCard.find('input[name$=\"creditCard_owner\"]').val(data.holder).trigger('change');\n    $creditCard.find('select[name$=\"_type\"]').val(data.type).trigger('change');\n    $creditCard.find('input[name*=\"_creditCard_number\"]').val(data.maskedNumber).trigger('change');\n    $creditCard.find('[name$=\"_month\"]').val(data.expirationMonth).trigger('change');\n    $creditCard.find('[name$=\"_year\"]').val(data.expirationYear).trigger('change');\n    $creditCard.find('input[name$=\"_cvn\"]').val('').trigger('change');\n}\n\n/**\n * @function\n * @description Updates the credit card form with the attributes of a given card\n * @param {String} cardID the credit card ID of a given card\n */\nfunction populateCreditCardForm(cardID) {\n    // load card details\n    var url = util.appendParamToURL(Urls.billingSelectCC, 'creditCardUUID', cardID);\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            if (!data) {\n                window.alert(Resources.CC_LOAD_ERROR);\n                return false;\n            }\n            setCCFields(data);\n        }\n    });\n}\n\n\nfunction populatePrivateLabelCardForm(cardID) {\n    // load card details\n    var url = util.appendParamToURL(Urls.billingSelectPrivateLabel, 'creditCardUUID', cardID);\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            if (!data) {\n                window.alert(Resources.CC_LOAD_ERROR);\n                return false;\n            }\n            var $privateLabelCard = $('[data-method=\"' + PaymentMethodConstants.AllianceData + '\"]');\n            $privateLabelCard.find('input[name*=\"_privateLabelCredit_number\"]').val(data.maskedNumber).trigger('change');\n        }\n    });\n}\n\n\n/**\n * @function\n * @description Changes the payment method form depending on the passed paymentMethodID\n * @param {String} paymentMethodID the ID of the payment method, to which the payment method form should be changed to\n */\nfunction updatePaymentMethod(paymentMethodID) {\n    var $paymentMethods = $('.payment-method');\n    $paymentMethods.removeClass('payment-method-expanded');\n\n    var $selectedPaymentMethod = $paymentMethods.filter('[data-method=\"' + paymentMethodID + '\"]');\n    if ($selectedPaymentMethod.length === 0) {\n        $selectedPaymentMethod = $('[data-method=\"Custom\"]');\n    }\n    $selectedPaymentMethod.addClass('payment-method-expanded');\n\n    // ensure checkbox of payment method is checked\n    $('input[name$=\"_selectedPaymentMethodID\"]').removeAttr('checked');\n    $('input[value=' + paymentMethodID + ']').prop('checked', 'checked');\n\n    formPrepare.validateForm();\n}\n\n/**\n * @function\n * @description loads billing address, Gift Certificates, Coupon and Payment methods\n */\nexports.init = function () {\n    var $checkoutForm = $('.checkout-billing');\n    var $addGiftCert = $('#add-giftcert');\n    var $giftCertCode = $('input[name$=\"_giftCertCode\"]');\n    var $addCoupon = $('#add-coupon');\n    var $couponCode = $('input[name$=\"_couponCode\"]');\n    var $selectPaymentMethod = $('.payment-method-options');\n    var selectedPaymentMethod = $selectPaymentMethod.find(':checked').val();\n\n    formPrepare.init({\n        formSelector: 'form[id$=\"billing\"]',\n        continueSelector: '[name$=\"billing_save\"]'\n    });\n\n    // default payment method to 'CREDIT_CARD'\n    updatePaymentMethod((selectedPaymentMethod) ? selectedPaymentMethod : PaymentMethodConstants.CreditCard);\n    $selectPaymentMethod.on('click', 'input[type=\"radio\"]', function () {\n        updatePaymentMethod($(this).val());\n    });\n\n    // select credit card from list\n    var $creditCardList = $('#creditCardList');\n    $creditCardList.on('change', function () {\n        var cardUUID = $(this).val();\n        if (!cardUUID) {return;}\n        populateCreditCardForm(cardUUID);\n\n        // remove server side error\n        $('.required.error').removeClass('error');\n        $('.error-message').remove();\n    });\n    \n    //preselect default credit card\n    if($creditCardList.length > 0){\n\t\t$creditCardList.find('option').eq(1).prop('selected', true);\n\t\t$creditCardList.trigger('change');\n\t}\n\n    \n    // select private label card from list\n    var $privateLabelCardList = $('#privateLabelCardList');\n    $privateLabelCardList.on('change', function () {\n        var cardUUID = $(this).val();\n        if (!cardUUID) {return;}\n        populatePrivateLabelCardForm(cardUUID);\n\n        // remove server side error\n        $('.required.error').removeClass('error');\n        $('.error-message').remove();\n    });\n\n    // preselect default private label card\n    if($privateLabelCardList.length > 0){\n    \t$privateLabelCardList.find('option').eq(1).prop('selected', true);\n    \t$privateLabelCardList.trigger('change');\n\t} \n    \n    $('#check-giftcert').on('click', function (e) {\n        e.preventDefault();\n        var $balance = $('.balance');\n        if ($giftCertCode.length === 0 || $giftCertCode.val().length === 0) {\n            var error = $balance.find('span.error');\n            if (error.length === 0) {\n                error = $('<span>').addClass('error').appendTo($balance);\n            }\n            error.html(Resources.GIFT_CERT_MISSING);\n            return;\n        }\n\n        giftcard.checkBalance($giftCertCode.val(), function (data) {\n            if (!data || !data.giftCertificate) {\n                $balance.html(Resources.GIFT_CERT_INVALID).removeClass('success').addClass('error');\n                return;\n            }\n            $balance.html(Resources.GIFT_CERT_BALANCE + ' ' + data.giftCertificate.balance).removeClass('error').addClass('success');\n        });\n    });\n\n    $addGiftCert.on('click', function (e) {\n        e.preventDefault();\n        var code = $giftCertCode.val(),\n            $error = $checkoutForm.find('.giftcert-error');\n        if (code.length === 0) {\n            $error.html(Resources.GIFT_CERT_MISSING);\n            return;\n        }\n\n        var url = util.appendParamsToUrl(Urls.redeemGiftCert, {giftCertCode: code, format: 'ajax'});\n        $.getJSON(url, function (data) {\n            var fail = false;\n            var msg = '';\n            if (!data) {\n                msg = Resources.BAD_RESPONSE;\n                fail = true;\n            } else if (!data.success) {\n                msg = data.message.split('<').join('&lt;').split('>').join('&gt;');\n                fail = true;\n            }\n            if (fail) {\n                $error.html(msg);\n                return;\n            } else {\n                window.location.assign(Urls.billing);\n            }\n        });\n    });\n\n    $addCoupon.on('click', function (e) {\n        e.preventDefault();\n        var $error = $checkoutForm.find('.coupon-error'),\n            code = $couponCode.val();\n        if (code.length === 0) {\n            $error.html(Resources.COUPON_CODE_MISSING);\n            return;\n        }\n\n        var url = util.appendParamsToUrl(Urls.addCoupon, {couponCode: code, format: 'ajax'});\n        $.getJSON(url, function (data) {\n            var fail = false;\n            var msg = '';\n            if (!data) {\n                msg = Resources.BAD_RESPONSE;\n                fail = true;\n            } else if (!data.success) {\n                msg = data.message.split('<').join('&lt;').split('>').join('&gt;');\n                fail = true;\n            }\n            if (fail) {\n                $error.html(msg);\n                return;\n            }\n\n            //basket check for displaying the payment section, if the adjusted total of the basket is 0 after applying the coupon\n            //this will force a page refresh to display the coupon message based on a parameter message\n            if (data.success && data.baskettotal === 0) {\n                window.location.assign(Urls.billing);\n            }\n        });\n    });\n\n    // trigger events on enter\n    $couponCode.on('keydown', function (e) {\n        if (e.which === 13) {\n            e.preventDefault();\n            $addCoupon.click();\n        }\n    });\n    $giftCertCode.on('keydown', function (e) {\n        if (e.which === 13) {\n            e.preventDefault();\n            $addGiftCert.click();\n        }\n    });\n};\n","'use strict';\n\nvar _ = require('lodash');\n\nvar $form, $continue, $requiredInputs, validator;\n\nvar hasEmptyRequired = function () {\n    // filter out only the visible fields\n    var requiredValues = $requiredInputs.filter(':visible').map(function () {\n        return $(this).val();\n    });\n    return _(requiredValues).contains('');\n};\n\nvar validateForm = function () {\n    // only validate form when all required fields are filled to avoid\n    // throwing errors on empty form\n    if (!validator) {\n        return;\n    }\n    if (!hasEmptyRequired()) {\n        if (validator.form()) {\n            $continue.removeAttr('disabled');\n        }\n    } else {\n        $continue.attr('disabled', 'disabled');\n    }\n};\n\nvar validateEl = function () {\n    if ($(this).val() === '') {\n        $continue.attr('disabled', 'disabled');\n    } else {\n        // enable continue button on last required field that is valid\n        // only validate single field\n        if (validator.element(this) && !hasEmptyRequired()) {\n            $continue.removeAttr('disabled');\n        } else {\n            $continue.attr('disabled', 'disabled');\n        }\n    }\n};\n\nvar init = function (opts) {\n    if (!opts.formSelector || !opts.continueSelector) {\n        throw new Error('Missing form and continue action selectors.');\n    }\n    $form = $(opts.formSelector);\n    $continue = $(opts.continueSelector);\n    validator = $form.validate();\n    $requiredInputs = $('.required', $form).find(':input');\n    validateForm();\n    // start listening\n    $requiredInputs.on('change', validateEl);\n    $requiredInputs.filter('input').on('keyup', _.debounce(validateEl, 200));\n};\n\nexports.init = init;\nexports.validateForm = validateForm;\nexports.validateEl = validateEl;\n","'use strict';\n\nvar address = require('./address'),\n    billing = require('./billing'),\n    multiship = require('./multiship'),\n    shipping = require('./shipping');\n\n/**\n * @function Initializes the page events depending on the checkout stage (shipping/billing)\n */\nexports.init = function () {\n    address.init();\n    if ($('.checkout-shipping').length > 0) {\n        shipping.init();\n    } else if ($('.checkout-multi-shipping').length > 0) {\n        multiship.init();\n    } else {\n        billing.init();\n    }\n\n    //if on the order review page and there are products that are not available diable the submit order button\n    if ($('.order-summary-footer').length > 0) {\n        if ($('.notavailable').length > 0) {\n            $('.order-summary-footer .submit-order .button-fancy-large').attr('disabled', 'disabled');\n        }\n    }\n};\n","'use strict';\n\nvar address = require('./address'),\n    formPrepare = require('./formPrepare'),\n    dialog = require('../../dialog'),\n    util = require('../../util');\n\n/**\n * @function\n * @description Initializes gift message box for multiship shipping, the message box starts off as hidden and this will display it if the radio button is checked to yes, also added event handler to listen for when a radio button is pressed to display the message box\n */\nfunction initMultiGiftMessageBox() {\n    $.each($('.item-list'), function () {\n        var $this = $(this);\n        var $giftMessage = $this.find('.gift-message-text');\n\n        //handle initial load\n        $giftMessage.toggleClass('hidden', $('input[name$=\"_isGift\"]:checked', this).val() !== 'true');\n\n        //set event listeners\n        $this.on('change', function () {\n            $giftMessage.toggleClass('hidden', $('input[name$=\"_isGift\"]:checked', this).val() !== 'true');\n        });\n    });\n}\n\n\n/**\n * @function\n * @description capture add edit adddress form events\n */\nfunction addEditAddress(target) {\n    var $addressForm = $('form[name$=\"multishipping_editAddress\"]'),\n        $addressDropdown = $addressForm.find('select[name$=_addressList]'),\n        $addressList = $addressForm.find('.address-list'),\n        add = true,\n        selectedAddressUUID = $(target).parent().siblings('.select-address').val();\n\n    $addressDropdown.on('change', function (e) {\n        e.preventDefault();\n        var selectedAddress = $addressList.find('select').val();\n        if (selectedAddress !== 'newAddress') {\n            selectedAddress = $.grep($addressList.data('addresses'), function (add) {\n                return add.UUID === selectedAddress;\n            })[0];\n            add = false;\n            // proceed to fill the form with the selected address\n            util.fillAddressFields(selectedAddress, $addressForm);\n        } else {\n            //reset the form if the value of the option is not a UUID\n            $addressForm.find('.input-text, .input-select').val('');\n        }\n    });\n\n    $addressForm.on('click', '.cancel', function (e) {\n        e.preventDefault();\n        dialog.close();\n    });\n\n    $addressForm.on('submit', function (e) {\n        e.preventDefault();\n        $.getJSON(Urls.addEditAddress, $addressForm.serialize(), function (response) {\n            if (!response.success) {\n                // @TODO: figure out a way to handle error on the form\n                return;\n            }\n            var address = response.address,\n                $shippingAddress = $(target).closest('.shippingaddress'),\n                $select = $shippingAddress.find('.select-address'),\n                $selected = $select.find('option:selected'),\n                newOption = '<option value=\"' + address.UUID + '\">' +\n                    ((address.ID) ? '(' + address.ID + ')' : address.firstName + ' ' + address.lastName) + ', ' +\n                    address.address1 + ', ' + address.city + ', ' + address.stateCode + ', ' + address.postalCode +\n                    '</option>';\n            dialog.close();\n            if (add) {\n                $('.shippingaddress select').removeClass('no-option').append(newOption);\n                $('.no-address').hide();\n            } else {\n                $('.shippingaddress select').find('option[value=\"' + address.UUID + '\"]').html(newOption);\n            }\n            // if there's no previously selected option, select it\n            if ($selected.length === 0 || $selected.val() === '') {\n                $select.find('option[value=\"' + address.UUID + '\"]').prop('selected', 'selected').trigger('change');\n            }\n        });\n    });\n\n    //preserve the uuid of the option for the hop up form\n    if (selectedAddressUUID) {\n        //update the form with selected address\n        $addressList.find('option').each(function () {\n            //check the values of the options\n            if ($(this).attr('value') === selectedAddressUUID) {\n                $(this).prop('selected', 'selected');\n                $addressDropdown.trigger('change');\n            }\n        });\n    }\n}\n\n/**\n * @function\n * @description shows gift message box in multiship, and if the page is the multi shipping address page it will call initmultishipshipaddress() to initialize the form\n */\nexports.init = function () {\n    initMultiGiftMessageBox();\n    if ($('.cart-row .shippingaddress .select-address').length > 0) {\n        formPrepare.init({\n            continueSelector: '[name$=\"addressSelection_save\"]',\n            formSelector: '[id$=\"multishipping_addressSelection\"]'\n        });\n    }\n    $('.edit-address').on('click', 'a', function (e) {\n        dialog.open({url: this.href, options: {open: function () {\n            address.init();\n            addEditAddress(e.target);\n        }}});\n    });\n};\n","'use strict';\n\nvar ajax = require('../../ajax'),\n\tformPrepare = require('./formPrepare'),\n\tprogress = require('../../progress'),\n    tooltip = require('../../tooltip'),\n\t\tutil = require('../../util'),\n\t\tcart = require('../cart'),\n\tshipping = require('./shipping'),\n\tTPromise = require('promise');\n\nvar shippingMethods;\n\nfunction initializeEvents() {\n\t$(document).on('change', '#dwfrm_billingaddress_country', function(){\n\t\trenderOptions('#dwfrm_billingaddress_states_state', '#dwfrm_billingaddress_country');\n\t\tvar $initialState = $('.bill-address-fields .initial-state');\n\t\tif ($initialState.length > 0 && $initialState.val() != '') {\n\t\t\t$('#dwfrm_billingaddress_states_state').val($initialState.val());\n\t\t}\n\n\t\tif (this.value !== 'US' && this.value !== 'CA') {\n\t\t\t$('#dwfrm_billingaddress_states_state').parents('.formfield').hide();\n\t\t} else {\n\t\t\t$('#dwfrm_billingaddress_states_state').parents('.formfield').show();\n\t\t}\n\t});\n\t$('#dwfrm_billingaddress_country').trigger('change');\n\n\t$(document).on('change', '#dwfrm_shippingaddress_country', function(){\n\t\trenderOptions('#dwfrm_shippingaddress_states_state', '#dwfrm_shippingaddress_country');\n\t\tvar $initialState = $('.editaddress-shipping .initial-state');\n\t\tif ($initialState.length > 0 && $initialState.val() != '') {\n\t\t\t$('#dwfrm_shippingaddress_states_state').val($initialState.val());\n\t\t}\n\n\t\tif (this.value !== 'US' && this.value !== 'CA') {\n\t\t\t$('#dwfrm_shippingaddress_states_state').parents('.formfield').hide();\n\t\t} else {\n\t\t\t$('#dwfrm_shippingaddress_states_state').parents('.formfield').show();\n\t\t}\n\n\t\tif($(this).val().toUpperCase() == 'US'){\n\t\t\t$('#shipping-international-info').hide();\n\t\t} else {\n\t\t\t$('#shipping-international-info').show();\n\t\t}\n\t});\n\t$('#dwfrm_shippingaddress_country').trigger('change');\n\n\t$(document).on('change', 'form [id*=\"_postal\"]', function () {\n\t\tvar $this = $(this);\n\t\t$this.val($this.val().toUpperCase());\n\t});\n\n\t$('.address-section').addClass('active');\n\n\t$('.shipping-same').on('click', function(){\n\t\t//$('.shipping-address-section').addClass('hidden');\n\t\t//$('#submitBilling').show();\n\t\tif($('.shipping-same').is(':checked')){\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t\t} else {\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t\t}\n\n\t});\n\n\t$('.add-diff').on('click', function(){\n\t\t//$('.shipping-address-section').removeClass('hidden');\n\t\t//$('#submitBilling').hide();\n\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t});\n\n\t/*BOOT-1186 explains behavior check before update*/\n\t$('.billing-address-form').on('click', '.edit-address-det', function (e) {\n\t\te.preventDefault();\n\n\t\tif($('.billing-address-type-selector input:checked').val() == 1){\n\t\t\t$('.billing-select-address').show();\n\t\t} else {\n\t\t\t$('.bill-address-fields').show();\n\t\t\t$('.billing-select-address').hide();\n\t\t}\n\n\t\t$('.billing-address-preview').hide();\n\t\t$('.billing-address-data.form-info').hide();\n\t\t$('.billing-address-form').show();\n\t\t$('#billingAddressForm').show();\n\t\t$('.shipping-address-form').data('hidden-editable', $('.shipping-address-data.form-info').html().length ? true : false).hide();\n\t\t$('.form-checkout.payment-section').removeClass('active').find('.shipping-payment-cont').addClass('hidden');\n\t});\n\n\t$('.shipping-address-section').on('click', '.edit-address-det', function (e) {\n\t\te.preventDefault();\n\n\t\t$('.shipping-address-form').data('hidden-editable', true).hide();\n\t\t$('.shipping-address-data').hide();\n\t\t$('.shipping-address-form').show();\n\t\t$('.billing-address-data.form-info').css('display', 'block');\n\t\t$('.form-checkout.payment-section').removeClass('active').find('.shipping-payment-cont').addClass('hidden');\n\t});\n\n\t$('.billing-address-type-selector input').on('click', function(e, saveFormVals){\n\t\tvar v = $(this).val();\n\t\tvar $billingAddressFormFields = $('#billingAddressForm .bill-address-fields');\n\t\tif(v == 1){\n\t\t\t$('.shipping-same').prop('checked', $billingAddressFormFields.data('same-checked') || false);\n\t\t\t$('.billing-select-address').show();\n\t\t\t$('.bill-address-fields').addClass('collapsed');\n\t\t\t$('.billing-address-preview').show();\n\t\t\t$('#dwfrm_billing_addressList').html($('#dwfrm_billing_addressList option:nth(0)'));\n\t\t\t$('.billing-address-preview').hide();\n\t\t\tvar $form = $('#billingAddressForm');\n\t\t\tvar selectedAddress = $('#dwfrm_billing_addressList option:nth(0)').data('address');\n\t\t\tutil.fillAddressFields(selectedAddress, $form);\n\n\t\t} else if(v == 2){\n\t\t\t$billingAddressFormFields.data('same-checked', $('.shipping-same').prop('checked'));\n\t\t\t$('.bill-address-fields .initial-state').val('');\n\t\t\t$('.billing-select-address').hide();\n\t\t\t$('.billing-address-preview').hide();\n\t\t\t$('.bill-address-fields').removeClass('collapsed');\n\t\t\tif(typeof saveFormVals == 'undefined' || !saveFormVals){\n\t\t\t\t$('#dwfrm_billing_addressList').val('');\n\t\t\t\t$billingAddressFormFields.find('input:text, input:password, input:file, textarea').not('input[name*=\"_email\"]').val('');\n\t\t\t\t$billingAddressFormFields.find('select option:selected').removeAttr('selected');\n\t\t\t\t$billingAddressFormFields.find('input:checkbox, input:radio').removeAttr('checked');\n\t\t\t}\n\t\t\t$('.shipping-same').prop('checked', true);\n\t\t\t$('#dwfrm_billingaddress_country').trigger('change');\n\t\t}\n\t\tif($('.shipping-same').is(':checked')){\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t\t} else {\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t\t}\n\t});\n\n\t$('.shipping-address-type-selector input').on('click', function(){\n\t\tvar v = $(this).val();\n\t\tvar $shippingAddressFormFields = $('#shippingAddressForm .editaddress-shipping');\n\t\tif(v == 1){\n\t\t\t$('.shipping-select-address').show();\n\t\t\t$('.editaddress-shipping').addClass('collapsed');\n\t\t\t$('.shipping-address-preview').html('').show();\n\t\t} else if(v == 2){\n\t\t\t$('.editaddress-shipping .initial-state').val('');\n\t\t\t$('.shipping-select-address').hide();\n\t\t\t$('.shipping-address-preview').hide();\n\t\t\t$('.editaddress-shipping').removeClass('collapsed');\n\t\t\t$('#dwfrm_singleshipping_addressList').val('');\n\t\t\t$shippingAddressFormFields.find('input:text, input:password, input:file, textarea').val('');\n\t\t\t$shippingAddressFormFields.find('select option:selected').removeAttr('selected');\n\t\t\t$shippingAddressFormFields.find('input:checkbox, input:radio').removeAttr('checked');\n\t\t\t$('#dwfrm_shippingaddress_country').trigger('change');\n\n\t\t}\n\t});\n\t/**\n\t * @function\n\t * @description Selects the first address from the list of addresses\n\t */\n\tvar $form = $('#billingAddressForm');\n    // select address from list\n    $('select[name$=\"_addressList\"]', $form).on('change', function () {\n        var selected = $(this).children(':selected').first();\n        var selectedAddress = $(selected).data('address');\n        if (!selectedAddress) { return; }\n        util.fillAddressFields(selectedAddress, $form);\n\n        $form.validate().form();\n    });\n\n    var shippingAddrForm = $('#shippingAddressForm');\n    $('select[name$=\"_addressList\"]', shippingAddrForm).on('change', function () {\n        var selected = $(this).children(':selected').first();\n        var selectedAddress = $(selected).data('address');\n        if (!selectedAddress) { return; }\n        util.fillAddressFields(selectedAddress, shippingAddrForm);\n\n        shippingAddrForm.validate().form();\n    });\n\n    //address submission\n    $('#submitBilling').on('click', function(e){\n    \te.preventDefault();\n    \t$('#submitBilling').attr('disabled', true);\n    \tprogress.show();\n\n    \t// prevent submitting saved address w/out a selection\n    \tif ($('.billing-address-type-selector input[value=1]').prop('checked') && $('#dwfrm_billing_addressList').val() == '') {\n    \t\t$('#submitBilling').attr('disabled', false);\n    \t\treturn;\n    \t}\n\n    \tif($('.shipping-same').is(':checked')){\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t\t} else {\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t\t}\n\n    \tvar $form = $('#billingAddressForm'),\n    \t\tactionName = $('#selectOpcAddress').attr('name');\n    \t$form.validate().settings.ignore = [\":not(.required)\"];\n    \t$form.validate().form();\n\n    \t$('.custom-email-error').remove();\n\n    \tvar isEmailValid = util.validateEmail($('#dwfrm_billingaddress_email').val());\n\n    \tif($form.valid() && isEmailValid){\n    \t\t//set billing address\n    \t\tsetOPCAddress('#billingAddressForm', actionName).then(function (response) {\n    \t\t\tvar data = JSON.parse(response);\n\n    \t\t\tif(data.status == 'success'){\n    \t\t\t\tupdateSummary();\n    \t\t\t\t$('#billingAddressForm').hide();\n\t        \t\t$('.billing-address-data').html('').append(buildDetailsBlock('#billingAddressForm')).show();\n\n    \t\t\t\tif($('.shipping-same').prop('checked')){\n    \t\t\t\t\tpopulateBillingToShipping('#shippingAddressForm', '#billingAddressForm');\n        \t    \t}\n    \t\t\t\t$('.shipping-address-cont').removeClass('hidden');\n\n    \t\t\t\tvar $shippingAddressForm = $('#shippingAddressForm');\n    \t\t\t\tif(SitePreferences.BYPASS_SHIPPING && $('.shipping-same').prop('checked')){\n    \t\t\t\t\tupdateShippingMethodList('#billingAddressForm');\n    \t\t\t\t\t$('.shipping-address-data').html('').append(buildDetailsBlock('#shippingAddressForm')).show();\n    \t\t\t\t\t$shippingAddressForm.hide();\n    \t\t\t\t\t$('#shippingAddressForm').data('shipping-filled', true);\n    \t\t\t\t\t$('.payment-section').addClass('active');\n    \t\t\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n        \t        \t$('.shipping-address-section').addClass('active');\n    \t\t\t\t} else {\n    \t\t\t\t\t$('.shipping-address-section').addClass('active');\n    \t\t\t\t\t$('.shipping-address-section').show();\n    \t\t\t\t\t$('.shipping-address-form').show();\n    \t\t\t\t}\n\n    \t\t\t\tif($('#shippingAddressForm').data('shipping-filled') == true){\n    \t\t\t\t\t$('.form-checkout.payment-section').addClass('active').find('.shipping-payment-cont').removeClass('hidden');\n    \t\t\t\t\t$shippingAddressForm.hide();\n    \t\t\t\t\t$('.shipping-address-data').show();\n    \t\t\t\t}\n\n    \t\t\t} else if(data.status == 'shippingRestrictionsError') {\n\t\t\t\t\topenRestrictionsPopup(data);\n    \t\t\t} else {\n    \t\t\t\tconsole.log('submission error');\n    \t\t\t}\n\n    \t\t\tprogress.hide();\n    \t\t\t$('#submitBilling').attr('disabled', false);\n    \t    }.bind(this));\n\n    \t} else {\n    \t\tprogress.hide();\n    \t\t$('#submitBilling').attr('disabled', false);\n\n    \t\tif (!isEmailValid && $form.valid()) {\n    \t\t\t$('#dwfrm_billingaddress_email').parent().append('<span class=\"error custom-email-error\">' + Resources.VALIDATE_EMAIL + '</span>');\n    \t\t}\n    \t\t$('.billing-address-type-selector input[value=\"2\"]').trigger('click', [true]);\n    \t}\n    });\n\n    $('#submitShipping').on('click', function(e){\n    \tvar $form = $('#shippingAddressForm'),\n\t\t\tactionName = $(this).attr('name');\n    \te.preventDefault();\n    \t$('#submitShipping').attr('disabled', true);\n    \tprogress.show();\n\n    \t// prevent submitting saved address w/out a selection\n    \tif ($('.shipping-address-type-selector input[value=1]').prop('checked') && $('#dwfrm_singleshipping_addressList').val() == '') {\n    \t\t$('#submitShipping').attr('disabled', false);\n    \t\treturn;\n    \t}\n\n    \t$form.validate().form();\n    \tif($form.valid()){\n    \t\tsetOPCAddress('#shippingAddressForm', actionName).then(function (response) {\n    \t\t\tvar data = JSON.parse(response);\n\n    \t\t\tif(data.status == 'success'){\n    \t\t\t\tupdateShippingMethodList('#shippingAddressForm');\n    \t\t\t\t$('#shippingAddressForm').data('shipping-filled', true);\n        \t\t\t$('#shippingAddressForm').hide();\n            \t\t$('.shipping-address-data').html('').append(buildDetailsBlock('#shippingAddressForm')).show();\n            \t\t//before proceed to payment check if billing address is correct\n            \t\tvar bilForm = $('#billingAddressForm');\n            \t\tbilForm.validate().settings.ignore = [\":not(.required)\"];\n\n            \t\tif(bilForm.valid()){\n            \t\t\tif($('#isShippingAddressSameAsBillingAddress').is(\":checked\")) { $('#isShippingAddressSameAsBillingAddress').click(); }\n            \t\t\t$('#submitBilling').click();\n\t            \t\t$('.shipping-payment-cont').removeClass('hidden');\n\t            \t\t$('.payment-section').addClass('active');\n                \t} else {\n                \t\t$('.shipping-payment-cont').addClass('hidden');\n\t            \t\t$('.payment-section').removeClass('active');\n\t            \t\t$('.billing-address-data.form-info').hide();\n\t            \t\tvar formBody = $('.billing-address-form');\n\t            \t\tformBody.show();\n\t            \t\tformBody.find('input.required.field.error').eq(0).focus();\n                \t}\n        \t\t\tupdateSummary();\n    \t\t\t} else {\n    \t\t\t\tconsole.log('submission error');\n    \t\t\t\tswitch (data.status) {\n    \t\t\t\t\tcase 'shippingRestrictionsError': {\n    \t\t\t\t\t\topenRestrictionsPopup(data);\n    \t\t\t\t\t}\n    \t\t\t\t}\n    \t\t\t}\n    \t\t\tprogress.hide();\n    \t\t\t$('#submitShipping').attr('disabled', false);\n    \t    }.bind(this));\n\n    \t} else {\n    \t\tprogress.hide();\n    \t\t$('#submitShipping').attr('disabled', false);\n    \t}\n\n    });\n\n\t$('.toggle.top, .toggle.bottom').on('click', function(e){\n    \te.preventDefault();\n    \t$('#internationalinfo').slideToggle();\n\t});\n\n\n\tvar billingSavedAddrDropdown = $('#dwfrm_billing_addressList');\n\t//preset default address if exists\n\tif(billingSavedAddrDropdown.length > 0 && billingSavedAddrDropdown.val() !== ''){\n\t\tsetTimeout(function(){\n\t\t\t//pass customer to second step in this case\n\t\t\t$('#billingAddressForm').hide();\n    \t\t$('.billing-address-data').html('').append(buildDetailsBlock('#billingAddressForm')).show();\n    \t\t$('.shipping-address-cont').removeClass('hidden');\n    \t\t$('.shipping-address-section').addClass('active');\n\t\t}, 13);\n\n\t}\n\n\tvar shippingSavedAddrDropdown = $('#dwfrm_singleshipping_addressList');\n\tif(shippingSavedAddrDropdown.length > 0 && shippingSavedAddrDropdown.val() !== ''){\n\t\tsetTimeout(function(){\n\t\t\tupdateShippingMethodList('#shippingAddressForm');\n\t\t\t//pass customer to third step in this case\n\t\t\t$('.shipping-address-data').html('').append(buildDetailsBlock('#shippingAddressForm')).show();\n\t        $('#shippingAddressForm').hide();\n\t\t\t$('.payment-section').addClass('active');\n\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n\t\t\t$('.shipping-address-cont').removeClass('hidden');\n\t\t\t$('#shippingAddressForm').data('shipping-filled', true);\n\t        updateSummary();\n\t\t}, 13);\n\t}\n\n\t//draw address preview on change\n\tbillingSavedAddrDropdown.on('change', function(){\n\t\tvar $this = $(this),\n\t\t\tupd = function(){\n\t\t\t\tvar el = $('.billing-address-preview').html('');\n\t\t\t\t$this.val() && el.append(buildDetailsBlock('#billingAddressForm', true)).show();\n\t\t\t};\n\n\t\tsetTimeout(upd, 13);\n\n\t});\n\tbillingSavedAddrDropdown.trigger('change');\n\n\t//draw address preview on change\n\tshippingSavedAddrDropdown.on('change', function(){\n\t\tvar $this = $(this),\n\t\t\tupd = function(){\n\t\t\t\tvar el = $('.shipping-address-preview').html('');\n\t\t\t\t$this.val() && el.append(buildDetailsBlock('#shippingAddressForm', true)).show();\n\t\t\t};\n\n\t\tsetTimeout(upd, 13);\n\t});\n\n\tif (shippingSavedAddrDropdown.length && shippingSavedAddrDropdown.parents('form').find('input[id*=_address1]').val() == '') {\n\t\tshippingSavedAddrDropdown.trigger('change');\n\t}\n\n\tsetTimeout(function(){\n\t\tif($('#shippingAddressForm input[id*=_firstName]').val() != ''){\n\t\t\tvar $form = $('#shippingAddressForm'),\n\t\t\tactionName = \"dwfrm_shippingaddress_saveopcaddress\";\n\n\t\t\t$form.validate().form();\n\t\t\tif($form.valid()){\n\t\t\t\tsetOPCAddress('#shippingAddressForm', actionName).then(function (response) {\n\t\t\t\t\tvar data = JSON.parse(response);\n\n\t\t\t\t\tif(data.status != 'success'){\n\t\t\t\t\t\tconsole.log('submission error');\n\t\t\t\t\t}\n\t\t\t    }.bind(this));\n\t\t\t}\n\t\t}\n\t}, 30);\n\n}\n\n/**\n * create address object from form\n * @param formSelector\n * @returns Address Object\n */\nfunction createAddressObj(formSelector){\n\tvar $form = $(formSelector);\n\treturn {\n\t\tfirstName: util.htmlEncode($form.find('input[name$=\"_firstName\"]').val()),\n\t\tlastName: util.htmlEncode($form.find('input[name$=\"_lastName\"]').val()),\n\t\taddress1: util.htmlEncode($form.find('input[name$=\"_address1\"]').val()),\n\t\taddress2: util.htmlEncode($form.find('input[name$=\"_address2\"]').val()),\n\t\taddress3: util.htmlEncode($form.find('input[name$=\"_address3\"]').val()),\n\t\tcountryCode: util.htmlEncode($form.find('select[id$=\"_country\"]').val()),\n\t\tstateCode: util.htmlEncode($form.find('select[id$=\"_state\"]').val()),\n\t\tpostalCode: util.htmlEncode($form.find('input[name$=\"_postal\"]').val().toUpperCase()),\n\t\tcity: util.htmlEncode($form.find('input[name$=\"_city\"]').val()),\n\t\tphone: util.htmlEncode($form.find('input[name$=\"_phone\"]').val()),\n\t\temail: util.htmlEncode($form.find('input[name$=\"_email\"]').val())\n\t};\n}\n\nfunction populateBillingToShipping(shippingAddrFormSelector, billingAddrFormSelector){\n\tvar shippingAddrForm = $(shippingAddrFormSelector);\n\tvar billingAddrObj = createAddressObj(billingAddrFormSelector);\n    shippingAddrForm.find('input[name$=\"_firstName\"]').val(billingAddrObj.firstName).trigger('change');\n    shippingAddrForm.find('input[name$=\"_lastName\"]').val(billingAddrObj.lastName).trigger('change');\n    shippingAddrForm.find('input[name$=\"_address1\"]').val(billingAddrObj.address1).trigger('change');\n    shippingAddrForm.find('input[name$=\"_address2\"]').val(billingAddrObj.address2).trigger('change');\n    shippingAddrForm.find('input[name$=\"_address3\"]').val(billingAddrObj.address3).trigger('change');\n    shippingAddrForm.find('input[name$=\"_postal\"]').val(billingAddrObj.postalCode).trigger('change');\n    shippingAddrForm.find('input[name$=\"_city\"]').val(billingAddrObj.city).trigger('change');\n    shippingAddrForm.find('select[id$=country]').val(billingAddrObj.countryCode).trigger('change');\n    shippingAddrForm.find('select[id$=state]').val(billingAddrObj.stateCode).trigger('change');\n    shippingAddrForm.find('input[name$=\"_phone\"]').val(billingAddrObj.phone).trigger('change');\n}\n\nfunction buildDetailsBlock(formSelector, compact){\n\tvar $form = $(formSelector),\n    \tdata = createAddressObj($form),\n    \thtmlText = $('<div/>', {\"class\": \"address-details-st\"}),\n    \tisCompact = typeof compact != undefined && compact == true,\n    \theader = isCompact ? '' : $form.attr('id') == 'billingAddressForm'? '<h6>Billing Recipient</h6>' : '<h6>Ship To:</h6>',\n    \teditButton = isCompact ? '' : '<p class=\"text-right\"><a href=\"#\" class=\"edit-address-det\" tabindex=\"0\">Edit<span class=\"visually-hidden\">&nbsp;Address Information</span></a></p>';\n\n    if(!isCompact && $form.attr('id') == 'shippingAddressForm') {\n    \t$('.shipping-address-section').addClass('active');\n    }\n    for ( var _k in data ) {\n    \tif ( data[_k] != null && data[_k].search(/\\^/) != -1 ) {\n    \t\tdata[_k] = data[_k].replace(/\\^/gi,\"'\");\n    \t}\n    }\n    if (data.email) {\n\n    \tvar htmlcontent = header;\n    \t\thtmlcontent += '<div>'+data.firstName + ' ' + data.lastName + ' </div>';\n    \t\thtmlcontent += '<div>' + data.address1 + ' </div>';\n    \t\tif (data.address2 !== '') {\n    \t\t\thtmlcontent += '<div>' + data.address2 + ' </div>';\n    \t\t}\n    \t\tif (data.address3 !== '') {\n    \t\t\thtmlcontent += '<div>' + data.address3 + ' </div>';\n    \t\t}\n\n    \t\thtmlcontent += '<div>' + data.city;\n\n\n    \t\tif(data.stateCode != null && data.stateCode != '' && data.stateCode != undefined && data.stateCode.toUpperCase() != 'OTHER') {\n    \t\t\thtmlcontent += ' ' + data.stateCode;\n    \t\t}\n\n    \t\thtmlcontent += ' ' + data.postalCode;\n    \t\thtmlcontent += ' ' + data.countryCode + '</div>';\n    \t\thtmlcontent += '<div>' + data.phone + '</div>';\n    \t\thtmlcontent += '<div>'+data.email+'</div>' + editButton;\n\n    \thtmlText.html(htmlcontent);\n\n    } else {\n    \tvar htmlcontent = header;\n    \t\thtmlcontent += '<div>'+data.firstName + ' ' + data.lastName + ' </div>';\n    \t\thtmlcontent += '<div>' + data.address1 + ' </div>';\n    \t\tif (data.address2 !== '') {\n    \t\t\thtmlcontent += '<div>' + data.address2 + ' </div>';\n    \t\t}\n    \t\tif (data.address3 !== '') {\n    \t\t\thtmlcontent += '<div>' + data.address3 + ' </div>';\n    \t\t}\n    \t\thtmlcontent += '<div>' + data.city;\n\n    \t\tif(data.stateCode != null && data.stateCode != '' && data.stateCode != undefined && data.stateCode.toUpperCase() != 'OTHER') {\n    \t\t\thtmlcontent += ' ' + data.stateCode;\n    \t\t}\n    \t\thtmlcontent += ' ' + data.postalCode;\n    \t\thtmlcontent += ' ' + data.countryCode +  '</div>';\n    \t\thtmlcontent += '<div>' + data.phone + '</div>' + editButton;\n\n    \thtmlText.html(htmlcontent);\n    }\n\n    return htmlText;\n}\n\n/**\n * @function\n * @description Helper method which constructs a URL for an AJAX request using the\n * entered address information as URL request parameters.\n */\nfunction getShippingMethodURL(formSelector, url, extraParams) {\n    var $form = $(formSelector);\n\n    var params = {\n        address1: $form.find('input[name$=\"_address1\"]').val(),\n        address2: $form.find('input[name$=\"_address2\"]').val(),\n        address3: $form.find('input[name$=\"_address3\"]').val(),\n        countryCode: $form.find('select[id$=\"_country\"]').val(),\n        stateCode: $form.find('select[id$=\"_state\"]').val(),\n        postalCode: $form.find('input[name$=\"_postal\"]').val(),\n        city: $form.find('input[name$=\"_city\"]').val()\n    };\n    return util.appendParamsToUrl(url, $.extend(params, extraParams));\n}\n\nfunction updateShippingMethodList(sel) {\n    var $shippingMethodList = $('#shipping-method-list');\n    if (!$shippingMethodList || $shippingMethodList.length === 0) { return; }\n    var url = getShippingMethodURL(sel, Urls.shippingMethodsJSON);\n\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            if (!data) {\n                window.alert('Couldn\\'t get list of applicable shipping methods.');\n                return false;\n            }\n\n            // We need to update the UI.  The list has changed.\n            // Cache the array of returned shipping methods.\n            shippingMethods = data;\n            // indicate progress\n            progress.show($shippingMethodList);\n\n            var shippingMethodListData = {\n        \t\tselectedPaymentMethod: $('#paymentSection input:checked').val()\n        \t}\n\n            // load the shipping method form\n            var smlUrl = getShippingMethodURL(sel, Urls.shippingMethodsList);\n\n            $shippingMethodList.load(smlUrl, shippingMethodListData, function () {\n                $shippingMethodList.fadeIn('fast');\n                // rebind the radio buttons onclick function to a handler.\n                $shippingMethodList.find('[name$=\"_shippingMethodID\"]').click(function () {\n                \t$('[name$=\"_shippingMethodID\"]').prop('disabled', true);\n                \tselectShippingMethod($(this).val());\n                });\n\n                progress.hide();\n                tooltip.init();\n                //if nothing is selected in the shipping methods select the first one\n                if ($shippingMethodList.find('.input-radio:checked').length === 0) {\n                    $shippingMethodList.find('.input-radio:first').prop('checked', 'checked');\n                }\n            });\n        }\n    });\n}\n\n/**\n * @function\n * @description updates the order summary based on a possibly recalculated basket after a shipping promotion has been applied\n */\nfunction updateSummary() {\n    cart.updateCart('dwfrm_cart_updateCart');\n\n    return;\n}\n\n/**\n * @function\n * @description selects a shipping method for the default shipment and updates the summary section on the right hand side\n * @param\n */\nfunction selectShippingMethod(shippingMethodID) {\n    // nothing entered\n    if (!shippingMethodID) {\n        return;\n    }\n\n    // attempt to set shipping method\n    var url = getShippingMethodURL('#shippingAddressForm', Urls.selectShippingMethodsList, {shippingMethodID: shippingMethodID});\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n\n            updateSummary();\n            if (!data || !data.shippingMethodID) {\n                window.alert('Couldn\\'t select shipping method.');\n                $('[name$=\"_shippingMethodID\"]').prop('disabled', false);\n                return false;\n            }\n            // display promotion in UI and update the summary section,\n            // if some promotions were applied\n            $('.shippingpromotions').empty();\n\n        }\n    });\n}\n\n/**\n * @description Make the AJAX request to set address data\n * @param {Element} form The form element that present address object\n * @param {Element} Action name to apply to form\n * @returns {Promise}\n */\nvar setOPCAddress = function (form, name) {\n    var $form = $(form),\n    \turl = (form == '#billingAddressForm') ? Urls.setOpcAddress :  $form.attr('action');\n\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(url),\n        data: $form.serialize() + '&' + name + '=' + name\n    }));\n};\n\nvar openRestrictionsPopup = function (data) {\n\tvar payload = JSON.parse(data.payload);\n\tvar popup = require('../../popup');\n\n\tvar list = $.map(payload.list, function (el) {\n\t\treturn '<li>' + el.name + ':<br>' + el.message + '</li>';\n\t}).join('');\n\n\tpopup.init({\n\t\ttitle: payload.title,\n\t\tcontent: payload.message + '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>',\n\t}).showPopup();\n}\n\nfunction renderOptions(optionParent, optionsStoreId) {\n\tvar options = '';\n\tvar optionsStoreOptions = $(optionsStoreId + ' option:selected').data('options');\n\tvar statesList;\n\n\tif (optionsStoreOptions) {\n\t\tstatesList = JSON.parse(optionsStoreOptions.replace(/\\'/g, '\\\"'));\n\n\t\tstatesList.forEach(function (state) {\n\t\t\toptions += '<option class=\"select-option\" label=\"' + state.label + '\" value=\"' + state.code + '\">' + state.label + '</option>';\n\t\t});\n\n\t\t$(optionParent).empty().append(options);\n\n\t\tif (statesList.length <= 1) {\n\t\t\t$(optionParent).removeClass('required');\n\t\t\t$(optionParent).parent().parent().parent().hide();\n\t\t} else {\n\t\t\t$(optionParent).addClass('required');\n\t\t\t$(optionParent).parent().parent().parent().show();\n\t\t}\n\t}\n}\n\n$(document).on('update-shipping', function() {\n\tif($('.shipping-methods-section').length == 0){ return; }\n\n\tsetTimeout(function(){\n\t\tupdateShippingMethodList('#shippingAddressForm');\n\t}, 100);\n});\n\nexports.init = function () {\n\tinitializeEvents();\n};\n\nexports.updateSummary = updateSummary;","'use strict';\n\nvar _ = require('lodash');\nvar ajax = require('../../ajax');\nvar findMoreStores = require('../../findMoreStores');\nvar tooltip = require('../../tooltip');\nvar util = require('../../util');\nvar TPromise = require('promise');\nvar AddressAutocompleteDialog;\nvar AddressVerificationDialog;\nvar AddressVerificationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/AddressVerification/AddressVerificationHelper');\nvar CheckoutConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar ValidationHelper = require('../../../../../bc_sheplersbootbarn_core/cartridge/scripts/util/ValidationHelper');\nvar ValidationRules = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\nvar ValidationSettings = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\n\nvar shippingMethods;\nvar isStoreShippingAddressOnly;\nvar options = {};\nvar dataBuffer = {};\n\nvar billingAddressFormContainerSelector = '.billing-address-form';\nvar $billingAddressFormContainer = $(billingAddressFormContainerSelector);\nvar billingAddressFormSelector = '#billingAddressForm';\nvar $billingAddressForm = $(billingAddressFormSelector);\nvar shippingAddressSectionSelector = '.form-checkout.shipping-address-section';\nvar $shippingAddressSection = $(shippingAddressSectionSelector);\nvar shippingAddressFormContainerSelector = '.shipping-address-form';\nvar $shippingAddressFormContainer = $(shippingAddressFormContainerSelector);\nvar shippingAddressFormSelector = '#shippingAddressForm';\nvar $shippingAddressForm = $(shippingAddressFormSelector);\nvar paymentFormContainerSelector = '.payment-section';\nvar $paymentFormContainer = $(paymentFormContainerSelector);\nvar paymentFormSelector = '#paymentSection';\nvar $paymentForm = $(paymentFormSelector);\nvar $sectionCheckout = $('.section-checkout');\nvar $shippingMethodList = $('.form-checkout.payment-section #shipping-method-list');\n\nvar shippingAddressFormValidator;\nvar billingAddressFormValidator;\n\nfunction initializeEvents() {\n\t$sectionCheckout.on('click', '.find-more-stores a', function () {\n\t\tfindMoreStores.initialize({ view: 'checkout', storeQuery: StoreQueryFilters.ShipToStoreEnabled });\n\t});\n\t\n\t$(document).on('click', '.international-checkout', function() {\n\t\tlocation.reload();\n\t});\n\t\n\t$(document).on('change', 'form [id*=\"_country\"]', function () {\n\t\tvar $this = $(this);\n\t\tvar $form = $this.closest('form');\n\t\tvar $stateDropdown = $form.find('[id*=\"states_state\"]');\n\n\t\trenderOptions('#' + $stateDropdown.attr('id'), '#' + $this.attr('id'));\n\n\t\tvar $initialState = $form.find('.initial-state');\n\t\tvar initialStateValue = $initialState.val();\n\t\tvar $selectedStateOption = $stateDropdown.find('option[value=\"' + initialStateValue + '\"]');\n\t\tif ($selectedStateOption.length > 0) {\n\t\t\t$stateDropdown.val(initialStateValue);\n\t\t\t$selectedStateOption.prop('selected', true);\n\t\t}\n\n\t\tif ($form.attr('id') == $shippingAddressForm.attr('id') && $this.val()) {\n\t\t\tif ($this.val().toUpperCase() == SiteConstants.CountryCodes.UnitedStates) {\n\t\t\t\t$('#shipping-international-info').hide();\n\t\t\t} else {\n\t\t\t\t$('#shipping-international-info').show();\n\t\t\t}\n\t\t}\n\t});\n\n\t$(document).on('change', 'form [id*=\"_postal\"]', function () {\n\t\tvar $this = $(this);\n\t\t$this.val($this.val().toUpperCase());\n\t});\n\n\t$('.shipping-same').on('click', function(){\n\t\tif($('.shipping-same').is(':checked')){\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t\t} else {\n\t\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t\t}\n\t});\n\n\t$('.add-diff').on('click', function(){\n\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t});\n\n\t$billingAddressFormContainer.on('click', '.edit-address-det', function (e) {\n\t\te.preventDefault();\n\t\teditBillingAddress();\n\t});\n\n\t$billingAddressFormContainer.on('click', '.cancel-address-det', function (e) {\n\t\te.preventDefault();\n\n\t\t$('.bill-address-fields').addClass('collapsed').hide();\n\t\t$('.billing-select-address').show();\n\n\t\t$('.billing-address-preview').show();\n\t\t$('.billing-address-data.form-info').show();\n\n\t\t$billingAddressForm.hide();\n\t\t$shippingAddressFormContainer.show();\n\n\t\t$shippingAddressSection.addClass('active').find('.shipping-address-cont').removeClass('hidden');\n\n\t\tif ($shippingAddressSection.attr('panel-mode') != 'view') {\n\t\t\t$shippingAddressForm.show();\n\t\t} else {\n\t\t\t$shippingAddressForm.hide();\n\t\t\t$('.form-checkout.payment-section').addClass('active').find('.shipping-payment-cont').removeClass('hidden');\n\t\t}\n\t\t\n\t\tif ($('.shipping-methods-section .shipping-restrictions').length == 0) {\n\t\t\t$('.payment-methods-section').show();\n\t\t}\n\t});\n\n\t$('.shipping-address-section').on('click', '.edit-address-det', function (e) {\n\t\te.preventDefault();\n\t\teditShippingAddress();\n\t});\n\n\t$('.shipping-address-section').on('click', '.add-address-det', function (e) {\n\t\te.preventDefault();\n\n\t\twriteShippingAddressFormToBuffer();\n\n\t\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'add');\n\t\t$shippingAddressFormContainer.data('hidden-editable', true).hide();\n\t\t$('.shipping-address-data').hide();\n\t\t$shippingAddressFormContainer.show();\n\n\t\t$shippingAddressForm.removeClass('add edit').addClass('add');\n\t\t$shippingAddressForm.find('input[name=\"action\"]').val('add');\n\n\t\t$billingAddressForm.hide();\n\t\t$('.billing-address-data.form-info').css('display', 'block');\n\t\t$('.form-checkout.payment-section').removeClass('active').find('.shipping-payment-cont').addClass('hidden');\n\n\t\tvar $shippingAddressFormFields = $shippingAddressForm.find('.editaddress-shipping');\n\t\t$('.editaddress-shipping .initial-state').val('');\n\n\t\t$('.shipping-select-address').hide();\n\t\t$('.editaddress-shipping').removeClass('collapsed');\n\t\t$('#dwfrm_singleshipping_addressList').val('');\n\n\t\t$shippingAddressFormFields.find('input:text, input:password, input:file, textarea').val('');\n\t\t$shippingAddressFormFields.find('option[default]').prop('selected', true);\n\t\t$shippingAddressFormFields.find('input:checkbox, input:radio').removeAttr('checked');\n\n\t\t$('#dwfrm_shippingaddress_country').trigger('change');\n\t});\n\n\t$('.shipping-address-section').on('click', '.cancel-address-det', function (e) {\n\t\te.preventDefault();\n\n\t\twriteBufferToShippingAddressForm();\n   \t\tsubmitShipping(true);\n\t});\n\n    $('.single.shipping-address-type-selector input').on('click', function () {\n\t\tvar shippingAddressType = $(this).val();\n        shippingAddressFormValidator.form();\n\t\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'blank');\n\t\t$('.shipping-address-cont span.error').remove();\n\t\t$('.shipping-address-cont input, .shipping-address-cont select').removeClass('error');\n\t\t\n        if (shippingAddressType == SiteConstants.AddressTypes.Customer) {\n        \t$shippingAddressForm.find('.formfield input[type=\"text\"], .formfield select').not('[disabled]').not('#dwfrm_shippingaddress_myStoreID').val('');\n        \t$('.form-checkout.shipping-address-section').attr('shipping-address-type', 'my-address').attr('value', 'false');\n        \t\n        \tif ($('#dwfrm_multipleshipping_addressList option').length > 0 || dataBuffer.shippingAddressFields && dataBuffer.shippingAddressFields['dwfrm_shippingaddress_firstName']) {\n\t\t\t\twriteBufferToShippingAddressForm();\n        \t\t\n\t\t\t\tif ($shippingAddressForm.valid()) {\n\t\t\t\t\t$('.shipping-address-data.form-info').html('').append(buildDetailsBlockForForm($shippingAddressForm));\n\t\t\t\t\t$('.shipping-address-data').show();\n\t\t\t\t\n\t\t\t\t\t$shippingAddressForm.hide();\n\t\t\t\t\t$('.payment-section').addClass('active');\n\t\t\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n\t\t\t\t\t$('.shipping-address-cont').removeClass('hidden'); \n\t\t\t\t\t$shippingAddressForm.data('shipping-filled', true);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ($('#dwfrm_multipleshipping_addressList option').length > 0) {\n\t\t\t\t\t$('#dwfrm_multipleshipping_addressList').trigger('change');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$shippingAddressForm.find('.formfield option[default]').prop('selected', true);\n\t\t\t\t$shippingAddressForm.data('shipping-filled', false);\n\t\t\t\t$('.form-checkout.address-section').attr('panel-mode', 'view');\n\n\t\t\t\t$shippingAddressFormContainer.data('hidden-editable', true).hide();\n\t\t\t\t$('.shipping-address-data.form-info').hide();\n\t\t\t\t$shippingAddressFormContainer.show();\n\t\t\t\t$shippingAddressForm.removeClass('add edit').addClass('edit');\n\t\t\t\t$shippingAddressForm.find('input[name=\"action\"]').val('edit');\n\n\t\t\t\t$('.editaddress-shipping').removeClass('collapsed');\n\t\t\t\tsetShipToStore(false);\n\t\t\t}\n\n\t\t\tsetShipToStore(isShipToStoreEnabled());\n\t\t\t$('.shipping-address-cont').removeClass('hidden');\n\n\t\t\tif (shippingAddressFormValidator.checkForm()) {\n\t\t\t\tsetOPCAddress(shippingAddressFormSelector, 'dwfrm_shippingaddress_saveopcaddress').then(function (data) {\n    \t\t\t\thandleShippingRestrictions(data);\t\n\t\t\t\t\t$('.payment-section').addClass('active');\n\t\t\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n\n\t\t\t\t\tupdateShippingMethodList($shippingAddressForm, true, null);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tupdateShippingMethodList($shippingAddressForm, true, null);\n\t\t\t\t$('.payment-section').removeClass('active');\n\t\t\t\t$('.shipping-payment-cont').addClass('hidden');\n\t\t\t}\n\n\t\t\t$('.billing-address-data.form-info').css('display', 'block');\n\n            if ($('.multiple.select-address option').length > 0) {\n            \t$('.multiple.select-address').show();\n            } else {\n            \t$('.multiple.select-address').hide();\n            }\n\n        \t$('.single.select-address').hide();\n        } else if (shippingAddressType == SiteConstants.AddressTypes.Store) {\n\t\t\t$shippingAddressForm.hide();\n            $('.editaddress-shipping').addClass('collapsed');\n            $('.multiple.select-address').hide();\n\n            if (SitePreferences.ENABLE_SHIP_TO_STORE_SELECTION) {\n                $('.single.select-address').show();\n\t\t\t}\n\t\t\t$('#mystores_addressList').trigger('change');\n        }\n    });\n\n    $('select[name$=\"_addressList\"]', $billingAddressForm).on('change', function () {\n        var selected = $(this).children(':selected').first();\n        var selectedAddress = $(selected).data('address');\n\n        if (!selectedAddress) { return; }\n\n        util.fillAddressFields(selectedAddress, $billingAddressForm);\n        billingAddressFormValidator.form();\n    });\n\n    $('select[name$=\"_addressList\"]', $shippingAddressForm).on('change', function () {\n        var selected = $(this).children(':selected').first();\n        var selectedAddress = $(selected).data('address');\n\n        if (!selectedAddress) { return; }\n\n        util.fillAddressFields(selectedAddress, $shippingAddressForm);\n        shippingAddressFormValidator.form();\n    });\n\n    $('#submitBilling').on('click', function(e){\n    \te.preventDefault();\n    \tsubmitBilling();\n    });\n\n    $('#submitShipping').on('click', function(e) {\n    \te.preventDefault();\n    \tsubmitShipping();\n    });\n\n\t$('.toggle.top, .toggle.bottom').on('click', function(e){\n    \te.preventDefault();\n    \t$('#internationalinfo').slideToggle();\n\t});\n\n\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\t$(document).off('keyup.AddressAutocomplete').on('keyup.AddressAutocomplete', billingAddressFormSelector + ' input[type=\"text\"], ' + shippingAddressFormSelector + ' input[type=\"text\"]', function (event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar $form = $this.closest('form');\n\t\t\tvar formValidator = $form.validate();\n\n\t\t\tif (event.keyCode == 8 || event.keyCode == 46) {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t} else if (!formValidator.checkForm() && ($this.attr('id').indexOf('_address1') >= 0 || $this.attr('id').indexOf('_address2') >= 0)) {\n\t\t\t\tvar addressAutocompleteHandler = function (addressAutocompleteData) {\n\t\t\t\t\tAddressAutocompleteDialog.initialize(options, addressAutocompleteData);\n\t\t\t\t}\n\t\t\t\n\t\t\t\tAddressVerificationHelper.AutocompleteAddress($form, $this, options).then(addressAutocompleteHandler);\n\t\t\t} else {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t}\n\t\t});\n\t\t\n\t\t$(document).off('SetAddressFromAddressAutocomplete').on('SetAddressFromAddressAutocomplete', function (event, data) {\n\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog(data.$form, data.Address);\n\t\t});\n\t}\n\n\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\t$(document).off('SetAddressFromAddressVerification').on('SetAddressFromAddressVerification', function (event, addressData) {\n\t\t\tif (addressData.AddressType == 'billing') {\n\t\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog($billingAddressForm, addressData);\n\t\t\t\tsubmitBilling(true);\n\t\t\t} else if (addressData.AddressType == 'shipping') {\n\t\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog($shippingAddressForm, addressData);\n\t\t\t\tsubmitShipping(false, true);\n\t\t\t}\n\t\t});\n\t}\n\n\t$(document).on('opc.SetShippingAddress', function (e, address) {\n\t\tvar templateSettings = {\n\t\t\t\tinterpolate: /{{([\\s\\S]+?)}}/g\n\t    \t};\n\n\t\tvar template = _.template($('#template-address-selector-option').html(), templateSettings);\n\n\t\taddress.ID = address.key;\n\t\tif (address.isMyStore && !address.myStoreID && address.storeId) {\n\t\t\taddress.myStoreID = address.storeId;\n\t\t}\n\n\t\tvar templateData = _.extend(address, {\n\t\t\tid: address.UUID,\n\t\t\tcssClass: 'find-more-store-option',\n\t\t\tselected: 'selected',\n\t\t\ttext: address.labelText\n\t\t});\n\n\t\tvar $addressList = $('#mystores_addressList');\n\n\t\tvar addressIndexInList = null;\n\t\t$addressList.find('option').each(function (index, object) {\n\t\t\tif (address.ID == $(object).val()) {\n\t\t\t\taddressIndexInList = index;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t    if (addressIndexInList) {\n\t\t\t$addressList.prop('selectedIndex', addressIndexInList);\n\t\t} else {\n\t\t\tdataBuffer['mystores_addressList'] = dataBuffer['mystores_addressList'].filter(function (address) {\n\t\t\t\treturn !address.isTemporary;\n\t\t\t});\n\n\t\t\taddress.isTemporary = true;\n\t\t\tdataBuffer['mystores_addressList'].push(address);\n\t\t\tdataBuffer['store_name_lookup'][address.firstName] = address.fullName;\n\t\t\t\n\t\t\t$addressList.find('.find-more-store-option').remove();\n\t\t\t$addressList.prepend(template(templateData)).prop('selectedIndex', 0);\n\t\t}\n\n\t    $('#mystores_addressList').trigger('change');\n\t});\n\n\t$(document).on('change', '#dwfrm_multipleshipping_addressList, #mystores_addressList', function (e) {\n\t\tvar $this = $(this);\n\t\tvar actionName = 'dwfrm_shippingaddress_saveopcaddress';\n\t\t$('.shipping-address-cont span.error').remove();\n\t\t$('.shipping-address-cont input, .shipping-address-cont select').removeClass('error');\n\n\t\tvar $target = $(e.currentTarget);\n        var selectedAddress;\n\t\tif ($target && $target.attr('id')) {\n\t\t\tvar dataBufferForAddressList = dataBuffer[$target.attr('id')];\n\t\t\tif (dataBufferForAddressList) {\n\t\t\t\tselectedAddress = dataBufferForAddressList.filter(function (address) {\n\t\t\t\t\treturn address.UUID == $target.val();\n\t\t\t\t})[0];\n\t\t\t}\n\t\t}\n\n        if (!selectedAddress) {\n        \treturn false;\n        }\n\n\t\tvar isStoreAddress = false;\n\t\tvar storeId;\n        if (selectedAddress.hasOwnProperty('isMyStore') && selectedAddress.myStoreID) {\n\t\t\tisStoreAddress = selectedAddress.isMyStore;\n\t\t\tstoreId = selectedAddress.myStoreID;\n        }\n\n\t\tsetShipToStore(isStoreAddress);\n\n\t\tif (isStoreAddress) {\n\t\t\t$shippingAddressForm.find('.formfield.myStoreID input').val(storeId);\n\t\t} else {\n\t\t\t$shippingAddressForm.find('.formfield input[type=\"text\"], .formfield select').not('[disabled]').not('#dwfrm_shippingaddress_myStoreID').val('');\n\t\t\tutil.fillAddressFields(selectedAddress, $shippingAddressForm);\n\t\t}\n\t\t$this.find('option.placeholder').remove();\n\n\t\tsetOPCAddress(shippingAddressFormSelector, actionName).then(function (data) {\n\t\t\thandleShippingRestrictions(data);\n\t\t\t$shippingAddressForm.data('shipping-filled', true);\n\t\t\t$shippingAddressForm.hide();\n\t\t\t$('.shipping-address-data.form-info').html('').append(buildDetailsBlockForAddress(selectedAddress, false, false, 'shippingAddressForm'));\n\t\t\t$('.shipping-address-data').show();\n\n\t\t\tif (billingAddressFormValidator.valid()) {\n\t\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n\t\t\t\t$('.payment-section').addClass('active');\n\t\t\t} else {\n\t\t\t\t$('.shipping-payment-cont').addClass('hidden');\n\t\t\t\t$('.payment-section').removeClass('active');\n\t\t\t\t$('.billing-address-data.form-info').hide();\n\n\t\t\t\t$billingAddressFormContainer.show();\n\t\t\t\t$billingAddressFormContainer.find('input.required.field.error').eq(0).focus();\n\t\t\t}\n\t\t\t\n\t\t\tupdateShippingMethodList($shippingAddressForm, true, isStoreAddress);\n\t\t}.bind(this));\n\t});\n\n\t$('#dwfrm_billing_addressList').on('change', function() {\n    \t$('.custom-email-error').remove();\n    \tvar isEmailValid = util.validateEmail($('#dwfrm_billingaddress_email').val());\n\n\t\tif ($(this).val() && billingAddressFormValidator.valid() && isEmailValid) {\n\t\t\t$billingAddressForm.hide();\n\t\t\t$('.billing-address-data').html('').append(buildDetailsBlockForForm($billingAddressForm)).show();\n\t\t\t$('.shipping-address-cont').removeClass('hidden');\n\t\t\t$('.shipping-address-section').addClass('active');\n\t\t\t$('.form-checkout.address-section').attr('panel-mode', 'view').attr('value', 'true');\n\t\t} else {\n\t\t\teditBillingAddress();\n\t\t\t$('.shipping-address-cont').addClass('hidden');\n\t\t\t$('.shipping-address-section').removeClass('active');\n\t\t}\n\t});\n\n\t$(document).off('click.ShipToStore.Change').on('click.ShipToStore.Change', '[shipping-method] .store-details .change', function (e) {\n\t\tvar $shippingMethod = $(this).closest('[shipping-method]');\n\t\t$shippingMethod.find('.store-details').hide();\n\t\t$shippingMethod.find('.store-selector').show();\n\t});\n\n\t$(document).off('change.ShipToStore.Apply').on('change.ShipToStore.Apply', '[shipping-method] .store-selector select', function (e) {\n\t\tvar $shippingMethod = $(this).closest('[shipping-method]');\n\t\tvar $selectedStore = $shippingMethod.find('.store-selector option:checked');\n\t\tvar storeId = $selectedStore.val();\n\t\t\n\t\t$shippingAddressForm.find('.formfield.myStoreID input').val(storeId);\n\n\t\tsetOPCAddress(shippingAddressFormSelector, 'dwfrm_shippingaddress_saveopcaddress').then(function (data) { \n\t\t\tupdateShippingMethodList($shippingAddressForm, true);\n\t\t});\n\n\t\t$shippingMethod.find('.store-details').show();\n\t\t$shippingMethod.find('.store-selector').hide();\n\t});\n\n\t$(document).off('click.ShipToStore.Cancel').on('click.ShipToStore.Cancel', '[shipping-method] .store-selector .cancel', function (e) {\n\t\tvar $shippingMethod = $(this).closest('[shipping-method]');\n\t\t$shippingMethod.find('.store-details').show();\n\t\t$shippingMethod.find('.store-selector').hide();\n\t});\n\n\t$(document).off('click.ShippingMethod.Select').on('click.ShippingMethod.Select', 'input[name*=\"_shippingMethodID\"]', function (event) {\n\t\tvar $this = $(this);\n\t\tvar $shippingMethod = $this.closest('[shipping-method]');\n\t\tvar $shipment = $this.closest('form');\n\n\t\tif ($shippingMethod.attr('status') == 'disabled') {\n\t\t\tevent.preventDefault();\n\t\t} else {\n\t\t\tselectShippingMethod($shipment.attr('shipment'), $this.val(), $shippingMethod.attr('is-ship-to-store') == 'true', $shippingMethod); \n\t\t}\n\t});\n\n\t$(document).off('focus.AutofillHandler').on('focus.AutofillHandler', 'div.billing-address-form input[type=\"text\"], div.shipping-address-form input[type=\"text\"]', function (event) {\n\t\tvar $this = $(this);\n\t\tvar $form = $this.closest('form');\n\t\tvar autofillCount = $form.find('input:-webkit-autofill').length;\n\n\t\tif (window.innerWidth <= 768) {\n\t\t\tif (autofillCount == 0) {\n\t\t\t\t$form.attr('auto-filled', false);\n\t\t\t}\n\n\t\t\tif ($form.attr('auto-filled') != 'true') {\n\t\t\t\tdataBuffer.AutofillDetectorInterval = setInterval(function() {\n\t\t\t\t\tautofillCount = $form.find('input:-webkit-autofill').length;\n\t\t\t\t\tif (autofillCount > 0 && $form.attr('auto-filled') != 'true') {\n\t\t\t\t\t\t$form.attr('auto-filled', true);\n\t\t\t\t\t\t$this.attr('inputmode', 'none');\n\t\t\t\t\t\t$this.trigger('blur');\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t$this.removeAttr('inputmode');\n\t\t\t\t\t\t}, 250);\n\t\t\t\t\t}\n\t\t\t\t}, 250);\n\t\t\t}\n\t\t}\n\t});\n}\n\n$(document).off('blur.AutofillHandler').on('blur.AutofillHandler', 'div.billing-address-form input[type=\"text\"], div.shipping-address-form input[type=\"text\"]', function (event) {\n\tif (dataBuffer && dataBuffer.AutofillDetectorInterval) {\n\t\tclearInterval(dataBuffer.AutofillDetectorInterval);\n\t}\n});\n\nfunction initializeUserInterface() {\n\t$('#dwfrm_shippingaddress_ID').val('');\n\t$('.form-checkout.address-section').attr('panel-mode', 'blank');\n\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'blank').attr('value', 'false');\n\n\tvar billingAddress = getAddressFromForm($billingAddressForm);\n\tvar shippingAddress = getAddressFromForm($shippingAddressForm);\n\tvar $billingSavedAddrDropdown = $('#dwfrm_billing_addressList');\n\tvar didBillingAddressSuccessHandlerRun = false;\n\tvar didShippingAddressSuccessHandlerRun = false;\n\t\n\t$('#dwfrm_billingaddress_country').trigger('change');\n\t$('#dwfrm_shippingaddress_country').trigger('change');\n\n\t$.validator.addMethod('requiredExcludingPunctuation', ValidationHelper.ValidateRequiredExcludingPunctuation, Resources.INVALID_VALUE);\n\t$.validator.addMethod('postalCode', ValidationHelper.ValidatePostalCode, Resources.INVALID_POSTAL_CODE);\n\t$.validator.addMethod('postOfficeBoxOnly', ValidationHelper.ValidateAddressForPostOfficeBoxOnly, Resources.INVALID_POST_OFFICE_BOX_ONLY);\n\t\n\tbillingAddressFormValidator = $billingAddressForm.validate();\n\tbillingAddressFormValidator.settings.ignore = [\":not(.required)\"];\n\tbillingAddressFormValidator.settings.onfocusout = ValidationSettings.Checkout.onfocusout;\n\tbillingAddressFormValidator.settings.errorPlacement = ValidationSettings.Checkout.errorPlacement;\n\t$billingAddressForm.find('input[name$=\"_firstName\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$billingAddressForm.find('input[name$=\"_lastName\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$billingAddressForm.find('input[name$=\"_address1\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$billingAddressForm.find('input[name$=\"_address1\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBoxOnly);\n\t$billingAddressForm.find('input[name$=\"_address2\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBoxOnly);\n\t$billingAddressForm.find('input[name$=\"_city\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$billingAddressForm.find('input[name$=\"_postal\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\n\tshippingAddressFormValidator = $shippingAddressForm.validate();\n\tshippingAddressFormValidator.settings.ignore = [\":not(.required)\"];\n\tshippingAddressFormValidator.settings.onfocusout = ValidationSettings.Checkout.onfocusout;\n\tshippingAddressFormValidator.settings.errorPlacement = ValidationSettings.Checkout.errorPlacement;\n\t$shippingAddressForm.find('input[name$=\"_firstName\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$shippingAddressForm.find('input[name$=\"_lastName\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$shippingAddressForm.find('input[name$=\"_address1\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$shippingAddressForm.find('input[name$=\"_address1\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBoxOnly);\n\t$shippingAddressForm.find('input[name$=\"_address2\"]').rules('add', ValidationRules.ValidateAddressForPostOfficeBoxOnly);\n\t$shippingAddressForm.find('input[name$=\"_city\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\t$shippingAddressForm.find('input[name$=\"_postal\"]').rules('add', ValidationRules.RequiredExcludingPunctuation);\n\n\tif (!billingAddress.address1 && $billingSavedAddrDropdown.find('option').length && $billingSavedAddrDropdown.val()) {\n\t\t$billingSavedAddrDropdown.trigger('change');\n\t} else {\n\t\tif (billingAddressFormValidator.checkForm()) {\n\t\t\t$billingAddressForm.find('input.shipping-same').prop('checked', false);\n\t\t\t$billingAddressForm.find('input.shipping-newsletter-signup').prop('checked', false);\n\t\t\tdidBillingAddressSuccessHandlerRun = billingAddressSuccessHandler(null, true);\n\t\t} else {\n\t\t\teditBillingAddress();\n\t\t}\n\t}\n\n\trenderMyStoresAddressSelector();\n\tvar $shippingSavedAddrDropdown = $('#dwfrm_multipleshipping_addressList');\n\tif (billingAddressFormValidator.checkForm() && !didBillingAddressSuccessHandlerRun) {\n\t\tif (!shippingAddress.address1 && $shippingSavedAddrDropdown.find('option').length && $shippingSavedAddrDropdown.val()) {\n\t\t\t$shippingSavedAddrDropdown.trigger('change');\n\t\t} else {\n\t\t\tif (shippingAddressFormValidator.checkForm()) {\n\t\t\t\tdidShippingAddressSuccessHandlerRun = shippingAddressSuccessHandler(true);\n\t\t\t\tverifyShipping();\n\t\t\t} else {\n\t\t\t\teditShippingAddress();\n\t\t\t}\n\t\t}\n\t}\n\t\n\t$('.form-checkout.shipping-address-section .select-address.multiple').show();\n\t$('.address-section').addClass('active');\n\t\n\tif (didBillingAddressSuccessHandlerRun && shippingAddressFormValidator.checkForm() && window.innerWidth <= 767) {\n\t\tsetTimeout(function() {\n\t\t\t$([document.documentElement, document.body]).scrollTop($('.form-checkout.payment-section').offset().top - $('.header-wrapper').height() + 20);\n\t\t}, 1000);\n\t}\n}\n\nfunction billingAddressSuccessHandler(responseData, skipUpdateShippingMethodList, isVerified) {\n\tvar $shippingSavedAddrDropdown = $('#dwfrm_multipleshipping_addressList');\n\tvar shippingAddress = getAddressFromForm($shippingAddressForm);\n\n\t$billingAddressForm.hide();\n\t$('.form-checkout.address-section').attr('panel-mode', 'view').attr('value', 'true');\n\t$('.billing-address-data').html('').append(buildDetailsBlockForForm($billingAddressForm)).show();\n\t$('.shipping-address-cont').removeClass('hidden');\n\n\tif (responseData && responseData.status == 'success' && ($('#isShippingAddressSameAsBillingAddress').prop('checked') || $('[has-store-pickup-shipment-only]').attr('has-store-pickup-shipment-only') == 'true')) {\n\t\tpopulateBillingAddressFormToShippingAddressForm();\n\t}\n\t\n\tif (responseData && responseData.status == 'shippingAddressValidationError') {\n\t\teditShippingAddress();\n\t} else if (SitePreferences.BYPASS_SHIPPING && ($('#isShippingAddressSameAsBillingAddress').prop('checked') || $('[has-store-pickup-shipment-only]').attr('has-store-pickup-shipment-only') == 'true')) {\n\t\t$('.shipping-address-data.form-info').html('').append(buildDetailsBlockForForm($shippingAddressForm));\n\t\t$('.shipping-address-data').show();\n\n\t\t$shippingAddressForm.hide();\n\t\t$shippingAddressForm.data('shipping-filled', true);\n\t\t$paymentFormContainer.addClass('active');\n\t\t$('.shipping-payment-cont').removeClass('hidden');\n\t\tsubmitShipping(null, isVerified);\n\t} else if (shippingAddressFormValidator.checkForm()) {\n\t\tshippingAddressSuccessHandler(skipUpdateShippingMethodList);\n\t} else if (!shippingAddress.address1 && $shippingSavedAddrDropdown.find('option').length && $shippingSavedAddrDropdown.val()) {\n\t\t$shippingSavedAddrDropdown.trigger('change');\n\t} else {\n\t\teditShippingAddress();\n\t}\n\n\t$('.shipping-address-section').addClass('active').show();\n\n\tif (!skipUpdateShippingMethodList) {\n\t\tupdateShippingMethodList($shippingAddressForm, true);\n\t}\n\n\tif ($shippingAddressForm.data('shipping-filled') == true) {\n\t\t$paymentFormContainer.addClass('active').find('.shipping-payment-cont').removeClass('hidden');\n\t\t$shippingAddressForm.hide();\n\t\t$('.shipping-address-data').show();\n\t}\n\n\tif (window.innerWidth <= 767) {\n\t\t$(window).scrollTop($('.shipping-address-section').offset().top - $('.header-wrapper').height());\n\t}\n\t\n\treturn true;\n}\n\nfunction shippingAddressSuccessHandler(skipUpdateShippingMethodList, isCancel, isVerified) {\n\tvar selectedAddressID;\n\tvar currentAddressIDs = [];\n\n\t$('.select-address.address-selector select option').map(function() { currentAddressIDs.push($(this).val()); });\n\n\tif ($shippingAddressForm.hasClass('add') || ($shippingAddressForm.hasClass('edit') && !$shippingAddressForm.find('.set-default-shipping input').prop('checked'))) {\n\t\tselectedAddressID = \"new\";\n\t\t$shippingAddressForm.find('input[name$=\"_ID\"]').val('');\n\n\t\tif ($('#dwfrm_multipleshipping_addressList').find('option.placeholder').length == 0) {\n\t\t\t$('#dwfrm_multipleshipping_addressList').prepend('<option class=\"placeholder\">' + Resources.OPC_SELECT_ADDR + '</option>').prop('selectedIndex', 0);\n\t\t}\n\t} else {\n\t\tselectedAddressID = $('.select-address.address-selector select').val();\n\t}\n\n\twriteShippingAddressFormToBuffer();\n\tvar panelMode = $shippingAddressSection.attr('panel-mode');\n\t$shippingAddressForm.removeClass('add edit');\n\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'view');\n\n\t$shippingAddressForm.find('.add-to-address-book input').prop('checked', false);\n\t$shippingAddressForm.find('.set-default-shipping input').prop('checked', false);\n\t\n\tvar renderAddressSelectorCallback = function () {\n\t\t$shippingAddressForm.data('shipping-filled', true);\n\t\t$shippingAddressForm.hide();\n\t\t$shippingAddressForm.find('input[name=\"action\"]').val('');\n\n\t\tif (!isCancel && (panelMode == 'add' || panelMode == 'edit')) {\n\t\t\t$('#dwfrm_multipleshipping_addressList').prop('selectedIndex', 0);\n\t\t}\n\n\t\t$('.shipping-address-data.form-info').html('').append(buildDetailsBlockForForm($shippingAddressForm));\n\t\t$('.shipping-address-data').show();\n\t\tif (!isVerified) {\n\t\t\tverifyShipping(isCancel, isVerified);\n\t\t}\n\n\t\tif (billingAddressFormValidator.checkForm()) {\n\t\t\t$('.shipping-payment-cont').removeClass('hidden');\n    \t\t$('.payment-section').addClass('active');\n\t\t} else {\n\t\t\t$('.shipping-payment-cont').addClass('hidden');\n\t\t\t$('.payment-section').removeClass('active');\n\t\t\t$('.billing-address-data.form-info').hide();\n\n\t\t\tvar formBody = $('.billing-address-form');\n\t\t\tformBody.show();\n\t\t\tformBody.find('input.required.field.error').eq(0).focus();\n\t\t}\n\n\t\tif (!skipUpdateShippingMethodList) {\n\t\t\tupdateShippingMethodList($shippingAddressForm, true, null, true);\n\t\t}\n\t}\n\n\tvar isAuthenticated = $sectionCheckout.attr('is-authenticated') == \"true\";\n\tif (isAuthenticated) {\n\t\trenderAddressSelector({\n\t\t\tcontainer: '.select-address.address-selector',\n\t\t\tel: '.select-address.address-selector .field-wrapper',\n\t\t\tid: 'dwfrm_multipleshipping_addressList',\n\t\t\tselected: selectedAddressID,\n\t\t\tcurrentAddresses: currentAddressIDs,\n\t\t\tcallback: renderAddressSelectorCallback\n\t\t});\n\t} else {\n\t\trenderAddressSelectorCallback();\n\t}\n\n\tif (window.innerWidth <= 767) {\n\t\t$(window).scrollTop($('.payment-section').offset().top - $('.header-wrapper').height());\n\t}\n\t\n\treturn true;\n}\n\nfunction submitBilling(isVerified) {\n\t$('#submitBilling').attr('disabled', true);\n\tif ($('.billing-address-type-selector input[value=1]').prop('checked') && $('#dwfrm_billing_addressList').val() == '') {\n\t\t$('#submitBilling').attr('disabled', false);\n\t\treturn;\n\t}\n\n\tif ($('#isShippingAddressSameAsBillingAddress').is(':checked') || $('[has-store-pickup-shipment-only]').attr('has-store-pickup-shipment-only') == 'true') {\n\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', true);\n\t} else {\n\t\t$('input[name$=\"_useAsShippingAddress\"]').prop('checked', false);\n\t}\n\n\tbillingAddressFormValidator.form();\n\t$('.custom-email-error').remove();\n\n\tvar isEmailValid = util.validateEmail($('#dwfrm_billingaddress_email').val());\n\tif (billingAddressFormValidator.valid() && isEmailValid) {\n\t\t$billingAddressForm = $(billingAddressFormSelector);\n\t\t$billingAddressFormContainer.find('.validation-error-container').removeAttr('role').hide();\n\t\tverifyBilling(null, isVerified);\n\t} else {\n\t\t$billingAddressFormContainer.find('.validation-error-container').attr('role','alert').show();\n\t\t$('#submitBilling').attr('disabled', false);\n\t\tif (!isEmailValid && billingAddressFormValidator.valid()) {\n\t\t\t$('#dwfrm_billingaddress_email').addClass('error').parent().append('<span class=\"error custom-email-error\">' + Resources.VALIDATE_EMAIL + '</span>');\n\t\t}\n\t\t$('.billing-address-type-selector input[value=\"2\"]').trigger('click', [true]);\n\t}\n}\n\nfunction verifyBilling(isCancel, isVerified) {\n\tvar addressDeliverable = function () {\n\t\tsetOPCAddress(billingAddressFormSelector, $('#selectOpcAddress').attr('name')).then(function (data) {\n\t\t\tbillingAddressSuccessHandler(data, null, true);\n\t\t\t$('#submitBilling').attr('disabled', false);\n\t\t});\n\t}\n\n\tvar addressNotDeliverable = function (addressVerifyData) {\n\t\tAddressVerificationDialog.initialize(options, 'billing', addressVerifyData);\n\t\t$('#submitBilling').attr('disabled', false);\n\t}\n\n\tvar country = $billingAddressForm.find('[id*=\"_country\"]').val();\n\tif (!isVerified && options && options.Lob && options.Lob.AddressVerification.Enabled && country.toUpperCase() == 'US') {\n\t\tAddressVerificationHelper.VerifyAddress($billingAddressForm, options).then(addressDeliverable, addressNotDeliverable);\n\t} else {\n\t\taddressDeliverable();\n\t}\n}\n\nfunction submitShipping(isCancel, isVerified) {\n\t$('#submitShipping').attr('disabled', true);\n\t$('.shipping-address-cont span.error').remove();\n\t$('.shipping-address-cont input, .shipping-address-cont select').removeClass('error');\n\n\tshippingAddressFormValidator.form();\n\tif ($shippingAddressForm.valid()) {\n\t\t$shippingAddressFormContainer.find('.validation-error-container').removeAttr('role').hide();\n\t\tverifyShipping(isCancel, isVerified);\n\t} else {\n\t\t$shippingAddressFormContainer.find('.validation-error-container').attr('role','alert').show();\n\t\t$('#submitShipping').attr('disabled', false);\n\t}\n}\n\nfunction verifyShipping(isCancel, isVerified) {\n\tvar addressDeliverable = function () {\n\t\tsetOPCAddress(shippingAddressFormSelector, $('#submitShipping').attr('name')).then(function (data) {\n\t\t\tvar isShippingRestricted = handleShippingRestrictions(data);\n\t\t\t$('#submitShipping').attr('disabled', false);\n\t\t\tif (!isShippingRestricted) {\n\t\t\t\tshippingAddressSuccessHandler(false, isCancel, true);\n\t\t\t\t$('.payment-methods-section').show();\n\t\t\t}\n\t\t});\n\t}\n\n\tvar addressNotDeliverable = function (addressVerifyData) {\n\t\tAddressVerificationDialog.initialize(options, 'shipping', addressVerifyData);\n\t\t$('#submitShipping').attr('disabled', false);\n\t}\n\n\tvar country = $shippingAddressForm.find('[id*=\"_country\"]').val();\n\tif (!isVerified && options && options.Lob && options.Lob.AddressVerification.Enabled && country.toUpperCase() == 'US') {\n\t\tAddressVerificationHelper.VerifyAddress($shippingAddressForm, options).then(addressDeliverable, addressNotDeliverable);\n\t} else {\n\t\taddressDeliverable();\n\t}\n}\n\nfunction writeBufferToAddressForm(name, $selector) {\n\tif (dataBuffer[name]) {\n\t\t$selector.each(function (index, element) {\n\t\t\tvar $field = $(element);\n\t\t\t$field.val(dataBuffer[name][$field.attr('name')] || '');\n\t\t});\n\t\t\n\t\tif (name == 'shippingAddressFields') {\n\t\t\tvar $form = $('.shipping-address-form');\n\t\t\tvar $countryDropdown = $form.find('[id*=\"_country\"]');\n\t\t\tvar $stateDropdown = $form.find('[id*=\"states_state\"]');\n\t\t\trenderOptions('#' + $stateDropdown.attr('id'), '#' + $countryDropdown.attr('id'));\n\t\t\t\n\t\t\tif ($('#dwfrm_shippingaddress_states_state').length > 0 && dataBuffer['shippingAddressFields']['dwfrm_shippingaddress_states_state']) {\n\t\t\t\t$('#dwfrm_shippingaddress_states_state').val(dataBuffer['shippingAddressFields']['dwfrm_shippingaddress_states_state']);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction writeBufferToShippingAddressForm() {\n\tvar $shippingAddressFields = $shippingAddressForm.find('.formfield input[type=\"text\"], .formfield select').not('[disabled]').not('#dwfrm_shippingaddress_myStoreID');\n\twriteBufferToAddressForm('shippingAddressFields', $shippingAddressFields);\n}\n\nfunction writeAddressFormToBuffer(name, $selector, doClear) {\n\t$selector.each(function (index, element) {\n\t\tvar $field = $(element);\n\n\t\tif ($field.val()) {\n\t\t\tif (!dataBuffer[name]) {\n\t\t\t\tdataBuffer[name] = {};\n\t\t\t}\n\n\t\t\tdataBuffer[name][$field.attr('name')] = $field.val();\n\t\t}\n\t});\n\n\tif (doClear) {\n\t\t$selector.val('');\n\t\t$selector.find('option[default]').prop('selected', true);\n\t}\n}\n\nfunction writeShippingAddressFormToBuffer(doClear) {\n\tvar $shippingAddressFields = $shippingAddressForm.find('.formfield input[type=\"text\"], .formfield select').not('[disabled]').not('#dwfrm_shippingaddress_myStoreID');\n\twriteAddressFormToBuffer('shippingAddressFields', $shippingAddressFields, doClear);\n}\n\n/**\n * create address object from form\n * @param $form\n * @returns Address Object\n */\nfunction getAddressFromForm($form) {\n\treturn {\n\t\tID: util.htmlEncode($form.find('input[name$=\"_ID\"]').val()),\n\t\tisStore: util.htmlEncode($form.find('input[name$=\"_isStore\"]').prop('checked')),\n\t\tfirstName: util.htmlEncode($form.find('input[name$=\"_firstName\"]').val()),\n\t\tlastName: util.htmlEncode($form.find('input[name$=\"_lastName\"]').val()),\n\t\taddress1: util.htmlEncode($form.find('input[name$=\"_address1\"]').val()),\n\t\taddress2: util.htmlEncode($form.find('input[name$=\"_address2\"]').val()),\n\t\taddress3: util.htmlEncode($form.find('input[name$=\"_address3\"]').val()),\n\t\tcountryCode: util.htmlEncode($form.find('select[id$=\"_country\"]').val()),\n\t\tstateCode: util.htmlEncode($form.find('select[id$=\"_state\"]').val()),\n\t\tpostalCode: $form.find('input[name$=\"_postal\"]').val() ? util.htmlEncode($form.find('input[name$=\"_postal\"]').val().toUpperCase()) : '',\n\t\tcity: util.htmlEncode($form.find('input[name$=\"_city\"]').val()),\n\t\tphone: util.htmlEncode($form.find('input[name$=\"_phone\"]').val()),\n\t\temail: util.htmlEncode($form.find('input[name$=\"_email\"]').val())\n\t};\n}\n\nfunction populateBillingAddressFormToShippingAddressForm() {\n\tvar billingAddress = getAddressFromForm($billingAddressForm);\n\n\t$shippingAddressForm.find('input[name$=\"_ID\"]').val('');\n\t$shippingAddressForm.find('input[name$=\"_firstName\"]').val(billingAddress.firstName).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_lastName\"]').val(billingAddress.lastName).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_address1\"]').val(billingAddress.address1).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_address2\"]').val(billingAddress.address2).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_address3\"]').val(billingAddress.address3).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_postal\"]').val(billingAddress.postalCode).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_city\"]').val(billingAddress.city).trigger('change');\n\t$shippingAddressForm.find('select[id$=country]').val(billingAddress.countryCode).trigger('change');\n\t$shippingAddressForm.find('select[id$=state]').val(billingAddress.stateCode).trigger('change');\n\t$shippingAddressForm.find('input[name$=\"_phone\"]').val(billingAddress.phone).trigger('change');\n\n    if ($('#dwfrm_multipleshipping_addressList').find('option.placeholder').length == 0) {\n    \t$('#dwfrm_multipleshipping_addressList').prepend('<option class=\"placeholder\">' + Resources.OPC_SELECT_ADDR + '</option>').prop('selectedIndex', 0);\n    }\n}\n\nfunction buildDetailsBlockForForm($form, isCompact, hideNickname) {\n\tvar address = getAddressFromForm($form);\n\tfor (var addressKey in address) {\n    \tif (address[addressKey] != null && address[addressKey].search(/\\^/) != -1) {\n    \t\taddress[addressKey] = address[addressKey].replace(/\\^/gi,\"'\");\n    \t}\n    }\n\n\treturn buildDetailsBlockForAddress(address, isCompact, hideNickname, $form.attr('id'));\n}\n\nfunction buildDetailsBlockForAddress(address, isCompact, hideNickname, formId) {\n\tvar shippingAddressType = getShippingAddressType();\n    var htmlText = $('<div/>', {\"class\": \"address-details-st\"});\n    var header = isCompact ? '' : formId == 'billingAddressForm' ? '<h6>Billing Recipient</h6>' : formId == 'shippingAddressForm' ? '<h6>Ship To:</h6>' : '';\n    var editButton = (!isCompact && !shippingAddressType || shippingAddressType == SiteConstants.AddressTypes.Customer) ? '<p class=\"text-right edit-address-container\"><a class=\"edit-address-det\" tabindex=\"0\">Edit<span class=\"visually-hidden\">&nbsp;Address Information</span></a></p>' : '';\n    var addNewButton = '';\n\tvar addressNickname = '';\n\t\n\tif (formId == 'shippingAddressForm') {\n\t\tif (address.address1 && !hideNickname) {\n\t\t\tif (address.ID && !address.myStoreID) {\n\t\t\t\taddressNickname = address.ID;\n\t\t\t} else if (formId == 'shippingAddressForm' && shippingAddressType == SiteConstants.AddressTypes.Customer && dataBuffer['dwfrm_multipleshipping_addressList']) {\n\t\t\t\tvar selectedAddressFromDropdown = dataBuffer['dwfrm_multipleshipping_addressList'].filter(function (addressOption) {\n\t\t\t\t\treturn addressOption.UUID == $('#dwfrm_multipleshipping_addressList').val();\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (selectedAddressFromDropdown.length > 0 && selectedAddressFromDropdown[0].displayValue && $('[has-warehouse-shipment]').attr('has-warehouse-shipment') == 'true') {\n\t\t\t\t\tutil.fillAddressFields(selectedAddressFromDropdown[0], $('#shippingAddressForm'));\n\t\t\t\t\twriteShippingAddressFormToBuffer();\n\t\t\t\t\taddressNickname = selectedAddressFromDropdown[0].displayValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (addressNickname) {\n\t\t\t\taddressNickname = '<span class=\"address-nickname\">' + addressNickname + '</span>';\n\t\t\t}\n\n\t\t\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'view').attr('value', 'true');\n\t\t}\n\t\t\n\t\tif (!isCompact && shippingAddressType == SiteConstants.AddressTypes.Customer) {\n\t\t\taddNewButton = '<p class=\"add-address-container\"><a class=\"add-address-det\" tabindex=\"0\">+ Add New Address</a></p>';\n\t\t}\n\t}\n\t\n    var htmlcontent = '';\n    if (address.address1) {\n\t    htmlcontent += header;\n\t    htmlcontent += '<div class=\"address\" tabindex=\"0\"><div>' + (address.myStoreID ? address.fullName : address.firstName) + ' ' + address.lastName + addressNickname + ' </div>';\n\t    htmlcontent += '<div>' + address.address1 + ' </div>';\n\t    if (address.address2) {\n\t    \thtmlcontent += '<div>' + address.address2 + ' </div>';\n\t    }\n\n\t    if (address.address3) {\n\t    \thtmlcontent += '<div>' + address.address3 + ' </div>';\n\t    }\n\n\t    htmlcontent += '<div>' + address.city;\n\n\t    if (address.stateCode && address.stateCode.toUpperCase() != 'OTHER') {\n\t    \thtmlcontent += ' ' + address.stateCode;\n\t    }\n\n\t    htmlcontent += ' ' + address.postalCode;\n\t\thtmlcontent += ' ' + address.countryCode + '</div>';\n\t\tif (address.phone) {\n\t\t\thtmlcontent += '<div>' + address.phone + '</div>';\n\t\t}\n\n\t    if (address.email) {\n\t    \thtmlcontent += '<div class=\"billing-email-address\">' + address.email + '</div>';\n\t\t}\n\t\thtmlcontent += '</div>';\n\n\t    htmlcontent += editButton;\n\t    htmlcontent += addNewButton;\n    }\n\n    htmlText.html(htmlcontent);\n\n    return htmlText;\n}\n\n/**\n * @function\n * @description Helper method which constructs a URL for an AJAX request using the\n * entered address information as URL request parameters.\n */\nfunction getShippingMethodURL($form, url, extraParams) {\n    var params = {\n\t\tisStore: $form.find('input[name$=\"_isStore\"]').prop('checked'),\n\t\tmyStoreID: $form.find('input[name$=\"_myStoreID\"]').val(),\n    \taddress1: $form.find('input[name$=\"_address1\"]').val(),\n        address2: $form.find('input[name$=\"_address2\"]').val(),\n        address3: $form.find('input[name$=\"_address3\"]').val(),\n        countryCode: $form.find('select[id$=\"_country\"]').val(),\n        stateCode: $form.find('select[id$=\"_state\"]').val(),\n        postalCode: $form.find('input[name$=\"_postal\"]').val(),\n        city: $form.find('input[name$=\"_city\"]').val()\n    };\n\n    return util.appendParamsToUrl(url, $.extend(params, extraParams));\n}\n\nfunction updateShippingMethodList($form, doUpdateSummary, isMyStore, doDataLayerPush, $selectedShippingMethod) {\n\tif (!$shippingMethodList || $shippingMethodList.length === 0) { return; }\n\t\n\tvar shippingMethodListData = {\n\t\tselectedPaymentMethod: $paymentForm.find('input[name*=\"_selectedPaymentMethodID\"]').val()\n\t}\n\n\tvar $shipToStoreOptionInAddressPanel = $('.single.shipping-address-type-selector');\n\tif ($shipToStoreOptionInAddressPanel.length > 0) {\n\t\tif ($shipToStoreOptionInAddressPanel.find('input:checked').val() == SiteConstants.AddressTypes.Store) {\n\t\t\tshippingMethodListData.ShipToStoreOnly = true;\n\n\t\t\tif (dataBuffer[CheckoutConstants.User.SelectedStoreShippingMethod]) {\n\t\t\t\tshippingMethodListData.SelectShippingMethod = dataBuffer[CheckoutConstants.User.SelectedStoreShippingMethod];\n\t\t\t}\n\t\t} else if ($shipToStoreOptionInAddressPanel.find('input:checked').val() == SiteConstants.AddressTypes.Customer) {\n\t\t\tshippingMethodListData.ShipToStoreExclude = true;\n\n\t\t\tif (dataBuffer[CheckoutConstants.User.SelectedCustomerShippingMethod]) {\n\t\t\t\tshippingMethodListData.SelectShippingMethod = dataBuffer[CheckoutConstants.User.SelectedCustomerShippingMethod];\n\t\t\t}\n\t\t}\n\t}\n\n\tif (isMyStore) {\n\t\tshippingMethodListData.ShipToStoreOnly = true;\n\t}\n\n\tvar shippingMethodListUrl = getShippingMethodURL($form, Urls.shippingMethodsList);\n\t$shippingMethodList.load(shippingMethodListUrl, shippingMethodListData, function () {\n\t\tvar selectedStore = $shippingAddressForm.find('.formfield.myStoreID input').val();\n\t\tvar $shipToStoreShippingMethods;\n\t\tif (options && options.AgentStore && options.AgentStore.StoreShippingAddressOnly) {\n\t\t\t$shipToStoreShippingMethods = $('[shipping-method]');\n\t\t} else {\n\t\t\t$shipToStoreShippingMethods = $('[shipping-method][is-ship-to-store=\"true\"]');\n\t\t}\n\n\t\tif ($shipToStoreShippingMethods.length > 0) {\n\t\t\tvar selectedStoreFromShippingMethod = $shipToStoreShippingMethods.find('.store-selector select').val();\n\n\t\t\tif (selectedStoreFromShippingMethod && selectedStoreFromShippingMethod != selectedStore && $shipToStoreShippingMethods.find('.input-radio').is(':checked')) {\n\t\t\t\tselectedStore = selectedStoreFromShippingMethod;\n\t\t\t\t$shippingAddressForm.find('.formfield.myStoreID input').val(selectedStore);\n\t\t\t\tsetOPCAddress(shippingAddressFormSelector, 'dwfrm_shippingaddress_saveopcaddress').then(function (data) { });\n\t\t\t}\n\n\t\t\tbuildShipToStoreDetails($shipToStoreShippingMethods);\n\t\t}\n\n\t\tif (selectedStore && dataBuffer && dataBuffer['mystores_addressList']) {\n\t\t\tvar selectedStoreInBuffer = dataBuffer['mystores_addressList'].filter(function (address) {\n\t\t\t\treturn address.myStoreID == selectedStore;\n\t\t\t})[0];\n\n\t\t\tif (selectedStoreInBuffer && selectedStoreInBuffer.UUID != $('#mystores_addressList').val()) {\n\t\t\t\t$('#mystores_addressList').val(selectedStoreInBuffer.UUID);\n\t\t\t\tvar shippingAddressType = getShippingAddressType();\n\t\t\t\tif (shippingAddressType == SiteConstants.AddressTypes.Store) {\n\t\t\t\t\t$('#mystores_addressList').trigger('change');\n\t\t\t\t\tdoUpdateSummary = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$shippingMethodList.fadeIn('fast');\n\n\t\tif (doUpdateSummary) {\n\t\t\tupdateSummary();\n\t\t}\n\t\t\n\t\ttooltip.init({\n\t\t\titems: '.shipping-method-tooltip',\n\t\t\ttooltipClass: 'shipping-method-tooltip'\n\t\t}, $('[shipping-method]'));\n\t\ttooltip.init({\n\t\t\titems: '.tooltip.RewardsCredit',\n\t\t\ttooltipClass: 'RewardsCredit'\n\t\t}, $('[payment-method=\"REWARDS_CREDIT\"]'));\n\t\ttooltip.init({\n\t\t\titems: '.tooltip.LoyaltyCredit',\n\t\t\ttooltipClass: 'LoyaltyCredit'\n\t\t}, $('[payment-method=\"LOYALTY_CREDIT\"]'));\n\t\ttooltip.init({\n\t\t\titems: '.tooltip'\n\t\t}, $('.form-row.cvn'));\n\n\t\tvar isStoreAddress = isShipToStoreEnabled();\n\t\tsetShipToStore(isStoreAddress);\n\n\t\tif (doDataLayerPush) {\n\t\t\tpushDataLayerForShippingMethods($shippingMethodList, $selectedShippingMethod);\n\t\t}\n\t});\n}\n\n/**\n * @function\n * @description updates the order summary based on a possibly recalculated basket after a shipping promotion has been applied\n */\nfunction updateSummary() {\n    $(document).trigger('Cart.Update', {\n\t\t'EventTriggers': {\n\t\t\t'update-shipping': false\n\t\t}\n\t});\n}\n\nfunction getShippingAddressType() {\n\tvar shippingAddressType = $('.single.shipping-address-type-selector input:checked').val();\n\tif (!shippingAddressType) {\n\t\tshippingAddressType = SiteConstants.AddressTypes.Customer;\n\t}\n\treturn shippingAddressType;\n}\n\nfunction renderMyStoresAddressSelector(parameters) {\n\tvar templateSettings = {\n    \tinterpolate: /{{([\\s\\S]+?)}}/g\n    };\n\n    var templates = [];\n\ttemplates['option'] = _.template($('#template-address-selector-option').html(), templateSettings);\n\n\t$.ajax({\n\t\tmethod: 'POST',\n\t\turl: Urls.getMyStoresAddressList,\n\t\tcontentType: 'application/json',\n\t\tdata: JSON.stringify({ storeQuery: StoreQueryFilters.ShipToStoreEnabled }),\n\t\tdataType: 'json',\n\t\tsuccess: function(data) {\n\t\t\tvar html = [];\n\t\t\thtml['options'] = '';\n\n\t\t\tdataBuffer['mystores_addressList'] = data.addresses;\n\t\t\tdataBuffer['store_name_lookup'] = {};\n\t\t\tdata.addresses.map(function (element) {\n\t\t\t\tdataBuffer['store_name_lookup'][element.myStoreID] = element.fullName;\n\t\t\t});\n\n\t\t\tvar isStoreAddressSelected = false;\n\t\t\tfor (var index = 0; index < data.addresses.length; index++) {\n\t\t\t\tvar address = data.addresses[index];\n\n\t\t\t\tif (address.isSelected) {\n\t\t\t\t\tisStoreAddressSelected = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar optionData = _.extend(address, {\n\t\t\t\t\tid: address.UUID,\n\t\t\t\t\tcssClass: '',\n\t\t\t\t\tselected: address.isSelected ? 'selected' : '',\n\t\t\t\t\ttext: address.labelText\n\t\t\t\t});\n\n\t\t\t\toptionData.ID = address.myStoreID;\n\t\t\t\thtml['options'] += templates['option'](optionData);\n\t\t\t}\n\n\t\t\t$('#mystores_addressList').html(html['options']);\n\n\t\t\tif (isStoreAddressSelected) {\n\t\t\t\tsetShipToStore(true);\n\t\t\t\t$('.single.shipping-address-type-selector input[value=\"' + SiteConstants.AddressTypes.Store + '\"]').click();\n\t\t\t}\n\t\t\t\n\t\t\tif (parameters && parameters.callback) {\n\t\t\t\tparameters.callback();\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction renderAddressSelector(parameters) {\n\tvar templateSettings = {\n    \tinterpolate: /{{([\\s\\S]+?)}}/g\n    };\n\n    var templates = [];\n    templates['selector'] = _.template($('#template-address-selector').html(), templateSettings);\n    templates['option'] = _.template($('#template-address-selector-option').html(), templateSettings);\n\n\t$.ajax({\n\t\tmethod: 'POST',\n\t\turl: Urls.getAddressList,\n\t\tcontentType: 'application/json',\n\t\tdata: JSON.stringify({ storeQuery: StoreQueryFilters.ShipToStoreEnabled }),\n\t\tdataType: 'json',\n\t\tsuccess: function(data) {\n\t\t\tvar html = [];\n\t\t\tvar hasAddressBookAddresses = false;\n\t\t\tvar selectedAddressID = null;\n\n\t\t\tdataBuffer[parameters.id] = data.addresses;\n\n\t\t\tvar isAddressSelectedInData = false;\n\t\t\tfor (var index = 0; index < data.addresses.length; index++) {\n\t\t\t\tvar address = data.addresses[index];\n\t\t\t\t\n\t\t\t\tif (address.isSelected) {\n\t\t\t\t\tisAddressSelectedInData = true;\n\t\t\t\t\tselectedAddressID = address.ID;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\thtml['options'] = '';\n\t\t\tfor (var index = 0; index < data.addresses.length; index++) {\n\t\t\t\tvar address = data.addresses[index];\n\n\t\t\t\tif (address.isShippingAddress) {\n\t\t\t\t\tvar addressId = address.key ? address.key : address.ID;\n\t\t\t\t\tvar isSelected = false;\n\n\t\t\t\t\tif (!$shippingAddressForm.find('input[name$=\"_address1\"]').val() && $('[has-warehouse-shipment]').attr('has-warehouse-shipment') == 'true') {\n\t\t\t\t\t\tif (!isAddressSelectedInData) {\n\t\t\t\t\t\t\tif (!selectedAddressID && parameters.currentAddresses && parameters.currentAddresses.length > 0 && parameters.currentAddresses.indexOf(address.UUID) >= 0) {\n\t\t\t\t\t\t\t\tisSelected = true;\n\t\t\t\t\t\t\t\tselectedAddressID = address.ID;\n\t\t\t\t\t\t\t} else if (!selectedAddressID && parameters.selected && address.ID == parameters.selected && parameters.selected != \"new\") {\n\t\t\t\t\t\t\t\tisSelected = true;\n\t\t\t\t\t\t\t\tselectedAddressID = address.ID;\n\t\t\t\t\t\t\t} else if (!selectedAddressID && address.ID == $('#dwfrm_multipleshipping_addressList:visible option').val() && parameters.selected != \"new\") {\n\t\t\t\t\t\t\t\tisSelected = true;\n\t\t\t\t\t\t\t\tselectedAddressID = address.ID;\n\t\t\t\t\t\t\t} else if (!selectedAddressID && address.isDefault && parameters.selected != \"new\") {\n\t\t\t\t\t\t\t\tisSelected = true;\n\t\t\t\t\t\t\t\tselectedAddressID = address.ID;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar optionData = _.extend(address, {\n\t\t\t\t\t\tid: address.UUID,\n\t\t\t\t\t\tcssClass: '',\n\t\t\t\t\t\tselected: isSelected || address.isSelected ? 'selected' : '',\n\t\t\t\t\t\ttext: '(' + (!address.displayValue ? addressId : address.displayValue) + ') ' + address.labelText\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!address.isMyStore) {\n\t\t\t\t\t\thasAddressBookAddresses = true;\n\t\t\t\t\t}\n\n\t\t\t\t\thtml['options'] += templates['option'](optionData);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (hasAddressBookAddresses) {\n\t\t\t\thtml['selector'] = templates['selector']({\n\t\t\t\t\tid: parameters.id,\n\t\t\t\t\toptions: html['options']\n\t\t\t\t});\n\n\t\t\t\tvar $html = $(html['selector']);\n\n\t\t\t\tif (isSelected || address.isSelected) {\n\t\t\t\t\t$html.find('option.placeholder').remove();\n\t\t\t\t}\n\n\t\t\t\t$(parameters.el).html($html);\n\t\t\t\t$(parameters.container).show();\n\t\t\t} else {\n\t\t\t\t$(parameters.container).hide();\n\t\t\t}\n\n\t\t\tif (parameters && parameters.callback) {\n\t\t\t\tparameters.callback();\n\t\t\t}\n\t\t}\n\t});\t\n}\n\nfunction editBillingAddress() {\n\t$('.bill-address-fields').removeClass('collapsed').show();\n\t$('.billing-select-address').hide();\n\t\n\t$('.billing-address-preview').hide();\n\t$('.billing-address-data.form-info').hide();\n\t\n\t$billingAddressFormContainer.show();\n\t$billingAddressForm.show();\n\t\n\t$shippingAddressFormContainer.data('hidden-editable', $('.shipping-address-data.form-info').html().length ? true : false).hide();\n\t\n\t$('.form-checkout.shipping-address-section').removeClass('active').find('.shipping-address-cont').addClass('hidden');\n\t$('.form-checkout.payment-section').removeClass('active').find('.shipping-payment-cont').addClass('hidden');\n}\n\nfunction editShippingAddress() {\n\twriteShippingAddressFormToBuffer();\n\topenShippingAddressForm();\n}\n\nfunction openShippingAddressForm() {\n\t$('.form-checkout.shipping-address-section').attr('panel-mode', 'edit');\n\t$shippingAddressFormContainer.data('hidden-editable', true).hide();\n\t$('.shipping-address-data').hide();\n\t$shippingAddressFormContainer.show();\n\t$shippingAddressForm.removeClass('add edit').addClass('edit');\n\t$shippingAddressForm.find('input[name=\"action\"]').val('edit');\n\t\t\n\t$billingAddressForm.hide();\n\t$('.billing-address-data.form-info').css('display', 'block');\n\t$('.form-checkout.payment-section').removeClass('active').find('.shipping-payment-cont').addClass('hidden');\n\t\n\t$('.shipping-select-address').hide();\n\t$('.editaddress-shipping').removeClass('collapsed');\n}\n\nfunction setShipToStore(isStoreAddress) {\n\t$sectionCheckout.attr('is-my-store', isStoreAddress);\n\t$('#dwfrm_shippingaddress_isStore').prop('checked', isStoreAddress);\n}\n\nfunction isShipToStoreEnabled() {\n\treturn $('#dwfrm_shippingaddress_isStore').prop('checked');\n}\n\nfunction buildShipToStoreDetails($shippingMethods) {\n\t$shippingMethods.each(function(index, element) {\n\t\tvar $shippingMethod = $(element);\n\t\tvar $selectedStore = $shippingMethod.find('.store-selector option:checked');\n\t\tvar storeSelectorCount = $shippingMethod.find('.store-selector option').length;\n\t\tvar storeData = $selectedStore.data('address');\n\t\tif (storeData && storeData.address1) {\n\t\t\tvar storeHtml = '<p>' + storeData.name + '</p>' +\n\t\t\t\t\t\t\t'<p>' + storeData.address1 + '</p>';\n\t\t\tif (storeData.address2) {\n\t\t\t\tstoreHtml += '<p>' + storeData.address2 + '</p>';\n\t\t\t}\n\t\t\tstoreHtml += '<p>' + storeData.city + ', ' + storeData.state + ' ' + storeData.postalCode + '</p>';\n\t\n\t\t\tif (storeSelectorCount > 1 && SitePreferences.ENABLE_SHIP_TO_STORE_SELECTION && !isStoreShippingAddressOnly) {\n\t\t\t\tstoreHtml += '<a class=\"action change\" tabindex=\"0\">Change Store</a>';\n\t\t\t}\n\n\t\t\t$shippingMethod.find('.store-details').html(storeHtml);\n\t\t}\n\t});\n}\n\n/**\n * @function\n * @description selects a shipping method for the default shipment and updates the summary section on the right hand side\n * @param\n */\nfunction selectShippingMethod(shipmentID, shippingMethodID, isShipToStore, $selectedShippingMethod) {\n    var shippingAddressType = getShippingAddressType();\n\tif (shippingAddressType == SiteConstants.AddressTypes.Customer) {\n\t\tdataBuffer[CheckoutConstants.User.SelectedCustomerShippingMethod] = shippingMethodID;\n\t} else if (shippingAddressType == SiteConstants.AddressTypes.Store) {\n\t\tdataBuffer[CheckoutConstants.User.SelectedStoreShippingMethod] = shippingMethodID;\n\t}\n\n\tif (isShipToStore || isStoreShippingAddressOnly) {\n\t\tsetShipToStore(true); \n\t} else {\n\t\tsetShipToStore(false);\n\t}\n\n    // attempt to set shipping method\n    var url = getShippingMethodURL($shippingAddressForm, Urls.selectShippingMethodsList, {shipmentID: shipmentID, shippingMethodID: shippingMethodID});\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            // display promotion in UI and update the summary section,\n            // if some promotions were applied\n            $('.shippingpromotions').empty();\n\n            $('[name*=\"_shippingMethodID\"]').prop('disabled', false);\n            updateShippingMethodList($shippingAddressForm, true, null, true, $selectedShippingMethod);\n        }\n    });\n}\n\n/**\n * @description Make the AJAX request to set address data\n * @param {Element} form The form element that present address object\n * @param {Element} Action name to apply to form\n * @returns {Promise}\n */\nvar setOPCAddress = function (form, name) {\n\tvar $form = $(form);\n\tvar url = (form == '#billingAddressForm') ? Urls.setOpcAddress : $form.attr('action');\n\tvar sanitizedFormData = {};\n\tvar serializedFormDataArray = $form.serializeArray();\n\tvar hasCountryField = false;\n\tfor (var serializedFormDataKey in serializedFormDataArray) {\n\t\tvar serializedFormElement = serializedFormDataArray[serializedFormDataKey];\n\t\tif (serializedFormElement && serializedFormElement.name && sanitizedFormData[serializedFormElement.name]) {\n\t\t\tsanitizedFormData[serializedFormElement.name] += ',' + serializedFormElement.value;\n\t\t} else {\n\t\t\tsanitizedFormData[serializedFormElement.name] = serializedFormElement.value;\n\t\t}\n\t\tif (serializedFormElement && serializedFormElement.name && serializedFormElement.name.indexOf('_country') < 0) {\n\t\t\thasCountryField = true;\n\t\t}\n\t}\n\tif (hasCountryField) {\n\t\tvar $countryField = $form.find('[name$=\"_country\"]');\n\t\tsanitizedFormData[$countryField.attr('name')] = $countryField.val();\n\t}\n\tsanitizedFormData[name] = name;\n\n    return new Promise(function (resolve, reject) {\n\t\t$.ajax({\n\t\t\ttype: 'POST',\n\t\t\turl: util.ajaxUrl(url),\n\t\t\tdata: sanitizedFormData,\n\t\t\tsuccess: function(data) {\n\t\t\t\tresolve(data);\n\t\t\t},\n\t\t\terror: function(data) {\n\t\t\t\treject(data);\n\t\t\t}\n\t\t});\n    });\n};\n\nfunction pushDataLayerForShippingMethods($shippingMethodList, $selectedShippingMethod) {\n\tvar $selectedShippingMethods;\n\tif ($selectedShippingMethod) {\n\t\t$selectedShippingMethods = $selectedShippingMethod;\n\t} else {\n\t\t$selectedShippingMethods = $shippingMethodList.find('input[type=\"radio\"]:checked');\n\t}\n\t$selectedShippingMethods.each(function(index, element) {\n\t\tvar $this = $(this);\n\t\tvar $shippingMethod = $this.closest('[shipping-method]');\n\t\tvar dataObject = {\n\t\t\tvalue: parseFloat($shippingMethod.attr('amount')),\n\t\t\tshipping_tier: $shippingMethod.attr('shipping-method')\n\t\t}\n\n\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddShippingInfo', dataObject, { ContainerSelector: '.order-item[shipment=\"' + $shippingMethod.closest('form').attr('shipment') + '\"]' }).catch(function() {});\n\t});\n}\n\nfunction handleShippingRestrictions(data) {\n\t$('.shipping-address-cont').find('> .error').remove();\n\tvar hasShippingRestrictions = data.status == 'shippingRestrictionsError';\n\tif (hasShippingRestrictions) {\n\t\topenRestrictionsPopup(data);\n\t}\n\n\treturn hasShippingRestrictions;\n}\n\nfunction openRestrictionsPopup(data) {\n\tvar payload = JSON.parse(data.payload);\n\tvar popup = require('../../popup');\n\t\n\tvar restrictionList = '';\n\tif (payload.list && payload.list.length > 0) {\n\t\tvar list = $.map(payload.list, function (el) {\n\t\t\tvar restrictionName = el.name ? el.name + ':<br/>' : '';\n\t\t\t\n\t\t\treturn '<li>' + restrictionName + el.message + '</li>';\n\t\t}).join('');\n\t\t\n\t\trestrictionList = '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>';\n\t}\n\t\n\tpopup.init({\n\t\ttitle: payload.title,\n\t\tcontent: payload.message + restrictionList\n\t}).showPopup();\n}\n\nfunction renderOptions(optionParent, optionsStoreId) {\n\tvar optionsHtml;\n\tvar optionsStoreOptions = $(optionsStoreId + ' option:selected').data('options');\n\tvar statesList;\n\t\n\tif (optionsStoreOptions) {\n\t\tstatesList = JSON.parse(optionsStoreOptions.replace(/\\'/g, '\\\"'));\n\t\t\n\t\tif (statesList.length > 1) {\n\t\t\toptionsHtml += '<option value=\"\">' + Resources.SelectPlaceholder + '</option>';\n\t\t}\n\t\t\n\t\tstatesList.forEach(function (state) {\n\t\t\toptionsHtml += '<option class=\"select-option\" label=\"' + state.label + '\" value=\"' + state.code + '\">' + state.label + '</option>';\n\t\t});\n\n\t\tvar $optionParent = $(optionParent);\n\t\t$optionParent.empty().append(optionsHtml);\n\n\t\tif (statesList.length <= 1) {\n\t\t\t$optionParent.prop('selectedIndex', statesList.length - 1);\n\t\t\t$optionParent.removeClass('required');\n\t\t\t$optionParent.closest('.formfield').hide();\n\t\t} else {\n\t\t\t$optionParent.addClass('required');\n\t\t\t$optionParent.closest('.formfield').show();\n\t\t}\n\t}\n}\n\n$(document).on('update-shipping', function() {\n\tif ($('.shipping-methods-section').length == 0) { return; }\n\tupdateShippingMethodList($shippingAddressForm);\n});\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter || {};\n\n\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\tAddressVerificationDialog = require('../../Lob/AddressVerification/AddressVerificationDialog');\n\t}\n\n\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\tAddressAutocompleteDialog = require('../../Lob/AddressAutocomplete/AddressAutocompleteDialog');\n\t}\n\n\tisStoreShippingAddressOnly = !!(options && options.AgentStore && options.AgentStore.StoreShippingAddressOnly);\n\tif (isStoreShippingAddressOnly) {\n\t\tsetShipToStore(true);\n\t}\n\tinitializeEvents();\n\tinitializeUserInterface();\n};\n\nexports.updateSummary = updateSummary;","'use strict';\n\nvar $errorBox = $('<div />', { 'id': 'errorBoxOPC', 'class': 'payment-declined p-2 mt-2', 'role': 'alert', 'tabindex': '0' });\nvar $errorBoxIcon = $('<i />', { 'class': 'fa fa-exclamation-triangle', 'role': 'presentation' });\nvar $errorBoxHeadline = $('<span />', { 'class': 'opc-error-box-headline' });\nvar $errorBoxMessage = $('<span />', { 'class': 'opc-error-box-message' });\n\nfunction getErrorMessage(fieldType) {\n\tvar errorMessage;\n\tswitch (true) {\n\t\tcase (fieldType.indexOf('_loyaltyNumber') > -1):\n            errorMessage = window.Resources.OPC_LOYALTY_NUMBER_ERROR;\n            break;\n\t\tcase (fieldType.indexOf('_loyaltyZipCode') > -1):\n\t\t\terrorMessage = window.Resources.OPC_LOYALTY_ZIP_ERROR;\n\t\t\tbreak;\n\t\tcase (fieldType.indexOf('_loyaltyPhoneNumber') > -1):\n\t\t\terrorMessage = window.Resources.OPC_LOYALTY_PHONE_ERROR;\n\t\t\tbreak;\n\t\tcase (fieldType.indexOf('_rewardsNumber') > -1):\n            errorMessage = window.Resources.OPC_REWARDS_NUMBER_ERROR;\n            break;\n\t\tcase (fieldType.indexOf('_rewardsZipCode') > -1):\n\t\t\terrorMessage = window.Resources.OPC_REWARDS_ZIP_ERROR;\n\t\t\tbreak;\n\t\tcase (fieldType.indexOf('_rewardsPhoneNumber') > -1):\n\t\t\terrorMessage = window.Resources.OPC_REWARDS_PHONE_ERROR;\n\t\t\tbreak;\n\t\tcase (fieldType.indexOf('_giftCard_number') > -1):\n            errorMessage = window.Resources.OPC_GIFT_CARD_ERROR;\n            break;\n\t\tcase (fieldType.indexOf('_giftCard_pin') > -1):\n            errorMessage = window.Resources.OPC_GIFT_CARD_PIN_ERROR;\n            break;\n        case (fieldType.indexOf('_privateLabelCredit_number') > -1):\n            errorMessage = window.Resources.OPC_PRIVATE_LABEL_ERROR;\n            break;\n        case (fieldType.indexOf('_creditCard_owner') > -1):\n            errorMessage = window.Resources.OPC_CARD_OWNER_ERROR;\n            break;\n\t\tcase (fieldType.indexOf('_creditCard_number') > -1):\n\t\t\terrorMessage = window.Resources.OPC_CARD_NUMBER_ERROR;\n\t\t\tbreak;\n\t\tcase (fieldType.indexOf('_creditCard_cvn') > -1):\n\t\t\terrorMessage = window.Resources.OPC_SECURITY_CODE_ERROR;\n\t\t\tbreak;\n        default:\n            return;\n    }\n\treturn errorMessage;\n}\n\nfunction getPaymentFormErrorMessages($form) {\n\tif (!$form || $form.length == 0 || $form.find('.field.error').length == 0) {\n\t\treturn;\n\t}\n\tvar errorsList = new Array();\n\t$form.find('.field.error').each(function (index, element) {\n\t\tvar errorMessage = getErrorMessage($(element).attr('name'));\n\t\tif (errorMessage) {\n\t\t\terrorsList.push(errorMessage);\n\t\t}\n\t});\n\treturn errorsList;\n}\n\nfunction paymentErrorBox(headline, message, errorItems) {\n\t$errorBox.html('');\n\n\tif (!headline || !message) {\n\t\treturn;\n\t}\n\n\t$errorBoxHeadline.html('&nbsp;' + headline + ':&nbsp;');\n\t$errorBoxMessage.html(message + '&nbsp;');\n\t$errorBox.append($errorBoxIcon).append($errorBoxHeadline).append($errorBoxMessage);\n\n\tif (errorItems && errorItems.length > 0) {\n\t\tfor (var i = 0; i < errorItems.length; i++) {\n\t\t\tvar $newErrorItem = errorListItem(errorItems[i]);\n\t\t\t$errorBox.append($newErrorItem);\n\t\t}\n\t}\n\n\treturn $errorBox;\n}\n\nfunction errorListItem(errorMsg) {\n\tvar $errorListItem = $('<span />', { 'class': 'opc-error-box-item' });\n\t\t$errorListItem.html(errorMsg + '&nbsp;');\n\n\treturn $errorListItem;\n}\n\nexports.getErrorMessages = getPaymentFormErrorMessages;\nexports.errorBox = paymentErrorBox;","'use strict';\n\nvar ajax = require('../../ajax'),\n    formPrepare = require('./formPrepare'),\n    progress = require('../../progress'),\n    tooltip = require('../../tooltip'),\n    util = require('../../util');\n\nvar shippingMethods;\n/**\n * @function\n * @description Initializes gift message box, if shipment is gift\n */\nfunction giftMessageBox() {\n    // show gift message box, if shipment is gift\n    $('.gift-message-text').toggleClass('hidden', $('input[name$=\"_shippingAddress_isGift\"]:checked').val() !== 'true');\n}\n\n/**\n * @function\n * @description updates the order summary based on a possibly recalculated basket after a shipping promotion has been applied\n */\nfunction updateSummary() {\n    var $summary = $('#secondary.summary');\n    // indicate progress\n    progress.show($summary);\n\n    // load the updated summary area\n    $summary.load(Urls.summaryRefreshURL, function () {\n        // hide edit shipping method link\n        $summary.fadeIn('fast');\n        $summary.find('.checkout-mini-cart .minishipment .header a').hide();\n        $summary.find('.order-totals-table .order-shipping .label a').hide();\n        $(document).trigger('update-summary');\n    });\n}\n\n/**\n * @function\n * @description Helper method which constructs a URL for an AJAX request using the\n * entered address information as URL request parameters.\n */\nfunction getShippingMethodURL(url, extraParams) {\n    var $form = $('.address');\n    var params = {\n        address1: $form.find('input[name$=\"_address1\"]').val(),\n        address2: $form.find('input[name$=\"_address2\"]').val(),\n        address3: $form.find('input[name$=\"_address3\"]').val(),\n        countryCode: $form.find('select[id$=\"_country\"]').val(),\n        stateCode: $form.find('select[id$=\"_state\"]').val(),\n        postalCode: $form.find('input[name$=\"_postal\"]').val(),\n        city: $form.find('input[name$=\"_city\"]').val()\n    };\n    return util.appendParamsToUrl(url, $.extend(params, extraParams));\n}\n\n/**\n * @function\n * @description selects a shipping method for the default shipment and updates the summary section on the right hand side\n * @param\n */\nfunction selectShippingMethod(shippingMethodID) {\n    // nothing entered\n    if (!shippingMethodID) {\n        return;\n    }\n    // attempt to set shipping method\n    var url = getShippingMethodURL(Urls.selectShippingMethodsList, {shippingMethodID: shippingMethodID});\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            updateSummary();\n            if (!data || !data.shippingMethodID) {\n                window.alert('Couldn\\'t select shipping method.');\n                return false;\n            }\n            // display promotion in UI and update the summary section,\n            // if some promotions were applied\n            $('.shippingpromotions').empty();\n\n            // TODO the for loop below isn't doing anything?\n            // if (data.shippingPriceAdjustments && data.shippingPriceAdjustments.length > 0) {\n            //     var len = data.shippingPriceAdjustments.length;\n            //     for (var i=0; i < len; i++) {\n            //         var spa = data.shippingPriceAdjustments[i];\n            //     }\n            // }\n        }\n    });\n}\n\n/**\n * @function\n * @description Make an AJAX request to the server to retrieve the list of applicable shipping methods\n * based on the merchandise in the cart and the currently entered shipping address\n * (the address may be only partially entered).  If the list of applicable shipping methods\n * has changed because new address information has been entered, then issue another AJAX\n * request which updates the currently selected shipping method (if needed) and also updates\n * the UI.\n */\nfunction updateShippingMethodList() {\n    var $shippingMethodList = $('#shipping-method-list');\n    if (!$shippingMethodList || $shippingMethodList.length === 0) { return; }\n    var url = getShippingMethodURL(Urls.shippingMethodsJSON);\n\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            if (!data) {\n                window.alert('Couldn\\'t get list of applicable shipping methods.');\n                return false;\n            }\n            if (shippingMethods && shippingMethods.toString() === data.toString()) {\n                // No need to update the UI.  The list has not changed.\n                return true;\n            }\n\n            // We need to update the UI.  The list has changed.\n            // Cache the array of returned shipping methods.\n            shippingMethods = data;\n            // indicate progress\n            progress.show($shippingMethodList);\n\n            // load the shipping method form\n            var smlUrl = getShippingMethodURL(Urls.shippingMethodsList);\n            $shippingMethodList.load(smlUrl, function () {\n                $shippingMethodList.fadeIn('fast');\n                // rebind the radio buttons onclick function to a handler.\n                $shippingMethodList.find('[name$=\"_shippingMethodID\"]').click(function () {\n                    selectShippingMethod($(this).val());\n                });\n\n                // update the summary\n                updateSummary();\n                progress.hide();\n                tooltip.init();\n                //if nothing is selected in the shipping methods select the first one\n                if ($shippingMethodList.find('.input-radio:checked').length === 0) {\n                    $shippingMethodList.find('.input-radio:first').prop('checked', 'checked');\n                }\n            });\n        }\n    });\n}\n\nexports.init = function () {\n    formPrepare.init({\n        continueSelector: '[name$=\"shippingAddress_save\"]',\n        formSelector:'[id$=\"singleshipping_shippingAddress\"]'\n    });\n    $('input[name$=\"_shippingAddress_isGift\"]').on('click', giftMessageBox);\n\n    $('.address').on('change',\n        'input[name$=\"_addressFields_address1\"], input[name$=\"_addressFields_address2\"], input[name$=\"_addressFields_address3\"], select[name$=\"_addressFields_states_state\"], input[name$=\"_addressFields_city\"], input[name$=\"_addressFields_zip\"]',\n        updateShippingMethodList\n    );\n\n    giftMessageBox();\n    updateShippingMethodList();\n};\n\nexports.updateShippingMethodList = updateShippingMethodList;\n","'use strict';\n\nvar _ = require('lodash');\nvar AddressAutocompleteDialog;\nvar AddressVerificationDialog;\nvar AddressVerificationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/js/AddressVerification/AddressVerificationHelper');\nvar ApplePay = require('./checkout/ApplePay');\nvar CheckoutConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants');\nvar GiftCard = require('./checkout/GiftCardPaymentPanel');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar PaymentMethodConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar RewardsCredit = require('./checkout/RewardsCredit');\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\nvar tooltip = require('../tooltip');\nvar TPromise = require('promise');\nvar util = require('../util');\n\nvar checkoutFormSelector = '#checkout-form';\nvar $checkoutForm = $(checkoutFormSelector);\nvar creditCardTypeListSelector = '.payment-card-list';\nvar $creditCardTypeList = $(creditCardTypeListSelector);\nvar creditCardNumberInputSelector = '.formfield.card-number input';\nvar $creditCardNumberInput = $(creditCardNumberInputSelector);\nvar creditCardExpirationMonthInputSelector = '.monthfield input';\nvar $creditCardExpirationMonthInput = $(creditCardExpirationMonthInputSelector);\nvar creditCardExpirationYearInputSelector = '.yearfield input';\nvar $creditCardExpirationYearInput = $(creditCardExpirationYearInputSelector);\nvar creditCardCVVInputSelector = '.form-row.cvn input';\nvar $creditCardCVVInput = $(creditCardCVVInputSelector);\nvar addressInputSelector = '.formfield.address1 input';\nvar $addressInput = $(addressInputSelector);\nvar submitPaymentSelector = '#submitOPCPayment';\nvar $submitPayment = $(submitPaymentSelector);\nvar $rewardsAccordion = $('.rewards');\nvar $rewardsPaymentContainer = $rewardsAccordion.find('[payment-method=\"REWARDS_CREDIT\"]');\nvar $rewardsForm = $rewardsPaymentContainer.find('.rewards-form');\nvar $rewardsApplied = $rewardsPaymentContainer.find('.rewards-applied');\n\nvar options = {};\nvar dataBuffer = {};\n\nfunction initialize(options) {\n    $(document).on('click', submitPaymentSelector, function(event) {\n    \tevent.preventDefault();\n\n\t\tvar addressDeliverable = function () {\n\t\t\tsubmitPayment();\n\t\t}\n\t\n\t\tvar addressNotDeliverable = function (addressVerifyData) {\n\t\t\tAddressVerificationDialog.initialize(options, 'billing', addressVerifyData);\n\t\t}\n\t\n\t\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\t\tAddressVerificationHelper.VerifyAddress($checkoutForm, options).then(addressDeliverable, addressNotDeliverable);\n\t\t} else {\n\t\t\taddressDeliverable();\n\t\t}\n    });\n\n\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\t$checkoutForm.off('keyup.AddressAutocomplete').on('keyup.AddressAutocomplete', 'input[type=\"text\"]', function (event) {\n\t\t\tvar $this = $(this);\n\t\t\tvar $form = $this.closest('form');\n\t\t\tvar formValidator = $form.validate();\n\n\t\t\tif (event.keyCode == 8 || event.keyCode == 46) {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t} else if (!formValidator.checkForm() && ($this.attr('id').indexOf('_address1') >= 0 || $this.attr('id').indexOf('_address2') >= 0)) {\n\t\t\t\tvar addressAutocompleteHandler = function (addressAutocompleteData) {\n\t\t\t\t\tAddressAutocompleteDialog.initialize(options, addressAutocompleteData);\n\t\t\t\t}\n\t\t\t\n\t\t\t\tAddressVerificationHelper.AutocompleteAddress($form, $this, options).then(addressAutocompleteHandler);\n\t\t\t} else {\n\t\t\t\t$this.parent().find('.address-autocomplete-dialog').remove();\n\t\t\t}\n\t\t});\n\t\t\n\t\t$(document).off('SetAddressFromAddressAutocomplete').on('SetAddressFromAddressAutocomplete', function (event, data) {\n\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog(data.$form, data.Address);\n\t\t\t$checkoutForm.find('#dwfrm_billing_billingAddress_email_emailAddress, input.phone, input.postal').trigger('blur.RewardsAccountSearch');\n\t\t});\n\t}\n\n\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\t$(document).off('SetAddressFromAddressVerification').on('SetAddressFromAddressVerification', function (event, addressData) {\n\t\t\tAddressVerificationHelper.SetAddressFromAddressVerificationDialog($checkoutForm, addressData);\n\t\t\tsubmitPayment();\n\t\t});\n\t}\n\n\t$checkoutForm.off('blur.RewardsAccountSearch').on('blur.RewardsAccountSearch', '#dwfrm_billing_billingAddress_email_emailAddress, input.phone, input.postal', function(event) {\n\t\tif (dataBuffer['RewardsAccountSearchRequest'] && dataBuffer['RewardsAccountSearchRequest'].readyState !== 4) {\n\t\t\tdataBuffer['RewardsAccountSearchRequest'].abort();\n\t\t\tdataBuffer['RewardsAccountSearchRequest'] = null;\n\t\t}\n\n\t\tvar $this = $(this);\n\t\tvar field = $this.closest('[field]').attr('field');\n\t\tvar value = $this.val();\n\t\tif (field && value) {\n\t\t\tif (!dataBuffer['RewardsData']) {\n\t\t\t\tdataBuffer['RewardsData'] = {};\n\t\t\t}\n\t\t\tdataBuffer['RewardsData'][field] = value;\n\n\t\t\tswitch (field) {\n\t\t\t\tcase 'emailAddress':\n\t\t\t\t\t$rewardsForm.find('#dwfrm_billing_rewards_rewardsEmail').val(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'phone':\n\t\t\t\t\t$rewardsForm.find('.field.phonenumber').val(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'postal':\n\t\t\t\t\t$rewardsForm.find('.field.zipcode').val(value);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvar isRewardsDataReady = dataBuffer['RewardsData']['emailAddress'] && dataBuffer['RewardsData']['phone'] && dataBuffer['RewardsData']['postal'];\n\t\t\tvar isRewardsNumberFieldEmpty = !$rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val();\n\t\t\tif (isRewardsDataReady && isRewardsNumberFieldEmpty) {\n\t\t\t\tvar payload = {\n\t\t\t\t\tEmailAddress: dataBuffer['RewardsData']['emailAddress'],\n\t\t\t\t\tPhoneNumber: dataBuffer['RewardsData']['phone'],\n\t\t\t\t\tZipCode: dataBuffer['RewardsData']['postal'],\n\t\t\t\t}\n\n\t\t\t\tif ($rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val()) {\n\t\t\t\t\tpayload.RewardsNumber = $rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val();\n\t\t\t\t}\n\n\t\t\t\tdataBuffer['RewardsAccountSearchRequest'] = $.ajax({\n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\turl: Urls.searchForRewards,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tdataType: 'json',\n\t\t\t\t\tdata: JSON.stringify(payload),\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\trenderRewardsData(data);\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function(xhr) {\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\n\t$rewardsForm.off('keyup.RewardsReset change.RewardsReset').on('keyup.RewardsReset change.RewardsReset', 'input', function(event) {\n\t\tvar isRewardsFormPopulated = false;\n\t\t$rewardsForm.find('input').each(function() {\n\t\t\tif ($(this).val()) {\n\t\t\t\tisRewardsFormPopulated = true;\n\t\t\t}\n\t\t});\n\t\tif (isRewardsFormPopulated) {\n\t\t\t$rewardsForm.find('.btn.reset-echo').removeAttr('disabled');\n\t\t} else {\n\t\t\t$rewardsForm.find('.btn.reset-echo').attr('disabled', 'true');\n\t\t}\n\t});\n\n\t$rewardsForm.off('click.RewardsReset').on('click.RewardsReset', '.btn.reset-echo', function(event) {\n\t\tevent.preventDefault();\n\n\t\tif ($rewardsApplied.find('.reward-row[status=\"applied\"]').length > 0) {\n\t\t\t$rewardsApplied.find('.reward-row[status=\"applied\"] .btn.remove').trigger('RewardsCredit.Remove', { ResetSessionData: true });\n\t\t} else {\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.resetRewardsSessionData,\n\t\t\t\ttype: 'POST'\n\t\t\t});\n\t\t}\n\t\t$rewardsApplied.html('');\n\t\t$rewardsForm.find('input').val('');\n\t\t$rewardsForm.find('.btn.reset-echo').attr('disabled', 'true');\n\t\t$rewardsForm.find('[match]').removeAttr('match');\n\t\t$rewardsAccordion.removeAttr('rewards-found');\n\t});\n\n\t$(document).off('RewardsAccountSearch').on('RewardsAccountSearch', function(event) {\n\t\tsearchRewards();\n\t});\n\n\tupdateCart('dwfrm_cart_updateCart');\n\n\t$rewardsForm.off('click.RewardsAccountSearch').on('click.RewardsAccountSearch', '.btn.search-echo', function(event) {\n\t\tevent.preventDefault();\n\t\tsearchRewards();\n\t});\n\n\t$creditCardNumberInput.off('keydown.CreditCardNumberHandler').on('keydown.CreditCardNumberHandler', function(event) {\n\t\t$creditCardTypeList.val('');\n\t});\n\n\t$creditCardNumberInput.off('keyup.CreditCardNumberHandler').on('keyup.CreditCardNumberHandler', function(event) {\n\t\tvar $this = $(this);\n\t\tvar creditCardNumber = $this.val();\n\t\t\n\t\tvar selectedCard = util.getCreditCardType(creditCardNumber);\n\t\tif (selectedCard) {\n\t\t\tif ($creditCardNumberInput.filter(':visible').length < 1) {\n\t\t\t\t$creditCardNumberInput.val(creditCardNumber);\n\t\t\t}\n\t\t\t\n\t\t\t$('input[name*=\"_creditCard_type\"]').val(selectedCard.PaymentCard);\n\t\t\t$('input[name*=\"_selectedPaymentMethodID\"]').val(selectedCard.PaymentMethod);\n\t\t\t$creditCardTypeList.find('input[type=\"radio\"][value=\"' + selectedCard.PaymentCardDisplayKey + '\"]').first().prop('checked', true).trigger('change', { doReset: false });\n\t\t\tvar $paymentCardImage = $creditCardTypeList.find('input[value=\"' + selectedCard.PaymentCardDisplayKey + '\"]');\n\t\t\tvar paymentCardImageUrl;\n\t\t\tif ($paymentCardImage && $paymentCardImage.length > 0) {\n\t\t\t\tpaymentCardImageUrl = $paymentCardImage.attr('payment-card-image');\n\t\t\t}\n\n\t\t\tif (paymentCardImageUrl) {\n\t\t\t\t$creditCardNumberInput.css('background-image', 'url(' + paymentCardImageUrl + ')');\n\t\t\t}\n\n\t\t\tif (creditCardNumber.length >= 16) {\n\t\t\t\t$creditCardExpirationMonthInput.focus();\n\t\t\t}\n\t\t\tif (selectedCard.PaymentMethod == 'Alliance_Data') {\n\t\t\t\t$('.formfield.card-name').hide();\n\t\t\t\t$('.formfield.card-name input').removeClass('required');\n\t\t\t\t$('.card-expiration-and-cvn').addClass('number-only');\n\t\t\t\t$('.card-expiration-and-cvn input').removeClass('required');\n\t\t\t}\n\t\t} else {\n\t\t\t$creditCardTypeList.find('input').prop('checked', false);\n\t\t\t$creditCardTypeList.find('option').prop('selected', false);\n\t\t\t$creditCardNumberInput.css('background-image', '');\n\t\t\t$('.formfield.card-name').show();\n\t\t\t$('.formfield.card-name input').addClass('required');\n\t\t\t$('.card-expiration-and-cvn').removeClass('number-only');\n\t\t\t$('.card-expiration-and-cvn input').addClass('required');\n\t\t}\n\t});\n\n\t$creditCardExpirationMonthInput.off('keydown.FieldBlock').on('keypress.FieldBlock', function(event) {\n\t\tif ($(this).val().length >= 2) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t});\n\n\t$creditCardExpirationMonthInput.off('keyup.FieldShift').on('keyup.FieldShift', function(event) {\n\t\tif ($(this).val().length >= 2) {\n\t\t\t$creditCardExpirationYearInput.focus();\n\t\t}\n\t});\n\n\t$creditCardExpirationYearInput.off('keydown.FieldBlock').on('keypress.FieldBlock', function(event) {\n\t\tif ($(this).val().length >= 2) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t});\n\n\t$creditCardExpirationYearInput.off('keyup.FieldShift').on('keyup.FieldShift', function(event) {\n\t\tif ($(this).val().length >= 2) {\n\t\t\t$creditCardCVVInput.focus();\n\t\t}\n\t});\n\n\t$creditCardCVVInput.off('keyup.FieldShift').on('keyup.FieldShift', function(event) {\n\t\tvar cvvLength = $('input[name*=\"_creditCard_type\"]').val() == 'Amex' ? 4 : 3;\n\n\t\tif ($(this).val().length >= cvvLength) {\n\t\t\t$addressInput.focus();\n\t\t}\n\t});\n\n\t$(document).on('click', '.accordion-head', function(event) {\n\t\t$(this).toggleClass('active');\n\t});\n\n\t$(document).off('click', 'button[name$=\"addCoupon\"]').on('click', 'button[name$=\"addCoupon\"]', function (event) {\n\t\tevent.preventDefault();\n\t\t\n\t\tvar $this = $(this);\n\t\tvar $container = $this.closest('.cart-coupon-code');\n\t\tvar $applyButton = $container.find('.btn-coupon-code');\n\t\t$('.error.coupon-error').text('');\n\t\t\n\t\t(function() {\n\t\t\t$applyButton.loading({\n\t\t\t\tIsLabelShown: false,\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\n\t\t\treturn TPromise.resolve($.ajax({\n\t\t\t\ttype: 'POST',\n\t\t\t\turl: util.ajaxUrl(Urls.onePageSubmit),\n\t\t\t\tdata: {\n\t\t\t\t\tdwfrm_cart_addCoupon: 'dwfrm_cart_addCoupon',\n\t\t\t\t\tdwfrm_cart_couponCode: $('.accordion.coupon #dwfrm_cart_couponCode').val(),\n\t\t\t\t\trespType: 'json'\n\t\t\t\t}\n\t\t\t}));\n\t\t}()).then(function (response) {\n\t\t\tif (response.success && response.success !== CheckoutConstants.ResponseCodes.AlreadyInBasket) {\t\t\t\t\n\t\t\t\t$(document).trigger('Cart.Update');\n\t\t\t} else {\n\t\t\t\tvar message = response.success == CheckoutConstants.ResponseCodes.AlreadyInBasket ? Resources.COUPON_ADD_ERROR_DUP : Resources.COUPON_ADD_ERROR;\n\t\t\t\t$('<span/>', {'class': 'error coupon-error', 'text': message}).insertAfter('.accordion.coupon .cart-coupon-code .pcode-coupon');\n\t\t\t\tif ($applyButton.attr('loading')) {\n\t\t\t\t\t$applyButton.loading('destroy');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t$(document).off('click', 'button[name$=\"deleteCoupon\"]').on('click', 'button[name$=\"deleteCoupon\"]', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $container = $this.closest('.coupon');\n\t\tvar name = $this.attr('name');\n\t\t(function(){\n\t\t\t$container.loading({\n\t\t\t\tIsLabelShown: false,\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\n\t\t\treturn TPromise.resolve($.ajax({\n\t\t\t\ttype: 'POST',\n\t\t\t\turl: util.ajaxUrl(Urls.onePageSubmit),\n\t\t\t\tdata: $('form#cart-items-form').serialize() + '&' + name + '=' + name + '&respType=json'\n\t\t\t}));\n\t\t}()).then(function (response) {\n\t\t\t$(document).trigger('Cart.Update');\n\t\t});\n\t});\n\n\t$(document).off('click', '.order-total-payments [payment-method] .remove').on('click', '.order-total-payments [payment-method] .remove', function (e) {\n\t\tvar paymentInstrumentUUID = $(e.currentTarget).closest('[payment-method').attr('uuid');\n\t\n\t\tif (paymentInstrumentUUID) {\n\t\t\tvar requestPayload = {\n\t\t\t\tUUID: paymentInstrumentUUID\n\t\t\t}\n\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.removePaymentInstrument,\n\t\t\t\ttype: 'POST',\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify(requestPayload),\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tlocation.reload();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t$(document).off('Cart.Update').on('Cart.Update', function (event, data) {\n    \tupdateCart('dwfrm_cart_updateCart', data);\n    });\n\n\tsearchRewards();\n\tupdateCart('dwfrm_cart_updateCart');\n}\n\nvar updateCartBuffer;\nvar updateCartXmlHttpRequestBuffer;\nfunction updateCart(triggerElementName, options, isCartPage) {\n\tif (updateCartXmlHttpRequestBuffer) {\n\t\tfor (var updateCartXmlHttpRequestKey in updateCartXmlHttpRequestBuffer) {\n\t\t\tvar updateCartXmlHttpRequest = updateCartXmlHttpRequestBuffer[updateCartXmlHttpRequestKey];\n\t\t\t\n\t\t\tif (updateCartXmlHttpRequest.readyState !== 4) { \n\t\t\t\tupdateCartXmlHttpRequest.abort();\n\t\t\t}\n\t\t}\n\t}\n\tupdateCartXmlHttpRequestBuffer = [];\n\tupdateCartBuffer = [];\n\n\tgetCartHtml(triggerElementName, options, isCartPage);\n\tif (!isCartPage) {\n\t\tgetOrderSummaryCalloutHtml(triggerElementName, options, isCartPage);\n\t}\n}\n\nfunction getCartHtml(triggerElementName, options, isCartPage) {\n    var $form = $('#checkout-form');\n    updateCartBuffer['Cart'] = null;\n\n\tupdateCartXmlHttpRequestBuffer['getCartHtml'] = $.ajax({\n\t\turl: Urls.onePageSubmit,\n\t\ttype: \"POST\",\n\t\tdata: triggerElementName + '=' + triggerElementName + '&selectedPaymentMethod=' + $('input[name*=\"_selectedPaymentMethodID\"]').val() + '&format=ajax',\n\t\tsuccess : function (data) {\n\t\t\tupdateCartBuffer['Cart'] = data;\n\t\t\tgetCartData(triggerElementName, options, isCartPage);\n\t\t\tupdateCartRender(triggerElementName, options, isCartPage);\n\t\t}\n\t});\n}\n\nfunction getOrderSummaryCalloutHtml(triggerElementName, options, isCartPage) {\n    updateCartBuffer['OrderSummaryCallout'] = null;\n\n\tupdateCartXmlHttpRequestBuffer['getOrderSummaryCalloutHtml'] = $.ajax({\n\t\turl: Urls.getOrderSummaryCalloutContentSlot,\n\t\tdataType: 'html',\n\t\tsuccess: function (data) {\n\t\t\tupdateCartBuffer['OrderSummaryCallout'] = data;\n\t\t\tupdateCartRender(triggerElementName, options, isCartPage);\n\t\t}\n\t});\n}\n\nfunction getCartData(triggerElementName, options, isCartPage) {\n\tupdateCartBuffer['CartData'] = null;\n\n\tupdateCartXmlHttpRequestBuffer['getCartData'] = $.ajax({\n\t    url : Urls.getCartData,\n\t\ttype : \"POST\",\n\t\tdata: {\n\t\t\tisCart: isCartPage\n\t\t},\n\t    success : function (data) {\n\t    \t$('[has-local-delivery-shipment]').attr('has-local-delivery-shipment', data.HasLocalDeliveryShipment || false);\n\t    \t$('[has-physical-shipment]').attr('has-physical-shipment', data.HasPhysicalShipment || false);\n\t\t\t$('[has-warehouse-shipment]').attr('has-warehouse-shipment', data.HasWarehouseShipment || false);\n\t\t\t$('[has-warehouse-shipment]').attr('has-shipping-methods', data.ShippingMethods ? data.ShippingMethods.join(' ') : false);\n\t    \t$('[has-gift-cards]').attr('has-gift-cards', data.HasGiftCards || false);\n\t    \t$('[has-gift-cards-only]').attr('has-gift-cards-only', data.HasGiftCardsOnly || false);\n\t\t\t$('[has-store-pickup-shipment]').attr('has-store-pickup-shipment', (data.Bopis && data.Bopis.HasStorePickupShipment) || false);\n\t\t\t$('[has-store-pickup-shipment-only]').attr('has-store-pickup-shipment-only', (data.Bopis && data.Bopis.HasStorePickupShipmentOnly) || false);\n\t    \t$(document).trigger('CartData.Update', data);\n\n\t    \tupdateCartBuffer['CartData'] = data;\n\t    \tif (data.Bopis) {\n\t    \t\tupdateCartBuffer['Bopis'] = data.Bopis;\n\t    \t}\n\t    \t\n\t    \tif (!data.IsGlobaleValidOrInactive) {\n\t    \t\t$('.section-checkout').addClass('global-e-validation-error');\n\t    \t\t$('.section-checkout').find('.cart-errors').addClass('active');\n\t    \t} else {\n\t    \t\t$('.section-checkout').removeClass('global-e-validation-error');\n\t    \t\t$('.section-checkout').find('.cart-errors').removeClass('active');\n\t    \t}\n\n\t    \tif (data.ShippingRestrictions && data.ShippingRestrictions.Status == 'shippingRestrictionsError') {\n\t\t\t\tif (isCartPage) {\n\t\t\t\t\t$('.opclogin-buttons').addClass('hide');\n\t\t\t\t} else {\n\t\t\t\t\t$('.payment-methods-section').hide();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (isCartPage) {\n\t\t\t\t\t$('.opclogin-buttons').removeClass('hide');\n\t\t\t\t\t$('.guest-checkout .error-form').remove();\n\t\t\t\t} else {\n\t\t\t\t\t$('.payment-methods-section').show();\n\t\t\t\t}\n\t\t\t}\n\t    \t\n\t    \thandleOrderTotal(triggerElementName, options, isCartPage);\n\t    }\n\t});\n}\n\nfunction handleOrderTotal(triggerElementName, options, isCartPage) {\n\tupdateCartBuffer['PaymentInstrumentHtml'] = null;\n\tvar removeAction = '<a class=\"remove\">Remove</a>';\n\t\n\tif (updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length > 0) {\n\t\tupdateCartBuffer['PaymentInstrumentHtml'] = '';\n\t\n\t\tfor (var paymentInstrumentKey in updateCartBuffer['CartData'].OrderTotal.paymentInstruments) {\n\t\t\tvar paymentInstrument = updateCartBuffer['CartData'].OrderTotal.paymentInstruments[paymentInstrumentKey];\n\t\t\tvar paymentInstrumentUUIDAttribute = 'uuid=\"' + paymentInstrument.UUID + '\"';\n\t\t\t\n\t\t\tswitch (paymentInstrument.paymentMethod.Id) {\n\t\t\t\tcase PaymentMethodConstants.RewardsCredit:\n\t\t    \t\tupdateCartBuffer['PaymentInstrumentHtml'] += '<div ' + paymentInstrumentUUIDAttribute + ' payment-method=\"' + paymentInstrument.paymentMethod.Id + '\" allow-remove=\"' + paymentInstrument.allowRemove + '\">' +\n\t\t    \t\t\t'<span class=\"label\"><span class=\"name\">B Rewarded</span>&nbsp;<span class=\"number\">Reward</span></span>' +\n\t\t    \t\t\t'<span class=\"value\">' + paymentInstrument.amountDisplay + '</span>' +\n\t\t    \t\t'</div>';\n\t\t    \tbreak;\n\t\t\t\n\t\t\t\tdefault:\n\t\t    \t\tupdateCartBuffer['PaymentInstrumentHtml'] += '<div ' + paymentInstrumentUUIDAttribute + ' payment-method=\"' + paymentInstrument.paymentMethod.Id + '\" allow-remove=\"' + paymentInstrument.allowRemove + '\">' +\n\t\t    \t\t\t'<span class=\"label\"><span class=\"name\">' + paymentInstrument.paymentMethod.Name + '</span>&nbsp;<span class=\"number\">' + paymentInstrument.numberLastFour + '</span>' + removeAction + '</span>' +\n\t\t    \t\t\t'<span class=\"value\">' + paymentInstrument.amountDisplay + '</span>' +\n\t\t    \t\t'</div>';\n\t\t    \tbreak;\n\t\t    }\n\t\t}\n\t} else {\n\t\t$(document).trigger('GiftCard.Clear');\n\t\t$(document).trigger('RewardsCredit.Clear');\n\t}\n\t\n\tif (updateCartBuffer['CartData'].OrderTotal.balance < updateCartBuffer['CartData'].OrderTotal.total) {\n\t\tupdateCartBuffer['BalanceDueHtml'] = '<span class=\"label\">Balance Due</span>' +\n\t\t\t'<span class=\"value\">' + updateCartBuffer['CartData'].OrderTotal.balanceDisplay + '</span>';\n\t}\n\t\n\tupdateCartRender(triggerElementName, options, isCartPage);\n}\n\nfunction updateCartRender(triggerElementName, options, isCartPage) {\n\tif (updateCartBuffer['Cart'] && (isCartPage || (updateCartBuffer['OrderSummaryCallout'] && updateCartBuffer['CartData']))) {\n\t\tvar $basketContainerHtml = $(updateCartBuffer['Cart']);\n\t\n\t\tif (updateCartBuffer['CartData'] && updateCartBuffer['CartData'].OrderTotal) {\n\t\t\t$basketContainerHtml.find('.order-total-price .value').html(updateCartBuffer['CartData'].OrderTotal.totalDisplay);\n\t    \t$('.payment-section .order-total-price .value').html(updateCartBuffer['CartData'].OrderTotal.totalDisplay);\n\t\t\n\t\t\tif (updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length > 0) {\n\t\t\t\t$basketContainerHtml.find('.order-totals-table').attr('payments-applied', updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length);\n\t    \t\t$('.payment-section').attr('payments-applied', updateCartBuffer['CartData'].OrderTotal.paymentInstruments.length);\n\t    \t} else {\n\t    \t\t$basketContainerHtml.find('.order-totals-table').removeAttr('payments-applied');\n\t    \t\t$('.payment-section').removeAttr('payments-applied');\n\t    \t}\n\t\t\n\t\t\t$basketContainerHtml.find('.order-totals-table').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t\t\t$('#wrapper').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t    \t$('.payment-section').attr('balance-due', updateCartBuffer['CartData'].OrderTotal.balance);\n\t\t\n\t\t\tif (updateCartBuffer['CartData'].OrderTotal.balance > 0) {\n\t\t\t\t$('.payment-method-options').show();\n\t\t\t\t$('.payment-section-footer[data-method=\"PayPal\"] button').hide();\n\t\t\t} else {\n\t\t\t\t$('.payment-method-options').hide();\n\t\t\t\t$('.payment-section-footer[data-method=\"PayPal\"] button').show();\n\t\t\t}\n\t\t\n\t    \tif (updateCartBuffer['BalanceDueHtml']) {\t\n\t    \t\t$basketContainerHtml.find('.order-balance-due').html(updateCartBuffer['BalanceDueHtml']);\n\t    \t\t$('.payment-section .order-balance-due').html(updateCartBuffer['BalanceDueHtml']);    \t\t\n\t    \t} else {\n\t    \t\t$('.payment-section .order-balance-due').html('');\n\t    \t}\n\t    \t\n\t    \tif (updateCartBuffer['PaymentInstrumentHtml']) {\n\t    \t\t$basketContainerHtml.find('.order-total-payments').html(updateCartBuffer['PaymentInstrumentHtml']);\n\t    \t\t$('.payment-section .order-total-payments').html(updateCartBuffer['PaymentInstrumentHtml']);\n\t    \t} else {\n\t    \t\t$('.payment-section .order-total-payments').html('');\n\t    \t}\n\t\t}\n\n\t\t$('.accordion.coupon .cart-coupon-code').html($basketContainerHtml.find('.cart-coupon-code').first().html());\n\t\t$('.basket-container').html($basketContainerHtml);\n\t\t\n\t\tif (updateCartBuffer['CartData']) {\n\t\t\tvar orderTotalForAffirm = updateCartBuffer['CartData'].OrderTotal.balance;\n\t\t\tif (!orderTotalForAffirm && updateCartBuffer['CartData'].OrderTotal.adjustedMerchandizeTotalPrice) {\n\t\t\t\torderTotalForAffirm = updateCartBuffer['CartData'].OrderTotal.adjustedMerchandizeTotalPrice;\n\t\t\t}\n\t\t\t\n\t\t\tif ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui && orderTotalForAffirm >= updateCartBuffer['CartData'].AffirmMinimumOrderTotal) {\n\t\t\t\t$('.affirm-product-modal').attr('data-amount', orderTotalForAffirm * 100);\n\t\t\t\taffirm.ui.refresh();\n\t\t\t} else {\n\t\t\t\t$('.affirm-product-modal').attr('data-amount', 5000);\n\t\t\t}\n\t\t}\n\n\t\tif ($('.basket-container').find('.product-availability-list .not-available').length > 0) {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').attr('disabled', 'disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t\t$('#submitOPCPayment').after('<div id=\"errorBoxOPC\" class=\"p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>' + Resources.Validation.Messages.Products.Availability + ':</b> ' + Resources.Validation.Messages.Products.AvailabilityExceeded + '</div>');\n\t\t} else if (updateCartBuffer['Bopis'] && updateCartBuffer['Bopis'].NumberOfBopisStoresInCart > updateCartBuffer['Bopis'].MaximumNumberOfBopisStoresInCart) {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').attr('disabled', 'disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t\t$('#submitOPCPayment').after('<div id=\"errorBoxOPC\" class=\"p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>' + Resources.Validation.Messages.General.CartLimit + ':</b> ' + Resources.Validation.Messages.Bopis.MaximumStoresExceeded + '</div>');\n\t\t} else {\n\t\t\t$('#submitOPCPayment, #submitOPCPaymentPrivateLabel').removeAttr('disabled');\n\t\t\t$('#errorBoxOPC').remove();\n\t\t}\n\t\t\n\t\tif (updateCartBuffer['OrderSummaryCallout']) {\t\n\t\t\t$('.callout-ordersummary').html(updateCartBuffer['OrderSummaryCallout']);\n\t\t}\n\n\t    if ($('.banner-cart-holder .btn-minicart').length > 0) {\n\t\t\t$.ajax({url : Urls.cartMiniCart, data : {desktop: '1'}, dataType: 'html', success : function(data) {\n\t            $('.banner-cart-holder').html(data);\n\t        }});\n\t\t\t\n\t    \t$.ajax({url : Urls.cartMiniCart, dataType: 'html', success : function(data) {\n\t    \t\tvar parentMiniCart = $(\".top-banner-inner-links #mini-cart\");\n\t    \t\t\n\t    \t\tif (parentMiniCart.length > 0) {\n\t    \t\t\tparentMiniCart.html(data);\n\t    \t\t}\n\t        }});\n\t\t}\n\t    \n        $.ajax({url: Urls.cartItemQuantity, data: {desktop: '1'}, dataType: 'html', success: function (data) {\n        \t$('.confirmation-message .item-count').html(data);\n\t        \n\t        var quantity = parseInt($('.confirmation-message .item-count').find('span').text(), 10);\n\t        if (!quantity) {\n\t            $('.checkout-buttons.mobile-only').hide();\t            \n\t\t\t}\n\t\t}});\n\t\t\n\t    \n\t    if (triggerElementName.indexOf('deleteProduct') > -1) {\n\t    \t$(document).trigger('refresh-required');\n\t    }\n\n\t\tif (!options || !options.EventTriggers || options.EventTriggers['update-summary']) {\n\t\t\t$(document).trigger('update-summary');\n\t\t}\n\t\t\n\t\tif (!options || !options.EventTriggers || options.EventTriggers['update-shipping']) {\n\t\t\t$(document).trigger('update-shipping');\n\t\t}\n\t    \n\t    $('[minimum-cart-total], [maximum-cart-total]').each(function(index, element) {\n\t    \tvar $this = $(this);\n\t    \tvar paymentMethodCartTotalMinimum = parseFloat($this.attr('minimum-cart-total'));\n\t    \tvar paymentMethodCartTotalMaximum = parseFloat($this.attr('maximum-cart-total'));\n\t    \n\t    \tvar isCartTotalMinimumValid = false;\n\t    \tif (isNaN(paymentMethodCartTotalMinimum) || updateCartBuffer['CartData'].OrderTotal.balance >= paymentMethodCartTotalMinimum) {\n\t    \t\tisCartTotalMinimumValid = true;\n\t    \t}\n\t    \t\n\t    \tvar isCartTotalMaximumValid = false;\n\t    \tif (isNaN(paymentMethodCartTotalMaximum) || updateCartBuffer['CartData'].OrderTotal.balance <= paymentMethodCartTotalMaximum) {\n\t    \t\tisCartTotalMaximumValid = true;\n\t    \t}\n\t    \t\n\t    \tif (isCartTotalMinimumValid && isCartTotalMaximumValid) {\n\t    \t\t$this.closest('.payment-method-option').attr('valid-for-balance-due', 'true');\n\t    \t} else {\n\t    \t\t$this.closest('.payment-method-option').attr('valid-for-balance-due', 'false');\n\t    \t}\n\t    });\n\t\t\n\t    if (updateCartBuffer['CartData'] && !updateCartBuffer['CartData'].HasPhysicalShipment && $('.single.shipping-address-type-selector input:checked').val() != SiteConstants.AddressTypes.Customer) {\n\t    \t$('.single.shipping-address-type-selector input[value=\"' + SiteConstants.AddressTypes.Customer + '\"]').click();\n\t    }\n\t\t\n\t\ttooltip.init({\n\t\t\titems: '.shipping-method-tooltip',\n\t\t\ttooltipClass: 'shipping-method-tooltip'\n\t\t}, $('[shipping-method]'));\n\n\t\ttooltip.init({\n\t\t\titems: '.tooltip'\n\t\t});\n\n\t\ttriggerSrFocus();\n\t\t$(document).trigger('QuantityStepper.TargetFocus');\n\t    $(document).trigger('Cart.UpdateSuccess');\n\t}\n}\n\nfunction triggerSrFocus() {\n\t$('[role=\"alert\"]').last().focus();\n}\n\nfunction submitPayment(data) {\n\t$submitPayment.loading({\n\t\tIsImageShown: false,\n\t\tLabel: Resources.Loading.Checkout.PlacingOrder\n\t});\n\t$submitPayment.attr('disabled', true);\n\t$('#errorBoxOPC').remove();\n\n\t$checkoutForm.validate().form();\t\n\t$checkoutForm.validate().settings.ignore = [];\n\t\n\tif ($checkoutForm.valid()) {\n\t\tsetOPCPaymentData($checkoutForm, $submitPayment.attr('name')).then(function(response) {\n\t\t\tvar data;\n\t\t\ttry {\n\t\t\t\tdata = JSON.parse(response);\n\t\t\t} catch (e) {\n\t\t\t\tdata = response;\n\t\t\t}\n\n\t\t\tif (data.hasOwnProperty('status') && data.status === 'success') {\n\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'affirmRedirect') {\n\t\t\t\tvar _affirm_config = {\n\t\t\t\t\tpublic_api_key: data.affirm.PublicApiKey,\n\t\t\t\t\tscript: data.affirm.Script\n\t\t\t\t};\n\t\t\t\t(function(l,g,m,e,a,f,b){var d,c=l[m]||{},h=document.createElement(f),n=document.getElementsByTagName(f)[0],k=function(a,b,c){return function(){a[b]._.push([c,arguments])}};c[e]=k(c,e,\"set\");d=c[e];c[a]={};c[a]._=[];d._=[];c[a][b]=k(c,a,b);a=0;for(b=\"set add save post open empty reset on off trigger ready setProduct\".split(\" \");a<b.length;a++)d[b[a]]=k(c,e,b[a]);a=0;for(b=[\"get\",\"token\",\"url\",\"items\"];a<b.length;a++)d[b[a]]=function(){};h.async=!0;h.src=g[f];n.parentNode.insertBefore(h,n);delete g[f];d(g);l[m]=c})(window,_affirm_config,\"affirm\",\"checkout\",\"ui\",\"script\",\"ready\");\n\t\t\t\t\n\t\t\t\taffirm.checkout(JSON.parse(data.affirm.AffirmCheckout));\n\t\t\t\taffirm.checkout.post();\n\t\t\t\taffirm.ui.ready(\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\taffirm.ui.error.on(\"close\", function(){\n\t\t\t\t\t\t\t// window.location.replace(data.affirm.RedirectUrl);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'shippingRestrictionsError'){\n\t\t\t\tvar popup = require('../popup');\n\t\t\t\tvar payload = JSON.parse(data.payload);\n\n\t\t\t\tvar list = $.map(payload.list, function (el) {\n\t\t\t\t\treturn '<li>' + el.name + ':<br>' + el.message + '</li>';\n\t\t\t\t}).join('');\n\t\t\t\t\n\t\t\t\tpopup.init({\n\t\t\t\t\ttitle: payload.title,\n\t\t\t\t\tcontent: payload.message + '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>',\n\t\t\t\t}).showPopup();\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'ValidationError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Validation Error:</b> ' + message + '</div>');\n\t\t\t} else {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Payment Declined:</b> ' + message + '</div>');\n\t\t\t}\n\t\t\t\n\t\t\t$submitPayment.loading('destroy');\n\t\t\t$submitPayment.attr('disabled', false);\n\t\t}).catch(function(response) {\n\t\t\tif (response.status == 302 && response.responseText) {\n\t\t\t\tlocation.href = response.responseText;\n\t\t\t}\n\t\t});\n\t} else {\n\t\t$submitPayment.loading('destroy');\n\t\t$submitPayment.attr('disabled', false);\n\t}\n}\n\nvar setOPCPaymentData = function ($form, name) {\n\tvar payload = $form.serialize() + '&' + name + '=' + name;\n\tvar $checkoutVariables = $('.button-and-terms input[type=\"hidden\"]');\n\t$checkoutVariables.each(function() {\n\t\tvar $this = $(this);\n\t\tpayload += '&' + $this.attr('name') + '=' + $this.val();\n\t});\n\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.setOpcAddress),\n        data: payload\n    }));\n};\n\nfunction searchRewards() {\n\tif (dataBuffer['RewardsAccountSearchRequest'] && dataBuffer['RewardsAccountSearchRequest'].readyState !== 4) {\n\t\tdataBuffer['RewardsAccountSearchRequest'].abort();\n\t\tdataBuffer['RewardsAccountSearchRequest'] = null;\n\t}\n\t$rewardsApplied.html('');\n\n\tvar payload = {\n\t\tEmailAddress: $rewardsForm.find('#dwfrm_billing_rewards_rewardsEmail').val(),\n\t\tPhoneNumber: $rewardsForm.find('.field.phonenumber').val(),\n\t\tZipCode: $rewardsForm.find('.field.zipcode').val(),\n\t}\n\n\tif ($rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val()) {\n\t\tpayload.RewardsNumber = $rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val();\n\t}\n\n\t$('.btn.search-echo').loading({\n\t\tIsLabelShown: false,\n\t\tBackgroundColor: 'transparent'\n\t});\n\n\tdataBuffer['RewardsAccountSearchRequest'] = $.ajax({\n\t\ttype: 'POST',\n\t\turl: Urls.searchForRewards,\n\t\tcontentType: 'application/json',\n\t\tdataType: 'json',\n\t\tdata: JSON.stringify(payload),\n\t\tsuccess: function(data) {\n\t\t\trenderRewardsData(data);\n\t\t},\n\t\tcomplete: function(xhr) {\n\t\t\tif ($('.btn.search-echo').attr('loading')) {\n\t\t\t\t$('.btn.search-echo').loading('destroy');\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction renderRewardsData(data) {\n\tif (data.Match && data.Rewards) {\n\t\tif (data.Rewards.rewardsNumber) {\n\t\t\t$rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val(data.Rewards.rewardsNumber);\n\t\t} else {\n\t\t\t$rewardsForm.find('#dwfrm_billing_rewards_rewardsNumber').val('');\n\t\t}\n\t\tif (data.Rewards.email) {\n\t\t\t$rewardsForm.find('#dwfrm_billing_rewards_rewardsEmail').val(data.Rewards.email);\n\t\t} else {\n\t\t\t$rewardsForm.find('#dwfrm_billing_rewards_rewardsEmail').val('');\n\t\t}\n\t\tif (data.Rewards.phone) {\n\t\t\t$rewardsForm.find('.field.phonenumber').val(data.Rewards.phone);\n\t\t} else {\n\t\t\t$rewardsForm.find('.field.phonenumber').val('');\n\t\t}\n\t\tif (data.Rewards.zipValue) {\n\t\t\t$rewardsForm.find('.field.zipcode').val(data.Rewards.zipValue);\n\t\t} else {\n\t\t\t$rewardsForm.find('.field.zipcode').val('');\n\t\t}\n\n\t\tif (data.Match.RewardsEmail) {\n\t\t\t$rewardsForm.find('.rewards-email-container').attr('match', 'true');\n\t\t} else {\n\t\t\t$rewardsForm.find('.rewards-email-container').attr('match', 'false');\n\t\t}\n\t\tif (data.Match.RewardsPhone) {\n\t\t\t$rewardsForm.find('.input-container.phone').attr('match', 'true');\n\t\t} else {\n\t\t\t$rewardsForm.find('.input-container.phone').attr('match', 'false');\n\t\t}\n\t\tif (data.Match.RewardsZip) {\n\t\t\t$rewardsForm.find('.input-container.zip').attr('match', 'true');\n\t\t} else {\n\t\t\t$rewardsForm.find('.input-container.zip').attr('match', 'false');\n\t\t}\n\t\t\n\t\tvar rewardsRowTemplate = _.template($('#template-rewards-credit-row-echo').html(), TemplateConstants.Lodash.Settings);\n\t\tvar status = '';\n\t\tvar message = '';\n\t\tif (parseFloat(data.Rewards.creditAmount) <= 0) {\n\t\t\tstatus = 'message';\n\t\t\tmessage = 'no rewards available';\n\t\t} else if ($rewardsForm.closest('[is-applied]').attr('is-applied') == 'true') {\n\t\t\tstatus = 'applied';\n\t\t} else {\n\t\t\tstatus = 'pending';\n\t\t}\n\n\t\tvar additionalData = '<table class=\"rewards-information\">' +\n\t\t\t\t\t\t\t\t'<tr><td>Address</td><td>' + data.Rewards.address + '</td></tr>' +\n\t\t\t\t\t\t\t\t'<tr><td>City</td><td>' + data.Rewards.city + '</td></tr>' +\n\t\t\t\t\t\t\t\t'<tr><td>State</td><td>' + data.Rewards.state + '</td></tr>' +\n\t\t\t\t\t\t\t\t'<tr><td>Zip</td><td>' + data.Rewards.zipValue + '</td></tr>' +\n\t\t\t\t\t\t\t\t'<tr><td>Country</td><td>' + data.Rewards.country + '</td></tr>' +\n\t\t\t\t\t\t\t\t'<tr><td>Phone</td><td>' + data.Rewards.phone + '</td></tr>' +\n\t\t\t\t\t\t\t'</table><table class=\"rewards-points\">' +\n\t\t\t\t\t\t\t\t'<tr><td>Points</td><td>' + data.Rewards.pointBalance + '</td></tr>' +\n\t\t\t\t\t\t\t'</table>';\n\n\t\t$rewardsApplied.html(rewardsRowTemplate({\n\t\t\tStatus: status,\n\t\t\tRewardsNumber: data.Rewards.rewardsNumber,\n\t\t\tName: data.Rewards.fullName,\n\t\t\tEmail: data.Rewards.email,\n\t\t\tRewardsAvailable: data.Rewards.creditAmountFormatted.replace('.00', ''),\n\t\t\tRewardsExpirationDate: data.Rewards.creditExpirationDate || 'n/a',\n\t\t\tMessage: message,\n\t\t\tAdditionalData: additionalData\n\t\t}));\n\t\tif ($rewardsAccordion.find('header .rewards-points').length) {\n\t\t\t$rewardsAccordion.find('header .rewards-points').text(data.Rewards.pointBalance);\n\t\t}\n\n\t\t$rewardsAccordion.attr('rewards-found', 'true');\n\t\t$rewardsForm.find('.btn.reset-echo').removeAttr('disabled');\n\t\tif (!$('.accordion.rewards .accordion-head').hasClass('active')) {\n\t\t\t$('.accordion.rewards .accordion-head').addClass('active');\n\t\t}\n\t} else {\n\t\t$rewardsAccordion.removeAttr('rewards-found');\n\t\t$rewardsApplied.html('<p class=\"no-results\">no rewards found</p>');\n\t}\n}\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\n\tif (options && options.Lob && options.Lob.AddressVerification.Enabled) {\n\t\tAddressVerificationDialog = require('../../../../app_storefront_core/cartridge/js/Lob/AddressVerification/AddressVerificationDialog');\n\t}\n\n\tif (options && options.Lob && options.Lob.AddressAutocomplete.Enabled) {\n\t\tAddressAutocompleteDialog = require('../../../../app_storefront_core/cartridge/js/Lob/AddressAutocomplete/AddressAutocompleteDialog');\n\t}\n\n\tGiftCard.initialize($.extend({ LoadingIndicator: {\n\t\tIsLabelShown: false,\n\t\tBackgroundColor: 'transparent'\n\t}}, options));\n\n\tRewardsCredit.initialize($.extend({ LoadingIndicator: {\n\t\tIsLabelShown: false,\n\t\tBackgroundColor: 'transparent'\n\t}}, options));\n\n\tApplePay.initialize(options);\n\n    initialize(options);\n};","'use strict';\n\nvar addProductToCart = require('./product/addToCart'),\n    ajax = require('../ajax'),\n    page = require('../page'),\n    productTile = require('../product-tile'),\n    quickview = require('../quickview');\n\n/**\n * @private\n * @function\n * @description Binds the click events to the remove-link and quick-view button\n */\nfunction initializeEvents() {\n    $('#compare-table').on('click', '.remove-link', function (e) {\n        e.preventDefault();\n        ajax.getJson({\n            url: this.href,\n            callback: function () {\n                page.refresh();\n            }\n        });\n    })\n    .on('click', '.open-quick-view', function (e) {\n        e.preventDefault();\n        var url = $(this).closest('.product').find('.thumb-link').attr('href');\n        quickview.show({\n            url: url,\n            source: 'quickview'\n        });\n    });\n\n    $('#compare-category-list').on('change', function () {\n        $(this).closest('form').submit();\n    });\n}\n\nexports.init = function () {\n    productTile.init();\n    initializeEvents();\n    addProductToCart();\n};\n","'use strict';\n\nvar\tutil = require('../util');\nvar page = require('../page');\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nfunction initializeEvents(){\n\t\n\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS && 'pagePath' in pageContext && (pageContext.pagePath == 'BRewardedBalanceCheck' || pageContext.pagePath == 'AccountView' || pageContext.pagePath == 'RewardsProgram')) {\n    \tpassBreadSetup();\n    }\n};\n\nfunction passBreadSetup() {\n\tvar rewardsNumber = $('.customer-rewards-number').text();\n\n\tBreadPayments.setup({\n\t\tloyaltyID: rewardsNumber,\n\t\tstoreNumber: util.isMobile() ? SitePreferences.PLCC_STORE_NUMBER_MOBILE : SitePreferences.PLCC_STORE_NUMBER_WEB,\n\t\texistingCardHolder: false,\n\t\tenv: SitePreferences.PLCC_ENVIRONMENT,\n\t});\n\n\tBreadPayments.registerPlacements([landingPlacement]);\n}\n\nexports.init = function () {\n    initializeEvents();    \n};\n","'use strict';\n\nvar quickview = require('../quickview');\nvar bonusProductsView = require('../bonus-products-view');\nvar TPromise = require('promise');\nvar util = require('../util');\nvar addresses = SitePreferences.ENABLE_ENHANCED_CHECKOUT ? require('./checkout/opcaddress_enhanced') : require('./checkout/opcaddress');\nvar formPrepare = require('./checkout/formPrepare');\nvar cart = require('./cart');\nvar opcpayment = require('./checkout/opcpayment');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar GiftCard = require('./checkout/GiftCardPaymentPanel');\nvar GoogleTagManagerClient = require('../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar recaptcha = require('../components/Recaptcha');\nvar RewardsCredit = require('./checkout/RewardsCredit');\nvar LoyaltyCredit = require('./checkout/LoyaltyCredit');\nvar CheckoutConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants');\nvar PaymentMethodConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar cartItemsFormSelector = 'form#cart-items-form';\nvar billingAddressFormSelector = '#billingAddressForm';\nvar $billingAddressForm = $(billingAddressFormSelector);\nvar shippingAddressFormSelector = '#shippingAddressForm';\nvar $shippingAddressForm = $(shippingAddressFormSelector);\nvar paymentSectionSelector = '.form-checkout.payment-section';\nvar $paymentSection = $(paymentSectionSelector);\nvar paymentFormSelector = '#paymentSection';\nvar $paymentForm = $(paymentFormSelector);\nvar creditCardListSelector = '#creditCardList';\nvar $creditCardList = $(creditCardListSelector);\nvar submitPaymentSelector = '.payment-section-footer button[name*=\"_submitPayment\"]:not(#submitOPCPaymentPrivateLabel)';\nvar $submitPayment = $(submitPaymentSelector);\nvar submitPrivateLabelPaymentSelector = '#submitOPCPaymentPrivateLabel';\nvar $submitPrivateLabelPayment = $(submitPrivateLabelPaymentSelector);\nvar basketContainerSelector = '.basket-container';\nvar $basketContainer = $(basketContainerSelector);\n\nvar placeOrderRecaptcha;\nvar placeOrderRecaptchaPaypal;\nvar placeOrderRecaptchaAffirm;\nvar placeOrderRecaptchaPrivateLabel;\nvar options = {};\nvar loaded = {};\n\n/**\n * @description Events should be divided to modules. This allows reinitialize events by sections after partial reload\n * @private\n * @function\n * @description Initializes events for the gift registration\n */\nfunction initializeEvents(options) {\n\tinitializeCartEvents(options);\n\tinitializePaymentMethodsEvents();\n\t\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n}\n\nfunction initializeCartEvents(options) {\n    $(document).on('click', 'a.add-to-wishlist', function (e) {\n    \t/*remove next line to use default dw wishlist functionality*/\n    \treturn false;\n    \te.preventDefault();\n\n    \tif(Customer.authenticated == true){\n    \t\t//post form here\n    \t} else {\n    \t\t$('html, body').animate({ scrollTop: $('.login-form').eq(0).offset().top}, 1000);\n    \t}\n    });\n    \n    if (SitePreferences.ALTERNATE_PICKUP_ENABLED) {\n\t\trenderAlternatePickup();\n\t}\n\n\t$paymentForm.on('change', '[name$=\"_creditCard_type\"]', function() {\n\t\tsetPlaceOrderButtonsDisabled(false);\n\t\t$(this).closest('div.form-row').find('div.field-wrapper.error').remove();\n\t});\n\n\t$submitPayment.on('click', function(e) {\n\t\te.preventDefault();\n\t\t\n\t\tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForPlaceOrder) {\n\t\t\tsubmitPayment();\n\t\t}\n    });\n\n\t$(document).on('Checkout.SubmitPayment', function () {\n\t\tif (options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder) {\n\t\t\tsubmitPayment();\n\t\t}\n\t});\n\t\n    $submitPrivateLabelPayment.on('click', function(e){\n    \te.preventDefault();\n    \t\n    \tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForPlaceOrder) {\n\t\t\tsubmitPaymentPrivateLabel();\t\n\t\t}\n    });\n    \n    $(document).on('Checkout.SubmitPaymentPrivateLabel', function () {\n    \tif (options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder) {\n\t\t\tsubmitPaymentPrivateLabel();\n\t\t}\n\t});\n    \n    var getCreditCardInfo = function (id) {\n        return TPromise.resolve($.ajax({\n            type: 'GET',\n            url: util.ajaxUrl(Urls.billingSelectCC),\n            data: {ccID: id}\n        }));\n    };\n\n    $creditCardList.on('change', function() {\n    \tvar ccID = $(this).val();\n    \tif (ccID.length <= 0) {\n    \t\treturn;\n    \t}\n    \tgetCreditCardInfo(ccID).then(function (response) {\n\t\t\tvar data = response;\n\t\t\tif (data.hasOwnProperty('maskedNumber')) {\n\t\t\t\t$('#dwfrm_billing_paymentMethods_creditCard_owner').val(data.holder).valid();\n\t\t\t\t$('#dwfrm_billing_paymentMethods_creditCard_type[value=\"'+data.type+'\"]')\n\t\t\t\t\t.first()\n\t\t\t\t\t.prop('checked', true)\n\t\t\t\t\t.trigger('change');\n\t\t\t\t$(\"[id^='dwfrm_billing_paymentMethods_creditCard_number']\").first().val(data.maskedNumber).valid();\n\t\t\t\t$('#dwfrm_billing_paymentMethods_creditCard_expiration_month').val(data.expirationMonth).trigger('change');\n\t\t\t\t$('#dwfrm_billing_paymentMethods_creditCard_expiration_year').val(data.expirationYear).trigger('change');\n\t\t\t\t$('input[name^=dwfrm_billing_paymentMethods_creditCard_cvn]').val('');\n\t\t\t}\n\t\t}.bind(this));\n\n    });\n\n    //preselect default credit card\n\tif($creditCardList.length > 0 && $('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val() == PaymentMethodConstants.CreditCard) {\n\t\t$creditCardList.find('option').eq(1).prop('selected', true);\n\t\t$creditCardList.trigger('change');\n\t}\n\n    var getPrivateLabelCardInfo = function (id) {\n        return TPromise.resolve($.ajax({\n            type: 'GET',\n            url: util.ajaxUrl(Urls.billingSelectPrivateLabel),\n            data: {cardId: id}\n        }));\n    };\n\n    var $privateLabelCardList = $('#privateLabelCardList');\n    $privateLabelCardList.on('change', function() {\n    \tvar cardId = $('#privateLabelCardList').val();\n    \tif (cardId.length <= 0) {\n    \t\treturn;\n    \t}\n    \tgetPrivateLabelCardInfo(cardId).then(function (response) {\n\t\t\tvar data = response;\n\t\t\tif (data.hasOwnProperty('maskedNumber')) {\n\t\t\t\t$(\"[id^='dwfrm_billing_paymentMethods_privateLabelCard_number']\").first().val(data.maskedNumber).valid();\n\t\t\t}\n\t\t}.bind(this));\n\n    });\n\n\t// preselect default private label card\n\tif ($privateLabelCardList.length > 0) {\n\t\t$privateLabelCardList.find('option').eq(1).prop('selected', true);\n\t\t$privateLabelCardList.trigger('change');\n\t}\n\n    addresses.init(options);\n    cart.init(options);\n}\n\nfunction renderAlternatePickup() {\n\t$(document).off('click', 'button.alt-pickup-button').on('click', 'button.alt-pickup-button', function (e) {\n    \te.preventDefault();\n\t\t$('#alt-pickup-modal').addClass('active-modal').show();\n\t\t$('fieldset span').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).off('click', '#alt-pickup-modal .close-modal').on('click', '#alt-pickup-modal .close-modal', function (e) {\n    \te.preventDefault();\n\t\t$('#alt-pickup-modal').removeClass('active-modal').hide();\n    });\n    \n    $(document).on('focus', 'input[name=\"firstName\"]', function () {\n\t\t$('.firstname-error').removeClass('error-msg');\n    });\n    \n    $(document).on('focus', 'input[name=\"lastName\"]', function () {\n\t\t$('.lastname-error').removeClass('error-msg');\n    });\n    \n    $(document).on('focus', 'input[name=\"email\"]', function () {\n\t\t$('.email-error').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).on('focus', 'input[name=\"phone\"]', function () {\n\t\t$('.phone-error').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).off('click', 'button#altPickupSubmit').on('click', 'button#altPickupSubmit', function (e) {\n    \te.preventDefault();\n\t\t\n    \tvar isFirstNameValid = true;\n\t\tvar firstName = $('input[name=\"firstName\"]').val();\n\t\tvar regexName = /^[a-z ,.'-]+$/i;\n\t\tif (firstName.length == 0 || firstName.match(regexName) == null) {\n\t\t\tisFirstNameValid = false;\n\t\t\t$('.firstname-error').addClass('error-msg');\n\t\t}\n\t\t\n\t\tvar isLastNameValid = true;\t\t\n\t\tvar lastName =$('input[name=\"lastName\"]').val();\n\t\tif (lastName.length == 0 || lastName.match(regexName) == null) {\n\t\t\tisLastNameValid = false;\n\t\t\t$('.lastname-error').addClass('error-msg');\n\t\t}\n\t\t\n\t\tvar isEmailValid = true;\t\t\n\t\tvar email = $('input[name=\"email\"]').val();\n\t\tvar regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/g;\n\t\tif (email.length > 0 && email.match(regexEmail) == null) {\n\t\t\tisEmailValid = false;\n\t\t\t$('.email-error').addClass('error-msg');\n\t\t}\n\n\t\tvar isPhoneValid = true;\n\t\tvar phone = $('input[name=\"phone\"]').val().replace(/\\D/g, '');\n\t\tvar regexPhone = /^\\+?\\(?([0-9][0-8][0-9])\\)?[\\-\\. ]?([2-9][0-9]{2})[\\-\\. ]?([0-9]{4})(\\s*x[0-9]+)?$/g;\n\t\tif (phone.length > 0 && phone.match(regexPhone) == null) {\n\t\t\tisPhoneValid = false;\n\t\t\t$('.phone-error').addClass('error-msg');\n\t\t}\n\t\t\n    \tif (email.length == 0 && phone.length == 0) {\n    \t\t$('.one-required').addClass('error');\n    \t\tisEmailValid = false;\n    \t\tisPhoneValid = false;\n    \t}\n    \t\n    \tif (!isEmailValid || !isPhoneValid) {\n    \t\treturn;\n    \t}\n    \t\n\t\tif (isFirstNameValid && isLastNameValid && (isEmailValid || isPhoneValid)) {\n\t\t\tvar cleanPhone = phone.replace(/\\D/g, '');\n\t\t\tvar shipmentID = $('.alternate-pickup').closest(\"form\").attr('shipment');\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.setAlternatePickup,\n\t\t\t\ttype: \"get\",\n\t\t\t\tdata: {\n\t\t\t\t\tshipmentID: shipmentID,\n\t\t\t\t\taltPickupFirstName: firstName,\n\t\t\t\t\taltPickupLastName: lastName,\n\t\t\t\t\taltPickupEmail: email,\n\t\t\t\t\taltPickupPhone: cleanPhone\n\t\t\t\t},\n\t\t\t\tsuccess: function (response) {\n\t\t\t\t\tvar data = JSON.parse(response);\n\t\t\t\t\t\t\n\t\t\t\t\tif (data.status == 'success') {\n\t\t\t\t\t\t$('span.alt-person').attr('data-firstname', firstName).attr('data-lastname', lastName).attr('data-email', email).attr('data-phone', cleanPhone);\n\t\t\t\t\t\tdisplayAlternatePickup (firstName + ' ' + lastName)\n\t\t\t\t\t\t$('#alt-pickup-modal').removeClass('active-modal').hide();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t\tconsole.log(textStatus, errorThrown);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n    });\n}\n\nfunction displayAlternatePickup (fullName) {\n\t$('.alternate-pickup span.alt-person').text(fullName);\n\t$('span.alt-header').show();\n\t$('button.alt-pickup-button').text('UPDATE');\n}\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder && options.Recaptcha.GoogleSiteKey) {\n\t\tif ($('#submitOPCPayment').length > 0) {\n\t\t\tplaceOrderRecaptcha = grecaptcha.render('submitOPCPayment', {\n\t\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t\t        callback: submitPayment,\n\t\t        badge: 'bottomleft'\n\t\t    });\n\t\t}\n\t\t\n\t\tif ($('#submitOPCPaymentPaypal').length > 0) {\n\t\t\tplaceOrderRecaptchaPaypal = grecaptcha.render('submitOPCPaymentPaypal', {\n\t\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t\t        callback: submitPayment,\n\t\t        badge: 'bottomleft'\n\t\t    });\n\t\t}\n\t\t\n\t\tif ($('#submitOPCPaymentForAffirm').length > 0) {\n\t\t\tplaceOrderRecaptchaAffirm = grecaptcha.render('submitOPCPaymentForAffirm', {\n\t\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t\t        callback: submitPayment,\n\t\t        badge: 'bottomleft'\n\t\t    });\n\t\t}\n\t\t\n\t\tif ($('#submitOPCPaymentPrivateLabel').length > 0) {\n\t\t\tplaceOrderRecaptchaPrivateLabel = grecaptcha.render('submitOPCPaymentPrivateLabel', {\n\t\t        sitekey: options.Recaptcha.GoogleSiteKey,\n\t\t        callback: submitPaymentPrivateLabel,\n\t\t        badge: 'bottomleft'\n\t\t    });\n\t\t}\n\t}\n}\n\nfunction loyaltyOptin() {\n\tif (SitePreferences.LOYALTY_ENABLED) {\n\t\tvar opt_email = $('.billing-email-address').text();\n\t\tvar opt_status = $('#loyalty_optin').prop('checked');\n\t\tvar dw_customer_id = (Customer.authenticated == true) ? $('.section-checkout').attr('data-customerid') : '';\n\t\t\n\t\tif (SitePreferences.CORDIAL_ENABLED) {\n\t\t\tif (opt_status == false) {\n\t\t\t\t// track Cordial loyalty optout event\n\t\t\t\tvar auth_data = {\n\t\t\t\t\temail: opt_email\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar contact_data = {\n\t\t\t\t    'channels': {\n\t\t\t\t        'email': {\n\t\t\t\t            'address': opt_email         \n\t\t\t\t        }\n\t\t\t\t    }\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tvar properties = {\n\t\t\t\t    'email': opt_email\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t\t\t['event', 'loyalty_optout', properties]\n\t\t\t\t\t]);\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn TPromise.resolve($.ajax({\n\t\t\turl: Urls.loyaltyOptin,\n\t\t\tdataType: 'JSON',\n\t\t\tmethod: 'POST',\n\t\t\tdata: {\n\t\t\t\t'email': opt_email,\n\t\t\t\t'dwCustomerID': dw_customer_id,\n\t\t\t\t'optStatus': opt_status\n\t\t\t},\t\t\t\t\t\t\n\t\t\tsuccess : function(data) {\n\t\t\t\tif (('error' in data && data['error'])) {\n\t\t\t\t\tconsole.log(data.message);\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\t} else {\n\t\tTPromise.resolve();\n\t}\n}\n\nfunction submitPayment() {\n\tvar balanceDue = parseFloat($paymentSection.attr('balance-due'));\n\t$submitPayment.filter(':visible').loading({\n\t\tIsImageShown: false,\n\t\tLabel: Resources.Loading.Checkout.PlacingOrder\n\t});\n\t\n\tsetPlaceOrderButtonsDisabled(true);\n\t\n\t$billingAddressForm.validate().form();\n\t$shippingAddressForm.validate().form();\n\t\n\tvar $creditCardType = $paymentForm.find('[name$=\"_creditCard_type\"]:checked').val();\n\tif (balanceDue > 0) {\n\t\t$paymentForm.validate().form();\n\t\t\n\t\tif (typeof $creditCardType === 'undefined') {\n    \t\t$paymentForm.find('[name$=\"_creditCard_type\"]').closest('div.form-row').find('div.field-wrapper.error').remove();\n    \t\tsetTimeout(function(){\n    \t\t\t$paymentForm.find('[name$=\"_creditCard_type\"]').closest('div.form-row').append('<div class=\"field-wrapper error\" style=\"height:0px;\"><span class=\"error\">' + Resources.REQUIRED_FIELD + '</span></div>');\n    \t\t}, 50);\n    \t}\n\t}\n\t\n\t//check first if addresses are valid\n\tvar isBillingAddressValid = false;\n\tvar isShippingAddressValid = false;\n\t\n\t$billingAddressForm.validate().settings.ignore = [];\n\t$shippingAddressForm.validate().settings.ignore = [];\n\t\n\tif ($billingAddressForm.valid()) {\n\t\tisBillingAddressValid = true;\n\t} else {\n\t\t$('.billing-address-data.form-info').hide();\n\t\t\n\t\t$billingAddressForm.show();\n\t\t$billingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tif ($shippingAddressForm.valid()) {\n\t\tisShippingAddressValid = true;\n\t} else {\n\t\t$('.shipping-address-data.form-info').hide();\n\t\t\n\t\t$shippingAddressForm.show();\n\t\t$shippingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tif (isBillingAddressValid && isShippingAddressValid && $('#shipping-method-list input:checked').length && (balanceDue == 0 || $paymentForm.valid())) {\n\t\t$('.payment-declined').remove();\n\t\t\n\t\tvar actionName = $submitPayment.filter(':visible').attr('name');\n\t\tsetOPCPaymentData($paymentForm, actionName).then(function (response) {\n\t\t\tvar data;\n            try {\n\t\t\t\tdata = JSON.parse(response);\n\t\t\t} catch (e) {\n\t\t\t\tdata = response;\n\t\t\t}\n\n\t\t\tif (data.hasOwnProperty('status') && data.status === 'success') {\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo').then(loyaltyOptin).then(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t}).catch(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'affirmRedirect') {\n\t\t\t\tvar _affirm_config = {\n\t\t\t\t\tpublic_api_key: data.affirm.PublicApiKey,\n\t\t\t\t    script: data.affirm.Script\n\t\t\t\t};\n\t\t\t\t(function(l,g,m,e,a,f,b){var d,c=l[m]||{},h=document.createElement(f),n=document.getElementsByTagName(f)[0],k=function(a,b,c){return function(){a[b]._.push([c,arguments])}};c[e]=k(c,e,\"set\");d=c[e];c[a]={};c[a]._=[];d._=[];c[a][b]=k(c,a,b);a=0;for(b=\"set add save post open empty reset on off trigger ready setProduct\".split(\" \");a<b.length;a++)d[b[a]]=k(c,e,b[a]);a=0;for(b=[\"get\",\"token\",\"url\",\"items\"];a<b.length;a++)d[b[a]]=function(){};h.async=!0;h.src=g[f];n.parentNode.insertBefore(h,n);delete g[f];d(g);l[m]=c})(window,_affirm_config,\"affirm\",\"checkout\",\"ui\",\"script\",\"ready\");\n\t\t\t\t\n\t\t\t\taffirm.checkout(JSON.parse(data.affirm.AffirmCheckout));\n\t\t\t\taffirm.checkout.post();\n\t\t\t\taffirm.ui.ready(\n\t\t\t\t    function() {\n\t\t\t\t        affirm.ui.error.on(\"close\", function(){\n\t\t\t\t            // window.location.replace(data.affirm.RedirectUrl);\n\t\t\t\t        });\n\t\t\t\t    }\n\t\t\t\t);\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'shippingRestrictionsError'){\n\t\t\t\tvar popup = require('../popup');\n\t\t\t\tvar payload = JSON.parse(data.payload);\n\n\t\t\t\tvar list = $.map(payload.list, function (el) {\n\t\t\t\t\treturn '<li>' + el.name + ':<br>' + el.message + '</li>';\n\t\t\t\t}).join('');\n\t\t\t\t\n\t\t\t\tpopup.init({\n\t\t\t\t\ttitle: payload.title,\n\t\t\t\t\tcontent: payload.message + '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>',\n\t\t\t\t}).showPopup();\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'BillingAddressError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Billing Address Error:</b> ' + message + '</div>');\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'ShippingAddressError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Shipping Address Error:</b> ' + message + '</div>');\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'ValidationError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Validation Error:</b> ' + message + '</div>');\n\t\t\t} else {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Payment Declined:</b> ' + message + '</div>');\n\t\t\t}\n\t\t\t\n\t\t\t$submitPayment.filter(':visible').loading('destroy');\n\t\t\tsetPlaceOrderButtonsDisabled(false);\n\t\t\tif (placeOrderRecaptcha != undefined) {\n\t\t\t\tgrecaptcha.reset(placeOrderRecaptcha);\n\t\t\t}\n\t\t\t\n\t\t\tif (placeOrderRecaptchaPaypal != undefined) {\n\t\t\t\tgrecaptcha.reset(placeOrderRecaptchaPaypal);\n\t\t\t}\n\t\t\t\n\t\t\tif (placeOrderRecaptchaAffirm != undefined) {\n\t\t\t\tgrecaptcha.reset(placeOrderRecaptchaAffirm);\n\t\t\t}\n\t\t}).catch(function(response) {\n\t\t\tif (response.status == 302 && response.responseText) { \n\t\t\t\tlocation.href = response.responseText;\n\t\t\t}\n\t\t});\n\t} else {\n\t\t$submitPayment.filter(':visible').loading('destroy');\n\t\tsetPlaceOrderButtonsDisabled(false);\n\n\t\t// Adding ADA compliance error messages for submitPayment section\n\t\t$paymentForm.validate().form();\n\t\tif ($paymentForm.find('.field.error').length > 0) {\n\t\t\t$('.payment-declined').remove();\n\t\t\tvar paymentFormErrorMessages = opcpayment.getErrorMessages($paymentForm);\n\t\t\tvar paymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', paymentFormErrorMessages);\n\t\t\tif (paymentFormErrorBox) {\n\t\t\t\t$submitPayment.after(paymentFormErrorBox);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (placeOrderRecaptcha != undefined) {\n\t\t\tgrecaptcha.reset(placeOrderRecaptcha);\n\t\t}\n\t\t\n\t\tif (placeOrderRecaptchaPaypal != undefined) {\n\t\t\tgrecaptcha.reset(placeOrderRecaptchaPaypal);\n\t\t}\n\t\t\n\t\tif (placeOrderRecaptchaAffirm != undefined) {\n\t\t\tgrecaptcha.reset(placeOrderRecaptchaAffirm);\n\t\t}\n\t}\n}\n\nfunction submitPaymentPrivateLabel() {\n\tvar balanceDue = parseFloat($paymentForm.find('[balance-due]').attr('balance-due'));\n\t$submitPrivateLabelPayment.loading({\n\t\tIsImageShown: false,\n\t\tLabel: Resources.Loading.Checkout.PlacingOrder\n\t});\n\t\n\tsetPlaceOrderButtonsDisabled(true);\n\t\n\tvar isBillingAddressValid = false;\n\tvar isShippingAddressValid = false;\n\t\n\t$billingAddressForm.validate().settings.ignore = [];\n\t$shippingAddressForm.validate().settings.ignore = [];\n\t\n\tif ($billingAddressForm.valid()) {\n\t\tisBillingAddressValid = true;\n\t} else {\n\t\t$('.billing-address-data.form-info').hide();\n\t\t\n\t\t$billingAddressForm.show();\n\t\t$billingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tif ($shippingAddressForm.valid()) {\n\t\tisShippingAddressValid = true;\n\t} else {\n\t\t$('.shipping-address-data.form-info').hide();\n\t\t\n\t\t$shippingAddressForm.show();\n\t\t$shippingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tif (isBillingAddressValid && isShippingAddressValid && $('#shipping-method-list input:checked').length && (balanceDue == 0 || $paymentForm.valid())) {\n\t\t$('.payment-declined').remove();\n\t\t\n\t\tvar actionName = $('#submitOPCPaymentPrivateLabel').attr('name');\n\t\tsetOPCPaymentData($paymentForm, actionName).then(function (response) {\n\t\t\tvar data = JSON.parse(response);\n\n\t\t\tif (data.hasOwnProperty('status') && data.status === 'success') {\n\t\t\t\tconsole.log('payment datalayer');\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo').then(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t}).catch(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'shippingRestrictionsError'){\n\t\t\t\tvar popup = require('../popup');\n\t\t\t\tvar payload = JSON.parse(data.payload);\n\n\t\t\t\tvar list = $.map(payload.list, function (el) {\n\t\t\t\t\treturn '<li>' + el.name + ':<br>' + el.message + '</li>';\n\t\t\t\t}).join('');\n\n\t\t\t\tpopup.init({\n\t\t\t\t\ttitle: payload.title,\n\t\t\t\t\tcontent: payload.message + '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>',\n\t\t\t\t}).showPopup();\n\t\t\t} else {\n\t\t\t\tvar message = Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\tif (data.hasOwnProperty('errorMessage')) {\n\t\t\t\t\tmessage = data.errorMessage;\n\t\t\t\t} else if(data.hasOwnProperty('message')) {\n\t\t\t\t\tmessage = data.message;\n\t\t\t\t}\n                $('#submitOPCPaymentPrivateLabel').after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Payment Declined:</b> ' + message + '</div>');\n\t\t\t}\n\t\t\t$submitPrivateLabelPayment.loading('destroy');\n\t\t\tsetPlaceOrderButtonsDisabled(false);\n\t\t\tif (placeOrderRecaptchaPrivateLabel != undefined) {\n\t\t\t\tgrecaptcha.reset(placeOrderRecaptchaPrivateLabel);\n\t\t\t}\n\t\t}.bind(this));\n\t} else {\n\t\t$submitPrivateLabelPayment.loading('destroy');\n\t\tsetPlaceOrderButtonsDisabled(false);\n\n\t\t// Adding ADA compliance error messages for submitPayment section\n\t\t$paymentForm.validate().form();\n\t\tif ($paymentForm.find('.field.error').length > 0) {\n\t\t\t$('.payment-declined').remove();\n\t\t\tvar paymentFormErrorMessages = opcpayment.getErrorMessages($paymentForm);\n\t\t\tvar paymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', paymentFormErrorMessages);\n\t\t\tif (paymentFormErrorBox) {\n\t\t\t\t$submitPrivateLabelPayment.after(paymentFormErrorBox);\n\t\t\t}\n\t\t}\n\n\t\tif (placeOrderRecaptchaPrivateLabel != undefined) {\n\t\t\tgrecaptcha.reset(placeOrderRecaptchaPrivateLabel);\n\t\t}\n\t}\n}\n\nfunction initializePaymentMethodsEvents () {\n\tvar ccListSelector = '#opc-cc-list input[type=\"radio\"]',\n\t\tccNumberSelector = 'input[name^=\"dwfrm_billing_paymentMethods_creditCard_number\"]';\n\n\t$(ccNumberSelector).parent().append('<div class=\"cc-image\"></div>');\n\t$('input[name^=\"dwfrm_billing_paymentMethods_privateLabelCredit_number\"]').parent().append('<div class=\"cc-image\"></div>');\n\t\n\t$paymentForm.attr('selected-payment-method', $('.input-radio.payment-method-selector:checked').val());\n\n\t$(document).on('change', ccListSelector, function () {\n\t\t$(ccNumberSelector)\n\t\t\t.parent()\n\t\t\t.find('.cc-image')\n\t\t\t.css('background-image', 'url(' + $(this).next().attr('src') + ')');\n\t});\n\n\tif ($(ccListSelector + ':checked').val()) {\n\t\t$(ccListSelector + ':checked').trigger('change');\n\t}\n\t\n\t$paymentForm.on('click', '.payment-method-selector', function (e) {\n\t    var paymentMethodId = ('' + $(this).attr('id')).replace('is-','');\n\t\t\n\t\t// Reset paymentForm errors when changing payment method groups \n\t\t$paymentForm.validate().resetForm();\n\t    \n\t    if (paymentMethodId) {\n\t    \t$('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val(paymentMethodId);\n\t\t\t$paymentForm.attr('selected-payment-method', paymentMethodId);\n\t    \t\n\t\t    $paymentForm.find('.payment-method').each(function() {\n\t\t        $(this).removeClass('payment-method-expanded');\n\t\t        \n\t\t        if ($(this).attr('data-method') == paymentMethodId) {\n\t\t            $(this).addClass('payment-method-expanded');\n\t\t        }\n\t\t    });\n\t\t    \n\t\t    var $paymentMethodPanel = $('.payment-method[data-method=\"' + paymentMethodId + '\"]');\n\t\t    if ($paymentMethodPanel.attr('payment-card-image')) {\n\t\t    \t$paymentMethodPanel.find('.cc-image').css('background-image', 'url(' + $paymentMethodPanel.attr('payment-card-image') + ')');\n\t    \t}\n\t    }\n\t    \n\t    if (window.innerWidth <= 767) {\n\t\t\t$([document.documentElement, document.body]).animate({\n\t\t\t\t// scrollTop: $('.payment-method-expanded').closest('.payment-method-option').offset().top - $('.top-banner').height() + 20\n\t\t\t\tscrollTop: $('#paymentSection').offset().top - $('.top-banner').height() - 15\n\t\t\t}, 250);\n\t    }\n\t    \n\t    addresses.updateSummary();\n\t});\n\n\t$(ccNumberSelector).on('keydown', function(e) {\n\t\t$creditCardList.val('');\n\t});\n\t\n\t$(ccNumberSelector).on('keyup', function(e){\n\t\tvar creditCardNumber = $(this).val();\n\t\t\n\t\tvar selectedCard = util.getCreditCardType(creditCardNumber);\n\t\tif (selectedCard) {\n\t\t\t$(ccListSelector).filter(\"[value='\"+ selectedCard.PaymentCardDisplayKey +\"']\").eq(0).trigger('click');\n\t\t} else {\n\t\t\t$('.cc-cardlist-select :input').removeAttr('checked').removeAttr('selected').val('');\n\t\t\t$(ccListSelector).prop('checked', false);\n\t\t\t$paymentForm.find('.payment-method[data-method=\"' + PaymentMethodConstants.CreditCard + '\"] .cc-image').css('background-image', '');\n\t\t}\n\t});\n\n\t$('.add-new-card').on('click', function(e){\n\t\te.preventDefault();\n\n\t\t$('input[name^=\"dwfrm_billing_paymentMethods_creditCard_owner\"]').val('');\n\t\t$('input[name^=\"dwfrm_billing_paymentMethods_creditCard_number\"]').val('');\n\t\t$('input[name^=\"dwfrm_billing_paymentMethods_creditCard_cvn\"]').val('');\n\t\t$('input[name^=\"dwfrm_billing_paymentMethods_creditCard_expiration_month\"]').val('');\n\t\t$('input[name^=\"dwfrm_billing_paymentMethods_creditCard_expiration_year\"]').val('');\n\t\t$('#opc-cc-list :input').removeAttr('checked');\n\t\t$('.cc-cardlist-select :input').removeAttr('checked').removeAttr('selected').val('');\n\t\t$('.cc-image').css('background-image', 'none');\n\t});\n}\n\nfunction setPlaceOrderButtonsDisabled(isDisabled) {\n\t$submitPayment.attr('disabled', isDisabled);\t\n\t$('#submitOPCPaymentPrivateLabel').attr('disabled', isDisabled);\t\n}\n\n/**\n * @description Make the AJAX request to set cart data\n * @param {Element} form The form element that present address object\n * @param {Element} Action name to apply to form\n * @returns {Promise}\n */\nvar setOPCPaymentData = function (form, name) {\n    var $form = $(form);\n\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.setOpcAddress),\n        data: $form.serialize() + '&' + name + '=' + name\n    }));\n};\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\t\n\tif (options && options.Recaptcha && (options.Recaptcha.EnabledForPlaceOrder || options.Recaptcha.EnabledForRewardsCredit || options.Recaptcha.EnabledForGiftCards)) {\n    \trecaptcha.initialize();\n\t}\n\tGiftCard.initialize(options);\n\tRewardsCredit.initialize(options);\n\tLoyaltyCredit.initialize(options);\n    initializeEvents(options);\n};","'use strict';\n\nvar quickview = require('../quickview');\nvar bonusProductsView = require('../bonus-products-view');\nvar TPromise = require('promise');\nvar util = require('../util');\nvar addresses = SitePreferences.ENABLE_ENHANCED_CHECKOUT ? require('./checkout/opcaddress_enhanced') : require('./checkout/opcaddress');\nvar formPrepare = require('./checkout/formPrepare');\nvar cart = require('./cart');\nvar opcpayment = require('./checkout/opcpayment');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar GiftCard = require('./checkout/GiftCardPaymentPanel');\nvar GoogleTagManagerClient = require('../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar PaymentVoucherPanel;\nvar recaptcha = require('../components/Recaptcha');\nvar RewardsCredit = require('./checkout/RewardsCredit');\nvar LoyaltyCredit = require('./checkout/LoyaltyCredit');\nvar CheckoutConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/CheckoutConstants');\nvar PaymentMethodConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar BopisProductLineItemHelper = require('../bopis/components/ProductLineItemHelper');\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar cartItemsFormSelector = 'form#cart-items-form';\nvar billingAddressFormSelector = '#billingAddressForm';\nvar $billingAddressForm = $(billingAddressFormSelector);\nvar shippingAddressFormSelector = '#shippingAddressForm';\nvar $shippingAddressForm = $(shippingAddressFormSelector);\nvar paymentSectionSelector = '.form-checkout.payment-section';\nvar $paymentSection = $(paymentSectionSelector);\nvar paymentFormSelector = '#paymentSection';\nvar $paymentForm = $(paymentFormSelector);\nvar creditCardListSelector = '#creditCardList';\nvar $creditCardList = $(creditCardListSelector);\nvar creditCardSaveCheckboxContainerSelector = 'div[field=\"saveCard\"]';\nvar $creditCardSaveCheckboxContainer = $(creditCardSaveCheckboxContainerSelector);\nvar creditCardSaveCheckboxSelector = '#dwfrm_billing_paymentMethods_creditCard_saveCard';\nvar $creditCardSaveCheckbox = $(creditCardSaveCheckboxSelector);\nvar submitPaymentSelector = '#submitOPCPayment';\nvar $submitPayment = $(submitPaymentSelector);\nvar basketContainerSelector = '.basket-container';\nvar $basketContainer = $(basketContainerSelector);\n\nvar placeOrderRecaptcha;\nvar options = {};\nvar loaded = {};\n\n/**\n * @description Events should be divided to modules. This allows reinitialize events by sections after partial reload \n * @private\n * @function\n * @description Initializes events for the gift registration\n */\nfunction initializeEvents(options) {\n\tinitializeCartEvents(options);\n\tinitializePaymentMethodsEvents();\n\t\n\trenderRecaptcha();\n\t$(document).on('Recaptcha.Loaded', function(event) {\n\t\tif (!loaded.Recaptcha) {\n\t\t\tloaded.Recaptcha = true;\n\t        renderRecaptcha();\n\t    }\n\t});\n}\n\nfunction initializeCartEvents(options) {\n\t$(document).on('click', 'a.add-to-wishlist', function (e) {\n    \t/*remove next line to use default dw wishlist functionality*/\n    \treturn false;\n    \te.preventDefault();\n    \t\n    \tif (Customer.authenticated == true) {\n    \t\t// post form here\n    \t} else {\n    \t\t$('html, body').animate({ scrollTop: $('.login-form').eq(0).offset().top}, 1000);\n    \t}\n    });\n\t\n\tif (SitePreferences.ALTERNATE_PICKUP_ENABLED) {\n\t\trenderAlternatePickup();\n\t}\n\n    $paymentForm.on('change', '[name$=\"_creditCard_type\"]', function() {\n    \t$submitPayment.removeAttr('disabled');\n    \t$(this).closest('div.form-row').find('div.field-wrapper.error').remove();\n    });\n\n    $(document).on('click', submitPaymentSelector, function(e) {\n    \te.preventDefault();\n\n    \tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForPlaceOrder) {\n\t\t\tsubmitPayment();\t\n\t\t}\n    });\n    \n    $(document).on('Checkout.SubmitPayment', function (event, data) {\n\t\tif ((options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder) || (data && data.SubmitPaymentForBopis)) {\n\t\t\tsubmitPayment(data);\n\t\t}\n\t});\n    \n    var getCreditCardInfo = function (id) {\n        return TPromise.resolve($.ajax({\n            type: 'GET',\n            url: util.ajaxUrl(Urls.billingGetCreditCard),\n            data: { creditCardUUID: id }\n        }));\n    };\n    \n    $creditCardList.on('change', function() {\n    \tvar creditCardUUID = $(this).val();\n    \t\n    \tif (creditCardUUID.length <= 0) {\n    \t\treturn;\n    \t}\n    \t\n    \tgetCreditCardInfo(creditCardUUID).then(function (data) {\n\t\t\tif (data && data.hasOwnProperty('maskedNumber')) {\n\t\t\t\tvar $paymentMethodGroup = $('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"]');\n\t\t\t\tvar $paymentMethod = $paymentMethodGroup.find('.payment-method[payment-method=\"' + data.paymentMethod + '\"]');\n\n\t\t\t\tvar paymentMethodRadioToSelect = data.paymentMethod == PaymentMethodConstants.CreditCard ? data.type : data.paymentMethod;\n\t\t\t\t$paymentMethodGroup.find('input[type=\"radio\"][value=\"' + paymentMethodRadioToSelect + '\"]').first().prop('checked', true).trigger('change', { doReset: false });\n\t\t\t\t\n\t\t\t\tif ($paymentMethod.find('[id*=\"_creditCard_owner\"]').length > 0 && data.hasOwnProperty('holder')) {\n\t\t\t\t\t$paymentMethod.find('[id*=\"_creditCard_owner\"]').val(data.holder).valid();\n\t\t\t\t}\n\n\t\t\t\t$('.pt_onepcheckout input[name*=\"_creditCard_type\"]').val(data.type);\n\t\t\t\t$paymentMethod.find('[id*=\"_number\"]').val(data.maskedNumber).valid();\n\t\t\t\t\n\t\t\t\tif ($paymentMethod.find('[id*=\"_creditCard_expiration_month\"]').length > 0 && data.hasOwnProperty('expirationMonth')) {\n\t\t\t\t\t$paymentMethod.find('[id*=\"_creditCard_expiration_month\"]').val(data.expirationMonth).trigger('change');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ($paymentMethod.find('[id*=\"_creditCard_expiration_year\"]').length > 0 && data.hasOwnProperty('expirationYear')) {\n\t\t\t\t\t$paymentMethod.find('[id*=\"_creditCard_expiration_year\"]').val(data.expirationYear).trigger('change');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ($paymentMethod.find('[id*=\"_creditCard_cvn\"]').length > 0) {\n\t\t\t\t\t$paymentMethod.find('[id*=\"_creditCard_cvn\"]').val('');\n\t\t\t\t}\n\n\t\t\t\t$creditCardSaveCheckboxContainer.hide();\n\t\t\t}\n\t\t}.bind(this));\t\n    });\n    \n\tif ($creditCardList.length > 0 && ($('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val() == PaymentMethodConstants.CreditCard || $('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val() == PaymentMethodConstants.AllianceData)) {\n\t\t$creditCardList.find('option').eq(1).prop('selected', true);\n\t\t$creditCardList.trigger('change');\n\t\t$creditCardSaveCheckboxContainer.hide();\n\t} else {\n\t\t$creditCardSaveCheckboxContainer.show();\n\t}\n\t\n    addresses.init(options);\n    cart.init(options);\n}\n\nfunction renderAlternatePickup() {\n\t$(document).off('click', 'button.alt-pickup-button').on('click', 'button.alt-pickup-button', function (e) {\n    \te.preventDefault();\n\t\t$('#alt-pickup-modal').addClass('active-modal').show();\n\t\t$('fieldset span').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).off('click', '#alt-pickup-modal .close-modal').on('click', '#alt-pickup-modal .close-modal', function (e) {\n    \te.preventDefault();\n\t\t$('#alt-pickup-modal').removeClass('active-modal').hide();\n    });\n    \n    $(document).on('focus', 'input[name=\"firstName\"]', function () {\n\t\t$('.firstname-error').removeClass('error-msg');\n    });\n    \n    $(document).on('focus', 'input[name=\"lastName\"]', function () {\n\t\t$('.lastname-error').removeClass('error-msg');\n    });\n    \n    $(document).on('focus', 'input[name=\"email\"]', function () {\n\t\t$('.email-error').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).on('focus', 'input[name=\"phone\"]', function () {\n\t\t$('.phone-error').removeClass('error-msg');\n\t\t$('.one-required').removeClass('error');\n    });\n    \n    $(document).off('click', 'button#altPickupSubmit').on('click', 'button#altPickupSubmit', function (e) {\n    \te.preventDefault();\n\t\t\n    \tvar isFirstNameValid = true;\n\t\tvar firstName = $('input[name=\"firstName\"]').val();\n\t\tvar regexName = /^[a-z ,.'-]+$/i;\n\t\tif (firstName.length == 0 || firstName.match(regexName) == null) {\n\t\t\tisFirstNameValid = false;\n\t\t\t$('.firstname-error').addClass('error-msg');\n\t\t}\n\t\t\n\t\tvar isLastNameValid = true;\t\t\n\t\tvar lastName =$('input[name=\"lastName\"]').val();\n\t\tif (lastName.length == 0 || lastName.match(regexName) == null) {\n\t\t\tisLastNameValid = false;\n\t\t\t$('.lastname-error').addClass('error-msg');\n\t\t}\n\t\t\n\t\tvar isEmailValid = true;\t\t\n\t\tvar email = $('input[name=\"email\"]').val();\n\t\tvar regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/g;\n\t\tif (email.length > 0 && email.match(regexEmail) == null) {\n\t\t\tisEmailValid = false;\n\t\t\t$('.email-error').addClass('error-msg');\n\t\t}\n\n\t\tvar isPhoneValid = true;\n\t\tvar phone = $('input[name=\"phone\"]').val().replace(/\\D/g, '');\n\t\tvar regexPhone = /^\\+?\\(?([0-9][0-8][0-9])\\)?[\\-\\. ]?([2-9][0-9]{2})[\\-\\. ]?([0-9]{4})(\\s*x[0-9]+)?$/g;\n\t\tif (phone.length > 0 && phone.match(regexPhone) == null) {\n\t\t\tisPhoneValid = false;\n\t\t\t$('.phone-error').addClass('error-msg');\n\t\t}\n\t\t\n    \tif (email.length == 0 && phone.length == 0) {\n    \t\t$('.one-required').addClass('error');\n    \t\tisEmailValid = false;\n    \t\tisPhoneValid = false;\n    \t}\n    \t\n    \tif (!isEmailValid || !isPhoneValid) {\n    \t\treturn;\n    \t}\n    \t\n\t\tif (isFirstNameValid && isLastNameValid && (isEmailValid || isPhoneValid)) {\n\t\t\tvar cleanPhone = phone.replace(/\\D/g, '');\n\t\t\tvar shipmentID = $('.alternate-pickup').closest(\"form\").attr('shipment');\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.setAlternatePickup,\n\t\t\t\ttype: \"get\",\n\t\t\t\tdata: {\n\t\t\t\t\tshipmentID: shipmentID,\n\t\t\t\t\taltPickupFirstName: firstName,\n\t\t\t\t\taltPickupLastName: lastName,\n\t\t\t\t\taltPickupEmail: email,\n\t\t\t\t\taltPickupPhone: cleanPhone\n\t\t\t\t},\n\t\t\t\tsuccess: function (response) {\n\t\t\t\t\tvar data = JSON.parse(response);\n\t\t\t\t\t\t\n\t\t\t\t\tif (data.status == 'success') {\n\t\t\t\t\t\t$('span.alt-person').attr('data-firstname', firstName).attr('data-lastname', lastName).attr('data-email', email).attr('data-phone', cleanPhone);\n\t\t\t\t\t\tdisplayAlternatePickup (firstName + ' ' + lastName)\n\t\t\t\t\t\t$('#alt-pickup-modal').removeClass('active-modal').hide();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t\tconsole.log(textStatus, errorThrown);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n    });\n}\n\nfunction displayAlternatePickup (fullName) {\n\t$('.alternate-pickup span.alt-person').text(fullName);\n\t$('span.alt-header').show();\n\t$('button.alt-pickup-button').text('UPDATE');\n}\n\nfunction renderRecaptcha() {\n\tif (loaded.Recaptcha && $('#submitOPCPayment').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder && options.Recaptcha.GoogleSiteKey && placeOrderRecaptcha == undefined) {\n\t\tplaceOrderRecaptcha = grecaptcha.render('submitOPCPayment', {\n\t        'sitekey': options.Recaptcha.GoogleSiteKey,\n\t        'callback': submitPayment,\n\t        'badge': 'bottomleft'\n\t    });\n\t}\n}\n\nfunction submitPaymentRecaptchaError() {\n\tif (loaded.Recaptcha && $('#submitOPCPayment').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForPlaceOrder && options.Recaptcha.GoogleSiteKey && placeOrderRecaptcha != undefined) {\n\t\tgrecaptcha.reset(placeOrderRecaptcha);\n\t\trenderRecaptcha();\n\t}\n}\n\nfunction submitPayment(data) {\n\tvar balanceDue = parseFloat($paymentSection.attr('balance-due'));\n\t$submitPayment.loading({\n\t\tIsImageShown: false,\n\t\tLabel: Resources.Loading.Checkout.PlacingOrder\n\t});\n\t$submitPayment.attr('disabled', true);\n\t$('#errorBoxOPC').remove();\n\n\t$billingAddressForm.validate().form();\n\t$shippingAddressForm.validate().form();\n\t\n\tvar $creditCardType = $paymentForm.find('[name$=\"_creditCard_type\"]:checked').val();\n\tif (balanceDue > 0) {\n\t\t$paymentForm.validate().form();\n\t\t\n\t\tif (typeof $creditCardType === 'undefined') {\n    \t\t$paymentForm.find('[name$=\"_creditCard_type\"]').closest('div.form-row').find('div.field-wrapper.error').remove();\n\n    \t\tsetTimeout(function(){\n    \t\t\t$paymentForm.find('[name$=\"_creditCard_type\"]').closest('div.form-row').append('<div class=\"field-wrapper error\" style=\"height:0px;\"><span class=\"error\">' + Resources.REQUIRED_FIELD + '</span></div>');\n    \t\t}, 50);\n\t\t}\n\t}\n\t\n\t// check first if addresses are valid\n\tvar isBillingAddressValid = false;\n\tvar isShippingAddressValid = false;\n\t\n\t$billingAddressForm.validate().settings.ignore = [];\n\t$shippingAddressForm.validate().settings.ignore = [];\n\t\n\tif ($billingAddressForm.valid()) {\n\t\tisBillingAddressValid = true;\n\t} else {\n\t\t$('.billing-address-data.form-info').hide();\n\t\t\n\t\t$billingAddressForm.show();\n\t\t$billingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tif ($shippingAddressForm.valid() || ($shippingAddressForm.find('.formfield.isStore input').prop('checked') && $shippingAddressForm.find('.formfield.myStoreID input').val())) {\n\t\tisShippingAddressValid = true;\n\t} else {\n\t\t$('.shipping-address-data.form-info').hide();\n\t\t\n\t\t$shippingAddressForm.show();\n\t\t$shippingAddressForm.find('input.required.field.error').eq(0).focus();\n\t}\n\t\n\tvar isBopisValid = false;\n\tif (data && data.SubmitPaymentForBopis) {\n\t\tisBopisValid = data.IsBopisInventoryValid;\n\t} else {\n\t\tvar $bopisProductLineItems = $(cartItemsFormSelector).find('.bopis-product-line-item[sku][store]');\n\t\t\n\t\tif ($bopisProductLineItems.length > 0) {\n\t\t\tBopisProductLineItemHelper.ValidateProductLineItems($(cartItemsFormSelector).find('.bopis-product-line-item[sku][store]'), { SuccessEvent: 'Checkout.SubmitPayment' });\n\t\t} else {\n\t\t\tisBopisValid = true;\n\t\t}\n\t}\n\t\n\tif (isBillingAddressValid && isShippingAddressValid && isBopisValid && $('#shipping-method-list input:checked').length && (balanceDue == 0 || $paymentForm.valid())) {\n\t\tvar $paymentFormToSet = $paymentForm.clone();\n\t\tvar actionName = $submitPayment.attr('name');\n\t\t\n\t\tvar selectedPaymentMethodId = $paymentForm.find('input[name*=\"selectedPaymentMethodID\"]').val();\n\t\t$paymentFormToSet.find('div[payment-method]').not('div[payment-method=\"' + selectedPaymentMethodId + '\"]').remove();\n\t\t\n\t\t$paymentFormToSet.find('select').each(function (index) {\n\t\t\t$(this).val($paymentForm.find('#' + $(this).attr('id')).val());\n\t\t});\n\t\t\n\t\tsetOPCPaymentData($paymentFormToSet, actionName).then(function(response) {\n\t\t\tvar data;\n\t\t\ttry {\n\t\t\t\tdata = JSON.parse(response);\n\t\t\t} catch (e) {\n\t\t\t\tdata = response;\n\t\t\t}\n\n\t\t\tif (data.hasOwnProperty('status') && data.status === 'success') {\n\t\t\t\tvar dataObject = {\n\t\t\t\t\tvalue: balanceDue,\n\t\t\t\t\tpayment_type: selectedPaymentMethodId\n\t\t\t\t}\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddPaymentInfo', dataObject).then(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t}).catch(function() {\n\t\t\t\t\tif (options.CheckoutMode == 'MobileApp') {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPageForMobileApp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.location.href = Urls.confirmationPage;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'affirmRedirect') {\n\t\t\t\tvar _affirm_config = {\n\t\t\t\t\tpublic_api_key: data.affirm.PublicApiKey,\n\t\t\t\t\tscript: data.affirm.Script\n\t\t\t\t};\n\t\t\t\t(function(l,g,m,e,a,f,b){var d,c=l[m]||{},h=document.createElement(f),n=document.getElementsByTagName(f)[0],k=function(a,b,c){return function(){a[b]._.push([c,arguments])}};c[e]=k(c,e,\"set\");d=c[e];c[a]={};c[a]._=[];d._=[];c[a][b]=k(c,a,b);a=0;for(b=\"set add save post open empty reset on off trigger ready setProduct\".split(\" \");a<b.length;a++)d[b[a]]=k(c,e,b[a]);a=0;for(b=[\"get\",\"token\",\"url\",\"items\"];a<b.length;a++)d[b[a]]=function(){};h.async=!0;h.src=g[f];n.parentNode.insertBefore(h,n);delete g[f];d(g);l[m]=c})(window,_affirm_config,\"affirm\",\"checkout\",\"ui\",\"script\",\"ready\");\n\t\t\t\t\n\t\t\t\taffirm.checkout(JSON.parse(data.affirm.AffirmCheckout));\n\t\t\t\taffirm.checkout.post();\n\t\t\t\taffirm.ui.ready(\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\taffirm.ui.error.on(\"close\", function(){\n\t\t\t\t\t\t\t// window.location.replace(data.affirm.RedirectUrl);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'shippingRestrictionsError') {\n\t\t\t\tvar popup = require('../popup');\n\t\t\t\tvar payload = JSON.parse(data.payload);\n\n\t\t\t\tvar list = $.map(payload.list, function (el) {\n\t\t\t\t\treturn '<li>' + el.name + ':<br>' + el.message + '</li>';\n\t\t\t\t}).join('');\n\t\t\t\t\n\t\t\t\tpopup.init({\n\t\t\t\t\ttitle: payload.title,\n\t\t\t\t\tcontent: payload.message + '<ul class=\"shipping-restrictions-popup__list\">' + list + '</ul>',\n\t\t\t\t}).showPopup();\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'BillingAddressError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Billing Address Error:</b> ' + message + '</div>');\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'ShippingAddressError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Shipping Address Error:</b> ' + message + '</div>');\n\t\t\t} else if (data.hasOwnProperty('status') && data.status === 'ValidationError') {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Validation Error:</b> ' + message + '</div>');\n\t\t\t} else {\n\t\t\t\tvar message = data.hasOwnProperty('message') ? data.message : Resources.Checkout.Confirm.Error.Generic;\n\t\t\t\t$submitPayment.after('<div id=\"errorBoxOPC\" class=\"payment-declined p-2 mt-2\" role=\"alert\" tabindex=\"0\"><i class=\"fa fa-exclamation-triangle\"></i> <b>Payment Declined:</b> ' + message + '</div>');\n\t\t\t}\n\t\t\t\n\t\t\t$submitPayment.loading('destroy');\n\t\t\t$submitPayment.attr('disabled', false);\n\t\t\tsubmitPaymentRecaptchaError();\n\t\t}).catch(function(response) {\n\t\t\tif (response.status == 302 && response.responseText) {\n\t\t\t\tlocation.href = response.responseText;\n\t\t\t}\n\t\t});\n\t} else {\n\t\t$submitPayment.loading('destroy');\n\t\t$submitPayment.attr('disabled', false);\n\n\t\t// Adding ADA compliance error messages for submitPayment section\n\t\t$paymentForm.validate().form();\n\t\tif ($paymentForm.find('.field.error').length > 0) {\n\t\t\t$('.payment-declined').remove();\n\t\t\tvar paymentFormErrorMessages = opcpayment.getErrorMessages($paymentForm);\n\t\t\tvar paymentFormErrorBox = opcpayment.errorBox('Cannot Proceed', 'Please fix the following errors:', paymentFormErrorMessages);\n\t\t\tif (paymentFormErrorBox) {\n\t\t\t\t$submitPayment.after(paymentFormErrorBox);\n\t\t\t}\n\t\t}\n\n\t\tsubmitPaymentRecaptchaError();\n\t}\n}\n\nfunction initializePaymentMethodsEvents() {\n\tvar creditCardListSelector = '.payment-card-list select, .payment-card-list input[type=\"radio\"]';\n\tvar creditCardNumberInput = 'input[name*=\"_creditCard_number\"], input[name*=\"_privateLabelCredit_number\"]';\n\t\n\t$(creditCardNumberInput).parent().append('<div class=\"cc-image\"></div>');\n\t\n\t$(document).on('change', creditCardListSelector, function (e, options) {\t\n\t\tvar $this = $(this);\n\n\t\toptions = options != undefined ? options : {};\n\t\toptions.doReset = options.doReset != undefined ? options.doReset : true;\n\t\t\n\t\tvar selectedCreditCardType = $this.val();\n\t\t\n\t\tif (selectedCreditCardType) {\n\t\t\tvar selectedPaymentMethodId = $this.attr('payment-method') || $this.find(':selected').attr('payment-method');\n\t\t\tvar selectedPaymentCardImageUrl = $this.attr('payment-card-image') || $this.find(':selected').attr('payment-card-image');\n\t\t\t\n\t\t\t$paymentForm.attr('selected-payment-method', selectedPaymentMethodId);\n\t\t\t$this.closest('[payment-method-group]').attr('payment-method', selectedPaymentMethodId);\n\t\t\t\n\t\t\t$('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val(selectedPaymentMethodId);\n\n\t\t\tif (!$('[payment-method=\"' + selectedPaymentMethodId + '\"].payment-method').hasClass('payment-method-expanded')) {\n\t\t\t\t$('.payment-method').removeClass('payment-method-expanded').hide();\n\t\t\t\t$('[payment-method=\"' + selectedPaymentMethodId + '\"].payment-method').addClass('payment-method-expanded').show();\t\n\t\t\t}\n\t\t\t\n\t\t\t$('.payment-card-list.grid').find('[payment-card]').hide();\n\t\t\t$('.payment-card-list.grid').find('[payment-card=\"' + selectedCreditCardType + '\"]').show();\n\t\t\t\n\t\t\t$(creditCardListSelector).filter('input[value=\"' + selectedCreditCardType + '\"]').prop('checked', true);\n\t\t\t$(creditCardListSelector).find('option[value=\"' + selectedCreditCardType + '\"]').prop('selected', true);\n\n\t\t\t$paymentForm.find('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"] .cc-image').css('background-image', 'url(' + selectedPaymentCardImageUrl + ')');\n\t\t\t\n\t\t\tif (options.doReset) {\n\t\t\t\tresetCreditCardFields($('[payment-method=\"' + selectedPaymentMethodId + '\"].payment-method'));\n\t\t\t\t$creditCardList.val('');\n\t\t\t}\n\t\t}\n\t});\n\t\n\t$paymentForm.on('click', '.payment-method-group-selector', function (e) {\n\t    var paymentMethodGroupId = $(this).val();\n\t    \n\t    if (paymentMethodGroupId) {\n\t    \t$paymentForm.attr('selected-payment-method-group', paymentMethodGroupId);\n\t\t    \n\t\t    $('.pt_onepcheckout input[name*=\"_selectedPaymentMethodID\"]').val($('[payment-method-group=\"' + paymentMethodGroupId + '\"]').attr('payment-method'));\n\t\t    \n\t\t    $('[payment-method-group]').hide().removeClass('expanded');\n\t\t    $('[payment-method-group=\"' + paymentMethodGroupId + '\"]').show().addClass('expanded');\n\t\t    \n\t\t    if ($('[payment-method-group=\"' + paymentMethodGroupId + '\"]').find('.payment-method-expanded').length < 1) {\n\t\t    \tvar $defaultPaymentMethod = $('[payment-method-group=\"' + paymentMethodGroupId + '\"]').find('.payment-method').first();\n\t\t    \t\n\t\t    \t$defaultPaymentMethod.addClass('payment-method-expanded').show();\n\t\t    \t\n\t\t    \tif ($defaultPaymentMethod.attr('payment-card-image')) {\n\t\t    \t\t$defaultPaymentMethod.find('.cc-image').css('background-image', 'url(' + $defaultPaymentMethod.attr('payment-card-image') + ')');\n\t\t    \t}\n\t\t    }\n\t\t    \n\t\t    if (window.innerWidth <= 767) {\n\t\t\t\t$([document.documentElement, document.body]).animate({\n\t\t\t\t\t// scrollTop: $('.payment-method-expanded').closest('.payment-method-option').offset().top - $('.top-banner').height() + 20\n\t\t\t\t\tscrollTop: $('#paymentSection').offset().top - $('.top-banner').height() - 15\n\t\t\t\t}, 250);\n\t\t    }\n\t\t    \n\t\t    // addresses.updateSummary();\n\t    }\n\t});\n\t\n\t$('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"] [credit-card-number-input]').on('keydown', function(e) {\n\t\t$creditCardList.val('');\n\t});\n\n\t$('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"] [credit-card-number-input]').on('keyup', function(e) {\n\t\tvar $this = $(this);\n\t\tvar creditCardNumber = $this.val();\n\t\t\n\t\tvar selectedCard = util.getCreditCardType(creditCardNumber);\n\t\tif (selectedCard) {\n\t\t\tvar $selectedCardNumberInput = $('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"] [payment-method=\"' + selectedCard.PaymentMethod + '\"] [credit-card-number-input]');\n\t\t\t\n\t\t\tif ($selectedCardNumberInput.filter(':visible').length < 1) {\n\t\t\t\t$selectedCardNumberInput.val(creditCardNumber);\n\t\t\t}\n\n\t\t\t$('.pt_onepcheckout input[name*=\"_creditCard_type\"]').val(selectedCard.PaymentCard);\n\t\t\t$(creditCardListSelector).filter('input[type=\"radio\"][value=\"' + selectedCard.PaymentCardDisplayKey + '\"]').first().prop('checked', true).trigger('change', { doReset: false });\n\t\t\t\n\t\t\tif ($selectedCardNumberInput.filter(':focus').length < 1) {\n\t\t\t\t$selectedCardNumberInput.focus().val(creditCardNumber);\n\t\t\t}\n\t\t} else {\n\t\t\t$('.cc-cardlist-select :input').removeAttr('checked').removeAttr('selected').val('');\n\t\t\t$('.payment-card-list.grid').find('[payment-card]').show();\n\t\t\t$(creditCardListSelector).filter('input').prop('checked', false);\n\t\t\t$(creditCardListSelector).find('option').prop('selected', false);\n\t\t\t$paymentForm.find('[payment-method-group=\"' + PaymentMethodConstants.CreditCard + '\"] .cc-image').css('background-image', '');\n\t\t}\n\n\t\t$creditCardSaveCheckboxContainer.show();\n\t});\n\t\n\t$('.add-new-card').on('click', function(e) {\n\t\te.preventDefault();\n\n\t\tresetCreditCardFields($(this).closest('[payment-method]'));\n\t\t$('#opc-cc-list :input').removeAttr('checked');\n\t\t$('.cc-cardlist-select :input').removeAttr('checked').removeAttr('selected').val('');\n\t\t$('.cc-image').css('background-image', 'none');\n\t});\n\t\n\t$(document).on('click', '.payment-method-option.accordion .form-label', function () {\n\t\t$(this).closest('.accordion').toggleClass('open');\n\t});\n}\n\nfunction resetCreditCardFields($paymentMethod) {\n\t$paymentMethod.find('input[name*=\"_owner\"]').val('');\n\t$paymentMethod.find('input[name*=\"_number\"]').val('');\n\t$paymentMethod.find('input[name*=\"_cvn\"]').val('');\n\t$paymentMethod.find('input[name*=\"_month\"]').val('');\n\t$paymentMethod.find('input[name*=\"_year\"]').val('');\n}\n\n/**\n * @description Make the AJAX request to set cart data\n * @param {Element} form The form element that present address object\n * @param {Element} Action name to apply to form\n * @returns {Promise}\n */\nvar setOPCPaymentData = function (formSelector, name) {\n    var $form = $(formSelector);\n\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.setOpcAddress),\n        data: $form.serialize() + '&' + name + '=' + name\n    }));\n};\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\t\n\tif (options && options.Recaptcha && (options.Recaptcha.EnabledForPlaceOrder || options.Recaptcha.EnabledForRewardsCredit || options.Recaptcha.EnabledForGiftCards)) {\n    \trecaptcha.initialize();\n\t}\n\t\n\tif (options.B2B && options.B2B.Enabled) {\n\t\tPaymentVoucherPanel = require('./checkout/PaymentVoucherPaymentPanel');\n\t\tPaymentVoucherPanel.initialize();\n\t}\n\tGiftCard.initialize(options);\n\tRewardsCredit.initialize(options);\n\tLoyaltyCredit.initialize(options);\n    initializeEvents(options);\n};","'use strict';\n\nvar tooltip = require('../tooltip');\n\nvar options = {};\nvar buffer = {};\n\nfunction triggerReactWebviewEvent() {\n\tif ('ReactNativeWebView' in window) {\n\t\twindow.ReactNativeWebView.postMessage(JSON.stringify({ action: 'order-page' }));\n\t}\n}\n\nfunction initializePriceSpiderOrderTracking() {\n\t$(document).on('DataLayer.OrderComplete', function (event, dataLayer) {\n\t\tvar psrid = sessionStorage.getItem('psrid');\n\t\tif (psrid && dataLayer && 'event' in dataLayer && dataLayer.event == 'purchase') {\t\n\t\t\tvar itemsTitle = [];\n\t\t\tvar itemsPrice = [];\n\t\t\tvar itemsQuantity = [];\n\t\t\tvar itemsSku = [];\n\t\t\tvar itemsManufacturer = [];\n\t\t\tvar itemElements = dataLayer.items;\n\t\t\tfor (var i = 0; i < itemElements.length; i++) {\n\t\t\t\titemsTitle.push(itemElements[i].item_name);\n\t\t\t\titemsQuantity.push(itemElements[i].quantity);\n\t\t\t\titemsPrice.push(itemElements[i].price);\n\t\t\t\titemsSku.push(itemElements[i].item_id);\n\t\t\t\titemsManufacturer.push(itemElements[i].item_brand);\n\t\t\t}\n\t\t\tvar order = pswtb.purchaseTracking.createOrder();\n\t\t\torder.currencyCode = dataLayer.currency;\n\t\t\torder.purchaseTotal = dataLayer.value;\n\t\t\tvar itemsDetails = [];\n\t\t\tfor (var y = 0; y < itemsTitle.length; y++) {\n\t\t\t\titemsDetails.push({\n\t\t\t\t\t\"productName\": itemsTitle[y],\n\t\t\t\t\t\"quantity\": itemsQuantity[y],\n\t\t\t\t\t\"unitPrice\": itemsPrice[y] / itemsQuantity[y],\n\t\t\t\t\t\"manufacturer\": itemsManufacturer[y],\n\t\t\t\t\t\"sku\": itemsSku[y]\n\t\t\t\t});\n\t\t\t}\n\t\t\torder.details = itemsDetails;\n\t\t\torder.redirectToken = psrid;\n\t\t\torder.submit();\n\t\t}\n\t});\n}\n\nfunction initializeVWOOrderTracking() {\n\tbuffer['items'] = null;\n\tif (SitePreferences.VWO_ENABLED && SitePreferences.VWO_PURCHASE_TRACKING_ENABLED) {\n\t\tbuffer['vwoLoadedInterval'] = setInterval(triggerVWOOrderTracking, 100);\n\n\t\t$(document).on('DataLayer.OrderComplete', function (event, dataLayer) {\n\t\t\tvar items = [];\n\t\t\tvar paymentMethods = '';\n\t\t\tif (pageContext.PaymentMethods) {\n\t\t\t\tpaymentMethods = pageContext.PaymentMethods.join(' | ');\n\t\t\t}\n\t\t\t$('.productCardMetadata').each(function() {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar itemDataLayer;\n\t\t\t\ttry {\n\t\t\t\t\titemDataLayer = JSON.parse($this.attr('data-product-ga4-json'));\n\t\t\t\t} catch(exception) {}\n\t\t\t\tif (itemDataLayer) {\n\t\t\t\t\tvar revenue = itemDataLayer.price;\n\t\t\t\t\tvar price = revenue;\n\t\t\t\t\tif (itemDataLayer.discount) {\n\t\t\t\t\t\tprice += itemDataLayer.discount;\n\t\t\t\t\t}\n\t\t\t\t\titems.push({\n\t\t\t\t\t\t\"price\": price.toFixed(2),\n\t\t\t\t\t\t\"item\": itemDataLayer.item_id,\n\t\t\t\t\t\t\"paymentMethod\": paymentMethods,\n\t\t\t\t\t\t\"registeredUser\": Customer.registered,\n\t\t\t\t\t\t\"revenue\": revenue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (items && items.length > 0) {\n\t\t\t\tbuffer['items'] = items;\n\t\t\t\ttriggerVWOOrderTracking();\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction triggerVWOOrderTracking() {\n\tif (buffer['items'] && window.VWO && window.VWO.event && typeof window.VWO.event == 'function') {\n\t\tclearInterval(buffer['vwoLoadedInterval']);\n\t\tfor (var itemIndex = 0; itemIndex < buffer['items'].length; itemIndex++) {\n\t\t\tvar item = buffer['items'][itemIndex];\n\t\t\tVWO.event(\"purchase\", item);\n\t\t}\n\t}\n}\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter;\n\n\ttooltip.init({\n\t\titems: '.tooltip'\n\t});\n\ttriggerReactWebviewEvent();\n\tinitializePriceSpiderOrderTracking();\n\tinitializeVWOOrderTracking();\n}","'use strict';\n\nvar _ = require('lodash');\nvar ajax = require('../../ajax');\nvar dialog = require('../../dialog');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar minicart = require('../../minicart');\nvar page = require('../../page');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TPromise = require('promise');\nvar util = require('../../util');\n\nvar dataBuffer = {};\n\n/**\n * Wraps the dialog close functionality in a function so that we can hook into the transitionEnd event\n * to fire the close event on the dialog.\n * This allows for an animation to complete before the dialog is closed and removed from the dom\n */\n var closeAddToCartModal = function () {\n\t// save overaly for class additions\n\tvar $overlay = $('.add-to-cart-modal-wrapper').parent().find('.ui-widget-overlay');\n\t\n\t// hook into transition end\n\tif (pageContext.site === SiteConstants.SiteIds.BootBarnRspUS) {\n\t\tvar currentModal = $('#dialog-container');\n\t\tif (currentModal.dialog('isOpen')) {\n\t\t\tcurrentModal.dialog('close');\n\t\t}\n\t} else {\n\t\t$('.add-to-cart-modal-wrapper').one('transitionend webkitTransitionEnd oTransitionEnd', function (e) {\n\t\t\tvar currentModal = $(this).find('#dialog-container');\n\t\t\tif (currentModal.dialog('isOpen')) {\n\t\t\t\tcurrentModal.dialog('close');\n\t\t\t}\n\t\t});\n\t}\n\t\n\t$overlay.removeClass('show');\n\t$('.add-to-cart-modal-wrapper').removeClass('show');\n}\n\n/**\n * @description Make the AJAX request to add an item to cart\n * @param {Element} form The form element that contains the item quantity and ID data\n * @returns {Promise}\n */\nvar addItemToCart = function (form) {\n    var $form = $(form),\n        $qty = $form.find('input[name=\"Quantity\"]');\n    if ($qty.length === 0 || isNaN($qty.val()) || parseInt($qty.val(), 10) === 0) {\n        $qty.val('1');\n    }\n    return TPromise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.addProduct),\n        data: $form.serialize()\n    }));\n};\n\n/**\n * @description Handler to handle the add to cart event\n */\nvar addToCart = function(event, data) {\n    event.preventDefault();\n\tvar $html = $('html');\n\tvar $container = $('#wrapper');\n    var $form = $('.pdpForm');\n    var sizeSelected = $('div.product-variations .size.size-options li.selected');\n\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\n    if (!isSizeSelected) {\n    \tdialog.open({\n\t\t\thtml: 'Please select a size',\n\t\t\toptions: {\n\t\t\t\tdialogClass: 'dialog-alert',\n\t\t\t\tdraggable: false\n\t\t\t}\n\t\t});\n    \treturn false;\n    }\n\n    if (!$('div.product-variations .color.color-options li.selected').length) {\n    \tdialog.open({\n\t\t\thtml: 'Please select a color',\n\t\t\toptions: {\n\t\t\t\tdialogClass: 'dialog-alert',\n\t\t\t\tdraggable: false\n\t\t\t}\n\t\t});\n    \treturn false;\n    }\n\n    var isBopis = false;\n\tvar $bopisAddToCartOptions = $('.bopis-add-to-cart-options-container');\n\tvar $bopisAddToCartOption;\n\tif ($bopisAddToCartOptions.length > 0) {\n\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnRspUS) {\n\t\t\t$bopisAddToCartOptions.find('input[name=\"AddToCartOption\"]').prop('checked', false);\n\t\t\t$(event.currentTarget).closest('li').find('input[name=\"AddToCartOption\"]').prop('checked', true);\n\t\t\t$bopisAddToCartOptions = $('.bopis-add-to-cart-options-container');\n\t\t}\n\t\t$bopisAddToCartOption = $bopisAddToCartOptions.find('input[name=\"AddToCartOption\"]:checked');\n\t\tvar $bopisAddToCartLabel = $bopisAddToCartOption.closest('li');\n\t\tvar $bopisOptionalMessage = $bopisAddToCartLabel.find('.add-to-cart-optional-message');\n\t\tif ($bopisOptionalMessage.length > 0) {\n\t\t\tdataBuffer['OptionalMessage'] = $bopisOptionalMessage.first().html().trim();\n\t\t}\n\t}\n\n    if ($(event.currentTarget).hasClass('bopis') || (data && data.bopis)) {\n    \tisBopis = true;\n    } else if ($bopisAddToCartOptions.length > 0) {\n\t\tvar bopisShippingOption = $bopisAddToCartOption.val();\n\t\tif (bopisShippingOption == 'delivery') {\n\t\t\t$(document).trigger('Bopis.LocalDelivery.Display', { OptionalMessage: dataBuffer['OptionalMessage'] });\n\t\t\treturn false;\n\t\t} else if (bopisShippingOption == 'shiptostorepickup') {\n\t\t\tisBopis = true;\n\t\t\tdata = data || {};\n\t\t\tdata.bopisStore = $bopisAddToCartOptions.find('.selected-store[store-id]').attr('store-id');\n\t\t\tdata.shippingOption = bopisShippingOption;\n\t\t} else if (bopisShippingOption == 'pickup') {\n\t\t\tisBopis = true;\n\t\t\tvar storeData;\n\t\t\tvar $storeData = $bopisAddToCartOptions.find('.selected-store[store-data]');\n\t\t\tif ($storeData.length > 0) {\n\t\t\t\tstoreData = JSON.parse($storeData.attr('store-data'))\n\t\t\t\tdata = data || {};\n\t\t\t\tdata.bopisStore = storeData.location.code;\n\t\t\t\tdata.quantityAvailable = storeData.detail.quantity;\n\t\t\t\tdata.shippingOption = bopisShippingOption;\n\t\t\t}\n\t\t}\n\t}\n\n    var $bopisStore;\n    if (isBopis) {\n    \t$bopisStore = $('input[name=\"Bopis_StoreSearch_StoreId\"]:checked');\n\t\t$('.product-add-to-cart input[name=\"bopis_store\"]').val(data.bopisStore ? data.bopisStore : $bopisStore.val());\n    \t$('.product-add-to-cart input[name=\"bopis_quantity_available\"]').val(data.quantityAvailable != undefined ? data.quantityAvailable : $bopisStore.attr('quantity-available'));\n    \t$('.product-add-to-cart input[name=\"bopis_shipping_option\"]').val(data.shippingOption ? data.shippingOption : '');\n    \t$('.product-add-to-cart input[name=\"bopis_delivery_address\"]').val(data.deliveryAddress ? data.deliveryAddress : '');\n    \t$('.product-add-to-cart input[name=\"bopis_delivery_note\"]').val(data.deliveryNote ? data.deliveryNote : '');\n    \t$('.product-add-to-cart input[name=\"bopis_delivery_gift_message\"]').val(data.giftMessage ? data.giftMessage : '');\n    \t$('.option-dropdown select[name*=\"_Bopis\"]').val('Yes');\n    } else {\n    \t$('.product-add-to-cart input[name=\"bopis_store\"]').val('');\n    \t$('.product-add-to-cart input[name=\"bopis_quantity_available\"]').val('');\n    \t$('.product-add-to-cart input[name=\"bopis_shipping_option\"]').val('');\n    \t$('.product-add-to-cart input[name=\"bopis_delivery_address\"]').val('');\n    \t$('.option-dropdown select[name*=\"_Bopis\"]').val('No');\n\t}\n\n\t$('.product-add-to-cart input[name=\"channel\"]').val(data && data.channel ? data.channel : '');\n\tif (data && 'csrf_token' in data && data.csrf_token) {\n\t\t$('#csrftoken').val(data.csrf_token);\n\t}\n    \n    if (sizeSelected.hasClass(\"tempselection\")) {\n    \tsizeSelected.addClass('enterSelected');\n    \tsizeSelected.trigger('click');\n    \tsizeSelected.find('.swatchanchor').trigger('click');\n    \tsetTimeout( function(){$(\"#add-to-cart\").click()}, 100 );\n    \treturn false;\n    }\n\n    if (typeof dataLayer !== 'undefined') {\n\t\tvar qty = $('.pt_product-details .pdpForm .product-add-to-cart select[id=Quantity]').val();\n\t\tvar variationAttr = $('.product-variations').data('attributes');\n\t\tvar sizeAttrValue = variationAttr.size.displayValue;\n\t\tif (sizeAttrValue == '' || sizeAttrValue == null ) {\n\t\t\tif (sizeSelected.hasClass(\"tempselection\") && sizeSelected.find('a.swatchanchor').data() != null ) {\n\t\t\t\tsizeSelected.addClass('enterSelected');\n\t\t\t\tvar sizeObjRef = sizeSelected.find('a.swatchanchor').data();\n\t\t\t\tsizeAttrValue = sizeObjRef.sizeName;\n\t\t\t\tsizeSelected.find('a.swatchanchor').trigger('click');\n\t\t\t}\n\t\t}\n\n\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('AddToCart');\n\n\t\tfor (var i=0; i < dataLayer.length; i++) {\n\t\t\tif (dataLayer[i].event == 'pdpDisplay') {\n\t\t\t\tvar selectedItem = dataLayer[i].ecommerce.detail.products[0];\n\t\t\t\tvar itemPrice = (selectedItem.silhouette == 'Gift Card') ?  parseInt((variationAttr.size.value).replace('$','')) : selectedItem.price;\n\t\t\t\tvar skuID = $('#pid').val();\n\t\t\t\tvar image = $('.product-primary-image [class*=\"-slide\"] .primary-image.first').find('a').attr('href');\n\t\t\t\tif (!image || image == undefined || image == null) {\n\t\t\t\t\timage = $('.product-primary-image [class*=\"-slide\"] .primary-image.first').find('img').attr('src');\n\t\t\t\t}\n\n\t\t\t\tif (SitePreferences.CORDIAL_ENABLED) {\t\t\t\t\n\t\t\t\t\tvar cart_data = [{\n\t\t\t\t\t    'productID': selectedItem.id,\n\t\t\t\t\t    'sku': skuID,\n\t\t\t\t\t    'category': (selectedItem.category).replace(/\\\\/g, \"\"),\n\t\t\t\t\t    'name': (selectedItem.name).replace(/\\\\/g, \"\"),\n\t\t\t\t\t    'qty': qty, \n\t\t\t\t\t    'itemPrice': itemPrice,\n\t\t\t\t\t    'image': image,\n\t\t\t\t\t    'url':$(location).attr(\"href\").split(\"?utm\")[0].split(\"#utm\")[0].split(\"&utm\")[0],\n\t\t\t\t\t    'attr': {\n\t\t\t\t\t        'manufacturer': selectedItem.brand,\n\t\t\t\t\t    \t'color': variationAttr.color.displayValue,\n\t\t\t\t\t        'size': variationAttr.size.displayValue\n\t\t\t\t\t    }\n\t\t\t\t\t}];\n\t\n\t\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\t\tcrdl([\n\t\t\t\t\t\t\t['cart', 'update'],\n\t\t\t\t\t\t\t['cartitem', 'add' , cart_data], \n\t\t\t\t\t\t\t['event', 'cart']\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar dateTime = Math.floor(Date.now() / 1000);\n\t\t\t\tvar eventID = 'addtocart-' + selectedItem.id + '-' + dateTime;\n\t\t\t\t\n\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS && SitePreferences.PINTEREST_ENABLED) {\n\t\t\t\t\tpintrk('track', 'addtocart', {\n\t\t\t\t\t\tevent_id: eventID,\n\t\t\t\t\t\tvalue: itemPrice * qty,\n\t\t\t\t\t\torder_quantity: qty,\n\t\t\t\t\t\tcurrency: $('meta[itemprop=\"priceCurrency\"]').attr('content'),\n\t\t\t\t\t\tline_items: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tproduct_name: (selectedItem.name).replace(/\\\\/g, \"\"),\n\t\t\t\t\t\t\t\tproduct_id: selectedItem.id,\n\t\t\t\t\t\t\t\tproduct_category: (selectedItem.category).replace(/\\\\/g, \"\"),\n\t\t\t\t\t\t\t\tproduct_variant_id: skuID,\n\t\t\t\t\t\t\t\tproduct_price: itemPrice,\n\t\t\t\t\t\t\t\tproduct_quantity: qty,\n\t\t\t\t\t\t\t\tproduct_brand: selectedItem.brand\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n    }\n\n    addItemToCart($form).then(function (response) {\n    \t$.ajax({url : Urls.cartItemCount, method: 'POST', dataType: 'json', success : function(data) {\n\t\t\tif (data && data.ProductCount != undefined) {\n    \t\t\t$('.btn-minicart span').html(Math.round(data.ProductCount));\n\t\t\t}\n    \t}});\n        var $uuid = $form.find('input[name=\"uuid\"]');\n        if ($uuid.length > 0 && $uuid.val().length > 0) {\n            page.refresh();\n        } else if(SitePreferences.REDIRECT_TO_CART && (!pageContext.options || pageContext.options.StoreUIVersion != '2024Redesign')){\n    \t\tvar redirectUrl = (SitePreferences.HIDE_BASKET) ? Urls.onePage : Urls.cartShow;\n    \t\twindow.location.href = redirectUrl;\n    \t} else {\n\t\t\tif (SitePreferences.ADD_TO_CART_MODAL || (pageContext.options && pageContext.options.StoreUIVersion == '2024Redesign')) {\n\t\t\t\tvar qtyAdded = $('.pt_product-details .pdpForm .product-add-to-cart select[id=Quantity]').val();\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: Urls.addToCartModalDisplay,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tstoreuiversion: pageContext && pageContext.options && pageContext.options.StoreUIVersion ? pageContext.options.StoreUIVersion : null,\n\t\t\t\t\t\tshippingoption: bopisShippingOption\n\t\t\t\t\t},\n\t\t\t\t\tdataType: 'html',\n\t\t\t\t\tsuccess: function(modalContent) {\n\t\t\t\t\t\tif (modalContent.length > 0) {\n\t\t\t\t\t\t\tvar $modalContent = $(modalContent);\n\t\t\t\t\t\t\tvar $recsContent;\n\t\t\t\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t\t\t\t\t\t\t$recsContent = $('#best_selling_products.accordion.product-recommendations').removeClass('accordion');\n\t\t\t\t\t\t\t} else if (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\t\t\t\t\t$recsContent = $('.recomm-prod-pdp-a2c-slot .accordion.product-recommendations').removeClass('accordion');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$recsContent = $('.main .accordion.product-recommendations').removeClass('accordion');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$recsContent.find('.accordion-head').removeClass('accordion-head');\n\t\t\t\t\t\t\t$recsContent.find('.accordion-body').removeClass('accordion-body');\n\n\t\t\t\t\t\t\tif ($recsContent.find('.slick-list').length > 0) {\n\t\t\t\t\t\t\t\tvar $recommendationsContentHtml = $($recsContent[0].outerHTML);\n\t\t\t\t\t\t\t\tvar $recommendationsSlides = $recommendationsContentHtml.find('.slide');\n\t\t\t\t\t\t\t\tvar recommendationsSlidesHtml = '';\n\t\t\t\t\t\t\t\t$recommendationsSlides.each(function(index, element) {\n\t\t\t\t\t\t\t\t\trecommendationsSlidesHtml += $(this)[0].outerHTML;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t$recommendationsContentHtml.find('.slides').html(recommendationsSlidesHtml);\n\t\t\t\t\t\t\t\t$recommendationsContentHtml.find('.slides').removeClass('slick-initialized slick-slider');\n\t\t\t\t\t\t\t\t$recommendationsContentHtml.find('.slide').removeClass('slick-slide slick-current slick-active slick-cloned').css('width', '');\n\t\t\t\t\t\t\t\t$modalContent.find('.product-recommendations-container').html($recommendationsContentHtml);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (dataBuffer['OptionalMessage']) {\n\t\t\t\t\t\t\t\tvar optionalMessageHtml = '<div class=\"add-to-cart-modal-optional-message\">' + dataBuffer['OptionalMessage'] + '</div>';\n\t\t\t\t\t\t\t\t$modalContent.find('.added-message').append(optionalMessageHtml);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$modalContent.attr('bopis-shipping-option', bopisShippingOption);\n\n\t\t\t\t\t\t\tvar scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n\n\t\t\t\t\t\t\tdialog.open({\n\t\t\t\t\t\t\t\thtml: $modalContent,\n\t\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\t\tdialogClass: 'add-to-cart-modal',\n\t\t\t\t\t\t\t\t\tdraggable: false,\n\t\t\t\t\t\t\t\t\tresizable: false,\n\t\t\t\t\t\t\t\t\twidth: 1090,\n\t\t\t\t\t\t\t\t\topen: function(event, ui) {\n\t\t\t\t\t\t\t\t\t\tdataBuffer['wrapperScrollTop'] = scrollTop;\n    \t\t\t\t\t\t\t\t\tdataBuffer['wrapperMarginTop'] = $container.css('margin-top');\n\t\t\t\t\t\t\t\t\t\t$container.attr('buffer-scrollTop', scrollTop);\n\n    \t\t\t\t\t\t\t\t\t$container.css('margin-top', parseFloat($container.css('margin-top')) - scrollTop);\n    \t\t\t\t\t\t\t\t\tdocument.body.scrollTop = document.documentElement.scrollTop = 0;\n    \t\t\t\t\t\t\t\t\t$html.addClass('scroll-lock');\n\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal').wrap('<div class=\"add-to-cart-modal-wrapper\"></div>');\n\n\t\t\t\t\t\t\t\t\t\t// add wrapper to close button \n\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal-wrapper').off('click.Dialog.CloseButtons').on('click.Dialog.CloseButtons', '.ui-dialog-titlebar-close, .btn.continue-shopping', function(event) {\n\t\t\t\t\t\t\t\t\t\t\tcloseAddToCartModal();\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t// add 'show' class to overlay for nice animate in\n\t\t\t\t\t\t\t\t\t\tvar $overlay = $('.add-to-cart-modal-wrapper').parent().find('.ui-widget-overlay');\n\t\t\t\t\t\t\t\t\t\t$overlay.addClass('add-to-cart-overlay');\n\t\t\t\t\t\t\t\t\t\t$overlay.addClass('show');\n\n\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal-wrapper').off('click.Dialog.Close').on('click.Dialog.Close', function(event) {\n\t\t\t\t\t\t\t\t\t\t\t// only call this block if the ui-widget background is clicked\n\t\t\t\t\t\t\t\t\t\t\tif ($(event.target).closest('.add-to-cart-modal').length <= 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tcloseAddToCartModal();\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\tif (parseFloat($('.add-to-cart-modal').css('top')) < 0) {\n\t\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal').css('top', '0');\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// move title from main content to top of the modal\n\t\t\t\t\t\t\t\t\t\tvar $addMessage = $('.add-to-cart-modal-content .main-content .added-message');\n\t\t\t\t\t\t\t\t\t\tif ($addMessage.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal-content').prepend($addMessage);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\t\t\t\t\t\t\t\tvar fulfillmentType = $('.bopis-add-to-cart-options-container').find('input[name=\"AddToCartOption\"]:checked').val();\n\t\t\t\t\t\t\t\t\t\t\tvar isBopis = fulfillmentType && (fulfillmentType == 'shiptostorepickup' || fulfillmentType == 'pickup');\n\t\t\t\t\t\t\t\t\t\t\tvar bopisStoreName = '';\n\t\t\t\t\t\t\t\t\t\t\tvar bopisStoreAddress = '';\n\t\t\t\t\t\t\t\t\t\t\tif (isBopis) {\n\t\t\t\t\t\t\t\t\t\t\t\tbopisStoreName = $('.bopis-add-to-cart-options-store-selector .selected-store').attr('store-name');\n\t\t\t\t\t\t\t\t\t\t\t\tbopisStoreAddress = $('.bopis-add-to-cart-options-store-selector .selected-store').attr('store-address');\n\t\t\t\t\t\t\t\t\t\t\t\tif (bopisStoreAddress && bopisStoreAddress.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$('.modal-mini-cart-store-message-container').removeClass('d-none');\n\t\t\t\t\t\t\t\t\t\t\t\t\t$('.modal-mini-cart-store-message-container').find('.modal-mini-cart-store-details').html('<strong>' +bopisStoreName+ '</strong><br />' +bopisStoreAddress);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tvar $containers = $('.add-to-cart-modal').find('.accordion, .section-offers');\n\t\t\t\t\t\t\t\t\t\tif ($containers.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t$containers.each(function() {\n\t\t\t\t\t\t\t\t\t\t\t\tvar $container = $(this);\n\t\t\t\t\t\t\t\t\t\t\t\tif ($container.find('.product-tile').length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar $containerHeader = $container.find('.accordion-head h5, .section-head h2').first();\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar $containerHeaderCheck = $containerHeader.find('span');\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ($containerHeaderCheck.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$containerHeader = $containerHeaderCheck;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ($containerHeader.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar dataObject = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpromotion_id: 'addtocartmodal',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpromotion_name: 'Add to Cart Modal'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ViewPromotion', dataObject, { Container: $container });\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal-wrapper').addClass('show');\n\t\t\t\t\t\t            },\n\t\t\t\t\t\t            close: function(event, ui) {\n\t\t\t\t\t\t            \tvar $html = $('html');\n\t\t\t\t\t\t\t\t    \tvar $container = $('#wrapper');\n\n\t\t\t\t\t\t\t\t    \t$html.removeClass('scroll-lock');\n\n\t\t\t\t\t\t            \tif (dataBuffer['wrapperScrollTop'] > 0) {\n\t\t\t\t\t\t\t    \t\t\tdocument.body.scrollTop = document.documentElement.scrollTop = dataBuffer['wrapperScrollTop'];\n\t\t\t\t\t\t\t    \t\t}\n\t\t\t\t\t\t\t\t\t\t$container.css('margin-top', parseFloat(dataBuffer['wrapperMarginTop']));\n\n\t\t\t\t\t\t\t\t\t\t$('.add-to-cart-modal').unwrap();\n\t\t\t\t\t\t            }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t$('.add-to-cart-modal .added-message .count').text('Item');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif ( $('.banner-cart-holder .btn-minicart').length > 0 ) {\n\t\t\t\t$.ajax({\n\t\t\t\t\turl : Urls.cartMiniCart,\n\t\t\t\t\tdata : {desktop: '1'},\n\t\t\t\t\tdataType: 'html',\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t$('.banner-cart-holder .btn-minicart').remove();\n\t\t\t\t\t\t$('.banner-cart-holder').append(data);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$.ajax({\n\t\t\t\t\turl : Urls.cartMiniCart,\n\t\t\t\t\tdataType: 'html',\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\tvar parentMiniCart = $('.top-banner-inner-links #mini-cart');\n\t\t\t\t\t\tif (parentMiniCart.length > 0) {\n\t\t\t\t\t\t\t$('.top-banner-inner-links #mini-cart a.mini-cart-link').remove();\n\t\t\t\t\t\t\tparentMiniCart.append(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t// do not close quickview if adding individual item that is part of product set\n\t\t\t// @TODO should notify the user some other way that the add action has completed successfully\n\t\t\tif (!$(this).hasClass('sub-product-item')) {\n\t\t\t\tdialog.close();\n\t\t\t}\n\t\t\tif(SitePreferences.ADD_TO_CART_MODAL != true){\n\t\t\t\tminicart.show(response);\n\t\t\t}\n        }\n    }.bind(this));\n\n};\n\n/**\n * @description Handler to handle the add all items to cart event\n */\nvar addAllToCart = function (e) {\n    e.preventDefault();\n    var $productForms = $('#product-set-list').find('form').toArray();\n    TPromise.all(_.map($productForms, addItemToCart))\n        .then(function (responses) {\n            dialog.close();\n            // show the final response only, which would include all the other items\n            minicart.show(responses[responses.length - 1]);\n        });\n};\n\n/**\n * @function\n * @description Binds the click event to a given target for the add-to-cart handling\n */\nmodule.exports = function () {\n    $('.add-to-cart[disabled]').attr('title', $('.availability-msg').text());\n    $('.product-detail').on('click', '.add-to-cart:not([disabled]):not([loading])', addToCart);\n\t$(document).on('ProductDetailPage.Bopis.AddItemToCart', addItemToCart);\n    $(document).on('ProductDetailPage.Bopis.AddToCart', addToCart);\n\t$('#add-all-to-cart').on('click', addAllToCart);\n};\n","'use strict';\n\nvar ajax =  require('../../ajax'),\n    util = require('../../util');\n\nvar updateContainer = function (data) {\n    var $availabilityMsg = $('#pdpMain .availability .availability-msg');\n    var message; // this should be lexically scoped, when `let` is supported (ES6)\n    if (!data) {\n        $availabilityMsg.html(Resources.ITEM_STATUS_NOTAVAILABLE);\n        return;\n    }\n    $availabilityMsg.empty();\n    // Look through levels ... if msg is not empty, then create span el\n    if (data.levels.IN_STOCK > 0) {\n        if (data.levels.PREORDER === 0 && data.levels.BACKORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n            // Just in stock\n            message = Resources.IN_STOCK;\n        } else {\n            // In stock with conditions ...\n            message = data.inStockMsg;\n        }\n        $availabilityMsg.append('<p class=\"in-stock-msg\">' + message + '</p>');\n    }\n    if (data.levels.PREORDER > 0) {\n        if (data.levels.IN_STOCK === 0 && data.levels.BACKORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n            message = Resources.PREORDER;\n        } else {\n            message = data.preOrderMsg;\n        }\n        $availabilityMsg.append('<p class=\"preorder-msg\">' + message + '</p>');\n    }\n    if (data.levels.BACKORDER > 0) {\n        if (data.levels.IN_STOCK === 0 && data.levels.PREORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n            message = Resources.BACKORDER;\n        } else {\n            message = data.backOrderMsg;\n        }\n        $availabilityMsg.append('<p class=\"backorder-msg\">' + message + '</p>');\n    }\n    if (data.inStockDate !== '') {\n        $availabilityMsg.append('<p class=\"in-stock-date-msg\">' + String.format(Resources.IN_STOCK_DATE, data.inStockDate) + '</p>');\n    }\n    if (data.levels.NOT_AVAILABLE > 0) {\n        if (data.levels.PREORDER === 0 && data.levels.BACKORDER === 0 && data.levels.IN_STOCK === 0) {\n            message = Resources.NOT_AVAILABLE;\n        } else {\n            message = Resources.REMAIN_NOT_AVAILABLE;\n        }\n        $availabilityMsg.append('<p class=\"not-available-msg\">' + message + '</p>');\n    }\n};\n\nvar getAvailability = function () {\n    ajax.getJson({\n        url: util.appendParamsToUrl(Urls.getAvailability, {\n            pid: $('#pid').val(),\n            Quantity: $(this).val()\n        }),\n        //callback: updateContainer\n    });\n};\n\nmodule.exports = function () {\n    $('#pdpMain').on('change', '.pdpForm input[name=\"Quantity\"]', getAvailability);\n};\n","'use strict';\nvar dialog = require('../../dialog');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar util = require('../../util');\n\nvar zoomMediaQuery = matchMedia('(min-width: 960px)');\n\n/**\n * @description Enables the zoom viewer on the product detail page\n * @param zmq {Media Query List}\n */\nvar loadZoom = function (zmq) {\n    var $imgZoom = $('#pdpMain .main-image'),\n        hiresUrl;\n    if (!zmq) {\n        zmq = zoomMediaQuery;\n    }\n    if ($imgZoom.length === 0 || dialog.isActive() || util.isMobile() || !zoomMediaQuery.matches) {\n        // remove zoom\n        $imgZoom.trigger('zoom.destroy');\n        return;\n    }\n    hiresUrl = $imgZoom.attr('href');\n\n    if (hiresUrl && hiresUrl !== 'null' && hiresUrl.indexOf('noimagelarge') === -1 && zoomMediaQuery.matches) {\n        $imgZoom.zoom({\n            url: hiresUrl\n        });\n    }\n};\n\nzoomMediaQuery.addListener(loadZoom);\n\n/**\n * @description Sets the main image attributes and the href for the surrounding <a> tag\n * @param {Object} atts Object with url, alt, title and hires properties\n */\nvar setMainImage = function (atts) {\n    $('#pdpMain .primary-image').attr({\n        src: atts.url,\n        alt: atts.alt,\n        title: atts.title\n    });\n    if (!dialog.isActive() && !util.isMobile()) {\n        $('#pdpMain .main-image').attr('href', atts.hires);\n    }\n    loadZoom();\n};\n\n/**\n * @description Replaces the images in the image container, for eg. when a different color was clicked.\n */\n\nvar replaceImages = function () {\n\t\n    var $newImages = $('#update-images'),\n        $win = $(window),\n        $imageContainer,\n        $header,\n        $promosClone,\n        $promosCloneMobile,\n        newImage = new Image();\n    \n    if ($win.width() <= 1024) {\n    \t$header =  $('#pdpMain .product-image-container').find('header').clone();\n    }\n    if ($newImages.length === 0) { return; }\n\n    // product container classes to handle styles while image is loading\n    $('#pdpMain .product-image-container').addClass('loading-image');\n    newImage.src = $newImages.find('.product-primary-image [class*=\"slide\"]').first().find('img').attr('src');\n    newImage.onload = function() {\n        $('#pdpMain .product-image-container').removeClass('loading-image');\n    }\n    \n    var attachPromosMobile = function() {\n        if (pageContext.site === SiteConstants.SiteIds.SheplersUS || pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n            var $imageContainerMobile = $('#pdpMain .product-image-container');\n        } else {\n            var $imageContainerMobile = $('#pdpMain .product-image-container-mobile');\n        }\n        var $promoMessagesMobile = $('#pdpMain .product-image-container-mobile .promo-messages'),\n            $promosCloneMobile = $promoMessagesMobile.find('.promo-messages').clone();\n        \n        if ($promoMessagesMobile.is(':empty') && $promosCloneMobile.length > 0) {\n            $imageContainerMobile.html($newImages.html());\n            $(\"<div class='promo-messages'></div>\").prependTo($imageContainerMobile);\n            $promosCloneMobile.prependTo($promoMessagesMobile);\n        }\n        else {\n            $imageContainerMobile.html($newImages.html());\n            $promosCloneMobile.prependTo($imageContainerMobile);\n        }\n    };\n\n    var attachPromosDesktop = function() {\n        var $imageContainer = $('#pdpMain .product-image-container'),\n            $promoMessages = $('#pdpMain .product-image-container .promo-messages'),\n            $promosClone = $promoMessages.clone();\n        \n        //window.console.log(\"$promoMessages: \",$promoMessages.length, \" $promosClone.length: \", $promosClone.length);\n        \n        if ($promoMessages.is(':empty') && $promosClone.length > 0) {\n            $imageContainer.html($newImages.html());\n            $(\"<div class='promo-messages'></div>\").prependTo($imageContainer);\n            $promosClone.prependTo($promoMessages);\n        }\n        else {\n            $imageContainer.html($newImages.html());\n            $promosClone.prependTo($imageContainer);\n        }\n    };\n\n    if ($win.width() <= 767 ) {\n        attachPromosMobile();\n    }\n    else {\n        attachPromosDesktop();\n    }\n    \n    $newImages.remove();\n    loadZoom();\n};\n\n/* @module image\n * @description this module handles the primary image viewer on PDP\n **/\n\n/**\n * @description by default, this function sets up zoom and event handler for thumbnail click\n **/\nmodule.exports = function () {\n    if (dialog.isActive() || util.isMobile()) {\n        $('#pdpMain .main-image').removeAttr('href');\n    }\n    loadZoom();\n    // handle product thumbnail click event\n    $('#pdpMain').on('click', '.productthumbnail', function () {\n        // switch indicator\n        $(this).closest('.product-thumbnails').find('.thumb.selected').removeClass('selected');\n        $(this).closest('.thumb').addClass('selected');\n\n        setMainImage($(this).data('lgimg'));\n    });\n};\nmodule.exports.loadZoom = loadZoom;\nmodule.exports.setMainImage = setMainImage;\nmodule.exports.replaceImages = replaceImages;\n","'use strict';\n\nvar dialog = require('../../dialog');\nvar productStoreInventory = require('../../storeinventory/product');\nvar tooltip = require('../../tooltip');\nvar util = require('../../util');\nvar addToCart = require('./addToCart');\nvar availability = require('./availability');\nvar image = require('./image');\nvar video = require('./video');\nvar productSet = require('./productSet');\nvar variant = require('./variant');\nvar requestGift = require('./requestGift');\nvar recaptcha = require('../../components/Recaptcha');\nvar recentlyViewedProducts = require('../../components/RecentlyViewedProducts');\nvar relevantProductRecommendations = require('../../components/RelevantProductRecommendations');\nvar sameDayShippingCountdown = require('../../components/SameDayShippingCountdown');\nvar ShopPay = require('../../../../../int_shoppay_sfra/cartridge/client/default/js/cart/initShopPayCart');\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar options = {};\nvar loaded = {};\nvar dataBuffer = {};\n\n/**\n * @description Initialize product detail page with reviews, recommendation and product navigation.\n */\nfunction initializeDom(options) {\n\ttooltip.init();\n\n\tvar $sameDayShippingCountdownContainer = $('.same-day-shipping-countdown');\n\tif ($sameDayShippingCountdownContainer.length > 0 && (!options || options.Channel != 'BootBarnExpress')) {\n\t\tsameDayShippingCountdown.initialize($sameDayShippingCountdownContainer, options.SameDayShipping);\n\t}\n\n\tif (pageContext.site == SiteConstants.SiteIds.BootBarnUS && window.innerWidth > 768) {\n\t\t$(document).find('.accordion-head').addClass('active');\n\t\t$(document).find('.accordion-body').css('display', 'block');\n\t}\n}\n\n/**\n * @description Initialize event handlers on product detail page\n */\nfunction initializeEvents(options) {\n    var $pdpMain = $('#pdpMain');\n\n    addToCart();\n    availability();\n    image();\n    video();\n    productSet();\n    requestGift({ Recaptcha: options.Recaptcha });\n\n    if (SitePreferences.STORE_PICKUP) {\n        productStoreInventory.init();\n    }\n\n\t$(document).on('click', '.product-swatches-accordion-button', function () {\n        var $accordion = $(this).closest('.accordion');\n\n        if ($accordion.length > 0) {\n            $accordion.toggleClass('active');\n        }\n    });\n\n    // Add to Wishlist and Add to Gift Registry links behaviors\n    $pdpMain.on('click', '[data-action=\"gift-registry\"]', function () {\n        var data = util.getQueryStringParams($('.pdpForm').serialize());\n        if (data.cartAction) {\n            delete data.cartAction;\n        }\n        var url = util.appendParamsToUrl(this.href, data);\n        this.setAttribute('href', url);\n    });\n\n    // product options\n    $pdpMain.on('change', '.product-options select', function () {\n        var salesPrice = $pdpMain.find('.product-add-to-cart .price-sales');\n        var selectedItem = $(this).children().filter(':selected').first();\n        salesPrice.text(selectedItem.data('combined'));\n    });\n\n    // prevent default behavior of thumbnail link and add this Button\n    $pdpMain.on('click', '.thumbnail-link, .unselectable a', function (e) {\n        e.preventDefault();\n    });\n\n    $pdpMain.on('click', 'a.size-chart-link', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href')\n        });\n    });\n\n    // Technology Features Tooltip\n    // $('.list-product-info figure img').each(function() {\n    // \tvar $img = $(this),\n    // \t\t$target = $img.parents('li').first().find('.tooltip-content img');\n\n    // \t$target.attr(\"src\", $img.data('hover')).attr(\"alt\", $img.attr(\"alt\")).attr(\"width\", \"236px\");\n    // });\n\n    // $('.list-product-info').tooltip({\n    //     items: 'li',\n    //     tooltipClass: 'techfeature-tooltip',\n    //     track: true,\n    //     content: function () {\n    //         return $(this).find('.tooltip-content').html();\n    //     }\n    // });\n\n\n\t$(document).on('click','.searchagain-btn',function() {\n\t\t$('#dialog-container .findStore-result').hide();\n\t\t$('#dialog-container .ui-dialog-footer').show();\n\t\t$('.ui-dialog').css({'height' : '230px !important','top':'260px !important'});\n\t});\n\n\t$(document).on('click','.find-store-btn',function() {\n\t\tdialog.open({\n\t\t\thtml:($('.findStoreDialog').html()).replace(/select-holder/g,''),\n\t\t\tcallback: function() {\n\t\t\t\t$(document).on('click','.findstore-formContainer .findStore-btn',function() {\n\t\t\t\t\tvar zipcode    = $('#dialog-container input.zipcode').val(),\n\t\t\t\t\t\tradius     = $('#dialog-container select.radius').val(),\n\t\t\t\t\t\tpostalcode = $('#dialog-container .postalcode select').val(),\n\t\t\t\t\t\tstatecode = $('#dialog-container .statecode select').val(),\n\t\t\t\t\t\tpid        = $('#dialog-container #pid').val(),\n\t\t\t\t\t\tvalues \t   = {\n\t\t\t\t\t\t\t\t\t\tpid : pid,\n\t\t\t\t\t\t\t\t\t\tzipCode : zipcode,\n\t\t\t\t\t\t\t\t\t\tradius : radius,\n\t\t\t\t\t\t\t\t\t\tstatecode : statecode,\n\t\t\t\t\t\t\t\t\t\tpostalcode : postalcode\n\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\turl: Urls.storeavailability,\n\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\tdata: values ,\n\t\t\t\t\t\tsuccess: function (response) {\n\t\t\t\t\t\t\t$('#dialog-container .findStore-result').show();\n\t\t\t\t\t\t\t$('#dialog-container .ui-dialog-footer').hide();\n\t\t\t\t\t\t\t$('#dialog-container .findStore-result').html(response).text();\n\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror: function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t\t\t\tconsole.log(textStatus, errorThrown);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\toptions: {\n\t\t\t\ttitle: Resources.FINDSTORE_TITLE\n\t\t\t},\n\t\t});\n\t\treturn false;\n\t});\n\n\t$(document).off('RecentlyViewedProducts.Done').on('RecentlyViewedProducts.Done', function(event) {\n\t\tloaded.RecentlyViewedProducts = true;\n\t\taddPromotionDataLayers();\n\t});\n\n\t$(document).off('EinsteinProductRecommendations.Done').on('EinsteinProductRecommendations.Done', function(event) {\n\t\tloaded.EinsteinProductRecommendations = true;\n\t\taddPromotionDataLayers();\n\t});\n\n\t$(document).off('RelevantProductRecommendations.Done').on('RelevantProductRecommendations.Done', function(event) {\n\t\tloaded.RelevantProductRecommendations += 1;\n\t\taddPromotionDataLayers();\n\t});\n}\n\nfunction addPromotionDataLayers() {\n\tif (loaded.RecentlyViewedProducts && loaded.EinsteinProductRecommendations && loaded.RelevantProductRecommendations == dataBuffer['RelevantProductRecommendationsCount']) {\n\t\t$(document).trigger('GoogleTagManager.AddPromotionDataLayers');\n\t}\n}\n\nvar product = {\n    initializeEvents: initializeEvents,\n    init: function (optionsParameter) {\n    \toptions = optionsParameter;\n\t\tloaded = {\n\t\t\tRecentlyViewedProducts: false,\n\t\t\tEinsteinProductRecommendations: false,\n\t\t\tRelevantProductRecommendations: 0\n\t\t};\n\t\tdataBuffer = {\n\t\t\tRelevantProductRecommendationsCount: 0\n\t\t};\n\n    \tif (options && options.Recaptcha && options.Recaptcha.EnabledForMerryMail) {\n        \trecaptcha.initialize();\n    \t}\n\n\t\tif (options && options.RecentlyViewedProducts) {\n    \t\trecentlyViewedProducts.initialize(options.RecentlyViewedProducts);\n    \t} else {\n\t\t\tloaded.RecentlyViewedProducts = true;\n\t\t}\n\n\t\tif (!options || !options.EinsteinProductRecommendations) {\n\t\t\tloaded.EinsteinProductRecommendations = true;\n\t\t}\n\n\t\tif (options && options.RelevantProductRecommendations) {\n\t\t\tdataBuffer['RelevantProductRecommendationsCount'] = options.RelevantProductRecommendations.Containers.length;\n\t\t\trelevantProductRecommendations.initialize(options.RelevantProductRecommendations);\n\t\t}\n\n\t\tvariant.initialize(options);\n\n\t\tinitializeDom(options);\n\t\tinitializeEvents(options);\n\t}\n};\n\nmodule.exports = product;\n","'use strict';\n\nvar ajax = require('../../ajax'),\n    tooltip = require('../../tooltip'),\n    util = require('../../util');\n\nmodule.exports = function () {\n    var $addToCart = $('#add-to-cart'),\n        $addAllToCart = $('#add-all-to-cart'),\n        $productSetList = $('#product-set-list');\n\n    var updateAddToCartButtons = function () {\n        if ($productSetList.find('.add-to-cart[disabled]').length > 0) {\n            $addAllToCart.attr('disabled', 'disabled');\n            // product set does not have an add-to-cart button, but product bundle does\n            $addToCart.attr('disabled', 'disabled');\n        } else {\n            $addAllToCart.removeAttr('disabled');\n            $addToCart.removeAttr('disabled');\n        }\n    };\n\n    if ($productSetList.length > 0) {\n        updateAddToCartButtons();\n    }\n    // click on swatch for product set\n    $productSetList.on('click', '.product-set-item .swatchanchor', function (e) {\n        e.preventDefault();\n        if ($(this).parents('li').hasClass('unselectable')) { return; }\n        var url = Urls.getSetItem + this.search;\n        var $container = $(this).closest('.product-set-item');\n        var qty = $container.find('form input[name=\"Quantity\"]').first().val();\n\n        ajax.load({\n            url: util.appendParamToURL(url, 'Quantity', isNaN(qty) ? '1' : qty),\n            target: $container,\n            callback: function () {\n                updateAddToCartButtons();\n                tooltip.init();\n            }\n        });\n    });\n};\n","'use strict';\n\nvar _ = require('lodash');\nvar dialog = require('../../dialog');\nvar ajax = require('../../ajax');\nvar page = require('../../page');\nvar util = require('../../util');\nvar TPromise = require('promise');\nvar validator = require('../../validator');\n\nvar options;\n\n/**\n * @description Get the product information\n * @param {event} e The click event from the request gift button\n * @returns {object} productInfo\n */\nvar getProductInfo = function(e) {\n\tvar productInfo;\n\tvar sizeSelected = $('div.product-variations .size.size-options li.selected');\n\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\n\tif (!isSizeSelected) {\n\t\talert('Please select a size');\n\t\treturn false;\n\t}\n\tif (!$('div.product-variations .color.color-options li.selected').length) {\n\t\talert('Please select a color');\n\t\treturn false;\n\t}\n\n\t// get product info\n\tif (typeof dataLayer !== 'undefined') {\n\t\tvar variationAttribute = $('.product-variations').data('attributes');\n\t\tvar sizeAttributeValue = variationAttribute.size.displayValue;\n\t\tif ( sizeAttributeValue == '' || sizeAttributeValue == null ) {\n\t\t\tif (sizeSelected.hasClass(\"tempselection\") && sizeSelected.find('a.swatchanchor').data() != null ) {\n\t\t\t\tsizeSelected.addClass('enterSelected');\n\t\t\t\tvar sizeObjectReference = sizeSelected.find('a.swatchanchor').data();\n\t\t\t\tsizeAttributeValue = sizeObjectReference.sizeName;\n\t\t\t\tsizeSelected.find('a.swatchanchor').trigger('click');\n\t\t\t}\n\t\t}\n\n\t\tfor(var i=0;i<dataLayer.length;i++) {\n\t\t\tif(dataLayer[i].event == 'pdpDisplay') {\n\t\t\t\tvar selectedItem = dataLayer[i].ecommerce.detail.products[0];\n\t\t\t\tvar isSwiper = $('.product-primary-image [class*=\"-initialized\"]').first().hasClass('swiper-initialized');\n\t\t\t\tvar activeImage = isSwiper ? $(e.target).closest('#pdpMain').find('.product-primary-image .swiper-slide-active img').attr('src') : $(e.target).closest('#pdpMain').find('.product-primary-image .slick-active .zoomedImage').attr('href');\n\t\t\t\tproductInfo = {\n\t\t\t\t\t\"id\": selectedItem.id,\n\t\t\t\t\t\"name\": selectedItem.name,\n\t\t\t\t\t\"imageUrl\": activeImage,\n\t\t\t\t\t\"size\": sizeAttributeValue,\n\t\t\t\t\t\"color\": variationAttribute.color.displayValue,\n\t\t\t\t\t\"colorCode\": variationAttribute.color.value\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t}\n\treturn productInfo;\n};\n\n/**\n * @description Formats a URL with preset product attributes\n * @param {object} productInfo An object containing the product's attributes\n * @returns {string} url\n */\nvar createProductUrl = function(productInfo) {\n\tvar url = window.location.hostname + window.location.pathname;\n\tif (productInfo.id && productInfo.id.length > 0) {\n\t\turl = url + '?dwvar_' + productInfo.id;\n\t\tif (productInfo.colorCode && productInfo.colorCode.length > 0) {\n\t\t\turl = url + '_color=' + productInfo.colorCode;\n\t\t}\n\t\tif (productInfo.size && productInfo.size.length > 0) {\n\t\t\turl = url + '#prefn1=size&prefv1=' + productInfo.size;\n\t\t}\n\t}\n\treturn url;\n};\n\n/**\n * @description Open the request gift dialog\n * @param {event} e The click event from the request gift button\n */\nvar requestGift = function(e) {\n\te.preventDefault();\n\t\n\tvar windowWidth = $(window).width();\n\t\n\tif (windowWidth <= 480) {\n\t\tvar dialogWidth = windowWidth - 20;\n\t} else if (windowWidth <= 840) {\n\t\tvar dialogWidth = windowWidth - 40;\n\t} else {\n\t\tvar dialogWidth = 800;\n\t}\n\n\tvar productInfo = getProductInfo(e);\n\tvar dialogClass = 'gift-dialog';\n\tvar templateSettings = {interpolate: /{{([\\s\\S]+?)}}/g};\n\tvar formTemplate = _.template($('#template-popup-form').html(), templateSettings);\n\tvar confirmationTemplate = _.template($('#template-popup-confirmation').html(), templateSettings);\n\n\tif (!productInfo) {\n\t\treturn false;\n\t}\n\n\tdialog.open({\n\t\thtml: formTemplate(productInfo),\n\t\toptions: {\n\t\t\ttitle: 'Send a hint',\n\t\t\twidth: dialogWidth,\n\t\t\tdialogClass: dialogClass,\n\t\t\tbuttons: [],\n\t\t\tmodal: true,\n\t\t\topen: function() {\n\t\t\t\tvar $form = $(this).find('#gift-form');\n\t\t\t\t// jquery validate doesn't require an email extension, so adding it manually\n\t\t\t\t$.validator.addMethod('MerryMailValidateEmail',\n\t\t\t\t\tfunction(value, element) {\n\t\t\t\t\t\treturn /^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$/.test(value);\n\t\t\t\t\t},\n\t\t\t\t\t'Please enter a valid email address.'\n\t\t\t\t);\n\t\t\t\t$.validator.addMethod('MerryMailValidateName',\n\t\t\t\t\tfunction(value, element) {\n\t\t\t\t\t\treturn !(/:\\/\\//.test(value)) && !(/\\w+([-+.'\\s]\\w)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*/.test(value));\n\t\t\t\t\t},\n\t\t\t\t\t'Please enter a valid name.'\n\t\t\t\t);\n\t\t\t\t\t\t\n\t\t\t\t$form.validate({\n\t\t\t\t\trules: {\n\t\t\t\t\t\tcustomMessage: {\n\t\t\t\t\t\t\trequired: {\n\t\t\t\t\t\t\t\tdepends: function(element) {\n\t\t\t\t\t\t\t\t\treturn $form.find('input[name=\"message\"][value=\"custom\"]').prop('checked');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsenderName: {\n\t\t\t\t\t\t\tMerryMailValidateName: true\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsenderEmail: {\n\t\t\t\t\t\t\tMerryMailValidateEmail: true\n\t\t\t\t\t\t},\n\t\t\t\t\t\trecipientName: {\n\t\t\t\t\t\t\tMerryMailValidateName: true\n\t\t\t\t\t\t},\n\t\t\t\t\t\trecipientEmail: {\n\t\t\t\t\t\t\tMerryMailValidateEmail: true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif ($('#merryMailSubmitButton').length > 0 && options && options.Recaptcha && options.Recaptcha.EnabledForMerryMail && options.Recaptcha.GoogleSiteKey) {\n\t\t\t\t\tgrecaptcha.render('merryMailSubmitButton', {\n\t\t\t        \tsitekey: options.Recaptcha.GoogleSiteKey,\n\t\t\t        \tcallback: submitMerryMail,\n\t\t\t        \tbadge: 'bottomleft'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// trigger radio button selection if user clicks into custom message input\n\t\t\t\t$(this).find('input[name=\"customMessage\"]').off('focus').on('focus', function(e) {\n\t\t\t\t\t$form.find('input[name=\"message\"][value=\"custom\"]').prop('checked', true).change();\n\t\t\t\t});\n\n\t\t\t\t$(document).off('MerryMail.Send').on('MerryMail.Send', function() {\n\t\t\t        if (!$form.valid()) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t        \n\t\t\t\t\tvar formData = {\n\t\t\t\t\t\trecipientName: $form.find('input[name=\"recipientName\"]').val(),\n\t\t\t\t\t\trecipientNameCaps: $form.find('input[name=\"recipientName\"]').val().toUpperCase(),\n\t\t\t\t\t\trecipientEmail: $form.find('input[name=\"recipientEmail\"]').val(),\n\t\t\t\t\t\tsenderName: $form.find('input[name=\"senderName\"]').val(),\n\t\t\t\t\t\tsenderEmail: $form.find('input[name=\"senderEmail\"]').val(),\n\t\t\t\t\t\tfromEmail: $('#merry-mail-from-email').text().length > 0 ? $('#merry-mail-from-email').text() : 'no-reply@demandware.net',\n\t\t\t\t\t\tsubject: $('#merry-mail-email-subject').text().replace('[sender_name]',$form.find('input[name=\"senderName\"]').val()),\n\t\t\t\t\t\tbaseUrl: $('#merry-mail-base-url').text(),\n\t\t\t\t\t\tunsubscribeUrl: $('#merry-mail-unsubscribe-url').text(),\n\t\t\t\t\t\tmessage: $form.find('input[name=\"message\"]:checked').val() === 'custom' ? $form.find('input[name=\"customMessage\"]').val() : $form.find('input[name=\"message\"]:checked').val(),\n\t\t\t\t\t\tproductId: productInfo.id,\n\t\t\t\t\t\tproductImage: window.location.hostname + productInfo.imageUrl,\n\t\t\t\t\t\tproductUrl: createProductUrl(productInfo),\n\t\t\t\t\t\tproductName: productInfo.name.replace(/\\\\(.)/mg, \"$1\"), // handle backslash escaping\n\t\t\t\t\t\tsize: productInfo.size,\n\t\t\t\t\t\tcolor: productInfo.color\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\turl: Urls.sendGiftRequestEmail,\n\t\t\t\t\t\tdata: formData,\n\t\t\t\t\t\tsuccess: function() {\n\t\t\t\t\t\t\tvar confirmMessage = $('#merry-mail-success-message').html().replace('[recipient_name]',formData.recipientName);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdialog.open({\n\t\t\t\t\t\t\t\thtml: confirmationTemplate({confirmMessage: confirmMessage}),\n\t\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\t\ttitle: 'Success!',\n\t\t\t\t\t\t\t\t\twidth: dialogWidth,\n\t\t\t\t\t\t\t\t\tdialogClass: dialogClass,\n\t\t\t\t\t\t\t\t\tbuttons: [{\n\t\t\t\t\t\t\t\t\t\ttext: 'OK',\n\t\t\t\t\t\t\t\t\t\tclick: function() {\n\t\t\t\t\t\t\t\t\t\t\tdialog.close();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (SitePreferences.GTM_ENABLED) {\n\t\t\t\t\t\t\t\tdataLayer.push({\n\t\t\t\t\t\t\t\t\t'event': SitePreferences.MERRYMAIL_GTM_EVENT_NAME,\n\t\t\t\t\t\t\t\t\t'merryMailProduct': {\n\t\t\t\t\t\t\t\t\t\t'name' : formData.productName,\n\t\t\t\t\t\t\t\t\t\t'url' : formData.productUrl\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t    });\n\t\t\t\t\n\t\t\t\t// handle click events on submit button\n\t\t\t\t$form.find('input[type=\"submit\"]').off('click').on('click', function(e) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\n\t\t\t\t\tif (!options || !options.Recaptcha || !options.Recaptcha.EnabledForMerryMail || !options.Recaptcha.GoogleSiteKey) {\n\t\t\t\t\t\t$(document).trigger('MerryMail.Send');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\t\n\tpopulateModalProductContent(productInfo);\n};\n\n/**\n * @description Populates the modal with applicable variant/product data\n */\nvar populateModalProductContent = function(productInfo) {\n\tvar productImageUrl = productInfo.imageUrl;\n\tvar currentProductUrl = createProductUrl(productInfo);\n\t\n\t$('.gift-dialog__sample-message .product-image').replaceWith('<img class=\"product-image\" src=\"' + productImageUrl + '?sw=500\" alt=\"\" />');\n\t\n\tvar hintText = $('strong.hint-item').html();\n\t$('strong.hint-item').replaceWith('<strong class=\"hint-item\"><a href=\"' + currentProductUrl + '\">' + hintText + '</a></strong>');\n};\n\n/**\n * @description updates the sender and recipient names in the sample message as the user enters that information into the form\n */\nvar updateSenderName = function() {\n\tvar currentSenderName = $('.gift-form__input[name=\"senderName\"]').val();\n\t\n\t$('.merry-mail-message-from').replaceWith('<span class=\"merry-mail-message-from replaced\">' + currentSenderName + '</span>');\n};\n\nvar updateRecipientName = function() {\n\tvar currentRecipientName = $('.gift-form__input[name=recipientName]').val();\n\t\n\t$('.merry-mail-message-to').replaceWith('<span class=\"merry-mail-message-to replaced\">' + currentRecipientName + '</span>');\n};\n\n\n/**\n * @function\n * @description Binds the click event to the button for the request gift handling\n */\nmodule.exports = function (optionsParameter) {\n\toptions = optionsParameter;\n\t\n\t$('.product-detail').on('click', '[data-action=\"requestGift\"]', requestGift);\n\t$(document).on('change', 'input.sender-name', updateSenderName);\n\t$(document).on('change', 'input.recipient-name', updateRecipientName);\n};\n","'use strict';\n\nvar _ = require('lodash');\nvar ajax = require('../../ajax');\nvar image = require('./image');\nvar GoogleTagManagerClient = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar productStoreInventory = require('../../storeinventory/product');\nvar rating = require('../../rating');\nvar tooltip = require('../../tooltip');\nvar util = require('../../util');\nvar bopisAddToCartOptions = require('../../bopis/components/AddToCartOptions');\nvar bopisStoreSearch = require('../../bopis/components/StoreSearch');\nvar wishlist = require('../../wishlist');\nvar sliders = require('../../sliders');\nvar imageGallery;\n\nvar SiteConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar TemplateConstants = require('../../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nvar html = {};\nvar data = {};\nvar loaded = {};\nvar options;\n\nfunction initializeDom() {\n\tloaded['content'] = true;\n\t\n\tupdateCSRFToken();\n\n\tvar selectorPayload = util.getQueryStringParams($('.pdpForm').serialize());\n\t\n\tvar queryStringParameters = util.getQueryStringParams(util.getQueryString(util.appendParamsToUrl(window.location.toString(), selectorPayload)));\n\tfor (var parameter in queryStringParameters) {\n\t\tselectorPayload[parameter] = queryStringParameters[parameter];\n\t}\n\n\tvar sizeValue = util.getPreferenceValueFromWindowLocation('size');\n\tif (sizeValue) {\n\t\tselectorPayload.setSize = sizeValue;\n\t}\n\t\n    buildSelectors(selectorPayload);\n\t$('.btn.add-to-cart').removeAttr('disabled').removeAttr('loading').find('.loading-indicator-container').remove();\n}\n\nfunction updateProductInfo() {\n\t$('li.selected-value').each(function() {\n\t\tvar $selectedItem = $(this);\n\t\t$selectedItem.parents('.attribute').first().find('.label .current, .select-dropdown .select-text').html($selectedItem.html());\n\t});\n}\n\nfunction updateCSRFToken() {\n    $.ajax({\n    \tmethod: 'get',\n    \turl: Urls.CSRFToken.Get,\n\t\tdataType: 'json',\n    \tsuccess: function(response) {\n    \t\t$('#csrftoken').val(response.token);\n    \t}\n    });\n}\n\nfunction updatePid() {\n\tif (data['pid']) {\n\t\t$('#pid').val(data['pid']);\n\t}\n}\n\nfunction buildSelectors(payload) {\n\tloaded['selectors'] = false;\n\t\n\tif (!payload) {\n\t\tpayload = util.getQueryStringParams($('.pdpForm').serialize());\n\t}\n    \n    var templates = [];\n    templates['variations'] = _.template($('#template-variations').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelector'] = _.template($('#template-variations-selector').html(), TemplateConstants.Lodash.Settings);\n\ttemplates['variationSelectorAttributeGuide'] = _.template($('#template-variations-attribute-guide').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdown'] = _.template($('#template-variations-selector-dropdown').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdownOption'] = _.template($('#template-variations-selector-dropdown-option').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorDropdownOptionSelected'] = _.template($('#template-variations-selector-dropdown-option-selected').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatch'] = _.template($('#template-variations-selector-swatch').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatchOption'] = _.template($('#template-variations-selector-swatch-option').html(), TemplateConstants.Lodash.Settings);\n    templates['variationSelectorSwatchOptionUnselectable'] = _.template($('#template-variations-selector-swatch-option-unselectable').html(), TemplateConstants.Lodash.Settings);\n    \n\tdata['attributeGuides'] = {};\n\n    $.ajax({\n    \tmethod: 'post',\n    \turl: Urls.getVariationAttributes,\n    \tdata: payload,\n\t\tdataType: 'json',\n    \tsuccess: function(response) {\n\t\t\thtml['variationSelectors'] = '';\n\t\t\tdata['IsRestrictedByGlobale'] = response.IsRestrictedByGlobale;\n\n\t\t\t// Color Swatch Length Check\n\t\t\tvar isMultiSwatch;\n\t\t\tif (response && 'variations' in response && response.variations.length) {\n\t\t\t\tisMultiSwatch = response.variations.filter(function(variantGroup) {\n\t\t\t\t\tif (variantGroup && 'type' in variantGroup && 'values' in variantGroup) {\n\t\t\t\t\t\treturn variantGroup.type == 'swatch' && variantGroup.values.length > 1; // Check for multiple color swatches\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar hasSizeAttribute = false;\n\t\t\tif (response && 'variations' in response && response.variations.length) {\n\t\t\t\thasSizeAttribute = response.variations.filter(function(variantGroup) {\n\t\t\t\t\tif (variantGroup && 'productVariationAttribute' in variantGroup && 'values' in variantGroup) {\n\t\t\t\t\t\treturn variantGroup.productVariationAttribute == 'size' && variantGroup.values.length > 1;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvar variations;\n\t\t\tif (hasSizeAttribute) {\n\t\t\t\tvariations = response.variations;\n\t\t\t} else {\n\t\t\t\tvariations = response.variations;\n\t\t\t}\n\t\t\tfor (var variation in response.variations) {\n\t\t\t\tvar variationData = response.variations[variation];\n\t\t\t\tvar variationDataValueSelected = null;\n\t\t\t\t\n\t\t\t\thtml['variationSelectorWidgetOptions'] = '';\n\t\t\t\t\t\t\t\t\n\t\t\t\tfor (var variationValue in variationData.values) {\n\t\t\t\t\tvar variationDataValue = variationData.values[variationValue];\n\t\t\t\t\tvar variationDataValueTemplate;\n\t\t\t\t\tvar variationText = (variationDataValue.attribute === 'size') ? variationDataValue.text.replace(' 1/2', '\\u00BD') : variationDataValue.text;\n\t\t\t\t\tvar widthDescription = variationDataValue.widthDescription ? '<span class=\"width-description\">' + variationDataValue.widthDescription + '</span>' : '';\n\t\t\t\t\tvar optionAriaLabel = variationDataValue.value;\n\t\t\t\t\tif (variationDataValue.shipping) {\n\t\t\t\t\t\toptionAriaLabel += + ' - ' + variationDataValue.shipping;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar variationDataValuePayload = {\n\t\t\t\t\t\tattribute: variationDataValue.attribute,\n\t\t\t\t\t\tvalueId: variationDataValue.valueId,\n\t\t\t\t\t\tvalue: variationDataValue.value,\n\t\t\t\t\t\ttitle: variationDataValue.title,\n\t\t\t\t\t\toptionAriaLabel: optionAriaLabel,\n\t\t\t\t\t\ttext: variationText,\n\t\t\t\t\t\twidthDescription: widthDescription,\n\t\t\t\t\t\tstock: variationDataValue.stock,\n\t\t\t\t\t\tshipping: variationDataValue.shipping,\n\t\t\t\t\t\tisSameDayShippingWindow: variationDataValue.isSameDayShippingWindow,\n\t\t\t\t\t\tquantitySourceType: variationDataValue.quantitySourceType,\n\t\t\t\t\t\thref: variationDataValue.href,\n\t\t\t\t\t\tselectable: variationDataValue.selectable ? 'selectable' : 'unselectable',\n\t\t\t\t\t\tselected: variationDataValue.selected ? 'selected' : '',\n\t\t\t\t\t\tswatchImageUrl: variationDataValue.images.swatch.url,\n\t\t\t\t\t\tlargeSwatchImageUrl: variationDataValue.images.largeSwatch.url,\n\t\t\t\t\t\threfAttribute: variationDataValue.selectable ? 'href' : 'xhref'\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (variationData.type == 'swatch') {\n\t\t\t\t\t\tif (variationDataValue.selectable) {\n\t\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorSwatchOption'];\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tvariationDataValuePayload.imageLarge = JSON.stringify({\n\t\t\t\t\t\t\t\turl: variationDataValue.images.large.url,\n\t\t\t\t\t\t\t\ttitle: variationDataValue.images.large.title,\n\t\t\t\t\t\t\t\talt: variationDataValue.images.large.alt,\n\t\t\t\t\t\t\t\thires: variationDataValue.images.hires.url\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorSwatchOptionUnselectable'];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvariationDataValueTemplate = templates['variationSelectorDropdownOption'];\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (variationDataValue.selected) {\n\t\t\t\t\t\t\tvariationDataValueSelected = variationDataValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\thtml['variationSelectorWidgetOptions'] += variationDataValueTemplate(variationDataValuePayload);\t\n\t\t\t\t}\t\n\t\t\t\t\n\t\t\t\t// Add color swatch length boolean to template data\n\t\t\t\tif (variationData.type == 'swatch') {\n\t\t\t\t\thtml['variationSelectorWidget'] = templates['variationSelectorSwatch']({\n\t\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\t\toptions: html['variationSelectorWidgetOptions'],\n\t\t\t\t\t\tmultiSwatchDisplay: isMultiSwatch.length > 0 ? 'd-block' : 'd-none'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar placeholder = variationData.label.placeholder,\n\t\t\t\t\t\tariaLabel = variationData.label.placeholder;\n\n\t\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS && variationData.productVariationAttribute === 'size' && variationDataValueSelected === null) {\n\t\t\t\t\t\tplaceholder += ' (' + variationData.label.message + ')';\n\t\t\t\t\t}\n\n\t\t\t\t\tif (variationDataValueSelected) {\n\t\t\t\t\t\tvar variationSelectedText = (variationData.productVariationAttribute === 'size') ? variationDataValueSelected.text.replace(' 1/2', '\\u00BD') : variationDataValueSelected.text;\n\t\t\t\t\t\tvar widthDescription = variationDataValueSelected.widthDescription ? '<span class=\"width-description\">' + variationDataValueSelected.widthDescription + '</span>' : '';\n\n\t\t\t\t\t\tplaceholder = templates['variationSelectorDropdownOptionSelected']({\n\t\t\t\t\t\t\ttext: variationSelectedText,\n\t\t\t\t\t\t\twidthDescription: widthDescription,\n\t\t\t\t\t\t\tstock: variationDataValueSelected.stock,\n\t\t\t\t\t\t\tshipping: variationDataValueSelected.shipping,\n\t\t\t\t\t\t\tisSameDayShippingWindow: variationDataValueSelected.isSameDayShippingWindow,\n\t\t\t\t\t\t\tquantitySourceType: variationDataValueSelected.quantitySourceType\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tariaLabel = 'Currently Selected: ' + variationDataValueSelected.value; \n\t\t\t\t\t\tif (variationDataValueSelected.shipping) {\n\t\t\t\t\t\t\tariaLabel += ' - ' + variationDataValueSelected.shipping;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add color swatch length boolean to template data\n\t\t\t\t\thtml['variationSelectorWidget'] = templates['variationSelectorDropdown']({\n\t\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\t\ttext: placeholder,\n\t\t\t\t\t\tariaLabel: ariaLabel,\n\t\t\t\t\t\toptions: html['variationSelectorWidgetOptions'],\n\t\t\t\t\t\tmultiSwatchDisplay: isMultiSwatch.length > 0 ? 'd-block' : 'd-none'\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\thtml['attributeGuide'] = '';\n\t\t\t\tif (variationData.attributeGuide) {\n\t\t\t\t\tdata['attributeGuides'][variationData.productVariationAttribute] = variationData.attributeGuide;\n\t\t\t\t\thtml['attributeGuide'] = templates['variationSelectorAttributeGuide'](_.extend(variationData.attributeGuide, { Attribute: variationData.productVariationAttribute }));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\thtml['variationSelector'] = templates['variationSelector']({\n\t\t\t\t\tattribute: variationData.productVariationAttribute,\n\t\t\t\t\tlabel: {\n\t\t\t\t\t\ttext: variationData.label.text,\n\t\t\t\t\t\tmessage: variationData.label.message\n\t\t\t\t\t},\n\t\t\t\t\tselector: html['variationSelectorWidget'],\n\t\t\t\t\tguide: html['attributeGuide']\n\t\t\t\t});\n\n\t\t\t\thtml['variationSelectors'] += html['variationSelector'];\n\t\t\t}\n\t\t\t\n\t\t\thtml['selectors'] = templates['variations']({\n\t\t\t\tselectors: html['variationSelectors']\n\t\t\t});\n\t\t\t\n\t\t\tdata['selected'] = response.selected;\n\t\t\tdata['pid'] = response.pid;\n\t\t\t\n\t\t\tloaded['selectors'] = true;\n\t\t\trenderVariationUpdates();\n    \t}\n\t});\n}\n\nfunction setAlternates() {\n\t$('ul.alternate-items li').sort(function(a,b) { return $(a).data('id') - $(b).data('id'); }).appendTo('.alternate-items');\n\tvar altType = $('ul.alternate-items').data('alternate');\n\tvar altDefault = $('ul.alternate-items').data('default');\n\tvar alternates = [];\n\n\tvar isSubscriptionProduct = $('.pdp-main').hasClass('subscription-product-template');\n\tvar colorSelected = $('.color-options .selected a');\n\tvar sizeSelected = $('.size-options .selected a').data('size-id');\n\n\tif (colorSelected && isSubscriptionProduct) {\n\t\talternates.push({'altID': $(colorSelected).parent('.selected').data('id'), 'altValue': $(colorSelected).attr('data-color-name')});\n\t}\n\t$('ul.alternate-items li').each(function(i, elem) {\n\t\talternates.push({'altID': $(elem).data('id'), 'altValue': $(elem).text().split('-')[1]});\n\t});\n\n\tif (sizeSelected && sizeSelected.length > 0 && $('.alternate').length > 0){\n\t\tupdateAlternates(sizeSelected);\n\t} else if (alternates && alternates.length > 0){\n\t\t$.ajax({\n\t\t\turl: Urls.getItemAlternates,\n\t\t\tdataType: 'JSON',\n\t\t\tmethod: 'POST',\n\t\t\tdata: {\n\t\t\t\t'alternates': JSON.stringify(alternates)\n\t\t\t},\n\t\t\tsuccess : function(data) {\n\t\t\t\tvar altSwatches = '';\n\t\t\t\tvar alternate = data.result;\n\t\t\t\t\n\t\t\t\t$.each(alternate, function(i, e){\n\t\t\t\t\tvar id = alternate[i].id;\n\t\t\t\t\tvar type = altType ? altType : 'Color';\n\t\t\t\t\tvar value = alternate[i].value;\n\t\t\t\t\tvar image = alternate[i].image;\n\t\t\t\t\tvar url = $('.alternate-items li[data-id='+id+']').data('url');\n\t\t\t\t\tvar altHidden = 'show-content';\n\t\t\t\t\tif ( i >= 11 ){\n\t\t\t\t\t\taltHidden = 'hidden-content';\n\t\t\t\t\t}\n\t\t\t\t\tif ( isSubscriptionProduct && id == $(colorSelected).parent('.selected').data('id') ){\n\t\t\t\t\t\t$(colorSelected).css('background', 'url('+image+')');\n\t\t\t\t\t} else {\n\t\t\t\t\t\taltSwatches += '<li class=\"unselectable alternate ' + altHidden + '\" data-id=\"'+id+'\" data-type=\"'+altType+'\" data-value=\"'+value+'\"><a class=\"swatchanchor\" href=\"'+url+'\" title=\"Select '+altType+': '+value+'\" value=\"'+value+'\" style=\"background: url('+image+'?sw=70&amp;sh=70&amp;sm=fit); background-repeat: no-repeat; background-size: contain; background-position: center;\"><span class=\"visually-hidden\">Select '+altType+':'+value+'</span></a></li>';\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (altSwatches.length > 0 ){\n\t\t\t\t\t$('.color.color-options').removeClass('color-d-none').append(altSwatches).find('li').sort(function(a,b) { return $(a).data('id') - $(b).data('id'); }).appendTo('.color-options');\n\t\t\t\t\tif (altType && altDefault){\n\t\t\t\t\t\t$('.color-options .selected').attr('data-type',altType).attr('data-value',altDefault).find('a.swatchanchor').attr('title','Select '+altType+': '+altDefault);\n\t\t\t\t\t\tvar newText = '<span class=\"text\">'+altType+'<span class=\"separator\">:</span> <span class=\"current color-current\">'+altDefault+'</span></span>';\n\t\t\t\t\t\t$('.attribute-color .text').html(newText);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (sizeSelected && sizeSelected.length > 0){\n\t\t\t\t\tupdateAlternates(sizeSelected);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar altHiddenCount = $('.hidden-content').length;\n\t\t\t\tvar altHiddenToggle = '+ ' + altHiddenCount;\n\t\t\t\tif (altHiddenCount > 0){\n\t\t\t\t\t$('.hidden-content').hide();\n\t\t\t\t\t$('.color.color-options').append('<button class=\"altButton\">' + altHiddenToggle + '</button>');\n\t\t\t\t}\n\n\t\t\t\t$('button.altButton').on('click', function(e){\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\t$(this).closest('.color-options').find('.hidden-content').toggle();\n\t\t\t\t\t$('.altButton').hide();\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t$(\".color-options li\").hover(function(){\n\t\t\t\t\tvar altTitle = $(this).data('type');\n\t\t\t\t\tvar altValue = $(this).data('value');\n\t\t\t\t\tvar newText = '<span class=\"text\">'+altType+'<span class=\"separator\">:</span> <span class=\"current color-current\">'+altValue+'</span></span>';\n\t\t\t\t\t$('.attribute-color .text').html(newText);\n\t\t\t\t}, function(){\n\t\t\t\t\tvar altTitle = $('.color-options .selected').data('type');\n\t\t\t\t\tvar altValue = $('.color-options .selected').data('value');\n\t\t\t\t\tvar newText = '<span class=\"text\">'+altType+'<span class=\"separator\">:</span> <span class=\"current color-current\">'+altValue+'</span></span>';\n\t\t\t\t\t$('.attribute-color .text').html(newText);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction updateAlternates(sizeSelected) {\n\tvar altupdates = [];\n\t$('ul.color-options li').each(function(i, elem) {\n\t\taltupdates.push(String($(elem).data('id')));\n\t});\n\t\n\tif(altupdates && altupdates.length > 0){\n\t\t$.ajax({\n\t\t\turl: Urls.updateItemAlternates,\n\t\t\tdataType: 'JSON',\n\t\t\tmethod: 'POST',\n\t\t\tdata: {\n\t\t\t\t'altupdates': JSON.stringify(altupdates),\n\t\t\t\t'size': sizeSelected\n\t\t\t},\n\t\t\tsuccess : function(data) {\n\t\t\t\tvar alternate = data.result;\n\t\t\t\t\n\t\t\t\t$.each(alternate, function(i, e){\n\t\t\t\t\tvar id = alternate[i].id;\n\t\t\t\t\tvar appendURL = alternate[i].appendURL;\n\t\t\t\t\tvar sizeAvailable = !alternate[i].sizeAvailable;\n\t\t\t\t\tvar oldURL = $('ul.color-options li[data-id='+id+'] a').attr('href');\n\t\t\t\t\tvar newURL = oldURL + appendURL;\n\t\t\t\t\t$('ul.color-options li.alternate[data-id=\"'+id+'\"] a').attr('href',newURL);\n\t\t\t\t\tif(appendURL == null || (typeof appendURL === \"string\" && appendURL.trim().length === 0)){\n\t\t\t\t\t\t$('ul.color-options li[data-id='+id+'] a').addClass('no-size');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction renderVariationUpdates() {\n\tif (loaded['content'] && loaded['selectors']) {\n\t\trenderSelectors();\n\t\tupdatePid();\n\t\tsetAlternates();\n\t\t\n\t\t$(document).trigger('SameDayShippingCountdown.Update');\n\t\t\n\t\tvar sizeSelected = $('div.product-variations .size.size-options li.selected');\n\t\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\t\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\t\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\t\tvar isColorSelected = $('div.product-variations .color.color-options li.selected').length;\n\t\t\n\t\tupdateWishlistButton(sizeSelected);\n\n\t\tif (isSizeSelected) {\n\t\t\t$('.attribute-size').addClass('size-selected');\n\t\t} else {\n\t\t\t$('.attribute-size').removeClass('size-selected');\n\t\t}\n\t    if (isSizeSelected && isColorSelected) {\n\t\t\t$('.btn.store-search').removeAttr('disabled');\n\n\t    \t$(document).trigger('ProductDetailPage.Variant.Selected');\n\t\t\t$(document).trigger('ProductDetailPage.Variant.AddToCartOptions');\n\t\t\t$(document).trigger('ProductDetailPage.Variant.StoreSearch');\n\t\t\t$(document).trigger('Currency.Update', $('#product-content'));\n\t    }\n\t    \n    \tvar $selectableCount = 0;\n    \t$('.product-options .attribute-size .select-dropdown ul.size-options li, .product-options .attribute-size .select-dropdown ul.length-options li').each(function() {\n        \tvar $selectClass = $(this).attr('class').replace('selected','').trim();\n        \tif( $selectClass == 'selectable'){\n        \t\t$selectableCount++;\n        \t}        \n        });\n\n\t\tif (data['IsRestrictedByGlobale'] || $selectableCount == 0) {\n\t\t\t$('.same-day-shipping-countdown').addClass('hidden');\n\t\t\t$('.product-options .attribute-size .select-dropdown').css({\"pointer-events\": \"none\", \"cursor\": \"default\"});\n\t\t\t$('.product-variation').addClass('not-available');\n\t\t\tif ($('.color-options .selectable').length > 1 || $('.alternate-items li').length > 1) {\n\t\t\t\t$('.product-variation').addClass('colors-selectable');\n\t\t\t}\n\t\t\tif (data['IsRestrictedByGlobale']) {\n\t\t\t\t$('.product-globale-unavailable').removeClass('hidden');\n\t\t\t} else if ($selectableCount == 0) {\n\t\t\t\t$('.product-out-of-stock').removeClass('hidden');\n\t\t\t}\n\t\t}\n\n\t\t$(document).trigger('ProductDetailPage.Variant.Updated');\n\t}\n}\n\nfunction renderSelectors() {\n\t$('.product-variations').html(html['selectors']);\n\t$('.product-variations').attr('data-attributes', JSON.stringify(data['selected']));\n\tcheckForSelectedSwatch($('.product-variations'));\n\n\t$('.attribute-guide-link').fancybox();\n}\n\nfunction checkForSelectedSwatch($container) {\n\tvar swatchIsSelected = $container.find('.color-options .selectable.selected').length > 0;\n\tif (!swatchIsSelected) {\n\t\t$container.find('.color-options .selectable:first-child>.swatchanchor').mouseenter();\n\t}\n}\n\n/**\n * @description update product content with new variant from href, load new content to #product-content panel\n * @param {String} href - url of the new product variant\n **/\nvar updateContent = function (href) {\n\tloaded['content'] = false;\n\t$('.btn.add-to-cart').attr('disabled', 'disabled').loading();\n\tvar bopisStoreSearchPostalCode = $('.bopis-store-search input[name=\"Bopis_StoreSearch_postalCode\"]').val();\n    var $pdpForm = $('.pdpForm');\n    var qty = $pdpForm.find('select[name=\"Quantity\"]').first().val();\n    var params = {\n        Quantity: isNaN(qty) ? '1' : qty,\n        format: 'ajax',\n        productlistid: $pdpForm.find('input[name=\"pid\"]').first().val(),\n        BopisEnabled: $('.bopis-store-search').length > 0 ? true : false,\n\t\tToken: $('.bopis-store-search input[name=\"csrf_token\"]').val()\n    };\n\n    buildSelectors(util.getQueryStringParams(util.getQueryString(util.appendParamsToUrl(href, params))));\n\t$.ajax({\n    \tmethod: 'GET',\n    \turl: util.appendParamsToUrl(href, params),\n    \tcomplete: function(html) {\n\t\t\tloaded['content'] = true;\n\t\t\t$('#product-content').html(html.responseText);\n\t\t\trenderVariationUpdates();\n\n\t\t\tif (bopisStoreSearchPostalCode) {\n        \t\t$('.bopis-store-search input[name=\"Bopis_StoreSearch_postalCode\"]').val(bopisStoreSearchPostalCode);\n        \t}\n        \t\n            if (SitePreferences.STORE_PICKUP) {\n                productStoreInventory.init();\n            }\n            image.replaceImages();\n            tooltip.init();\n            // rating.init();\n            updateProductInfo();\n            initializeImageGallery();            \n\t\t\tupdateCSRFToken();\n\t\t\t// GoogleTagManagerClient.PushDataLayerForDataLayerType('ViewItem');\n            \n            setTimeout(function(){$(document).trigger('update-review-text');}, 500);\n\n            if ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui) {\n\t\t\t    affirm.ui.refresh();\n\t\t\t}\n            \n\t\t\tvar variantSelected = isVariantSelected();\n            if ($('.bopis-store-search').length > 0 || $('.bopis-add-to-cart-options-container').length > 0) {\n            \tif (variantSelected) {\n            \t\toptions.Bopis.IsVariantSelected = true;\n            \t}\n\t\t\t\tinitializeBopis();\n\t\t\t}\n\n\t\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\tupdateAddToCartRecommendations();\n\t\t\t}\n\t\t\t$('.btn.add-to-cart').removeAttr('disabled').removeAttr('loading').find('.loading-indicator-container').remove();    \t\t\n    \t}\n    });\n};\n\nfunction isVariantSelected() {\n\tvar sizeSelected = $('div.product-variations .size.size-options li.selected').length;\n\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\tvar colorSelected = $('div.product-variations .color.color-options li.selected').length;\n\n\treturn (sizeSelected || (lengthSelected && widthSelected)) && colorSelected;\n}\n\nfunction updateAddToCartRecommendations() {\n\tvar intervalCount = 0;\n\tvar addToCartRecommendationsCheck = setInterval(function() {\n\t\tif ( $('.recomm-prod-pdp-a2c-slot .accordion.product-recommendations').length > 0 ) {\n\t\t\tclearInterval(addToCartRecommendationsCheck);\n\t\t\tinitSlider();\n\t\t\treturn;\n\t\t}\n\n\t\tif (intervalCount === 50) {\n\t\t\tclearInterval(addToCartRecommendationsCheck);\n\t\t\treturn;\n\t\t}\n\n\t\tintervalCount++;\n\t}, 200);\n\n\tfunction initSlider() {\n\t\tsliders.init('.recomm-prod-pdp-a2c-slot .accordion.product-recommendations .slides', {breakpoints: {0: {slidesToShow: 1, arrows: true, dots: true}, 768: {slidesToShow: 3, arrows: true, dots: false}, 1024: {slidesToShow: 4, arrows: true, dots: false}}}, true);\n\t}\n}\n\nfunction sizeMenuOpenClose(event, el, open) {\n\tvar $this = el;\n\tvar $container = $this.closest('.select-dropdown');\n\tvar $menu = $container.find('.select-dropdown-inner');\n\t\n\tif (open) {\n\t\t$this.addClass('active');\n\t\t$menu.addClass('expand');\n\t\t$menu.find('li.selectable a').removeAttr('tabindex');\n\t} else {\n\t\t$this.removeClass('active');\n\t\t$menu.removeClass('expand');\n\t\t$menu.find('li.selectable a').attr('tabindex', '-1');\n\t\tif ($menu.find('.tempselection').length > 0) {\n\t\t\t$menu.find('.tempselection').removeClass('selected tempselection');\n\t\t}\n\t\tif (event.keyCode) {\n\t\t\t$container.addClass('focus-visible-indicator').focus();\n\t\t}\n\t}\n\n\tif ($menu.hasClass('expand')) {\n\t\tscrollToCurrentSize();\n\t\tsetTimeout(function(){\n\t\t\t$menu.addClass('expand-close');\n\t\t}, 100);\n\t} else {\n\t\t$menu.removeClass('expand-close');\n\t}\n}\n\nfunction selectSizeOption(el) {\n\tvar $selected = $(el);\n\t\n\t$selected\n\t\t.addClass('selected')\n\t\t.siblings()\n\t\t.removeClass('selected');\n\n\t$selected\n\t\t.closest('.select-dropdown-inner')\n\t\t.removeClass('expand')\n\t\t.removeClass('expand-close')\n\t\t.prev('.select-text')\n\t\t.removeClass('active');\n}\n\nfunction updateWishlistButton(sizeSelected) {\n\tvar variantId = $('#pid').val();\n\tvar isWishlistItem = wishlist.checkWishlistForItem(variantId);\n\tvar sizeText = '';\n\n\tif (sizeSelected) {\n\t\tsizeText = sizeSelected.find('.size').text();\n\t}\n\tif (isWishlistItem) { \n\t\twishlist.prepareWishlistRemoveUI($('.pdp-main .wishlist-item-status-button'), sizeText);\n\t} else {\n\t\twishlist.prepareWishlistAddUI($('.pdp-main .wishlist-item-status-button'), null, sizeText);\n\t}\n}\n\nfunction initializeEvents () {\n\tvar $pdpMain = $('#pdpMain');\n\n    // hover on swatch - should update main image with swatch image.\n//    $pdpMain.off('mouseenter.Variant.SwatchAnchor').on('mouseenter.Variant.SwatchAnchor', '.color>li>.swatchanchor', function (e) {\n//        e.preventDefault();\n//        if ($(this).parents('li').hasClass('unselectable')) { return; }\n//        if ($(this).parents('li').hasClass('selected')) { return; }\n//        updateContent(this.href);\n//    });\n\n    // click on swatch - should update main image with swatch image.\n    $pdpMain.off('click.Variant.SwatchAnchor').on('click.Variant.SwatchAnchor', '.product-detail .swatchanchor', function (e) {\n\t\te.preventDefault();\n        var didReload = false;\n        if ($(this).parents('li').hasClass('unselectable')) {\n        \tif ($(this).parents('li').hasClass('alternate')) {\n        \t\tvar altUrlLoad = $(this).attr('href');    \t\t\n        \t\twindow.location.href = altUrlLoad;\n        \t}\n        \t\n        \t$('li.drop-down-select-value').each(function() {\n    \t\t\tvar $selectedItem = $(this);\n    \t\t\t$selectedItem.siblings('li.selected-value').html($selectedItem.html());\n        \t\t$selectedItem.parents('.attribute').first().find('.label .current, .select-dropdown .select-text').html($selectedItem.html());\n        \t\tif ( $selectedItem.parents('.select-dropdown-inner') != null ) {\n        \t\t\t$selectedItem.parents('.select-dropdown-inner').find( 'li.selected' ).removeClass('selected');\n        \t\t}\n        \t});\n    \t\tif ( $(this).attr('xhref') != null ) {\n    \t\t\tupdateContent($(this).attr('xhref'));\n    \t\t\tdidReload = true;\n    \t\t} else { return; }\n    \t}\n        if ( !didReload ) {\n\t        var link = this;\n\t        if (!link.href) {\n\t        \tlink = $(this).parent()[0];\n\t        }\n\t        updateContent(link.href);\n        }\n    });\n\n    // change drop down variation attribute - should replace product content with new variant\n    $pdpMain.off('change.Variant.VariationSelect').on('change.Variant.VariationSelect', '.variation-select', function () {\n        if ($(this).val().length === 0) { return; }\n        updateContent($(this).val());\n    });\n\n\t// Custom Select Dropdown\n    $pdpMain.off('click.Variant.Selector.Expand').on('click.Variant.Selector.Expand', '.select-dropdown .select-text', function (event) {\n\t\tevent.preventDefault();\n\t\tvar $this = $(this);\n\t\tvar toggleOpen = !$this.hasClass('active');\n\t\tsizeMenuOpenClose(event, $this, toggleOpen);\n\t});\n\n    $(document).off('click.Variant.General.Close').on('click.Variant.General.Close', function(event) {\n    \t$('div.product-variations ul.select-dropdown-inner.expand-close').each(function () {\n    \t\t$(this).siblings('.select-text').trigger('click');\n    \t});\n\t});\n\n\t$pdpMain.off('click.Variant.Selector.Select').on('click.Variant.Selector.Select', '.select-dropdown .selectable', function(event) {\n\t\tevent.preventDefault();\n\t\tselectSizeOption(this);\n\t});\n\n\t// Color Options\n    $pdpMain.off('click.Variant.Color.Select').on('click.Variant.Color.Select', '.color-options a', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar nameColor = $(this).data('color-name');\n\n\t\t$(this)\n\t\t\t.parent()\n\t\t\t.addClass('selected')\n\t\t\t.siblings()\n\t\t\t.removeClass('selected');\n\n\t\t$(this)\n\t\t\t.closest('.attribute')\n\t\t\t.find('.color-current')\n\t\t\t.text(nameColor);\n\t});\n    \n    $(document).on('keyup', 'div.product-variations div.select-dropdown', function(e) {\n\t\tvar $listContainer = $(this),\n\t\t\t$listParent = $listContainer.children('ul.select-dropdown-inner'),\n\t\t\t$defaultTextElement = $listContainer.children('.select-text'),\n\t\t\t$sizeList = $listParent.find('li.selectable'),\n\t\t\t$selected = $sizeList.filter('.selected'),\n\t\t\tisMenuOpen = $listParent.hasClass('expand');\n\n\t\tantiHover.init($listParent.width(), $listParent.height());\n\n\t\tif (e.shiftKey && e.keyCode == 9 && isMenuOpen) { // Tab backwards\n\t\t\tselectOptionKeydown(e, 'up', isMenuOpen);\n\t\t} else {\n\t\t\tswitch(e.keyCode) {\n\t\t\t\tcase 38: // Up Arrow\n\t\t\t\t\tselectOptionKeydown(e, 'up', isMenuOpen);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 40: // Down Arrow\n\t\t\t\t\tif (!isMenuOpen) {\n\t\t\t\t\t\tsizeMenuOpenClose(e, $defaultTextElement, true);\n\t\t\t\t\t}\n\t\t\t\t\tselectOptionKeydown(e, 'down', isMenuOpen);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 9: // Tab forwards\n\t\t\t\t\tif (isMenuOpen) {\n\t\t\t\t\t\tselectOptionKeydown(e, 'down', isMenuOpen);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 27: // Escape key\n\t\t\t\t\tif (isMenuOpen) {\n\t\t\t\t\t\tsizeMenuOpenClose(e, $defaultTextElement, false);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 13: // Enter key\n\t\t\t\t\t$listContainer.find('.select-text').toggleClass('active');\n\t\t\t\t\t$listParent.toggleClass('expand').toggleClass('expand-close').toggleClass('size-d-none');\n\t\t\t\t\t$sizeList.find('a[tabindex]').length > 0 ? $sizeList.find('a').removeAttr('tabindex') : $sizeList.find('a').attr('tabindex', '-1');\t\n\t\t\t\t\tif (!$selected) {\n\t\t\t\t\t\t$defaultTextElement.trigger('click');\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$selected.find('a.swatchanchor').trigger('click');\n\t\t\t\t\t}\t\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t});\n\n    $(document).off('mousemove.Variant.AntiHover').on('mousemove.Variant.AntiHover', '#anti-hover', function(e) {\n    \tantiHover.moveremove(parseInt(e.clientX), parseInt(e.clientY));\n    });\n\n    var swatches = $('div.product-variation ul.color-options li.selectable');\n\tif (swatches.length && !swatches.is('.selected')) {\n\t\tsetColor();\n\t}\n\t\n\tupdateProductInfo();\n    initializeImageGallery();\n};\n\nfunction setColor(){\n\tvar d = new $.Deferred();\n\n\tsetTimeout(function(){\n    \tvar swatches = $('div.product-variation ul.color-options li.selectable');\n    \tif (swatches.length && !swatches.is('.selected')) {\n    \t\tswatches.first().find('a').trigger('click');\n    \t\tsetTimeout(function(){d.resolve()}, 150);\n    \t}\n    \t\n    }, 50);\n\t\n\treturn d.promise()\n}\n\nvar antiHover = {\n\t$antiHover: null,\n\tposX: 0,\n\tposY: 0,\n\tremove: function() {\n\t\tif (this.$antiHover) this.$antiHover.remove();\n\t\tthis.posX = 0;\n\t\tthis.posY = 0;\n\t},\n\tmoveremove: function(x, y) {\n\t\tthis.posX = (this.posX == 0) ? x : this.posX;\n\t\tthis.posY = (this.posY == 0) ? y : this.posY;\n\t\tif (this.posX != x || this.posY != y) {\n\t\t\t$('div.product-variations ul.select-dropdown-inner li.selectable').removeClass('selected');\n\t\t\tthis.remove();\n\t\t}\n\t},\n\tcheck: function() {\n\t\treturn (this.$antiHover && this.$antiHover.length);\n\t},\n\tinit: function(w, h) {\n\t\tthis.remove();\n\t\t$('.value.select-dropdown').append('<div style=\"position: absolute;\" id=\"anti-hover\"></div>');\n\t\tthis.$antiHover = $('#anti-hover');\n\t\tthis.$antiHover\n\t\t\t.css('z-index', 1000)\n\t\t\t.css('height', h)\n\t\t\t.css('width', w);\n\t}\n\n};\n\nfunction selectOptionKeydown(e, action, isMenuOpen) {\n\te.preventDefault();\n\n\tvar $listParent = $('div.product-variations ul.select-dropdown-inner'),\n\t\t$listContainer = $listParent.closest('.select-dropdown'),\n\t\t$defaultTextElement = $listContainer.children('.select-text'),\n\t\t$sizeList = $listParent.find('li.selectable'),\n\t\t$selected = $sizeList.filter('.selected'),\n\t\theight = parseInt($sizeList.first().css('height').replace(/px/, '')),\n\t\t$current;\n\n\t\tif ($selected.length <= 0) {\n\t\t\t$selected = $listParent.find('.focus-visible-indicator').closest('li.selectable') ? $selected : null;\n\t\t}\n\t\tif (!$selected || !$selected.length) {\n\t\t\t$current = $sizeList.eq(0);\n\t\t} else if (action == 'up') {\n\t\t\tif ($selected.is(':first-child')) {\n\t\t\t\t$current = $sizeList.eq(0);\n\t\t\t\t// If this is first list item, and user pressed Up Arrow, then we need to close the menu\n\t\t\t\tsizeMenuOpenClose(e, $defaultTextElement, false);\n\t\t\t} else {\n\t\t\t\t$current = $selected.prev();\n\t\t\t}\n\t\t} else {\n\t\t\tif (!$selected.next().hasClass('selectable')) {\n\t\t\t\t$current = $sizeList.last();\n\t\t\t\t// If this is last list item, and user pressed Down Arrow, then we need to close the menu\n\t\t\t\tsizeMenuOpenClose(e, $defaultTextElement, false);\n\t\t\t} else {\n\t\t\t\t$current = $selected.next();\n\t\t\t}\n\t\t}\n\n\t\tvar listParentTop = 0;\n\t\tvar listParentBottom = listParentTop + $listParent.height();\n\t\tvar currentTop = $current.position().top;\n\t\tvar currentBottom = currentTop + $current.height();\n\t\tvar faultPx = 10;\n\t\tif (currentBottom + faultPx > listParentBottom) {\n\t\t\t$listParent.scrollTop(parseInt($listParent.scrollTop()) + height);\n\t\t} else if (currentTop < listParentTop) {\n\t\t\t$listParent.scrollTop(parseInt($listParent.scrollTop()) - height);\n\t\t}\t\n\n\t\t//$current.parents('.attribute').first().find('.label .current, .select-dropdown .select-text').html($current.find('a').html());\n\t\t$sizeList.removeClass('selected tempselection');\n\t\t$current.addClass('selected tempselection').find('a').addClass('focus-visible-indicator').focus();\n\t\t// Needed to combat auto-scroll behavior that happens in previous line when focus added to <a>\n\t\tif ($current.is(':first-child')) {\n\t\t\t$listParent.scrollTop(0);\n\t\t}\n}\n\nfunction scrollToCurrentSize() {\n\tvar $listParent = $('div.product-variations ul.select-dropdown-inner'),\n\t\t$sizeList = $listParent.find('li.selectable'),\n\t\t$selected = $sizeList.filter('.selected'),\n\t\theight = $sizeList.first().css('height').replace(/px/, '');\n\n\tif ($selected) {\n\t\t$listParent.scrollTop(height * $sizeList.index($selected));\n\t}\n}\n\nfunction initializeImageGallery() {\n\tvar params;\n\tif (SitePreferences.PRIMARY_PRODUCT_SLIDER == 'swiperJS') { \n\t\timageGallery = require('../../components/ImageGallery/Swiper');\n\t\tif (SitePreferences.PRIMARY_PRODUCT_SLIDER_CONFIG) {\n\t\t\tparams = JSON.parse(SitePreferences.PRIMARY_PRODUCT_SLIDER_CONFIG);\n\t\t}\n\t} else {\n\t\timageGallery = require('../../components/ImageGallery/SlickAndImgViewer2');\n\t}\n\timageGallery.initialize(params);\n}\n\nfunction initializeBopis() {\n\tif ($('.bopis-add-to-cart-options-container').length > 0) {\n\t\tbopisAddToCartOptions.initialize($('.bopis-add-to-cart-options-container'), $.extend(options.Bopis, { Channel: options.Channel, ProductId: options.ProductId, StoreUIVersion: options.StoreUIVersion }));\n\t}\n\t\n\tif ($('.bopis-store-search').length > 0) {\n\t\tbopisStoreSearch.initialize($('.bopis-store-search'), $.extend(options.Bopis, { Channel: options.Channel }));\n\t}\n}\n\nfunction initialize(optionsParameter) {\n\toptions = optionsParameter;\n\tinitializeDom();\n\tinitializeEvents();\n\tinitializeBopis();\n}\n\nvar variant = {\n\tinitialize: initialize,\n\tinitializeDom: initializeDom,\n\tinitializeEvents: initializeEvents\n};\n\nmodule.exports = variant;","'use strict';\nvar direction, videoCount, width, height, videoCounter = 0, posValue = 0, lastCounter = 0, arrowPos;\n\nvar setCarousel = function(){\n\tvideoCount = $('.video-container ul li').length;\n\twidth = $('.video-container').width();\n\theight = width * 315 / 420;\n\t$('.youtube-video iframe').css({'width': width + 'px','height': height + 'px'});\n\twidth += 40;\n\tarrowPos = height / 2 - 20;\n\t$('.video-container .arrows .arrow').css('top', arrowPos + 'px');\n};\n\nvar arrowClick = function(arrow){\n\tdirection = arrow.hasClass('left') ? 'left' : 'right';\n\tlastCounter = videoCounter;\n\tif(direction == 'right'){\n\t\tif(videoCounter == (videoCount - 1)){\n\t\t\tposValue = 0;\n\t\t\tvideoCounter = 0;\n\t\t}\n\t\telse{\n\t\t\tvideoCounter++;\n\t\t\tposValue = videoCounter * width;\n\t\t}\n\t}\n\telse{\n\t\tif(videoCounter == 0){\n\t\t\tposValue = (videoCount - 1) * width;\n\t\t\tvideoCounter = videoCount - 1;\n\t\t}\n\t\telse{\n\t\t\tvideoCounter--;\n\t\t\tposValue = videoCounter * width;\n\t\t}\n\t}\n\t$('.video-container ul').animate({'left':'-' + posValue + 'px'}, 'fast');\n\tvar iframe = $('.youtube-video iframe:eq('+ lastCounter +')');\n\t$(iframe).attr('src', $(iframe).attr('src'));\n};\n\nmodule.exports = function () {\n\tsetCarousel();\n    $('.video-container .arrows .arrow').on('click', function(){\n    \tarrowClick($(this));\n    });\n};","'use strict';\n\nvar addProductToCart = require('./product/addToCart'),\n    ajax = require('../ajax'),\n    quickview = require('../quickview'),\n    util = require('../util');\n\n/**\n * @function\n * @description Loads address details to a given address and fills the address form\n * @param {String} addressID The ID of the address to which data will be loaded\n */\nfunction populateForm(addressID, $form) {\n    // load address details\n    var url = Urls.giftRegAdd + addressID;\n    ajax.getJson({\n        url: url,\n        callback: function (data) {\n            if (!data || !data.address) {\n                window.alert(Resources.REG_ADDR_ERROR);\n                return false;\n            }\n            // fill the form\n            $form.find('[name$=\"_addressid\"]').val(data.address.ID);\n            $form.find('[name$=\"_firstname\"]').val(data.address.firstName);\n            $form.find('[name$=\"_lastname\"]').val(data.address.lastName);\n            $form.find('[name$=\"_address1\"]').val(data.address.address1);\n            $form.find('[name$=\"_address2\"]').val(data.address.address2);\n            $form.find('[name$=\"_city\"]').val(data.address.city);\n            $form.find('[name$=\"_country\"]').val(data.address.countryCode).trigger('change');\n            $form.find('[name$=\"_postal\"]').val(data.address.postalCode);\n            $form.find('[name$=\"_state\"]').val(data.address.stateCode);\n            $form.find('[name$=\"_phone\"]').val(data.address.phone);\n            // $form.parent('form').validate().form();\n        }\n    });\n}\n\n/**\n * @private\n * @function\n * @description Initializes events for the gift registration\n */\nfunction initializeEvents() {\n    var $eventAddressForm = $('form[name$=\"_giftregistry\"]'),\n        $beforeAddress = $eventAddressForm.find('fieldset[name=\"address-before\"]'),\n        $afterAddress = $eventAddressForm.find('fieldset[name=\"address-after\"]');\n\n    $('.usepreevent').on('click', function () {\n        // filter out storefront toolkit\n        $(':input', $beforeAddress).not('[id^=\"ext\"]').not('select[name$=\"_addressBeforeList\"]').each(function () {\n            var fieldName = $(this).attr('name'),\n                $afterField = $afterAddress.find('[name=\"' + fieldName.replace('Before', 'After') + '\"]');\n            $afterField.val($(this).val()).trigger('change');\n        });\n    });\n    $eventAddressForm.on('change', 'select[name$=\"_addressBeforeList\"]', function () {\n        var addressID = $(this).val();\n        if (addressID.length === 0) { return; }\n        populateForm(addressID, $beforeAddress);\n    })\n    .on('change', 'select[name$=\"_addressAfterList\"]', function () {\n        var addressID = $(this).val();\n        if (addressID.length === 0) { return; }\n        populateForm(addressID, $afterAddress);\n    });\n\n    $('form[name$=\"_giftregistry_items\"]').on('click', '.item-details a', function (e) {\n        e.preventDefault();\n        var productListID = $('input[name=productListID]').val();\n        quickview.show({\n            url: e.target.href,\n            source: 'giftregistry',\n            productlistid: productListID\n        });\n    });\n\n}\n\nexports.init = function () {\n    initializeEvents();\n    addProductToCart();\n\n    util.setDeleteConfirmation('.item-list', String.format(Resources.CONFIRM_DELETE, Resources.TITLE_GIFTREGISTRY));\n};\n","'use strict';\n\nvar bootBarnExpressRefinementWizard = require('../BootBarnExpress/components/BootBarnExpressRefinementWizard');\nvar compareWidget = require('../compare-widget');\nvar dialog = require('../dialog');\nvar GoogleTagManagerClient = require('../../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar productTile = require('../product-tile');\nvar page = require('../page');\nvar sizeRefinements = require('../size-refinements');\nvar styleCounts = require('../style-counts');\nvar util = require('../util');\nvar wishlist = require('../wishlist');\nvar sliders = require('../sliders');\n\nvar ImageConstants;\n\nvar RefinementUIVersionConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/RefinementConstants').RefinementsUIVersions;\nvar SiteConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\nvar ValidationSettings = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Settings;\nvar ValidationRules = require('../../../../bc_sheplersbootbarn_core/cartridge/js/ValidationConstants').Rules;\n\nvar options;\nvar dataBuffer = [];\nvar $html = $('html');\nvar $refinementsInner = $('.refinements');\nvar refinementsExpanded;\nvar refinementsViewAll;\nvar loadingIndicatorSettings;\n\nvar $bootFinderEmailForm;\nvar bootFinderEmailValidator;\n\nvar previousSortApplied;\n\n/**\n * @private\n * @function\n * @description replaces breadcrumbs, lefthand nav and product listing with ajax and puts a loading indicator over the product listing\n */\nfunction updateProductListing(url, callback, isLoadMore) {\n    if (!url || url === window.location.href) {\n    \tif ($('body').attr('loading')) {\n    \t\t$('body').loading('destroy');\n    \t}\n\t\tif ($('.apply-refinements').hasClass('loading')) {\n    \t\t$('.apply-refinements').loading('destroy');\n    \t}\n\t\tif (typeof callback == 'function') {\n\t\t\tcallback();\n\t\t}\n        return;\n    }\n\n\tif (options.StoreUIVersion == '2024Redesign' || (options && options.Pagination && options.Pagination.Mode == 'LoadMore')) {\n\t\t$('.btn.load-more').loading({ IsImageShown: false });\n\t}\n\n    updateInventoryMessages(url);\n\tsaveExpandedRefinements();\n\t\n\t$.ajax({\n\t\turl: util.appendParamToURL(url, 'format', 'ajax'),\n\t\ttype: 'GET',\n\t\tsuccess: function(data) {\n\t\t\t$('body').removeClass('refinements-mobile-scroll-lock').css('top', '');\n\t\t\tif ($('body').attr('loading') == 'loading') {\n\t\t\t\t$('body').loading('destroy');\n\t\t\t}\n\n\t\t\thistory.pushState({}, '', url);\n\t\t\tvar $content = $(data);\n\t\t\tif (isLoadMore) {\n\t\t\t\tvar $productGrid = $content.find('#search-result-items');\n\t\t\t\tvar productTileCount = $productGrid.find('.grid-tile').length + $('#search-result-items').find('.grid-tile').length;\n\t\t\t\tvar productTotalCount = parseInt($content.find('.search-result-options.bottom .count').text().replace(/\\D/g, ''), 10);\n\t\t\t\tdataBuffer['PaginationCount'] = productTotalCount;\n\t\t\t\tdataBuffer['PaginationIndex'] += options.Pagination.Size;\n\t\t\t\t$('#search-result-items').append($productGrid.html());\n\t\t\t\t$('.search-result-options .display-count').text(productTileCount);\n\n\t\t\t\tif (productTileCount >= dataBuffer['PaginationCount']) {\n\t\t\t\t\t$('.btn.load-more').hide();\n\t\t\t\t} else {\n\t\t\t\t\t$('.btn.load-more').show();\n\t\t\t\t}\n\n\t\t\t\tif (options.StoreUIVersion == '2024Redesign' || (options && options.Pagination && options.Pagination.Mode == 'LoadMore')) {\n\t\t\t\t\t$('.btn.load-more').loading('destroy');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdataBuffer['PaginationIndex'] = 0;\n\t\t\t\t$('#main').html($content);\n\t\t\t\t\n\t\t\t\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t\t\t\t$('#grid-sort-header').selectmenu({\n\t\t\t\t\t\t'width': 205\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif ('variantInventoryMessagingUrl' in page && page.variantInventoryMessagingUrl) {\n\t\t\t\t\tshowVariantInventoryMessaging();\n\t\t\t\t}\n\n\t\t\t\tif (!checkForUpdatedRefinementHandling() && $('#primary').length > 0) {\n\t\t\t\t\t$('html,body').animate({\n\t\t\t\t\t\tscrollTop: $('#primary').offset().top\n\t\t\t\t\t}, 1000);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$refinementsInner = $('.refinements');\n\t\t\tredrawUpdatedRefinementHandling($content, url);\t\t\t\t\n\t\t\tcompareWidget.init();\n\t\t\tproductTile.init();\n\t\t\tsizeRefinements.init();\n\t\t\tinitializeRefinementControls();\t\t\t\n\t\t\tredrawShopMyStore();\n\t\t\tsliders.initializeCategorySliders('.main-content .category-landing-slider:not(.slick-initialized)');\n\t\t\twishlist.renderAllWishlistButtons();\n\n\t\t\tif ('affirm' in window && 'ui' in affirm && 'refresh' in affirm.ui) {\n\t\t\t\taffirm.ui.refresh();\n\t\t\t}\n\n\t\t\t$(document).trigger('CategoryHeaderSliders.Initialize');\n\t\t\t$(document).trigger('EinsteinProductRecommendations.Initialize');\n\t\t\tif ($('#categoryTitle').length > 0) {\n\t\t\t\tsetTimeout(function(){window.top.document.title = $('#categoryTitle').data('title');}, 3000);\n\t\t\t}\n\t\n\t\t\tinitializeThumbDataLayer(url);\n\n\t\t\tif (options.StyleCountCache) {\n\t\t\t\tstyleCounts.render(options.StyleCountCache);\n\t\t\t}\n\t\t\t\n\t\t\tif (typeof callback == 'function') {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t},\n\t\tcomplete: function(data, status, xhr) {\n\t\t\tif ((data.status == 301 || data.status == 302) && data.responseText) {\n\t\t\t\tlocation.href = data.responseText;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction updateInventoryMessages(url, callback) {\n\tvar urlParams = util.getQueryStringParams(url);\n\n\tvar inventoryLinkUrl = Urls.getInventoryLink;\n\tfor (var urlParameter in urlParams) {\n\t\tif (urlParams[urlParameter]) {\n\t\t\tinventoryLinkUrl = util.appendParamToURL(inventoryLinkUrl, urlParameter, urlParams[urlParameter]);\n\t\t}\n\t}\n\n\t$.post(inventoryLinkUrl, function(data) {\n\t\tvar dataObj = JSON.parse(data);\n\t\t\n\t\tif (dataObj.status && dataObj.url.length) {\n\t\t\tvar newUrl = dataObj.url;\n\t\t\t\n\t\t\tif (urlParams.hasOwnProperty('start') && urlParams.start > 0) {\n\t\t\t\tnewUrl = util.appendParamToURL(newUrl, 'start', urlParams.start);\n\t\t\t}\n\t\t\t\n\t\t\tif (urlParams.hasOwnProperty('sz')) {\n\t\t\t\tnewUrl = util.appendParamToURL(newUrl, 'sz', urlParams.sz);\n\t\t\t}\n\t\t\t\n\t\t\tpage.variantInventoryMessagingUrl = newUrl;\n\t\t}\n\t\t \n\t\ttypeof callback == 'function' && callback();\n\t});\n}\n\nfunction getUrlParams(url) {\n\tvar vars = {};\n\n\tvar parts = url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {\n\t\tvars[key] = value;\n    });\n\n\treturn vars;\n}\n\nfunction initializeThumbDataLayer(url) {\n\tvar data = {};\n\t\n\tvar currentCategoryId = $('.currCGID').val();\n\tif (currentCategoryId && currentCategoryId != 'null') {\n\t\tdata.cgid = currentCategoryId;\n\t}\n\t\n\tif (getUrlParams(url)['sz']) {\n\t\tdata.sz = getUrlParams(url)['sz'];\n\t}\n\t\n\tif (getUrlParams(url)['start']) {\n\t\tdata.start = getUrlParams(url)['start'];\n\t}\n\t\n\tif (getUrlParams(url)['q']) {\n\t\tdata.q = decodeURIComponent(getUrlParams(url)['q']);\n\t}\n\t\n\tif (getUrlParams(url)['srule']) {\n\t\tdata.srule = decodeURIComponent(getUrlParams(url)['srule']);\n\t}\n\t\n\tfor (var preferenceIndex = 1; preferenceIndex < 9; preferenceIndex++) {\n\t\tif (getUrlParams(url)['prefn' + preferenceIndex]) {\n\t\t\tdata['prefn' + preferenceIndex] = decodeURIComponent(getUrlParams(url)['prefn' + preferenceIndex]);\n\t\t}\n\t\t\n\t\tif (getUrlParams(url)['prefv' + preferenceIndex]) {\n\t\t\tdata['prefv' + preferenceIndex] = decodeURIComponent(getUrlParams(url)['prefv' + preferenceIndex]);\n\t\t}\n\t}\n\t\n\tGoogleTagManagerClient.PushDataLayerForPage(pageContext);\n}\n\nfunction filterRefinements(container, filterText) {\n\tcontainer.find('.checks label').each(function() {\n\t\tvar $filter = $(this);\n\t\tif (filterText === \"\") {\n\t\t\t// Reset filter\n\t\t\t$filter.parent().show();\n\t\t}\n\t\telse {\n\t\t\tvar labelText = $filter.html().trim().toUpperCase();\n\t\t\tif (labelText.indexOf(filterText) > -1) {\n\t\t\t\t$filter.parent().show();\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$filter.parent().hide();\n\t\t\t}\n\t\t}\n\t});\n}\n\n/**\n * @private\n * @function\n * @description Initializes the following search refinement controls:<br/>\n * <p>scroll bar</p>\n * <p>section dropdowns</p>\n * <p>range slider</p>\n * <p>textbox filter</p>\n */\nfunction initializeRefinementControls() {\n\tif ($('.refinements .refinement:visible').length > 2) {\n\t\t$('.refinements .show-all-refinements').addClass('active');\n\t}\n\t\n\tif ($('.refinement input:checked, .refinement [refinement-value].modified:not(:checked)').length > 0) {\n\t\t$('.refinements').addClass('refinements-applied');\n\t}\n\t\n\t// handle toggle refinement blocks\n\t$('.refinement:not(.disabled) .toggle').off('click');\n\t$('.refinement:not(.disabled) .toggle').on('click', function (event) {\n\t\tvar $this = $(this);\n\t\tvar $refinementBody = $this.parent().find('.refinement-body');\n\n\t\tif (!$this.hasClass('expanded')) {\n\t\t\t$this.closest('.refinement').addClass('expanded');\n\t\t} else {\n\t\t\t$this.closest('.refinement').removeClass('expanded');\n\t\t\t\n\t\t}\n\t\t$this.toggleClass('expanded');\n\t\tif ($this.hasClass('expanded')) {\n\t\t    $refinementBody.stop().show();\n        } else {\n\t\t\t$refinementBody.stop().hide();\n        }\n\t\t\n\t\tif ($('.refinement.expanded').length > 0) {\n\t\t\t$('.refinements').addClass('refinement-expanded');\n\t\t} else {\n\t\t\t$('.refinements').removeClass('refinement-expanded');\n\t\t}\n\t\t\n\t\tif ($this.closest('.show-all-refinements').length > 0) {\n\t\t\t$this.parent().toggleClass('expanded');\n\t\t\treturn;\n\t\t}\n\n\t\tsaveExpandedRefinements();\n\t\tif (options.StoreUIVersion == '2024Redesign') {\n\t\t\tupdateSelectedRefinements();\n\t\t}\n\t\t$(document).trigger('StickyRefinements.Refresh');\n\t\t\n\t\tsetTimeout(function(){\n\t\t\tvar cssClass = $this.parent().attr('class');\n\t\t\tvar refinementGroup = $.trim(cssClass.replace(/refinement/, ''));\n\t\t\trefGroupsStates.saveState(refinementGroup, $this.hasClass('expanded'));\n\t\t}.bind(this), 30);\n\t});\n\n\t$('.refinement .form-row input[type=text]').on('input', function() {\n\t\tvar $input = $(this);\n\n\t    window.clearTimeout($input.data(\"timeout\"));\n\t    $input.data(\"timeout\", setTimeout(function () {\n\t    \tfilterRefinements($input.parents('.refinement').first(), $input.val().trim().toUpperCase());\n\t    }, 1000));\n\t});\n\n\tpriceSlider();\n}\n\n/**\n * @private\n * @function\n * @description Initializes events for the following elements:<br/>\n * <p>refinement blocks</p>\n * <p>updating grid: refinements, pagination, breadcrumb</p>\n * <p>item click</p>\n * <p>sorting changes</p>\n */\nfunction initializeEvents() {\n\t/*\n\t * Added a JS for search result page to prevent refinement from having a margin-top even the header is not showing\n\t */\n\tif ((options.RefinementsUIVersion != RefinementUIVersionConstants.Updated) && window.innerWidth < 767) {\n\t\tif($(\".search-phrase-container\").length) {\n\t\t\t$('.pt_product-search-result #secondary .refinements-inner').css({'margin-top': '60px'});\n\t\t}\n\t}\n\n\t$(window).on('resize', function() {\n\t\tif ((options.RefinementsUIVersion == RefinementUIVersionConstants.Updated) && window.innerWidth > 767) {\n\t\t\t$('.modified').removeClass('modified').prop('checked', !$('.modified').prop('checked'));\n\t\t}\n\t});\n\n\t$(document).ready(function() {\n\t\t$(\"body\").delegate(\".product-swatches-all\", \"click\", function() {\n\t\t\t$(this).parent().find(\".swatch-list li\").removeClass('hide');\n\t\t});\n\n\t\tpreviousSortApplied = $('#grid-sort-header').find('option:selected').text();\n\t});\n\n\tvar $main = $('#main');\n    // compare checked\n    $main.on('click', 'input[type=\"checkbox\"].compare-check', function () {\n        var cb = $(this);\n        var tile = cb.closest('.product-tile');\n\n        var func = this.checked ? compareWidget.addProduct : compareWidget.removeProduct;\n        var itemImg = tile.find('.product-image a img').first();\n        func({\n            itemid: tile.data('itemid'),\n            uuid: tile[0].id,\n            img: itemImg,\n            cb: cb\n        });\n    });\n\n    $(document).off('click.Toggle.Refinements').on('click.Toggle.Refinements', '.toggle-refinements', function(event) {\n    \tevent.preventDefault();\n    \t\n    \tif (!$('.refinements-inner-container').hasClass('open')) {\n\t     \t$('.refinements-inner-container').find('.toggle.expanded, .toggle.selected, .refinement.expanded').removeClass('expanded selected');\n\t     \t$('.refinements').removeClass('refinement-expanded');\n\t     \t$('.refinement-body').hide();\n    \t}\n    \t\n    \ttoggleBodyScrollLock();\n    \t$('.refinements-inner-container').toggleClass('open');\n    \tredrawUpdatedRefinementHandling();\n    });\n    \n    $main.off('click.Toggle.Sorting').on('click.Toggle.Sorting', '.toggle-sort', function(event) {\n    \tevent.preventDefault();\n    \t\n\t\t$('.sort-by.modal').toggle();\n\t\t$('.sort-by.modal').toggleClass('open');\n\t\t$('#search-result').toggleClass('active');\n\t\t\n    });\n    \n    $main.off('click.Select.Sorting').on('click.Select.Sorting', '.sort-by.modal input', function(event) {\n    \tevent.stopImmediatePropagation();\n    \t\n    \tvar $this = $(this);\n\t\t$('.sort-by.modal').toggle();\n\t\t$('.sort-by.modal').toggleClass('open');\n\t\t$('body').loading(loadingIndicatorSettings);\n\t\tupdateProductListing($this.val());\n    });\n    \n    // handle events for updating grid\n    $main.on('click', '.refinements-head a, .refinements-inner a, .pagination-bar a, .breadcrumb-refinement-value a', function (e) {\n\t\tvar $this = $(this);\n\n    \tif (!$this.hasClass('ref-filter') && checkForUpdatedRefinementHandling()) {\n    \t\te.preventDefault();\n    \t\tvar refinementValue = $this.attr('value');\n    \t\t\n    \t\t$this.closest('.refinement-body-inner').find('li[refinement-value=\"' + refinementValue + '\"], a[value=\"' + refinementValue + '\"]').toggleClass('modified');\n    \t\tredrawUpdatedRefinementHandling();\n    \t\treturn;\t\n    \t}\n    \t\n        // don't intercept for category and folder refinements, as well as unselectable\n        if ($this.parents('.category-refinement').length > 0 || $this.parents('.folder-refinement').length > 0 || $this.parent().hasClass('unselectable')) {\n            return;\n        }\n        e.preventDefault();\n\n\t\tvar activeRefinementsCount = $('[refinement-value].selected').length - $('.swatches[class*=\"popular-\"] [refinement-value].selected').length;\n\t\tif ($this.parent().hasClass('selected') && activeRefinementsCount == 1 && options.CategoryLandingPageContent && options.CategoryLandingPageContent.Url) {\n\t\t\tlocation.href = options.CategoryLandingPageContent.Url;\n    \t\treturn;\n\t\t}\n\n        if ($this.hasClass('breadcrumb-element') && $this.attr('href') != null) {\n    \t\tlocation.href = this.href;\n    \t\treturn;\n        }\n\n        // hide or show/expand all refinement items\n        if ($this.hasClass('ref-filter')) {\n        \tvar ref = '.' + $(this).data('ref');\n        \t$(ref).find('.toggleable').toggleClass('hidden');\n        \tif ($this.hasClass('more-link')) {\n        \t\t$this.parents('li').hide().closest('.refinement').addClass('more-expanded');\n        \t} else {\n        \t\t$(ref).find('.more-link').parents('li').show().closest('.refinement').removeClass('more-expanded');\n        \t}\n\t\t\tsaveExpandedRefinements();\n        \treturn;\n        }\n\n\t\tif ($this.length > 0 && !$('html').hasClass('size-mobile')) {\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t}\n\n\t\tif (SitePreferences.GA_NEW_ACTIONS_ENABLED) {\n\t\t\tvar refinementId = $this.closest('[refinement-id]').attr('refinement-id') || null;\n\t\t\tvar refinementValue = $this.attr('value') ? $this.attr('value').replace('\"',\" INCH\") : null;\n\t\t\tif (refinementId && refinementValue) {\n\t\t\t\tvar refinementAnalyticsTaggingData =  { \n\t\t\t\t\t'action_name': 'filter',\n\t\t\t\t\t'action_page_type': 'plp',\n\t\t\t\t\t'action_value': refinementId, \n\t\t\t\t\t'action_items': refinementValue\n\t\t\t\t};\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('Event', refinementAnalyticsTaggingData);\n\t\t\t}\n\t\t}\n\n        updateProductListing(this.href);\n\n\t\tvar selection = $('div.product-selections ul li');\n\t\tvar refGroup = $(selection[selection.length-2]).find('span:first').data('refgroup-id');\n\t\tif (refGroup && refGroup.length > 0 && refGroupsStates.checkState(refGroup)) {\n\t\t\t$('#refinements-inner .refinement.'+refGroup+' .toggle')[0].click();\n\t\t}\n    });\n\n    // handle events item click. append params.\n    $main.on('click', '.product-tile a:not(\"#quickviewbutton\")', function () {\n        var a = $(this);\n        // get current page refinement values\n        var wl = window.location;\n\n        var qsParams = (wl.search.length > 1) ? util.getQueryStringParams(wl.search.substr(1)) : {};\n        var hashParams = (wl.hash.length > 1) ? util.getQueryStringParams(wl.hash.substr(1)) : {};\n\n        // merge hash params with querystring params\n        var params = $.extend(hashParams, qsParams);\n        if (!params.start) {\n            params.start = 0;\n        }\n        // get the index of the selected item and save as start parameter\n        var tile = a.closest('.product-tile');\n        var idx = tile.data('idx') ? + tile.data('idx') : 0;\n\n        // convert params.start to integer and add index\n        params.start = (+params.start) + (idx + 1);\n        // set the hash and allow normal action to continue\n        a[0].hash = $.param(params);\n    });\n\n    // handle sorting change\n    $main.on('change', '.sort-by select', function (e) {\n        e.preventDefault();\n        \n\t\tif ($('html').hasClass('size-mobile')) {\n\t\t\tvar isSortingChanged = false;\n\t\t\tvar $sortingRule = $('.modal.open .sort-by option:checked');\n\t\t\tif ($sortingRule && $sortingRule.length > 0) {\n\t\t\t\tisSortingChanged = !$sortingRule.attr('selected');\n\t\t\t}\n\n\t\t\tif (isSortingChanged || $refinementsInner.find('[refinement-value].modified, .list-selections .value.pending-clear').length > 0) {\n\t\t\t\t$refinementsInner.addClass('refinements-modified');\n\t\t\t\t$('.refinements-inner-container-footer .apply-refinements').removeClass('disabled');\n\t\t\t} else {\n\t\t\t\t$refinementsInner.removeClass('refinements-modified');\n\t\t\t\t$('.refinements-inner-container-footer .apply-refinements').addClass('disabled');\n\t\t\t}\n\t\t} else {\n\t\t\t$('body').loading(loadingIndicatorSettings);\t\t\n\t\t\tvar selectedSort = $(this).find('option:selected').val();\n\n\t\t\tif (SitePreferences.GA_NEW_ACTIONS_ENABLED) {\n\t\t\t\tvar newSortValue = $(this).find('option:selected').text();\n\t\t\t\tvar oldSortValue = previousSortApplied ? previousSortApplied : 'Top Sellers';\n\t\t\t\tif (newSortValue && oldSortValue) {\n\t\t\t\t\tvar sortAnalyticsTaggingData =  { \n\t\t\t\t\t\t'action_name': 'sort',\n\t\t\t\t\t\t'action_page_type': 'plp',\n\t\t\t\t\t\t'action_value': newSortValue, \n\t\t\t\t\t\t'action_items': 'from ' + oldSortValue\n\t\t\t\t\t};\n\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('Event', sortAnalyticsTaggingData);\n\t\t\t\t}\n\t\t\t\tpreviousSortApplied = newSortValue;\n\t\t\t}\n\n\t\t\tif ($(this).attr('id') == 'mobile-sort'){\n\t\t\t\tupdateProductListing(selectedSort);\n\t\t\t} else {\n\t\t\t\tif (checkForUpdatedRefinementHandling()) {\n\t\t\t\t\tupdateProductListing(selectedSort);\n\t\t\t\t} else {\n\t\t\t\t\tdocument.location.href = selectedSort;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n    });\n\n\t$('.search-result-page').on('click', '#grid-sort-header-menu li', function () {\n\t\t$('.sort-by select').prop('selectedIndex', $(this).index()).first().trigger('change');\n\t});\n\n    $main.on('change', '.items-per-page select', function () {\n        var refineUrl = $(this).find('option:selected').val();\n        if (refineUrl === 'INFINITE_SCROLL') {\n            $('html').addClass('infinite-scroll').removeClass('disable-infinite-scroll');\n        } else {\n            $('html').addClass('disable-infinite-scroll').removeClass('infinite-scroll');\n            updateProductListing(refineUrl);\n        }\n\t});\n\n\t$main.on('click', '.mobile-refinements .toggle-button', function() {\n\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS && options.RefinementsUIVersion != RefinementUIVersionConstants.Updated) {\n\t\t\tif ($(this).hasClass('sort-by-toggle')) {\n\t\t\t\t\n\t\t\t\t//Ensure both sort-by and refinements aren't open simultaneously \n\t\t\t\t$('#secondary.refinements').removeClass('active');\n\t\t\t\t$('.mobile-refinements .refine-toggle').removeClass('active');\n\n\t\t\t\t//container for new sorting options\n\t\t\t\tvar sortByOptionsContainer = $('.mobile-refinements .sort-by-options');\n\t\t\t\tif(sortByOptionsContainer.html().length < 1) {\n\n\t\t\t\t\t//sort-by form for reference and pulling options\n\t\t\t\t\tvar currentSortByOptions = $('.mobile-refinements #sort-by #grid-sort-header option');\n\n\t\t\t\t\tsortByOptionsContainer.append(\"<ul class='sort-by-list'></ul>\");\n\n\t\t\t\t\t//create new list with data linked to form\n\t\t\t\t\tcurrentSortByOptions.each(function() {\n\t\t\t\t\t\tvar selectedValue = $(this).prop('selected');\n\n\t\t\t\t\t\tif (typeof selectedValue !== typeof undefined && selectedValue !== false) {\n\t\t\t\t\t\t\tvar newOption = '<li class=\"selectable-option selected\" data-option-for=\"'  + $(this).attr('value') + '\">' + $(this).text() + '</li>';\n\t\t\t\t\t\t\tsortByOptionsContainer.find('ul').append(newOption);\n\t\t\t\t\t\t} else  {\n\t\t\t\t\t\t\tvar newOption = '<li class=\"selectable-option\" data-option-for=\"'  + $(this).attr('value') + '\">' + $(this).text() + '</li>';\n\t\t\t\t\t\t\tsortByOptionsContainer.find('ul').append(newOption);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t//toggle sort-by options to active state\n\t\t\t\t$('.mobile-refinements .sort-by-options').toggleClass('active');\n\t\t\t\t$(this).toggleClass('active');\n\t\t\t} else if ($(this).hasClass('refine-toggle')) {\n\t\t\t\t//Ensure both sort-by and refinements aren't open simultaneously\n\t\t\t\t$('.mobile-refinements .sort-by-options').removeClass('active');\n\t\t\t\t$('.mobile-refinements .sort-by-toggle').removeClass('active');\n\t\t\t\t//toggle refinements options to active state\n\t\t\t\t$('#secondary.refinements').toggleClass('active');\n\t\t\t\t$(this).toggleClass('active');\n\t\t\t}\n\t\t}\t\n\t});\n\t$main.on('click', '.sort-by-options .sort-by-list .selectable-option', function() {\n\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t\t//set correct sort-by form option as selected\n\t\t\tvar optionValue = $(this).attr('data-option-for');\n\t\t\t$('.mobile-refinements .sort-by#sort-by form #grid-sort-header option[value=\"'+optionValue+'\"]').prop('selected', true);\n\t\t\t//Trigger form change to fire sort-by change watcher\n\t\t\t$('.mobile-refinements .sort-by#sort-by form #grid-sort-header option').change();\n\t\t}\n\t});\n\n    // refinement checkboxes\n    $main.on('click', '.refinement .checks input', function (event) {\n\t\tvar $this = $(this);\n\t\tvar $refinement = $this.closest('[refinement-value]');\n\t\tif ($refinement.length > 0 && !$('html').hasClass('size-mobile')) {\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t}\n\n\t\tif ($this.closest('.refinement.sort-by').length > 0) {\n\t\t\t$this.closest('.refinement-body').find('[refinement-value] input').not($this).removeClass('modified').prop('checked', false);\n\t\t\t$this.toggleClass('modified');\n\t\t}\n    \tif (checkForUpdatedRefinementHandling()) {\n\t\t\tvar refinementValue = $this.val().replace('\"',\" INCH\");\n    \t\tif ($this.closest('[is-price-refinement=\"true\"]').length > 0) {\n\t\t\t\t$('[is-price-refinement=\"true\"] input').not($this).prop('checked', false).removeAttr('checked').removeClass('modified');\n\t\t\t\t$refinement.toggleClass('modified');\n\t\t\t} else {\n\t\t\t\tvar $equalValueInputs = $this.closest('.refinement-body').find('[refinement-value=\"' + refinementValue + '\"]');\n\t    \t\t$equalValueInputs.toggleClass('modified');\n\t    \t\t$equalValueInputs.not($this).prop('checked', $this.prop('checked'));\n    \t\t}\n    \t\tredrawUpdatedRefinementHandling();\n    \t\treturn;\t\n    \t}\n\n\t\tif (SitePreferences.GA_NEW_ACTIONS_ENABLED && $this.is(':checked')) {\n\t\t\tvar refinementId = $this.closest('[refinement-id]').attr('refinement-id') || null;\n\t\t\tvar refinementValue = $this.val() ? $this.val().replace('\"',\" INCH\") : null;\n\t\t\tif (refinementId && refinementValue) {\n\t\t\t\tvar refinementAnalyticsTaggingData =  { \n\t\t\t\t\t'action_name': 'filter',\n\t\t\t\t\t'action_page_type': 'plp',\n\t\t\t\t\t'action_value': refinementId, \n\t\t\t\t\t'action_items': refinementValue\n\t\t\t\t};\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('Event', refinementAnalyticsTaggingData);\n\t\t\t}\n\t\t}\n\n\t\tvar url = $(this).parents('li').first().find('.visually-hidden > a').first().attr('href');\n\n\t\tupdateProductListing(url);\n    });\n\n    $main.on('click', '.result-options .switch input[name=\"field-switch\"]', function () {\n    \tif (checkForUpdatedRefinementHandling()) {\n    \t\tupdateProductListing($(this).parents('.switch').find('.visually-hidden input[name=\"field-true\"] + a').first().attr('href'));\n    \t} else {\n    \t\tdocument.location = $(this).parents('.switch').find('.visually-hidden input[name=\"field-true\"] + a').first().attr('href');\n    \t}\n    });\n\n    $(document).on('click', '.list-selections li:not(.pending-selections) a.close-btn, .clear-all .close-btn', function (e) {\n    \te.preventDefault();\n\n    \tvar $this = $(this);\n    \tif ($this.closest('.value').hasClass('applied') && $this.closest('.modal').length > 0) {\n    \t\t$this.closest('.value').toggleClass('pending-clear');\n    \t\tredrawUpdatedRefinementHandling();\n    \t\treturn;\t\n    \t}\n\n\t\t$('body').loading(loadingIndicatorSettings);\n\t\tvar activeRefinementsCount = $('[refinement-value].selected').length - $('.swatches[class*=\"popular-\"] [refinement-value].selected').length;\n\t\tif (activeRefinementsCount == 1 && options.CategoryLandingPageContent && options.CategoryLandingPageContent.Url) {\n\t\t\tlocation.href = options.CategoryLandingPageContent.Url;\n    \t\treturn;\n\t\t}\n\n    \tvar href = $this.attr('href');\n    \tif (href == null || href == 'null') {\n    \t\tvar search = document.location.search;\n    \t\tupdateProductListing(document.location.pathname + search.substr(0, search.indexOf('&')));\n    \t} else {\n    \t\tupdateProductListing(href);\n    \t}\n\t});\n    \n    $(document).on('click', '.list-selections li.pending-selections a.close-btn', function (e) {\n    \te.preventDefault();\n\n    \tvar pendingRefinementId = $(this).closest('[data-refgroup-id]').attr('data-refgroup-id');\n    \tvar pendingRefinementValue = $(this).closest('span').attr('refinement-value');\n\t\tvar selector = '[refinement-id=\"' + pendingRefinementId + '\"] ul [refinement-value=\"' + pendingRefinementValue + '\"]';\n\n    \tvar $pendingRefinementInput = $refinementsInner.find(selector);    \t\n    \tif ($pendingRefinementInput.find('input').length > 0) {\n    \t\t$pendingRefinementInput.find('input').click();\n    \t} else if ($pendingRefinementInput.find('a').length > 0) {\n    \t\t$pendingRefinementInput.find('a').click();\n    \t}\n\t});\n    \n    $main.on('click', '.product-swatches-accordion-button', function () {\n    \tvar $accordion = $(this).closest('.accordion');\n    \t\n    \tif ($accordion.length > 0) {\n    \t\t$accordion.toggleClass('active');\n    \t}\n    });\n\n\t$(document).off('click.ShopMyStore', '.shop-my-store .checkbox-toggle input').on('click.ShopMyStore', '.shop-my-store .checkbox-toggle input', function(event) {\n\t\tvar $this = $(this);\n\n\t\tvar url;\n\t\tif ($this.prop('checked'))  {\n\t\t\turl = $this.attr('href-refine');\n\t\t} else {\n\t\t\turl = $this.attr('href-relax');\n\t\t\t$('body').attr('is-shop-my-store-active', false);\n\t\t}\n\n\t\tif (url) {\n\t\t\t$('.shop-my-store .checkbox-toggle').loading({ IsLabelShown: false, IsImageShown: false });\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\n\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ShopYourStore', { enabled: $this.prop('checked') });\n\n\t\t\turl = util.appendParamToURL(url, 'shopmystore', $this.prop('checked'));\n\t\t\tupdateProductListing(url);\n\t\t} else {\n\t\t\tevent.preventDefault();\n\t\t}\n    });\n\n\t$(document).off('ShopMyStore.Update').on('ShopMyStore.Update', function(event, storeId) {\n\t\tif ($('.shop-my-store .checkbox-toggle input').prop('checked')) {\n\t\t\tvar url = location.protocol + '//' + location.hostname + location.pathname;\n\t\t\tvar queryStringParameters = util.getQueryStringParams(location.search);\n\t\t\tfor (var queryStringParameterKey in queryStringParameters) {\n\t\t\t\tvar queryStringParameterValue = queryStringParameters[queryStringParameterKey];\n\t\t\t\tif (queryStringParameterValue && queryStringParameterValue.indexOf('availableStores') > -1) {\n\t\t\t\t\tvar refinementIndex;\n\t\t\t\t\tvar refinementIndexMatch = queryStringParameterKey.match(/prefn([0-9])+/);\n\t\t\t\t\tif (refinementIndexMatch && refinementIndexMatch.length > 1) {\n\t\t\t\t\t\trefinementIndex = refinementIndexMatch[1];\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\n\t\t\tif (refinementIndex && storeId) {\n\t\t\t\tqueryStringParameters['prefv' + refinementIndex] = storeId;\n\t\t\t}\n\t\n\t\t\tfor (var queryStringParameterKey in queryStringParameters) {\n\t\t\t\tvar queryStringParameterValue = queryStringParameters[queryStringParameterKey];\n\t\t\t\tif (queryStringParameterKey != 'start' && queryStringParameterKey != 'sz') {\n\t\t\t\t\turl = util.appendParamToURL(url, queryStringParameterKey, queryStringParameterValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$('body').loading({\n\t\t\t\tIsImageShown: false,\n\t\t\t\tContent: '<h6>Hold Your Horses!</h6><p>Your selections are loading...</p>',\n\t\t\t\tCssClass: 'shopyourstore',\n\t\t\t\tBackgroundColor: 'transparent'\n\t\t\t});\n\n\t\t\tupdateProductListing(url);\n\t\t} else {\n\t\t\tredrawShopMyStore();\n\t\t}\n\t});\n\n    searchStores();\n    initializeRefinementControls();\n\tif (pageContext.site === SiteConstants.SiteIds.BootBarnUS) {\n\t\t$('#grid-sort-header').selectmenu({\n\t\t\t'width': 205\n\t\t});\n\t}\n    \n    $main.on('click', '.apply-refinements:not(.disabled)', function(event) {\n    \tevent.preventDefault();\n\t\t$(this).attr('data-apply-refinements','true');\n    \t\n\t\tvar pendingRefinementsDelta = $('#secondary [refinement-value]:not(.selected):not([class*=\"popular\"]).modified').length - $('#secondary [refinement-value].selected:not([class*=\"popular\"]).modified').length;\n\t\tvar activeRefinementsCount = $('#secondary [refinement-value].selected').length - $('#secondary .swatches[class*=\"popular-\"] [refinement-value].selected').length - $('#secondary .list-selections .pending-clear').length + pendingRefinementsDelta;\n\t\tif (activeRefinementsCount == 0 && options.CategoryLandingPageContent && options.CategoryLandingPageContent.Url) {\n\t\t\tlocation.href = options.CategoryLandingPageContent.Url;\n    \t\treturn;\n\t\t}\n\n\t\tif (SitePreferences.GA_NEW_ACTIONS_ENABLED) {\n\t\t\tvar $refinement =  $('.refinements').find('[refinement-id]:not(.sort-by)');\n\t\t\tvar $selectedRefinements = $refinement.find('ul:not([class*=\"popular\"]) li[refinement-value]:not(.selected).modified, ul:not([class*=\"popular\"]) li[refinement-value].selected:not(.modified)');\n\t\t\tif ($selectedRefinements.length > 0) {\n\t\t\t\tvar refinementId, refinementValue;\n\t\t\t\t$selectedRefinements.each(function () {\n\t\t\t\t\trefinementId = $(this).closest('[refinement-id]').attr('refinement-id');\n\t\t\t\t\trefinementValue = refinementId.toUpperCase() == 'PRICE' ? $(this).find('.refinement-label').text().replace(/\\s+/g, ' ').trim() : $(this).attr('refinement-value').replace(' INCH','\"');\n\t\t\t\t\tif (refinementId && refinementValue) {\n\t\t\t\t\t\tvar refinementAnalyticsTaggingData =  { \n\t\t\t\t\t\t\t'action_name': 'filter',\n\t\t\t\t\t\t\t'action_page_type': 'plp',\n\t\t\t\t\t\t\t'action_value': refinementId, \n\t\t\t\t\t\t\t'action_items': refinementValue\n\t\t\t\t\t\t};\n\t\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('Event', refinementAnalyticsTaggingData);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\t\n\t\t\t\n\t\t\t// The newSortValue will only be populated if a change to sort has occurred, and GA tagging only gets fired if newSortValue has data\n\t\t\tvar newSortValue = $('#mobile-sort option:checked').length > 0 ? $('#mobile-sort option:checked')[0].label : null;\n\t\t\tvar oldSortValue = previousSortApplied ? previousSortApplied : 'Top Sellers';\n\t\t\tif (newSortValue && oldSortValue) {\n\t\t\t\tvar sortAnalyticsTaggingData =  { \n\t\t\t\t\t'action_name': 'sort',\n\t\t\t\t\t'action_page_type': 'plp',\n\t\t\t\t\t'action_value': newSortValue, \n\t\t\t\t\t'action_items': 'from ' + oldSortValue\n\t\t\t\t};\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('Event', sortAnalyticsTaggingData);\n\t\t\t}\n\t\t\tpreviousSortApplied = newSortValue;\n\t\t}\n\t\t\n    \t$('body').loading(loadingIndicatorSettings);\n    \tupdateProductListing(buildUrlForSelectedRefinements(null, null, false, true));\n    });\n    \n    $main.on('click', '.clear-refinements:not(.disabled)', function(event) {\n    \tevent.preventDefault();\n    \t\n    \tvar $this = $(this);\n    \tvar href = $this.attr('href');\n    \tvar $refinementsModalProductSelections = $('.refinements-inner-container-header .product-selections');\n    \t\n    \tif ($refinementsModalProductSelections.find('.list-selections .value.applied').length > 0) {\n    \t\tif (checkForUpdatedRefinementHandling()) {\n    \t\t\t$('.clear-refinements').loading({\n    \t\t\t\tIsImageShown: false\t\n    \t\t\t});\n    \t\t\tupdateProductListing($(this).attr('href'));\n    \t\t} else {\n    \t\t\tdocument.location = $(this).attr('href');\n    \t\t}\n    \t} else {\n    \t\t$('.refinement[uuid]').find('li[refinement-value]:not(.selected).modified').removeClass('modified');\n    \t\t$('.refinement[uuid]').find('li[refinement-value]:not(.selected)').find('input:checked').prop('checked', false);\n    \t\tredrawUpdatedRefinementHandling();\n    \t}\n    });\n\n\t$(document).on('click', '#main .btn.load-more:not(.disabled)', function(event) {\n\t\tevent.preventDefault();\n\t\tvar $loadMoreButton = $(this);\n\n\t\t// Let's disable the button after first click, so that functionality can complete before being re-enabled\n\t\t$loadMoreButton.addClass('disabled');\n\n\t\tif (!dataBuffer['PaginationIndex']) {\n\t\t\tdataBuffer['PaginationIndex'] = options.Pagination.Start;\n\t\t}\n\t\tif (!dataBuffer['PaginationCount']) {\n\t\t\tdataBuffer['PaginationCount'] = options.Pagination.Count;\n\t\t}\n\t\t\n\t\tvar url = document.location.href;\n\t\tvar currentQueryStringParameters = util.getQueryStringParams(util.getQueryString(url));\n\t\tif (currentQueryStringParameters['start']) {\n\t\t\turl = util.removeParamFromURL(url, 'start');\n\t\t}\n\t\turl = util.appendParamToURL(url, 'start', dataBuffer['PaginationIndex'] + options.Pagination.Size);\n\n\t\tupdateProductListing(url, function() {\n\t\t\t// Use the callback function to re-enable the Load More button\n\t\t\t$loadMoreButton.removeClass('disabled');\n\t\t}, true);\n\t});\n}\n\nfunction toggleBodyScrollLock() {\n\tvar $body = $('body');\n\tvar bodyScrollLockClass = 'refinements-mobile-scroll-lock';\n\n\tif ($body.hasClass(bodyScrollLockClass)) {\n\t\t$body.removeClass(bodyScrollLockClass);\n\t\t$body.css('top', '');\n\t\tdocument.body.scrollTop = document.documentElement.scrollTop = dataBuffer['scrollTop'];\n\t} else {\n\t\tvar scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n    \tdataBuffer['scrollTop'] = scrollTop;\n    \t$body.css('top', 0 - scrollTop);\n    \t$body.addClass(bodyScrollLockClass);\n\t}\n}\n\nfunction buildUrlForSelectedRefinements(baseUrl, urlForParameters, includeCategory, includeSort) {\n\tvar refinementValuesBuffer = {};\n\t\n\t$refinementsInner.find('[refinement-id]:not(.price-refinement):not(.sort-by)').each(function() {\n\t\tvar $refinement = $(this);\n\t\tvar $selectedRefinements = $refinement.find('li[refinement-value]:not(.selected).modified, li[refinement-value].selected:not(.modified)');\n\t\t\n\t\tif ($selectedRefinements.length > 0) {\n    \t\tvar refinementId = $refinement.attr('refinement-id');\n    \t\tvar mappedRefinementId;\n\t\t\tif (refinementId == 'availableStores2' || refinementId == 'availableStores3') {\n\t\t\t\tmappedRefinementId = 'availableStores';\t\n\t\t\t} else {\n\t\t\t\tmappedRefinementId = refinementId;\n\t\t\t}\n    \t\t\n    \t\tif (!refinementValuesBuffer[mappedRefinementId]) {\n    \t\t\trefinementValuesBuffer[mappedRefinementId] = [];\n    \t\t}\n    \t\t\n    \t\t$selectedRefinements.each(function () {\n    \t\t\tvar value = $(this).attr('refinement-value').replace(' INCH','\"');\n    \t\t\tvar isNewValue = true;\n    \t\t\tfor (var index = 0; index < refinementValuesBuffer[mappedRefinementId].length; index++) {\n    \t\t\t\tif (refinementValuesBuffer[mappedRefinementId][index] == value) {\n    \t\t\t\t\tisNewValue = false;\n    \t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n    \t\t\tif (isNewValue && $refinementsInner.find('.list-selections [data-refgroup-id=\"' + refinementId + '\"] [value=\"' + $(this).attr('refinement-value').replace(/[\"']/g, \"\") + '\"].pending-clear').length == 0) {\n\t\t\t\t\trefinementValuesBuffer[mappedRefinementId].push(value);\n    \t\t\t}\n    \t\t});\n\t\t}\n\t});\n\t\n\tvar url = baseUrl || options.SearchUrl;\n\tvar currentCategoryId = $('.currCGID').val();\n\tif (includeCategory && currentCategoryId && currentCategoryId != 'null') {\n\t\turl = util.removeParamFromURL(url, 'cgid');\n\t\turl = util.appendParamToURL(url, 'cgid', $('.currCGID').val());\n\t}\n\t\n\tvar currentQueryString = util.getQueryString(urlForParameters || document.location.href);\n\tvar currentQueryStringParameters = util.getQueryStringParams(currentQueryString);\n\tif (currentQueryStringParameters['q']) {\n\t\turl = util.removeParamFromURL(url, 'q');\n\t\turl = util.appendParamToURL(url, 'q', options.SearchPhrase);\n\t}\n\t\n\tif (currentQueryStringParameters['srule']) {\n\t\turl = util.removeParamFromURL(url, 'srule');\n\t\turl = util.appendParamToURL(url, 'srule', currentQueryStringParameters['srule']);\n\t}\n\n\tvar availableStoresValue;\n\tvar activeRefinementIndex = 1;\n\twhile (url.indexOf('prefn' + activeRefinementIndex) >= 0) {\n\t\tif (currentQueryStringParameters['prefn' + activeRefinementIndex] == 'availableStores') {\n\t\t\tavailableStoresValue = currentQueryStringParameters['prefv' + activeRefinementIndex];\n\t\t}\n\n\t\turl = util.removeParamFromURL(url, 'prefn' + activeRefinementIndex);\n\t\turl = util.removeParamFromURL(url, 'prefv' + activeRefinementIndex);\n\t\tactiveRefinementIndex++;\n\t}\n\n\tvar availableStoresRefinementIndex;\n\tfor (var currentQueryStringParameterKey in currentQueryStringParameters) {\n\t\tvar currentQueryStringParameterValue = currentQueryStringParameters[currentQueryStringParameterKey];\n\t\tif (currentQueryStringParameterValue && currentQueryStringParameterValue.indexOf('availableStores') > -1) {\n\t\t\tvar refinementIndexMatch = currentQueryStringParameterKey.match(/prefn([0-9])+/);\n\t\t\tif (refinementIndexMatch && refinementIndexMatch.length > 1) {\n\t\t\t\tavailableStoresRefinementIndex = refinementIndexMatch[1];\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!availableStoresValue && availableStoresRefinementIndex) {\n\t\tavailableStoresValue = currentQueryStringParameters['prefv' + availableStoresRefinementIndex];\n\t}\n\n\tif (availableStoresValue && !refinementValuesBuffer['availableStores']) {\n\t\trefinementValuesBuffer['availableStores'] = [];\n\t\trefinementValuesBuffer['availableStores'].push(availableStoresValue);\n\t}\n\t\n\tvar activeRefinementIndex = 1;\n\tfor (var refinementId in refinementValuesBuffer) {\n\t\tif (refinementId && refinementValuesBuffer[refinementId].length > 0) {\n\t\t\turl = util.appendParamToURL(url, 'prefn' + activeRefinementIndex, refinementId);\n\t\t\turl = util.appendParamToURL(url, 'prefv' + activeRefinementIndex, refinementValuesBuffer[refinementId].join('|'));\n\t\t\tactiveRefinementIndex++;\n\t\t}\n\t}\n\t\n\tif ($('[is-price-refinement=\"true\"] input:checked').length > 0 || SitePreferences.PRICE_SLIDER_ENABLED) {\n\t\tvar currentWindowUrlQS = util.getQueryString(window.location.href);\n\t\tvar urlParams = util.getQueryStringParams(currentWindowUrlQS); // Get url parameters in object format\n\t\tvar $refinementPrice = $('[is-price-refinement=\"true\"] input:checked').closest('[is-price-refinement=\"true\"]');\n\n\t\turl = util.removeParamFromURL(url, 'pmin');\n\t\turl = util.removeParamFromURL(url, 'pmax');\n\n\t\tif (SitePreferences.PRICE_SLIDER_ENABLED) { \n\t\t\tif ($('html').hasClass('size-mobile')) {\n\t\t\t\turl = initMobilePriceSlider(url);\n\t\t\t} else {\n\t\t\t\tif (urlParams.pmin) {\n\t\t\t\t\turl = util.appendParamToURL(url, 'pmin', urlParams.pmin);\n\t\t\t\t}\n\t\t\t\tif (urlParams.pmax) {\n\t\t\t\t\turl = util.appendParamToURL(url, 'pmax', urlParams.pmax);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ($refinementPrice.attr('pmin')) {\n\t\t\t\turl = util.appendParamToURL(url, 'pmin', $refinementPrice.attr('pmin'));\n\t\t\t}\n\t\t\tif ($refinementPrice.attr('pmax')) {\n\t\t\t\turl = util.appendParamToURL(url, 'pmax', $refinementPrice.attr('pmax'));\n\t\t\t}\n\t\t}\n\t}\n\n\tif (includeSort && checkForUpdatedRefinementHandling()) {\n\t\turl = util.removeParamFromURL(url, 'srule');\n\t\t\n\t\tvar $sortingRule = $refinementsInner.find('.sort-by option:checked, .sort-by input:checked');\n\t\tif ($sortingRule && $sortingRule.length > 0) {\n\t\t\tvar sortingRule = $sortingRule.attr('sorting-rule');\n\n\t\t\tif (sortingRule && sortingRule.indexOf('Default') < 0) {\n\t\t\t\turl = util.appendParamToURL(url, 'srule', sortingRule);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn url;\n}\n\nfunction checkForUpdatedRefinementHandling() {\n\tif ((options.RefinementsUIVersion == RefinementUIVersionConstants.Updated) && $html.hasClass('size-mobile') && (pageContext.site != SiteConstants.SiteIds.BootBarnRspUS || options.StoreUIVersion == '2024Redesign')) {\n    \treturn true;\n\t}\n\t\n\treturn false;\n}\n\nfunction redrawUpdatedRefinementHandling($contentParameter, urlForParameters) {\n\tvar $content;\n\tif ($contentParameter && $contentParameter.length > 0) {\n\t\t$content = $contentParameter.find('.refinements');\n\t}\n\tif (!$content || $content.length == 0) {\n\t\t$content = $refinementsInner;\n\t}\n\n\t//updateMultiPriceRefinements($content, urlForParameters);\n\tupdateRefinementCounts($content, urlForParameters);\n\tif (options.StoreUIVersion == '2024Redesign') {\n\t\tupdateSelectedRefinements();\n\t}\n\tupdatePendingRefinements();\n\n\tvar isSortingChanged = false;\n\tvar $sortingRule = $('.modal.open .sort-by option:checked, .modal.open .sort-by input:checked');\n\tif ($sortingRule && $sortingRule.length > 0) {\n\t\tisSortingChanged = !$sortingRule.attr('selected');\n\t}\n\n\tif (isSortingChanged || $content.find('[refinement-value].modified, .list-selections .value.pending-clear').length > 0) {\n\t\t$content.addClass('refinements-modified');\n\t\t$('.refinements-inner-container-footer .apply-refinements').removeClass('disabled');\n\t} else {\n\t\t$content.removeClass('refinements-modified');\n\t\t$('.refinements-inner-container-footer .apply-refinements').addClass('disabled');\n\t}\n\t\n\tif ($('[is-price-refinement=\"true\"] input:checked').length > 0) {\n\t\t$content.addClass('price-selected');\n\t} else {\n\t\t$content.removeClass('price-selected');\n\t}\n\t\n\tvar $refinementsModalProductSelections = $('.refinements-inner-container-header .product-selections');\t\n\tif (($refinementsModalProductSelections.find('.list-selections .value.applied').length + $refinementsModalProductSelections.find('.list-selections > .pending-selections > span').length) > 0) {\n\t\t$refinementsModalProductSelections.show();\n\t\t$('.refinements-inner-container-footer .clear-refinements').removeClass('disabled');\n\t} else {\n\t\t$refinementsModalProductSelections.hide();\n\t\t$('.refinements-inner-container-footer .clear-refinements').addClass('disabled');\n\t}\n\tvar $productSelectionContainer;\n\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t$productSelectionContainer = $('.primary-content > .sort-and-refine > .product-selections');\n\t} else {\n\t\t$productSelectionContainer = $('.primary-content > .product-selections');\n\t}\n\n\tif ($productSelectionContainer.find('.list-selections .value.applied').length > 0) {\n\t\t$productSelectionContainer.show();\n\t} else {\n\t\t$productSelectionContainer.hide();\n\t}\n}\n\nfunction updateSelectedRefinements() {\n\tvar $refinements = $refinementsInner.find('.refinement[uuid].expanded');\n\t$refinements.each(function() {\n\t\tvar $refinement = $(this);\n\n\t\tvar $selectedRefinementsContainer = $refinement.find('.toggle').find('.list-selections');\n\t\tif (!$selectedRefinementsContainer || !$selectedRefinementsContainer.length) {\n\t\t\t$refinement.find('.toggle').append('<div class=\"product-selections\"><ul class=\"list-selections\"/></div>');\n\t\t\t$selectedRefinementsContainer = $refinement.find('.toggle .list-selections');\n\t\t}\n\n\t\tvar $selectedRefinementsValues;\n\t\tif (options.StoreUIVersion == '2024Redesign') {\n\t\t\t$selectedRefinementsValues = $refinement.find('ul:not(.popular)').find('li[refinement-value].selected');\n\t\t} else {\n\t\t\t$selectedRefinementsValues = $refinement.find('ul:not(.popular)').find('li[refinement-value].selected, input:checked:not(.modified)');\n\t\t}\n\t\tvar selectedRefinementsBuffer = [];\n\t\t$selectedRefinementsValues.each(function(index, element) {\n\t\t\tvar $this = $(this);\n\t\t\tvar selectedRefinementId = $this.closest('[refinement-id]').attr('refinement-id');\n\t\t\tvar selectedRefinementValue = $this.closest('[refinement-value]').attr('refinement-value');\n\t\t\tvar selectedRefinementText = $this.closest('[refinement-value]').attr('display-value') || selectedRefinementValue;\n\t\t\t\n\t\t\tif (!selectedRefinementsBuffer[selectedRefinementId]) {\n\t\t\t\tselectedRefinementsBuffer[selectedRefinementId] = [];\n\t\t\t}\n\t\t\t\n\t\t\tvar isNewValue = true;\n\t\t\tfor (var index = 0; index < selectedRefinementsBuffer[selectedRefinementId].length; index++) {\n\t\t\t\tif (selectedRefinementsBuffer[selectedRefinementId][index].Value == selectedRefinementValue) {\n\t\t\t\t\tisNewValue = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (isNewValue) {\n\t\t\t\tselectedRefinementsBuffer[selectedRefinementId].push({\n\t\t\t\t\tText: selectedRefinementText,\n\t\t\t\t\tValue: selectedRefinementValue\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tvar selectedRefinementsHtml = '';\n\t\tfor (var selectedRefinementElement in selectedRefinementsBuffer) {\n\t\t\tvar selectedRefinement = selectedRefinementsBuffer[selectedRefinementElement];\n\t\t\t\n\t\t\tvar selectedRefinementValuesHtml = '';\n\t\t\tfor (var selectedRefinementDataElement in selectedRefinement) {\n\t\t\t\tvar selectedRefinementData = selectedRefinement[selectedRefinementDataElement];\n\t\t\t\tvar selectedRefinementText = selectedRefinementData.Text;\n\t\t\t\tvar selectedRefinementValue = selectedRefinementData.Value;\n\t\t\t\t\n\t\t\t\tif (selectedRefinementValuesHtml) {\n\t\t\t\t\tselectedRefinementValuesHtml += '<span class=\"delimiter\">,</span>';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar selectedRefinementDisplayValue = selectedRefinementValue;\n\t\t\t\tif (selectedRefinementElement == 'Price') {\n\t\t\t\t\tselectedRefinementDisplayValue = $refinementsInner.find('[refinement-id=\"' + selectedRefinementElement + '\"]').attr('display-value');\n\t\t\t\t} else if (selectedRefinementElement == 'size') {\n\t\t\t\t\tselectedRefinementDisplayValue = 'Size ' + selectedRefinementDisplayValue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tselectedRefinementValuesHtml += '<span class=\"value\" refinement-value=\"' + selectedRefinementValue + '\">' +\n\t\t\t\t\t\t\t\t\t\t\t\t\tselectedRefinementText +\n\t\t\t\t\t\t\t\t\t\t\t\t\t'<a class=\"close-btn\"><i class=\"fa fa-close\"></i></a>' +\n\t\t\t\t\t\t\t\t\t\t\t\t'</span>';\n\t\t\t}\n\t\t\t\n\t\t\tselectedRefinementsHtml += '<span data-refgroup-id=\"' + selectedRefinementElement + '\">' +\n\t\t\t\t\t\t\t\t\t\t\t'<span class=\"key\">' + selectedRefinementElement + '</span>' +\n\t\t\t\t\t\t\t\t\t\t\t'<span class=\"colon\">:</span>' +\n\t\t\t\t\t\t\t\t\t\t\tselectedRefinementValuesHtml +\n\t\t\t\t\t\t\t\t\t\t'</span>';\n\t\t}\n\t\t\n\t\t$selectedRefinementsContainer.html(selectedRefinementsHtml);\n\t});\n}\n\nfunction updatePendingRefinements() {\n\tvar $pendingRefinementsContainer;\n\tif (options.StoreUIVersion == '2024Redesign') {\n\t\tvar $selectedRefinementsContainer = $refinementsInner.find('.refinement.expanded .toggle').find('.product-selections');\n\t\tif (!$selectedRefinementsContainer || !$selectedRefinementsContainer.length) {\n\t\t\t$refinementsInner.find('.refinement.expanded .toggle').append('<div class=\"product-selections\"><ul class=\"list-selections\"/></div>');\n\t\t}\n\n\t\t$pendingRefinementsContainer = $refinementsInner.find('.refinement.expanded .toggle').find('.pending-selections');\n\t\tif (!$pendingRefinementsContainer || !$pendingRefinementsContainer.length) {\n\t\t\t$refinementsInner.find('.refinement.expanded .toggle .list-selections').append('<li class=\"pending-selections\"/>');\n\t\t\t$pendingRefinementsContainer = $refinementsInner.find('.refinement.expanded .toggle .list-selections .pending-selections');\n\t\t}\n\t} else {\n\t\t$pendingRefinementsContainer = $refinementsInner.find('.pending-selections');\n\t}\n\t\n\tvar $pendingRefinementsValues;\n\tif (options.StoreUIVersion == '2024Redesign') {\n\t\t$pendingRefinementsValues = $('.refinement[uuid].expanded ul:not(.popular)').find('li[refinement-value]:not(.selected).modified, input.modified:not([checked=\"checked\"])');\n\t} else {\n\t\t$pendingRefinementsValues = $('.refinement[uuid] ul:not(.popular)').find('li[refinement-value]:not(.selected).modified');\n\t}\n\tvar pendingRefinementsBuffer = [];\n\n\t$pendingRefinementsValues.each(function(index, element) {\n\t\tvar $this = $(this);\n\t\tvar pendingRefinementId = $this.closest('[refinement-id]').attr('refinement-id');\n\t\tvar pendingRefinementValue = $this.closest('[refinement-value]').attr('refinement-value');\n\t\tvar pendingRefinementText = $this.closest('[refinement-value]').attr('display-value') || pendingRefinementValue;\n\t\t\n\t\tif (!pendingRefinementsBuffer[pendingRefinementId]) {\n\t\t\tpendingRefinementsBuffer[pendingRefinementId] = [];\n\t\t}\n\t\t\n\t\tvar isNewValue = true;\n\t\tfor (var index = 0; index < pendingRefinementsBuffer[pendingRefinementId].length; index++) {\n\t\t\tif (pendingRefinementsBuffer[pendingRefinementId][index].Value == pendingRefinementValue) {\n\t\t\t\tisNewValue = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (isNewValue) {\n\t\t\tpendingRefinementsBuffer[pendingRefinementId].push({\n\t\t\t\tText: pendingRefinementText,\n\t\t\t\tValue: pendingRefinementValue\n\t\t\t});\n\t\t}\n\t});\n\t\n\tvar pendingRefinementsHtml = '';\n\tfor (var pendingRefinementElement in pendingRefinementsBuffer) {\n\t\tvar pendingRefinement = pendingRefinementsBuffer[pendingRefinementElement];\n\t\t\n\t\tvar pendingRefinementValuesHtml = '';\n\t\tfor (var pendingRefinementDataElement in pendingRefinement) {\n\t\t\tvar pendingRefinementData = pendingRefinement[pendingRefinementDataElement];\n\t\t\tvar pendingRefinementText = pendingRefinementData.Text;\n\t\t\tvar pendingRefinementValue = pendingRefinementData.Value;\n\t\t\t\n\t\t\tif (pendingRefinementValuesHtml) {\n\t\t\t\tpendingRefinementValuesHtml += '<span class=\"delimiter\">,</span>';\n\t\t\t}\n\t\t\t\n\t\t\tvar pendingRefinementDisplayValue = pendingRefinementValue;\n\t\t\tif (pendingRefinementElement == 'Price') {\n\t\t\t\tpendingRefinementDisplayValue = $refinementsInner.find('[refinement-id=\"' + pendingRefinementElement + '\"]').attr('display-value');\n\t\t\t} else if (pendingRefinementElement == 'size') {\n\t\t\t\tpendingRefinementDisplayValue = 'Size ' + pendingRefinementDisplayValue;\n\t\t\t}\n\t\t\t\n\t\t\tpendingRefinementValuesHtml += '<span class=\"value\" refinement-value=\"' + pendingRefinementValue + '\">' +\n\t\t\t\t\t\t\t\t\t\t\t\tpendingRefinementText +\n\t\t\t\t\t\t\t\t\t\t\t\t'<a class=\"close-btn\"><i class=\"fa fa-close\"></i></a>' +\n\t\t\t\t\t\t\t\t\t\t\t'</span>';\n\t\t}\n\t\t\n\t\tpendingRefinementsHtml += '<span data-refgroup-id=\"' + pendingRefinementElement + '\">' +\n\t\t\t\t\t\t\t\t\t\t'<span class=\"key\">' + pendingRefinementElement + '</span>' +\n\t\t\t\t\t\t\t\t\t\t'<span class=\"colon\">:</span>' +\n\t\t\t\t\t\t\t\t\t\tpendingRefinementValuesHtml +\n\t\t\t\t\t\t\t\t\t'</span>';\n\t}\n\t\n\t$pendingRefinementsContainer.html(pendingRefinementsHtml);\n}\n\nfunction updateRefinementCounts($contentParameter, urlForParameters) {\n\tvar url = buildUrlForSelectedRefinements(Urls.getRefinementCounts, null, true);\n\tvar $content = $contentParameter || $(document);\n\tvar $refinements = $content.find('.refinement[uuid]');\n\tvar $refinementProductCount = $content.find('.refinement .toggle .product-count');\n\t$refinementProductCount.loading();\n\n\tvar refinementGroups = [];\n\tvar refinementGroupIndex = 0;\n\tvar refinementGroupSizeLimit = 2000;\n\tvar refinementGroupSizeCurrent = 0;\n\t$.each($refinements, function(index, element) {\n\t\tvar $refinement = $(element);\n\t\tvar refinementValueCount = $refinement.find('[refinement-value]').length;\n\t\tif ((refinementValueCount + refinementGroupSizeCurrent) >= refinementGroupSizeLimit) {\n\t\t\trefinementGroupIndex++;\n\t\t\trefinementGroupSizeCurrent = 0;\n\t\t}\n\n\t\tif (!refinementGroups[refinementGroupIndex]) {\n\t\t\trefinementGroups[refinementGroupIndex] = $refinement;\n\t\t} else {\n\t\t\trefinementGroups[refinementGroupIndex] = refinementGroups[refinementGroupIndex].add($refinement);\n\t\t}\n\n\t\trefinementGroupSizeCurrent += refinementValueCount;\n\t});\n\n\tdataBuffer['updateRefinementCountsRefinementGroupIndex'] = 0;\n\tdataBuffer['updateRefinementCountsRefinementGroupCount'] = refinementGroups.length;\n\n\t$.each(refinementGroups, function(index, element) {\n\t\tvar $refinementGroup = $(element);\n\t\tupdateRefinementCountsForRefinements(url, $refinementGroup);\n\t});\n}\n\nfunction updateRefinementCountsForRefinements(url, $refinements) {\n\tvar refinementIds = $refinements.map(function(index, element) {\n\t\treturn $(element).attr('refinement-id');\n\t}).get();\n\n\tif (refinementIds) {\n\t\tvar $refinementProductCount = $refinements.find('.toggle .product-count');\n\t\t$refinementProductCount.loading();\n\n\t\tif (dataBuffer['updateRefinementCountsRefinementGroupCount'] && dataBuffer['updateRefinementCountsRefinementGroupCount'] > 1) {\n\t\t\turl = util.appendParamToURL(url, 'refinements', refinementIds.join());\n\t\t}\n\n\t\t$.ajax({\n\t\t\ttype: 'get',\n\t\t\turl: url,\n\t\t\tsuccess: function(data) {\n\t\t\t\t$refinements.each(function(index, element) {\n\t\t\t\t\tvar $refinement = $(element);\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tvar refinementId = $refinement.attr('refinement-id');\n\t\t\t\t\t\tvar $refinementValues = $refinement.find('ul li[refinement-value]');\n\t\t\t\t\t\tif (data.Refinements[refinementId]) {\n\t\t\t\t\t\t\t$.each($refinementValues, function(index, element) {\n\t\t\t\t\t\t\t\tvar $refinementValue = $(element);\n\t\t\t\t\t\t\t\tvar refinementValue = $refinementValue.attr('refinement-value');\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif ($refinementValue.find('input[type=\"checkbox\"]').prop('checked') || data.Refinements[refinementId][refinementValue]) {\n\t\t\t\t\t\t\t\t\t$refinementValue.attr('refinement-count', data.Refinements[refinementId][refinementValue]).find('.refinement-count').html(data.Refinements[refinementId][refinementValue]);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$refinementValue.attr('refinement-count', 0).find('.refinement-count').html('0');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tvar $popularRefinementValues = $refinement.find('ul.popular-sizes, ul.popular').find('li[refinement-value]');\n\t\t\t\t\t\t\tvar $popularRefinementValuesChecksContainer = $refinement.find('.checks-container.popular');\n\t\t\t\t\t\t\tvar hasPopularRefinementValues = $popularRefinementValues.filter(':not([refinement-count=\"0\"])').length > 0 || $popularRefinementValues.filter(':not([refinement-count=\"0\"])').find('input:checked').length > 0;\n\t\t\t\t\t\t\tif (hasPopularRefinementValues) {\n\t\t\t\t\t\t\t\t$popularRefinementValuesChecksContainer.show();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$popularRefinementValuesChecksContainer.hide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar $normalRefinementValues = $refinement.find('ul:not(.popular-sizes):not(.popular)').find('li[refinement-value]');\n\t\t\t\t\t\t\tvar $normalRefinementValuesChecksContainer = $refinement.find('.checks-container:not(.popular)');\n\t\t\t\t\t\t\tvar hasNormalRefinementValues = $normalRefinementValues.filter(':not([refinement-count=\"0\"])').length > 0 || $normalRefinementValues.filter(':not([refinement-count=\"0\"])').find('input:checked').length > 0;\n\t\t\t\t\t\t\tif (hasNormalRefinementValues) {\n\t\t\t\t\t\t\t\t$normalRefinementValuesChecksContainer.show();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$normalRefinementValuesChecksContainer.hide();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/* --- Price slider modifications --- */\n\t\t\t\t\t\t\tvar hasPriceSlider = SitePreferences.PRICE_SLIDER_ENABLED && (refinementId == 'Price' || refinementId == 'ref-postDiscountPrice'); \n\t\t\t\t\t\t\tif (hasPriceSlider) {\n\t\t\t\t\t\t\t\tvar pageUrl = util.getQueryString(window.location.href);\n\t\t\t\t\t\t\t\tif (pageUrl) {\n\t\t\t\t\t\t\t\t\tvar hasPriceAttributes = pageUrl.indexOf('pmin') > -1 || pageUrl.indexOf('pmax') > -1;\n\t\t\t\t\t\t\t\t\tvar isMobile = $('html').hasClass('size-mobile');\n\t\t\t\t\t\t\t\t\tif (hasPriceAttributes && !isMobile) {\n\t\t\t\t\t\t\t\t\t\t$('.price-refinement').find('.refinement-body').show();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t$('.price-refinement').find('.refinement-body').hide();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (hasNormalRefinementValues || hasPopularRefinementValues || hasPriceSlider) {\n\t\t\t\t\t\t\t\t$refinement.removeClass('hidden');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$refinement.addClass('hidden');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$refinement.addClass('hidden');\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ($refinement.find('ul.checks, ul.swatches').find('li').length == 0) {\n\t\t\t\t\t\t\t$refinement.addClass('hidden');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$refinement.removeClass('hidden');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$refinement.removeAttr('loading');\n\t\t\t\t\tupdateMoreLess($refinement);\n\t\t\t\t});\n\t\t\t},\n\t\t\tcomplete: function() {\n\t\t\t\tdataBuffer['updateRefinementCountsRefinementGroupIndex']++;\n\t\t\t\tif ($refinementProductCount.attr('loading')) {\n\t\t\t\t\t$refinementProductCount.loading('destroy');\n\t\t\t\t}\n\t\t\t\tupdateRefinementCountsComplete();\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction updateRefinementCountsComplete() {\n\tif (dataBuffer['updateRefinementCountsRefinementGroupIndex'] == dataBuffer['updateRefinementCountsRefinementGroupCount']) {\n\t\tupdateProductCountInHeader();\n\t\tupdateRefinementsInHeader();\n\t}\n}\n\nfunction updateProductCountInHeader() {\n\tvar $refinementsProductCount = $('.refinements .slot-grid-subheader .product-count span');\n\tvar $headerProductCount = $('.top-banner .slot-grid-subheader .product-count span');\n\n\tif ($refinementsProductCount.length > 0 && $headerProductCount.length > 0) {\n\t\t$headerProductCount.text($refinementsProductCount.text());\n\t}\n}\n\nfunction updateRefinementsInHeader() {\n\tvar $refinementsRefinements = $('.primary-content .product-selections');\n\tvar $headerRefinements = $('.top-banner .product-selections');\n\n\tif ($refinementsRefinements.length > 0 && $headerRefinements.length > 0) {\n\t\t$headerRefinements.html($refinementsRefinements.html());\n\t}\n}\n\nfunction updateMoreLess($refinement) {\n\tvar refinementId = $refinement.attr('refinement-id');\n\tvar $refinementValuesContainer = $refinement.find('ul:not(.popular-sizes):not(.popular)');\n\tvar $refinementContainer = $refinementValuesContainer.closest('.refinement-body-inner');\n\tvar $moreLink = $refinementValuesContainer.find('.ref-filter.more-link').closest('li').detach().first();\n\tvar $refinementValues = $refinementValuesContainer.find('li[refinement-value]');\n\tvar $refinementValuesVisible = $refinementValues.filter(':not([refinement-count=\"0\"])');\n\n\tif ($moreLink.length > 0) {\n\t\tvar moreLessCount;\n\t\tif (pageContext.site == SiteConstants.SiteIds.BootBarnUS && $refinement.attr('refinement-id') == 'size') {\n\t\t\tmoreLessCount = 12;\n\t\t} else if (pageContext.site == SiteConstants.SiteIds.BootBarnRspUS && options.StoreUIVersion == '2024Redesign') {\n\t\t\tmoreLessCount = 100000;\n\t\t} else {\n\t\t\tmoreLessCount = 9;\n\t\t}\n\n\t\tif ($refinementValuesVisible.length > moreLessCount) {\n\t\t\tvar moreLessIndex = $refinementValuesVisible.index($refinementValuesVisible.eq(moreLessCount));\n\t\t\t$refinementValuesVisible.slice(0, moreLessIndex).removeClass('toggleable hidden');\n\t\t\t$refinementValuesVisible.slice(moreLessIndex, $refinementValues.length).addClass('toggleable hidden');\n\t\t\t$refinementValuesVisible.eq(moreLessIndex - 1).after($moreLink);\n\t\t\t$refinementValuesContainer.find('.more-link-container').show();\n\t\t\t$refinementContainer.find('.less-refinement').show();\n\t\t} else {\n\t\t\t$refinementValuesVisible.removeClass('toggleable hidden');\n\t\t\t$refinementValuesVisible.eq($refinementValuesVisible.length - 1).after($moreLink);\n\t\t\t$refinementValuesContainer.find('.more-link-container').hide();\n\t\t\t$refinementContainer.find('.less-refinement').hide();\n\t\t}\n\t}\n\n\tif (!$('html').hasClass('size-mobile') || window.innerWidth > 767) {\n\t\tif (refinementsExpanded) {\n\t\t\tif (refinementsExpanded.indexOf(refinementId) > -1) {\n\t\t\t\t$refinement.addClass('expanded');\n\t\t\t\t$refinement.find('.toggle').addClass('expanded');\n\t\t\t\t$refinement.find('.toggle-content').show();\n\t\t\t} else {\n\t\t\t\t$refinement.removeClass('expanded');\n\t\t\t\t$refinement.find('.toggle').removeClass('expanded');\n\t\t\t\t$refinement.find('.toggle-content').hide();\n\t\t\t}\n\t\t}\n\t\tif ($('.refinement.expanded').length > 0) {\n\t\t\t$('.refinements').addClass('refinement-expanded');\n\t\t} else {\n\t\t\t$('.refinements').removeClass('refinement-expanded');\n\t\t}\n\n\t\tif (refinementsViewAll && $refinementValuesVisible.length > moreLessCount) {\n\t\t\tif (refinementsViewAll.indexOf(refinementId) > -1) {\n\t\t\t\t$refinement.addClass('more-expanded');\n\t\t\t\t$refinement.find('.toggleable').removeClass('hidden');\n\t\t\t\t$refinement.find('.more-link-container').css('display', 'none');\n\t\t\t\t$refinement.find('.less-refinement.toggleable').removeClass('hidden');\n\t\t\t} else {\n\t\t\t\t$refinement.removeClass('more-expanded');\n\t\t\t\t$refinement.find('.more-link-container').css('display', 'list-item');\n\t\t\t\t$refinement.find('.less-refinement.toggleable').addClass('hidden');\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar refGroupsStates = {\n\t\tcookieRefGroupsKey: 'refgroup',\n\t\tsaveState: function(refgroup, visible) {\n\t\t\tif (this.getCookie('dw_cookies_accepted')) {\n\t\t\t\tvar getRefGroupCookie = this.getCookie(this.cookieRefGroupsKey) || '{}';\n\t\t\t\tvar getRefGroupObj = JSON.parse(getRefGroupCookie);\n\t\t\t\tgetRefGroupObj[refgroup] = visible;\n\t\t\t\tgetRefGroupCookie = JSON.stringify(getRefGroupObj);\n\t\t\t\tthis.setCookie('refgroup', getRefGroupCookie);\n\t\t\t}\n\t\t},\n\t\tcheckState: function(refgroup) {\n\t\t\tif (this.getCookie('dw_cookies_accepted')) {\n\t\t\t\tvar getRefGroupCookie = this.getCookie(this.cookieRefGroupsKey);\n\t\t\t\tif (getRefGroupCookie) {\n\t\t\t\t\tvar getRefGroupObj = JSON.parse(getRefGroupCookie);\n\t\t\t\t\tif (getRefGroupObj[refgroup] != undefined) {\n\t\t\t\t\t\treturn getRefGroupObj[refgroup];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tgetCookie: function (key) {\n\t\t    var cookies = document.cookie.split(';');\n\t\t    for (var i = 0; i < cookies.length; i++) {\n\t\t        var tokens = cookies[i].split('=');\n\t\t        var cookieKey = tokens[0].trim();\n\t\t        if (cookieKey === key) {\n\t\t            return tokens[1];\n\t\t        }\n\t\t    }\n\t\t    return '';\n\t\t},\n\t\tsetCookie: function(key, value, minutes) {\n\t\t    var date = new Date();\n\t\t    date.setTime(date + (minutes * 60 * 1000));\n\t\t    document.cookie = key + '=' + value + '; expires=' + date.toGMTString() + '; path=/';\n\t\t}\n}\n\nfunction searchStores() {\n\tvar searchStoresQuery = $('.search-stores-query');\n\n\t$('.go-find-stores').on('click', function (e) {\n\t\tvar el = $(e.target),\n\t\t\tdata = {\n\t\t\t\ttypeKey: el.attr('type')\n\t\t\t};\n\n\t\tif (el.attr('type') === 'geo') {\n\t\t\tif (navigator.geolocation) {\n\t\t\t\tnavigator.geolocation.getCurrentPosition(function(position) {\n\t\t\t\t\tdata.longitude = position.coords.longitude;\n\t\t\t\t\tdata.latitude = position.coords.latitude;\n\n\t\t\t\t\tsearchStoresAJAX(data);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\talert('Your browser not supported geolocation');\n\t\t\t}\n\t\t} else {\n\t\t\tdata.searchKey = searchStoresQuery.val().trim();\n\n\t\t\tvar geocoder = new google.maps.Geocoder();\n\t\t\tgeocoder.geocode( { 'address': searchStoresQuery.val().trim()}, function(results, status) {\n\t\t\t\tif (status == google.maps.GeocoderStatus.OK) {\n\t\t\t\t  \tdata.longitude = results[0].geometry.location.lng();\n\t\t\t\t  \tdata.latitude = results[0].geometry.location.lat();\n\n\t\t\t\t  \tsearchStoresAJAX(data);\n\t\t\t\t} else {\n\t\t\t\t\talert(\"Geocode was not successful for the following reason: \" + status);\n\t\t\t\t}\n\t\t    });\n\t\t}\n\t});\n}\n\nfunction searchStoresAJAX(params) {\n\t$.ajax({\n\t\ttype: 'get',\n\t\turl: Urls.searchStores,\n\t\tdata: params,\n\n\t\tsuccess: function (data) {\n\t\t\tvar popupList = $('.category-popup-list-stores');\n\n\t\t\t$('.grid-page-storeselector-popup').dialog('close');\n\t\t\tpopupList\n\t\t\t\t.html(data)\n\t\t\t\t.dialog({\n\t\t\t\t\twidth: 450,\n\t\t\t\t\tautoOpen: false,\n\t\t\t\t\tmodal: true,\n\t\t\t\t\tresizable: false\n\t\t\t\t});\n\n\t\t\tpopupList.parent().find('.ui-dialog-title').html(data.match(/Stores near.{0,}/mi)[0].replace('</span>', ''));\n\t\t\tpopupList.dialog('open');\n\t\t}\n\t});\n}\n\nfunction showVariantInventoryMessaging() {\n  \tif (options && options.Bopis && options.Bopis.IsLocationSearchFiltered) {\n\t\treturn;\n\t}\n\n  $.ajax({\n      dataType: 'json',\n      url: page.variantInventoryMessagingUrl,\n      async: true\n  })\n  // success\n  .done(function (values) {\n\t  if (values) {\n\t\t  values.forEach(function(val, idx) {\n\t\t\t  var $tile = $('[data-itemid=\"' + val.masterProductID + '\"]');\n\t\t\t  if ($tile.length > 0) {\n\t\t\t\t  if ( typeof val.urlHash != 'undefined' ) {\n\t\t\t\t\t  var filterP = val.urlHash.replace('#','').split('=')[0];\n\t\t\t\t\t  var rr = new RegExp(\"prefn[0-9]=\"+filterP);\n\t\t\t\t\t  if ( location.href.match(rr) ) {\n\t\t\t\t\t\t  if (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t\t\t\t\t\t//Put the inventory message in the product badge if variantWhsInStock is false\n\t\t\t\t\t\t\tvar productBadge = $tile.find('.product-badge.whs-in-stock');\n\t\t\t\t\t\t\tif (val.variantWhsInStock == 'true') {\n\t\t\t\t\t\t\t\tproductBadge.show();\n\t\t\t\t\t\t\t} else if (val.dropshipLead <= 10) {\n\t\t\t\t\t\t\t\tproductBadge.text(val.inventoryMsg);\n\t\t\t\t\t\t\t\tproductBadge.removeClass('whs-in-stock').addClass('availability-msg').show();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t  } else {\n\t\t\t\t\t\t\tvar $msg = $('<div />').attr('class', 'availability-msg').text(val.inventoryMsg); \n\t\t\t\t\t\t\t$tile.find('.product-pricing').append($msg);\n\t\t\t\t\t\t\tif (val.variantWhsInStock == 'true') {\n\t\t\t\t\t\t\t\t$tile.find('.whs-in-stock').show();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t  }\n\t\t\t\t\t  }\n\t\t\t\t  }\n\t\t\t  }\n\t\t  });\n\t  }\n  })\n  .fail(function (xhr, textStatus) {\n      if (textStatus === 'parsererror') {\n          console.log('Inventory Messaging Error ' + Resources.BAD_RESPONSE);\n      }\n  });\n}\n\nfunction saveScrollPosition() {\n\tif (sessionStorage) {\n\t\t$(document).off('scroll.ScrollPositionSave').on('scroll.ScrollPositionSave', function(event) {\n\t\t\tvar categoryId = $('.currCGID').val();\n\t\t\tvar sessionStorageScrollPosition;\n\t\t\ttry {\n\t\t\t\tsessionStorageScrollPosition = JSON.parse(sessionStorage.ScrollPosition);\n\t\t\t} catch(exception) {}\n\t\t\tif (!sessionStorageScrollPosition || typeof sessionStorageScrollPosition != 'object' || !sessionStorageScrollPosition[categoryId]) {\n\t\t\t\tsessionStorageScrollPosition = {};\t\n\t\t\t}\n\t\t\tsessionStorageScrollPosition[categoryId] = $(window).scrollTop();\n\t\t\tsessionStorage.ScrollPosition = JSON.stringify(sessionStorageScrollPosition);\n\t\t});\n\t}\n}\n\nfunction loadScrollPosition() {\n\tif (sessionStorage) {\n\t\tvar categoryId = $('.currCGID').val();\n\t\tvar sessionStorageScrollPosition;\n\t\ttry {\n\t\t\tsessionStorageScrollPosition = JSON.parse(sessionStorage.ScrollPosition);\n\t\t} catch(exception) {}\n\t\tif (sessionStorageScrollPosition && typeof sessionStorageScrollPosition == 'object' && sessionStorageScrollPosition[categoryId]) {\n\t\t\t$(window).scrollTop(sessionStorageScrollPosition[categoryId]);\n\t\t}\n\t}\n}\n\nfunction initializeStickyRefinements() {\n\t$(document).off('scroll.StickyRefinements StickyRefinements.Refresh').on('scroll.StickyRefinements StickyRefinements.Refresh', function(event) {\n\t\tvar $refinements = $('#secondary');\n\t\tvar $primary = $('#primary');\n\n\t\tif ($('html').hasClass('size-mobile') || window.innerWidth <= 767) {\n\t\t\t$refinements.css('transform', '');\n\t\t\t$refinements.scrollTop(0);\n\t\t\t$refinements.height('auto');\n\t\t} else {\n\t\t\tvar documentScrollTop = parseInt($(document).scrollTop(), 10);\n\t\t\tvar documentScrollDelta = 0;\n\t\t\tif (dataBuffer['documentScrollTop']) {\n\t\t\t\tdocumentScrollDelta = documentScrollTop - dataBuffer['documentScrollTop'];\n\t\t\t}\n\t\t\tvar windowHeight = parseInt($(window).height(), 10);\n\t\t\tvar windowBottom = documentScrollTop + windowHeight;\n\t\t\tvar refinementsScrollHeight = parseInt($refinements[0].scrollHeight, 10);\n\t\t\tvar refinementsOffsetTop = parseInt($refinements.offset().top, 10);\n\t\t\tvar refinementsOffsetBottom = parseInt($refinements.offset().top + refinementsScrollHeight, 10);\n\t\t\tvar primaryTop = parseInt($primary.offset().top, 10);\n\t\t\tvar primaryBottom = primaryTop + parseInt($primary.outerHeight(), 10);\n\t\t\tvar documentScrollTopFromPrimaryTop = documentScrollTop - primaryTop;\n            if (documentScrollTopFromPrimaryTop < 0) {\n                documentScrollTopFromPrimaryTop = 0;\n            }\n            var windowBottomFromPrimaryBottom = windowBottom - primaryBottom;\n            if (windowBottomFromPrimaryBottom < 0) {\n                windowBottomFromPrimaryBottom = 0;\n            }\n            var refinementsOffsetTopNew;\n            var refinementsOffsetBottomNew;\n            if (documentScrollDelta) {\n                refinementsOffsetTopNew = refinementsOffsetTop + documentScrollDelta;\n                refinementsOffsetBottomNew = refinementsOffsetTopNew + refinementsScrollHeight;\n            }\n\n\t\t\tvar refinementsTranslateY;\n\t\t\tif ($refinements.outerHeight() >= $primary.outerHeight()) {\n\t\t\t\trefinementsTranslateY = 0;\n\t\t\t} else if (documentScrollDelta >= 0) {\n\t\t\t\trefinementsTranslateY = refinementsOffsetTop - primaryTop;\n\n\t\t\t\tif ($refinements.hasClass('top')) {\n\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\trefinementsTranslateY = refinementsTranslateY - documentScrollDelta;\n\t\t\t\t}\n\n\t\t\t\tif (refinementsOffsetBottom >= primaryBottom) {\n\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\trefinementsTranslateY = primaryBottom - primaryTop - refinementsScrollHeight;\n\t\t\t\t} else if (refinementsOffsetBottom < windowBottom && primaryBottom >= windowBottom) {\n\t\t\t\t\tif (refinementsScrollHeight > windowHeight) {\n\t\t\t\t\t\t$('body').addClass('sticky-refinements');\n\t\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\t\t$refinements.addClass('bottom');\n\t\t\t\t\t} else if (documentScrollTop >= primaryTop) {\n\t\t\t\t\t\t$('body').addClass('sticky-refinements');\n\t\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\t\t$refinements.addClass('top');\n\t\t\t\t\t}\n\t\t\t\t} else if (refinementsOffsetBottom < windowBottom && primaryBottom < windowBottom) {\n\t\t\t\t\tif ((documentScrollTop + refinementsScrollHeight) > primaryBottom) {\n\t\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\t\trefinementsTranslateY = primaryBottom - primaryTop - refinementsScrollHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$('body').addClass('sticky-refinements');\n\t\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\t\t$refinements.addClass('top');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (documentScrollDelta < 0) {\n\t\t\t\trefinementsTranslateY = refinementsOffsetTop - primaryTop;\n\n\t\t\t\tif ($refinements.hasClass('bottom')) {\n\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\trefinementsTranslateY = refinementsTranslateY - documentScrollDelta;\n\t\t\t\t}\n\n\t\t\t\tif (refinementsOffsetTop <= primaryTop && documentScrollTop <= primaryTop) {\n\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\trefinementsTranslateY = 0;\n\t\t\t\t} else if (refinementsOffsetBottom >= primaryBottom && refinementsOffsetTop <= documentScrollTop) {\n\t\t\t\t\t$('body').removeClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\trefinementsTranslateY = primaryBottom - primaryTop - refinementsScrollHeight;\n\t\t\t\t} else if (refinementsOffsetTop >= documentScrollTop && refinementsOffsetTop > primaryTop) {\n\t\t\t\t\t$('body').addClass('sticky-refinements');\n\t\t\t\t\t$refinements.removeClass('top bottom');\n\t\t\t\t\t$refinements.addClass('top');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (refinementsTranslateY != undefined) {\n\t\t\t\t$refinements.css('transform', 'translateY(' + refinementsTranslateY + 'px)');\n\t\t\t}\n\n\t\t\tdataBuffer['documentScrollTop'] = documentScrollTop;\n\t\t}\n\t});\n}\n\nfunction initializeStickySubheader() {\n\t$(document).off('scroll.StickySubheader').on('scroll.StickySubheader', function(event) {\n\t\tvar $slotGridSubheader = $('.slot-grid-subheader');\n\t\tvar $slotGridSubheaderFixed = $('.slot-grid-subheader-fixed');\n\t\tif ($slotGridSubheader.length > 0 && $slotGridSubheaderFixed.length > 0) {\n\t\t\tvar $primary = $('#primary');\n\t\t\tvar documentScrollTop = $(document).scrollTop();\n\t\t\tvar windowHeight = $(window).height();\n\t\t\tvar windowBottom = documentScrollTop + windowHeight;\n\t\t\tvar primaryTop = $primary.offset().top;\n\t\t\tvar primaryBottom = primaryTop + $primary.outerHeight();\n\n\t\t\tif (primaryBottom < windowBottom) {\n\t\t\t\t$slotGridSubheaderFixed.addClass('hidden');\n\t\t\t} else if ($slotGridSubheader.offset().top < documentScrollTop) {\n\t\t\t\t$slotGridSubheaderFixed.removeClass('hidden');\n\t\t\t} else {\n\t\t\t\t$slotGridSubheaderFixed.addClass('hidden');\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initializeRefinementFilterByText() {\n\t$(document).off('keyup.RefinementFilterText').on('keyup.RefinementFilterText', '.refinement .refinement-filter-text input', function(event) {\n\t\tvar $this = $(this);\n\t\tvar filterText = $this.val();\n\t\tvar filterTextRegEx;\n\t\tvar $container = $this.closest('.refinement-filter-text');\n\t\tvar $reset = $container.find('a.reset');\n\t\tvar $noResults = $container.find('.no-results');\n\t\tvar $refinement = $this.closest('.refinement');\n\t\tvar $refinementValues = $this.closest('.checks-container').find('[refinement-value]:not([refinement-count=\"0\"])');\n\n\t\tif (filterText) {\n\t\t\tfilterTextRegEx = new RegExp('^' + filterText + '| ' + filterText, 'gi');\n\t\t\t$reset.addClass('show');\n\t\t\t$refinement.addClass('filter-text');\n\t\t\t$refinementValues.each(function(index, element) {\n\t\t\t\tvar $refinementValue = $(this);\n\t\t\t\tif ($refinementValue.attr('refinement-value').match(filterTextRegEx)) {\n\t\t\t\t\t$refinementValue.addClass('filter-text-show');\n\t\t\t\t} else {\n\t\t\t\t\t$refinementValue.removeClass('filter-text-show').hide();\n\t\t\t\t}\n\t\t\t});\n\t\t\tif ($refinementValues.filter(':visible').length == 0) {\n\t\t\t\t$noResults.find('span').text(filterText);\n\t\t\t\t$noResults.show();\n\t\t\t} else {\n\t\t\t\t$noResults.hide();\n\t\t\t}\n\t\t} else {\n\t\t\t$reset.removeClass('show');\n\t\t\t$refinement.removeClass('filter-text');\n\t\t\t$refinementValues.removeClass('filter-text-show').css('display', '');\n\t\t\t$noResults.hide();\n\t\t}\n\t});\n\n\t$(document).off('click.RefinementFilterTextReset').on('click.RefinementFilterTextReset', '.refinement .refinement-filter-text a.reset', function(event) {\n\t\tvar $this = $(this);\n\t\tvar $container = $this.closest('.refinement-filter-text');\n\t\tvar $noResults = $container.find('.no-results');\n\t\tvar $refinement = $this.closest('.refinement');\n\t\tvar $refinementValues = $this.closest('.checks-container').find('[refinement-value]');\n\n\t\t$this.removeClass('show');\n\t\t$refinement.removeClass('filter-text');\n\t\t$refinement.find('.refinement-filter-text input').val('');\n\t\t$refinementValues.removeClass('filter-text-show').css('display', '');\n\t\t$noResults.hide();\n\t});\n}\n\nfunction saveExpandedRefinements() {\n\trefinementsExpanded = $('.refinements [refinement-id].expanded').map(function(index, element) {\n\t\treturn $(this).attr('refinement-id');\n\t}).get();\n\n\trefinementsViewAll = $('.refinements [refinement-id].more-expanded').map(function(index, element) {\n\t\treturn $(this).attr('refinement-id');\n\t}).get();\n}\n\nfunction redrawShopMyStore() {\n\t$.ajax({\n\t\tmethod: 'GET',\n\t\turl: util.appendParamToURL(Urls.Stores.GetShopMyStorePanel + location.search, 'cgid', $('.currCGID').val()),\n\t\tdataType: 'html',\n\t\tsuccess: function(data) {\n\t\t\t$('.shop-my-store').replaceWith(data);\n\t\t\tupdateShopMyStore();\n\t\t}\n\t});\n}\n\nfunction updateShopMyStore() {\n\tif ($('.shop-my-store-toggle input:checked').length > 0) {\n\t\t$('body').attr('is-shop-my-store-active', true);\n\t} else {\n\t\t$('body').attr('is-shop-my-store-active', false);\n\t}\n}\n\nfunction initializeRangefinderEvents() {\n\t$(document).off('click.RefinementFilterTextReset').on('click.RefinementFilterTextReset', '.product-tile a', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $product = $this.closest('[data-itemid]');\n\t\tif ($product.length > 0) {\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t\tdialog.open({\n                url: util.appendParamToURL(Urls.productDetail, 'pid', $product.attr('data-itemid')),\n\t\t\t\tcallback: function() {\n\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t}\n            });\n\t\t}\n\t});\n}\n\nfunction initializeBootFinderEvents() {\n\tvar $bootFinderResultsBanner = $('.bootfinder-resultsbanner');\n\tif ($bootFinderResultsBanner && $bootFinderResultsBanner.length) {\n\t\t$bootFinderEmailForm = $bootFinderResultsBanner.find('form.email');\n\t\tbootFinderEmailValidator = $bootFinderEmailForm.validate(ValidationSettings.Global);\n\t\tbootFinderEmailValidator.settings.onfocusout = ValidationSettings.Global.onfocusout;\n\t\tbootFinderEmailValidator.settings.errorPlacement = ValidationSettings.Global.errorPlacement;\n\t\t$bootFinderEmailForm.find('input[name=\"email\"]').rules('add', $.extend(ValidationRules.Email, {\n\t\t\trequired: true,\n\t\t\tmessages: {\n\t\t\t\trequired: $.validator.format('Please enter an email address.')\n\t\t\t}\n\t\t}));\n\t\t$bootFinderEmailForm.find('input[name=\"useragreement\"]').rules('add', {\n\t\t\trequired: true,\n\t\t\tmessages: {\n\t\t\t\trequired: $.validator.format('Please agree to the terms and conditions.')\n\t\t\t}\n\t\t});\n\n\t\t$(document).off('click.BootFinderResultsEmail').on('click.BootFinderResultsEmail', '.bootfinder-resultsbanner .btn.send-results-email', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tif ($bootFinderEmailForm && $bootFinderEmailForm.valid()) {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar $container = $this.closest('form');\n\t\t\t\t$container.loading($.extend(loadingIndicatorSettings, {\n\t\t\t\t\tIsLabelShown: true,\n\t\t\t\t\tContent: 'Sending Email...'\n\t\t\t\t}));\n\t\t\t\tvar urlParameters = util.getQueryStringParams(window.location.href);\n\t\t\t\tvar bootFinderSendResultsEmailUrl = Urls.BootFinder.SendResultsEmail;\n\t\t\t\tbootFinderSendResultsEmailUrl = util.appendParamToURL(bootFinderSendResultsEmailUrl, 'cgid', $('.currCGID').val());\n\t\t\t\tfor (var urlParameter in urlParameters) {\n\t\t\t\t\tif (urlParameters[urlParameter]) {\n\t\t\t\t\t\tbootFinderSendResultsEmailUrl = util.appendParamToURL(bootFinderSendResultsEmailUrl, urlParameter, urlParameters[urlParameter]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar payload = {\n\t\t\t\t\temail: $container.find('input[type=\"email\"]').val(),\n\t\t\t\t\turl: util.removeParamFromURL(window.location.href, 'bootfinderviewresults')\n\t\t\t\t}\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: 'post',\n\t\t\t\t\turl: bootFinderSendResultsEmailUrl,\n\t\t\t\t\tdata: payload,\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\t$container.loading('destroy');\n\t\t\t\t\t\tif (data && data.success) {\n\t\t\t\t\t\t\t$container.find('.validation-error-container').html('<span class=\"error\">Email sent!</span>');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$container.find('.validation-error-container').html('<span class=\"error\">An error occurred sending the email. Please try again.</span>');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction getDecodedNumber(stringNumber) {\n\tvar decodedNumber = decodeURIComponent(stringNumber);\n\tvar cleanedNumber = parseInt(decodedNumber.replace(/,/g, ''));\n\treturn cleanedNumber;\n}\n\nfunction priceSlider() {\n\tif (!SitePreferences.PRICE_SLIDER_ENABLED) {\n\t\treturn;\n\t} else {\n\t\t$(document).ready(function() {\t\n\t\t\tvar maxProductPrice = 1200;\t// Set default value of slider max to $1200. This gets overwritten later in code depending on returned results.\n\t\t\tvar urlQueryString = util.getQueryString(window.location.href);\n\t\t\tvar urlParams = util.getQueryStringParams(urlQueryString); // Get url parameters in object format\n\t\t\tvar hasCategory = ['cgid'] in urlParams;\n\t\t\tvar hasQuery = ['q'] in urlParams;\n\t\t\tvar hiddenFieldCategoryId = $('.currCGID').val();\n\t\t\tvar sliderMinValue = 0;\n\t\t\tvar\tsliderMaxValue = maxProductPrice;\n\t\t\tvar psmi = urlParams.psmi;\n\t\t\tvar convertedPrices;\n\n\t\t\tif (urlParams.pmin) {\n\t\t\t\turlParams.pmin = getDecodedNumber(urlParams.pmin); // Remove commas from price minimum and transform string into integer\n\t\t\t\tif (urlParams.pmin < 0) {\n\t\t\t\t\turlParams.pmin = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (urlParams.pmax) {\n\t\t\t\turlParams.pmax = getDecodedNumber(urlParams.pmax); // Remove commas from price maximum and transform string into integer\n\t\t\t\tif (urlParams.pmax < urlParams.pmin) {\n\t\t\t\t\turlParams.pmax = urlParams.pmin;\n\t\t\t\t}\n\t\t\t\t// Needed because server-side will only return products less than priceMax, not equal to. Add 1 to get products equal to.\n\t\t\t\tif (!psmi || psmi != 'true') {\n\t\t\t\t\turlParams.pmax = urlParams.pmax + 1; \n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!hasQuery && !hasCategory && hiddenFieldCategoryId) {\n\t\t\t\t// If url params don't have a cgid or a query, try grabbing cgid from hidden field on page to use for productSearchModel \n\t\t\t\turlParams.cgid = hiddenFieldCategoryId;\n\t\t\t}\n\n\t\t\t// Use server-side script to get highest priced product, and to get GLOBALE prices if applicable\n\t\t\tvar modifiedUrl = util.appendParamsToUrl(Urls.Search.GetPriceSliderPrices, urlParams);\n\t\t\t$.ajax({\n\t\t\t\ttype: 'POST',\n\t\t\t\turl: modifiedUrl,\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify({\n\t\t\t\t\tsliderMin: sliderMinValue,\n\t\t\t\t\tsliderMax: sliderMaxValue,\n\t\t\t\t\tpriceSliderSortingRule: 'price-high-to-low'\n\t\t\t\t}),\n\t\t\t\tsuccess: function(response) {\n\t\t\t\t\tif (!response || response.status == 'ERROR') {\n\t\t\t\t\t\t// Error handling\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmaxProductPrice = response.convertedSliderPmax.convertedValue;\n\t\t\t\t\t\t\tconvertedPrices = response;\n\t\t\t\t\t\t} catch(e) {\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tinitializePriceSlider(maxProductPrice, convertedPrices, psmi);\n\t\t\t\t}\n\t\t\t});\t\t\n\t\t});\n\t}\n}\n\nfunction initializePriceSlider(maxProductPrice, convertedPrices, psmi) {\n\tvar $priceSlider = $('#price-slider');\n\tvar $priceSliderContainer = $priceSlider.closest('.price-slider-parent');\n\tvar isMobile = $('html').hasClass('size-mobile');\n\tvar sliderBottomValue = 0;\n\tvar sliderTopValue = maxProductPrice ? (Math.ceil(maxProductPrice / 5) * 5) : 1200;\n\tvar userPmin = 0;\n\tvar userPmax = sliderTopValue;\n\tvar convertedSymbol, convertedSliderMin, convertedSliderMax, convertedUserMin, convertedUserMax, convertedSliderRange, convertedPriceRange;\n\n\t// Null checks\n\tif (!convertedPrices) {\n\t\tconvertedSymbol = '$';\n\t\tconvertedSliderMin = sliderBottomValue;\n\t\tconvertedSliderMax = sliderTopValue;\n\t\tconvertedUserMin = userPmin;\n\t\tconvertedUserMax = userPmax;\n\t} else {\n\t\tconvertedSymbol = convertedPrices.convertedSliderPmax.convertedSymbol;\n\t\tconvertedSliderMin = convertedPrices.convertedSliderPmin.convertedValue;\n\t\tconvertedSliderMax = convertedPrices.convertedSliderPmax.convertedValue;\n\t\tconvertedUserMin = convertedPrices.convertedUserPmin.convertedValue;\n\t\tconvertedUserMax = convertedPrices.convertedUserPmax.convertedValue;\n\t}\n\n\t// If slider instance is already initialized, go ahead and destroy before creating a new initialization\n\tif ($priceSlider.slider('instance')) {\n\t\t$('#price-slider').slider('destroy');\n\t}\n\t\n\t// Checks rounded pricing against converted pricing\n\tif (sliderTopValue != convertedSliderMax) {\n\t\t// Do this check before the rounded up value is applied to convertedSliderMax\n\t\tif (convertedUserMax == convertedSliderMax) {\n\t\t\tconvertedUserMax = sliderTopValue;\n\t\t}\n\t\t// Now update convertedSliderMax to rounded value\n\t\tconvertedSliderMax = sliderTopValue;\n\t}\n\t// If we have a pmin or pmax applied, then ensure that the price refinment bucket is expanded\n\tif ((convertedUserMin != convertedSliderMin) || (convertedUserMax != convertedSliderMax)) {\n\t\tif (!isMobile && !$('.price-refinement').hasClass('expanded')) {\n\t\t\t$('.price-refinement').addClass('expanded');\n\t\t}\n\t\t// If we somehow have a greater userPmax than highestPricedProduct in category, go ahead and revert userPmax to highestPricedProduct value\n\t\tif (convertedUserMax > convertedSliderMax) {\n\t\t\tconvertedUserMax = convertedSliderMax;\n\t\t}\n\t}\n\t// Update the DOM attributes with conversion factor to use when price slider is modified\n\tvar conversionFactor = 1;\n\tif (convertedPrices) {\n\t\tconversionFactor = convertedPrices.convertedSliderPmax.defaultValue / convertedPrices.convertedSliderPmax.convertedValue;\n\t}\n\t$priceSliderContainer.attr('data-currency-conversion-factor', conversionFactor.toString());\n\n\t\n\t// Initialize price slider\n\t$('#price-slider').slider({\n\t\trange: true,\n\t\tmin: convertedSliderMin,\n\t\tmax: convertedSliderMax,\n\t\tvalues: [ convertedUserMin, convertedUserMax ],\n\t\tslide: function(event, ui) {\n\t\t\t// On slide event, grab user input for pmin/pmax and apply to slider text, plus input fields\n\t\t\tconvertedUserMin = ui.values[0];\n\t\t\tconvertedUserMax = ui.values[1];\n\t\t\tconvertedPriceRange = convertedSymbol + convertedUserMin + ' - ' + convertedSymbol + convertedUserMax;\n\t\t\tconvertedSliderRange = convertedSymbol + convertedSliderMin + ' - ' + convertedSymbol + convertedSliderMax;\n\t\t\t$('.price-range-amount').text(convertedPriceRange);\n\t\t\t$('#price-slider > .ui-slider-range').attr('title', 'Applied Price Range: ' + convertedPriceRange);\n\t\t\t$('#price-slider').attr('title', 'Max Range: ' + convertedSliderRange);\n\t\t\t$('[data-name=\"price-input-min\"] .price-input-currency-symbol').html(convertedSymbol);\n\t\t\t$('[data-name=\"price-input-max\"] .price-input-currency-symbol').html(convertedSymbol);\n\t\t\t$('input.price-input-min').val(convertedUserMin);\n\t\t\t$('input.price-input-max').val(convertedUserMax);\n\t\t},\n\t\tstop: function(event, ui) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tconvertedUserMin = ui.values[0];\n\t\t\t\tconvertedUserMax = ui.values[1];\n\t\t\t\tif (!isMobile) { // Desktop\n\t\t\t\t\ttriggerPriceSlider(convertedUserMin, convertedUserMax);\n\t\t\t\t} else { //Mobile\n\t\t\t\t\tpriceSliderInputs(convertedUserMin, convertedUserMax, isMobile);\n\t\t\t\t}\n\t\t\t}, 750); // 0.75 seconds\n\t\t}\n\t});\t\n\n\t// For slider initialization, grab slider min and max and apply values to slider text and inputs, so everything matches at time of first load\n\tconvertedUserMin = $('#price-slider').slider('values', 0);\n\tconvertedUserMax = $('#price-slider').slider('values', 1);\n\tconvertedPriceRange = convertedSymbol + convertedUserMin + ' - ' + convertedSymbol + convertedUserMax;\n\tconvertedSliderRange = convertedSymbol + convertedSliderMin + ' - ' + convertedSymbol + convertedSliderMax;\n\t$('.price-range-amount').text(convertedPriceRange);\n\t$('#price-slider > .ui-slider-range').attr('title', 'Applied Price Range: ' + convertedPriceRange);\n\t$('#price-slider').attr('title', 'Max Range: ' + convertedSliderRange);\n\t$('[data-name=\"price-input-min\"] .price-input-currency-symbol').html(convertedSymbol);\n\t$('[data-name=\"price-input-max\"] .price-input-currency-symbol').html(convertedSymbol);\n\t$('input.price-input-min').val(convertedUserMin);\n\t$('input.price-input-max').val(convertedUserMax);\n\n\t// Price inputs\n\t$(document).off('keypress', '.price-input-container input').on('keypress', '.price-input-container input', function(e) {\n\t\t$('.price-inputs-apply-button button').css('display','block');\n\t}).off('click', '.price-inputs-apply-button button').on('click', '.price-inputs-apply-button button', function(e) {\n\t\tpriceSliderInputs(convertedSliderMin, convertedSliderMax, isMobile);\n\t})\n}\n\nfunction priceSliderGoogleAnalyticsTagging() {\n\tif (SitePreferences.GA_NEW_ACTIONS_ENABLED) {\n\t\tvar refinementId = $('#price-slider').closest('[refinement-id]').attr('refinement-id') || null;\n\t\tvar refinementValue = $('#price-slider').closest('.price-slider-parent').find('.price-range-header .price-range-amount').text() || null;\n\t\tif (refinementId && refinementValue) {\n\t\t\tvar refinementAnalyticsTaggingData =  { \n\t\t\t\t'action_value': { 'refinement_category': refinementId }, \n\t\t\t\t'action_items': { 'refinement_value': refinementValue }\n\t\t\t};\n\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ApplyRefinement', refinementAnalyticsTaggingData);\n\t\t}\n\t}\n}\n\nfunction initMobilePriceSlider(url) {\n\tvar isPriceSlider = SitePreferences.PRICE_SLIDER_ENABLED && $('#price-slider').slider('instance');\n\tvar isMobile = $('html').hasClass('size-mobile');\n\tvar $applyRefinementsBtn = $('.apply-refinements:not(.disabled)');\n\tvar isButtonClick = $applyRefinementsBtn.length > 0 && $applyRefinementsBtn[0].hasAttribute('data-apply-refinements') && $applyRefinementsBtn.attr('data-apply-refinements') == 'true';\n\t\n\tif (isPriceSlider && isMobile && isButtonClick) {\n\t\tvar isPriceSliderChanged = ($('#price-slider').slider('option', 'min') != $('#price-slider').slider('values', 0) || $('#price-slider').slider('option', 'max') != $('#price-slider').slider('values', 1)) || false;\n\t\tif (isPriceSliderChanged) {\n\t\t\tvar userPriceMin = $('#price-slider').slider('values', 0);\n\t\t\tvar userPriceMax = $('#price-slider').slider('values', 1);\n\t\t\t$applyRefinementsBtn.attr('data-apply-refinements','false');\n\t\t\treturn triggerPriceSlider(userPriceMin, userPriceMax, url);\n\t\t} else {\n\t\t\treturn url;\n\t\t}\n\t} else {\n\t\treturn url;\n\t}\n}\n\nfunction priceSliderInputs(sliderBottomValue, sliderTopValue, isMobile) {\n\t// Input fields\n\tvar inputPmin = $('.price-input-min').val() ? parseInt($('.price-input-min').val()) : sliderBottomValue;\n\tvar inputPmax = $('.price-input-max').val() ? parseInt($('.price-input-max').val()) : sliderTopValue;\n\tif (inputPmin < 0) {\n\t\tinputPmin = 0;\n\t\t$('.price-input-min').val(inputPmin);\n\t}\n\tif (inputPmax > sliderTopValue) {\n\t\tinputPmax = sliderTopValue;\n\t\t$('.price-input-max').val(inputPmax);\n\t}\n\t// Update the price slider values based on the input fields\n\tvar $priceSlider = $('#price-slider').slider('instance');\n\tif ($priceSlider) {\n\t\t$('#price-slider').slider({\n\t\t\tvalues: [ inputPmin, inputPmax ]\n\t\t});\n\t}\n\n\tif (!isMobile || pageContext.site == SiteConstants.SiteIds.BootBarnRspUS) {\n\t\t// Desktop\t\n\t\ttriggerPriceSlider(inputPmin, inputPmax);\n\t} else {\n\t\t// Mobile\n\t\tif ($priceSlider) {\n\t\t\tvar isPriceSliderChanged = ($('#price-slider').slider('option', 'min') != $('#price-slider').slider('values', 0) || $('#price-slider').slider('option', 'max') != $('#price-slider').slider('values', 1)) || false;\n\t\t\tif (isPriceSliderChanged) {\n\t\t\t\t$('.refinements').addClass('refinements-modified');\n\t\t\t\t$('.refinements-inner-container-footer .apply-refinements').removeClass('disabled');\n\t\t\t} else {\n\t\t\t\t$('.refinements').removeClass('refinements-modified');\n\t\t\t\t$('.refinements-inner-container-footer .apply-refinements').addClass('disabled');\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Expects numbers as parameters, not strings\nfunction triggerPriceSlider(priceMin, priceMax, passedUrl) {\n\ttry {\n\t\tvar url = passedUrl;\n\t\tif (!passedUrl || pageContext.site == SiteConstants.SiteIds.BootBarnRspUS) {\n\t\t\t$('body').loading(loadingIndicatorSettings);\n\t\t\turl = window.location.href;\n\t\t}\n\n\t\t// Take user local currency and revert it back to U.S. (merchant site currency) before running the search query\n\t\tvar currencyConversionFactor = parseFloat($('#price-slider').closest('.price-slider-parent').attr('data-currency-conversion-factor'));\n\t\tvar revertedPmin = priceMin * currencyConversionFactor;\n\t\tvar revertedPmax = priceMax * currencyConversionFactor; \n\t\trevertedPmax = revertedPmax + 1; // Needed because server-side will only return products less than priceMax, not equal to. Add 1 to get products equal to.\n\n\t\turl = util.removeParamFromURL(url, 'pmin');\n\t\turl = util.removeParamFromURL(url, 'pmax');\n\t\turl = util.removeParamFromURL(url, 'psmi');\n\t\turl = util.appendParamToURL(url, 'pmin', revertedPmin.toFixed());\n\t\turl = util.appendParamToURL(url, 'pmax', revertedPmax.toFixed());\n\t\turl = util.appendParamToURL(url, 'psmi', 'true');\n\n\t\tpriceSliderGoogleAnalyticsTagging();\n\t\t\n\t\tif (!passedUrl || pageContext.site == SiteConstants.SiteIds.BootBarnRspUS) {\n\t\t\tupdateProductListing(url);\n\t\t} else {\n\t\t\treturn url;\n\t\t}\n\t} catch (e) {\n\t\t$('body').loading('destroy');\n\t}\n}\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter || {};\n\n\tImageConstants = pageContext.site === SiteConstants.SiteIds.CountryOutfittersUS ? require('../../../../app_storefront_countryoutfitters/cartridge/js/ImageConstants') : require('../../../../bc_sheplersbootbarn_core/cartridge/js/ImageConstants');\n\t\n    compareWidget.init();\n    if ('variantInventoryMessagingUrl' in page && page.variantInventoryMessagingUrl) {\n    \tvar urlParams = util.getQueryStringParams(window.location.search.substr(1));\n    \tif(urlParams.hasOwnProperty('start') && urlParams.start > 0){\n    \t\tupdateInventoryMessages(window.location.href, showVariantInventoryMessaging);\n    \t} else {\n            showVariantInventoryMessaging();\n    \t}\n    }\n\n    productTile.init();\n    sizeRefinements.init();\n    initializeEvents();\n\tupdateShopMyStore();\n\tsliders.initializeCategorySliders('.main-content .category-landing-slider:not(.slick-initialized)');\n\tinitializeRefinementFilterByText();\n\tif (pageContext.site == SiteConstants.SiteIds.BootBarnUS) {\n\t\tinitializeBootFinderEvents();\n\t}\n\tloadScrollPosition();\n\tsaveScrollPosition();\n\tif (pageContext.site == SiteConstants.SiteIds.CountryOutfittersUS) {\n\t\tinitializeStickyRefinements();\n\t\t// initializeStickySubheader();\n\t}\n\n\tloadingIndicatorSettings = {\n\t\tIsLabelShown: false,\n\t\tCssClass: 'fullscreen',\n\t\tBackgroundColor: 'transparent'\n\t};\n\n\tif (pageContext.site == SiteConstants.SiteIds.Rangefinder) {\n\t\tinitializeRangefinderEvents();\n\t}\n\n\tif (options) {\n\t\tif (options.StyleCountCache) {\n\t\t\tstyleCounts.render(options.StyleCountCache);\n\t\t}\n\n\t\tif (options.Bopis && options.Bopis.Enabled && options.Bopis.SelectedLocations) {\n\t\t\tbootBarnExpressRefinementWizard.initialize($('#dialog-bootbarnexpress-refinement-wizard'), options);\n\t\t}\n\n\t\tif (options.RefinementsUIVersion == RefinementUIVersionConstants.Updated) {\n\t\t\tupdateRefinementCounts();\n\t\t\tif (options.StoreUIVersion == '2024Redesign') {\n\t\t\t\tupdateSelectedRefinements();\n\t\t\t\tupdatePendingRefinements();\n\t\t\t}\n\t\t\n\t\t\tvar $productSelectionContainer;\n\t\t\tif (pageContext.site === SiteConstants.SiteIds.SheplersUS) {\n\t\t\t\t$productSelectionContainer = $('.primary-content > .sort-and-refine > .product-selections');\n\t\t\t} else {\n\t\t\t\t$productSelectionContainer = $('.primary-content > .product-selections')\n\t\t\t}\n\n\t\t\tif ($productSelectionContainer.find('.list-selections .value.applied').length > 0) {\n\t\t\t\t$productSelectionContainer.show();\n\t\t\t} else {\n\t\t\t\t$productSelectionContainer.hide();\n\t\t\t}\n\t\t}\n\t}\n};\n","'use strict';\n\nvar LocationSearch = require('../../../../app_storefront_core/cartridge/js/bopis/components/LocationSearch');\n\nexports.init = function (options) {\n\tvar loadingIndicatorSettings = {\n\t\tIsLabelShown: false,\n\t\tCssClass: 'fullscreen',\n\t\tBackgroundColor: 'transparent'\n\t};\n\n\tif ($('.pt_storefront .search-stores').length > 0) {\n\t\tvar locationSearch = new LocationSearch();\n\t\t$(document).off('click.Storefront.StoreSearch').on('click.Storefront.StoreSearch', '.pt_storefront .search-stores:not(.disabled)', function(event) {\n\t\t\tevent.preventDefault();\n\n\t\t\tlocationSearch.initialize($('.location-search-dialog'), options);\n\t\t\t$('.location-search-dialog').trigger('LocationSearch.FormSubmit');\n\t\t});\n\t}\n\n\t$('.pt_storefront .section .btn:not(.search-stores)').off('click.LoadingIndicator').on('click.LoadingIndicator', function() {\n\t\t$('body').loading(loadingIndicatorSettings);\n\t});\n};","'use strict';\n\nvar _ = require('lodash');\nvar loadingIndicator = require('../components/LoadingIndicator');\nvar GeolocationHelper = require('../../../../bc_sheplersbootbarn_core/cartridge/js/Geolocation/GeolocationHelper');\nvar shopYourStoreDialog = require('../bopis/components/ShopYourStoreDialog');\nvar TemplateConstants = require('../../../../bc_sheplersbootbarn_core/cartridge/js/TemplateConstants');\n\nvar options;\nvar dataBuffer;\nvar inputSearchTimer;\n\nvar $container;\nvar $content;\nvar $useMyLocationButton;\nvar $searchButton;\nvar $locationSearchResults;\nvar locationSearchResultContainerTemplate;\nvar locationSearchResultItemTemplate;\n\nfunction initializeEvents() {\n\t$(document).off('click.ShopYourStoreDialog').on('click.ShopYourStoreDialog', '.shop-store-inventory', function(event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $store = $this.closest('[store-id]');\n\t\tshopYourStoreDialog.initialize({\n\t\t\tStoreId: $store.attr('store-id'),\n\t\t\tStoreName: $store.attr('store-name')\n\t\t});\n\t});\n\n\t$('.pt_store-locator').off('click.UseMyLocation').on('click.UseMyLocation', '.use-my-location', function (event) {\n\t\tevent.preventDefault();\n\n\t\tdataBuffer.limit = window.outerWidth >= 1024 ? 10 : 5;\n\t\tdataBuffer.offset = 0;\n\t\tdataBuffer.query = '';\n\t\t$('.store-filter-container [type=\"text\"]').val('');\n\n\t\t$useMyLocationButton.loading();\n\t\t$locationSearchResults.html('');\n\t\t$locationSearchResults.loading();\n\t\tGeolocationHelper.GetPosition().then(function(position) {\n\t\t\tdataBuffer.position = position;\n\t\t\tgetStoreList();\n\t\t}).catch(function() {\n\t\t\tif ($locationSearchResults.attr('loading')) {\n\t\t\t\t$locationSearchResults.loading('destroy');\n\t\t\t}\n\t\t});\n\t});\n\n\t$('.pt_store-locator').off('submit.Search').on('submit.Search', '.store-filter-container form', function (event) {\n\t\tevent.preventDefault();\n\t\tsearch();\n\t});\n\n\t$('.pt_store-locator').off('click.Search').on('click.Search', '.store-filter-container .btn.btn-primary', function (event) {\n\t\tevent.preventDefault();\n\t\tsearch();\n\t});\n\n\t$('.pt_store-locator').off('click.LoadMore').on('click.LoadMore', '.location-search-results .load-more', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tdataBuffer.limit = window.outerWidth >= 1024 ? 10 : 5;\n\t\tdataBuffer.offset += dataBuffer.limit;\n\t\t$this.parent().loading();\n\t\tGeolocationHelper.GetPosition().then(function(position) {\n\t\t\tdataBuffer.position = position;\n\t\t\tgetStoreList();\n\t\t}).catch(function() {\n\t\t\tif ($locationSearchResults.attr('loading')) {\n\t\t\t\t$locationSearchResults.loading('destroy');\n\t\t\t}\n\t\t});\n\t});\n}\n\nfunction search() {\n\tdataBuffer.limit = window.outerWidth >= 1024 ? 10 : 5;\n\tdataBuffer.offset = 0;\n\tdataBuffer.query = $('.store-filter-container [type=\"text\"]').val();\n\n\t$searchButton.loading();\n\t$locationSearchResults.html('');\n\t$locationSearchResults.loading();\n\tGeolocationHelper.GetPosition().then(function(position) {\n\t\tdataBuffer.position = position;\n\t\tgetStoreList();\n\t}).catch(function() {\n\t\tif ($locationSearchResults.attr('loading')) {\n\t\t\t$locationSearchResults.loading('destroy');\n\t\t}\n\t});\n}\n\nfunction getStoreList() {\n\tvar geolocationPosition;\n\tif (dataBuffer.position && dataBuffer.position.coords) {\n\t\tgeolocationPosition = {\n\t\t\tcoords: {\n\t\t\t\taccuracy: dataBuffer.position.coords.accuracy,\n\t\t\t\tlatitude: dataBuffer.position.coords.latitude,\n\t\t\t\tlongitude: dataBuffer.position.coords.longitude\n\t\t\t},\n\t\t\ttimestamp: dataBuffer.position.timestamp\n\t\t};\n\t}\n\n\tvar payload = {\n\t\tSource: 'StoreLocatorPage',\n\t\tGeolocationPosition: geolocationPosition\n\t};\n\tif (dataBuffer.query != undefined) {\n\t\tpayload.Query = dataBuffer.query;\n\t}\n\tif (dataBuffer.limit != undefined) {\n\t\tpayload.Limit = dataBuffer.limit;\n\t}\n\tif (dataBuffer.offset != undefined) {\n\t\tpayload.Offset = dataBuffer.offset;\n\t}\n\n\t$.ajax({\n\t\tmethod: 'POST',\n\t\turl: Urls.Bopis.GetStoresForGeolocationPosition,\n\t\tcontentType: 'application/json',\n\t\tdata: JSON.stringify(payload),\n\t\tdataType: 'json',\n\t\tsuccess: function(data) {\n\t\t\trenderStoreList(data);\n\t\t},\n\t\terror: function() {\n\t\t\t\n\t\t}\n\t});\t\t\n}\n\nfunction renderStoreList(data) {\n\tvar locationData;\n\tif (data && data.ServiceSuccessfullyCalled && data.InquiryResult && data.InquiryResult.data && data.InquiryResult.data.length > 0) {\n\t\tlocationData = data.InquiryResult.data;\n\t}\n\n\t$container.attr('state', 'result');\n\tif (locationData && locationData.length > 0) {\n\t\tlocationData = locationData.sort(function(left, right) {\n\t\t\treturn left.distance - right.distance;\n\t\t});\n\t\t\n\t\tdataBuffer['StoresDisplayed'] = [];\n\t\t$container.attr('result-count', locationData.length);\n\t\t\n\t\tvar storeListHtml = '';\n\t\t$locationSearchResults.find('.no-results').remove();\n\t\tfor (var locationElement in locationData) {\n\t\t\tvar location = locationData[locationElement];\n\t\t\t\n\t\t\tif (location && !dataBuffer['StoresDisplayed'][location.code] && location.StoreInfo.StateCodeParsed && location.StoreInfo.PostalCode) {\n\t\t\t\tvar storePhone = '';\n\t\t\t\tvar storeOpenUntil = '';\n\t\t\t\tif (location.StoreInfo) {\n\t\t\t\t\tif (location.StoreInfo.Phone) {\n\t\t\t\t\t\tstorePhone = location.StoreInfo.Phone;\n\t\t\t\t\t}\n\t\t\t\t\tif (location.StoreInfo.OpenUntil) {\n\t\t\t\t\t\tstoreOpenUntil = location.StoreInfo.OpenUntil;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar storeInventoryLink = '';\n\t\t\t\tif (location.StoreInfo.StoreInventoryLink) {\n\t\t\t\t\tstoreInventoryLink = '<a class=\"shop-store-inventory\">' + Resources.Stores.ShopStoreInventory + '</a>';\n\t\t\t\t}\n\n\t\t\t\tvar directionsLink = '';\n\t\t\t\tif (location.StoreInfo.DirectionsUrl) {\n\t\t\t\t\tdirectionsLink = '<a class=\"directions\" href=\"' + location.StoreInfo.DirectionsUrl + '\" target=\"_blank\">Directions</a>';\n\t\t\t\t}\n\n\t\t\t\tstoreListHtml += locationSearchResultItemTemplate({\n\t\t\t\t\tStoreId: location.code,\n\t\t\t\t\tStoreName: location.StoreInfo.Name,\n\t\t\t\t\tDistance: location.StoreInfo.Distance.toFixed(1) + ' mi',\n\t\t\t\t\tHtml: '<a href=\"' + Urls.storeDetails + '?StoreID=' + location.code + '\">' + location.StoreInfo.Name + '</a><br/>' +\n\t\t\t\t\t\t\tlocation.StoreInfo.Address1 + '<br/>' + \n\t\t\t\t\t\t\tlocation.StoreInfo.City + ', ' + location.StoreInfo.StateCodeParsed + ' ' + location.StoreInfo.PostalCode.substr(0, 5) + '<br/>' +\n\t\t\t\t\t\t\tstorePhone + '<br/>' +\n\t\t\t\t\t\t\tstoreOpenUntil,\n\t\t\t\t\tDirectionsLink: directionsLink,\n\t\t\t\t\tStoreInventoryLink: storeInventoryLink\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tdataBuffer['StoresDisplayed'][location.code] = true;\n\t\t}\n\t\tif (data.InquiryResult.meta && data.InquiryResult.meta.page < data.InquiryResult.meta.pages) {\n\t\t\tstoreListHtml += '<li class=\"load-more-container\"><a class=\"load-more\">Load More</a></li>';\n\t\t}\n\t\t\n\t\tvar resultHtml = locationSearchResultContainerTemplate({\n\t\t\tHtml: storeListHtml\n\t\t});\n\t\t$locationSearchResults.find('.load-more-container').remove();\n\t\t$locationSearchResults.append(resultHtml);\n\t} else {\n\t\t$container.attr('result-count', '0');\n\t\t$locationSearchResults.html('<li class=\"no-results\">No stores found! Please try a different search.</li>');\n\t}\n\n\tif ($useMyLocationButton.attr('loading')) {\n\t\t$useMyLocationButton.loading('destroy');\n\t}\n\tif ($searchButton.attr('loading')) {\n\t\t$searchButton.loading('destroy');\n\t}\n\tif ($locationSearchResults.attr('loading')) {\n\t\t$locationSearchResults.loading('destroy');\n\t}\n}\n\nexports.init = function (optionsParameter) {\n\toptions = optionsParameter || {};\n\tdataBuffer = {\n\t\toffset: 0\n\t};\n\n\t$container = $('#stores_main');\n\t$content = $container.find('.content');\n\t$useMyLocationButton = $('.store-filter-container .use-my-location');\n\t$searchButton = $('.store-filter-container .btn.btn-primary');\n\t$locationSearchResults = $('.location-search-results');\n\tlocationSearchResultContainerTemplate = _.template($('#template-bopis-result-container').html(), TemplateConstants.Lodash.Settings);\n\tlocationSearchResultItemTemplate = _.template($('#template-bopis-result-item-store-locator').html(), TemplateConstants.Lodash.Settings);\t\n\n\tinitializeEvents();\n};","'use strict';\r\n\r\nmodule.exports = {\r\n\t\r\n\telementPrefix: 'shipping-restrictions-popup',\r\n\telement: null,\r\n\tdefaultTitle: '',\r\n\tdefaultContent: '',\r\n\t\r\n\tinit: function (options) {\r\n\t\tif (!$( '.' + this.elementPrefix ).length) {\r\n\t\t\t$('body').append('<div class=\"' + this.elementPrefix + '\"><div class=\"' + this.elementPrefix + '__popup\"><h2 class=\"' + this.elementPrefix + '__h2\"></h2><a class=\"' + this.elementPrefix + '__close\" href=\"#\">&times;</a><div class=\"' + this.elementPrefix + '__content\"></div></div></div>');\r\n\t\t\tthis.element = $( '.' + this.elementPrefix );\r\n\t\t\tvar el = this;\r\n\t\t\tthis.element.find('.' + this.elementPrefix + '__close').on('click', function (e) {\r\n\t\t\t\tel.hidePopup(e);\r\n\t\t\t});\r\n\t\t}\r\n\t\tthis.element.find('.' + this.elementPrefix + '__h2').html(options.title || this.defaultTitle);\r\n\t\tthis.element.find('.' + this.elementPrefix + '__content').html(options.content || this.defaultContent);\r\n\t\treturn this;\r\n\t},\r\n\t\r\n\tshowPopup: function () {\r\n    \tthis.element.addClass(this.elementPrefix + '__visible');\r\n    \treturn this;\r\n    },\r\n    \r\n    hidePopup: function (e) {\r\n    \te.preventDefault();\r\n    \tthis.element.removeClass(this.elementPrefix + '__visible');\r\n    },\r\n};\r\n","'use strict';\n\nvar imagesLoaded = require('imagesloaded');\nvar util = require('./util');\n\nexports.syncHeightOfTiles = syncHeightOfTiles;\n\nvar windowWidth;\n\nfunction gridViewToggle() {\n    $('.toggle-grid').on('click', function () {\n        $('.search-result-content').toggleClass('wide-tiles');\n        $(this).toggleClass('wide');\n    });\n}\n\n/**\n * @private\n * @function\n * @description line clamping for product tile product titles.\n */\n\n function clampProductTileTitles() {\n    $('h6.product-name .name-link').each(function(index, clampTitle) {\n        $clamp(clampTitle, {\n            clamp: 2,\n            useNativeCLamp: false\n        });\n    });\n }\n \n function initializeSwatches() {\n\t $('.grid-tile').each(function(index, element) {\n\t\t$(element).find('.yes-alts ul.swatch-list li').each(function(i, elem) {\n\t\t\tvar altDisplay = 'show-content';\n\t\t\tif ( i >= 4 ){\n\t\t\t\taltDisplay = 'hidden-content';\n\t\t\t}\n\t\t\t$(elem).addClass(altDisplay);\n\t\t});\n\t\tvar altHiddenCount = $(element).find('.hidden-content').length;\n\t\tvar altHiddenToggle = '+ ' + altHiddenCount;\n\t\tvar altButtonExists = $(element).find('.altButton').length;\n\t\tif (altHiddenCount > 0){\n\t\t\t$(element).find('.hidden-content').hide();\n\t\t\tif (altButtonExists == 0){\n\t\t\t\t$(element).find('.yes-alts ul.swatch-list').append('<button class=\"altButton\">' + altHiddenToggle + '</button>');\n\t\t\t} else {\n\t\t\t\t$(element).find('.altButton').text(altHiddenToggle);\n\t\t\t}\n\t\t}\n\t});\n }\n\n/**\n * @private\n * @function\n * @description Initializes events on the product-tile for the following elements:\n * - swatches\n * - thumbnails\n */\nfunction initializeEvents() {\n    gridViewToggle();\n    initializeSwatches();\n    \n    $(document).ready(function() {\n    \t$('#search-result-items .grid-tile').each(function() {\n    \t\tvar $gridItem = $(this),\n    \t\t\t$primaryColor = $gridItem.data('primary-color'),\n    \t\t\t$thumb = $gridItem.find('.product-image .thumb-link img').eq(0),\n    \t\t\t$thumblink = $gridItem.find('.product-image a.thumb-link').eq(0),\n    \t\t\t$namelink = $gridItem.find('.product-content .product-name a.name-link').eq(0);\n    \t\t$gridItem.find('.product-content .product-swatches .swatch-list li').each(function() {\n    \t\t\tvar $currswatch = $(this),\n    \t\t\t\t$currhref = $currswatch.find('a.swatch').attr('href'),\n    \t\t\t\t$currcolor = $currswatch.data('color');\n    \t\t\tif ($primaryColor == $currcolor) {\n    \t\t\t\tvar $data = $currswatch.find('.swatch-image').data('thumb');\n    \t\t\t\t\n    \t\t\t\tif ($thumblink.attr('selected-locations')) {\n    \t\t\t\t\t$currhref = util.appendParamToURL($currhref, 'selectedLocations', $thumblink.attr('selected-locations'));\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\t$namelink.attr('href', $currhref);\n    \t\t\t\t$thumblink.attr('href', $currhref);\n    \t\t\t\t\n\t\t\t\t\tif ($data) {\n\t\t\t\t\t\t$thumb.attr({\n\t\t\t\t\t\t\tsrc: $data.src,\n\t\t\t\t\t\t\talt: $data.alt,\n\t\t\t\t\t\t\ttitle: $data.title\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n    \t\t\t}\n    \t\t})\n    \t});\n\n\t\t$(window).off('load.ProductTile resize.ProductTile').on('load.ProductTile resize.ProductTile', function () {\n            if (windowWidth != $(window).width()) {\n\t\t\t    syncHeightOfTiles();\n            }\n\t\t});\n\n\t\timagesLoaded($('#search-result-items .grid-tile')).on('done', function () {\n\t\t\tsyncHeightOfTiles();\n        });\n    });\n    \n\t$('.swatch-list .swatch').on('click', function (event) {\n\t\tevent.preventDefault();\n\n        // get current thumb details\n        var $tile = $(this).closest('.product-tile'),\n            $thumb = $tile.find('.product-image .thumb-link img').eq(0),\n            data = $(this).children('.swatch-image').filter(':first').data('thumb'),\n            current = $thumb.data('current');\n\n        // If this is the first time, then record the current img\n        if (!current) {\n            $thumb.data('current', {\n                src: $thumb[0].src,\n                alt: $thumb[0].alt,\n                title: $thumb[0].title\n            });\n        }\n\n        // Set the tile image to the values provided on the swatch data attributes\n\t\tif (data) {\n\t\t\t$thumb.attr({\n\t\t\t\tsrc: data.src,\n\t\t\t\talt: data.alt,\n\t\t\t\ttitle: data.title\n\t\t\t});\n\t\t}\n    });\n\t\n    // check every 2 secs if BV stars has already loaded\n    // in case BV is just delayed in showing up, we need to check the interval for at least 5x to prevent infinite loop\n    var hideStars = setInterval(function(){\n    \tvar ctr = 0;\n    \t$(\"div[id^=BVRRInlineRating]\").each(function () {\n    \t\tif ($(this).find(\".bv-rating-stars-on\").width() > 0) { } else { $(this).find(\".bv-stars-container\").attr(\"style\", \"display:none !important\"); }\n    \t\tif ($(this).find(\".bv-rating-stars-on\").length) {\n    \t\t\tclearInterval(hideStars);\n    \t\t} else { ctr++;\t}\n    \t});\n    \tif (ctr>10) { clearInterval(hideStars); } //we need to stop the function if BV is not configured.\n    }, 2000);\n\n    var attemptsToChangeText = 0;\n    var addTextReviewsToCountReviews = setInterval(function(){\n    \tattemptsToChangeText++;\n    \t$('div[id^=BVRRInlineRating]').each(function(){\n    \t\tvar $rating = $(this).find('span.bv-rating-label');\n    \t\tif ($rating.length) {\n    \t\t\tvar text = $rating.html();\n        \t\tif (text.indexOf(Resources.REVIEWS) < 0) {\n        \t\t\t$rating.html(text.replace(')', ' ' + Resources.REVIEWS + ')'));\n        \t\t\tclearInterval(addTextReviewsToCountReviews);\n        \t\t}\n    \t\t}\n    \t});\n    \tif (attemptsToChangeText > 15) {\n    \t\tclearInterval(addTextReviewsToCountReviews);\n    \t}\n    }, 500);\n    \n    $(document).on('click', 'div.bv-compat', function(){\n        var $tileBlock = $(this).closest('div.product-tile');\n        if ($tileBlock) {\n            location.href = $tileBlock.find('a.thumb-link').attr('href');\n        }\n    });\n\n    clampProductTileTitles();\n}\n\nfunction syncHeightOfTiles() {\n\tvar $tiles = $('.tiles-container .product-tile');\n    if ($tiles.length === 0) { return; }\n\n\t$tiles.find('.product-image .thumb-link').syncHeightToAverage();\n\t$tiles.each(function (idx) {\n\t\t$(this).data('idx', idx);\n\t});\n}\n\nexports.init = function () {\n    windowWidth = $(window).width();\n\n    initializeEvents();\n};\n","'use strict';\r\n\r\nmodule.exports = {\r\n\t\r\n\tinit: function (options) {\r\n\t\tif ($('.rotate-3d__img').length) {\r\n\t\t\t$('.rotate-3d__container').prepend('<a href=\"#\" class=\"rotate-3d__rotate rotate-3d__rotateLeft\">&nbsp;</a><a href=\"#\" class=\"rotate-3d__rotate rotate-3d__rotateRight\">&nbsp;</a>');\r\n\t\t\t$('.rotate-3d__rotateLeft').on('click', function (e) {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\t$('.rotate-3d__img').trigger(\"stepLeft\");\r\n\t\t\t});\r\n\t\t\t$('.rotate-3d__rotateRight').on('click', function (e) {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\t$('.rotate-3d__img').trigger(\"stepRight\");\r\n\t\t\t});\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n};\r\n","'use strict';\n\nvar $loader;\n\n/**\n * @function\n * @description Shows an AJAX-loader on top of a given container\n * @param {Element} container The Element on top of which the AJAX-Loader will be shown\n */\nvar show = function (container, displayInLine) {\n    var target = (!container || $(container).length === 0) ? $('body') : $(container);\n    $loader = $loader || $('.loader');\n\n    if ($loader.length === 0) {\n        $loader = $('<div/>').addClass('loader')\n            .append($('<div/>').addClass('loader-indicator'), $('<div/>').addClass('loader-bg'));\n    }\n\n    if (displayInLine) {\n        $loader.css('display', 'inline-block');\n    } else {\n        $loader.css('display', 'block');\n    }\n    return $loader.appendTo(target);\n};\n/**\n * @function\n * @description Hides an AJAX-loader\n */\nvar hide = function () {\n    if ($loader) {\n        $loader.hide();\n    }\n};\n\nexports.show = show;\nexports.hide = hide;\n","'use strict';\n\nvar page = require('./page');\nvar DataLayerConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/DataLayerConstants');\nvar GoogleTagManagerClient = require('../../../bc_sheplersbootbarn_core/cartridge/js/util/GoogleTagManagerClient');\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar isCheckout, isEchoCart, fnUpdateCart, fnRenderCart, $focusedElement;\nvar loadingIndicatorSettings = {\n    IsLabelShown: false,\n    CssClass: 'fullscreen',\n    BackgroundColor: 'transparent'\n};\n\nfunction updateStepperQtyUI($this, increment) {\n\tvar $quantityStepper = increment != undefined ? $this.parent('.quantity-stepper') : $this;\n\tvar $input = $quantityStepper.find('input.input-text');\n\tvar quantity = parseInt($input.val());\n\t// Only increment or decrement quantity if a boolean was passed into the function\n\tif (increment != undefined) {\n\t\tincrement ? quantity++ : quantity--;\n\t}\n\t\n\t// Enable or Disable the plus/minus signs on the quantity stepper\n\tvar $incButton = $quantityStepper.find('button.increase.plus');\n\tvar $decButton = $quantityStepper.find('button.decrease.minus');\n\n\tif (quantity <= 1) {\n\t\t$decButton.addClass('disabled').attr('disabled', 'disabled');\n\t\t$incButton.removeClass('disabled').removeAttr('disabled');\n\t} else if (quantity > 1) {\n\t\t$decButton.removeClass('disabled').removeAttr('disabled');\n\t\t$incButton.removeClass('disabled').removeAttr('disabled');\n\t}\n\n\t// Update the value of the quantity stepper\n\t$input.attr('quantity-buffer', quantity);\n\t$input.val(quantity);\n}\n\nfunction updateMiniCartUI(increment, $lineItem) {\n\tvar $miniCartElm = $('.mini-cart .minicart-quantity').length > 0 ? $('.mini-cart .minicart-quantity') : $('.mini-cart .btn-minicart .btn-minicart-qty');\n\tvar miniCartTotal;\n\tif ($miniCartElm.length > 0) {\n\t\tminiCartTotal = parseInt($miniCartElm.html().trim());\n\t}\n\n\tif ((increment != null && typeof increment === \"boolean\") && !$lineItem) {\n\t\tincrement ? miniCartTotal++ : miniCartTotal--;\n\t} else if ((increment == null || typeof increment != \"boolean\") && $lineItem) {\n\t\tvar itemQty = parseInt($lineItem.find('.opc-qty').val());\n\t\tminiCartTotal = itemQty && typeof itemQty == 'number' && itemQty > 0 ? miniCartTotal - itemQty : miniCartTotal;\n\t\t$lineItem.remove();\n\t}\n\t\n\t// Update the basket quantity on the main navigation bar > minicart icon\n\tminiCartTotal >= 1 ? $miniCartElm.html(miniCartTotal) : $miniCartElm.html(0);\n\n\t// Update the minicart modal, if it's currently open\n\tif ($('.add-to-cart-modal').length > 0) {\n\t\tvar productRecommendationsHtml = $('.add-to-cart-modal  .main-content .product-recommendations-container').html();\n\t\t$.ajax({url : Urls.addToCartModalDisplay, dataType: 'html', success : function(modalContent) {\n\t\t\tif (modalContent.length > 0) {\n\t\t\t\t$('.add-to-cart-modal .ui-dialog-content').html(modalContent);\n\t\t\t\t$('.add-to-cart-modal-content .main-content .product-recommendations-container').append(productRecommendationsHtml);\n\t\t\t\t// Reference addToCart.js > addItemToCart() > line 314 (Move title from main content to top of the modal)\n\t\t\t\tif ($('.add-to-cart-modal-content').length > 0) {\n\t\t\t\t\tvar $addMessage = $('.add-to-cart-modal-content .main-content .added-message');\n\t\t\t\t\t// Reference addToCart.js > addItemToCart() > line 377 (Inserts the word 'Item' into the minicart title)\n\t\t\t\t\t$('.add-to-cart-modal-content .added-message .count').text('Item');\n\t\t\t\t\tif ($addMessage.length > 0) {\n\t\t\t\t\t\t$('.add-to-cart-modal-content').prepend($addMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}});\n\t}\n}\n\nfunction updateCartTotals() {\n\tif (isCheckout && fnUpdateCart) {\n\t\tfnUpdateCart($('.update-cart-button').attr('name'));\n\t}\n\tif (isEchoCart && fnRenderCart) {\n\t\tfnRenderCart();\n\t}\n}\n\nfunction removeFromCartDataLayer($this) {\n\tvar $item = $this.closest('[data-uuid]');\n\tif ($item) {\n\t\tvar productDataForUniversalAnalytics = JSON.parse($item.find('[data-product-gtm-json]').attr('data-product-gtm-json'));\n\t\tvar productDataForGoogleAnalytics4 = JSON.parse($item.find('[data-product-ga4-json]').attr('data-product-ga4-json'));\n\n\t\tvar dataObject = {\n\t\t\tUniversalAnalytics: {\n\t\t\t\tecommerce: {\n\t\t\t\t\tremove: {\n\t\t\t\t\t\tproducts: [productDataForUniversalAnalytics]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\t\t\t\t\t\t\t\n\t\t\tGoogleAnalytics4: {\n\t\t\t\tvalue: productDataForGoogleAnalytics4.price,\n\t\t\t\titems: [productDataForGoogleAnalytics4]\n\t\t\t}\n\t\t}\n\n\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('RemoveFromCart', dataObject);\n\t}\n}\n\nfunction quantityDatalayerEvents($this, eventType, quantity) {\n\tvar $item = $this.closest('[data-uuid]');\n\n\tvar eventName;\n\tvar ecommerceKey;\n\tif (eventType == DataLayerConstants.EventTypes.Minus) {\n\t\teventName = DataLayerConstants.Events.Cart.RemoveFromCart.Name;\n\t\tecommerceKey = 'remove';\n\t} else {\n\t\teventName = DataLayerConstants.Events.Cart.AddToCart.Name;\n\t\tecommerceKey = 'add';\n\t} \n\t\n\tvar productDataForUniversalAnalytics = JSON.parse($item.find('[data-product-gtm-json]').attr('data-product-gtm-json'));\n\tvar productDataForGoogleAnalytics4 = JSON.parse($item.find('[data-product-ga4-json]').attr('data-product-ga4-json'));\n\tif (quantity) {\n\t\tproductDataForUniversalAnalytics.quantity = quantity;\n\t\tproductDataForGoogleAnalytics4.quantity = quantity;\n\t}\n\n\tvar dataObject = {\n\t\tUniversalAnalytics: {\n\t\t\tecommerce: {}\n\t\t},\t\t\t\t\t\t\t\n\t\tGoogleAnalytics4: {\n\t\t\tvalue: productDataForGoogleAnalytics4.price,\n\t\t\titems: [productDataForGoogleAnalytics4]\n\t\t}\n\t}\n\n\tdataObject.UniversalAnalytics.ecommerce[ecommerceKey] = {\n\t\tproducts: [productDataForUniversalAnalytics]\n\t}\n\n\tGoogleTagManagerClient.PushDataLayerForDataLayerType(eventName, dataObject);\n}\n\nfunction quantityChangeEvents($this, quantity, increment) {\n\tvar eventType = increment ? DataLayerConstants.EventTypes.Plus : DataLayerConstants.EventTypes.Minus;\n\tquantityDatalayerEvents($this, eventType, quantity);\n}\n\nfunction initialize(updateCart, renderCart) {\n\tisCheckout = (pageContext && pageContext.type == 'cart' || pageContext.type == 'onepcheckout' || pageContext.type == 'onepcheckout_groups') || (page.ns && page.ns == 'cart' || page.ns == 'onepcheckout' || page.ns == 'onepcheckout_groups');\n\tisEchoCart = (pageContext && 'type' in pageContext && pageContext.type == 'cart_echo') || (page.ns && page.ns == 'cart_echo');\n\tfnUpdateCart = updateCart && typeof updateCart === 'function' ? updateCart : null;\n\tfnRenderCart = renderCart && typeof renderCart === 'function' ? renderCart : null;\n\n\t// Remove Button\n\t$(document).off('click.QuantityStepper.ProductRemove').on('click.QuantityStepper.ProductRemove', '.quantity-stepper-remove .remove', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar $this = $(this);\n\t\tvar $itemRow = $this.closest('[data-uuid]');\n\t\tvar isMiniCart = $itemRow.attr('class').indexOf('mini-cart') > -1;\n\t\t$('body').loading(loadingIndicatorSettings);\n\n\t\t$.ajax({\n\t\t\ttype: 'POST',\n\t\t\turl: Urls.Cart.RemoveProduct,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\tProductLineItemUUID: $itemRow.data('uuid'),\n\t\t\t}),\n\t\t\tdataType: 'json',\n\t\t\tcomplete: function(xhr) {\n\t\t\t\t$('body').loading('destroy');\n\t\t\t\tupdateCartTotals();\n\t\t\t\tif (isMiniCart) {\n\t\t\t\t\tupdateMiniCartUI(null, $itemRow);\n\t\t\t\t}\n\t\t\t\tremoveFromCartDataLayer($this);\n\t\t\t}\n\t\t});\n\t});\n\n\t// Plus/Minus Qty Buttons\n\t$(document).off('click.QuantityStepper.QuantityChange', '.quantity-stepper button:not(\".disabled\")').on('click.QuantityStepper.QuantityChange', '.quantity-stepper button:not(\".disabled\")', function (event) {\n\t\tevent.preventDefault();\n\n\t\tvar $stepperButton = $(this);\n\t\tvar isIncrement = $stepperButton.hasClass('increase');\n\t\tvar cartQtyUrl = isIncrement ? Urls.Cart.AddProductQuantity : Urls.Cart.RemoveProductQuantity;\n\n\t\t$focusedElement = $stepperButton;\n\t\t$('body').loading(loadingIndicatorSettings);\n\t\t$.ajax({\n\t\t\ttype: 'POST',\n\t\t\turl: cartQtyUrl,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify({\n\t\t\t\tProductLineItemUUID: $(this).closest('[data-uuid]').data('uuid'),\n\t\t\t\tQuantity: 1\n\t\t\t}),\n\t\t\tdataType: 'json',\n\t\t\tcomplete: function(xhr) {\n\t\t\t\t$('body').loading('destroy');\n\t\t\t\tupdateStepperQtyUI($stepperButton, isIncrement);\n\t\t\t\tupdateMiniCartUI(isIncrement);\n\t\t\t\tupdateCartTotals();\n\t\t\t\tquantityChangeEvents($stepperButton, 1, isIncrement);\n\t\t\t}\n\t\t});\n\t});\n\n\t// On change of product qty in Cart, check the UI value of Quantity Stepper, and make qty = 1 if value isn't valid\n\t$(document).off('change.QuantityStepper.QuantityChange').on('change.QuantityStepper.QuantityChange', '.quantity-stepper input[name$=_quantity]', function () {\n\t\tif (isNaN($(this).val()) || parseInt($(this).val(), 10) === 0) {\n\t\t\t$(this).val('1');\n\t\t\t$focusedElement = $(this);\n\t\t}\n\t});\n\n\t// Keyboard events for Quantity Stepper\n\t$(document).off('keydown.QuantityStepper.QuantityChange').on('keydown.QuantityStepper.QuantityChange', '.quantity-stepper input[name$=_quantity]', function (event) {\n\t\tvar $this = $(this);\n\n\t\tif (event.which === SiteConstants.KeyCodes.Enter) {\n\t\t\tevent.preventDefault();\n\t\t\t$focusedElement = $this;\n\t\t\tif ($(event.target).val() > 0) {\n\t\t\t\tvar quantityDelta = parseInt($this.val(), 10) - parseInt($this.attr('quantity-buffer'), 10);\n\t\t\t\tupdateStepperQtyUI($this, true);\n\t\t\t\tupdateMiniCartUI(true);\n\t\t\t\tupdateCartTotals();\n\t\t\t\tquantityChangeEvents($this, Math.abs(quantityDelta), quantityDelta > 0);\n\t\t\t\t$this.attr('quantity-buffer', $this.val());\n\t\t\t}\n\t\t}\n\t});\n\n\t$(document).off('QuantityStepper.TargetFocus').on('QuantityStepper.TargetFocus', function () {\n\t\tif ($focusedElement) {\n\t\t\t$focusedElement.focus();\n\t\t}\n\t});\n}\n\nexports.init = initialize;","'use strict';\n\nvar dialog = require('./dialog'),\n    product = require('./pages/product'),\n    util = require('./util'),\n    _ = require('lodash');\n\n\nvar makeUrl = function (url, source, productListID) {\n    if (source) {\n        url = util.appendParamToURL(url, 'source', source);\n    }\n    if (productListID) {\n        url = util.appendParamToURL(url, 'productlistid', productListID);\n    }\n    return url;\n};\n\nvar removeParam = function (url) {\n    if (url.indexOf('?') !== -1) {\n        return url.substring(0, url.indexOf('?'));\n    } else {\n        return url;\n    }\n};\n\nvar quickview = {\n    init: function () {\n        if (!this.exists()) {\n            this.$container = $('<div/>').attr('id', 'QuickViewDialog').appendTo(document.body);\n        }\n        this.productLinks = $('#search-result-items .thumb-link').map(function (index, thumbLink) {\n            return $(thumbLink).attr('href');\n        });\n    },\n\n    setup: function (qvUrl) {\n\n        product.initializeEvents();\n\n     },\n\n    /**\n     * @param {Number} step - How many products away from current product to navigate to. Negative number means navigate backward\n     */\n    navigateQuickview: function (step) {\n        // default step to 0\n        this.productLinkIndex += (step ? step : 0);\n        var url = makeUrl(this.productLinks[this.productLinkIndex], 'quickview');\n        dialog.replace({\n            url: url,\n            callback: this.setup.bind(this, url)\n        });\n    },\n\n    /**\n     * @description show quick view dialog\n     * @param {Object} options\n     * @param {String} options.url - url of the product details\n     * @param {String} options.source - source of the dialog to be appended to URL\n     * @param {String} options.productlistid - to be appended to URL\n     * @param {Function} options.callback - callback once the dialog is opened\n     */\n    show: function (options) {\n        var url;\n        if (!this.exists()) {\n            this.init();\n        }\n        url = makeUrl(options.url, options.source, options.productlistid);\n\n        dialog.open({\n            target: this.$container,\n            url: url,\n            options: {\n                width: 1068,\n                title: Resources.QUICK_VIEW_POPUP,\n                open: function () {\n                    this.setup(url);\n                    if (typeof options.callback === 'function') { options.callback(); }\n                }.bind(this)\n            }\n        });\n    },\n    exists: function () {\n        return this.$container && (this.$container.length > 0);\n    }\n};\n\nmodule.exports = quickview;\n","'use strict';\n\n/**\n * copied from https://github.com/darkskyapp/string-hash\n */\nfunction hashFn(str) {\n    var hash = 5381,\n        i = str.length;\n\n    while (i) {\n        hash = (hash * 33) ^ str.charCodeAt(--i);\n    }\n    /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed\n    * integers. Since we want the results to be always positive, convert the\n    * signed int to an unsigned by doing an unsigned bitshift. */\n    return hash >>> 0;\n}\n\n/**\n * Create rating based on hash ranging from 2-5\n * @param pid\n */\nfunction getRating(pid) {\n    return hashFn(pid.toString()) % 30 / 10 + 2;\n}\n\nmodule.exports = {\n    init: function () {\n        $('.variant-info .product-review').each(function (index, review) {\n            var pid = $(review).data('pid');\n            if (!pid) {\n                return;\n            }\n            // rating range from 2 - 5\n            var rating = getRating(pid);\n            var baseRating = Math.floor(rating);\n            var starsCount = 0;\n            for (var i = 0; i < baseRating; i++) {\n                $('.rating', review).append('<i class=\"fa fa-star\"></i>');\n                starsCount++;\n            }\n            // give half star for anything in between\n            if (rating > baseRating) {\n                $('.rating', review).append('<i class=\"fa fa-star-half-o\"></i>');\n                starsCount++;\n            }\n            if (starsCount < 5) {\n                for (var j = 0; j < 5 - starsCount; j++) {\n                    $('.rating', review).append('<i class=\"fa fa-star-o\"></i>');\n                }\n            }\n        });\n    }\n};\n","'use strict';\n\n/* -------------------------\n * REGISTER\n * -------------------------\n */\n\nvar alert = require('./alert');\nvar dialog = require('./dialog');\nvar loadingIndicator = require('./components/LoadingIndicator');\nvar wishlist = require('./wishlist');\n\nvar RequestHelper = require('./helpers/RequestHelper');\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar options = {};\nvar loadingIndicatorSettings = {\n    IsLabelShown: false,\n    CssClass: 'fullscreen',\n    BackgroundColor: 'transparent'\n};\n\nfunction errorHandling(data, dialogTitle, dialogHtml) {\n    if (data && typeof data === 'object' && 'message' in data) {\n        console.log(data.message);\n    }\n    dialog.open({\n        html: dialogHtml,\n        options: {\n            title: dialogTitle,\n            draggable: false,\n            open: function(event, ui) {                                    \n                $('body').addClass('dialog-open');\n            },\n            close: function(event, ui) {\n                $('body').removeClass('dialog-open');\n            }\n        }\n    });\n}\n\nfunction validateRegistrationForm($form) {\t\n    var rewardsFormFields = {\n        email: $form.find('#dwfrm_rewardsregistration_rewardscustomer_email'),\n        firstName: $form.find('#dwfrm_rewardsregistration_rewardscustomer_firstname'),\n        lastName: $form.find('#dwfrm_rewardsregistration_rewardscustomer_lastname'),\n        phone: $form.find('#dwfrm_rewardsregistration_rewardscustomer_phone'),\n        zip: $form.find('#dwfrm_rewardsregistration_rewardscustomeraddress_zipcode').length > 0 ? $form.find('#dwfrm_rewardsregistration_rewardscustomeraddress_zipcode') : $form.find('#dwfrm_rewardsregistration_rewardscustomer_zipcode')\n    }\n\tif ($form.find('input[name*=\"dwfrm_rewardsregistration_rewardscustomer_password\"]').length > 0) {\n\t\trewardsFormFields.password = $form.find('input[name*=\"dwfrm_rewardsregistration_rewardscustomer_password\"]');\n\t}\n    var registrationFormFields = {\n        email: $form.find('#dwfrm_profile_customer_email'),\n        confirmEmail: $form.find('#dwfrm_profile_customer_emailconfirm'),\n        firstName: $form.find('#dwfrm_profile_customer_firstname'),\n        lastName: $form.find('#dwfrm_profile_customer_lastname')\n    }\n\tif ($form.find('input[name*=\"dwfrm_profile_login_password_\"]').length > 0) {\n\t\tregistrationFormFields.password = $form.find('input[name*=\"dwfrm_profile_login_password_\"]');\n\t}\n\tif ($form.find('input[name*=\"dwfrm_profile_login_passwordconfirm\"]').length > 0) {\n\t\tregistrationFormFields.confirmPassword = $form.find('input[name*=\"dwfrm_profile_login_passwordconfirm\"]');\n\t}\n    var checkFormFields = $form.attr('id') == 'dwfrm_rewardsregistration' ? rewardsFormFields : registrationFormFields;\n\tvar formValidation = new Array();\n    var regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/g;\n\tvar regexPhone = /^\\+?\\(?([0-9][0-8][0-9])\\)?[\\-\\. ]?([2-9][0-9]{2})[\\-\\. ]?([0-9]{4})(\\s*x[0-9]+)?$/g;\n    var regexZip = /^(\\d{5})(-\\d{4})?$/g;\n    var regexPassword = /^(?=.*?[A-z])(?=.*?[0-9])(?=.*?[#?!\\=\\/\\,\\.\\~\\`\\(\\)\\{\\}\\[\\]\\\\@_$%^&*-]).{8,20}$/g;\n\n    for (var fieldName in checkFormFields) {\n        var fieldValue = checkFormFields[fieldName].length ? checkFormFields[fieldName].val().trim() : null;\n\n        if (fieldValue != null && fieldValue.length > 0) {\n            if (fieldName == 'email' || fieldName == 'confirmEmail') {\n                if (String(fieldValue).match(regexEmail) == null) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\tvar emailFormatErrorClass = fieldName == 'email' ? 'span.invalid-email-format' : 'span.invalid-email-confirm-format';\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find(emailFormatErrorClass).removeClass('d-none');\n                }\n\t\t\t\tif (fieldName == 'confirmEmail' && (fieldValue != checkFormFields['email'].val().trim())) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find('span.invalid-email-confirm-mismatch').removeClass('d-none');\n                }\n            }\n            if (fieldName == 'phone') {\n                if (String(fieldValue).match(regexPhone) == null) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find('span.invalid-phone-format').removeClass('d-none');\n                }\n            }\n            if (fieldName == 'zip') {\n                if (String(fieldValue).match(regexZip) == null) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find('span.invalid-zip-format').removeClass('d-none');\n                }\n            }\n            if (fieldName == 'password' || fieldName == 'confirmPassword') {\n                if (String(fieldValue).match(regexPassword) == null) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\tvar passwordFormatErrorClass = fieldName == 'password' ? 'span.invalid-password-format' : 'span.invalid-password-confirm-format';\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find(passwordFormatErrorClass).removeClass('d-none');\n                }\n                if (fieldName == 'confirmPassword' && (fieldValue != checkFormFields['password'].val().trim())) {\n                    formValidation.push(false);\n                    checkFormFields[fieldName].addClass('error');\n\t\t\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find('span.invalid-password-confirm-mismatch').removeClass('d-none');\n                }\n            }\n        } else {\n            formValidation.push(false);\n            checkFormFields[fieldName].addClass('error');\n\t\t\t$('.registration-dialog-error[data-relation=\"'+fieldName+'\"]').find('span.invalid-missing-fields').removeClass('d-none');\n        }\n    }\n\t\t\t\n\tif (formValidation.length > 0) {\n        return false;\n    } else {\n        $form.find('.registration-dialog-error span').addClass('d-none');\n        return true;\n    }\n}\n\n// Cordial rewards registration tracking (BB)\nfunction rewardsRegisterCordialEvent($form, isRegisterDialog, callback) {\n    var rewardsFormFields = {\n        email: $form.find('#dwfrm_rewardsregistration_rewardscustomer_email').val().trim(),\n        firstName: $form.find('#dwfrm_rewardsregistration_rewardscustomer_firstname').val().trim(),\n        lastName: $form.find('#dwfrm_rewardsregistration_rewardscustomer_lastname').val().trim(),\n        phone: $form.find('#dwfrm_rewardsregistration_rewardscustomer_phone').val().trim(),\n        zip: $form.find('#dwfrm_rewardsregistration_rewardscustomeraddress_zipcode').length > 0 ? $form.find('#dwfrm_rewardsregistration_rewardscustomeraddress_zipcode').val().trim() : $form.find('#dwfrm_rewardsregistration_rewardscustomer_zipcode').val().trim()\n    }\n    var signupEvent = \"\";\n\n\tvar auth_data = {\n\t\temail: rewardsFormFields['email']\n\t}\t\t\n\tvar contact_data = {\n\t\t'channels': {\n\t\t\t'email': {\n\t\t\t\t'address': rewardsFormFields['email']      \n\t\t\t}\n\t\t},\t\t    \n\t\t'first_name': rewardsFormFields['firstName'],\n\t\t'last_name': rewardsFormFields['lastName'],\n\t\t'phone': rewardsFormFields['phone'],\n\t\t'postal_code': rewardsFormFields['zip'],\n\t\t'source_create': 'myaccount',\n\t\t'geo_location': {\n\t\t\t'postal_code': rewardsFormFields['zip']\n\t\t}\n\t};\t\t\t\n\tvar loginProperties = {\n\t\t\"email\": rewardsFormFields['email'],\n\t\t\"loginType\": isRegisterDialog ? \"registration-dialog\" : \"regular-registration\"\n\t};\t\n\tvar registerProperties = {\n\t\t\"email\": rewardsFormFields['email'],\n\t\t\"registerType\": isRegisterDialog ? \"registration-dialog\" : \"regular-registration\"\n\t};\t\t\t\n\tif ($('input#dwfrm_rewardsregistration_receiveRewardsEmail').is(':checked')) {\n\t\tvar contact_data = {\n\t\t\t'channels': {\n\t\t\t\t'email': {\n\t\t\t\t\t'address': rewardsFormFields['email'],\n\t\t\t\t\t'subscribeStatus': 'subscribed'\t\t\t\t            \n\t\t\t\t}\n\t\t\t},\t\t    \n\t\t\t'first_name': rewardsFormFields['firstName'],\n\t\t\t'last_name': rewardsFormFields['lastName'],\n\t\t\t'phone': rewardsFormFields['phone'],\n\t\t\t'postal_code': rewardsFormFields['zip'],\n\t\t\t'signup_source': 'rewards',\n\t\t\t'source_create': 'myaccount',\n\t\t\t'welcome_signup_rewards_online': true,\n\t\t\t'geo_location': {\n\t\t\t\t'postal_code': rewardsFormFields['zip']\n\t\t\t}\n\t\t};\t\t\n\t\tvar properties = {\n\t\t\t\"signup_source\": 'rewards',\n\t\t\t\"welcome_signup_rewards_online\": true\n\t\t};\t\t\n\t\tsignupEvent = ['event', 'email_signup', properties];\n\t}\t\n\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\tcrdl([\t\t\t\t\n\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t['event', 'account_create', registerProperties],\n\t\t\t\t['event', 'login', loginProperties],\n\t\t\t\tsignupEvent\n\t\t\t]);\n\t\t}\n\t\tif (callback) callback();\n\t}).catch();\t\n}\n\n// Cordial registration tracking (SHP and CO)\nfunction registerCordialEvent($form, isRegisterDialog, callback) {\n    var registrationFormFields = {\n        email: $form.find('#dwfrm_profile_customer_email').val().trim(),\n        firstName: $form.find('#dwfrm_profile_customer_firstname').val().trim(),\n        lastName: $form.find('#dwfrm_profile_customer_lastname').val().trim()\n    }\n\tvar signupEvent = \"\";\t\n\n\tvar auth_data = {\n\t\temail: registrationFormFields['email']\n\t}\t\t\t\n\tvar contact_data = {\n\t\t'channels': {\n\t\t\t'email': {\n\t\t\t\t'address': registrationFormFields['email']\t\t\t            \n\t\t\t}\n\t\t},\t\t    \n\t\t'first_name': registrationFormFields['firstName'],\n\t\t'last_name': registrationFormFields['lastName'],\n\t\t'source_create': 'myaccount'\n\t};\n\tvar loginProperties = {\n\t\t\"email\": registrationFormFields['email'],\n\t\t\"loginType\": isRegisterDialog ? \"registration-dialog\" : \"registration\"\n\t};\t\t\n\tvar registerProperties = {\n\t\t\"email\": registrationFormFields['email'],\n\t\t\"registerType\": isRegisterDialog ? \"registration-dialog\" : \"registration\"\n\t};\t\t\t\t\t\t\n\tif ($('input#dwfrm_profile_customer_addtoemaillist').is(':checked')) {\n\t\tvar contact_data = {\n\t\t\t'channels': {\n\t\t\t\t'email': {\n\t\t\t\t\t'address': registrationFormFields['email'],\n\t\t\t\t\t'subscribeStatus': 'subscribed'\n\t\t\t\t}\n\t\t\t},\t\t    \n\t\t\t'first_name': registrationFormFields['firstName'],\n\t\t\t'last_name': registrationFormFields['lastName'],\n\t\t\t'signup_source': 'myaccount',\n\t\t\t'source_create': 'myaccount',\n\t\t\t'welcome_signup': true\n\t\t};\t\t\n\t\tvar properties = {\n\t\t\t\"signup_source\": \"myaccount\",\n\t\t\t\"page\": \"myaccount\",\n\t\t\t\"welcome_signup\": true\n\t\t};\n\t\tsignupEvent = ['event', 'email_signup', properties];\n\t}\n\tRequestHelper.Validate('Cordial-EmailSignup').then(function() {\n\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\tcrdl([\t\t\t\t\n\t\t\t\t['contact', auth_data, contact_data],\n\t\t\t\t['event', 'account_create', registerProperties],\n\t\t\t\t['event', 'login', loginProperties],\n\t\t\t\tsignupEvent\n\t\t\t]);\n\t\t}\n\t\tif (callback) callback();\n\t}).catch();\t\n}\n\n/**\n * @private\n * @function\n * @description add rules to code input field\n */\nfunction initAddRulesForCodeInput() {\n    $('form#verify-code').validate();\n    $('#verify-code #enter-code').rules('add', {\n        required: true,\n        digits: true,\n        minlength: 6,\n        messages: {\n            required: Resources.VALIDATE_CODE,\n            minlength: Resources.VALIDATE_CODE\n        },\n        normalizer: function(value) {\n            return $.trim(value);\n        }\n    });\n}\n\n/**\n * @private\n * @function\n * @description init registration button event for registration page and dialog\n */\nfunction initRegistrationButton() {\n    $(document).off('click.Registration').on('click.Registration', '.accountRegisterButton, .saveRewardsRegistration.btn, .confirmationRegisterButton', function(event) {\n\t\tevent.preventDefault();\n\t\tevent.stopImmediatePropagation();\n\t\tvar dialogHtml = '<p style=\"padding: 10px;\">Oops, something went wrong with registration. Please try again later.</p>';\n        var $registrationButton = $(this);\n\t\tvar $registrationForm = $registrationButton.closest('form[data-form-type=\"register\"]');\n        var formUrl = $registrationForm.attr('action');\n\t\tvar isConfirmationPage = $registrationButton.hasClass('confirmationRegisterButton');\n\n\t\t// Clear previous form errors\n\t\t$registrationForm.find('input').removeClass('error');\n\t\t$registrationForm.find('.registration-dialog-error span').addClass('d-none');\n\n\t\tvar isValidForm = validateRegistrationForm($registrationForm);\n\t\tvar isRegisterDialog = formUrl.indexOf('loginDialog') >= 0;\n\t\tvar formData = $registrationForm.serialize(); \n\t\tformData += '&' + $registrationButton.attr('name') + '=' + $registrationButton.attr('value');\n\t\tif (pageContext.options.Token) {\n\t\t\tformData += '&csrf_token=' + pageContext.options.Token;\n\t\t}\n\t\t\n        // Using AJAX instead of default HTML button submit for registration dialog and \"Create an Account\" page\n        if (isValidForm) {\n            $('body').loading(loadingIndicatorSettings);\n            if (SitePreferences.RETENTION_COM_ENABLED) {\n            \tgeq.suppress();\n            }           \n            $.ajax({\n                type: 'POST',\n                url: formUrl,\n                data: formData,\n                success: function(data, textStatus, jqXHR) {\n                    if (typeof data === 'object' && 'result' in data) {\n                        if (data.result == 'error') {\n\t\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\t\tif (isRegisterDialog || isConfirmationPage) {\n\t\t\t\t\t\t\t\tvar errorsFound;\n\t\t\t\t\t\t\t\tif (data.validationErrors) {\n\t\t\t\t\t\t\t\t\terrorsFound = JSON.parse(data.validationErrors);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (errorsFound && Object.keys(errorsFound).length > 0) {\n\t\t\t\t\t\t\t\t\tfor (var fieldName in errorsFound) {\n\t\t\t\t\t\t\t\t\t\t$('[name*=\"' +fieldName+ '\"]').addClass('error');\n\t\t\t\t\t\t\t\t\t\t$(errorsFound[fieldName]).removeClass('d-none');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\terrorHandling(data, 'Register - Error', dialogHtml);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twindow.location.href = data.registerDialogContinueUrl;\n\t\t\t\t\t\t\t}\n                        } else if (data.result == 'success') {\n\t\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\t\t// If a rewards account was found in rewards DB, then verify customer and tie newly registered email address to exisitng rewards account\n                            if ('validateCustomer' in data && data.validateCustomer) {\n                                if (SitePreferences.CORDIAL_ENABLED) {\n                                    if ($registrationForm.attr('id') == 'dwfrm_rewardsregistration') {\n\t\t\t\t\t\t\t\t\t\trewardsRegisterCordialEvent($registrationForm, isRegisterDialog);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tregisterCordialEvent($registrationForm, isRegisterDialog);\n\t\t\t\t\t\t\t\t\t}\n                                }\n\t\t\t\t\t\t\t\tvar newAttributes = {\n\t\t\t\t\t\t\t\t\t\"data-modal-type\": \"register\",\n                                    \"data-continue-url\": 'registerDialogContinueUrl' in data ? data.registerDialogContinueUrl : '',\n                                    \"data-first-name\": 'customerFirstName' in data ? data.customerFirstName : '',\n                                    \"data-store-number\": 'storeFromProfile' in data ? data.storeFromProfile : '',\n                                    \"data-cart-quantity\": 'cartQuantity' in data ? data.cartQuantity : ''\n                                }\n                                $('.login-dialog-validate-customer').html(data.validateCustomer);\n                                $('.login-dialog-validate-customer').addClass('validate-customer-show follow-account-dialog-path').attr(newAttributes);\n                                // For register-dialog because the validation form is only loaded into page via AJAX, so rules can't be added until form is loaded\n                                initAddRulesForCodeInput();\n                            } else {\n\t\t\t\t\t\t\t\tif (isConfirmationPage) {\n\t\t\t\t\t\t\t\t\t// Redirect to My Account if this is a registration from order confirmation page\n\t\t\t\t\t\t\t\t\tdata.registerDialogContinueUrl = Urls.account;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (SitePreferences.CORDIAL_ENABLED) {\n\t\t\t\t\t\t\t\t\tif ($registrationForm.attr('id') == 'dwfrm_rewardsregistration') {\n\t\t\t\t\t\t\t\t\t\trewardsRegisterCordialEvent($registrationForm, isRegisterDialog, function() {\n\t\t\t\t\t\t\t\t\t\t\t$(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: data, isAccountDialog: isRegisterDialog, displayMessage: 'register' });\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tregisterCordialEvent($registrationForm, isRegisterDialog, function() {\n\t\t\t\t\t\t\t\t\t\t\t$(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: data, isAccountDialog: isRegisterDialog, displayMessage: 'register' });\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$(document).trigger('PostAjaxAuthenticationActions.Initialize', { results: data, isAccountDialog: isRegisterDialog, displayMessage: 'register' });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n                        } else {\n\t\t\t\t\t\t\t$('body').loading('destroy');\n                        \terrorHandling(data, 'Register - Error', dialogHtml);\n\t\t\t\t\t\t}\n                    } else {\n\t\t\t\t\t\t$('body').loading('destroy');\n\t\t\t\t\t\tif (isRegisterDialog) {\n\t\t\t\t\t\t\terrorHandling(data, 'Register - Error', dialogHtml);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twindow.location.href = location.href;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    $('body').loading('destroy');\n\t\t\t\t\tif (!isRegisterDialog) {\n\t\t\t\t\t\twindow.location.href = location.href;\n\t\t\t\t\t}\n                }\n            });\n        }  \n\t});\n}\n\n/**\n * @private\n * @function\n * @description displays the registration form in the dialog on button click\n */\nfunction initRegistrationForm() {\n\t$('body').on('click', '#toggle-registration', function(e) {\n\t\te.preventDefault();\n\t\tvar $dialog = $(this).parents('.login-dialog');\n\t\tvar $dialogTitlebar = $dialog.find('.ui-dialog-titlebar');\n\t\tvar $dialogContent = $dialog.find('.ui-dialog-content');\n\t\tvar $dialogFormsContainer = $dialog.find('.login-dialog-forms-container');\n\t\tvar calculatedSpacing = $(window).height() * 0.21;\n\t\tvar newDialogHeight = $(window).height() - calculatedSpacing;\n\t\tvar newTopValue = $(window).scrollTop() + (calculatedSpacing * 0.233);\n\n\t\tif ($dialogTitlebar && $dialogTitlebar.is(\":visible\")) {\n\t\t\tnewDialogHeight = newDialogHeight + $dialogTitlebar.outerHeight();\n\t\t}\n\n\t\tvar paddingTop = '32px';\n\t\tvar currentSite = pageContext && pageContext.site ? pageContext.site : null;\n\t\tif ((currentSite && currentSite == SiteConstants.SiteIds.BootBarnUS) || (pageContext && pageContext.isstoresite)) {\n\t\t\tpaddingTop = '28px';\n\t\t}\n\n\t\t$('.login-dialog-signin-container, #toggle-registration').hide();\n\t\t$('.login-dialog-register-form').addClass('register-form-show');\n\t\t$dialog.css({\n\t\t\t'height': newDialogHeight+'px',\n\t\t\t'top': newTopValue+'px',\n\t\t\t'overflow': 'visible'\n\t\t  });\n\t\t$dialogContent.css({\n\t\t\t'height': '100%',\n\t\t\t'padding': '0 11px 20px',\n\t\t\t'padding-top': paddingTop\n\t\t});\n\t\t$dialogFormsContainer.css('height','100%');\n\t});\n}\n\nmodule.exports = {\n    init: function (optionsParameter) {\n        options = optionsParameter;\n\n\t\tinitRegistrationForm();\n        initRegistrationButton();\n    }\n};","'use strict';\n\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nvar siteName;\nvar $win = $(window);\n\n\n/**\n     * @function\n     * @description Configures parameters and required object instances\n     */\nfunction init () {\n    siteName = window.pageContext.site || '';\n\n    $('.top-banner .header-search button').on('click', function(event) {\n        event.preventDefault();\n\n        var $this = $(this);\n        var $searchForm = $this.closest('form');\n        var $searchInput = $searchForm.find('[name=\"q\"]');\n        var action = $searchForm.attr('action');\n        var keyword = $searchInput.val();\n        var url = action + \"?q=\" + keyword;\n\n        if (keyword && keyword != $searchInput.attr('placeholder')) {\n            $searchForm.attr('action', url);\n            $searchForm.submit();\n        }\n    });\n\n    if (siteName == SiteConstants.SiteIds.BootBarnUS) {\n        $('.header-search').on('click',function() {\n            $('.header-search').addClass('active');\n        });\n\n        $('.header-search input#q').focusout(function() {\n            $('.header-search').removeClass('active');\n        });\n    }\n    if (SitePreferences.PROMOTED_SEARCHES) {\n        $(document).on('focus click keydown', '.header-search input#q, .header-search input#mobile-q', function() {\n            promotedSuggestions();\n            // TO-DO: When ticket pops up for suggested searches, create another preference and add the IF statement here\n        });\n\n        $(document).on('mouseleave', '.search-suggestions-container, .header-search [name=\"q\"]', function(e) {\n            var searchHeader = document.querySelector('.header-search');\n            if (!searchHeader.contains(e.relatedTarget) && $('.search-suggestions-container').find(e.relatedTarget).length < 1) {\n                $('.search-suggestions-container').hide();\n            }\n        });\n\n        $(document).on('click', '.close-search-suggestions', function() {\n            $('.search-suggestions-container').hide();\n        });  \n        \n        $(document).off('SearchBar.Expand').on('SearchBar.Expand', function() {\n            expand();\n        });\n\n        $(document).off('SearchBar.ScrollTop').on('SearchBar.ScrollTop', function() {\n            scrollTop();\n        });\n\n        $(document).off('SearchBar.Hide').on('SearchBar.Hide', function() {\n            hide();\n        });\n    }\n}\n\n/**\n * @function\n * @description\n */\nfunction expand () {\n    $('.top-banner').toggleClass('search-enabled');\n    var $target = $('.header-search');\n    if (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n        $target = $('.search-holder');\n    }\n            \n    if ((siteName == SiteConstants.SiteIds.SheplersUS || siteName == SiteConstants.SiteIds.CountryOutfittersUS) && $('html').hasClass('size-mobile')) {\n        $target.css('top', $('.top-banner-bar').outerHeight() + $('.top-banner-inner').outerHeight() - $win.scrollTop());\n    } else {\n        $target.css('top', '');\n    }\n            \n    if (siteName == SiteConstants.SiteIds.SheplersUS) {\n        $target.find('input[type=\"text\"]').focus();\n    }\n            \n    if ($('.top-banner').hasClass('search-enabled') && $('html').hasClass('size-mobile') && $('.top-banner-bar').attr('data-header-for') == 'bootbarn_us') {\n        $('#search #q').focus();\n    }\n}\n\n/**\n * @function\n * @description\n */\nfunction scrollTop () {\n    if (siteName == SiteConstants.SiteIds.SheplersUS || siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n        var $target = $('.header-search');\n        if (siteName == SiteConstants.SiteIds.CountryOutfittersUS) {\n            $target = $('.search-holder');\n        }\n        \n        if ($('html').hasClass('size-mobile')) {\n            $target.css('top', $('.top-banner-bar').outerHeight() + $('.top-banner-inner').outerHeight() - $win.scrollTop());\n        } else {\n            $target.css('top', '');\n        }\n    }\n}\n\n/**\n * @function\n * @description\n */\nfunction hide () {\n    if($('.header-search').hasClass('show')) {\n        $('.header-search').removeClass('show');\n        if (siteName != SiteConstants.SiteIds.BootBarnRspUS) {\n            $('.top-banner').removeClass('search-enabled');\n        }\n    }\n}\n\n/**\n * @function\n * @description trigger promoted suggestions for site search\n */\nfunction promotedSuggestions () {\n    var isContentPopulated = $('.search-suggestions-container > div').length > 0;\n    if ($('.search-suggestions-container').is(':hidden') && isContentPopulated) {\n        $('.search-suggestions-container').show();\n    }\n}\n\nexports.init = init;\n","'use strict';\n\n/**\n * @private\n * @function\n * @description Binds event to the place holder (.blur)\n */\nfunction initializeEvents() {\n    $('#q').focus(function () {\n        var input = $(this);\n        if (input.val() === input.attr('placeholder')) {\n            input.val('');\n        }\n    })\n    .blur(function () {\n        var input = $(this);\n        if (input.val() === '' || input.val() === input.attr('placeholder')) {\n            input.val(input.attr('placeholder'));\n        }\n    })\n    .blur();\n}\n\nexports.init = initializeEvents;\n","'use strict';\n\nvar page = require('./page');\n\nvar isTouchMoved = false;\nvar isCurrentTargetSwatch = false;\n\nfunction initializeEvents() {\n\t$(document).off('click.Swatch.Menu.Close').on('click.Swatch.Menu.Close', function (event) {\n\t\tvar $currentTarget = $(event.currentTarget);\n\t\t\n\t\tif ($currentTarget.closest('.slide-down-swatch').length == 0) {\n\t\t\t$('.slide-down-swatch ul').slideUp();\n\t\t}\n\t});\n\t\n\t$(document).off('touchstart.Swatch.Menu.Close').on('touchstart.Swatch.Menu.Close', function (event) {\n\t\tvar $currentTarget = $(event.currentTarget);\n\t\t\n\t\tisTouchMoved = false;\n\t\tisCurrentTargetSwatch = $currentTarget.closest('.slide-down-swatch').length > 0;\n\t});\n\t\n\t$(document).off('touchmove.Swatch.Menu.Close').on('touchmove.Swatch.Menu.Close', function (event) {\n\t\tisTouchMoved = true;\n\t});\n\t\n\t$(document).off('touchend.Swatch.Menu.Close').on('touchend.Swatch.Menu.Close', function (event) {\n\t\tif (!isCurrentTargetSwatch && !isTouchMoved) {\n\t\t\t$('.slide-down-swatch ul').slideUp();\n\t\t}\n\t});\n\t\n\t$('.swatches.size > li > a.slide-down').on('click', function(event) {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\t\t\t\n\t\t$(this)\n\t\t.next('ul')\n\t\t.stop()\n\t\t.slideToggle()\n\t\t.parent()\n\t\t.siblings()\n\t\t.children('ul')\n\t\t.slideUp()\n\t\t.prev('.slide-down');\n\t});\n\n\t// Default selected value as slide down\n\t$('.swatches.size > li > a.slide-down')\n\t.next('ul')\n\t.find('.current')\n\t.closest('ul')\n\t.prev('.slide-down')\n\t.addClass('current')\n\t.closest('li').addClass('active');\n\n\t$('.refinements .swatches.size > li.active > ul').slideDown();\n\n\t$('.swatches > li.slide-down-swatch > ul').off('click');\n\n\t// Remove empty tiles \n\t$('.swatches.size > li > a.slide-down').next('ul').each(function() {\n\t\tif ($(this).find('li').length === 0) {\n\t\t\t$(this).closest('li').remove();\n\t\t}\n\t});\n}\n\nvar sizeRefinements = {\n\tinit: function() {\n\t\tinitializeEvents();\n\t}\n};\n\nmodule.exports = sizeRefinements;","'use strict';\n\n/* -------------------------\n * ADA Slick Mods\n * -------------------------\n */\n\nexports.init = function init () {\n    $(document).off('SlickSliderAccessibilityMods').on('SlickSliderAccessibilityMods', function(event) {\n        $('.slick-slider .slick-slide, .slick-slider .slick-active').removeAttr('aria-describedby role tabindex');\t\t\t\n        $('.slick-slider .slick-dots button').each(function() {\n            var buttonVal = $(this).html();\n            var addSpan = '<span class=\"visually-hidden\">' + buttonVal + '</span>';\n            $(this).html(addSpan);\n        });\n    });\n};","'use strict';\n\n/* ----------------------------------------\n * -- Sliders --\n * \n * Configuration Options:\n *                loop:  BOOLEAN  Both; If no option given, programmatically set to true.\n *                dots:  BOOLEAN  Both; If no option given, programmatically set to true.\n *          pagination:  OBJECT   Swiper only; If no option given, pagination is omitted from slider settings.\n *              arrows:  BOOLEAN  Both; If no option given, automatically set to true in widget background.\n *      arrowsPosition:  STRING   ['inside' or 'outside'] Swiper only; If no option given, automatically set to the outside.\n *          navigation:  OBJECT   Swiper only; If no option given, navigation is omitted from slider settings.\n *        slidesToShow:  NUMBER   Both; If no option given, programmatically set to 1.\n *      slidesToScroll:  NUMBER   Both; If no option given, programmatically set to 1.\n *            autoplay:  NUMBER   Both; When given, number is programmatically set to Autoplay Speed and Autoplay is set to true. If no option given, autoplay is set to false.\n *         breakpoints:  OBJECT   Both; Properties are looped over to apply various breakpoint settings. If no option given, breakpoints is omitted from slider settings.\n *     \n * Example Code:\n *        sliders.init('.some-class-name', \n *        {\n *             loop: true, \n *             dots: true, \n *             pagination: {el: '.swiper-pagination', clickable: true}, \n *             arrows: true,\n *             arrowsPosition: 'inside',\n *             navigation: {nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev'},\n *             slidesToShow: 6,\n *             slidesToScroll: 1,\n *             autoplay: 3000,\n *             breakpoints: {0: {slidesToShow: 1}, 768: {slidesToShow: 3}}\n *        });\n * \n * \n * Additional configuration options exist for both sliders, but additional code changes would be needed to include them. \n * \n * Reference slider documentation:\n * \n * Swiper documentation - https://swiperjs.com/swiper-api\n * Slick documentation - https://kenwheeler.github.io/slick/\n *  \n * ----------------------------------------\n */\n\nvar SiteConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/SiteConstants');\n\nexports.init = init;\nexports.initializeCategorySliders = initializeCategorySliders;\nexports.initializeRecommendationSlider = initializeRecommendationSlider;\n\nfunction getUniqueNumber() {\n\tvar dateObject = new Date();\n\tvar uniqueNumber = dateObject.valueOf();\n    var suffixNumber = 1 + Math.floor(Math.random() * 100);\n    uniqueNumber = uniqueNumber + suffixNumber;\n\treturn uniqueNumber;\n}\n\nfunction convertedSlickBreakpointSize(breakpointSize, breakpointSizeArray) {\n    var sortedBreakpointSizes = breakpointSizeArray.sort(function (a, b) { return a - b; });\n    var convertedBreakpointSize;\n    \n    if (breakpointSize == 0) {\n        var mobileMaxSize = sortedBreakpointSizes[sortedBreakpointSizes.indexOf(0) + 1];\n        if (mobileMaxSize) {\n            convertedBreakpointSize = mobileMaxSize - 1;\n        } else {\n            convertedBreakpointSize = 767;\n        }\n    } else if (breakpointSize == 768) {\n        var desktopMaxSize = sortedBreakpointSizes[sortedBreakpointSizes.indexOf(768) + 1];\n        if (desktopMaxSize) {\n            convertedBreakpointSize = desktopMaxSize - 1;\n        } else {\n            convertedBreakpointSize = 9999;\n        }\n    } else {\n        var breakpointMaxSize = sortedBreakpointSizes[sortedBreakpointSizes.indexOf(breakpointSize) + 1];\n        if (breakpointMaxSize) {\n            convertedBreakpointSize = breakpointMaxSize - 1;\n        } else {\n            convertedBreakpointSize = 9999;\n        }\n    }\n\n    return convertedBreakpointSize;\n}\n\nfunction initSlick(elementSelector, settings) {\n    if (!elementSelector) {\n        return;\n    }\n\n    var sliderSettings = {\n        infinite: true,\n        slidesToShow: 1,\n        slidesToScroll: 1\n    };\n    if (settings) {\n        if ('loop' in settings) {\n            sliderSettings.infinite = settings.loop;\n        }\n        if ('dots' in settings) {\n            sliderSettings.dots = settings.dots;\n        }\n        if ('arrows' in settings) {\n            sliderSettings.arrows = settings.arrows;\n        }\n        if ('slidesToShow' in settings) {\n            sliderSettings.slidesToShow = settings.slidesToShow;\n        }\n        if ('slidesToScroll' in settings) {\n            sliderSettings.slidesToScroll = settings.slidesToScroll;\n        }\n        if ('autoplay' in settings) {\n            sliderSettings.autoplay = true;\n            sliderSettings.autoplaySpeed = settings.autoplay;\n        }\n        if ('breakpoints' in settings) {\n            sliderSettings.responsive = [];\n            var breakpointSizeArray = Object.keys(settings.breakpoints).map(function (x) { \n                return parseInt(x); // Extra precaution of sanitizing data for use in mathematical equations\n            });\n            for (var breakpointSize in settings.breakpoints) {\n                breakpointSize = parseInt(breakpointSize);\n                var convertedBreakpointSize = convertedSlickBreakpointSize(breakpointSize, breakpointSizeArray);\n                var breakpointSettingsObject = {\n                    breakpoint: convertedBreakpointSize,\n                    settings: {}\n                };\n                var breakpointSizeSettings = settings.breakpoints[breakpointSize];\n                for (var sizeSetting in breakpointSizeSettings) {\n                    if ('loop' == sizeSetting) {\n                        breakpointSettingsObject.settings.infinite = breakpointSizeSettings[sizeSetting];\n                    }\n                    if ('dots' == sizeSetting) {\n                        breakpointSettingsObject.settings.dots = breakpointSizeSettings[sizeSetting];\n                    }\n                    if ('arrows' == sizeSetting) {\n                        breakpointSettingsObject.settings.arrows = breakpointSizeSettings[sizeSetting];\n                    }\n                    if ('slidesToShow' == sizeSetting) {\n                        if (convertedBreakpointSize == 9999) {\n                            sliderSettings.slidesToShow = breakpointSizeSettings[sizeSetting];\n                        } else {\n                            breakpointSettingsObject.settings.slidesToShow = breakpointSizeSettings[sizeSetting];\n                        }\n                    }\n                    if ('slidesToScroll' == sizeSetting) {\n                        if (convertedBreakpointSize == 9999) {\n                            sliderSettings.slidesToScroll = breakpointSizeSettings[sizeSetting];\n                        } else {\n                            breakpointSettingsObject.settings.slidesToScroll = breakpointSizeSettings[sizeSetting];\n                        }\n                    }\n                    if ('autoplay' == sizeSetting) {\n                        if (convertedBreakpointSize == 9999) {\n                            sliderSettings.autoplay = true;\n                            sliderSettings.autoplaySpeed = breakpointSizeSettings[sizeSetting].autoplay;\n                        } else {\n                            breakpointSettingsObject.settings.autoplay = true;\n                            breakpointSettingsObject.settings.autoplaySpeed = breakpointSizeSettings[sizeSetting];\n                        }\n                    }\n                }\n                //if (convertedBreakpointSize != 9999) {\n                    sliderSettings.responsive.push(breakpointSettingsObject);\n                //}\n            }\n        }\n\n        $(elementSelector).slick(sliderSettings);\n    } else {\n        $(elementSelector).slick();\n    }\n}\n\nfunction initSwiper(elementSelector, settings, classesForSettings) {\n    if (!elementSelector) {\n        return;\n    }\n\n    var sliderSettings = {\n        loop: true,\n        spaceBetween: 20,\n        preventInteractionOnTransition: true,\n        a11y: {\n            enabled: true,\n            firstSlideMessage: 'This is the first slide',\n            lastSlideMessage: 'This is the last slide'\n        },\n        keyboard: {\n\t\t\tenabled: true,\n\t\t\tpageUpDown: true\n\t\t}\n    };\n    if (settings) {\n        if ('loop' in settings) {\n            sliderSettings.loop = settings.loop;\n        }\n        if ('pagination' in settings || 'dots' in settings) {\n            if (settings.pagination) {\n                if ('el' in settings.pagination && settings.pagination.el.length > 0) {\n                    sliderSettings.pagination = settings.pagination;\n                }\n            } else {\n                if (settings.dots) {\n                    sliderSettings.pagination = {\n                        el: '.swiper-pagination',\n                        clickable: true\n                    }\n                }\n            }\n        } \n        if ('navigation' in settings || 'arrows' in settings) {\n            if (settings.navigation) {\n                if ('nextEl' in settings.navigation && settings.navigation.nextEl.length > 0) {\n                    sliderSettings.navigation = settings.navigation;\n                }\n            } else {\n                if (settings.arrows) {\n                    sliderSettings.navigation = {\n                        nextEl: '.swiper-button-next',\n                        prevEl: '.swiper-button-prev'\n                    }\n                }\n            }\n        }\n        if ('slidesToShow' in settings) {\n            sliderSettings.slidesPerView = settings.slidesToShow;\n        }\n        if ('autoplay' in settings) {\n            sliderSettings.autoplay = {\n                delay: settings.autoplay,\n                disableOnInteraction: true\n            };\n        }\n        if ('breakpoints' in settings) {\n            sliderSettings.breakpoints = {};\n            for (var breakpointSize in settings.breakpoints) {\n                breakpointSize = parseInt(breakpointSize);\n                sliderSettings.breakpoints[breakpointSize] = {};\n                var breakpointSizeSettings = settings.breakpoints[breakpointSize];\n                for (var sizeSetting in breakpointSizeSettings) {\n                    if ('loop' == sizeSetting) {\n                        sliderSettings.loop = breakpointSizeSettings[sizeSetting];\n                    }\n                    if ('dots' == sizeSetting && breakpointSizeSettings[sizeSetting] == true) {\n                        sliderSettings.breakpoints[breakpointSize].pagination = {\n                            enabled: breakpointSizeSettings[sizeSetting],\n                            el: '.swiper-pagination',\n                            clickable: true\n                        };\n                        if (classesForSettings && classesForSettings.pagination) {\n                            sliderSettings.breakpoints[breakpointSize].pagination.el = classesForSettings.pagination;\n                        }  \n                    }\n                    if ('arrows' == sizeSetting && breakpointSizeSettings[sizeSetting] == true) {\n                        sliderSettings.breakpoints[breakpointSize].navigation = {\n                            enabled: breakpointSizeSettings[sizeSetting],\n                            nextEl: '.swiper-button-next',\n                            prevEl: '.swiper-button-prev'\n                        };\n                        if (classesForSettings && classesForSettings.next && classesForSettings.prev) {\n                            sliderSettings.breakpoints[breakpointSize].navigation.nextEl = classesForSettings.next;\n                            sliderSettings.breakpoints[breakpointSize].navigation.prevEl = classesForSettings.prev;\n                        }\n                    }\n                    if ('slidesToShow' == sizeSetting) {\n                        sliderSettings.breakpoints[breakpointSize].slidesPerView = breakpointSizeSettings.slidesToShow;\n                    }\n                    if ('slidesToScroll' == sizeSetting) {\n                        sliderSettings.breakpoints[breakpointSize].slidesPerGroup = breakpointSizeSettings.slidesToScroll;\n                    }\n                    if ('autoplay' in breakpointSizeSettings) {\n                        sliderSettings.autoplay = {\n                            delay: breakpointSizeSettings.autoplay,\n                            disableOnInteraction: true\n                        };\n                    } else {\n                        sliderSettings.breakpoints[breakpointSize].autoplay = false;\n                    }\n                }\n            }\n        }\n    }\n    \n    return new Swiper (elementSelector, sliderSettings);\n}\n\nfunction formatSlickHTML($element, settings, isEinstein) {\n    var originalSlideElements = $element.children().toArray();\n    var uniqueSlider;\n\n    if ($element.attr('id') && $element.attr('id').indexOf('slider-index') > -1) {\n        uniqueSlider = $element.attr('id');\n    } else {\n        uniqueSlider = 'slider-index-' + getUniqueNumber().toString();\n    }\n\n    $element.attr('id', uniqueSlider);\n\n    // Einstein CQuotient scripts are mixed in with slides at time of slider initialization. Rework the HTML structure.\n    if (originalSlideElements.length > 0 && isEinstein) {\n        var modifiedSlideElements = [];\n        var cqScripts = [];\n\n        $.each(originalSlideElements, function(index, element) {\n            if (element.tagName.toUpperCase() === 'SCRIPT') {\n                cqScripts.push(element);\n            } else {\n                if (element.tagName.toUpperCase() === 'LI') {\n                    modifiedSlideElements.push(element);\n                }  \n            }\n        });\n\n        if (cqScripts.length > 0) {\n            $element.closest('div.slider-clip').append(cqScripts);\n        }\n\n        $element.html('');\n        $element.append(modifiedSlideElements);\n    }\n    return;\n}\n\nfunction formatSwiperHTML($element, settings, isEinstein) {\n    var originalSlideElements = $element.children().toArray();\n    var uniqueSlider, sortedSlidesPerViewArray, addSlides, finalSlides;\n    var isLoop = true;\n    var slidesPerViewArray = [];\n    var cqScripts = [];\n    var modifiedSlideElements = [];\n    var duplicatedSlideElements = [];\n    var hasSwiperHTML = $element.hasClass('swiper-full-wrapper') && $element.find('.swiper').length > 0;\n    var swiperClassesForSettings = {};\n\n    if ($element.attr('id') && $element.attr('id').indexOf('slider-index') > -1) {\n        uniqueSlider = $element.attr('id');\n    } else {\n        uniqueSlider = 'slider-index-' + getUniqueNumber().toString();\n    }\n\n    var $swiperParent = $('<div />', { 'class': 'swiper', 'id': uniqueSlider }),\n        $swiperPagination = $('<div />', { 'class': 'swiper-pagination swiper-pagination-' + uniqueSlider }),\n        $swiperNavigation = $('<div />', { 'class': 'swiper-navigation-buttons-container' }),\n        $swiperPrevArrow = $('<div />', { 'class': 'swiper-button-prev swiper-button-prev-' + uniqueSlider }),\n        $swiperNextArrow = $('<div />', { 'class': 'swiper-button-next swiper-button-next-' + uniqueSlider }),\n        $swiperWrapper = $('<div />', { 'class': 'swiper-wrapper' });\n\n    if (settings) {\n        if ('breakpoints' in settings) {\n            for (var breakpointSize in settings.breakpoints) {\n                var breakpointSizeSettings = settings.breakpoints[breakpointSize];\n\n                /* --- Swiper Arrows Navigation --- */\n                // Swiper does not display arrows by default the way Slick does. We must actively include them to match the defaults of Slick.\n                var navDisplayClass = breakpointSize == '0' ? 'show-mobile-nav-buttons' : 'show-desktop-nav-buttons';\n                $swiperNavigation.addClass(navDisplayClass);\n\n                // If arrows were deliberately set to false in settings, that means hide them for all breakpoint sizes.\n                if ('arrows' in settings) {\n                    if (settings.arrows == false) {\n                        $swiperNavigation.removeClass('show-mobile-nav-buttons show-desktop-nav-buttons');\n                    }\n                // Else if arrows were deliberately set to false for specific breakpoint, then hide for that breakpoint.\n                } else if ('arrows' in breakpointSizeSettings) {\n                    if (breakpointSizeSettings.arrows == false) {\n                        $swiperNavigation.removeClass(navDisplayClass);\n                    }\n                }\n\n                /* --- Swiper Dots Pagination --- */\n                // Swiper does not display pagination dots by default the way Slick does. We must actively include them to match the defaults of Slick.\n                var paginationDisplayClass = breakpointSize == '0' ? 'show-mobile-pagination' : 'show-desktop-pagniation';\n                $swiperPagination.addClass(paginationDisplayClass);\n\n                // If dots were deliberately set to false in settings, that means hide them for all breakpoint sizes.\n                if ('dots' in settings) {\n                    if (settings.dots == false) {\n                        $swiperPagination.removeClass('show-mobile-pagination show-desktop-pagniation');\n                    }\n                // Else if dots were deliberately set to false for specific breakpoint, then hide for that breakpoint.\n                } else if ('dots' in breakpointSizeSettings) {\n                    if (breakpointSizeSettings.dots == false) {\n                        $swiperPagination.removeClass(paginationDisplayClass);\n                    }\n                }\n\n                if ('slidesToShow' in breakpointSizeSettings) {\n                    slidesPerViewArray.push(parseInt(breakpointSizeSettings.slidesToShow));\n                }\n            }\n        } else {\n            // Swiper does not display arrows by default the way Slick does. We must actively include them to match the defaults of Slick.\n            $swiperNavigation.addClass('show-mobile-nav-buttons show-desktop-nav-buttons');\n\n            // If arrows were deliberately set to false in settings, that means hide them for all breakpoint sizes.\n            if ('arrows' in settings) {\n                if (settings.arrows == false) {\n                    $swiperNavigation.removeClass('show-mobile-nav-buttons show-desktop-nav-buttons');\n                }\n            }\n\n            // Swiper does not display pagination dots by default the way Slick does. We must actively include them to match the defaults of Slick.\n            $swiperPagination.addClass('show-desktop-pagniation show-mobile-pagination');\n\n            // If dots were deliberately set to false in settings, that means hide them for all breakpoint sizes.\n            if ('dots' in settings) {\n                if (settings.dots == false) {\n                    $swiperPagination.removeClass('show-desktop-pagniation show-mobile-pagination');\n                }\n            }\n        }\n        if ('loop' in settings) {\n            isLoop = settings.loop;\n        }\n    }    \n\n    if (slidesPerViewArray) {\n        sortedSlidesPerViewArray = slidesPerViewArray.sort(function (a, b) { return a - b; });\n    }\n\n    if (!hasSwiperHTML && originalSlideElements.length > 0) {\n        $element.addClass('swiper-full-wrapper');\n\n        // Einstein CQuotient scripts are mixed in with slides at time of slider initialization. Rework the HTML structure.\n        if (isEinstein) {\n            $.each(originalSlideElements, function(index, element) {\n                if (element.tagName.toUpperCase() === 'SCRIPT') {\n                    cqScripts.push(element);\n                } else {\n                    var formattedSlide;\n                    if (element.tagName.toUpperCase() === 'DIV') {\n                        formattedSlide = $(element).addClass('swiper-slide');\n                    } else {\n                        formattedSlide = $('<div />', { 'class': 'swiper-slide' }).html($(element).html());\n                    }\n                    modifiedSlideElements.push(formattedSlide);\n                }\n            });\n        } else {\n            // Proceed to modify regular slide elements (non-Einstein)\n            modifiedSlideElements = originalSlideElements.map(function(element, index) {\n                if (element.tagName.toUpperCase() === 'DIV') {\n                    return $(element).addClass('swiper-slide')[0];\n                } else {\n                    return $('<div />', { 'class': 'swiper-slide' }).html($(element).html())[0];\n                }\n            });\n        }\n\n        // Add additional slides (according to lowest common multiple) to fix loop bug in Swiper\n        if (modifiedSlideElements && sortedSlidesPerViewArray && isLoop) {\n            var LCM = leastCommonMultiple(sortedSlidesPerViewArray);\n            if (sortedSlidesPerViewArray.indexOf(LCM) > -1) {\n                addSlides = (LCM * 2) - modifiedSlideElements.length;\n            } else {\n                addSlides = LCM - modifiedSlideElements.length;\n            }\n            if (addSlides < 0) {\n                var HCM = sortedSlidesPerViewArray.reduce(function (a, b) { return a * b; });\n                addSlides = HCM - modifiedSlideElements.length;\n            }\n            $.each(modifiedSlideElements, function(idx, item) {\n                if (idx < addSlides) {\n                    duplicatedSlideElements.push($(item).clone());\n                }\n            });\n        }\n\n        // Create final array of slide elements\n        finalSlides = $.merge(modifiedSlideElements, duplicatedSlideElements);\n\n        // Append new swiper HTML elements to swiper wrapper\n        $swiperWrapper.append(finalSlides);\n        $swiperNavigation.append($swiperPrevArrow).append($swiperNextArrow);\n        $swiperParent.append($swiperWrapper).append($swiperPagination);\n\n        // Set slide arrows either inside or outside slider container\n        var arrowsPosition = settings && 'arrowsPosition' in settings ? settings.arrowsPosition : null;\n        if (arrowsPosition && arrowsPosition == 'inside') {\n            $swiperParent.append($swiperNavigation).addClass('swiper-inside-navigation');\n        }\n\n        // Replace swiper wrapper contents with new HTML\n        $element.html($swiperParent);\n\n        if (!arrowsPosition || arrowsPosition == 'outside') { // If arrows are outside, we have to wait until swiper wrapper has content in line above before we prepend\n            $element.prepend($swiperNavigation);\n        }\n        if (isEinstein && cqScripts.length > 0) {\n            $element.append(cqScripts);\n        }\n\n        // Grab the unique classes from all the new elements above and return for further use\n        swiperClassesForSettings.parent = '#' + uniqueSlider;\n        swiperClassesForSettings.pagination = '.swiper-pagination-' + uniqueSlider;\n        swiperClassesForSettings.prev = '.swiper-button-prev-' + uniqueSlider;\n        swiperClassesForSettings.next = '.swiper-button-next-' + uniqueSlider;\n    }\n    return swiperClassesForSettings;\n}\n\nfunction init (elementClass, settings, isEinstein) {\n    var selector = elementClass;\n    if (!elementClass || ($(elementClass).length == 0 && elementClass.indexOf(':has') < 0)) {\n        return;\n    }\n    if (SitePreferences.CONTENT_SLOT_SLIDER == 'swiperJS') { \n        $(elementClass).each(function(n, elm) {\n            var $element = $(elm);\n            var hasSwiperHTML = $element.find('.swiper-initialized').length > 0;\n\n            if (!hasSwiperHTML) {\n                var classesForSettings = formatSwiperHTML($element, settings, isEinstein);\n                if (!settings) {\n                    settings = {};\n                }\n                if (classesForSettings) {\n                    // Override selector class for ID if we have it\n                    selector = classesForSettings.parent ? classesForSettings.parent : selector;\n                    settings.pagination = {\n                        el: classesForSettings.pagination,\n                        clickable: true\n                    };\n                    settings.navigation = {\n                        nextEl: classesForSettings.next,\n                        prevEl: classesForSettings.prev\n                    };    \n                }\n                return initSwiper(selector, settings, classesForSettings);\n            }\n        });\n    } else {\n        $(elementClass).each(function(n, elm) {\n            var $element = $(elm);\n            var elementIdSelector;\n            formatSlickHTML($element, settings, isEinstein);\n            elementIdSelector = '#' + $element.attr('id');\n            initSlick(elementIdSelector, settings);\n        });\n    }\n}\n\nfunction leastCommonMultiple(values) {\n    function gcd(a, b) {\n        // Greatest common divisor of 2 integers\n        return !b ? a : gcd(b, a % b);\n    }\n\n    function lcm(a, b) {\n        // Least common multiple of 2 integers\n        return (a * b) / gcd(a, b);   \n    }\n\n    var multiple = values[0];\n    // Least common multiple of a list of integers\n    values.forEach(function(n) {\n        multiple = lcm(multiple, n);\n    });\n\n    // Return least common multiple for array of values\n    return multiple;\n}\n\nfunction initializeCategorySliders(elementClass) {\n\tvar $categorySliders = $(elementClass);\n\tif ($categorySliders.length > 0) {\n\t\t$categorySliders.each(function(index, element) {\n\t\t\tvar $element = $(element);\n            var categorySliderOptions = {\n                breakpoints: {}\n            };\n            var uniqueSlider = 'category-slider-index-' + getUniqueNumber().toString();\n            $element.addClass(uniqueSlider);\n\n\t\t\t// Desktop slot config options\n\t\t\tvar categorySliderDesktopOptions = $element.attr('slider-desktop-options');\n\t\t\tif (categorySliderDesktopOptions) {\n\t\t\t\tcategorySliderDesktopOptions = JSON.parse(categorySliderDesktopOptions);\n                categorySliderOptions.breakpoints[categorySliderDesktopOptions.breakpointSize] = categorySliderDesktopOptions;\n\t\t\t}\n\t\t\t// Mobile slot config options\n\t\t\tvar categorySliderMobileOptions = $element.attr('slider-mobile-options');\n\t\t\tif (categorySliderMobileOptions) {\n\t\t\t\tcategorySliderMobileOptions = JSON.parse(categorySliderMobileOptions);\n                categorySliderOptions.breakpoints[categorySliderMobileOptions.breakpointSize] = categorySliderMobileOptions;\n\t\t\t}\n\n            init('.' + uniqueSlider, categorySliderOptions);\n\t\t});\n\t}\n}\n\nfunction initializeRecommendationSlider() {\n\tvar attemptNumber = 0;\n\tvar timer = setInterval(recommendationSliderIntervalHandler, 500);\n\tfunction recommendationSliderIntervalHandler() {\n        var sliderInitializedClass = SitePreferences.CONTENT_SLOT_SLIDER == 'swiperJS' ? 'swiper-initialized' : 'slick-initialized';\n        var sliderSelector = '.product-recommendations .slider-products-primary .slides';\n        var recommendationSliderInitialized;\n\n        if (pageContext.site == SiteConstants.SiteIds.BootBarnUS) {\n            sliderSelector = '.recomm-prod-anchor-slot ' + sliderSelector;\n        }\n\n        if (SitePreferences.CONTENT_SLOT_SLIDER == 'swiperJS') {\n            recommendationSliderInitialized = $(sliderSelector).find('.' + sliderInitializedClass).length > 0;\n        } else {\n            recommendationSliderInitialized = $(sliderSelector).filter(function(index) {\n                return $(this).hasClass(sliderInitializedClass);\n            }).length > 0;\n        }\n\n\t\tattemptNumber++;\n\t\tif(recommendationSliderInitialized || attemptNumber > 20) {\n\t\t\t$(document).trigger('EinsteinProductRecommendations.Done', $('#product-recommendations'));\n            if (SitePreferences.CONTENT_SLOT_SLIDER == 'imgViewer2Slick') { \n\t\t\t    $(document).trigger('SlickSliderAccessibilityMods');\n            }\n\t\t\tclearInterval(timer);\n\t\t\treturn;\n\t\t}\n        $('.slider-products-primary').trigger('init-slider');\n\t}\n}","'use strict';\n\nvar inventory = require('./');\n\nvar cartInventory = {\n    setSelectedStore: function (storeId) {\n        var $selectedStore = $('.store-tile.' + storeId),\n            $lineItem = $('.cart-row[data-uuid=\"' + this.uuid + '\"]'),\n            storeAddress = $selectedStore.find('.store-address').html(),\n            storeStatus = $selectedStore.find('.store-status').data('status'),\n            storeStatusText = $selectedStore.find('.store-status').text();\n        this.selectedStore = storeId;\n\n        $lineItem.find('.instore-delivery .selected-store-address')\n            .data('storeId', storeId)\n            .attr('data-store-id', storeId)\n            .html(storeAddress);\n        $lineItem.find('.instore-delivery .selected-store-availability')\n            .data('status', storeStatus)\n            .attr('data-status', storeStatus)\n            .text(storeStatusText);\n        $lineItem.find('.instore-delivery .delivery-option').removeAttr('disabled').trigger('click');\n    },\n    cartSelectStore: function (selectedStore) {\n        var self = this;\n        inventory.getStoresInventory(this.uuid).then(function (stores) {\n            inventory.selectStoreDialog({\n                stores: stores,\n                selectedStoreId: selectedStore,\n                selectedStoreText: Resources.SELECTED_STORE,\n                continueCallback: function () {},\n                selectStoreCallback: self.setSelectedStore.bind(self)\n            });\n        }).done();\n    },\n    setDeliveryOption: function (value, storeId) {\n        // set loading state\n        $('.item-delivery-options')\n            .addClass('loading')\n            .children().hide();\n\n        var data = {\n            plid: this.uuid,\n            storepickup: (value === 'store' ? true : false)\n        };\n        if (value === 'store') {\n            data.storepickup = true;\n            data.storeid = storeId;\n        } else {\n            data.storepickup = false;\n        }\n        $.ajax({\n            url: Urls.setStorePickup,\n            data: data,\n            success: function () {\n                // remove loading state\n                $('.item-delivery-options')\n                    .removeClass('loading')\n                    .children().show();\n            }\n        });\n    },\n    init: function () {\n        var self = this;\n        $('.item-delivery-options .set-preferred-store').on('click', function (e) {\n            e.preventDefault();\n            self.uuid = $(this).data('uuid');\n            var selectedStore = $(this).closest('.instore-delivery').find('.selected-store-address').data('storeId');\n            if (!User.zip) {\n                inventory.zipPrompt(function () {\n                    self.cartSelectStore(selectedStore);\n                });\n            } else {\n                self.cartSelectStore(selectedStore);\n            }\n        });\n        $('.item-delivery-options .delivery-option').on('click', function () {\n            // reset the uuid\n            var selectedStore = $(this).closest('.instore-delivery').find('.selected-store-address').data('storeId');\n            self.uuid = $(this).closest('.cart-row').data('uuid');\n            self.setDeliveryOption($(this).val(), selectedStore);\n        });\n    }\n};\n\nmodule.exports = cartInventory;\n","'use strict';\n\nvar _ = require('lodash'),\n    dialog = require('../dialog'),\n    TPromise = require('promise'),\n    util = require('../util');\n\nvar newLine = '\\n';\nvar storeTemplate = function (store, selectedStoreId, selectedStoreText) {\n    return [\n        '<li class=\"store-tile ' + store.storeId + (store.storeId === selectedStoreId ? ' selected' : '') + '\">',\n        '    <p class=\"store-address\">',\n        '        ' + store.address1 + '<br/>',\n        '        ' + store.city + ', ' + store.stateCode + ' ' + store.postalCode,\n        '    </p>',\n        '    <p class=\"store-status\" data-status=\"' + store.statusclass + '\">' + store.status + '</p>',\n        '    <button class=\"select-store-button\" data-store-id=\"' + store.storeId + '\"' +\n        (store.statusclass !== 'store-in-stock' ? 'disabled=\"disabled\"' : '') + '>',\n        '        ' + (store.storeId === selectedStoreId ? selectedStoreText : Resources.SELECT_STORE),\n        '    </button>',\n        '</li>'\n    ].join(newLine);\n};\n\nvar storeListTemplate = function (stores, selectedStoreId, selectedStoreText) {\n    if (stores && stores.length) {\n        return [\n            '<div class=\"store-list-container\">',\n            '<ul class=\"store-list\">',\n            _.map(stores, function (store) {\n                return storeTemplate(store, selectedStoreId, selectedStoreText);\n            }).join(newLine),\n            '</ul>',\n            '</div>',\n            '<div class=\"store-list-pagination\">',\n            '</div>'\n        ].join(newLine);\n    } else {\n        return '<div class=\"no-results\">' + Resources.INVALID_ZIP + '</div>';\n    }\n};\n\nvar zipPromptTemplate = function () {\n    return [\n        '<div id=\"preferred-store-panel\">',\n        '    <input type=\"text\" id=\"user-zip\" placeholder=\"' + Resources.ENTER_ZIP + '\" name=\"zipCode\"/>',\n        '</div>'\n    ].join(newLine);\n};\n\n/**\n * @description test whether zipcode is valid for either US or Canada\n * @return {Boolean} true if the zipcode is valid for either country, false if it's invalid for both\n **/\nvar validateZipCode = function (zipCode) {\n    var regexes = {\n            canada: /^[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJKLMNPRSTVWXYZ]( )?\\d[ABCEGHJKLMNPRSTVWXYZ]\\d$/i,\n            usa: /^\\d{5}(-\\d{4})?$/\n        },\n        valid = false;\n    if (!zipCode) { return; }\n    _.each(regexes, function (re) {\n        var regexp = new RegExp(re);\n        valid = regexp.test(zipCode);\n    });\n    return valid;\n};\n\nvar storeinventory = {\n    zipPrompt: function (callback) {\n        var self = this;\n        dialog.open({\n            html: zipPromptTemplate(),\n            options: {\n                title: Resources.STORE_NEAR_YOU,\n                width: 500,\n                buttons: [{\n                    text: Resources.SEARCH,\n                    click: function () {\n                        var zipCode = $('#user-zip').val();\n                        if (validateZipCode(zipCode)) {\n                            self.setUserZip(zipCode);\n                            if (callback) {\n                                callback(zipCode);\n                            }\n                        }\n                    }\n                }],\n                open: function () {\n                    $('#user-zip').on('keypress', function (e) {\n                        if (e.which === 13) {\n                            // trigger the search button\n                            $('.ui-dialog-buttonset .ui-button').trigger('click');\n                        }\n                    });\n                }\n            }\n        });\n    },\n    getStoresInventory: function (pid) {\n      return TPromise.resolve($.ajax({\n          url: util.appendParamsToUrl(Urls.storesInventory, {\n              pid: pid,\n              zipCode: User.zip\n          }),\n          dataType: 'json'\n      }));\n    },\n    /**\n     * @description open the dialog to select store\n     * @param {Array} options.stores\n     * @param {String} options.selectedStoreId\n     * @param {String} options.selectedStoreText\n     * @param {Function} options.continueCallback\n     * @param {Function} options.selectStoreCallback\n     **/\n    selectStoreDialog: function (options) {\n        var self = this,\n            stores = options.stores,\n            selectedStoreId = options.selectedStoreId,\n            selectedStoreText = options.selectedStoreText,\n            storeList = storeListTemplate(stores, selectedStoreId, selectedStoreText);\n        dialog.open({\n            html: storeList,\n            options: {\n                title: Resources.SELECT_STORE + ' - ' + User.zip,\n                buttons: [{\n                    text: Resources.CHANGE_LOCATION,\n                    click: function () {\n                        self.setUserZip(null);\n                        // trigger the event to start the process all over again\n                        $('.set-preferred-store').trigger('click');\n                    }.bind(this)\n                }, {\n                    text: Resources.CONTINUE,\n                    click: function () {\n                        if (options.continueCallback) {\n                            options.continueCallback(stores);\n                        }\n                        dialog.close();\n                    }\n                }],\n                open: function () {\n                    $('.select-store-button').on('click', function (e) {\n                        e.preventDefault();\n                        var storeId = $(this).data('storeId');\n                        // if the store is already selected, don't select again\n                        if (storeId === selectedStoreId) { return; }\n                        $('.store-list .store-tile.selected').removeClass('selected')\n                            .find('.select-store-button').text(Resources.SELECT_STORE);\n                        $(this).text(selectedStoreText)\n                            .closest('.store-tile').addClass('selected');\n                        if (options.selectStoreCallback) {\n                            options.selectStoreCallback(storeId);\n                        }\n                    });\n                }\n            }\n        });\n    },\n    setUserZip: function (zip) {\n        User.zip = zip;\n\n        $.ajax({\n            type: 'POST',\n            url: Urls.setZipCode,\n            data: {\n                zipCode: zip\n            }\n        });\n    },\n    shippingLoad: function () {\n        var $checkoutForm = $('.address');\n        $checkoutForm.off('click');\n        $checkoutForm.on('click', 'input[name$=\"_shippingAddress_isGift\"]', function () {\n            $(this).parent().siblings('.gift-message-text').toggleClass('hidden', $('input[name$=\"_shippingAddress_isGift\"]:checked').val());\n        });\n    }\n};\n\nmodule.exports = storeinventory;\n","'use strict';\n\nvar _ = require('lodash'),\n    inventory = require('./');\n\nvar newLine = '\\n';\nvar pdpStoreTemplate = function (store) {\n    return [\n        '<li class=\"store-list-item ' + (store.storeId === User.storeId ? ' selected' : '') + '\">',\n        '    <div class=\"store-address\">' + store.address1 + ', ' + store.city + ' ' + store.stateCode +\n        ' ' + store.postalCode + '</div>',\n        '    <div class=\"store-status\" data-status=\"' + store.statusclass + '\">' + store.status + '</div>',\n        '</li>'\n    ].join(newLine);\n};\nvar pdpStoresListingTemplate = function (stores) {\n    if (stores && stores.length) {\n        return [\n            '<div class=\"store-list-pdp-container\">',\n            (stores.length > 1 ? '    <a class=\"stores-toggle collapsed\" href=\"#\">' + Resources.SEE_MORE + '</a>' : ''),\n            '    <ul class=\"store-list-pdp\">',\n            _.map(stores, pdpStoreTemplate).join(newLine),\n            '    </ul>',\n            '</div>'\n        ].join(newLine);\n    }\n};\n\nvar storesListing = function (stores) {\n    // list all stores on PDP page\n    if ($('.store-list-pdp-container').length) {\n        $('.store-list-pdp-container').remove();\n    }\n    $('.availability-results').append(pdpStoresListingTemplate(stores));\n};\n\nvar productInventory = {\n    setPreferredStore: function (storeId) {\n        User.storeId = storeId;\n        $.ajax({\n            url: Urls.setPreferredStore,\n            type: 'POST',\n            data: {storeId: storeId}\n        });\n    },\n    productSelectStore: function () {\n        var self = this;\n        inventory.getStoresInventory(this.pid).then(function (stores) {\n            inventory.selectStoreDialog({\n                stores: stores,\n                selectedStoreId: User.storeId,\n                selectedStoreText: Resources.PREFERRED_STORE,\n                continueCallback: storesListing,\n                selectStoreCallback: self.setPreferredStore\n            });\n        }).done();\n    },\n    init: function () {\n        var $availabilityContainer = $('.availability-results'),\n            self = this;\n        this.pid = $('input[name=\"pid\"]').val();\n\n        $('#product-content .set-preferred-store').on('click', function (e) {\n            e.preventDefault();\n            if (!User.zip) {\n                inventory.zipPrompt(function () {\n                    self.productSelectStore();\n                });\n            } else {\n                self.productSelectStore();\n            }\n        });\n\n        if ($availabilityContainer.length) {\n            if (User.storeId) {\n                inventory.getStoresInventory(this.pid).then(storesListing);\n            }\n\n            // See more or less stores in the listing\n            $availabilityContainer.on('click', '.stores-toggle', function (e) {\n                e.preventDefault();\n                $('.store-list-pdp .store-list-item').toggleClass('visible');\n                if ($(this).hasClass('collapsed')) {\n                    $(this).text(Resources.SEE_LESS);\n                } else {\n                    $(this).text(Resources.SEE_MORE);\n                }\n                $(this).toggleClass('collapsed');\n            });\n        }\n    }\n};\n\nmodule.exports = productInventory;\n","'use strict';\n\nvar render = function(styleCountCache) {\n\tif (styleCountCache) {\n\t\t$('[data-link-category]').each(function() {\n\t\t\tvar categoryId = $(this).data('link-category');\n\t\t\t\n\t\t\tif (categoryId) {\n\t\t\t\tvar categoryRefinements = styleCountCache.CategoryLinks[categoryId];\n\t\t\t\tif (categoryRefinements && categoryRefinements.count > 0) {\n\t\t\t\t\tvar $styleCount = $(this).find('.style-number'); \n\t\t\t\t\tvar messageTemplate = categoryRefinements.count > 1 ? Resources.STYLE_PLURAL : Resources.STYLE_SINGULAR;\n\t\t\t\t\tvar message = messageTemplate.replace('{0}', categoryRefinements.count);\n\t\t\t\t\t$styleCount.addClass('visible').text(message);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\t\n\t\t\t}\n\n\t\t\t$(this).closest('li').remove();\n\t\t});\n\n\t\t$('[data-link-attribute-id]').each(function() {\n\t\t\tvar categoryId = $(this).data('link-cgid'),\n\t\t\trefinementId = $(this).data('link-attribute-id'),\n\t\t\trefinementValue = $(this).data('link-attribute-value');\n\n\t\t\tvar categoryRefinements = styleCountCache.RefinementLinks[categoryId];\n\t\t\tif (categoryRefinements) {\n\t\t\t\tvar attributeRefinements = categoryRefinements[refinementId];\n\t\t\t\tif (attributeRefinements) {\n\t\t\t\t\tvar attributeRefinement = attributeRefinements[refinementValue];\n\t\t\t\t\t\n\t\t\t\t\tif (attributeRefinement && attributeRefinement.count > 0) {\n\t\t\t\t\t\tvar $styleCount = $(this).find('.style-number');\n\t\t\t\t\t\tvar messageTemplate = attributeRefinement.count > 1 ? Resources.STYLE_PLURAL : Resources.STYLE_SINGULAR;\n\t\t\t\t\t\tvar message = messageTemplate.replace('{0}', attributeRefinement.count);\n\t\t\t\t\t\t$styleCount.addClass('visible').text(message);\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t}         \t\t\n\t\t\t}\n\t\t\t\n\t\t\t$(this).closest('li').remove();\n\t\t});\n\t}\n}\n\nmodule.exports.render = render;","'use strict';\n\n/**\n * Checks the TLS and displays a warning if appropriate\n * @function getUserAgent Checks the TLS and displays a warning if appropriate\n **/\nfunction getUserAgent() {\n    // Use an external service to check the TLS of the browser\n    // NOTE: this implementation uses https://www.howsmyssl.com\n    //     you may also wish to consider the API available at https://www.ssllabs.com/projects/ssllabs-apis/index.html\n    var url = 'https://www.howsmyssl.com/a/check';\n    var cookieName = 'dw_TLSWarning';\n    var cookieValue = getCookie(cookieName);\n\n    // Test to see if this browser has already been flagged by looking at its cookies\n    if (!cookieValue) {\n        getTLS(url, function (message) {\n            if (message.length > 0) {\n                showWarning(message[0]);\n\n                // the browser is bad - set the cookie to true (for 15 minutes)\n                setCookie(cookieName, 'true', 15);\n            } else {\n                // else the browser is good, set the cookie to false (for 30 days) so we don't check again\n                setCookie(cookieName, 'false', 60 * 24 * 30);\n            }\n        });\n    } else if (cookieValue === 'true') {\n        // if we already know that this is an invalid browser, show the warning\n        showWarning(Resources.TLS_WARNING);\n    }\n}\n\n/**\n * Calls out to the TLS service and calls the callback with a message (if necessary)\n * @function getTLS\n *\n * @param {string} url - URL of external TLS-checking API\n * @param {function} callback - function to call with response\n **/\nfunction getTLS(url, callback) {\n    var message = [];\n\n    // First, see if the browser is among the suspect browsers to see if a TLS check is necessary\n    var userAgent = navigator.userAgent;\n\n    /** This list derived from https://www.ssllabs.com/ssltest/clients.html **/\n    var badBrowsers = ['MSIE 6.0','MSIE 7.0','MSIE 8.0','MSIE 9.0','MSIE 10.0',\n                       'Android 2.3.7', 'Android 4.0.4', 'Android 4.1.1', 'Android 4.2.2', 'Android 4.3',\n                       'Safari 5.1.9 / OS X 10.6.8', 'Safari 6.0.4 / OS X 10.8.4 '];\n    function checkTLSLevel(data) {\n        // If we can determine the TLS level, check to see if it's less than 1.2\n        if (parseFloat(data.tls_version.split(' ')[1]) < 1.1) {\n            message.push(Resources.TLS_WARNING);\n            callback(message);\n\n            //If you want to track statistics on bad TLS hits, include this call\n            $.ajax({url: Urls.TLSBadTLS});\n        }\n    }\n\n    function reportBadBrowser () {\n        // If the TLS level cannot be determined just report that this browser is suspect\n        message.push(Resources.TLS_WARNING);\n        callback(message);\n\n        //If you want to track statistics on deprecated browsers, include this call\n        $.ajax({url: Urls.TLSBadBrowser});\n    }\n\n    for (var i = 0; i < badBrowsers.length; i++) {\n        if (userAgent.match(badBrowsers[i])) {\n            // It's a suspect browser, let's see what it's TLS level is\n            $.ajax({\n                url: url\n            }).done(checkTLSLevel).fail(reportBadBrowser);\n            break;\n        }\n    }\n\n    /** For testing purposes, uncomment this block\n        message.push(Resources.TLS_WARNING);\n    **/\n    callback(message);\n}\n\n/**\n * @function showWarning turns on the browser-compatibility-alert and sets the message\n *\n * @param {string} message - the message that will be shown upon detection of a bad browser\n **/\nfunction showWarning(message) {\n    $('<div/>').addClass('browser-compatibility-alert').append($('<p/>').addClass('browser-error').html(message)).appendTo('#browser-check');\n}\n\n/**\n * @function getCookie\n *\n * @param {string} key - The cookie name\n * @returns {string} value - the value of the cookie if found, null otherwise\n **/\nfunction getCookie(key) {\n    var cookies = document.cookie.split(';');\n    for (var i = 0; i < cookies.length; i++) {\n        var tokens = cookies[i].split('=');\n        var cookieKey = tokens[0].trim();\n        if (cookieKey === key) {\n            return tokens[1];\n        }\n    }\n    return '';\n}\n\n/**\n * @function setCookie\n *\n * @param {string} key - The cookie name\n * @param {string} value - The cookie value\n * @param {integer} minutes - The number of minutes to expire the cookie\n **/\nfunction setCookie (key, value, minutes) {\n    var date = new Date();\n    date.setTime(date + (minutes * 60 * 1000));\n\n    document.cookie = key + '=' + value + '; expires=' + date.toGMTString() + '; path=/';\n}\n\n/**\n * Export the getUserAgent function\n */\n\nexports.getUserAgent = getUserAgent;\n","'use strict';\n\n/**\n * @function\n * @description Initializes the tooltip-content and layout\n */\nexports.init = function(optionsParameter, $containerParameter) {\n\tvar defaultOptions = {\n        items: '.tooltip',\n        track: true,\n        content: function () {\n            return $(this).find('.tooltip-content').html();\n        }\n    };\n\t\n\tvar options;\n\tif (optionsParameter) {\n\t\toptions = $.extend(defaultOptions, optionsParameter);\n\t} else {\n\t\toptions = defaultOptions;\n\t}\n\t\n\tvar $container;\n\tif ($containerParameter) {\n\t\t$container = $containerParameter;\n\t} else {\n\t\t$container = $(document);\n\t}\n\t\n    $container.tooltip(options);\n    \n    $(document).off('click', '.tooltip').on('click', '.tooltip', function(e) {\n    \te.preventDefault();\n    });\n    \n    $(document).off('click', '.share-link').on('click', '.share-link', function(e) {\n        e.preventDefault();\n        var target = $(this).data('target');\n        if (target) {\n            $(target).toggleClass('active');\n        }\n    });\n};\n","'use strict';\n\nvar _ = require('lodash');\nvar PaymentMethodConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').PaymentMethods;\nvar CreditCardConstants = require('../../../bc_sheplersbootbarn_core/cartridge/js/PaymentInstrumentConstants').CreditCards;\n\nvar util = {\n    /**\n     * @function\n     * @description appends the parameter with the given name and value to the given url and returns the changed url\n     * @param {String} url the url to which the parameter will be added\n     * @param {String} name the name of the parameter\n     * @param {String} value the value of the parameter\n     */\n    appendParamToURL: function (url, name, value) {\n        // quit if the param already exists\n        if (url.indexOf(name + '=') !== -1) {\n            return url;\n        }\n        var separator = url.indexOf('?') !== -1 ? '&' : '?';\n\t\tvar anchor = '';\n\t\tif (url.indexOf('#') > -1) {\n            var urlAndAnchor = url.split('#');\n\t\t\turl = urlAndAnchor[0];\n\t\t\tanchor = '#' + urlAndAnchor[1];\n        }\n        return url + separator + name + (value ? '=' + encodeURIComponent(value) : '') + anchor;\n    },\n\n    /**\n     * @function\n     * @description remove the parameter and its value from the given url and returns the changed url\n     * @param {String} url the url from which the parameter will be removed\n     * @param {String} name the name of parameter that will be removed from url\n     */\n    removeParamFromURL: function (url, name) {\n        if (url.indexOf('?') === -1 || url.indexOf(name + '=') === -1) {\n            return url;\n        }\n        var hash;\n        var params;\n        var domain = url.split('?')[0];\n        var paramUrl = url.split('?')[1];\n        var newParams = [];\n        // if there is a hash at the end, store the hash\n        if (paramUrl.indexOf('#') > -1) {\n            hash = paramUrl.split('#')[1] || '';\n            paramUrl = paramUrl.split('#')[0];\n        }\n        params = paramUrl.split('&');\n        for (var i = 0; i < params.length; i++) {\n            // put back param to newParams array if it is not the one to be removed\n            if (params[i].split('=')[0] !== name) {\n                newParams.push(params[i]);\n            }\n        }\n        return domain + '?' + newParams.join('&') + (hash ? '#' + hash : '');\n    },\n\n    /**\n     * @function\n     * @description appends the parameters to the given url and returns the changed url\n     * @param {String} url the url to which the parameters will be added\n     * @param {Object} params\n     */\n    appendParamsToUrl: function (url, params) {\n        var _url = url;\n        _.each(params, function (value, name) {\n            _url = this.appendParamToURL(_url, name, value);\n        }.bind(this));\n        return _url;\n    },\n    /**\n     * @function\n     * @description extract the query string from URL\n     * @param {String} url the url to extra query string from\n     **/\n    getQueryString: function (url) {\n        var qs;\n        if (!_.isString(url)) { return; }\n        var a = document.createElement('a');\n        a.href = url;\n        if (a.search) {\n            qs = a.search.substr(1); // remove the leading ?\n        }\n        return qs;\n    },\n    /**\n     * @function\n     * @description\n     * @param {String}\n     * @param {String}\n     */\n    elementInViewport: function (el, offsetToTop) {\n        var top = el.offsetTop,\n            left = el.offsetLeft,\n            width = el.offsetWidth,\n            height = el.offsetHeight;\n\n        while (el.offsetParent) {\n            el = el.offsetParent;\n            top += el.offsetTop;\n            left += el.offsetLeft;\n        }\n\n        if (typeof(offsetToTop) !== 'undefined') {\n            top -= offsetToTop;\n        }\n\n        if (window.pageXOffset !== null) {\n            return (\n                top < (window.pageYOffset + window.innerHeight) &&\n                left < (window.pageXOffset + window.innerWidth) &&\n                (top + height) > window.pageYOffset &&\n                (left + width) > window.pageXOffset\n            );\n        }\n\n        if (document.compatMode === 'CSS1Compat') {\n            return (\n                top < (window.document.documentElement.scrollTop + window.document.documentElement.clientHeight) &&\n                left < (window.document.documentElement.scrollLeft + window.document.documentElement.clientWidth) &&\n                (top + height) > window.document.documentElement.scrollTop &&\n                (left + width) > window.document.documentElement.scrollLeft\n            );\n        }\n    },\n\n    /**\n     * @function\n     * @description Appends the parameter 'format=ajax' to a given path\n     * @param {String} path the relative path\n     */\n    ajaxUrl: function (path) {\n        return this.appendParamToURL(path, 'format', 'ajax');\n    },\n\n    /**\n     * @function\n     * @description\n     * @param {String} url\n     */\n    toAbsoluteUrl: function (url) {\n        if (url.indexOf('http') !== 0 && url.charAt(0) !== '/') {\n            url = '/' + url;\n        }\n        return url;\n    },\n    /**\n     * @function\n     * @description Loads css dynamically from given urls\n     * @param {Array} urls Array of urls from which css will be dynamically loaded.\n     */\n    loadDynamicCss: function (urls) {\n        var i, len = urls.length;\n        for (i = 0; i < len; i++) {\n            this.loadedCssFiles.push(this.loadCssFile(urls[i]));\n        }\n    },\n\n    /**\n     * @function\n     * @description Loads css file dynamically from given url\n     * @param {String} url The url from which css file will be dynamically loaded.\n     */\n    loadCssFile: function (url) {\n        return $('<link/>').appendTo($('head')).attr({\n            type: 'text/css',\n            rel: 'stylesheet'\n        }).attr('href', url); // for i.e. <9, href must be added after link has been appended to head\n    },\n    // array to keep track of the dynamically loaded CSS files\n    loadedCssFiles: [],\n\n    /**\n     * @function\n     * @description Removes all css files which were dynamically loaded\n     */\n    clearDynamicCss: function () {\n        var i = this.loadedCssFiles.length;\n        while (0 > i--) {\n            $(this.loadedCssFiles[i]).remove();\n        }\n        this.loadedCssFiles = [];\n    },\n    /**\n     * @function\n     * @description Extracts all parameters from a given query string into an object\n     * @param {String} qs The query string from which the parameters will be extracted\n     */\n    getQueryStringParams: function (qs) {\n        if (!qs || qs.length === 0) { return {}; }\n        var params = {},\n            unescapedQS = unescape(qs);\n        // Use the String::replace method to iterate over each\n        // name-value pair in the string.\n        unescapedQS.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'),\n            function ($0, $1, $2, $3) {\n                params[$1] = $3;\n            }\n        );\n        return params;\n    },\n\n    fillAddressFields: function (address, $form) {\n        for (var field in address) {\n            if (field === 'UUID' || field === 'key') {\n                continue;\n            }\n            // if the key in address object ends with 'Code', remove that suffix\n            // keys that ends with 'Code' are postalCode, stateCode and countryCode\n            // update the state fields\n            if (field === 'countryCode') {\n            \t$form.find('[name$=\"country\"]').val(address['countryCode'].toUpperCase()).trigger('change');\n                // retrigger state selection after country has changed\n                // this results in duplication of the state code, but is a necessary evil\n                // for now because sometimes countryCode comes after stateCode\n                            \t\n            \tvar selectedStateValue = address['stateCode'];\n            \tif ($form.find('[name$=\"state\"] option[label=\"' + address['stateCode'] + '\"]').length > 0) {\n            \t\tselectedStateValue = $form.find('[name$=\"state\"] option[label=\"' + address['stateCode'] + '\"]').val();\n            \t}\n            \t\n            \t$form.find('[name$=\"state\"]').val(selectedStateValue);\n            } else if (field === 'stateCode') {\n\t\t\t\tvar selectedStateValue = address['stateCode'];\n            \tif ($form.find('[name$=\"state\"] option[label=\"' + address['stateCode'] + '\"]').length > 0) {\n            \t\tselectedStateValue = $form.find('[name$=\"state\"] option[label=\"' + address['stateCode'] + '\"]').val();\n            \t}\n            \t\n            \t$form.find('[name$=\"state\"]').val(selectedStateValue);\n            } else {\n            \tif (address[field] != null) {\n            \t\t$form.find('[name$=\"_' + field.replace('Code', '') + '\"]').val((''+address[field]).replace(/\\^/gi,\"'\"));\n            \t} else {\n            \t\t$form.find('[name$=\"_' + field.replace('Code', '') + '\"]').val(address[field]);\n            \t}\n            }\n        }\n    },\n    /**\n     * @function\n     * @description Updates the number of the remaining character\n     * based on the character limit in a text area\n     */\n    limitCharacters: function () {\n        $('form').find('textarea[data-character-limit]').each(function () {\n            var characterLimit = $(this).data('character-limit');\n            var charCountHtml = String.format(Resources.CHAR_LIMIT_MSG,\n                '<span class=\"char-remain-count\">' + characterLimit + '</span>',\n                '<span class=\"char-allowed-count\">' + characterLimit + '</span>');\n            var charCountContainer = $(this).next('div.char-count');\n            if (charCountContainer.length === 0) {\n                charCountContainer = $('<div class=\"char-count\"/>').insertAfter($(this));\n            }\n            charCountContainer.html(charCountHtml);\n            // trigger the keydown event so that any existing character data is calculated\n            $(this).change();\n        });\n    },\n    /**\n     * @function\n     * @description Binds the onclick-event to a delete button on a given container,\n     * which opens a confirmation box with a given message\n     * @param {String} container The name of element to which the function will be bind\n     * @param {String} message The message the will be shown upon a click\n     */\n    setDeleteConfirmation: function (container, message) {\n        $(container).on('click', '.delete', function () {\n            return window.confirm(message);\n        });\n    },\n    /**\n     * @function\n     * @description Scrolls a browser window to a given x point\n     * @param {String} The x coordinate\n     */\n    scrollBrowser: function (xLocation) {\n        $('html, body').animate({scrollTop: xLocation}, 500);\n    },\n    \n    isTouchDevice: function() {\n    \t//detect touch-ability (maxTouchPoints for windows surface)\n    \treturn ('ontouchstart' in window || navigator.msMaxTouchPoints || navigator.maxTouchPoints > 0);\n    },\n\n    isMobile: function () {\n        var mobileAgentHash = ['mobile', 'tablet', 'phone', 'ipad', 'ipod', 'android', 'blackberry', 'windows ce', 'opera mini', 'palm'];\n        var    idx = 0;\n        var isMobile = false;\n        var userAgent = (navigator.userAgent).toLowerCase();\n\n        while (mobileAgentHash[idx] && !isMobile) {\n            isMobile = (userAgent.indexOf(mobileAgentHash[idx]) >= 0);\n            idx++;\n        }\n        return isMobile;\n    },\n    \n    /**\n     * @function\n     * @description Validates e-mail address\n     * @param {String} E-mail address\n     * @returns {Boolean}\n     */\n    validateEmail: function (email) {\n        var re = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n        return re.test(email);\n    },\n\n    /**\n     * @function\n     * @description Helper method to encode inputs and prevent xss\n     * @param {String} input value\n     * @returns {String}\n     */\n    htmlEncode: function (value) { \n        if (value) {\n            return jQuery('<div/>').text(value).html(); \n        } else {\n            return '';\n        }\n    },\n    \n    /**\n     * Limits a text input to a defined length. \n     * @param (String) inputSelector - A jQuery selector for the input to limit.\n     * @param (Number) lengthLimit - The length to limit the input to.\n     * @return void\n     */\n    limitInputToLength: function (inputSelector, lengthLimit) {\n        $(inputSelector).on(\"keyup click\", function () {\n            if (this.value.length > lengthLimit) {\n                this.value = this.value.substring(0, lengthLimit);\n    \t\t}\n    \t});\n    },\n    \n    /**\n     * Detects the credit card type based off of the provided credit card number.\n     * @param (String) creditCardNumber - The credit card number to detect the type for.\n     * @return (String) - The type of credit card.\n     */\n    getCreditCardType: function (creditCardNumber) {\n        creditCardNumber = creditCardNumber.replace(/\\D/g, '');\n        \n        if (creditCardNumber.length >= 4) {\n\t        var creditCardTypes = [\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.Visa,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Visa,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^4[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.AmericanExpress,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.AmericanExpress,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^3[47][0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.Diners,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Discover,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^3(?:0[0-59]{1}|[689])[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.JCB,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.JCB,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^(?:2131|1800|35)[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.Mastercard,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Mastercard,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^(5[1-5])[0-9]{0,}$')\n\t        \t},\n\t\t\t\t{\n\t        \t\tPaymentCard: CreditCardConstants.MastercardSeries2,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Mastercard,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^(222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.Discover,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Discover,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.Maestro,\n\t        \t\tPaymentCardDisplayKey: CreditCardConstants.Mastercard,\n\t        \t\tPaymentMethod: PaymentMethodConstants.CreditCard,\n\t        \t\tPattern: new RegExp('^(5[06789]|6)[0-9]{0,}$')\n\t        \t},\n\t        \t{\n\t        \t\tPaymentCard: CreditCardConstants.BootBarnCredit,\n\t        \t\tPaymentCardDisplayKey: PaymentMethodConstants.AllianceData,\n\t        \t\tPaymentMethod: PaymentMethodConstants.AllianceData,\n\t        \t\tPattern: new RegExp('^7788[0-9]{0,}$')\n\t        \t}\n\t        ]\n\t        \n\t        for (var creditCardTypeKey in creditCardTypes) {\n\t        \tvar creditCardType = creditCardTypes[creditCardTypeKey];\n\t        \t\n\t        \tif (creditCardType.Pattern && creditCardNumber.match(creditCardType.Pattern)) {\n\t        \t\treturn creditCardType;\n\t        \t}\n\t        }\n        }\n\n        return false;\n    },\n    \n    /**\n     * Masks a provided number.\n     * @param (Number or String) number - The number to mask.\n     * @param (Number) lengthToShow - The length of the number to leave unmasked at end.\n     * @param (String) maskCharacter - The character to use for masking. Defaults to *.\n     * @return (String) - The type of credit card.\n     */\n    getMaskedNumber: function (number, lengthToShow, maskPattern) {\n    \tif (!number) {\n    \t\treturn '';\t\n    \t}\n    \t\n    \tlengthToShow = lengthToShow || 4;\n    \tmaskPattern = maskPattern || '*';\n       \t\n       \tvar numberMasked;\n    \tif (maskPattern.length > 1) {\n    \t\tnumberMasked = maskPattern;\n    \t} else if (maskPattern.length >= 1) {\n    \t\tnumberMasked = new Array(number.length + 1).join(maskPattern);\n    \t}\n            \n    \tnumber += '';\n    \tif (number != null && number != '') { \n    \t\tnumberMasked = numberMasked.substr(0, number.length - lengthToShow); \n    \t\tnumberMasked += number.substr(number.length - lengthToShow);\n    \t}\n        \n        return numberMasked;\n    },\n\n\tgetPreferenceValueFromWindowLocation: function (preferenceName) {\n\t\tvar hash = window.location.hash.substr(1),\n\t\t\tpreferenceValue = '',\n\t\t\thashTable = hash.split('&').reduce(function (hashTable, item) {\n\t\t\t\tvar parts = item.split('=');\n\t\t\t\thashTable[parts[0]] = decodeURIComponent(parts[1]).replace(/[\\+\\s]+/g, ' ');\n\t\t\t\treturn hashTable;\n\t\t\t}, {});\n\t\t\n\t\tfor (var i = 1; i <= 5; i++){\n\t\t\tif(!hashTable.hasOwnProperty('prefn' + i)){   \t\n\t\t\t\tbreak;\n\t\t\t} else if(hashTable['prefn' + i] == preferenceName){\n\t\t\t\tpreferenceValue = hashTable['prefv' + i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn preferenceValue;\n\t}\n};\n\nmodule.exports = util;\n","'use strict';\n\nvar naPhone = /^\\+?\\(?([0-9][0-8][0-9])\\)?[\\-\\. ]?([2-9][0-9]{2})[\\-\\. ]?([0-9]{4})(\\s*x[0-9]+)?$/;\nvar internationalNumber = /^(?:\\s*\\+)?[\\d\\s\\.\\-\\(\\)]+$/;\nvar defaultPostal = /^\\d{3,7}$/;\nvar regex = {\n    phone: {\n        us: naPhone,\n        ca: internationalNumber,\n        fr: internationalNumber,\n        it: internationalNumber,\n        jp: internationalNumber,\n        cn: /.*/,\n        gb: internationalNumber\n    },\n    postal: {\n        us: /^\\d{5}(-\\d{4})?$/,\n        ca: /^[ABCEGHJKLMNPRSTVXY]{1}\\d{1}[A-Z]{1} *\\d{1}[A-Z]{1}\\d{1}$/i,\n        fr: /^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$/,\n        it: /^([0-9]){5}$/,\n        jp: /^([0-9]){3}[-]([0-9]){4}$/,\n        cn: /^([0-9]){6}$/,\n        gb: /^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$/i\n    },\n    notCC: /^(?!(([0-9 -]){13,19})).*$/\n};\n// global form validator settings\nvar settings = {\n    errorClass: 'error',\n    errorElement: 'span',\n    onkeyup: false,\n    onfocusout: function (element) {\n        if (!this.checkable(element)) {\n            this.element(element);\n        }\n    },\n    errorPlacement: function (error, element) {\n    \terror.appendTo(element.parent());\n    }\n};\n/**\n * @function\n * @description Validates a given phone number against the countries phone regex\n * @param {String} value The phone number which will be validated\n * @param {String} el The input field\n */\nvar validatePhone = function (value, el) {\n    var country = $(el).closest('form').find('.country');\n    var countryValue;\n    if (country.length > 0) {\n        countryValue = country.val();\n    }\n\n    if (!countryValue || !regex.phone[country.val().toLowerCase()]) {\n        return true;\n    }\n\n    var rgx = regex.phone[country.val().toLowerCase()];\n    var isOptional = this.optional(el);\n    var isValid = rgx.test($.trim(value));\n\n    return isOptional || isValid;\n};\n\nvar validatePostal = function (value, el) {\n    var country = $(el).closest('form').find('.country');\n    var countryValue;\n    if (country.length > 0) {\n        countryValue = country.val();\n    }\n\n    if (!countryValue || !regex.postal[country.val().toLowerCase()]) {\n        return true;\n    }\n\n    var rgx = regex.postal[countryValue.toLowerCase()];\n    var isOptional = this.optional(el);\n    var isValid = rgx.test($.trim(value));\n\n    return isOptional || isValid;\n};\n/**\n * @function\n * @description Validates that a credit card owner is not a Credit card number\n * @param {String} value The owner field which will be validated\n * @param {String} el The input field\n */\nvar validateOwner = function (value) {\n    var isValid = regex.notCC.test($.trim(value));\n    return isValid;\n};\n\n/**\n * Add phone validation method to jQuery validation plugin.\n * Text fields must have 'phone' css class to be validated as phone\n */\n$.validator.addMethod('phone', validatePhone, Resources.INVALID_PHONE);\n$.validator.addMethod('postal', validatePostal, Resources.INVALID_ZIP);\n\n/**\n * Add CCOwner validation method to jQuery validation plugin.\n * Text fields must have 'owner' css class to be validated as not a credit card\n */\n$.validator.addMethod('owner', validateOwner, Resources.INVALID_OWNER);\n\n/**\n * Add gift cert amount validation method to jQuery validation plugin.\n * Text fields must have 'gift-cert-amont' css class to be validated\n */\n$.validator.addMethod('gift-cert-amount', function (value, el) {\n    var isOptional = this.optional(el);\n    var isValid = (!isNaN(value)) && (parseFloat(value) >= 5) && (parseFloat(value) <= 5000);\n    return isOptional || isValid;\n}, Resources.GIFT_CERT_AMOUNT_INVALID);\n\n/**\n * Add positive number validation method to jQuery validation plugin.\n * Text fields must have 'positivenumber' css class to be validated as positivenumber\n */\n$.validator.addMethod('positivenumber', function (value) {\n    if ($.trim(value).length === 0) { return true; }\n    return (!isNaN(value) && Number(value) >= 0);\n}, Resources.VALIDATE_NUMBER);\n\n/**\n * Add method to check for email extension when validating emails,\n * since default settings don't require an extension\n */\n$.validator.addMethod(\"requireEmailExtension\", function(value, element) {\n    if ($.trim(value).length === 0) { return true; }\n    return /^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$/.test(value);\n}, Resources.VALIDATE_EMAIL);\n\n/*\n * Lets you say \"at least X inputs that match selector Y must be filled.\"\n *\n * The end result is that neither of these inputs:\n *\n *  <input class=\"productinfo\" name=\"partnumber\">\n *  <input class=\"productinfo\" name=\"description\">\n *\n *  ...will validate unless at least one of them is filled.\n *\n * partnumber:  {require_from_group: [1,\".productinfo\"]},\n * description: {require_from_group: [1,\".productinfo\"]}\n *\n * options[0]: number of fields that must be filled in the group\n * options[1]: CSS selector that defines the group of conditionally required fields\n */\n$.validator.addMethod( \"require_from_group\", function( value, element, options ) {\n    var $fields = $(options[1], element.form);\n    var $fieldsFirst = $fields.eq(0);\n    var validator = $fieldsFirst.data(\"valid_req_grp\") ? $fieldsFirst.data(\"valid_req_grp\") : $.extend({}, this);\n    var isValid = $fields.filter(function() {\n        return validator.elementValue(this);\n    }).length >= options[0];\n\n    // Store the cloned validator for future validation\n    $fieldsFirst.data(\"valid_req_grp\", validator);\n\n    // If element isn't being validated, run each require_from_group field's validation rules\n    if (!$(element).data(\"being_validated\")) {\n        $fields.data(\"being_validated\", true);\n        $fields.each(function() {\n            validator.element(this);\n        });\n        $fields.data(\"being_validated\", false);\n    }\n    return isValid;\n}, $.validator.format(\"Please fill at least {0} of these fields.\"));\n\n$.extend($.validator.messages, {\n    required: Resources.VALIDATE_REQUIRED,\n    remote: Resources.VALIDATE_REMOTE,\n    email: Resources.VALIDATE_EMAIL,\n    url: Resources.VALIDATE_URL,\n    date: Resources.VALIDATE_DATE,\n    dateISO: Resources.VALIDATE_DATEISO,\n    number: Resources.VALIDATE_NUMBER,\n    digits: Resources.VALIDATE_DIGITS,\n    creditcard: Resources.VALIDATE_CREDITCARD,\n    equalTo: Resources.VALIDATE_EQUALTO,\n    maxlength: $.validator.format(Resources.VALIDATE_MAXLENGTH),\n    minlength: $.validator.format(Resources.VALIDATE_MINLENGTH),\n    rangelength: $.validator.format(Resources.VALIDATE_RANGELENGTH),\n    range: $.validator.format(Resources.VALIDATE_RANGE),\n    max: $.validator.format(Resources.VALIDATE_MAX),\n    min: $.validator.format(Resources.VALIDATE_MIN)\n});\n\nvar validator = {\n    regex: regex,\n    settings: settings,\n    init: function () {\n        var self = this;\n        $('form:not(.suppress)').each(function () {\n            $(this).validate(self.settings);\n        });\n    },\n    initForm: function (f) {\n        $(f).validate(this.settings);\n    }\n};\n\nmodule.exports = validator;\n","/* \n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n * watermark.js - Create watermarked images with Canvas and JS\n *\n * Version: 1 (2011-04-04)\n * Copyright (c) 2011\tPatrick Wied ( http://www.patrick-wied.at )\n * This code is licensed under the terms of the MIT LICENSE\n *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n */\n\nmodule.exports = function(w){\n\tvar w = window;\n\tvar wm = (function(w){\n\t\tvar doc = w.document,\n\t\tgcanvas = {},\n\t\tgctx = {},\n\t\timgQueue = [],\n\t\tclassNames = [\"watermark\"],\n\t\twatermark = false,\n\t\twatermarkPosition = \"bottom-right\",\n\t\twatermarkPath = \"watermark.png?\"+(+(new Date())),\n\t\topacity = (255/(100/50)), // 50%\n\t\tinitCanvas = function(){\n\t\t\tgcanvas = doc.createElement(\"canvas\");\n\t\t\tgcanvas.style.cssText = \"display:none;\";\n\t\t\tgctx = gcanvas.getContext(\"2d\");\n\t\t\tdoc.body.appendChild(gcanvas);\n\t\t},\n\t\tinitWatermark = function(){\n\t\t\twatermark = new Image();\n\t\t\twatermark.src = \"\";\n\t\t\twatermark.src = watermarkPath;\n\t\t\t\n\t\t\tif(opacity != 255){\n\t\t\t\tif(!watermark.complete)\n\t\t\t\t\twatermark.onload = function(){\t\n\t\t\t\t\t\tapplyTransparency();\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tapplyTransparency();\n\t\t\t\t\n\n\t\t\t}else{\n\t\t\t\tapplyWatermarks();\n\t\t\t}\n\t\t\t\n\t\t},\n\t\t// function for applying transparency to the watermark\n\t\tapplyTransparency = function(){\n\t\t\tvar w = watermark.width || watermark.offsetWidth,\n\t\t\th = watermark.height || watermark.offsetHeight;\n\t\t\tsetCanvasSize(w, h);\n\t\t\tgctx.drawImage(watermark, 0, 0);\n\t\t\t\t\t\n\t\t\tvar image = gctx.getImageData(0, 0, w, h);\n\t\t\tvar imageData = image.data,\n\t\t\tlength = imageData.length;\n\t\t\tfor(var i=3; i < length; i+=4){  \n\t\t\t\timageData[i] = (imageData[i]<opacity)?imageData[i]:opacity;\n\t\t\t}\n\t\t\timage.data = imageData;\n\t\t\tgctx.putImageData(image, 0, 0);\n\t\t\twatermark.onload = null;\n\t\t\twatermark.src = \"\";\n\t\t\twatermark.src = gcanvas.toDataURL();\n\t\t\t// assign img attributes to the transparent watermark\n\t\t\t// because browsers recalculation doesn't work as fast as needed\n\t\t\twatermark.width = w;\n\t\t\twatermark.height = h;\n\n\t\t\tapplyWatermarks();\n\t\t},\n\t\tconfigure = function(config){\n\t\t\tif(config[\"watermark\"])\n\t\t\t\twatermark = config[\"watermark\"];\n\t\t\tif(config[\"path\"])\n\t\t\t\twatermarkPath = config[\"path\"];\n\t\t\tif(config[\"position\"])\n\t\t\t\twatermarkPosition = config[\"position\"];\n\t\t\tif(config[\"opacity\"])\n\t\t\t\topacity = (255/(100/config[\"opacity\"]));\n\t\t\tif(config[\"classNames\"])\n\t\t\t\tclassNames = config[\"classNames\"];\n\t\t\t\n\t\t\tinitCanvas();\n\t\t\tinitWatermark();\n\t\t}\n\t\tsetCanvasSize = function(w, h){\n\t\t\tgcanvas.width = w;\n\t\t\tgcanvas.height = h;\n\t\t},\n\t\tapplyWatermark = function(img){\n\t\t\tgcanvas.width = img.naturalWidth || img.width || img.offsetWidth;\n\t\t\tgcanvas.height = img.naturalHeight || img.height || img.offsetHeight;\n\t\t\tgctx.drawImage(img, 0, 0);\n\t\t\tvar position = watermarkPosition,\n\t\t\tx = 0,\n\t\t\ty = 0;\n\t\t\tif(position.indexOf(\"top\")!=-1)\n\t\t\t\ty = 10;\n\t\t\telse if(position.indexOf(\"middle\")!=-1)\n\t\t\t\ty = (gcanvas.height-watermark.height) / 2;\n\t\t\telse\n\t\t\t\ty = gcanvas.height-watermark.height-10;\n\t\t\t\n\t\t\tif(position.indexOf(\"left\")!=-1)\n\t\t\t\tx = 10;\n\t\t\telse if(position.indexOf(\"center\")!=-1)\n\t\t\t\tx = (gcanvas.width-watermark.width) / 2;\n\t\t\telse\n\t\t\t\tx = gcanvas.width-watermark.width-10;\n\n\n\t\t\tgctx.drawImage(watermark, x, y);\n\t\t\timg.onload = null;\n\t\n\t\t\timg.src = gcanvas.toDataURL();\n\n\t\t},\n\t\tapplyWatermarks = function(){\n\t\t\tsetTimeout(function(){\n\t\t\t\tfor(var i = 0; i < classNames.length; i++){\n\t\t\t\t\tvar els = doc.getElementsByClassName(classNames[i]),\n\t\t\t\t\tlen = els.length;\n\t\t\t\t\twhile(len--){\n\t\t\t\t\t\tvar img = els[len];\n\t\t\t\t\t\tif(img.tagName.toUpperCase() != \"IMG\" || (img.tagName.toUpperCase() == \"IMG\" && img.getAttribute('src').indexOf('data:image/png') > -1) || img.naturalWidth == 0)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!img.complete){\n\t\t\t\t\t\t\timg.onload = function(){\n\t\t\t\t\t\t\t\tapplyWatermark(this);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tapplyWatermark(img);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},10);\n\t\t};\n\t\t\n\t\t\n\t\treturn {\n\t\t\tinit: function(config){\n\t\t\t\tconfigure(config);\n\t\t\t}\n\t\t};\n\t})(w);\n\tw.wmark = wm;\n};","'use strict';\n\nvar dialog = require('./dialog');\nvar progress = require('./progress');\nvar loginDialog = require('./loginDialog');\n\n/* -------------------------\n * WISHLIST\n * -------------------------\n */\n\nfunction errorHandling(data, dialogTitle, dialogHtml) {\n    if (data && typeof data === 'object' && 'message' in data) {\n        console.log(data.message);\n    }\n    dialog.open({\n        html: dialogHtml,\n        options: {\n            title: dialogTitle,\n            draggable: false,\n            open: function(event, ui) {                                    \n                $('body').addClass('dialog-open');\n            },\n            close: function(event, ui) {\n                $('body').removeClass('dialog-open');\n            }\n        }\n    });\n}\n\nfunction updateCSRFToken() {\n\tif (pageContext && pageContext.options) {\n\t\t$.ajax({\n\t\t\tmethod: 'get',\n\t\t\turl: Urls.CSRFToken.Get,\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(response) {\n\t\t\t\tpageContext.options.Token = response.token;\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction checkWishlistForItem(wishlistItemId) {\n    if ('localStorage' in window && window['localStorage'] !== null && 'WishlistProductIDs' in window.localStorage && window.localStorage.WishlistProductIDs.length > 0) {\n        var wishlistItems = JSON.parse(window.localStorage.WishlistProductIDs);\n        var pageType = pageContext && 'type' in pageContext && pageContext.type ? pageContext.type : $('#wrapper').attr('class');\n        var isWishlistItem = wishlistItems.filter(function(productObject) {\n            if (productObject.productID == wishlistItemId) { return true }\n            // If this is NOT a PDP, then we need to run additional checks to see if Master Product or any of the Variations are in the wishlist\n            if (pageType != 'product') {\n                if (productObject.masterID == wishlistItemId) { return true }\n                if (productObject.variants.indexOf(wishlistItemId) > -1) { return true }\n            }\n        });\n        return isWishlistItem.length > 0;\n    } else {\n        return false;\n    }\n}\n\nfunction modifyWishlistInStorage(data) {\n    if ('localStorage' in window && window['localStorage'] !== null) {\n        if (!window.localStorage.WishlistProductIDs) {\n            window.localStorage.WishlistProductIDs = '[]';\n        }\n        var item = 'productData' in data && data.productData.productID ? data.productData.productID : null;\n        var isDataAction = data.action;\n        var wishlistItems = JSON.parse(window.localStorage.WishlistProductIDs);\n\n        if (item && isDataAction) {\n            if (isDataAction == 'wishlistItemAdded') {\n                wishlistItems.push(data.productData);\n                window.localStorage.WishlistProductIDs = JSON.stringify(wishlistItems);\n            }\n            if (isDataAction == 'wishlistItemRemoved' && wishlistItems.length > 0) {\n                var modifiedWishlist = wishlistItems.filter(function(productObject) {\n                    if (productObject.productID != item) { return true }\n                });\n                window.localStorage.WishlistProductIDs = JSON.stringify(modifiedWishlist);\n            }\n        }\n    }\n}\n\nfunction addWishlistEvent(event, productID) {\n\tvar eventType = \"wishlist_\" + event;\n\tvar url, image;\n\tvar images = [];\n\t\n\tvar thisTile = $('.product-tile[data-itemid=\"'+productID+'\"]');\n\tvar thisItem = JSON.parse($('.productCardMetadata.event-browse[data-pid=\"'+productID+'\"]').attr('data-product-gtm-json'));\n\tif (thisTile.length > 0) {\n\t\turl = thisTile.find('.thumb-link').attr('href');\n\t\timage = thisTile.find('.thumb-link img').attr('src');\n\t\timages.push(image);\n\t} else {\n\t\tvar selectedSizeOption = $('div.product-variations .size.size-options li.selected .swatchanchor');\n\t\tvar selectedSizeUrl = selectedSizeOption.attr('href').replace('Product-Variation', 'Product-Show');\n\t\tvar selectedSizeValue = selectedSizeOption.attr('data-size-id').replace(/ /g, '%20');\n\t\turl = selectedSizeUrl.replace(\"_size=\", \"_size=\"+selectedSizeValue);\n\t\t$('.product-primary-image [class*=\"-slide\"]').not('.slick-cloned').each(function (index) {\n\t\t\tif(index > -1) {\n\t\t\t\tvar image = $(this).find('a').attr('href');\n\t\t\t\tif (!image || image == undefined || image == null) {\n\t\t\t\t\timage = $(this).find('img').attr('src');\n\t\t\t\t}\n\t\t\t\tif (images.indexOf(image) === -1) {\n\t\t\t\t\timages.push(image);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t\n\tvar properties = {\n\t\t\"productID\": thisItem[\"id\"],\n\t\t\"productName\": thisItem[\"name\"].replace(/\\\\/g, \"\"),\n\t\t\"category\": thisItem[\"category\"].replace(/\\\\/g, \"\"),\n\t\t\"price\": thisItem[\"price\"],\n\t\t\"images\": images,\n\t\t\"url\": url,\n\t\t\"attr\": {\n\t\t\t\"manufacturer\": thisItem[\"brand\"]\n\t\t},\n\t};\n\n\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\tcrdl('event', eventType, properties); \n\t}\t\n}\n\nfunction prepareWishlistAddUI(buttons, wishlistItemId, sizeText) {\n    if (!buttons) {\n        return;\n    } else {\n        buttons.each(function(idx, element) {\n            var $button = $(element);\n            var addUrl = Urls.wishlistAdd + '?pid=' + $button.attr('data-pid');\n            $button.removeClass('wishlist-item-added').addClass('wishlist-item-ready');\n            $button.css('display', 'inline-block');\n            $button.attr('data-url', addUrl);\n            $button.attr('data-action', 'AddInternal');\n            $button.attr('title', ($button.attr('data-title-add') + ' - ' + sizeText));\n            if ($button.attr('id') == 'wishlist-button') {\n                $button.find('span').html($button.attr('data-add-message'));\n            }\n        });\n    }\n    \n    if ($('.pt_wish-list').length > 0 && (wishlistItemId)) {\n        if ('localStorage' in window && window['localStorage'] !== null && 'WishlistProductIDs' in window.localStorage && window.localStorage.WishlistProductIDs.length > 0) {\n            var wishlistItems = JSON.parse(window.localStorage.WishlistProductIDs);\n            var variationModel = wishlistItems.filter(function(productObject) {\n                if (productObject.productID == wishlistItemId || productObject.masterID == wishlistItemId || productObject.variants.indexOf(wishlistItemId) > -1) { \n                    return productObject;\n                }\n            });\n            if (variationModel.length) {\n                var wishlistItemsToRemove = variationModel[0];\n                for (var key in wishlistItemsToRemove) {\n                    var value = wishlistItemsToRemove[key];\n                    // If matching variant or master\n                    if (key == 'productID' || key == 'masterID') {\n                        $('.product-tile[data-itemid=\"'+value+'\"]').parents('li.wishlist-item').remove();\n                    // Else, check the other variants\n                    } else {\n                        var variants = value.split(',');\n                        var i = 0;\n                        while (i < variants.length) {\n                            var variantID = variants[i];\n                            $('.product-tile[data-itemid=\"'+variantID+'\"]').parents('li.wishlist-item').remove();\n                            i++;\n                        }\n                    }\n                }\n                // If user removes all shareable products from wishlist, then hide the share toggle and set the wishlist to private\n                if ($('li.wishlist-item[data-shareable-item=\"true\"]').length < 1) {\n                    $('.wishlist-share-container').hide();\n                    $('.share-wishlist-toggle input[name=\"share-wishlist-checkbox\"]').prop('checked', false).trigger('change');\n                }\n                if ($('li.wishlist-item').length < 1) {\n                    $('.wishlist-message.empty-wishlist').removeClass('d-none');\n                }\n            }\n        }\n    }\n}\n\nfunction prepareWishlistRemoveUI(buttons, sizeText) {\n    if (!buttons) {\n        return;\n    } else {\n        buttons.each(function(idx, element) {\n            var $button = $(element);\n            var removeUrl = Urls.wishlistRemove + '?pid=' + $button.attr('data-pid');\n            $button.removeClass('wishlist-item-ready').addClass('wishlist-item-added');\n            $button.css('display', 'inline-block');\n            $button.attr('data-url', removeUrl);\n            $button.attr('data-action', 'RemoveInternal');\n            $button.attr('title', ($button.attr('data-title-remove') + ' - ' + sizeText));\n            if ($button.attr('id') == 'wishlist-button') {\n                $button.find('span').html($button.attr('data-remove-message'));\n            }\n        });\n    }\n}\n\nfunction renderAllWishlistButtons() {\n    $('.wishlist-item-status-button').each(function() {\n        var $button = $(this);\n        var wishlistItemId = $button.attr('data-pid');\n        if (wishlistItemId && wishlistItemId != '') {\n            var isWishlistItem = checkWishlistForItem(wishlistItemId);\n            if (isWishlistItem) { \n                prepareWishlistRemoveUI($button);\n            } else {\n                prepareWishlistAddUI($button, wishlistItemId);\n            }\n        }\n    });\n}\n\nfunction validateEmailForm($email, $message) {\t\n    $('.share-wishlist-menu-popup .error-container').addClass('d-none');\n\n    var regexEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/g;\t\n    var regexMessage = /^[A-Za-z0-9 _.,!\"'\\/()$]*/g;\n    var email = $email.val().trim();\n    var message = $message.val().trim();\n\tvar formValidation = true;\n\t\t\t\n\tif ((!email || email.length == 0) || String(email).match(regexEmail) == null) {\n\t\tformValidation = false;\n        $email.addClass('error');\n\t    $('#share-wishlist-email-popup .invalid-email-format').removeClass('d-none');\n\t}\n    if ((!message || message.length == 0) || String(message).match(regexMessage) == null) {\n        formValidation = false;\n        $message.addClass('error');\n        $('#share-wishlist-email-popup .invalid-email-message-format').removeClass('d-none');\n    }\n\t\t\t\n\tif (!formValidation) {\n        return false;\n    } else {\n        return true;\n    }\n}\n\nfunction init () {\n    $(document).ready(function() {\n\n        updateCSRFToken();\n\n        /**\n         * On page load, make AJAX call to get wishlist items and store in localStorage. From localStorage, compare the items being loaded on \n         * page to see if any are in wishlist, and mark the heart icons accordingly. \n         */\n        if ('localStorage' in window && window['localStorage'] !== null) {\n            // Only make AJAX call to get wishlist product IDs if customer is logged in\n            if (Customer.authenticated) {\n                $.ajax({\n                    type: 'GET',\n                    url: Urls.wishlistGetItems,\n                    contentType: 'application/json',\n                    error: function(jqXHR, textStatus, errorThrown) {\n                        $('.wishlist-item-status-button').css('display', 'inline-block');\n                        window.localStorage.WishlistProductIDs = '';\n                    },\n                    success: function(response) {\n                        if (response) {\n                            if (typeof response === 'object' && 'wishlist' in response) {\n                                window.localStorage.WishlistProductIDs = JSON.stringify(response.wishlist);\n                                renderAllWishlistButtons();\n                            } else {\n                                $('.wishlist-item-status-button').css('display', 'inline-block');\n                                window.localStorage.WishlistProductIDs = '';\n                            }\n                        }\n                    }\n                });   \n            // If guest user, just render the wishlist buttons as empty\n            } else {\n                window.localStorage.WishlistProductIDs = '';\n                renderAllWishlistButtons();\n            }\n        }\n\n        /**\n         * On click of a wishlist heart button, open a login dialog (if guest user) or add/remove item from wishlist (if logged-in customer)\n         */\n        $('body').on('click', '.wishlist-item-status-button, .wishlist-button', function(event) {\n            event.preventDefault();\n            var $button = $(this);\n            var wishlistUrl = $button.attr('data-url');\n            var wishlistController = $button.attr('data-controller');\n            var wishlistAction = $button.attr('data-action');\n            var productID = $button.attr('data-pid');\n\n            var isProductPage = $('.pt_product-details').length;\n            var continueWishlist = true;\n\n            if (isProductPage) {\n                var sizeSelected = $('div.product-variations .size.size-options li.selected');\n\t\t\t\tvar lengthSelected = $('div.product-variations .length.length-options li.selected').length;\n\t\t\t\tvar widthSelected = $('div.product-variations .width.width-options li.selected').length;\n\t\t\t\tvar isSizeSelected = sizeSelected.length || (lengthSelected && widthSelected);\n\t\t\t\tvar isColorSelected = $('div.product-variations .color.color-options li.selected').length;\n                if (!isSizeSelected) {\n                    alert('Please select a size');\n                    continueWishlist = false;\n                }\n            }\n            \n            if (continueWishlist) {\n            \t//Cordial wishlist add/remove events\n            \tif ($button.hasClass('wishlist-item-added')) {\n    \t\t\t\taddWishlistEvent('remove', productID);\n    \t\t\t} else {\n    \t\t\t\taddWishlistEvent('add', productID);\n    \t\t\t}\n            \t\n                // WISHLIST REPORTING: Track wishlist-item-status-button clicks (both guest and logged-in users)\n                $.ajax({\n                    type: 'POST',\n                    url: Urls.wishlistTrackActions,\n                    contentType: 'application/json',\n                    data: JSON.stringify({\n                        action: wishlistAction,\n                        pid: productID\n                    }),\n                    error: function(jqXHR, textStatus, errorThrown) {\n                        console.log('Wishlist-TrackActions: Error in incrementing wishlist action counters. ERROR TEXT: '+textStatus+', ERROR THROWN: '+errorThrown+'.');\n                    },\n                    success: function(response) {\n                        if (response) {}\n                    }\n                });\n\n                // If guest user, open a login dialog\n                if (!Customer.authenticated) {\n                    var params = wishlistUrl.substring(wishlistUrl.indexOf('?'), wishlistUrl.length);\n                    loginDialog.show(function() {\n                        // For reporting\n                        $('.login-dialog-forms-container [data-login-source]').attr('data-login-source', 'wishlist-modal'); \n                        $('.login-dialog-forms-container [data-passwordless-login-source]').attr('data-passwordless-login-source', 'wishlist-modal');\n                    }, wishlistController, wishlistAction, productID, params, wishlistUrl);\n                // Else, if logged-in user, allow customer to add/remove wishlist item\n                } else {\n                    $.ajax({\n                        type: 'GET',\n                        url: wishlistUrl,\n                        contentType: 'application/json',\n                        error: function(jqXHR, textStatus, errorThrown) {\n                            errorHandling(errorThrown, 'Wishlist - Error', '<p style=\"padding: 10px;\">There was a problem handling your request. Please try again later.</p>');\n                        },\n                        success: function(response) {\n                            if (response && response.result && response.result == 'success' && response.action) {\n                                modifyWishlistInStorage(response);\n                                if (response.action == 'wishlistItemRemoved') {\n                                    var productIdRemoved = response && response.formattedData && response.formattedData.productID ? response.formattedData.productID : null;\n                                    prepareWishlistAddUI($button, productIdRemoved);\n                                } else {\n                                    prepareWishlistRemoveUI($button);\n                                }\n                            } else {\n                                var dialogHtml = '<p style=\"padding: 10px;\">Unable to modify wishlist at this time. Please try again later.</p>';\n                                if (response && response.action) {\n                                    if (response.action == 'wishlistItemRemoved') {\n                                        dialogHtml = '<p style=\"padding: 10px;\">Unable to remove item from wishlist. Please try again later.</p>';\n                                    } else {\n                                        dialogHtml = '<p style=\"padding: 10px;\">Unable to add item to wishlist. Please try again later.</p>';\n                                    }\n                                }\n                                errorHandling(null, 'Wishlist - Error', dialogHtml);\n                            }\n                        }\n                    });\n                }\n            }\n        });\n\n        /**\n         * Add product to customer's cart when \"Add to Cart\" button is clicked on Wishlist page\n         */\n        $('body').on('click', '.wishlist-add-to-cart-button', function() {\n            var $button = $(this);\n            var productId = $button.attr('data-pid');\n            $button.find('span').html('');\n            progress.show($button.find('span'), true);\n\n            $.ajax({\n                type: 'POST',\n                url: Urls.addProduct,\n                data: {\n                     pid: productId,\n                     csrf_token: pageContext.options.Token\n                },\n                error: function(jqXHR, textStatus, errorThrown) {\n                    progress.hide();\n                    $button.find('span').html('Add to Cart');\n                    errorHandling(errorThrown, 'Wishlist - Error', '<p style=\"padding: 10px;\">Unable to add item to cart. Please try again later.</p>');\n                },\n                success: function(response) {\n                    var $miniCartElm = $('.mini-cart .minicart-quantity').length > 0 ? $('.mini-cart .minicart-quantity') : $('.mini-cart .btn-minicart .btn-minicart-qty');\n                    var miniCartTotal;\n                    if ($miniCartElm.length > 0) {\n                        miniCartTotal = parseInt($miniCartElm.html().trim());\n                    }  \n                    miniCartTotal++;                  \n                    $miniCartElm.html(miniCartTotal);\n                    $button.attr('disabled', true).addClass('disabled');\n                    $button.find('span').html('<i class=\"fa fa-check\" aria-hidden=\"true\"></i> Item Added');\n\n                    // Only fire this AJAX call if the customer successfully added the product to their cart. On error of addProduct, do nothing.\n                    if (Customer.authenticated) {\n                        // WISHLIST REPORTING: Track 'Add to Cart' clicks from wishlist page\n                        $.ajax({\n                            type: 'GET',\n                            url: Urls.wishlistTrackAddToCart,\n                            contentType: 'application/json',\n                            error: function(jqXHR, textStatus, errorThrown) {\n                                console.log('Wishlist-TrackAddToCart: Error in incrementing wishlist Add-to-Cart counter. ERROR TEXT: '+textStatus+', ERROR THROWN: '+errorThrown+'.');\n                            },\n                            success: function(response) {\n                                if (response) {}\n                            }\n                        });\n                    }\n                }\n            });\n            \n            if (SitePreferences.CORDIAL_ENABLED) {\n            \tvar thisItem = $('.product-tile[data-itemid=\"'+productId+'\"]');\n            \tvar itemMeta = JSON.parse($('.productCardMetadata.event-browse[data-pid=\"'+productId+'\"]').attr('data-product-gtm-json'));\n\t\t\t\tvar cart_data = [{\n\t\t\t\t    'productID': itemMeta[\"id\"],\n\t\t\t\t    'sku': itemMeta[\"skuid\"],\n\t\t\t\t    'category': itemMeta[\"category\"].replace(/\\\\/g, \"\"),\n\t\t\t\t    'name': itemMeta[\"name\"].replace(/\\\\/g, \"\"),\n\t\t\t\t    'qty': '1', \n\t\t\t\t    'itemPrice': itemMeta[\"price\"],\n\t\t\t\t    'image': thisItem.find('.tile-image').attr('src'),\n\t\t\t\t    'url': thisItem.find('.thumb-link').attr('href'),\n\t\t\t\t    'attr': {\n\t\t\t\t        'manufacturer': itemMeta[\"brand\"],\n\t\t\t\t    \t'color': thisItem.find('.product-color').text().replace('Color: ',\"\"),\n\t\t\t\t        'size': thisItem.find('.product-size').text().replace('Size: ',\"\")\n\t\t\t\t    }\n\t\t\t\t}];\n\n\t\t\t\tif (typeof crdl !== 'undefined' && typeof crdl === 'function') {\n\t\t\t\t\tcrdl([\n\t\t\t\t\t\t['cart', 'update'],\n\t\t\t\t\t\t['cartitem', 'add' , cart_data], \n\t\t\t\t\t\t['event', 'cart']\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t}\n        });\n\n        $('body').on('click', '#mobile-share-wishlist-button', function() {\n            $('.wishlist-share-mobile-container').slideToggle('slow');\n        });\n        $('body').on('change', '.share-wishlist-toggle input[name=\"share-wishlist-checkbox\"]', function() {\n            var status = $(this).is(':checked');\n            if (status) {\n                $('#share-wishlist-menu').slideDown('slow').css('display','flex');\n            } else {\n                $('#share-wishlist-menu').slideUp('slow').removeClass('show-share-wishlist-menu').css('display','none');\n            }\n            if (Customer.authenticated) {\n                var wishlistID = $('input[name=\"current_wishlist_id\"]').val().trim();\n                if (wishlistID) {\n                    $.ajax({\n                        method: 'GET',\n                        url: Urls.wishlistSetPublic,\n                        data: {\n                            WishlistID: wishlistID,\n                            SetPublic: status\n                        }\n                    }).done(function(response) {\n                        if (response.result == 'error') {\n                            errorHandling(null, '', 'Wishlist Share - Error', '<p style=\"padding: 10px;\">Oops, something went wrong and cannot update your Wishlist at this time. Please try again later.</p>');\n                        } else if (response.result == 'success') {\n                            // No on-screen visuals need to occur\n                        }\n                    });\n                } else {\n                    errorHandling(null, '', 'Wishlist Share - Error', '<p style=\"padding: 10px;\">Oops, something went wrong and we could not retrieve your Wishlist. Please try again later.</p>');\n                }\n            } else {\n                window.location.href = Urls.account;\n            }\n        });\n        $('body').on('click', '.share-wishlist-menu-popup .close-button', function() {\n            var $this = $(this);\n            $this.parents('.share-wishlist-menu-popup').addClass('d-none');\n            var shareLink = $this.parents('.share-wishlist-menu-popup').attr('id').indexOf('link-popup') > -1;\n            if (shareLink) {\n                $this.siblings('.form-row-button').find('button[name=\"share-wishlist-link-copy\"]').removeClass('btn-complete disabled').html('Copy');\n            }\n        });\n        $('body').on('click', 'button[name=\"share-wishlist-link-copy\"]:not(.disabled)', function() {\n            var $button = $(this);\n            var wishlistUrl = $('#share-wishlist-link-popup .share-wishlist-url a').html();\n            navigator.clipboard.writeText(wishlistUrl);\n            $button.addClass('btn-complete disabled').html('<i class=\"fa fa-check\" aria-hidden=\"true\"></i> Copied!');\n        });\n        $('body').on('click', 'button[name=\"share-wishlist-email-send\"]:not(.disabled)', function() {\n            var $this = $(this);\n            var $email = $('#wishlist-share-email-input');\n            var $message = $('#wishlist-share-email-message');\n            var isValidEmailForm = validateEmailForm($email, $message);\n            if (isValidEmailForm) {\n                if (Customer.authenticated) {\n                    var wishlistID = $('input[name=\"current_wishlist_id\"]').val().trim();\n                    if (wishlistID) {\n                        $.ajax({\n                            method: 'POST',\n                            url: Urls.wishlistShareByEmail,\n                            data: {\n                                WishlistID: wishlistID,\n                                ToEmail: $email.val(),\n                                EmailMessage: $message.val()\n                            }\n                        }).done(function(response) {\n                            if (response.result == 'error') {\n                                errorHandling(null, '', 'Wishlist Share - Error', '<p style=\"padding: 10px;\">Oops, something went wrong and could not send your Wishlist email. Please try again later.</p>');\n                            } else if (response.result == 'success') {\n                                $this.parents('#share-wishlist-email-popup').addClass('share-wishlist-email-success');\n                            }\n                        });\n                    } else {\n                        errorHandling(null, '', 'Wishlist Share - Error', '<p style=\"padding: 10px;\">Oops, something went wrong and we could not retrieve your Wishlist for sharing. Please try again later.</p>');\n                    }\n                } else {\n                    window.location.href = Urls.account;\n                }\n            }\n        });\n        $('body').on('click', '#share-wishlist-menu .btn-open', function() {\n            var $button = $(this);\n            var $sharePopup = $button.siblings('.share-wishlist-menu-popup');\n            if ($sharePopup.length) {\n                $sharePopup.removeClass('d-none share-wishlist-email-success');\n            }\n        });\n    });\n}\n\nexports.checkWishlistForItem = checkWishlistForItem;\nexports.prepareWishlistAddUI = prepareWishlistAddUI;\nexports.prepareWishlistRemoveUI = prepareWishlistRemoveUI;\nexports.renderAllWishlistButtons = renderAllWishlistButtons;\nexports.init = init;","'use strict';\n\nexports.SlickSlider = {\n\tOptions: {\n\t\tSingle: {\n\t\t\taccessibility:  true,\n\t\t\tinfinite: \t\ttrue,\n\t\t\tdots: \t\t\tfalse,\n\t\t\tarrows: \t\tfalse,\n\t\t\tslidesToShow: \t1,\n\t\t\tslidesToScroll: 1,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767,\n\t\t\t\t\tsettings: \t{\n\t\t\t\t\t\tdots: true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tThumbnail: {\n\t\t\taccessibility:  true,\n\t\t\tdraggable: true,\n\t\t\tinfinite: false,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: false,\n\t\t\tslidesToShow: 7,\n\t\t\tslidesToScroll: 7\n\t\t},\n\t\tCategoryLanding: {\n\t\t\taccessibility:  true,\n\t\t\tdraggable: true,\n\t\t\tinfinite: true,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: true,\n\t\t\tslidesToShow: 4,\n\t\t\tslidesToScroll: 4,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200,\n\t\t\t\t\tsettings: {\n\t\t\t\t\t\tslidesToShow: 3,\n\t\t\t\t\t\tslidesToScroll: 3\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t}\n}","module.exports={\"NY\":{\"005\":true,\"063\":true,\"100\":true,\"101\":true,\"102\":true,\"103\":true,\"104\":true,\"105\":true,\"106\":true,\"107\":true,\"108\":true,\"109\":true,\"110\":true,\"111\":true,\"112\":true,\"113\":true,\"114\":true,\"115\":true,\"116\":true,\"117\":true,\"118\":true,\"119\":true,\"120\":true,\"121\":true,\"122\":true,\"123\":true,\"124\":true,\"125\":true,\"126\":true,\"127\":true,\"128\":true,\"129\":true,\"130\":true,\"131\":true,\"132\":true,\"133\":true,\"134\":true,\"135\":true,\"136\":true,\"137\":true,\"138\":true,\"139\":true,\"140\":true,\"141\":true,\"142\":true,\"143\":true,\"144\":true,\"145\":true,\"146\":true,\"147\":true,\"148\":true,\"149\":true},\"PR\":{\"006\":true,\"007\":true,\"008\":true,\"009\":true},\"VI\":{\"006\":true,\"007\":true,\"008\":true,\"009\":true},\"MA\":{\"010\":true,\"011\":true,\"012\":true,\"013\":true,\"014\":true,\"015\":true,\"016\":true,\"017\":true,\"018\":true,\"019\":true,\"020\":true,\"021\":true,\"022\":true,\"023\":true,\"024\":true,\"025\":true,\"026\":true,\"027\":true,\"055\":true},\"RI\":{\"028\":true,\"029\":true},\"NH\":{\"030\":true,\"031\":true,\"032\":true,\"033\":true,\"034\":true,\"035\":true,\"036\":true,\"037\":true,\"038\":true,\"039\":true},\"VT\":{\"035\":true,\"036\":true,\"037\":true,\"050\":true,\"051\":true,\"052\":true,\"053\":true,\"054\":true,\"056\":true,\"057\":true,\"058\":true,\"059\":true},\"ME\":{\"039\":true,\"040\":true,\"041\":true,\"042\":true,\"043\":true,\"044\":true,\"045\":true,\"046\":true,\"047\":true,\"048\":true,\"049\":true},\"CT\":{\"060\":true,\"061\":true,\"062\":true,\"063\":true,\"064\":true,\"065\":true,\"066\":true,\"067\":true,\"068\":true,\"069\":true},\"NJ\":{\"070\":true,\"071\":true,\"072\":true,\"073\":true,\"074\":true,\"075\":true,\"076\":true,\"077\":true,\"078\":true,\"079\":true,\"080\":true,\"081\":true,\"082\":true,\"083\":true,\"084\":true,\"085\":true,\"086\":true,\"087\":true,\"088\":true,\"089\":true},\"AE\":{\"090\":true,\"091\":true,\"092\":true,\"093\":true,\"094\":true,\"095\":true,\"096\":true,\"097\":true,\"098\":true,\"099\":true},\"PA\":{\"150\":true,\"151\":true,\"152\":true,\"153\":true,\"154\":true,\"155\":true,\"156\":true,\"157\":true,\"158\":true,\"159\":true,\"160\":true,\"161\":true,\"162\":true,\"163\":true,\"164\":true,\"165\":true,\"166\":true,\"167\":true,\"168\":true,\"169\":true,\"170\":true,\"171\":true,\"172\":true,\"173\":true,\"174\":true,\"175\":true,\"176\":true,\"177\":true,\"178\":true,\"179\":true,\"180\":true,\"181\":true,\"182\":true,\"183\":true,\"184\":true,\"185\":true,\"186\":true,\"187\":true,\"188\":true,\"189\":true,\"190\":true,\"191\":true,\"192\":true,\"193\":true,\"194\":true,\"195\":true,\"196\":true,\"197\":true},\"DE\":{\"197\":true,\"198\":true,\"199\":true},\"DC\":{\"200\":true,\"202\":true,\"203\":true,\"204\":true,\"205\":true},\"VA\":{\"201\":true,\"220\":true,\"221\":true,\"222\":true,\"223\":true,\"224\":true,\"225\":true,\"226\":true,\"227\":true,\"228\":true,\"229\":true,\"230\":true,\"231\":true,\"232\":true,\"233\":true,\"234\":true,\"235\":true,\"236\":true,\"237\":true,\"238\":true,\"239\":true,\"240\":true,\"241\":true,\"242\":true,\"243\":true,\"244\":true,\"245\":true,\"246\":true},\"MD\":{\"206\":true,\"207\":true,\"208\":true,\"209\":true,\"210\":true,\"211\":true,\"212\":true,\"214\":true,\"215\":true,\"216\":true,\"217\":true,\"218\":true,\"219\":true,\"267\":true},\"WV\":{\"246\":true,\"247\":true,\"248\":true,\"249\":true,\"250\":true,\"251\":true,\"252\":true,\"253\":true,\"254\":true,\"255\":true,\"256\":true,\"257\":true,\"258\":true,\"259\":true,\"260\":true,\"261\":true,\"262\":true,\"263\":true,\"264\":true,\"265\":true,\"266\":true,\"267\":true,\"268\":true},\"NC\":{\"270\":true,\"271\":true,\"272\":true,\"273\":true,\"274\":true,\"275\":true,\"276\":true,\"277\":true,\"278\":true,\"279\":true,\"280\":true,\"281\":true,\"282\":true,\"283\":true,\"284\":true,\"285\":true,\"286\":true,\"287\":true,\"288\":true,\"289\":true,\"297\":true},\"SC\":{\"290\":true,\"291\":true,\"292\":true,\"293\":true,\"294\":true,\"295\":true,\"296\":true,\"297\":true,\"298\":true,\"299\":true},\"GA\":{\"298\":true,\"299\":true,\"300\":true,\"301\":true,\"302\":true,\"303\":true,\"304\":true,\"305\":true,\"306\":true,\"307\":true,\"308\":true,\"309\":true,\"310\":true,\"311\":true,\"312\":true,\"313\":true,\"314\":true,\"315\":true,\"316\":true,\"317\":true,\"318\":true,\"319\":true,\"398\":true,\"399\":true},\"FL\":{\"320\":true,\"321\":true,\"322\":true,\"323\":true,\"324\":true,\"325\":true,\"326\":true,\"327\":true,\"328\":true,\"329\":true,\"330\":true,\"331\":true,\"332\":true,\"333\":true,\"334\":true,\"335\":true,\"336\":true,\"337\":true,\"338\":true,\"339\":true,\"341\":true,\"342\":true,\"344\":true,\"346\":true,\"347\":true,\"349\":true},\"AA\":{\"331\":true,\"340\":true},\"AP\":{\"340\":true,\"962\":true,\"963\":true,\"964\":true,\"965\":true,\"966\":true},\"AL\":{\"350\":true,\"351\":true,\"352\":true,\"354\":true,\"355\":true,\"356\":true,\"357\":true,\"358\":true,\"359\":true,\"360\":true,\"361\":true,\"362\":true,\"363\":true,\"364\":true,\"365\":true,\"366\":true,\"367\":true,\"368\":true,\"369\":true},\"MS\":{\"369\":true,\"370\":true,\"386\":true,\"387\":true,\"388\":true,\"389\":true,\"390\":true,\"391\":true,\"392\":true,\"393\":true,\"394\":true,\"395\":true,\"396\":true,\"397\":true},\"TN\":{\"370\":true,\"371\":true,\"372\":true,\"373\":true,\"374\":true,\"375\":true,\"376\":true,\"377\":true,\"378\":true,\"379\":true,\"380\":true,\"381\":true,\"382\":true,\"383\":true,\"384\":true,\"385\":true,\"386\":true,\"723\":true},\"KY\":{\"400\":true,\"401\":true,\"402\":true,\"403\":true,\"404\":true,\"405\":true,\"406\":true,\"407\":true,\"408\":true,\"409\":true,\"410\":true,\"411\":true,\"412\":true,\"413\":true,\"414\":true,\"415\":true,\"416\":true,\"417\":true,\"418\":true,\"420\":true,\"421\":true,\"422\":true,\"423\":true,\"424\":true,\"425\":true,\"426\":true,\"427\":true,\"471\":true},\"OH\":{\"410\":true,\"430\":true,\"431\":true,\"432\":true,\"433\":true,\"434\":true,\"435\":true,\"436\":true,\"437\":true,\"438\":true,\"439\":true,\"440\":true,\"441\":true,\"442\":true,\"443\":true,\"444\":true,\"445\":true,\"446\":true,\"447\":true,\"448\":true,\"449\":true,\"450\":true,\"451\":true,\"452\":true,\"453\":true,\"454\":true,\"455\":true,\"456\":true,\"457\":true,\"458\":true,\"459\":true,\"470\":true,\"472\":true},\"IN\":{\"424\":true,\"460\":true,\"461\":true,\"462\":true,\"463\":true,\"464\":true,\"465\":true,\"466\":true,\"467\":true,\"468\":true,\"469\":true,\"470\":true,\"471\":true,\"472\":true,\"473\":true,\"474\":true,\"475\":true,\"476\":true,\"477\":true,\"478\":true,\"479\":true},\"MI\":{\"480\":true,\"481\":true,\"482\":true,\"483\":true,\"484\":true,\"485\":true,\"486\":true,\"487\":true,\"488\":true,\"489\":true,\"490\":true,\"491\":true,\"492\":true,\"493\":true,\"494\":true,\"495\":true,\"496\":true,\"497\":true,\"498\":true,\"499\":true},\"IA\":{\"500\":true,\"501\":true,\"502\":true,\"503\":true,\"504\":true,\"505\":true,\"506\":true,\"507\":true,\"508\":true,\"509\":true,\"510\":true,\"511\":true,\"512\":true,\"513\":true,\"514\":true,\"515\":true,\"516\":true,\"520\":true,\"521\":true,\"522\":true,\"523\":true,\"524\":true,\"525\":true,\"526\":true,\"527\":true,\"528\":true},\"NE\":{\"515\":true,\"516\":true,\"680\":true,\"681\":true,\"683\":true,\"684\":true,\"685\":true,\"686\":true,\"687\":true,\"688\":true,\"689\":true,\"690\":true,\"691\":true,\"692\":true,\"693\":true},\"IL\":{\"527\":true,\"600\":true,\"601\":true,\"602\":true,\"603\":true,\"604\":true,\"605\":true,\"606\":true,\"607\":true,\"608\":true,\"609\":true,\"610\":true,\"611\":true,\"612\":true,\"613\":true,\"614\":true,\"615\":true,\"616\":true,\"617\":true,\"618\":true,\"619\":true,\"620\":true,\"622\":true,\"623\":true,\"624\":true,\"625\":true,\"626\":true,\"627\":true,\"628\":true,\"629\":true,\"634\":true,\"635\":true},\"WI\":{\"530\":true,\"531\":true,\"532\":true,\"534\":true,\"535\":true,\"537\":true,\"538\":true,\"539\":true,\"540\":true,\"541\":true,\"542\":true,\"543\":true,\"544\":true,\"545\":true,\"546\":true,\"547\":true,\"548\":true,\"549\":true},\"MN\":{\"540\":true,\"550\":true,\"551\":true,\"553\":true,\"554\":true,\"556\":true,\"557\":true,\"558\":true,\"559\":true,\"560\":true,\"561\":true,\"562\":true,\"563\":true,\"564\":true,\"565\":true,\"566\":true,\"567\":true},\"ND\":{\"567\":true,\"580\":true,\"581\":true,\"582\":true,\"583\":true,\"584\":true,\"585\":true,\"586\":true,\"587\":true,\"588\":true},\"SD\":{\"570\":true,\"571\":true,\"572\":true,\"573\":true,\"574\":true,\"575\":true,\"576\":true,\"577\":true},\"MT\":{\"590\":true,\"591\":true,\"592\":true,\"593\":true,\"594\":true,\"595\":true,\"596\":true,\"597\":true,\"598\":true,\"599\":true},\"MO\":{\"620\":true,\"622\":true,\"630\":true,\"631\":true,\"633\":true,\"634\":true,\"635\":true,\"636\":true,\"637\":true,\"638\":true,\"639\":true,\"640\":true,\"641\":true,\"644\":true,\"645\":true,\"646\":true,\"647\":true,\"648\":true,\"649\":true,\"650\":true,\"651\":true,\"652\":true,\"653\":true,\"654\":true,\"655\":true,\"656\":true,\"657\":true,\"658\":true},\"KS\":{\"660\":true,\"661\":true,\"662\":true,\"664\":true,\"665\":true,\"666\":true,\"667\":true,\"668\":true,\"669\":true,\"670\":true,\"671\":true,\"672\":true,\"673\":true,\"674\":true,\"675\":true,\"676\":true,\"677\":true,\"678\":true,\"679\":true},\"LA\":{\"700\":true,\"701\":true,\"703\":true,\"704\":true,\"705\":true,\"706\":true,\"707\":true,\"708\":true,\"710\":true,\"711\":true,\"712\":true,\"713\":true,\"714\":true},\"AR\":{\"716\":true,\"717\":true,\"718\":true,\"719\":true,\"720\":true,\"721\":true,\"722\":true,\"723\":true,\"724\":true,\"725\":true,\"726\":true,\"727\":true,\"728\":true,\"729\":true},\"OK\":{\"730\":true,\"731\":true,\"734\":true,\"735\":true,\"736\":true,\"737\":true,\"738\":true,\"739\":true,\"740\":true,\"741\":true,\"743\":true,\"744\":true,\"745\":true,\"746\":true,\"747\":true,\"748\":true,\"749\":true},\"TX\":{\"733\":true,\"739\":true,\"750\":true,\"751\":true,\"752\":true,\"753\":true,\"754\":true,\"755\":true,\"756\":true,\"757\":true,\"758\":true,\"759\":true,\"760\":true,\"761\":true,\"762\":true,\"763\":true,\"764\":true,\"765\":true,\"766\":true,\"767\":true,\"768\":true,\"769\":true,\"770\":true,\"771\":true,\"772\":true,\"773\":true,\"774\":true,\"775\":true,\"776\":true,\"777\":true,\"778\":true,\"779\":true,\"780\":true,\"781\":true,\"782\":true,\"783\":true,\"784\":true,\"785\":true,\"786\":true,\"787\":true,\"788\":true,\"789\":true,\"790\":true,\"791\":true,\"792\":true,\"793\":true,\"794\":true,\"795\":true,\"796\":true,\"797\":true,\"798\":true,\"799\":true,\"885\":true},\"CO\":{\"800\":true,\"801\":true,\"802\":true,\"803\":true,\"804\":true,\"805\":true,\"806\":true,\"807\":true,\"808\":true,\"809\":true,\"810\":true,\"811\":true,\"812\":true,\"813\":true,\"814\":true,\"815\":true,\"816\":true},\"WY\":{\"820\":true,\"821\":true,\"822\":true,\"823\":true,\"824\":true,\"825\":true,\"826\":true,\"827\":true,\"828\":true,\"829\":true,\"830\":true,\"831\":true,\"834\":true},\"ID\":{\"832\":true,\"833\":true,\"834\":true,\"835\":true,\"836\":true,\"837\":true,\"838\":true,\"979\":true,\"994\":true},\"WA\":{\"838\":true,\"980\":true,\"981\":true,\"982\":true,\"983\":true,\"984\":true,\"985\":true,\"986\":true,\"988\":true,\"989\":true,\"990\":true,\"991\":true,\"992\":true,\"993\":true,\"994\":true},\"UT\":{\"840\":true,\"841\":true,\"842\":true,\"843\":true,\"844\":true,\"845\":true,\"846\":true,\"847\":true},\"AZ\":{\"850\":true,\"851\":true,\"852\":true,\"853\":true,\"855\":true,\"856\":true,\"857\":true,\"859\":true,\"860\":true,\"863\":true,\"864\":true,\"865\":true},\"NM\":{\"870\":true,\"871\":true,\"872\":true,\"873\":true,\"874\":true,\"875\":true,\"877\":true,\"878\":true,\"879\":true,\"880\":true,\"881\":true,\"882\":true,\"883\":true,\"884\":true},\"NV\":{\"877\":true,\"889\":true,\"890\":true,\"891\":true,\"893\":true,\"894\":true,\"895\":true,\"897\":true,\"898\":true,\"961\":true},\"CA\":{\"900\":true,\"901\":true,\"902\":true,\"903\":true,\"904\":true,\"905\":true,\"906\":true,\"907\":true,\"908\":true,\"910\":true,\"911\":true,\"912\":true,\"913\":true,\"914\":true,\"915\":true,\"916\":true,\"917\":true,\"918\":true,\"919\":true,\"920\":true,\"921\":true,\"922\":true,\"923\":true,\"924\":true,\"925\":true,\"926\":true,\"927\":true,\"928\":true,\"930\":true,\"931\":true,\"932\":true,\"933\":true,\"934\":true,\"935\":true,\"936\":true,\"937\":true,\"938\":true,\"939\":true,\"940\":true,\"941\":true,\"942\":true,\"943\":true,\"944\":true,\"945\":true,\"946\":true,\"947\":true,\"948\":true,\"949\":true,\"950\":true,\"951\":true,\"952\":true,\"953\":true,\"954\":true,\"955\":true,\"956\":true,\"957\":true,\"958\":true,\"959\":true,\"960\":true,\"961\":true},\"HI\":{\"967\":true,\"968\":true},\"AS\":{\"967\":true},\"GU\":{\"969\":true},\"MH\":{\"969\":true},\"OR\":{\"970\":true,\"971\":true,\"972\":true,\"973\":true,\"974\":true,\"975\":true,\"976\":true,\"977\":true,\"978\":true,\"979\":true,\"986\":true},\"AK\":{\"995\":true,\"996\":true,\"997\":true,\"998\":true,\"999\":true}}","module.exports={\"100\":\"NY\",\"101\":\"NY\",\"102\":\"NY\",\"103\":\"NY\",\"104\":\"NY\",\"105\":\"NY\",\"106\":\"NY\",\"107\":\"NY\",\"108\":\"NY\",\"109\":\"NY\",\"110\":\"NY\",\"111\":\"NY\",\"112\":\"NY\",\"113\":\"NY\",\"114\":\"NY\",\"115\":\"NY\",\"116\":\"NY\",\"117\":\"NY\",\"118\":\"NY\",\"119\":\"NY\",\"120\":\"NY\",\"121\":\"NY\",\"122\":\"NY\",\"123\":\"NY\",\"124\":\"NY\",\"125\":\"NY\",\"126\":\"NY\",\"127\":\"NY\",\"128\":\"NY\",\"129\":\"NY\",\"130\":\"NY\",\"131\":\"NY\",\"132\":\"NY\",\"133\":\"NY\",\"134\":\"NY\",\"135\":\"NY\",\"136\":\"NY\",\"137\":\"NY\",\"138\":\"NY\",\"139\":\"NY\",\"140\":\"NY\",\"141\":\"NY\",\"142\":\"NY\",\"143\":\"NY\",\"144\":\"NY\",\"145\":\"NY\",\"146\":\"NY\",\"147\":\"NY\",\"148\":\"NY\",\"149\":\"NY\",\"150\":\"PA\",\"151\":\"PA\",\"152\":\"PA\",\"153\":\"PA\",\"154\":\"PA\",\"155\":\"PA\",\"156\":\"PA\",\"157\":\"PA\",\"158\":\"PA\",\"159\":\"PA\",\"160\":\"PA\",\"161\":\"PA\",\"162\":\"PA\",\"163\":\"PA\",\"164\":\"PA\",\"165\":\"PA\",\"166\":\"PA\",\"167\":\"PA\",\"168\":\"PA\",\"169\":\"PA\",\"170\":\"PA\",\"171\":\"PA\",\"172\":\"PA\",\"173\":\"PA\",\"174\":\"PA\",\"175\":\"PA\",\"176\":\"PA\",\"177\":\"PA\",\"178\":\"PA\",\"179\":\"PA\",\"180\":\"PA\",\"181\":\"PA\",\"182\":\"PA\",\"183\":\"PA\",\"184\":\"PA\",\"185\":\"PA\",\"186\":\"PA\",\"187\":\"PA\",\"188\":\"PA\",\"189\":\"PA\",\"190\":\"PA\",\"191\":\"PA\",\"192\":\"PA\",\"193\":\"PA\",\"194\":\"PA\",\"195\":\"PA\",\"196\":\"PA\",\"197\":\"DE\",\"198\":\"DE\",\"199\":\"DE\",\"200\":\"DC\",\"201\":\"VA\",\"202\":\"DC\",\"203\":\"DC\",\"204\":\"DC\",\"205\":\"DC\",\"206\":\"MD\",\"207\":\"MD\",\"208\":\"MD\",\"209\":\"MD\",\"210\":\"MD\",\"211\":\"MD\",\"212\":\"MD\",\"214\":\"MD\",\"215\":\"MD\",\"216\":\"MD\",\"217\":\"MD\",\"218\":\"MD\",\"219\":\"MD\",\"220\":\"VA\",\"221\":\"VA\",\"222\":\"VA\",\"223\":\"VA\",\"224\":\"VA\",\"225\":\"VA\",\"226\":\"VA\",\"227\":\"VA\",\"228\":\"VA\",\"229\":\"VA\",\"230\":\"VA\",\"231\":\"VA\",\"232\":\"VA\",\"233\":\"VA\",\"234\":\"VA\",\"235\":\"VA\",\"236\":\"VA\",\"237\":\"VA\",\"238\":\"VA\",\"239\":\"VA\",\"240\":\"VA\",\"241\":\"VA\",\"242\":\"VA\",\"243\":\"VA\",\"244\":\"VA\",\"245\":\"VA\",\"246\":\"WV\",\"247\":\"WV\",\"248\":\"WV\",\"249\":\"WV\",\"250\":\"WV\",\"251\":\"WV\",\"252\":\"WV\",\"253\":\"WV\",\"254\":\"WV\",\"255\":\"WV\",\"256\":\"WV\",\"257\":\"WV\",\"258\":\"WV\",\"259\":\"WV\",\"260\":\"WV\",\"261\":\"WV\",\"262\":\"WV\",\"263\":\"WV\",\"264\":\"WV\",\"265\":\"WV\",\"266\":\"WV\",\"267\":\"WV\",\"268\":\"WV\",\"270\":\"NC\",\"271\":\"NC\",\"272\":\"NC\",\"273\":\"NC\",\"274\":\"NC\",\"275\":\"NC\",\"276\":\"NC\",\"277\":\"NC\",\"278\":\"NC\",\"279\":\"NC\",\"280\":\"NC\",\"281\":\"NC\",\"282\":\"NC\",\"283\":\"NC\",\"284\":\"NC\",\"285\":\"NC\",\"286\":\"NC\",\"287\":\"NC\",\"288\":\"NC\",\"289\":\"NC\",\"290\":\"SC\",\"291\":\"SC\",\"292\":\"SC\",\"293\":\"SC\",\"294\":\"SC\",\"295\":\"SC\",\"296\":\"SC\",\"297\":\"SC\",\"298\":\"GA\",\"299\":\"GA\",\"300\":\"GA\",\"301\":\"GA\",\"302\":\"GA\",\"303\":\"GA\",\"304\":\"GA\",\"305\":\"GA\",\"306\":\"GA\",\"307\":\"GA\",\"308\":\"GA\",\"309\":\"GA\",\"310\":\"GA\",\"311\":\"GA\",\"312\":\"GA\",\"313\":\"GA\",\"314\":\"GA\",\"315\":\"GA\",\"316\":\"GA\",\"317\":\"GA\",\"318\":\"GA\",\"319\":\"GA\",\"320\":\"FL\",\"321\":\"FL\",\"322\":\"FL\",\"323\":\"FL\",\"324\":\"FL\",\"325\":\"FL\",\"326\":\"FL\",\"327\":\"FL\",\"328\":\"FL\",\"329\":\"FL\",\"330\":\"FL\",\"331\":\"AA\",\"332\":\"FL\",\"333\":\"FL\",\"334\":\"FL\",\"335\":\"FL\",\"336\":\"FL\",\"337\":\"FL\",\"338\":\"FL\",\"339\":\"FL\",\"340\":\"AP\",\"341\":\"FL\",\"342\":\"FL\",\"344\":\"FL\",\"346\":\"FL\",\"347\":\"FL\",\"349\":\"FL\",\"350\":\"AL\",\"351\":\"AL\",\"352\":\"AL\",\"354\":\"AL\",\"355\":\"AL\",\"356\":\"AL\",\"357\":\"AL\",\"358\":\"AL\",\"359\":\"AL\",\"360\":\"AL\",\"361\":\"AL\",\"362\":\"AL\",\"363\":\"AL\",\"364\":\"AL\",\"365\":\"AL\",\"366\":\"AL\",\"367\":\"AL\",\"368\":\"AL\",\"369\":\"MS\",\"370\":\"TN\",\"371\":\"TN\",\"372\":\"TN\",\"373\":\"TN\",\"374\":\"TN\",\"375\":\"TN\",\"376\":\"TN\",\"377\":\"TN\",\"378\":\"TN\",\"379\":\"TN\",\"380\":\"TN\",\"381\":\"TN\",\"382\":\"TN\",\"383\":\"TN\",\"384\":\"TN\",\"385\":\"TN\",\"386\":\"TN\",\"387\":\"MS\",\"388\":\"MS\",\"389\":\"MS\",\"390\":\"MS\",\"391\":\"MS\",\"392\":\"MS\",\"393\":\"MS\",\"394\":\"MS\",\"395\":\"MS\",\"396\":\"MS\",\"397\":\"MS\",\"398\":\"GA\",\"399\":\"GA\",\"400\":\"KY\",\"401\":\"KY\",\"402\":\"KY\",\"403\":\"KY\",\"404\":\"KY\",\"405\":\"KY\",\"406\":\"KY\",\"407\":\"KY\",\"408\":\"KY\",\"409\":\"KY\",\"410\":\"OH\",\"411\":\"KY\",\"412\":\"KY\",\"413\":\"KY\",\"414\":\"KY\",\"415\":\"KY\",\"416\":\"KY\",\"417\":\"KY\",\"418\":\"KY\",\"420\":\"KY\",\"421\":\"KY\",\"422\":\"KY\",\"423\":\"KY\",\"424\":\"IN\",\"425\":\"KY\",\"426\":\"KY\",\"427\":\"KY\",\"430\":\"OH\",\"431\":\"OH\",\"432\":\"OH\",\"433\":\"OH\",\"434\":\"OH\",\"435\":\"OH\",\"436\":\"OH\",\"437\":\"OH\",\"438\":\"OH\",\"439\":\"OH\",\"440\":\"OH\",\"441\":\"OH\",\"442\":\"OH\",\"443\":\"OH\",\"444\":\"OH\",\"445\":\"OH\",\"446\":\"OH\",\"447\":\"OH\",\"448\":\"OH\",\"449\":\"OH\",\"450\":\"OH\",\"451\":\"OH\",\"452\":\"OH\",\"453\":\"OH\",\"454\":\"OH\",\"455\":\"OH\",\"456\":\"OH\",\"457\":\"OH\",\"458\":\"OH\",\"459\":\"OH\",\"460\":\"IN\",\"461\":\"IN\",\"462\":\"IN\",\"463\":\"IN\",\"464\":\"IN\",\"465\":\"IN\",\"466\":\"IN\",\"467\":\"IN\",\"468\":\"IN\",\"469\":\"IN\",\"470\":\"IN\",\"471\":\"IN\",\"472\":\"IN\",\"473\":\"IN\",\"474\":\"IN\",\"475\":\"IN\",\"476\":\"IN\",\"477\":\"IN\",\"478\":\"IN\",\"479\":\"IN\",\"480\":\"MI\",\"481\":\"MI\",\"482\":\"MI\",\"483\":\"MI\",\"484\":\"MI\",\"485\":\"MI\",\"486\":\"MI\",\"487\":\"MI\",\"488\":\"MI\",\"489\":\"MI\",\"490\":\"MI\",\"491\":\"MI\",\"492\":\"MI\",\"493\":\"MI\",\"494\":\"MI\",\"495\":\"MI\",\"496\":\"MI\",\"497\":\"MI\",\"498\":\"MI\",\"499\":\"MI\",\"500\":\"IA\",\"501\":\"IA\",\"502\":\"IA\",\"503\":\"IA\",\"504\":\"IA\",\"505\":\"IA\",\"506\":\"IA\",\"507\":\"IA\",\"508\":\"IA\",\"509\":\"IA\",\"510\":\"IA\",\"511\":\"IA\",\"512\":\"IA\",\"513\":\"IA\",\"514\":\"IA\",\"515\":\"NE\",\"516\":\"NE\",\"520\":\"IA\",\"521\":\"IA\",\"522\":\"IA\",\"523\":\"IA\",\"524\":\"IA\",\"525\":\"IA\",\"526\":\"IA\",\"527\":\"IL\",\"528\":\"IA\",\"530\":\"WI\",\"531\":\"WI\",\"532\":\"WI\",\"534\":\"WI\",\"535\":\"WI\",\"537\":\"WI\",\"538\":\"WI\",\"539\":\"WI\",\"540\":\"MN\",\"541\":\"WI\",\"542\":\"WI\",\"543\":\"WI\",\"544\":\"WI\",\"545\":\"WI\",\"546\":\"WI\",\"547\":\"WI\",\"548\":\"WI\",\"549\":\"WI\",\"550\":\"MN\",\"551\":\"MN\",\"553\":\"MN\",\"554\":\"MN\",\"556\":\"MN\",\"557\":\"MN\",\"558\":\"MN\",\"559\":\"MN\",\"560\":\"MN\",\"561\":\"MN\",\"562\":\"MN\",\"563\":\"MN\",\"564\":\"MN\",\"565\":\"MN\",\"566\":\"MN\",\"567\":\"ND\",\"570\":\"SD\",\"571\":\"SD\",\"572\":\"SD\",\"573\":\"SD\",\"574\":\"SD\",\"575\":\"SD\",\"576\":\"SD\",\"577\":\"SD\",\"580\":\"ND\",\"581\":\"ND\",\"582\":\"ND\",\"583\":\"ND\",\"584\":\"ND\",\"585\":\"ND\",\"586\":\"ND\",\"587\":\"ND\",\"588\":\"ND\",\"590\":\"MT\",\"591\":\"MT\",\"592\":\"MT\",\"593\":\"MT\",\"594\":\"MT\",\"595\":\"MT\",\"596\":\"MT\",\"597\":\"MT\",\"598\":\"MT\",\"599\":\"MT\",\"600\":\"IL\",\"601\":\"IL\",\"602\":\"IL\",\"603\":\"IL\",\"604\":\"IL\",\"605\":\"IL\",\"606\":\"IL\",\"607\":\"IL\",\"608\":\"IL\",\"609\":\"IL\",\"610\":\"IL\",\"611\":\"IL\",\"612\":\"IL\",\"613\":\"IL\",\"614\":\"IL\",\"615\":\"IL\",\"616\":\"IL\",\"617\":\"IL\",\"618\":\"IL\",\"619\":\"IL\",\"620\":\"MO\",\"622\":\"MO\",\"623\":\"IL\",\"624\":\"IL\",\"625\":\"IL\",\"626\":\"IL\",\"627\":\"IL\",\"628\":\"IL\",\"629\":\"IL\",\"630\":\"MO\",\"631\":\"MO\",\"633\":\"MO\",\"634\":\"MO\",\"635\":\"MO\",\"636\":\"MO\",\"637\":\"MO\",\"638\":\"MO\",\"639\":\"MO\",\"640\":\"MO\",\"641\":\"MO\",\"644\":\"MO\",\"645\":\"MO\",\"646\":\"MO\",\"647\":\"MO\",\"648\":\"MO\",\"649\":\"MO\",\"650\":\"MO\",\"651\":\"MO\",\"652\":\"MO\",\"653\":\"MO\",\"654\":\"MO\",\"655\":\"MO\",\"656\":\"MO\",\"657\":\"MO\",\"658\":\"MO\",\"660\":\"KS\",\"661\":\"KS\",\"662\":\"KS\",\"664\":\"KS\",\"665\":\"KS\",\"666\":\"KS\",\"667\":\"KS\",\"668\":\"KS\",\"669\":\"KS\",\"670\":\"KS\",\"671\":\"KS\",\"672\":\"KS\",\"673\":\"KS\",\"674\":\"KS\",\"675\":\"KS\",\"676\":\"KS\",\"677\":\"KS\",\"678\":\"KS\",\"679\":\"KS\",\"680\":\"NE\",\"681\":\"NE\",\"683\":\"NE\",\"684\":\"NE\",\"685\":\"NE\",\"686\":\"NE\",\"687\":\"NE\",\"688\":\"NE\",\"689\":\"NE\",\"690\":\"NE\",\"691\":\"NE\",\"692\":\"NE\",\"693\":\"NE\",\"700\":\"LA\",\"701\":\"LA\",\"703\":\"LA\",\"704\":\"LA\",\"705\":\"LA\",\"706\":\"LA\",\"707\":\"LA\",\"708\":\"LA\",\"710\":\"LA\",\"711\":\"LA\",\"712\":\"LA\",\"713\":\"LA\",\"714\":\"LA\",\"716\":\"AR\",\"717\":\"AR\",\"718\":\"AR\",\"719\":\"AR\",\"720\":\"AR\",\"721\":\"AR\",\"722\":\"AR\",\"723\":\"AR\",\"724\":\"AR\",\"725\":\"AR\",\"726\":\"AR\",\"727\":\"AR\",\"728\":\"AR\",\"729\":\"AR\",\"730\":\"OK\",\"731\":\"OK\",\"733\":\"TX\",\"734\":\"OK\",\"735\":\"OK\",\"736\":\"OK\",\"737\":\"OK\",\"738\":\"OK\",\"739\":\"TX\",\"740\":\"OK\",\"741\":\"OK\",\"743\":\"OK\",\"744\":\"OK\",\"745\":\"OK\",\"746\":\"OK\",\"747\":\"OK\",\"748\":\"OK\",\"749\":\"OK\",\"750\":\"TX\",\"751\":\"TX\",\"752\":\"TX\",\"753\":\"TX\",\"754\":\"TX\",\"755\":\"TX\",\"756\":\"TX\",\"757\":\"TX\",\"758\":\"TX\",\"759\":\"TX\",\"760\":\"TX\",\"761\":\"TX\",\"762\":\"TX\",\"763\":\"TX\",\"764\":\"TX\",\"765\":\"TX\",\"766\":\"TX\",\"767\":\"TX\",\"768\":\"TX\",\"769\":\"TX\",\"770\":\"TX\",\"771\":\"TX\",\"772\":\"TX\",\"773\":\"TX\",\"774\":\"TX\",\"775\":\"TX\",\"776\":\"TX\",\"777\":\"TX\",\"778\":\"TX\",\"779\":\"TX\",\"780\":\"TX\",\"781\":\"TX\",\"782\":\"TX\",\"783\":\"TX\",\"784\":\"TX\",\"785\":\"TX\",\"786\":\"TX\",\"787\":\"TX\",\"788\":\"TX\",\"789\":\"TX\",\"790\":\"TX\",\"791\":\"TX\",\"792\":\"TX\",\"793\":\"TX\",\"794\":\"TX\",\"795\":\"TX\",\"796\":\"TX\",\"797\":\"TX\",\"798\":\"TX\",\"799\":\"TX\",\"800\":\"CO\",\"801\":\"CO\",\"802\":\"CO\",\"803\":\"CO\",\"804\":\"CO\",\"805\":\"CO\",\"806\":\"CO\",\"807\":\"CO\",\"808\":\"CO\",\"809\":\"CO\",\"810\":\"CO\",\"811\":\"CO\",\"812\":\"CO\",\"813\":\"CO\",\"814\":\"CO\",\"815\":\"CO\",\"816\":\"CO\",\"820\":\"WY\",\"821\":\"WY\",\"822\":\"WY\",\"823\":\"WY\",\"824\":\"WY\",\"825\":\"WY\",\"826\":\"WY\",\"827\":\"WY\",\"828\":\"WY\",\"829\":\"WY\",\"830\":\"WY\",\"831\":\"WY\",\"832\":\"ID\",\"833\":\"ID\",\"834\":\"ID\",\"835\":\"ID\",\"836\":\"ID\",\"837\":\"ID\",\"838\":\"WA\",\"840\":\"UT\",\"841\":\"UT\",\"842\":\"UT\",\"843\":\"UT\",\"844\":\"UT\",\"845\":\"UT\",\"846\":\"UT\",\"847\":\"UT\",\"850\":\"AZ\",\"851\":\"AZ\",\"852\":\"AZ\",\"853\":\"AZ\",\"855\":\"AZ\",\"856\":\"AZ\",\"857\":\"AZ\",\"859\":\"AZ\",\"860\":\"AZ\",\"863\":\"AZ\",\"864\":\"AZ\",\"865\":\"AZ\",\"870\":\"NM\",\"871\":\"NM\",\"872\":\"NM\",\"873\":\"NM\",\"874\":\"NM\",\"875\":\"NM\",\"877\":\"NV\",\"878\":\"NM\",\"879\":\"NM\",\"880\":\"NM\",\"881\":\"NM\",\"882\":\"NM\",\"883\":\"NM\",\"884\":\"NM\",\"885\":\"TX\",\"889\":\"NV\",\"890\":\"NV\",\"891\":\"NV\",\"893\":\"NV\",\"894\":\"NV\",\"895\":\"NV\",\"897\":\"NV\",\"898\":\"NV\",\"900\":\"CA\",\"901\":\"CA\",\"902\":\"CA\",\"903\":\"CA\",\"904\":\"CA\",\"905\":\"CA\",\"906\":\"CA\",\"907\":\"CA\",\"908\":\"CA\",\"910\":\"CA\",\"911\":\"CA\",\"912\":\"CA\",\"913\":\"CA\",\"914\":\"CA\",\"915\":\"CA\",\"916\":\"CA\",\"917\":\"CA\",\"918\":\"CA\",\"919\":\"CA\",\"920\":\"CA\",\"921\":\"CA\",\"922\":\"CA\",\"923\":\"CA\",\"924\":\"CA\",\"925\":\"CA\",\"926\":\"CA\",\"927\":\"CA\",\"928\":\"CA\",\"930\":\"CA\",\"931\":\"CA\",\"932\":\"CA\",\"933\":\"CA\",\"934\":\"CA\",\"935\":\"CA\",\"936\":\"CA\",\"937\":\"CA\",\"938\":\"CA\",\"939\":\"CA\",\"940\":\"CA\",\"941\":\"CA\",\"942\":\"CA\",\"943\":\"CA\",\"944\":\"CA\",\"945\":\"CA\",\"946\":\"CA\",\"947\":\"CA\",\"948\":\"CA\",\"949\":\"CA\",\"950\":\"CA\",\"951\":\"CA\",\"952\":\"CA\",\"953\":\"CA\",\"954\":\"CA\",\"955\":\"CA\",\"956\":\"CA\",\"957\":\"CA\",\"958\":\"CA\",\"959\":\"CA\",\"960\":\"CA\",\"961\":\"CA\",\"962\":\"AP\",\"963\":\"AP\",\"964\":\"AP\",\"965\":\"AP\",\"966\":\"AP\",\"967\":\"AS\",\"968\":\"HI\",\"969\":\"MH\",\"970\":\"OR\",\"971\":\"OR\",\"972\":\"OR\",\"973\":\"OR\",\"974\":\"OR\",\"975\":\"OR\",\"976\":\"OR\",\"977\":\"OR\",\"978\":\"OR\",\"979\":\"OR\",\"980\":\"WA\",\"981\":\"WA\",\"982\":\"WA\",\"983\":\"WA\",\"984\":\"WA\",\"985\":\"WA\",\"986\":\"OR\",\"988\":\"WA\",\"989\":\"WA\",\"990\":\"WA\",\"991\":\"WA\",\"992\":\"WA\",\"993\":\"WA\",\"994\":\"WA\",\"995\":\"AK\",\"996\":\"AK\",\"997\":\"AK\",\"998\":\"AK\",\"999\":\"AK\",\"005\":\"NY\",\"063\":\"CT\",\"006\":\"VI\",\"007\":\"VI\",\"008\":\"VI\",\"009\":\"VI\",\"010\":\"MA\",\"011\":\"MA\",\"012\":\"MA\",\"013\":\"MA\",\"014\":\"MA\",\"015\":\"MA\",\"016\":\"MA\",\"017\":\"MA\",\"018\":\"MA\",\"019\":\"MA\",\"020\":\"MA\",\"021\":\"MA\",\"022\":\"MA\",\"023\":\"MA\",\"024\":\"MA\",\"025\":\"MA\",\"026\":\"MA\",\"027\":\"MA\",\"055\":\"MA\",\"028\":\"RI\",\"029\":\"RI\",\"030\":\"NH\",\"031\":\"NH\",\"032\":\"NH\",\"033\":\"NH\",\"034\":\"NH\",\"035\":\"VT\",\"036\":\"VT\",\"037\":\"VT\",\"038\":\"NH\",\"039\":\"ME\",\"050\":\"VT\",\"051\":\"VT\",\"052\":\"VT\",\"053\":\"VT\",\"054\":\"VT\",\"056\":\"VT\",\"057\":\"VT\",\"058\":\"VT\",\"059\":\"VT\",\"040\":\"ME\",\"041\":\"ME\",\"042\":\"ME\",\"043\":\"ME\",\"044\":\"ME\",\"045\":\"ME\",\"046\":\"ME\",\"047\":\"ME\",\"048\":\"ME\",\"049\":\"ME\",\"060\":\"CT\",\"061\":\"CT\",\"062\":\"CT\",\"064\":\"CT\",\"065\":\"CT\",\"066\":\"CT\",\"067\":\"CT\",\"068\":\"CT\",\"069\":\"CT\",\"070\":\"NJ\",\"071\":\"NJ\",\"072\":\"NJ\",\"073\":\"NJ\",\"074\":\"NJ\",\"075\":\"NJ\",\"076\":\"NJ\",\"077\":\"NJ\",\"078\":\"NJ\",\"079\":\"NJ\",\"080\":\"NJ\",\"081\":\"NJ\",\"082\":\"NJ\",\"083\":\"NJ\",\"084\":\"NJ\",\"085\":\"NJ\",\"086\":\"NJ\",\"087\":\"NJ\",\"088\":\"NJ\",\"089\":\"NJ\",\"090\":\"AE\",\"091\":\"AE\",\"092\":\"AE\",\"093\":\"AE\",\"094\":\"AE\",\"095\":\"AE\",\"096\":\"AE\",\"097\":\"AE\",\"098\":\"AE\",\"099\":\"AE\"}","'use strict';\n\nexports.VerifyAddress = verifyAddress;\nexports.AutocompleteAddress = autocompleteAddress;\nexports.SetAddressFromAddressVerificationDialog = setAddressFromAddressVerificationDialog;\nexports.BuildAddressObjectFromCheckoutForm = buildAddressObjectFromCheckoutForm;\nexports.BuildAddressObjectFromAddressAutocompleteSuggestion = buildAddressObjectFromAddressAutocompleteSuggestion;\nexports.BuildAddressObjectFromAddressVerifyResponse = buildAddressObjectFromAddressVerifyResponse;\nexports.CompareAddressObjects = compareAddressObjects;\n\nvar dataBuffer = {};\n\nfunction verifyAddress($form, options) {\n\treturn new Promise(function(resolve, reject) {\n\t\tvar addressVerificationPayload = {\n\t\t\tprimary_line: $form.find('input[name$=\"_address1\"]').val() || '',\n\t\t\tsecondary_line: $form.find('input[name$=\"_address2\"]').val() || '',\n\t\t\tcity: $form.find('input[name$=\"_city\"]').val() || '',\n\t\t\tstate: $form.find('select[name$=\"_state\"]').val() || '',\n\t\t\tzip_code: $form.find('input[name$=\"postal\"]').val() || ''\n\t\t};\n\t\taddressVerificationPayload[options.CSRFToken.Name] = options.CSRFToken.Token;\n\n\t\t$.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.Lob.AddressVerify,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify(addressVerificationPayload),\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\tif (!data || !data.ServiceSuccessfullyCalled) {\n\t\t\t\t\tresolve(data);\n\t\t\t\t} else {\n\t\t\t\t\tdata.Status = 'deliverable';\n\t\t\t\t\tdata.Match = true;\n\t\t\t\t\tif (data.InquiryResult) {\n\t\t\t\t\t\tdata.AddressOriginal = buildAddressObjectFromCheckoutForm($form);\n\t\t\t\t\t\tdata.AddressVerified = buildAddressObjectFromAddressVerifyResponse(data);\n\t\t\t\t\t\tdata.AddressComparison = compareAddressObjects(data.AddressOriginal, data.AddressVerified);\n\t\t\t\t\t\tdata.Match = data.AddressComparison.Match;\n\t\t\t\t\t\tdata.Status = data.InquiryResult.deliverability;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (data.Status == 'deliverable' && data.Match) {\n\t\t\t\t\t\tresolve(data);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function(data) {\n\t\t\t\tresolve(data);\n\t\t\t},\n\t\t});\n\t});\n}\n\nfunction autocompleteAddress($form, $field, options) {\n\treturn new Promise(function(resolve, reject) {\n\t\tvar addressAutocompletePayload = {\n\t\t\taddress_prefix: $form.find('input[name$=\"_address1\"]').val() || '',\n\t\t\tcity: $form.find('input[name$=\"_city\"]').val() || '',\n\t\t\tstate: $form.find('select[name$=\"_state\"]').val() || '',\n\t\t\tzip_code: $form.find('input[name$=\"postal\"]').val() || ''\n\t\t};\n\t\taddressAutocompletePayload[options.CSRFToken.Name] = options.CSRFToken.Token;\n\n\t\tif (dataBuffer && dataBuffer['AutocompleteAddressAjax'] && dataBuffer['AutocompleteAddressAjax'].readyState !== 4) {\n\t\t\tdataBuffer['AutocompleteAddressAjax'].abort();\n\t\t}\n\n\t\tdataBuffer['AutocompleteAddressAjax'] = $.ajax({\n\t\t\tmethod: 'POST',\n\t\t\turl: Urls.Lob.AddressAutocomplete,\n\t\t\tcontentType: 'application/json',\n\t\t\tdata: JSON.stringify(addressAutocompletePayload),\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function(data) {\n\t\t\t\tif (!data || !data.ServiceSuccessfullyCalled) {\n\t\t\t\t\tresolve(data);\n\t\t\t\t} else {\n\t\t\t\t\tdata.$form = $form;\n\t\t\t\t\tdata.$field = $field;\n\n\t\t\t\t\tresolve(data);\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t});\n}\n\nfunction setAddressFromAddressVerificationDialog($form, addressData) {\n\tif (addressData.FirstName) {\n\t\t$form.find('input[name$=\"_firstName\"]').val(addressData.FirstName);\n\t}\n\tif (addressData.LastName) {\n\t\t$form.find('input[name$=\"_lastName\"]').val(addressData.LastName);\n\t}\n\t$form.find('input[name$=\"_address1\"]').val(addressData.PrimaryLine);\n\t$form.find('input[name$=\"_address2\"]').val(addressData.SecondaryLine);\n\t$form.find('input[name$=\"_city\"]').val(addressData.City);\n\t$form.find('select[name$=\"_state\"]').val(addressData.StateCode);\n\t$form.find('input[name$=\"_postal\"]').val(addressData.PostalCode);\n\tif (addressData.CountryCode) {\n\t\t$form.find('select[name$=\"_countryCode\"]').val(addressData.CountryCode);\n\t}\n\tif (addressData.Phone) {\n\t\t$form.find('input[name$=\"phone\"]').val(addressData.Phone);\n\t}\n}\n\nfunction buildAddressObjectFromCheckoutForm($form) {\n\tvar addressObject = {};\n\t\n\taddressObject.PrimaryLine = $form.find('input[name$=\"_address1\"]').val();\n\taddressObject.SecondaryLine = $form.find('input[name$=\"_address2\"]').val();\n\taddressObject.City = $form.find('input[name$=\"_city\"]').val();\n\taddressObject.StateCode = $form.find('select[id$=\"_state\"]').val();\n\taddressObject.PostalCode = $form.find('input[name$=\"_postal\"]').val();\n\n\treturn addressObject;\n}\n\nfunction buildAddressObjectFromAddressAutocompleteSuggestion(data) {\n\tvar addressObject = {};\n\n\tif (data) {\n\t\taddressObject.PrimaryLine = data.primary_line || '';\n\t\taddressObject.SecondaryLine = data.secondary_line || '';\n\t\taddressObject.StateCode = data.state || '';\n\t\taddressObject.PostalCode = data.zip_code || '';\n\t\taddressObject.City = data.city || '';\n\t}\n\n\treturn addressObject;\n}\n\nfunction buildAddressObjectFromAddressVerifyResponse(data) {\n\tvar addressObject = {};\n\n\tif (data && data.InquiryResult) {\n\t\taddressObject.PrimaryLine = data.InquiryResult.primary_line || '';\n\t\taddressObject.SecondaryLine = data.InquiryResult.secondary_line || '';\n\t\taddressObject.StateCode = data.InquiryResult.components.state || '';\n\t\taddressObject.PostalCode = data.InquiryResult.components.zip_code || '';\n\t\taddressObject.City = data.InquiryResult.components.city || '';\n\t}\n\n\treturn addressObject;\n}\n\nfunction compareAddressObjects(addressOriginal, addressVerified) {\n\tvar addressObject = {};\n\n\tif (addressOriginal && addressVerified) {\n\t\taddressObject.PrimaryLine = compareAddressElement(addressOriginal.PrimaryLine, addressVerified.PrimaryLine);\n\t\taddressObject.SecondaryLine = compareAddressElement(addressOriginal.SecondaryLine, addressVerified.SecondaryLine);\n\t\taddressObject.StateCode = compareAddressElement(addressOriginal.StateCode, addressVerified.StateCode);\n\t\taddressObject.PostalCode = compareAddressElement(addressOriginal.PostalCode, addressVerified.PostalCode);\n\t\taddressObject.City = compareAddressElement(addressOriginal.City, addressVerified.City);\n\t}\n\n\tvar fieldsDifferent = [];\n\tfor (var addressElement in addressObject) {\n\t\tif (!addressObject[addressElement]) {\n\t\t\tfieldsDifferent[fieldsDifferent.length] = addressElement;\n\t\t}\n\t}\n\taddressObject.FieldsDifferent = fieldsDifferent;\n\taddressObject.Match = fieldsDifferent.length == 0;\n\n\treturn addressObject;\n}\n\nfunction compareAddressElement(addressElementOriginal, addressElementVerified) {\n\taddressElementOriginal = addressElementOriginal || '';\n\taddressElementVerified = addressElementVerified || '';\n\n\treturn addressElementOriginal.trim().toLowerCase() == addressElementVerified.trim().toLowerCase();\n}","'use strict';\n\nexports.ResponseCodes = {\n\tAlreadyInBasket: 'ALREADY_IN_BASKET'\n}\n\nexports.User = {\n\tSelectedCustomerShippingMethod: 'selectedCustomerShippingMethod',\n\tSelectedStoreShippingMethod: 'selectedStoreShippingMethod'\n}\n\nexports.ShippingMethods = {\n\tBopis: 'Bopis',\n\tLocalDelivery: 'LocalDelivery',\n\tShipToStore: 'Ship-to-Store',\n\tShipToStorePickup: 'My_Store_Free_Shipping',\n\tShipToStorePickupForWhip: 'WHIP FREE Ship-to-store',\n\tVirtual: 'Virtual'\n}","'use strict';\n\nexports.Events = {\n\tCart: {\n\t\tAddToCart: {\n\t\t\tName: 'AddToCart'\n\t\t},\n\t\tRemoveFromCart: {\n\t\t\tName: 'RemoveFromCart'\n\t\t}\n\t}\n}\n\nexports.EventTypes = {\n\tMinus: 'minus',\n\tPlus: 'plus'\n}","'use strict';\n\nexports.GetPosition = getPosition;\n\nfunction getPosition() {\n\treturn new Promise(function(resolve) {\n\t\tif (navigator.geolocation) {\n\t\t\tvar geolocationSuccess = function(position) {\t\n\t\t\t\tresolve(position);\n\t\t\t};\n\n\t\t\tvar geolocationError = function() {\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tnavigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError);\n\t\t} else {\n\t\t\tresolve();\n\t\t}\n\t});\n}","'use strict';\n\nexports.SlickSlider = {\n\tOptions: {\n\t\tSingle: {\n\t\t\taccessibility:  true,\n\t\t\tinfinite: \t\ttrue,\n\t\t\tdots: \t\t\tfalse,\n\t\t\tarrows: \t\tfalse,\n\t\t\tslidesToShow: \t1,\n\t\t\tslidesToScroll: 1,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767,\n\t\t\t\t\tsettings: \t{\n\t\t\t\t\t\tdots: \ttrue,\n\t\t\t\t\t\tarrows: true\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tThumbnail: {\n\t\t\taccessibility:  true,\n\t\t\tdraggable: false,\n\t\t\tinfinite: false,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: false,\n\t\t\tslidesToShow: 7,\n\t\t\tslidesToScroll: 7,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200,\n\t\t\t\t\tsettings: {\n\t\t\t\t\t\tslidesToShow: 4,\n\t\t\t\t\t\tslidesToScroll: 4\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tCategoryLanding: {\n\t\t\taccessibility:  true,\n\t\t\tdraggable: true,\n\t\t\tinfinite: true,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: true,\n\t\t\tslidesToShow: 4,\n\t\t\tslidesToScroll: 4,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200,\n\t\t\t\t\tsettings: {\n\t\t\t\t\t\tslidesToShow: 3,\n\t\t\t\t\t\tslidesToScroll: 3\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t}\n}","'use strict';\n\nexports.PaymentMethods = {\n\tAllianceData: 'Alliance_Data',\n\tApplePay: 'DW_APPLE_PAY',\n\tBillMeLater: 'BML',\n\tCreditCard: 'CREDIT_CARD',\n\tGiftCertificate: 'GIFT_CERTIFICATE',\n\tPayPal: 'PayPal',\n\tGlobale: 'GLOBALE',\n\tRewardsCredit: 'REWARDS_CREDIT',\n\tLoyaltyCredit: 'LOYALTY_CREDIT',\n\tStoredValueSolutions: 'SVS_Gift_Card',\n\tAffirm: 'Affirm',\n\tPaymentVoucher: 'B2B_Payment_Voucher',\n\tShopPay: 'ShopPay'\n};\n\nexports.CreditCards = {\n\tAmericanExpress: 'Amex',\n\tBootBarnCredit: 'Boot Barn Credit Card',\n\tDiscover: 'Discover',\n\tJCB: 'JCB',\n\tMaestro: 'Maestro',\n\tMastercard: 'Master',\n\tMastercardSeries2: 'Master Series 2',\n\tVisa: 'Visa'\n};","'use strict';\n\nexports.RefinementsUIVersions = {\n\tUpdated: 'Updated',\n\tLegacy: 'Legacy'\n}","'use strict';\n\nmodule.exports = {\n\tValidation: {\n\t\tEmail: /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,\n\t\tOrderNumber: /^[a-zA-Z]{0,6}[-._]{0,1}[0-9]{6,12}$/,\n\t\tPostalCode: /^[a-zA-Z0-9][a-zA-Z0-9\\- ]{0,10}[a-zA-Z0-9]$/,\n\t\tPostOfficeBox: /((((p[\\s\\.]?)\\s?[o\\s][\\.]?)\\s?)|(post\\s?office\\s?)|(postal\\s?)|(post\\s?))((box|bin|b\\.?)?\\s?((num|number|no|#)\\.?)?\\s?\\d+)/i,\n\t\tZipCode: /^[0-9]{5}(-[0-9]{4})*$/,\n\t\tRequiredExcludingPunctuation: /^[#]*[^_\\W]+/,\n\t\tGiftCardNumberLength: /(\\d)/g,\n\t\tGiftCardNumberValues: /^[-\\s0-9]*$/,\n\t}\n}\n\n// Email pattern is from W3C spec, same that jQuery Validate uses: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address\n// Postal Code pattern is from https://stackoverflow.com/questions/578406/what-is-the-ultimate-postal-code-and-zip-regex\n// PO Box pattern is modified from https://stackoverflow.com/questions/5680050/po-box-regular-expression-validation","'use strict';\n\nexports.AddressTypes = {\n\tCustomer: 'CustomerAddress',\n\tStore: 'StoreAddress'\n}\n\nexports.CountryCodes = {\n\tUnitedStates: 'US',\n\tCanada: 'CA'\n}\n\nexports.StateCodes = {\n\tNewYork: 'NY'\n}\n\nexports.KeyCodes = {\n\tEnter: 13,\n\tTab: 9,\n\tArrowLeft: 37,\n\tArrowUp: 38,\n\tArrowRight: 39,\n\tArrowDown: 40\n}\n\nexports.Responsive = {\n\tWidths: {\n\t\tMobile: 767,\n\t\tTablet: 1024\n\t}\n}\n\nexports.SiteIds = {\n\tBootBarnUS: 'bootbarn_us',\n\tSheplersUS: 'sheplers_us',\n\tCountryOutfittersUS: 'country_outfitters_us',\n\tBootBarnRspUS: 'bootbarn_rsp_us',\n\tBootBarnPayments: 'bootbarn_payments',\n\tBootBarnB2BUS: 'bootbarn_b2b_us',\n\tRangefinder: 'rangefinder'\n}\n\nexports.ProductRecommendationSystems = {\n\tEinstein: 'Einstein',\n\tRelevant: 'Relevant'\n}","'use strict';\n\nexports.Lodash = {\n\tSettings: {\n\t\tinterpolate: /{{([\\s\\S]+?)}}/g\n\t}\n}","'use strict';\n\nexports.Settings = {\n\tGlobal: {\n\t    errorClass: 'error',\n\t    errorElement: 'span',\n\t    onkeyup: false,\n\t    errorPlacement: function (error, element) {\n\t\t\tvar $validationErrorContainer = element.closest('form').find('.validation-error-container');\n\t\t\tif ($validationErrorContainer.length > 0) {\n\t\t\t\terror.appendTo($validationErrorContainer);\n\t    \t} else if (element.attr('error-container')) {\n\t    \t\terror.appendTo($(element.attr('error-container')));\n\t    \t} else {\n\t    \t\terror.appendTo(element.parent());\n\t    \t}\n\t    }\n\t},\n\tCheckout: {\n\t    errorPlacement: function(error, element) {\n\t    \tif (element.attr('error-container')) {\n\t    \t\terror.appendTo($(element.attr('error-container')));\n\t    \t} else {\n\t    \t\terror.appendTo(element.parent());\n\t    \t}\n\n\t\t\tvar $validationErrorContainer = element.closest('form').find('.validation-error-container');\n\t\t\tif ($validationErrorContainer.length > 0) {\n\t\t\t\tvar $element = $(element);\n\t\t\t\tvar $elementValidationError = $validationErrorContainer.find('.validation-error[field=\"' + $element.attr('id') + '\"]');\n\t\t\t\tif ($elementValidationError.length <= 0) {\n\t\t\t\t\tvar validationErrorText = $('<span class=\"validation-error\" field=\"' + $element.attr('id') + '\" />').text($element.closest('.formfield').find('label span').text() + ' is required.');\n\t\t\t\t\t$validationErrorContainer.append(validationErrorText);\n\t\t\t\t}\n\t\t\t}\n\t    },\n\t\tonfocusout: function(element) {\n\t\t\tif (!this.checkable(element)) {\n\t\t\t\tvar isElementValid = this.element(element);\n\t\t\t\tvar $element = $(element);\n\t\t\t\tvar $validationErrorContainer = $element.closest('form').find('.validation-error-container');\n\t\t\t\tvar $elementValidationError = $validationErrorContainer.find('.validation-error[field=\"' + $element.attr('id') + '\"]');\n\t\t\t\tif (isElementValid && $elementValidationError.length > 0) {\n\t\t\t\t\t$elementValidationError.remove();\n\t\t\t\t} else if (!isElementValid && $elementValidationError.length <= 0) {\n\t\t\t\t\tvar validationErrorText = $('<span class=\"validation-error\" field=\"' + $element.attr('id') + '\" />').text($element.closest('.formfield').find('label span').text() + ' is required.');\n\t\t\t\t\t$validationErrorContainer.append(validationErrorText);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexports.Rules = {\n\tRequiredExcludingPunctuation: {\n\t\trequiredExcludingPunctuation: true\n\t},\n\tValidateAddressForPostOfficeBox: {\n\t\tpostOfficeBox: true\n\t},\n\tValidateAddressForPostOfficeBoxOnly: {\n\t\tpostOfficeBoxOnly: true\n\t},\n\tEmail: {\n\t\temail: true,\n\t\tminlength: 1\n\t},\n\tOrderNumber: {\n\t\torderNumber: true\n\t},\n\tPostalCode: {\n\t\tpostalCode: true\n\t},\n\tPostalCodeAndStateCode: {\n\t\tpostalCode: true,\n\t\tzipCodeForStateCode: true\n\t},\n\tZipCode: {\n\t\tzipCode: true\n\t},\n\tZipCodeAndStateCode: {\n\t\tzipCode: true,\n\t\tzipCodeForStateCode: true\n\t},\n\tStateCodeForCaliforniaStateLine: {\n\t\tstateCodeForCaliforniaStateLine: true\n\t},\n\tGiftCard: {\n\t\tNumber: {\n\t\t\trequired: true,\n\t\t\tgiftCardNumberLength: true,\n\t\t\tgiftCardNumberValues: true\n\t\t},\n\t\tPin: {\n\t\t\trequired: true,\n\t\t\tdigits: true,\n\t\t\tminlength: 4,\n\t\t\tmaxlength: 8,\n\t\t\tmessages: {\n\t\t\t\tminlength: $.validator.format(Resources.Validation.Messages.Numbers.MinimumLength),\n\t\t\t\tmaxlength: $.validator.format(Resources.Validation.Messages.Numbers.MaximumLength)\n\t\t\t}\n\t\t}\n\t},\n\tRewardsCredit: {\n\t\tNumber: {\n\t\t\trequired: true,\n\t\t\tdigits: true,\n\t\t\tminlength: 16,\n\t\t\tmaxlength: 16,\n\t\t\tmessages: {\n\t\t\t\tminlength: $.validator.format(Resources.Validation.Messages.Numbers.MinimumLength),\n\t\t\t\tmaxlength: $.validator.format(Resources.Validation.Messages.Numbers.MaximumLength)\n\t\t\t}\n\t\t}\n\t},\n\tLoyaltyCredit: {\n\t\tNumber: {\n\t\t\trequired: true,\n\t\t\tdigits: true,\n\t\t\tminlength: 1,\n\t\t\tmaxlength: 10,\n\t\t\tmessages: {\n\t\t\t\tminlength: $.validator.format(Resources.Validation.Messages.Numbers.MinimumLength),\n\t\t\t\tmaxlength: $.validator.format(Resources.Validation.Messages.Numbers.MaximumLength)\n\t\t\t}\n\t\t}\n\t},\n\tPaymentVoucher: {\n\t\tNumber: {\n\t\t\trequired: true,\n\t\t\tdigits: false,\n\t\t\tminlength: 1,\n\t\t\tmaxlength: 28,\n\t\t\tmessages: {\n\t\t\t\tminlength: $.validator.format(Resources.Validation.Messages.Numbers.MinimumLength),\n\t\t\t\tmaxlength: $.validator.format(Resources.Validation.Messages.Numbers.MaximumLength)\n\t\t\t}\n\t\t}\n\t}\n}","'use strict';\n\nexports.PushDataLayerForPage = pushDataLayerForPage;\nexports.PushDataLayerForDataLayerType = pushDataLayerForDataLayerType;\nexports.PushDataLayerForEvent = pushDataLayerForEvent;\n\nfunction pushDataLayerForPage(page) {\n\twindow.dataLayer = window.dataLayer || [];\n\n\tif (page) {\n\t\tif (page.options && page.options.GoogleTagManager && page.options.GoogleTagManager.EnableGoogleAnalytics4) {\n\t\t\tpushDataLayerForPageForGoogleAnalytics4(page);\n\t\t}\n\t\tpushDataLayerForPageForUniversalAnalytics(page);\n\t}\n}\n\nfunction pushDataLayerForPageForGoogleAnalytics4(page) {\n\twindow.dataLayer = window.dataLayer || [];\n\n\tif (page) {\n\t\tif (page.options && page.options.GoogleTagManager && page.options.GoogleTagManager.DataLayerCacheForGoogleAnalytics4) {\n\t\t\tvar dataLayer;\n\t\t\tif (page.ns == 'orderconfirmation') {\n\t\t\t\tdataLayer = page.options.GoogleTagManager.DataLayerCacheForGoogleAnalytics4;\n\t\t\t\tdataLayer.items = getProductDataLayer('data-product-ga4-json');\n\t\t\t\tpushDataLayer(dataLayer);\n\t\t\t\t$(document).trigger('DataLayer.OrderComplete', dataLayer);\n\t\t\t} else {\n\t\t\t\t// This should be activated when UA is removed.\n\t\t\t\t// $.ajax({\n\t\t\t\t// \turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\t// \ttype: 'POST',\n\t\t\t\t// \tdata: {\n\t\t\t\t// \t\tDataLayerType: 'General',\n\t\t\t\t// \t\tDataLayerVersion: 'GoogleAnalytics4'\n\t\t\t\t// \t},\n\t\t\t\t// \tdataType: 'json',\n\t\t\t\t// \tsuccess: function(data) {\n\t\t\t\t// \t\tdataLayer = $.extend(page.options.GoogleTagManager.DataLayerCacheForGoogleAnalytics4, data);\n\t\t\t\t// \t\twindow.dataLayer.push(dataLayer);\n\t\t\t\t// \t},\n\t\t\t\t// \terror: function() {\n\t\t\t\t\t\t\n\t\t\t\t// \t}\n\t\t\t\t// });\n\t\t\t}\n\n\t\t\t// This should be activated when UA is removed.\n\t\t\t// $(document).trigger('DataLayer.OrderComplete', dataLayer);\n\t\t}\n\t\t\n\t\tif (page.ns != 'orderconfirmation') {\n\t\t\tvar payload = {};\n\n\t\t\tvar dataLayerPageType;\n\t\t\tif (page.options && page.options.GoogleTagManager && page.options.GoogleTagManager.PageType) {\n\t\t\t\tdataLayerPageType = page.options.GoogleTagManager.PageType;\n\t\t\t} else {\n\t\t\t\tdataLayerPageType = page.ns;\n\t\t\t}\t\t\n\t\t\tpayload.Page = dataLayerPageType;\t\n\n\t\t\tif (page.options && page.options.GoogleTagManager) {\n\t\t\t\tpayload.Options = JSON.stringify(page.options.GoogleTagManager);\n\t\t\t\tpayload.DataLayerVersion = 'GoogleAnalytics4';\n\t\t\t}\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\ttype: 'POST',\n\t\t\t\tdata: payload,\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (page.options && page.options.GoogleTagManager && page.options.GoogleTagManager.DataLayerCacheForGoogleAnalytics4) {\n\t\t\t\t\t\tdata = $.extend(page.options.GoogleTagManager.DataLayerCacheForGoogleAnalytics4, data);\n\t\t\t\t\t}\n\t\t\t\t\tif (page.ns == 'product') {\n\t\t\t\t\t\tif (!data.value && data.items && data.items.length > 0) {\n\t\t\t\t\t\t\tdata.currency = data.items[0].currency;\n\t\t\t\t\t\t\tdata.value = data.items[0].price;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (page.ns == 'search') {\n\t\t\t\t\t\tdata.items = getProductDataLayer('data-product-ga4-json', { Container: $('.search-result-content') });\n\t\t\t\t\t} else if (page.ns == 'cart' || page.ns == 'onepcheckout' || page.ns == 'onepcheckout_groups') {\n\t\t\t\t\t\tdata.items = getProductDataLayer('data-product-ga4-json');\n\t\t\t\t\t\tif (!data.value && data.items && data.items.length > 0) {\n\t\t\t\t\t\t\tvar value = 0;\n\t\t\t\t\t\t\tfor (var itemKey in data.items) {\n\t\t\t\t\t\t\t\tvar item = data.items[itemKey];\n\t\t\t\t\t\t\t\tvalue += item.price;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdata.value = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpushDataLayer(data);\n\t\t\t\t\t$(document).trigger('DataLayer.OrderComplete', data);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction pushDataLayerForPageForUniversalAnalytics(page) {\n\twindow.dataLayer = window.dataLayer || [];\n\n\tif (page) {\n\t\tif (page.options && page.options.GoogleTagManager && page.options.GoogleTagManager.DataLayerCache) {\n\t\t\tvar dataLayer;\n\t\t\tif (page.ns == 'orderconfirmation') {\n\t\t\t\tdataLayer = page.options.GoogleTagManager.DataLayerCache;\n\t\t\t\tdataLayer.ecommerce = dataLayer.ecommerce || {};\n\t\t\t\tdataLayer.ecommerce.purchase = dataLayer.ecommerce.purchase || {};\n\t\t\t\tdataLayer.ecommerce.purchase.products = getProductDataLayer();\n\t\t\t\tpushDataLayer(dataLayer);\n\t\t\t\t// $(document).trigger('DataLayer.OrderComplete', dataLayer);\n\t\t\t} else {\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tDataLayerType: 'General',\n\t\t\t\t\t\tDataLayerVersion: 'UniversalAnalytics'\n\t\t\t\t\t},\n\t\t\t\t\tdataType: 'json',\n\t\t\t\t\tsuccess: function(data) {\n\t\t\t\t\t\tdataLayer = $.extend(page.options.GoogleTagManager.DataLayerCache, data);\n\t\t\t\t\t\tpushDataLayer(dataLayer);\n\t\t\t\t\t\t$(document).trigger('DataLayer.OrderComplete', dataLayer);\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (page.ns != 'orderconfirmation') {\n\t\t\tvar payload = {\n\t\t\t\tPage: page.ns\n\t\t\t}\n\t\t\t\n\t\t\tif (page.options && page.options.GoogleTagManager) {\n\t\t\t\tpayload.Options = JSON.stringify(page.options.GoogleTagManager);\n\t\t\t\tpayload.DataLayerVersion = 'UniversalAnalytics';\n\t\t\t}\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\ttype: 'POST',\n\t\t\t\tdata: payload,\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tif (page.ns == 'search') {\n\t\t\t\t\t\tdata.ecommerce = data.ecommerce || {};\n\t\t\t\t\t\tdata.ecommerce.impressions = getProductDataLayer(null, { Container: $('.search-result-content') });\n\t\t\t\t\t} else if (page.ns == 'product') {\n\t\t\t\t\t\tdata.ecommerce = data.ecommerce || {};\n\t\t\t\t\t\tdata.ecommerce.detail = data.ecommerce.detail || {};\n\t\t\t\t\t\tdata.ecommerce.detail.products = getProductDataLayer();\n\t\t\t\t\t} else if (page.ns == 'cart' || page.ns == 'onepcheckout' || page.ns == 'onepcheckout_groups') {\n\t\t\t\t\t\tdata.ecommerce = data.ecommerce || {};\n\t\t\t\t\t\tdata.ecommerce.cartContents = getProductDataLayer();\n\t\t\t\t\t}\n\t\t\t\t\tpushDataLayer(data);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction pushDataLayerForDataLayerType(dataLayerType, dataObject, options) {\n\tvar dataObject = dataObject || {};\n\n\treturn new Promise(function(resolve, reject) {\n\t\tvar ajaxCompleteStatus = {\n\t\t\tGoogleAnalytics4: '',\n\t\t\tUniversalAnalytics: ''\n\t\t}\n\n\t\tvar ajaxComplete = function() {\n\t\t\tif (ajaxCompleteStatus.UniversalAnalytics == 'success' && ajaxCompleteStatus.GoogleAnalytics4 == 'success') {\n\t\t\t\tresolve();\n\t\t\t} else if (ajaxCompleteStatus.UniversalAnalytics && ajaxCompleteStatus.GoogleAnalytics4 && (ajaxCompleteStatus.UniversalAnalytics == 'error' || ajaxCompleteStatus.GoogleAnalytics4 == 'error')) {\n\t\t\t\treject();\n\t\t\t}\n\t\t}\n\n\t\tif (dataLayerType != 'Event') {\n\t\t\tpushDataLayerForDataLayerTypeForDataLayerVersion(dataLayerType, dataObject.UniversalAnalytics || Object.assign({}, dataObject), 'UniversalAnalytics', options).then(function() {\n\t\t\t\tajaxCompleteStatus.UniversalAnalytics = 'success';\n\t\t\t\tajaxComplete();\n\t\t\t}).catch(function() {\n\t\t\t\tajaxCompleteStatus.UniversalAnalytics = 'error';\n\t\t\t\tajaxComplete();\n\t\t\t});\n\t\t}\n\t\tpushDataLayerForDataLayerTypeForDataLayerVersion(dataLayerType, dataObject.GoogleAnalytics4 || Object.assign({}, dataObject), 'GoogleAnalytics4', options).then(function() {\n\t\t\tajaxCompleteStatus.GoogleAnalytics4 = 'success';\n\t\t\tajaxComplete();\n\t\t}).catch(function() {\n\t\t\tajaxCompleteStatus.GoogleAnalytics4 = 'error';\n\t\t\tajaxComplete();\n\t\t});;\n\t});\n}\n\nfunction pushDataLayerForDataLayerTypeForDataLayerVersion(dataLayerType, dataObject, dataLayerVersion, options) {\n\tvar dataLayerType = dataLayerType || 'General';\n\tvar dataLayerVersion = dataLayerVersion || 'UniversalAnalytics';\n\tvar dataObject = dataObject || {};\n\n\treturn new Promise(function(resolve, reject) {\n\t\tif (dataLayerType) {\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\ttype: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\tDataLayerType: dataLayerType,\n\t\t\t\t\tDataLayerVersion: dataLayerVersion\n\t\t\t\t},\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tvar dataLayer;\n\t\t\t\t\tif (data && !$.isEmptyObject(data)) {\n\t\t\t\t\t\tdataLayer = $.extend(data, dataObject);\n\n\t\t\t\t\t\tif (dataLayerType == 'AddPaymentInfo') {\n\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\tContainerSelector: options && options.ContainerSelector ? options.ContainerSelector : ''\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (dataLayerType == 'AddShippingInfo') {\n\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\tContainerSelector: options && options.ContainerSelector ? options.ContainerSelector : ''\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (dataLayerType == 'AddToCart') {\n\t\t\t\t\t\t\tif ((dataLayer.event == 'add_to_cart' && (!dataLayer.items || dataLayer.items.length == 0)) || (dataLayer.event == 'addToCart' && (!dataLayer.ecommerce || !dataLayer.ecommerce || !dataLayer.ecommerce.add || !dataLayer.ecommerce.add.products || dataLayer.ecommerce.add.products.length == 0))) {\n\t\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\t\tContainerSelector: options && options.ContainerSelector ? options.ContainerSelector : '',\n\t\t\t\t\t\t\t\t\tFilterSelector: '.pdp-browse',\n\t\t\t\t\t\t\t\t\tUniversalAnalyticsKey: 'add'\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (dataLayer.items && dataLayer.items.length > 0) {\n\t\t\t\t\t\t\t\tif (!dataLayer.items[0].quantity) {\n\t\t\t\t\t\t\t\t\tdataLayer.items[0].quantity = 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdataLayer.currency = dataLayer.items[0].currency;\n\t\t\t\t\t\t\t\tdataLayer.value = dataLayer.items[0].price;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (dataLayerType == 'RemoveFromCart') {\n\t\t\t\t\t\t\tif (dataLayer.items && dataLayer.items.length > 0) {\n\t\t\t\t\t\t\t\tif (!dataLayer.items[0].quantity) {\n\t\t\t\t\t\t\t\t\tdataLayer.items[0].quantity = 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdataLayer.currency = dataLayer.items[0].currency;\n\t\t\t\t\t\t\t\tdataLayer.value = dataLayer.items[0].price;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (dataLayerType == 'SelectPromotion') {\n\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\tContainer: options && options.Container ? options.Container : ''\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (dataLayerType == 'ViewItem') {\n\t\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\t\tContainerSelector: options && options.ContainerSelector ? options.ContainerSelector : '',\n\t\t\t\t\t\t\t\t\tFilterSelector: '.pdp-browse',\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tUniversalAnalyticsKey: 'detail'\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (dataLayerType == 'ViewPromotion') {\n\t\t\t\t\t\t\tdecorateDataLayerWithProductData(dataLayer, {\n\t\t\t\t\t\t\t\tDataLayerVersion: dataLayerVersion,\n\t\t\t\t\t\t\t\tContainer: options && options.Container ? options.Container : ''\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpushDataLayer(dataLayer);\n\t\t\t\t\t}\n\t\t\t\t\tresolve(dataLayer);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\treject();\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treject();\n\t\t}\n\t});\n}\n\nfunction pushDataLayerForEvent(eventName, dataObject, dataLayerType, dataLayerVersion) {\n\tvar dataObject = dataObject || {};\n\n\treturn new Promise(function(resolve, reject) {\n\t\tif (eventName) {\n\t\t\t$.ajax({\n\t\t\t\turl: Urls.GoogleTagManager.GetDataLayer,\n\t\t\t\ttype: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\tDataLayerType: dataLayerType || 'General',\n\t\t\t\t\tDataLayerVersion: dataLayerVersion || 'UniversalAnalytics'\n\t\t\t\t},\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function(data) {\n\t\t\t\t\tvar dataLayer = $.extend(dataObject, data);\n\t\t\t\t\tdataLayer.event = eventName;\n\t\t\t\t\tpushDataLayer(dataLayer);\n\t\t\t\t\tresolve(dataLayer);\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\treject();\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treject();\n\t\t}\n\t});\n}\n\nfunction decorateDataLayerWithProductData(dataLayer, options) {\n\tvar universalAnalyticsKey = options && options.UniversalAnalyticsKey ? options.UniversalAnalyticsKey : '';\n\n\tif (options && options.DataLayerVersion == 'GoogleAnalytics4') {\n\t\tdataLayer.items = getProductDataLayer('data-product-ga4-json', options);\n\t} else {\n\t\tdataLayer.ecommerce = dataLayer.ecommerce || {};\n\t\tdataLayer.ecommerce[universalAnalyticsKey] = dataLayer.ecommerce[universalAnalyticsKey] || {};\n\t\tdataLayer.ecommerce[universalAnalyticsKey].products = getProductDataLayer(null, options);\n\t}\n}\n\nfunction getProductDataLayer(attributeIdParameter, options) {\n\tvar dataLayerProducts = window.dataLayerProducts || [];\n\tvar attributeId = attributeIdParameter || 'data-product-gtm-json';\n\tvar container = options && options.Container ? options.Container : '';\n\tvar containerSelector = options && options.ContainerSelector ? options.ContainerSelector : '';\n\tvar filterSelector = options && options.FilterSelector ? options.FilterSelector : '';\n\n\tvar $productCards;\n\tif (container) {\n\t\t$productCards = container.find('[' + attributeId + ']' + filterSelector);\n\t} else if (containerSelector) {\n\t\t$productCards = $(containerSelector).find('[' + attributeId + ']' + filterSelector);\n\t} else {\n\t\t$productCards = $('[' + attributeId + ']' + filterSelector);\n\t}\n\t$productCards.each(function(index, element) {\n\t\tvar $element = $(element);\n\n\t\tvar slickIndex = null;\n\t\tvar isValid = true;\n\t\tif ($element.closest('[data-slick-index]').length > 0) {\n\t\t\tslickIndex = parseInt($element.closest('[data-slick-index]').data('slick-index'), 10) + 1;\n\t\t\tif (slickIndex < 1) {\n\t\t\t\tisValid = false;\n\t\t\t}\n\t\t}\n\n\t\tif (isValid) {\n\t\t\tvar jsonObject = JSON.parse($element.attr(attributeId));\n\t\t\tif (attributeId == 'data-product-gtm-json') {\n\t\t\t\tjsonObject.position = index;\n\t\t\t} else {\n\t\t\t\tjsonObject.index = index;\n\t\t\t}\n\t\t\tdataLayerProducts.push(jsonObject);\n\t\t}\n\t});\n\t\t\n\treturn dataLayerProducts;\n}\n\nfunction pushDataLayer(dataLayer) {\n\tvar isCartPage = pageContext && pageContext.options && pageContext.options.isCartPage;\n\tvar isCheckoutPage = pageContext && pageContext.options && pageContext.options.isCheckoutPage;\n\tvar isConfirmationPage = pageContext && pageContext.options && pageContext.options.isConfirmationPage;\n\tvar reactDataLayerPages = pageContext && pageContext.options && pageContext.options.MobileApp && pageContext.options.MobileApp.ReactDataLayerPages ? pageContext.options.MobileApp.ReactDataLayerPages : [];\n\tvar sendReactEventForCart = isCartPage && reactDataLayerPages.indexOf('Cart') > -1;\n\tvar sendReactEventForCheckout = isCheckoutPage && reactDataLayerPages.indexOf('Checkout') > -1;\n\tvar sendReactEventForConfirmation = isConfirmationPage && reactDataLayerPages.indexOf('Confirmation') > -1;\n\n\tif ('ReactNativeWebView' in window && (sendReactEventForCart || sendReactEventForCheckout || sendReactEventForConfirmation)) {\n\t\ttriggerReactWebviewEvent(dataLayer.event, dataLayer);\n\t} else {\n\t\twindow.dataLayer.push(dataLayer);\n\t}\n}\n\nfunction triggerReactWebviewEvent(action, dataLayer) {\n\tif ('ReactNativeWebView' in window) {\n\t\tvar message =  {\n\t\t\taction: action\n\t\t}\n\t\tif (dataLayer) {\n\t\t\tmessage.dataLayer = dataLayer;\n\t\t}\n\n\t\twindow.ReactNativeWebView.postMessage(JSON.stringify(message));\n\t}\n}","'use strict';\n\nvar RegexValidationPatterns = require('../../js/RegexPatterns').Validation;\nvar StateToZipCodeMap = require('../../data/StateToZipCodeMap.json');\n\nexports.ValidateRequiredExcludingPunctuation = validateRequiredExcludingPunctuation;\nexports.ValidateOrderNumber = validateOrderNumber;\nexports.ValidateAddressForPostOfficeBox = validateAddressForPostOfficeBox;\nexports.ValidateAddressForPostOfficeBoxOnly = validateAddressForPostOfficeBoxOnly;\nexports.ValidatePostalCode = validatePostalCode;\nexports.ValidateZipCode = validateZipCode;\nexports.ValidateZipCodePrefixForStateCode = validateZipCodePrefixForStateCode;\nexports.ValidateZipCodePrefixForStateCodeValues = validateZipCodePrefixForStateCodeValues;\nexports.ValidateStateCodeForCaliforniaStateLine = validateStateCodeForCaliforniaStateLine;\nexports.ValidateGiftCardNumberLength = validateGiftCardNumberLength;\nexports.ValidateGiftCardNumberValues = validateGiftCardNumberValues;\n\nfunction validateRequiredExcludingPunctuation(value, element) {\n    return RegexValidationPatterns.RequiredExcludingPunctuation.test((value + '').trim());\n};\n\nfunction validateOrderNumber(value, element) {\n    return RegexValidationPatterns.OrderNumber.test((value + '').trim());\n};\n\nfunction validateAddressForPostOfficeBox(value, element) {\n\treturn !RegexValidationPatterns.PostOfficeBox.test((value + '').trim());\n}\n\nfunction validateAddressForPostOfficeBoxOnly(value, element) {\n\tvar address1 = $(element).closest('form').find('input[name$=\"_address1\"]').val();\n\tvar address2 = $(element).closest('form').find('input[name$=\"_address2\"]').val();\n\n\treturn (!RegexValidationPatterns.PostOfficeBox.test((address1 + '').trim()) && !RegexValidationPatterns.PostOfficeBox.test((address2 + '').trim())) || (!address1 || !address2);\n}\n\nfunction validatePostalCode(value, element) {\n    return RegexValidationPatterns.PostalCode.test((value + '').trim());\n};\n\nfunction validateZipCode(value, element) {\n    return RegexValidationPatterns.ZipCode.test((value + '').trim());\n};\n\nfunction validateZipCodePrefixForStateCode(value, element) {\n\tvar zipCodePrefix = value.substr(0,3);\n\tvar stateCode = $(element).closest('form').find('select[name$=\"_states_state\"]').val().toUpperCase();\n\tif (stateCode && StateToZipCodeMap && StateToZipCodeMap[stateCode]) {\n\t\treturn StateToZipCodeMap[stateCode][zipCodePrefix];\n\t}\n\n    return true;\n};\n\nfunction validateZipCodePrefixForStateCodeValues(zipCode, stateCode) {\n\tvar zipCodePrefix = zipCode.substr(0,3);\n\tif (StateToZipCodeMap && StateToZipCodeMap[stateCode]) {\n\t\treturn StateToZipCodeMap[stateCode][zipCodePrefix];\n\t}\n\n    return true;\n};\n\nfunction validateStateCodeForCaliforniaStateLine(value, element) {\n\tvar stateCodeForStore = $(element).closest('[store-state]').attr('store-state');\n\n\tif ((value != 'CA' && stateCodeForStore != 'CA') || value == stateCodeForStore) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nfunction validateGiftCardNumberLength(value, element) {\n\tvar digits = (value + '').trim().match(RegexValidationPatterns.GiftCardNumberLength);\n\treturn digits && digits.length == 19;\n};\n\nfunction validateGiftCardNumberValues(value, element) {\n\treturn RegexValidationPatterns.GiftCardNumberValues.test((value + '').trim());\n};","'use strict';\n\nexports.SlickSlider = {\n\tOptions: {\n\t\tSingle: {\n\t\t\tinfinite: \t\ttrue,\n\t\t\tdots: \t\t\tfalse,\n\t\t\tarrows: \t\tfalse,\n\t\t\tslidesToShow: \t1,\n\t\t\tslidesToScroll: 1,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767,\n\t\t\t\t\tsettings: \t{\n\t\t\t\t\t\tdots: \ttrue,\n\t\t\t\t\t\tarrows: true\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tThumbnail: {\n\t\t\tdraggable: true,\n\t\t\tinfinite: false,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: false,\n\t\t\tslidesToShow: 7,\n\t\t\tslidesToScroll: 7,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200,\n\t\t\t\t\tsettings: {\n\t\t\t\t\t\tslidesToShow: 4,\n\t\t\t\t\t\tslidesToScroll: 4\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}/*,\n\t\tCategoryLanding: {\n\t\t\tdraggable: true,\n\t\t\tinfinite: true,\n\t\t\tfocusOnSelect: \tfalse,\n\t\t\tdots: false,\n\t\t\tarrows: true,\n\t\t\tslidesToShow: 4,\n\t\t\tslidesToScroll: 4,\n\t\t\tresponsive: \t[\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 767\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbreakpoint: 1200,\n\t\t\t\t\tsettings: {\n\t\t\t\t\t\tslidesToShow: 3,\n\t\t\t\t\t\tslidesToScroll: 3\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}*/\n\t}\n}","/* Global Variables */\nvar helper = require('../helpers/shoppayHelper');\nvar isBuyNow = window.shoppayClientRefs ? window.shoppayClientRefs.constants.isBuyNow : null;\nvar isAATest = window.shoppayClientRefs && window.shoppayClientRefs.preferences.shoppayAATest ? window.shoppayClientRefs.preferences.shoppayAATest : false;\nvar session;\n\n$(document).ready(function () {\n    if (window.ShopPay) {\n        initShopPayConfig();\n\t\tif (window.shoppayClientRefs.preferences.shoppayEmailListenerEnabled && $('.shopify-email-listener').length) {\n\t\t\tinitShopPayEmailRecognition();\n\t\t}\n\t\tinitShopPayButton();\n        var readyOnPageLoad = helper.isReadyToOrderOnPageLoad();\n        if (readyOnPageLoad) {\n            var pageLoadData = helper.getInitProductData();\n            helper.setInitProductData(pageLoadData); // updates global prod data.\n        }\n\n        /*  The below code triggers if a product is a Buy Now item, but is not ready to order on page load\n            (ex: required product attributes like color or size are not yet chosen). Here, a watcher is set\n            to capture user interactions when product attributes are selected. Helper scripts will be triggered\n            by these interactions to determine if the item is ready to order when all required attributes are\n            selected.\n        */\n        if (isBuyNow && !readyOnPageLoad) {\n            $('body').on('product:afterAttributeSelect', initBuyNow); // receives the Event & Response\n        } else {\n            session = initShopPaySession();\n        }\n    }\n\n\t$(document).on('Cart.UpdateSuccess', function() {\n\t\tif (window.ShopPay && !isBuyNow) {\n\t\t\tif (!session) {\n\t\t\t\tsession = initShopPaySession();\n\t\t\t} else {\n\t\t\t\tvar paymentRequestResponse = helper.buildPaymentRequest(session);\n\t\t\t\tvar responseJSON =  paymentRequestResponse ? paymentRequestResponse.responseJSON : null;\n\t\n\t\t\t\tif (responseJSON) {\n\t\t\t\t\thelper.shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"));\n\t\t\t\t}\n\t\n\t\t\t\tif (responseJSON && !responseJSON.error && responseJSON.paymentRequest !== null) {\n\t\t\t\t\tsession.close();\n\t\t\t\t\tsession = initShopPaySession();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n});\n\nfunction initShopPayConfig() {\n    window.ShopPay.PaymentRequest.configure({\n        shopId: window.shoppayClientRefs.preferences.shoppayStoreId,\n        clientId: window.shoppayClientRefs.preferences.shoppayClientId,\n        debug: window.shoppayClientRefs.preferences.shoppayModalDebugEnabled\n    });\n}\n\nfunction initShopPayButton() {\n\tvar paymentSelectors = ['#shop-pay-button-container', '#shop-pay-button-container-mobile', '#shop-pay-button-container-desktop']\n\tfor (var paymentSelectorIndex in paymentSelectors) {\n\t\tvar paymentSelector = paymentSelectors[paymentSelectorIndex];\n\t\tif ($(paymentSelector).length > 0) {\n\t\t\twindow.ShopPay.PaymentRequest.createButton({buyWith: isBuyNow}).render(paymentSelector);\n\t\t\thelper.shoppayMutationObserver(paymentSelector);\n\t\t}\n\t}\n}\n\n\nfunction initBuyNow(e, response) {\n    var responseProduct = response.data.product;\n    var { buyNow, readyToOrder, id, selectedQuantity, options, childProducts } = responseProduct;\n\n    if (responseProduct && buyNow) {\n        if (readyToOrder) {\n            initShopPaySession(buyNow, readyToOrder);\n            helper.setInitProductData({\n                pid: id,\n                quantity: selectedQuantity,\n                options: options\n            });\n            if (childProducts) {\n                helper.productData.childProducts = childProducts;\n            }\n        }\n    }\n}\n\nfunction initShopPayEmailRecognition() {\n    /*  If your checkout is not built with SFRA or you have customized and removed the 'email-guest'\n        id on the email input you will need to update the id value for emailInputId\n\n        Note: A 1.5 second delay has been added before attaching to the email trigger to the email field to\n        accommodate users who may have incorporated browser autofills. The pop-up will appear if the field\n        is autofilled with a recognized email address\n    */\n    setTimeout(function() {\n\t\t$('.shopify-email-listener:visible').each(function() {\n\t\t\twindow.ShopPay.PaymentRequest.createLogin({emailInputId: $(this).attr('id')}).render('#shop-pay-login-container');\n\t\t});\n    }, 1500);\n}\n\n$('body').on('cart:update product:afterAddToCart promotion:success', function () {\n    /*  Only interested in cart updates on Cart page (cart updates are not triggered in checkout). Buy Now already\n        has a separate event handler for changes to attribute selections\n    */\n    if (window.ShopPay && !isBuyNow) {\n        if (!session) {\n            session = initShopPaySession();\n        } else {\n            var paymentRequestResponse = helper.buildPaymentRequest(session);\n            var responseJSON =  paymentRequestResponse ? paymentRequestResponse.responseJSON : null;\n\n            if (responseJSON) {\n                helper.shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"));\n            }\n\n            if (responseJSON && !responseJSON.error && responseJSON.paymentRequest !== null) {\n                session.close();\n                session = initShopPaySession();\n            }\n        }\n    }\n});\n\n\nfunction initShopPaySession(paymentRequestInput, readyToOrder) {\n    var paymentRequest;\n    var paymentRequestResponse;\n    var responseJSON;\n\n    if (isBuyNow && paymentRequestInput) {\n        paymentRequest = paymentRequestInput;\n    } else if (isBuyNow && !paymentRequestInput) {\n        var productData = helper.getInitProductData();\n        if (productData) {\n            paymentRequestResponse = helper.createResponse(productData, window.shoppayClientRefs.urls.BuyNowData);\n            if (paymentRequestResponse.exception || paymentRequestResponse.error){\n                /*  No need to close any session because a session does not exist at this point (has not yet been\n                    initiated). Return to exit function - don't reload the page in case there is a page rendering\n                    issue (will result in infinite reload loop).\n                */\n                return;\n            }\n            paymentRequest = paymentRequestResponse.paymentRequest;\n            responseJSON = paymentRequestResponse ? paymentRequestResponse : null;\n        }\n    } else {\n        paymentRequestResponse = helper.buildPaymentRequest(session);\n        responseJSON = paymentRequestResponse ? paymentRequestResponse.responseJSON : null;\n    }\n\n    if (paymentRequest || (responseJSON && !responseJSON.error)) {\n        var initialPaymentRequest = responseJSON && responseJSON.paymentRequest ? window.ShopPay.PaymentRequest.build(responseJSON.paymentRequest) : window.ShopPay.PaymentRequest.build(paymentRequest);\n        // Enable BuyNow Button Click on PDP if Product is Ready To Order\n        helper.shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"), readyToOrder);\n\n        var shoppaySession = window.ShopPay.PaymentRequest.createSession({\n            paymentRequest: initialPaymentRequest\n        });\n\n        if (shoppaySession) {\n            helper.setSessionListeners(shoppaySession);\n            $('body').off('product:afterAttributeSelect', initBuyNow);\n\n            $('body').on('product:afterAttributeSelect', function(e, response) {\n                var responseProduct = response.data.product;\n                if (isBuyNow && responseProduct.buyNow) {\n                    helper.setInitProductData({\n                        pid: responseProduct.id,\n                        quantity: responseProduct.selectedQuantity,\n                        options: responseProduct.options\n                    });\n                    if (shoppaySession) {\n                        shoppaySession.close();\n                        let updatedPaymentRequest = window.ShopPay.PaymentRequest.build(responseProduct.buyNow);\n                        shoppaySession = window.ShopPay.PaymentRequest.createSession({\n                            paymentRequest: updatedPaymentRequest\n                        });\n\n                        helper.setSessionListeners(shoppaySession);\n                    }\n\n                } else {\n                    $.ajax({\n                        url: helper.getUrlWithCsrfToken(window.shoppayClientRefs.urls.GetCartSummary),\n                        type: 'GET',\n                        contentType: 'application/json',\n                        async: false,\n                        success: function (data) {\n                            if (!data.error) {\n                                if (shoppaySession) {\n                                    shoppaySession.close();\n                                }\n                                let paymentRequest = window.ShopPay.PaymentRequest.build(response.product.buyNow);\n                                shoppaySession = window.ShopPay.PaymentRequest.createSession({\n                                    paymentRequest: paymentRequest\n                                });\n                                helper.setSessionListeners(shoppaySession);\n                            }\n                        },\n                        error: function (err) {\n                            if (err.responseJSON || err.status !== 200) {\n                                session.close();\n                                // modal hasn't opened yet so \"windowclosed\" listener won't fire\n                                window.location.reload();\n                                return;\n                            }\n                        }\n                    });\n                }\n            });\n        }\n\n        return shoppaySession;\n    }\n}\n\nmodule.exports = {\n    initShopPaySession: initShopPaySession\n};","/* eslint-disable no-unused-vars */\n/* Global Variables */\nlet checkoutUrl = null;\nlet observer;\nlet orderConfirmationData;\nlet productData = {};\nlet reloadOnClose = true;\nlet sourceIdentifier = null;\nconst technicalErrorMsg = window.shoppayClientRefs ? window.shoppayClientRefs.constants.technicalError : null;\nlet token = null;\n\n/**\n * Add csrf token param to url\n * @param {string} url - source url\n * @param {string} basketId - UUID of the temporary basket in the session, if applicable\n * @returns {string} - url with csrf_token param\n */\nfunction getUrlWithCsrfToken(url, basketId) {\n    const urlInstance = new URL(url, location.origin);\n\n    urlInstance.searchParams.append('csrf_token', getCsrfToken());\n\n    if (basketId) {\n        urlInstance.searchParams.append('basketId', basketId);\n    }\n\n    return urlInstance.toString();\n}\n\n/**\n * Get CSRF Token\n * @returns {string} - csrf token value\n */\nfunction getCsrfToken() {\n    let $element = document.querySelector('[data-csrf-token]');\n\n    if ($element && $element.attributes['data-csrf-token'] && $element.attributes['data-csrf-token'].value) {\n        return $element.attributes['data-csrf-token'].value;\n    }\n\n    return '';\n}\n\n/**\n * Get Init Product Data (page load and captures data available on page load)\n * @returns {Object} - productData with the following structure: { pid: prodId, quantity: selectedQuantity, options: selectedOptions }\n */\nfunction getInitProductData() {\n    let productData = null;\n    let $element = document.querySelector('[data-buy-now-init]');\n    if ($element && $element.attributes['data-buy-now-init'] && $element.attributes['data-buy-now-init'].value) {\n        productData = JSON.parse($element.attributes['data-buy-now-init'].value);\n    }\n    return productData;\n}\n\n/**\n * Set Init Product Data\n * @param {Object} data - accepts product data obj & updates global productData variable: { pid: prodId, quantity: selectedQuantity, options: selectedOptions }\n */\nfunction setInitProductData(data) {\n    productData = data;\n}\n\n/**\n * Sets Up ShopPay listener Events\n * @param {Object} session - Accepts the Shop Pay session object and establishes necessary event listeners on the session.\n */\nfunction setSessionListeners(session) {\n    session.addEventListener(\"sessionrequested\", function (ev) {\n        let sessionPaymentRequest;\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            $.ajax({\n                url: getUrlWithCsrfToken(window.shoppayClientRefs.urls.PrepareBasket),\n                method: 'POST',\n                async: false,\n                data: JSON.stringify(productData),\n                contentType: 'application/json',\n                success: function (data) {\n                    if (!data.error) {\n                        sessionPaymentRequest = data.paymentRequest;\n                        sourceIdentifier = data.basketId;\n                    } else {\n                        /*  session.completeSessionRequest() does not take an errors array as input so just return\n                            and use default modal error handling.\n                        */\n                        return;\n                    }\n                },\n                error: function (err) {\n                    /*  session.completeSessionRequest() does not take an errors array as input so just\n                        destroy the session and return.\n                    */\n                    setTimeout(function() {\n                        session.close();\n                        // Event listeners have loaded so window.location.reload() will be called in windowclosed\n                    }, 2000);\n                    return;\n                }\n            });\n        } else {\n            sessionPaymentRequest = session.paymentRequest;\n        }\n\n        let requestData = {\n            paymentRequest: sessionPaymentRequest\n        };\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        $.ajax({\n            url: getUrlWithCsrfToken(window.shoppayClientRefs.urls.BeginSession),\n            method: 'POST',\n            async: false,\n            data: JSON.stringify(requestData),\n            contentType: 'application/json',\n            success: function (data) {\n                if (!data.error) {\n                    token = data.token;\n                    checkoutUrl = data.checkoutUrl;\n                    sourceIdentifier = data.sourceIdentifier;\n                    session.completeSessionRequest({token, checkoutUrl, sourceIdentifier});\n                } else {\n                    let errorMsg = technicalErrorMsg;\n                    if (data.errorMsg) {\n                        errorMsg = data.errorMsg;\n                    }\n                    /*  session.completeSessionRequest() does not take an errors array as input so just return\n                        and use default modal error handling.\n                    */\n                    return;\n                }\n            },\n            error: function (err) {\n                /*  session.completeSessionRequest() does not take an errors array as input so just\n                    destroy the session and return.\n                */\n                setTimeout(function() {\n                    session.close();\n                    // Event listeners have loaded so window.location.reload() will be called in windowclosed\n                }, 2000);\n                return;\n            }\n\n        });\n    });\n\n    session.addEventListener(\"discountcodechanged\", function(ev) {\n        const currentPaymentRequest = session.paymentRequest;\n        let requestData = {\n            discountCodes: ev.discountCodes\n        };\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        let responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.DiscountCodeChanged);\n        if (responseJSON.exception){\n            session.completeDiscountCodeChange({\n                errors: [\n                    {\n                        type: \"discountCodeError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            let errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completeDiscountCodeChange({\n                errors: [\n                    {\n                        type: \"discountCodeError\",\n                        message: errorMsg\n                    }\n                ]\n            });\n            return;\n        }\n        const { deliveryMethods, discountCodes, lineItems, shippingLines, subtotal, discounts, totalShippingPrice, totalTax, total } = responseJSON.paymentRequest;\n\n\t\tvar paymentRequestObject = {};\n\t\tfor (var propertyKey in currentPaymentRequest) {\n\t\t\tpaymentRequestObject[propertyKey] = currentPaymentRequest[propertyKey];\n\t\t}\n\n        let updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, {\n            // ...currentPaymentRequest,\n            discountCodes: discountCodes,\n            lineItems: lineItems,\n            shippingLines: shippingLines,\n            deliveryMethods: deliveryMethods,\n            subtotal: subtotal,\n            discounts: discounts,\n            totalTax: totalTax,\n            total: total\n        }));\n        if (totalShippingPrice) {\n            updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(updatedPaymentRequest, {\n                // ...updatedPaymentRequest,\n                totalShippingPrice: totalShippingPrice\n            }));\n        }\n\n        session.completeDiscountCodeChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n\n    session.addEventListener(\"deliverymethodchanged\", function(ev) {\n        const currentPaymentRequest = session.paymentRequest;\n        let requestData = {\n            deliveryMethod: ev.deliveryMethod,\n            paymentRequest: currentPaymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        let responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.DeliveryMethodChanged);\n        if (responseJSON.exception) {\n            session.completeDeliveryMethodChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            let errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            const { shippingLines, totalShippingPrice, totalTax, total } = responseJSON.paymentRequest;\n            const updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, {\n                // ...currentPaymentRequest,\n                shippingLines: shippingLines,\n                totalShippingPrice: totalShippingPrice,\n                totalTax: totalTax,\n                total: total\n            }));\n\n            session.completeDeliveryMethodChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: errorMsg\n                    }\n                ],\n                updatedPaymentRequest: updatedPaymentRequest\n            });\n            return;\n        }\n        const { shippingLines, totalShippingPrice, totalTax, total } = responseJSON.paymentRequest;\n\n        // Update the payment request based on the delivery method change and update the total accordingly\n        const updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, {\n            // ...currentPaymentRequest,\n            shippingLines: shippingLines,\n            totalShippingPrice: totalShippingPrice,\n            totalTax: totalTax,\n            total: total\n        }));\n\n        session.completeDeliveryMethodChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n\n    session.addEventListener(\"shippingaddresschanged\", function(ev) {\n        const currentPaymentRequest = session.paymentRequest;\n        if (!ev.shippingAddress) {\n            /* This event is triggered with no shipping address when a customer clicks \"change\"\n               to choose an alternate email address in the modal\n            */\n            session.completeShippingAddressChange({ updatedPaymentRequest: currentPaymentRequest });\n            return;\n        }\n        let requestData = {\n            shippingAddress: ev.shippingAddress,\n            paymentRequest: currentPaymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        let responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.ShippingAddressChanged);\n        if (responseJSON.exception) {\n            session.completeShippingAddressChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            let errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completeShippingAddressChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: errorMsg\n                    }\n                ]\n            });\n            return;\n        }\n        const { deliveryMethods, shippingLines, totalShippingPrice, totalTax, total } = responseJSON.paymentRequest;\n\n        // Update the payment request based on the shipping address change\n        const updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, {\n            // ...currentPaymentRequest,\n            deliveryMethods: deliveryMethods,\n            shippingLines: shippingLines,\n            totalShippingPrice: totalShippingPrice,\n            totalTax: totalTax,\n            total: total\n        }));\n\n        session.completeShippingAddressChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n\n    session.addEventListener(\"paymentconfirmationrequested\", function(ev) {\n        const requestData = {\n            token: session.token,\n            paymentRequest: session.paymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        let responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.SubmitPayment);\n        if (responseJSON.exception) {\n            session.completePaymentConfirmationRequest({\n                errors: [\n                    {\n                        type: \"generalError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            let errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completePaymentConfirmationRequest({\n                errors: [\n                    {\n                        type: \"generalError\",\n                        message: errorMsg\n                    }\n                ]\n            });\n            return;\n        }\n\n        orderConfirmationData = {\n            orderID: responseJSON.orderID,\n            orderToken: responseJSON.orderToken,\n            continueUrl: responseJSON.continueUrl\n        };\n        session.completePaymentConfirmationRequest();\n    });\n\n    session.addEventListener(\"paymentcomplete\", function(ev) {\n\t\tvar requestData = {\n            token: session.token,\n            paymentRequest: session.paymentRequest,\n\t\t\tevent: ev\n        };\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\t\tvar responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.PaymentComplete);\n\t\tif (ev.processingStatus.status === \"completed\") {\n\t\t\treloadOnClose = false;\n\t\t\tsession.close();\n\t\t\tvar data = orderConfirmationData;\n\t\t\tvar redirect = $('<form>').appendTo(document.body).attr({\n\t\t\t\tmethod: 'POST',\n\t\t\t\taction: data.continueUrl\n\t\t\t});\n\t\t\t$('<input>').appendTo(redirect).attr({\n\t\t\t\tname: 'orderID',\n\t\t\t\tvalue: data.orderID\n\t\t\t});\n\t\t\t$('<input>').appendTo(redirect).attr({\n\t\t\t\tname: 'orderToken',\n\t\t\t\tvalue: data.orderToken\n\t\t\t});\n\t\t\tredirect.submit();\n\t\t}\n    });\n\n    session.addEventListener(\"windowclosed\", function(ev) {\n        // Reset global value to default\n        // if (!reloadOnClose) {\n        //     reloadOnClose = true;\n        // } else {\n        //     window.location.reload();\n        // }\n\t\tvar requestData = {\n            token: session.token,\n            paymentRequest: session.paymentRequest,\n\t\t\tevent: ev\n        };\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\t\tvar responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.WindowClosed);\n    });\n\n\tsession.addEventListener(\"deliverymethodtypechanged\", function(ev) {\n\t\tvar currentPaymentRequest = session.paymentRequest;\n        var requestData = {\n            deliveryMethodType: ev.deliveryMethodType,\n            paymentRequest: currentPaymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        var responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.DeliveryMethodTypeChanged);\n\t\tvar updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, responseJSON.paymentRequest));\n        if (responseJSON.exception) {\n            session.completeDeliveryMethodTypeChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            var errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completeDeliveryMethodTypeChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: errorMsg\n                    }\n                ],\n                updatedPaymentRequest: updatedPaymentRequest\n            });\n            return;\n        }\n\t\tsession.completeDeliveryMethodTypeChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n\n\tsession.addEventListener(\"pickuplocationchanged\", function(ev) {\n\t\tvar currentPaymentRequest = session.paymentRequest;\n        var requestData = {\n            pickupLocation: ev.pickupLocation,\n            paymentRequest: currentPaymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        var responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.PickupLocationChanged);\n\t\tvar updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, responseJSON.paymentRequest));\n        if (responseJSON.exception) {\n            session.completePickupLocationChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            var errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completePickupLocationChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: errorMsg\n                    }\n                ],\n                updatedPaymentRequest: updatedPaymentRequest\n            });\n            return;\n        }\n\t\tsession.completePickupLocationChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n\n\tsession.addEventListener(\"pickuplocationfilterchanged\", function(ev) {\n\t\tvar currentPaymentRequest = session.paymentRequest;\n        var requestData = {\n            buyerLocation: ev.buyerLocation,\n            paymentRequest: currentPaymentRequest,\n        };\n\n        if (window.shoppayClientRefs.constants.isBuyNow) {\n            requestData.basketId = sourceIdentifier;\n        }\n\n        var responseJSON = createResponse(requestData, window.shoppayClientRefs.urls.PickupLocationFilterChanged);\n\t\tvar updatedPaymentRequest = window.ShopPay.PaymentRequest.build($.extend(currentPaymentRequest, responseJSON.paymentRequest));\n        if (responseJSON.exception) {\n            session.completePickupLocationFilterChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: technicalErrorMsg\n                    }\n                ]\n            });\n            setTimeout(function() {\n                session.close();\n                // Event listeners have loaded so window.location.reload() will be called in windowclosed\n            }, 2000);\n            return;\n        } else if (responseJSON.error) {\n            var errorMsg = technicalErrorMsg;\n            if (responseJSON.errorMsg) {\n                errorMsg = responseJSON.errorMsg;\n            }\n            session.completePickupLocationFilterChange({\n                errors: [\n                    {\n                        type: \"shippingAddressError\",\n                        message: errorMsg\n                    }\n                ],\n                updatedPaymentRequest: updatedPaymentRequest\n            });\n            return;\n        }\n\t\tsession.completePickupLocationFilterChange({ updatedPaymentRequest: updatedPaymentRequest });\n    });\n}\n\n/**\n * Enables & Disables Shop Pay's Buy Now button click based on whether the product is ready to order on the PDP\n */\nfunction shoppayBtnDisabledStyle(elem, isReadyToOrder, forceDisable) {\n    let readyToOrderPageLoad = isReadyToOrderOnPageLoad();\n    let isBuyNow = window.shoppayClientRefs.constants.isBuyNow;\n\n    if (elem) {\n        // An error occurred, disable the button\n        if (!isBuyNow && forceDisable) {\n            elem.style.pointerEvents = 'none';\n            if (observer) {\n                observer.disconnect();\n            }\n            return;\n        }\n        if (!isBuyNow || (isBuyNow && (isReadyToOrder || readyToOrderPageLoad))) {\n            elem.style.pointerEvents = 'auto';\n        } else {\n            elem.style.pointerEvents = 'none';\n        }\n    }\n}\n\n/**\n * Watches for when ShopPay button is first rendered to the page to then apply correct button styling depending on whether the basket is empty or not\n */\nfunction shoppayMutationObserver(elemSelector) {\n    observer = new MutationObserver((mutationsList, observer) => {\n        const renderedShopPayElem = document.querySelector(elemSelector);\n        if (renderedShopPayElem) {\n            shoppayBtnDisabledStyle(renderedShopPayElem);\n            observer.disconnect();\n        }\n    });\n\n    observer.observe(document.body, { childList: true, subtree: true });\n}\n\n/**\n * Checks whether a Buy Now product is ready on page load or not (ex: simple products vs. variants with multiple options to choose from, etc.)\n */\nfunction isReadyToOrderOnPageLoad() {\n    let readyToOrder = false;\n    let $element = document.querySelector('[data-ready-to-order]');\n    if ($element && $element.attributes['data-ready-to-order'] && $element.attributes['data-ready-to-order'].value) {\n        readyToOrder = $element.attributes['data-ready-to-order'].value === \"true\";\n    }\n    return readyToOrder;\n}\n\n/**\n * Handles AJAX call to create / update the payment response needed for the ShopPay.PaymentRequest.build() method.\n * @param {Object} requestObj - a request object that contains relevant event data & session data.\n * @param {string} controllerURL - String url of the targeted controller (based on the urls Obj set in shoppayGlobalRefs.js)\n * @returns {Object} responseJSON - an updated response object to be used in the build & on the ShopPay.PaymentRequest object.\n */\nfunction createResponse (requestObj, controllerURL) {\n    let responseJSON;\n    $.ajax({\n        url: getUrlWithCsrfToken(controllerURL),\n        method: 'POST',\n        async: false,\n        data: JSON.stringify(requestObj),\n        contentType: 'application/json',\n        success: function(data) {\n            responseJSON = data;\n            responseJSON.exception = false;\n        },\n        error: function (err) {\n            responseJSON = err.responseJSON ? err.responseJSON : {};\n            responseJSON.exception = true;\n        }\n    });\n\n    return responseJSON;\n}\n\n/**\n * Handles AJAX call to get the payment response.\n * @returns {Object} paymentResponse - an response object.\n */\nfunction buildPaymentRequest(session) {\n    let token = document.querySelector('[data-csrf-token]');\n    let response;\n    if (token) {\n        const paymentResponse = $.ajax({\n            url: getUrlWithCsrfToken(window.shoppayClientRefs.urls.GetCartSummary),\n            type: 'GET',\n            contentType: 'application/json',\n            async: false,\n            success: function(data) {\n                if (!data.error) {\n                    response = {\n                        responseJSON: data\n                    };\n                } else {\n                    shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"), null, true);\n                }\n            },\n            error: function(err) {\n                if (session) {\n                    /*  Return to exit function - don't reload the page in case there is a page rendering\n                        issue (will result in infinite reload loop).\n                    */\n                    session.close();\n                }\n                shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"), null, true);\n            }\n        });\n        return response;\n    } else {\n        /*  Return to exit function - don't reload the page in case there is a page rendering\n            issue (will result in infinite reload loop).\n        */\n        if (session) {\n            session.close();\n        }\n        shoppayBtnDisabledStyle(document.getElementById(\"shop-pay-button-container\"), null, true);\n    }\n}\n\nmodule.exports = {\n    buildPaymentRequest: buildPaymentRequest,\n    createResponse: createResponse,\n    getCsrfToken: getCsrfToken,\n    getInitProductData: getInitProductData,\n    getUrlWithCsrfToken: getUrlWithCsrfToken,\n    isReadyToOrderOnPageLoad: isReadyToOrderOnPageLoad,\n    productData: productData,\n    setInitProductData: setInitProductData,\n    setSessionListeners: setSessionListeners,\n    shoppayBtnDisabledStyle: shoppayBtnDisabledStyle,\n    shoppayMutationObserver: shoppayMutationObserver,\n};\n","'use strict';\n\nexports.ServiceSuffixes = {\n\tServiceSuite: '/ecomm/0.1',\n\tAuthenticate: '/authenticate/root',\n\tPurchaseGiftCard: '/fulfillment/0.1/purchaseegift/'\n};\n\nexports.MessagePrefixes = {\n\tNonSuccess: 'Stored Value Solutions returned a result other than OK and/or without data ',\n\tError: 'Stored Value Solutions encountered and unexpected exception '\n};\n\nexports.TransactionInformation = {\n\tSuccess: 'Successful Transaction - No Additional Information',\n\tFailure: {\n\t\tBalanceExceeded: 'Order Failure - Requested Amount Exceeded Gift Card Balance',\n\t\tHeldAmountReleased: 'Order Failure - Releasing Amount Held by Pre-Authorization'\n\t}\n}\n\nexports.TransactionTypes = {\n\tBalanceInquiry: 'Balance Inquiry',\n\tPreAuthorization: 'Pre-Authorization',\n\tPreAuthorizationComplete: 'Pre-Authorization Complete'\n}\n\nexports.ResponseParsers = {\n\tbalanceInquiryResponse: {\n\t\tPath: '/int_svs/cartridge/scripts/BalanceInquiryResponseParser',\n\t\tBodyNode: 'balanceInquiryReturn'\n\t},\n\tpreAuthResponse: {\n\t\tPath: '/int_svs/cartridge/scripts/PreAuthorizationResponseParser',\n\t\tBodyNode: 'preAuthReturn'\n\t},\n\tpreAuthCompleteResponse: {\n\t\tPath: '/int_svs/cartridge/scripts/PreAuthorizationCompleteResponseParser',\n\t\tBodyNode: 'preAuthCompleteReturn'\n\t}\n};\n\nexports.ReturnCodes = {\n\tApproval: '01',\n\tInactiveCard: '02',\n\tInvalidCardNumber: '03',\n\tInvalidTransactionCode: '04',\n\tInsufficientFunds: '05',\n\tNoPreviousAuthorizations: '06',\n\tInvalidMessage: '07',\n\tNoCardFound: '08',\n\tInsufficentFundsDueToOutstandingPreAuthorization: '09',\n\tDenialNoPreviousAuthorization: '10',\n\tNoAuthorizationNumber: '11',\n\tInvalidAuthorizationNumber: '12',\n\tMaximumSingleRechargeExceeded: '13',\n\tMaximumWOrkingBalanceExceeded: '14',\n\tHostUnavailable: '15',\n\tInvalidCardStatus: '16',\n\tUnknownDealerStoreCodeSpecialEdit: '17',\n\tMaximumNumberOfRechargesExceeded: '18',\n\tInvalidCardVerificationValueOrSecondarySecurityCode: '19',\n\tInvalidPinNumberOrPinLocked: '20',\n\tCardAlreadyIssued: '21',\n\tCardNotIssued: '22',\n\tCardAlreadyUsed: '23',\n\tManualTransactionNotAllowed: '24',\n\tMagStripeReadNotValid: '25',\n\tTransactionTypeUnknown: '26',\n\tInvalidTenderType: '27',\n\tInvalidCustomerType: '28',\n\tMaxNumbherOfRedemptionExceeded: '30',\n\tInvalidCurrencyCode: '31',\n\tInvalidServerId: '32',\n\tFrozenCardOrUnknown: '33',\n\tInvalidAmount: '34',\n\tTransactionRejectedInvalidTransactionPromotionWideOrInvalidForOriginatingMerchantAndStore: '36',\n\tTransactionRejectedInvalidMerchantAndStoreCombinationForPromotion: '37',\n\tTransactionRejectedExceededMaximumNumberOfPromotionCards: '38',\n\tTransactionDeclinedAmountLessThanMinimum: '42',\n\tFailureInRetrievingData: '99',\n\tRateLimitExceeded: '999'\n};\n\nexports.ReturnDescriptionMessagesForReturnCodes = {\n\t'03': 'Invalid Card or PIN Number',\n\t'08': 'Invalid Card or PIN Number',\n\t'20': 'Invalid Card or PIN Number'\n}\n\nexports.GiftCardTypes = {\n\teGift: 'eGift',\n\tPhysical: 'Physical',\n\tNotApplicable: 'NotApplicable'\n};\n\nexports.OrderTypes = {\n\tInteractive: 'I',\n\tWeb: 'W'\n};"],"preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvaW1hZ2VzbG9hZGVkL2ltYWdlc2xvYWRlZC5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvbm9kZV9tb2R1bGVzL2V2ZW50aWUvZXZlbnRpZS5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvbm9kZV9tb2R1bGVzL3dvbGZ5ODctZXZlbnRlbWl0dGVyL0V2ZW50RW1pdHRlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL3Byb21pc2UvbGliL2RvbmUuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZXM2LWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZmluYWxseS5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9ub2RlLWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvc3luY2hyb25vdXMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9ub2RlX21vZHVsZXMvYXNhcC9icm93c2VyLWFzYXAuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9ub2RlX21vZHVsZXMvYXNhcC9icm93c2VyLXJhdy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9Cb290QmFybkV4cHJlc3MvY29tcG9uZW50cy9Cb290QmFybkV4cHJlc3NSZWZpbmVtZW50V2l6YXJkLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL0xvYi9BZGRyZXNzQXV0b2NvbXBsZXRlL0FkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvTG9iL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9hamF4LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2FsZXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2FwcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib251cy1wcm9kdWN0cy12aWV3LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2JvcGlzL2NvbXBvbmVudHMvQWRkVG9DYXJ0T3B0aW9ucy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL0FkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL0xvY2FsRGVsaXZlcnlEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvYm9waXMvY29tcG9uZW50cy9Mb2NhdGlvblNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL1Byb2R1Y3RMaW5lSXRlbUhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL1Nob3BZb3VyU3RvcmVEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvYm9waXMvY29tcG9uZW50cy9TdG9yZVNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jYXB0Y2hhLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBhcmUtd2lkZ2V0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvQ2Fyb3VzZWxWaWRlby5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0Nvb2tpZU5vdGlmaWNhdGlvbi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0VtYWlsRm9ybS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0VtYWlsU2lnbnVwLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvR2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0dpZnRDYXJkQmFsYW5jZUlucXVpcnlEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9HbG9iYWxlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvSW1hZ2VHYWxsZXJ5L1NsaWNrQW5kSW1nVmlld2VyMi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0ltYWdlR2FsbGVyeS9Td2lwZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvTmF2aWdhdGlvbkNvbnRyb2xsZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9PcmRlclN0YXR1c0Zvcm0uanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9SZWNhcHRjaGEuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9SZWNlbnRseVZpZXdlZFByb2R1Y3RzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvU2FtZURheVNoaXBwaW5nQ291bnRkb3duLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2Nvb2tpZXByaXZhY3kuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY291bnRkb3duLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvdW50cmllcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9kaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZmluZE1vcmVTdG9yZXMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZ2lmdGNhcmQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZ2lmdGNlcnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvaGVscGVycy9HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5SGVscGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2hlbHBlcnMvUmVxdWVzdEhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9qcXVlcnktZXh0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xhenlsb2FkUGFnZUVsZW1lbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xvZ2luLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xvZ2luRGlhbG9nLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL21pbmljYXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2UuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvQXV0aGVudGljYXRpb24vRW1haWxBZGRyZXNzQ2FwdHVyZS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9hY2NvdW50LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2Jvb3RiYXJuZXhwcmVzcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9ib290ZmluZGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NhcnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2FydF9lY2hvLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NhdGVnb3J5bGFuZGluZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9BcHBsZVBheS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9HaWZ0Q2FyZFBheW1lbnRQYW5lbC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9Mb3lhbHR5Q3JlZGl0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L1BheW1lbnRWb3VjaGVyUGF5bWVudFBhbmVsLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L1Jld2FyZHNDcmVkaXQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvYWRkcmVzcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9iaWxsaW5nLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L2Zvcm1QcmVwYXJlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L2luZGV4LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L211bHRpc2hpcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9vcGNhZGRyZXNzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L29wY2FkZHJlc3NfZW5oYW5jZWQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvb3BjcGF5bWVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9zaGlwcGluZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dF9lY2hvLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NvbXBhcmUuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY29udGVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9vbmVwY2hlY2tvdXQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvb25lcGNoZWNrb3V0X2dyb3Vwcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9vcmRlcmNvbmZpcm1hdGlvbi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2FkZFRvQ2FydC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2F2YWlsYWJpbGl0eS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2ltYWdlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvaW5kZXguanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC9wcm9kdWN0U2V0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvcmVxdWVzdEdpZnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC92YXJpYW50LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvdmlkZW8uanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcmVnaXN0cnkuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvc2VhcmNoLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3N0b3JlZnJvbnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvc3RvcmVsb2NhdG9yLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BvcHVwLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3Byb2R1Y3QtdGlsZS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wcm9kdWN0Um90YXRlM2QuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcHJvZ3Jlc3MuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcXVhbnRpdHlTdGVwcGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3F1aWNrdmlldy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9yYXRpbmcuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcmVnaXN0ZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc2VhcmNoYmFyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NlYXJjaHBsYWNlaG9sZGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NpemUtcmVmaW5lbWVudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc2xpY2tTbGlkZXJIZWxwZXJzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NsaWRlcnMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc3RvcmVpbnZlbnRvcnkvY2FydC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9pbmRleC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9wcm9kdWN0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3N0eWxlLWNvdW50cy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy90bHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvdG9vbHRpcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy91dGlsLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3ZhbGlkYXRvci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy93YXRlcm1hcmsuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvd2lzaGxpc3QuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY291bnRyeW91dGZpdHRlcnMvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvZGF0YS9TdGF0ZVRvWmlwQ29kZU1hcC5qc29uIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvZGF0YS9aaXBDb2RlVG9TdGF0ZU1hcC5qc29uIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQ2hlY2tvdXRDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9EYXRhTGF5ZXJDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9HZW9sb2NhdGlvbi9HZW9sb2NhdGlvbkhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9SZWZpbmVtZW50Q29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUmVnZXhQYXR0ZXJucy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9ib290YmFybl9yc3AvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2ludF9zaG9wcGF5X3NmcmEvY2FydHJpZGdlL2NsaWVudC9kZWZhdWx0L2pzL2NhcnQvaW5pdFNob3BQYXlDYXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2ludF9zaG9wcGF5X3NmcmEvY2FydHJpZGdlL2NsaWVudC9kZWZhdWx0L2pzL2hlbHBlcnMvc2hvcHBheUhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9pbnRfc3ZzL2NhcnRyaWRnZS9zY3JpcHRzL0dpZnRDYXJkQ29uc3RhbnRzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMxZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMvallBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDL05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3prQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDelhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxa0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ovQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbm5CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2x2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDanNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvcUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsZ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0NEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2h3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3g0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNseUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL09BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN2NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM2lCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBOztBQ0FBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3paQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMXNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvKiFcbiAqIGltYWdlc0xvYWRlZCB2My4yLjBcbiAqIEphdmFTY3JpcHQgaXMgYWxsIGxpa2UgXCJZb3UgaW1hZ2VzIGFyZSBkb25lIHlldCBvciB3aGF0P1wiXG4gKiBNSVQgTGljZW5zZVxuICovXG5cbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHsgJ3VzZSBzdHJpY3QnO1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cblxuICAvKmdsb2JhbCBkZWZpbmU6IGZhbHNlLCBtb2R1bGU6IGZhbHNlLCByZXF1aXJlOiBmYWxzZSAqL1xuXG4gIGlmICggdHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG4gICAgLy8gQU1EXG4gICAgZGVmaW5lKCBbXG4gICAgICAnZXZlbnRFbWl0dGVyL0V2ZW50RW1pdHRlcicsXG4gICAgICAnZXZlbnRpZS9ldmVudGllJ1xuICAgIF0sIGZ1bmN0aW9uKCBFdmVudEVtaXR0ZXIsIGV2ZW50aWUgKSB7XG4gICAgICByZXR1cm4gZmFjdG9yeSggd2luZG93LCBFdmVudEVtaXR0ZXIsIGV2ZW50aWUgKTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShcbiAgICAgIHdpbmRvdyxcbiAgICAgIHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyksXG4gICAgICByZXF1aXJlKCdldmVudGllJylcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmltYWdlc0xvYWRlZCA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICB3aW5kb3cuRXZlbnRFbWl0dGVyLFxuICAgICAgd2luZG93LmV2ZW50aWVcbiAgICApO1xuICB9XG5cbn0pKCB3aW5kb3csXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICBmYWN0b3J5IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIGZhY3RvcnkoIHdpbmRvdywgRXZlbnRFbWl0dGVyLCBldmVudGllICkge1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciAkID0gd2luZG93LmpRdWVyeTtcbnZhciBjb25zb2xlID0gd2luZG93LmNvbnNvbGU7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLy8gZXh0ZW5kIG9iamVjdHNcbmZ1bmN0aW9uIGV4dGVuZCggYSwgYiApIHtcbiAgZm9yICggdmFyIHByb3AgaW4gYiApIHtcbiAgICBhWyBwcm9wIF0gPSBiWyBwcm9wIF07XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbnZhciBvYmpUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5mdW5jdGlvbiBpc0FycmF5KCBvYmogKSB7XG4gIHJldHVybiBvYmpUb1N0cmluZy5jYWxsKCBvYmogKSA9PSAnW29iamVjdCBBcnJheV0nO1xufVxuXG4vLyB0dXJuIGVsZW1lbnQgb3Igbm9kZUxpc3QgaW50byBhbiBhcnJheVxuZnVuY3Rpb24gbWFrZUFycmF5KCBvYmogKSB7XG4gIHZhciBhcnkgPSBbXTtcbiAgaWYgKCBpc0FycmF5KCBvYmogKSApIHtcbiAgICAvLyB1c2Ugb2JqZWN0IGlmIGFscmVhZHkgYW4gYXJyYXlcbiAgICBhcnkgPSBvYmo7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBvYmoubGVuZ3RoID09ICdudW1iZXInICkge1xuICAgIC8vIGNvbnZlcnQgbm9kZUxpc3QgdG8gYXJyYXlcbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgb2JqLmxlbmd0aDsgaSsrICkge1xuICAgICAgYXJ5LnB1c2goIG9ialtpXSApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBhcnJheSBvZiBzaW5nbGUgaW5kZXhcbiAgICBhcnkucHVzaCggb2JqICk7XG4gIH1cbiAgcmV0dXJuIGFyeTtcbn1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBpbWFnZXNMb2FkZWQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvKipcbiAgICogQHBhcmFtIHtBcnJheSwgRWxlbWVudCwgTm9kZUxpc3QsIFN0cmluZ30gZWxlbVxuICAgKiBAcGFyYW0ge09iamVjdCBvciBGdW5jdGlvbn0gb3B0aW9ucyAtIGlmIGZ1bmN0aW9uLCB1c2UgYXMgY2FsbGJhY2tcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gb25BbHdheXMgLSBjYWxsYmFjayBmdW5jdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gSW1hZ2VzTG9hZGVkKCBlbGVtLCBvcHRpb25zLCBvbkFsd2F5cyApIHtcbiAgICAvLyBjb2VyY2UgSW1hZ2VzTG9hZGVkKCkgd2l0aG91dCBuZXcsIHRvIGJlIG5ldyBJbWFnZXNMb2FkZWQoKVxuICAgIGlmICggISggdGhpcyBpbnN0YW5jZW9mIEltYWdlc0xvYWRlZCApICkge1xuICAgICAgcmV0dXJuIG5ldyBJbWFnZXNMb2FkZWQoIGVsZW0sIG9wdGlvbnMsIG9uQWx3YXlzICk7XG4gICAgfVxuICAgIC8vIHVzZSBlbGVtIGFzIHNlbGVjdG9yIHN0cmluZ1xuICAgIGlmICggdHlwZW9mIGVsZW0gPT0gJ3N0cmluZycgKSB7XG4gICAgICBlbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCggZWxlbSApO1xuICAgIH1cblxuICAgIHRoaXMuZWxlbWVudHMgPSBtYWtlQXJyYXkoIGVsZW0gKTtcbiAgICB0aGlzLm9wdGlvbnMgPSBleHRlbmQoIHt9LCB0aGlzLm9wdGlvbnMgKTtcblxuICAgIGlmICggdHlwZW9mIG9wdGlvbnMgPT0gJ2Z1bmN0aW9uJyApIHtcbiAgICAgIG9uQWx3YXlzID0gb3B0aW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgZXh0ZW5kKCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMgKTtcbiAgICB9XG5cbiAgICBpZiAoIG9uQWx3YXlzICkge1xuICAgICAgdGhpcy5vbiggJ2Fsd2F5cycsIG9uQWx3YXlzICk7XG4gICAgfVxuXG4gICAgdGhpcy5nZXRJbWFnZXMoKTtcblxuICAgIGlmICggJCApIHtcbiAgICAgIC8vIGFkZCBqUXVlcnkgRGVmZXJyZWQgb2JqZWN0XG4gICAgICB0aGlzLmpxRGVmZXJyZWQgPSBuZXcgJC5EZWZlcnJlZCgpO1xuICAgIH1cblxuICAgIC8vIEhBQ0sgY2hlY2sgYXN5bmMgdG8gYWxsb3cgdGltZSB0byBiaW5kIGxpc3RlbmVyc1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG4gICAgICBfdGhpcy5jaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgSW1hZ2VzTG9hZGVkLnByb3RvdHlwZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLm9wdGlvbnMgPSB7fTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmdldEltYWdlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaW1hZ2VzID0gW107XG5cbiAgICAvLyBmaWx0ZXIgJiBmaW5kIGl0ZW1zIGlmIHdlIGhhdmUgYW4gaXRlbSBzZWxlY3RvclxuICAgIGZvciAoIHZhciBpPTA7IGkgPCB0aGlzLmVsZW1lbnRzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGVsZW0gPSB0aGlzLmVsZW1lbnRzW2ldO1xuICAgICAgdGhpcy5hZGRFbGVtZW50SW1hZ2VzKCBlbGVtICk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge05vZGV9IGVsZW1lbnRcbiAgICovXG4gIEltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkRWxlbWVudEltYWdlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuICAgIC8vIGZpbHRlciBzaWJsaW5nc1xuICAgIGlmICggZWxlbS5ub2RlTmFtZSA9PSAnSU1HJyApIHtcbiAgICAgIHRoaXMuYWRkSW1hZ2UoIGVsZW0gKTtcbiAgICB9XG4gICAgLy8gZ2V0IGJhY2tncm91bmQgaW1hZ2Ugb24gZWxlbWVudFxuICAgIGlmICggdGhpcy5vcHRpb25zLmJhY2tncm91bmQgPT09IHRydWUgKSB7XG4gICAgICB0aGlzLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzKCBlbGVtICk7XG4gICAgfVxuXG4gICAgLy8gZmluZCBjaGlsZHJlblxuICAgIC8vIG5vIG5vbi1lbGVtZW50IG5vZGVzLCAjMTQzXG4gICAgdmFyIG5vZGVUeXBlID0gZWxlbS5ub2RlVHlwZTtcbiAgICBpZiAoICFub2RlVHlwZSB8fCAhZWxlbWVudE5vZGVUeXBlc1sgbm9kZVR5cGUgXSApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGNoaWxkSW1ncyA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCgnaW1nJyk7XG4gICAgLy8gY29uY2F0IGNoaWxkRWxlbXMgdG8gZmlsdGVyRm91bmQgYXJyYXlcbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgY2hpbGRJbWdzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGltZyA9IGNoaWxkSW1nc1tpXTtcbiAgICAgIHRoaXMuYWRkSW1hZ2UoIGltZyApO1xuICAgIH1cblxuICAgIC8vIGdldCBjaGlsZCBiYWNrZ3JvdW5kIGltYWdlc1xuICAgIGlmICggdHlwZW9mIHRoaXMub3B0aW9ucy5iYWNrZ3JvdW5kID09ICdzdHJpbmcnICkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gZWxlbS5xdWVyeVNlbGVjdG9yQWxsKCB0aGlzLm9wdGlvbnMuYmFja2dyb3VuZCApO1xuICAgICAgZm9yICggaT0wOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKysgKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICB0aGlzLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzKCBjaGlsZCApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgZWxlbWVudE5vZGVUeXBlcyA9IHtcbiAgICAxOiB0cnVlLFxuICAgIDk6IHRydWUsXG4gICAgMTE6IHRydWVcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gICAgdmFyIHN0eWxlID0gZ2V0U3R5bGUoIGVsZW0gKTtcbiAgICAvLyBnZXQgdXJsIGluc2lkZSB1cmwoXCIuLi5cIilcbiAgICB2YXIgcmVVUkwgPSAvdXJsXFwoWydcIl0qKFteJ1wiXFwpXSspWydcIl0qXFwpL2dpO1xuICAgIHZhciBtYXRjaGVzID0gcmVVUkwuZXhlYyggc3R5bGUuYmFja2dyb3VuZEltYWdlICk7XG4gICAgd2hpbGUgKCBtYXRjaGVzICE9PSBudWxsICkge1xuICAgICAgdmFyIHVybCA9IG1hdGNoZXMgJiYgbWF0Y2hlc1sxXTtcbiAgICAgIGlmICggdXJsICkge1xuICAgICAgICB0aGlzLmFkZEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICAgICAgfVxuICAgICAgbWF0Y2hlcyA9IHJlVVJMLmV4ZWMoIHN0eWxlLmJhY2tncm91bmRJbWFnZSApO1xuICAgIH1cbiAgfTtcblxuICAvLyBJRThcbiAgdmFyIGdldFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUgfHwgZnVuY3Rpb24oIGVsZW0gKSB7XG4gICAgcmV0dXJuIGVsZW0uY3VycmVudFN0eWxlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0ltYWdlfSBpbWdcbiAgICovXG4gIEltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkSW1hZ2UgPSBmdW5jdGlvbiggaW1nICkge1xuICAgIHZhciBsb2FkaW5nSW1hZ2UgPSBuZXcgTG9hZGluZ0ltYWdlKCBpbWcgKTtcbiAgICB0aGlzLmltYWdlcy5wdXNoKCBsb2FkaW5nSW1hZ2UgKTtcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmFkZEJhY2tncm91bmQgPSBmdW5jdGlvbiggdXJsLCBlbGVtICkge1xuICAgIHZhciBiYWNrZ3JvdW5kID0gbmV3IEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICAgIHRoaXMuaW1hZ2VzLnB1c2goIGJhY2tncm91bmQgKTtcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB0aGlzLnByb2dyZXNzZWRDb3VudCA9IDA7XG4gICAgdGhpcy5oYXNBbnlCcm9rZW4gPSBmYWxzZTtcbiAgICAvLyBjb21wbGV0ZSBpZiBubyBpbWFnZXNcbiAgICBpZiAoICF0aGlzLmltYWdlcy5sZW5ndGggKSB7XG4gICAgICB0aGlzLmNvbXBsZXRlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Qcm9ncmVzcyggaW1hZ2UsIGVsZW0sIG1lc3NhZ2UgKSB7XG4gICAgICAvLyBIQUNLIC0gQ2hyb21lIHRyaWdnZXJzIGV2ZW50IGJlZm9yZSBvYmplY3QgcHJvcGVydGllcyBoYXZlIGNoYW5nZWQuICM4M1xuICAgICAgc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG4gICAgICAgIF90aGlzLnByb2dyZXNzKCBpbWFnZSwgZWxlbSwgbWVzc2FnZSApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICggdmFyIGk9MDsgaSA8IHRoaXMuaW1hZ2VzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGxvYWRpbmdJbWFnZSA9IHRoaXMuaW1hZ2VzW2ldO1xuICAgICAgbG9hZGluZ0ltYWdlLm9uY2UoICdwcm9ncmVzcycsIG9uUHJvZ3Jlc3MgKTtcbiAgICAgIGxvYWRpbmdJbWFnZS5jaGVjaygpO1xuICAgIH1cbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLnByb2dyZXNzID0gZnVuY3Rpb24oIGltYWdlLCBlbGVtLCBtZXNzYWdlICkge1xuICAgIHRoaXMucHJvZ3Jlc3NlZENvdW50Kys7XG4gICAgdGhpcy5oYXNBbnlCcm9rZW4gPSB0aGlzLmhhc0FueUJyb2tlbiB8fCAhaW1hZ2UuaXNMb2FkZWQ7XG4gICAgLy8gcHJvZ3Jlc3MgZXZlbnRcbiAgICB0aGlzLmVtaXQoICdwcm9ncmVzcycsIHRoaXMsIGltYWdlLCBlbGVtICk7XG4gICAgaWYgKCB0aGlzLmpxRGVmZXJyZWQgJiYgdGhpcy5qcURlZmVycmVkLm5vdGlmeSApIHtcbiAgICAgIHRoaXMuanFEZWZlcnJlZC5ub3RpZnkoIHRoaXMsIGltYWdlICk7XG4gICAgfVxuICAgIC8vIGNoZWNrIGlmIGNvbXBsZXRlZFxuICAgIGlmICggdGhpcy5wcm9ncmVzc2VkQ291bnQgPT0gdGhpcy5pbWFnZXMubGVuZ3RoICkge1xuICAgICAgdGhpcy5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIGlmICggdGhpcy5vcHRpb25zLmRlYnVnICYmIGNvbnNvbGUgKSB7XG4gICAgICBjb25zb2xlLmxvZyggJ3Byb2dyZXNzOiAnICsgbWVzc2FnZSwgaW1hZ2UsIGVsZW0gKTtcbiAgICB9XG4gIH07XG5cbiAgSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBldmVudE5hbWUgPSB0aGlzLmhhc0FueUJyb2tlbiA/ICdmYWlsJyA6ICdkb25lJztcbiAgICB0aGlzLmlzQ29tcGxldGUgPSB0cnVlO1xuICAgIHRoaXMuZW1pdCggZXZlbnROYW1lLCB0aGlzICk7XG4gICAgdGhpcy5lbWl0KCAnYWx3YXlzJywgdGhpcyApO1xuICAgIGlmICggdGhpcy5qcURlZmVycmVkICkge1xuICAgICAgdmFyIGpxTWV0aG9kID0gdGhpcy5oYXNBbnlCcm9rZW4gPyAncmVqZWN0JyA6ICdyZXNvbHZlJztcbiAgICAgIHRoaXMuanFEZWZlcnJlZFsganFNZXRob2QgXSggdGhpcyApO1xuICAgIH1cbiAgfTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICBmdW5jdGlvbiBMb2FkaW5nSW1hZ2UoIGltZyApIHtcbiAgICB0aGlzLmltZyA9IGltZztcbiAgfVxuXG4gIExvYWRpbmdJbWFnZS5wcm90b3R5cGUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgTG9hZGluZ0ltYWdlLnByb3RvdHlwZS5jaGVjayA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIElmIGNvbXBsZXRlIGlzIHRydWUgYW5kIGJyb3dzZXIgc3VwcG9ydHMgbmF0dXJhbCBzaXplcyxcbiAgICAvLyB0cnkgdG8gY2hlY2sgZm9yIGltYWdlIHN0YXR1cyBtYW51YWxseS5cbiAgICB2YXIgaXNDb21wbGV0ZSA9IHRoaXMuZ2V0SXNJbWFnZUNvbXBsZXRlKCk7XG4gICAgaWYgKCBpc0NvbXBsZXRlICkge1xuICAgICAgLy8gcmVwb3J0IGJhc2VkIG9uIG5hdHVyYWxXaWR0aFxuICAgICAgdGhpcy5jb25maXJtKCB0aGlzLmltZy5uYXR1cmFsV2lkdGggIT09IDAsICduYXR1cmFsV2lkdGgnICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgbm9uZSBvZiB0aGUgY2hlY2tzIGFib3ZlIG1hdGNoZWQsIHNpbXVsYXRlIGxvYWRpbmcgb24gZGV0YWNoZWQgZWxlbWVudC5cbiAgICB0aGlzLnByb3h5SW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgICBldmVudGllLmJpbmQoIHRoaXMucHJveHlJbWFnZSwgJ2xvYWQnLCB0aGlzICk7XG4gICAgZXZlbnRpZS5iaW5kKCB0aGlzLnByb3h5SW1hZ2UsICdlcnJvcicsIHRoaXMgKTtcbiAgICAvLyBiaW5kIHRvIGltYWdlIGFzIHdlbGwgZm9yIEZpcmVmb3guICMxOTFcbiAgICBldmVudGllLmJpbmQoIHRoaXMuaW1nLCAnbG9hZCcsIHRoaXMgKTtcbiAgICBldmVudGllLmJpbmQoIHRoaXMuaW1nLCAnZXJyb3InLCB0aGlzICk7XG4gICAgdGhpcy5wcm94eUltYWdlLnNyYyA9IHRoaXMuaW1nLnNyYztcbiAgfTtcblxuICBMb2FkaW5nSW1hZ2UucHJvdG90eXBlLmdldElzSW1hZ2VDb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmltZy5jb21wbGV0ZSAmJiB0aGlzLmltZy5uYXR1cmFsV2lkdGggIT09IHVuZGVmaW5lZDtcbiAgfTtcblxuICBMb2FkaW5nSW1hZ2UucHJvdG90eXBlLmNvbmZpcm0gPSBmdW5jdGlvbiggaXNMb2FkZWQsIG1lc3NhZ2UgKSB7XG4gICAgdGhpcy5pc0xvYWRlZCA9IGlzTG9hZGVkO1xuICAgIHRoaXMuZW1pdCggJ3Byb2dyZXNzJywgdGhpcywgdGhpcy5pbWcsIG1lc3NhZ2UgKTtcbiAgfTtcblxuICAvLyAtLS0tLSBldmVudHMgLS0tLS0gLy9cblxuICAvLyB0cmlnZ2VyIHNwZWNpZmllZCBoYW5kbGVyIGZvciBldmVudCB0eXBlXG4gIExvYWRpbmdJbWFnZS5wcm90b3R5cGUuaGFuZGxlRXZlbnQgPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gICAgdmFyIG1ldGhvZCA9ICdvbicgKyBldmVudC50eXBlO1xuICAgIGlmICggdGhpc1sgbWV0aG9kIF0gKSB7XG4gICAgICB0aGlzWyBtZXRob2QgXSggZXZlbnQgKTtcbiAgICB9XG4gIH07XG5cbiAgTG9hZGluZ0ltYWdlLnByb3RvdHlwZS5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmNvbmZpcm0oIHRydWUsICdvbmxvYWQnICk7XG4gICAgdGhpcy51bmJpbmRFdmVudHMoKTtcbiAgfTtcblxuICBMb2FkaW5nSW1hZ2UucHJvdG90eXBlLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmNvbmZpcm0oIGZhbHNlLCAnb25lcnJvcicgKTtcbiAgICB0aGlzLnVuYmluZEV2ZW50cygpO1xuICB9O1xuXG4gIExvYWRpbmdJbWFnZS5wcm90b3R5cGUudW5iaW5kRXZlbnRzID0gZnVuY3Rpb24oKSB7XG4gICAgZXZlbnRpZS51bmJpbmQoIHRoaXMucHJveHlJbWFnZSwgJ2xvYWQnLCB0aGlzICk7XG4gICAgZXZlbnRpZS51bmJpbmQoIHRoaXMucHJveHlJbWFnZSwgJ2Vycm9yJywgdGhpcyApO1xuICAgIGV2ZW50aWUudW5iaW5kKCB0aGlzLmltZywgJ2xvYWQnLCB0aGlzICk7XG4gICAgZXZlbnRpZS51bmJpbmQoIHRoaXMuaW1nLCAnZXJyb3InLCB0aGlzICk7XG4gIH07XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQmFja2dyb3VuZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gIGZ1bmN0aW9uIEJhY2tncm91bmQoIHVybCwgZWxlbWVudCApIHtcbiAgICB0aGlzLnVybCA9IHVybDtcbiAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMuaW1nID0gbmV3IEltYWdlKCk7XG4gIH1cblxuICAvLyBpbmhlcml0IExvYWRpbmdJbWFnZSBwcm90b3R5cGVcbiAgQmFja2dyb3VuZC5wcm90b3R5cGUgPSBuZXcgTG9hZGluZ0ltYWdlKCk7XG5cbiAgQmFja2dyb3VuZC5wcm90b3R5cGUuY2hlY2sgPSBmdW5jdGlvbigpIHtcbiAgICBldmVudGllLmJpbmQoIHRoaXMuaW1nLCAnbG9hZCcsIHRoaXMgKTtcbiAgICBldmVudGllLmJpbmQoIHRoaXMuaW1nLCAnZXJyb3InLCB0aGlzICk7XG4gICAgdGhpcy5pbWcuc3JjID0gdGhpcy51cmw7XG4gICAgLy8gY2hlY2sgaWYgaW1hZ2UgaXMgYWxyZWFkeSBjb21wbGV0ZVxuICAgIHZhciBpc0NvbXBsZXRlID0gdGhpcy5nZXRJc0ltYWdlQ29tcGxldGUoKTtcbiAgICBpZiAoIGlzQ29tcGxldGUgKSB7XG4gICAgICB0aGlzLmNvbmZpcm0oIHRoaXMuaW1nLm5hdHVyYWxXaWR0aCAhPT0gMCwgJ25hdHVyYWxXaWR0aCcgKTtcbiAgICAgIHRoaXMudW5iaW5kRXZlbnRzKCk7XG4gICAgfVxuICB9O1xuXG4gIEJhY2tncm91bmQucHJvdG90eXBlLnVuYmluZEV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICAgIGV2ZW50aWUudW5iaW5kKCB0aGlzLmltZywgJ2xvYWQnLCB0aGlzICk7XG4gICAgZXZlbnRpZS51bmJpbmQoIHRoaXMuaW1nLCAnZXJyb3InLCB0aGlzICk7XG4gIH07XG5cbiAgQmFja2dyb3VuZC5wcm90b3R5cGUuY29uZmlybSA9IGZ1bmN0aW9uKCBpc0xvYWRlZCwgbWVzc2FnZSApIHtcbiAgICB0aGlzLmlzTG9hZGVkID0gaXNMb2FkZWQ7XG4gICAgdGhpcy5lbWl0KCAncHJvZ3Jlc3MnLCB0aGlzLCB0aGlzLmVsZW1lbnQsIG1lc3NhZ2UgKTtcbiAgfTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBqUXVlcnkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICBJbWFnZXNMb2FkZWQubWFrZUpRdWVyeVBsdWdpbiA9IGZ1bmN0aW9uKCBqUXVlcnkgKSB7XG4gICAgalF1ZXJ5ID0galF1ZXJ5IHx8IHdpbmRvdy5qUXVlcnk7XG4gICAgaWYgKCAhalF1ZXJ5ICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBzZXQgbG9jYWwgdmFyaWFibGVcbiAgICAkID0galF1ZXJ5O1xuICAgIC8vICQoKS5pbWFnZXNMb2FkZWQoKVxuICAgICQuZm4uaW1hZ2VzTG9hZGVkID0gZnVuY3Rpb24oIG9wdGlvbnMsIGNhbGxiYWNrICkge1xuICAgICAgdmFyIGluc3RhbmNlID0gbmV3IEltYWdlc0xvYWRlZCggdGhpcywgb3B0aW9ucywgY2FsbGJhY2sgKTtcbiAgICAgIHJldHVybiBpbnN0YW5jZS5qcURlZmVycmVkLnByb21pc2UoICQodGhpcykgKTtcbiAgICB9O1xuICB9O1xuICAvLyB0cnkgbWFraW5nIHBsdWdpblxuICBJbWFnZXNMb2FkZWQubWFrZUpRdWVyeVBsdWdpbigpO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gIHJldHVybiBJbWFnZXNMb2FkZWQ7XG5cbn0pO1xuIiwiLyohXG4gKiBldmVudGllIHYxLjAuNlxuICogZXZlbnQgYmluZGluZyBoZWxwZXJcbiAqICAgZXZlbnRpZS5iaW5kKCBlbGVtLCAnY2xpY2snLCBteUZuIClcbiAqICAgZXZlbnRpZS51bmJpbmQoIGVsZW0sICdjbGljaycsIG15Rm4gKVxuICogTUlUIGxpY2Vuc2VcbiAqL1xuXG4vKmpzaGludCBicm93c2VyOiB0cnVlLCB1bmRlZjogdHJ1ZSwgdW51c2VkOiB0cnVlICovXG4vKmdsb2JhbCBkZWZpbmU6IGZhbHNlLCBtb2R1bGU6IGZhbHNlICovXG5cbiggZnVuY3Rpb24oIHdpbmRvdyApIHtcblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZG9jRWxlbSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxudmFyIGJpbmQgPSBmdW5jdGlvbigpIHt9O1xuXG5mdW5jdGlvbiBnZXRJRUV2ZW50KCBvYmogKSB7XG4gIHZhciBldmVudCA9IHdpbmRvdy5ldmVudDtcbiAgLy8gYWRkIGV2ZW50LnRhcmdldFxuICBldmVudC50YXJnZXQgPSBldmVudC50YXJnZXQgfHwgZXZlbnQuc3JjRWxlbWVudCB8fCBvYmo7XG4gIHJldHVybiBldmVudDtcbn1cblxuaWYgKCBkb2NFbGVtLmFkZEV2ZW50TGlzdGVuZXIgKSB7XG4gIGJpbmQgPSBmdW5jdGlvbiggb2JqLCB0eXBlLCBmbiApIHtcbiAgICBvYmouYWRkRXZlbnRMaXN0ZW5lciggdHlwZSwgZm4sIGZhbHNlICk7XG4gIH07XG59IGVsc2UgaWYgKCBkb2NFbGVtLmF0dGFjaEV2ZW50ICkge1xuICBiaW5kID0gZnVuY3Rpb24oIG9iaiwgdHlwZSwgZm4gKSB7XG4gICAgb2JqWyB0eXBlICsgZm4gXSA9IGZuLmhhbmRsZUV2ZW50ID9cbiAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZXZlbnQgPSBnZXRJRUV2ZW50KCBvYmogKTtcbiAgICAgICAgZm4uaGFuZGxlRXZlbnQuY2FsbCggZm4sIGV2ZW50ICk7XG4gICAgICB9IDpcbiAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZXZlbnQgPSBnZXRJRUV2ZW50KCBvYmogKTtcbiAgICAgICAgZm4uY2FsbCggb2JqLCBldmVudCApO1xuICAgICAgfTtcbiAgICBvYmouYXR0YWNoRXZlbnQoIFwib25cIiArIHR5cGUsIG9ialsgdHlwZSArIGZuIF0gKTtcbiAgfTtcbn1cblxudmFyIHVuYmluZCA9IGZ1bmN0aW9uKCkge307XG5cbmlmICggZG9jRWxlbS5yZW1vdmVFdmVudExpc3RlbmVyICkge1xuICB1bmJpbmQgPSBmdW5jdGlvbiggb2JqLCB0eXBlLCBmbiApIHtcbiAgICBvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lciggdHlwZSwgZm4sIGZhbHNlICk7XG4gIH07XG59IGVsc2UgaWYgKCBkb2NFbGVtLmRldGFjaEV2ZW50ICkge1xuICB1bmJpbmQgPSBmdW5jdGlvbiggb2JqLCB0eXBlLCBmbiApIHtcbiAgICBvYmouZGV0YWNoRXZlbnQoIFwib25cIiArIHR5cGUsIG9ialsgdHlwZSArIGZuIF0gKTtcbiAgICB0cnkge1xuICAgICAgZGVsZXRlIG9ialsgdHlwZSArIGZuIF07XG4gICAgfSBjYXRjaCAoIGVyciApIHtcbiAgICAgIC8vIGNhbid0IGRlbGV0ZSB3aW5kb3cgb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgIG9ialsgdHlwZSArIGZuIF0gPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9O1xufVxuXG52YXIgZXZlbnRpZSA9IHtcbiAgYmluZDogYmluZCxcbiAgdW5iaW5kOiB1bmJpbmRcbn07XG5cbi8vIC0tLS0tIG1vZHVsZSBkZWZpbml0aW9uIC0tLS0tIC8vXG5cbmlmICggdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kICkge1xuICAvLyBBTURcbiAgZGVmaW5lKCBldmVudGllICk7XG59IGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG4gIC8vIENvbW1vbkpTXG4gIG1vZHVsZS5leHBvcnRzID0gZXZlbnRpZTtcbn0gZWxzZSB7XG4gIC8vIGJyb3dzZXIgZ2xvYmFsXG4gIHdpbmRvdy5ldmVudGllID0gZXZlbnRpZTtcbn1cblxufSkoIHdpbmRvdyApO1xuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjQuMi4xMSAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIGV4cG9ydHMgPSB0aGlzO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcbiAgICAgICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59LmNhbGwodGhpcykpO1xuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogbG9kYXNoIDMuMTAuMSAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIG1vZGVybiAtZCAtbyAuL2luZGV4LmpzYFxuICogQ29weXJpZ2h0IDIwMTItMjAxNSBUaGUgRG9qbyBGb3VuZGF0aW9uIDxodHRwOi8vZG9qb2ZvdW5kYXRpb24ub3JnLz5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgMjAwOS0yMDE1IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICovXG47KGZ1bmN0aW9uKCkge1xuXG4gIC8qKiBVc2VkIGFzIGEgc2FmZSByZWZlcmVuY2UgZm9yIGB1bmRlZmluZWRgIGluIHByZS1FUzUgZW52aXJvbm1lbnRzLiAqL1xuICB2YXIgdW5kZWZpbmVkO1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlci4gKi9cbiAgdmFyIFZFUlNJT04gPSAnMy4xMC4xJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB3cmFwcGVyIG1ldGFkYXRhLiAqL1xuICB2YXIgQklORF9GTEFHID0gMSxcbiAgICAgIEJJTkRfS0VZX0ZMQUcgPSAyLFxuICAgICAgQ1VSUllfQk9VTkRfRkxBRyA9IDQsXG4gICAgICBDVVJSWV9GTEFHID0gOCxcbiAgICAgIENVUlJZX1JJR0hUX0ZMQUcgPSAxNixcbiAgICAgIFBBUlRJQUxfRkxBRyA9IDMyLFxuICAgICAgUEFSVElBTF9SSUdIVF9GTEFHID0gNjQsXG4gICAgICBBUllfRkxBRyA9IDEyOCxcbiAgICAgIFJFQVJHX0ZMQUcgPSAyNTY7XG5cbiAgLyoqIFVzZWQgYXMgZGVmYXVsdCBvcHRpb25zIGZvciBgXy50cnVuY2AuICovXG4gIHZhciBERUZBVUxUX1RSVU5DX0xFTkdUSCA9IDMwLFxuICAgICAgREVGQVVMVF9UUlVOQ19PTUlTU0lPTiA9ICcuLi4nO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCB3aGVuIGEgZnVuY3Rpb24gYmVjb21lcyBob3QuICovXG4gIHZhciBIT1RfQ09VTlQgPSAxNTAsXG4gICAgICBIT1RfU1BBTiA9IDE2O1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBzaXplIHRvIGVuYWJsZSBsYXJnZSBhcnJheSBvcHRpbWl6YXRpb25zLiAqL1xuICB2YXIgTEFSR0VfQVJSQVlfU0laRSA9IDIwMDtcblxuICAvKiogVXNlZCB0byBpbmRpY2F0ZSB0aGUgdHlwZSBvZiBsYXp5IGl0ZXJhdGVlcy4gKi9cbiAgdmFyIExBWllfRklMVEVSX0ZMQUcgPSAxLFxuICAgICAgTEFaWV9NQVBfRkxBRyA9IDI7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIGBUeXBlRXJyb3JgIG1lc3NhZ2UgZm9yIFwiRnVuY3Rpb25zXCIgbWV0aG9kcy4gKi9cbiAgdmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuICAvKiogVXNlZCBhcyB0aGUgaW50ZXJuYWwgYXJndW1lbnQgcGxhY2Vob2xkZXIuICovXG4gIHZhciBQTEFDRUhPTERFUiA9ICdfX2xvZGFzaF9wbGFjZWhvbGRlcl9fJztcblxuICAvKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG4gIHZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgICBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgICAgbWFwVGFnID0gJ1tvYmplY3QgTWFwXScsXG4gICAgICBudW1iZXJUYWcgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgICAgd2Vha01hcFRhZyA9ICdbb2JqZWN0IFdlYWtNYXBdJztcblxuICB2YXIgYXJyYXlCdWZmZXJUYWcgPSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nLFxuICAgICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGVtcHR5IHN0cmluZyBsaXRlcmFscyBpbiBjb21waWxlZCB0ZW1wbGF0ZSBzb3VyY2UuICovXG4gIHZhciByZUVtcHR5U3RyaW5nTGVhZGluZyA9IC9cXGJfX3AgXFwrPSAnJzsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdNaWRkbGUgPSAvXFxiKF9fcCBcXCs9KSAnJyBcXCsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdUcmFpbGluZyA9IC8oX19lXFwoLio/XFwpfFxcYl9fdFxcKSkgXFwrXFxuJyc7L2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggSFRNTCBlbnRpdGllcyBhbmQgSFRNTCBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgcmVFc2NhcGVkSHRtbCA9IC8mKD86YW1wfGx0fGd0fHF1b3R8IzM5fCM5Nik7L2csXG4gICAgICByZVVuZXNjYXBlZEh0bWwgPSAvWyY8PlwiJ2BdL2csXG4gICAgICByZUhhc0VzY2FwZWRIdG1sID0gUmVnRXhwKHJlRXNjYXBlZEh0bWwuc291cmNlKSxcbiAgICAgIHJlSGFzVW5lc2NhcGVkSHRtbCA9IFJlZ0V4cChyZVVuZXNjYXBlZEh0bWwuc291cmNlKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLiAqL1xuICB2YXIgcmVFc2NhcGUgPSAvPCUtKFtcXHNcXFNdKz8pJT4vZyxcbiAgICAgIHJlRXZhbHVhdGUgPSAvPCUoW1xcc1xcU10rPyklPi9nLFxuICAgICAgcmVJbnRlcnBvbGF0ZSA9IC88JT0oW1xcc1xcU10rPyklPi9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHByb3BlcnR5IG5hbWVzIHdpdGhpbiBwcm9wZXJ0eSBwYXRocy4gKi9cbiAgdmFyIHJlSXNEZWVwUHJvcCA9IC9cXC58XFxbKD86W15bXFxdXSp8KFtcIiddKSg/Oig/IVxcMSlbXlxcblxcXFxdfFxcXFwuKSo/XFwxKVxcXS8sXG4gICAgICByZUlzUGxhaW5Qcm9wID0gL15cXHcqJC8sXG4gICAgICByZVByb3BOYW1lID0gL1teLltcXF1dK3xcXFsoPzooLT9cXGQrKD86XFwuXFxkKyk/KXwoW1wiJ10pKCg/Oig/IVxcMilbXlxcblxcXFxdfFxcXFwuKSo/KVxcMilcXF0vZztcblxuICAvKipcbiAgICogVXNlZCB0byBtYXRjaCBgUmVnRXhwYCBbc3ludGF4IGNoYXJhY3RlcnNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXBhdHRlcm5zKVxuICAgKiBhbmQgdGhvc2Ugb3V0bGluZWQgYnkgW2BFc2NhcGVSZWdFeHBQYXR0ZXJuYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtZXNjYXBlcmVnZXhwcGF0dGVybikuXG4gICAqL1xuICB2YXIgcmVSZWdFeHBDaGFycyA9IC9eWzohLF18W1xcXFxeJC4qKz8oKVtcXF17fXxcXC9dfCheWzAtOWEtZkEtRm5ydHV2eF0pfChbXFxuXFxyXFx1MjAyOFxcdTIwMjldKS9nLFxuICAgICAgcmVIYXNSZWdFeHBDaGFycyA9IFJlZ0V4cChyZVJlZ0V4cENoYXJzLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKS4gKi9cbiAgdmFyIHJlQ29tYm9NYXJrID0gL1tcXHUwMzAwLVxcdTAzNmZcXHVmZTIwLVxcdWZlMjNdL2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYmFja3NsYXNoZXMgaW4gcHJvcGVydHkgcGF0aHMuICovXG4gIHZhciByZUVzY2FwZUNoYXIgPSAvXFxcXChcXFxcKT8vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBbRVMgdGVtcGxhdGUgZGVsaW1pdGVyc10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtdGVtcGxhdGUtbGl0ZXJhbC1sZXhpY2FsLWNvbXBvbmVudHMpLiAqL1xuICB2YXIgcmVFc1RlbXBsYXRlID0gL1xcJFxceyhbXlxcXFx9XSooPzpcXFxcLlteXFxcXH1dKikqKVxcfS9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgIGZsYWdzIGZyb20gdGhlaXIgY29lcmNlZCBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVGbGFncyA9IC9cXHcqJC87XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUhhc0hleFByZWZpeCA9IC9eMFt4WF0vO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBob3N0IGNvbnN0cnVjdG9ycyAoU2FmYXJpID4gNSkuICovXG4gIHZhciByZUlzSG9zdEN0b3IgPSAvXlxcW29iamVjdCAuKz9Db25zdHJ1Y3RvclxcXSQvO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCB1bnNpZ25lZCBpbnRlZ2VyIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNVaW50ID0gL15cXGQrJC87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggbGF0aW4tMSBzdXBwbGVtZW50YXJ5IGxldHRlcnMgKGV4Y2x1ZGluZyBtYXRoZW1hdGljYWwgb3BlcmF0b3JzKS4gKi9cbiAgdmFyIHJlTGF0aW4xID0gL1tcXHhjMC1cXHhkNlxceGQ4LVxceGRlXFx4ZGYtXFx4ZjZcXHhmOC1cXHhmZl0vZztcblxuICAvKiogVXNlZCB0byBlbnN1cmUgY2FwdHVyaW5nIG9yZGVyIG9mIHRlbXBsYXRlIGRlbGltaXRlcnMuICovXG4gIHZhciByZU5vTWF0Y2ggPSAvKCReKS87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdW5lc2NhcGVkIGNoYXJhY3RlcnMgaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzLiAqL1xuICB2YXIgcmVVbmVzY2FwZWRTdHJpbmcgPSAvWydcXG5cXHJcXHUyMDI4XFx1MjAyOVxcXFxdL2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggd29yZHMgdG8gY3JlYXRlIGNvbXBvdW5kIHdvcmRzLiAqL1xuICB2YXIgcmVXb3JkcyA9IChmdW5jdGlvbigpIHtcbiAgICB2YXIgdXBwZXIgPSAnW0EtWlxcXFx4YzAtXFxcXHhkNlxcXFx4ZDgtXFxcXHhkZV0nLFxuICAgICAgICBsb3dlciA9ICdbYS16XFxcXHhkZi1cXFxceGY2XFxcXHhmOC1cXFxceGZmXSsnO1xuXG4gICAgcmV0dXJuIFJlZ0V4cCh1cHBlciArICcrKD89JyArIHVwcGVyICsgbG93ZXIgKyAnKXwnICsgdXBwZXIgKyAnPycgKyBsb3dlciArICd8JyArIHVwcGVyICsgJyt8WzAtOV0rJywgJ2cnKTtcbiAgfSgpKTtcblxuICAvKiogVXNlZCB0byBhc3NpZ24gZGVmYXVsdCBgY29udGV4dGAgb2JqZWN0IHByb3BlcnRpZXMuICovXG4gIHZhciBjb250ZXh0UHJvcHMgPSBbXG4gICAgJ0FycmF5JywgJ0FycmF5QnVmZmVyJywgJ0RhdGUnLCAnRXJyb3InLCAnRmxvYXQzMkFycmF5JywgJ0Zsb2F0NjRBcnJheScsXG4gICAgJ0Z1bmN0aW9uJywgJ0ludDhBcnJheScsICdJbnQxNkFycmF5JywgJ0ludDMyQXJyYXknLCAnTWF0aCcsICdOdW1iZXInLFxuICAgICdPYmplY3QnLCAnUmVnRXhwJywgJ1NldCcsICdTdHJpbmcnLCAnXycsICdjbGVhclRpbWVvdXQnLCAnaXNGaW5pdGUnLFxuICAgICdwYXJzZUZsb2F0JywgJ3BhcnNlSW50JywgJ3NldFRpbWVvdXQnLCAnVHlwZUVycm9yJywgJ1VpbnQ4QXJyYXknLFxuICAgICdVaW50OENsYW1wZWRBcnJheScsICdVaW50MTZBcnJheScsICdVaW50MzJBcnJheScsICdXZWFrTWFwJ1xuICBdO1xuXG4gIC8qKiBVc2VkIHRvIG1ha2UgdGVtcGxhdGUgc291cmNlVVJMcyBlYXNpZXIgdG8gaWRlbnRpZnkuICovXG4gIHZhciB0ZW1wbGF0ZUNvdW50ZXIgPSAtMTtcblxuICAvKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBvZiB0eXBlZCBhcnJheXMuICovXG4gIHZhciB0eXBlZEFycmF5VGFncyA9IHt9O1xuICB0eXBlZEFycmF5VGFnc1tmbG9hdDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Zsb2F0NjRUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbaW50OFRhZ10gPSB0eXBlZEFycmF5VGFnc1tpbnQxNlRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tpbnQzMlRhZ10gPSB0eXBlZEFycmF5VGFnc1t1aW50OFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1t1aW50OENsYW1wZWRUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDE2VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuICB0eXBlZEFycmF5VGFnc1thcmdzVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2FycmF5VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2FycmF5QnVmZmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Jvb2xUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbZGF0ZVRhZ10gPSB0eXBlZEFycmF5VGFnc1tlcnJvclRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tmdW5jVGFnXSA9IHR5cGVkQXJyYXlUYWdzW21hcFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tudW1iZXJUYWddID0gdHlwZWRBcnJheVRhZ3Nbb2JqZWN0VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3JlZ2V4cFRhZ10gPSB0eXBlZEFycmF5VGFnc1tzZXRUYWddID1cbiAgdHlwZWRBcnJheVRhZ3Nbc3RyaW5nVGFnXSA9IHR5cGVkQXJyYXlUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbiAgLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgc3VwcG9ydGVkIGJ5IGBfLmNsb25lYC4gKi9cbiAgdmFyIGNsb25lYWJsZVRhZ3MgPSB7fTtcbiAgY2xvbmVhYmxlVGFnc1thcmdzVGFnXSA9IGNsb25lYWJsZVRhZ3NbYXJyYXlUYWddID1cbiAgY2xvbmVhYmxlVGFnc1thcnJheUJ1ZmZlclRhZ10gPSBjbG9uZWFibGVUYWdzW2Jvb2xUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tkYXRlVGFnXSA9IGNsb25lYWJsZVRhZ3NbZmxvYXQzMlRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2Zsb2F0NjRUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQ4VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbaW50MTZUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQzMlRhZ10gPVxuICBjbG9uZWFibGVUYWdzW251bWJlclRhZ10gPSBjbG9uZWFibGVUYWdzW29iamVjdFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW3JlZ2V4cFRhZ10gPSBjbG9uZWFibGVUYWdzW3N0cmluZ1RhZ10gPVxuICBjbG9uZWFibGVUYWdzW3VpbnQ4VGFnXSA9IGNsb25lYWJsZVRhZ3NbdWludDhDbGFtcGVkVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbdWludDE2VGFnXSA9IGNsb25lYWJsZVRhZ3NbdWludDMyVGFnXSA9IHRydWU7XG4gIGNsb25lYWJsZVRhZ3NbZXJyb3JUYWddID0gY2xvbmVhYmxlVGFnc1tmdW5jVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbbWFwVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc2V0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3Nbd2Vha01hcFRhZ10gPSBmYWxzZTtcblxuICAvKiogVXNlZCB0byBtYXAgbGF0aW4tMSBzdXBwbGVtZW50YXJ5IGxldHRlcnMgdG8gYmFzaWMgbGF0aW4gbGV0dGVycy4gKi9cbiAgdmFyIGRlYnVycmVkTGV0dGVycyA9IHtcbiAgICAnXFx4YzAnOiAnQScsICAnXFx4YzEnOiAnQScsICdcXHhjMic6ICdBJywgJ1xceGMzJzogJ0EnLCAnXFx4YzQnOiAnQScsICdcXHhjNSc6ICdBJyxcbiAgICAnXFx4ZTAnOiAnYScsICAnXFx4ZTEnOiAnYScsICdcXHhlMic6ICdhJywgJ1xceGUzJzogJ2EnLCAnXFx4ZTQnOiAnYScsICdcXHhlNSc6ICdhJyxcbiAgICAnXFx4YzcnOiAnQycsICAnXFx4ZTcnOiAnYycsXG4gICAgJ1xceGQwJzogJ0QnLCAgJ1xceGYwJzogJ2QnLFxuICAgICdcXHhjOCc6ICdFJywgICdcXHhjOSc6ICdFJywgJ1xceGNhJzogJ0UnLCAnXFx4Y2InOiAnRScsXG4gICAgJ1xceGU4JzogJ2UnLCAgJ1xceGU5JzogJ2UnLCAnXFx4ZWEnOiAnZScsICdcXHhlYic6ICdlJyxcbiAgICAnXFx4Y0MnOiAnSScsICAnXFx4Y2QnOiAnSScsICdcXHhjZSc6ICdJJywgJ1xceGNmJzogJ0knLFxuICAgICdcXHhlQyc6ICdpJywgICdcXHhlZCc6ICdpJywgJ1xceGVlJzogJ2knLCAnXFx4ZWYnOiAnaScsXG4gICAgJ1xceGQxJzogJ04nLCAgJ1xceGYxJzogJ24nLFxuICAgICdcXHhkMic6ICdPJywgICdcXHhkMyc6ICdPJywgJ1xceGQ0JzogJ08nLCAnXFx4ZDUnOiAnTycsICdcXHhkNic6ICdPJywgJ1xceGQ4JzogJ08nLFxuICAgICdcXHhmMic6ICdvJywgICdcXHhmMyc6ICdvJywgJ1xceGY0JzogJ28nLCAnXFx4ZjUnOiAnbycsICdcXHhmNic6ICdvJywgJ1xceGY4JzogJ28nLFxuICAgICdcXHhkOSc6ICdVJywgICdcXHhkYSc6ICdVJywgJ1xceGRiJzogJ1UnLCAnXFx4ZGMnOiAnVScsXG4gICAgJ1xceGY5JzogJ3UnLCAgJ1xceGZhJzogJ3UnLCAnXFx4ZmInOiAndScsICdcXHhmYyc6ICd1JyxcbiAgICAnXFx4ZGQnOiAnWScsICAnXFx4ZmQnOiAneScsICdcXHhmZic6ICd5JyxcbiAgICAnXFx4YzYnOiAnQWUnLCAnXFx4ZTYnOiAnYWUnLFxuICAgICdcXHhkZSc6ICdUaCcsICdcXHhmZSc6ICd0aCcsXG4gICAgJ1xceGRmJzogJ3NzJ1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBjaGFyYWN0ZXJzIHRvIEhUTUwgZW50aXRpZXMuICovXG4gIHZhciBodG1sRXNjYXBlcyA9IHtcbiAgICAnJic6ICcmYW1wOycsXG4gICAgJzwnOiAnJmx0OycsXG4gICAgJz4nOiAnJmd0OycsXG4gICAgJ1wiJzogJyZxdW90OycsXG4gICAgXCInXCI6ICcmIzM5OycsXG4gICAgJ2AnOiAnJiM5NjsnXG4gIH07XG5cbiAgLyoqIFVzZWQgdG8gbWFwIEhUTUwgZW50aXRpZXMgdG8gY2hhcmFjdGVycy4gKi9cbiAgdmFyIGh0bWxVbmVzY2FwZXMgPSB7XG4gICAgJyZhbXA7JzogJyYnLFxuICAgICcmbHQ7JzogJzwnLFxuICAgICcmZ3Q7JzogJz4nLFxuICAgICcmcXVvdDsnOiAnXCInLFxuICAgICcmIzM5Oyc6IFwiJ1wiLFxuICAgICcmIzk2Oyc6ICdgJ1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgcmVnZXhlcy4gKi9cbiAgdmFyIHJlZ2V4cEVzY2FwZXMgPSB7XG4gICAgJzAnOiAneDMwJywgJzEnOiAneDMxJywgJzInOiAneDMyJywgJzMnOiAneDMzJywgJzQnOiAneDM0JyxcbiAgICAnNSc6ICd4MzUnLCAnNic6ICd4MzYnLCAnNyc6ICd4MzcnLCAnOCc6ICd4MzgnLCAnOSc6ICd4MzknLFxuICAgICdBJzogJ3g0MScsICdCJzogJ3g0MicsICdDJzogJ3g0MycsICdEJzogJ3g0NCcsICdFJzogJ3g0NScsICdGJzogJ3g0NicsXG4gICAgJ2EnOiAneDYxJywgJ2InOiAneDYyJywgJ2MnOiAneDYzJywgJ2QnOiAneDY0JywgJ2UnOiAneDY1JywgJ2YnOiAneDY2JyxcbiAgICAnbic6ICd4NmUnLCAncic6ICd4NzInLCAndCc6ICd4NzQnLCAndSc6ICd4NzUnLCAndic6ICd4NzYnLCAneCc6ICd4NzgnXG4gIH07XG5cbiAgLyoqIFVzZWQgdG8gZXNjYXBlIGNoYXJhY3RlcnMgZm9yIGluY2x1c2lvbiBpbiBjb21waWxlZCBzdHJpbmcgbGl0ZXJhbHMuICovXG4gIHZhciBzdHJpbmdFc2NhcGVzID0ge1xuICAgICdcXFxcJzogJ1xcXFwnLFxuICAgIFwiJ1wiOiBcIidcIixcbiAgICAnXFxuJzogJ24nLFxuICAgICdcXHInOiAncicsXG4gICAgJ1xcdTIwMjgnOiAndTIwMjgnLFxuICAgICdcXHUyMDI5JzogJ3UyMDI5J1xuICB9O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzICYmICFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCAmJiBnbG9iYWw7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbiAgdmFyIGZyZWVTZWxmID0gb2JqZWN0VHlwZXNbdHlwZW9mIHNlbGZdICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgJiYgc2VsZjtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHdpbmRvd2AuICovXG4gIHZhciBmcmVlV2luZG93ID0gb2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93ICYmIHdpbmRvdy5PYmplY3QgJiYgd2luZG93O1xuXG4gIC8qKiBEZXRlY3QgdGhlIHBvcHVsYXIgQ29tbW9uSlMgZXh0ZW5zaW9uIGBtb2R1bGUuZXhwb3J0c2AuICovXG4gIHZhciBtb2R1bGVFeHBvcnRzID0gZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLmV4cG9ydHMgPT09IGZyZWVFeHBvcnRzICYmIGZyZWVFeHBvcnRzO1xuXG4gIC8qKlxuICAgKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgKlxuICAgKiBUaGUgYHRoaXNgIHZhbHVlIGlzIHVzZWQgaWYgaXQncyB0aGUgZ2xvYmFsIG9iamVjdCB0byBhdm9pZCBHcmVhc2Vtb25rZXknc1xuICAgKiByZXN0cmljdGVkIGB3aW5kb3dgIG9iamVjdCwgb3RoZXJ3aXNlIHRoZSBgd2luZG93YCBvYmplY3QgaXMgdXNlZC5cbiAgICovXG4gIHZhciByb290ID0gZnJlZUdsb2JhbCB8fCAoKGZyZWVXaW5kb3cgIT09ICh0aGlzICYmIHRoaXMud2luZG93KSkgJiYgZnJlZVdpbmRvdykgfHwgZnJlZVNlbGYgfHwgdGhpcztcblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGNvbXBhcmVBc2NlbmRpbmdgIHdoaWNoIGNvbXBhcmVzIHZhbHVlcyBhbmRcbiAgICogc29ydHMgdGhlbSBpbiBhc2NlbmRpbmcgb3JkZXIgd2l0aG91dCBndWFyYW50ZWVpbmcgYSBzdGFibGUgc29ydC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3IgZm9yIGB2YWx1ZWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlQ29tcGFyZUFzY2VuZGluZyh2YWx1ZSwgb3RoZXIpIHtcbiAgICBpZiAodmFsdWUgIT09IG90aGVyKSB7XG4gICAgICB2YXIgdmFsSXNOdWxsID0gdmFsdWUgPT09IG51bGwsXG4gICAgICAgICAgdmFsSXNVbmRlZiA9IHZhbHVlID09PSB1bmRlZmluZWQsXG4gICAgICAgICAgdmFsSXNSZWZsZXhpdmUgPSB2YWx1ZSA9PT0gdmFsdWU7XG5cbiAgICAgIHZhciBvdGhJc051bGwgPSBvdGhlciA9PT0gbnVsbCxcbiAgICAgICAgICBvdGhJc1VuZGVmID0gb3RoZXIgPT09IHVuZGVmaW5lZCxcbiAgICAgICAgICBvdGhJc1JlZmxleGl2ZSA9IG90aGVyID09PSBvdGhlcjtcblxuICAgICAgaWYgKCh2YWx1ZSA+IG90aGVyICYmICFvdGhJc051bGwpIHx8ICF2YWxJc1JlZmxleGl2ZSB8fFxuICAgICAgICAgICh2YWxJc051bGwgJiYgIW90aElzVW5kZWYgJiYgb3RoSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgKHZhbElzVW5kZWYgJiYgb3RoSXNSZWZsZXhpdmUpKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgICAgaWYgKCh2YWx1ZSA8IG90aGVyICYmICF2YWxJc051bGwpIHx8ICFvdGhJc1JlZmxleGl2ZSB8fFxuICAgICAgICAgIChvdGhJc051bGwgJiYgIXZhbElzVW5kZWYgJiYgdmFsSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgKG90aElzVW5kZWYgJiYgdmFsSXNSZWZsZXhpdmUpKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmluZEluZGV4YCBhbmQgYF8uZmluZExhc3RJbmRleGAgd2l0aG91dFxuICAgKiBzdXBwb3J0IGZvciBjYWxsYmFjayBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBmcm9tUmlnaHQpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICBpbmRleCA9IGZyb21SaWdodCA/IGxlbmd0aCA6IC0xO1xuXG4gICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmluZGV4T2ZgIHdpdGhvdXQgc3VwcG9ydCBmb3IgYmluYXJ5IHNlYXJjaGVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgaWYgKHZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGluZGV4T2ZOYU4oYXJyYXksIGZyb21JbmRleCk7XG4gICAgfVxuICAgIHZhciBpbmRleCA9IGZyb21JbmRleCAtIDEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0Z1bmN0aW9uYCB3aXRob3V0IHN1cHBvcnQgZm9yIGVudmlyb25tZW50c1xuICAgKiB3aXRoIGluY29ycmVjdCBgdHlwZW9mYCByZXN1bHRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJc0Z1bmN0aW9uKHZhbHVlKSB7XG4gICAgLy8gQXZvaWQgYSBDaGFrcmEgSklUIGJ1ZyBpbiBjb21wYXRpYmlsaXR5IG1vZGVzIG9mIElFIDExLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvaXNzdWVzLzE2MjEgZm9yIG1vcmUgZGV0YWlscy5cbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdmdW5jdGlvbicgfHwgZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIHN0cmluZyBpZiBpdCdzIG5vdCBvbmUuIEFuIGVtcHR5IHN0cmluZyBpcyByZXR1cm5lZFxuICAgKiBmb3IgYG51bGxgIG9yIGB1bmRlZmluZWRgIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVRvU3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGwgPyAnJyA6ICh2YWx1ZSArICcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLnRyaW1gIGFuZCBgXy50cmltTGVmdGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgY2hhcmFjdGVyXG4gICAqIG9mIGBzdHJpbmdgIHRoYXQgaXMgbm90IGZvdW5kIGluIGBjaGFyc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhcnMgVGhlIGNoYXJhY3RlcnMgdG8gZmluZC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBub3QgZm91bmQgaW4gYGNoYXJzYC5cbiAgICovXG4gIGZ1bmN0aW9uIGNoYXJzTGVmdEluZGV4KHN0cmluZywgY2hhcnMpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoICYmIGNoYXJzLmluZGV4T2Yoc3RyaW5nLmNoYXJBdChpbmRleCkpID4gLTEpIHt9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udHJpbWAgYW5kIGBfLnRyaW1SaWdodGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgbGFzdCBjaGFyYWN0ZXJcbiAgICogb2YgYHN0cmluZ2AgdGhhdCBpcyBub3QgZm91bmQgaW4gYGNoYXJzYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFycyBUaGUgY2hhcmFjdGVycyB0byBmaW5kLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbGFzdCBjaGFyYWN0ZXIgbm90IGZvdW5kIGluIGBjaGFyc2AuXG4gICAqL1xuICBmdW5jdGlvbiBjaGFyc1JpZ2h0SW5kZXgoc3RyaW5nLCBjaGFycykge1xuICAgIHZhciBpbmRleCA9IHN0cmluZy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoaW5kZXgtLSAmJiBjaGFycy5pbmRleE9mKHN0cmluZy5jaGFyQXQoaW5kZXgpKSA+IC0xKSB7fVxuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLnNvcnRCeWAgdG8gY29tcGFyZSB0cmFuc2Zvcm1lZCBlbGVtZW50cyBvZiBhIGNvbGxlY3Rpb24gYW5kIHN0YWJsZVxuICAgKiBzb3J0IHRoZW0gaW4gYXNjZW5kaW5nIG9yZGVyLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3IgZm9yIGBvYmplY3RgLlxuICAgKi9cbiAgZnVuY3Rpb24gY29tcGFyZUFzY2VuZGluZyhvYmplY3QsIG90aGVyKSB7XG4gICAgcmV0dXJuIGJhc2VDb21wYXJlQXNjZW5kaW5nKG9iamVjdC5jcml0ZXJpYSwgb3RoZXIuY3JpdGVyaWEpIHx8IChvYmplY3QuaW5kZXggLSBvdGhlci5pbmRleCk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy5zb3J0QnlPcmRlcmAgdG8gY29tcGFyZSBtdWx0aXBsZSBwcm9wZXJ0aWVzIG9mIGEgdmFsdWUgdG8gYW5vdGhlclxuICAgKiBhbmQgc3RhYmxlIHNvcnQgdGhlbS5cbiAgICpcbiAgICogSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXNzIGFyZSBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyLiBPdGhlcndpc2UsXG4gICAqIGEgdmFsdWUgaXMgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlciBpZiBpdHMgY29ycmVzcG9uZGluZyBvcmRlciBpcyBcImFzY1wiLCBhbmRcbiAgICogZGVzY2VuZGluZyBpZiBcImRlc2NcIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbltdfSBvcmRlcnMgVGhlIG9yZGVyIHRvIHNvcnQgYnkgZm9yIGVhY2ggcHJvcGVydHkuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHNvcnQgb3JkZXIgaW5kaWNhdG9yIGZvciBgb2JqZWN0YC5cbiAgICovXG4gIGZ1bmN0aW9uIGNvbXBhcmVNdWx0aXBsZShvYmplY3QsIG90aGVyLCBvcmRlcnMpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgb2JqQ3JpdGVyaWEgPSBvYmplY3QuY3JpdGVyaWEsXG4gICAgICAgIG90aENyaXRlcmlhID0gb3RoZXIuY3JpdGVyaWEsXG4gICAgICAgIGxlbmd0aCA9IG9iakNyaXRlcmlhLmxlbmd0aCxcbiAgICAgICAgb3JkZXJzTGVuZ3RoID0gb3JkZXJzLmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZUNvbXBhcmVBc2NlbmRpbmcob2JqQ3JpdGVyaWFbaW5kZXhdLCBvdGhDcml0ZXJpYVtpbmRleF0pO1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICBpZiAoaW5kZXggPj0gb3JkZXJzTGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3JkZXIgPSBvcmRlcnNbaW5kZXhdO1xuICAgICAgICByZXR1cm4gcmVzdWx0ICogKChvcmRlciA9PT0gJ2FzYycgfHwgb3JkZXIgPT09IHRydWUpID8gMSA6IC0xKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRml4ZXMgYW4gYEFycmF5I3NvcnRgIGJ1ZyBpbiB0aGUgSlMgZW5naW5lIGVtYmVkZGVkIGluIEFkb2JlIGFwcGxpY2F0aW9uc1xuICAgIC8vIHRoYXQgY2F1c2VzIGl0LCB1bmRlciBjZXJ0YWluIGNpcmN1bXN0YW5jZXMsIHRvIHByb3ZpZGUgdGhlIHNhbWUgdmFsdWUgZm9yXG4gICAgLy8gYG9iamVjdGAgYW5kIGBvdGhlcmAuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvcHVsbC8xMjQ3XG4gICAgLy8gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAvL1xuICAgIC8vIFRoaXMgYWxzbyBlbnN1cmVzIGEgc3RhYmxlIHNvcnQgaW4gVjggYW5kIG90aGVyIGVuZ2luZXMuXG4gICAgLy8gU2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD05MCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJldHVybiBvYmplY3QuaW5kZXggLSBvdGhlci5pbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLmRlYnVycmAgdG8gY29udmVydCBsYXRpbi0xIHN1cHBsZW1lbnRhcnkgbGV0dGVycyB0byBiYXNpYyBsYXRpbiBsZXR0ZXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGV0dGVyIFRoZSBtYXRjaGVkIGxldHRlciB0byBkZWJ1cnIuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGRlYnVycmVkIGxldHRlci5cbiAgICovXG4gIGZ1bmN0aW9uIGRlYnVyckxldHRlcihsZXR0ZXIpIHtcbiAgICByZXR1cm4gZGVidXJyZWRMZXR0ZXJzW2xldHRlcl07XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy5lc2NhcGVgIHRvIGNvbnZlcnQgY2hhcmFjdGVycyB0byBIVE1MIGVudGl0aWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hyIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlSHRtbENoYXIoY2hyKSB7XG4gICAgcmV0dXJuIGh0bWxFc2NhcGVzW2Nocl07XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy5lc2NhcGVSZWdFeHBgIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgcmVnZXhlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNociBUaGUgbWF0Y2hlZCBjaGFyYWN0ZXIgdG8gZXNjYXBlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGVhZGluZ0NoYXIgVGhlIGNhcHR1cmUgZ3JvdXAgZm9yIGEgbGVhZGluZyBjaGFyYWN0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB3aGl0ZXNwYWNlQ2hhciBUaGUgY2FwdHVyZSBncm91cCBmb3IgYSB3aGl0ZXNwYWNlIGNoYXJhY3Rlci5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiBlc2NhcGVSZWdFeHBDaGFyKGNociwgbGVhZGluZ0NoYXIsIHdoaXRlc3BhY2VDaGFyKSB7XG4gICAgaWYgKGxlYWRpbmdDaGFyKSB7XG4gICAgICBjaHIgPSByZWdleHBFc2NhcGVzW2Nocl07XG4gICAgfSBlbHNlIGlmICh3aGl0ZXNwYWNlQ2hhcikge1xuICAgICAgY2hyID0gc3RyaW5nRXNjYXBlc1tjaHJdO1xuICAgIH1cbiAgICByZXR1cm4gJ1xcXFwnICsgY2hyO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udGVtcGxhdGVgIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hyIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlU3RyaW5nQ2hhcihjaHIpIHtcbiAgICByZXR1cm4gJ1xcXFwnICsgc3RyaW5nRXNjYXBlc1tjaHJdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGBOYU5gIGlzIGZvdW5kIGluIGBhcnJheWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgYE5hTmAsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGluZGV4T2ZOYU4oYXJyYXksIGZyb21JbmRleCwgZnJvbVJpZ2h0KSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgaW5kZXggPSBmcm9tSW5kZXggKyAoZnJvbVJpZ2h0ID8gMCA6IC0xKTtcblxuICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICB2YXIgb3RoZXIgPSBhcnJheVtpbmRleF07XG4gICAgICBpZiAob3RoZXIgIT09IG90aGVyKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICAgIHJldHVybiAhIXZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JztcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGB0cmltbWVkTGVmdEluZGV4YCBhbmQgYHRyaW1tZWRSaWdodEluZGV4YCB0byBkZXRlcm1pbmUgaWYgYVxuICAgKiBjaGFyYWN0ZXIgY29kZSBpcyB3aGl0ZXNwYWNlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gY2hhckNvZGUgVGhlIGNoYXJhY3RlciBjb2RlIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgY2hhckNvZGVgIGlzIHdoaXRlc3BhY2UsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzU3BhY2UoY2hhckNvZGUpIHtcbiAgICByZXR1cm4gKChjaGFyQ29kZSA8PSAxNjAgJiYgKGNoYXJDb2RlID49IDkgJiYgY2hhckNvZGUgPD0gMTMpIHx8IGNoYXJDb2RlID09IDMyIHx8IGNoYXJDb2RlID09IDE2MCkgfHwgY2hhckNvZGUgPT0gNTc2MCB8fCBjaGFyQ29kZSA9PSA2MTU4IHx8XG4gICAgICAoY2hhckNvZGUgPj0gODE5MiAmJiAoY2hhckNvZGUgPD0gODIwMiB8fCBjaGFyQ29kZSA9PSA4MjMyIHx8IGNoYXJDb2RlID09IDgyMzMgfHwgY2hhckNvZGUgPT0gODIzOSB8fCBjaGFyQ29kZSA9PSA4Mjg3IHx8IGNoYXJDb2RlID09IDEyMjg4IHx8IGNoYXJDb2RlID09IDY1Mjc5KSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIGFsbCBgcGxhY2Vob2xkZXJgIGVsZW1lbnRzIGluIGBhcnJheWAgd2l0aCBhbiBpbnRlcm5hbCBwbGFjZWhvbGRlclxuICAgKiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiB0aGVpciBpbmRleGVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgKiBAcGFyYW0geyp9IHBsYWNlaG9sZGVyIFRoZSBwbGFjZWhvbGRlciB0byByZXBsYWNlLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgKi9cbiAgZnVuY3Rpb24gcmVwbGFjZUhvbGRlcnMoYXJyYXksIHBsYWNlaG9sZGVyKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzSW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgYXJyYXlbaW5kZXhdID0gUExBQ0VIT0xERVI7XG4gICAgICAgIHJlc3VsdFsrK3Jlc0luZGV4XSA9IGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuaXFgIG9wdGltaXplZCBmb3Igc29ydGVkIGFycmF5cyB3aXRob3V0IHN1cHBvcnRcbiAgICogZm9yIGNhbGxiYWNrIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUtdmFsdWUtZnJlZSBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHNvcnRlZFVuaXEoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIHNlZW4sXG4gICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzSW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSA6IHZhbHVlO1xuXG4gICAgICBpZiAoIWluZGV4IHx8IHNlZW4gIT09IGNvbXB1dGVkKSB7XG4gICAgICAgIHNlZW4gPSBjb21wdXRlZDtcbiAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbUxlZnRgIHRvIGdldCB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IG5vbi13aGl0ZXNwYWNlXG4gICAqIGNoYXJhY3RlciBvZiBgc3RyaW5nYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltbWVkTGVmdEluZGV4KHN0cmluZykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGggJiYgaXNTcGFjZShzdHJpbmcuY2hhckNvZGVBdChpbmRleCkpKSB7fVxuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLnRyaW1gIGFuZCBgXy50cmltUmlnaHRgIHRvIGdldCB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgbm9uLXdoaXRlc3BhY2VcbiAgICogY2hhcmFjdGVyIG9mIGBzdHJpbmdgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbW1lZFJpZ2h0SW5kZXgoc3RyaW5nKSB7XG4gICAgdmFyIGluZGV4ID0gc3RyaW5nLmxlbmd0aDtcblxuICAgIHdoaWxlIChpbmRleC0tICYmIGlzU3BhY2Uoc3RyaW5nLmNoYXJDb2RlQXQoaW5kZXgpKSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy51bmVzY2FwZWAgdG8gY29udmVydCBIVE1MIGVudGl0aWVzIHRvIGNoYXJhY3RlcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIHVuZXNjYXBlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gdW5lc2NhcGVIdG1sQ2hhcihjaHIpIHtcbiAgICByZXR1cm4gaHRtbFVuZXNjYXBlc1tjaHJdO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBwcmlzdGluZSBgbG9kYXNoYCBmdW5jdGlvbiB1c2luZyB0aGUgZ2l2ZW4gYGNvbnRleHRgIG9iamVjdC5cbiAgICpcbiAgICogQHN0YXRpY1xuICAgKiBAbWVtYmVyT2YgX1xuICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gW2NvbnRleHQ9cm9vdF0gVGhlIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYSBuZXcgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIF8ubWl4aW4oeyAnZm9vJzogXy5jb25zdGFudCgnZm9vJykgfSk7XG4gICAqXG4gICAqIHZhciBsb2Rhc2ggPSBfLnJ1bkluQ29udGV4dCgpO1xuICAgKiBsb2Rhc2gubWl4aW4oeyAnYmFyJzogbG9kYXNoLmNvbnN0YW50KCdiYXInKSB9KTtcbiAgICpcbiAgICogXy5pc0Z1bmN0aW9uKF8uZm9vKTtcbiAgICogLy8gPT4gdHJ1ZVxuICAgKiBfLmlzRnVuY3Rpb24oXy5iYXIpO1xuICAgKiAvLyA9PiBmYWxzZVxuICAgKlxuICAgKiBsb2Rhc2guaXNGdW5jdGlvbihsb2Rhc2guZm9vKTtcbiAgICogLy8gPT4gZmFsc2VcbiAgICogbG9kYXNoLmlzRnVuY3Rpb24obG9kYXNoLmJhcik7XG4gICAqIC8vID0+IHRydWVcbiAgICpcbiAgICogLy8gdXNpbmcgYGNvbnRleHRgIHRvIG1vY2sgYERhdGUjZ2V0VGltZWAgdXNlIGluIGBfLm5vd2BcbiAgICogdmFyIG1vY2sgPSBfLnJ1bkluQ29udGV4dCh7XG4gICAqICAgJ0RhdGUnOiBmdW5jdGlvbigpIHtcbiAgICogICAgIHJldHVybiB7ICdnZXRUaW1lJzogZ2V0VGltZU1vY2sgfTtcbiAgICogICB9XG4gICAqIH0pO1xuICAgKlxuICAgKiAvLyBvciBjcmVhdGluZyBhIHN1cGVkLXVwIGBkZWZlcmAgaW4gTm9kZS5qc1xuICAgKiB2YXIgZGVmZXIgPSBfLnJ1bkluQ29udGV4dCh7ICdzZXRUaW1lb3V0Jzogc2V0SW1tZWRpYXRlIH0pLmRlZmVyO1xuICAgKi9cbiAgZnVuY3Rpb24gcnVuSW5Db250ZXh0KGNvbnRleHQpIHtcbiAgICAvLyBBdm9pZCBpc3N1ZXMgd2l0aCBzb21lIEVTMyBlbnZpcm9ubWVudHMgdGhhdCBhdHRlbXB0IHRvIHVzZSB2YWx1ZXMsIG5hbWVkXG4gICAgLy8gYWZ0ZXIgYnVpbHQtaW4gY29uc3RydWN0b3JzIGxpa2UgYE9iamVjdGAsIGZvciB0aGUgY3JlYXRpb24gb2YgbGl0ZXJhbHMuXG4gICAgLy8gRVM1IGNsZWFycyB0aGlzIHVwIGJ5IHN0YXRpbmcgdGhhdCBsaXRlcmFscyBtdXN0IHVzZSBidWlsdC1pbiBjb25zdHJ1Y3RvcnMuXG4gICAgLy8gU2VlIGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDExLjEuNSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIGNvbnRleHQgPSBjb250ZXh0ID8gXy5kZWZhdWx0cyhyb290Lk9iamVjdCgpLCBjb250ZXh0LCBfLnBpY2socm9vdCwgY29udGV4dFByb3BzKSkgOiByb290O1xuXG4gICAgLyoqIE5hdGl2ZSBjb25zdHJ1Y3RvciByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBBcnJheSA9IGNvbnRleHQuQXJyYXksXG4gICAgICAgIERhdGUgPSBjb250ZXh0LkRhdGUsXG4gICAgICAgIEVycm9yID0gY29udGV4dC5FcnJvcixcbiAgICAgICAgRnVuY3Rpb24gPSBjb250ZXh0LkZ1bmN0aW9uLFxuICAgICAgICBNYXRoID0gY29udGV4dC5NYXRoLFxuICAgICAgICBOdW1iZXIgPSBjb250ZXh0Lk51bWJlcixcbiAgICAgICAgT2JqZWN0ID0gY29udGV4dC5PYmplY3QsXG4gICAgICAgIFJlZ0V4cCA9IGNvbnRleHQuUmVnRXhwLFxuICAgICAgICBTdHJpbmcgPSBjb250ZXh0LlN0cmluZyxcbiAgICAgICAgVHlwZUVycm9yID0gY29udGV4dC5UeXBlRXJyb3I7XG5cbiAgICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBhcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlLFxuICAgICAgICBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGUsXG4gICAgICAgIHN0cmluZ1Byb3RvID0gU3RyaW5nLnByb3RvdHlwZTtcblxuICAgIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGRlY29tcGlsZWQgc291cmNlIG9mIGZ1bmN0aW9ucy4gKi9cbiAgICB2YXIgZm5Ub1N0cmluZyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZztcblxuICAgIC8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xuICAgIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gICAgLyoqIFVzZWQgdG8gZ2VuZXJhdGUgdW5pcXVlIElEcy4gKi9cbiAgICB2YXIgaWRDb3VudGVyID0gMDtcblxuICAgIC8qKlxuICAgICAqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gICAgICogb2YgdmFsdWVzLlxuICAgICAqL1xuICAgIHZhciBvYmpUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gICAgLyoqIFVzZWQgdG8gcmVzdG9yZSB0aGUgb3JpZ2luYWwgYF9gIHJlZmVyZW5jZSBpbiBgXy5ub0NvbmZsaWN0YC4gKi9cbiAgICB2YXIgb2xkRGFzaCA9IHJvb3QuXztcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBhIG1ldGhvZCBpcyBuYXRpdmUuICovXG4gICAgdmFyIHJlSXNOYXRpdmUgPSBSZWdFeHAoJ14nICtcbiAgICAgIGZuVG9TdHJpbmcuY2FsbChoYXNPd25Qcm9wZXJ0eSkucmVwbGFjZSgvW1xcXFxeJC4qKz8oKVtcXF17fXxdL2csICdcXFxcJCYnKVxuICAgICAgLnJlcGxhY2UoL2hhc093blByb3BlcnR5fChmdW5jdGlvbikuKj8oPz1cXFxcXFwoKXwgZm9yIC4rPyg/PVxcXFxcXF0pL2csICckMS4qPycpICsgJyQnXG4gICAgKTtcblxuICAgIC8qKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gICAgdmFyIEFycmF5QnVmZmVyID0gY29udGV4dC5BcnJheUJ1ZmZlcixcbiAgICAgICAgY2xlYXJUaW1lb3V0ID0gY29udGV4dC5jbGVhclRpbWVvdXQsXG4gICAgICAgIHBhcnNlRmxvYXQgPSBjb250ZXh0LnBhcnNlRmxvYXQsXG4gICAgICAgIHBvdyA9IE1hdGgucG93LFxuICAgICAgICBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3RvLnByb3BlcnR5SXNFbnVtZXJhYmxlLFxuICAgICAgICBTZXQgPSBnZXROYXRpdmUoY29udGV4dCwgJ1NldCcpLFxuICAgICAgICBzZXRUaW1lb3V0ID0gY29udGV4dC5zZXRUaW1lb3V0LFxuICAgICAgICBzcGxpY2UgPSBhcnJheVByb3RvLnNwbGljZSxcbiAgICAgICAgVWludDhBcnJheSA9IGNvbnRleHQuVWludDhBcnJheSxcbiAgICAgICAgV2Vha01hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnV2Vha01hcCcpO1xuXG4gICAgLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbiAgICB2YXIgbmF0aXZlQ2VpbCA9IE1hdGguY2VpbCxcbiAgICAgICAgbmF0aXZlQ3JlYXRlID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2NyZWF0ZScpLFxuICAgICAgICBuYXRpdmVGbG9vciA9IE1hdGguZmxvb3IsXG4gICAgICAgIG5hdGl2ZUlzQXJyYXkgPSBnZXROYXRpdmUoQXJyYXksICdpc0FycmF5JyksXG4gICAgICAgIG5hdGl2ZUlzRmluaXRlID0gY29udGV4dC5pc0Zpbml0ZSxcbiAgICAgICAgbmF0aXZlS2V5cyA9IGdldE5hdGl2ZShPYmplY3QsICdrZXlzJyksXG4gICAgICAgIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgICAgICBuYXRpdmVNaW4gPSBNYXRoLm1pbixcbiAgICAgICAgbmF0aXZlTm93ID0gZ2V0TmF0aXZlKERhdGUsICdub3cnKSxcbiAgICAgICAgbmF0aXZlUGFyc2VJbnQgPSBjb250ZXh0LnBhcnNlSW50LFxuICAgICAgICBuYXRpdmVSYW5kb20gPSBNYXRoLnJhbmRvbTtcblxuICAgIC8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIGAtSW5maW5pdHlgIGFuZCBgSW5maW5pdHlgLiAqL1xuICAgIHZhciBORUdBVElWRV9JTkZJTklUWSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSxcbiAgICAgICAgUE9TSVRJVkVfSU5GSU5JVFkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG5cbiAgICAvKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB0aGUgbWF4aW11bSBsZW5ndGggYW5kIGluZGV4IG9mIGFuIGFycmF5LiAqL1xuICAgIHZhciBNQVhfQVJSQVlfTEVOR1RIID0gNDI5NDk2NzI5NSxcbiAgICAgICAgTUFYX0FSUkFZX0lOREVYID0gTUFYX0FSUkFZX0xFTkdUSCAtIDEsXG4gICAgICAgIEhBTEZfTUFYX0FSUkFZX0xFTkdUSCA9IE1BWF9BUlJBWV9MRU5HVEggPj4+IDE7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGFzIHRoZSBbbWF4aW11bSBsZW5ndGhdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLW51bWJlci5tYXhfc2FmZV9pbnRlZ2VyKVxuICAgICAqIG9mIGFuIGFycmF5LWxpa2UgdmFsdWUuXG4gICAgICovXG4gICAgdmFyIE1BWF9TQUZFX0lOVEVHRVIgPSA5MDA3MTk5MjU0NzQwOTkxO1xuXG4gICAgLyoqIFVzZWQgdG8gc3RvcmUgZnVuY3Rpb24gbWV0YWRhdGEuICovXG4gICAgdmFyIG1ldGFNYXAgPSBXZWFrTWFwICYmIG5ldyBXZWFrTWFwO1xuXG4gICAgLyoqIFVzZWQgdG8gbG9va3VwIHVubWluaWZpZWQgZnVuY3Rpb24gbmFtZXMuICovXG4gICAgdmFyIHJlYWxOYW1lcyA9IHt9O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIG9iamVjdCB3aGljaCB3cmFwcyBgdmFsdWVgIHRvIGVuYWJsZSBpbXBsaWNpdCBjaGFpbmluZy5cbiAgICAgKiBNZXRob2RzIHRoYXQgb3BlcmF0ZSBvbiBhbmQgcmV0dXJuIGFycmF5cywgY29sbGVjdGlvbnMsIGFuZCBmdW5jdGlvbnMgY2FuXG4gICAgICogYmUgY2hhaW5lZCB0b2dldGhlci4gTWV0aG9kcyB0aGF0IHJldHJpZXZlIGEgc2luZ2xlIHZhbHVlIG9yIG1heSByZXR1cm4gYVxuICAgICAqIHByaW1pdGl2ZSB2YWx1ZSB3aWxsIGF1dG9tYXRpY2FsbHkgZW5kIHRoZSBjaGFpbiByZXR1cm5pbmcgdGhlIHVud3JhcHBlZFxuICAgICAqIHZhbHVlLiBFeHBsaWNpdCBjaGFpbmluZyBtYXkgYmUgZW5hYmxlZCB1c2luZyBgXy5jaGFpbmAuIFRoZSBleGVjdXRpb24gb2ZcbiAgICAgKiBjaGFpbmVkIG1ldGhvZHMgaXMgbGF6eSwgdGhhdCBpcywgZXhlY3V0aW9uIGlzIGRlZmVycmVkIHVudGlsIGBfI3ZhbHVlYFxuICAgICAqIGlzIGltcGxpY2l0bHkgb3IgZXhwbGljaXRseSBjYWxsZWQuXG4gICAgICpcbiAgICAgKiBMYXp5IGV2YWx1YXRpb24gYWxsb3dzIHNldmVyYWwgbWV0aG9kcyB0byBzdXBwb3J0IHNob3J0Y3V0IGZ1c2lvbi4gU2hvcnRjdXRcbiAgICAgKiBmdXNpb24gaXMgYW4gb3B0aW1pemF0aW9uIHN0cmF0ZWd5IHdoaWNoIG1lcmdlIGl0ZXJhdGVlIGNhbGxzOyB0aGlzIGNhbiBoZWxwXG4gICAgICogdG8gYXZvaWQgdGhlIGNyZWF0aW9uIG9mIGludGVybWVkaWF0ZSBkYXRhIHN0cnVjdHVyZXMgYW5kIGdyZWF0bHkgcmVkdWNlIHRoZVxuICAgICAqIG51bWJlciBvZiBpdGVyYXRlZSBleGVjdXRpb25zLlxuICAgICAqXG4gICAgICogQ2hhaW5pbmcgaXMgc3VwcG9ydGVkIGluIGN1c3RvbSBidWlsZHMgYXMgbG9uZyBhcyB0aGUgYF8jdmFsdWVgIG1ldGhvZCBpc1xuICAgICAqIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgaW5jbHVkZWQgaW4gdGhlIGJ1aWxkLlxuICAgICAqXG4gICAgICogSW4gYWRkaXRpb24gdG8gbG9kYXNoIG1ldGhvZHMsIHdyYXBwZXJzIGhhdmUgYEFycmF5YCBhbmQgYFN0cmluZ2AgbWV0aG9kcy5cbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIGBBcnJheWAgbWV0aG9kcyBhcmU6XG4gICAgICogYGNvbmNhdGAsIGBqb2luYCwgYHBvcGAsIGBwdXNoYCwgYHJldmVyc2VgLCBgc2hpZnRgLCBgc2xpY2VgLCBgc29ydGAsXG4gICAgICogYHNwbGljZWAsIGFuZCBgdW5zaGlmdGBcbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIGBTdHJpbmdgIG1ldGhvZHMgYXJlOlxuICAgICAqIGByZXBsYWNlYCBhbmQgYHNwbGl0YFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uIGFyZTpcbiAgICAgKiBgY29tcGFjdGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBkcm9wUmlnaHRXaGlsZWAsIGBkcm9wV2hpbGVgLCBgZmlsdGVyYCxcbiAgICAgKiBgZmlyc3RgLCBgaW5pdGlhbGAsIGBsYXN0YCwgYG1hcGAsIGBwbHVja2AsIGByZWplY3RgLCBgcmVzdGAsIGByZXZlcnNlYCxcbiAgICAgKiBgc2xpY2VgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGFrZVJpZ2h0V2hpbGVgLCBgdGFrZVdoaWxlYCwgYHRvQXJyYXlgLFxuICAgICAqIGFuZCBgd2hlcmVgXG4gICAgICpcbiAgICAgKiBUaGUgY2hhaW5hYmxlIHdyYXBwZXIgbWV0aG9kcyBhcmU6XG4gICAgICogYGFmdGVyYCwgYGFyeWAsIGBhc3NpZ25gLCBgYXRgLCBgYmVmb3JlYCwgYGJpbmRgLCBgYmluZEFsbGAsIGBiaW5kS2V5YCxcbiAgICAgKiBgY2FsbGJhY2tgLCBgY2hhaW5gLCBgY2h1bmtgLCBgY29tbWl0YCwgYGNvbXBhY3RgLCBgY29uY2F0YCwgYGNvbnN0YW50YCxcbiAgICAgKiBgY291bnRCeWAsIGBjcmVhdGVgLCBgY3VycnlgLCBgZGVib3VuY2VgLCBgZGVmYXVsdHNgLCBgZGVmYXVsdHNEZWVwYCxcbiAgICAgKiBgZGVmZXJgLCBgZGVsYXlgLCBgZGlmZmVyZW5jZWAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBkcm9wUmlnaHRXaGlsZWAsXG4gICAgICogYGRyb3BXaGlsZWAsIGBmaWxsYCwgYGZpbHRlcmAsIGBmbGF0dGVuYCwgYGZsYXR0ZW5EZWVwYCwgYGZsb3dgLCBgZmxvd1JpZ2h0YCxcbiAgICAgKiBgZm9yRWFjaGAsIGBmb3JFYWNoUmlnaHRgLCBgZm9ySW5gLCBgZm9ySW5SaWdodGAsIGBmb3JPd25gLCBgZm9yT3duUmlnaHRgLFxuICAgICAqIGBmdW5jdGlvbnNgLCBgZ3JvdXBCeWAsIGBpbmRleEJ5YCwgYGluaXRpYWxgLCBgaW50ZXJzZWN0aW9uYCwgYGludmVydGAsXG4gICAgICogYGludm9rZWAsIGBrZXlzYCwgYGtleXNJbmAsIGBtYXBgLCBgbWFwS2V5c2AsIGBtYXBWYWx1ZXNgLCBgbWF0Y2hlc2AsXG4gICAgICogYG1hdGNoZXNQcm9wZXJ0eWAsIGBtZW1vaXplYCwgYG1lcmdlYCwgYG1ldGhvZGAsIGBtZXRob2RPZmAsIGBtaXhpbmAsXG4gICAgICogYG1vZEFyZ3NgLCBgbmVnYXRlYCwgYG9taXRgLCBgb25jZWAsIGBwYWlyc2AsIGBwYXJ0aWFsYCwgYHBhcnRpYWxSaWdodGAsXG4gICAgICogYHBhcnRpdGlvbmAsIGBwaWNrYCwgYHBsYW50YCwgYHBsdWNrYCwgYHByb3BlcnR5YCwgYHByb3BlcnR5T2ZgLCBgcHVsbGAsXG4gICAgICogYHB1bGxBdGAsIGBwdXNoYCwgYHJhbmdlYCwgYHJlYXJnYCwgYHJlamVjdGAsIGByZW1vdmVgLCBgcmVzdGAsIGByZXN0UGFyYW1gLFxuICAgICAqIGByZXZlcnNlYCwgYHNldGAsIGBzaHVmZmxlYCwgYHNsaWNlYCwgYHNvcnRgLCBgc29ydEJ5YCwgYHNvcnRCeUFsbGAsXG4gICAgICogYHNvcnRCeU9yZGVyYCwgYHNwbGljZWAsIGBzcHJlYWRgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGFrZVJpZ2h0V2hpbGVgLFxuICAgICAqIGB0YWtlV2hpbGVgLCBgdGFwYCwgYHRocm90dGxlYCwgYHRocnVgLCBgdGltZXNgLCBgdG9BcnJheWAsIGB0b1BsYWluT2JqZWN0YCxcbiAgICAgKiBgdHJhbnNmb3JtYCwgYHVuaW9uYCwgYHVuaXFgLCBgdW5zaGlmdGAsIGB1bnppcGAsIGB1bnppcFdpdGhgLCBgdmFsdWVzYCxcbiAgICAgKiBgdmFsdWVzSW5gLCBgd2hlcmVgLCBgd2l0aG91dGAsIGB3cmFwYCwgYHhvcmAsIGB6aXBgLCBgemlwT2JqZWN0YCwgYHppcFdpdGhgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBtZXRob2RzIHRoYXQgYXJlICoqbm90KiogY2hhaW5hYmxlIGJ5IGRlZmF1bHQgYXJlOlxuICAgICAqIGBhZGRgLCBgYXR0ZW1wdGAsIGBjYW1lbENhc2VgLCBgY2FwaXRhbGl6ZWAsIGBjZWlsYCwgYGNsb25lYCwgYGNsb25lRGVlcGAsXG4gICAgICogYGRlYnVycmAsIGBlbmRzV2l0aGAsIGBlc2NhcGVgLCBgZXNjYXBlUmVnRXhwYCwgYGV2ZXJ5YCwgYGZpbmRgLCBgZmluZEluZGV4YCxcbiAgICAgKiBgZmluZEtleWAsIGBmaW5kTGFzdGAsIGBmaW5kTGFzdEluZGV4YCwgYGZpbmRMYXN0S2V5YCwgYGZpbmRXaGVyZWAsIGBmaXJzdGAsXG4gICAgICogYGZsb29yYCwgYGdldGAsIGBndGAsIGBndGVgLCBgaGFzYCwgYGlkZW50aXR5YCwgYGluY2x1ZGVzYCwgYGluZGV4T2ZgLFxuICAgICAqIGBpblJhbmdlYCwgYGlzQXJndW1lbnRzYCwgYGlzQXJyYXlgLCBgaXNCb29sZWFuYCwgYGlzRGF0ZWAsIGBpc0VsZW1lbnRgLFxuICAgICAqIGBpc0VtcHR5YCwgYGlzRXF1YWxgLCBgaXNFcnJvcmAsIGBpc0Zpbml0ZWAgYGlzRnVuY3Rpb25gLCBgaXNNYXRjaGAsXG4gICAgICogYGlzTmF0aXZlYCwgYGlzTmFOYCwgYGlzTnVsbGAsIGBpc051bWJlcmAsIGBpc09iamVjdGAsIGBpc1BsYWluT2JqZWN0YCxcbiAgICAgKiBgaXNSZWdFeHBgLCBgaXNTdHJpbmdgLCBgaXNVbmRlZmluZWRgLCBgaXNUeXBlZEFycmF5YCwgYGpvaW5gLCBga2ViYWJDYXNlYCxcbiAgICAgKiBgbGFzdGAsIGBsYXN0SW5kZXhPZmAsIGBsdGAsIGBsdGVgLCBgbWF4YCwgYG1pbmAsIGBub0NvbmZsaWN0YCwgYG5vb3BgLFxuICAgICAqIGBub3dgLCBgcGFkYCwgYHBhZExlZnRgLCBgcGFkUmlnaHRgLCBgcGFyc2VJbnRgLCBgcG9wYCwgYHJhbmRvbWAsIGByZWR1Y2VgLFxuICAgICAqIGByZWR1Y2VSaWdodGAsIGByZXBlYXRgLCBgcmVzdWx0YCwgYHJvdW5kYCwgYHJ1bkluQ29udGV4dGAsIGBzaGlmdGAsIGBzaXplYCxcbiAgICAgKiBgc25ha2VDYXNlYCwgYHNvbWVgLCBgc29ydGVkSW5kZXhgLCBgc29ydGVkTGFzdEluZGV4YCwgYHN0YXJ0Q2FzZWAsXG4gICAgICogYHN0YXJ0c1dpdGhgLCBgc3VtYCwgYHRlbXBsYXRlYCwgYHRyaW1gLCBgdHJpbUxlZnRgLCBgdHJpbVJpZ2h0YCwgYHRydW5jYCxcbiAgICAgKiBgdW5lc2NhcGVgLCBgdW5pcXVlSWRgLCBgdmFsdWVgLCBhbmQgYHdvcmRzYFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kIGBzYW1wbGVgIHdpbGwgcmV0dXJuIGEgd3JhcHBlZCB2YWx1ZSB3aGVuIGBuYCBpcyBwcm92aWRlZCxcbiAgICAgKiBvdGhlcndpc2UgYW4gdW53cmFwcGVkIHZhbHVlIGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQG5hbWUgX1xuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBjYXRlZ29yeSBDaGFpblxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyLCAzXSk7XG4gICAgICpcbiAgICAgKiAvLyByZXR1cm5zIGFuIHVud3JhcHBlZCB2YWx1ZVxuICAgICAqIHdyYXBwZWQucmVkdWNlKGZ1bmN0aW9uKHRvdGFsLCBuKSB7XG4gICAgICogICByZXR1cm4gdG90YWwgKyBuO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDZcbiAgICAgKlxuICAgICAqIC8vIHJldHVybnMgYSB3cmFwcGVkIHZhbHVlXG4gICAgICogdmFyIHNxdWFyZXMgPSB3cmFwcGVkLm1hcChmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAqIG47XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShzcXVhcmVzLnZhbHVlKCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb2Rhc2godmFsdWUpIHtcbiAgICAgIGlmIChpc09iamVjdExpa2UodmFsdWUpICYmICFpc0FycmF5KHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpKSB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExvZGFzaFdyYXBwZXIpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdfX2NoYWluX18nKSAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnX193cmFwcGVkX18nKSkge1xuICAgICAgICAgIHJldHVybiB3cmFwcGVyQ2xvbmUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBmdW5jdGlvbiB3aG9zZSBwcm90b3R5cGUgYWxsIGNoYWluaW5nIHdyYXBwZXJzIGluaGVyaXQgZnJvbS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUxvZGFzaCgpIHtcbiAgICAgIC8vIE5vIG9wZXJhdGlvbiBwZXJmb3JtZWQuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIGBsb2Rhc2hgIHdyYXBwZXIgb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtjaGFpbkFsbF0gRW5hYmxlIGNoYWluaW5nIGZvciBhbGwgd3JhcHBlciBtZXRob2RzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthY3Rpb25zPVtdXSBBY3Rpb25zIHRvIHBlZm9ybSB0byByZXNvbHZlIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTG9kYXNoV3JhcHBlcih2YWx1ZSwgY2hhaW5BbGwsIGFjdGlvbnMpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBhY3Rpb25zIHx8IFtdO1xuICAgICAgdGhpcy5fX2NoYWluX18gPSAhIWNoYWluQWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIG9iamVjdCBlbnZpcm9ubWVudCBmZWF0dXJlIGZsYWdzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHN1cHBvcnQgPSBsb2Rhc2guc3VwcG9ydCA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogQnkgZGVmYXVsdCwgdGhlIHRlbXBsYXRlIGRlbGltaXRlcnMgdXNlZCBieSBsb2Rhc2ggYXJlIGxpa2UgdGhvc2UgaW5cbiAgICAgKiBlbWJlZGRlZCBSdWJ5IChFUkIpLiBDaGFuZ2UgdGhlIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2VcbiAgICAgKiBhbHRlcm5hdGl2ZSBkZWxpbWl0ZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgbG9kYXNoLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBiZSBIVE1MLWVzY2FwZWQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUgUmVnRXhwXG4gICAgICAgKi9cbiAgICAgICdlc2NhcGUnOiByZUVzY2FwZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIGRldGVjdCBjb2RlIHRvIGJlIGV2YWx1YXRlZC5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSBSZWdFeHBcbiAgICAgICAqL1xuICAgICAgJ2V2YWx1YXRlJzogcmVFdmFsdWF0ZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIGRldGVjdCBgZGF0YWAgcHJvcGVydHkgdmFsdWVzIHRvIGluamVjdC5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSBSZWdFeHBcbiAgICAgICAqL1xuICAgICAgJ2ludGVycG9sYXRlJzogcmVJbnRlcnBvbGF0ZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIHJlZmVyZW5jZSB0aGUgZGF0YSBvYmplY3QgaW4gdGhlIHRlbXBsYXRlIHRleHQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUgc3RyaW5nXG4gICAgICAgKi9cbiAgICAgICd2YXJpYWJsZSc6ICcnLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gaW1wb3J0IHZhcmlhYmxlcyBpbnRvIHRoZSBjb21waWxlZCB0ZW1wbGF0ZS5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgICAqL1xuICAgICAgJ2ltcG9ydHMnOiB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEEgcmVmZXJlbmNlIHRvIHRoZSBgbG9kYXNoYCBmdW5jdGlvbi5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5ncy5pbXBvcnRzXG4gICAgICAgICAqIEB0eXBlIEZ1bmN0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAnXyc6IGxvZGFzaFxuICAgICAgfVxuICAgIH07XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbGF6eSB3cmFwcGVyIG9iamVjdCB3aGljaCB3cmFwcyBgdmFsdWVgIHRvIGVuYWJsZSBsYXp5IGV2YWx1YXRpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTGF6eVdyYXBwZXIodmFsdWUpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgICAgIHRoaXMuX19kaXJfXyA9IDE7XG4gICAgICB0aGlzLl9fZmlsdGVyZWRfXyA9IGZhbHNlO1xuICAgICAgdGhpcy5fX2l0ZXJhdGVlc19fID0gW107XG4gICAgICB0aGlzLl9fdGFrZUNvdW50X18gPSBQT1NJVElWRV9JTkZJTklUWTtcbiAgICAgIHRoaXMuX192aWV3c19fID0gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBsYXp5IHdyYXBwZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbG9uZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBgTGF6eVdyYXBwZXJgIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXp5Q2xvbmUoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbmV3IExhenlXcmFwcGVyKHRoaXMuX193cmFwcGVkX18pO1xuICAgICAgcmVzdWx0Ll9fYWN0aW9uc19fID0gYXJyYXlDb3B5KHRoaXMuX19hY3Rpb25zX18pO1xuICAgICAgcmVzdWx0Ll9fZGlyX18gPSB0aGlzLl9fZGlyX187XG4gICAgICByZXN1bHQuX19maWx0ZXJlZF9fID0gdGhpcy5fX2ZpbHRlcmVkX187XG4gICAgICByZXN1bHQuX19pdGVyYXRlZXNfXyA9IGFycmF5Q29weSh0aGlzLl9faXRlcmF0ZWVzX18pO1xuICAgICAgcmVzdWx0Ll9fdGFrZUNvdW50X18gPSB0aGlzLl9fdGFrZUNvdW50X187XG4gICAgICByZXN1bHQuX192aWV3c19fID0gYXJyYXlDb3B5KHRoaXMuX192aWV3c19fKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZXJzZXMgdGhlIGRpcmVjdGlvbiBvZiBsYXp5IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgcmV2ZXJzZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyByZXZlcnNlZCBgTGF6eVdyYXBwZXJgIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXp5UmV2ZXJzZSgpIHtcbiAgICAgIGlmICh0aGlzLl9fZmlsdGVyZWRfXykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IExhenlXcmFwcGVyKHRoaXMpO1xuICAgICAgICByZXN1bHQuX19kaXJfXyA9IC0xO1xuICAgICAgICByZXN1bHQuX19maWx0ZXJlZF9fID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IHRoaXMuY2xvbmUoKTtcbiAgICAgICAgcmVzdWx0Ll9fZGlyX18gKj0gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4dHJhY3RzIHRoZSB1bndyYXBwZWQgdmFsdWUgZnJvbSBpdHMgbGF6eSB3cmFwcGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSB2YWx1ZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eVZhbHVlKCkge1xuICAgICAgdmFyIGFycmF5ID0gdGhpcy5fX3dyYXBwZWRfXy52YWx1ZSgpLFxuICAgICAgICAgIGRpciA9IHRoaXMuX19kaXJfXyxcbiAgICAgICAgICBpc0FyciA9IGlzQXJyYXkoYXJyYXkpLFxuICAgICAgICAgIGlzUmlnaHQgPSBkaXIgPCAwLFxuICAgICAgICAgIGFyckxlbmd0aCA9IGlzQXJyID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICB2aWV3ID0gZ2V0VmlldygwLCBhcnJMZW5ndGgsIHRoaXMuX192aWV3c19fKSxcbiAgICAgICAgICBzdGFydCA9IHZpZXcuc3RhcnQsXG4gICAgICAgICAgZW5kID0gdmlldy5lbmQsXG4gICAgICAgICAgbGVuZ3RoID0gZW5kIC0gc3RhcnQsXG4gICAgICAgICAgaW5kZXggPSBpc1JpZ2h0ID8gZW5kIDogKHN0YXJ0IC0gMSksXG4gICAgICAgICAgaXRlcmF0ZWVzID0gdGhpcy5fX2l0ZXJhdGVlc19fLFxuICAgICAgICAgIGl0ZXJMZW5ndGggPSBpdGVyYXRlZXMubGVuZ3RoLFxuICAgICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgICB0YWtlQ291bnQgPSBuYXRpdmVNaW4obGVuZ3RoLCB0aGlzLl9fdGFrZUNvdW50X18pO1xuXG4gICAgICBpZiAoIWlzQXJyIHx8IGFyckxlbmd0aCA8IExBUkdFX0FSUkFZX1NJWkUgfHwgKGFyckxlbmd0aCA9PSBsZW5ndGggJiYgdGFrZUNvdW50ID09IGxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VXcmFwcGVyVmFsdWUoKGlzUmlnaHQgJiYgaXNBcnIpID8gYXJyYXkucmV2ZXJzZSgpIDogYXJyYXksIHRoaXMuX19hY3Rpb25zX18pO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuXG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlIChsZW5ndGgtLSAmJiByZXNJbmRleCA8IHRha2VDb3VudCkge1xuICAgICAgICBpbmRleCArPSBkaXI7XG5cbiAgICAgICAgdmFyIGl0ZXJJbmRleCA9IC0xLFxuICAgICAgICAgICAgdmFsdWUgPSBhcnJheVtpbmRleF07XG5cbiAgICAgICAgd2hpbGUgKCsraXRlckluZGV4IDwgaXRlckxlbmd0aCkge1xuICAgICAgICAgIHZhciBkYXRhID0gaXRlcmF0ZWVzW2l0ZXJJbmRleF0sXG4gICAgICAgICAgICAgIGl0ZXJhdGVlID0gZGF0YS5pdGVyYXRlZSxcbiAgICAgICAgICAgICAgdHlwZSA9IGRhdGEudHlwZSxcbiAgICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgICAgICBpZiAodHlwZSA9PSBMQVpZX01BUF9GTEFHKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGNvbXB1dGVkO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIWNvbXB1dGVkKSB7XG4gICAgICAgICAgICBpZiAodHlwZSA9PSBMQVpZX0ZJTFRFUl9GTEFHKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2FjaGUgb2JqZWN0IHRvIHN0b3JlIGtleS92YWx1ZSBwYWlycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBuYW1lIENhY2hlXG4gICAgICogQG1lbWJlck9mIF8ubWVtb2l6ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIE1hcENhY2hlKCkge1xuICAgICAgdGhpcy5fX2RhdGFfXyA9IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBjYWNoZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZGVsZXRlXG4gICAgICogQG1lbWJlck9mIF8ubWVtb2l6ZS5DYWNoZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQgc3VjY2Vzc2Z1bGx5LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwRGVsZXRlKGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuaGFzKGtleSkgJiYgZGVsZXRlIHRoaXMuX19kYXRhX19ba2V5XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjYWNoZWQgdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgXy5tZW1vaXplLkNhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNhY2hlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBHZXQoa2V5KSB7XG4gICAgICByZXR1cm4ga2V5ID09ICdfX3Byb3RvX18nID8gdW5kZWZpbmVkIDogdGhpcy5fX2RhdGFfX1trZXldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIGNhY2hlZCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgXy5tZW1vaXplLkNhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcEhhcyhrZXkpIHtcbiAgICAgIHJldHVybiBrZXkgIT0gJ19fcHJvdG9fXycgJiYgaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLl9fZGF0YV9fLCBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgYHZhbHVlYCB0byBga2V5YCBvZiB0aGUgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHNldFxuICAgICAqIEBtZW1iZXJPZiBfLm1lbW9pemUuQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGNhY2hlLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNhY2hlLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNhY2hlIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBTZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgaWYgKGtleSAhPSAnX19wcm90b19fJykge1xuICAgICAgICB0aGlzLl9fZGF0YV9fW2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQ3JlYXRlcyBhIGNhY2hlIG9iamVjdCB0byBzdG9yZSB1bmlxdWUgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFNldENhY2hlKHZhbHVlcykge1xuICAgICAgdmFyIGxlbmd0aCA9IHZhbHVlcyA/IHZhbHVlcy5sZW5ndGggOiAwO1xuXG4gICAgICB0aGlzLmRhdGEgPSB7ICdoYXNoJzogbmF0aXZlQ3JlYXRlKG51bGwpLCAnc2V0JzogbmV3IFNldCB9O1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHRoaXMucHVzaCh2YWx1ZXNbbGVuZ3RoXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gYGNhY2hlYCBtaW1pY2tpbmcgdGhlIHJldHVybiBzaWduYXR1cmUgb2ZcbiAgICAgKiBgXy5pbmRleE9mYCBieSByZXR1cm5pbmcgYDBgIGlmIHRoZSB2YWx1ZSBpcyBmb3VuZCwgZWxzZSBgLTFgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gY2FjaGUgVGhlIGNhY2hlIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYDBgIGlmIGB2YWx1ZWAgaXMgZm91bmQsIGVsc2UgYC0xYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYWNoZUluZGV4T2YoY2FjaGUsIHZhbHVlKSB7XG4gICAgICB2YXIgZGF0YSA9IGNhY2hlLmRhdGEsXG4gICAgICAgICAgcmVzdWx0ID0gKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fCBpc09iamVjdCh2YWx1ZSkpID8gZGF0YS5zZXQuaGFzKHZhbHVlKSA6IGRhdGEuaGFzaFt2YWx1ZV07XG5cbiAgICAgIHJldHVybiByZXN1bHQgPyAwIDogLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBgdmFsdWVgIHRvIHRoZSBjYWNoZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgcHVzaFxuICAgICAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhY2hlUHVzaCh2YWx1ZSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLmRhdGE7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8IGlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICBkYXRhLnNldC5hZGQodmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGF0YS5oYXNoW3ZhbHVlXSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBhcnJheSBqb2luaW5nIGBhcnJheWAgd2l0aCBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gam9pbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvdGhlciBUaGUgb3RoZXIgYXJyYXkgdG8gam9pbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBjb25jYXRlbmF0ZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlDb25jYXQoYXJyYXksIG90aGVyKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgb3RoSW5kZXggPSAtMSxcbiAgICAgICAgICBvdGhMZW5ndGggPSBvdGhlci5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoICsgb3RoTGVuZ3RoKTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGFycmF5W2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK290aEluZGV4IDwgb3RoTGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleCsrXSA9IG90aGVyW290aEluZGV4XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29waWVzIHRoZSB2YWx1ZXMgb2YgYHNvdXJjZWAgdG8gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gc291cmNlIFRoZSBhcnJheSB0byBjb3B5IHZhbHVlcyBmcm9tLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheT1bXV0gVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIHRvLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFycmF5Q29weShzb3VyY2UsIGFycmF5KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBzb3VyY2UubGVuZ3RoO1xuXG4gICAgICBhcnJheSB8fCAoYXJyYXkgPSBBcnJheShsZW5ndGgpKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGFycmF5W2luZGV4XSA9IHNvdXJjZVtpbmRleF07XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlFYWNoKGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpID09PSBmYWxzZSkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hSaWdodGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAgICogY2FsbGJhY2sgc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheUVhY2hSaWdodChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbbGVuZ3RoXSwgbGVuZ3RoLCBhcnJheSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZXZlcnlgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlFdmVyeShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGlmICghcHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlRXh0cmVtdW1gIGZvciBhcnJheXMgd2hpY2ggaW52b2tlcyBgaXRlcmF0ZWVgXG4gICAgICogd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb21wYXJhdG9yIFRoZSBmdW5jdGlvbiB1c2VkIHRvIGNvbXBhcmUgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gZXhWYWx1ZSBUaGUgaW5pdGlhbCBleHRyZW11bSB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZXh0cmVtdW0gdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlFeHRyZW11bShhcnJheSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IsIGV4VmFsdWUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBjb21wdXRlZCA9IGV4VmFsdWUsXG4gICAgICAgICAgcmVzdWx0ID0gY29tcHV0ZWQ7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGN1cnJlbnQgPSAraXRlcmF0ZWUodmFsdWUpO1xuXG4gICAgICAgIGlmIChjb21wYXJhdG9yKGN1cnJlbnQsIGNvbXB1dGVkKSkge1xuICAgICAgICAgIGNvbXB1dGVkID0gY3VycmVudDtcbiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZmlsdGVyYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2tcbiAgICAgKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheUZpbHRlcihhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzSW5kZXggPSAtMSxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLm1hcGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrXG4gICAgICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlNYXAoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGl0ZXJhdGVlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwZW5kcyB0aGUgZWxlbWVudHMgb2YgYHZhbHVlc2AgdG8gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBhcHBlbmQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlQdXNoKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgb2Zmc2V0ID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBhcnJheVtvZmZzZXQgKyBpbmRleF0gPSB2YWx1ZXNbaW5kZXhdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5yZWR1Y2VgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2luaXRGcm9tQXJyYXldIFNwZWNpZnkgdXNpbmcgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YFxuICAgICAqICBhcyB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlSZWR1Y2UoYXJyYXksIGl0ZXJhdGVlLCBhY2N1bXVsYXRvciwgaW5pdEZyb21BcnJheSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBpZiAoaW5pdEZyb21BcnJheSAmJiBsZW5ndGgpIHtcbiAgICAgICAgYWNjdW11bGF0b3IgPSBhcnJheVsrK2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8ucmVkdWNlUmlnaHRgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgICAqIGNhbGxiYWNrIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2luaXRGcm9tQXJyYXldIFNwZWNpZnkgdXNpbmcgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgXG4gICAgICogIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVJlZHVjZVJpZ2h0KGFycmF5LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRGcm9tQXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoaW5pdEZyb21BcnJheSAmJiBsZW5ndGgpIHtcbiAgICAgICAgYWNjdW11bGF0b3IgPSBhcnJheVstLWxlbmd0aF07XG4gICAgICB9XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgYWNjdW11bGF0b3IgPSBpdGVyYXRlZShhY2N1bXVsYXRvciwgYXJyYXlbbGVuZ3RoXSwgbGVuZ3RoLCBhcnJheSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNvbWVgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFycmF5U29tZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc3VtYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2tcbiAgICAgKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy4uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdW0uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlTdW0oYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IDA7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICByZXN1bHQgKz0gK2l0ZXJhdGVlKGFycmF5W2xlbmd0aF0pIHx8IDA7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNgIHRvIGN1c3RvbWl6ZSBpdHMgYF8uYXNzaWduYCB1c2UuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gb2JqZWN0VmFsdWUgVGhlIGRlc3RpbmF0aW9uIG9iamVjdCBwcm9wZXJ0eSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0geyp9IHNvdXJjZVZhbHVlIFRoZSBzb3VyY2Ugb2JqZWN0IHByb3BlcnR5IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB2YWx1ZSB0byBhc3NpZ24gdG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NpZ25EZWZhdWx0cyhvYmplY3RWYWx1ZSwgc291cmNlVmFsdWUpIHtcbiAgICAgIHJldHVybiBvYmplY3RWYWx1ZSA9PT0gdW5kZWZpbmVkID8gc291cmNlVmFsdWUgOiBvYmplY3RWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGJ5IGBfLnRlbXBsYXRlYCB0byBjdXN0b21pemUgaXRzIGBfLmFzc2lnbmAgdXNlLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYXNzaWduRGVmYXVsdHNgIGV4Y2VwdCB0aGF0IGl0IGlnbm9yZXNcbiAgICAgKiBpbmhlcml0ZWQgcHJvcGVydHkgdmFsdWVzIHdoZW4gY2hlY2tpbmcgaWYgYSBwcm9wZXJ0eSBpcyBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBvYmplY3RWYWx1ZSBUaGUgZGVzdGluYXRpb24gb2JqZWN0IHByb3BlcnR5IHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gc291cmNlVmFsdWUgVGhlIHNvdXJjZSBvYmplY3QgcHJvcGVydHkgdmFsdWUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IGFzc29jaWF0ZWQgd2l0aCB0aGUgb2JqZWN0IGFuZCBzb3VyY2UgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdmFsdWUgdG8gYXNzaWduIHRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduT3duRGVmYXVsdHMob2JqZWN0VmFsdWUsIHNvdXJjZVZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgcmV0dXJuIChvYmplY3RWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8ICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSlcbiAgICAgICAgPyBzb3VyY2VWYWx1ZVxuICAgICAgICA6IG9iamVjdFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5hc3NpZ25gIGZvciBjdXN0b21pemluZyBhc3NpZ25lZCB2YWx1ZXMgd2l0aG91dFxuICAgICAqIHN1cHBvcnQgZm9yIGFyZ3VtZW50IGp1Z2dsaW5nLCBtdWx0aXBsZSBzb3VyY2VzLCBhbmQgYHRoaXNgIGJpbmRpbmcgYGN1c3RvbWl6ZXJgXG4gICAgICogZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduV2l0aChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplcikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcHJvcHMgPSBrZXlzKHNvdXJjZSksXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdLFxuICAgICAgICAgICAgdmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICAgIHJlc3VsdCA9IGN1c3RvbWl6ZXIodmFsdWUsIHNvdXJjZVtrZXldLCBrZXksIG9iamVjdCwgc291cmNlKTtcblxuICAgICAgICBpZiAoKHJlc3VsdCA9PT0gcmVzdWx0ID8gKHJlc3VsdCAhPT0gdmFsdWUpIDogKHZhbHVlID09PSB2YWx1ZSkpIHx8XG4gICAgICAgICAgICAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSkge1xuICAgICAgICAgIG9iamVjdFtrZXldID0gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmFzc2lnbmAgd2l0aG91dCBzdXBwb3J0IGZvciBhcmd1bWVudCBqdWdnbGluZyxcbiAgICAgKiBtdWx0aXBsZSBzb3VyY2VzLCBhbmQgYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXNzaWduKG9iamVjdCwgc291cmNlKSB7XG4gICAgICByZXR1cm4gc291cmNlID09IG51bGxcbiAgICAgICAgPyBvYmplY3RcbiAgICAgICAgOiBiYXNlQ29weShzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5hdGAgd2l0aG91dCBzdXBwb3J0IGZvciBzdHJpbmcgY29sbGVjdGlvbnNcbiAgICAgKiBhbmQgaW5kaXZpZHVhbCBrZXkgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJbXXxzdHJpbmdbXX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIG9yIGluZGV4ZXMgb2YgZWxlbWVudHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwaWNrZWQgZWxlbWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUF0KGNvbGxlY3Rpb24sIHByb3BzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc05pbCA9IGNvbGxlY3Rpb24gPT0gbnVsbCxcbiAgICAgICAgICBpc0FyciA9ICFpc05pbCAmJiBpc0FycmF5TGlrZShjb2xsZWN0aW9uKSxcbiAgICAgICAgICBsZW5ndGggPSBpc0FyciA/IGNvbGxlY3Rpb24ubGVuZ3RoIDogMCxcbiAgICAgICAgICBwcm9wc0xlbmd0aCA9IHByb3BzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShwcm9wc0xlbmd0aCk7XG5cbiAgICAgIHdoaWxlKCsraW5kZXggPCBwcm9wc0xlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuICAgICAgICBpZiAoaXNBcnIpIHtcbiAgICAgICAgICByZXN1bHRbaW5kZXhdID0gaXNJbmRleChrZXksIGxlbmd0aCkgPyBjb2xsZWN0aW9uW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0W2luZGV4XSA9IGlzTmlsID8gdW5kZWZpbmVkIDogY29sbGVjdGlvbltrZXldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHRvIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20uXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGNvcHkuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3Q9e31dIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIHRvLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNvcHkoc291cmNlLCBwcm9wcywgb2JqZWN0KSB7XG4gICAgICBvYmplY3QgfHwgKG9iamVjdCA9IHt9KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuICAgICAgICBvYmplY3Rba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jYWxsYmFja2Agd2hpY2ggc3VwcG9ydHMgc3BlY2lmeWluZyB0aGVcbiAgICAgKiBudW1iZXIgb2YgYXJndW1lbnRzIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFtmdW5jPV8uaWRlbnRpdHldIFRoZSB2YWx1ZSB0byBjb252ZXJ0IHRvIGEgY2FsbGJhY2suXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ0NvdW50XSBUaGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDYWxsYmFjayhmdW5jLCB0aGlzQXJnLCBhcmdDb3VudCkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZnVuYztcbiAgICAgIGlmICh0eXBlID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNBcmcgPT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gZnVuY1xuICAgICAgICAgIDogYmluZENhbGxiYWNrKGZ1bmMsIHRoaXNBcmcsIGFyZ0NvdW50KTtcbiAgICAgIH1cbiAgICAgIGlmIChmdW5jID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGlkZW50aXR5O1xuICAgICAgfVxuICAgICAgaWYgKHR5cGUgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VNYXRjaGVzKGZ1bmMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXNBcmcgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHByb3BlcnR5KGZ1bmMpXG4gICAgICAgIDogYmFzZU1hdGNoZXNQcm9wZXJ0eShmdW5jLCB0aGlzQXJnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jbG9uZWAgd2l0aG91dCBzdXBwb3J0IGZvciBhcmd1bWVudCBqdWdnbGluZ1xuICAgICAqIGFuZCBgdGhpc2AgYmluZGluZyBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSBUaGUga2V5IG9mIGB2YWx1ZWAuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgYHZhbHVlYCBiZWxvbmdzIHRvLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gQXNzb2NpYXRlcyBjbG9uZXMgd2l0aCBzb3VyY2UgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNsb25lKHZhbHVlLCBpc0RlZXAsIGN1c3RvbWl6ZXIsIGtleSwgb2JqZWN0LCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgdmFyIHJlc3VsdDtcbiAgICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICAgIHJlc3VsdCA9IG9iamVjdCA/IGN1c3RvbWl6ZXIodmFsdWUsIGtleSwgb2JqZWN0KSA6IGN1c3RvbWl6ZXIodmFsdWUpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBpZiAoIWlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICB2YXIgaXNBcnIgPSBpc0FycmF5KHZhbHVlKTtcbiAgICAgIGlmIChpc0Fycikge1xuICAgICAgICByZXN1bHQgPSBpbml0Q2xvbmVBcnJheSh2YWx1ZSk7XG4gICAgICAgIGlmICghaXNEZWVwKSB7XG4gICAgICAgICAgcmV0dXJuIGFycmF5Q29weSh2YWx1ZSwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHRhZyA9IG9ialRvU3RyaW5nLmNhbGwodmFsdWUpLFxuICAgICAgICAgICAgaXNGdW5jID0gdGFnID09IGZ1bmNUYWc7XG5cbiAgICAgICAgaWYgKHRhZyA9PSBvYmplY3RUYWcgfHwgdGFnID09IGFyZ3NUYWcgfHwgKGlzRnVuYyAmJiAhb2JqZWN0KSkge1xuICAgICAgICAgIHJlc3VsdCA9IGluaXRDbG9uZU9iamVjdChpc0Z1bmMgPyB7fSA6IHZhbHVlKTtcbiAgICAgICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICAgICAgcmV0dXJuIGJhc2VBc3NpZ24ocmVzdWx0LCB2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBjbG9uZWFibGVUYWdzW3RhZ11cbiAgICAgICAgICAgID8gaW5pdENsb25lQnlUYWcodmFsdWUsIHRhZywgaXNEZWVwKVxuICAgICAgICAgICAgOiAob2JqZWN0ID8gdmFsdWUgOiB7fSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIENoZWNrIGZvciBjaXJjdWxhciByZWZlcmVuY2VzIGFuZCByZXR1cm4gaXRzIGNvcnJlc3BvbmRpbmcgY2xvbmUuXG4gICAgICBzdGFja0EgfHwgKHN0YWNrQSA9IFtdKTtcbiAgICAgIHN0YWNrQiB8fCAoc3RhY2tCID0gW10pO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gc3RhY2tBLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoc3RhY2tBW2xlbmd0aF0gPT0gdmFsdWUpIHtcbiAgICAgICAgICByZXR1cm4gc3RhY2tCW2xlbmd0aF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgc291cmNlIHZhbHVlIHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cyBhbmQgYXNzb2NpYXRlIGl0IHdpdGggaXRzIGNsb25lLlxuICAgICAgc3RhY2tBLnB1c2godmFsdWUpO1xuICAgICAgc3RhY2tCLnB1c2gocmVzdWx0KTtcblxuICAgICAgLy8gUmVjdXJzaXZlbHkgcG9wdWxhdGUgY2xvbmUgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgIChpc0FyciA/IGFycmF5RWFjaCA6IGJhc2VGb3JPd24pKHZhbHVlLCBmdW5jdGlvbihzdWJWYWx1ZSwga2V5KSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gYmFzZUNsb25lKHN1YlZhbHVlLCBpc0RlZXAsIGN1c3RvbWl6ZXIsIGtleSwgdmFsdWUsIHN0YWNrQSwgc3RhY2tCKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jcmVhdGVgIHdpdGhvdXQgc3VwcG9ydCBmb3IgYXNzaWduaW5nXG4gICAgICogcHJvcGVydGllcyB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwcm90b3R5cGUgVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUNyZWF0ZSA9IChmdW5jdGlvbigpIHtcbiAgICAgIGZ1bmN0aW9uIG9iamVjdCgpIHt9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocHJvdG90eXBlKSB7XG4gICAgICAgIGlmIChpc09iamVjdChwcm90b3R5cGUpKSB7XG4gICAgICAgICAgb2JqZWN0LnByb3RvdHlwZSA9IHByb3RvdHlwZTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IG9iamVjdDtcbiAgICAgICAgICBvYmplY3QucHJvdG90eXBlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwge307XG4gICAgICB9O1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5kZWxheWAgYW5kIGBfLmRlZmVyYCB3aGljaCBhY2NlcHRzIGFuIGluZGV4XG4gICAgICogb2Ygd2hlcmUgdG8gc2xpY2UgdGhlIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkgaW52b2NhdGlvbi5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gYXJncyBUaGUgYXJndW1lbnRzIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VEZWxheShmdW5jLCB3YWl0LCBhcmdzKSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpIHsgZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpOyB9LCB3YWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5kaWZmZXJlbmNlYCB3aGljaCBhY2NlcHRzIGEgc2luZ2xlIGFycmF5XG4gICAgICogb2YgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VEaWZmZXJlbmNlKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmRleE9mID0gZ2V0SW5kZXhPZigpLFxuICAgICAgICAgIGlzQ29tbW9uID0gaW5kZXhPZiA9PSBiYXNlSW5kZXhPZixcbiAgICAgICAgICBjYWNoZSA9IChpc0NvbW1vbiAmJiB2YWx1ZXMubGVuZ3RoID49IExBUkdFX0FSUkFZX1NJWkUpID8gY3JlYXRlQ2FjaGUodmFsdWVzKSA6IG51bGwsXG4gICAgICAgICAgdmFsdWVzTGVuZ3RoID0gdmFsdWVzLmxlbmd0aDtcblxuICAgICAgaWYgKGNhY2hlKSB7XG4gICAgICAgIGluZGV4T2YgPSBjYWNoZUluZGV4T2Y7XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIHZhbHVlcyA9IGNhY2hlO1xuICAgICAgfVxuICAgICAgb3V0ZXI6XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG5cbiAgICAgICAgaWYgKGlzQ29tbW9uICYmIHZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgICAgIHZhciB2YWx1ZXNJbmRleCA9IHZhbHVlc0xlbmd0aDtcbiAgICAgICAgICB3aGlsZSAodmFsdWVzSW5kZXgtLSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlc1t2YWx1ZXNJbmRleF0gPT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaW5kZXhPZih2YWx1ZXMsIHZhbHVlLCAwKSA8IDApIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yRWFjaGAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdHxzdHJpbmd9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqL1xuICAgIHZhciBiYXNlRWFjaCA9IGNyZWF0ZUJhc2VFYWNoKGJhc2VGb3JPd24pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yRWFjaFJpZ2h0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrXG4gICAgICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fHN0cmluZ30gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICovXG4gICAgdmFyIGJhc2VFYWNoUmlnaHQgPSBjcmVhdGVCYXNlRWFjaChiYXNlRm9yT3duUmlnaHQsIHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZXZlcnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2tcbiAgICAgKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUV2ZXJ5KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0ID0gISFwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBleHRyZW11bSB2YWx1ZSBvZiBgY29sbGVjdGlvbmAgaW52b2tpbmcgYGl0ZXJhdGVlYCBmb3IgZWFjaCB2YWx1ZVxuICAgICAqIGluIGBjb2xsZWN0aW9uYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5IHdoaWNoIHRoZSB2YWx1ZSBpcyByYW5rZWQuXG4gICAgICogVGhlIGBpdGVyYXRlZWAgaXMgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgZnVuY3Rpb24gdXNlZCB0byBjb21wYXJlIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0geyp9IGV4VmFsdWUgVGhlIGluaXRpYWwgZXh0cmVtdW0gdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGV4dHJlbXVtIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VFeHRyZW11bShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgY29tcGFyYXRvciwgZXhWYWx1ZSkge1xuICAgICAgdmFyIGNvbXB1dGVkID0gZXhWYWx1ZSxcbiAgICAgICAgICByZXN1bHQgPSBjb21wdXRlZDtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHZhciBjdXJyZW50ID0gK2l0ZXJhdGVlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIGlmIChjb21wYXJhdG9yKGN1cnJlbnQsIGNvbXB1dGVkKSB8fCAoY3VycmVudCA9PT0gZXhWYWx1ZSAmJiBjdXJyZW50ID09PSByZXN1bHQpKSB7XG4gICAgICAgICAgY29tcHV0ZWQgPSBjdXJyZW50O1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmlsbGAgd2l0aG91dCBhbiBpdGVyYXRlZSBjYWxsIGd1YXJkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmlsbC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBmaWxsIGBhcnJheWAgd2l0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBzdGFydCA9IHN0YXJ0ID09IG51bGwgPyAwIDogKCtzdGFydCB8fCAwKTtcbiAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgc3RhcnQgPSAtc3RhcnQgPiBsZW5ndGggPyAwIDogKGxlbmd0aCArIHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGVuZCA9IChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiBsZW5ndGgpID8gbGVuZ3RoIDogKCtlbmQgfHwgMCk7XG4gICAgICBpZiAoZW5kIDwgMCkge1xuICAgICAgICBlbmQgKz0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgbGVuZ3RoID0gc3RhcnQgPiBlbmQgPyAwIDogKGVuZCA+Pj4gMCk7XG4gICAgICBzdGFydCA+Pj49IDA7XG5cbiAgICAgIHdoaWxlIChzdGFydCA8IGxlbmd0aCkge1xuICAgICAgICBhcnJheVtzdGFydCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbHRlcmAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGaWx0ZXIoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmluZGAsIGBfLmZpbmRMYXN0YCwgYF8uZmluZEtleWAsIGFuZCBgXy5maW5kTGFzdEtleWAsXG4gICAgICogd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFjayBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZywgd2hpY2ggaXRlcmF0ZXNcbiAgICAgKiBvdmVyIGBjb2xsZWN0aW9uYCB1c2luZyB0aGUgcHJvdmlkZWQgYGVhY2hGdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRLZXldIFNwZWNpZnkgcmV0dXJuaW5nIHRoZSBrZXkgb2YgdGhlIGZvdW5kIGVsZW1lbnRcbiAgICAgKiAgaW5zdGVhZCBvZiB0aGUgZWxlbWVudCBpdHNlbGYuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZvdW5kIGVsZW1lbnQgb3IgaXRzIGtleSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRmluZChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGVhY2hGdW5jLCByZXRLZXkpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGtleSwgY29sbGVjdGlvbikpIHtcbiAgICAgICAgICByZXN1bHQgPSByZXRLZXkgPyBrZXkgOiB2YWx1ZTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mbGF0dGVuYCB3aXRoIGFkZGVkIHN1cHBvcnQgZm9yIHJlc3RyaWN0aW5nXG4gICAgICogZmxhdHRlbmluZyBhbmQgc3BlY2lmeWluZyB0aGUgc3RhcnQgaW5kZXguXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgZmxhdHRlbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1N0cmljdF0gUmVzdHJpY3QgZmxhdHRlbmluZyB0byBhcnJheXMtbGlrZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHQ9W11dIFRoZSBpbml0aWFsIHJlc3VsdCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZsYXR0ZW4oYXJyYXksIGlzRGVlcCwgaXNTdHJpY3QsIHJlc3VsdCkge1xuICAgICAgcmVzdWx0IHx8IChyZXN1bHQgPSBbXSk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBpc0FycmF5TGlrZSh2YWx1ZSkgJiZcbiAgICAgICAgICAgIChpc1N0cmljdCB8fCBpc0FycmF5KHZhbHVlKSB8fCBpc0FyZ3VtZW50cyh2YWx1ZSkpKSB7XG4gICAgICAgICAgaWYgKGlzRGVlcCkge1xuICAgICAgICAgICAgLy8gUmVjdXJzaXZlbHkgZmxhdHRlbiBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgICAgIGJhc2VGbGF0dGVuKHZhbHVlLCBpc0RlZXAsIGlzU3RyaWN0LCByZXN1bHQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcnJheVB1c2gocmVzdWx0LCB2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCFpc1N0cmljdCkge1xuICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBiYXNlRm9ySW5gIGFuZCBgYmFzZUZvck93bmAgd2hpY2ggaXRlcmF0ZXNcbiAgICAgKiBvdmVyIGBvYmplY3RgIHByb3BlcnRpZXMgcmV0dXJuZWQgYnkgYGtleXNGdW5jYCBpbnZva2luZyBgaXRlcmF0ZWVgIGZvclxuICAgICAqIGVhY2ggcHJvcGVydHkuIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb24gZWFybHkgYnkgZXhwbGljaXRseVxuICAgICAqIHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIHZhciBiYXNlRm9yID0gY3JlYXRlQmFzZUZvcigpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiYXNlRm9yYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIHByb3BlcnRpZXNcbiAgICAgKiBpbiB0aGUgb3Bwb3NpdGUgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgdmFyIGJhc2VGb3JSaWdodCA9IGNyZWF0ZUJhc2VGb3IodHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JJbmAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRm9ySW4ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGb3Iob2JqZWN0LCBpdGVyYXRlZSwga2V5c0luKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JPd25gIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2tcbiAgICAgKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZvck93bihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZUZvcihvYmplY3QsIGl0ZXJhdGVlLCBrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JPd25SaWdodGAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRm9yT3duUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGb3JSaWdodChvYmplY3QsIGl0ZXJhdGVlLCBrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mdW5jdGlvbnNgIHdoaWNoIGNyZWF0ZXMgYW4gYXJyYXkgb2ZcbiAgICAgKiBgb2JqZWN0YCBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmaWx0ZXJlZCBmcm9tIHRob3NlIHByb3ZpZGVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gZmlsdGVyLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHByb3BlcnR5IG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGdW5jdGlvbnMob2JqZWN0LCBwcm9wcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIHJlc0luZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKG9iamVjdFtrZXldKSkge1xuICAgICAgICAgIHJlc3VsdFsrK3Jlc0luZGV4XSA9IGtleTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgZ2V0YCB3aXRob3V0IHN1cHBvcnQgZm9yIHN0cmluZyBwYXRoc1xuICAgICAqIGFuZCBkZWZhdWx0IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhdGhLZXldIFRoZSBrZXkgcmVwcmVzZW50YXRpb24gb2YgcGF0aC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUdldChvYmplY3QsIHBhdGgsIHBhdGhLZXkpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAocGF0aEtleSAhPT0gdW5kZWZpbmVkICYmIHBhdGhLZXkgaW4gdG9PYmplY3Qob2JqZWN0KSkge1xuICAgICAgICBwYXRoID0gW3BhdGhLZXldO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICBsZW5ndGggPSBwYXRoLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKG9iamVjdCAhPSBudWxsICYmIGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIG9iamVjdCA9IG9iamVjdFtwYXRoW2luZGV4KytdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoaW5kZXggJiYgaW5kZXggPT0gbGVuZ3RoKSA/IG9iamVjdCA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0VxdWFsYCB3aXRob3V0IHN1cHBvcnQgZm9yIGB0aGlzYCBiaW5kaW5nXG4gICAgICogYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmluZyB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNMb29zZV0gU3BlY2lmeSBwZXJmb3JtaW5nIHBhcnRpYWwgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQV0gVHJhY2tzIHRyYXZlcnNlZCBgdmFsdWVgIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQl0gVHJhY2tzIHRyYXZlcnNlZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNFcXVhbCh2YWx1ZSwgb3RoZXIsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKSB7XG4gICAgICBpZiAodmFsdWUgPT09IG90aGVyKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09IG51bGwgfHwgb3RoZXIgPT0gbnVsbCB8fCAoIWlzT2JqZWN0KHZhbHVlKSAmJiAhaXNPYmplY3RMaWtlKG90aGVyKSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXI7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUlzRXF1YWxEZWVwKHZhbHVlLCBvdGhlciwgYmFzZUlzRXF1YWwsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gICAgICogZGVlcCBjb21wYXJpc29ucyBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzIGVuYWJsaW5nIG9iamVjdHMgd2l0aCBjaXJjdWxhclxuICAgICAqIHJlZmVyZW5jZXMgdG8gYmUgY29tcGFyZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmluZyBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzTG9vc2VdIFNwZWNpZnkgcGVyZm9ybWluZyBwYXJ0aWFsIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgYHZhbHVlYCBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0I9W11dIFRyYWNrcyB0cmF2ZXJzZWQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0VxdWFsRGVlcChvYmplY3QsIG90aGVyLCBlcXVhbEZ1bmMsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKSB7XG4gICAgICB2YXIgb2JqSXNBcnIgPSBpc0FycmF5KG9iamVjdCksXG4gICAgICAgICAgb3RoSXNBcnIgPSBpc0FycmF5KG90aGVyKSxcbiAgICAgICAgICBvYmpUYWcgPSBhcnJheVRhZyxcbiAgICAgICAgICBvdGhUYWcgPSBhcnJheVRhZztcblxuICAgICAgaWYgKCFvYmpJc0Fycikge1xuICAgICAgICBvYmpUYWcgPSBvYmpUb1N0cmluZy5jYWxsKG9iamVjdCk7XG4gICAgICAgIGlmIChvYmpUYWcgPT0gYXJnc1RhZykge1xuICAgICAgICAgIG9ialRhZyA9IG9iamVjdFRhZztcbiAgICAgICAgfSBlbHNlIGlmIChvYmpUYWcgIT0gb2JqZWN0VGFnKSB7XG4gICAgICAgICAgb2JqSXNBcnIgPSBpc1R5cGVkQXJyYXkob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFvdGhJc0Fycikge1xuICAgICAgICBvdGhUYWcgPSBvYmpUb1N0cmluZy5jYWxsKG90aGVyKTtcbiAgICAgICAgaWYgKG90aFRhZyA9PSBhcmdzVGFnKSB7XG4gICAgICAgICAgb3RoVGFnID0gb2JqZWN0VGFnO1xuICAgICAgICB9IGVsc2UgaWYgKG90aFRhZyAhPSBvYmplY3RUYWcpIHtcbiAgICAgICAgICBvdGhJc0FyciA9IGlzVHlwZWRBcnJheShvdGhlcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBvYmpJc09iaiA9IG9ialRhZyA9PSBvYmplY3RUYWcsXG4gICAgICAgICAgb3RoSXNPYmogPSBvdGhUYWcgPT0gb2JqZWN0VGFnLFxuICAgICAgICAgIGlzU2FtZVRhZyA9IG9ialRhZyA9PSBvdGhUYWc7XG5cbiAgICAgIGlmIChpc1NhbWVUYWcgJiYgIShvYmpJc0FyciB8fCBvYmpJc09iaikpIHtcbiAgICAgICAgcmV0dXJuIGVxdWFsQnlUYWcob2JqZWN0LCBvdGhlciwgb2JqVGFnKTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNMb29zZSkge1xuICAgICAgICB2YXIgb2JqSXNXcmFwcGVkID0gb2JqSXNPYmogJiYgaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsICdfX3dyYXBwZWRfXycpLFxuICAgICAgICAgICAgb3RoSXNXcmFwcGVkID0gb3RoSXNPYmogJiYgaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwgJ19fd3JhcHBlZF9fJyk7XG5cbiAgICAgICAgaWYgKG9iaklzV3JhcHBlZCB8fCBvdGhJc1dyYXBwZWQpIHtcbiAgICAgICAgICByZXR1cm4gZXF1YWxGdW5jKG9iaklzV3JhcHBlZCA/IG9iamVjdC52YWx1ZSgpIDogb2JqZWN0LCBvdGhJc1dyYXBwZWQgPyBvdGhlci52YWx1ZSgpIDogb3RoZXIsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFpc1NhbWVUYWcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gQXNzdW1lIGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgLy8gRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gZGV0ZWN0aW5nIGNpcmN1bGFyIHJlZmVyZW5jZXMgc2VlIGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jSk8uXG4gICAgICBzdGFja0EgfHwgKHN0YWNrQSA9IFtdKTtcbiAgICAgIHN0YWNrQiB8fCAoc3RhY2tCID0gW10pO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gc3RhY2tBLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoc3RhY2tBW2xlbmd0aF0gPT0gb2JqZWN0KSB7XG4gICAgICAgICAgcmV0dXJuIHN0YWNrQltsZW5ndGhdID09IG90aGVyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBBZGQgYG9iamVjdGAgYW5kIGBvdGhlcmAgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgICAgc3RhY2tBLnB1c2gob2JqZWN0KTtcbiAgICAgIHN0YWNrQi5wdXNoKG90aGVyKTtcblxuICAgICAgdmFyIHJlc3VsdCA9IChvYmpJc0FyciA/IGVxdWFsQXJyYXlzIDogZXF1YWxPYmplY3RzKShvYmplY3QsIG90aGVyLCBlcXVhbEZ1bmMsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKTtcblxuICAgICAgc3RhY2tBLnBvcCgpO1xuICAgICAgc3RhY2tCLnBvcCgpO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTWF0Y2hgIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2tcbiAgICAgKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbWF0Y2hEYXRhIFRoZSBwcm9wZXJ5IG5hbWVzLCB2YWx1ZXMsIGFuZCBjb21wYXJlIGZsYWdzIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmluZyBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBpcyBhIG1hdGNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzTWF0Y2gob2JqZWN0LCBtYXRjaERhdGEsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBpbmRleCA9IG1hdGNoRGF0YS5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gaW5kZXgsXG4gICAgICAgICAgbm9DdXN0b21pemVyID0gIWN1c3RvbWl6ZXI7XG5cbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gIWxlbmd0aDtcbiAgICAgIH1cbiAgICAgIG9iamVjdCA9IHRvT2JqZWN0KG9iamVjdCk7XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICB2YXIgZGF0YSA9IG1hdGNoRGF0YVtpbmRleF07XG4gICAgICAgIGlmICgobm9DdXN0b21pemVyICYmIGRhdGFbMl0pXG4gICAgICAgICAgICAgID8gZGF0YVsxXSAhPT0gb2JqZWN0W2RhdGFbMF1dXG4gICAgICAgICAgICAgIDogIShkYXRhWzBdIGluIG9iamVjdClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgZGF0YSA9IG1hdGNoRGF0YVtpbmRleF07XG4gICAgICAgIHZhciBrZXkgPSBkYXRhWzBdLFxuICAgICAgICAgICAgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICAgIHNyY1ZhbHVlID0gZGF0YVsxXTtcblxuICAgICAgICBpZiAobm9DdXN0b21pemVyICYmIGRhdGFbMl0pIHtcbiAgICAgICAgICBpZiAob2JqVmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciByZXN1bHQgPSBjdXN0b21pemVyID8gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgaWYgKCEocmVzdWx0ID09PSB1bmRlZmluZWQgPyBiYXNlSXNFcXVhbChzcmNWYWx1ZSwgb2JqVmFsdWUsIGN1c3RvbWl6ZXIsIHRydWUpIDogcmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWFwYCB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrIHNob3J0aGFuZHNcbiAgICAgKiBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBBcnJheShjb2xsZWN0aW9uLmxlbmd0aCkgOiBbXTtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICByZXN1bHRbKytpbmRleF0gPSBpdGVyYXRlZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXRjaGVzYCB3aGljaCBkb2VzIG5vdCBjbG9uZSBgc291cmNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWF0Y2hlcyhzb3VyY2UpIHtcbiAgICAgIHZhciBtYXRjaERhdGEgPSBnZXRNYXRjaERhdGEoc291cmNlKTtcbiAgICAgIGlmIChtYXRjaERhdGEubGVuZ3RoID09IDEgJiYgbWF0Y2hEYXRhWzBdWzJdKSB7XG4gICAgICAgIHZhciBrZXkgPSBtYXRjaERhdGFbMF1bMF0sXG4gICAgICAgICAgICB2YWx1ZSA9IG1hdGNoRGF0YVswXVsxXTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBvYmplY3Rba2V5XSA9PT0gdmFsdWUgJiYgKHZhbHVlICE9PSB1bmRlZmluZWQgfHwgKGtleSBpbiB0b09iamVjdChvYmplY3QpKSk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBiYXNlSXNNYXRjaChvYmplY3QsIG1hdGNoRGF0YSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1hdGNoZXNQcm9wZXJ0eWAgd2hpY2ggZG9lcyBub3QgY2xvbmUgYHNyY1ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNYXRjaGVzUHJvcGVydHkocGF0aCwgc3JjVmFsdWUpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkocGF0aCksXG4gICAgICAgICAgaXNDb21tb24gPSBpc0tleShwYXRoKSAmJiBpc1N0cmljdENvbXBhcmFibGUoc3JjVmFsdWUpLFxuICAgICAgICAgIHBhdGhLZXkgPSAocGF0aCArICcnKTtcblxuICAgICAgcGF0aCA9IHRvUGF0aChwYXRoKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBrZXkgPSBwYXRoS2V5O1xuICAgICAgICBvYmplY3QgPSB0b09iamVjdChvYmplY3QpO1xuICAgICAgICBpZiAoKGlzQXJyIHx8ICFpc0NvbW1vbikgJiYgIShrZXkgaW4gb2JqZWN0KSkge1xuICAgICAgICAgIG9iamVjdCA9IHBhdGgubGVuZ3RoID09IDEgPyBvYmplY3QgOiBiYXNlR2V0KG9iamVjdCwgYmFzZVNsaWNlKHBhdGgsIDAsIC0xKSk7XG4gICAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGtleSA9IGxhc3QocGF0aCk7XG4gICAgICAgICAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0W2tleV0gPT09IHNyY1ZhbHVlXG4gICAgICAgICAgPyAoc3JjVmFsdWUgIT09IHVuZGVmaW5lZCB8fCAoa2V5IGluIG9iamVjdCkpXG4gICAgICAgICAgOiBiYXNlSXNFcXVhbChzcmNWYWx1ZSwgb2JqZWN0W2tleV0sIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1lcmdlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFyZ3VtZW50IGp1Z2dsaW5nLFxuICAgICAqIG11bHRpcGxlIHNvdXJjZXMsIGFuZCBgdGhpc2AgYmluZGluZyBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBtZXJnZWQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gQXNzb2NpYXRlcyB2YWx1ZXMgd2l0aCBzb3VyY2UgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1lcmdlKG9iamVjdCwgc291cmNlLCBjdXN0b21pemVyLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICB9XG4gICAgICB2YXIgaXNTcmNBcnIgPSBpc0FycmF5TGlrZShzb3VyY2UpICYmIChpc0FycmF5KHNvdXJjZSkgfHwgaXNUeXBlZEFycmF5KHNvdXJjZSkpLFxuICAgICAgICAgIHByb3BzID0gaXNTcmNBcnIgPyB1bmRlZmluZWQgOiBrZXlzKHNvdXJjZSk7XG5cbiAgICAgIGFycmF5RWFjaChwcm9wcyB8fCBzb3VyY2UsIGZ1bmN0aW9uKHNyY1ZhbHVlLCBrZXkpIHtcbiAgICAgICAgaWYgKHByb3BzKSB7XG4gICAgICAgICAga2V5ID0gc3JjVmFsdWU7XG4gICAgICAgICAgc3JjVmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNPYmplY3RMaWtlKHNyY1ZhbHVlKSkge1xuICAgICAgICAgIHN0YWNrQSB8fCAoc3RhY2tBID0gW10pO1xuICAgICAgICAgIHN0YWNrQiB8fCAoc3RhY2tCID0gW10pO1xuICAgICAgICAgIGJhc2VNZXJnZURlZXAob2JqZWN0LCBzb3VyY2UsIGtleSwgYmFzZU1lcmdlLCBjdXN0b21pemVyLCBzdGFja0EsIHN0YWNrQik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICAgIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKHZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGlzQ29tbW9uID0gcmVzdWx0ID09PSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICBpZiAoaXNDb21tb24pIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHNyY1ZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoKHJlc3VsdCAhPT0gdW5kZWZpbmVkIHx8IChpc1NyY0FyciAmJiAhKGtleSBpbiBvYmplY3QpKSkgJiZcbiAgICAgICAgICAgICAgKGlzQ29tbW9uIHx8IChyZXN1bHQgPT09IHJlc3VsdCA/IChyZXN1bHQgIT09IHZhbHVlKSA6ICh2YWx1ZSA9PT0gdmFsdWUpKSkpIHtcbiAgICAgICAgICAgIG9iamVjdFtrZXldID0gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZU1lcmdlYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gICAgICogZGVlcCBtZXJnZXMgYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBlbmFibGluZyBvYmplY3RzIHdpdGggY2lyY3VsYXJcbiAgICAgKiByZWZlcmVuY2VzIHRvIGJlIG1lcmdlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBtZXJnZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXJnZUZ1bmMgVGhlIGZ1bmN0aW9uIHRvIG1lcmdlIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBtZXJnZWQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gQXNzb2NpYXRlcyB2YWx1ZXMgd2l0aCBzb3VyY2UgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNZXJnZURlZXAob2JqZWN0LCBzb3VyY2UsIGtleSwgbWVyZ2VGdW5jLCBjdXN0b21pemVyLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgdmFyIGxlbmd0aCA9IHN0YWNrQS5sZW5ndGgsXG4gICAgICAgICAgc3JjVmFsdWUgPSBzb3VyY2Vba2V5XTtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIGlmIChzdGFja0FbbGVuZ3RoXSA9PSBzcmNWYWx1ZSkge1xuICAgICAgICAgIG9iamVjdFtrZXldID0gc3RhY2tCW2xlbmd0aF07XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgdmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICByZXN1bHQgPSBjdXN0b21pemVyID8gY3VzdG9taXplcih2YWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UpIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGlzQ29tbW9uID0gcmVzdWx0ID09PSB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChpc0NvbW1vbikge1xuICAgICAgICByZXN1bHQgPSBzcmNWYWx1ZTtcbiAgICAgICAgaWYgKGlzQXJyYXlMaWtlKHNyY1ZhbHVlKSAmJiAoaXNBcnJheShzcmNWYWx1ZSkgfHwgaXNUeXBlZEFycmF5KHNyY1ZhbHVlKSkpIHtcbiAgICAgICAgICByZXN1bHQgPSBpc0FycmF5KHZhbHVlKVxuICAgICAgICAgICAgPyB2YWx1ZVxuICAgICAgICAgICAgOiAoaXNBcnJheUxpa2UodmFsdWUpID8gYXJyYXlDb3B5KHZhbHVlKSA6IFtdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc1BsYWluT2JqZWN0KHNyY1ZhbHVlKSB8fCBpc0FyZ3VtZW50cyhzcmNWYWx1ZSkpIHtcbiAgICAgICAgICByZXN1bHQgPSBpc0FyZ3VtZW50cyh2YWx1ZSlcbiAgICAgICAgICAgID8gdG9QbGFpbk9iamVjdCh2YWx1ZSlcbiAgICAgICAgICAgIDogKGlzUGxhaW5PYmplY3QodmFsdWUpID8gdmFsdWUgOiB7fSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQWRkIHRoZSBzb3VyY2UgdmFsdWUgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzIGFuZCBhc3NvY2lhdGVcbiAgICAgIC8vIGl0IHdpdGggaXRzIG1lcmdlZCB2YWx1ZS5cbiAgICAgIHN0YWNrQS5wdXNoKHNyY1ZhbHVlKTtcbiAgICAgIHN0YWNrQi5wdXNoKHJlc3VsdCk7XG5cbiAgICAgIGlmIChpc0NvbW1vbikge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBtZXJnZSBvYmplY3RzIGFuZCBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgb2JqZWN0W2tleV0gPSBtZXJnZUZ1bmMocmVzdWx0LCBzcmNWYWx1ZSwgY3VzdG9taXplciwgc3RhY2tBLCBzdGFja0IpO1xuICAgICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IHJlc3VsdCA/IChyZXN1bHQgIT09IHZhbHVlKSA6ICh2YWx1ZSA9PT0gdmFsdWUpKSB7XG4gICAgICAgIG9iamVjdFtrZXldID0gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnByb3BlcnR5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eShrZXkpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZVByb3BlcnR5YCB3aGljaCBzdXBwb3J0cyBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eURlZXAocGF0aCkge1xuICAgICAgdmFyIHBhdGhLZXkgPSAocGF0aCArICcnKTtcbiAgICAgIHBhdGggPSB0b1BhdGgocGF0aCk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBiYXNlR2V0KG9iamVjdCwgcGF0aCwgcGF0aEtleSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnB1bGxBdGAgd2l0aG91dCBzdXBwb3J0IGZvciBpbmRpdmlkdWFsXG4gICAgICogaW5kZXggYXJndW1lbnRzIGFuZCBjYXB0dXJpbmcgdGhlIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJbXX0gaW5kZXhlcyBUaGUgaW5kZXhlcyBvZiBlbGVtZW50cyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVB1bGxBdChhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gaW5kZXhlcy5sZW5ndGggOiAwO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGluZGV4ZXNbbGVuZ3RoXTtcbiAgICAgICAgaWYgKGluZGV4ICE9IHByZXZpb3VzICYmIGlzSW5kZXgoaW5kZXgpKSB7XG4gICAgICAgICAgdmFyIHByZXZpb3VzID0gaW5kZXg7XG4gICAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJhbmRvbWAgd2l0aG91dCBzdXBwb3J0IGZvciBhcmd1bWVudCBqdWdnbGluZ1xuICAgICAqIGFuZCByZXR1cm5pbmcgZmxvYXRpbmctcG9pbnQgbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1pbiBUaGUgbWluaW11bSBwb3NzaWJsZSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4IFRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHJhbmRvbSBudW1iZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVJhbmRvbShtaW4sIG1heCkge1xuICAgICAgcmV0dXJuIG1pbiArIG5hdGl2ZUZsb29yKG5hdGl2ZVJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yZWR1Y2VgIGFuZCBgXy5yZWR1Y2VSaWdodGAgd2l0aG91dCBzdXBwb3J0XG4gICAgICogZm9yIGNhbGxiYWNrIHNob3J0aGFuZHMgYW5kIGB0aGlzYCBiaW5kaW5nLCB3aGljaCBpdGVyYXRlcyBvdmVyIGBjb2xsZWN0aW9uYFxuICAgICAqIHVzaW5nIHRoZSBwcm92aWRlZCBgZWFjaEZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBhY2N1bXVsYXRvciBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluaXRGcm9tQ29sbGVjdGlvbiBTcGVjaWZ5IHVzaW5nIHRoZSBmaXJzdCBvciBsYXN0IGVsZW1lbnRcbiAgICAgKiAgb2YgYGNvbGxlY3Rpb25gIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYGNvbGxlY3Rpb25gLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmVkdWNlKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBhY2N1bXVsYXRvciwgaW5pdEZyb21Db2xsZWN0aW9uLCBlYWNoRnVuYykge1xuICAgICAgZWFjaEZ1bmMoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGFjY3VtdWxhdG9yID0gaW5pdEZyb21Db2xsZWN0aW9uXG4gICAgICAgICAgPyAoaW5pdEZyb21Db2xsZWN0aW9uID0gZmFsc2UsIHZhbHVlKVxuICAgICAgICAgIDogaXRlcmF0ZWUoYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgc2V0RGF0YWAgd2l0aG91dCBzdXBwb3J0IGZvciBob3QgbG9vcCBkZXRlY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBUaGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZVNldERhdGEgPSAhbWV0YU1hcCA/IGlkZW50aXR5IDogZnVuY3Rpb24oZnVuYywgZGF0YSkge1xuICAgICAgbWV0YU1hcC5zZXQoZnVuYywgZGF0YSk7XG4gICAgICByZXR1cm4gZnVuYztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc2xpY2VgIHdpdGhvdXQgYW4gaXRlcmF0ZWUgY2FsbCBndWFyZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNsaWNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNsaWNlKGFycmF5LCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHN0YXJ0ID0gc3RhcnQgPT0gbnVsbCA/IDAgOiAoK3N0YXJ0IHx8IDApO1xuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IC1zdGFydCA+IGxlbmd0aCA/IDAgOiAobGVuZ3RoICsgc3RhcnQpO1xuICAgICAgfVxuICAgICAgZW5kID0gKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IGxlbmd0aCkgPyBsZW5ndGggOiAoK2VuZCB8fCAwKTtcbiAgICAgIGlmIChlbmQgPCAwKSB7XG4gICAgICAgIGVuZCArPSBsZW5ndGg7XG4gICAgICB9XG4gICAgICBsZW5ndGggPSBzdGFydCA+IGVuZCA/IDAgOiAoKGVuZCAtIHN0YXJ0KSA+Pj4gMCk7XG4gICAgICBzdGFydCA+Pj49IDA7XG5cbiAgICAgIHZhciByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGFycmF5W2luZGV4ICsgc3RhcnRdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zb21lYCB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrIHNob3J0aGFuZHNcbiAgICAgKiBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvbWUoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuXG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0ID0gcHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIHJldHVybiAhcmVzdWx0O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gISFyZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydEJ5YCB3aGljaCB1c2VzIGBjb21wYXJlcmAgdG8gZGVmaW5lXG4gICAgICogdGhlIHNvcnQgb3JkZXIgb2YgYGFycmF5YCBhbmQgcmVwbGFjZXMgY3JpdGVyaWEgb2JqZWN0cyB3aXRoIHRoZWlyXG4gICAgICogY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzb3J0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmVyIFRoZSBmdW5jdGlvbiB0byBkZWZpbmUgc29ydCBvcmRlci5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU29ydEJ5KGFycmF5LCBjb21wYXJlcikge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgYXJyYXkuc29ydChjb21wYXJlcik7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgYXJyYXlbbGVuZ3RoXSA9IGFycmF5W2xlbmd0aF0udmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydEJ5T3JkZXJgIHdpdGhvdXQgcGFyYW0gZ3VhcmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXXxPYmplY3RbXXxzdHJpbmdbXX0gaXRlcmF0ZWVzIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW5bXX0gb3JkZXJzIFRoZSBzb3J0IG9yZGVycyBvZiBgaXRlcmF0ZWVzYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvcnRCeU9yZGVyKGNvbGxlY3Rpb24sIGl0ZXJhdGVlcywgb3JkZXJzKSB7XG4gICAgICB2YXIgY2FsbGJhY2sgPSBnZXRDYWxsYmFjaygpLFxuICAgICAgICAgIGluZGV4ID0gLTE7XG5cbiAgICAgIGl0ZXJhdGVlcyA9IGFycmF5TWFwKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHsgcmV0dXJuIGNhbGxiYWNrKGl0ZXJhdGVlKTsgfSk7XG5cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlTWFwKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciBjcml0ZXJpYSA9IGFycmF5TWFwKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHsgcmV0dXJuIGl0ZXJhdGVlKHZhbHVlKTsgfSk7XG4gICAgICAgIHJldHVybiB7ICdjcml0ZXJpYSc6IGNyaXRlcmlhLCAnaW5kZXgnOiArK2luZGV4LCAndmFsdWUnOiB2YWx1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBiYXNlU29ydEJ5KHJlc3VsdCwgZnVuY3Rpb24ob2JqZWN0LCBvdGhlcikge1xuICAgICAgICByZXR1cm4gY29tcGFyZU11bHRpcGxlKG9iamVjdCwgb3RoZXIsIG9yZGVycyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zdW1gIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2sgc2hvcnRoYW5kc1xuICAgICAqIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU3VtKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gMDtcbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICByZXN1bHQgKz0gK2l0ZXJhdGVlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikgfHwgMDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bmlxYCB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrIHNob3J0aGFuZHNcbiAgICAgKiBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUtdmFsdWUtZnJlZSBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVW5pcShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluZGV4T2YgPSBnZXRJbmRleE9mKCksXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGlzQ29tbW9uID0gaW5kZXhPZiA9PSBiYXNlSW5kZXhPZixcbiAgICAgICAgICBpc0xhcmdlID0gaXNDb21tb24gJiYgbGVuZ3RoID49IExBUkdFX0FSUkFZX1NJWkUsXG4gICAgICAgICAgc2VlbiA9IGlzTGFyZ2UgPyBjcmVhdGVDYWNoZSgpIDogbnVsbCxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgaWYgKHNlZW4pIHtcbiAgICAgICAgaW5kZXhPZiA9IGNhY2hlSW5kZXhPZjtcbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlzTGFyZ2UgPSBmYWxzZTtcbiAgICAgICAgc2VlbiA9IGl0ZXJhdGVlID8gW10gOiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSA6IHZhbHVlO1xuXG4gICAgICAgIGlmIChpc0NvbW1vbiAmJiB2YWx1ZSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICB2YXIgc2VlbkluZGV4ID0gc2Vlbi5sZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHNlZW5JbmRleC0tKSB7XG4gICAgICAgICAgICBpZiAoc2VlbltzZWVuSW5kZXhdID09PSBjb21wdXRlZCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaW5kZXhPZihzZWVuLCBjb21wdXRlZCwgMCkgPCAwKSB7XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlIHx8IGlzTGFyZ2UpIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy52YWx1ZXNgIGFuZCBgXy52YWx1ZXNJbmAgd2hpY2ggY3JlYXRlcyBhblxuICAgICAqIGFycmF5IG9mIGBvYmplY3RgIHByb3BlcnR5IHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm9wZXJ0eSBuYW1lc1xuICAgICAqIG9mIGBwcm9wc2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gZ2V0IHZhbHVlcyBmb3IuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VWYWx1ZXMob2JqZWN0LCBwcm9wcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBvYmplY3RbcHJvcHNbaW5kZXhdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZHJvcFJpZ2h0V2hpbGVgLCBgXy5kcm9wV2hpbGVgLCBgXy50YWtlUmlnaHRXaGlsZWAsXG4gICAgICogYW5kIGBfLnRha2VXaGlsZWAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFjayBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRHJvcF0gU3BlY2lmeSBkcm9wcGluZyBlbGVtZW50cyBpbnN0ZWFkIG9mIHRha2luZyB0aGVtLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlV2hpbGUoYXJyYXksIHByZWRpY2F0ZSwgaXNEcm9wLCBmcm9tUmlnaHQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgaW5kZXggPSBmcm9tUmlnaHQgPyBsZW5ndGggOiAtMTtcblxuICAgICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkgJiYgcHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge31cbiAgICAgIHJldHVybiBpc0Ryb3BcbiAgICAgICAgPyBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyAwIDogaW5kZXgpLCAoZnJvbVJpZ2h0ID8gaW5kZXggKyAxIDogbGVuZ3RoKSlcbiAgICAgICAgOiBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyBpbmRleCArIDEgOiAwKSwgKGZyb21SaWdodCA/IGxlbmd0aCA6IGluZGV4KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHdyYXBwZXJWYWx1ZWAgd2hpY2ggcmV0dXJucyB0aGUgcmVzdWx0IG9mXG4gICAgICogcGVyZm9ybWluZyBhIHNlcXVlbmNlIG9mIGFjdGlvbnMgb24gdGhlIHVud3JhcHBlZCBgdmFsdWVgLCB3aGVyZSBlYWNoXG4gICAgICogc3VjY2Vzc2l2ZSBhY3Rpb24gaXMgc3VwcGxpZWQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcHJldmlvdXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhY3Rpb25zIEFjdGlvbnMgdG8gcGVmb3JtIHRvIHJlc29sdmUgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVdyYXBwZXJWYWx1ZSh2YWx1ZSwgYWN0aW9ucykge1xuICAgICAgdmFyIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC52YWx1ZSgpO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYWN0aW9ucy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBhY3Rpb24gPSBhY3Rpb25zW2luZGV4XTtcbiAgICAgICAgcmVzdWx0ID0gYWN0aW9uLmZ1bmMuYXBwbHkoYWN0aW9uLnRoaXNBcmcsIGFycmF5UHVzaChbcmVzdWx0XSwgYWN0aW9uLmFyZ3MpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgYSBiaW5hcnkgc2VhcmNoIG9mIGBhcnJheWAgdG8gZGV0ZXJtaW5lIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgXG4gICAgICogc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YCBpbiBvcmRlciB0byBtYWludGFpbiBpdHMgc29ydCBvcmRlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JldEhpZ2hlc3RdIFNwZWNpZnkgcmV0dXJuaW5nIHRoZSBoaWdoZXN0IHF1YWxpZmllZCBpbmRleC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmluYXJ5SW5kZXgoYXJyYXksIHZhbHVlLCByZXRIaWdoZXN0KSB7XG4gICAgICB2YXIgbG93ID0gMCxcbiAgICAgICAgICBoaWdoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiBsb3c7XG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiYgdmFsdWUgPT09IHZhbHVlICYmIGhpZ2ggPD0gSEFMRl9NQVhfQVJSQVlfTEVOR1RIKSB7XG4gICAgICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMSxcbiAgICAgICAgICAgICAgY29tcHV0ZWQgPSBhcnJheVttaWRdO1xuXG4gICAgICAgICAgaWYgKChyZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKSkgJiYgY29tcHV0ZWQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhpZ2ggPSBtaWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoaWdoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJpbmFyeUluZGV4QnkoYXJyYXksIHZhbHVlLCBpZGVudGl0eSwgcmV0SGlnaGVzdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiaW5hcnlJbmRleGAgZXhjZXB0IHRoYXQgaXQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvclxuICAgICAqIGB2YWx1ZWAgYW5kIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIHRvIGNvbXB1dGUgdGhlaXIgc29ydCByYW5raW5nLiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJpbmFyeUluZGV4QnkoYXJyYXksIHZhbHVlLCBpdGVyYXRlZSwgcmV0SGlnaGVzdCkge1xuICAgICAgdmFsdWUgPSBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgdmFsSXNOYU4gPSB2YWx1ZSAhPT0gdmFsdWUsXG4gICAgICAgICAgdmFsSXNOdWxsID0gdmFsdWUgPT09IG51bGwsXG4gICAgICAgICAgdmFsSXNVbmRlZiA9IHZhbHVlID09PSB1bmRlZmluZWQ7XG5cbiAgICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICAgIHZhciBtaWQgPSBuYXRpdmVGbG9vcigobG93ICsgaGlnaCkgLyAyKSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUoYXJyYXlbbWlkXSksXG4gICAgICAgICAgICBpc0RlZiA9IGNvbXB1dGVkICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICBpc1JlZmxleGl2ZSA9IGNvbXB1dGVkID09PSBjb21wdXRlZDtcblxuICAgICAgICBpZiAodmFsSXNOYU4pIHtcbiAgICAgICAgICB2YXIgc2V0TG93ID0gaXNSZWZsZXhpdmUgfHwgcmV0SGlnaGVzdDtcbiAgICAgICAgfSBlbHNlIGlmICh2YWxJc051bGwpIHtcbiAgICAgICAgICBzZXRMb3cgPSBpc1JlZmxleGl2ZSAmJiBpc0RlZiAmJiAocmV0SGlnaGVzdCB8fCBjb21wdXRlZCAhPSBudWxsKTtcbiAgICAgICAgfSBlbHNlIGlmICh2YWxJc1VuZGVmKSB7XG4gICAgICAgICAgc2V0TG93ID0gaXNSZWZsZXhpdmUgJiYgKHJldEhpZ2hlc3QgfHwgaXNEZWYpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbXB1dGVkID09IG51bGwpIHtcbiAgICAgICAgICBzZXRMb3cgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRMb3cgPSByZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0TG93KSB7XG4gICAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBoaWdoID0gbWlkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmF0aXZlTWluKGhpZ2gsIE1BWF9BUlJBWV9JTkRFWCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlQ2FsbGJhY2tgIHdoaWNoIG9ubHkgc3VwcG9ydHMgYHRoaXNgIGJpbmRpbmdcbiAgICAgKiBhbmQgc3BlY2lmeWluZyB0aGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmluZC5cbiAgICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ0NvdW50XSBUaGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJpbmRDYWxsYmFjayhmdW5jLCB0aGlzQXJnLCBhcmdDb3VudCkge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGlkZW50aXR5O1xuICAgICAgfVxuICAgICAgaWYgKHRoaXNBcmcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZnVuYztcbiAgICAgIH1cbiAgICAgIHN3aXRjaCAoYXJnQ291bnQpIHtcbiAgICAgICAgY2FzZSAxOiByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5jYWxsKHRoaXNBcmcsIHZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgY2FzZSAzOiByZXR1cm4gZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICB9O1xuICAgICAgICBjYXNlIDQ6IHJldHVybiBmdW5jdGlvbihhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgICAgfTtcbiAgICAgICAgY2FzZSA1OiByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyLCBrZXksIG9iamVjdCwgc291cmNlKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCB2YWx1ZSwgb3RoZXIsIGtleSwgb2JqZWN0LCBzb3VyY2UpO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmd1bWVudHMpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGdpdmVuIGFycmF5IGJ1ZmZlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheUJ1ZmZlcn0gYnVmZmVyIFRoZSBhcnJheSBidWZmZXIgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge0FycmF5QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYXJyYXkgYnVmZmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJ1ZmZlckNsb25lKGJ1ZmZlcikge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheUJ1ZmZlcihidWZmZXIuYnl0ZUxlbmd0aCksXG4gICAgICAgICAgdmlldyA9IG5ldyBVaW50OEFycmF5KHJlc3VsdCk7XG5cbiAgICAgIHZpZXcuc2V0KG5ldyBVaW50OEFycmF5KGJ1ZmZlcikpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IHRoYXQgaXMgdGhlIGNvbXBvc2l0aW9uIG9mIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cyxcbiAgICAgKiBwbGFjZWhvbGRlcnMsIGFuZCBwcm92aWRlZCBhcmd1bWVudHMgaW50byBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBhcmdzIFRoZSBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFydGlhbHMgVGhlIGFyZ3VtZW50cyB0byBwcmVwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGhvbGRlcnMgVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21wb3NlZCBhcmd1bWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcG9zZUFyZ3MoYXJncywgcGFydGlhbHMsIGhvbGRlcnMpIHtcbiAgICAgIHZhciBob2xkZXJzTGVuZ3RoID0gaG9sZGVycy5sZW5ndGgsXG4gICAgICAgICAgYXJnc0luZGV4ID0gLTEsXG4gICAgICAgICAgYXJnc0xlbmd0aCA9IG5hdGl2ZU1heChhcmdzLmxlbmd0aCAtIGhvbGRlcnNMZW5ndGgsIDApLFxuICAgICAgICAgIGxlZnRJbmRleCA9IC0xLFxuICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVmdExlbmd0aCArIGFyZ3NMZW5ndGgpO1xuXG4gICAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2FyZ3NJbmRleCA8IGhvbGRlcnNMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2hvbGRlcnNbYXJnc0luZGV4XV0gPSBhcmdzW2FyZ3NJbmRleF07XG4gICAgICB9XG4gICAgICB3aGlsZSAoYXJnc0xlbmd0aC0tKSB7XG4gICAgICAgIHJlc3VsdFtsZWZ0SW5kZXgrK10gPSBhcmdzW2FyZ3NJbmRleCsrXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBjb21wb3NlQXJnc2AgZXhjZXB0IHRoYXQgdGhlIGFyZ3VtZW50cyBjb21wb3NpdGlvblxuICAgICAqIGlzIHRhaWxvcmVkIGZvciBgXy5wYXJ0aWFsUmlnaHRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gYXBwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGhvbGRlcnMgVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21wb3NlZCBhcmd1bWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFscywgaG9sZGVycykge1xuICAgICAgdmFyIGhvbGRlcnNJbmRleCA9IC0xLFxuICAgICAgICAgIGhvbGRlcnNMZW5ndGggPSBob2xkZXJzLmxlbmd0aCxcbiAgICAgICAgICBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gbmF0aXZlTWF4KGFyZ3MubGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICAgICAgcmlnaHRJbmRleCA9IC0xLFxuICAgICAgICAgIHJpZ2h0TGVuZ3RoID0gcGFydGlhbHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGFyZ3NMZW5ndGggKyByaWdodExlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2FyZ3NJbmRleCA8IGFyZ3NMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2FyZ3NJbmRleF0gPSBhcmdzW2FyZ3NJbmRleF07XG4gICAgICB9XG4gICAgICB2YXIgb2Zmc2V0ID0gYXJnc0luZGV4O1xuICAgICAgd2hpbGUgKCsrcmlnaHRJbmRleCA8IHJpZ2h0TGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtvZmZzZXQgKyByaWdodEluZGV4XSA9IHBhcnRpYWxzW3JpZ2h0SW5kZXhdO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsraG9sZGVyc0luZGV4IDwgaG9sZGVyc0xlbmd0aCkge1xuICAgICAgICByZXN1bHRbb2Zmc2V0ICsgaG9sZGVyc1tob2xkZXJzSW5kZXhdXSA9IGFyZ3NbYXJnc0luZGV4KytdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uY291bnRCeWAsIGBfLmdyb3VwQnlgLCBgXy5pbmRleEJ5YCwgb3IgYF8ucGFydGl0aW9uYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQga2V5cyBhbmQgdmFsdWVzIG9mIHRoZSBhY2N1bXVsYXRvciBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2luaXRpYWxpemVyXSBUaGUgZnVuY3Rpb24gdG8gaW5pdGlhbGl6ZSB0aGUgYWNjdW11bGF0b3Igb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFnZ3JlZ2F0b3IgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQWdncmVnYXRvcihzZXR0ZXIsIGluaXRpYWxpemVyKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGluaXRpYWxpemVyID8gaW5pdGlhbGl6ZXIoKSA6IHt9O1xuICAgICAgICBpdGVyYXRlZSA9IGdldENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAzKTtcblxuICAgICAgICBpZiAoaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblxuICAgICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBjb2xsZWN0aW9uW2luZGV4XTtcbiAgICAgICAgICAgIHNldHRlcihyZXN1bHQsIHZhbHVlLCBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICAgICAgc2V0dGVyKHJlc3VsdCwgdmFsdWUsIGl0ZXJhdGVlKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uYXNzaWduYCwgYF8uZGVmYXVsdHNgLCBvciBgXy5tZXJnZWAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGFzc2lnbmVyIFRoZSBmdW5jdGlvbiB0byBhc3NpZ24gdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFzc2lnbmVyIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUFzc2lnbmVyKGFzc2lnbmVyKSB7XG4gICAgICByZXR1cm4gcmVzdFBhcmFtKGZ1bmN0aW9uKG9iamVjdCwgc291cmNlcykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG9iamVjdCA9PSBudWxsID8gMCA6IHNvdXJjZXMubGVuZ3RoLFxuICAgICAgICAgICAgY3VzdG9taXplciA9IGxlbmd0aCA+IDIgPyBzb3VyY2VzW2xlbmd0aCAtIDJdIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZ3VhcmQgPSBsZW5ndGggPiAyID8gc291cmNlc1syXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHRoaXNBcmcgPSBsZW5ndGggPiAxID8gc291cmNlc1tsZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAodHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIGN1c3RvbWl6ZXIgPSBiaW5kQ2FsbGJhY2soY3VzdG9taXplciwgdGhpc0FyZywgNSk7XG4gICAgICAgICAgbGVuZ3RoIC09IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3VzdG9taXplciA9IHR5cGVvZiB0aGlzQXJnID09ICdmdW5jdGlvbicgPyB0aGlzQXJnIDogdW5kZWZpbmVkO1xuICAgICAgICAgIGxlbmd0aCAtPSAoY3VzdG9taXplciA/IDEgOiAwKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoc291cmNlc1swXSwgc291cmNlc1sxXSwgZ3VhcmQpKSB7XG4gICAgICAgICAgY3VzdG9taXplciA9IGxlbmd0aCA8IDMgPyB1bmRlZmluZWQgOiBjdXN0b21pemVyO1xuICAgICAgICAgIGxlbmd0aCA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgc291cmNlID0gc291cmNlc1tpbmRleF07XG4gICAgICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICAgICAgYXNzaWduZXIob2JqZWN0LCBzb3VyY2UsIGN1c3RvbWl6ZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBiYXNlRWFjaGAgb3IgYGJhc2VFYWNoUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGEgY29sbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VFYWNoKGVhY2hGdW5jLCBmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gY29sbGVjdGlvbiA/IGdldExlbmd0aChjb2xsZWN0aW9uKSA6IDA7XG4gICAgICAgIGlmICghaXNMZW5ndGgobGVuZ3RoKSkge1xuICAgICAgICAgIHJldHVybiBlYWNoRnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTEsXG4gICAgICAgICAgICBpdGVyYWJsZSA9IHRvT2JqZWN0KGNvbGxlY3Rpb24pO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKGl0ZXJhYmxlW2luZGV4XSwgaW5kZXgsIGl0ZXJhYmxlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGJhc2UgZnVuY3Rpb24gZm9yIGBfLmZvckluYCBvciBgXy5mb3JJblJpZ2h0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYmFzZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVCYXNlRm9yKGZyb21SaWdodCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCwgaXRlcmF0ZWUsIGtleXNGdW5jKSB7XG4gICAgICAgIHZhciBpdGVyYWJsZSA9IHRvT2JqZWN0KG9iamVjdCksXG4gICAgICAgICAgICBwcm9wcyA9IGtleXNGdW5jKG9iamVjdCksXG4gICAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgICBpbmRleCA9IGZyb21SaWdodCA/IGxlbmd0aCA6IC0xO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICAgICAgdmFyIGtleSA9IHByb3BzW2luZGV4XTtcbiAgICAgICAgICBpZiAoaXRlcmF0ZWUoaXRlcmFibGVba2V5XSwga2V5LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggdGhlIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBiaW5kLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQmluZFdyYXBwZXIoZnVuYywgdGhpc0FyZykge1xuICAgICAgdmFyIEN0b3IgPSBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGZuID0gKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXNBcmcsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYFNldGAgY2FjaGUgb2JqZWN0IHRvIG9wdGltaXplIGxpbmVhciBzZWFyY2hlcyBvZiBsYXJnZSBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gY2FjaGUuXG4gICAgICogQHJldHVybnMge251bGx8T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgY2FjaGUgb2JqZWN0IGlmIGBTZXRgIGlzIHN1cHBvcnRlZCwgZWxzZSBgbnVsbGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ2FjaGUodmFsdWVzKSB7XG4gICAgICByZXR1cm4gKG5hdGl2ZUNyZWF0ZSAmJiBTZXQpID8gbmV3IFNldENhY2hlKHZhbHVlcykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGNvbXBvdW5kIHdvcmRzIG91dCBvZiB0aGUgd29yZHMgaW4gYVxuICAgICAqIGdpdmVuIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmUgZWFjaCB3b3JkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvdW5kZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ29tcG91bmRlcihjYWxsYmFjaykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGFycmF5ID0gd29yZHMoZGVidXJyKHN0cmluZykpLFxuICAgICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG5cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICByZXN1bHQgPSBjYWxsYmFjayhyZXN1bHQsIGFycmF5W2luZGV4XSwgaW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGluc3RhbmNlIG9mIGBDdG9yYCByZWdhcmRsZXNzIG9mXG4gICAgICogd2hldGhlciBpdCB3YXMgaW52b2tlZCBhcyBwYXJ0IG9mIGEgYG5ld2AgZXhwcmVzc2lvbiBvciBieSBgY2FsbGAgb3IgYGFwcGx5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gQ3RvciBUaGUgY29uc3RydWN0b3IgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUN0b3JXcmFwcGVyKEN0b3IpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gVXNlIGEgYHN3aXRjaGAgc3RhdGVtZW50IHRvIHdvcmsgd2l0aCBjbGFzcyBjb25zdHJ1Y3RvcnMuXG4gICAgICAgIC8vIFNlZSBodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1lY21hc2NyaXB0LWZ1bmN0aW9uLW9iamVjdHMtY2FsbC10aGlzYXJndW1lbnQtYXJndW1lbnRzbGlzdFxuICAgICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDogcmV0dXJuIG5ldyBDdG9yO1xuICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0pO1xuICAgICAgICAgIGNhc2UgMjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgICAgICAgIGNhc2UgMzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICAgIGNhc2UgNDogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pO1xuICAgICAgICAgIGNhc2UgNTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0pO1xuICAgICAgICAgIGNhc2UgNjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pO1xuICAgICAgICAgIGNhc2UgNzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0sIGFyZ3NbNl0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aGlzQmluZGluZyA9IGJhc2VDcmVhdGUoQ3Rvci5wcm90b3R5cGUpLFxuICAgICAgICAgICAgcmVzdWx0ID0gQ3Rvci5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG5cbiAgICAgICAgLy8gTWltaWMgdGhlIGNvbnN0cnVjdG9yJ3MgYHJldHVybmAgYmVoYXZpb3IuXG4gICAgICAgIC8vIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxMy4yLjIgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHJlc3VsdCkgPyByZXN1bHQgOiB0aGlzQmluZGluZztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLmN1cnJ5YCBvciBgXy5jdXJyeVJpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmbGFnIFRoZSBjdXJyeSBiaXQgZmxhZy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyeSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDdXJyeShmbGFnKSB7XG4gICAgICBmdW5jdGlvbiBjdXJyeUZ1bmMoZnVuYywgYXJpdHksIGd1YXJkKSB7XG4gICAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChmdW5jLCBhcml0eSwgZ3VhcmQpKSB7XG4gICAgICAgICAgYXJpdHkgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVdyYXBwZXIoZnVuYywgZmxhZywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGFyaXR5KTtcbiAgICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnlGdW5jLnBsYWNlaG9sZGVyO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGN1cnJ5RnVuYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZGVmYXVsdHNgIG9yIGBfLmRlZmF1bHRzRGVlcGAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGFzc2lnbmVyIFRoZSBmdW5jdGlvbiB0byBhc3NpZ24gdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZGVmYXVsdHMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRGVmYXVsdHMoYXNzaWduZXIsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHJldHVybiByZXN0UGFyYW0oZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgb2JqZWN0ID0gYXJnc1swXTtcbiAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfVxuICAgICAgICBhcmdzLnB1c2goY3VzdG9taXplcik7XG4gICAgICAgIHJldHVybiBhc3NpZ25lci5hcHBseSh1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLm1heGAgb3IgYF8ubWluYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgZnVuY3Rpb24gdXNlZCB0byBjb21wYXJlIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0geyp9IGV4VmFsdWUgVGhlIGluaXRpYWwgZXh0cmVtdW0gdmFsdWUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZXh0cmVtdW0gZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRXh0cmVtdW0oY29tcGFyYXRvciwgZXhWYWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCB0aGlzQXJnKSB7XG4gICAgICAgIGlmICh0aGlzQXJnICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCB0aGlzQXJnKSkge1xuICAgICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGl0ZXJhdGVlID0gZ2V0Q2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDMpO1xuICAgICAgICBpZiAoaXRlcmF0ZWUubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICBjb2xsZWN0aW9uID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGNvbGxlY3Rpb24gOiB0b0l0ZXJhYmxlKGNvbGxlY3Rpb24pO1xuICAgICAgICAgIHZhciByZXN1bHQgPSBhcnJheUV4dHJlbXVtKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBjb21wYXJhdG9yLCBleFZhbHVlKTtcbiAgICAgICAgICBpZiAoIShjb2xsZWN0aW9uLmxlbmd0aCAmJiByZXN1bHQgPT09IGV4VmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmFzZUV4dHJlbXVtKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBjb21wYXJhdG9yLCBleFZhbHVlKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLmZpbmRgIG9yIGBfLmZpbmRMYXN0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBhIGNvbGxlY3Rpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZmluZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVGaW5kKGVhY2hGdW5jLCBmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgICAgcHJlZGljYXRlID0gZ2V0Q2FsbGJhY2socHJlZGljYXRlLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgaWYgKGlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgICAgICB2YXIgaW5kZXggPSBiYXNlRmluZEluZGV4KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZnJvbVJpZ2h0KTtcbiAgICAgICAgICByZXR1cm4gaW5kZXggPiAtMSA/IGNvbGxlY3Rpb25baW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiYXNlRmluZChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGVhY2hGdW5jKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLmZpbmRJbmRleGAgb3IgYF8uZmluZExhc3RJbmRleGAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZpbmQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRmluZEluZGV4KGZyb21SaWdodCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBwcmVkaWNhdGUgPSBnZXRDYWxsYmFjayhwcmVkaWNhdGUsIHRoaXNBcmcsIDMpO1xuICAgICAgICByZXR1cm4gYmFzZUZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBmcm9tUmlnaHQpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZmluZEtleWAgb3IgYF8uZmluZExhc3RLZXlgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvYmplY3RGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYW4gb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZpbmQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRmluZEtleShvYmplY3RGdW5jKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0LCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgICAgcHJlZGljYXRlID0gZ2V0Q2FsbGJhY2socHJlZGljYXRlLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgcmV0dXJuIGJhc2VGaW5kKG9iamVjdCwgcHJlZGljYXRlLCBvYmplY3RGdW5jLCB0cnVlKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLmZsb3dgIG9yIGBfLmZsb3dSaWdodGAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZsb3cgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRmxvdyhmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHdyYXBwZXIsXG4gICAgICAgICAgICBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICAgICAgaW5kZXggPSBmcm9tUmlnaHQgPyBsZW5ndGggOiAtMSxcbiAgICAgICAgICAgIGxlZnRJbmRleCA9IDAsXG4gICAgICAgICAgICBmdW5jcyA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgICAgICB2YXIgZnVuYyA9IGZ1bmNzW2xlZnRJbmRleCsrXSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCF3cmFwcGVyICYmIExvZGFzaFdyYXBwZXIucHJvdG90eXBlLnRocnUgJiYgZ2V0RnVuY05hbWUoZnVuYykgPT0gJ3dyYXBwZXInKSB7XG4gICAgICAgICAgICB3cmFwcGVyID0gbmV3IExvZGFzaFdyYXBwZXIoW10sIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IHdyYXBwZXIgPyAtMSA6IGxlbmd0aDtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBmdW5jID0gZnVuY3NbaW5kZXhdO1xuXG4gICAgICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgICAgIGRhdGEgPSBmdW5jTmFtZSA9PSAnd3JhcHBlcicgPyBnZXREYXRhKGZ1bmMpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKGRhdGEgJiYgaXNMYXppYWJsZShkYXRhWzBdKSAmJiBkYXRhWzFdID09IChBUllfRkxBRyB8IENVUlJZX0ZMQUcgfCBQQVJUSUFMX0ZMQUcgfCBSRUFSR19GTEFHKSAmJiAhZGF0YVs0XS5sZW5ndGggJiYgZGF0YVs5XSA9PSAxKSB7XG4gICAgICAgICAgICB3cmFwcGVyID0gd3JhcHBlcltnZXRGdW5jTmFtZShkYXRhWzBdKV0uYXBwbHkod3JhcHBlciwgZGF0YVszXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdyYXBwZXIgPSAoZnVuYy5sZW5ndGggPT0gMSAmJiBpc0xhemlhYmxlKGZ1bmMpKSA/IHdyYXBwZXJbZnVuY05hbWVdKCkgOiB3cmFwcGVyLnRocnUoZnVuYyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICAgICAgdmFsdWUgPSBhcmdzWzBdO1xuXG4gICAgICAgICAgaWYgKHdyYXBwZXIgJiYgYXJncy5sZW5ndGggPT0gMSAmJiBpc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPj0gTEFSR0VfQVJSQVlfU0laRSkge1xuICAgICAgICAgICAgcmV0dXJuIHdyYXBwZXIucGxhbnQodmFsdWUpLnZhbHVlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBpbmRleCA9IDAsXG4gICAgICAgICAgICAgIHJlc3VsdCA9IGxlbmd0aCA/IGZ1bmNzW2luZGV4XS5hcHBseSh0aGlzLCBhcmdzKSA6IHZhbHVlO1xuXG4gICAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmNzW2luZGV4XS5jYWxsKHRoaXMsIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBmb3IgYF8uZm9yRWFjaGAgb3IgYF8uZm9yRWFjaFJpZ2h0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXJyYXlGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYW4gYXJyYXkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBhIGNvbGxlY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZWFjaCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVGb3JFYWNoKGFycmF5RnVuYywgZWFjaEZ1bmMpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSwgdGhpc0FyZykge1xuICAgICAgICByZXR1cm4gKHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nICYmIHRoaXNBcmcgPT09IHVuZGVmaW5lZCAmJiBpc0FycmF5KGNvbGxlY3Rpb24pKVxuICAgICAgICAgID8gYXJyYXlGdW5jKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKVxuICAgICAgICAgIDogZWFjaEZ1bmMoY29sbGVjdGlvbiwgYmluZENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAzKSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBmb3IgYF8uZm9ySW5gIG9yIGBfLmZvckluUmlnaHRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvYmplY3RGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYW4gb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGVhY2ggZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRm9ySW4ob2JqZWN0RnVuYykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpdGVyYXRlZSAhPSAnZnVuY3Rpb24nIHx8IHRoaXNBcmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGl0ZXJhdGVlID0gYmluZENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0RnVuYyhvYmplY3QsIGl0ZXJhdGVlLCBrZXlzSW4pO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gZm9yIGBfLmZvck93bmAgb3IgYF8uZm9yT3duUmlnaHRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvYmplY3RGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYW4gb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGVhY2ggZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRm9yT3duKG9iamVjdEZ1bmMpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlLCB0aGlzQXJnKSB7XG4gICAgICAgIGlmICh0eXBlb2YgaXRlcmF0ZWUgIT0gJ2Z1bmN0aW9uJyB8fCB0aGlzQXJnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpdGVyYXRlZSA9IGJpbmRDYWxsYmFjayhpdGVyYXRlZSwgdGhpc0FyZywgMyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdEZ1bmMob2JqZWN0LCBpdGVyYXRlZSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBmb3IgYF8ubWFwS2V5c2Agb3IgYF8ubWFwVmFsdWVzYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNNYXBLZXlzXSBTcGVjaWZ5IG1hcHBpbmcga2V5cyBpbnN0ZWFkIG9mIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBtYXAgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlT2JqZWN0TWFwcGVyKGlzTWFwS2V5cykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICBpdGVyYXRlZSA9IGdldENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAzKTtcblxuICAgICAgICBiYXNlRm9yT3duKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSwgb2JqZWN0KSB7XG4gICAgICAgICAgdmFyIG1hcHBlZCA9IGl0ZXJhdGVlKHZhbHVlLCBrZXksIG9iamVjdCk7XG4gICAgICAgICAga2V5ID0gaXNNYXBLZXlzID8gbWFwcGVkIDoga2V5O1xuICAgICAgICAgIHZhbHVlID0gaXNNYXBLZXlzID8gdmFsdWUgOiBtYXBwZWQ7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBmb3IgYF8ucGFkTGVmdGAgb3IgYF8ucGFkUmlnaHRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgcGFkZGluZyBmcm9tIHRoZSByaWdodC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFkRGlyKGZyb21SaWdodCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZywgbGVuZ3RoLCBjaGFycykge1xuICAgICAgICBzdHJpbmcgPSBiYXNlVG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgICAgcmV0dXJuIChmcm9tUmlnaHQgPyBzdHJpbmcgOiAnJykgKyBjcmVhdGVQYWRkaW5nKHN0cmluZywgbGVuZ3RoLCBjaGFycykgKyAoZnJvbVJpZ2h0ID8gJycgOiBzdHJpbmcpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8ucGFydGlhbGAgb3IgYF8ucGFydGlhbFJpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmbGFnIFRoZSBwYXJ0aWFsIGJpdCBmbGFnLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhcnRpYWwgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFydGlhbChmbGFnKSB7XG4gICAgICB2YXIgcGFydGlhbEZ1bmMgPSByZXN0UGFyYW0oZnVuY3Rpb24oZnVuYywgcGFydGlhbHMpIHtcbiAgICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgcGFydGlhbEZ1bmMucGxhY2Vob2xkZXIpO1xuICAgICAgICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCBmbGFnLCB1bmRlZmluZWQsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHBhcnRpYWxGdW5jO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBmb3IgYF8ucmVkdWNlYCBvciBgXy5yZWR1Y2VSaWdodGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGFycmF5RnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGFuIGFycmF5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYSBjb2xsZWN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGVhY2ggZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUmVkdWNlKGFycmF5RnVuYywgZWFjaEZ1bmMpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIGluaXRGcm9tQXJyYXkgPSBhcmd1bWVudHMubGVuZ3RoIDwgMztcbiAgICAgICAgcmV0dXJuICh0eXBlb2YgaXRlcmF0ZWUgPT0gJ2Z1bmN0aW9uJyAmJiB0aGlzQXJnID09PSB1bmRlZmluZWQgJiYgaXNBcnJheShjb2xsZWN0aW9uKSlcbiAgICAgICAgICA/IGFycmF5RnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRGcm9tQXJyYXkpXG4gICAgICAgICAgOiBiYXNlUmVkdWNlKGNvbGxlY3Rpb24sIGdldENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCA0KSwgYWNjdW11bGF0b3IsIGluaXRGcm9tQXJyYXksIGVhY2hGdW5jKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggb3B0aW9uYWwgYHRoaXNgXG4gICAgICogYmluZGluZyBvZiwgcGFydGlhbCBhcHBsaWNhdGlvbiwgYW5kIGN1cnJ5aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gcmVmZXJlbmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIG9mIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBwZXJgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzXSBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc1JpZ2h0XSBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzUmlnaHRdIFRoZSBgcGFydGlhbHNSaWdodGAgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVIeWJyaWRXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQXJ5ID0gYml0bWFzayAmIEFSWV9GTEFHLFxuICAgICAgICAgIGlzQmluZCA9IGJpdG1hc2sgJiBCSU5EX0ZMQUcsXG4gICAgICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIEJJTkRfS0VZX0ZMQUcsXG4gICAgICAgICAgaXNDdXJyeSA9IGJpdG1hc2sgJiBDVVJSWV9GTEFHLFxuICAgICAgICAgIGlzQ3VycnlCb3VuZCA9IGJpdG1hc2sgJiBDVVJSWV9CT1VORF9GTEFHLFxuICAgICAgICAgIGlzQ3VycnlSaWdodCA9IGJpdG1hc2sgJiBDVVJSWV9SSUdIVF9GTEFHLFxuICAgICAgICAgIEN0b3IgPSBpc0JpbmRLZXkgPyB1bmRlZmluZWQgOiBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgLy8gQXZvaWQgYGFyZ3VtZW50c2Agb2JqZWN0IHVzZSBkaXNxdWFsaWZ5aW5nIG9wdGltaXphdGlvbnMgYnlcbiAgICAgICAgLy8gY29udmVydGluZyBpdCB0byBhbiBhcnJheSBiZWZvcmUgcHJvdmlkaW5nIGl0IHRvIG90aGVyIGZ1bmN0aW9ucy5cbiAgICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBpbmRleCA9IGxlbmd0aCxcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgYXJnc1tpbmRleF0gPSBhcmd1bWVudHNbaW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJ0aWFscykge1xuICAgICAgICAgIGFyZ3MgPSBjb21wb3NlQXJncyhhcmdzLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRpYWxzUmlnaHQpIHtcbiAgICAgICAgICBhcmdzID0gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0N1cnJ5IHx8IGlzQ3VycnlSaWdodCkge1xuICAgICAgICAgIHZhciBwbGFjZWhvbGRlciA9IHdyYXBwZXIucGxhY2Vob2xkZXIsXG4gICAgICAgICAgICAgIGFyZ3NIb2xkZXJzID0gcmVwbGFjZUhvbGRlcnMoYXJncywgcGxhY2Vob2xkZXIpO1xuXG4gICAgICAgICAgbGVuZ3RoIC09IGFyZ3NIb2xkZXJzLmxlbmd0aDtcbiAgICAgICAgICBpZiAobGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICAgIHZhciBuZXdBcmdQb3MgPSBhcmdQb3MgPyBhcnJheUNvcHkoYXJnUG9zKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBuZXdBcml0eSA9IG5hdGl2ZU1heChhcml0eSAtIGxlbmd0aCwgMCksXG4gICAgICAgICAgICAgICAgbmV3c0hvbGRlcnMgPSBpc0N1cnJ5ID8gYXJnc0hvbGRlcnMgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgbmV3SG9sZGVyc1JpZ2h0ID0gaXNDdXJyeSA/IHVuZGVmaW5lZCA6IGFyZ3NIb2xkZXJzLFxuICAgICAgICAgICAgICAgIG5ld1BhcnRpYWxzID0gaXNDdXJyeSA/IGFyZ3MgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgbmV3UGFydGlhbHNSaWdodCA9IGlzQ3VycnkgPyB1bmRlZmluZWQgOiBhcmdzO1xuXG4gICAgICAgICAgICBiaXRtYXNrIHw9IChpc0N1cnJ5ID8gUEFSVElBTF9GTEFHIDogUEFSVElBTF9SSUdIVF9GTEFHKTtcbiAgICAgICAgICAgIGJpdG1hc2sgJj0gfihpc0N1cnJ5ID8gUEFSVElBTF9SSUdIVF9GTEFHIDogUEFSVElBTF9GTEFHKTtcblxuICAgICAgICAgICAgaWYgKCFpc0N1cnJ5Qm91bmQpIHtcbiAgICAgICAgICAgICAgYml0bWFzayAmPSB+KEJJTkRfRkxBRyB8IEJJTkRfS0VZX0ZMQUcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5ld0RhdGEgPSBbZnVuYywgYml0bWFzaywgdGhpc0FyZywgbmV3UGFydGlhbHMsIG5ld3NIb2xkZXJzLCBuZXdQYXJ0aWFsc1JpZ2h0LCBuZXdIb2xkZXJzUmlnaHQsIG5ld0FyZ1BvcywgYXJ5LCBuZXdBcml0eV0sXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gY3JlYXRlSHlicmlkV3JhcHBlci5hcHBseSh1bmRlZmluZWQsIG5ld0RhdGEpO1xuXG4gICAgICAgICAgICBpZiAoaXNMYXppYWJsZShmdW5jKSkge1xuICAgICAgICAgICAgICBzZXREYXRhKHJlc3VsdCwgbmV3RGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQucGxhY2Vob2xkZXIgPSBwbGFjZWhvbGRlcjtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB0aGlzQmluZGluZyA9IGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLFxuICAgICAgICAgICAgZm4gPSBpc0JpbmRLZXkgPyB0aGlzQmluZGluZ1tmdW5jXSA6IGZ1bmM7XG5cbiAgICAgICAgaWYgKGFyZ1Bvcykge1xuICAgICAgICAgIGFyZ3MgPSByZW9yZGVyKGFyZ3MsIGFyZ1Bvcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQXJ5ICYmIGFyeSA8IGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgYXJncy5sZW5ndGggPSBhcnk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikge1xuICAgICAgICAgIGZuID0gQ3RvciB8fCBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpc0JpbmRpbmcsIGFyZ3MpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgcGFkZGluZyByZXF1aXJlZCBmb3IgYHN0cmluZ2AgYmFzZWQgb24gdGhlIGdpdmVuIGBsZW5ndGhgLlxuICAgICAqIFRoZSBgY2hhcnNgIHN0cmluZyBpcyB0cnVuY2F0ZWQgaWYgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGV4Y2VlZHMgYGxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjcmVhdGUgcGFkZGluZyBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWQgZm9yIGBzdHJpbmdgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVBhZGRpbmcoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICB2YXIgc3RyTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIGxlbmd0aCA9ICtsZW5ndGg7XG5cbiAgICAgIGlmIChzdHJMZW5ndGggPj0gbGVuZ3RoIHx8ICFuYXRpdmVJc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICAgIHZhciBwYWRMZW5ndGggPSBsZW5ndGggLSBzdHJMZW5ndGg7XG4gICAgICBjaGFycyA9IGNoYXJzID09IG51bGwgPyAnICcgOiAoY2hhcnMgKyAnJyk7XG4gICAgICByZXR1cm4gcmVwZWF0KGNoYXJzLCBuYXRpdmVDZWlsKHBhZExlbmd0aCAvIGNoYXJzLmxlbmd0aCkpLnNsaWNlKDAsIHBhZExlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggdGhlIG9wdGlvbmFsIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgIGFuZCB0aGUgYHBhcnRpYWxzYCBwcmVwZW5kZWQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAgICAgKiB0aGUgd3JhcHBlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBvZiBmbGFncy4gU2VlIGBjcmVhdGVXcmFwcGVyYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVBhcnRpYWxXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzKSB7XG4gICAgICB2YXIgaXNCaW5kID0gYml0bWFzayAmIEJJTkRfRkxBRyxcbiAgICAgICAgICBDdG9yID0gY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgICAgIC8vIEF2b2lkIGBhcmd1bWVudHNgIG9iamVjdCB1c2UgZGlzcXVhbGlmeWluZyBvcHRpbWl6YXRpb25zIGJ5XG4gICAgICAgIC8vIGNvbnZlcnRpbmcgaXQgdG8gYW4gYXJyYXkgYmVmb3JlIHByb3ZpZGluZyBpdCBgZnVuY2AuXG4gICAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICAgIGFyZ3NMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICAgICAgbGVmdEluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZWZ0TGVuZ3RoID0gcGFydGlhbHMubGVuZ3RoLFxuICAgICAgICAgICAgYXJncyA9IEFycmF5KGxlZnRMZW5ndGggKyBhcmdzTGVuZ3RoKTtcblxuICAgICAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICAgICAgYXJnc1tsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSAoYXJnc0xlbmd0aC0tKSB7XG4gICAgICAgICAgYXJnc1tsZWZ0SW5kZXgrK10gPSBhcmd1bWVudHNbKythcmdzSW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IHJvb3QgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgICAgIHJldHVybiBmbi5hcHBseShpc0JpbmQgPyB0aGlzQXJnIDogdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uY2VpbGAsIGBfLmZsb29yYCwgb3IgYF8ucm91bmRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSBUaGUgbmFtZSBvZiB0aGUgYE1hdGhgIG1ldGhvZCB0byB1c2Ugd2hlbiByb3VuZGluZy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByb3VuZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSb3VuZChtZXRob2ROYW1lKSB7XG4gICAgICB2YXIgZnVuYyA9IE1hdGhbbWV0aG9kTmFtZV07XG4gICAgICByZXR1cm4gZnVuY3Rpb24obnVtYmVyLCBwcmVjaXNpb24pIHtcbiAgICAgICAgcHJlY2lzaW9uID0gcHJlY2lzaW9uID09PSB1bmRlZmluZWQgPyAwIDogKCtwcmVjaXNpb24gfHwgMCk7XG4gICAgICAgIGlmIChwcmVjaXNpb24pIHtcbiAgICAgICAgICBwcmVjaXNpb24gPSBwb3coMTAsIHByZWNpc2lvbik7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMobnVtYmVyICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYyhudW1iZXIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uc29ydGVkSW5kZXhgIG9yIGBfLnNvcnRlZExhc3RJbmRleGAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JldEhpZ2hlc3RdIFNwZWNpZnkgcmV0dXJuaW5nIHRoZSBoaWdoZXN0IHF1YWxpZmllZCBpbmRleC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBpbmRleCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVTb3J0ZWRJbmRleChyZXRIaWdoZXN0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIHZhbHVlLCBpdGVyYXRlZSwgdGhpc0FyZykge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBnZXRDYWxsYmFjayhpdGVyYXRlZSk7XG4gICAgICAgIHJldHVybiAoaXRlcmF0ZWUgPT0gbnVsbCAmJiBjYWxsYmFjayA9PT0gYmFzZUNhbGxiYWNrKVxuICAgICAgICAgID8gYmluYXJ5SW5kZXgoYXJyYXksIHZhbHVlLCByZXRIaWdoZXN0KVxuICAgICAgICAgIDogYmluYXJ5SW5kZXhCeShhcnJheSwgdmFsdWUsIGNhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAxKSwgcmV0SGlnaGVzdCk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGVpdGhlciBjdXJyaWVzIG9yIGludm9rZXMgYGZ1bmNgIHdpdGggb3B0aW9uYWxcbiAgICAgKiBgdGhpc2AgYmluZGluZyBhbmQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gcmVmZXJlbmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIG9mIGZsYWdzLlxuICAgICAqICBUaGUgYml0bWFzayBtYXkgYmUgY29tcG9zZWQgb2YgdGhlIGZvbGxvd2luZyBmbGFnczpcbiAgICAgKiAgICAgMSAtIGBfLmJpbmRgXG4gICAgICogICAgIDIgLSBgXy5iaW5kS2V5YFxuICAgICAqICAgICA0IC0gYF8uY3VycnlgIG9yIGBfLmN1cnJ5UmlnaHRgIG9mIGEgYm91bmQgZnVuY3Rpb25cbiAgICAgKiAgICAgOCAtIGBfLmN1cnJ5YFxuICAgICAqICAgIDE2IC0gYF8uY3VycnlSaWdodGBcbiAgICAgKiAgICAzMiAtIGBfLnBhcnRpYWxgXG4gICAgICogICAgNjQgLSBgXy5wYXJ0aWFsUmlnaHRgXG4gICAgICogICAxMjggLSBgXy5yZWFyZ2BcbiAgICAgKiAgIDI1NiAtIGBfLmFyeWBcbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBhcmdQb3MsIGFyeSwgYXJpdHkpIHtcbiAgICAgIHZhciBpc0JpbmRLZXkgPSBiaXRtYXNrICYgQklORF9LRVlfRkxBRztcbiAgICAgIGlmICghaXNCaW5kS2V5ICYmIHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IHBhcnRpYWxzID8gcGFydGlhbHMubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIGJpdG1hc2sgJj0gfihQQVJUSUFMX0ZMQUcgfCBQQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBsZW5ndGggLT0gKGhvbGRlcnMgPyBob2xkZXJzLmxlbmd0aCA6IDApO1xuICAgICAgaWYgKGJpdG1hc2sgJiBQQVJUSUFMX1JJR0hUX0ZMQUcpIHtcbiAgICAgICAgdmFyIHBhcnRpYWxzUmlnaHQgPSBwYXJ0aWFscyxcbiAgICAgICAgICAgIGhvbGRlcnNSaWdodCA9IGhvbGRlcnM7XG5cbiAgICAgICAgcGFydGlhbHMgPSBob2xkZXJzID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgdmFyIGRhdGEgPSBpc0JpbmRLZXkgPyB1bmRlZmluZWQgOiBnZXREYXRhKGZ1bmMpLFxuICAgICAgICAgIG5ld0RhdGEgPSBbZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIHBhcnRpYWxzUmlnaHQsIGhvbGRlcnNSaWdodCwgYXJnUG9zLCBhcnksIGFyaXR5XTtcblxuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgbWVyZ2VEYXRhKG5ld0RhdGEsIGRhdGEpO1xuICAgICAgICBiaXRtYXNrID0gbmV3RGF0YVsxXTtcbiAgICAgICAgYXJpdHkgPSBuZXdEYXRhWzldO1xuICAgICAgfVxuICAgICAgbmV3RGF0YVs5XSA9IGFyaXR5ID09IG51bGxcbiAgICAgICAgPyAoaXNCaW5kS2V5ID8gMCA6IGZ1bmMubGVuZ3RoKVxuICAgICAgICA6IChuYXRpdmVNYXgoYXJpdHkgLSBsZW5ndGgsIDApIHx8IDApO1xuXG4gICAgICBpZiAoYml0bWFzayA9PSBCSU5EX0ZMQUcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZUJpbmRXcmFwcGVyKG5ld0RhdGFbMF0sIG5ld0RhdGFbMl0pO1xuICAgICAgfSBlbHNlIGlmICgoYml0bWFzayA9PSBQQVJUSUFMX0ZMQUcgfHwgYml0bWFzayA9PSAoQklORF9GTEFHIHwgUEFSVElBTF9GTEFHKSkgJiYgIW5ld0RhdGFbNF0ubGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZVBhcnRpYWxXcmFwcGVyLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSBjcmVhdGVIeWJyaWRXcmFwcGVyLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICB9XG4gICAgICB2YXIgc2V0dGVyID0gZGF0YSA/IGJhc2VTZXREYXRhIDogc2V0RGF0YTtcbiAgICAgIHJldHVybiBzZXR0ZXIocmVzdWx0LCBuZXdEYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIGFycmF5cyB3aXRoIHN1cHBvcnQgZm9yXG4gICAgICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvdGhlciBUaGUgb3RoZXIgYXJyYXkgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIGFycmF5cy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0xvb3NlXSBTcGVjaWZ5IHBlcmZvcm1pbmcgcGFydGlhbCBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tBXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tCXSBUcmFja3MgdHJhdmVyc2VkIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGFycmF5cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxdWFsQXJyYXlzKGFycmF5LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgYXJyTGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIG90aExlbmd0aCA9IG90aGVyLmxlbmd0aDtcblxuICAgICAgaWYgKGFyckxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIShpc0xvb3NlICYmIG90aExlbmd0aCA+IGFyckxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gSWdub3JlIG5vbi1pbmRleCBwcm9wZXJ0aWVzLlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBhcnJMZW5ndGgpIHtcbiAgICAgICAgdmFyIGFyclZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgb3RoVmFsdWUgPSBvdGhlcltpbmRleF0sXG4gICAgICAgICAgICByZXN1bHQgPSBjdXN0b21pemVyID8gY3VzdG9taXplcihpc0xvb3NlID8gb3RoVmFsdWUgOiBhcnJWYWx1ZSwgaXNMb29zZSA/IGFyclZhbHVlIDogb3RoVmFsdWUsIGluZGV4KSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIGlmIChpc0xvb3NlKSB7XG4gICAgICAgICAgaWYgKCFhcnJheVNvbWUob3RoZXIsIGZ1bmN0aW9uKG90aFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFyclZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQik7XG4gICAgICAgICAgICAgIH0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEoYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgY29tcGFyaW5nIG9iamVjdHMgb2ZcbiAgICAgKiB0aGUgc2FtZSBgdG9TdHJpbmdUYWdgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gb25seSBzdXBwb3J0cyBjb21wYXJpbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICAgICAqIGBCb29sZWFuYCwgYERhdGVgLCBgRXJyb3JgLCBgTnVtYmVyYCwgYFJlZ0V4cGAsIG9yIGBTdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdHMgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIHRhZykge1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBib29sVGFnOlxuICAgICAgICBjYXNlIGRhdGVUYWc6XG4gICAgICAgICAgLy8gQ29lcmNlIGRhdGVzIGFuZCBib29sZWFucyB0byBudW1iZXJzLCBkYXRlcyB0byBtaWxsaXNlY29uZHMgYW5kIGJvb2xlYW5zXG4gICAgICAgICAgLy8gdG8gYDFgIG9yIGAwYCB0cmVhdGluZyBpbnZhbGlkIGRhdGVzIGNvZXJjZWQgdG8gYE5hTmAgYXMgbm90IGVxdWFsLlxuICAgICAgICAgIHJldHVybiArb2JqZWN0ID09ICtvdGhlcjtcblxuICAgICAgICBjYXNlIGVycm9yVGFnOlxuICAgICAgICAgIHJldHVybiBvYmplY3QubmFtZSA9PSBvdGhlci5uYW1lICYmIG9iamVjdC5tZXNzYWdlID09IG90aGVyLm1lc3NhZ2U7XG5cbiAgICAgICAgY2FzZSBudW1iZXJUYWc6XG4gICAgICAgICAgLy8gVHJlYXQgYE5hTmAgdnMuIGBOYU5gIGFzIGVxdWFsLlxuICAgICAgICAgIHJldHVybiAob2JqZWN0ICE9ICtvYmplY3QpXG4gICAgICAgICAgICA/IG90aGVyICE9ICtvdGhlclxuICAgICAgICAgICAgOiBvYmplY3QgPT0gK290aGVyO1xuXG4gICAgICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgICAgICAvLyBDb2VyY2UgcmVnZXhlcyB0byBzdHJpbmdzIGFuZCB0cmVhdCBzdHJpbmdzIHByaW1pdGl2ZXMgYW5kIHN0cmluZ1xuICAgICAgICAgIC8vIG9iamVjdHMgYXMgZXF1YWwuIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxNS4xMC42LjQgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICByZXR1cm4gb2JqZWN0ID09IChvdGhlciArICcnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIG9iamVjdHMgd2l0aCBzdXBwb3J0IGZvclxuICAgICAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0xvb3NlXSBTcGVjaWZ5IHBlcmZvcm1pbmcgcGFydGlhbCBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tBXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tCXSBUcmFja3MgdHJhdmVyc2VkIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbE9iamVjdHMob2JqZWN0LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgdmFyIG9ialByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIG9iakxlbmd0aCA9IG9ialByb3BzLmxlbmd0aCxcbiAgICAgICAgICBvdGhQcm9wcyA9IGtleXMob3RoZXIpLFxuICAgICAgICAgIG90aExlbmd0aCA9IG90aFByb3BzLmxlbmd0aDtcblxuICAgICAgaWYgKG9iakxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIWlzTG9vc2UpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gb2JqTGVuZ3RoO1xuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgdmFyIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICAgICAgaWYgKCEoaXNMb29zZSA/IGtleSBpbiBvdGhlciA6IGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsIGtleSkpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgc2tpcEN0b3IgPSBpc0xvb3NlO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBvYmpMZW5ndGgpIHtcbiAgICAgICAga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgICAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICAgIG90aFZhbHVlID0gb3RoZXJba2V5XSxcbiAgICAgICAgICAgIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKGlzTG9vc2UgPyBvdGhWYWx1ZSA6IG9ialZhbHVlLCBpc0xvb3NlPyBvYmpWYWx1ZSA6IG90aFZhbHVlLCBrZXkpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBpZiAoIShyZXN1bHQgPT09IHVuZGVmaW5lZCA/IGVxdWFsRnVuYyhvYmpWYWx1ZSwgb3RoVmFsdWUsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKSA6IHJlc3VsdCkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2tpcEN0b3IgfHwgKHNraXBDdG9yID0ga2V5ID09ICdjb25zdHJ1Y3RvcicpO1xuICAgICAgfVxuICAgICAgaWYgKCFza2lwQ3Rvcikge1xuICAgICAgICB2YXIgb2JqQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcixcbiAgICAgICAgICAgIG90aEN0b3IgPSBvdGhlci5jb25zdHJ1Y3RvcjtcblxuICAgICAgICAvLyBOb24gYE9iamVjdGAgb2JqZWN0IGluc3RhbmNlcyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVhbC5cbiAgICAgICAgaWYgKG9iakN0b3IgIT0gb3RoQ3RvciAmJlxuICAgICAgICAgICAgKCdjb25zdHJ1Y3RvcicgaW4gb2JqZWN0ICYmICdjb25zdHJ1Y3RvcicgaW4gb3RoZXIpICYmXG4gICAgICAgICAgICAhKHR5cGVvZiBvYmpDdG9yID09ICdmdW5jdGlvbicgJiYgb2JqQ3RvciBpbnN0YW5jZW9mIG9iakN0b3IgJiZcbiAgICAgICAgICAgICAgdHlwZW9mIG90aEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBvdGhDdG9yIGluc3RhbmNlb2Ygb3RoQ3RvcikpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGFwcHJvcHJpYXRlIFwiY2FsbGJhY2tcIiBmdW5jdGlvbi4gSWYgdGhlIGBfLmNhbGxiYWNrYCBtZXRob2QgaXNcbiAgICAgKiBjdXN0b21pemVkIHRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgY3VzdG9tIG1ldGhvZCwgb3RoZXJ3aXNlIGl0IHJldHVybnNcbiAgICAgKiB0aGUgYGJhc2VDYWxsYmFja2AgZnVuY3Rpb24uIElmIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdGhlIGNob3NlbiBmdW5jdGlvblxuICAgICAqIGlzIGludm9rZWQgd2l0aCB0aGVtIGFuZCBpdHMgcmVzdWx0IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNob3NlbiBmdW5jdGlvbiBvciBpdHMgcmVzdWx0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldENhbGxiYWNrKGZ1bmMsIHRoaXNBcmcsIGFyZ0NvdW50KSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoLmNhbGxiYWNrIHx8IGNhbGxiYWNrO1xuICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSBjYWxsYmFjayA/IGJhc2VDYWxsYmFjayA6IHJlc3VsdDtcbiAgICAgIHJldHVybiBhcmdDb3VudCA/IHJlc3VsdChmdW5jLCB0aGlzQXJnLCBhcmdDb3VudCkgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWV0YWRhdGEgZm9yIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgZ2V0RGF0YSA9ICFtZXRhTWFwID8gbm9vcCA6IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICAgIHJldHVybiBtZXRhTWFwLmdldChmdW5jKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmFtZSBvZiBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0RnVuY05hbWUoZnVuYykge1xuICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMubmFtZSxcbiAgICAgICAgICBhcnJheSA9IHJlYWxOYW1lc1tyZXN1bHRdLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBkYXRhID0gYXJyYXlbbGVuZ3RoXSxcbiAgICAgICAgICAgIG90aGVyRnVuYyA9IGRhdGEuZnVuYztcbiAgICAgICAgaWYgKG90aGVyRnVuYyA9PSBudWxsIHx8IG90aGVyRnVuYyA9PSBmdW5jKSB7XG4gICAgICAgICAgcmV0dXJuIGRhdGEubmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhcHByb3ByaWF0ZSBcImluZGV4T2ZcIiBmdW5jdGlvbi4gSWYgdGhlIGBfLmluZGV4T2ZgIG1ldGhvZCBpc1xuICAgICAqIGN1c3RvbWl6ZWQgdGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSBjdXN0b20gbWV0aG9kLCBvdGhlcndpc2UgaXQgcmV0dXJuc1xuICAgICAqIHRoZSBgYmFzZUluZGV4T2ZgIGZ1bmN0aW9uLiBJZiBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRoZSBjaG9zZW4gZnVuY3Rpb25cbiAgICAgKiBpcyBpbnZva2VkIHdpdGggdGhlbSBhbmQgaXRzIHJlc3VsdCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufG51bWJlcn0gUmV0dXJucyB0aGUgY2hvc2VuIGZ1bmN0aW9uIG9yIGl0cyByZXN1bHQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SW5kZXhPZihjb2xsZWN0aW9uLCB0YXJnZXQsIGZyb21JbmRleCkge1xuICAgICAgdmFyIHJlc3VsdCA9IGxvZGFzaC5pbmRleE9mIHx8IGluZGV4T2Y7XG4gICAgICByZXN1bHQgPSByZXN1bHQgPT09IGluZGV4T2YgPyBiYXNlSW5kZXhPZiA6IHJlc3VsdDtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uID8gcmVzdWx0KGNvbGxlY3Rpb24sIHRhcmdldCwgZnJvbUluZGV4KSA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IHZhbHVlIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBhdm9pZCBhIFtKSVQgYnVnXShodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNzkyKVxuICAgICAqIHRoYXQgYWZmZWN0cyBTYWZhcmkgb24gYXQgbGVhc3QgaU9TIDguMS04LjMgQVJNNjQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgXCJsZW5ndGhcIiB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgZ2V0TGVuZ3RoID0gYmFzZVByb3BlcnR5KCdsZW5ndGgnKTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHByb3BlcnkgbmFtZXMsIHZhbHVlcywgYW5kIGNvbXBhcmUgZmxhZ3Mgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG1hdGNoIGRhdGEgb2YgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWF0Y2hEYXRhKG9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHBhaXJzKG9iamVjdCksXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHJlc3VsdFtsZW5ndGhdWzJdID0gaXNTdHJpY3RDb21wYXJhYmxlKHJlc3VsdFtsZW5ndGhdWzFdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmF0aXZlIGZ1bmN0aW9uIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBpZiBpdCdzIG5hdGl2ZSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgICByZXR1cm4gaXNOYXRpdmUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmlldywgYXBwbHlpbmcgYW55IGB0cmFuc2Zvcm1zYCB0byB0aGUgYHN0YXJ0YCBhbmQgYGVuZGAgcG9zaXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSB2aWV3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgdmlldy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB0cmFuc2Zvcm1zIFRoZSB0cmFuc2Zvcm1hdGlvbnMgdG8gYXBwbHkgdG8gdGhlIHZpZXcuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgYHN0YXJ0YCBhbmQgYGVuZGBcbiAgICAgKiAgcG9zaXRpb25zIG9mIHRoZSB2aWV3LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZpZXcoc3RhcnQsIGVuZCwgdHJhbnNmb3Jtcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdHJhbnNmb3Jtcy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBkYXRhID0gdHJhbnNmb3Jtc1tpbmRleF0sXG4gICAgICAgICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gICAgICAgIHN3aXRjaCAoZGF0YS50eXBlKSB7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6ICAgICAgc3RhcnQgKz0gc2l6ZTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcFJpZ2h0JzogZW5kIC09IHNpemU7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2UnOiAgICAgIGVuZCA9IG5hdGl2ZU1pbihlbmQsIHN0YXJ0ICsgc2l6ZSk7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2VSaWdodCc6IHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0LCBlbmQgLSBzaXplKTsgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7ICdzdGFydCc6IHN0YXJ0LCAnZW5kJzogZW5kIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYW4gYXJyYXkgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGluaXRpYWxpemVkIGNsb25lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRDbG9uZUFycmF5KGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IG5ldyBhcnJheS5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gICAgICAvLyBBZGQgYXJyYXkgcHJvcGVydGllcyBhc3NpZ25lZCBieSBgUmVnRXhwI2V4ZWNgLlxuICAgICAgaWYgKGxlbmd0aCAmJiB0eXBlb2YgYXJyYXlbMF0gPT0gJ3N0cmluZycgJiYgaGFzT3duUHJvcGVydHkuY2FsbChhcnJheSwgJ2luZGV4JykpIHtcbiAgICAgICAgcmVzdWx0LmluZGV4ID0gYXJyYXkuaW5kZXg7XG4gICAgICAgIHJlc3VsdC5pbnB1dCA9IGFycmF5LmlucHV0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhbiBvYmplY3QgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVPYmplY3Qob2JqZWN0KSB7XG4gICAgICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgICAgIGlmICghKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiYgQ3RvciBpbnN0YW5jZW9mIEN0b3IpKSB7XG4gICAgICAgIEN0b3IgPSBPYmplY3Q7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEN0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lIGJhc2VkIG9uIGl0cyBgdG9TdHJpbmdUYWdgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gb25seSBzdXBwb3J0cyBjbG9uaW5nIHZhbHVlcyB3aXRoIHRhZ3Mgb2ZcbiAgICAgKiBgQm9vbGVhbmAsIGBEYXRlYCwgYEVycm9yYCwgYE51bWJlcmAsIGBSZWdFeHBgLCBvciBgU3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGluaXRpYWxpemVkIGNsb25lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRDbG9uZUJ5VGFnKG9iamVjdCwgdGFnLCBpc0RlZXApIHtcbiAgICAgIHZhciBDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgICAgICByZXR1cm4gYnVmZmVyQ2xvbmUob2JqZWN0KTtcblxuICAgICAgICBjYXNlIGJvb2xUYWc6XG4gICAgICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3IoK29iamVjdCk7XG5cbiAgICAgICAgY2FzZSBmbG9hdDMyVGFnOiBjYXNlIGZsb2F0NjRUYWc6XG4gICAgICAgIGNhc2UgaW50OFRhZzogY2FzZSBpbnQxNlRhZzogY2FzZSBpbnQzMlRhZzpcbiAgICAgICAgY2FzZSB1aW50OFRhZzogY2FzZSB1aW50OENsYW1wZWRUYWc6IGNhc2UgdWludDE2VGFnOiBjYXNlIHVpbnQzMlRhZzpcbiAgICAgICAgICB2YXIgYnVmZmVyID0gb2JqZWN0LmJ1ZmZlcjtcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3IoaXNEZWVwID8gYnVmZmVyQ2xvbmUoYnVmZmVyKSA6IGJ1ZmZlciwgb2JqZWN0LmJ5dGVPZmZzZXQsIG9iamVjdC5sZW5ndGgpO1xuXG4gICAgICAgIGNhc2UgbnVtYmVyVGFnOlxuICAgICAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3Iob2JqZWN0KTtcblxuICAgICAgICBjYXNlIHJlZ2V4cFRhZzpcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IEN0b3Iob2JqZWN0LnNvdXJjZSwgcmVGbGFncy5leGVjKG9iamVjdCkpO1xuICAgICAgICAgIHJlc3VsdC5sYXN0SW5kZXggPSBvYmplY3QubGFzdEluZGV4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9uIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW52b2tlUGF0aChvYmplY3QsIHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmIChvYmplY3QgIT0gbnVsbCAmJiAhaXNLZXkocGF0aCwgb2JqZWN0KSkge1xuICAgICAgICBwYXRoID0gdG9QYXRoKHBhdGgpO1xuICAgICAgICBvYmplY3QgPSBwYXRoLmxlbmd0aCA9PSAxID8gb2JqZWN0IDogYmFzZUdldChvYmplY3QsIGJhc2VTbGljZShwYXRoLCAwLCAtMSkpO1xuICAgICAgICBwYXRoID0gbGFzdChwYXRoKTtcbiAgICAgIH1cbiAgICAgIHZhciBmdW5jID0gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBvYmplY3RbcGF0aF07XG4gICAgICByZXR1cm4gZnVuYyA9PSBudWxsID8gdW5kZWZpbmVkIDogZnVuYy5hcHBseShvYmplY3QsIGFyZ3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0FycmF5TGlrZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgaXNMZW5ndGgoZ2V0TGVuZ3RoKHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGluZGV4LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD1NQVhfU0FGRV9JTlRFR0VSXSBUaGUgdXBwZXIgYm91bmRzIG9mIGEgdmFsaWQgaW5kZXguXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBpbmRleCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSW5kZXgodmFsdWUsIGxlbmd0aCkge1xuICAgICAgdmFsdWUgPSAodHlwZW9mIHZhbHVlID09ICdudW1iZXInIHx8IHJlSXNVaW50LnRlc3QodmFsdWUpKSA/ICt2YWx1ZSA6IC0xO1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoID09IG51bGwgPyBNQVhfU0FGRV9JTlRFR0VSIDogbGVuZ3RoO1xuICAgICAgcmV0dXJuIHZhbHVlID4gLTEgJiYgdmFsdWUgJSAxID09IDAgJiYgdmFsdWUgPCBsZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSBwcm92aWRlZCBhcmd1bWVudHMgYXJlIGZyb20gYW4gaXRlcmF0ZWUgY2FsbC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIHZhbHVlIGFyZ3VtZW50LlxuICAgICAqIEBwYXJhbSB7Kn0gaW5kZXggVGhlIHBvdGVudGlhbCBpdGVyYXRlZSBpbmRleCBvciBrZXkgYXJndW1lbnQuXG4gICAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIHBvdGVudGlhbCBpdGVyYXRlZSBvYmplY3QgYXJndW1lbnQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBhcmd1bWVudHMgYXJlIGZyb20gYW4gaXRlcmF0ZWUgY2FsbCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSXRlcmF0ZWVDYWxsKHZhbHVlLCBpbmRleCwgb2JqZWN0KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgaW5kZXg7XG4gICAgICBpZiAodHlwZSA9PSAnbnVtYmVyJ1xuICAgICAgICAgID8gKGlzQXJyYXlMaWtlKG9iamVjdCkgJiYgaXNJbmRleChpbmRleCwgb2JqZWN0Lmxlbmd0aCkpXG4gICAgICAgICAgOiAodHlwZSA9PSAnc3RyaW5nJyAmJiBpbmRleCBpbiBvYmplY3QpKSB7XG4gICAgICAgIHZhciBvdGhlciA9IG9iamVjdFtpbmRleF07XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWUgPyAodmFsdWUgPT09IG90aGVyKSA6IChvdGhlciAhPT0gb3RoZXIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgbm90IGEgcHJvcGVydHkgcGF0aC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkga2V5cyBvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHByb3BlcnR5IG5hbWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0tleSh2YWx1ZSwgb2JqZWN0KSB7XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgICAgIGlmICgodHlwZSA9PSAnc3RyaW5nJyAmJiByZUlzUGxhaW5Qcm9wLnRlc3QodmFsdWUpKSB8fCB0eXBlID09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSAhcmVJc0RlZXBQcm9wLnRlc3QodmFsdWUpO1xuICAgICAgcmV0dXJuIHJlc3VsdCB8fCAob2JqZWN0ICE9IG51bGwgJiYgdmFsdWUgaW4gdG9PYmplY3Qob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgYSBsYXp5IGNvdW50ZXJwYXJ0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGhhcyBhIGxhenkgY291bnRlcnBhcnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0xhemlhYmxlKGZ1bmMpIHtcbiAgICAgIHZhciBmdW5jTmFtZSA9IGdldEZ1bmNOYW1lKGZ1bmMpO1xuICAgICAgaWYgKCEoZnVuY05hbWUgaW4gTGF6eVdyYXBwZXIucHJvdG90eXBlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgb3RoZXIgPSBsb2Rhc2hbZnVuY05hbWVdO1xuICAgICAgaWYgKGZ1bmMgPT09IG90aGVyKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgdmFyIGRhdGEgPSBnZXREYXRhKG90aGVyKTtcbiAgICAgIHJldHVybiAhIWRhdGEgJiYgZnVuYyA9PT0gZGF0YVswXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgbGVuZ3RoLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gaXMgYmFzZWQgb24gW2BUb0xlbmd0aGBdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXRvbGVuZ3RoKS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBsZW5ndGgsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0xlbmd0aCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaWYgc3VpdGFibGUgZm9yIHN0cmljdFxuICAgICAqICBlcXVhbGl0eSBjb21wYXJpc29ucywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSAmJiAhaXNPYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlcyB0aGUgZnVuY3Rpb24gbWV0YWRhdGEgb2YgYHNvdXJjZWAgaW50byBgZGF0YWAuXG4gICAgICpcbiAgICAgKiBNZXJnaW5nIG1ldGFkYXRhIHJlZHVjZXMgdGhlIG51bWJlciBvZiB3cmFwcGVycyByZXF1aXJlZCB0byBpbnZva2UgYSBmdW5jdGlvbi5cbiAgICAgKiBUaGlzIGlzIHBvc3NpYmxlIGJlY2F1c2UgbWV0aG9kcyBsaWtlIGBfLmJpbmRgLCBgXy5jdXJyeWAsIGFuZCBgXy5wYXJ0aWFsYFxuICAgICAqIG1heSBiZSBhcHBsaWVkIHJlZ2FyZGxlc3Mgb2YgZXhlY3V0aW9uIG9yZGVyLiBNZXRob2RzIGxpa2UgYF8uYXJ5YCBhbmQgYF8ucmVhcmdgXG4gICAgICogYXVnbWVudCBmdW5jdGlvbiBhcmd1bWVudHMsIG1ha2luZyB0aGUgb3JkZXIgaW4gd2hpY2ggdGhleSBhcmUgZXhlY3V0ZWQgaW1wb3J0YW50LFxuICAgICAqIHByZXZlbnRpbmcgdGhlIG1lcmdpbmcgb2YgbWV0YWRhdGEuIEhvd2V2ZXIsIHdlIG1ha2UgYW4gZXhjZXB0aW9uIGZvciBhIHNhZmVcbiAgICAgKiBjb21tb24gY2FzZSB3aGVyZSBjdXJyaWVkIGZ1bmN0aW9ucyBoYXZlIGBfLmFyeWAgYW5kIG9yIGBfLnJlYXJnYCBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBkYXRhIFRoZSBkZXN0aW5hdGlvbiBtZXRhZGF0YS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIHNvdXJjZSBtZXRhZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGRhdGFgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1lcmdlRGF0YShkYXRhLCBzb3VyY2UpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gZGF0YVsxXSxcbiAgICAgICAgICBzcmNCaXRtYXNrID0gc291cmNlWzFdLFxuICAgICAgICAgIG5ld0JpdG1hc2sgPSBiaXRtYXNrIHwgc3JjQml0bWFzayxcbiAgICAgICAgICBpc0NvbW1vbiA9IG5ld0JpdG1hc2sgPCBBUllfRkxBRztcblxuICAgICAgdmFyIGlzQ29tYm8gPVxuICAgICAgICAoc3JjQml0bWFzayA9PSBBUllfRkxBRyAmJiBiaXRtYXNrID09IENVUlJZX0ZMQUcpIHx8XG4gICAgICAgIChzcmNCaXRtYXNrID09IEFSWV9GTEFHICYmIGJpdG1hc2sgPT0gUkVBUkdfRkxBRyAmJiBkYXRhWzddLmxlbmd0aCA8PSBzb3VyY2VbOF0pIHx8XG4gICAgICAgIChzcmNCaXRtYXNrID09IChBUllfRkxBRyB8IFJFQVJHX0ZMQUcpICYmIGJpdG1hc2sgPT0gQ1VSUllfRkxBRyk7XG5cbiAgICAgIC8vIEV4aXQgZWFybHkgaWYgbWV0YWRhdGEgY2FuJ3QgYmUgbWVyZ2VkLlxuICAgICAgaWYgKCEoaXNDb21tb24gfHwgaXNDb21ibykpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGB0aGlzQXJnYCBpZiBhdmFpbGFibGUuXG4gICAgICBpZiAoc3JjQml0bWFzayAmIEJJTkRfRkxBRykge1xuICAgICAgICBkYXRhWzJdID0gc291cmNlWzJdO1xuICAgICAgICAvLyBTZXQgd2hlbiBjdXJyeWluZyBhIGJvdW5kIGZ1bmN0aW9uLlxuICAgICAgICBuZXdCaXRtYXNrIHw9IChiaXRtYXNrICYgQklORF9GTEFHKSA/IDAgOiBDVVJSWV9CT1VORF9GTEFHO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIGFyZ3VtZW50cy5cbiAgICAgIHZhciB2YWx1ZSA9IHNvdXJjZVszXTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB2YXIgcGFydGlhbHMgPSBkYXRhWzNdO1xuICAgICAgICBkYXRhWzNdID0gcGFydGlhbHMgPyBjb21wb3NlQXJncyhwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs0XSkgOiBhcnJheUNvcHkodmFsdWUpO1xuICAgICAgICBkYXRhWzRdID0gcGFydGlhbHMgPyByZXBsYWNlSG9sZGVycyhkYXRhWzNdLCBQTEFDRUhPTERFUikgOiBhcnJheUNvcHkoc291cmNlWzRdKTtcbiAgICAgIH1cbiAgICAgIC8vIENvbXBvc2UgcGFydGlhbCByaWdodCBhcmd1bWVudHMuXG4gICAgICB2YWx1ZSA9IHNvdXJjZVs1XTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBwYXJ0aWFscyA9IGRhdGFbNV07XG4gICAgICAgIGRhdGFbNV0gPSBwYXJ0aWFscyA/IGNvbXBvc2VBcmdzUmlnaHQocGFydGlhbHMsIHZhbHVlLCBzb3VyY2VbNl0pIDogYXJyYXlDb3B5KHZhbHVlKTtcbiAgICAgICAgZGF0YVs2XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVs1XSwgUExBQ0VIT0xERVIpIDogYXJyYXlDb3B5KHNvdXJjZVs2XSk7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcmdQb3NgIGlmIGF2YWlsYWJsZS5cbiAgICAgIHZhbHVlID0gc291cmNlWzddO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIGRhdGFbN10gPSBhcnJheUNvcHkodmFsdWUpO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJ5YCBpZiBpdCdzIHNtYWxsZXIuXG4gICAgICBpZiAoc3JjQml0bWFzayAmIEFSWV9GTEFHKSB7XG4gICAgICAgIGRhdGFbOF0gPSBkYXRhWzhdID09IG51bGwgPyBzb3VyY2VbOF0gOiBuYXRpdmVNaW4oZGF0YVs4XSwgc291cmNlWzhdKTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYGFyaXR5YCBpZiBvbmUgaXMgbm90IHByb3ZpZGVkLlxuICAgICAgaWYgKGRhdGFbOV0gPT0gbnVsbCkge1xuICAgICAgICBkYXRhWzldID0gc291cmNlWzldO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgZnVuY2AgYW5kIG1lcmdlIGJpdG1hc2tzLlxuICAgICAgZGF0YVswXSA9IHNvdXJjZVswXTtcbiAgICAgIGRhdGFbMV0gPSBuZXdCaXRtYXNrO1xuXG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGJ5IGBfLmRlZmF1bHRzRGVlcGAgdG8gY3VzdG9taXplIGl0cyBgXy5tZXJnZWAgdXNlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IG9iamVjdFZhbHVlIFRoZSBkZXN0aW5hdGlvbiBvYmplY3QgcHJvcGVydHkgdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBzb3VyY2VWYWx1ZSBUaGUgc291cmNlIG9iamVjdCBwcm9wZXJ0eSB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdmFsdWUgdG8gYXNzaWduIHRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2VEZWZhdWx0cyhvYmplY3RWYWx1ZSwgc291cmNlVmFsdWUpIHtcbiAgICAgIHJldHVybiBvYmplY3RWYWx1ZSA9PT0gdW5kZWZpbmVkID8gc291cmNlVmFsdWUgOiBtZXJnZShvYmplY3RWYWx1ZSwgc291cmNlVmFsdWUsIG1lcmdlRGVmYXVsdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5waWNrYCB3aGljaCBwaWNrcyBgb2JqZWN0YCBwcm9wZXJ0aWVzIHNwZWNpZmllZFxuICAgICAqIGJ5IGBwcm9wc2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIHBpY2suXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwaWNrQnlBcnJheShvYmplY3QsIHByb3BzKSB7XG4gICAgICBvYmplY3QgPSB0b09iamVjdChvYmplY3QpO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8ucGlja2Agd2hpY2ggcGlja3MgYG9iamVjdGAgcHJvcGVydGllcyBgcHJlZGljYXRlYFxuICAgICAqIHJldHVybnMgdHJ1dGh5IGZvci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBpY2tCeUNhbGxiYWNrKG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBiYXNlRm9ySW4ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBvYmplY3QpKSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlb3JkZXIgYGFycmF5YCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBpbmRleGVzIHdoZXJlIHRoZSBlbGVtZW50IGF0XG4gICAgICogdGhlIGZpcnN0IGluZGV4IGlzIGFzc2lnbmVkIGFzIHRoZSBmaXJzdCBlbGVtZW50LCB0aGUgZWxlbWVudCBhdFxuICAgICAqIHRoZSBzZWNvbmQgaW5kZXggaXMgYXNzaWduZWQgYXMgdGhlIHNlY29uZCBlbGVtZW50LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byByZW9yZGVyLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGluZGV4ZXMgVGhlIGFycmFuZ2VkIGFycmF5IGluZGV4ZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVvcmRlcihhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNaW4oaW5kZXhlcy5sZW5ndGgsIGFyckxlbmd0aCksXG4gICAgICAgICAgb2xkQXJyYXkgPSBhcnJheUNvcHkoYXJyYXkpO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGluZGV4ID0gaW5kZXhlc1tsZW5ndGhdO1xuICAgICAgICBhcnJheVtsZW5ndGhdID0gaXNJbmRleChpbmRleCwgYXJyTGVuZ3RoKSA/IG9sZEFycmF5W2luZGV4XSA6IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSWYgdGhpcyBmdW5jdGlvbiBiZWNvbWVzIGhvdCwgaS5lLiBpcyBpbnZva2VkIGEgbG90IGluIGEgc2hvcnRcbiAgICAgKiBwZXJpb2Qgb2YgdGltZSwgaXQgd2lsbCB0cmlwIGl0cyBicmVha2VyIGFuZCB0cmFuc2l0aW9uIHRvIGFuIGlkZW50aXR5IGZ1bmN0aW9uXG4gICAgICogdG8gYXZvaWQgZ2FyYmFnZSBjb2xsZWN0aW9uIHBhdXNlcyBpbiBWOC4gU2VlIFtWOCBpc3N1ZSAyMDcwXShodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjA3MClcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhc3NvY2lhdGUgbWV0YWRhdGEgd2l0aC5cbiAgICAgKiBAcGFyYW0geyp9IGRhdGEgVGhlIG1ldGFkYXRhLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgZnVuY2AuXG4gICAgICovXG4gICAgdmFyIHNldERhdGEgPSAoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgY291bnQgPSAwLFxuICAgICAgICAgIGxhc3RDYWxsZWQgPSAwO1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICAgICAgICB2YXIgc3RhbXAgPSBub3coKSxcbiAgICAgICAgICAgIHJlbWFpbmluZyA9IEhPVF9TUEFOIC0gKHN0YW1wIC0gbGFzdENhbGxlZCk7XG5cbiAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICBpZiAocmVtYWluaW5nID4gMCkge1xuICAgICAgICAgIGlmICgrK2NvdW50ID49IEhPVF9DT1VOVCkge1xuICAgICAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiYXNlU2V0RGF0YShrZXksIHZhbHVlKTtcbiAgICAgIH07XG4gICAgfSgpKTtcblxuICAgIC8qKlxuICAgICAqIEEgZmFsbGJhY2sgaW1wbGVtZW50YXRpb24gb2YgYE9iamVjdC5rZXlzYCB3aGljaCBjcmVhdGVzIGFuIGFycmF5IG9mIHRoZVxuICAgICAqIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaGltS2V5cyhvYmplY3QpIHtcbiAgICAgIHZhciBwcm9wcyA9IGtleXNJbihvYmplY3QpLFxuICAgICAgICAgIHByb3BzTGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzTGVuZ3RoICYmIG9iamVjdC5sZW5ndGg7XG5cbiAgICAgIHZhciBhbGxvd0luZGV4ZXMgPSAhIWxlbmd0aCAmJiBpc0xlbmd0aChsZW5ndGgpICYmXG4gICAgICAgIChpc0FycmF5KG9iamVjdCkgfHwgaXNBcmd1bWVudHMob2JqZWN0KSk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IHByb3BzTGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIGlmICgoYWxsb3dJbmRleGVzICYmIGlzSW5kZXgoa2V5LCBsZW5ndGgpKSB8fCBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBhcnJheS1saWtlIG9iamVjdCBpZiBpdCdzIG5vdCBvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyB0aGUgYXJyYXktbGlrZSBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9JdGVyYWJsZSh2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKCFpc0FycmF5TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlcyh2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNPYmplY3QodmFsdWUpID8gdmFsdWUgOiBPYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gb2JqZWN0IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9PYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdCh2YWx1ZSkgPyB2YWx1ZSA6IE9iamVjdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBwcm9wZXJ0eSBwYXRoIGFycmF5IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHByb3BlcnR5IHBhdGggYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYXRoKHZhbHVlKSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgYmFzZVRvU3RyaW5nKHZhbHVlKS5yZXBsYWNlKHJlUHJvcE5hbWUsIGZ1bmN0aW9uKG1hdGNoLCBudW1iZXIsIHF1b3RlLCBzdHJpbmcpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gocXVvdGUgPyBzdHJpbmcucmVwbGFjZShyZUVzY2FwZUNoYXIsICckMScpIDogKG51bWJlciB8fCBtYXRjaCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgd3JhcHBlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB3cmFwcGVyIFRoZSB3cmFwcGVyIHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCB3cmFwcGVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDbG9uZSh3cmFwcGVyKSB7XG4gICAgICByZXR1cm4gd3JhcHBlciBpbnN0YW5jZW9mIExhenlXcmFwcGVyXG4gICAgICAgID8gd3JhcHBlci5jbG9uZSgpXG4gICAgICAgIDogbmV3IExvZGFzaFdyYXBwZXIod3JhcHBlci5fX3dyYXBwZWRfXywgd3JhcHBlci5fX2NoYWluX18sIGFycmF5Q29weSh3cmFwcGVyLl9fYWN0aW9uc19fKSk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cyBzcGxpdCBpbnRvIGdyb3VwcyB0aGUgbGVuZ3RoIG9mIGBzaXplYC5cbiAgICAgKiBJZiBgY29sbGVjdGlvbmAgY2FuJ3QgYmUgc3BsaXQgZXZlbmx5LCB0aGUgZmluYWwgY2h1bmsgd2lsbCBiZSB0aGUgcmVtYWluaW5nXG4gICAgICogZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3NpemU9MV0gVGhlIGxlbmd0aCBvZiBlYWNoIGNodW5rLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IGNvbnRhaW5pbmcgY2h1bmtzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNodW5rKFsnYScsICdiJywgJ2MnLCAnZCddLCAyKTtcbiAgICAgKiAvLyA9PiBbWydhJywgJ2InXSwgWydjJywgJ2QnXV1cbiAgICAgKlxuICAgICAqIF8uY2h1bmsoWydhJywgJ2InLCAnYycsICdkJ10sIDMpO1xuICAgICAqIC8vID0+IFtbJ2EnLCAnYicsICdjJ10sIFsnZCddXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNodW5rKGFycmF5LCBzaXplLCBndWFyZCkge1xuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoYXJyYXksIHNpemUsIGd1YXJkKSA6IHNpemUgPT0gbnVsbCkge1xuICAgICAgICBzaXplID0gMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemUgPSBuYXRpdmVNYXgobmF0aXZlRmxvb3Ioc2l6ZSkgfHwgMSwgMSk7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICByZXNJbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KG5hdGl2ZUNlaWwobGVuZ3RoIC8gc2l6ZSkpO1xuXG4gICAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gYmFzZVNsaWNlKGFycmF5LCBpbmRleCwgKGluZGV4ICs9IHNpemUpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSB3aXRoIGFsbCBmYWxzZXkgdmFsdWVzIHJlbW92ZWQuIFRoZSB2YWx1ZXMgYGZhbHNlYCwgYG51bGxgLFxuICAgICAqIGAwYCwgYFwiXCJgLCBgdW5kZWZpbmVkYCwgYW5kIGBOYU5gIGFyZSBmYWxzZXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY29tcGFjdChbMCwgMSwgZmFsc2UsIDIsICcnLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFjdChhcnJheSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwLFxuICAgICAgICAgIHJlc0luZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB1bmlxdWUgYGFycmF5YCB2YWx1ZXMgbm90IGluY2x1ZGVkIGluIHRoZSBvdGhlclxuICAgICAqIHByb3ZpZGVkIGFycmF5cyB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFt2YWx1ZXNdIFRoZSBhcnJheXMgb2YgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2UoWzEsIDIsIDNdLCBbNCwgMl0pO1xuICAgICAqIC8vID0+IFsxLCAzXVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiAoaXNPYmplY3RMaWtlKGFycmF5KSAmJiBpc0FycmF5TGlrZShhcnJheSkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgZmFsc2UsIHRydWUpKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBiZWdpbm5pbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZHJvcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzNdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSwgMCk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgbiwgZ3VhcmQpIDogbiA9PSBudWxsKSB7XG4gICAgICAgIG4gPSAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgbiA8IDAgPyAwIDogbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBlbmQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZHJvcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wUmlnaHQoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoYXJyYXksIG4sIGd1YXJkKSA6IG4gPT0gbnVsbCkge1xuICAgICAgICBuID0gMTtcbiAgICAgIH1cbiAgICAgIG4gPSBsZW5ndGggLSAoK24gfHwgMCk7XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCAwLCBuIDwgMCA/IDAgOiBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBleGNsdWRpbmcgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBlbmQuXG4gICAgICogRWxlbWVudHMgYXJlIGRyb3BwZWQgdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBtYXRjaCB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKFsxLCAyLCAzXSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gPiAxO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucGx1Y2soXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH0pLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlLCB0aGlzQXJnKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMyksIHRydWUsIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZXhjbHVkaW5nIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqIEVsZW1lbnRzIGFyZSBkcm9wcGVkIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYSB2YWx1ZSBpcyBhbHNvIHByb3ZpZGVkIGZvciBgdGhpc0FyZ2AgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc1Byb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICAgICAqIHZhbHVlLCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRyb3BXaGlsZShbMSwgMiwgM10sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuIDwgMztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8uZHJvcFdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8uZHJvcFdoaWxlKHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucGx1Y2soXy5kcm9wV2hpbGUodXNlcnMsICdhY3RpdmUnKSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3BXaGlsZShhcnJheSwgcHJlZGljYXRlLCB0aGlzQXJnKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMyksIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmlsbHMgZWxlbWVudHMgb2YgYGFycmF5YCB3aXRoIGB2YWx1ZWAgZnJvbSBgc3RhcnRgIHVwIHRvLCBidXQgbm90XG4gICAgICogaW5jbHVkaW5nLCBgZW5kYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmlsbC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBmaWxsIGBhcnJheWAgd2l0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8uZmlsbChhcnJheSwgJ2EnKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWydhJywgJ2EnLCAnYSddXG4gICAgICpcbiAgICAgKiBfLmZpbGwoQXJyYXkoMyksIDIpO1xuICAgICAqIC8vID0+IFsyLCAyLCAyXVxuICAgICAqXG4gICAgICogXy5maWxsKFs0LCA2LCA4XSwgJyonLCAxLCAyKTtcbiAgICAgKiAvLyA9PiBbNCwgJyonLCA4XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0ICYmIHR5cGVvZiBzdGFydCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgdmFsdWUsIHN0YXJ0KSkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIGVuZCA9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlRmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudCBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgaW5zdGVhZCBvZiB0aGUgZWxlbWVudCBpdHNlbGYuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYSB2YWx1ZSBpcyBhbHNvIHByb3ZpZGVkIGZvciBgdGhpc0FyZ2AgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc1Byb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICAgICAqIHZhbHVlLCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBjaHIudXNlciA9PSAnYmFybmV5JztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc2AgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIHsgJ3VzZXInOiAnZnJlZCcsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIHZhciBmaW5kSW5kZXggPSBjcmVhdGVGaW5kSW5kZXgoKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZEluZGV4YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzXG4gICAgICogb2YgYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZvdW5kIGVsZW1lbnQsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maW5kTGFzdEluZGV4KHVzZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBjaHIudXNlciA9PSAncGViYmxlcyc7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsICdhY3RpdmUnLCBmYWxzZSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgdmFyIGZpbmRMYXN0SW5kZXggPSBjcmVhdGVGaW5kSW5kZXgodHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgaGVhZFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZmlyc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZpcnN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5maXJzdChbXSk7XG4gICAgICogLy8gPT4gdW5kZWZpbmVkXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmlyc3QoYXJyYXkpIHtcbiAgICAgIHJldHVybiBhcnJheSA/IGFycmF5WzBdIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZsYXR0ZW5zIGEgbmVzdGVkIGFycmF5LiBJZiBgaXNEZWVwYCBpcyBgdHJ1ZWAgdGhlIGFycmF5IGlzIHJlY3Vyc2l2ZWx5XG4gICAgICogZmxhdHRlbmVkLCBvdGhlcndpc2UgaXQgaXMgb25seSBmbGF0dGVuZWQgYSBzaW5nbGUgbGV2ZWwuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmxhdHRlbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGZsYXR0ZW4uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW4oWzEsIFsyLCAzLCBbNF1dXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIFs0XV1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIGBpc0RlZXBgXG4gICAgICogXy5mbGF0dGVuKFsxLCBbMiwgMywgWzRdXV0sIHRydWUpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXR0ZW4oYXJyYXksIGlzRGVlcCwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoYXJyYXksIGlzRGVlcCwgZ3VhcmQpKSB7XG4gICAgICAgIGlzRGVlcCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VGbGF0dGVuKGFycmF5LCBpc0RlZXApIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmxhdHRlbnMgYSBuZXN0ZWQgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcmVjdXJzaXZlbHkgZmxhdHRlbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbkRlZXAoWzEsIFsyLCAzLCBbNF1dXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbkRlZXAoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZUZsYXR0ZW4oYXJyYXksIHRydWUpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYHZhbHVlYCBpcyBmb3VuZCBpbiBgYXJyYXlgXG4gICAgICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIElmIGBmcm9tSW5kZXhgIGlzIG5lZ2F0aXZlLCBpdCBpcyB1c2VkIGFzIHRoZSBvZmZzZXRcbiAgICAgKiBmcm9tIHRoZSBlbmQgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBzb3J0ZWQgcHJvdmlkaW5nIGB0cnVlYCBmb3IgYGZyb21JbmRleGBcbiAgICAgKiBwZXJmb3JtcyBhIGZhc3RlciBiaW5hcnkgc2VhcmNoLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbnxudW1iZXJ9IFtmcm9tSW5kZXg9MF0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tIG9yIGB0cnVlYFxuICAgICAqICB0byBwZXJmb3JtIGEgYmluYXJ5IHNlYXJjaCBvbiBhIHNvcnRlZCBhcnJheS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluZGV4T2YoWzEsIDIsIDEsIDJdLCAyKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBgZnJvbUluZGV4YFxuICAgICAqIF8uaW5kZXhPZihbMSwgMiwgMSwgMl0sIDIsIDIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIC8vIHBlcmZvcm1pbmcgYSBiaW5hcnkgc2VhcmNoXG4gICAgICogXy5pbmRleE9mKFsxLCAxLCAyLCAyXSwgMiwgdHJ1ZSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIGZyb21JbmRleCA9PSAnbnVtYmVyJykge1xuICAgICAgICBmcm9tSW5kZXggPSBmcm9tSW5kZXggPCAwID8gbmF0aXZlTWF4KGxlbmd0aCArIGZyb21JbmRleCwgMCkgOiBmcm9tSW5kZXg7XG4gICAgICB9IGVsc2UgaWYgKGZyb21JbmRleCkge1xuICAgICAgICB2YXIgaW5kZXggPSBiaW5hcnlJbmRleChhcnJheSwgdmFsdWUpO1xuICAgICAgICBpZiAoaW5kZXggPCBsZW5ndGggJiZcbiAgICAgICAgICAgICh2YWx1ZSA9PT0gdmFsdWUgPyAodmFsdWUgPT09IGFycmF5W2luZGV4XSkgOiAoYXJyYXlbaW5kZXhdICE9PSBhcnJheVtpbmRleF0pKSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXggfHwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgYnV0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5pdGlhbChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRpYWwoYXJyYXkpIHtcbiAgICAgIHJldHVybiBkcm9wUmlnaHQoYXJyYXksIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcyB0aGF0IGFyZSBpbmNsdWRlZCBpbiBhbGwgb2YgdGhlIHByb3ZpZGVkXG4gICAgICogYXJyYXlzIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHNoYXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBfLmludGVyc2VjdGlvbihbMSwgMl0sIFs0LCAyXSwgWzIsIDFdKTtcbiAgICAgKiAvLyA9PiBbMl1cbiAgICAgKi9cbiAgICB2YXIgaW50ZXJzZWN0aW9uID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIG90aExlbmd0aCA9IGFycmF5cy5sZW5ndGgsXG4gICAgICAgICAgb3RoSW5kZXggPSBvdGhMZW5ndGgsXG4gICAgICAgICAgY2FjaGVzID0gQXJyYXkobGVuZ3RoKSxcbiAgICAgICAgICBpbmRleE9mID0gZ2V0SW5kZXhPZigpLFxuICAgICAgICAgIGlzQ29tbW9uID0gaW5kZXhPZiA9PSBiYXNlSW5kZXhPZixcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKG90aEluZGV4LS0pIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlzW290aEluZGV4XSA9IGlzQXJyYXlMaWtlKHZhbHVlID0gYXJyYXlzW290aEluZGV4XSkgPyB2YWx1ZSA6IFtdO1xuICAgICAgICBjYWNoZXNbb3RoSW5kZXhdID0gKGlzQ29tbW9uICYmIHZhbHVlLmxlbmd0aCA+PSAxMjApID8gY3JlYXRlQ2FjaGUob3RoSW5kZXggJiYgdmFsdWUpIDogbnVsbDtcbiAgICAgIH1cbiAgICAgIHZhciBhcnJheSA9IGFycmF5c1swXSxcbiAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICBzZWVuID0gY2FjaGVzWzBdO1xuXG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAoKHNlZW4gPyBjYWNoZUluZGV4T2Yoc2VlbiwgdmFsdWUpIDogaW5kZXhPZihyZXN1bHQsIHZhbHVlLCAwKSkgPCAwKSB7XG4gICAgICAgICAgdmFyIG90aEluZGV4ID0gb3RoTGVuZ3RoO1xuICAgICAgICAgIHdoaWxlICgtLW90aEluZGV4KSB7XG4gICAgICAgICAgICB2YXIgY2FjaGUgPSBjYWNoZXNbb3RoSW5kZXhdO1xuICAgICAgICAgICAgaWYgKChjYWNoZSA/IGNhY2hlSW5kZXhPZihjYWNoZSwgdmFsdWUpIDogaW5kZXhPZihhcnJheXNbb3RoSW5kZXhdLCB2YWx1ZSwgMCkpIDwgMCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNlZW4pIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhc3QoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYXJyYXlbbGVuZ3RoIC0gMV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbmRleE9mYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYGFycmF5YCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtib29sZWFufG51bWJlcn0gW2Zyb21JbmRleD1hcnJheS5sZW5ndGgtMV0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tXG4gICAgICogIG9yIGB0cnVlYCB0byBwZXJmb3JtIGEgYmluYXJ5IHNlYXJjaCBvbiBhIHNvcnRlZCBhcnJheS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAyLCAxLCAyXSwgMik7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgYGZyb21JbmRleGBcbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAyLCAxLCAyXSwgMiwgMik7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogLy8gcGVyZm9ybWluZyBhIGJpbmFyeSBzZWFyY2hcbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAxLCAyLCAyXSwgMiwgdHJ1ZSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgaWYgKHR5cGVvZiBmcm9tSW5kZXggPT0gJ251bWJlcicpIHtcbiAgICAgICAgaW5kZXggPSAoZnJvbUluZGV4IDwgMCA/IG5hdGl2ZU1heChsZW5ndGggKyBmcm9tSW5kZXgsIDApIDogbmF0aXZlTWluKGZyb21JbmRleCB8fCAwLCBsZW5ndGggLSAxKSkgKyAxO1xuICAgICAgfSBlbHNlIGlmIChmcm9tSW5kZXgpIHtcbiAgICAgICAgaW5kZXggPSBiaW5hcnlJbmRleChhcnJheSwgdmFsdWUsIHRydWUpIC0gMTtcbiAgICAgICAgdmFyIG90aGVyID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAodmFsdWUgPT09IHZhbHVlID8gKHZhbHVlID09PSBvdGhlcikgOiAob3RoZXIgIT09IG90aGVyKSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpbmRleE9mTmFOKGFycmF5LCBpbmRleCwgdHJ1ZSk7XG4gICAgICB9XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHByb3ZpZGVkIHZhbHVlcyBmcm9tIGBhcnJheWAgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ud2l0aG91dGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDMsIDEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXy5wdWxsKGFycmF5LCAyLCAzKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbCgpIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgIGFycmF5ID0gYXJnc1swXTtcblxuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgIGluZGV4T2YgPSBnZXRJbmRleE9mKCksXG4gICAgICAgICAgbGVuZ3RoID0gYXJncy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBmcm9tSW5kZXggPSAwLFxuICAgICAgICAgICAgdmFsdWUgPSBhcmdzW2luZGV4XTtcblxuICAgICAgICB3aGlsZSAoKGZyb21JbmRleCA9IGluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpKSA+IC0xKSB7XG4gICAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGZyb21JbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGVsZW1lbnRzIGZyb20gYGFycmF5YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiBpbmRleGVzIGFuZCByZXR1cm5zXG4gICAgICogYW4gYXJyYXkgb2YgdGhlIHJlbW92ZWQgZWxlbWVudHMuIEluZGV4ZXMgbWF5IGJlIHNwZWNpZmllZCBhcyBhbiBhcnJheSBvZlxuICAgICAqIGluZGV4ZXMgb3IgYXMgaW5kaXZpZHVhbCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmF0YCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW10pfSBbaW5kZXhlc10gVGhlIGluZGV4ZXMgb2YgZWxlbWVudHMgdG8gcmVtb3ZlLFxuICAgICAqICBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBpbmRleGVzIG9yIGFycmF5cyBvZiBpbmRleGVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFs1LCAxMCwgMTUsIDIwXTtcbiAgICAgKiB2YXIgZXZlbnMgPSBfLnB1bGxBdChhcnJheSwgMSwgMyk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzUsIDE1XVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coZXZlbnMpO1xuICAgICAqIC8vID0+IFsxMCwgMjBdXG4gICAgICovXG4gICAgdmFyIHB1bGxBdCA9IHJlc3RQYXJhbShmdW5jdGlvbihhcnJheSwgaW5kZXhlcykge1xuICAgICAgaW5kZXhlcyA9IGJhc2VGbGF0dGVuKGluZGV4ZXMpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZUF0KGFycmF5LCBpbmRleGVzKTtcbiAgICAgIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMuc29ydChiYXNlQ29tcGFyZUFzY2VuZGluZykpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGVsZW1lbnRzIGZyb20gYGFycmF5YCB0aGF0IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvclxuICAgICAqIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZSByZW1vdmVkIGVsZW1lbnRzLiBUaGUgcHJlZGljYXRlIGlzIGJvdW5kIHRvXG4gICAgICogYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYSB2YWx1ZSBpcyBhbHNvIHByb3ZpZGVkIGZvciBgdGhpc0FyZ2AgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc1Byb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICAgICAqIHZhbHVlLCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZmlsdGVyYCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDMsIDRdO1xuICAgICAqIHZhciBldmVucyA9IF8ucmVtb3ZlKGFycmF5LCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMSwgM11cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGV2ZW5zKTtcbiAgICAgKiAvLyA9PiBbMiwgNF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZW1vdmUoYXJyYXksIHByZWRpY2F0ZSwgdGhpc0FyZykge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5kZXhlcyA9IFtdLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgcHJlZGljYXRlID0gZ2V0Q2FsbGJhY2socHJlZGljYXRlLCB0aGlzQXJnLCAzKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgICBpbmRleGVzLnB1c2goaW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBiYXNlUHVsbEF0KGFycmF5LCBpbmRleGVzKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgYnV0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgdGFpbFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVzdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlc3QoYXJyYXkpIHtcbiAgICAgIHJldHVybiBkcm9wKGFycmF5LCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBmcm9tIGBzdGFydGAgdXAgdG8sIGJ1dCBub3QgaW5jbHVkaW5nLCBgZW5kYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyB1c2VkIGluc3RlYWQgb2YgYEFycmF5I3NsaWNlYCB0byBzdXBwb3J0IG5vZGVcbiAgICAgKiBsaXN0cyBpbiBJRSA8IDkgYW5kIHRvIGVuc3VyZSBkZW5zZSBhcnJheXMgYXJlIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNsaWNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoZW5kICYmIHR5cGVvZiBlbmQgIT0gJ251bWJlcicgJiYgaXNJdGVyYXRlZUNhbGwoYXJyYXksIHN0YXJ0LCBlbmQpKSB7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgZW5kID0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlcyBhIGJpbmFyeSBzZWFyY2ggdG8gZGV0ZXJtaW5lIHRoZSBsb3dlc3QgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGRcbiAgICAgKiBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuIElmIGFuIGl0ZXJhdGVlXG4gICAgICogZnVuY3Rpb24gaXMgcHJvdmlkZWQgaXQgaXMgaW52b2tlZCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWBcbiAgICAgKiB0byBjb21wdXRlIHRoZWlyIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmRcbiAgICAgKiBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgaXRlcmF0ZWVgIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYSB2YWx1ZSBpcyBhbHNvIHByb3ZpZGVkIGZvciBgdGhpc0FyZ2AgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc1Byb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICAgICAqIHZhbHVlLCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZEluZGV4KFszMCwgNTBdLCA0MCk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleChbNCwgNCwgNSwgNV0sIDUpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIHZhciBkaWN0ID0geyAnZGF0YSc6IHsgJ3RoaXJ0eSc6IDMwLCAnZm9ydHknOiA0MCwgJ2ZpZnR5JzogNTAgfSB9O1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgYW4gaXRlcmF0ZWUgZnVuY3Rpb25cbiAgICAgKiBfLnNvcnRlZEluZGV4KFsndGhpcnR5JywgJ2ZpZnR5J10sICdmb3J0eScsIGZ1bmN0aW9uKHdvcmQpIHtcbiAgICAgKiAgIHJldHVybiB0aGlzLmRhdGFbd29yZF07XG4gICAgICogfSwgZGljdCk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnNvcnRlZEluZGV4KFt7ICd4JzogMzAgfSwgeyAneCc6IDUwIH1dLCB7ICd4JzogNDAgfSwgJ3gnKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgdmFyIHNvcnRlZEluZGV4ID0gY3JlYXRlU29ydGVkSW5kZXgoKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydGVkSW5kZXhgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGhpZ2hlc3RcbiAgICAgKiBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG9cbiAgICAgKiBtYWludGFpbiBpdHMgc29ydCBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXgoWzQsIDQsIDUsIDVdLCA1KTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICovXG4gICAgdmFyIHNvcnRlZExhc3RJbmRleCA9IGNyZWF0ZVNvcnRlZEluZGV4KHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHRha2UuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2UoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoYXJyYXksIG4sIGd1YXJkKSA6IG4gPT0gbnVsbCkge1xuICAgICAgICBuID0gMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIDAsIG4gPCAwID8gMCA6IG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIHRha2VuIGZyb20gdGhlIGVuZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MV0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byB0YWtlLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2VSaWdodChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgbiwgZ3VhcmQpIDogbiA9PSBudWxsKSB7XG4gICAgICAgIG4gPSAxO1xuICAgICAgfVxuICAgICAgbiA9IGxlbmd0aCAtICgrbiB8fCAwKTtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIG4gPCAwID8gMCA6IG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgZW5kLiBFbGVtZW50cyBhcmVcbiAgICAgKiB0YWtlbiB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpcyBib3VuZCB0byBgdGhpc0FyZ2BcbiAgICAgKiBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHRXaGlsZShbMSwgMiwgM10sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuID4gMTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9KSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLnRha2VSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLnRha2VSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlLCB0aGlzQXJnKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMyksIGZhbHNlLCB0cnVlKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgYmVnaW5uaW5nLiBFbGVtZW50c1xuICAgICAqIGFyZSB0YWtlbiB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpcyBib3VuZCB0b1xuICAgICAqIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWtlV2hpbGUoWzEsIDIsIDNdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiA8IDM7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZX0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8udGFrZVdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8udGFrZVdoaWxlKHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8udGFrZVdoaWxlKHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlV2hpbGUoYXJyYXksIHByZWRpY2F0ZSwgdGhpc0FyZykge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRDYWxsYmFjayhwcmVkaWNhdGUsIHRoaXNBcmcsIDMpKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcywgaW4gb3JkZXIsIGZyb20gYWxsIG9mIHRoZSBwcm92aWRlZCBhcnJheXNcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21iaW5lZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pb24oWzEsIDJdLCBbNCwgMl0sIFsyLCAxXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDRdXG4gICAgICovXG4gICAgdmFyIHVuaW9uID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFycmF5cywgZmFsc2UsIHRydWUpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkdXBsaWNhdGUtZnJlZSB2ZXJzaW9uIG9mIGFuIGFycmF5LCB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLCBpbiB3aGljaCBvbmx5IHRoZSBmaXJzdCBvY2N1cmVuY2Ugb2YgZWFjaCBlbGVtZW50XG4gICAgICogaXMga2VwdC4gUHJvdmlkaW5nIGB0cnVlYCBmb3IgYGlzU29ydGVkYCBwZXJmb3JtcyBhIGZhc3RlciBzZWFyY2ggYWxnb3JpdGhtXG4gICAgICogZm9yIHNvcnRlZCBhcnJheXMuIElmIGFuIGl0ZXJhdGVlIGZ1bmN0aW9uIGlzIHByb3ZpZGVkIGl0IGlzIGludm9rZWQgZm9yXG4gICAgICogZWFjaCBlbGVtZW50IGluIHRoZSBhcnJheSB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5IHdoaWNoIHVuaXF1ZW5lc3NcbiAgICAgKiBpcyBjb21wdXRlZC4gVGhlIGBpdGVyYXRlZWAgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgaXRlcmF0ZWVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyB1bmlxdWVcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1NvcnRlZF0gU3BlY2lmeSB0aGUgYXJyYXkgaXMgc29ydGVkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlXSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZS12YWx1ZS1mcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXEoWzIsIDEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIGBpc1NvcnRlZGBcbiAgICAgKiBfLnVuaXEoWzEsIDEsIDJdLCB0cnVlKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIGFuIGl0ZXJhdGVlIGZ1bmN0aW9uXG4gICAgICogXy51bmlxKFsxLCAyLjUsIDEuNSwgMl0sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiB0aGlzLmZsb29yKG4pO1xuICAgICAqIH0sIE1hdGgpO1xuICAgICAqIC8vID0+IFsxLCAyLjVdXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8udW5pcShbeyAneCc6IDEgfSwgeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcShhcnJheSwgaXNTb3J0ZWQsIGl0ZXJhdGVlLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGlzU29ydGVkICE9IG51bGwgJiYgdHlwZW9mIGlzU29ydGVkICE9ICdib29sZWFuJykge1xuICAgICAgICB0aGlzQXJnID0gaXRlcmF0ZWU7XG4gICAgICAgIGl0ZXJhdGVlID0gaXNJdGVyYXRlZUNhbGwoYXJyYXksIGlzU29ydGVkLCB0aGlzQXJnKSA/IHVuZGVmaW5lZCA6IGlzU29ydGVkO1xuICAgICAgICBpc1NvcnRlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGNhbGxiYWNrID0gZ2V0Q2FsbGJhY2soKTtcbiAgICAgIGlmICghKGl0ZXJhdGVlID09IG51bGwgJiYgY2FsbGJhY2sgPT09IGJhc2VDYWxsYmFjaykpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSBjYWxsYmFjayhpdGVyYXRlZSwgdGhpc0FyZywgMyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKGlzU29ydGVkICYmIGdldEluZGV4T2YoKSA9PSBiYXNlSW5kZXhPZilcbiAgICAgICAgPyBzb3J0ZWRVbmlxKGFycmF5LCBpdGVyYXRlZSlcbiAgICAgICAgOiBiYXNlVW5pcShhcnJheSwgaXRlcmF0ZWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGFuIGFycmF5IG9mIGdyb3VwZWRcbiAgICAgKiBlbGVtZW50cyBhbmQgY3JlYXRlcyBhbiBhcnJheSByZWdyb3VwaW5nIHRoZSBlbGVtZW50cyB0byB0aGVpciBwcmUtemlwXG4gICAgICogY29uZmlndXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgemlwcGVkID0gXy56aXAoWydmcmVkJywgJ2Jhcm5leSddLCBbMzAsIDQwXSwgW3RydWUsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gW1snZnJlZCcsIDMwLCB0cnVlXSwgWydiYXJuZXknLCA0MCwgZmFsc2VdXVxuICAgICAqXG4gICAgICogXy51bnppcCh6aXBwZWQpO1xuICAgICAqIC8vID0+IFtbJ2ZyZWQnLCAnYmFybmV5J10sIFszMCwgNDBdLCBbdHJ1ZSwgZmFsc2VdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuemlwKGFycmF5KSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IDA7XG5cbiAgICAgIGFycmF5ID0gYXJyYXlGaWx0ZXIoYXJyYXksIGZ1bmN0aW9uKGdyb3VwKSB7XG4gICAgICAgIGlmIChpc0FycmF5TGlrZShncm91cCkpIHtcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgoZ3JvdXAubGVuZ3RoLCBsZW5ndGgpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHZhciByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGFycmF5TWFwKGFycmF5LCBiYXNlUHJvcGVydHkoaW5kZXgpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bnppcGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhbiBpdGVyYXRlZSB0byBzcGVjaWZ5XG4gICAgICogaG93IHJlZ3JvdXBlZCB2YWx1ZXMgc2hvdWxkIGJlIGNvbWJpbmVkLiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2BcbiAgICAgKiBhbmQgaW52b2tlZCB3aXRoIGZvdXIgYXJndW1lbnRzOiAoYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgZ3JvdXApLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBmdW5jdGlvbiB0byBjb21iaW5lIHJlZ3JvdXBlZCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgemlwcGVkID0gXy56aXAoWzEsIDJdLCBbMTAsIDIwXSwgWzEwMCwgMjAwXSk7XG4gICAgICogLy8gPT4gW1sxLCAxMCwgMTAwXSwgWzIsIDIwLCAyMDBdXVxuICAgICAqXG4gICAgICogXy51bnppcFdpdGgoemlwcGVkLCBfLmFkZCk7XG4gICAgICogLy8gPT4gWzMsIDMwLCAzMDBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW56aXBXaXRoKGFycmF5LCBpdGVyYXRlZSwgdGhpc0FyZykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSB1bnppcChhcnJheSk7XG4gICAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaXRlcmF0ZWUgPSBiaW5kQ2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDQpO1xuICAgICAgcmV0dXJuIGFycmF5TWFwKHJlc3VsdCwgZnVuY3Rpb24oZ3JvdXApIHtcbiAgICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKGdyb3VwLCBpdGVyYXRlZSwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgZXhjbHVkaW5nIGFsbCBwcm92aWRlZCB2YWx1ZXMgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWx0ZXIuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndpdGhvdXQoWzEsIDIsIDEsIDNdLCAxLCAyKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKi9cbiAgICB2YXIgd2l0aG91dCA9IHJlc3RQYXJhbShmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2UoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIHZhbHVlcylcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcyB0aGF0IGlzIHRoZSBbc3ltbWV0cmljIGRpZmZlcmVuY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1N5bW1ldHJpY19kaWZmZXJlbmNlKVxuICAgICAqIG9mIHRoZSBwcm92aWRlZCBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnhvcihbMSwgMl0sIFs0LCAyXSk7XG4gICAgICogLy8gPT4gWzEsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24geG9yKCkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgICAgaWYgKGlzQXJyYXlMaWtlKGFycmF5KSkge1xuICAgICAgICAgIHZhciByZXN1bHQgPSByZXN1bHRcbiAgICAgICAgICAgID8gYXJyYXlQdXNoKGJhc2VEaWZmZXJlbmNlKHJlc3VsdCwgYXJyYXkpLCBiYXNlRGlmZmVyZW5jZShhcnJheSwgcmVzdWx0KSlcbiAgICAgICAgICAgIDogYXJyYXk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQgPyBiYXNlVW5pcShyZXN1bHQpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLCB0aGUgZmlyc3Qgb2Ygd2hpY2ggY29udGFpbnMgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgdGhlIHNlY29uZCBvZiB3aGljaCBjb250YWlucyB0aGUgc2Vjb25kIGVsZW1lbnRzXG4gICAgICogb2YgdGhlIGdpdmVuIGFycmF5cywgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwKFsnZnJlZCcsICdiYXJuZXknXSwgWzMwLCA0MF0sIFt0cnVlLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IFtbJ2ZyZWQnLCAzMCwgdHJ1ZV0sIFsnYmFybmV5JywgNDAsIGZhbHNlXV1cbiAgICAgKi9cbiAgICB2YXIgemlwID0gcmVzdFBhcmFtKHVuemlwKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnZlcnNlIG9mIGBfLnBhaXJzYDsgdGhpcyBtZXRob2QgcmV0dXJucyBhbiBvYmplY3QgY29tcG9zZWQgZnJvbSBhcnJheXNcbiAgICAgKiBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgdmFsdWVzLiBQcm92aWRlIGVpdGhlciBhIHNpbmdsZSB0d28gZGltZW5zaW9uYWwgYXJyYXksXG4gICAgICogZS5nLiBgW1trZXkxLCB2YWx1ZTFdLCBba2V5MiwgdmFsdWUyXV1gIG9yIHR3byBhcnJheXMsIG9uZSBvZiBwcm9wZXJ0eSBuYW1lc1xuICAgICAqIGFuZCBvbmUgb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgb2JqZWN0XG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXM9W11dIFRoZSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy56aXBPYmplY3QoW1snZnJlZCcsIDMwXSwgWydiYXJuZXknLCA0MF1dKTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogMzAsICdiYXJuZXknOiA0MCB9XG4gICAgICpcbiAgICAgKiBfLnppcE9iamVjdChbJ2ZyZWQnLCAnYmFybmV5J10sIFszMCwgNDBdKTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogMzAsICdiYXJuZXknOiA0MCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gemlwT2JqZWN0KHByb3BzLCB2YWx1ZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzID8gcHJvcHMubGVuZ3RoIDogMCxcbiAgICAgICAgICByZXN1bHQgPSB7fTtcblxuICAgICAgaWYgKGxlbmd0aCAmJiAhdmFsdWVzICYmICFpc0FycmF5KHByb3BzWzBdKSkge1xuICAgICAgICB2YWx1ZXMgPSBbXTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIGlmICh2YWx1ZXMpIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlc1tpbmRleF07XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5KSB7XG4gICAgICAgICAgcmVzdWx0W2tleVswXV0gPSBrZXlbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYW4gaXRlcmF0ZWUgdG8gc3BlY2lmeVxuICAgICAqIGhvdyBncm91cGVkIHZhbHVlcyBzaG91bGQgYmUgY29tYmluZWQuIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYFxuICAgICAqIGFuZCBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6IChhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBncm91cCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgZnVuY3Rpb24gdG8gY29tYmluZSBncm91cGVkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcFdpdGgoWzEsIDJdLCBbMTAsIDIwXSwgWzEwMCwgMjAwXSwgXy5hZGQpO1xuICAgICAqIC8vID0+IFsxMTEsIDIyMl1cbiAgICAgKi9cbiAgICB2YXIgemlwV2l0aCA9IHJlc3RQYXJhbShmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheXMubGVuZ3RoLFxuICAgICAgICAgIGl0ZXJhdGVlID0gbGVuZ3RoID4gMiA/IGFycmF5c1tsZW5ndGggLSAyXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICB0aGlzQXJnID0gbGVuZ3RoID4gMSA/IGFycmF5c1tsZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKGxlbmd0aCA+IDIgJiYgdHlwZW9mIGl0ZXJhdGVlID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgbGVuZ3RoIC09IDI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpdGVyYXRlZSA9IChsZW5ndGggPiAxICYmIHR5cGVvZiB0aGlzQXJnID09ICdmdW5jdGlvbicpID8gKC0tbGVuZ3RoLCB0aGlzQXJnKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpc0FyZyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGFycmF5cy5sZW5ndGggPSBsZW5ndGg7XG4gICAgICByZXR1cm4gdW56aXBXaXRoKGFycmF5cywgaXRlcmF0ZWUsIHRoaXNBcmcpO1xuICAgIH0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIG9iamVjdCB0aGF0IHdyYXBzIGB2YWx1ZWAgd2l0aCBleHBsaWNpdCBtZXRob2RcbiAgICAgKiBjaGFpbmluZyBlbmFibGVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENoYWluXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogdmFyIHlvdW5nZXN0ID0gXy5jaGFpbih1c2VycylcbiAgICAgKiAgIC5zb3J0QnkoJ2FnZScpXG4gICAgICogICAubWFwKGZ1bmN0aW9uKGNocikge1xuICAgICAqICAgICByZXR1cm4gY2hyLnVzZXIgKyAnIGlzICcgKyBjaHIuYWdlO1xuICAgICAqICAgfSlcbiAgICAgKiAgIC5maXJzdCgpXG4gICAgICogICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiAncGViYmxlcyBpcyAxJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNoYWluKHZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoKHZhbHVlKTtcbiAgICAgIHJlc3VsdC5fX2NoYWluX18gPSB0cnVlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpbnZva2VzIGBpbnRlcmNlcHRvcmAgYW5kIHJldHVybnMgYHZhbHVlYC4gVGhlIGludGVyY2VwdG9yIGlzXG4gICAgICogYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLiBUaGUgcHVycG9zZSBvZlxuICAgICAqIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiBpbiBvcmRlciB0byBwZXJmb3JtIG9wZXJhdGlvbnNcbiAgICAgKiBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW4gdGhlIGNoYWluLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENoYWluXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvdmlkZSB0byBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGludGVyY2VwdG9yIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgYHZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pXG4gICAgICogIC50YXAoZnVuY3Rpb24oYXJyYXkpIHtcbiAgICAgKiAgICBhcnJheS5wb3AoKTtcbiAgICAgKiAgfSlcbiAgICAgKiAgLnJldmVyc2UoKVxuICAgICAqICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YXAodmFsdWUsIGludGVyY2VwdG9yLCB0aGlzQXJnKSB7XG4gICAgICBpbnRlcmNlcHRvci5jYWxsKHRoaXNBcmcsIHZhbHVlKTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnRhcGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgcmVzdWx0IG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm92aWRlIHRvIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW50ZXJjZXB0b3IgVGhlIGZ1bmN0aW9uIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGludGVyY2VwdG9yYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oJyAgYWJjICAnKVxuICAgICAqICAuY2hhaW4oKVxuICAgICAqICAudHJpbSgpXG4gICAgICogIC50aHJ1KGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICAgcmV0dXJuIFt2YWx1ZV07XG4gICAgICogIH0pXG4gICAgICogIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsnYWJjJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aHJ1KHZhbHVlLCBpbnRlcmNlcHRvciwgdGhpc0FyZykge1xuICAgICAgcmV0dXJuIGludGVyY2VwdG9yLmNhbGwodGhpc0FyZywgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMgZXhwbGljaXQgbWV0aG9kIGNoYWluaW5nIG9uIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNoYWluXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gd2l0aG91dCBleHBsaWNpdCBjaGFpbmluZ1xuICAgICAqIF8odXNlcnMpLmZpcnN0KCk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfVxuICAgICAqXG4gICAgICogLy8gd2l0aCBleHBsaWNpdCBjaGFpbmluZ1xuICAgICAqIF8odXNlcnMpLmNoYWluKClcbiAgICAgKiAgIC5maXJzdCgpXG4gICAgICogICAucGljaygndXNlcicpXG4gICAgICogICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDaGFpbigpIHtcbiAgICAgIHJldHVybiBjaGFpbih0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyB0aGUgY2hhaW5lZCBzZXF1ZW5jZSBhbmQgcmV0dXJucyB0aGUgd3JhcHBlZCByZXN1bHQuXG4gICAgICpcbiAgICAgKiBAbmFtZSBjb21taXRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDaGFpblxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMl07XG4gICAgICogdmFyIHdyYXBwZWQgPSBfKGFycmF5KS5wdXNoKDMpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogd3JhcHBlZCA9IHdyYXBwZWQuY29tbWl0KCk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogd3JhcHBlZC5sYXN0KCk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDb21taXQoKSB7XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodGhpcy52YWx1ZSgpLCB0aGlzLl9fY2hhaW5fXyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBhcnJheSBqb2luaW5nIGEgd3JhcHBlZCBhcnJheSB3aXRoIGFueSBhZGRpdGlvbmFsIGFycmF5c1xuICAgICAqIGFuZC9vciB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAbmFtZSBjb25jYXRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDaGFpblxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjb25jYXRlbmF0ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBjb25jYXRlbmF0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxXTtcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oYXJyYXkpLmNvbmNhdCgyLCBbM10sIFtbNF1dKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKHdyYXBwZWQudmFsdWUoKSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIFs0XV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKi9cbiAgICB2YXIgd3JhcHBlckNvbmNhdCA9IHJlc3RQYXJhbShmdW5jdGlvbih2YWx1ZXMpIHtcbiAgICAgIHZhbHVlcyA9IGJhc2VGbGF0dGVuKHZhbHVlcyk7XG4gICAgICByZXR1cm4gdGhpcy50aHJ1KGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICAgIHJldHVybiBhcnJheUNvbmNhdChpc0FycmF5KGFycmF5KSA/IGFycmF5IDogW3RvT2JqZWN0KGFycmF5KV0sIHZhbHVlcyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgY2hhaW5lZCBzZXF1ZW5jZSBwbGFudGluZyBgdmFsdWVgIGFzIHRoZSB3cmFwcGVkIHZhbHVlLlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhbnRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDaGFpblxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMl07XG4gICAgICogdmFyIHdyYXBwZWQgPSBfKGFycmF5KS5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiBNYXRoLnBvdyh2YWx1ZSwgMik7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiB2YXIgb3RoZXIgPSBbMywgNF07XG4gICAgICogdmFyIG90aGVyV3JhcHBlZCA9IHdyYXBwZWQucGxhbnQob3RoZXIpO1xuICAgICAqXG4gICAgICogb3RoZXJXcmFwcGVkLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzksIDE2XVxuICAgICAqXG4gICAgICogd3JhcHBlZC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsxLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJQbGFudCh2YWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCxcbiAgICAgICAgICBwYXJlbnQgPSB0aGlzO1xuXG4gICAgICB3aGlsZSAocGFyZW50IGluc3RhbmNlb2YgYmFzZUxvZGFzaCkge1xuICAgICAgICB2YXIgY2xvbmUgPSB3cmFwcGVyQ2xvbmUocGFyZW50KTtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gY2xvbmU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xvbmU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXZpb3VzID0gY2xvbmU7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5fX3dyYXBwZWRfXztcbiAgICAgIH1cbiAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldmVyc2VzIHRoZSB3cmFwcGVkIGFycmF5IHNvIHRoZSBmaXJzdCBlbGVtZW50IGJlY29tZXMgdGhlIGxhc3QsIHRoZVxuICAgICAqIHNlY29uZCBlbGVtZW50IGJlY29tZXMgdGhlIHNlY29uZCB0byBsYXN0LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyB0aGUgd3JhcHBlZCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHJldmVyc2VcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDaGFpblxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyByZXZlcnNlZCBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICpcbiAgICAgKiBfKGFycmF5KS5yZXZlcnNlKCkudmFsdWUoKVxuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJSZXZlcnNlKCkge1xuICAgICAgdmFyIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXztcblxuICAgICAgdmFyIGludGVyY2VwdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuICh3cmFwcGVkICYmIHdyYXBwZWQuX19kaXJfXyA8IDApID8gdmFsdWUgOiB2YWx1ZS5yZXZlcnNlKCk7XG4gICAgICB9O1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpIHtcbiAgICAgICAgdmFyIHdyYXBwZWQgPSB2YWx1ZTtcbiAgICAgICAgaWYgKHRoaXMuX19hY3Rpb25zX18ubGVuZ3RoKSB7XG4gICAgICAgICAgd3JhcHBlZCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICB3cmFwcGVkID0gd3JhcHBlZC5yZXZlcnNlKCk7XG4gICAgICAgIHdyYXBwZWQuX19hY3Rpb25zX18ucHVzaCh7ICdmdW5jJzogdGhydSwgJ2FyZ3MnOiBbaW50ZXJjZXB0b3JdLCAndGhpc0FyZyc6IHVuZGVmaW5lZCB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHdyYXBwZWQsIHRoaXMuX19jaGFpbl9fKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnRocnUoaW50ZXJjZXB0b3IpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2R1Y2VzIHRoZSByZXN1bHQgb2YgY29lcmNpbmcgdGhlIHVud3JhcHBlZCB2YWx1ZSB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb2VyY2VkIHN0cmluZyB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pLnRvU3RyaW5nKCk7XG4gICAgICogLy8gPT4gJzEsMiwzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJUb1N0cmluZygpIHtcbiAgICAgIHJldHVybiAodGhpcy52YWx1ZSgpICsgJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVzIHRoZSBjaGFpbmVkIHNlcXVlbmNlIHRvIGV4dHJhY3QgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHZhbHVlXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgcnVuLCB0b0pTT04sIHZhbHVlT2ZcbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKFsxLCAyLCAzXSkudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyVmFsdWUoKSB7XG4gICAgICByZXR1cm4gYmFzZVdyYXBwZXJWYWx1ZSh0aGlzLl9fd3JhcHBlZF9fLCB0aGlzLl9fYWN0aW9uc19fKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIGtleXMsIG9yIGluZGV4ZXMsXG4gICAgICogb2YgYGNvbGxlY3Rpb25gLiBLZXlzIG1heSBiZSBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBhcmd1bWVudHMgb3IgYXMgYXJyYXlzXG4gICAgICogb2Yga2V5cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW118c3RyaW5nfHN0cmluZ1tdKX0gW3Byb3BzXSBUaGUgcHJvcGVydHkgbmFtZXNcbiAgICAgKiAgb3IgaW5kZXhlcyBvZiBlbGVtZW50cyB0byBwaWNrLCBzcGVjaWZpZWQgaW5kaXZpZHVhbGx5IG9yIGluIGFycmF5cy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwaWNrZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYXQoWydhJywgJ2InLCAnYyddLCBbMCwgMl0pO1xuICAgICAqIC8vID0+IFsnYScsICdjJ11cbiAgICAgKlxuICAgICAqIF8uYXQoWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ10sIDAsIDIpO1xuICAgICAqIC8vID0+IFsnYmFybmV5JywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIHZhciBhdCA9IHJlc3RQYXJhbShmdW5jdGlvbihjb2xsZWN0aW9uLCBwcm9wcykge1xuICAgICAgcmV0dXJuIGJhc2VBdChjb2xsZWN0aW9uLCBiYXNlRmxhdHRlbihwcm9wcykpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlXG4gICAgICogb2YgZWFjaCBrZXkgaXMgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUga2V5IHdhcyByZXR1cm5lZCBieSBgaXRlcmF0ZWVgLlxuICAgICAqIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNvdW50QnkoWzQuMywgNi4xLCA2LjRdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gTWF0aC5mbG9vcihuKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICc0JzogMSwgJzYnOiAyIH1cbiAgICAgKlxuICAgICAqIF8uY291bnRCeShbNC4zLCA2LjEsIDYuNF0sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiB0aGlzLmZsb29yKG4pO1xuICAgICAqIH0sIE1hdGgpO1xuICAgICAqIC8vID0+IHsgJzQnOiAxLCAnNic6IDIgfVxuICAgICAqXG4gICAgICogXy5jb3VudEJ5KFsnb25lJywgJ3R3bycsICd0aHJlZSddLCAnbGVuZ3RoJyk7XG4gICAgICogLy8gPT4geyAnMyc6IDIsICc1JzogMSB9XG4gICAgICovXG4gICAgdmFyIGNvdW50QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIGtleSkgPyArK3Jlc3VsdFtrZXldIDogKHJlc3VsdFtrZXldID0gMSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yICoqYWxsKiogZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqIFRoZSBwcmVkaWNhdGUgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGFsbFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFsbCBlbGVtZW50cyBwYXNzIHRoZSBwcmVkaWNhdGUgY2hlY2ssXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ldmVyeShbdHJ1ZSwgMSwgbnVsbCwgJ3llcyddLCBCb29sZWFuKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZXZlcnkodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmV2ZXJ5KHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5ldmVyeSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXZlcnkoY29sbGVjdGlvbiwgcHJlZGljYXRlLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUV2ZXJ5IDogYmFzZUV2ZXJ5O1xuICAgICAgaWYgKHRoaXNBcmcgJiYgaXNJdGVyYXRlZUNhbGwoY29sbGVjdGlvbiwgcHJlZGljYXRlLCB0aGlzQXJnKSkge1xuICAgICAgICBwcmVkaWNhdGUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHByZWRpY2F0ZSAhPSAnZnVuY3Rpb24nIHx8IHRoaXNBcmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwcmVkaWNhdGUgPSBnZXRDYWxsYmFjayhwcmVkaWNhdGUsIHRoaXNBcmcsIDMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgcHJlZGljYXRlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGFsbCBlbGVtZW50c1xuICAgICAqIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgc2VsZWN0XG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgcHJlZGljYXRlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5maWx0ZXIoWzQsIDUsIDZdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbNCwgNl1cbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8uZmlsdGVyKHVzZXJzLCB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLmZpbHRlcih1c2VycywgJ2FjdGl2ZScsIGZhbHNlKSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8uZmlsdGVyKHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbHRlcihjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHByZWRpY2F0ZSA9IGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMyk7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBwcmVkaWNhdGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLCByZXR1cm5pbmcgdGhlIGZpcnN0IGVsZW1lbnRcbiAgICAgKiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZFxuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGRldGVjdFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChfLmZpbmQodXNlcnMsIGZ1bmN0aW9uKGNocikge1xuICAgICAqICAgcmV0dXJuIGNoci5hZ2UgPCA0MDtcbiAgICAgKiB9KSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiAnYmFybmV5J1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucmVzdWx0KF8uZmluZCh1c2VycywgeyAnYWdlJzogMSwgJ2FjdGl2ZSc6IHRydWUgfSksICd1c2VyJyk7XG4gICAgICogLy8gPT4gJ3BlYmJsZXMnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnJlc3VsdChfLmZpbmQodXNlcnMsICdhY3RpdmUnLCBmYWxzZSksICd1c2VyJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucmVzdWx0KF8uZmluZCh1c2VycywgJ2FjdGl2ZScpLCAndXNlcicpO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICovXG4gICAgdmFyIGZpbmQgPSBjcmVhdGVGaW5kKGJhc2VFYWNoKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtYXRjaGVkIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3QoWzEsIDIsIDMsIDRdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgdmFyIGZpbmRMYXN0ID0gY3JlYXRlRmluZChiYXNlRWFjaFJpZ2h0LCB0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYCBhbmQgdGhlXG4gICAgICogc291cmNlIG9iamVjdCwgcmV0dXJuaW5nIHRoZSBmaXJzdCBlbGVtZW50IHRoYXQgaGFzIGVxdWl2YWxlbnQgcHJvcGVydHlcbiAgICAgKiB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2Qgc3VwcG9ydHMgY29tcGFyaW5nIGFycmF5cywgYm9vbGVhbnMsIGBEYXRlYCBvYmplY3RzLFxuICAgICAqIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsIGFuZCBzdHJpbmdzLiBPYmplY3RzIGFyZSBjb21wYXJlZCBieVxuICAgICAqIHRoZWlyIG93biwgbm90IGluaGVyaXRlZCwgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLiBGb3IgY29tcGFyaW5nIGEgc2luZ2xlXG4gICAgICogb3duIG9yIGluaGVyaXRlZCBwcm9wZXJ0eSB2YWx1ZSBzZWUgYF8ubWF0Y2hlc1Byb3BlcnR5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtYXRjaGVkIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KF8uZmluZFdoZXJlKHVzZXJzLCB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSksICd1c2VyJyk7XG4gICAgICogLy8gPT4gJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KF8uZmluZFdoZXJlKHVzZXJzLCB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0pLCAndXNlcicpO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRXaGVyZShjb2xsZWN0aW9uLCBzb3VyY2UpIHtcbiAgICAgIHJldHVybiBmaW5kKGNvbGxlY3Rpb24sIGJhc2VNYXRjaGVzKHNvdXJjZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gIGludm9raW5nIGBpdGVyYXRlZWAgZm9yIGVhY2ggZWxlbWVudC5cbiAgICAgKiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6XG4gICAgICogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5XG4gICAgICogYnkgZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBBcyB3aXRoIG90aGVyIFwiQ29sbGVjdGlvbnNcIiBtZXRob2RzLCBvYmplY3RzIHdpdGggYSBcImxlbmd0aFwiIHByb3BlcnR5XG4gICAgICogYXJlIGl0ZXJhdGVkIGxpa2UgYXJyYXlzLiBUbyBhdm9pZCB0aGlzIGJlaGF2aW9yIGBfLmZvckluYCBvciBgXy5mb3JPd25gXG4gICAgICogbWF5IGJlIHVzZWQgZm9yIG9iamVjdCBpdGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgZWFjaFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fHN0cmluZ30gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDJdKS5mb3JFYWNoKGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKG4pO1xuICAgICAqIH0pLnZhbHVlKCk7XG4gICAgICogLy8gPT4gbG9ncyBlYWNoIHZhbHVlIGZyb20gbGVmdCB0byByaWdodCBhbmQgcmV0dXJucyB0aGUgYXJyYXlcbiAgICAgKlxuICAgICAqIF8uZm9yRWFjaCh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKG4sIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2cobiwga2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzIGVhY2ggdmFsdWUta2V5IHBhaXIgYW5kIHJldHVybnMgdGhlIG9iamVjdCAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIHZhciBmb3JFYWNoID0gY3JlYXRlRm9yRWFjaChhcnJheUVhY2gsIGJhc2VFYWNoKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9yRWFjaGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgZWFjaFJpZ2h0XG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R8c3RyaW5nfSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMl0pLmZvckVhY2hSaWdodChmdW5jdGlvbihuKSB7XG4gICAgICogICBjb25zb2xlLmxvZyhuKTtcbiAgICAgKiB9KS52YWx1ZSgpO1xuICAgICAqIC8vID0+IGxvZ3MgZWFjaCB2YWx1ZSBmcm9tIHJpZ2h0IHRvIGxlZnQgYW5kIHJldHVybnMgdGhlIGFycmF5XG4gICAgICovXG4gICAgdmFyIGZvckVhY2hSaWdodCA9IGNyZWF0ZUZvckVhY2goYXJyYXlFYWNoUmlnaHQsIGJhc2VFYWNoUmlnaHQpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlXG4gICAgICogb2YgZWFjaCBrZXkgaXMgYW4gYXJyYXkgb2YgdGhlIGVsZW1lbnRzIHJlc3BvbnNpYmxlIGZvciBnZW5lcmF0aW5nIHRoZSBrZXkuXG4gICAgICogVGhlIGBpdGVyYXRlZWAgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgaXRlcmF0ZWVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbXBvc2VkIGFnZ3JlZ2F0ZSBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3JvdXBCeShbNC4yLCA2LjEsIDYuNF0sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBNYXRoLmZsb29yKG4pO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IHsgJzQnOiBbNC4yXSwgJzYnOiBbNi4xLCA2LjRdIH1cbiAgICAgKlxuICAgICAqIF8uZ3JvdXBCeShbNC4yLCA2LjEsIDYuNF0sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiB0aGlzLmZsb29yKG4pO1xuICAgICAqIH0sIE1hdGgpO1xuICAgICAqIC8vID0+IHsgJzQnOiBbNC4yXSwgJzYnOiBbNi4xLCA2LjRdIH1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5ncm91cEJ5KFsnb25lJywgJ3R3bycsICd0aHJlZSddLCAnbGVuZ3RoJyk7XG4gICAgICogLy8gPT4geyAnMyc6IFsnb25lJywgJ3R3byddLCAnNSc6IFsndGhyZWUnXSB9XG4gICAgICovXG4gICAgdmFyIGdyb3VwQnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCBrZXkpKSB7XG4gICAgICAgIHJlc3VsdFtrZXldLnB1c2godmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBbdmFsdWVdO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gYGNvbGxlY3Rpb25gIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIElmIGBmcm9tSW5kZXhgIGlzIG5lZ2F0aXZlLCBpdCBpcyB1c2VkIGFzIHRoZSBvZmZzZXRcbiAgICAgKiBmcm9tIHRoZSBlbmQgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGNvbnRhaW5zLCBpbmNsdWRlXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0gdGFyZ2V0IFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYSBtYXRjaGluZyBlbGVtZW50IGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoWzEsIDIsIDNdLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKFsxLCAyLCAzXSwgMSwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoeyAndXNlcic6ICdmcmVkJywgJ2FnZSc6IDQwIH0sICdmcmVkJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pbmNsdWRlcygncGViYmxlcycsICdlYicpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmNsdWRlcyhjb2xsZWN0aW9uLCB0YXJnZXQsIGZyb21JbmRleCwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uID8gZ2V0TGVuZ3RoKGNvbGxlY3Rpb24pIDogMDtcbiAgICAgIGlmICghaXNMZW5ndGgobGVuZ3RoKSkge1xuICAgICAgICBjb2xsZWN0aW9uID0gdmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgZnJvbUluZGV4ICE9ICdudW1iZXInIHx8IChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbCh0YXJnZXQsIGZyb21JbmRleCwgZ3VhcmQpKSkge1xuICAgICAgICBmcm9tSW5kZXggPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnJvbUluZGV4ID0gZnJvbUluZGV4IDwgMCA/IG5hdGl2ZU1heChsZW5ndGggKyBmcm9tSW5kZXgsIDApIDogKGZyb21JbmRleCB8fCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAodHlwZW9mIGNvbGxlY3Rpb24gPT0gJ3N0cmluZycgfHwgIWlzQXJyYXkoY29sbGVjdGlvbikgJiYgaXNTdHJpbmcoY29sbGVjdGlvbikpXG4gICAgICAgID8gKGZyb21JbmRleCA8PSBsZW5ndGggJiYgY29sbGVjdGlvbi5pbmRleE9mKHRhcmdldCwgZnJvbUluZGV4KSA+IC0xKVxuICAgICAgICA6ICghIWxlbmd0aCAmJiBnZXRJbmRleE9mKGNvbGxlY3Rpb24sIHRhcmdldCwgZnJvbUluZGV4KSA+IC0xKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiBrZXlzIGdlbmVyYXRlZCBmcm9tIHRoZSByZXN1bHRzIG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIHRocm91Z2ggYGl0ZXJhdGVlYC4gVGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVcbiAgICAgKiBvZiBlYWNoIGtleSBpcyB0aGUgbGFzdCBlbGVtZW50IHJlc3BvbnNpYmxlIGZvciBnZW5lcmF0aW5nIHRoZSBrZXkuIFRoZVxuICAgICAqIGl0ZXJhdGVlIGZ1bmN0aW9uIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIga2V5RGF0YSA9IFtcbiAgICAgKiAgIHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LFxuICAgICAqICAgeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmluZGV4Qnkoa2V5RGF0YSwgJ2RpcicpO1xuICAgICAqIC8vID0+IHsgJ2xlZnQnOiB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSwgJ3JpZ2h0JzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICpcbiAgICAgKiBfLmluZGV4Qnkoa2V5RGF0YSwgZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICogICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShvYmplY3QuY29kZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnYSc6IHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LCAnZCc6IHsgJ2Rpcic6ICdyaWdodCcsICdjb2RlJzogMTAwIH0gfVxuICAgICAqXG4gICAgICogXy5pbmRleEJ5KGtleURhdGEsIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAqICAgcmV0dXJuIHRoaXMuZnJvbUNoYXJDb2RlKG9iamVjdC5jb2RlKTtcbiAgICAgKiB9LCBTdHJpbmcpO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSwgJ2QnOiB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9IH1cbiAgICAgKi9cbiAgICB2YXIgaW5kZXhCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gLCByZXR1cm5pbmdcbiAgICAgKiBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZiBlYWNoIGludm9rZWQgbWV0aG9kLiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICAgKiBhcmUgcHJvdmlkZWQgdG8gZWFjaCBpbnZva2VkIG1ldGhvZC4gSWYgYG1ldGhvZE5hbWVgIGlzIGEgZnVuY3Rpb24gaXQgaXNcbiAgICAgKiBpbnZva2VkIGZvciwgYW5kIGB0aGlzYCBib3VuZCB0bywgZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fEZ1bmN0aW9ufHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZSBvclxuICAgICAqICB0aGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHJlc3VsdHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW52b2tlKFtbNSwgMSwgN10sIFszLCAyLCAxXV0sICdzb3J0Jyk7XG4gICAgICogLy8gPT4gW1sxLCA1LCA3XSwgWzEsIDIsIDNdXVxuICAgICAqXG4gICAgICogXy5pbnZva2UoWzEyMywgNDU2XSwgU3RyaW5nLnByb3RvdHlwZS5zcGxpdCwgJycpO1xuICAgICAqIC8vID0+IFtbJzEnLCAnMicsICczJ10sIFsnNCcsICc1JywgJzYnXV1cbiAgICAgKi9cbiAgICB2YXIgaW52b2tlID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGNvbGxlY3Rpb24sIHBhdGgsIGFyZ3MpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGlzRnVuYyA9IHR5cGVvZiBwYXRoID09ICdmdW5jdGlvbicsXG4gICAgICAgICAgaXNQcm9wID0gaXNLZXkocGF0aCksXG4gICAgICAgICAgcmVzdWx0ID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBBcnJheShjb2xsZWN0aW9uLmxlbmd0aCkgOiBbXTtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgdmFyIGZ1bmMgPSBpc0Z1bmMgPyBwYXRoIDogKChpc1Byb3AgJiYgdmFsdWUgIT0gbnVsbCkgPyB2YWx1ZVtwYXRoXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IGZ1bmMgPyBmdW5jLmFwcGx5KHZhbHVlLCBhcmdzKSA6IGludm9rZVBhdGgodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgYnkgcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gIHRocm91Z2hcbiAgICAgKiBgaXRlcmF0ZWVgLiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgaXRlcmF0ZWVgIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYSB2YWx1ZSBpcyBhbHNvIHByb3ZpZGVkIGZvciBgdGhpc0FyZ2AgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc1Byb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICAgICAqIHZhbHVlLCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogTWFueSBsb2Rhc2ggbWV0aG9kcyBhcmUgZ3VhcmRlZCB0byB3b3JrIGFzIGl0ZXJhdGVlcyBmb3IgbWV0aG9kcyBsaWtlXG4gICAgICogYF8uZXZlcnlgLCBgXy5maWx0ZXJgLCBgXy5tYXBgLCBgXy5tYXBWYWx1ZXNgLCBgXy5yZWplY3RgLCBhbmQgYF8uc29tZWAuXG4gICAgICpcbiAgICAgKiBUaGUgZ3VhcmRlZCBtZXRob2RzIGFyZTpcbiAgICAgKiBgYXJ5YCwgYGNhbGxiYWNrYCwgYGNodW5rYCwgYGNsb25lYCwgYGNyZWF0ZWAsIGBjdXJyeWAsIGBjdXJyeVJpZ2h0YCxcbiAgICAgKiBgZHJvcGAsIGBkcm9wUmlnaHRgLCBgZXZlcnlgLCBgZmlsbGAsIGBmbGF0dGVuYCwgYGludmVydGAsIGBtYXhgLCBgbWluYCxcbiAgICAgKiBgcGFyc2VJbnRgLCBgc2xpY2VgLCBgc29ydEJ5YCwgYHRha2VgLCBgdGFrZVJpZ2h0YCwgYHRlbXBsYXRlYCwgYHRyaW1gLFxuICAgICAqIGB0cmltTGVmdGAsIGB0cmltUmlnaHRgLCBgdHJ1bmNgLCBgcmFuZG9tYCwgYHJhbmdlYCwgYHNhbXBsZWAsIGBzb21lYCxcbiAgICAgKiBgc3VtYCwgYHVuaXFgLCBhbmQgYHdvcmRzYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGNvbGxlY3RcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHRpbWVzVGhyZWUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiAzO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWFwKFsxLCAyXSwgdGltZXNUaHJlZSk7XG4gICAgICogLy8gPT4gWzMsIDZdXG4gICAgICpcbiAgICAgKiBfLm1hcCh7ICdhJzogMSwgJ2InOiAyIH0sIHRpbWVzVGhyZWUpO1xuICAgICAqIC8vID0+IFszLCA2XSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLm1hcCh1c2VycywgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5TWFwIDogYmFzZU1hcDtcbiAgICAgIGl0ZXJhdGVlID0gZ2V0Q2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDMpO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgaXRlcmF0ZWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZWxlbWVudHMgc3BsaXQgaW50byB0d28gZ3JvdXBzLCB0aGUgZmlyc3Qgb2Ygd2hpY2hcbiAgICAgKiBjb250YWlucyBlbGVtZW50cyBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IsIHdoaWxlIHRoZSBzZWNvbmQgb2Ygd2hpY2hcbiAgICAgKiBjb250YWlucyBlbGVtZW50cyBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgYm91bmRcbiAgICAgKiB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgcHJlZGljYXRlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFydGl0aW9uKFsxLCAyLCAzXSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFtbMSwgM10sIFsyXV1cbiAgICAgKlxuICAgICAqIF8ucGFydGl0aW9uKFsxLjIsIDIuMywgMy40XSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIHRoaXMuZmxvb3IobikgJSAyO1xuICAgICAqIH0sIE1hdGgpO1xuICAgICAqIC8vID0+IFtbMS4yLCAzLjRdLCBbMi4zXV1cbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWdlJzogMSwgICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIHZhciBtYXBwZXIgPSBmdW5jdGlvbihhcnJheSkge1xuICAgICAqICAgcmV0dXJuIF8ucGx1Y2soYXJyYXksICd1c2VyJyk7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLm1hcChfLnBhcnRpdGlvbih1c2VycywgeyAnYWdlJzogMSwgJ2FjdGl2ZSc6IGZhbHNlIH0pLCBtYXBwZXIpO1xuICAgICAqIC8vID0+IFtbJ3BlYmJsZXMnXSwgWydiYXJuZXknLCAnZnJlZCddXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5tYXAoXy5wYXJ0aXRpb24odXNlcnMsICdhY3RpdmUnLCBmYWxzZSksIG1hcHBlcik7XG4gICAgICogLy8gPT4gW1snYmFybmV5JywgJ3BlYmJsZXMnXSwgWydmcmVkJ11dXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ubWFwKF8ucGFydGl0aW9uKHVzZXJzLCAnYWN0aXZlJyksIG1hcHBlcik7XG4gICAgICogLy8gPT4gW1snZnJlZCddLCBbJ2Jhcm5leScsICdwZWJibGVzJ11dXG4gICAgICovXG4gICAgdmFyIHBhcnRpdGlvbiA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRba2V5ID8gMCA6IDFdLnB1c2godmFsdWUpO1xuICAgIH0sIGZ1bmN0aW9uKCkgeyByZXR1cm4gW1tdLCBbXV07IH0pO1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgYHBhdGhgIGZyb20gYWxsIGVsZW1lbnRzIGluIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gcGx1Y2suXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucGx1Y2sodXNlcnMsICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiB2YXIgdXNlckluZGV4ID0gXy5pbmRleEJ5KHVzZXJzLCAndXNlcicpO1xuICAgICAqIF8ucGx1Y2sodXNlckluZGV4LCAnYWdlJyk7XG4gICAgICogLy8gPT4gWzM2LCA0MF0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwbHVjayhjb2xsZWN0aW9uLCBwYXRoKSB7XG4gICAgICByZXR1cm4gbWFwKGNvbGxlY3Rpb24sIHByb3BlcnR5KHBhdGgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWR1Y2VzIGBjb2xsZWN0aW9uYCB0byBhIHZhbHVlIHdoaWNoIGlzIHRoZSBhY2N1bXVsYXRlZCByZXN1bHQgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAgdGhyb3VnaCBgaXRlcmF0ZWVgLCB3aGVyZSBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgKiBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLiBJZiBgYWNjdW11bGF0b3JgXG4gICAgICogaXMgbm90IHByb3ZpZGVkIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCBpcyB1c2VkIGFzIHRoZSBpbml0aWFsXG4gICAgICogdmFsdWUuIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIGZvdXIgYXJndW1lbnRzOlxuICAgICAqIChhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBNYW55IGxvZGFzaCBtZXRob2RzIGFyZSBndWFyZGVkIHRvIHdvcmsgYXMgaXRlcmF0ZWVzIGZvciBtZXRob2RzIGxpa2VcbiAgICAgKiBgXy5yZWR1Y2VgLCBgXy5yZWR1Y2VSaWdodGAsIGFuZCBgXy50cmFuc2Zvcm1gLlxuICAgICAqXG4gICAgICogVGhlIGd1YXJkZWQgbWV0aG9kcyBhcmU6XG4gICAgICogYGFzc2lnbmAsIGBkZWZhdWx0c2AsIGBkZWZhdWx0c0RlZXBgLCBgaW5jbHVkZXNgLCBgbWVyZ2VgLCBgc29ydEJ5QWxsYCxcbiAgICAgKiBhbmQgYHNvcnRCeU9yZGVyYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGZvbGRsLCBpbmplY3RcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZWR1Y2UoWzEsIDJdLCBmdW5jdGlvbih0b3RhbCwgbikge1xuICAgICAqICAgcmV0dXJuIHRvdGFsICsgbjtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnJlZHVjZSh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKHJlc3VsdCwgbiwga2V5KSB7XG4gICAgICogICByZXN1bHRba2V5XSA9IG4gKiAzO1xuICAgICAqICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgKiB9LCB7fSk7XG4gICAgICogLy8gPT4geyAnYSc6IDMsICdiJzogNiB9IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgdmFyIHJlZHVjZSA9IGNyZWF0ZVJlZHVjZShhcnJheVJlZHVjZSwgYmFzZUVhY2gpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5yZWR1Y2VgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGZvbGRyXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFtbMCwgMV0sIFsyLCAzXSwgWzQsIDVdXTtcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlUmlnaHQoYXJyYXksIGZ1bmN0aW9uKGZsYXR0ZW5lZCwgb3RoZXIpIHtcbiAgICAgKiAgIHJldHVybiBmbGF0dGVuZWQuY29uY2F0KG90aGVyKTtcbiAgICAgKiB9LCBbXSk7XG4gICAgICogLy8gPT4gWzQsIDUsIDIsIDMsIDAsIDFdXG4gICAgICovXG4gICAgdmFyIHJlZHVjZVJpZ2h0ID0gY3JlYXRlUmVkdWNlKGFycmF5UmVkdWNlUmlnaHQsIGJhc2VFYWNoUmlnaHQpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLmZpbHRlcmA7IHRoaXMgbWV0aG9kIHJldHVybnMgdGhlIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYFxuICAgICAqIHRoYXQgYHByZWRpY2F0ZWAgZG9lcyAqKm5vdCoqIHJldHVybiB0cnV0aHkgZm9yLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgcHJlZGljYXRlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZWplY3QoWzEsIDIsIDMsIDRdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbMSwgM11cbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5tYXRjaGVzYCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8ucmVqZWN0KHVzZXJzLCB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfSksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLnJlamVjdCh1c2VycywgJ2FjdGl2ZScsIGZhbHNlKSwgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLnByb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8ucmVqZWN0KHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlamVjdChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHByZWRpY2F0ZSA9IGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMyk7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuICFwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYSByYW5kb20gZWxlbWVudCBvciBgbmAgcmFuZG9tIGVsZW1lbnRzIGZyb20gYSBjb2xsZWN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbl0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byBzYW1wbGUuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJhbmRvbSBzYW1wbGUocykuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2FtcGxlKFsxLCAyLCAzLCA0XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5zYW1wbGUoWzEsIDIsIDMsIDRdLCAyKTtcbiAgICAgKiAvLyA9PiBbMywgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW1wbGUoY29sbGVjdGlvbiwgbiwgZ3VhcmQpIHtcbiAgICAgIGlmIChndWFyZCA/IGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIG4sIGd1YXJkKSA6IG4gPT0gbnVsbCkge1xuICAgICAgICBjb2xsZWN0aW9uID0gdG9JdGVyYWJsZShjb2xsZWN0aW9uKTtcbiAgICAgICAgdmFyIGxlbmd0aCA9IGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgICAgICByZXR1cm4gbGVuZ3RoID4gMCA/IGNvbGxlY3Rpb25bYmFzZVJhbmRvbSgwLCBsZW5ndGggLSAxKV0gOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICByZXN1bHQgPSB0b0FycmF5KGNvbGxlY3Rpb24pLFxuICAgICAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGgsXG4gICAgICAgICAgbGFzdEluZGV4ID0gbGVuZ3RoIC0gMTtcblxuICAgICAgbiA9IG5hdGl2ZU1pbihuIDwgMCA/IDAgOiAoK24gfHwgMCksIGxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgdmFyIHJhbmQgPSBiYXNlUmFuZG9tKGluZGV4LCBsYXN0SW5kZXgpLFxuICAgICAgICAgICAgdmFsdWUgPSByZXN1bHRbcmFuZF07XG5cbiAgICAgICAgcmVzdWx0W3JhbmRdID0gcmVzdWx0W2luZGV4XTtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmVzdWx0Lmxlbmd0aCA9IG47XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygc2h1ZmZsZWQgdmFsdWVzLCB1c2luZyBhIHZlcnNpb24gb2YgdGhlXG4gICAgICogW0Zpc2hlci1ZYXRlcyBzaHVmZmxlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GaXNoZXItWWF0ZXNfc2h1ZmZsZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNodWZmbGUoWzEsIDIsIDMsIDRdKTtcbiAgICAgKiAvLyA9PiBbNCwgMSwgMywgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHJldHVybiBzYW1wbGUoY29sbGVjdGlvbiwgUE9TSVRJVkVfSU5GSU5JVFkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNpemUgb2YgYGNvbGxlY3Rpb25gIGJ5IHJldHVybmluZyBpdHMgbGVuZ3RoIGZvciBhcnJheS1saWtlXG4gICAgICogdmFsdWVzIG9yIHRoZSBudW1iZXIgb2Ygb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBmb3Igb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc2l6ZSBvZiBgY29sbGVjdGlvbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2l6ZShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8uc2l6ZSh7ICdhJzogMSwgJ2InOiAyIH0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIF8uc2l6ZSgncGViYmxlcycpO1xuICAgICAqIC8vID0+IDdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaXplKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uID8gZ2V0TGVuZ3RoKGNvbGxlY3Rpb24pIDogMDtcbiAgICAgIHJldHVybiBpc0xlbmd0aChsZW5ndGgpID8gbGVuZ3RoIDoga2V5cyhjb2xsZWN0aW9uKS5sZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciAqKmFueSoqIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqIFRoZSBmdW5jdGlvbiByZXR1cm5zIGFzIHNvb24gYXMgaXQgZmluZHMgYSBwYXNzaW5nIHZhbHVlIGFuZCBkb2VzIG5vdCBpdGVyYXRlXG4gICAgICogb3ZlciB0aGUgZW50aXJlIGNvbGxlY3Rpb24uIFRoZSBwcmVkaWNhdGUgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGFueVxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYHByZWRpY2F0ZWAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29tZShbbnVsbCwgMCwgJ3llcycsIGZhbHNlXSwgQm9vbGVhbik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc2AgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5zb21lKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5zb21lKHVzZXJzLCAnYWN0aXZlJywgZmFsc2UpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5zb21lKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvbWUoY29sbGVjdGlvbiwgcHJlZGljYXRlLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheVNvbWUgOiBiYXNlU29tZTtcbiAgICAgIGlmICh0aGlzQXJnICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgdGhpc0FyZykpIHtcbiAgICAgICAgcHJlZGljYXRlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwcmVkaWNhdGUgIT0gJ2Z1bmN0aW9uJyB8fCB0aGlzQXJnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcHJlZGljYXRlID0gZ2V0Q2FsbGJhY2socHJlZGljYXRlLCB0aGlzQXJnLCAzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cywgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlciBieSB0aGUgcmVzdWx0cyBvZlxuICAgICAqIHJ1bm5pbmcgZWFjaCBlbGVtZW50IGluIGEgY29sbGVjdGlvbiB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoaXMgbWV0aG9kIHBlcmZvcm1zXG4gICAgICogYSBzdGFibGUgc29ydCwgdGhhdCBpcywgaXQgcHJlc2VydmVzIHRoZSBvcmlnaW5hbCBzb3J0IG9yZGVyIG9mIGVxdWFsIGVsZW1lbnRzLlxuICAgICAqIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydEJ5KFsxLCAyLCAzXSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIE1hdGguc2luKG4pO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFszLCAxLCAyXVxuICAgICAqXG4gICAgICogXy5zb3J0QnkoWzEsIDIsIDNdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gdGhpcy5zaW4obik7XG4gICAgICogfSwgTWF0aCk7XG4gICAgICogLy8gPT4gWzMsIDEsIDJdXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucGx1Y2soXy5zb3J0QnkodXNlcnMsICd1c2VyJyksICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0QnkoY29sbGVjdGlvbiwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgIGlmIChjb2xsZWN0aW9uID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXNBcmcgJiYgaXNJdGVyYXRlZUNhbGwoY29sbGVjdGlvbiwgaXRlcmF0ZWUsIHRoaXNBcmcpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTE7XG4gICAgICBpdGVyYXRlZSA9IGdldENhbGxiYWNrKGl0ZXJhdGVlLCB0aGlzQXJnLCAzKTtcblxuICAgICAgdmFyIHJlc3VsdCA9IGJhc2VNYXAoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICByZXR1cm4geyAnY3JpdGVyaWEnOiBpdGVyYXRlZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSwgJ2luZGV4JzogKytpbmRleCwgJ3ZhbHVlJzogdmFsdWUgfTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGJhc2VTb3J0QnkocmVzdWx0LCBjb21wYXJlQXNjZW5kaW5nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnNvcnRCeWAgZXhjZXB0IHRoYXQgaXQgY2FuIHNvcnQgYnkgbXVsdGlwbGUgaXRlcmF0ZWVzXG4gICAgICogb3IgcHJvcGVydHkgbmFtZXMuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGFuIGl0ZXJhdGVlIHRoZSBjcmVhdGVkIGBfLnByb3BlcnR5YFxuICAgICAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBhbiBpdGVyYXRlZSB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXXxPYmplY3R8T2JqZWN0W118c3RyaW5nfHN0cmluZ1tdKX0gaXRlcmF0ZWVzXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieSwgc3BlY2lmaWVkIGFzIGluZGl2aWR1YWwgdmFsdWVzIG9yIGFycmF5cyBvZiB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgc29ydGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0OCB9LFxuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQyIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ubWFwKF8uc29ydEJ5QWxsKHVzZXJzLCBbJ3VzZXInLCAnYWdlJ10pLCBfLnZhbHVlcyk7XG4gICAgICogLy8gPT4gW1snYmFybmV5JywgMzRdLCBbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDJdLCBbJ2ZyZWQnLCA0OF1dXG4gICAgICpcbiAgICAgKiBfLm1hcChfLnNvcnRCeUFsbCh1c2VycywgJ3VzZXInLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBNYXRoLmZsb29yKGNoci5hZ2UgLyAxMCk7XG4gICAgICogfSksIF8udmFsdWVzKTtcbiAgICAgKiAvLyA9PiBbWydiYXJuZXknLCAzNl0sIFsnYmFybmV5JywgMzRdLCBbJ2ZyZWQnLCA0OF0sIFsnZnJlZCcsIDQyXV1cbiAgICAgKi9cbiAgICB2YXIgc29ydEJ5QWxsID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGl0ZXJhdGVlcykge1xuICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgZ3VhcmQgPSBpdGVyYXRlZXNbMl07XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoaXRlcmF0ZWVzWzBdLCBpdGVyYXRlZXNbMV0sIGd1YXJkKSkge1xuICAgICAgICBpdGVyYXRlZXMubGVuZ3RoID0gMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlU29ydEJ5T3JkZXIoY29sbGVjdGlvbiwgYmFzZUZsYXR0ZW4oaXRlcmF0ZWVzKSwgW10pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0QnlBbGxgIGV4Y2VwdCB0aGF0IGl0IGFsbG93cyBzcGVjaWZ5aW5nIHRoZVxuICAgICAqIHNvcnQgb3JkZXJzIG9mIHRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS4gSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbFxuICAgICAqIHZhbHVlcyBhcmUgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlci4gT3RoZXJ3aXNlLCBhIHZhbHVlIGlzIHNvcnRlZCBpblxuICAgICAqIGFzY2VuZGluZyBvcmRlciBpZiBpdHMgY29ycmVzcG9uZGluZyBvcmRlciBpcyBcImFzY1wiLCBhbmQgZGVzY2VuZGluZyBpZiBcImRlc2NcIi5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYW4gaXRlcmF0ZWUgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGFuIGl0ZXJhdGVlIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW118T2JqZWN0W118c3RyaW5nW119IGl0ZXJhdGVlcyBUaGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuXG4gICAgICogQHBhcmFtIHtib29sZWFuW119IFtvcmRlcnNdIFRoZSBzb3J0IG9yZGVycyBvZiBgaXRlcmF0ZWVzYC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQ4IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDIgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gc29ydCBieSBgdXNlcmAgaW4gYXNjZW5kaW5nIG9yZGVyIGFuZCBieSBgYWdlYCBpbiBkZXNjZW5kaW5nIG9yZGVyXG4gICAgICogXy5tYXAoXy5zb3J0QnlPcmRlcih1c2VycywgWyd1c2VyJywgJ2FnZSddLCBbJ2FzYycsICdkZXNjJ10pLCBfLnZhbHVlcyk7XG4gICAgICogLy8gPT4gW1snYmFybmV5JywgMzZdLCBbJ2Jhcm5leScsIDM0XSwgWydmcmVkJywgNDhdLCBbJ2ZyZWQnLCA0Ml1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydEJ5T3JkZXIoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMsIGd1YXJkKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChpdGVyYXRlZXMsIG9yZGVycywgZ3VhcmQpKSB7XG4gICAgICAgIG9yZGVycyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGlmICghaXNBcnJheShpdGVyYXRlZXMpKSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IGl0ZXJhdGVlcyA9PSBudWxsID8gW10gOiBbaXRlcmF0ZWVzXTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNBcnJheShvcmRlcnMpKSB7XG4gICAgICAgIG9yZGVycyA9IG9yZGVycyA9PSBudWxsID8gW10gOiBbb3JkZXJzXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlU29ydEJ5T3JkZXIoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYCBhbmQgdGhlXG4gICAgICogc291cmNlIG9iamVjdCwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGFsbCBlbGVtZW50cyB0aGF0IGhhdmUgZXF1aXZhbGVudFxuICAgICAqIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBzdXBwb3J0cyBjb21wYXJpbmcgYXJyYXlzLCBib29sZWFucywgYERhdGVgIG9iamVjdHMsXG4gICAgICogbnVtYmVycywgYE9iamVjdGAgb2JqZWN0cywgcmVnZXhlcywgYW5kIHN0cmluZ3MuIE9iamVjdHMgYXJlIGNvbXBhcmVkIGJ5XG4gICAgICogdGhlaXIgb3duLCBub3QgaW5oZXJpdGVkLCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuIEZvciBjb21wYXJpbmcgYSBzaW5nbGVcbiAgICAgKiBvd24gb3IgaW5oZXJpdGVkIHByb3BlcnR5IHZhbHVlIHNlZSBgXy5tYXRjaGVzUHJvcGVydHlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UsICdwZXRzJzogWydob3BweSddIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUsICdwZXRzJzogWydiYWJ5IHB1c3MnLCAnZGlubyddIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5wbHVjayhfLndoZXJlKHVzZXJzLCB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0pLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIF8ucGx1Y2soXy53aGVyZSh1c2VycywgeyAncGV0cyc6IFsnZGlubyddIH0pLCAndXNlcicpO1xuICAgICAqIC8vID0+IFsnZnJlZCddXG4gICAgICovXG4gICAgZnVuY3Rpb24gd2hlcmUoY29sbGVjdGlvbiwgc291cmNlKSB7XG4gICAgICByZXR1cm4gZmlsdGVyKGNvbGxlY3Rpb24sIGJhc2VNYXRjaGVzKHNvdXJjZSkpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2UgdGhlIFVuaXggZXBvY2hcbiAgICAgKiAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBEYXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmZXIoZnVuY3Rpb24oc3RhbXApIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gICAgICogfSwgXy5ub3coKSk7XG4gICAgICogLy8gPT4gbG9ncyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBpdCB0b29rIGZvciB0aGUgZGVmZXJyZWQgZnVuY3Rpb24gdG8gYmUgaW52b2tlZFxuICAgICAqL1xuICAgIHZhciBub3cgPSBuYXRpdmVOb3cgfHwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5iZWZvcmVgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogYGZ1bmNgIG9uY2UgaXQgaXMgY2FsbGVkIGBuYCBvciBtb3JlIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiBjYWxscyBiZWZvcmUgYGZ1bmNgIGlzIGludm9rZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVzdHJpY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmVzdHJpY3RlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHNhdmVzID0gWydwcm9maWxlJywgJ3NldHRpbmdzJ107XG4gICAgICpcbiAgICAgKiB2YXIgZG9uZSA9IF8uYWZ0ZXIoc2F2ZXMubGVuZ3RoLCBmdW5jdGlvbigpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKCdkb25lIHNhdmluZyEnKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIF8uZm9yRWFjaChzYXZlcywgZnVuY3Rpb24odHlwZSkge1xuICAgICAqICAgYXN5bmNTYXZlKHsgJ3R5cGUnOiB0eXBlLCAnY29tcGxldGUnOiBkb25lIH0pO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ2RvbmUgc2F2aW5nIScgYWZ0ZXIgdGhlIHR3byBhc3luYyBzYXZlcyBoYXZlIGNvbXBsZXRlZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFmdGVyKG4sIGZ1bmMpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbiA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdmFyIHRlbXAgPSBuO1xuICAgICAgICAgIG4gPSBmdW5jO1xuICAgICAgICAgIGZ1bmMgPSB0ZW1wO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbiA9IG5hdGl2ZUlzRmluaXRlKG4gPSArbikgPyBuIDogMDtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKC0tbiA8IDEpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdXAgdG8gYG5gIGFyZ3VtZW50cyBpZ25vcmluZyBhbnlcbiAgICAgKiBhZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IGNhcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzgnLCAnMTAnXSwgXy5hcnkocGFyc2VJbnQsIDEpKTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJ5KGZ1bmMsIG4sIGd1YXJkKSB7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoZnVuYywgbiwgZ3VhcmQpKSB7XG4gICAgICAgIG4gPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBuID0gKGZ1bmMgJiYgbiA9PSBudWxsKSA/IGZ1bmMubGVuZ3RoIDogbmF0aXZlTWF4KCtuIHx8IDAsIDApO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgQVJZX0ZMQUcsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2AsIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHNcbiAgICAgKiBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbiwgd2hpbGUgaXQgaXMgY2FsbGVkIGxlc3MgdGhhbiBgbmAgdGltZXMuIFN1YnNlcXVlbnRcbiAgICAgKiBjYWxscyB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgY2FsbHMgYXQgd2hpY2ggYGZ1bmNgIGlzIG5vIGxvbmdlciBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGpRdWVyeSgnI2FkZCcpLm9uKCdjbGljaycsIF8uYmVmb3JlKDUsIGFkZENvbnRhY3RUb0xpc3QpKTtcbiAgICAgKiAvLyA9PiBhbGxvd3MgYWRkaW5nIHVwIHRvIDQgY29udGFjdHMgdG8gdGhlIGxpc3RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiZWZvcmUobiwgZnVuYykge1xuICAgICAgdmFyIHJlc3VsdDtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbiA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdmFyIHRlbXAgPSBuO1xuICAgICAgICAgIG4gPSBmdW5jO1xuICAgICAgICAgIGZ1bmMgPSB0ZW1wO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoLS1uID4gMCkge1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobiA8PSAxKSB7XG4gICAgICAgICAgZnVuYyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiBgdGhpc0FyZ2BcbiAgICAgKiBhbmQgcHJlcGVuZHMgYW55IGFkZGl0aW9uYWwgYF8uYmluZGAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZVxuICAgICAqIGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogVGhlIGBfLmJpbmQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpYyBidWlsZHMsXG4gICAgICogbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBuYXRpdmUgYEZ1bmN0aW9uI2JpbmRgIHRoaXMgbWV0aG9kIGRvZXMgbm90IHNldCB0aGUgXCJsZW5ndGhcIlxuICAgICAqIHByb3BlcnR5IG9mIGJvdW5kIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGJpbmQuXG4gICAgICogQHBhcmFtIHsqfSB0aGlzQXJnIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBncmVldCA9IGZ1bmN0aW9uKGdyZWV0aW5nLCBwdW5jdHVhdGlvbikge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnIH07XG4gICAgICpcbiAgICAgKiB2YXIgYm91bmQgPSBfLmJpbmQoZ3JlZXQsIG9iamVjdCwgJ2hpJyk7XG4gICAgICogYm91bmQoJyEnKTtcbiAgICAgKiAvLyA9PiAnaGkgZnJlZCEnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBwbGFjZWhvbGRlcnNcbiAgICAgKiB2YXIgYm91bmQgPSBfLmJpbmQoZ3JlZXQsIG9iamVjdCwgXywgJyEnKTtcbiAgICAgKiBib3VuZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGkgZnJlZCEnXG4gICAgICovXG4gICAgdmFyIGJpbmQgPSByZXN0UGFyYW0oZnVuY3Rpb24oZnVuYywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gQklORF9GTEFHO1xuICAgICAgaWYgKHBhcnRpYWxzLmxlbmd0aCkge1xuICAgICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBiaW5kLnBsYWNlaG9sZGVyKTtcbiAgICAgICAgYml0bWFzayB8PSBQQVJUSUFMX0ZMQUc7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBCaW5kcyBtZXRob2RzIG9mIGFuIG9iamVjdCB0byB0aGUgb2JqZWN0IGl0c2VsZiwgb3ZlcndyaXRpbmcgdGhlIGV4aXN0aW5nXG4gICAgICogbWV0aG9kLiBNZXRob2QgbmFtZXMgbWF5IGJlIHNwZWNpZmllZCBhcyBpbmRpdmlkdWFsIGFyZ3VtZW50cyBvciBhcyBhcnJheXNcbiAgICAgKiBvZiBtZXRob2QgbmFtZXMuIElmIG5vIG1ldGhvZCBuYW1lcyBhcmUgcHJvdmlkZWQgYWxsIGVudW1lcmFibGUgZnVuY3Rpb25cbiAgICAgKiBwcm9wZXJ0aWVzLCBvd24gYW5kIGluaGVyaXRlZCwgb2YgYG9iamVjdGAgYXJlIGJvdW5kLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXMgbm90IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBib3VuZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gYmluZCBhbmQgYXNzaWduIHRoZSBib3VuZCBtZXRob2RzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKHN0cmluZ3xzdHJpbmdbXSl9IFttZXRob2ROYW1lc10gVGhlIG9iamVjdCBtZXRob2QgbmFtZXMgdG8gYmluZCxcbiAgICAgKiAgc3BlY2lmaWVkIGFzIGluZGl2aWR1YWwgbWV0aG9kIG5hbWVzIG9yIGFycmF5cyBvZiBtZXRob2QgbmFtZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHZpZXcgPSB7XG4gICAgICogICAnbGFiZWwnOiAnZG9jcycsXG4gICAgICogICAnb25DbGljayc6IGZ1bmN0aW9uKCkge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnY2xpY2tlZCAnICsgdGhpcy5sYWJlbCk7XG4gICAgICogICB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uYmluZEFsbCh2aWV3KTtcbiAgICAgKiBqUXVlcnkoJyNkb2NzJykub24oJ2NsaWNrJywgdmlldy5vbkNsaWNrKTtcbiAgICAgKiAvLyA9PiBsb2dzICdjbGlja2VkIGRvY3MnIHdoZW4gdGhlIGVsZW1lbnQgaXMgY2xpY2tlZFxuICAgICAqL1xuICAgIHZhciBiaW5kQWxsID0gcmVzdFBhcmFtKGZ1bmN0aW9uKG9iamVjdCwgbWV0aG9kTmFtZXMpIHtcbiAgICAgIG1ldGhvZE5hbWVzID0gbWV0aG9kTmFtZXMubGVuZ3RoID8gYmFzZUZsYXR0ZW4obWV0aG9kTmFtZXMpIDogZnVuY3Rpb25zKG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IG1ldGhvZE5hbWVzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGtleSA9IG1ldGhvZE5hbWVzW2luZGV4XTtcbiAgICAgICAgb2JqZWN0W2tleV0gPSBjcmVhdGVXcmFwcGVyKG9iamVjdFtrZXldLCBCSU5EX0ZMQUcsIG9iamVjdCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBvYmplY3Rba2V5XWAgYW5kIHByZXBlbmRzXG4gICAgICogYW55IGFkZGl0aW9uYWwgYF8uYmluZEtleWAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBib3VuZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGRpZmZlcnMgZnJvbSBgXy5iaW5kYCBieSBhbGxvd2luZyBib3VuZCBmdW5jdGlvbnMgdG8gcmVmZXJlbmNlXG4gICAgICogbWV0aG9kcyB0aGF0IG1heSBiZSByZWRlZmluZWQgb3IgZG9uJ3QgeWV0IGV4aXN0LlxuICAgICAqIFNlZSBbUGV0ZXIgTWljaGF1eCdzIGFydGljbGVdKGh0dHA6Ly9wZXRlci5taWNoYXV4LmNhL2FydGljbGVzL2xhenktZnVuY3Rpb24tZGVmaW5pdGlvbi1wYXR0ZXJuKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZEtleS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdGhlIG1ldGhvZCBiZWxvbmdzIHRvLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgbWV0aG9kLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ3VzZXInOiAnZnJlZCcsXG4gICAgICogICAnZ3JlZXQnOiBmdW5jdGlvbihncmVldGluZywgcHVuY3R1YXRpb24pIHtcbiAgICAgKiAgICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogICB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZEtleShvYmplY3QsICdncmVldCcsICdoaScpO1xuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqXG4gICAgICogb2JqZWN0LmdyZWV0ID0gZnVuY3Rpb24oZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAneWEgJyArIHRoaXMudXNlciArIHB1bmN0dWF0aW9uO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaXlhIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgcGxhY2Vob2xkZXJzXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kS2V5KG9iamVjdCwgJ2dyZWV0JywgXywgJyEnKTtcbiAgICAgKiBib3VuZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGl5YSBmcmVkISdcbiAgICAgKi9cbiAgICB2YXIgYmluZEtleSA9IHJlc3RQYXJhbShmdW5jdGlvbihvYmplY3QsIGtleSwgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gQklORF9GTEFHIHwgQklORF9LRVlfRkxBRztcbiAgICAgIGlmIChwYXJ0aWFscy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgYmluZEtleS5wbGFjZWhvbGRlcik7XG4gICAgICAgIGJpdG1hc2sgfD0gUEFSVElBTF9GTEFHO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoa2V5LCBiaXRtYXNrLCBvYmplY3QsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgb25lIG9yIG1vcmUgYXJndW1lbnRzIG9mIGBmdW5jYCB0aGF0IHdoZW5cbiAgICAgKiBjYWxsZWQgZWl0aGVyIGludm9rZXMgYGZ1bmNgIHJldHVybmluZyBpdHMgcmVzdWx0LCBpZiBhbGwgYGZ1bmNgIGFyZ3VtZW50c1xuICAgICAqIGhhdmUgYmVlbiBwcm92aWRlZCwgb3IgcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBvbmUgb3IgbW9yZSBvZiB0aGVcbiAgICAgKiByZW1haW5pbmcgYGZ1bmNgIGFyZ3VtZW50cywgYW5kIHNvIG9uLiBUaGUgYXJpdHkgb2YgYGZ1bmNgIG1heSBiZSBzcGVjaWZpZWRcbiAgICAgKiBpZiBgZnVuYy5sZW5ndGhgIGlzIG5vdCBzdWZmaWNpZW50LlxuICAgICAqXG4gICAgICogVGhlIGBfLmN1cnJ5LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWMgYnVpbGRzLFxuICAgICAqIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2VzIG5vdCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgY3VycmllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5PWZ1bmMubGVuZ3RoXSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhYmMgPSBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICogICByZXR1cm4gW2EsIGIsIGNdO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgY3VycmllZCA9IF8uY3VycnkoYWJjKTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSkoMikoMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIpKDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyLCAzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHBsYWNlaG9sZGVyc1xuICAgICAqIGN1cnJpZWQoMSkoXywgMykoMik7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgdmFyIGN1cnJ5ID0gY3JlYXRlQ3VycnkoQ1VSUllfRkxBRyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmN1cnJ5YCBleGNlcHQgdGhhdCBhcmd1bWVudHMgYXJlIGFwcGxpZWQgdG8gYGZ1bmNgXG4gICAgICogaW4gdGhlIG1hbm5lciBvZiBgXy5wYXJ0aWFsUmlnaHRgIGluc3RlYWQgb2YgYF8ucGFydGlhbGAuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uY3VycnlSaWdodC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lcyBub3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIGN1cnJpZWQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY3VycnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eT1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYWJjID0gZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGN1cnJpZWQgPSBfLmN1cnJ5UmlnaHQoYWJjKTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMykoMikoMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDIsIDMpKDEpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyLCAzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHBsYWNlaG9sZGVyc1xuICAgICAqIGN1cnJpZWQoMykoMSwgXykoMik7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgdmFyIGN1cnJ5UmlnaHQgPSBjcmVhdGVDdXJyeShDVVJSWV9SSUdIVF9GTEFHKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICAgICAqIG1pbGxpc2Vjb25kcyBoYXZlIGVsYXBzZWQgc2luY2UgdGhlIGxhc3QgdGltZSB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHdhc1xuICAgICAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAgICAgKiBkZWxheWVkIGludm9jYXRpb25zLiBQcm92aWRlIGFuIG9wdGlvbnMgb2JqZWN0IHRvIGluZGljYXRlIHRoYXQgYGZ1bmNgXG4gICAgICogc2hvdWxkIGJlIGludm9rZWQgb24gdGhlIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICAgICAqIFN1YnNlcXVlbnQgY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdFxuICAgICAqIGBmdW5jYCBpbnZvY2F0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpcyBpbnZva2VkXG4gICAgICogb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiBpc1xuICAgICAqIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAgICAgKlxuICAgICAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwOi8vZHJ1cGFsbW90aW9uLmNvbS9hcnRpY2xlL2RlYm91bmNlLWFuZC10aHJvdHRsZS12aXN1YWwtZXhwbGFuYXRpb24pXG4gICAgICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmdcbiAgICAgKiAgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMubWF4V2FpdF0gVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZVxuICAgICAqICBkZWxheWVkIGJlZm9yZSBpdCBpcyBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV0gU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmdcbiAgICAgKiAgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIGF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXhcbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICAgICAqXG4gICAgICogLy8gaW52b2tlIGBzZW5kTWFpbGAgd2hlbiB0aGUgY2xpY2sgZXZlbnQgaXMgZmlyZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxsc1xuICAgICAqIGpRdWVyeSgnI3Bvc3Rib3gnKS5vbignY2xpY2snLCBfLmRlYm91bmNlKHNlbmRNYWlsLCAzMDAsIHtcbiAgICAgKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAgICAgKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gICAgICogfSkpO1xuICAgICAqXG4gICAgICogLy8gZW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxsc1xuICAgICAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAgICAgKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwge1xuICAgICAqICAgJ21heFdhaXQnOiAxMDAwXG4gICAgICogfSkpO1xuICAgICAqXG4gICAgICogLy8gY2FuY2VsIGEgZGVib3VuY2VkIGNhbGxcbiAgICAgKiB2YXIgdG9kb0NoYW5nZXMgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAxMDAwKTtcbiAgICAgKiBPYmplY3Qub2JzZXJ2ZShtb2RlbHMudG9kbywgdG9kb0NoYW5nZXMpO1xuICAgICAqXG4gICAgICogT2JqZWN0Lm9ic2VydmUobW9kZWxzLCBmdW5jdGlvbihjaGFuZ2VzKSB7XG4gICAgICogICBpZiAoXy5maW5kKGNoYW5nZXMsIHsgJ3VzZXInOiAndG9kbycsICd0eXBlJzogJ2RlbGV0ZSd9KSkge1xuICAgICAqICAgICB0b2RvQ2hhbmdlcy5jYW5jZWwoKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9LCBbJ2RlbGV0ZSddKTtcbiAgICAgKlxuICAgICAqIC8vIC4uLmF0IHNvbWUgcG9pbnQgYG1vZGVscy50b2RvYCBpcyBjaGFuZ2VkXG4gICAgICogbW9kZWxzLnRvZG8uY29tcGxldGVkID0gdHJ1ZTtcbiAgICAgKlxuICAgICAqIC8vIC4uLmJlZm9yZSAxIHNlY29uZCBoYXMgcGFzc2VkIGBtb2RlbHMudG9kb2AgaXMgZGVsZXRlZFxuICAgICAqIC8vIHdoaWNoIGNhbmNlbHMgdGhlIGRlYm91bmNlZCBgdG9kb0NoYW5nZXNgIGNhbGxcbiAgICAgKiBkZWxldGUgbW9kZWxzLnRvZG87XG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgICAgdmFyIGFyZ3MsXG4gICAgICAgICAgbWF4VGltZW91dElkLFxuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICBzdGFtcCxcbiAgICAgICAgICB0aGlzQXJnLFxuICAgICAgICAgIHRpbWVvdXRJZCxcbiAgICAgICAgICB0cmFpbGluZ0NhbGwsXG4gICAgICAgICAgbGFzdENhbGxlZCA9IDAsXG4gICAgICAgICAgbWF4V2FpdCA9IGZhbHNlLFxuICAgICAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgd2FpdCA9IHdhaXQgPCAwID8gMCA6ICgrd2FpdCB8fCAwKTtcbiAgICAgIGlmIChvcHRpb25zID09PSB0cnVlKSB7XG4gICAgICAgIHZhciBsZWFkaW5nID0gdHJ1ZTtcbiAgICAgICAgdHJhaWxpbmcgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgICAgICBtYXhXYWl0ID0gJ21heFdhaXQnIGluIG9wdGlvbnMgJiYgbmF0aXZlTWF4KCtvcHRpb25zLm1heFdhaXQgfHwgMCwgd2FpdCk7XG4gICAgICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICAgICAgaWYgKHRpbWVvdXRJZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXhUaW1lb3V0SWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQobWF4VGltZW91dElkKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0Q2FsbGVkID0gMDtcbiAgICAgICAgbWF4VGltZW91dElkID0gdGltZW91dElkID0gdHJhaWxpbmdDYWxsID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjb21wbGV0ZShpc0NhbGxlZCwgaWQpIHtcbiAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGlkKTtcbiAgICAgICAgfVxuICAgICAgICBtYXhUaW1lb3V0SWQgPSB0aW1lb3V0SWQgPSB0cmFpbGluZ0NhbGwgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChpc0NhbGxlZCkge1xuICAgICAgICAgIGxhc3RDYWxsZWQgPSBub3coKTtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICAgIGlmICghdGltZW91dElkICYmICFtYXhUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGFyZ3MgPSB0aGlzQXJnID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZWxheWVkKCkge1xuICAgICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3coKSAtIHN0YW1wKTtcbiAgICAgICAgaWYgKHJlbWFpbmluZyA8PSAwIHx8IHJlbWFpbmluZyA+IHdhaXQpIHtcbiAgICAgICAgICBjb21wbGV0ZSh0cmFpbGluZ0NhbGwsIG1heFRpbWVvdXRJZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChkZWxheWVkLCByZW1haW5pbmcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG1heERlbGF5ZWQoKSB7XG4gICAgICAgIGNvbXBsZXRlKHRyYWlsaW5nLCB0aW1lb3V0SWQpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZWJvdW5jZWQoKSB7XG4gICAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHN0YW1wID0gbm93KCk7XG4gICAgICAgIHRoaXNBcmcgPSB0aGlzO1xuICAgICAgICB0cmFpbGluZ0NhbGwgPSB0cmFpbGluZyAmJiAodGltZW91dElkIHx8ICFsZWFkaW5nKTtcblxuICAgICAgICBpZiAobWF4V2FpdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB2YXIgbGVhZGluZ0NhbGwgPSBsZWFkaW5nICYmICF0aW1lb3V0SWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFtYXhUaW1lb3V0SWQgJiYgIWxlYWRpbmcpIHtcbiAgICAgICAgICAgIGxhc3RDYWxsZWQgPSBzdGFtcDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHJlbWFpbmluZyA9IG1heFdhaXQgLSAoc3RhbXAgLSBsYXN0Q2FsbGVkKSxcbiAgICAgICAgICAgICAgaXNDYWxsZWQgPSByZW1haW5pbmcgPD0gMCB8fCByZW1haW5pbmcgPiBtYXhXYWl0O1xuXG4gICAgICAgICAgaWYgKGlzQ2FsbGVkKSB7XG4gICAgICAgICAgICBpZiAobWF4VGltZW91dElkKSB7XG4gICAgICAgICAgICAgIG1heFRpbWVvdXRJZCA9IGNsZWFyVGltZW91dChtYXhUaW1lb3V0SWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoIW1heFRpbWVvdXRJZCkge1xuICAgICAgICAgICAgbWF4VGltZW91dElkID0gc2V0VGltZW91dChtYXhEZWxheWVkLCByZW1haW5pbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNDYWxsZWQgJiYgdGltZW91dElkKSB7XG4gICAgICAgICAgdGltZW91dElkID0gY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRpbWVvdXRJZCAmJiB3YWl0ICE9PSBtYXhXYWl0KSB7XG4gICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChkZWxheWVkLCB3YWl0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGVhZGluZ0NhbGwpIHtcbiAgICAgICAgICBpc0NhbGxlZCA9IHRydWU7XG4gICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNDYWxsZWQgJiYgIXRpbWVvdXRJZCAmJiAhbWF4VGltZW91dElkKSB7XG4gICAgICAgICAgYXJncyA9IHRoaXNBcmcgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gICAgICByZXR1cm4gZGVib3VuY2VkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlZmVycyBpbnZva2luZyB0aGUgYGZ1bmNgIHVudGlsIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzIGNsZWFyZWQuIEFueVxuICAgICAqIGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCBpcyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVmZXIuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIGZ1bmN0aW9uIHdpdGguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXIgaWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmZXIoZnVuY3Rpb24odGV4dCkge1xuICAgICAqICAgY29uc29sZS5sb2codGV4dCk7XG4gICAgICogfSwgJ2RlZmVycmVkJyk7XG4gICAgICogLy8gbG9ncyAnZGVmZXJyZWQnIGFmdGVyIG9uZSBvciBtb3JlIG1pbGxpc2Vjb25kc1xuICAgICAqL1xuICAgIHZhciBkZWZlciA9IHJlc3RQYXJhbShmdW5jdGlvbihmdW5jLCBhcmdzKSB7XG4gICAgICByZXR1cm4gYmFzZURlbGF5KGZ1bmMsIDEsIGFyZ3MpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyBgZnVuY2AgYWZ0ZXIgYHdhaXRgIG1pbGxpc2Vjb25kcy4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZVxuICAgICAqIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0IGlzIGludm9rZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheSBpbnZvY2F0aW9uLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBmdW5jdGlvbiB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlbGF5KGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKHRleHQpO1xuICAgICAqIH0sIDEwMDAsICdsYXRlcicpO1xuICAgICAqIC8vID0+IGxvZ3MgJ2xhdGVyJyBhZnRlciBvbmUgc2Vjb25kXG4gICAgICovXG4gICAgdmFyIGRlbGF5ID0gcmVzdFBhcmFtKGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGFyZ3MpIHtcbiAgICAgIHJldHVybiBiYXNlRGVsYXkoZnVuYywgd2FpdCwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSByZXN1bHQgb2YgaW52b2tpbmcgdGhlIHByb3ZpZGVkXG4gICAgICogZnVuY3Rpb25zIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLCB3aGVyZSBlYWNoXG4gICAgICogc3VjY2Vzc2l2ZSBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn0gW2Z1bmNzXSBGdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3coXy5hZGQsIHNxdWFyZSk7XG4gICAgICogYWRkU3F1YXJlKDEsIDIpO1xuICAgICAqIC8vID0+IDlcbiAgICAgKi9cbiAgICB2YXIgZmxvdyA9IGNyZWF0ZUZsb3coKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmxvd2AgZXhjZXB0IHRoYXQgaXQgY3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXRcbiAgICAgKiBpbnZva2VzIHRoZSBwcm92aWRlZCBmdW5jdGlvbnMgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGJhY2tmbG93LCBjb21wb3NlXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn0gW2Z1bmNzXSBGdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3dSaWdodChzcXVhcmUsIF8uYWRkKTtcbiAgICAgKiBhZGRTcXVhcmUoMSwgMik7XG4gICAgICogLy8gPT4gOVxuICAgICAqL1xuICAgIHZhciBmbG93UmlnaHQgPSBjcmVhdGVGbG93KHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgbWVtb2l6ZXMgdGhlIHJlc3VsdCBvZiBgZnVuY2AuIElmIGByZXNvbHZlcmAgaXNcbiAgICAgKiBwcm92aWRlZCBpdCBkZXRlcm1pbmVzIHRoZSBjYWNoZSBrZXkgZm9yIHN0b3JpbmcgdGhlIHJlc3VsdCBiYXNlZCBvbiB0aGVcbiAgICAgKiBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIG1lbW9pemVkIGZ1bmN0aW9uLiBCeSBkZWZhdWx0LCB0aGUgZmlyc3QgYXJndW1lbnRcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24gaXMgY29lcmNlZCB0byBhIHN0cmluZyBhbmQgdXNlZCBhcyB0aGVcbiAgICAgKiBjYWNoZSBrZXkuIFRoZSBgZnVuY2AgaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgbWVtb2l6ZWRcbiAgICAgKiBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGUgY2FjaGUgaXMgZXhwb3NlZCBhcyB0aGUgYGNhY2hlYCBwcm9wZXJ0eSBvbiB0aGUgbWVtb2l6ZWRcbiAgICAgKiBmdW5jdGlvbi4gSXRzIGNyZWF0aW9uIG1heSBiZSBjdXN0b21pemVkIGJ5IHJlcGxhY2luZyB0aGUgYF8ubWVtb2l6ZS5DYWNoZWBcbiAgICAgKiBjb25zdHJ1Y3RvciB3aXRoIG9uZSB3aG9zZSBpbnN0YW5jZXMgaW1wbGVtZW50IHRoZSBbYE1hcGBdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXByb3BlcnRpZXMtb2YtdGhlLW1hcC1wcm90b3R5cGUtb2JqZWN0KVxuICAgICAqIG1ldGhvZCBpbnRlcmZhY2Ugb2YgYGdldGAsIGBoYXNgLCBhbmQgYHNldGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBoYXZlIGl0cyBvdXRwdXQgbWVtb2l6ZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3Jlc29sdmVyXSBUaGUgZnVuY3Rpb24gdG8gcmVzb2x2ZSB0aGUgY2FjaGUga2V5LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG1lbW9pemluZyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVwcGVyQ2FzZSA9IF8ubWVtb2l6ZShmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgKiAgIHJldHVybiBzdHJpbmcudG9VcHBlckNhc2UoKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHVwcGVyQ2FzZSgnZnJlZCcpO1xuICAgICAqIC8vID0+ICdGUkVEJ1xuICAgICAqXG4gICAgICogLy8gbW9kaWZ5aW5nIHRoZSByZXN1bHQgY2FjaGVcbiAgICAgKiB1cHBlckNhc2UuY2FjaGUuc2V0KCdmcmVkJywgJ0JBUk5FWScpO1xuICAgICAqIHVwcGVyQ2FzZSgnZnJlZCcpO1xuICAgICAqIC8vID0+ICdCQVJORVknXG4gICAgICpcbiAgICAgKiAvLyByZXBsYWNpbmcgYF8ubWVtb2l6ZS5DYWNoZWBcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ3VzZXInOiAnYmFybmV5JyB9O1xuICAgICAqIHZhciBpZGVudGl0eSA9IF8ubWVtb2l6ZShfLmlkZW50aXR5KTtcbiAgICAgKlxuICAgICAqIGlkZW50aXR5KG9iamVjdCk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdmcmVkJyB9XG4gICAgICogaWRlbnRpdHkob3RoZXIpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqXG4gICAgICogXy5tZW1vaXplLkNhY2hlID0gV2Vha01hcDtcbiAgICAgKiB2YXIgaWRlbnRpdHkgPSBfLm1lbW9pemUoXy5pZGVudGl0eSk7XG4gICAgICpcbiAgICAgKiBpZGVudGl0eShvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIGlkZW50aXR5KG90aGVyKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1lbW9pemUoZnVuYywgcmVzb2x2ZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nIHx8IChyZXNvbHZlciAmJiB0eXBlb2YgcmVzb2x2ZXIgIT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgdmFyIG1lbW9pemVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAga2V5ID0gcmVzb2x2ZXIgPyByZXNvbHZlci5hcHBseSh0aGlzLCBhcmdzKSA6IGFyZ3NbMF0sXG4gICAgICAgICAgICBjYWNoZSA9IG1lbW9pemVkLmNhY2hlO1xuXG4gICAgICAgIGlmIChjYWNoZS5oYXMoa2V5KSkge1xuICAgICAgICAgIHJldHVybiBjYWNoZS5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgbWVtb2l6ZWQuY2FjaGUgPSBjYWNoZS5zZXQoa2V5LCByZXN1bHQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICAgIG1lbW9pemVkLmNhY2hlID0gbmV3IG1lbW9pemUuQ2FjaGU7XG4gICAgICByZXR1cm4gbWVtb2l6ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcnVucyBlYWNoIGFyZ3VtZW50IHRocm91Z2ggYSBjb3JyZXNwb25kaW5nXG4gICAgICogdHJhbnNmb3JtIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW3RyYW5zZm9ybXNdIFRoZSBmdW5jdGlvbnMgdG8gdHJhbnNmb3JtXG4gICAgICogYXJndW1lbnRzLCBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBmdW5jdGlvbnMgb3IgYXJyYXlzIG9mIGZ1bmN0aW9ucy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZG91YmxlZChuKSB7XG4gICAgICogICByZXR1cm4gbiAqIDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgbW9kZGVkID0gXy5tb2RBcmdzKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHJldHVybiBbeCwgeV07XG4gICAgICogfSwgc3F1YXJlLCBkb3VibGVkKTtcbiAgICAgKlxuICAgICAqIG1vZGRlZCgxLCAyKTtcbiAgICAgKiAvLyA9PiBbMSwgNF1cbiAgICAgKlxuICAgICAqIG1vZGRlZCg1LCAxMCk7XG4gICAgICogLy8gPT4gWzI1LCAyMF1cbiAgICAgKi9cbiAgICB2YXIgbW9kQXJncyA9IHJlc3RQYXJhbShmdW5jdGlvbihmdW5jLCB0cmFuc2Zvcm1zKSB7XG4gICAgICB0cmFuc2Zvcm1zID0gYmFzZUZsYXR0ZW4odHJhbnNmb3Jtcyk7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJyB8fCAhYXJyYXlFdmVyeSh0cmFuc2Zvcm1zLCBiYXNlSXNGdW5jdGlvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IHRyYW5zZm9ybXMubGVuZ3RoO1xuICAgICAgcmV0dXJuIHJlc3RQYXJhbShmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgIHZhciBpbmRleCA9IG5hdGl2ZU1pbihhcmdzLmxlbmd0aCwgbGVuZ3RoKTtcbiAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IHRyYW5zZm9ybXNbaW5kZXhdKGFyZ3NbaW5kZXhdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgbmVnYXRlcyB0aGUgcmVzdWx0IG9mIHRoZSBwcmVkaWNhdGUgYGZ1bmNgLiBUaGVcbiAgICAgKiBgZnVuY2AgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGVcbiAgICAgKiBjcmVhdGVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBwcmVkaWNhdGUgdG8gbmVnYXRlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBpc0V2ZW4obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5maWx0ZXIoWzEsIDIsIDMsIDQsIDUsIDZdLCBfLm5lZ2F0ZShpc0V2ZW4pKTtcbiAgICAgKiAvLyA9PiBbMSwgMywgNV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBuZWdhdGUocHJlZGljYXRlKSB7XG4gICAgICBpZiAodHlwZW9mIHByZWRpY2F0ZSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICFwcmVkaWNhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXMgcmVzdHJpY3RlZCB0byBpbnZva2luZyBgZnVuY2Agb25jZS4gUmVwZWF0IGNhbGxzXG4gICAgICogdG8gdGhlIGZ1bmN0aW9uIHJldHVybiB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGNhbGwuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgaW5pdGlhbGl6ZSA9IF8ub25jZShjcmVhdGVBcHBsaWNhdGlvbik7XG4gICAgICogaW5pdGlhbGl6ZSgpO1xuICAgICAqIGluaXRpYWxpemUoKTtcbiAgICAgKiAvLyBgaW5pdGlhbGl6ZWAgaW52b2tlcyBgY3JlYXRlQXBwbGljYXRpb25gIG9uY2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBvbmNlKGZ1bmMpIHtcbiAgICAgIHJldHVybiBiZWZvcmUoMiwgZnVuYyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBgcGFydGlhbGAgYXJndW1lbnRzIHByZXBlbmRlZFxuICAgICAqIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBuZXcgZnVuY3Rpb24uIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYmluZGAgZXhjZXB0XG4gICAgICogaXQgZG9lcyAqKm5vdCoqIGFsdGVyIHRoZSBgdGhpc2AgYmluZGluZy5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5wYXJ0aWFsLnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2VzIG5vdCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgcGFydGlhbGx5XG4gICAgICogYXBwbGllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkgYXJndW1lbnRzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhcnRpYWxseSBhcHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZ3JlZXQgPSBmdW5jdGlvbihncmVldGluZywgbmFtZSkge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgbmFtZTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWwoZ3JlZXQsICdoZWxsbycpO1xuICAgICAqIHNheUhlbGxvVG8oJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHBsYWNlaG9sZGVyc1xuICAgICAqIHZhciBncmVldEZyZWQgPSBfLnBhcnRpYWwoZ3JlZXQsIF8sICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsID0gY3JlYXRlUGFydGlhbChQQVJUSUFMX0ZMQUcpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wYXJ0aWFsYCBleGNlcHQgdGhhdCBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHNcbiAgICAgKiBhcmUgYXBwZW5kZWQgdG8gdGhvc2UgcHJvdmlkZWQgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5wYXJ0aWFsUmlnaHQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpY1xuICAgICAqIGJ1aWxkcywgbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXMgbm90IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBwYXJ0aWFsbHlcbiAgICAgKiBhcHBsaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHBhcnRpYWxseSBhcHBseSBhcmd1bWVudHMgdG8uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFydGlhbGx5IGFwcGxpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBncmVldCA9IGZ1bmN0aW9uKGdyZWV0aW5nLCBuYW1lKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyBuYW1lO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgZ3JlZXRGcmVkID0gXy5wYXJ0aWFsUmlnaHQoZ3JlZXQsICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgcGxhY2Vob2xkZXJzXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWxSaWdodChncmVldCwgJ2hlbGxvJywgXyk7XG4gICAgICogc2F5SGVsbG9UbygnZnJlZCcpO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsUmlnaHQgPSBjcmVhdGVQYXJ0aWFsKFBBUlRJQUxfUklHSFRfRkxBRyk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGFyZ3VtZW50cyBhcnJhbmdlZCBhY2NvcmRpbmdcbiAgICAgKiB0byB0aGUgc3BlY2lmaWVkIGluZGV4ZXMgd2hlcmUgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBmaXJzdCBpbmRleCBpc1xuICAgICAqIHByb3ZpZGVkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCwgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBzZWNvbmQgaW5kZXggaXNcbiAgICAgKiBwcm92aWRlZCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZWFycmFuZ2UgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW10pfSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcmd1bWVudCBpbmRleGVzLFxuICAgICAqICBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBpbmRleGVzIG9yIGFycmF5cyBvZiBpbmRleGVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgcmVhcmdlZCA9IF8ucmVhcmcoZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9LCAyLCAwLCAxKTtcbiAgICAgKlxuICAgICAqIHJlYXJnZWQoJ2InLCAnYycsICdhJylcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIHZhciBtYXAgPSBfLnJlYXJnKF8ubWFwLCBbMSwgMF0pO1xuICAgICAqIG1hcChmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAqIDM7XG4gICAgICogfSwgWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMywgNiwgOV1cbiAgICAgKi9cbiAgICB2YXIgcmVhcmcgPSByZXN0UGFyYW0oZnVuY3Rpb24oZnVuYywgaW5kZXhlcykge1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgUkVBUkdfRkxBRywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYmFzZUZsYXR0ZW4oaW5kZXhlcykpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlXG4gICAgICogY3JlYXRlZCBmdW5jdGlvbiBhbmQgYXJndW1lbnRzIGZyb20gYHN0YXJ0YCBhbmQgYmV5b25kIHByb3ZpZGVkIGFzIGFuIGFycmF5LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uIHRoZSBbcmVzdCBwYXJhbWV0ZXJdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0Z1bmN0aW9ucy9yZXN0X3BhcmFtZXRlcnMpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PWZ1bmMubGVuZ3RoLTFdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgcmVzdCBwYXJhbWV0ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBzYXkgPSBfLnJlc3RQYXJhbShmdW5jdGlvbih3aGF0LCBuYW1lcykge1xuICAgICAqICAgcmV0dXJuIHdoYXQgKyAnICcgKyBfLmluaXRpYWwobmFtZXMpLmpvaW4oJywgJykgK1xuICAgICAqICAgICAoXy5zaXplKG5hbWVzKSA+IDEgPyAnLCAmICcgOiAnJykgKyBfLmxhc3QobmFtZXMpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogc2F5KCdoZWxsbycsICdmcmVkJywgJ2Jhcm5leScsICdwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQsIGJhcm5leSwgJiBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlc3RQYXJhbShmdW5jLCBzdGFydCkge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSBuYXRpdmVNYXgoc3RhcnQgPT09IHVuZGVmaW5lZCA/IChmdW5jLmxlbmd0aCAtIDEpIDogKCtzdGFydCB8fCAwKSwgMCk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChhcmdzLmxlbmd0aCAtIHN0YXJ0LCAwKSxcbiAgICAgICAgICAgIHJlc3QgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgcmVzdFtpbmRleF0gPSBhcmdzW3N0YXJ0ICsgaW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoc3RhcnQpIHtcbiAgICAgICAgICBjYXNlIDA6IHJldHVybiBmdW5jLmNhbGwodGhpcywgcmVzdCk7XG4gICAgICAgICAgY2FzZSAxOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIGFyZ3NbMF0sIHJlc3QpO1xuICAgICAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzLCBhcmdzWzBdLCBhcmdzWzFdLCByZXN0KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3RoZXJBcmdzID0gQXJyYXkoc3RhcnQgKyAxKTtcbiAgICAgICAgaW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzdGFydCkge1xuICAgICAgICAgIG90aGVyQXJnc1tpbmRleF0gPSBhcmdzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBvdGhlckFyZ3Nbc3RhcnRdID0gcmVzdDtcbiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgb3RoZXJBcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlIGNyZWF0ZWRcbiAgICAgKiBmdW5jdGlvbiBhbmQgYW4gYXJyYXkgb2YgYXJndW1lbnRzIG11Y2ggbGlrZSBbYEZ1bmN0aW9uI2FwcGx5YF0oaHR0cHM6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMy40LjMpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uIHRoZSBbc3ByZWFkIG9wZXJhdG9yXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9PcGVyYXRvcnMvU3ByZWFkX29wZXJhdG9yKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHNwcmVhZCBhcmd1bWVudHMgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHNheSA9IF8uc3ByZWFkKGZ1bmN0aW9uKHdobywgd2hhdCkge1xuICAgICAqICAgcmV0dXJuIHdobyArICcgc2F5cyAnICsgd2hhdDtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHNheShbJ2ZyZWQnLCAnaGVsbG8nXSk7XG4gICAgICogLy8gPT4gJ2ZyZWQgc2F5cyBoZWxsbydcbiAgICAgKlxuICAgICAqIC8vIHdpdGggYSBQcm9taXNlXG4gICAgICogdmFyIG51bWJlcnMgPSBQcm9taXNlLmFsbChbXG4gICAgICogICBQcm9taXNlLnJlc29sdmUoNDApLFxuICAgICAqICAgUHJvbWlzZS5yZXNvbHZlKDM2KVxuICAgICAqIF0pO1xuICAgICAqXG4gICAgICogbnVtYmVycy50aGVuKF8uc3ByZWFkKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHJldHVybiB4ICsgeTtcbiAgICAgKiB9KSk7XG4gICAgICogLy8gPT4gYSBQcm9taXNlIG9mIDc2XG4gICAgICovXG4gICAgZnVuY3Rpb24gc3ByZWFkKGZ1bmMpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSkge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcnJheSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAgICAgKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICAgICAqIG1ldGhvZCB0byBjYW5jZWwgZGVsYXllZCBpbnZvY2F0aW9ucy4gUHJvdmlkZSBhbiBvcHRpb25zIG9iamVjdCB0byBpbmRpY2F0ZVxuICAgICAqIHRoYXQgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZVxuICAgICAqIGB3YWl0YCB0aW1lb3V0LiBTdWJzZXF1ZW50IGNhbGxzIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJuIHRoZVxuICAgICAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgY2FsbC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXMgaW52b2tlZFxuICAgICAqIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gaXNcbiAgICAgKiBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gICAgICpcbiAgICAgKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cDovL2RydXBhbG1vdGlvbi5jb20vYXJ0aWNsZS9kZWJvdW5jZS1hbmQtdGhyb3R0bGUtdmlzdWFsLWV4cGxhbmF0aW9uKVxuICAgICAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8udGhyb3R0bGVgIGFuZCBgXy5kZWJvdW5jZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gdGhyb3R0bGUgaW52b2NhdGlvbnMgdG8uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPXRydWVdIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmdcbiAgICAgKiAgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nXG4gICAgICogIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBhdm9pZCBleGNlc3NpdmVseSB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgc2Nyb2xsaW5nXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCkpO1xuICAgICAqXG4gICAgICogLy8gaW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXNcbiAgICAgKiBqUXVlcnkoJy5pbnRlcmFjdGl2ZScpLm9uKCdjbGljaycsIF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7XG4gICAgICogICAndHJhaWxpbmcnOiBmYWxzZVxuICAgICAqIH0pKTtcbiAgICAgKlxuICAgICAqIC8vIGNhbmNlbCBhIHRyYWlsaW5nIHRocm90dGxlZCBjYWxsXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgdGhyb3R0bGVkLmNhbmNlbCk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgICAgdmFyIGxlYWRpbmcgPSB0cnVlLFxuICAgICAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgICAgIGxlYWRpbmcgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgICAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHsgJ2xlYWRpbmcnOiBsZWFkaW5nLCAnbWF4V2FpdCc6ICt3YWl0LCAndHJhaWxpbmcnOiB0cmFpbGluZyB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwcm92aWRlcyBgdmFsdWVgIHRvIHRoZSB3cmFwcGVyIGZ1bmN0aW9uIGFzIGl0c1xuICAgICAqIGZpcnN0IGFyZ3VtZW50LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGZ1bmN0aW9uIGFyZVxuICAgICAqIGFwcGVuZGVkIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSB3cmFwcGVyIGZ1bmN0aW9uLiBUaGUgd3JhcHBlciBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBwZXIgVGhlIHdyYXBwZXIgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBwID0gXy53cmFwKF8uZXNjYXBlLCBmdW5jdGlvbihmdW5jLCB0ZXh0KSB7XG4gICAgICogICByZXR1cm4gJzxwPicgKyBmdW5jKHRleHQpICsgJzwvcD4nO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogcCgnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnPHA+ZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzPC9wPidcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwKHZhbHVlLCB3cmFwcGVyKSB7XG4gICAgICB3cmFwcGVyID0gd3JhcHBlciA9PSBudWxsID8gaWRlbnRpdHkgOiB3cmFwcGVyO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIod3JhcHBlciwgUEFSVElBTF9GTEFHLCB1bmRlZmluZWQsIFt2YWx1ZV0sIFtdKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHZhbHVlYC4gSWYgYGlzRGVlcGAgaXMgYHRydWVgIG5lc3RlZCBvYmplY3RzIGFyZSBjbG9uZWQsXG4gICAgICogb3RoZXJ3aXNlIHRoZXkgYXJlIGFzc2lnbmVkIGJ5IHJlZmVyZW5jZS4gSWYgYGN1c3RvbWl6ZXJgIGlzIHByb3ZpZGVkIGl0IGlzXG4gICAgICogaW52b2tlZCB0byBwcm9kdWNlIHRoZSBjbG9uZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIGNsb25pbmcgaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgYm91bmQgdG9cbiAgICAgKiBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnQ7ICh2YWx1ZSBbLCBpbmRleHxrZXksIG9iamVjdF0pLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlXG4gICAgICogW3N0cnVjdHVyZWQgY2xvbmUgYWxnb3JpdGhtXShodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sNS9pbmZyYXN0cnVjdHVyZS5odG1sI2ludGVybmFsLXN0cnVjdHVyZWQtY2xvbmluZy1hbGdvcml0aG0pLlxuICAgICAqIFRoZSBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYGFyZ3VtZW50c2Agb2JqZWN0cyBhbmQgb2JqZWN0cyBjcmVhdGVkIGJ5XG4gICAgICogY29uc3RydWN0b3JzIG90aGVyIHRoYW4gYE9iamVjdGAgYXJlIGNsb25lZCB0byBwbGFpbiBgT2JqZWN0YCBvYmplY3RzLiBBblxuICAgICAqIGVtcHR5IG9iamVjdCBpcyByZXR1cm5lZCBmb3IgdW5jbG9uZWFibGUgdmFsdWVzIHN1Y2ggYXMgZnVuY3Rpb25zLCBET00gbm9kZXMsXG4gICAgICogTWFwcywgU2V0cywgYW5kIFdlYWtNYXBzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY3VzdG9taXplcmAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogdmFyIHNoYWxsb3cgPSBfLmNsb25lKHVzZXJzKTtcbiAgICAgKiBzaGFsbG93WzBdID09PSB1c2Vyc1swXTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiB2YXIgZGVlcCA9IF8uY2xvbmUodXNlcnMsIHRydWUpO1xuICAgICAqIGRlZXBbMF0gPT09IHVzZXJzWzBdO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBhIGN1c3RvbWl6ZXIgY2FsbGJhY2tcbiAgICAgKiB2YXIgZWwgPSBfLmNsb25lKGRvY3VtZW50LmJvZHksIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICBpZiAoXy5pc0VsZW1lbnQodmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiB2YWx1ZS5jbG9uZU5vZGUoZmFsc2UpO1xuICAgICAqICAgfVxuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogZWwgPT09IGRvY3VtZW50LmJvZHlcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqIGVsLm5vZGVOYW1lXG4gICAgICogLy8gPT4gQk9EWVxuICAgICAqIGVsLmNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZSh2YWx1ZSwgaXNEZWVwLCBjdXN0b21pemVyLCB0aGlzQXJnKSB7XG4gICAgICBpZiAoaXNEZWVwICYmIHR5cGVvZiBpc0RlZXAgIT0gJ2Jvb2xlYW4nICYmIGlzSXRlcmF0ZWVDYWxsKHZhbHVlLCBpc0RlZXAsIGN1c3RvbWl6ZXIpKSB7XG4gICAgICAgIGlzRGVlcCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAodHlwZW9mIGlzRGVlcCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXNBcmcgPSBjdXN0b21pemVyO1xuICAgICAgICBjdXN0b21pemVyID0gaXNEZWVwO1xuICAgICAgICBpc0RlZXAgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nXG4gICAgICAgID8gYmFzZUNsb25lKHZhbHVlLCBpc0RlZXAsIGJpbmRDYWxsYmFjayhjdXN0b21pemVyLCB0aGlzQXJnLCAxKSlcbiAgICAgICAgOiBiYXNlQ2xvbmUodmFsdWUsIGlzRGVlcCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlZXAgY2xvbmUgb2YgYHZhbHVlYC4gSWYgYGN1c3RvbWl6ZXJgIGlzIHByb3ZpZGVkIGl0IGlzIGludm9rZWRcbiAgICAgKiB0byBwcm9kdWNlIHRoZSBjbG9uZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCBjbG9uaW5nXG4gICAgICogaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgYm91bmQgdG8gYHRoaXNBcmdgXG4gICAgICogYW5kIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnQ7ICh2YWx1ZSBbLCBpbmRleHxrZXksIG9iamVjdF0pLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlXG4gICAgICogW3N0cnVjdHVyZWQgY2xvbmUgYWxnb3JpdGhtXShodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sNS9pbmZyYXN0cnVjdHVyZS5odG1sI2ludGVybmFsLXN0cnVjdHVyZWQtY2xvbmluZy1hbGdvcml0aG0pLlxuICAgICAqIFRoZSBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYGFyZ3VtZW50c2Agb2JqZWN0cyBhbmQgb2JqZWN0cyBjcmVhdGVkIGJ5XG4gICAgICogY29uc3RydWN0b3JzIG90aGVyIHRoYW4gYE9iamVjdGAgYXJlIGNsb25lZCB0byBwbGFpbiBgT2JqZWN0YCBvYmplY3RzLiBBblxuICAgICAqIGVtcHR5IG9iamVjdCBpcyByZXR1cm5lZCBmb3IgdW5jbG9uZWFibGUgdmFsdWVzIHN1Y2ggYXMgZnVuY3Rpb25zLCBET00gbm9kZXMsXG4gICAgICogTWFwcywgU2V0cywgYW5kIFdlYWtNYXBzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBkZWVwIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY3VzdG9taXplcmAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiB2YXIgZGVlcCA9IF8uY2xvbmVEZWVwKHVzZXJzKTtcbiAgICAgKiBkZWVwWzBdID09PSB1c2Vyc1swXTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgYSBjdXN0b21pemVyIGNhbGxiYWNrXG4gICAgICogdmFyIGVsID0gXy5jbG9uZURlZXAoZG9jdW1lbnQuYm9keSwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIGlmIChfLmlzRWxlbWVudCh2YWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIHZhbHVlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGVsID09PSBkb2N1bWVudC5ib2R5XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKiBlbC5ub2RlTmFtZVxuICAgICAqIC8vID0+IEJPRFlcbiAgICAgKiBlbC5jaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGVlcCh2YWx1ZSwgY3VzdG9taXplciwgdGhpc0FyZykge1xuICAgICAgcmV0dXJuIHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbidcbiAgICAgICAgPyBiYXNlQ2xvbmUodmFsdWUsIHRydWUsIGJpbmRDYWxsYmFjayhjdXN0b21pemVyLCB0aGlzQXJnLCAxKSlcbiAgICAgICAgOiBiYXNlQ2xvbmUodmFsdWUsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ndCgzLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmd0KDMsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmd0KDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ3QodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPiBvdGhlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ3RlKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlID49IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcmd1bWVudHMoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQXJndW1lbnRzKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBpc0FycmF5TGlrZSh2YWx1ZSkgJiZcbiAgICAgICAgaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgJ2NhbGxlZScpICYmICFwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHZhbHVlLCAnY2FsbGVlJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhbiBgQXJyYXlgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzQXJyYXkgPSBuYXRpdmVJc0FycmF5IHx8IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBpc0xlbmd0aCh2YWx1ZS5sZW5ndGgpICYmIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09IGFycmF5VGFnO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYm9vbGVhbiBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQm9vbGVhbihmYWxzZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Jvb2xlYW4obnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdHJ1ZSB8fCB2YWx1ZSA9PT0gZmFsc2UgfHwgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gYm9vbFRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBEYXRlYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNEYXRlKG5ldyBEYXRlKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRGF0ZSgnTW9uIEFwcmlsIDIzIDIwMTInKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRGF0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gZGF0ZVRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIERPTSBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIERPTSBlbGVtZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFbGVtZW50KGRvY3VtZW50LmJvZHkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbGVtZW50KCc8Ym9keT4nKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRWxlbWVudCh2YWx1ZSkge1xuICAgICAgcmV0dXJuICEhdmFsdWUgJiYgdmFsdWUubm9kZVR5cGUgPT09IDEgJiYgaXNPYmplY3RMaWtlKHZhbHVlKSAmJiAhaXNQbGFpbk9iamVjdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgZW1wdHkuIEEgdmFsdWUgaXMgY29uc2lkZXJlZCBlbXB0eSB1bmxlc3MgaXQgaXMgYW5cbiAgICAgKiBgYXJndW1lbnRzYCBvYmplY3QsIGFycmF5LCBzdHJpbmcsIG9yIGpRdWVyeS1saWtlIGNvbGxlY3Rpb24gd2l0aCBhIGxlbmd0aFxuICAgICAqIGdyZWF0ZXIgdGhhbiBgMGAgb3IgYW4gb2JqZWN0IHdpdGggb3duIGVudW1lcmFibGUgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBlbXB0eSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHRydWUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSgxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHsgJ2EnOiAxIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBpZiAoaXNBcnJheUxpa2UodmFsdWUpICYmIChpc0FycmF5KHZhbHVlKSB8fCBpc1N0cmluZyh2YWx1ZSkgfHwgaXNBcmd1bWVudHModmFsdWUpIHx8XG4gICAgICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaXNGdW5jdGlvbih2YWx1ZS5zcGxpY2UpKSkpIHtcbiAgICAgICAgcmV0dXJuICF2YWx1ZS5sZW5ndGg7XG4gICAgICB9XG4gICAgICByZXR1cm4gIWtleXModmFsdWUpLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlXG4gICAgICogZXF1aXZhbGVudC4gSWYgYGN1c3RvbWl6ZXJgIGlzIHByb3ZpZGVkIGl0IGlzIGludm9rZWQgdG8gY29tcGFyZSB2YWx1ZXMuXG4gICAgICogSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAgY29tcGFyaXNvbnMgYXJlIGhhbmRsZWQgYnkgdGhlIG1ldGhvZFxuICAgICAqIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM6ICh2YWx1ZSwgb3RoZXIgWywgaW5kZXh8a2V5XSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2Qgc3VwcG9ydHMgY29tcGFyaW5nIGFycmF5cywgYm9vbGVhbnMsIGBEYXRlYCBvYmplY3RzLFxuICAgICAqIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsIGFuZCBzdHJpbmdzLiBPYmplY3RzIGFyZSBjb21wYXJlZCBieVxuICAgICAqIHRoZWlyIG93biwgbm90IGluaGVyaXRlZCwgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLiBGdW5jdGlvbnMgYW5kIERPTSBub2Rlc1xuICAgICAqIGFyZSAqKm5vdCoqIHN1cHBvcnRlZC4gUHJvdmlkZSBhIGN1c3RvbWl6ZXIgZnVuY3Rpb24gdG8gZXh0ZW5kIHN1cHBvcnRcbiAgICAgKiBmb3IgY29tcGFyaW5nIG90aGVyIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBlcVxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIHZhbHVlIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY3VzdG9taXplcmAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKiB2YXIgb3RoZXIgPSB7ICd1c2VyJzogJ2ZyZWQnIH07XG4gICAgICpcbiAgICAgKiBvYmplY3QgPT0gb3RoZXI7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbChvYmplY3QsIG90aGVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBhIGN1c3RvbWl6ZXIgY2FsbGJhY2tcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2hlbGxvJywgJ2dvb2RieWUnXTtcbiAgICAgKiB2YXIgb3RoZXIgPSBbJ2hpJywgJ2dvb2RieWUnXTtcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbChhcnJheSwgb3RoZXIsIGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAqICAgaWYgKF8uZXZlcnkoW3ZhbHVlLCBvdGhlcl0sIFJlZ0V4cC5wcm90b3R5cGUudGVzdCwgL15oKD86aXxlbGxvKSQvKSkge1xuICAgICAqICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcXVhbCh2YWx1ZSwgb3RoZXIsIGN1c3RvbWl6ZXIsIHRoaXNBcmcpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gYmluZENhbGxiYWNrKGN1c3RvbWl6ZXIsIHRoaXNBcmcsIDMpIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKHZhbHVlLCBvdGhlcikgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyLCBjdXN0b21pemVyKSA6ICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGBFcnJvcmAsIGBFdmFsRXJyb3JgLCBgUmFuZ2VFcnJvcmAsIGBSZWZlcmVuY2VFcnJvcmAsXG4gICAgICogYFN5bnRheEVycm9yYCwgYFR5cGVFcnJvcmAsIG9yIGBVUklFcnJvcmAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBlcnJvciBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Vycm9yKG5ldyBFcnJvcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Vycm9yKEVycm9yKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRXJyb3IodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIHR5cGVvZiB2YWx1ZS5tZXNzYWdlID09ICdzdHJpbmcnICYmIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09IGVycm9yVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgZmluaXRlIHByaW1pdGl2ZSBudW1iZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gW2BOdW1iZXIuaXNGaW5pdGVgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1udW1iZXIuaXNmaW5pdGUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGZpbml0ZSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSgxMCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSgnMTAnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSh0cnVlKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZShPYmplY3QoMTApKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZShJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Zpbml0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiBuYXRpdmVJc0Zpbml0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBGdW5jdGlvbmAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRnVuY3Rpb24oXyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Z1bmN0aW9uKC9hYmMvKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIC8vIFRoZSB1c2Ugb2YgYE9iamVjdCN0b1N0cmluZ2AgYXZvaWRzIGlzc3VlcyB3aXRoIHRoZSBgdHlwZW9mYCBvcGVyYXRvclxuICAgICAgLy8gaW4gb2xkZXIgdmVyc2lvbnMgb2YgQ2hyb21lIGFuZCBTYWZhcmkgd2hpY2ggcmV0dXJuICdmdW5jdGlvbicgZm9yIHJlZ2V4ZXNcbiAgICAgIC8vIGFuZCBTYWZhcmkgOCBlcXVpdmFsZW50cyB3aGljaCByZXR1cm4gJ29iamVjdCcgZm9yIHR5cGVkIGFycmF5IGNvbnN0cnVjdG9ycy5cbiAgICAgIHJldHVybiBpc09iamVjdCh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gZnVuY1RhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGUgW2xhbmd1YWdlIHR5cGVdKGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDgpIG9mIGBPYmplY3RgLlxuICAgICAqIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdCh7fSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QoMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgICAgLy8gQXZvaWQgYSBWOCBKSVQgYnVnIGluIENocm9tZSAxOS0yMC5cbiAgICAgIC8vIFNlZSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjI5MSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICByZXR1cm4gISF2YWx1ZSAmJiAodHlwZSA9PSAnb2JqZWN0JyB8fCB0eXBlID09ICdmdW5jdGlvbicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYG9iamVjdGAgYW5kIGBzb3VyY2VgIHRvIGRldGVybWluZSBpZlxuICAgICAqIGBvYmplY3RgIGNvbnRhaW5zIGVxdWl2YWxlbnQgcHJvcGVydHkgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgaXMgcHJvdmlkZWRcbiAgICAgKiBpdCBpcyBpbnZva2VkIHRvIGNvbXBhcmUgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIGNvbXBhcmlzb25zIGFyZSBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBib3VuZFxuICAgICAqIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBvdGhlciwgaW5kZXh8a2V5KS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBzdXBwb3J0cyBjb21wYXJpbmcgcHJvcGVydGllcyBvZiBhcnJheXMsIGJvb2xlYW5zLFxuICAgICAqIGBEYXRlYCBvYmplY3RzLCBudW1iZXJzLCBgT2JqZWN0YCBvYmplY3RzLCByZWdleGVzLCBhbmQgc3RyaW5ncy4gRnVuY3Rpb25zXG4gICAgICogYW5kIERPTSBub2RlcyBhcmUgKipub3QqKiBzdXBwb3J0ZWQuIFByb3ZpZGUgYSBjdXN0b21pemVyIGZ1bmN0aW9uIHRvIGV4dGVuZFxuICAgICAqIHN1cHBvcnQgZm9yIGNvbXBhcmluZyBvdGhlciB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgdmFsdWUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjdXN0b21pemVyYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJywgJ2FnZSc6IDQwIH07XG4gICAgICpcbiAgICAgKiBfLmlzTWF0Y2gob2JqZWN0LCB7ICdhZ2UnOiA0MCB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTWF0Y2gob2JqZWN0LCB7ICdhZ2UnOiAzNiB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgYSBjdXN0b21pemVyIGNhbGxiYWNrXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2dyZWV0aW5nJzogJ2hlbGxvJyB9O1xuICAgICAqIHZhciBzb3VyY2UgPSB7ICdncmVldGluZyc6ICdoaScgfTtcbiAgICAgKlxuICAgICAqIF8uaXNNYXRjaChvYmplY3QsIHNvdXJjZSwgZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICogICByZXR1cm4gXy5ldmVyeShbdmFsdWUsIG90aGVyXSwgUmVnRXhwLnByb3RvdHlwZS50ZXN0LCAvXmgoPzppfGVsbG8pJC8pIHx8IHVuZGVmaW5lZDtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNNYXRjaChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplciwgdGhpc0FyZykge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBiaW5kQ2FsbGJhY2soY3VzdG9taXplciwgdGhpc0FyZywgMykgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZUlzTWF0Y2gob2JqZWN0LCBnZXRNYXRjaERhdGEoc291cmNlKSwgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYE5hTmAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgbm90IHRoZSBzYW1lIGFzIFtgaXNOYU5gXShodHRwczovL2VzNS5naXRodWIuaW8vI3gxNS4xLjIuNClcbiAgICAgKiB3aGljaCByZXR1cm5zIGB0cnVlYCBmb3IgYHVuZGVmaW5lZGAgYW5kIG90aGVyIG5vbi1udW1lcmljIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYE5hTmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc05hTihOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4obmV3IE51bWJlcihOYU4pKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBpc05hTih1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4odW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmFOKHZhbHVlKSB7XG4gICAgICAvLyBBbiBgTmFOYCBwcmltaXRpdmUgaXMgdGhlIG9ubHkgdmFsdWUgdGhhdCBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLlxuICAgICAgLy8gUGVyZm9ybSB0aGUgYHRvU3RyaW5nVGFnYCBjaGVjayBmaXJzdCB0byBhdm9pZCBlcnJvcnMgd2l0aCBzb21lIGhvc3Qgb2JqZWN0cyBpbiBJRS5cbiAgICAgIHJldHVybiBpc051bWJlcih2YWx1ZSkgJiYgdmFsdWUgIT0gK3ZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbiwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmF0aXZlKEFycmF5LnByb3RvdHlwZS5wdXNoKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmF0aXZlKF8pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOYXRpdmUodmFsdWUpIHtcbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gcmVJc05hdGl2ZS50ZXN0KGZuVG9TdHJpbmcuY2FsbCh2YWx1ZSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgcmVJc0hvc3RDdG9yLnRlc3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBudWxsYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYG51bGxgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOdWxsKG51bGwpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdWxsKHZvaWQgMCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc051bGwodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYE51bWJlcmAgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUbyBleGNsdWRlIGBJbmZpbml0eWAsIGAtSW5maW5pdHlgLCBhbmQgYE5hTmAsIHdoaWNoIGFyZSBjbGFzc2lmaWVkXG4gICAgICogYXMgbnVtYmVycywgdXNlIHRoZSBgXy5pc0Zpbml0ZWAgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKDguNCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcihOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoJzguNCcpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOdW1iZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgfHwgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gbnVtYmVyVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHBsYWluIG9iamVjdCwgdGhhdCBpcywgYW4gb2JqZWN0IGNyZWF0ZWQgYnkgdGhlXG4gICAgICogYE9iamVjdGAgY29uc3RydWN0b3Igb3Igb25lIHdpdGggYSBgW1tQcm90b3R5cGVdXWAgb2YgYG51bGxgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGFzc3VtZXMgb2JqZWN0cyBjcmVhdGVkIGJ5IHRoZSBgT2JqZWN0YCBjb25zdHJ1Y3RvclxuICAgICAqIGhhdmUgbm8gaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QobmV3IEZvbyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoeyAneCc6IDAsICd5JzogMCB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoT2JqZWN0LmNyZWF0ZShudWxsKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIHZhciBDdG9yO1xuXG4gICAgICAvLyBFeGl0IGVhcmx5IGZvciBub24gYE9iamVjdGAgb2JqZWN0cy5cbiAgICAgIGlmICghKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gb2JqZWN0VGFnICYmICFpc0FyZ3VtZW50cyh2YWx1ZSkpIHx8XG4gICAgICAgICAgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnY29uc3RydWN0b3InKSAmJiAoQ3RvciA9IHZhbHVlLmNvbnN0cnVjdG9yLCB0eXBlb2YgQ3RvciA9PSAnZnVuY3Rpb24nICYmICEoQ3RvciBpbnN0YW5jZW9mIEN0b3IpKSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gSUUgPCA5IGl0ZXJhdGVzIGluaGVyaXRlZCBwcm9wZXJ0aWVzIGJlZm9yZSBvd24gcHJvcGVydGllcy4gSWYgdGhlIGZpcnN0XG4gICAgICAvLyBpdGVyYXRlZCBwcm9wZXJ0eSBpcyBhbiBvYmplY3QncyBvd24gcHJvcGVydHkgdGhlbiB0aGVyZSBhcmUgbm8gaW5oZXJpdGVkXG4gICAgICAvLyBlbnVtZXJhYmxlIHByb3BlcnRpZXMuXG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgLy8gSW4gbW9zdCBlbnZpcm9ubWVudHMgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMgYXJlIGl0ZXJhdGVkIGJlZm9yZVxuICAgICAgLy8gaXRzIGluaGVyaXRlZCBwcm9wZXJ0aWVzLiBJZiB0aGUgbGFzdCBpdGVyYXRlZCBwcm9wZXJ0eSBpcyBhbiBvYmplY3Qnc1xuICAgICAgLy8gb3duIHByb3BlcnR5IHRoZW4gdGhlcmUgYXJlIG5vIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuXG4gICAgICBiYXNlRm9ySW4odmFsdWUsIGZ1bmN0aW9uKHN1YlZhbHVlLCBrZXkpIHtcbiAgICAgICAgcmVzdWx0ID0ga2V5O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgfHwgaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgcmVzdWx0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFJlZ0V4cGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzUmVnRXhwKC9hYmMvKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzUmVnRXhwKCcvYWJjLycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNSZWdFeHAodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdCh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gcmVnZXhwVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3RyaW5nYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU3RyaW5nKCdhYmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU3RyaW5nKDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNTdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHwgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gc3RyaW5nVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgdHlwZWQgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNUeXBlZEFycmF5KG5ldyBVaW50OEFycmF5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzVHlwZWRBcnJheShbXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1R5cGVkQXJyYXkodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgISF0eXBlZEFycmF5VGFnc1tvYmpUb1N0cmluZy5jYWxsKHZhbHVlKV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGB1bmRlZmluZWRgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNVbmRlZmluZWQodm9pZCAwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzVW5kZWZpbmVkKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sdCgxLCAzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmx0KDMsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmx0KDMsIDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbHQodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPCBvdGhlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubHRlKDEsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHRlKDMsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHRlKDMsIDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbHRlKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlIDw9IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIChmdW5jdGlvbigpIHtcbiAgICAgKiAgIHJldHVybiBfLnRvQXJyYXkoYXJndW1lbnRzKS5zbGljZSgxKTtcbiAgICAgKiB9KDEsIDIsIDMpKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0FycmF5KHZhbHVlKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gdmFsdWUgPyBnZXRMZW5ndGgodmFsdWUpIDogMDtcbiAgICAgIGlmICghaXNMZW5ndGgobGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gdmFsdWVzKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheUNvcHkodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBwbGFpbiBvYmplY3QgZmxhdHRlbmluZyBpbmhlcml0ZWQgZW51bWVyYWJsZVxuICAgICAqIHByb3BlcnRpZXMgb2YgYHZhbHVlYCB0byBvd24gcHJvcGVydGllcyBvZiB0aGUgcGxhaW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBwbGFpbiBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ2EnOiAxIH0sIG5ldyBGb28pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqXG4gICAgICogXy5hc3NpZ24oeyAnYSc6IDEgfSwgXy50b1BsYWluT2JqZWN0KG5ldyBGb28pKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlQ29weSh2YWx1ZSwga2V5c0luKHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgbWVyZ2VzIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgdGhlIHNvdXJjZSBvYmplY3QocyksIHRoYXRcbiAgICAgKiBkb24ndCByZXNvbHZlIHRvIGB1bmRlZmluZWRgIGludG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdC4gU3Vic2VxdWVudCBzb3VyY2VzXG4gICAgICogb3ZlcndyaXRlIHByb3BlcnR5IGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHNvdXJjZXMuIElmIGBjdXN0b21pemVyYCBpc1xuICAgICAqIHByb3ZpZGVkIGl0IGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgbWVyZ2VkIHZhbHVlcyBvZiB0aGUgZGVzdGluYXRpb24gYW5kXG4gICAgICogc291cmNlIHByb3BlcnRpZXMuIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgIG1lcmdpbmcgaXMgaGFuZGxlZFxuICAgICAqIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWRcbiAgICAgKiB3aXRoIGZpdmUgYXJndW1lbnRzOiAob2JqZWN0VmFsdWUsIHNvdXJjZVZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IFtzb3VyY2VzXSBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY3VzdG9taXplcmAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2RhdGEnOiBbeyAndXNlcic6ICdiYXJuZXknIH0sIHsgJ3VzZXInOiAnZnJlZCcgfV1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGFnZXMgPSB7XG4gICAgICogICAnZGF0YSc6IFt7ICdhZ2UnOiAzNiB9LCB7ICdhZ2UnOiA0MCB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1lcmdlKHVzZXJzLCBhZ2VzKTtcbiAgICAgKiAvLyA9PiB7ICdkYXRhJzogW3sgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sIHsgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCB9XSB9XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBhIGN1c3RvbWl6ZXIgY2FsbGJhY2tcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ2ZydWl0cyc6IFsnYXBwbGUnXSxcbiAgICAgKiAgICd2ZWdldGFibGVzJzogWydiZWV0J11cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIG90aGVyID0ge1xuICAgICAqICAgJ2ZydWl0cyc6IFsnYmFuYW5hJ10sXG4gICAgICogICAndmVnZXRhYmxlcyc6IFsnY2Fycm90J11cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5tZXJnZShvYmplY3QsIG90aGVyLCBmdW5jdGlvbihhLCBiKSB7XG4gICAgICogICBpZiAoXy5pc0FycmF5KGEpKSB7XG4gICAgICogICAgIHJldHVybiBhLmNvbmNhdChiKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdmcnVpdHMnOiBbJ2FwcGxlJywgJ2JhbmFuYSddLCAndmVnZXRhYmxlcyc6IFsnYmVldCcsICdjYXJyb3QnXSB9XG4gICAgICovXG4gICAgdmFyIG1lcmdlID0gY3JlYXRlQXNzaWduZXIoYmFzZU1lcmdlKTtcblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0KHMpIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdC4gU3Vic2VxdWVudCBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyBzb3VyY2VzLlxuICAgICAqIElmIGBjdXN0b21pemVyYCBpcyBwcm92aWRlZCBpdCBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIGZpdmUgYXJndW1lbnRzOlxuICAgICAqIChvYmplY3RWYWx1ZSwgc291cmNlVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAgYW5kIGlzIGJhc2VkIG9uXG4gICAgICogW2BPYmplY3QuYXNzaWduYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LmFzc2lnbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgZXh0ZW5kXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjdXN0b21pemVyYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmFzc2lnbih7ICd1c2VyJzogJ2Jhcm5leScgfSwgeyAnYWdlJzogNDAgfSwgeyAndXNlcic6ICdmcmVkJyB9KTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgYSBjdXN0b21pemVyIGNhbGxiYWNrXG4gICAgICogdmFyIGRlZmF1bHRzID0gXy5wYXJ0aWFsUmlnaHQoXy5hc3NpZ24sIGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQodmFsdWUpID8gb3RoZXIgOiB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGRlZmF1bHRzKHsgJ3VzZXInOiAnYmFybmV5JyB9LCB7ICdhZ2UnOiAzNiB9LCB7ICd1c2VyJzogJ2ZyZWQnIH0pO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHJldHVybiBjdXN0b21pemVyXG4gICAgICAgID8gYXNzaWduV2l0aChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplcilcbiAgICAgICAgOiBiYXNlQXNzaWduKG9iamVjdCwgc291cmNlKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGUgZ2l2ZW4gYHByb3RvdHlwZWAgb2JqZWN0LiBJZiBhXG4gICAgICogYHByb3BlcnRpZXNgIG9iamVjdCBpcyBwcm92aWRlZCBpdHMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBhcmUgYXNzaWduZWRcbiAgICAgKiB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHByb3RvdHlwZSBUaGUgb2JqZWN0IHRvIGluaGVyaXQgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3Byb3BlcnRpZXNdIFRoZSBwcm9wZXJ0aWVzIHRvIGFzc2lnbiB0byB0aGUgb2JqZWN0LlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIFNoYXBlKCkge1xuICAgICAqICAgdGhpcy54ID0gMDtcbiAgICAgKiAgIHRoaXMueSA9IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQ2lyY2xlKCkge1xuICAgICAqICAgU2hhcGUuY2FsbCh0aGlzKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBDaXJjbGUucHJvdG90eXBlID0gXy5jcmVhdGUoU2hhcGUucHJvdG90eXBlLCB7XG4gICAgICogICAnY29uc3RydWN0b3InOiBDaXJjbGVcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHZhciBjaXJjbGUgPSBuZXcgQ2lyY2xlO1xuICAgICAqIGNpcmNsZSBpbnN0YW5jZW9mIENpcmNsZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjaXJjbGUgaW5zdGFuY2VvZiBTaGFwZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlKHByb3RvdHlwZSwgcHJvcGVydGllcywgZ3VhcmQpIHtcbiAgICAgIHZhciByZXN1bHQgPSBiYXNlQ3JlYXRlKHByb3RvdHlwZSk7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwocHJvdG90eXBlLCBwcm9wZXJ0aWVzLCBndWFyZCkpIHtcbiAgICAgICAgcHJvcGVydGllcyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9wZXJ0aWVzID8gYmFzZUFzc2lnbihyZXN1bHQsIHByb3BlcnRpZXMpIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0KHMpIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdCBmb3IgYWxsIGRlc3RpbmF0aW9uIHByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgLiBPbmNlIGFcbiAgICAgKiBwcm9wZXJ0eSBpcyBzZXQsIGFkZGl0aW9uYWwgdmFsdWVzIG9mIHRoZSBzYW1lIHByb3BlcnR5IGFyZSBpZ25vcmVkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmYXVsdHMoeyAndXNlcic6ICdiYXJuZXknIH0sIHsgJ2FnZSc6IDM2IH0sIHsgJ3VzZXInOiAnZnJlZCcgfSk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfVxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0cyA9IGNyZWF0ZURlZmF1bHRzKGFzc2lnbiwgYXNzaWduRGVmYXVsdHMpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5kZWZhdWx0c2AgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgYXNzaWduc1xuICAgICAqIGRlZmF1bHQgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRzRGVlcCh7ICd1c2VyJzogeyAnbmFtZSc6ICdiYXJuZXknIH0gfSwgeyAndXNlcic6IHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiAzNiB9IH0pO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9IH1cbiAgICAgKlxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0c0RlZXAgPSBjcmVhdGVEZWZhdWx0cyhtZXJnZSwgbWVyZ2VEZWZhdWx0cyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGtleSBvZiB0aGUgZmlyc3RcbiAgICAgKiBlbGVtZW50IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfSBSZXR1cm5zIHRoZSBrZXkgb2YgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2Jhcm5leSc6ICB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgICdmcmVkJzogICAgeyAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgJ3BlYmJsZXMnOiB7ICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsIGZ1bmN0aW9uKGNocikge1xuICAgICAqICAgcmV0dXJuIGNoci5hZ2UgPCA0MDtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnYmFybmV5JyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEtleSh1c2VycywgeyAnYWdlJzogMSwgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gJ3BlYmJsZXMnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsICdhY3RpdmUnLCBmYWxzZSk7XG4gICAgICogLy8gPT4gJ2ZyZWQnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICovXG4gICAgdmFyIGZpbmRLZXkgPSBjcmVhdGVGaW5kS2V5KGJhc2VGb3JPd24pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kS2V5YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYSBjb2xsZWN0aW9uIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYHByZWRpY2F0ZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICAgICAqIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfSBSZXR1cm5zIHRoZSBrZXkgb2YgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2Jhcm5leSc6ICB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgICdmcmVkJzogICAgeyAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgJ3BlYmJsZXMnOiB7ICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0S2V5KHVzZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBjaHIuYWdlIDwgNDA7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gcmV0dXJucyBgcGViYmxlc2AgYXNzdW1pbmcgYF8uZmluZEtleWAgcmV0dXJucyBgYmFybmV5YFxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZExhc3RLZXkodXNlcnMsIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiAnYmFybmV5J1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqL1xuICAgIHZhciBmaW5kTGFzdEtleSA9IGNyZWF0ZUZpbmRLZXkoYmFzZUZvck93blJpZ2h0KTtcblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdCBpbnZva2luZ1xuICAgICAqIGBpdGVyYXRlZWAgZm9yIGVhY2ggcHJvcGVydHkuIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGtleSwgb2JqZWN0KS4gSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0XG4gICAgICogaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JJbihuZXcgRm9vLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ2EnLCAnYicsIGFuZCAnYycgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICB2YXIgZm9ySW4gPSBjcmVhdGVGb3JJbihiYXNlRm9yKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9ySW5gIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllcyBvZlxuICAgICAqIGBvYmplY3RgIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvckluUmlnaHQobmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzICdjJywgJ2InLCBhbmQgJ2EnIGFzc3VtaW5nIGBfLmZvckluIGAgbG9ncyAnYScsICdiJywgYW5kICdjJ1xuICAgICAqL1xuICAgIHZhciBmb3JJblJpZ2h0ID0gY3JlYXRlRm9ySW4oYmFzZUZvclJpZ2h0KTtcblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBhbiBvYmplY3QgaW52b2tpbmcgYGl0ZXJhdGVlYFxuICAgICAqIGZvciBlYWNoIHByb3BlcnR5LiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aFxuICAgICAqIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBrZXksIG9iamVjdCkuIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb25cbiAgICAgKiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9yT3duKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyAnYScgYW5kICdiJyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIHZhciBmb3JPd24gPSBjcmVhdGVGb3JPd24oYmFzZUZvck93bik7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvck93bmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBwcm9wZXJ0aWVzIG9mXG4gICAgICogYG9iamVjdGAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9yT3duUmlnaHQobmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzICdiJyBhbmQgJ2EnIGFzc3VtaW5nIGBfLmZvck93bmAgbG9ncyAnYScgYW5kICdiJ1xuICAgICAqL1xuICAgIHZhciBmb3JPd25SaWdodCA9IGNyZWF0ZUZvck93bihiYXNlRm9yT3duUmlnaHQpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmcm9tIGFsbCBlbnVtZXJhYmxlIHByb3BlcnRpZXMsXG4gICAgICogb3duIGFuZCBpbmhlcml0ZWQsIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIG1ldGhvZHNcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zKF8pO1xuICAgICAqIC8vID0+IFsnYWZ0ZXInLCAnYXJ5JywgJ2Fzc2lnbicsIC4uLl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmdW5jdGlvbnMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gYmFzZUZ1bmN0aW9ucyhvYmplY3QsIGtleXNJbihvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0eSB2YWx1ZSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuIElmIHRoZSByZXNvbHZlZCB2YWx1ZSBpc1xuICAgICAqIGB1bmRlZmluZWRgIHRoZSBgZGVmYXVsdFZhbHVlYCBpcyB1c2VkIGluIGl0cyBwbGFjZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IFtkZWZhdWx0VmFsdWVdIFRoZSB2YWx1ZSByZXR1cm5lZCBpZiB0aGUgcmVzb2x2ZWQgdmFsdWUgaXMgYHVuZGVmaW5lZGAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCAnYVswXS5iLmMnKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLmdldChvYmplY3QsIFsnYScsICcwJywgJ2InLCAnYyddKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLmdldChvYmplY3QsICdhLmIuYycsICdkZWZhdWx0Jyk7XG4gICAgICogLy8gPT4gJ2RlZmF1bHQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0KG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBiYXNlR2V0KG9iamVjdCwgdG9QYXRoKHBhdGgpLCBwYXRoICsgJycpO1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gZGVmYXVsdFZhbHVlIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3QgcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgcGF0aGAgaXMgYSBkaXJlY3QgcHJvcGVydHksIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiB7ICdiJzogeyAnYyc6IDMgfSB9IH07XG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsICdhJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXMob2JqZWN0LCAnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsIFsnYScsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhcyhvYmplY3QsIHBhdGgpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHBhdGgpO1xuICAgICAgaWYgKCFyZXN1bHQgJiYgIWlzS2V5KHBhdGgpKSB7XG4gICAgICAgIHBhdGggPSB0b1BhdGgocGF0aCk7XG4gICAgICAgIG9iamVjdCA9IHBhdGgubGVuZ3RoID09IDEgPyBvYmplY3QgOiBiYXNlR2V0KG9iamVjdCwgYmFzZVNsaWNlKHBhdGgsIDAsIC0xKSk7XG4gICAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBwYXRoID0gbGFzdChwYXRoKTtcbiAgICAgICAgcmVzdWx0ID0gaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHBhdGgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoaXNMZW5ndGgob2JqZWN0Lmxlbmd0aCkgJiYgaXNJbmRleChwYXRoLCBvYmplY3QubGVuZ3RoKSAmJlxuICAgICAgICAoaXNBcnJheShvYmplY3QpIHx8IGlzQXJndW1lbnRzKG9iamVjdCkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgaW52ZXJ0ZWQga2V5cyBhbmQgdmFsdWVzIG9mIGBvYmplY3RgLlxuICAgICAqIElmIGBvYmplY3RgIGNvbnRhaW5zIGR1cGxpY2F0ZSB2YWx1ZXMsIHN1YnNlcXVlbnQgdmFsdWVzIG92ZXJ3cml0ZSBwcm9wZXJ0eVxuICAgICAqIGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHZhbHVlcyB1bmxlc3MgYG11bHRpVmFsdWVgIGlzIGB0cnVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW52ZXJ0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW211bHRpVmFsdWVdIEFsbG93IG11bHRpcGxlIHZhbHVlcyBwZXIga2V5LlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBpbnZlcnRlZCBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfTtcbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0KG9iamVjdCk7XG4gICAgICogLy8gPT4geyAnMSc6ICdjJywgJzInOiAnYicgfVxuICAgICAqXG4gICAgICogLy8gd2l0aCBgbXVsdGlWYWx1ZWBcbiAgICAgKiBfLmludmVydChvYmplY3QsIHRydWUpO1xuICAgICAqIC8vID0+IHsgJzEnOiBbJ2EnLCAnYyddLCAnMic6IFsnYiddIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbnZlcnQob2JqZWN0LCBtdWx0aVZhbHVlLCBndWFyZCkge1xuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKG9iamVjdCwgbXVsdGlWYWx1ZSwgZ3VhcmQpKSB7XG4gICAgICAgIG11bHRpVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBwcm9wcyA9IGtleXMob2JqZWN0KSxcbiAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF0sXG4gICAgICAgICAgICB2YWx1ZSA9IG9iamVjdFtrZXldO1xuXG4gICAgICAgIGlmIChtdWx0aVZhbHVlKSB7XG4gICAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCB2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFt2YWx1ZV0ucHVzaChrZXkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRbdmFsdWVdID0gW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHJlc3VsdFt2YWx1ZV0gPSBrZXk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy4gU2VlIHRoZVxuICAgICAqIFtFUyBzcGVjXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1vYmplY3Qua2V5cylcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5rZXlzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIF8ua2V5cygnaGknKTtcbiAgICAgKiAvLyA9PiBbJzAnLCAnMSddXG4gICAgICovXG4gICAgdmFyIGtleXMgPSAhbmF0aXZlS2V5cyA/IHNoaW1LZXlzIDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICB2YXIgQ3RvciA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgaWYgKCh0eXBlb2YgQ3RvciA9PSAnZnVuY3Rpb24nICYmIEN0b3IucHJvdG90eXBlID09PSBvYmplY3QpIHx8XG4gICAgICAgICAgKHR5cGVvZiBvYmplY3QgIT0gJ2Z1bmN0aW9uJyAmJiBpc0FycmF5TGlrZShvYmplY3QpKSkge1xuICAgICAgICByZXR1cm4gc2hpbUtleXMob2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc09iamVjdChvYmplY3QpID8gbmF0aXZlS2V5cyhvYmplY3QpIDogW107XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8ua2V5c0luKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJywgJ2MnXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGtleXNJbihvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gb2JqZWN0Lmxlbmd0aDtcbiAgICAgIGxlbmd0aCA9IChsZW5ndGggJiYgaXNMZW5ndGgobGVuZ3RoKSAmJlxuICAgICAgICAoaXNBcnJheShvYmplY3QpIHx8IGlzQXJndW1lbnRzKG9iamVjdCkpICYmIGxlbmd0aCkgfHwgMDtcblxuICAgICAgdmFyIEN0b3IgPSBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc1Byb3RvID0gdHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yLnByb3RvdHlwZSA9PT0gb2JqZWN0LFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCksXG4gICAgICAgICAgc2tpcEluZGV4ZXMgPSBsZW5ndGggPiAwO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gKGluZGV4ICsgJycpO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICBpZiAoIShza2lwSW5kZXhlcyAmJiBpc0luZGV4KGtleSwgbGVuZ3RoKSkgJiZcbiAgICAgICAgICAgICEoa2V5ID09ICdjb25zdHJ1Y3RvcicgJiYgKGlzUHJvdG8gfHwgIWhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5tYXBWYWx1ZXNgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGFuIG9iamVjdCB3aXRoIHRoZVxuICAgICAqIHNhbWUgdmFsdWVzIGFzIGBvYmplY3RgIGFuZCBrZXlzIGdlbmVyYXRlZCBieSBydW5uaW5nIGVhY2ggb3duIGVudW1lcmFibGVcbiAgICAgKiBwcm9wZXJ0eSBvZiBgb2JqZWN0YCB0aHJvdWdoIGBpdGVyYXRlZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1hcEtleXMoeyAnYSc6IDEsICdiJzogMiB9LCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICByZXR1cm4ga2V5ICsgdmFsdWU7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnYTEnOiAxLCAnYjInOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgbWFwS2V5cyA9IGNyZWF0ZU9iamVjdE1hcHBlcih0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyBgb2JqZWN0YCBhbmQgdmFsdWVzIGdlbmVyYXRlZCBieVxuICAgICAqIHJ1bm5pbmcgZWFjaCBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBvZiBgb2JqZWN0YCB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoZVxuICAgICAqIGl0ZXJhdGVlIGZ1bmN0aW9uIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAgICAgKiBzdHlsZSBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIGEgbWF0Y2hpbmcgcHJvcGVydHlcbiAgICAgKiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgaXRlcmF0ZWVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW5cbiAgICAgKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gICAgICogIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwVmFsdWVzKHsgJ2EnOiAxLCAnYic6IDIgfSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gKiAzO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAzLCAnYic6IDYgfVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2ZyZWQnOiAgICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ubWFwVmFsdWVzKHVzZXJzLCAnYWdlJyk7XG4gICAgICogLy8gPT4geyAnZnJlZCc6IDQwLCAncGViYmxlcyc6IDEgfSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIHZhciBtYXBWYWx1ZXMgPSBjcmVhdGVPYmplY3RNYXBwZXIoKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5waWNrYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlXG4gICAgICogb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGBvYmplY3RgIHRoYXQgYXJlIG5vdCBvbWl0dGVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnwuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3ByZWRpY2F0ZV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyXG4gICAgICogIGl0ZXJhdGlvbiBvciBwcm9wZXJ0eSBuYW1lcyB0byBvbWl0LCBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBwcm9wZXJ0eVxuICAgICAqICBuYW1lcyBvciBhcnJheXMgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdChvYmplY3QsICdhZ2UnKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKlxuICAgICAqIF8ub21pdChvYmplY3QsIF8uaXNOdW1iZXIpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqL1xuICAgIHZhciBvbWl0ID0gcmVzdFBhcmFtKGZ1bmN0aW9uKG9iamVjdCwgcHJvcHMpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHByb3BzWzBdICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIHByb3BzID0gYXJyYXlNYXAoYmFzZUZsYXR0ZW4ocHJvcHMpLCBTdHJpbmcpO1xuICAgICAgICByZXR1cm4gcGlja0J5QXJyYXkob2JqZWN0LCBiYXNlRGlmZmVyZW5jZShrZXlzSW4ob2JqZWN0KSwgcHJvcHMpKTtcbiAgICAgIH1cbiAgICAgIHZhciBwcmVkaWNhdGUgPSBiaW5kQ2FsbGJhY2socHJvcHNbMF0sIHByb3BzWzFdLCAzKTtcbiAgICAgIHJldHVybiBwaWNrQnlDYWxsYmFjayhvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICByZXR1cm4gIXByZWRpY2F0ZSh2YWx1ZSwga2V5LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgdHdvIGRpbWVuc2lvbmFsIGFycmF5IG9mIHRoZSBrZXktdmFsdWUgcGFpcnMgZm9yIGBvYmplY3RgLFxuICAgICAqIGUuZy4gYFtba2V5MSwgdmFsdWUxXSwgW2tleTIsIHZhbHVlMl1dYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhaXJzKHsgJ2Jhcm5leSc6IDM2LCAnZnJlZCc6IDQwIH0pO1xuICAgICAqIC8vID0+IFtbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDBdXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhaXJzKG9iamVjdCkge1xuICAgICAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcHJvcHMgPSBrZXlzKG9iamVjdCksXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBba2V5LCBvYmplY3Rba2V5XV07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZSBwaWNrZWQgYG9iamVjdGAgcHJvcGVydGllcy4gUHJvcGVydHlcbiAgICAgKiBuYW1lcyBtYXkgYmUgc3BlY2lmaWVkIGFzIGluZGl2aWR1YWwgYXJndW1lbnRzIG9yIGFzIGFycmF5cyBvZiBwcm9wZXJ0eVxuICAgICAqIG5hbWVzLiBJZiBgcHJlZGljYXRlYCBpcyBwcm92aWRlZCBpdCBpcyBpbnZva2VkIGZvciBlYWNoIHByb3BlcnR5IG9mIGBvYmplY3RgXG4gICAgICogcGlja2luZyB0aGUgcHJvcGVydGllcyBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnwuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3ByZWRpY2F0ZV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyXG4gICAgICogIGl0ZXJhdGlvbiBvciBwcm9wZXJ0eSBuYW1lcyB0byBwaWNrLCBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBwcm9wZXJ0eVxuICAgICAqICBuYW1lcyBvciBhcnJheXMgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBwcmVkaWNhdGVgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfTtcbiAgICAgKlxuICAgICAqIF8ucGljayhvYmplY3QsICd1c2VyJyk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdmcmVkJyB9XG4gICAgICpcbiAgICAgKiBfLnBpY2sob2JqZWN0LCBfLmlzU3RyaW5nKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKi9cbiAgICB2YXIgcGljayA9IHJlc3RQYXJhbShmdW5jdGlvbihvYmplY3QsIHByb3BzKSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHR5cGVvZiBwcm9wc1swXSA9PSAnZnVuY3Rpb24nXG4gICAgICAgID8gcGlja0J5Q2FsbGJhY2sob2JqZWN0LCBiaW5kQ2FsbGJhY2socHJvcHNbMF0sIHByb3BzWzFdLCAzKSlcbiAgICAgICAgOiBwaWNrQnlBcnJheShvYmplY3QsIGJhc2VGbGF0dGVuKHByb3BzKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmdldGAgZXhjZXB0IHRoYXQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGEgZnVuY3Rpb25cbiAgICAgKiBpdCBpcyBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIGl0cyBwYXJlbnQgb2JqZWN0IGFuZCBpdHMgcmVzdWx0XG4gICAgICogaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byByZXNvbHZlLlxuICAgICAqIEBwYXJhbSB7Kn0gW2RlZmF1bHRWYWx1ZV0gVGhlIHZhbHVlIHJldHVybmVkIGlmIHRoZSByZXNvbHZlZCB2YWx1ZSBpcyBgdW5kZWZpbmVkYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjMSc6IDMsICdjMic6IF8uY29uc3RhbnQoNCkgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMxJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMyJyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYS5iLmMnLCAnZGVmYXVsdCcpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYS5iLmMnLCBfLmNvbnN0YW50KCdkZWZhdWx0JykpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlc3VsdChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W3BhdGhdO1xuICAgICAgaWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChvYmplY3QgIT0gbnVsbCAmJiAhaXNLZXkocGF0aCwgb2JqZWN0KSkge1xuICAgICAgICAgIHBhdGggPSB0b1BhdGgocGF0aCk7XG4gICAgICAgICAgb2JqZWN0ID0gcGF0aC5sZW5ndGggPT0gMSA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBiYXNlU2xpY2UocGF0aCwgMCwgLTEpKTtcbiAgICAgICAgICByZXN1bHQgPSBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IG9iamVjdFtsYXN0KHBhdGgpXTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGRlZmF1bHRWYWx1ZSA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0Z1bmN0aW9uKHJlc3VsdCkgPyByZXN1bHQuY2FsbChvYmplY3QpIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIGBwYXRoYCBvbiBgb2JqZWN0YC4gSWYgYSBwb3J0aW9uIG9mIGBwYXRoYFxuICAgICAqIGRvZXMgbm90IGV4aXN0IGl0IGlzIGNyZWF0ZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGF1Z21lbnQuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uc2V0KG9iamVjdCwgJ2FbMF0uYi5jJywgNCk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LmFbMF0uYi5jKTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICpcbiAgICAgKiBfLnNldChvYmplY3QsICd4WzBdLnkueicsIDUpO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC54WzBdLnkueik7XG4gICAgICogLy8gPT4gNVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldChvYmplY3QsIHBhdGgsIHZhbHVlKSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH1cbiAgICAgIHZhciBwYXRoS2V5ID0gKHBhdGggKyAnJyk7XG4gICAgICBwYXRoID0gKG9iamVjdFtwYXRoS2V5XSAhPSBudWxsIHx8IGlzS2V5KHBhdGgsIG9iamVjdCkpID8gW3BhdGhLZXldIDogdG9QYXRoKHBhdGgpO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwYXRoLmxlbmd0aCxcbiAgICAgICAgICBsYXN0SW5kZXggPSBsZW5ndGggLSAxLFxuICAgICAgICAgIG5lc3RlZCA9IG9iamVjdDtcblxuICAgICAgd2hpbGUgKG5lc3RlZCAhPSBudWxsICYmICsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGtleSA9IHBhdGhbaW5kZXhdO1xuICAgICAgICBpZiAoaXNPYmplY3QobmVzdGVkKSkge1xuICAgICAgICAgIGlmIChpbmRleCA9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgIG5lc3RlZFtrZXldID0gdmFsdWU7XG4gICAgICAgICAgfSBlbHNlIGlmIChuZXN0ZWRba2V5XSA9PSBudWxsKSB7XG4gICAgICAgICAgICBuZXN0ZWRba2V5XSA9IGlzSW5kZXgocGF0aFtpbmRleCArIDFdKSA/IFtdIDoge307XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG5lc3RlZCA9IG5lc3RlZFtrZXldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBhbHRlcm5hdGl2ZSB0byBgXy5yZWR1Y2VgOyB0aGlzIG1ldGhvZCB0cmFuc2Zvcm1zIGBvYmplY3RgIHRvIGEgbmV3XG4gICAgICogYGFjY3VtdWxhdG9yYCBvYmplY3Qgd2hpY2ggaXMgdGhlIHJlc3VsdCBvZiBydW5uaW5nIGVhY2ggb2YgaXRzIG93biBlbnVtZXJhYmxlXG4gICAgICogcHJvcGVydGllcyB0aHJvdWdoIGBpdGVyYXRlZWAsIHdpdGggZWFjaCBpbnZvY2F0aW9uIHBvdGVudGlhbGx5IG11dGF0aW5nXG4gICAgICogdGhlIGBhY2N1bXVsYXRvcmAgb2JqZWN0LiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWRcbiAgICAgKiB3aXRoIGZvdXIgYXJndW1lbnRzOiAoYWNjdW11bGF0b3IsIHZhbHVlLCBrZXksIG9iamVjdCkuIEl0ZXJhdGVlIGZ1bmN0aW9uc1xuICAgICAqIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBjdXN0b20gYWNjdW11bGF0b3IgdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRyYW5zZm9ybShbMiwgMywgNF0sIGZ1bmN0aW9uKHJlc3VsdCwgbikge1xuICAgICAqICAgcmVzdWx0LnB1c2gobiAqPSBuKTtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAwO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFs0LCA5XVxuICAgICAqXG4gICAgICogXy50cmFuc2Zvcm0oeyAnYSc6IDEsICdiJzogMiB9LCBmdW5jdGlvbihyZXN1bHQsIG4sIGtleSkge1xuICAgICAqICAgcmVzdWx0W2tleV0gPSBuICogMztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMywgJ2InOiA2IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm0ob2JqZWN0LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkob2JqZWN0KSB8fCBpc1R5cGVkQXJyYXkob2JqZWN0KTtcbiAgICAgIGl0ZXJhdGVlID0gZ2V0Q2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDQpO1xuXG4gICAgICBpZiAoYWNjdW11bGF0b3IgPT0gbnVsbCkge1xuICAgICAgICBpZiAoaXNBcnIgfHwgaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICAgIHZhciBDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgICAgIGlmIChpc0Fycikge1xuICAgICAgICAgICAgYWNjdW11bGF0b3IgPSBpc0FycmF5KG9iamVjdCkgPyBuZXcgQ3RvciA6IFtdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhY2N1bXVsYXRvciA9IGJhc2VDcmVhdGUoaXNGdW5jdGlvbihDdG9yKSA/IEN0b3IucHJvdG90eXBlIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgKGlzQXJyID8gYXJyYXlFYWNoIDogYmFzZUZvck93bikob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIG9iamVjdCkge1xuICAgICAgICByZXR1cm4gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgb2JqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBOb24tb2JqZWN0IHZhbHVlcyBhcmUgY29lcmNlZCB0byBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8udmFsdWVzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogXy52YWx1ZXMoJ2hpJyk7XG4gICAgICogLy8gPT4gWydoJywgJ2knXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlVmFsdWVzKG9iamVjdCwga2V5cyhvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnR5IHZhbHVlc1xuICAgICAqIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy52YWx1ZXNJbihuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB2YWx1ZXNJbihvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlVmFsdWVzKG9iamVjdCwga2V5c0luKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgbmAgaXMgYmV0d2VlbiBgc3RhcnRgIGFuZCB1cCB0byBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIElmXG4gICAgICogYGVuZGAgaXMgbm90IHNwZWNpZmllZCBpdCBpcyBzZXQgdG8gYHN0YXJ0YCB3aXRoIGBzdGFydGAgdGhlbiBzZXQgdG8gYDBgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBuYCBpcyBpbiB0aGUgcmFuZ2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDMsIDIsIDQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSg0LCA4KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoNCwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSgyLCAyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDEuMiwgMik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDUuMiwgNCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpblJhbmdlKHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICBzdGFydCA9ICtzdGFydCB8fCAwO1xuICAgICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbmQgPSArZW5kIHx8IDA7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWUgPj0gbmF0aXZlTWluKHN0YXJ0LCBlbmQpICYmIHZhbHVlIDwgbmF0aXZlTWF4KHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2R1Y2VzIGEgcmFuZG9tIG51bWJlciBiZXR3ZWVuIGBtaW5gIGFuZCBgbWF4YCAoaW5jbHVzaXZlKS4gSWYgb25seSBvbmVcbiAgICAgKiBhcmd1bWVudCBpcyBwcm92aWRlZCBhIG51bWJlciBiZXR3ZWVuIGAwYCBhbmQgdGhlIGdpdmVuIG51bWJlciBpcyByZXR1cm5lZC5cbiAgICAgKiBJZiBgZmxvYXRpbmdgIGlzIGB0cnVlYCwgb3IgZWl0aGVyIGBtaW5gIG9yIGBtYXhgIGFyZSBmbG9hdHMsIGEgZmxvYXRpbmctcG9pbnRcbiAgICAgKiBudW1iZXIgaXMgcmV0dXJuZWQgaW5zdGVhZCBvZiBhbiBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbWluPTBdIFRoZSBtaW5pbXVtIHBvc3NpYmxlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbWF4PTFdIFRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zsb2F0aW5nXSBTcGVjaWZ5IHJldHVybmluZyBhIGZsb2F0aW5nLXBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgwLCA1KTtcbiAgICAgKiAvLyA9PiBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSk7XG4gICAgICogLy8gPT4gYWxzbyBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSwgdHJ1ZSk7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAwIGFuZCA1XG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgxLjIsIDUuMik7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAxLjIgYW5kIDUuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJhbmRvbShtaW4sIG1heCwgZmxvYXRpbmcpIHtcbiAgICAgIGlmIChmbG9hdGluZyAmJiBpc0l0ZXJhdGVlQ2FsbChtaW4sIG1heCwgZmxvYXRpbmcpKSB7XG4gICAgICAgIG1heCA9IGZsb2F0aW5nID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgdmFyIG5vTWluID0gbWluID09IG51bGwsXG4gICAgICAgICAgbm9NYXggPSBtYXggPT0gbnVsbDtcblxuICAgICAgaWYgKGZsb2F0aW5nID09IG51bGwpIHtcbiAgICAgICAgaWYgKG5vTWF4ICYmIHR5cGVvZiBtaW4gPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgZmxvYXRpbmcgPSBtaW47XG4gICAgICAgICAgbWluID0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgbWF4ID09ICdib29sZWFuJykge1xuICAgICAgICAgIGZsb2F0aW5nID0gbWF4O1xuICAgICAgICAgIG5vTWF4ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG5vTWluICYmIG5vTWF4KSB7XG4gICAgICAgIG1heCA9IDE7XG4gICAgICAgIG5vTWF4ID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBtaW4gPSArbWluIHx8IDA7XG4gICAgICBpZiAobm9NYXgpIHtcbiAgICAgICAgbWF4ID0gbWluO1xuICAgICAgICBtaW4gPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF4ID0gK21heCB8fCAwO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nIHx8IG1pbiAlIDEgfHwgbWF4ICUgMSkge1xuICAgICAgICB2YXIgcmFuZCA9IG5hdGl2ZVJhbmRvbSgpO1xuICAgICAgICByZXR1cm4gbmF0aXZlTWluKG1pbiArIChyYW5kICogKG1heCAtIG1pbiArIHBhcnNlRmxvYXQoJzFlLScgKyAoKHJhbmQgKyAnJykubGVuZ3RoIC0gMSkpKSksIG1heCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVJhbmRvbShtaW4sIG1heCk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG8gW2NhbWVsIGNhc2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NhbWVsQ2FzZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjYW1lbCBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FtZWxDYXNlKCdGb28gQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb0JhcidcbiAgICAgKlxuICAgICAqIF8uY2FtZWxDYXNlKCctLWZvby1iYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJ19fZm9vX2Jhcl9fJyk7XG4gICAgICogLy8gPT4gJ2Zvb0JhcidcbiAgICAgKi9cbiAgICB2YXIgY2FtZWxDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICB3b3JkID0gd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICh3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZC5zbGljZSgxKSkgOiB3b3JkKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENhcGl0YWxpemVzIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FwaXRhbGl6ZSgnZnJlZCcpO1xuICAgICAqIC8vID0+ICdGcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSBiYXNlVG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcgJiYgKHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVidXJycyBgc3RyaW5nYCBieSBjb252ZXJ0aW5nIFtsYXRpbi0xIHN1cHBsZW1lbnRhcnkgbGV0dGVyc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW4tMV9TdXBwbGVtZW50XyhVbmljb2RlX2Jsb2NrKSNDaGFyYWN0ZXJfdGFibGUpXG4gICAgICogdG8gYmFzaWMgbGF0aW4gbGV0dGVycyBhbmQgcmVtb3ZpbmcgW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBkZWJ1cnIuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlYnVycignZMOpasOgIHZ1Jyk7XG4gICAgICogLy8gPT4gJ2RlamEgdnUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVidXJyKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gc3RyaW5nICYmIHN0cmluZy5yZXBsYWNlKHJlTGF0aW4xLCBkZWJ1cnJMZXR0ZXIpLnJlcGxhY2UocmVDb21ib01hcmssICcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHN0cmluZ2AgZW5kcyB3aXRoIHRoZSBnaXZlbiB0YXJnZXQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3RhcmdldF0gVGhlIHN0cmluZyB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcG9zaXRpb249c3RyaW5nLmxlbmd0aF0gVGhlIHBvc2l0aW9uIHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgc3RyaW5nYCBlbmRzIHdpdGggYHRhcmdldGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lbmRzV2l0aCgnYWJjJywgJ2MnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicsIDIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlbmRzV2l0aChzdHJpbmcsIHRhcmdldCwgcG9zaXRpb24pIHtcbiAgICAgIHN0cmluZyA9IGJhc2VUb1N0cmluZyhzdHJpbmcpO1xuICAgICAgdGFyZ2V0ID0gKHRhcmdldCArICcnKTtcblxuICAgICAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBsZW5ndGhcbiAgICAgICAgOiBuYXRpdmVNaW4ocG9zaXRpb24gPCAwID8gMCA6ICgrcG9zaXRpb24gfHwgMCksIGxlbmd0aCk7XG5cbiAgICAgIHBvc2l0aW9uIC09IHRhcmdldC5sZW5ndGg7XG4gICAgICByZXR1cm4gcG9zaXRpb24gPj0gMCAmJiBzdHJpbmcuaW5kZXhPZih0YXJnZXQsIHBvc2l0aW9uKSA9PSBwb3NpdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgY2hhcmFjdGVycyBcIiZcIiwgXCI8XCIsIFwiPlwiLCAnXCInLCBcIidcIiwgYW5kIFwiXFxgXCIsIGluIGBzdHJpbmdgIHRvXG4gICAgICogdGhlaXIgY29ycmVzcG9uZGluZyBIVE1MIGVudGl0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vIG90aGVyIGNoYXJhY3RlcnMgYXJlIGVzY2FwZWQuIFRvIGVzY2FwZSBhZGRpdGlvbmFsIGNoYXJhY3RlcnNcbiAgICAgKiB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBUaG91Z2ggdGhlIFwiPlwiIGNoYXJhY3RlciBpcyBlc2NhcGVkIGZvciBzeW1tZXRyeSwgY2hhcmFjdGVycyBsaWtlXG4gICAgICogXCI+XCIgYW5kIFwiL1wiIGRvbid0IG5lZWQgZXNjYXBpbmcgaW4gSFRNTCBhbmQgaGF2ZSBubyBzcGVjaWFsIG1lYW5pbmdcbiAgICAgKiB1bmxlc3MgdGhleSdyZSBwYXJ0IG9mIGEgdGFnIG9yIHVucXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZS5cbiAgICAgKiBTZWUgW01hdGhpYXMgQnluZW5zJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2FtYmlndW91cy1hbXBlcnNhbmRzKVxuICAgICAqICh1bmRlciBcInNlbWktcmVsYXRlZCBmdW4gZmFjdFwiKSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQmFja3RpY2tzIGFyZSBlc2NhcGVkIGJlY2F1c2UgaW4gSW50ZXJuZXQgRXhwbG9yZXIgPCA5LCB0aGV5IGNhbiBicmVhayBvdXRcbiAgICAgKiBvZiBhdHRyaWJ1dGUgdmFsdWVzIG9yIEhUTUwgY29tbWVudHMuIFNlZSBbIzU5XShodHRwczovL2h0bWw1c2VjLm9yZy8jNTkpLFxuICAgICAqIFsjMTAyXShodHRwczovL2h0bWw1c2VjLm9yZy8jMTAyKSwgWyMxMDhdKGh0dHBzOi8vaHRtbDVzZWMub3JnLyMxMDgpLCBhbmRcbiAgICAgKiBbIzEzM10oaHR0cHM6Ly9odG1sNXNlYy5vcmcvIzEzMykgb2YgdGhlIFtIVE1MNSBTZWN1cml0eSBDaGVhdHNoZWV0XShodHRwczovL2h0bWw1c2VjLm9yZy8pXG4gICAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIFdoZW4gd29ya2luZyB3aXRoIEhUTUwgeW91IHNob3VsZCBhbHdheXMgW3F1b3RlIGF0dHJpYnV0ZSB2YWx1ZXNdKGh0dHA6Ly93b25rby5jb20vcG9zdC9odG1sLWVzY2FwaW5nKVxuICAgICAqIHRvIHJlZHVjZSBYU1MgdmVjdG9ycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXNjYXBlKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+ICdmcmVkLCBiYXJuZXksICZhbXA7IHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXNjYXBlKHN0cmluZykge1xuICAgICAgLy8gUmVzZXQgYGxhc3RJbmRleGAgYmVjYXVzZSBpbiBJRSA8IDkgYFN0cmluZyNyZXBsYWNlYCBkb2VzIG5vdC5cbiAgICAgIHN0cmluZyA9IGJhc2VUb1N0cmluZyhzdHJpbmcpO1xuICAgICAgcmV0dXJuIChzdHJpbmcgJiYgcmVIYXNVbmVzY2FwZWRIdG1sLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZVVuZXNjYXBlZEh0bWwsIGVzY2FwZUh0bWxDaGFyKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFc2NhcGVzIHRoZSBgUmVnRXhwYCBzcGVjaWFsIGNoYXJhY3RlcnMgXCJcXFwiLCBcIi9cIiwgXCJeXCIsIFwiJFwiLCBcIi5cIiwgXCJ8XCIsIFwiP1wiLFxuICAgICAqIFwiKlwiLCBcIitcIiwgXCIoXCIsIFwiKVwiLCBcIltcIiwgXCJdXCIsIFwie1wiIGFuZCBcIn1cIiBpbiBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXNjYXBlUmVnRXhwKCdbbG9kYXNoXShodHRwczovL2xvZGFzaC5jb20vKScpO1xuICAgICAqIC8vID0+ICdcXFtsb2Rhc2hcXF1cXChodHRwczpcXC9cXC9sb2Rhc2hcXC5jb21cXC9cXCknXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gKHN0cmluZyAmJiByZUhhc1JlZ0V4cENoYXJzLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZVJlZ0V4cENoYXJzLCBlc2NhcGVSZWdFeHBDaGFyKVxuICAgICAgICA6IChzdHJpbmcgfHwgJyg/OiknKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBba2ViYWIgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGV0dGVyX2Nhc2UjU3BlY2lhbF9jYXNlX3N0eWxlcykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBrZWJhYiBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdGb28gQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvby1iYXInXG4gICAgICpcbiAgICAgKiBfLmtlYmFiQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvby1iYXInXG4gICAgICpcbiAgICAgKiBfLmtlYmFiQ2FzZSgnX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKi9cbiAgICB2YXIga2ViYWJDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJy0nIDogJycpICsgd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgc2lkZXMgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuXG4gICAgICogUGFkZGluZyBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBjYW4ndCBiZSBldmVubHkgZGl2aWRlZCBieSBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZCgnYWJjJywgOCk7XG4gICAgICogLy8gPT4gJyAgYWJjICAgJ1xuICAgICAqXG4gICAgICogXy5wYWQoJ2FiYycsIDgsICdfLScpO1xuICAgICAqIC8vID0+ICdfLWFiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkKCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IGJhc2VUb1N0cmluZyhzdHJpbmcpO1xuICAgICAgbGVuZ3RoID0gK2xlbmd0aDtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICBpZiAoc3RyTGVuZ3RoID49IGxlbmd0aCB8fCAhbmF0aXZlSXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIG1pZCA9IChsZW5ndGggLSBzdHJMZW5ndGgpIC8gMixcbiAgICAgICAgICBsZWZ0TGVuZ3RoID0gbmF0aXZlRmxvb3IobWlkKSxcbiAgICAgICAgICByaWdodExlbmd0aCA9IG5hdGl2ZUNlaWwobWlkKTtcblxuICAgICAgY2hhcnMgPSBjcmVhdGVQYWRkaW5nKCcnLCByaWdodExlbmd0aCwgY2hhcnMpO1xuICAgICAgcmV0dXJuIGNoYXJzLnNsaWNlKDAsIGxlZnRMZW5ndGgpICsgc3RyaW5nICsgY2hhcnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgbGVmdCBzaWRlIGlmIGl0J3Mgc2hvcnRlciB0aGFuIGBsZW5ndGhgLiBQYWRkaW5nXG4gICAgICogY2hhcmFjdGVycyBhcmUgdHJ1bmNhdGVkIGlmIHRoZXkgZXhjZWVkIGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHBhZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD0wXSBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFkTGVmdCgnYWJjJywgNik7XG4gICAgICogLy8gPT4gJyAgIGFiYydcbiAgICAgKlxuICAgICAqIF8ucGFkTGVmdCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ18tX2FiYydcbiAgICAgKlxuICAgICAqIF8ucGFkTGVmdCgnYWJjJywgMyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKi9cbiAgICB2YXIgcGFkTGVmdCA9IGNyZWF0ZVBhZERpcigpO1xuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgcmlnaHQgc2lkZSBpZiBpdCdzIHNob3J0ZXIgdGhhbiBgbGVuZ3RoYC4gUGFkZGluZ1xuICAgICAqIGNoYXJhY3RlcnMgYXJlIHRydW5jYXRlZCBpZiB0aGV5IGV4Y2VlZCBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZFJpZ2h0KCdhYmMnLCA2KTtcbiAgICAgKiAvLyA9PiAnYWJjICAgJ1xuICAgICAqXG4gICAgICogXy5wYWRSaWdodCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkUmlnaHQoJ2FiYycsIDMpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICovXG4gICAgdmFyIHBhZFJpZ2h0ID0gY3JlYXRlUGFkRGlyKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG8gYW4gaW50ZWdlciBvZiB0aGUgc3BlY2lmaWVkIHJhZGl4LiBJZiBgcmFkaXhgIGlzXG4gICAgICogYHVuZGVmaW5lZGAgb3IgYDBgLCBhIGByYWRpeGAgb2YgYDEwYCBpcyB1c2VkIHVubGVzcyBgdmFsdWVgIGlzIGEgaGV4YWRlY2ltYWwsXG4gICAgICogaW4gd2hpY2ggY2FzZSBhIGByYWRpeGAgb2YgYDE2YCBpcyB1c2VkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGFsaWducyB3aXRoIHRoZSBbRVM1IGltcGxlbWVudGF0aW9uXShodHRwczovL2VzNS5naXRodWIuaW8vI0UpXG4gICAgICogb2YgYHBhcnNlSW50YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3JhZGl4XSBUaGUgcmFkaXggdG8gaW50ZXJwcmV0IGB2YWx1ZWAgYnkuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFyc2VJbnQoJzA4Jyk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzA4JywgJzEwJ10sIF8ucGFyc2VJbnQpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJzZUludChzdHJpbmcsIHJhZGl4LCBndWFyZCkge1xuICAgICAgLy8gRmlyZWZveCA8IDIxIGFuZCBPcGVyYSA8IDE1IGZvbGxvdyBFUzMgZm9yIGBwYXJzZUludGAuXG4gICAgICAvLyBDaHJvbWUgZmFpbHMgdG8gdHJpbSBsZWFkaW5nIDxCT00+IHdoaXRlc3BhY2UgY2hhcmFjdGVycy5cbiAgICAgIC8vIFNlZSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzEwOSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoc3RyaW5nLCByYWRpeCwgZ3VhcmQpIDogcmFkaXggPT0gbnVsbCkge1xuICAgICAgICByYWRpeCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKHJhZGl4KSB7XG4gICAgICAgIHJhZGl4ID0gK3JhZGl4O1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdHJpbShzdHJpbmcpO1xuICAgICAgcmV0dXJuIG5hdGl2ZVBhcnNlSW50KHN0cmluZywgcmFkaXggfHwgKHJlSGFzSGV4UHJlZml4LnRlc3Qoc3RyaW5nKSA/IDE2IDogMTApKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXBlYXRzIHRoZSBnaXZlbiBzdHJpbmcgYG5gIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHJlcGVhdC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MF0gVGhlIG51bWJlciBvZiB0aW1lcyB0byByZXBlYXQgdGhlIHN0cmluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByZXBlYXRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCcqJywgMyk7XG4gICAgICogLy8gPT4gJyoqKidcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCdhYmMnLCAyKTtcbiAgICAgKiAvLyA9PiAnYWJjYWJjJ1xuICAgICAqXG4gICAgICogXy5yZXBlYXQoJ2FiYycsIDApO1xuICAgICAqIC8vID0+ICcnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVwZWF0KHN0cmluZywgbikge1xuICAgICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBuID0gK247XG4gICAgICBpZiAobiA8IDEgfHwgIXN0cmluZyB8fCAhbmF0aXZlSXNGaW5pdGUobikpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIC8vIExldmVyYWdlIHRoZSBleHBvbmVudGlhdGlvbiBieSBzcXVhcmluZyBhbGdvcml0aG0gZm9yIGEgZmFzdGVyIHJlcGVhdC5cbiAgICAgIC8vIFNlZSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FeHBvbmVudGlhdGlvbl9ieV9zcXVhcmluZyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgZG8ge1xuICAgICAgICBpZiAobiAlIDIpIHtcbiAgICAgICAgICByZXN1bHQgKz0gc3RyaW5nO1xuICAgICAgICB9XG4gICAgICAgIG4gPSBuYXRpdmVGbG9vcihuIC8gMik7XG4gICAgICAgIHN0cmluZyArPSBzdHJpbmc7XG4gICAgICB9IHdoaWxlIChuKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBbc25ha2UgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU25ha2VfY2FzZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzbmFrZSBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc25ha2VDYXNlKCdGb28gQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnLS1mb28tYmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICovXG4gICAgdmFyIHNuYWtlQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICdfJyA6ICcnKSArIHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIFtzdGFydCBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTdHlsaXN0aWNfb3Jfc3BlY2lhbGlzZWRfdXNhZ2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RhcnQgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnLS1mb28tYmFyJyk7XG4gICAgICogLy8gPT4gJ0ZvbyBCYXInXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ0ZvbyBCYXInXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnRm9vIEJhcidcbiAgICAgKi9cbiAgICB2YXIgc3RhcnRDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJyAnIDogJycpICsgKHdvcmQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyB3b3JkLnNsaWNlKDEpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgc3RyaW5nYCBzdGFydHMgd2l0aCB0aGUgZ2l2ZW4gdGFyZ2V0IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFt0YXJnZXRdIFRoZSBzdHJpbmcgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3Bvc2l0aW9uPTBdIFRoZSBwb3NpdGlvbiB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHN0cmluZ2Agc3RhcnRzIHdpdGggYHRhcmdldGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2InKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYicsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFydHNXaXRoKHN0cmluZywgdGFyZ2V0LCBwb3NpdGlvbikge1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uID09IG51bGxcbiAgICAgICAgPyAwXG4gICAgICAgIDogbmF0aXZlTWluKHBvc2l0aW9uIDwgMCA/IDAgOiAoK3Bvc2l0aW9uIHx8IDApLCBzdHJpbmcubGVuZ3RoKTtcblxuICAgICAgcmV0dXJuIHN0cmluZy5sYXN0SW5kZXhPZih0YXJnZXQsIHBvc2l0aW9uKSA9PSBwb3NpdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY29tcGlsZWQgdGVtcGxhdGUgZnVuY3Rpb24gdGhhdCBjYW4gaW50ZXJwb2xhdGUgZGF0YSBwcm9wZXJ0aWVzXG4gICAgICogaW4gXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlcnMsIEhUTUwtZXNjYXBlIGludGVycG9sYXRlZCBkYXRhIHByb3BlcnRpZXMgaW5cbiAgICAgKiBcImVzY2FwZVwiIGRlbGltaXRlcnMsIGFuZCBleGVjdXRlIEphdmFTY3JpcHQgaW4gXCJldmFsdWF0ZVwiIGRlbGltaXRlcnMuIERhdGFcbiAgICAgKiBwcm9wZXJ0aWVzIG1heSBiZSBhY2Nlc3NlZCBhcyBmcmVlIHZhcmlhYmxlcyBpbiB0aGUgdGVtcGxhdGUuIElmIGEgc2V0dGluZ1xuICAgICAqIG9iamVjdCBpcyBwcm92aWRlZCBpdCB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgYF8udGVtcGxhdGVTZXR0aW5nc2AgdmFsdWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIEluIHRoZSBkZXZlbG9wbWVudCBidWlsZCBgXy50ZW1wbGF0ZWAgdXRpbGl6ZXNcbiAgICAgKiBbc291cmNlVVJMc10oaHR0cDovL3d3dy5odG1sNXJvY2tzLmNvbS9lbi90dXRvcmlhbHMvZGV2ZWxvcGVydG9vbHMvc291cmNlbWFwcy8jdG9jLXNvdXJjZXVybClcbiAgICAgKiBmb3IgZWFzaWVyIGRlYnVnZ2luZy5cbiAgICAgKlxuICAgICAqIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHByZWNvbXBpbGluZyB0ZW1wbGF0ZXMgc2VlXG4gICAgICogW2xvZGFzaCdzIGN1c3RvbSBidWlsZHMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9sb2Rhc2guY29tL2N1c3RvbS1idWlsZHMpLlxuICAgICAqXG4gICAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gQ2hyb21lIGV4dGVuc2lvbiBzYW5kYm94ZXMgc2VlXG4gICAgICogW0Nocm9tZSdzIGV4dGVuc2lvbnMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9kZXZlbG9wZXIuY2hyb21lLmNvbS9leHRlbnNpb25zL3NhbmRib3hpbmdFdmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHRlbXBsYXRlIHN0cmluZy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gW29wdGlvbnMuZXNjYXBlXSBUaGUgSFRNTCBcImVzY2FwZVwiIGRlbGltaXRlci5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gW29wdGlvbnMuZXZhbHVhdGVdIFRoZSBcImV2YWx1YXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5pbXBvcnRzXSBBbiBvYmplY3QgdG8gaW1wb3J0IGludG8gdGhlIHRlbXBsYXRlIGFzIGZyZWUgdmFyaWFibGVzLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBbb3B0aW9ucy5pbnRlcnBvbGF0ZV0gVGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnNvdXJjZVVSTF0gVGhlIHNvdXJjZVVSTCBvZiB0aGUgdGVtcGxhdGUncyBjb21waWxlZCBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnZhcmlhYmxlXSBUaGUgZGF0YSBvYmplY3QgdmFyaWFibGUgbmFtZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtvdGhlck9wdGlvbnNdIEVuYWJsZXMgdGhlIGxlZ2FjeSBgb3B0aW9uc2AgcGFyYW0gc2lnbmF0dXJlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY29tcGlsZWQgdGVtcGxhdGUgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyIHRvIGNyZWF0ZSBhIGNvbXBpbGVkIHRlbXBsYXRlXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdmcmVkJyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCEnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgSFRNTCBcImVzY2FwZVwiIGRlbGltaXRlciB0byBlc2NhcGUgZGF0YSBwcm9wZXJ0eSB2YWx1ZXNcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8Yj48JS0gdmFsdWUgJT48L2I+Jyk7XG4gICAgICogY29tcGlsZWQoeyAndmFsdWUnOiAnPHNjcmlwdD4nIH0pO1xuICAgICAqIC8vID0+ICc8Yj4mbHQ7c2NyaXB0Jmd0OzwvYj4nXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlciB0byBleGVjdXRlIEphdmFTY3JpcHQgYW5kIGdlbmVyYXRlIEhUTUxcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JSBfLmZvckVhY2godXNlcnMsIGZ1bmN0aW9uKHVzZXIpIHsgJT48bGk+PCUtIHVzZXIgJT48L2xpPjwlIH0pOyAlPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXJzJzogWydmcmVkJywgJ2Jhcm5leSddIH0pO1xuICAgICAqIC8vID0+ICc8bGk+ZnJlZDwvbGk+PGxpPmJhcm5leTwvbGk+J1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGludGVybmFsIGBwcmludGAgZnVuY3Rpb24gaW4gXCJldmFsdWF0ZVwiIGRlbGltaXRlcnNcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JSBwcmludChcImhlbGxvIFwiICsgdXNlcik7ICU+IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnYmFybmV5JyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gYmFybmV5ISdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBFUyBkZWxpbWl0ZXIgYXMgYW4gYWx0ZXJuYXRpdmUgdG8gdGhlIGRlZmF1bHQgXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlclxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvICR7IHVzZXIgfSEnKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2VyJzogJ3BlYmJsZXMnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBwZWJibGVzISdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIGN1c3RvbSB0ZW1wbGF0ZSBkZWxpbWl0ZXJzXG4gICAgICogXy50ZW1wbGF0ZVNldHRpbmdzLmludGVycG9sYXRlID0gL3t7KFtcXHNcXFNdKz8pfX0vZztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyB7eyB1c2VyIH19IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnbXVzdGFjaGUnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBtdXN0YWNoZSEnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBiYWNrc2xhc2hlcyB0byB0cmVhdCBkZWxpbWl0ZXJzIGFzIHBsYWluIHRleHRcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JT0gXCJcXFxcPCUtIHZhbHVlICVcXFxcPlwiICU+Jyk7XG4gICAgICogY29tcGlsZWQoeyAndmFsdWUnOiAnaWdub3JlZCcgfSk7XG4gICAgICogLy8gPT4gJzwlLSB2YWx1ZSAlPidcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgaW1wb3J0c2Agb3B0aW9uIHRvIGltcG9ydCBgalF1ZXJ5YCBhcyBganFgXG4gICAgICogdmFyIHRleHQgPSAnPCUganEuZWFjaCh1c2VycywgZnVuY3Rpb24odXNlcikgeyAlPjxsaT48JS0gdXNlciAlPjwvbGk+PCUgfSk7ICU+JztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKHRleHQsIHsgJ2ltcG9ydHMnOiB7ICdqcSc6IGpRdWVyeSB9IH0pO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXJzJzogWydmcmVkJywgJ2Jhcm5leSddIH0pO1xuICAgICAqIC8vID0+ICc8bGk+ZnJlZDwvbGk+PGxpPmJhcm5leTwvbGk+J1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBzb3VyY2VVUkxgIG9wdGlvbiB0byBzcGVjaWZ5IGEgY3VzdG9tIHNvdXJjZVVSTCBmb3IgdGhlIHRlbXBsYXRlXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJywgeyAnc291cmNlVVJMJzogJy9iYXNpYy9ncmVldGluZy5qc3QnIH0pO1xuICAgICAqIGNvbXBpbGVkKGRhdGEpO1xuICAgICAqIC8vID0+IGZpbmQgdGhlIHNvdXJjZSBvZiBcImdyZWV0aW5nLmpzdFwiIHVuZGVyIHRoZSBTb3VyY2VzIHRhYiBvciBSZXNvdXJjZXMgcGFuZWwgb2YgdGhlIHdlYiBpbnNwZWN0b3JcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgdmFyaWFibGVgIG9wdGlvbiB0byBlbnN1cmUgYSB3aXRoLXN0YXRlbWVudCBpc24ndCB1c2VkIGluIHRoZSBjb21waWxlZCB0ZW1wbGF0ZVxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hpIDwlPSBkYXRhLnVzZXIgJT4hJywgeyAndmFyaWFibGUnOiAnZGF0YScgfSk7XG4gICAgICogY29tcGlsZWQuc291cmNlO1xuICAgICAqIC8vID0+IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgKiAvLyAgIHZhciBfX3QsIF9fcCA9ICcnO1xuICAgICAqIC8vICAgX19wICs9ICdoaSAnICsgKChfX3QgPSAoIGRhdGEudXNlciApKSA9PSBudWxsID8gJycgOiBfX3QpICsgJyEnO1xuICAgICAqIC8vICAgcmV0dXJuIF9fcDtcbiAgICAgKiAvLyB9XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYHNvdXJjZWAgcHJvcGVydHkgdG8gaW5saW5lIGNvbXBpbGVkIHRlbXBsYXRlcyBmb3IgbWVhbmluZ2Z1bFxuICAgICAqIC8vIGxpbmUgbnVtYmVycyBpbiBlcnJvciBtZXNzYWdlcyBhbmQgYSBzdGFjayB0cmFjZVxuICAgICAqIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKGN3ZCwgJ2pzdC5qcycpLCAnXFxcbiAgICAgKiAgIHZhciBKU1QgPSB7XFxcbiAgICAgKiAgICAgXCJtYWluXCI6ICcgKyBfLnRlbXBsYXRlKG1haW5UZXh0KS5zb3VyY2UgKyAnXFxcbiAgICAgKiAgIH07XFxcbiAgICAgKiAnKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0ZW1wbGF0ZShzdHJpbmcsIG9wdGlvbnMsIG90aGVyT3B0aW9ucykge1xuICAgICAgLy8gQmFzZWQgb24gSm9obiBSZXNpZydzIGB0bXBsYCBpbXBsZW1lbnRhdGlvbiAoaHR0cDovL2Vqb2huLm9yZy9ibG9nL2phdmFzY3JpcHQtbWljcm8tdGVtcGxhdGluZy8pXG4gICAgICAvLyBhbmQgTGF1cmEgRG9rdG9yb3ZhJ3MgZG9ULmpzIChodHRwczovL2dpdGh1Yi5jb20vb2xhZG8vZG9UKS5cbiAgICAgIHZhciBzZXR0aW5ncyA9IGxvZGFzaC50ZW1wbGF0ZVNldHRpbmdzO1xuXG4gICAgICBpZiAob3RoZXJPcHRpb25zICYmIGlzSXRlcmF0ZWVDYWxsKHN0cmluZywgb3B0aW9ucywgb3RoZXJPcHRpb25zKSkge1xuICAgICAgICBvcHRpb25zID0gb3RoZXJPcHRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBvcHRpb25zID0gYXNzaWduV2l0aChiYXNlQXNzaWduKHt9LCBvdGhlck9wdGlvbnMgfHwgb3B0aW9ucyksIHNldHRpbmdzLCBhc3NpZ25Pd25EZWZhdWx0cyk7XG5cbiAgICAgIHZhciBpbXBvcnRzID0gYXNzaWduV2l0aChiYXNlQXNzaWduKHt9LCBvcHRpb25zLmltcG9ydHMpLCBzZXR0aW5ncy5pbXBvcnRzLCBhc3NpZ25Pd25EZWZhdWx0cyksXG4gICAgICAgICAgaW1wb3J0c0tleXMgPSBrZXlzKGltcG9ydHMpLFxuICAgICAgICAgIGltcG9ydHNWYWx1ZXMgPSBiYXNlVmFsdWVzKGltcG9ydHMsIGltcG9ydHNLZXlzKTtcblxuICAgICAgdmFyIGlzRXNjYXBpbmcsXG4gICAgICAgICAgaXNFdmFsdWF0aW5nLFxuICAgICAgICAgIGluZGV4ID0gMCxcbiAgICAgICAgICBpbnRlcnBvbGF0ZSA9IG9wdGlvbnMuaW50ZXJwb2xhdGUgfHwgcmVOb01hdGNoLFxuICAgICAgICAgIHNvdXJjZSA9IFwiX19wICs9ICdcIjtcblxuICAgICAgLy8gQ29tcGlsZSB0aGUgcmVnZXhwIHRvIG1hdGNoIGVhY2ggZGVsaW1pdGVyLlxuICAgICAgdmFyIHJlRGVsaW1pdGVycyA9IFJlZ0V4cChcbiAgICAgICAgKG9wdGlvbnMuZXNjYXBlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wnICtcbiAgICAgICAgaW50ZXJwb2xhdGUuc291cmNlICsgJ3wnICtcbiAgICAgICAgKGludGVycG9sYXRlID09PSByZUludGVycG9sYXRlID8gcmVFc1RlbXBsYXRlIDogcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAob3B0aW9ucy5ldmFsdWF0ZSB8fCByZU5vTWF0Y2gpLnNvdXJjZSArICd8JCdcbiAgICAgICwgJ2cnKTtcblxuICAgICAgLy8gVXNlIGEgc291cmNlVVJMIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICcvLyMgc291cmNlVVJMPScgK1xuICAgICAgICAoJ3NvdXJjZVVSTCcgaW4gb3B0aW9uc1xuICAgICAgICAgID8gb3B0aW9ucy5zb3VyY2VVUkxcbiAgICAgICAgICA6ICgnbG9kYXNoLnRlbXBsYXRlU291cmNlc1snICsgKCsrdGVtcGxhdGVDb3VudGVyKSArICddJylcbiAgICAgICAgKSArICdcXG4nO1xuXG4gICAgICBzdHJpbmcucmVwbGFjZShyZURlbGltaXRlcnMsIGZ1bmN0aW9uKG1hdGNoLCBlc2NhcGVWYWx1ZSwgaW50ZXJwb2xhdGVWYWx1ZSwgZXNUZW1wbGF0ZVZhbHVlLCBldmFsdWF0ZVZhbHVlLCBvZmZzZXQpIHtcbiAgICAgICAgaW50ZXJwb2xhdGVWYWx1ZSB8fCAoaW50ZXJwb2xhdGVWYWx1ZSA9IGVzVGVtcGxhdGVWYWx1ZSk7XG5cbiAgICAgICAgLy8gRXNjYXBlIGNoYXJhY3RlcnMgdGhhdCBjYW4ndCBiZSBpbmNsdWRlZCBpbiBzdHJpbmcgbGl0ZXJhbHMuXG4gICAgICAgIHNvdXJjZSArPSBzdHJpbmcuc2xpY2UoaW5kZXgsIG9mZnNldCkucmVwbGFjZShyZVVuZXNjYXBlZFN0cmluZywgZXNjYXBlU3RyaW5nQ2hhcik7XG5cbiAgICAgICAgLy8gUmVwbGFjZSBkZWxpbWl0ZXJzIHdpdGggc25pcHBldHMuXG4gICAgICAgIGlmIChlc2NhcGVWYWx1ZSkge1xuICAgICAgICAgIGlzRXNjYXBpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbl9fZShcIiArIGVzY2FwZVZhbHVlICsgXCIpICtcXG4nXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2YWx1YXRlVmFsdWUpIHtcbiAgICAgICAgICBpc0V2YWx1YXRpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIic7XFxuXCIgKyBldmFsdWF0ZVZhbHVlICsgXCI7XFxuX19wICs9ICdcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW50ZXJwb2xhdGVWYWx1ZSkge1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbigoX190ID0gKFwiICsgaW50ZXJwb2xhdGVWYWx1ZSArIFwiKSkgPT0gbnVsbCA/ICcnIDogX190KSArXFxuJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuXG4gICAgICAgIC8vIFRoZSBKUyBlbmdpbmUgZW1iZWRkZWQgaW4gQWRvYmUgcHJvZHVjdHMgcmVxdWlyZXMgcmV0dXJuaW5nIHRoZSBgbWF0Y2hgXG4gICAgICAgIC8vIHN0cmluZyBpbiBvcmRlciB0byBwcm9kdWNlIHRoZSBjb3JyZWN0IGBvZmZzZXRgIHZhbHVlLlxuICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICB9KTtcblxuICAgICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgICAgLy8gSWYgYHZhcmlhYmxlYCBpcyBub3Qgc3BlY2lmaWVkIHdyYXAgYSB3aXRoLXN0YXRlbWVudCBhcm91bmQgdGhlIGdlbmVyYXRlZFxuICAgICAgLy8gY29kZSB0byBhZGQgdGhlIGRhdGEgb2JqZWN0IHRvIHRoZSB0b3Agb2YgdGhlIHNjb3BlIGNoYWluLlxuICAgICAgdmFyIHZhcmlhYmxlID0gb3B0aW9ucy52YXJpYWJsZTtcbiAgICAgIGlmICghdmFyaWFibGUpIHtcbiAgICAgICAgc291cmNlID0gJ3dpdGggKG9iaikge1xcbicgKyBzb3VyY2UgKyAnXFxufVxcbic7XG4gICAgICB9XG4gICAgICAvLyBDbGVhbnVwIGNvZGUgYnkgc3RyaXBwaW5nIGVtcHR5IHN0cmluZ3MuXG4gICAgICBzb3VyY2UgPSAoaXNFdmFsdWF0aW5nID8gc291cmNlLnJlcGxhY2UocmVFbXB0eVN0cmluZ0xlYWRpbmcsICcnKSA6IHNvdXJjZSlcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ01pZGRsZSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ1RyYWlsaW5nLCAnJDE7Jyk7XG5cbiAgICAgIC8vIEZyYW1lIGNvZGUgYXMgdGhlIGZ1bmN0aW9uIGJvZHkuXG4gICAgICBzb3VyY2UgPSAnZnVuY3Rpb24oJyArICh2YXJpYWJsZSB8fCAnb2JqJykgKyAnKSB7XFxuJyArXG4gICAgICAgICh2YXJpYWJsZVxuICAgICAgICAgID8gJydcbiAgICAgICAgICA6ICdvYmogfHwgKG9iaiA9IHt9KTtcXG4nXG4gICAgICAgICkgK1xuICAgICAgICBcInZhciBfX3QsIF9fcCA9ICcnXCIgK1xuICAgICAgICAoaXNFc2NhcGluZ1xuICAgICAgICAgICA/ICcsIF9fZSA9IF8uZXNjYXBlJ1xuICAgICAgICAgICA6ICcnXG4gICAgICAgICkgK1xuICAgICAgICAoaXNFdmFsdWF0aW5nXG4gICAgICAgICAgPyAnLCBfX2ogPSBBcnJheS5wcm90b3R5cGUuam9pbjtcXG4nICtcbiAgICAgICAgICAgIFwiZnVuY3Rpb24gcHJpbnQoKSB7IF9fcCArPSBfX2ouY2FsbChhcmd1bWVudHMsICcnKSB9XFxuXCJcbiAgICAgICAgICA6ICc7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgc291cmNlICtcbiAgICAgICAgJ3JldHVybiBfX3BcXG59JztcblxuICAgICAgdmFyIHJlc3VsdCA9IGF0dGVtcHQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBGdW5jdGlvbihpbXBvcnRzS2V5cywgc291cmNlVVJMICsgJ3JldHVybiAnICsgc291cmNlKS5hcHBseSh1bmRlZmluZWQsIGltcG9ydHNWYWx1ZXMpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uJ3Mgc291cmNlIGJ5IGl0cyBgdG9TdHJpbmdgIG1ldGhvZCBvclxuICAgICAgLy8gdGhlIGBzb3VyY2VgIHByb3BlcnR5IGFzIGEgY29udmVuaWVuY2UgZm9yIGlubGluaW5nIGNvbXBpbGVkIHRlbXBsYXRlcy5cbiAgICAgIHJlc3VsdC5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICBpZiAoaXNFcnJvcihyZXN1bHQpKSB7XG4gICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbSgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLnRyaW0oJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLm1hcChbJyAgZm9vICAnLCAnICBiYXIgICddLCBfLnRyaW0pO1xuICAgICAqIC8vID0+IFsnZm9vJywgJ2JhciddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbShzdHJpbmcsIGNoYXJzLCBndWFyZCkge1xuICAgICAgdmFyIHZhbHVlID0gc3RyaW5nO1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoIXN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwodmFsdWUsIGNoYXJzLCBndWFyZCkgOiBjaGFycyA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcuc2xpY2UodHJpbW1lZExlZnRJbmRleChzdHJpbmcpLCB0cmltbWVkUmlnaHRJbmRleChzdHJpbmcpICsgMSk7XG4gICAgICB9XG4gICAgICBjaGFycyA9IChjaGFycyArICcnKTtcbiAgICAgIHJldHVybiBzdHJpbmcuc2xpY2UoY2hhcnNMZWZ0SW5kZXgoc3RyaW5nLCBjaGFycyksIGNoYXJzUmlnaHRJbmRleChzdHJpbmcsIGNoYXJzKSArIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGVhZGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbUxlZnQoJyAgYWJjICAnKTtcbiAgICAgKiAvLyA9PiAnYWJjICAnXG4gICAgICpcbiAgICAgKiBfLnRyaW1MZWZ0KCctXy1hYmMtXy0nLCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnYWJjLV8tJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyaW1MZWZ0KHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICB2YXIgdmFsdWUgPSBzdHJpbmc7XG4gICAgICBzdHJpbmcgPSBiYXNlVG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGlmICghc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICBpZiAoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbCh2YWx1ZSwgY2hhcnMsIGd1YXJkKSA6IGNoYXJzID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5zbGljZSh0cmltbWVkTGVmdEluZGV4KHN0cmluZykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZy5zbGljZShjaGFyc0xlZnRJbmRleChzdHJpbmcsIChjaGFycyArICcnKSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdHJhaWxpbmcgd2hpdGVzcGFjZSBvciBzcGVjaWZpZWQgY2hhcmFjdGVycyBmcm9tIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz13aGl0ZXNwYWNlXSBUaGUgY2hhcmFjdGVycyB0byB0cmltLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRyaW1SaWdodCgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICcgIGFiYydcbiAgICAgKlxuICAgICAqIF8udHJpbVJpZ2h0KCctXy1hYmMtXy0nLCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnLV8tYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyaW1SaWdodChzdHJpbmcsIGNoYXJzLCBndWFyZCkge1xuICAgICAgdmFyIHZhbHVlID0gc3RyaW5nO1xuICAgICAgc3RyaW5nID0gYmFzZVRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoIXN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgaWYgKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwodmFsdWUsIGNoYXJzLCBndWFyZCkgOiBjaGFycyA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcuc2xpY2UoMCwgdHJpbW1lZFJpZ2h0SW5kZXgoc3RyaW5nKSArIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZy5zbGljZSgwLCBjaGFyc1JpZ2h0SW5kZXgoc3RyaW5nLCAoY2hhcnMgKyAnJykpICsgMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGVzIGBzdHJpbmdgIGlmIGl0J3MgbG9uZ2VyIHRoYW4gdGhlIGdpdmVuIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBUaGUgbGFzdCBjaGFyYWN0ZXJzIG9mIHRoZSB0cnVuY2F0ZWQgc3RyaW5nIGFyZSByZXBsYWNlZCB3aXRoIHRoZSBvbWlzc2lvblxuICAgICAqIHN0cmluZyB3aGljaCBkZWZhdWx0cyB0byBcIi4uLlwiLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRydW5jYXRlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fG51bWJlcn0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdCBvciBtYXhpbXVtIHN0cmluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmxlbmd0aD0zMF0gVGhlIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMub21pc3Npb249Jy4uLiddIFRoZSBzdHJpbmcgdG8gaW5kaWNhdGUgdGV4dCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW29wdGlvbnMuc2VwYXJhdG9yXSBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gdHJ1bmNhdGUgdG8uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGEgY2FsbGJhY2sgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJ1bmNhdGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cnVuYygnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycpO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm8uLi4nXG4gICAgICpcbiAgICAgKiBfLnRydW5jKCdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm9yaW5vJywgMjQpO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG4uLi4nXG4gICAgICpcbiAgICAgKiBfLnRydW5jKCdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm9yaW5vJywge1xuICAgICAqICAgJ2xlbmd0aCc6IDI0LFxuICAgICAqICAgJ3NlcGFyYXRvcic6ICcgJ1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuYygnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdsZW5ndGgnOiAyNCxcbiAgICAgKiAgICdzZXBhcmF0b3InOiAvLD8gKy9cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuYygnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdvbWlzc2lvbic6ICcgWy4uLl0nXG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZyBbLi4uXSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cnVuYyhzdHJpbmcsIG9wdGlvbnMsIGd1YXJkKSB7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoc3RyaW5nLCBvcHRpb25zLCBndWFyZCkpIHtcbiAgICAgICAgb3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBERUZBVUxUX1RSVU5DX0xFTkdUSCxcbiAgICAgICAgICBvbWlzc2lvbiA9IERFRkFVTFRfVFJVTkNfT01JU1NJT047XG5cbiAgICAgIGlmIChvcHRpb25zICE9IG51bGwpIHtcbiAgICAgICAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICAgICAgdmFyIHNlcGFyYXRvciA9ICdzZXBhcmF0b3InIGluIG9wdGlvbnMgPyBvcHRpb25zLnNlcGFyYXRvciA6IHNlcGFyYXRvcjtcbiAgICAgICAgICBsZW5ndGggPSAnbGVuZ3RoJyBpbiBvcHRpb25zID8gKCtvcHRpb25zLmxlbmd0aCB8fCAwKSA6IGxlbmd0aDtcbiAgICAgICAgICBvbWlzc2lvbiA9ICdvbWlzc2lvbicgaW4gb3B0aW9ucyA/IGJhc2VUb1N0cmluZyhvcHRpb25zLm9taXNzaW9uKSA6IG9taXNzaW9uO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxlbmd0aCA9ICtvcHRpb25zIHx8IDA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0cmluZyA9IGJhc2VUb1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKGxlbmd0aCA+PSBzdHJpbmcubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgZW5kID0gbGVuZ3RoIC0gb21pc3Npb24ubGVuZ3RoO1xuICAgICAgaWYgKGVuZCA8IDEpIHtcbiAgICAgICAgcmV0dXJuIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHN0cmluZy5zbGljZSgwLCBlbmQpO1xuICAgICAgaWYgKHNlcGFyYXRvciA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgKyBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIGlmIChpc1JlZ0V4cChzZXBhcmF0b3IpKSB7XG4gICAgICAgIGlmIChzdHJpbmcuc2xpY2UoZW5kKS5zZWFyY2goc2VwYXJhdG9yKSkge1xuICAgICAgICAgIHZhciBtYXRjaCxcbiAgICAgICAgICAgICAgbmV3RW5kLFxuICAgICAgICAgICAgICBzdWJzdHJpbmcgPSBzdHJpbmcuc2xpY2UoMCwgZW5kKTtcblxuICAgICAgICAgIGlmICghc2VwYXJhdG9yLmdsb2JhbCkge1xuICAgICAgICAgICAgc2VwYXJhdG9yID0gUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIChyZUZsYWdzLmV4ZWMoc2VwYXJhdG9yKSB8fCAnJykgKyAnZycpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICB3aGlsZSAoKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3Vic3RyaW5nKSkpIHtcbiAgICAgICAgICAgIG5ld0VuZCA9IG1hdGNoLmluZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMCwgbmV3RW5kID09IG51bGwgPyBlbmQgOiBuZXdFbmQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZy5pbmRleE9mKHNlcGFyYXRvciwgZW5kKSAhPSBlbmQpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gcmVzdWx0Lmxhc3RJbmRleE9mKHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnNsaWNlKDAsIGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdCArIG9taXNzaW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnZlcnNlIG9mIGBfLmVzY2FwZWA7IHRoaXMgbWV0aG9kIGNvbnZlcnRzIHRoZSBIVE1MIGVudGl0aWVzXG4gICAgICogYCZhbXA7YCwgYCZsdDtgLCBgJmd0O2AsIGAmcXVvdDtgLCBgJiMzOTtgLCBhbmQgYCYjOTY7YCBpbiBgc3RyaW5nYCB0byB0aGVpclxuICAgICAqIGNvcnJlc3BvbmRpbmcgY2hhcmFjdGVycy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBObyBvdGhlciBIVE1MIGVudGl0aWVzIGFyZSB1bmVzY2FwZWQuIFRvIHVuZXNjYXBlIGFkZGl0aW9uYWwgSFRNTFxuICAgICAqIGVudGl0aWVzIHVzZSBhIHRoaXJkLXBhcnR5IGxpYnJhcnkgbGlrZSBbX2hlX10oaHR0cHM6Ly9tdGhzLmJlL2hlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byB1bmVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmVzY2FwZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuZXNjYXBlKCdmcmVkLCBiYXJuZXksICZhbXA7IHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5lc2NhcGUoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSBiYXNlVG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiAoc3RyaW5nICYmIHJlSGFzRXNjYXBlZEh0bWwudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlRXNjYXBlZEh0bWwsIHVuZXNjYXBlSHRtbENoYXIpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW3BhdHRlcm5dIFRoZSBwYXR0ZXJuIHRvIG1hdGNoIHdvcmRzLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhIGNhbGxiYWNrIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgd29yZHMgb2YgYHN0cmluZ2AuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ud29yZHMoJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ2Jhcm5leScsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIF8ud29yZHMoJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJywgL1teLCBdKy9nKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnLCAnYmFybmV5JywgJyYnLCAncGViYmxlcyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gd29yZHMoc3RyaW5nLCBwYXR0ZXJuLCBndWFyZCkge1xuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHN0cmluZywgcGF0dGVybiwgZ3VhcmQpKSB7XG4gICAgICAgIHBhdHRlcm4gPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSBiYXNlVG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcubWF0Y2gocGF0dGVybiB8fCByZVdvcmRzKSB8fCBbXTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0cyB0byBpbnZva2UgYGZ1bmNgLCByZXR1cm5pbmcgZWl0aGVyIHRoZSByZXN1bHQgb3IgdGhlIGNhdWdodCBlcnJvclxuICAgICAqIG9iamVjdC4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCBpcyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhdHRlbXB0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBgZnVuY2AgcmVzdWx0IG9yIGVycm9yIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gYXZvaWQgdGhyb3dpbmcgZXJyb3JzIGZvciBpbnZhbGlkIHNlbGVjdG9yc1xuICAgICAqIHZhciBlbGVtZW50cyA9IF8uYXR0ZW1wdChmdW5jdGlvbihzZWxlY3Rvcikge1xuICAgICAqICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICAgICAqIH0sICc+Xz4nKTtcbiAgICAgKlxuICAgICAqIGlmIChfLmlzRXJyb3IoZWxlbWVudHMpKSB7XG4gICAgICogICBlbGVtZW50cyA9IFtdO1xuICAgICAqIH1cbiAgICAgKi9cbiAgICB2YXIgYXR0ZW1wdCA9IHJlc3RQYXJhbShmdW5jdGlvbihmdW5jLCBhcmdzKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIHJldHVybiBpc0Vycm9yKGUpID8gZSA6IG5ldyBFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIGB0aGlzQXJnYFxuICAgICAqIGFuZCBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uIElmIGBmdW5jYCBpcyBhIHByb3BlcnR5IG5hbWUgdGhlXG4gICAgICogY3JlYXRlZCBjYWxsYmFjayByZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZSBmb3IgYSBnaXZlbiBlbGVtZW50LiBJZiBgZnVuY2BcbiAgICAgKiBpcyBhbiBvYmplY3QgdGhlIGNyZWF0ZWQgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgY29udGFpblxuICAgICAqIHRoZSBlcXVpdmFsZW50IG9iamVjdCBwcm9wZXJ0aWVzLCBvdGhlcndpc2UgaXQgcmV0dXJucyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGl0ZXJhdGVlXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0geyp9IFtmdW5jPV8uaWRlbnRpdHldIFRoZSB2YWx1ZSB0byBjb252ZXJ0IHRvIGEgY2FsbGJhY2suXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB3cmFwIHRvIGNyZWF0ZSBjdXN0b20gY2FsbGJhY2sgc2hvcnRoYW5kc1xuICAgICAqIF8uY2FsbGJhY2sgPSBfLndyYXAoXy5jYWxsYmFjaywgZnVuY3Rpb24oY2FsbGJhY2ssIGZ1bmMsIHRoaXNBcmcpIHtcbiAgICAgKiAgIHZhciBtYXRjaCA9IC9eKC4rPylfXyhbZ2xddCkoLispJC8uZXhlYyhmdW5jKTtcbiAgICAgKiAgIGlmICghbWF0Y2gpIHtcbiAgICAgKiAgICAgcmV0dXJuIGNhbGxiYWNrKGZ1bmMsIHRoaXNBcmcpO1xuICAgICAqICAgfVxuICAgICAqICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAqICAgICByZXR1cm4gbWF0Y2hbMl0gPT0gJ2d0J1xuICAgICAqICAgICAgID8gb2JqZWN0W21hdGNoWzFdXSA+IG1hdGNoWzNdXG4gICAgICogICAgICAgOiBvYmplY3RbbWF0Y2hbMV1dIDwgbWF0Y2hbM107XG4gICAgICogICB9O1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIodXNlcnMsICdhZ2VfX2d0MzYnKTtcbiAgICAgKiAvLyA9PiBbeyAndXNlcic6ICdmcmVkJywgJ2FnZSc6IDQwIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FsbGJhY2soZnVuYywgdGhpc0FyZywgZ3VhcmQpIHtcbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChmdW5jLCB0aGlzQXJnLCBndWFyZCkpIHtcbiAgICAgICAgdGhpc0FyZyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc09iamVjdExpa2UoZnVuYylcbiAgICAgICAgPyBtYXRjaGVzKGZ1bmMpXG4gICAgICAgIDogYmFzZUNhbGxiYWNrKGZ1bmMsIHRoaXNBcmcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmV0dXJuIGZyb20gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKiB2YXIgZ2V0dGVyID0gXy5jb25zdGFudChvYmplY3QpO1xuICAgICAqXG4gICAgICogZ2V0dGVyKCkgPT09IG9iamVjdDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uc3RhbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBmaXJzdCBhcmd1bWVudCBwcm92aWRlZCB0byBpdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBBbnkgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgYHZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIF8uaWRlbnRpdHkob2JqZWN0KSA9PT0gb2JqZWN0O1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpZGVudGl0eSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYSBnaXZlbiBvYmplY3RcbiAgICAgKiBhbmQgYHNvdXJjZWAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIG9iamVjdCBoYXMgZXF1aXZhbGVudCBwcm9wZXJ0eVxuICAgICAqIHZhbHVlcywgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHN1cHBvcnRzIGNvbXBhcmluZyBhcnJheXMsIGJvb2xlYW5zLCBgRGF0ZWAgb2JqZWN0cyxcbiAgICAgKiBudW1iZXJzLCBgT2JqZWN0YCBvYmplY3RzLCByZWdleGVzLCBhbmQgc3RyaW5ncy4gT2JqZWN0cyBhcmUgY29tcGFyZWQgYnlcbiAgICAgKiB0aGVpciBvd24sIG5vdCBpbmhlcml0ZWQsIGVudW1lcmFibGUgcHJvcGVydGllcy4gRm9yIGNvbXBhcmluZyBhIHNpbmdsZVxuICAgICAqIG93biBvciBpbmhlcml0ZWQgcHJvcGVydHkgdmFsdWUgc2VlIGBfLm1hdGNoZXNQcm9wZXJ0eWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLm1hdGNoZXMoeyAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9KSk7XG4gICAgICogLy8gPT4gW3sgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hlcyhzb3VyY2UpIHtcbiAgICAgIHJldHVybiBiYXNlTWF0Y2hlcyhiYXNlQ2xvbmUoc291cmNlLCB0cnVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY29tcGFyZXMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIGBwYXRoYCBvbiBhIGdpdmVuXG4gICAgICogb2JqZWN0IHRvIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2Qgc3VwcG9ydHMgY29tcGFyaW5nIGFycmF5cywgYm9vbGVhbnMsIGBEYXRlYCBvYmplY3RzLFxuICAgICAqIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsIGFuZCBzdHJpbmdzLiBPYmplY3RzIGFyZSBjb21wYXJlZCBieVxuICAgICAqIHRoZWlyIG93biwgbm90IGluaGVyaXRlZCwgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmQodXNlcnMsIF8ubWF0Y2hlc1Byb3BlcnR5KCd1c2VyJywgJ2ZyZWQnKSk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdmcmVkJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hlc1Byb3BlcnR5KHBhdGgsIHNyY1ZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZU1hdGNoZXNQcm9wZXJ0eShwYXRoLCBiYXNlQ2xvbmUoc3JjVmFsdWUsIHRydWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9uIGEgZ2l2ZW4gb2JqZWN0LlxuICAgICAqIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdG8gdGhlIGludm9rZWQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiB7ICdjJzogXy5jb25zdGFudCgyKSB9IH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogeyAnYyc6IF8uY29uc3RhbnQoMSkgfSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5tZXRob2QoJ2EuYi5jJykpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqXG4gICAgICogXy5pbnZva2UoXy5zb3J0Qnkob2JqZWN0cywgXy5tZXRob2QoWydhJywgJ2InLCAnYyddKSksICdhLmIuYycpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIHZhciBtZXRob2QgPSByZXN0UGFyYW0oZnVuY3Rpb24ocGF0aCwgYXJncykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gaW52b2tlUGF0aChvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5tZXRob2RgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogdGhlIG1ldGhvZCBhdCBhIGdpdmVuIHBhdGggb24gYG9iamVjdGAuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmVcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IF8udGltZXMoMywgXy5jb25zdGFudCksXG4gICAgICogICAgIG9iamVjdCA9IHsgJ2EnOiBhcnJheSwgJ2InOiBhcnJheSwgJ2MnOiBhcnJheSB9O1xuICAgICAqXG4gICAgICogXy5tYXAoWydhWzJdJywgJ2NbMF0nXSwgXy5tZXRob2RPZihvYmplY3QpKTtcbiAgICAgKiAvLyA9PiBbMiwgMF1cbiAgICAgKlxuICAgICAqIF8ubWFwKFtbJ2EnLCAnMiddLCBbJ2MnLCAnMCddXSwgXy5tZXRob2RPZihvYmplY3QpKTtcbiAgICAgKiAvLyA9PiBbMiwgMF1cbiAgICAgKi9cbiAgICB2YXIgbWV0aG9kT2YgPSByZXN0UGFyYW0oZnVuY3Rpb24ob2JqZWN0LCBhcmdzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocGF0aCkge1xuICAgICAgICByZXR1cm4gaW52b2tlUGF0aChvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYWxsIG93biBlbnVtZXJhYmxlIGZ1bmN0aW9uIHByb3BlcnRpZXMgb2YgYSBzb3VyY2Ugb2JqZWN0IHRvIHRoZVxuICAgICAqIGRlc3RpbmF0aW9uIG9iamVjdC4gSWYgYG9iamVjdGAgaXMgYSBmdW5jdGlvbiB0aGVuIG1ldGhvZHMgYXJlIGFkZGVkIHRvXG4gICAgICogaXRzIHByb3RvdHlwZSBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVzZSBgXy5ydW5JbkNvbnRleHRgIHRvIGNyZWF0ZSBhIHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHRvXG4gICAgICogYXZvaWQgY29uZmxpY3RzIGNhdXNlZCBieSBtb2RpZnlpbmcgdGhlIG9yaWdpbmFsLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdH0gW29iamVjdD1sb2Rhc2hdIFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5jaGFpbj10cnVlXSBTcGVjaWZ5IHdoZXRoZXIgdGhlIGZ1bmN0aW9ucyBhZGRlZFxuICAgICAqICBhcmUgY2hhaW5hYmxlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbnxPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHZvd2VscyhzdHJpbmcpIHtcbiAgICAgKiAgIHJldHVybiBfLmZpbHRlcihzdHJpbmcsIGZ1bmN0aW9uKHYpIHtcbiAgICAgKiAgICAgcmV0dXJuIC9bYWVpb3VdL2kudGVzdCh2KTtcbiAgICAgKiAgIH0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWl4aW4oeyAndm93ZWxzJzogdm93ZWxzIH0pO1xuICAgICAqIF8udm93ZWxzKCdmcmVkJyk7XG4gICAgICogLy8gPT4gWydlJ11cbiAgICAgKlxuICAgICAqIF8oJ2ZyZWQnKS52b3dlbHMoKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsnZSddXG4gICAgICpcbiAgICAgKiBfLm1peGluKHsgJ3Zvd2Vscyc6IHZvd2VscyB9LCB7ICdjaGFpbic6IGZhbHNlIH0pO1xuICAgICAqIF8oJ2ZyZWQnKS52b3dlbHMoKTtcbiAgICAgKiAvLyA9PiBbJ2UnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1peGluKG9iamVjdCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgICBpZiAob3B0aW9ucyA9PSBudWxsKSB7XG4gICAgICAgIHZhciBpc09iaiA9IGlzT2JqZWN0KHNvdXJjZSksXG4gICAgICAgICAgICBwcm9wcyA9IGlzT2JqID8ga2V5cyhzb3VyY2UpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgbWV0aG9kTmFtZXMgPSAocHJvcHMgJiYgcHJvcHMubGVuZ3RoKSA/IGJhc2VGdW5jdGlvbnMoc291cmNlLCBwcm9wcykgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKCEobWV0aG9kTmFtZXMgPyBtZXRob2ROYW1lcy5sZW5ndGggOiBpc09iaikpIHtcbiAgICAgICAgICBtZXRob2ROYW1lcyA9IGZhbHNlO1xuICAgICAgICAgIG9wdGlvbnMgPSBzb3VyY2U7XG4gICAgICAgICAgc291cmNlID0gb2JqZWN0O1xuICAgICAgICAgIG9iamVjdCA9IHRoaXM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghbWV0aG9kTmFtZXMpIHtcbiAgICAgICAgbWV0aG9kTmFtZXMgPSBiYXNlRnVuY3Rpb25zKHNvdXJjZSwga2V5cyhzb3VyY2UpKTtcbiAgICAgIH1cbiAgICAgIHZhciBjaGFpbiA9IHRydWUsXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc0Z1bmMgPSBpc0Z1bmN0aW9uKG9iamVjdCksXG4gICAgICAgICAgbGVuZ3RoID0gbWV0aG9kTmFtZXMubGVuZ3RoO1xuXG4gICAgICBpZiAob3B0aW9ucyA9PT0gZmFsc2UpIHtcbiAgICAgICAgY2hhaW4gPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3Qob3B0aW9ucykgJiYgJ2NoYWluJyBpbiBvcHRpb25zKSB7XG4gICAgICAgIGNoYWluID0gb3B0aW9ucy5jaGFpbjtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBtZXRob2ROYW1lID0gbWV0aG9kTmFtZXNbaW5kZXhdLFxuICAgICAgICAgICAgZnVuYyA9IHNvdXJjZVttZXRob2ROYW1lXTtcblxuICAgICAgICBvYmplY3RbbWV0aG9kTmFtZV0gPSBmdW5jO1xuICAgICAgICBpZiAoaXNGdW5jKSB7XG4gICAgICAgICAgb2JqZWN0LnByb3RvdHlwZVttZXRob2ROYW1lXSA9IChmdW5jdGlvbihmdW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fO1xuICAgICAgICAgICAgICBpZiAoY2hhaW4gfHwgY2hhaW5BbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gb2JqZWN0KHRoaXMuX193cmFwcGVkX18pLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25zID0gcmVzdWx0Ll9fYWN0aW9uc19fID0gYXJyYXlDb3B5KHRoaXMuX19hY3Rpb25zX18pO1xuXG4gICAgICAgICAgICAgICAgYWN0aW9ucy5wdXNoKHsgJ2Z1bmMnOiBmdW5jLCAnYXJncyc6IGFyZ3VtZW50cywgJ3RoaXNBcmcnOiBvYmplY3QgfSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0Ll9fY2hhaW5fXyA9IGNoYWluQWxsO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkob2JqZWN0LCBhcnJheVB1c2goW3RoaXMudmFsdWUoKV0sIGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KGZ1bmMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBgX2AgdmFyaWFibGUgdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvXG4gICAgICogdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgbG9kYXNoID0gXy5ub0NvbmZsaWN0KCk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgIHJvb3QuXyA9IG9sZERhc2g7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIG5vLW9wZXJhdGlvbiBmdW5jdGlvbiB0aGF0IHJldHVybnMgYHVuZGVmaW5lZGAgcmVnYXJkbGVzcyBvZiB0aGVcbiAgICAgKiBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqXG4gICAgICogXy5ub29wKG9iamVjdCkgPT09IHVuZGVmaW5lZDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbm9vcCgpIHtcbiAgICAgIC8vIE5vIG9wZXJhdGlvbiBwZXJmb3JtZWQuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgYXQgYHBhdGhgIG9uIGFcbiAgICAgKiBnaXZlbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiB7ICdjJzogMiB9IH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogeyAnYyc6IDEgfSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5wcm9wZXJ0eSgnYS5iLmMnKSk7XG4gICAgICogLy8gPT4gWzIsIDFdXG4gICAgICpcbiAgICAgKiBfLnBsdWNrKF8uc29ydEJ5KG9iamVjdHMsIF8ucHJvcGVydHkoWydhJywgJ2InLCAnYyddKSksICdhLmIuYycpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHByb3BlcnR5KHBhdGgpIHtcbiAgICAgIHJldHVybiBpc0tleShwYXRoKSA/IGJhc2VQcm9wZXJ0eShwYXRoKSA6IGJhc2VQcm9wZXJ0eURlZXAocGF0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLnByb3BlcnR5YDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJuc1xuICAgICAqIHRoZSBwcm9wZXJ0eSB2YWx1ZSBhdCBhIGdpdmVuIHBhdGggb24gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0eVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzAsIDEsIDJdLFxuICAgICAqICAgICBvYmplY3QgPSB7ICdhJzogYXJyYXksICdiJzogYXJyYXksICdjJzogYXJyYXkgfTtcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnYVsyXScsICdjWzBdJ10sIF8ucHJvcGVydHlPZihvYmplY3QpKTtcbiAgICAgKiAvLyA9PiBbMiwgMF1cbiAgICAgKlxuICAgICAqIF8ubWFwKFtbJ2EnLCAnMiddLCBbJ2MnLCAnMCddXSwgXy5wcm9wZXJ0eU9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHByb3BlcnR5T2Yob2JqZWN0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocGF0aCkge1xuICAgICAgICByZXR1cm4gYmFzZUdldChvYmplY3QsIHRvUGF0aChwYXRoKSwgcGF0aCArICcnKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBudW1iZXJzIChwb3NpdGl2ZSBhbmQvb3IgbmVnYXRpdmUpIHByb2dyZXNzaW5nIGZyb21cbiAgICAgKiBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIElmIGBlbmRgIGlzIG5vdCBzcGVjaWZpZWQgaXQgaXNcbiAgICAgKiBzZXQgdG8gYHN0YXJ0YCB3aXRoIGBzdGFydGAgdGhlbiBzZXQgdG8gYDBgLiBJZiBgZW5kYCBpcyBsZXNzIHRoYW4gYHN0YXJ0YFxuICAgICAqIGEgemVyby1sZW5ndGggcmFuZ2UgaXMgY3JlYXRlZCB1bmxlc3MgYSBuZWdhdGl2ZSBgc3RlcGAgaXMgc3BlY2lmaWVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0ZXA9MV0gVGhlIHZhbHVlIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgbnVtYmVycy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5nZSg0KTtcbiAgICAgKiAvLyA9PiBbMCwgMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDRdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMCwgNSwgMTAsIDE1XVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwLCAtNCwgLTEpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA0LCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMSwgMV1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByYW5nZShzdGFydCwgZW5kLCBzdGVwKSB7XG4gICAgICBpZiAoc3RlcCAmJiBpc0l0ZXJhdGVlQ2FsbChzdGFydCwgZW5kLCBzdGVwKSkge1xuICAgICAgICBlbmQgPSBzdGVwID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSArc3RhcnQgfHwgMDtcbiAgICAgIHN0ZXAgPSBzdGVwID09IG51bGwgPyAxIDogKCtzdGVwIHx8IDApO1xuXG4gICAgICBpZiAoZW5kID09IG51bGwpIHtcbiAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVuZCA9ICtlbmQgfHwgMDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBgQXJyYXkobGVuZ3RoKWAgc28gZW5naW5lcyBsaWtlIENoYWtyYSBhbmQgVjggYXZvaWQgc2xvd2VyIG1vZGVzLlxuICAgICAgLy8gU2VlIGh0dHBzOi8veW91dHUuYmUvWEFxSXBHVThaWmsjdD0xN20yNXMgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChuYXRpdmVDZWlsKChlbmQgLSBzdGFydCkgLyAoc3RlcCB8fCAxKSksIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBzdGFydDtcbiAgICAgICAgc3RhcnQgKz0gc3RlcDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyB0aGUgaXRlcmF0ZWUgZnVuY3Rpb24gYG5gIHRpbWVzLCByZXR1cm5pbmcgYW4gYXJyYXkgb2YgdGhlIHJlc3VsdHNcbiAgICAgKiBvZiBlYWNoIGludm9jYXRpb24uIFRoZSBgaXRlcmF0ZWVgIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoXG4gICAgICogb25lIGFyZ3VtZW50OyAoaW5kZXgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdHlcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIHRpbWVzIHRvIGludm9rZSBgaXRlcmF0ZWVgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcmVzdWx0cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGRpY2VSb2xscyA9IF8udGltZXMoMywgXy5wYXJ0aWFsKF8ucmFuZG9tLCAxLCA2LCBmYWxzZSkpO1xuICAgICAqIC8vID0+IFszLCA2LCA0XVxuICAgICAqXG4gICAgICogXy50aW1lcygzLCBmdW5jdGlvbihuKSB7XG4gICAgICogICBtYWdlLmNhc3RTcGVsbChuKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBpbnZva2VzIGBtYWdlLmNhc3RTcGVsbChuKWAgdGhyZWUgdGltZXMgd2l0aCBgbmAgb2YgYDBgLCBgMWAsIGFuZCBgMmBcbiAgICAgKlxuICAgICAqIF8udGltZXMoMywgZnVuY3Rpb24obikge1xuICAgICAqICAgdGhpcy5jYXN0KG4pO1xuICAgICAqIH0sIG1hZ2UpO1xuICAgICAqIC8vID0+IGFsc28gaW52b2tlcyBgbWFnZS5jYXN0U3BlbGwobilgIHRocmVlIHRpbWVzXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGltZXMobiwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgIG4gPSBuYXRpdmVGbG9vcihuKTtcblxuICAgICAgLy8gRXhpdCBlYXJseSB0byBhdm9pZCBhIEpTQyBKSVQgYnVnIGluIFNhZmFyaSA4XG4gICAgICAvLyB3aGVyZSBgQXJyYXkoMClgIGlzIHRyZWF0ZWQgYXMgYEFycmF5KDEpYC5cbiAgICAgIGlmIChuIDwgMSB8fCAhbmF0aXZlSXNGaW5pdGUobikpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobmF0aXZlTWluKG4sIE1BWF9BUlJBWV9MRU5HVEgpKTtcblxuICAgICAgaXRlcmF0ZWUgPSBiaW5kQ2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDEpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBuKSB7XG4gICAgICAgIGlmIChpbmRleCA8IE1BWF9BUlJBWV9MRU5HVEgpIHtcbiAgICAgICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoaW5kZXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZXJhdGVlKGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQuIElmIGBwcmVmaXhgIGlzIHByb3ZpZGVkIHRoZSBJRCBpcyBhcHBlbmRlZCB0byBpdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtwcmVmaXhdIFRoZSB2YWx1ZSB0byBwcmVmaXggdGhlIElEIHdpdGguXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdW5pcXVlIElELlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXF1ZUlkKCdjb250YWN0XycpO1xuICAgICAqIC8vID0+ICdjb250YWN0XzEwNCdcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoKTtcbiAgICAgKiAvLyA9PiAnMTA1J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXF1ZUlkKHByZWZpeCkge1xuICAgICAgdmFyIGlkID0gKytpZENvdW50ZXI7XG4gICAgICByZXR1cm4gYmFzZVRvU3RyaW5nKHByZWZpeCkgKyBpZDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBBZGRzIHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYXVnZW5kIFRoZSBmaXJzdCBudW1iZXIgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRlbmQgVGhlIHNlY29uZCBudW1iZXIgdG8gYWRkLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5hZGQoNiwgNCk7XG4gICAgICogLy8gPT4gMTBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZGQoYXVnZW5kLCBhZGRlbmQpIHtcbiAgICAgIHJldHVybiAoK2F1Z2VuZCB8fCAwKSArICgrYWRkZW5kIHx8IDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgYG5gIHJvdW5kZWQgdXAgdG8gYHByZWNpc2lvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgdG8gcm91bmQgdXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwcmVjaXNpb249MF0gVGhlIHByZWNpc2lvbiB0byByb3VuZCB1cCB0by5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByb3VuZGVkIHVwIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jZWlsKDQuMDA2KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICpcbiAgICAgKiBfLmNlaWwoNi4wMDQsIDIpO1xuICAgICAqIC8vID0+IDYuMDFcbiAgICAgKlxuICAgICAqIF8uY2VpbCg2MDQwLCAtMik7XG4gICAgICogLy8gPT4gNjEwMFxuICAgICAqL1xuICAgIHZhciBjZWlsID0gY3JlYXRlUm91bmQoJ2NlaWwnKTtcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgYG5gIHJvdW5kZWQgZG93biB0byBgcHJlY2lzaW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciB0byByb3VuZCBkb3duLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgZG93biB0by5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByb3VuZGVkIGRvd24gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsb29yKDQuMDA2KTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICpcbiAgICAgKiBfLmZsb29yKDAuMDQ2LCAyKTtcbiAgICAgKiAvLyA9PiAwLjA0XG4gICAgICpcbiAgICAgKiBfLmZsb29yKDQwNjAsIC0yKTtcbiAgICAgKiAvLyA9PiA0MDAwXG4gICAgICovXG4gICAgdmFyIGZsb29yID0gY3JlYXRlUm91bmQoJ2Zsb29yJyk7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBtYXhpbXVtIHZhbHVlIG9mIGBjb2xsZWN0aW9uYC4gSWYgYGNvbGxlY3Rpb25gIGlzIGVtcHR5IG9yIGZhbHNleVxuICAgICAqIGAtSW5maW5pdHlgIGlzIHJldHVybmVkLiBJZiBhbiBpdGVyYXRlZSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpdCBpcyBpbnZva2VkXG4gICAgICogZm9yIGVhY2ggdmFsdWUgaW4gYGNvbGxlY3Rpb25gIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2ggdGhlIHZhbHVlXG4gICAgICogaXMgcmFua2VkLiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWVdIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXgoW10pO1xuICAgICAqIC8vID0+IC1JbmZpbml0eVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXgodXNlcnMsIGZ1bmN0aW9uKGNocikge1xuICAgICAqICAgcmV0dXJuIGNoci5hZ2U7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdmcmVkJywgJ2FnZSc6IDQwIH1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgXy5wcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5tYXgodXNlcnMsICdhZ2UnKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfVxuICAgICAqL1xuICAgIHZhciBtYXggPSBjcmVhdGVFeHRyZW11bShndCwgTkVHQVRJVkVfSU5GSU5JVFkpO1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbWluaW11bSB2YWx1ZSBvZiBgY29sbGVjdGlvbmAuIElmIGBjb2xsZWN0aW9uYCBpcyBlbXB0eSBvciBmYWxzZXlcbiAgICAgKiBgSW5maW5pdHlgIGlzIHJldHVybmVkLiBJZiBhbiBpdGVyYXRlZSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpdCBpcyBpbnZva2VkXG4gICAgICogZm9yIGVhY2ggdmFsdWUgaW4gYGNvbGxlY3Rpb25gIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2ggdGhlIHZhbHVlXG4gICAgICogaXMgcmFua2VkLiBUaGUgYGl0ZXJhdGVlYCBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ucHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhIHZhbHVlIGlzIGFsc28gcHJvdmlkZWQgZm9yIGB0aGlzQXJnYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzUHJvcGVydHlgXG4gICAgICogc3R5bGUgY2FsbGJhY2sgcmV0dXJucyBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSBhIG1hdGNoaW5nIHByb3BlcnR5XG4gICAgICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5tYXRjaGVzYCBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gICAgICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWVdIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1pbmltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWluKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5taW4oW10pO1xuICAgICAqIC8vID0+IEluZmluaXR5XG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLm1pbih1c2VycywgZnVuY3Rpb24oY2hyKSB7XG4gICAgICogICByZXR1cm4gY2hyLmFnZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ubWluKHVzZXJzLCAnYWdlJyk7XG4gICAgICogLy8gPT4geyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfVxuICAgICAqL1xuICAgIHZhciBtaW4gPSBjcmVhdGVFeHRyZW11bShsdCwgUE9TSVRJVkVfSU5GSU5JVFkpO1xuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyBgbmAgcm91bmRlZCB0byBgcHJlY2lzaW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciB0byByb3VuZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3ByZWNpc2lvbj0wXSBUaGUgcHJlY2lzaW9uIHRvIHJvdW5kIHRvLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHJvdW5kZWQgbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJvdW5kKDQuMDA2KTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICpcbiAgICAgKiBfLnJvdW5kKDQuMDA2LCAyKTtcbiAgICAgKiAvLyA9PiA0LjAxXG4gICAgICpcbiAgICAgKiBfLnJvdW5kKDQwNjAsIC0yKTtcbiAgICAgKiAvLyA9PiA0MTAwXG4gICAgICovXG4gICAgdmFyIHJvdW5kID0gY3JlYXRlUm91bmQoJ3JvdW5kJyk7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiBgY29sbGVjdGlvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWVdIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBpdGVyYXRlZWAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN1bShbNCwgNl0pO1xuICAgICAqIC8vID0+IDEwXG4gICAgICpcbiAgICAgKiBfLnN1bSh7ICdhJzogNCwgJ2InOiA2IH0pO1xuICAgICAqIC8vID0+IDEwXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFtcbiAgICAgKiAgIHsgJ24nOiA0IH0sXG4gICAgICogICB7ICduJzogNiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uc3VtKG9iamVjdHMsIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAqICAgcmV0dXJuIG9iamVjdC5uO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDEwXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uc3VtKG9iamVjdHMsICduJyk7XG4gICAgICogLy8gPT4gMTBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdW0oY29sbGVjdGlvbiwgaXRlcmF0ZWUsIHRoaXNBcmcpIHtcbiAgICAgIGlmICh0aGlzQXJnICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCB0aGlzQXJnKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGl0ZXJhdGVlID0gZ2V0Q2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDMpO1xuICAgICAgcmV0dXJuIGl0ZXJhdGVlLmxlbmd0aCA9PSAxXG4gICAgICAgID8gYXJyYXlTdW0oaXNBcnJheShjb2xsZWN0aW9uKSA/IGNvbGxlY3Rpb24gOiB0b0l0ZXJhYmxlKGNvbGxlY3Rpb24pLCBpdGVyYXRlZSlcbiAgICAgICAgOiBiYXNlU3VtKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBFbnN1cmUgd3JhcHBlcnMgYXJlIGluc3RhbmNlcyBvZiBgYmFzZUxvZGFzaGAuXG4gICAgbG9kYXNoLnByb3RvdHlwZSA9IGJhc2VMb2Rhc2gucHJvdG90eXBlO1xuXG4gICAgTG9kYXNoV3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMb2Rhc2hXcmFwcGVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IExvZGFzaFdyYXBwZXI7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBMYXp5V3JhcHBlcjtcblxuICAgIC8vIEFkZCBmdW5jdGlvbnMgdG8gdGhlIGBNYXBgIGNhY2hlLlxuICAgIE1hcENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBtYXBEZWxldGU7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlLmdldCA9IG1hcEdldDtcbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuaGFzID0gbWFwSGFzO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZS5zZXQgPSBtYXBTZXQ7XG5cbiAgICAvLyBBZGQgZnVuY3Rpb25zIHRvIHRoZSBgU2V0YCBjYWNoZS5cbiAgICBTZXRDYWNoZS5wcm90b3R5cGUucHVzaCA9IGNhY2hlUHVzaDtcblxuICAgIC8vIEFzc2lnbiBjYWNoZSB0byBgXy5tZW1vaXplYC5cbiAgICBtZW1vaXplLkNhY2hlID0gTWFwQ2FjaGU7XG5cbiAgICAvLyBBZGQgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIHdyYXBwZWQgdmFsdWVzIHdoZW4gY2hhaW5pbmcuXG4gICAgbG9kYXNoLmFmdGVyID0gYWZ0ZXI7XG4gICAgbG9kYXNoLmFyeSA9IGFyeTtcbiAgICBsb2Rhc2guYXNzaWduID0gYXNzaWduO1xuICAgIGxvZGFzaC5hdCA9IGF0O1xuICAgIGxvZGFzaC5iZWZvcmUgPSBiZWZvcmU7XG4gICAgbG9kYXNoLmJpbmQgPSBiaW5kO1xuICAgIGxvZGFzaC5iaW5kQWxsID0gYmluZEFsbDtcbiAgICBsb2Rhc2guYmluZEtleSA9IGJpbmRLZXk7XG4gICAgbG9kYXNoLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgbG9kYXNoLmNoYWluID0gY2hhaW47XG4gICAgbG9kYXNoLmNodW5rID0gY2h1bms7XG4gICAgbG9kYXNoLmNvbXBhY3QgPSBjb21wYWN0O1xuICAgIGxvZGFzaC5jb25zdGFudCA9IGNvbnN0YW50O1xuICAgIGxvZGFzaC5jb3VudEJ5ID0gY291bnRCeTtcbiAgICBsb2Rhc2guY3JlYXRlID0gY3JlYXRlO1xuICAgIGxvZGFzaC5jdXJyeSA9IGN1cnJ5O1xuICAgIGxvZGFzaC5jdXJyeVJpZ2h0ID0gY3VycnlSaWdodDtcbiAgICBsb2Rhc2guZGVib3VuY2UgPSBkZWJvdW5jZTtcbiAgICBsb2Rhc2guZGVmYXVsdHMgPSBkZWZhdWx0cztcbiAgICBsb2Rhc2guZGVmYXVsdHNEZWVwID0gZGVmYXVsdHNEZWVwO1xuICAgIGxvZGFzaC5kZWZlciA9IGRlZmVyO1xuICAgIGxvZGFzaC5kZWxheSA9IGRlbGF5O1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlID0gZGlmZmVyZW5jZTtcbiAgICBsb2Rhc2guZHJvcCA9IGRyb3A7XG4gICAgbG9kYXNoLmRyb3BSaWdodCA9IGRyb3BSaWdodDtcbiAgICBsb2Rhc2guZHJvcFJpZ2h0V2hpbGUgPSBkcm9wUmlnaHRXaGlsZTtcbiAgICBsb2Rhc2guZHJvcFdoaWxlID0gZHJvcFdoaWxlO1xuICAgIGxvZGFzaC5maWxsID0gZmlsbDtcbiAgICBsb2Rhc2guZmlsdGVyID0gZmlsdGVyO1xuICAgIGxvZGFzaC5mbGF0dGVuID0gZmxhdHRlbjtcbiAgICBsb2Rhc2guZmxhdHRlbkRlZXAgPSBmbGF0dGVuRGVlcDtcbiAgICBsb2Rhc2guZmxvdyA9IGZsb3c7XG4gICAgbG9kYXNoLmZsb3dSaWdodCA9IGZsb3dSaWdodDtcbiAgICBsb2Rhc2guZm9yRWFjaCA9IGZvckVhY2g7XG4gICAgbG9kYXNoLmZvckVhY2hSaWdodCA9IGZvckVhY2hSaWdodDtcbiAgICBsb2Rhc2guZm9ySW4gPSBmb3JJbjtcbiAgICBsb2Rhc2guZm9ySW5SaWdodCA9IGZvckluUmlnaHQ7XG4gICAgbG9kYXNoLmZvck93biA9IGZvck93bjtcbiAgICBsb2Rhc2guZm9yT3duUmlnaHQgPSBmb3JPd25SaWdodDtcbiAgICBsb2Rhc2guZnVuY3Rpb25zID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5ncm91cEJ5ID0gZ3JvdXBCeTtcbiAgICBsb2Rhc2guaW5kZXhCeSA9IGluZGV4Qnk7XG4gICAgbG9kYXNoLmluaXRpYWwgPSBpbml0aWFsO1xuICAgIGxvZGFzaC5pbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3Rpb247XG4gICAgbG9kYXNoLmludmVydCA9IGludmVydDtcbiAgICBsb2Rhc2guaW52b2tlID0gaW52b2tlO1xuICAgIGxvZGFzaC5rZXlzID0ga2V5cztcbiAgICBsb2Rhc2gua2V5c0luID0ga2V5c0luO1xuICAgIGxvZGFzaC5tYXAgPSBtYXA7XG4gICAgbG9kYXNoLm1hcEtleXMgPSBtYXBLZXlzO1xuICAgIGxvZGFzaC5tYXBWYWx1ZXMgPSBtYXBWYWx1ZXM7XG4gICAgbG9kYXNoLm1hdGNoZXMgPSBtYXRjaGVzO1xuICAgIGxvZGFzaC5tYXRjaGVzUHJvcGVydHkgPSBtYXRjaGVzUHJvcGVydHk7XG4gICAgbG9kYXNoLm1lbW9pemUgPSBtZW1vaXplO1xuICAgIGxvZGFzaC5tZXJnZSA9IG1lcmdlO1xuICAgIGxvZGFzaC5tZXRob2QgPSBtZXRob2Q7XG4gICAgbG9kYXNoLm1ldGhvZE9mID0gbWV0aG9kT2Y7XG4gICAgbG9kYXNoLm1peGluID0gbWl4aW47XG4gICAgbG9kYXNoLm1vZEFyZ3MgPSBtb2RBcmdzO1xuICAgIGxvZGFzaC5uZWdhdGUgPSBuZWdhdGU7XG4gICAgbG9kYXNoLm9taXQgPSBvbWl0O1xuICAgIGxvZGFzaC5vbmNlID0gb25jZTtcbiAgICBsb2Rhc2gucGFpcnMgPSBwYWlycztcbiAgICBsb2Rhc2gucGFydGlhbCA9IHBhcnRpYWw7XG4gICAgbG9kYXNoLnBhcnRpYWxSaWdodCA9IHBhcnRpYWxSaWdodDtcbiAgICBsb2Rhc2gucGFydGl0aW9uID0gcGFydGl0aW9uO1xuICAgIGxvZGFzaC5waWNrID0gcGljaztcbiAgICBsb2Rhc2gucGx1Y2sgPSBwbHVjaztcbiAgICBsb2Rhc2gucHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICBsb2Rhc2gucHJvcGVydHlPZiA9IHByb3BlcnR5T2Y7XG4gICAgbG9kYXNoLnB1bGwgPSBwdWxsO1xuICAgIGxvZGFzaC5wdWxsQXQgPSBwdWxsQXQ7XG4gICAgbG9kYXNoLnJhbmdlID0gcmFuZ2U7XG4gICAgbG9kYXNoLnJlYXJnID0gcmVhcmc7XG4gICAgbG9kYXNoLnJlamVjdCA9IHJlamVjdDtcbiAgICBsb2Rhc2gucmVtb3ZlID0gcmVtb3ZlO1xuICAgIGxvZGFzaC5yZXN0ID0gcmVzdDtcbiAgICBsb2Rhc2gucmVzdFBhcmFtID0gcmVzdFBhcmFtO1xuICAgIGxvZGFzaC5zZXQgPSBzZXQ7XG4gICAgbG9kYXNoLnNodWZmbGUgPSBzaHVmZmxlO1xuICAgIGxvZGFzaC5zbGljZSA9IHNsaWNlO1xuICAgIGxvZGFzaC5zb3J0QnkgPSBzb3J0Qnk7XG4gICAgbG9kYXNoLnNvcnRCeUFsbCA9IHNvcnRCeUFsbDtcbiAgICBsb2Rhc2guc29ydEJ5T3JkZXIgPSBzb3J0QnlPcmRlcjtcbiAgICBsb2Rhc2guc3ByZWFkID0gc3ByZWFkO1xuICAgIGxvZGFzaC50YWtlID0gdGFrZTtcbiAgICBsb2Rhc2gudGFrZVJpZ2h0ID0gdGFrZVJpZ2h0O1xuICAgIGxvZGFzaC50YWtlUmlnaHRXaGlsZSA9IHRha2VSaWdodFdoaWxlO1xuICAgIGxvZGFzaC50YWtlV2hpbGUgPSB0YWtlV2hpbGU7XG4gICAgbG9kYXNoLnRhcCA9IHRhcDtcbiAgICBsb2Rhc2gudGhyb3R0bGUgPSB0aHJvdHRsZTtcbiAgICBsb2Rhc2gudGhydSA9IHRocnU7XG4gICAgbG9kYXNoLnRpbWVzID0gdGltZXM7XG4gICAgbG9kYXNoLnRvQXJyYXkgPSB0b0FycmF5O1xuICAgIGxvZGFzaC50b1BsYWluT2JqZWN0ID0gdG9QbGFpbk9iamVjdDtcbiAgICBsb2Rhc2gudHJhbnNmb3JtID0gdHJhbnNmb3JtO1xuICAgIGxvZGFzaC51bmlvbiA9IHVuaW9uO1xuICAgIGxvZGFzaC51bmlxID0gdW5pcTtcbiAgICBsb2Rhc2gudW56aXAgPSB1bnppcDtcbiAgICBsb2Rhc2gudW56aXBXaXRoID0gdW56aXBXaXRoO1xuICAgIGxvZGFzaC52YWx1ZXMgPSB2YWx1ZXM7XG4gICAgbG9kYXNoLnZhbHVlc0luID0gdmFsdWVzSW47XG4gICAgbG9kYXNoLndoZXJlID0gd2hlcmU7XG4gICAgbG9kYXNoLndpdGhvdXQgPSB3aXRob3V0O1xuICAgIGxvZGFzaC53cmFwID0gd3JhcDtcbiAgICBsb2Rhc2gueG9yID0geG9yO1xuICAgIGxvZGFzaC56aXAgPSB6aXA7XG4gICAgbG9kYXNoLnppcE9iamVjdCA9IHppcE9iamVjdDtcbiAgICBsb2Rhc2guemlwV2l0aCA9IHppcFdpdGg7XG5cbiAgICAvLyBBZGQgYWxpYXNlcy5cbiAgICBsb2Rhc2guYmFja2Zsb3cgPSBmbG93UmlnaHQ7XG4gICAgbG9kYXNoLmNvbGxlY3QgPSBtYXA7XG4gICAgbG9kYXNoLmNvbXBvc2UgPSBmbG93UmlnaHQ7XG4gICAgbG9kYXNoLmVhY2ggPSBmb3JFYWNoO1xuICAgIGxvZGFzaC5lYWNoUmlnaHQgPSBmb3JFYWNoUmlnaHQ7XG4gICAgbG9kYXNoLmV4dGVuZCA9IGFzc2lnbjtcbiAgICBsb2Rhc2guaXRlcmF0ZWUgPSBjYWxsYmFjaztcbiAgICBsb2Rhc2gubWV0aG9kcyA9IGZ1bmN0aW9ucztcbiAgICBsb2Rhc2gub2JqZWN0ID0gemlwT2JqZWN0O1xuICAgIGxvZGFzaC5zZWxlY3QgPSBmaWx0ZXI7XG4gICAgbG9kYXNoLnRhaWwgPSByZXN0O1xuICAgIGxvZGFzaC51bmlxdWUgPSB1bmlxO1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgbWl4aW4obG9kYXNoLCBsb2Rhc2gpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0aGF0IHJldHVybiB1bndyYXBwZWQgdmFsdWVzIHdoZW4gY2hhaW5pbmcuXG4gICAgbG9kYXNoLmFkZCA9IGFkZDtcbiAgICBsb2Rhc2guYXR0ZW1wdCA9IGF0dGVtcHQ7XG4gICAgbG9kYXNoLmNhbWVsQ2FzZSA9IGNhbWVsQ2FzZTtcbiAgICBsb2Rhc2guY2FwaXRhbGl6ZSA9IGNhcGl0YWxpemU7XG4gICAgbG9kYXNoLmNlaWwgPSBjZWlsO1xuICAgIGxvZGFzaC5jbG9uZSA9IGNsb25lO1xuICAgIGxvZGFzaC5jbG9uZURlZXAgPSBjbG9uZURlZXA7XG4gICAgbG9kYXNoLmRlYnVyciA9IGRlYnVycjtcbiAgICBsb2Rhc2guZW5kc1dpdGggPSBlbmRzV2l0aDtcbiAgICBsb2Rhc2guZXNjYXBlID0gZXNjYXBlO1xuICAgIGxvZGFzaC5lc2NhcGVSZWdFeHAgPSBlc2NhcGVSZWdFeHA7XG4gICAgbG9kYXNoLmV2ZXJ5ID0gZXZlcnk7XG4gICAgbG9kYXNoLmZpbmQgPSBmaW5kO1xuICAgIGxvZGFzaC5maW5kSW5kZXggPSBmaW5kSW5kZXg7XG4gICAgbG9kYXNoLmZpbmRLZXkgPSBmaW5kS2V5O1xuICAgIGxvZGFzaC5maW5kTGFzdCA9IGZpbmRMYXN0O1xuICAgIGxvZGFzaC5maW5kTGFzdEluZGV4ID0gZmluZExhc3RJbmRleDtcbiAgICBsb2Rhc2guZmluZExhc3RLZXkgPSBmaW5kTGFzdEtleTtcbiAgICBsb2Rhc2guZmluZFdoZXJlID0gZmluZFdoZXJlO1xuICAgIGxvZGFzaC5maXJzdCA9IGZpcnN0O1xuICAgIGxvZGFzaC5mbG9vciA9IGZsb29yO1xuICAgIGxvZGFzaC5nZXQgPSBnZXQ7XG4gICAgbG9kYXNoLmd0ID0gZ3Q7XG4gICAgbG9kYXNoLmd0ZSA9IGd0ZTtcbiAgICBsb2Rhc2guaGFzID0gaGFzO1xuICAgIGxvZGFzaC5pZGVudGl0eSA9IGlkZW50aXR5O1xuICAgIGxvZGFzaC5pbmNsdWRlcyA9IGluY2x1ZGVzO1xuICAgIGxvZGFzaC5pbmRleE9mID0gaW5kZXhPZjtcbiAgICBsb2Rhc2guaW5SYW5nZSA9IGluUmFuZ2U7XG4gICAgbG9kYXNoLmlzQXJndW1lbnRzID0gaXNBcmd1bWVudHM7XG4gICAgbG9kYXNoLmlzQXJyYXkgPSBpc0FycmF5O1xuICAgIGxvZGFzaC5pc0Jvb2xlYW4gPSBpc0Jvb2xlYW47XG4gICAgbG9kYXNoLmlzRGF0ZSA9IGlzRGF0ZTtcbiAgICBsb2Rhc2guaXNFbGVtZW50ID0gaXNFbGVtZW50O1xuICAgIGxvZGFzaC5pc0VtcHR5ID0gaXNFbXB0eTtcbiAgICBsb2Rhc2guaXNFcXVhbCA9IGlzRXF1YWw7XG4gICAgbG9kYXNoLmlzRXJyb3IgPSBpc0Vycm9yO1xuICAgIGxvZGFzaC5pc0Zpbml0ZSA9IGlzRmluaXRlO1xuICAgIGxvZGFzaC5pc0Z1bmN0aW9uID0gaXNGdW5jdGlvbjtcbiAgICBsb2Rhc2guaXNNYXRjaCA9IGlzTWF0Y2g7XG4gICAgbG9kYXNoLmlzTmFOID0gaXNOYU47XG4gICAgbG9kYXNoLmlzTmF0aXZlID0gaXNOYXRpdmU7XG4gICAgbG9kYXNoLmlzTnVsbCA9IGlzTnVsbDtcbiAgICBsb2Rhc2guaXNOdW1iZXIgPSBpc051bWJlcjtcbiAgICBsb2Rhc2guaXNPYmplY3QgPSBpc09iamVjdDtcbiAgICBsb2Rhc2guaXNQbGFpbk9iamVjdCA9IGlzUGxhaW5PYmplY3Q7XG4gICAgbG9kYXNoLmlzUmVnRXhwID0gaXNSZWdFeHA7XG4gICAgbG9kYXNoLmlzU3RyaW5nID0gaXNTdHJpbmc7XG4gICAgbG9kYXNoLmlzVHlwZWRBcnJheSA9IGlzVHlwZWRBcnJheTtcbiAgICBsb2Rhc2guaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcbiAgICBsb2Rhc2gua2ViYWJDYXNlID0ga2ViYWJDYXNlO1xuICAgIGxvZGFzaC5sYXN0ID0gbGFzdDtcbiAgICBsb2Rhc2gubGFzdEluZGV4T2YgPSBsYXN0SW5kZXhPZjtcbiAgICBsb2Rhc2gubHQgPSBsdDtcbiAgICBsb2Rhc2gubHRlID0gbHRlO1xuICAgIGxvZGFzaC5tYXggPSBtYXg7XG4gICAgbG9kYXNoLm1pbiA9IG1pbjtcbiAgICBsb2Rhc2gubm9Db25mbGljdCA9IG5vQ29uZmxpY3Q7XG4gICAgbG9kYXNoLm5vb3AgPSBub29wO1xuICAgIGxvZGFzaC5ub3cgPSBub3c7XG4gICAgbG9kYXNoLnBhZCA9IHBhZDtcbiAgICBsb2Rhc2gucGFkTGVmdCA9IHBhZExlZnQ7XG4gICAgbG9kYXNoLnBhZFJpZ2h0ID0gcGFkUmlnaHQ7XG4gICAgbG9kYXNoLnBhcnNlSW50ID0gcGFyc2VJbnQ7XG4gICAgbG9kYXNoLnJhbmRvbSA9IHJhbmRvbTtcbiAgICBsb2Rhc2gucmVkdWNlID0gcmVkdWNlO1xuICAgIGxvZGFzaC5yZWR1Y2VSaWdodCA9IHJlZHVjZVJpZ2h0O1xuICAgIGxvZGFzaC5yZXBlYXQgPSByZXBlYXQ7XG4gICAgbG9kYXNoLnJlc3VsdCA9IHJlc3VsdDtcbiAgICBsb2Rhc2gucm91bmQgPSByb3VuZDtcbiAgICBsb2Rhc2gucnVuSW5Db250ZXh0ID0gcnVuSW5Db250ZXh0O1xuICAgIGxvZGFzaC5zaXplID0gc2l6ZTtcbiAgICBsb2Rhc2guc25ha2VDYXNlID0gc25ha2VDYXNlO1xuICAgIGxvZGFzaC5zb21lID0gc29tZTtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXggPSBzb3J0ZWRJbmRleDtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4ID0gc29ydGVkTGFzdEluZGV4O1xuICAgIGxvZGFzaC5zdGFydENhc2UgPSBzdGFydENhc2U7XG4gICAgbG9kYXNoLnN0YXJ0c1dpdGggPSBzdGFydHNXaXRoO1xuICAgIGxvZGFzaC5zdW0gPSBzdW07XG4gICAgbG9kYXNoLnRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgbG9kYXNoLnRyaW0gPSB0cmltO1xuICAgIGxvZGFzaC50cmltTGVmdCA9IHRyaW1MZWZ0O1xuICAgIGxvZGFzaC50cmltUmlnaHQgPSB0cmltUmlnaHQ7XG4gICAgbG9kYXNoLnRydW5jID0gdHJ1bmM7XG4gICAgbG9kYXNoLnVuZXNjYXBlID0gdW5lc2NhcGU7XG4gICAgbG9kYXNoLnVuaXF1ZUlkID0gdW5pcXVlSWQ7XG4gICAgbG9kYXNoLndvcmRzID0gd29yZHM7XG5cbiAgICAvLyBBZGQgYWxpYXNlcy5cbiAgICBsb2Rhc2guYWxsID0gZXZlcnk7XG4gICAgbG9kYXNoLmFueSA9IHNvbWU7XG4gICAgbG9kYXNoLmNvbnRhaW5zID0gaW5jbHVkZXM7XG4gICAgbG9kYXNoLmVxID0gaXNFcXVhbDtcbiAgICBsb2Rhc2guZGV0ZWN0ID0gZmluZDtcbiAgICBsb2Rhc2guZm9sZGwgPSByZWR1Y2U7XG4gICAgbG9kYXNoLmZvbGRyID0gcmVkdWNlUmlnaHQ7XG4gICAgbG9kYXNoLmhlYWQgPSBmaXJzdDtcbiAgICBsb2Rhc2guaW5jbHVkZSA9IGluY2x1ZGVzO1xuICAgIGxvZGFzaC5pbmplY3QgPSByZWR1Y2U7XG5cbiAgICBtaXhpbihsb2Rhc2gsIChmdW5jdGlvbigpIHtcbiAgICAgIHZhciBzb3VyY2UgPSB7fTtcbiAgICAgIGJhc2VGb3JPd24obG9kYXNoLCBmdW5jdGlvbihmdW5jLCBtZXRob2ROYW1lKSB7XG4gICAgICAgIGlmICghbG9kYXNoLnByb3RvdHlwZVttZXRob2ROYW1lXSkge1xuICAgICAgICAgIHNvdXJjZVttZXRob2ROYW1lXSA9IGZ1bmM7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9KCkpLCBmYWxzZSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBBZGQgZnVuY3Rpb25zIGNhcGFibGUgb2YgcmV0dXJuaW5nIHdyYXBwZWQgYW5kIHVud3JhcHBlZCB2YWx1ZXMgd2hlbiBjaGFpbmluZy5cbiAgICBsb2Rhc2guc2FtcGxlID0gc2FtcGxlO1xuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5zYW1wbGUgPSBmdW5jdGlvbihuKSB7XG4gICAgICBpZiAoIXRoaXMuX19jaGFpbl9fICYmIG4gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gc2FtcGxlKHRoaXMudmFsdWUoKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy50aHJ1KGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBzYW1wbGUodmFsdWUsIG4pO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEB0eXBlIHN0cmluZ1xuICAgICAqL1xuICAgIGxvZGFzaC5WRVJTSU9OID0gVkVSU0lPTjtcblxuICAgIC8vIEFzc2lnbiBkZWZhdWx0IHBsYWNlaG9sZGVycy5cbiAgICBhcnJheUVhY2goWydiaW5kJywgJ2JpbmRLZXknLCAnY3VycnknLCAnY3VycnlSaWdodCcsICdwYXJ0aWFsJywgJ3BhcnRpYWxSaWdodCddLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICBsb2Rhc2hbbWV0aG9kTmFtZV0ucGxhY2Vob2xkZXIgPSBsb2Rhc2g7XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5kcm9wYCBhbmQgYF8udGFrZWAgdmFyaWFudHMuXG4gICAgYXJyYXlFYWNoKFsnZHJvcCcsICd0YWtlJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihuKSB7XG4gICAgICAgIHZhciBmaWx0ZXJlZCA9IHRoaXMuX19maWx0ZXJlZF9fO1xuICAgICAgICBpZiAoZmlsdGVyZWQgJiYgIWluZGV4KSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBuID0gbiA9PSBudWxsID8gMSA6IG5hdGl2ZU1heChuYXRpdmVGbG9vcihuKSB8fCAwLCAwKTtcblxuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5jbG9uZSgpO1xuICAgICAgICBpZiAoZmlsdGVyZWQpIHtcbiAgICAgICAgICByZXN1bHQuX190YWtlQ291bnRfXyA9IG5hdGl2ZU1pbihyZXN1bHQuX190YWtlQ291bnRfXywgbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0Ll9fdmlld3NfXy5wdXNoKHsgJ3NpemUnOiBuLCAndHlwZSc6IG1ldGhvZE5hbWUgKyAocmVzdWx0Ll9fZGlyX18gPCAwID8gJ1JpZ2h0JyA6ICcnKSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcblxuICAgICAgTGF6eVdyYXBwZXIucHJvdG90eXBlW21ldGhvZE5hbWUgKyAnUmlnaHQnXSA9IGZ1bmN0aW9uKG4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpW21ldGhvZE5hbWVdKG4pLnJldmVyc2UoKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIHRoYXQgYWNjZXB0IGFuIGBpdGVyYXRlZWAgdmFsdWUuXG4gICAgYXJyYXlFYWNoKFsnZmlsdGVyJywgJ21hcCcsICd0YWtlV2hpbGUnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciB0eXBlID0gaW5kZXggKyAxLFxuICAgICAgICAgIGlzRmlsdGVyID0gdHlwZSAhPSBMQVpZX01BUF9GTEFHO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihpdGVyYXRlZSwgdGhpc0FyZykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5jbG9uZSgpO1xuICAgICAgICByZXN1bHQuX19pdGVyYXRlZXNfXy5wdXNoKHsgJ2l0ZXJhdGVlJzogZ2V0Q2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDEpLCAndHlwZSc6IHR5cGUgfSk7XG4gICAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSByZXN1bHQuX19maWx0ZXJlZF9fIHx8IGlzRmlsdGVyO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgZm9yIGBfLmZpcnN0YCBhbmQgYF8ubGFzdGAuXG4gICAgYXJyYXlFYWNoKFsnZmlyc3QnLCAnbGFzdCddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIHRha2VOYW1lID0gJ3Rha2UnICsgKGluZGV4ID8gJ1JpZ2h0JyA6ICcnKTtcblxuICAgICAgTGF6eVdyYXBwZXIucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzW3Rha2VOYW1lXSgxKS52YWx1ZSgpWzBdO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgZm9yIGBfLmluaXRpYWxgIGFuZCBgXy5yZXN0YC5cbiAgICBhcnJheUVhY2goWydpbml0aWFsJywgJ3Jlc3QnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciBkcm9wTmFtZSA9ICdkcm9wJyArIChpbmRleCA/ICcnIDogJ1JpZ2h0Jyk7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fX2ZpbHRlcmVkX18gPyBuZXcgTGF6eVdyYXBwZXIodGhpcykgOiB0aGlzW2Ryb3BOYW1lXSgxKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5wbHVja2AgYW5kIGBfLndoZXJlYC5cbiAgICBhcnJheUVhY2goWydwbHVjaycsICd3aGVyZSddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIG9wZXJhdGlvbk5hbWUgPSBpbmRleCA/ICdmaWx0ZXInIDogJ21hcCcsXG4gICAgICAgICAgY3JlYXRlQ2FsbGJhY2sgPSBpbmRleCA/IGJhc2VNYXRjaGVzIDogcHJvcGVydHk7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0aGlzW29wZXJhdGlvbk5hbWVdKGNyZWF0ZUNhbGxiYWNrKHZhbHVlKSk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNvbXBhY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpbHRlcihpZGVudGl0eSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5yZWplY3QgPSBmdW5jdGlvbihwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgIHByZWRpY2F0ZSA9IGdldENhbGxiYWNrKHByZWRpY2F0ZSwgdGhpc0FyZywgMSk7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuICFwcmVkaWNhdGUodmFsdWUpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICAgIHN0YXJ0ID0gc3RhcnQgPT0gbnVsbCA/IDAgOiAoK3N0YXJ0IHx8IDApO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gdGhpcztcbiAgICAgIGlmIChyZXN1bHQuX19maWx0ZXJlZF9fICYmIChzdGFydCA+IDAgfHwgZW5kIDwgMCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXp5V3JhcHBlcihyZXN1bHQpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudGFrZVJpZ2h0KC1zdGFydCk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXJ0KSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC5kcm9wKHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbmQgPSAoK2VuZCB8fCAwKTtcbiAgICAgICAgcmVzdWx0ID0gZW5kIDwgMCA/IHJlc3VsdC5kcm9wUmlnaHQoLWVuZCkgOiByZXN1bHQudGFrZShlbmQgLSBzdGFydCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUudGFrZVJpZ2h0V2hpbGUgPSBmdW5jdGlvbihwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICAgIHJldHVybiB0aGlzLnJldmVyc2UoKS50YWtlV2hpbGUocHJlZGljYXRlLCB0aGlzQXJnKS5yZXZlcnNlKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy50YWtlKFBPU0lUSVZFX0lORklOSVRZKTtcbiAgICB9O1xuXG4gICAgLy8gQWRkIGBMYXp5V3JhcHBlcmAgbWV0aG9kcyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgYmFzZUZvck93bihMYXp5V3JhcHBlci5wcm90b3R5cGUsIGZ1bmN0aW9uKGZ1bmMsIG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBjaGVja0l0ZXJhdGVlID0gL14oPzpmaWx0ZXJ8bWFwfHJlamVjdCl8V2hpbGUkLy50ZXN0KG1ldGhvZE5hbWUpLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86Zmlyc3R8bGFzdCkkLy50ZXN0KG1ldGhvZE5hbWUpLFxuICAgICAgICAgIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbcmV0VW53cmFwcGVkID8gKCd0YWtlJyArIChtZXRob2ROYW1lID09ICdsYXN0JyA/ICdSaWdodCcgOiAnJykpIDogbWV0aG9kTmFtZV07XG5cbiAgICAgIGlmICghbG9kYXNoRnVuYykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsb2Rhc2gucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gcmV0VW53cmFwcGVkID8gWzFdIDogYXJndW1lbnRzLFxuICAgICAgICAgICAgY2hhaW5BbGwgPSB0aGlzLl9fY2hhaW5fXyxcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICAgIGlzSHlicmlkID0gISF0aGlzLl9fYWN0aW9uc19fLmxlbmd0aCxcbiAgICAgICAgICAgIGlzTGF6eSA9IHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIsXG4gICAgICAgICAgICBpdGVyYXRlZSA9IGFyZ3NbMF0sXG4gICAgICAgICAgICB1c2VMYXp5ID0gaXNMYXp5IHx8IGlzQXJyYXkodmFsdWUpO1xuXG4gICAgICAgIGlmICh1c2VMYXp5ICYmIGNoZWNrSXRlcmF0ZWUgJiYgdHlwZW9mIGl0ZXJhdGVlID09ICdmdW5jdGlvbicgJiYgaXRlcmF0ZWUubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgICAvLyBBdm9pZCBsYXp5IHVzZSBpZiB0aGUgaXRlcmF0ZWUgaGFzIGEgXCJsZW5ndGhcIiB2YWx1ZSBvdGhlciB0aGFuIGAxYC5cbiAgICAgICAgICBpc0xhenkgPSB1c2VMYXp5ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGludGVyY2VwdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICByZXR1cm4gKHJldFVud3JhcHBlZCAmJiBjaGFpbkFsbClcbiAgICAgICAgICAgID8gbG9kYXNoRnVuYyh2YWx1ZSwgMSlbMF1cbiAgICAgICAgICAgIDogbG9kYXNoRnVuYy5hcHBseSh1bmRlZmluZWQsIGFycmF5UHVzaChbdmFsdWVdLCBhcmdzKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIGFjdGlvbiA9IHsgJ2Z1bmMnOiB0aHJ1LCAnYXJncyc6IFtpbnRlcmNlcHRvcl0sICd0aGlzQXJnJzogdW5kZWZpbmVkIH0sXG4gICAgICAgICAgICBvbmx5TGF6eSA9IGlzTGF6eSAmJiAhaXNIeWJyaWQ7XG5cbiAgICAgICAgaWYgKHJldFVud3JhcHBlZCAmJiAhY2hhaW5BbGwpIHtcbiAgICAgICAgICBpZiAob25seUxhenkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuY2xvbmUoKTtcbiAgICAgICAgICAgIHZhbHVlLl9fYWN0aW9uc19fLnB1c2goYWN0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiBmdW5jLmNhbGwodmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbG9kYXNoRnVuYy5jYWxsKHVuZGVmaW5lZCwgdGhpcy52YWx1ZSgpKVswXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJldFVud3JhcHBlZCAmJiB1c2VMYXp5KSB7XG4gICAgICAgICAgdmFsdWUgPSBvbmx5TGF6eSA/IHZhbHVlIDogbmV3IExhenlXcmFwcGVyKHRoaXMpO1xuICAgICAgICAgIHZhciByZXN1bHQgPSBmdW5jLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICAgICAgICByZXN1bHQuX19hY3Rpb25zX18ucHVzaChhY3Rpb24pO1xuICAgICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy50aHJ1KGludGVyY2VwdG9yKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYEFycmF5YCBhbmQgYFN0cmluZ2AgbWV0aG9kcyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgYXJyYXlFYWNoKFsnam9pbicsICdwb3AnLCAncHVzaCcsICdyZXBsYWNlJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3NwbGl0JywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSAoL14oPzpyZXBsYWNlfHNwbGl0KSQvLnRlc3QobWV0aG9kTmFtZSkgPyBzdHJpbmdQcm90byA6IGFycmF5UHJvdG8pW21ldGhvZE5hbWVdLFxuICAgICAgICAgIGNoYWluTmFtZSA9IC9eKD86cHVzaHxzb3J0fHVuc2hpZnQpJC8udGVzdChtZXRob2ROYW1lKSA/ICd0YXAnIDogJ3RocnUnLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86am9pbnxwb3B8cmVwbGFjZXxzaGlmdCkkLy50ZXN0KG1ldGhvZE5hbWUpO1xuXG4gICAgICBsb2Rhc2gucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBpZiAocmV0VW53cmFwcGVkICYmICF0aGlzLl9fY2hhaW5fXykge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMudmFsdWUoKSwgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXNbY2hhaW5OYW1lXShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gTWFwIG1pbmlmaWVkIGZ1bmN0aW9uIG5hbWVzIHRvIHRoZWlyIHJlYWwgbmFtZXMuXG4gICAgYmFzZUZvck93bihMYXp5V3JhcHBlci5wcm90b3R5cGUsIGZ1bmN0aW9uKGZ1bmMsIG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBsb2Rhc2hGdW5jID0gbG9kYXNoW21ldGhvZE5hbWVdO1xuICAgICAgaWYgKGxvZGFzaEZ1bmMpIHtcbiAgICAgICAgdmFyIGtleSA9IGxvZGFzaEZ1bmMubmFtZSxcbiAgICAgICAgICAgIG5hbWVzID0gcmVhbE5hbWVzW2tleV0gfHwgKHJlYWxOYW1lc1trZXldID0gW10pO1xuXG4gICAgICAgIG5hbWVzLnB1c2goeyAnbmFtZSc6IG1ldGhvZE5hbWUsICdmdW5jJzogbG9kYXNoRnVuYyB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlYWxOYW1lc1tjcmVhdGVIeWJyaWRXcmFwcGVyKHVuZGVmaW5lZCwgQklORF9LRVlfRkxBRykubmFtZV0gPSBbeyAnbmFtZSc6ICd3cmFwcGVyJywgJ2Z1bmMnOiB1bmRlZmluZWQgfV07XG5cbiAgICAvLyBBZGQgZnVuY3Rpb25zIHRvIHRoZSBsYXp5IHdyYXBwZXIuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNsb25lID0gbGF6eUNsb25lO1xuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5yZXZlcnNlID0gbGF6eVJldmVyc2U7XG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnZhbHVlID0gbGF6eVZhbHVlO1xuXG4gICAgLy8gQWRkIGNoYWluaW5nIGZ1bmN0aW9ucyB0byB0aGUgYGxvZGFzaGAgd3JhcHBlci5cbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29tbWl0ID0gd3JhcHBlckNvbW1pdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNvbmNhdCA9IHdyYXBwZXJDb25jYXQ7XG4gICAgbG9kYXNoLnByb3RvdHlwZS5wbGFudCA9IHdyYXBwZXJQbGFudDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnJldmVyc2UgPSB3cmFwcGVyUmV2ZXJzZTtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnRvU3RyaW5nID0gd3JhcHBlclRvU3RyaW5nO1xuICAgIGxvZGFzaC5wcm90b3R5cGUucnVuID0gbG9kYXNoLnByb3RvdHlwZS50b0pTT04gPSBsb2Rhc2gucHJvdG90eXBlLnZhbHVlT2YgPSBsb2Rhc2gucHJvdG90eXBlLnZhbHVlID0gd3JhcHBlclZhbHVlO1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9uIGFsaWFzZXMgdG8gdGhlIGBsb2Rhc2hgIHdyYXBwZXIuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5jb2xsZWN0ID0gbG9kYXNoLnByb3RvdHlwZS5tYXA7XG4gICAgbG9kYXNoLnByb3RvdHlwZS5oZWFkID0gbG9kYXNoLnByb3RvdHlwZS5maXJzdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnNlbGVjdCA9IGxvZGFzaC5wcm90b3R5cGUuZmlsdGVyO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudGFpbCA9IGxvZGFzaC5wcm90b3R5cGUucmVzdDtcblxuICAgIHJldHVybiBsb2Rhc2g7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvLyBFeHBvcnQgbG9kYXNoLlxuICB2YXIgXyA9IHJ1bkluQ29udGV4dCgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMgbGlrZSByLmpzIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgbG9kYXNoIHRvIHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gYW4gQU1EIGxvYWRlciBpcyBwcmVzZW50IHRvIGF2b2lkXG4gICAgLy8gZXJyb3JzIGluIGNhc2VzIHdoZXJlIGxvZGFzaCBpcyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGFuZCBub3QgaW50ZW5kZWRcbiAgICAvLyBhcyBhbiBBTUQgbW9kdWxlLiBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3JcbiAgICAvLyBtb3JlIGRldGFpbHMuXG4gICAgcm9vdC5fID0gXztcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvLCB0aHJvdWdoIHBhdGggbWFwcGluZywgaXQgY2FuIGJlXG4gICAgLy8gcmVmZXJlbmNlZCBhcyB0aGUgXCJ1bmRlcnNjb3JlXCIgbW9kdWxlLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIE5vZGUuanMgb3IgUmluZ29KUy5cbiAgICBpZiAobW9kdWxlRXhwb3J0cykge1xuICAgICAgKGZyZWVNb2R1bGUuZXhwb3J0cyA9IF8pLl8gPSBfO1xuICAgIH1cbiAgICAvLyBFeHBvcnQgZm9yIFJoaW5vIHdpdGggQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBlbHNlIHtcbiAgICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgZm9yIGEgYnJvd3NlciBvciBSaGluby5cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGliJylcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFzYXAgPSByZXF1aXJlKCdhc2FwL3JhdycpO1xuXG5mdW5jdGlvbiBub29wKCkge31cblxuLy8gU3RhdGVzOlxuLy9cbi8vIDAgLSBwZW5kaW5nXG4vLyAxIC0gZnVsZmlsbGVkIHdpdGggX3ZhbHVlXG4vLyAyIC0gcmVqZWN0ZWQgd2l0aCBfdmFsdWVcbi8vIDMgLSBhZG9wdGVkIHRoZSBzdGF0ZSBvZiBhbm90aGVyIHByb21pc2UsIF92YWx1ZVxuLy9cbi8vIG9uY2UgdGhlIHN0YXRlIGlzIG5vIGxvbmdlciBwZW5kaW5nICgwKSBpdCBpcyBpbW11dGFibGVcblxuLy8gQWxsIGBfYCBwcmVmaXhlZCBwcm9wZXJ0aWVzIHdpbGwgYmUgcmVkdWNlZCB0byBgX3tyYW5kb20gbnVtYmVyfWBcbi8vIGF0IGJ1aWxkIHRpbWUgdG8gb2JmdXNjYXRlIHRoZW0gYW5kIGRpc2NvdXJhZ2UgdGhlaXIgdXNlLlxuLy8gV2UgZG9uJ3QgdXNlIHN5bWJvbHMgb3IgT2JqZWN0LmRlZmluZVByb3BlcnR5IHRvIGZ1bGx5IGhpZGUgdGhlbVxuLy8gYmVjYXVzZSB0aGUgcGVyZm9ybWFuY2UgaXNuJ3QgZ29vZCBlbm91Z2guXG5cblxuLy8gdG8gYXZvaWQgdXNpbmcgdHJ5L2NhdGNoIGluc2lkZSBjcml0aWNhbCBmdW5jdGlvbnMsIHdlXG4vLyBleHRyYWN0IHRoZW0gdG8gaGVyZS5cbnZhciBMQVNUX0VSUk9SID0gbnVsbDtcbnZhciBJU19FUlJPUiA9IHt9O1xuZnVuY3Rpb24gZ2V0VGhlbihvYmopIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gb2JqLnRoZW47XG4gIH0gY2F0Y2ggKGV4KSB7XG4gICAgTEFTVF9FUlJPUiA9IGV4O1xuICAgIHJldHVybiBJU19FUlJPUjtcbiAgfVxufVxuXG5mdW5jdGlvbiB0cnlDYWxsT25lKGZuLCBhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGZuKGEpO1xuICB9IGNhdGNoIChleCkge1xuICAgIExBU1RfRVJST1IgPSBleDtcbiAgICByZXR1cm4gSVNfRVJST1I7XG4gIH1cbn1cbmZ1bmN0aW9uIHRyeUNhbGxUd28oZm4sIGEsIGIpIHtcbiAgdHJ5IHtcbiAgICBmbihhLCBiKTtcbiAgfSBjYXRjaCAoZXgpIHtcbiAgICBMQVNUX0VSUk9SID0gZXg7XG4gICAgcmV0dXJuIElTX0VSUk9SO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gUHJvbWlzZTtcblxuZnVuY3Rpb24gUHJvbWlzZShmbikge1xuICBpZiAodHlwZW9mIHRoaXMgIT09ICdvYmplY3QnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignUHJvbWlzZXMgbXVzdCBiZSBjb25zdHJ1Y3RlZCB2aWEgbmV3Jyk7XG4gIH1cbiAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Byb21pc2UgY29uc3RydWN0b3JcXCdzIGFyZ3VtZW50IGlzIG5vdCBhIGZ1bmN0aW9uJyk7XG4gIH1cbiAgdGhpcy5fNDAgPSAwO1xuICB0aGlzLl82NSA9IDA7XG4gIHRoaXMuXzU1ID0gbnVsbDtcbiAgdGhpcy5fNzIgPSBudWxsO1xuICBpZiAoZm4gPT09IG5vb3ApIHJldHVybjtcbiAgZG9SZXNvbHZlKGZuLCB0aGlzKTtcbn1cblByb21pc2UuXzM3ID0gbnVsbDtcblByb21pc2UuXzg3ID0gbnVsbDtcblByb21pc2UuXzYxID0gbm9vcDtcblxuUHJvbWlzZS5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gIGlmICh0aGlzLmNvbnN0cnVjdG9yICE9PSBQcm9taXNlKSB7XG4gICAgcmV0dXJuIHNhZmVUaGVuKHRoaXMsIG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKTtcbiAgfVxuICB2YXIgcmVzID0gbmV3IFByb21pc2Uobm9vcCk7XG4gIGhhbmRsZSh0aGlzLCBuZXcgSGFuZGxlcihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgcmVzKSk7XG4gIHJldHVybiByZXM7XG59O1xuXG5mdW5jdGlvbiBzYWZlVGhlbihzZWxmLCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuICByZXR1cm4gbmV3IHNlbGYuY29uc3RydWN0b3IoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciByZXMgPSBuZXcgUHJvbWlzZShub29wKTtcbiAgICByZXMudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgIGhhbmRsZShzZWxmLCBuZXcgSGFuZGxlcihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgcmVzKSk7XG4gIH0pO1xufVxuZnVuY3Rpb24gaGFuZGxlKHNlbGYsIGRlZmVycmVkKSB7XG4gIHdoaWxlIChzZWxmLl82NSA9PT0gMykge1xuICAgIHNlbGYgPSBzZWxmLl81NTtcbiAgfVxuICBpZiAoUHJvbWlzZS5fMzcpIHtcbiAgICBQcm9taXNlLl8zNyhzZWxmKTtcbiAgfVxuICBpZiAoc2VsZi5fNjUgPT09IDApIHtcbiAgICBpZiAoc2VsZi5fNDAgPT09IDApIHtcbiAgICAgIHNlbGYuXzQwID0gMTtcbiAgICAgIHNlbGYuXzcyID0gZGVmZXJyZWQ7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzZWxmLl80MCA9PT0gMSkge1xuICAgICAgc2VsZi5fNDAgPSAyO1xuICAgICAgc2VsZi5fNzIgPSBbc2VsZi5fNzIsIGRlZmVycmVkXTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc2VsZi5fNzIucHVzaChkZWZlcnJlZCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGhhbmRsZVJlc29sdmVkKHNlbGYsIGRlZmVycmVkKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzb2x2ZWQoc2VsZiwgZGVmZXJyZWQpIHtcbiAgYXNhcChmdW5jdGlvbigpIHtcbiAgICB2YXIgY2IgPSBzZWxmLl82NSA9PT0gMSA/IGRlZmVycmVkLm9uRnVsZmlsbGVkIDogZGVmZXJyZWQub25SZWplY3RlZDtcbiAgICBpZiAoY2IgPT09IG51bGwpIHtcbiAgICAgIGlmIChzZWxmLl82NSA9PT0gMSkge1xuICAgICAgICByZXNvbHZlKGRlZmVycmVkLnByb21pc2UsIHNlbGYuXzU1KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlamVjdChkZWZlcnJlZC5wcm9taXNlLCBzZWxmLl81NSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciByZXQgPSB0cnlDYWxsT25lKGNiLCBzZWxmLl81NSk7XG4gICAgaWYgKHJldCA9PT0gSVNfRVJST1IpIHtcbiAgICAgIHJlamVjdChkZWZlcnJlZC5wcm9taXNlLCBMQVNUX0VSUk9SKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzb2x2ZShkZWZlcnJlZC5wcm9taXNlLCByZXQpO1xuICAgIH1cbiAgfSk7XG59XG5mdW5jdGlvbiByZXNvbHZlKHNlbGYsIG5ld1ZhbHVlKSB7XG4gIC8vIFByb21pc2UgUmVzb2x1dGlvbiBQcm9jZWR1cmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9wcm9taXNlcy1hcGx1cy9wcm9taXNlcy1zcGVjI3RoZS1wcm9taXNlLXJlc29sdXRpb24tcHJvY2VkdXJlXG4gIGlmIChuZXdWYWx1ZSA9PT0gc2VsZikge1xuICAgIHJldHVybiByZWplY3QoXG4gICAgICBzZWxmLFxuICAgICAgbmV3IFR5cGVFcnJvcignQSBwcm9taXNlIGNhbm5vdCBiZSByZXNvbHZlZCB3aXRoIGl0c2VsZi4nKVxuICAgICk7XG4gIH1cbiAgaWYgKFxuICAgIG5ld1ZhbHVlICYmXG4gICAgKHR5cGVvZiBuZXdWYWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG5ld1ZhbHVlID09PSAnZnVuY3Rpb24nKVxuICApIHtcbiAgICB2YXIgdGhlbiA9IGdldFRoZW4obmV3VmFsdWUpO1xuICAgIGlmICh0aGVuID09PSBJU19FUlJPUikge1xuICAgICAgcmV0dXJuIHJlamVjdChzZWxmLCBMQVNUX0VSUk9SKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgdGhlbiA9PT0gc2VsZi50aGVuICYmXG4gICAgICBuZXdWYWx1ZSBpbnN0YW5jZW9mIFByb21pc2VcbiAgICApIHtcbiAgICAgIHNlbGYuXzY1ID0gMztcbiAgICAgIHNlbGYuXzU1ID0gbmV3VmFsdWU7XG4gICAgICBmaW5hbGUoc2VsZik7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZG9SZXNvbHZlKHRoZW4uYmluZChuZXdWYWx1ZSksIHNlbGYpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuICBzZWxmLl82NSA9IDE7XG4gIHNlbGYuXzU1ID0gbmV3VmFsdWU7XG4gIGZpbmFsZShzZWxmKTtcbn1cblxuZnVuY3Rpb24gcmVqZWN0KHNlbGYsIG5ld1ZhbHVlKSB7XG4gIHNlbGYuXzY1ID0gMjtcbiAgc2VsZi5fNTUgPSBuZXdWYWx1ZTtcbiAgaWYgKFByb21pc2UuXzg3KSB7XG4gICAgUHJvbWlzZS5fODcoc2VsZiwgbmV3VmFsdWUpO1xuICB9XG4gIGZpbmFsZShzZWxmKTtcbn1cbmZ1bmN0aW9uIGZpbmFsZShzZWxmKSB7XG4gIGlmIChzZWxmLl80MCA9PT0gMSkge1xuICAgIGhhbmRsZShzZWxmLCBzZWxmLl83Mik7XG4gICAgc2VsZi5fNzIgPSBudWxsO1xuICB9XG4gIGlmIChzZWxmLl80MCA9PT0gMikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5fNzIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZShzZWxmLCBzZWxmLl83MltpXSk7XG4gICAgfVxuICAgIHNlbGYuXzcyID0gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBIYW5kbGVyKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBwcm9taXNlKXtcbiAgdGhpcy5vbkZ1bGZpbGxlZCA9IHR5cGVvZiBvbkZ1bGZpbGxlZCA9PT0gJ2Z1bmN0aW9uJyA/IG9uRnVsZmlsbGVkIDogbnVsbDtcbiAgdGhpcy5vblJlamVjdGVkID0gdHlwZW9mIG9uUmVqZWN0ZWQgPT09ICdmdW5jdGlvbicgPyBvblJlamVjdGVkIDogbnVsbDtcbiAgdGhpcy5wcm9taXNlID0gcHJvbWlzZTtcbn1cblxuLyoqXG4gKiBUYWtlIGEgcG90ZW50aWFsbHkgbWlzYmVoYXZpbmcgcmVzb2x2ZXIgZnVuY3Rpb24gYW5kIG1ha2Ugc3VyZVxuICogb25GdWxmaWxsZWQgYW5kIG9uUmVqZWN0ZWQgYXJlIG9ubHkgY2FsbGVkIG9uY2UuXG4gKlxuICogTWFrZXMgbm8gZ3VhcmFudGVlcyBhYm91dCBhc3luY2hyb255LlxuICovXG5mdW5jdGlvbiBkb1Jlc29sdmUoZm4sIHByb21pc2UpIHtcbiAgdmFyIGRvbmUgPSBmYWxzZTtcbiAgdmFyIHJlcyA9IHRyeUNhbGxUd28oZm4sIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIGlmIChkb25lKSByZXR1cm47XG4gICAgZG9uZSA9IHRydWU7XG4gICAgcmVzb2x2ZShwcm9taXNlLCB2YWx1ZSk7XG4gIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICBpZiAoZG9uZSkgcmV0dXJuO1xuICAgIGRvbmUgPSB0cnVlO1xuICAgIHJlamVjdChwcm9taXNlLCByZWFzb24pO1xuICB9KTtcbiAgaWYgKCFkb25lICYmIHJlcyA9PT0gSVNfRVJST1IpIHtcbiAgICBkb25lID0gdHJ1ZTtcbiAgICByZWplY3QocHJvbWlzZSwgTEFTVF9FUlJPUik7XG4gIH1cbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFByb21pc2UgPSByZXF1aXJlKCcuL2NvcmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQcm9taXNlO1xuUHJvbWlzZS5wcm90b3R5cGUuZG9uZSA9IGZ1bmN0aW9uIChvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuICB2YXIgc2VsZiA9IGFyZ3VtZW50cy5sZW5ndGggPyB0aGlzLnRoZW4uYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IHRoaXM7XG4gIHNlbGYudGhlbihudWxsLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSwgMCk7XG4gIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLy9UaGlzIGZpbGUgY29udGFpbnMgdGhlIEVTNiBleHRlbnNpb25zIHRvIHRoZSBjb3JlIFByb21pc2VzL0ErIEFQSVxuXG52YXIgUHJvbWlzZSA9IHJlcXVpcmUoJy4vY29yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG5cbi8qIFN0YXRpYyBGdW5jdGlvbnMgKi9cblxudmFyIFRSVUUgPSB2YWx1ZVByb21pc2UodHJ1ZSk7XG52YXIgRkFMU0UgPSB2YWx1ZVByb21pc2UoZmFsc2UpO1xudmFyIE5VTEwgPSB2YWx1ZVByb21pc2UobnVsbCk7XG52YXIgVU5ERUZJTkVEID0gdmFsdWVQcm9taXNlKHVuZGVmaW5lZCk7XG52YXIgWkVSTyA9IHZhbHVlUHJvbWlzZSgwKTtcbnZhciBFTVBUWVNUUklORyA9IHZhbHVlUHJvbWlzZSgnJyk7XG5cbmZ1bmN0aW9uIHZhbHVlUHJvbWlzZSh2YWx1ZSkge1xuICB2YXIgcCA9IG5ldyBQcm9taXNlKFByb21pc2UuXzYxKTtcbiAgcC5fNjUgPSAxO1xuICBwLl81NSA9IHZhbHVlO1xuICByZXR1cm4gcDtcbn1cblByb21pc2UucmVzb2x2ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBQcm9taXNlKSByZXR1cm4gdmFsdWU7XG5cbiAgaWYgKHZhbHVlID09PSBudWxsKSByZXR1cm4gTlVMTDtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybiBVTkRFRklORUQ7XG4gIGlmICh2YWx1ZSA9PT0gdHJ1ZSkgcmV0dXJuIFRSVUU7XG4gIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHJldHVybiBGQUxTRTtcbiAgaWYgKHZhbHVlID09PSAwKSByZXR1cm4gWkVSTztcbiAgaWYgKHZhbHVlID09PSAnJykgcmV0dXJuIEVNUFRZU1RSSU5HO1xuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRyeSB7XG4gICAgICB2YXIgdGhlbiA9IHZhbHVlLnRoZW47XG4gICAgICBpZiAodHlwZW9mIHRoZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHRoZW4uYmluZCh2YWx1ZSkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICByZWplY3QoZXgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB2YWx1ZVByb21pc2UodmFsdWUpO1xufTtcblxuUHJvbWlzZS5hbGwgPSBmdW5jdGlvbiAoYXJyKSB7XG4gIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJyKTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHJlc29sdmUoW10pO1xuICAgIHZhciByZW1haW5pbmcgPSBhcmdzLmxlbmd0aDtcbiAgICBmdW5jdGlvbiByZXMoaSwgdmFsKSB7XG4gICAgICBpZiAodmFsICYmICh0eXBlb2YgdmFsID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgUHJvbWlzZSAmJiB2YWwudGhlbiA9PT0gUHJvbWlzZS5wcm90b3R5cGUudGhlbikge1xuICAgICAgICAgIHdoaWxlICh2YWwuXzY1ID09PSAzKSB7XG4gICAgICAgICAgICB2YWwgPSB2YWwuXzU1O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodmFsLl82NSA9PT0gMSkgcmV0dXJuIHJlcyhpLCB2YWwuXzU1KTtcbiAgICAgICAgICBpZiAodmFsLl82NSA9PT0gMikgcmVqZWN0KHZhbC5fNTUpO1xuICAgICAgICAgIHZhbC50aGVuKGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgICAgIHJlcyhpLCB2YWwpO1xuICAgICAgICAgIH0sIHJlamVjdCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB0aGVuID0gdmFsLnRoZW47XG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YXIgcCA9IG5ldyBQcm9taXNlKHRoZW4uYmluZCh2YWwpKTtcbiAgICAgICAgICAgIHAudGhlbihmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgICAgICAgIHJlcyhpLCB2YWwpO1xuICAgICAgICAgICAgfSwgcmVqZWN0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFyZ3NbaV0gPSB2YWw7XG4gICAgICBpZiAoLS1yZW1haW5pbmcgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZShhcmdzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXMoaSwgYXJnc1tpXSk7XG4gICAgfVxuICB9KTtcbn07XG5cblByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgcmVqZWN0KHZhbHVlKTtcbiAgfSk7XG59O1xuXG5Qcm9taXNlLnJhY2UgPSBmdW5jdGlvbiAodmFsdWVzKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFsdWVzLmZvckVhY2goZnVuY3Rpb24odmFsdWUpe1xuICAgICAgUHJvbWlzZS5yZXNvbHZlKHZhbHVlKS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgfSk7XG4gIH0pO1xufTtcblxuLyogUHJvdG90eXBlIE1ldGhvZHMgKi9cblxuUHJvbWlzZS5wcm90b3R5cGVbJ2NhdGNoJ10gPSBmdW5jdGlvbiAob25SZWplY3RlZCkge1xuICByZXR1cm4gdGhpcy50aGVuKG51bGwsIG9uUmVqZWN0ZWQpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFByb21pc2UgPSByZXF1aXJlKCcuL2NvcmUuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQcm9taXNlO1xuUHJvbWlzZS5wcm90b3R5cGVbJ2ZpbmFsbHknXSA9IGZ1bmN0aW9uIChmKSB7XG4gIHJldHVybiB0aGlzLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmKCkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0pO1xuICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmKCkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pO1xuICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9jb3JlLmpzJyk7XG5yZXF1aXJlKCcuL2RvbmUuanMnKTtcbnJlcXVpcmUoJy4vZmluYWxseS5qcycpO1xucmVxdWlyZSgnLi9lczYtZXh0ZW5zaW9ucy5qcycpO1xucmVxdWlyZSgnLi9ub2RlLWV4dGVuc2lvbnMuanMnKTtcbnJlcXVpcmUoJy4vc3luY2hyb25vdXMuanMnKTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gVGhpcyBmaWxlIGNvbnRhaW5zIHRoZW4vcHJvbWlzZSBzcGVjaWZpYyBleHRlbnNpb25zIHRoYXQgYXJlIG9ubHkgdXNlZnVsXG4vLyBmb3Igbm9kZS5qcyBpbnRlcm9wXG5cbnZhciBQcm9taXNlID0gcmVxdWlyZSgnLi9jb3JlLmpzJyk7XG52YXIgYXNhcCA9IHJlcXVpcmUoJ2FzYXAnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQcm9taXNlO1xuXG4vKiBTdGF0aWMgRnVuY3Rpb25zICovXG5cblByb21pc2UuZGVub2RlaWZ5ID0gZnVuY3Rpb24gKGZuLCBhcmd1bWVudENvdW50KSB7XG4gIGlmIChcbiAgICB0eXBlb2YgYXJndW1lbnRDb3VudCA9PT0gJ251bWJlcicgJiYgYXJndW1lbnRDb3VudCAhPT0gSW5maW5pdHlcbiAgKSB7XG4gICAgcmV0dXJuIGRlbm9kZWlmeVdpdGhDb3VudChmbiwgYXJndW1lbnRDb3VudCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGRlbm9kZWlmeVdpdGhvdXRDb3VudChmbik7XG4gIH1cbn07XG5cbnZhciBjYWxsYmFja0ZuID0gKFxuICAnZnVuY3Rpb24gKGVyciwgcmVzKSB7JyArXG4gICdpZiAoZXJyKSB7IHJqKGVycik7IH0gZWxzZSB7IHJzKHJlcyk7IH0nICtcbiAgJ30nXG4pO1xuZnVuY3Rpb24gZGVub2RlaWZ5V2l0aENvdW50KGZuLCBhcmd1bWVudENvdW50KSB7XG4gIHZhciBhcmdzID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRDb3VudDsgaSsrKSB7XG4gICAgYXJncy5wdXNoKCdhJyArIGkpO1xuICB9XG4gIHZhciBib2R5ID0gW1xuICAgICdyZXR1cm4gZnVuY3Rpb24gKCcgKyBhcmdzLmpvaW4oJywnKSArICcpIHsnLFxuICAgICd2YXIgc2VsZiA9IHRoaXM7JyxcbiAgICAncmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChycywgcmopIHsnLFxuICAgICd2YXIgcmVzID0gZm4uY2FsbCgnLFxuICAgIFsnc2VsZiddLmNvbmNhdChhcmdzKS5jb25jYXQoW2NhbGxiYWNrRm5dKS5qb2luKCcsJyksXG4gICAgJyk7JyxcbiAgICAnaWYgKHJlcyAmJicsXG4gICAgJyh0eXBlb2YgcmVzID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiByZXMgPT09IFwiZnVuY3Rpb25cIikgJiYnLFxuICAgICd0eXBlb2YgcmVzLnRoZW4gPT09IFwiZnVuY3Rpb25cIicsXG4gICAgJykge3JzKHJlcyk7fScsXG4gICAgJ30pOycsXG4gICAgJ307J1xuICBdLmpvaW4oJycpO1xuICByZXR1cm4gRnVuY3Rpb24oWydQcm9taXNlJywgJ2ZuJ10sIGJvZHkpKFByb21pc2UsIGZuKTtcbn1cbmZ1bmN0aW9uIGRlbm9kZWlmeVdpdGhvdXRDb3VudChmbikge1xuICB2YXIgZm5MZW5ndGggPSBNYXRoLm1heChmbi5sZW5ndGggLSAxLCAzKTtcbiAgdmFyIGFyZ3MgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBmbkxlbmd0aDsgaSsrKSB7XG4gICAgYXJncy5wdXNoKCdhJyArIGkpO1xuICB9XG4gIHZhciBib2R5ID0gW1xuICAgICdyZXR1cm4gZnVuY3Rpb24gKCcgKyBhcmdzLmpvaW4oJywnKSArICcpIHsnLFxuICAgICd2YXIgc2VsZiA9IHRoaXM7JyxcbiAgICAndmFyIGFyZ3M7JyxcbiAgICAndmFyIGFyZ0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7JyxcbiAgICAnaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAnICsgZm5MZW5ndGggKyAnKSB7JyxcbiAgICAnYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoICsgMSk7JyxcbiAgICAnZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsnLFxuICAgICdhcmdzW2ldID0gYXJndW1lbnRzW2ldOycsXG4gICAgJ30nLFxuICAgICd9JyxcbiAgICAncmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChycywgcmopIHsnLFxuICAgICd2YXIgY2IgPSAnICsgY2FsbGJhY2tGbiArICc7JyxcbiAgICAndmFyIHJlczsnLFxuICAgICdzd2l0Y2ggKGFyZ0xlbmd0aCkgeycsXG4gICAgYXJncy5jb25jYXQoWydleHRyYSddKS5tYXAoZnVuY3Rpb24gKF8sIGluZGV4KSB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICAnY2FzZSAnICsgKGluZGV4KSArICc6JyArXG4gICAgICAgICdyZXMgPSBmbi5jYWxsKCcgKyBbJ3NlbGYnXS5jb25jYXQoYXJncy5zbGljZSgwLCBpbmRleCkpLmNvbmNhdCgnY2InKS5qb2luKCcsJykgKyAnKTsnICtcbiAgICAgICAgJ2JyZWFrOydcbiAgICAgICk7XG4gICAgfSkuam9pbignJyksXG4gICAgJ2RlZmF1bHQ6JyxcbiAgICAnYXJnc1thcmdMZW5ndGhdID0gY2I7JyxcbiAgICAncmVzID0gZm4uYXBwbHkoc2VsZiwgYXJncyk7JyxcbiAgICAnfScsXG4gICAgXG4gICAgJ2lmIChyZXMgJiYnLFxuICAgICcodHlwZW9mIHJlcyA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgcmVzID09PSBcImZ1bmN0aW9uXCIpICYmJyxcbiAgICAndHlwZW9mIHJlcy50aGVuID09PSBcImZ1bmN0aW9uXCInLFxuICAgICcpIHtycyhyZXMpO30nLFxuICAgICd9KTsnLFxuICAgICd9OydcbiAgXS5qb2luKCcnKTtcblxuICByZXR1cm4gRnVuY3Rpb24oXG4gICAgWydQcm9taXNlJywgJ2ZuJ10sXG4gICAgYm9keVxuICApKFByb21pc2UsIGZuKTtcbn1cblxuUHJvbWlzZS5ub2RlaWZ5ID0gZnVuY3Rpb24gKGZuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgIHZhciBjYWxsYmFjayA9XG4gICAgICB0eXBlb2YgYXJnc1thcmdzLmxlbmd0aCAtIDFdID09PSAnZnVuY3Rpb24nID8gYXJncy5wb3AoKSA6IG51bGw7XG4gICAgdmFyIGN0eCA9IHRoaXM7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpLm5vZGVpZnkoY2FsbGJhY2ssIGN0eCk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIGlmIChjYWxsYmFjayA9PT0gbnVsbCB8fCB0eXBlb2YgY2FsbGJhY2sgPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICByZWplY3QoZXgpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFzYXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNhbGxiYWNrLmNhbGwoY3R4LCBleCk7XG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS5ub2RlaWZ5ID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdHgpIHtcbiAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPSAnZnVuY3Rpb24nKSByZXR1cm4gdGhpcztcblxuICB0aGlzLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgYXNhcChmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsYmFjay5jYWxsKGN0eCwgbnVsbCwgdmFsdWUpO1xuICAgIH0pO1xuICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgYXNhcChmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsYmFjay5jYWxsKGN0eCwgZXJyKTtcbiAgICB9KTtcbiAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUHJvbWlzZSA9IHJlcXVpcmUoJy4vY29yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG5Qcm9taXNlLmVuYWJsZVN5bmNocm9ub3VzID0gZnVuY3Rpb24gKCkge1xuICBQcm9taXNlLnByb3RvdHlwZS5pc1BlbmRpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTdGF0ZSgpID09IDA7XG4gIH07XG5cbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNGdWxmaWxsZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTdGF0ZSgpID09IDE7XG4gIH07XG5cbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNSZWplY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmdldFN0YXRlKCkgPT0gMjtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fNjUgPT09IDMpIHtcbiAgICAgIHJldHVybiB0aGlzLl81NS5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0Z1bGZpbGxlZCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBnZXQgYSB2YWx1ZSBvZiBhbiB1bmZ1bGZpbGxlZCBwcm9taXNlLicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl81NTtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS5nZXRSZWFzb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuXzY1ID09PSAzKSB7XG4gICAgICByZXR1cm4gdGhpcy5fNTUuZ2V0UmVhc29uKCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzUmVqZWN0ZWQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IGEgcmVqZWN0aW9uIHJlYXNvbiBvZiBhIG5vbi1yZWplY3RlZCBwcm9taXNlLicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl81NTtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fNjUgPT09IDMpIHtcbiAgICAgIHJldHVybiB0aGlzLl81NS5nZXRTdGF0ZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fNjUgPT09IC0xIHx8IHRoaXMuXzY1ID09PSAtMikge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuXzY1O1xuICB9O1xufTtcblxuUHJvbWlzZS5kaXNhYmxlU3luY2hyb25vdXMgPSBmdW5jdGlvbigpIHtcbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNQZW5kaW5nID0gdW5kZWZpbmVkO1xuICBQcm9taXNlLnByb3RvdHlwZS5pc0Z1bGZpbGxlZCA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNSZWplY3RlZCA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuZ2V0VmFsdWUgPSB1bmRlZmluZWQ7XG4gIFByb21pc2UucHJvdG90eXBlLmdldFJlYXNvbiA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuZ2V0U3RhdGUgPSB1bmRlZmluZWQ7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8vIHJhd0FzYXAgcHJvdmlkZXMgZXZlcnl0aGluZyB3ZSBuZWVkIGV4Y2VwdCBleGNlcHRpb24gbWFuYWdlbWVudC5cbnZhciByYXdBc2FwID0gcmVxdWlyZShcIi4vcmF3XCIpO1xuLy8gUmF3VGFza3MgYXJlIHJlY3ljbGVkIHRvIHJlZHVjZSBHQyBjaHVybi5cbnZhciBmcmVlVGFza3MgPSBbXTtcbi8vIFdlIHF1ZXVlIGVycm9ycyB0byBlbnN1cmUgdGhleSBhcmUgdGhyb3duIGluIHJpZ2h0IG9yZGVyIChGSUZPKS5cbi8vIEFycmF5LWFzLXF1ZXVlIGlzIGdvb2QgZW5vdWdoIGhlcmUsIHNpbmNlIHdlIGFyZSBqdXN0IGRlYWxpbmcgd2l0aCBleGNlcHRpb25zLlxudmFyIHBlbmRpbmdFcnJvcnMgPSBbXTtcbnZhciByZXF1ZXN0RXJyb3JUaHJvdyA9IHJhd0FzYXAubWFrZVJlcXVlc3RDYWxsRnJvbVRpbWVyKHRocm93Rmlyc3RFcnJvcik7XG5cbmZ1bmN0aW9uIHRocm93Rmlyc3RFcnJvcigpIHtcbiAgICBpZiAocGVuZGluZ0Vycm9ycy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgcGVuZGluZ0Vycm9ycy5zaGlmdCgpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxscyBhIHRhc2sgYXMgc29vbiBhcyBwb3NzaWJsZSBhZnRlciByZXR1cm5pbmcsIGluIGl0cyBvd24gZXZlbnQsIHdpdGggcHJpb3JpdHlcbiAqIG92ZXIgb3RoZXIgZXZlbnRzIGxpa2UgYW5pbWF0aW9uLCByZWZsb3csIGFuZCByZXBhaW50LiBBbiBlcnJvciB0aHJvd24gZnJvbSBhblxuICogZXZlbnQgd2lsbCBub3QgaW50ZXJydXB0LCBub3IgZXZlbiBzdWJzdGFudGlhbGx5IHNsb3cgZG93biB0aGUgcHJvY2Vzc2luZyBvZlxuICogb3RoZXIgZXZlbnRzLCBidXQgd2lsbCBiZSByYXRoZXIgcG9zdHBvbmVkIHRvIGEgbG93ZXIgcHJpb3JpdHkgZXZlbnQuXG4gKiBAcGFyYW0ge3tjYWxsfX0gdGFzayBBIGNhbGxhYmxlIG9iamVjdCwgdHlwaWNhbGx5IGEgZnVuY3Rpb24gdGhhdCB0YWtlcyBub1xuICogYXJndW1lbnRzLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGFzYXA7XG5mdW5jdGlvbiBhc2FwKHRhc2spIHtcbiAgICB2YXIgcmF3VGFzaztcbiAgICBpZiAoZnJlZVRhc2tzLmxlbmd0aCkge1xuICAgICAgICByYXdUYXNrID0gZnJlZVRhc2tzLnBvcCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJhd1Rhc2sgPSBuZXcgUmF3VGFzaygpO1xuICAgIH1cbiAgICByYXdUYXNrLnRhc2sgPSB0YXNrO1xuICAgIHJhd0FzYXAocmF3VGFzayk7XG59XG5cbi8vIFdlIHdyYXAgdGFza3Mgd2l0aCByZWN5Y2xhYmxlIHRhc2sgb2JqZWN0cy4gIEEgdGFzayBvYmplY3QgaW1wbGVtZW50c1xuLy8gYGNhbGxgLCBqdXN0IGxpa2UgYSBmdW5jdGlvbi5cbmZ1bmN0aW9uIFJhd1Rhc2soKSB7XG4gICAgdGhpcy50YXNrID0gbnVsbDtcbn1cblxuLy8gVGhlIHNvbGUgcHVycG9zZSBvZiB3cmFwcGluZyB0aGUgdGFzayBpcyB0byBjYXRjaCB0aGUgZXhjZXB0aW9uIGFuZCByZWN5Y2xlXG4vLyB0aGUgdGFzayBvYmplY3QgYWZ0ZXIgaXRzIHNpbmdsZSB1c2UuXG5SYXdUYXNrLnByb3RvdHlwZS5jYWxsID0gZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIHRoaXMudGFzay5jYWxsKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGFzYXAub25lcnJvcikge1xuICAgICAgICAgICAgLy8gVGhpcyBob29rIGV4aXN0cyBwdXJlbHkgZm9yIHRlc3RpbmcgcHVycG9zZXMuXG4gICAgICAgICAgICAvLyBJdHMgbmFtZSB3aWxsIGJlIHBlcmlvZGljYWxseSByYW5kb21pemVkIHRvIGJyZWFrIGFueSBjb2RlIHRoYXRcbiAgICAgICAgICAgIC8vIGRlcGVuZHMgb24gaXRzIGV4aXN0ZW5jZS5cbiAgICAgICAgICAgIGFzYXAub25lcnJvcihlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJbiBhIHdlYiBicm93c2VyLCBleGNlcHRpb25zIGFyZSBub3QgZmF0YWwuIEhvd2V2ZXIsIHRvIGF2b2lkXG4gICAgICAgICAgICAvLyBzbG93aW5nIGRvd24gdGhlIHF1ZXVlIG9mIHBlbmRpbmcgdGFza3MsIHdlIHJldGhyb3cgdGhlIGVycm9yIGluIGFcbiAgICAgICAgICAgIC8vIGxvd2VyIHByaW9yaXR5IHR1cm4uXG4gICAgICAgICAgICBwZW5kaW5nRXJyb3JzLnB1c2goZXJyb3IpO1xuICAgICAgICAgICAgcmVxdWVzdEVycm9yVGhyb3coKTtcbiAgICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMudGFzayA9IG51bGw7XG4gICAgICAgIGZyZWVUYXNrc1tmcmVlVGFza3MubGVuZ3RoXSA9IHRoaXM7XG4gICAgfVxufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vLyBVc2UgdGhlIGZhc3Rlc3QgbWVhbnMgcG9zc2libGUgdG8gZXhlY3V0ZSBhIHRhc2sgaW4gaXRzIG93biB0dXJuLCB3aXRoXG4vLyBwcmlvcml0eSBvdmVyIG90aGVyIGV2ZW50cyBpbmNsdWRpbmcgSU8sIGFuaW1hdGlvbiwgcmVmbG93LCBhbmQgcmVkcmF3XG4vLyBldmVudHMgaW4gYnJvd3NlcnMuXG4vL1xuLy8gQW4gZXhjZXB0aW9uIHRocm93biBieSBhIHRhc2sgd2lsbCBwZXJtYW5lbnRseSBpbnRlcnJ1cHQgdGhlIHByb2Nlc3Npbmcgb2Zcbi8vIHN1YnNlcXVlbnQgdGFza3MuIFRoZSBoaWdoZXIgbGV2ZWwgYGFzYXBgIGZ1bmN0aW9uIGVuc3VyZXMgdGhhdCBpZiBhblxuLy8gZXhjZXB0aW9uIGlzIHRocm93biBieSBhIHRhc2ssIHRoYXQgdGhlIHRhc2sgcXVldWUgd2lsbCBjb250aW51ZSBmbHVzaGluZyBhc1xuLy8gc29vbiBhcyBwb3NzaWJsZSwgYnV0IGlmIHlvdSB1c2UgYHJhd0FzYXBgIGRpcmVjdGx5LCB5b3UgYXJlIHJlc3BvbnNpYmxlIHRvXG4vLyBlaXRoZXIgZW5zdXJlIHRoYXQgbm8gZXhjZXB0aW9ucyBhcmUgdGhyb3duIGZyb20geW91ciB0YXNrLCBvciB0byBtYW51YWxseVxuLy8gY2FsbCBgcmF3QXNhcC5yZXF1ZXN0Rmx1c2hgIGlmIGFuIGV4Y2VwdGlvbiBpcyB0aHJvd24uXG5tb2R1bGUuZXhwb3J0cyA9IHJhd0FzYXA7XG5mdW5jdGlvbiByYXdBc2FwKHRhc2spIHtcbiAgICBpZiAoIXF1ZXVlLmxlbmd0aCkge1xuICAgICAgICByZXF1ZXN0Rmx1c2goKTtcbiAgICAgICAgZmx1c2hpbmcgPSB0cnVlO1xuICAgIH1cbiAgICAvLyBFcXVpdmFsZW50IHRvIHB1c2gsIGJ1dCBhdm9pZHMgYSBmdW5jdGlvbiBjYWxsLlxuICAgIHF1ZXVlW3F1ZXVlLmxlbmd0aF0gPSB0YXNrO1xufVxuXG52YXIgcXVldWUgPSBbXTtcbi8vIE9uY2UgYSBmbHVzaCBoYXMgYmVlbiByZXF1ZXN0ZWQsIG5vIGZ1cnRoZXIgY2FsbHMgdG8gYHJlcXVlc3RGbHVzaGAgYXJlXG4vLyBuZWNlc3NhcnkgdW50aWwgdGhlIG5leHQgYGZsdXNoYCBjb21wbGV0ZXMuXG52YXIgZmx1c2hpbmcgPSBmYWxzZTtcbi8vIGByZXF1ZXN0Rmx1c2hgIGlzIGFuIGltcGxlbWVudGF0aW9uLXNwZWNpZmljIG1ldGhvZCB0aGF0IGF0dGVtcHRzIHRvIGtpY2tcbi8vIG9mZiBhIGBmbHVzaGAgZXZlbnQgYXMgcXVpY2tseSBhcyBwb3NzaWJsZS4gYGZsdXNoYCB3aWxsIGF0dGVtcHQgdG8gZXhoYXVzdFxuLy8gdGhlIGV2ZW50IHF1ZXVlIGJlZm9yZSB5aWVsZGluZyB0byB0aGUgYnJvd3NlcidzIG93biBldmVudCBsb29wLlxudmFyIHJlcXVlc3RGbHVzaDtcbi8vIFRoZSBwb3NpdGlvbiBvZiB0aGUgbmV4dCB0YXNrIHRvIGV4ZWN1dGUgaW4gdGhlIHRhc2sgcXVldWUuIFRoaXMgaXNcbi8vIHByZXNlcnZlZCBiZXR3ZWVuIGNhbGxzIHRvIGBmbHVzaGAgc28gdGhhdCBpdCBjYW4gYmUgcmVzdW1lZCBpZlxuLy8gYSB0YXNrIHRocm93cyBhbiBleGNlcHRpb24uXG52YXIgaW5kZXggPSAwO1xuLy8gSWYgYSB0YXNrIHNjaGVkdWxlcyBhZGRpdGlvbmFsIHRhc2tzIHJlY3Vyc2l2ZWx5LCB0aGUgdGFzayBxdWV1ZSBjYW4gZ3Jvd1xuLy8gdW5ib3VuZGVkLiBUbyBwcmV2ZW50IG1lbW9yeSBleGhhdXN0aW9uLCB0aGUgdGFzayBxdWV1ZSB3aWxsIHBlcmlvZGljYWxseVxuLy8gdHJ1bmNhdGUgYWxyZWFkeS1jb21wbGV0ZWQgdGFza3MuXG52YXIgY2FwYWNpdHkgPSAxMDI0O1xuXG4vLyBUaGUgZmx1c2ggZnVuY3Rpb24gcHJvY2Vzc2VzIGFsbCB0YXNrcyB0aGF0IGhhdmUgYmVlbiBzY2hlZHVsZWQgd2l0aFxuLy8gYHJhd0FzYXBgIHVubGVzcyBhbmQgdW50aWwgb25lIG9mIHRob3NlIHRhc2tzIHRocm93cyBhbiBleGNlcHRpb24uXG4vLyBJZiBhIHRhc2sgdGhyb3dzIGFuIGV4Y2VwdGlvbiwgYGZsdXNoYCBlbnN1cmVzIHRoYXQgaXRzIHN0YXRlIHdpbGwgcmVtYWluXG4vLyBjb25zaXN0ZW50IGFuZCB3aWxsIHJlc3VtZSB3aGVyZSBpdCBsZWZ0IG9mZiB3aGVuIGNhbGxlZCBhZ2Fpbi5cbi8vIEhvd2V2ZXIsIGBmbHVzaGAgZG9lcyBub3QgbWFrZSBhbnkgYXJyYW5nZW1lbnRzIHRvIGJlIGNhbGxlZCBhZ2FpbiBpZiBhblxuLy8gZXhjZXB0aW9uIGlzIHRocm93bi5cbmZ1bmN0aW9uIGZsdXNoKCkge1xuICAgIHdoaWxlIChpbmRleCA8IHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgY3VycmVudEluZGV4ID0gaW5kZXg7XG4gICAgICAgIC8vIEFkdmFuY2UgdGhlIGluZGV4IGJlZm9yZSBjYWxsaW5nIHRoZSB0YXNrLiBUaGlzIGVuc3VyZXMgdGhhdCB3ZSB3aWxsXG4gICAgICAgIC8vIGJlZ2luIGZsdXNoaW5nIG9uIHRoZSBuZXh0IHRhc2sgdGhlIHRhc2sgdGhyb3dzIGFuIGVycm9yLlxuICAgICAgICBpbmRleCA9IGluZGV4ICsgMTtcbiAgICAgICAgcXVldWVbY3VycmVudEluZGV4XS5jYWxsKCk7XG4gICAgICAgIC8vIFByZXZlbnQgbGVha2luZyBtZW1vcnkgZm9yIGxvbmcgY2hhaW5zIG9mIHJlY3Vyc2l2ZSBjYWxscyB0byBgYXNhcGAuXG4gICAgICAgIC8vIElmIHdlIGNhbGwgYGFzYXBgIHdpdGhpbiB0YXNrcyBzY2hlZHVsZWQgYnkgYGFzYXBgLCB0aGUgcXVldWUgd2lsbFxuICAgICAgICAvLyBncm93LCBidXQgdG8gYXZvaWQgYW4gTyhuKSB3YWxrIGZvciBldmVyeSB0YXNrIHdlIGV4ZWN1dGUsIHdlIGRvbid0XG4gICAgICAgIC8vIHNoaWZ0IHRhc2tzIG9mZiB0aGUgcXVldWUgYWZ0ZXIgdGhleSBoYXZlIGJlZW4gZXhlY3V0ZWQuXG4gICAgICAgIC8vIEluc3RlYWQsIHdlIHBlcmlvZGljYWxseSBzaGlmdCAxMDI0IHRhc2tzIG9mZiB0aGUgcXVldWUuXG4gICAgICAgIGlmIChpbmRleCA+IGNhcGFjaXR5KSB7XG4gICAgICAgICAgICAvLyBNYW51YWxseSBzaGlmdCBhbGwgdmFsdWVzIHN0YXJ0aW5nIGF0IHRoZSBpbmRleCBiYWNrIHRvIHRoZVxuICAgICAgICAgICAgLy8gYmVnaW5uaW5nIG9mIHRoZSBxdWV1ZS5cbiAgICAgICAgICAgIGZvciAodmFyIHNjYW4gPSAwLCBuZXdMZW5ndGggPSBxdWV1ZS5sZW5ndGggLSBpbmRleDsgc2NhbiA8IG5ld0xlbmd0aDsgc2NhbisrKSB7XG4gICAgICAgICAgICAgICAgcXVldWVbc2Nhbl0gPSBxdWV1ZVtzY2FuICsgaW5kZXhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcXVldWUubGVuZ3RoIC09IGluZGV4O1xuICAgICAgICAgICAgaW5kZXggPSAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLmxlbmd0aCA9IDA7XG4gICAgaW5kZXggPSAwO1xuICAgIGZsdXNoaW5nID0gZmFsc2U7XG59XG5cbi8vIGByZXF1ZXN0Rmx1c2hgIGlzIGltcGxlbWVudGVkIHVzaW5nIGEgc3RyYXRlZ3kgYmFzZWQgb24gZGF0YSBjb2xsZWN0ZWQgZnJvbVxuLy8gZXZlcnkgYXZhaWxhYmxlIFNhdWNlTGFicyBTZWxlbml1bSB3ZWIgZHJpdmVyIHdvcmtlciBhdCB0aW1lIG9mIHdyaXRpbmcuXG4vLyBodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xbUctNVVZR3VwNXF4R2RFTVdraFA2QldDejA1M05VYjJFMVFvVVRVMTZ1QS9lZGl0I2dpZD03ODM3MjQ1OTNcblxuLy8gU2FmYXJpIDYgYW5kIDYuMSBmb3IgZGVza3RvcCwgaVBhZCwgYW5kIGlQaG9uZSBhcmUgdGhlIG9ubHkgYnJvd3NlcnMgdGhhdFxuLy8gaGF2ZSBXZWJLaXRNdXRhdGlvbk9ic2VydmVyIGJ1dCBub3QgdW4tcHJlZml4ZWQgTXV0YXRpb25PYnNlcnZlci5cbi8vIE11c3QgdXNlIGBnbG9iYWxgIG9yIGBzZWxmYCBpbnN0ZWFkIG9mIGB3aW5kb3dgIHRvIHdvcmsgaW4gYm90aCBmcmFtZXMgYW5kIHdlYlxuLy8gd29ya2Vycy4gYGdsb2JhbGAgaXMgYSBwcm92aXNpb24gb2YgQnJvd3NlcmlmeSwgTXIsIE1ycywgb3IgTW9wLlxuXG4vKiBnbG9iYWxzIHNlbGYgKi9cbnZhciBzY29wZSA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiBzZWxmO1xudmFyIEJyb3dzZXJNdXRhdGlvbk9ic2VydmVyID0gc2NvcGUuTXV0YXRpb25PYnNlcnZlciB8fCBzY29wZS5XZWJLaXRNdXRhdGlvbk9ic2VydmVyO1xuXG4vLyBNdXRhdGlvbk9ic2VydmVycyBhcmUgZGVzaXJhYmxlIGJlY2F1c2UgdGhleSBoYXZlIGhpZ2ggcHJpb3JpdHkgYW5kIHdvcmtcbi8vIHJlbGlhYmx5IGV2ZXJ5d2hlcmUgdGhleSBhcmUgaW1wbGVtZW50ZWQuXG4vLyBUaGV5IGFyZSBpbXBsZW1lbnRlZCBpbiBhbGwgbW9kZXJuIGJyb3dzZXJzLlxuLy9cbi8vIC0gQW5kcm9pZCA0LTQuM1xuLy8gLSBDaHJvbWUgMjYtMzRcbi8vIC0gRmlyZWZveCAxNC0yOVxuLy8gLSBJbnRlcm5ldCBFeHBsb3JlciAxMVxuLy8gLSBpUGFkIFNhZmFyaSA2LTcuMVxuLy8gLSBpUGhvbmUgU2FmYXJpIDctNy4xXG4vLyAtIFNhZmFyaSA2LTdcbmlmICh0eXBlb2YgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJlcXVlc3RGbHVzaCA9IG1ha2VSZXF1ZXN0Q2FsbEZyb21NdXRhdGlvbk9ic2VydmVyKGZsdXNoKTtcblxuLy8gTWVzc2FnZUNoYW5uZWxzIGFyZSBkZXNpcmFibGUgYmVjYXVzZSB0aGV5IGdpdmUgZGlyZWN0IGFjY2VzcyB0byB0aGUgSFRNTFxuLy8gdGFzayBxdWV1ZSwgYXJlIGltcGxlbWVudGVkIGluIEludGVybmV0IEV4cGxvcmVyIDEwLCBTYWZhcmkgNS4wLTEsIGFuZCBPcGVyYVxuLy8gMTEtMTIsIGFuZCBpbiB3ZWIgd29ya2VycyBpbiBtYW55IGVuZ2luZXMuXG4vLyBBbHRob3VnaCBtZXNzYWdlIGNoYW5uZWxzIHlpZWxkIHRvIGFueSBxdWV1ZWQgcmVuZGVyaW5nIGFuZCBJTyB0YXNrcywgdGhleVxuLy8gd291bGQgYmUgYmV0dGVyIHRoYW4gaW1wb3NpbmcgdGhlIDRtcyBkZWxheSBvZiB0aW1lcnMuXG4vLyBIb3dldmVyLCB0aGV5IGRvIG5vdCB3b3JrIHJlbGlhYmx5IGluIEludGVybmV0IEV4cGxvcmVyIG9yIFNhZmFyaS5cblxuLy8gSW50ZXJuZXQgRXhwbG9yZXIgMTAgaXMgdGhlIG9ubHkgYnJvd3NlciB0aGF0IGhhcyBzZXRJbW1lZGlhdGUgYnV0IGRvZXNcbi8vIG5vdCBoYXZlIE11dGF0aW9uT2JzZXJ2ZXJzLlxuLy8gQWx0aG91Z2ggc2V0SW1tZWRpYXRlIHlpZWxkcyB0byB0aGUgYnJvd3NlcidzIHJlbmRlcmVyLCBpdCB3b3VsZCBiZVxuLy8gcHJlZmVycmFibGUgdG8gZmFsbGluZyBiYWNrIHRvIHNldFRpbWVvdXQgc2luY2UgaXQgZG9lcyBub3QgaGF2ZVxuLy8gdGhlIG1pbmltdW0gNG1zIHBlbmFsdHkuXG4vLyBVbmZvcnR1bmF0ZWx5IHRoZXJlIGFwcGVhcnMgdG8gYmUgYSBidWcgaW4gSW50ZXJuZXQgRXhwbG9yZXIgMTAgTW9iaWxlIChhbmRcbi8vIERlc2t0b3AgdG8gYSBsZXNzZXIgZXh0ZW50KSB0aGF0IHJlbmRlcnMgYm90aCBzZXRJbW1lZGlhdGUgYW5kXG4vLyBNZXNzYWdlQ2hhbm5lbCB1c2VsZXNzIGZvciB0aGUgcHVycG9zZXMgb2YgQVNBUC5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9rcmlza293YWwvcS9pc3N1ZXMvMzk2XG5cbi8vIFRpbWVycyBhcmUgaW1wbGVtZW50ZWQgdW5pdmVyc2FsbHkuXG4vLyBXZSBmYWxsIGJhY2sgdG8gdGltZXJzIGluIHdvcmtlcnMgaW4gbW9zdCBlbmdpbmVzLCBhbmQgaW4gZm9yZWdyb3VuZFxuLy8gY29udGV4dHMgaW4gdGhlIGZvbGxvd2luZyBicm93c2Vycy5cbi8vIEhvd2V2ZXIsIG5vdGUgdGhhdCBldmVuIHRoaXMgc2ltcGxlIGNhc2UgcmVxdWlyZXMgbnVhbmNlcyB0byBvcGVyYXRlIGluIGFcbi8vIGJyb2FkIHNwZWN0cnVtIG9mIGJyb3dzZXJzLlxuLy9cbi8vIC0gRmlyZWZveCAzLTEzXG4vLyAtIEludGVybmV0IEV4cGxvcmVyIDYtOVxuLy8gLSBpUGFkIFNhZmFyaSA0LjNcbi8vIC0gTHlueCAyLjguN1xufSBlbHNlIHtcbiAgICByZXF1ZXN0Rmx1c2ggPSBtYWtlUmVxdWVzdENhbGxGcm9tVGltZXIoZmx1c2gpO1xufVxuXG4vLyBgcmVxdWVzdEZsdXNoYCByZXF1ZXN0cyB0aGF0IHRoZSBoaWdoIHByaW9yaXR5IGV2ZW50IHF1ZXVlIGJlIGZsdXNoZWQgYXNcbi8vIHNvb24gYXMgcG9zc2libGUuXG4vLyBUaGlzIGlzIHVzZWZ1bCB0byBwcmV2ZW50IGFuIGVycm9yIHRocm93biBpbiBhIHRhc2sgZnJvbSBzdGFsbGluZyB0aGUgZXZlbnRcbi8vIHF1ZXVlIGlmIHRoZSBleGNlcHRpb24gaGFuZGxlZCBieSBOb2RlLmpz4oCZc1xuLy8gYHByb2Nlc3Mub24oXCJ1bmNhdWdodEV4Y2VwdGlvblwiKWAgb3IgYnkgYSBkb21haW4uXG5yYXdBc2FwLnJlcXVlc3RGbHVzaCA9IHJlcXVlc3RGbHVzaDtcblxuLy8gVG8gcmVxdWVzdCBhIGhpZ2ggcHJpb3JpdHkgZXZlbnQsIHdlIGluZHVjZSBhIG11dGF0aW9uIG9ic2VydmVyIGJ5IHRvZ2dsaW5nXG4vLyB0aGUgdGV4dCBvZiBhIHRleHQgbm9kZSBiZXR3ZWVuIFwiMVwiIGFuZCBcIi0xXCIuXG5mdW5jdGlvbiBtYWtlUmVxdWVzdENhbGxGcm9tTXV0YXRpb25PYnNlcnZlcihjYWxsYmFjaykge1xuICAgIHZhciB0b2dnbGUgPSAxO1xuICAgIHZhciBvYnNlcnZlciA9IG5ldyBCcm93c2VyTXV0YXRpb25PYnNlcnZlcihjYWxsYmFjayk7XG4gICAgdmFyIG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKG5vZGUsIHtjaGFyYWN0ZXJEYXRhOiB0cnVlfSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHJlcXVlc3RDYWxsKCkge1xuICAgICAgICB0b2dnbGUgPSAtdG9nZ2xlO1xuICAgICAgICBub2RlLmRhdGEgPSB0b2dnbGU7XG4gICAgfTtcbn1cblxuLy8gVGhlIG1lc3NhZ2UgY2hhbm5lbCB0ZWNobmlxdWUgd2FzIGRpc2NvdmVyZWQgYnkgTWFsdGUgVWJsIGFuZCB3YXMgdGhlXG4vLyBvcmlnaW5hbCBmb3VuZGF0aW9uIGZvciB0aGlzIGxpYnJhcnkuXG4vLyBodHRwOi8vd3d3Lm5vbmJsb2NraW5nLmlvLzIwMTEvMDYvd2luZG93bmV4dHRpY2suaHRtbFxuXG4vLyBTYWZhcmkgNi4wLjUgKGF0IGxlYXN0KSBpbnRlcm1pdHRlbnRseSBmYWlscyB0byBjcmVhdGUgbWVzc2FnZSBwb3J0cyBvbiBhXG4vLyBwYWdlJ3MgZmlyc3QgbG9hZC4gVGhhbmtmdWxseSwgdGhpcyB2ZXJzaW9uIG9mIFNhZmFyaSBzdXBwb3J0c1xuLy8gTXV0YXRpb25PYnNlcnZlcnMsIHNvIHdlIGRvbid0IG5lZWQgdG8gZmFsbCBiYWNrIGluIHRoYXQgY2FzZS5cblxuLy8gZnVuY3Rpb24gbWFrZVJlcXVlc3RDYWxsRnJvbU1lc3NhZ2VDaGFubmVsKGNhbGxiYWNrKSB7XG4vLyAgICAgdmFyIGNoYW5uZWwgPSBuZXcgTWVzc2FnZUNoYW5uZWwoKTtcbi8vICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGNhbGxiYWNrO1xuLy8gICAgIHJldHVybiBmdW5jdGlvbiByZXF1ZXN0Q2FsbCgpIHtcbi8vICAgICAgICAgY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZSgwKTtcbi8vICAgICB9O1xuLy8gfVxuXG4vLyBGb3IgcmVhc29ucyBleHBsYWluZWQgYWJvdmUsIHdlIGFyZSBhbHNvIHVuYWJsZSB0byB1c2UgYHNldEltbWVkaWF0ZWBcbi8vIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLlxuLy8gRXZlbiBpZiB3ZSB3ZXJlLCB0aGVyZSBpcyBhbm90aGVyIGJ1ZyBpbiBJbnRlcm5ldCBFeHBsb3JlciAxMC5cbi8vIEl0IGlzIG5vdCBzdWZmaWNpZW50IHRvIGFzc2lnbiBgc2V0SW1tZWRpYXRlYCB0byBgcmVxdWVzdEZsdXNoYCBiZWNhdXNlXG4vLyBgc2V0SW1tZWRpYXRlYCBtdXN0IGJlIGNhbGxlZCAqYnkgbmFtZSogYW5kIHRoZXJlZm9yZSBtdXN0IGJlIHdyYXBwZWQgaW4gYVxuLy8gY2xvc3VyZS5cbi8vIE5ldmVyIGZvcmdldC5cblxuLy8gZnVuY3Rpb24gbWFrZVJlcXVlc3RDYWxsRnJvbVNldEltbWVkaWF0ZShjYWxsYmFjaykge1xuLy8gICAgIHJldHVybiBmdW5jdGlvbiByZXF1ZXN0Q2FsbCgpIHtcbi8vICAgICAgICAgc2V0SW1tZWRpYXRlKGNhbGxiYWNrKTtcbi8vICAgICB9O1xuLy8gfVxuXG4vLyBTYWZhcmkgNi4wIGhhcyBhIHByb2JsZW0gd2hlcmUgdGltZXJzIHdpbGwgZ2V0IGxvc3Qgd2hpbGUgdGhlIHVzZXIgaXNcbi8vIHNjcm9sbGluZy4gVGhpcyBwcm9ibGVtIGRvZXMgbm90IGltcGFjdCBBU0FQIGJlY2F1c2UgU2FmYXJpIDYuMCBzdXBwb3J0c1xuLy8gbXV0YXRpb24gb2JzZXJ2ZXJzLCBzbyB0aGF0IGltcGxlbWVudGF0aW9uIGlzIHVzZWQgaW5zdGVhZC5cbi8vIEhvd2V2ZXIsIGlmIHdlIGV2ZXIgZWxlY3QgdG8gdXNlIHRpbWVycyBpbiBTYWZhcmksIHRoZSBwcmV2YWxlbnQgd29yay1hcm91bmRcbi8vIGlzIHRvIGFkZCBhIHNjcm9sbCBldmVudCBsaXN0ZW5lciB0aGF0IGNhbGxzIGZvciBhIGZsdXNoLlxuXG4vLyBgc2V0VGltZW91dGAgZG9lcyBub3QgY2FsbCB0aGUgcGFzc2VkIGNhbGxiYWNrIGlmIHRoZSBkZWxheSBpcyBsZXNzIHRoYW5cbi8vIGFwcHJveGltYXRlbHkgNyBpbiB3ZWIgd29ya2VycyBpbiBGaXJlZm94IDggdGhyb3VnaCAxOCwgYW5kIHNvbWV0aW1lcyBub3Rcbi8vIGV2ZW4gdGhlbi5cblxuZnVuY3Rpb24gbWFrZVJlcXVlc3RDYWxsRnJvbVRpbWVyKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHJlcXVlc3RDYWxsKCkge1xuICAgICAgICAvLyBXZSBkaXNwYXRjaCBhIHRpbWVvdXQgd2l0aCBhIHNwZWNpZmllZCBkZWxheSBvZiAwIGZvciBlbmdpbmVzIHRoYXRcbiAgICAgICAgLy8gY2FuIHJlbGlhYmx5IGFjY29tbW9kYXRlIHRoYXQgcmVxdWVzdC4gVGhpcyB3aWxsIHVzdWFsbHkgYmUgc25hcHBlZFxuICAgICAgICAvLyB0byBhIDQgbWlsaXNlY29uZCBkZWxheSwgYnV0IG9uY2Ugd2UncmUgZmx1c2hpbmcsIHRoZXJlJ3Mgbm8gZGVsYXlcbiAgICAgICAgLy8gYmV0d2VlbiBldmVudHMuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChoYW5kbGVUaW1lciwgMCk7XG4gICAgICAgIC8vIEhvd2V2ZXIsIHNpbmNlIHRoaXMgdGltZXIgZ2V0cyBmcmVxdWVudGx5IGRyb3BwZWQgaW4gRmlyZWZveFxuICAgICAgICAvLyB3b3JrZXJzLCB3ZSBlbmxpc3QgYW4gaW50ZXJ2YWwgaGFuZGxlIHRoYXQgd2lsbCB0cnkgdG8gZmlyZVxuICAgICAgICAvLyBhbiBldmVudCAyMCB0aW1lcyBwZXIgc2Vjb25kIHVudGlsIGl0IHN1Y2NlZWRzLlxuICAgICAgICB2YXIgaW50ZXJ2YWxIYW5kbGUgPSBzZXRJbnRlcnZhbChoYW5kbGVUaW1lciwgNTApO1xuXG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRpbWVyKCkge1xuICAgICAgICAgICAgLy8gV2hpY2hldmVyIHRpbWVyIHN1Y2NlZWRzIHdpbGwgY2FuY2VsIGJvdGggdGltZXJzIGFuZFxuICAgICAgICAgICAgLy8gZXhlY3V0ZSB0aGUgY2FsbGJhY2suXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dEhhbmRsZSk7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsSGFuZGxlKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9O1xufVxuXG4vLyBUaGlzIGlzIGZvciBgYXNhcC5qc2Agb25seS5cbi8vIEl0cyBuYW1lIHdpbGwgYmUgcGVyaW9kaWNhbGx5IHJhbmRvbWl6ZWQgdG8gYnJlYWsgYW55IGNvZGUgdGhhdCBkZXBlbmRzIG9uXG4vLyBpdHMgZXhpc3RlbmNlLlxucmF3QXNhcC5tYWtlUmVxdWVzdENhbGxGcm9tVGltZXIgPSBtYWtlUmVxdWVzdENhbGxGcm9tVGltZXI7XG5cbi8vIEFTQVAgd2FzIG9yaWdpbmFsbHkgYSBuZXh0VGljayBzaGltIGluY2x1ZGVkIGluIFEuIFRoaXMgd2FzIGZhY3RvcmVkIG91dFxuLy8gaW50byB0aGlzIEFTQVAgcGFja2FnZS4gSXQgd2FzIGxhdGVyIGFkYXB0ZWQgdG8gUlNWUCB3aGljaCBtYWRlIGZ1cnRoZXJcbi8vIGFtZW5kbWVudHMuIFRoZXNlIGRlY2lzaW9ucywgcGFydGljdWxhcmx5IHRvIG1hcmdpbmFsaXplIE1lc3NhZ2VDaGFubmVsIGFuZFxuLy8gdG8gY2FwdHVyZSB0aGUgTXV0YXRpb25PYnNlcnZlciBpbXBsZW1lbnRhdGlvbiBpbiBhIGNsb3N1cmUsIHdlcmUgaW50ZWdyYXRlZFxuLy8gYmFjayBpbnRvIEFTQVAgcHJvcGVyLlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3RpbGRlaW8vcnN2cC5qcy9ibG9iL2NkZGY3MjMyNTQ2YTljZjg1ODUyNGI3NWNkZTZmOWVkZjcyNjIwYTcvbGliL3JzdnAvYXNhcC5qc1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xuXG52YXIgJGNvbnRhaW5lcjtcbnZhciBTdGVwc0NvbmZpZ3VyYXRpb247XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoJGNvbnRhaW5lclBhcmFtZXRlciwgb3B0aW9uc1BhcmFtZXRlcikge1xuXHRkYXRhQnVmZmVyID0ge307XG5cdG9wdGlvbnMgPSAkLmV4dGVuZCh7XG5cdFx0c3VjY2Vzc0NhbGxiYWNrOiBudWxsLFxuXHRcdGVycm9yQ2FsbGJhY2s6IG51bGxcblx0fSwgb3B0aW9uc1BhcmFtZXRlcik7XG5cdFxuXHQkY29udGFpbmVyID0gJGNvbnRhaW5lclBhcmFtZXRlcjtcblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkJvcGlzICYmIG9wdGlvbnMuQm9waXMuRW5hYmxlZCkge1xuXHRcdGlmIChvcHRpb25zLkJvcGlzLlNlbGVjdGVkTG9jYXRpb25zICYmIG9wdGlvbnMuQm9waXMuU3RlcENvbmZpZ3VyYXRpb24pIHtcblx0XHRcdFN0ZXBzQ29uZmlndXJhdGlvbiA9IG9wdGlvbnMuQm9waXMuU3RlcENvbmZpZ3VyYXRpb247XG5cdFx0XHRcblx0XHRcdGlmICghb3B0aW9ucy5Cb3Bpcy5Jc0xvY2F0aW9uU2VhcmNoRmlsdGVyZWQgJiYgd2luZG93LmxvY2F0aW9uLnNlYXJjaC5pbmRleE9mKCdwcmVmbjInKSA8IDApIHtcblx0XHRcdFx0JGNvbnRhaW5lci5hZGRDbGFzcygnb3BlbicpO1xuXHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGJ1aWxkU3RlcFBsYWNlaG9sZGVycygwKTtcblx0XHRcdGlmIChTdGVwc0NvbmZpZ3VyYXRpb25bMF0uVHlwZSA9PSAnQ2F0ZWdvcnknKSB7XG5cdFx0XHRcdGJ1aWxkU3RlcFdpdGhDYXRlZ29yaWVzKDApO1xuXHRcdFx0fSBlbHNlIGlmIChTdGVwc0NvbmZpZ3VyYXRpb25bMF0uVHlwZSA9PSAnUmVmaW5lbWVudCcpIHtcblx0XHRcdFx0YnVpbGRTdGVwV2l0aFNpemVzKDApO1xuXHRcdFx0fVxuXG5cdFx0XHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNlbGVjdE5ld0ZpbHRlcnMnKS5vbignY2xpY2suU2VsZWN0TmV3RmlsdGVycycsICcuY2FsbG91dC1zZWxlY3RlZC1sb2NhdGlvbiAuc2VsZWN0LW5ldy1maWx0ZXJzJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0JGNvbnRhaW5lci5hZGRDbGFzcygnb3BlbicpO1xuXHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLlNlZU1vcmVTaXplcycpLm9uKCdjbGljay5TZWVNb3JlU2l6ZXMnLCAnW3N0ZXBdIGEuc2VlLW1vcmUtc2l6ZXMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwXVtyZWZpbmVtZW50PVwic2l6ZVwiXSAucmVmaW5lbWVudFZhbHVlcycpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH0pO1xuXHRcdFx0XG5cdFx0XHQkY29udGFpbmVyLm9mZignY2xpY2suU2VhcmNoQ2F0ZWdvcnknKS5vbignY2xpY2suU2VhcmNoQ2F0ZWdvcnknLCAnW3N0ZXBdIGEuc2VsZWN0YWJsZTpub3QoLnBsYWNlaG9sZGVyKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHR2YXIgc3RlcCA9IHBhcnNlSW50KCR0aGlzLmNsb3Nlc3QoJ1tzdGVwXScpLmF0dHIoJ3N0ZXAnKSwgMTApO1xuXHRcdFx0XHR2YXIgc3RlcENvbmZpZ3VyYXRpb24gPSBTdGVwc0NvbmZpZ3VyYXRpb25bc3RlcCArIDFdO1xuXHRcdFx0XHR2YXIgY2F0ZWdvcnlJZDtcblx0XHRcdFx0aWYgKCR0aGlzLmF0dHIoJ2NhdGVnb3J5LWlkJykpIHtcblx0XHRcdFx0XHRjYXRlZ29yeUlkID0gJHRoaXMuYXR0cignY2F0ZWdvcnktaWQnKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCdbc3RlcD1cIicgKyBzdGVwICsgJ1wiXSBhJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHRcdGlmICgoc3RlcCArIDIpIDw9IFN0ZXBzQ29uZmlndXJhdGlvbi5sZW5ndGgpIHtcblx0XHRcdFx0XHRmb3IgKHZhciBzdGVwSW5kZXggPSBzdGVwICsgMjsgc3RlcEluZGV4IDwgU3RlcHNDb25maWd1cmF0aW9uLmxlbmd0aDsgc3RlcEluZGV4KyspIHtcblx0XHRcdFx0XHRcdGJ1aWxkU3RlcFBsYWNlaG9sZGVyKHN0ZXBJbmRleCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdCR0aGlzLmFkZENsYXNzKCdzZWxlY3RlZCcpO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIHNlbGVjdGVkQ2F0ZWdvcnkgPSAkY29udGFpbmVyLmZpbmQoJy5zdGVwcyBhW2NhdGVnb3J5LWlkXS5zZWxlY3RlZCcpLmxhc3QoKS5hdHRyKCdjYXRlZ29yeS1pZCcpO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRTaXplID0gJGNvbnRhaW5lci5maW5kKCcuc3RlcHMgYVtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxhc3QoKS5hdHRyKCdyZWZpbmVtZW50LXZhbHVlJyk7XG5cdFx0XHRcdHZhciBzZWxlY3RlZExlbmd0aCA9ICRjb250YWluZXIuZmluZCgnLnN0ZXBzIGFbcmVmaW5lbWVudC1sZW5ndGhdLnNlbGVjdGVkJykubGFzdCgpLmF0dHIoJ3JlZmluZW1lbnQtbGVuZ3RoJyk7XG5cdFx0XHRcdHZhciBzZWxlY3RlZFdpZHRoID0gJGNvbnRhaW5lci5maW5kKCcuc3RlcHMgYVtyZWZpbmVtZW50LXdpZHRoXS5zZWxlY3RlZCcpLmxhc3QoKS5hdHRyKCdyZWZpbmVtZW50LXdpZHRoJyk7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoY2F0ZWdvcnlJZCkge1xuXHRcdFx0XHRcdGlmIChzdGVwQ29uZmlndXJhdGlvbi5UeXBlID09ICdDYXRlZ29yeScpIHtcblx0XHRcdFx0XHRcdGJ1aWxkU3RlcFdpdGhDYXRlZ29yaWVzKHN0ZXAgKyAxLCBjYXRlZ29yeUlkKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHN0ZXBDb25maWd1cmF0aW9uLlR5cGUgPT0gJ1JlZmluZW1lbnQnKSB7XG5cdFx0XHRcdFx0XHRidWlsZFN0ZXBXaXRoU2l6ZXMoc3RlcCArIDEsIGNhdGVnb3J5SWQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmIChzZWxlY3RlZExlbmd0aCAmJiBzZWxlY3RlZFdpZHRoKSB7XG5cdFx0XHRcdFx0dXBkYXRlUHJvZHVjdENvdW50Rm9yQ2F0ZWdvcnlBbmRTaXplKHN0ZXAgKyAxLCBzZWxlY3RlZENhdGVnb3J5LCBzZWxlY3RlZExlbmd0aCArICcgJyArIHNlbGVjdGVkV2lkdGgpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHNlbGVjdGVkTGVuZ3RoICYmIGRhdGFCdWZmZXJbJ1dpZHRoc0J5TGVuZ3RoJ10gJiYgZGF0YUJ1ZmZlclsnV2lkdGhzQnlMZW5ndGgnXVtzZWxlY3RlZExlbmd0aF0pIHtcblx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRTaXplcyA9ICcnO1xuXHRcdFx0XHRcdGZvciAodmFyIHdpZHRoRm9yTGVuZ3RoS2V5IGluIGRhdGFCdWZmZXJbJ1dpZHRoc0J5TGVuZ3RoJ11bc2VsZWN0ZWRMZW5ndGhdKSB7XG5cdFx0XHRcdFx0XHR2YXIgd2lkdGhGb3JMZW5ndGggPSBkYXRhQnVmZmVyWydXaWR0aHNCeUxlbmd0aCddW3NlbGVjdGVkTGVuZ3RoXVt3aWR0aEZvckxlbmd0aEtleV07XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmIChzZWxlY3RlZFNpemVzKSB7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdGVkU2l6ZXMgKz0gJ3wnO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRzZWxlY3RlZFNpemVzICs9IHNlbGVjdGVkTGVuZ3RoICsgJyAnICsgd2lkdGhGb3JMZW5ndGg7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHVwZGF0ZVByb2R1Y3RDb3VudEZvckNhdGVnb3J5QW5kU2l6ZShzdGVwICsgMSwgc2VsZWN0ZWRDYXRlZ29yeSwgc2VsZWN0ZWRTaXplcyk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoc2VsZWN0ZWRTaXplKSB7XG5cdFx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCdbc3RlcF1bcmVmaW5lbWVudD1cIndpZHRoXCJdJykucmVtb3ZlKCk7XG5cdFx0XHRcdFx0dXBkYXRlUHJvZHVjdENvdW50Rm9yQ2F0ZWdvcnlBbmRTaXplKHN0ZXAgKyAxLCBzZWxlY3RlZENhdGVnb3J5LCBzZWxlY3RlZFNpemUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJy5idG4ucmVzZXQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHR2YXIgYWxsU3RlcHNIYXZlU2VsZWN0ZWRWYWx1ZSA9IHRydWU7XG5cdFx0XHRcdCRjb250YWluZXIuZmluZCgnW3N0ZXBdJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoJCh0aGlzKS5maW5kKCcuc2VsZWN0YWJsZS5zZWxlY3RlZCcpLmxlbmd0aCA8IDEpIHtcblx0XHRcdFx0XHRcdGFsbFN0ZXBzSGF2ZVNlbGVjdGVkVmFsdWUgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRpZiAoYWxsU3RlcHNIYXZlU2VsZWN0ZWRWYWx1ZSkge1xuXHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnLmJ0bi5hcHBseScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCcuYnRuLmFwcGx5JykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdCRjb250YWluZXIub2ZmKCdjbGljay5TZWFyY2hMZW5ndGgnKS5vbignY2xpY2suU2VhcmNoTGVuZ3RoJywgJ1tzdGVwXSBhLnNlbGVjdGFibGVbcmVmaW5lbWVudC1sZW5ndGhdOm5vdCgucGxhY2Vob2xkZXIpJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciBzdGVwID0gcGFyc2VJbnQoJHRoaXMuY2xvc2VzdCgnW3N0ZXBdJykuYXR0cignc3RlcCcpLCAxMCk7XG5cdFx0XHRcdHZhciBzdGVwQ29uZmlndXJhdGlvbiA9IFN0ZXBzQ29uZmlndXJhdGlvbltzdGVwICsgMV07XG5cdFx0XHRcdHZhciBzZWxlY3RlZENhdGVnb3J5ID0gJGNvbnRhaW5lci5maW5kKCcuc3RlcHMgYVtjYXRlZ29yeS1pZF0uc2VsZWN0ZWQnKS5sYXN0KCkuYXR0cignY2F0ZWdvcnktaWQnKTtcblx0XHRcdFx0dmFyIHNlbGVjdGVkTGVuZ3RoID0gJGNvbnRhaW5lci5maW5kKCcuc3RlcHMgYVtyZWZpbmVtZW50LWxlbmd0aF0uc2VsZWN0ZWQnKS5sYXN0KCkuYXR0cigncmVmaW5lbWVudC1sZW5ndGgnKTtcblx0XHRcdFx0XG5cdFx0XHRcdGJ1aWxkU3RlcFdpdGhXaWR0aHMoc3RlcCArIDEsIHNlbGVjdGVkQ2F0ZWdvcnksIHNlbGVjdGVkTGVuZ3RoKTtcblx0XHRcdH0pO1xuXHRcdFx0XG5cdFx0XHQkY29udGFpbmVyLm9mZignY2xpY2suQXBwbHknKS5vbignY2xpY2suQXBwbHknLCAnLmJ0bi5hcHBseScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdCRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ29wZW4nKTtcblx0XHRcdFx0XG5cdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKHtcblx0XHRcdFx0XHRDb250ZW50OiAnPGg2PkhvbGQgWW91ciBIb3JzZXMhPC9oNj48cD5Zb3VyIHNlbGVjdGlvbnMgYXJlIGxvYWRpbmcuLi48L3A+Jyxcblx0XHRcdFx0XHRDc3NDbGFzczogJ2Jvb3RiYXJuZXhwcmVzcycsXG5cdFx0XHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyICRzZWxlY3RlZENhdGVnb3J5ID0gJGNvbnRhaW5lci5maW5kKCcuc3RlcHMgYVtjYXRlZ29yeS1pZF0uc2VsZWN0ZWQnKS5sYXN0KCk7XG5cdFx0XHRcdHZhciBzZWxlY3RlZENhdGVnb3J5ID0gJHNlbGVjdGVkQ2F0ZWdvcnkuYXR0cignY2F0ZWdvcnktaWQnKTtcblx0XHRcdFx0dmFyIHNlbGVjdGVkQ2F0ZWdvcnlVcmwgPSAkc2VsZWN0ZWRDYXRlZ29yeS5hdHRyKCdjYXRlZ29yeS11cmwnKTtcblx0XHRcdFx0dmFyIHNlbGVjdGVkU2l6ZSA9ICRjb250YWluZXIuZmluZCgnLnN0ZXBzIGFbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sYXN0KCkuYXR0cigncmVmaW5lbWVudC12YWx1ZScpO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRMZW5ndGggPSAkY29udGFpbmVyLmZpbmQoJy5zdGVwcyBhW3JlZmluZW1lbnQtbGVuZ3RoXS5zZWxlY3RlZCcpLmxhc3QoKS5hdHRyKCdyZWZpbmVtZW50LWxlbmd0aCcpO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRXaWR0aCA9ICRjb250YWluZXIuZmluZCgnLnN0ZXBzIGFbcmVmaW5lbWVudC13aWR0aF0uc2VsZWN0ZWQnKS5sYXN0KCkuYXR0cigncmVmaW5lbWVudC13aWR0aCcpO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRMb2NhdGlvbiA9IG9wdGlvbnMuQm9waXMuU2VsZWN0ZWRMb2NhdGlvbnNbMF0uU3RvcmVJZDtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChzZWxlY3RlZExvY2F0aW9uICYmIHNlbGVjdGVkQ2F0ZWdvcnlVcmwpIHtcblx0XHRcdFx0XHR2YXIgdXJsID0gd2luZG93LmxvY2F0aW9uLm9yaWdpbiArIHNlbGVjdGVkQ2F0ZWdvcnlVcmw7XG5cdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuMScsICdhdmFpbGFibGVTdG9yZXMnKTtcblx0XHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncHJlZnYxJywgc2VsZWN0ZWRMb2NhdGlvbik7XG5cdFx0XHRcdFxuXHRcdFx0XHRcdGlmIChzZWxlY3RlZExlbmd0aCAmJiBzZWxlY3RlZFdpZHRoKSB7XG5cdFx0XHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncHJlZm4yJywgJ3NpemUnKTtcblx0XHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmdjInLCBzZWxlY3RlZExlbmd0aCArICcgJyArIHNlbGVjdGVkV2lkdGgpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoc2VsZWN0ZWRMZW5ndGggJiYgZGF0YUJ1ZmZlclsnV2lkdGhzQnlMZW5ndGgnXSAmJiBkYXRhQnVmZmVyWydXaWR0aHNCeUxlbmd0aCddW3NlbGVjdGVkTGVuZ3RoXSkge1xuXHRcdFx0XHRcdFx0dmFyIHNlbGVjdGVkU2l6ZXMgPSAnJztcblx0XHRcdFx0XHRcdGZvciAodmFyIHdpZHRoRm9yTGVuZ3RoS2V5IGluIGRhdGFCdWZmZXJbJ1dpZHRoc0J5TGVuZ3RoJ11bc2VsZWN0ZWRMZW5ndGhdKSB7XG5cdFx0XHRcdFx0XHRcdHZhciB3aWR0aEZvckxlbmd0aCA9IGRhdGFCdWZmZXJbJ1dpZHRoc0J5TGVuZ3RoJ11bc2VsZWN0ZWRMZW5ndGhdW3dpZHRoRm9yTGVuZ3RoS2V5XTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGlmIChzZWxlY3RlZFNpemVzKSB7XG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRTaXplcyArPSAnfCc7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdHNlbGVjdGVkU2l6ZXMgKz0gc2VsZWN0ZWRMZW5ndGggKyAnICcgKyB3aWR0aEZvckxlbmd0aDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuMicsICdzaXplJyk7XG5cdFx0XHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncHJlZnYyJywgc2VsZWN0ZWRTaXplcyk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChzZWxlY3RlZFNpemUpIHtcblx0XHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmbjInLCAnc2l6ZScpO1xuXHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZ2MicsIHNlbGVjdGVkU2l6ZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLlJlc2V0Jykub24oJ2NsaWNrLlJlc2V0JywgJy5idG4ucmVzZXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJy5zdGVwcycpLmh0bWwoJycpO1xuXHRcdFx0XHRidWlsZFN0ZXBQbGFjZWhvbGRlcnMoMCk7XG5cdFx0XHRcdGJ1aWxkU3RlcFdpdGhDYXRlZ29yaWVzKDApO1xuXHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJy5idG4uYXBwbHksIC5idG4ucmVzZXQnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdCRjb250YWluZXIub2ZmKCdjbGljay5DbG9zZScpLm9uKCdjbGljay5DbG9zZScsICcuY2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHQkY29udGFpbmVyLnJlbW92ZUNsYXNzKCdvcGVuJyk7XG5cdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc2Nyb2xsLWxvY2snKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBidWlsZFN0ZXBXaXRoQ2F0ZWdvcmllcyhzdGVwLCBjYXRlZ29yeUlkUGFyYW1ldGVyKSB7XG5cdHZhciBjYXRlZ29yeUlkID0gY2F0ZWdvcnlJZFBhcmFtZXRlciB8fCAncm9vdCc7XG5cdCRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQtY29udGFpbmVyJykubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZVxuXHR9KTtcblx0dmFyICRzdGVwID0gJGNvbnRhaW5lci5maW5kKCdbc3RlcD1cIicgKyBzdGVwICsgJ1wiXScpO1xuXHRpZiAoJHN0ZXAubGVuZ3RoIDwgMSkge1xuXHRcdCRjb250YWluZXIuZmluZCgnLnN0ZXBzJykuYXBwZW5kKCc8ZGl2IHN0ZXA9XCInICsgc3RlcCArICdcIj48L2Rpdj4nKTtcblx0XHQkc3RlcCA9ICRjb250YWluZXIuZmluZCgnW3N0ZXA9XCInICsgc3RlcCArICdcIl0nKTtcblx0fVxuXHQkc3RlcC5sb2FkaW5nKHtcblx0XHRJc0ltYWdlU2hvd246IGZhbHNlLFxuICAgICAgICBDb250ZW50OiAnPHA+WW91ciBzZWxlY3Rpb25zIGFyZSBsb2FkaW5nLi4uPC9wPicsXG5cdFx0Q3NzQ2xhc3M6ICdib290YmFybmV4cHJlc3MnLFxuXHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHR9KTtcblx0aWYgKCRzdGVwLmZpbmQoJ2g1JykubGVuZ3RoID4gMCkge1xuXHRcdCRzdGVwLmZpbmQoJy5sb2FkaW5nLWluZGljYXRvci1jb250YWluZXInKS5jc3MoJ21hcmdpbi10b3AnLCAkc3RlcC5maW5kKCdoNScpLmlubmVySGVpZ2h0KCkpO1xuXHR9XG5cblx0JC5hamF4KHtcbiAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgdXJsOiBVcmxzLkJvb3RCYXJuRXhwcmVzcy5HZXRTdWJDYXRlZ29yaWVzRm9yQ2F0ZWdvcnlJZCxcbiAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgZGF0YToge1xuXHQgICAgICAgIGNnaWQ6IGNhdGVnb3J5SWQsXG4gICAgICAgICAgICBwcmVmbjE6ICdhdmFpbGFibGVTdG9yZXMnLFxuICAgICAgICAgICAgcHJlZnYxOiBvcHRpb25zLkJvcGlzLlNlbGVjdGVkTG9jYXRpb25zWzBdLlN0b3JlSWRcblx0ICAgIH0sXG4gICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgICRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChkYXRhICYmIGRhdGEuUHJvZHVjdENvdW50KSB7XG4gICAgICAgICAgICBcdCRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQnKS5odG1sKGRhdGEuUHJvZHVjdENvdW50LnRvTG9jYWxlU3RyaW5nKCdlbicpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5DYXRlZ29yaWVzKSB7XG4gICAgICAgICAgICBcdHZhciBzdGVwSHRtbDtcbiAgICAgICAgICAgIFx0aWYgKFN0ZXBzQ29uZmlndXJhdGlvbltzdGVwXSAmJiBTdGVwc0NvbmZpZ3VyYXRpb25bc3RlcF0uSGVhZGVyKSB7XG4gICAgICAgICAgICBcdFx0c3RlcEh0bWwgPSAnPGg1PicgKyBTdGVwc0NvbmZpZ3VyYXRpb25bc3RlcF0uSGVhZGVyICsgJzwvaDU+JztcbiAgICAgICAgICAgIFx0fSBlbHNlIHtcbiAgICAgICAgICAgIFx0XHRzdGVwSHRtbCA9ICcnO1xuICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdGZvciAodmFyIGNhdGVnb3J5S2V5IGluIGRhdGEuQ2F0ZWdvcmllcykge1xuICAgICAgICAgICAgXHRcdHZhciBjYXRlZ29yeSA9IGRhdGEuQ2F0ZWdvcmllc1tjYXRlZ29yeUtleV07XHRcdFxuICAgICAgICAgICAgXHRcdHN0ZXBIdG1sICs9ICc8YSBjYXRlZ29yeS1pZD1cIicgKyBjYXRlZ29yeS5JZCArICdcIiBjYXRlZ29yeS11cmw9XCInICsgY2F0ZWdvcnkuVXJsICsgJ1wiIGNsYXNzPVwic2VsZWN0YWJsZVwiPicgKyBjYXRlZ29yeS5OYW1lICsgJzwvYT4nO1xuICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdFxuICAgICAgICBcdFx0JHN0ZXAuaHRtbChzdGVwSHRtbCkuc2hvdygpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgXHRcdHNjcm9sbFRvU3RlcCgkc3RlcCk7XG4gICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIFx0b3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2soaW5xdWlyeVJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsICcwJyk7XG4gICAgICAgICAgICAgICAgJHN0ZXAuc2hvdygpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQtY29udGFpbmVyJykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICAkc3RlcC5zaG93KCkubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgJGNvbnRhaW5lci5maW5kKCcucHJvZHVjdC1jb3VudC1jb250YWluZXInKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgIH1cbiAgICB9KTtcdFxufVxuXG5mdW5jdGlvbiBidWlsZFN0ZXBXaXRoU2l6ZXMoc3RlcCwgY2F0ZWdvcnlJZFBhcmFtZXRlcikge1xuXHR2YXIgY2F0ZWdvcnlJZCA9IGNhdGVnb3J5SWRQYXJhbWV0ZXIgfHwgJ3Jvb3QnO1xuXHQkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LWNvdW50LWNvbnRhaW5lcicpLmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2Vcblx0fSk7XG5cdHZhciAkc3RlcCA9ICRjb250YWluZXIuZmluZCgnW3N0ZXA9XCInICsgc3RlcCArICdcIl0nKTtcblx0aWYgKCRzdGVwLmxlbmd0aCA8IDEpIHtcblx0XHQkY29udGFpbmVyLmZpbmQoJy5zdGVwcycpLmFwcGVuZCgnPGRpdiBzdGVwPVwiJyArIHN0ZXAgKyAnXCI+PC9kaXY+Jyk7XG5cdFx0JHN0ZXAgPSAkY29udGFpbmVyLmZpbmQoJ1tzdGVwPVwiJyArIHN0ZXAgKyAnXCJdJyk7XG5cdH1cblx0JHN0ZXAubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcbiAgICAgICAgQ29udGVudDogJzxwPllvdXIgc2VsZWN0aW9ucyBhcmUgbG9hZGluZy4uLjwvcD4nLFxuXHRcdENzc0NsYXNzOiAnYm9vdGJhcm5leHByZXNzJyxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fSk7XG5cdGlmICgkc3RlcC5maW5kKCdoNScpLmxlbmd0aCA+IDApIHtcblx0XHQkc3RlcC5maW5kKCcubG9hZGluZy1pbmRpY2F0b3ItY29udGFpbmVyJykuY3NzKCdtYXJnaW4tdG9wJywgJHN0ZXAuZmluZCgnaDUnKS5pbm5lckhlaWdodCgpKTtcblx0fVxuXHRkYXRhQnVmZmVyWydXaWR0aHNCeUxlbmd0aCddID0ge307XG5cblx0JC5hamF4KHtcblx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdHVybDogVXJscy5Cb290QmFybkV4cHJlc3MuR2V0U29ydGVkUmVmaW5lbWVudFZhbHVlc0ZvclJlZmluZW1lbnRJZCxcblx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdGRhdGE6IHtcbiAgICAgICAgICAgIGNnaWQ6IGNhdGVnb3J5SWQsXG4gICAgICAgICAgICByZWZpbmVtZW50SWQ6IFN0ZXBzQ29uZmlndXJhdGlvbltzdGVwIC0gMV0uUmVmaW5lbWVudCB8fCAnc2l6ZScsXG4gICAgICAgICAgICBwcmVmbjE6ICdhdmFpbGFibGVTdG9yZXMnLFxuICAgICAgICAgICAgcHJlZnYxOiBvcHRpb25zLkJvcGlzLlNlbGVjdGVkTG9jYXRpb25zWzBdLlN0b3JlSWRcblx0XHR9LFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdyZXN1bHQnKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5Qcm9kdWN0Q291bnQpIHtcbiAgICAgICAgICAgIFx0JGNvbnRhaW5lci5maW5kKCcucHJvZHVjdC1jb3VudCcpLmh0bWwoZGF0YS5Qcm9kdWN0Q291bnQudG9Mb2NhbGVTdHJpbmcoJ2VuJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLlJlZmluZW1lbnRWYWx1ZXMpIHtcbiAgICAgICAgICAgIFx0dmFyIHBvcHVsYXJTaXplc0h0bWwgPSAnJztcblx0XHRcdFx0dmFyIGhpZGVSZWZpbmVtZW50VmFsdWVzID0gJyc7XG5cdFx0XHRcdHZhciBoYXNXaWR0aHMgPSBmYWxzZTtcbiAgICAgICAgICAgIFx0aWYgKGRhdGEuUG9wdWxhclNpemVzICYmIGRhdGEuUG9wdWxhclNpemVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIFx0XHRwb3B1bGFyU2l6ZXNIdG1sID0gJzxoNj5Nb3N0IFBvcHVsYXI8L2g2Pic7XG4gICAgICAgICAgICBcdFx0XG4gICAgICAgICAgICBcdFx0dmFyIHBhcnNlZFBvcHVsYXJTaXplUmVmaW5lbWVudFZhbHVlcyA9IHBhcnNlU2l6ZVJlZmluZW1lbnRWYWx1ZXNJbnRvTGVuZ3RoQW5kV2lkdGgoZGF0YS5Qb3B1bGFyU2l6ZXMpO1xuICAgICAgICAgICAgXHRcdGlmIChwYXJzZWRQb3B1bGFyU2l6ZVJlZmluZW1lbnRWYWx1ZXMgJiYgcGFyc2VkUG9wdWxhclNpemVSZWZpbmVtZW50VmFsdWVzLkxlbmd0aHMgJiYgcGFyc2VkUG9wdWxhclNpemVSZWZpbmVtZW50VmFsdWVzLkxlbmd0aHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgXHRcdFx0Zm9yICh2YXIgcmVmaW5lbWVudEtleSBpbiBwYXJzZWRQb3B1bGFyU2l6ZVJlZmluZW1lbnRWYWx1ZXMuTGVuZ3Rocykge1xuXHRcdCAgICAgICAgICAgIFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gcGFyc2VkUG9wdWxhclNpemVSZWZpbmVtZW50VmFsdWVzLkxlbmd0aHNbcmVmaW5lbWVudEtleV07XG5cdFx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50QXR0cmlidXRlO1xuXHRcdCAgICAgICAgICAgIFx0XHRpZiAocGFyc2VkUG9wdWxhclNpemVSZWZpbmVtZW50VmFsdWVzLldpZHRoc0J5TGVuZ3RoW3JlZmluZW1lbnRWYWx1ZV0pIHtcblx0XHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50QXR0cmlidXRlID0gJ3JlZmluZW1lbnQtbGVuZ3RoJztcblx0XHRcdFx0XHRcdFx0XHRoYXNXaWR0aHMgPSB0cnVlO1xuXHRcdCAgICAgICAgICAgIFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRBdHRyaWJ1dGUgPSAncmVmaW5lbWVudC12YWx1ZSc7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHQgICAgICAgICAgICBcdFx0XG5cdFx0ICAgICAgICAgICAgXHRcdHBvcHVsYXJTaXplc0h0bWwgKz0gJzxhICcgKyByZWZpbmVtZW50QXR0cmlidXRlICsgJz1cIicgKyByZWZpbmVtZW50VmFsdWUgKyAnXCIgY2xhc3M9XCJzZWxlY3RhYmxlXCI+JyArIHJlZmluZW1lbnRWYWx1ZSArICc8L2E+Jztcblx0XHQgICAgICAgICAgICBcdH1cbiAgICAgICAgICAgIFx0XHR9IGVsc2Uge1xuXHRcdCAgICAgICAgICAgIFx0Zm9yICh2YXIgcmVmaW5lbWVudEtleSBpbiBkYXRhLlBvcHVsYXJTaXplcykge1xuXHRcdCAgICAgICAgICAgIFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gZGF0YS5Qb3B1bGFyU2l6ZXNbcmVmaW5lbWVudEtleV07XG5cdFx0ICAgICAgICAgICAgXHRcdHBvcHVsYXJTaXplc0h0bWwgKz0gJzxhIHJlZmluZW1lbnQtdmFsdWU9XCInICsgcmVmaW5lbWVudFZhbHVlLnZhbHVlICsgJ1wiIGNsYXNzPVwic2VsZWN0YWJsZVwiPicgKyByZWZpbmVtZW50VmFsdWUuZGlzcGxheVZhbHVlICsgJzwvYT4nO1xuXHRcdCAgICAgICAgICAgIFx0fVxuICAgICAgICAgICAgXHRcdH1cblx0ICAgICAgICAgICAgXHRwb3B1bGFyU2l6ZXNIdG1sID0gJzxkaXYgY2xhc3M9XCJwb3B1bGFyU2l6ZXNcIj4nICsgcG9wdWxhclNpemVzSHRtbCArICc8L2Rpdj4nICsgJzxhIGNsYXNzPVwic2VlLW1vcmUtc2l6ZXNcIj5TZWUgTW9yZSBTaXplczwvYT4nO1xuXHQgICAgICAgICAgICBcdGhpZGVSZWZpbmVtZW50VmFsdWVzID0gJyBoaWRkZW4nO1xuICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdHZhciBzaXplc0hlYWRlckh0bWw7XG4gICAgICAgICAgICBcdHZhciByZWZpbmVtZW50VmFsdWVzSHRtbCA9ICcnO1xuICAgICAgICAgICAgXHRcbiAgICAgICAgICAgIFx0dmFyIHBhcnNlZFNpemVSZWZpbmVtZW50VmFsdWVzID0gcGFyc2VTaXplUmVmaW5lbWVudFZhbHVlc0ludG9MZW5ndGhBbmRXaWR0aChkYXRhLlJlZmluZW1lbnRWYWx1ZXMpO1xuICAgICAgICAgICAgXHRpZiAocGFyc2VkU2l6ZVJlZmluZW1lbnRWYWx1ZXMgJiYgcGFyc2VkU2l6ZVJlZmluZW1lbnRWYWx1ZXMuTGVuZ3RocyAmJiBwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5MZW5ndGhzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIFx0XHRzaXplc0hlYWRlckh0bWwgPSAnPGg1PkZpbHRlciBCeSBTaXplPC9oNT4nO1xuICAgICAgICAgICAgXHRcdFxuICAgICAgICAgICAgXHRcdGlmIChwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5XaWR0aHNCeUxlbmd0aCAmJiBwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5XaWR0aHNCeUxlbmd0aC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBcdFx0XHRkYXRhQnVmZmVyWydXaWR0aHNCeUxlbmd0aCddID0gcGFyc2VkU2l6ZVJlZmluZW1lbnRWYWx1ZXMuV2lkdGhzQnlMZW5ndGg7XG4gICAgICAgICAgICBcdFx0fVxuICAgICAgICAgICAgXHRcdFxuICAgICAgICAgICAgXHRcdGZvciAodmFyIHJlZmluZW1lbnRLZXkgaW4gcGFyc2VkU2l6ZVJlZmluZW1lbnRWYWx1ZXMuTGVuZ3Rocykge1xuICAgICAgICAgICAgXHRcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9IHBhcnNlZFNpemVSZWZpbmVtZW50VmFsdWVzLkxlbmd0aHNbcmVmaW5lbWVudEtleV07XG4gICAgICAgICAgICBcdFx0XHR2YXIgcmVmaW5lbWVudEF0dHJpYnV0ZSA9ICdyZWZpbmVtZW50LWxlbmd0aCc7XG4gICAgICAgICAgICBcdFx0XHRpZiAocGFyc2VkU2l6ZVJlZmluZW1lbnRWYWx1ZXMuV2lkdGhzQnlMZW5ndGhbcmVmaW5lbWVudFZhbHVlXSAmJiBwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5XaWR0aHNCeUxlbmd0aFtyZWZpbmVtZW50VmFsdWVdLmxlbmd0aCA9PSAxKSB7XG5cdCAgICAgICAgICAgIFx0XHRcdHJlZmluZW1lbnRWYWx1ZSArPSAnICcgKyBwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5XaWR0aHNCeUxlbmd0aFtyZWZpbmVtZW50VmFsdWVdWzBdO1xuXHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50QXR0cmlidXRlID0gJ3JlZmluZW1lbnQtdmFsdWUnO1xuXHQgICAgICAgICAgICBcdFx0fSBlbHNlIGlmIChwYXJzZWRTaXplUmVmaW5lbWVudFZhbHVlcy5XaWR0aHNCeUxlbmd0aFtyZWZpbmVtZW50VmFsdWVdKSB7XG5cdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRBdHRyaWJ1dGUgPSAncmVmaW5lbWVudC1sZW5ndGgnO1xuXHRcdFx0XHRcdFx0XHRoYXNXaWR0aHMgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmVmaW5lbWVudEF0dHJpYnV0ZSA9ICdyZWZpbmVtZW50LXZhbHVlJztcblx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgIFx0XHRcdFxuXHQgICAgICAgICAgICBcdFx0cmVmaW5lbWVudFZhbHVlc0h0bWwgKz0gJzxhICcgKyByZWZpbmVtZW50QXR0cmlidXRlICsgJz1cIicgKyByZWZpbmVtZW50VmFsdWUgKyAnXCIgY2xhc3M9XCJzZWxlY3RhYmxlXCI+JyArIHJlZmluZW1lbnRWYWx1ZSArICc8L2E+Jztcblx0ICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdH0gZWxzZSB7XG4gICAgICAgICAgICBcdFx0c2l6ZXNIZWFkZXJIdG1sID0gJzxoNT5GaWx0ZXIgQnkgU2l6ZTwvaDU+JztcbiAgICAgICAgICAgIFx0XHRcblx0ICAgICAgICAgICAgXHRmb3IgKHZhciByZWZpbmVtZW50S2V5IGluIGRhdGEuUmVmaW5lbWVudFZhbHVlcykge1xuXHQgICAgICAgICAgICBcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9IGRhdGEuUmVmaW5lbWVudFZhbHVlc1tyZWZpbmVtZW50S2V5XTtcblx0ICAgICAgICAgICAgXHRcdHJlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8YSByZWZpbmVtZW50LXZhbHVlPVwiJyArIHJlZmluZW1lbnRWYWx1ZS52YWx1ZSArICdcIiBjbGFzcz1cInNlbGVjdGFibGVcIj4nICsgcmVmaW5lbWVudFZhbHVlLmRpc3BsYXlWYWx1ZSArICc8L2E+Jztcblx0ICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdH1cbiAgICAgICAgICAgIFx0XG4gICAgICAgICAgICBcdHZhciBzdGVwSHRtbCA9IHNpemVzSGVhZGVySHRtbCArIHBvcHVsYXJTaXplc0h0bWwgKyAnPGRpdiBjbGFzcz1cInJlZmluZW1lbnRWYWx1ZXMnICsgaGlkZVJlZmluZW1lbnRWYWx1ZXMgKyAnXCI+JyArIHJlZmluZW1lbnRWYWx1ZXNIdG1sICsgJzwvZGl2Pic7XG5cblx0XHRcdFx0aWYgKGhhc1dpZHRocykge1xuXHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnW3N0ZXBdW3JlZmluZW1lbnQ9XCJ3aWR0aFwiXScpLnNob3coKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwXVtyZWZpbmVtZW50PVwid2lkdGhcIl0nKS5oaWRlKCk7XG5cdFx0XHRcdH1cblxuICAgICAgICBcdFx0JHN0ZXAuaHRtbChzdGVwSHRtbCkuc2hvdygpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgXHRcdCRzdGVwLmF0dHIoJ3JlZmluZW1lbnQnLCAnc2l6ZScpO1xuICAgICAgICBcdFx0c2Nyb2xsVG9TdGVwKCRzdGVwKTtcbiAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3VjY2Vzc0NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgXHRvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjayhpbnF1aXJ5UmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgJzAnKTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQtY29udGFpbmVyJykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICAkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LWNvdW50LWNvbnRhaW5lcicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBidWlsZFN0ZXBXaXRoV2lkdGhzKHN0ZXAsIGNhdGVnb3J5SWRQYXJhbWV0ZXIsIGxlbmd0aFBhcmFtZXRlcikge1xuXHR2YXIgY2F0ZWdvcnlJZCA9IGNhdGVnb3J5SWRQYXJhbWV0ZXIgfHwgJ3Jvb3QnO1xuXHQkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LWNvdW50LWNvbnRhaW5lcicpLmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2Vcblx0fSk7XG5cdHZhciAkc3RlcCA9ICRjb250YWluZXIuZmluZCgnW3N0ZXA9XCInICsgc3RlcCArICdcIl0nKTtcblx0aWYgKCRzdGVwLmxlbmd0aCA8IDEpIHtcblx0XHQkY29udGFpbmVyLmZpbmQoJy5zdGVwcycpLmFwcGVuZCgnPGRpdiBzdGVwPVwiJyArIHN0ZXAgKyAnXCI+PC9kaXY+Jyk7XG5cdFx0JHN0ZXAgPSAkY29udGFpbmVyLmZpbmQoJ1tzdGVwPVwiJyArIHN0ZXAgKyAnXCJdJyk7XG5cdH1cblx0XG5cdHZhciByZWZpbmVtZW50VmFsdWVzSHRtbCA9ICcnO1xuXHR2YXIgd2lkdGhUeXBlO1xuXHRmb3IgKHZhciByZWZpbmVtZW50VmFsdWVLZXkgaW4gZGF0YUJ1ZmZlclsnV2lkdGhzQnlMZW5ndGgnXVtsZW5ndGhQYXJhbWV0ZXJdKSB7XG5cdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9IGRhdGFCdWZmZXJbJ1dpZHRoc0J5TGVuZ3RoJ11bbGVuZ3RoUGFyYW1ldGVyXVtyZWZpbmVtZW50VmFsdWVLZXldO1xuXHRcdHZhciByZWZpbmVtZW50VmFsdWVEaXNwbGF5ID0gcmVmaW5lbWVudFZhbHVlID09ICdEJyA/IHJlZmluZW1lbnRWYWx1ZSArICcmbmJzcDs8c3BhbiBjbGFzcz1cIndpZHRoLW5vdGVcIj4oUkVHKTwvc3Bhbj4nIDogcmVmaW5lbWVudFZhbHVlO1xuXHRcdHJlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8YSByZWZpbmVtZW50LXdpZHRoPVwiJyArIHJlZmluZW1lbnRWYWx1ZSArICdcIiBjbGFzcz1cInNlbGVjdGFibGVcIj4nICsgcmVmaW5lbWVudFZhbHVlRGlzcGxheSArICc8L2E+Jztcblx0XHRcblx0XHRpZiAoIXdpZHRoVHlwZSkge1xuXHRcdFx0dmFyIHdpZHRoUGFyc2VkQXNJbnRlZ2VyID0gcGFyc2VJbnQocmVmaW5lbWVudFZhbHVlLCAxMCk7XG5cdFx0XHRcblx0XHRcdGlmICh3aWR0aFBhcnNlZEFzSW50ZWdlciA9PSByZWZpbmVtZW50VmFsdWUpIHtcblx0XHRcdFx0d2lkdGhUeXBlID0gJ3BhbnRzJztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR2YXIgd2lkdGhzSGVhZGVySHRtbDtcblx0dmFyIHdpZHRoVHlwZUxhYmVsO1xuXHRpZiAod2lkdGhUeXBlID09ICdwYW50cycpIHtcblx0XHR3aWR0aFR5cGVMYWJlbCA9ICdJbnNlYW0nO1xuXHR9IGVsc2Uge1xuXHRcdHdpZHRoVHlwZUxhYmVsID0gJ1dpZHRoJztcblx0fVxuXHR3aWR0aHNIZWFkZXJIdG1sID0gJzxoNT5GaWx0ZXIgQnkgJyArIHdpZHRoVHlwZUxhYmVsICsgJzwvaDU+Jztcblx0dmFyIHN0ZXBIdG1sID0gd2lkdGhzSGVhZGVySHRtbCArICc8ZGl2IGNsYXNzPVwicmVmaW5lbWVudFZhbHVlc1wiPicgKyByZWZpbmVtZW50VmFsdWVzSHRtbCArICc8L2Rpdj4nO1xuXHRcblx0JHN0ZXAuaHRtbChzdGVwSHRtbCkuc2hvdygpO1xuXHQkc3RlcC5hdHRyKCdyZWZpbmVtZW50JywgJ3dpZHRoJyk7XG5cdHNjcm9sbFRvU3RlcCgkc3RlcCk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU3RlcFBsYWNlaG9sZGVycyhzdGVwKSB7XG5cdGZvciAodmFyIHN0ZXBJbmRleCA9IHN0ZXA7IHN0ZXBJbmRleCA8IG9wdGlvbnMuQm9waXMuU3RlcENvbmZpZ3VyYXRpb24ubGVuZ3RoOyBzdGVwSW5kZXgrKykge1xuXHRcdHZhciAkc3RlcCA9ICRjb250YWluZXIuZmluZCgnW3N0ZXA9XCInICsgc3RlcEluZGV4ICsgJ1wiXScpO1xuXHRcdGlmICgkc3RlcC5sZW5ndGggPCAxKSB7XG5cdFx0XHQkY29udGFpbmVyLmZpbmQoJy5zdGVwcycpLmFwcGVuZCgnPGRpdiBzdGVwPVwiJyArIHN0ZXBJbmRleCArICdcIj48L2Rpdj4nKTtcblx0XHRcdCRzdGVwID0gJGNvbnRhaW5lci5maW5kKCdbc3RlcD1cIicgKyBzdGVwSW5kZXggKyAnXCJdJyk7XG5cdFx0fVxuXHRcdGJ1aWxkU3RlcFBsYWNlaG9sZGVyKHN0ZXBJbmRleCwgJHN0ZXApO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU3RlcFBsYWNlaG9sZGVyKHN0ZXAsICRzdGVwKSB7XG5cdHZhciBzdGVwQ29uZmlndXJhdGlvbiA9IG9wdGlvbnMuQm9waXMuU3RlcENvbmZpZ3VyYXRpb25bc3RlcF07XG5cblx0aWYgKCEkc3RlcCkge1xuXHRcdHZhciAkc3RlcCA9ICRjb250YWluZXIuZmluZCgnW3N0ZXA9XCInICsgc3RlcCArICdcIl0nKTtcblx0XHRpZiAoJHN0ZXAubGVuZ3RoIDwgMSkge1xuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcuc3RlcHMnKS5hcHBlbmQoJzxkaXYgc3RlcD1cIicgKyBzdGVwICsgJ1wiPjwvZGl2PicpO1xuXHRcdFx0JHN0ZXAgPSAkY29udGFpbmVyLmZpbmQoJ1tzdGVwPVwiJyArIHN0ZXAgKyAnXCJdJyk7XG5cdFx0fVxuXHR9XG5cblx0aWYgKHN0ZXBDb25maWd1cmF0aW9uLlJlZmluZW1lbnQpIHtcblx0XHQkc3RlcC5hdHRyKCdyZWZpbmVtZW50Jywgc3RlcENvbmZpZ3VyYXRpb24uUmVmaW5lbWVudCk7XG5cdH1cblxuXHRpZiAoc3RlcENvbmZpZ3VyYXRpb24gJiYgc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIpIHtcblx0XHR2YXIgc3RlcEhlYWRlckh0bWwgPSAnJztcblx0XHRpZiAoc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIuSGVhZGVyKSB7XG5cdFx0XHRzdGVwSGVhZGVySHRtbCA9ICc8aDUgY2xhc3M9XCJwbGFjZWhvbGRlclwiPicgKyBzdGVwQ29uZmlndXJhdGlvbi5QbGFjZWhvbGRlci5IZWFkZXIgKyAnPC9oNT4nO1xuXHRcdH0gZWxzZSBpZiAoc3RlcENvbmZpZ3VyYXRpb24uSGVhZGVyKSB7XG5cdFx0XHRzdGVwSGVhZGVySHRtbCA9ICc8aDUgY2xhc3M9XCJwbGFjZWhvbGRlclwiPicgKyBzdGVwQ29uZmlndXJhdGlvbi5IZWFkZXIgKyAnPC9oNT4nO1xuXHRcdH1cblxuXHRcdHZhciByZWZpbmVtZW50VmFsdWVzSHRtbCA9ICcnO1xuXHRcdGlmIChzdGVwQ29uZmlndXJhdGlvbi5QbGFjZWhvbGRlci5WYWx1ZXMpIHtcblx0XHRcdGZvciAodmFyIHJlZmluZW1lbnRLZXkgaW4gc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIuVmFsdWVzKSB7XG5cdFx0XHRcdHJlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8YSByZWZpbmVtZW50LXZhbHVlPVwiJyArIHN0ZXBDb25maWd1cmF0aW9uLlBsYWNlaG9sZGVyLlZhbHVlc1tyZWZpbmVtZW50S2V5XSArICdcIiBjbGFzcz1cInBsYWNlaG9sZGVyIHNlbGVjdGFibGVcIj4nICsgc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIuVmFsdWVzW3JlZmluZW1lbnRLZXldICsgJzwvYT4nO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIuVGV4dCkge1xuXHRcdFx0cmVmaW5lbWVudFZhbHVlc0h0bWwgKz0gJzxwIGNsYXNzPVwicGxhY2Vob2xkZXJcIj4nICsgc3RlcENvbmZpZ3VyYXRpb24uUGxhY2Vob2xkZXIuVGV4dCArICc8L3A+Jztcblx0XHR9XG5cdFx0XG5cdFx0aWYgKHN0ZXBDb25maWd1cmF0aW9uLlJlZmluZW1lbnQgPT0gJ3NpemUnKSB7XG5cdFx0XHRyZWZpbmVtZW50VmFsdWVzSHRtbCA9ICc8ZGl2IGNsYXNzPVwicG9wdWxhclNpemVzXCI+PGg2IGNsYXNzPVwicGxhY2Vob2xkZXJcIj5Nb3N0IFBvcHVsYXI8L2g2PicgKyByZWZpbmVtZW50VmFsdWVzSHRtbCArICc8L2Rpdj48YSBjbGFzcz1cInNlZS1tb3JlLXNpemVzIHBsYWNlaG9sZGVyXCI+U2VlIE1vcmUgU2l6ZXM8L2E+Jztcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVmaW5lbWVudFZhbHVlc0h0bWwgPSAnPGRpdiBjbGFzcz1cInJlZmluZW1lbnRWYWx1ZXNcIj4nICsgcmVmaW5lbWVudFZhbHVlc0h0bWwgKyAnPC9kaXY+Jztcblx0XHR9XG5cblx0XHQkc3RlcC5odG1sKHN0ZXBIZWFkZXJIdG1sICsgcmVmaW5lbWVudFZhbHVlc0h0bWwpO1xuXHR9IGVsc2Uge1xuXHRcdCRzdGVwLmh0bWwoJycpLmhpZGUoKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVQcm9kdWN0Q291bnRGb3JDYXRlZ29yeUFuZFNpemUoc3RlcCwgc2VsZWN0ZWRDYXRlZ29yeSwgc2VsZWN0ZWRTaXplKSB7XG5cdCRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQtY29udGFpbmVyJykubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZVxuXHR9KTtcblx0XG5cdCQuYWpheCh7XG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIHVybDogVXJscy5Cb290QmFybkV4cHJlc3MuR2V0U29ydGVkUmVmaW5lbWVudFZhbHVlc0ZvclJlZmluZW1lbnRJZCxcbiAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgY2dpZDogc2VsZWN0ZWRDYXRlZ29yeSxcbiAgICAgICAgICAgIHByZWZuMTogJ2F2YWlsYWJsZVN0b3JlcycsXG4gICAgICAgICAgICBwcmVmdjE6IG9wdGlvbnMuQm9waXMuU2VsZWN0ZWRMb2NhdGlvbnNbMF0uU3RvcmVJZCxcbiAgICAgICAgICAgIHByZWZuMjogJ3NpemUnLFxuICAgICAgICAgICAgcHJlZnYyOiBzZWxlY3RlZFNpemVcbiAgICAgICAgfSxcbiAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5Qcm9kdWN0Q291bnQpIHtcbiAgICAgICAgICAgIFx0JGNvbnRhaW5lci5maW5kKCcucHJvZHVjdC1jb3VudCcpLmh0bWwoZGF0YS5Qcm9kdWN0Q291bnQudG9Mb2NhbGVTdHJpbmcoJ2VuJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG5cdFx0XHRpZiAob3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIFx0b3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2soaW5xdWlyeVJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICRjb250YWluZXIuZmluZCgnLnByb2R1Y3QtY291bnQtY29udGFpbmVyJykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG4gICAgICAgIFx0aWYgKG9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgXHRcbiAgICAgICAgXHQkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LWNvdW50LWNvbnRhaW5lcicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZVNpemVSZWZpbmVtZW50VmFsdWVzSW50b0xlbmd0aEFuZFdpZHRoKHJlZmluZW1lbnRWYWx1ZXMpIHtcblx0dmFyIHNpemVSZWZpbmVtZW50VmFsdWVzTGVuZ3RocyA9IFtdO1xuXHR2YXIgc2l6ZVJlZmluZW1lbnRWYWx1ZXNXaWR0aHMgPSBbXTtcblx0dmFyIHNpemVSZWZpbmVtZW50VmFsdWVzV2lkdGhzQnlMZW5ndGggPSBbXTtcblx0XG5cdGlmIChyZWZpbmVtZW50VmFsdWVzKSB7XG5cdFx0Zm9yICh2YXIgcmVmaW5lbWVudEtleSBpbiByZWZpbmVtZW50VmFsdWVzKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gcmVmaW5lbWVudFZhbHVlc1tyZWZpbmVtZW50S2V5XTtcblx0XHRcdFxuXHRcdFx0dmFyIHNwbGl0UmVmaW5lbWVudFZhbHVlID0gcmVmaW5lbWVudFZhbHVlLnZhbHVlLnNwbGl0KCcgJyk7XG5cdFx0XHRpZiAoc3BsaXRSZWZpbmVtZW50VmFsdWUgJiYgJ2xlbmd0aCcgaW4gc3BsaXRSZWZpbmVtZW50VmFsdWUgJiYgc3BsaXRSZWZpbmVtZW50VmFsdWUubGVuZ3RoID4gMSkge1xuXHRcdFx0XHR2YXIgc2l6ZVJlZmluZW1lbnRWYWx1ZVdpZHRoID0gc3BsaXRSZWZpbmVtZW50VmFsdWUucG9wKCk7XG5cdFx0XHRcdHZhciBzaXplUmVmaW5lbWVudFZhbHVlTGVuZ3RoID0gc3BsaXRSZWZpbmVtZW50VmFsdWUuam9pbignICcpO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCFzaXplUmVmaW5lbWVudFZhbHVlc1dpZHRoc0J5TGVuZ3RoW3NpemVSZWZpbmVtZW50VmFsdWVMZW5ndGhdKSB7XG5cdFx0XHRcdFx0c2l6ZVJlZmluZW1lbnRWYWx1ZXNXaWR0aHNCeUxlbmd0aFtzaXplUmVmaW5lbWVudFZhbHVlTGVuZ3RoXSA9IFtdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHNpemVSZWZpbmVtZW50VmFsdWVzV2lkdGhzQnlMZW5ndGhbc2l6ZVJlZmluZW1lbnRWYWx1ZUxlbmd0aF0ucHVzaChzaXplUmVmaW5lbWVudFZhbHVlV2lkdGgpO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKHNpemVSZWZpbmVtZW50VmFsdWVzTGVuZ3Rocy5pbmRleE9mKHNpemVSZWZpbmVtZW50VmFsdWVMZW5ndGgpIDwgMCkge1xuXHRcdFx0XHRcdHNpemVSZWZpbmVtZW50VmFsdWVzTGVuZ3Rocy5wdXNoKHNpemVSZWZpbmVtZW50VmFsdWVMZW5ndGgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoc2l6ZVJlZmluZW1lbnRWYWx1ZXNXaWR0aHMuaW5kZXhPZihzaXplUmVmaW5lbWVudFZhbHVlV2lkdGgpIDwgMCkge1xuXHRcdFx0XHRcdHNpemVSZWZpbmVtZW50VmFsdWVzV2lkdGhzLnB1c2goc2l6ZVJlZmluZW1lbnRWYWx1ZVdpZHRoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2l6ZVJlZmluZW1lbnRWYWx1ZXNMZW5ndGhzLnB1c2gocmVmaW5lbWVudFZhbHVlLnZhbHVlKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdHZhciBwYXlsb2FkID0ge1xuXHRcdExlbmd0aHM6IHNpemVSZWZpbmVtZW50VmFsdWVzTGVuZ3Rocyxcblx0XHRXaWR0aHM6IHNpemVSZWZpbmVtZW50VmFsdWVzV2lkdGhzLFxuXHRcdFdpZHRoc0J5TGVuZ3RoOiBzaXplUmVmaW5lbWVudFZhbHVlc1dpZHRoc0J5TGVuZ3RoXG5cdH1cblx0XG5cdHJldHVybiBwYXlsb2FkO1xufVxuXG5mdW5jdGlvbiBzY3JvbGxUb1N0ZXAoJHN0ZXApIHtcblx0JGNvbnRhaW5lci5maW5kKCcubW9kYWwtYm9keScpLmFuaW1hdGUoe1xuXHRcdHNjcm9sbFRvcDogJHN0ZXAucG9zaXRpb24oKS50b3Bcblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlcicpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xudmFyIHRlbXBsYXRlcztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyLCBhZGRyZXNzRGF0YSkge1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXHRkYXRhQnVmZmVyID0gJC5leHRlbmQoe30sIGFkZHJlc3NEYXRhKTtcblxuXHRpZiAoYWRkcmVzc0RhdGEgJiYgYWRkcmVzc0RhdGEuJGZpZWxkICYmIGFkZHJlc3NEYXRhLiRmb3JtKSB7XG5cdFx0dGVtcGxhdGVzID0ge307XG5cdFx0dGVtcGxhdGVzLmNvbnRhaW5lciA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3MtYXV0b2NvbXBsZXRlLWNvbnRhaW5lcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0XHR0ZW1wbGF0ZXMuYWRkcmVzcyA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3MtYXV0b2NvbXBsZXRlLWl0ZW0nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cblx0XHR2YXIgYWRkcmVzc1N1Z2dlc3Rpb25zSHRtbCA9ICcnO1xuXHRcdGlmIChhZGRyZXNzRGF0YSAmJiBhZGRyZXNzRGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGFkZHJlc3NEYXRhLklucXVpcnlSZXN1bHQuc3VnZ2VzdGlvbnMgJiYgYWRkcmVzc0RhdGEuSW5xdWlyeVJlc3VsdC5zdWdnZXN0aW9ucy5sZW5ndGggPiAwKSB7XG5cdFx0XHRmb3IgKHZhciBhZGRyZXNzU3VnZ2VzdGlvbktleSBpbiBhZGRyZXNzRGF0YS5JbnF1aXJ5UmVzdWx0LnN1Z2dlc3Rpb25zKSB7XG5cdFx0XHRcdHZhciBhZGRyZXNzU3VnZ2VzdGlvbiA9IGFkZHJlc3NEYXRhLklucXVpcnlSZXN1bHQuc3VnZ2VzdGlvbnNbYWRkcmVzc1N1Z2dlc3Rpb25LZXldO1xuXHRcdFx0XHRhZGRyZXNzU3VnZ2VzdGlvbnNIdG1sICs9IHRlbXBsYXRlcy5hZGRyZXNzKHsgQWRkcmVzczogYnVpbGRBZGRyZXNzSHRtbEZyb21BZGRyZXNzT2JqZWN0KEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuQnVpbGRBZGRyZXNzT2JqZWN0RnJvbUFkZHJlc3NBdXRvY29tcGxldGVTdWdnZXN0aW9uKGFkZHJlc3NTdWdnZXN0aW9uKSkgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyICRmaWVsZENvbnRhaW5lciA9IGFkZHJlc3NEYXRhLiRmaWVsZC5wYXJlbnQoKTtcblx0XHRpZiAoJGZpZWxkQ29udGFpbmVyLmZpbmQoJy5hZGRyZXNzLWF1dG9jb21wbGV0ZS1kaWFsb2cnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkZmllbGRDb250YWluZXIuZmluZCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdH1cblxuXHRcdHZhciBhZGRyZXNzU3VnZ2VzdGlvbnNDb250YWluZXJIdG1sID0gdGVtcGxhdGVzLmNvbnRhaW5lcih7IEFkZHJlc3NlczogYWRkcmVzc1N1Z2dlc3Rpb25zSHRtbCB9KTtcblx0XHQkZmllbGRDb250YWluZXIucHJlcGVuZChhZGRyZXNzU3VnZ2VzdGlvbnNDb250YWluZXJIdG1sKTtcblxuXHRcdGFkZHJlc3NEYXRhLiRmb3JtLm9mZignY2xpY2suQWRkcmVzc0F1dG9jb21wbGV0ZVNlbGVjdCcpLm9uKCdjbGljay5BZGRyZXNzQXV0b2NvbXBsZXRlU2VsZWN0JywgJy5hZGRyZXNzLWF1dG9jb21wbGV0ZS1kaWFsb2cgbGknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblxuXHRcdFx0YWRkcmVzc0RhdGEuJGZvcm0uZmluZCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2V0QWRkcmVzc0Zyb21BZGRyZXNzQXV0b2NvbXBsZXRlJywge1xuXHRcdFx0XHQkZm9ybTogYWRkcmVzc0RhdGEuJGZvcm0sXG5cdFx0XHRcdCRmaWVsZDogYWRkcmVzc0RhdGEuJGZpZWxkLFxuXHRcdFx0XHRBZGRyZXNzOiBBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLkJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbihhZGRyZXNzRGF0YS5JbnF1aXJ5UmVzdWx0LnN1Z2dlc3Rpb25zWyR0aGlzLmluZGV4KCldKVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkFkZHJlc3NBdXRvY29tcGxldGVDbG9zZScpLm9uKCdjbGljay5BZGRyZXNzQXV0b2NvbXBsZXRlQ2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0dmFyICR0YXJnZXQgPSAkKGV2ZW50LmN1cnJlbnRUYXJnZXQpO1xuXG5cdFx0XHRpZiAoJHRhcmdldC5jbG9zZXN0KCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykubGVuZ3RoID09IDApIHtcblx0XHRcdFx0JCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWRkcmVzc0h0bWxGcm9tQWRkcmVzc09iamVjdChhZGRyZXNzT2JqZWN0KSB7XG5cdHZhciBhZGRyZXNzQXJyYXkgPSBbXTtcblx0aWYgKGFkZHJlc3NPYmplY3QuUHJpbWFyeUxpbmUpIHtcblx0XHRhZGRyZXNzQXJyYXlbYWRkcmVzc0FycmF5Lmxlbmd0aF0gPSBhZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lO1xuXHR9XG5cdGlmIChhZGRyZXNzT2JqZWN0LkNpdHkgfHwgYWRkcmVzc09iamVjdC5TdGF0ZUNvZGUgfHwgYWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlKSB7XG5cdFx0dmFyIGFkZHJlc3NMaW5lID0gJyc7XG5cdFx0aWYgKGFkZHJlc3NPYmplY3QuQ2l0eSkge1xuXHRcdFx0YWRkcmVzc0xpbmUgKz0gYWRkcmVzc09iamVjdC5DaXR5ICsgJywgJztcblx0XHR9XG5cdFx0aWYgKGFkZHJlc3NPYmplY3QuU3RhdGVDb2RlKSB7XG5cdFx0XHRhZGRyZXNzTGluZSArPSBhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZTtcblx0XHRcdGlmIChhZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUpIHtcblx0XHRcdFx0YWRkcmVzc0xpbmUgKz0gJyAnO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoYWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlKSB7XG5cdFx0XHRhZGRyZXNzTGluZSArPSBhZGRyZXNzT2JqZWN0LlBvc3RhbENvZGU7XG5cdFx0fVxuXG5cdFx0YWRkcmVzc0FycmF5W2FkZHJlc3NBcnJheS5sZW5ndGhdID0gYWRkcmVzc0xpbmU7XG5cdH1cblxuXHRyZXR1cm4gYWRkcmVzc0FycmF5LmpvaW4oJzxici8+Jyk7XG59XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xudmFyIHRlbXBsYXRlcztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyLCBhZGRyZXNzVHlwZSwgYWRkcmVzc0RhdGEpIHtcblx0b3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRzdWNjZXNzQ2FsbGJhY2s6IG51bGwsXG5cdFx0ZXJyb3JDYWxsYmFjazogbnVsbFxuXHR9LCBvcHRpb25zUGFyYW1ldGVyKTtcblx0ZGF0YUJ1ZmZlciA9ICQuZXh0ZW5kKHt9LCBhZGRyZXNzRGF0YSk7XG5cdHRlbXBsYXRlcyA9IHt9O1xuXHR0ZW1wbGF0ZXMuYWRkcmVzcyA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3MtdmVyaWZpY2F0aW9uLWFkZHJlc3MnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cblx0ZGlhbG9nLm9wZW4oe1xuXHRcdGh0bWw6ICQoJyNkaWFsb2ctYWRkcmVzcy12ZXJpZmljYXRpb24nKS5odG1sKCksXG5cdFx0b3B0aW9uczoge1xuXHRcdFx0ZGlhbG9nQ2xhc3M6ICdkaWFsb2ctYWRkcmVzcy12ZXJpZmljYXRpb24nLFxuXHRcdFx0d2lkdGg6IDMyMCxcblx0XHRcdGRyYWdnYWJsZTogZmFsc2UsXG5cdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0b3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciAkYWRkcmVzc2VzID0gJHRoaXMuZmluZCgnLmFkZHJlc3NlcycpO1xuXHRcdFx0XHQkYWRkcmVzc2VzLmh0bWwoJycpO1xuXHRcdFx0XHQkdGhpcy5jbG9zZXN0KCcudWktZGlhbG9nJykuYXR0cignc3RhdHVzJywgZGF0YUJ1ZmZlci5TdGF0dXMpO1xuXG5cdFx0XHRcdHZhciBhZGRyZXNzUmVjb21tZW5kZWRIdG1sO1xuXHRcdFx0XHRpZiAoZGF0YUJ1ZmZlci5TdGF0dXMgPT0gJ2RlbGl2ZXJhYmxlJyAmJiAhZGF0YUJ1ZmZlci5NYXRjaCkge1xuXHRcdFx0XHRcdGFkZHJlc3NSZWNvbW1lbmRlZEh0bWwgPSB0ZW1wbGF0ZXMuYWRkcmVzcyh7XG5cdFx0XHRcdFx0XHRBZGRyZXNzVHlwZTogYWRkcmVzc1R5cGUsXG5cdFx0XHRcdFx0XHRBY3Rpb246ICdyZWNvbW1lbmRlZCcsXG5cdFx0XHRcdFx0XHRDbGFzczogJ3NlbGVjdGVkJyxcblx0XHRcdFx0XHRcdENoZWNrZWQ6ICdjaGVja2VkJyxcblx0XHRcdFx0XHRcdEhlYWRlcjogJ1JlY29tbWVuZGVkIEFkZHJlc3MnLFxuXHRcdFx0XHRcdFx0QWRkcmVzczogYnVpbGRBZGRyZXNzSHRtbEZyb21BZGRyZXNzT2JqZWN0KGRhdGFCdWZmZXIuQWRkcmVzc1ZlcmlmaWVkKVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGFkZHJlc3NFbnRlcmVkSHRtbDtcblx0XHRcdFx0YWRkcmVzc0VudGVyZWRIdG1sID0gdGVtcGxhdGVzLmFkZHJlc3Moe1xuXHRcdFx0XHRcdEFkZHJlc3NUeXBlOiBhZGRyZXNzVHlwZSxcblx0XHRcdFx0XHRBY3Rpb246ICdlbnRlcmVkJyxcblx0XHRcdFx0XHRDbGFzczogIWFkZHJlc3NSZWNvbW1lbmRlZEh0bWwgPyAnc2VsZWN0ZWQnIDogJycsXG5cdFx0XHRcdFx0Q2hlY2tlZDogIWFkZHJlc3NSZWNvbW1lbmRlZEh0bWwgPyAnY2hlY2tlZCcgOiAnJyxcblx0XHRcdFx0XHRIZWFkZXI6ICdBZGRyZXNzIGFzIEVudGVyZWQnLFxuXHRcdFx0XHRcdEFkZHJlc3M6IGJ1aWxkQWRkcmVzc0h0bWxGcm9tQWRkcmVzc09iamVjdChkYXRhQnVmZmVyLkFkZHJlc3NPcmlnaW5hbClcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aWYgKGFkZHJlc3NSZWNvbW1lbmRlZEh0bWwpIHtcblx0XHRcdFx0XHQkYWRkcmVzc2VzLmFwcGVuZChhZGRyZXNzUmVjb21tZW5kZWRIdG1sKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoYWRkcmVzc0VudGVyZWRIdG1sKSB7XG5cdFx0XHRcdFx0JGFkZHJlc3Nlcy5hcHBlbmQoYWRkcmVzc0VudGVyZWRIdG1sKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCR0aGlzLmZpbmQoJy5hZGRyZXNzLXR5cGUnKS50ZXh0KGFkZHJlc3NUeXBlKTtcblx0XHRcdFx0JHRoaXMuZmluZCgnaDM6dmlzaWJsZScpLmZvY3VzKCk7IC8vIEFEQSBjb21wbGlhbmNlIC0gYWRkIGZvY3VzIHRvIGZpcnN0IGVsZW1lbnQgaW4gbW9kYWwgdG8gaGVscCBzY3JlZW4gcmVhZGVyc1xuXHRcdFx0XHRcblx0XHRcdFx0JHRoaXMub2ZmKCdjbGljay5BZGRyZXNzU2VsZWN0Jykub24oJ2NsaWNrLkFkZHJlc3NTZWxlY3QnLCAnLmFkZHJlc3MtY29udGFpbmVyIC5yYWRpby1sYXJnZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHR2YXIgJGFkZHJlc3NDb250YWluZXIgPSAkKHRoaXMpLmNsb3Nlc3QoJy5hZGRyZXNzLWNvbnRhaW5lcicpO1xuXG5cdFx0XHRcdFx0JHRoaXMuZmluZCgnLmFkZHJlc3MtY29udGFpbmVyJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NDb250YWluZXIuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NDb250YWluZXIuZmluZCgnaW5wdXQnKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suQWRkcmVzc1VzZScpLm9uKCdjbGljay5BZGRyZXNzVXNlJywgJy5hZGRyZXNzLXVzZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHR2YXIgYWRkcmVzc1RvVXNlID0gJCh0aGlzKS5jbG9zZXN0KCcuYWRkcmVzcy1jb250YWluZXInKS5maW5kKCdpbnB1dCcpLnZhbCgpO1xuXHRcdFx0XHRcdHZhciBhZGRyZXNzT2JqZWN0O1xuXHRcdFx0XHRcdGlmIChhZGRyZXNzVG9Vc2UgPT0gJ3JlY29tbWVuZGVkJykge1xuXHRcdFx0XHRcdFx0YWRkcmVzc09iamVjdCA9IGRhdGFCdWZmZXIuQWRkcmVzc1ZlcmlmaWVkO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoYWRkcmVzc1RvVXNlID09ICdlbnRlcmVkJykge1xuXHRcdFx0XHRcdFx0YWRkcmVzc09iamVjdCA9IGRhdGFCdWZmZXIuQWRkcmVzc09yaWdpbmFsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChhZGRyZXNzT2JqZWN0KSB7XG5cdFx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nLCAkLmV4dGVuZChhZGRyZXNzT2JqZWN0LCB7IEFkZHJlc3NUeXBlOiBhZGRyZXNzVHlwZSB9KSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCR0aGlzLmRpYWxvZygnY2xvc2UnKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0JHRoaXMub2ZmKCdjbGljay5BZGRyZXNzQ29udGludWUnKS5vbignY2xpY2suQWRkcmVzc0NvbnRpbnVlJywgJy5hZGRyZXNzLWNvbnRpbnVlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbicsICQuZXh0ZW5kKGRhdGFCdWZmZXIuQWRkcmVzc09yaWdpbmFsLCB7IEFkZHJlc3NUeXBlOiBhZGRyZXNzVHlwZSB9KSk7XG5cdFx0XHRcdFx0JHRoaXMuZGlhbG9nKCdjbG9zZScpO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0XG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suQWRkcmVzc0VkaXQnKS5vbignY2xpY2suQWRkcmVzc0VkaXQnLCAnLmFkZHJlc3MtZWRpdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHQkdGhpcy5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHRcdFx0dmFyICRmb2N1c0VsZW1lbnQgPSAkKCcjYmlsbGluZ0FkZHJlc3NGb3JtJykuZmluZCgnaW5wdXRbbmFtZT1cImR3ZnJtX2JpbGxpbmdhZGRyZXNzX2FkZHJlc3MxXCJdJyk7XG5cdFx0XHRcdFx0aWYgKGFkZHJlc3NUeXBlID09ICdzaGlwcGluZycpIHtcblx0XHRcdFx0XHRcdCRmb2N1c0VsZW1lbnQgPSAkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpLmZpbmQoJ2lucHV0W25hbWU9XCJkd2ZybV9zaGlwcGluZ2FkZHJlc3NfYWRkcmVzczFcIl0nKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JGZvY3VzRWxlbWVudC5mb2N1cygpO1xuXHRcdFx0XHR9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suU2VsZWN0QWRkcmVzcycpO1xuXHRcdFx0XHQkdGhpcy5vZmYoJ2NsaWNrLlVzZUVudGVyZWRBZGRyZXNzJyk7XG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suVXNlUmVjb21tZW5kZWRBZGRyZXNzJyk7XG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suRWRpdFNoaXBwaW5nQWRkcmVzcycpO1xuICAgICAgICAgICAgfVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWRkcmVzc0h0bWxGcm9tQWRkcmVzc09iamVjdChhZGRyZXNzT2JqZWN0KSB7XG5cdHZhciBhZGRyZXNzQXJyYXkgPSBbXTtcblx0aWYgKGFkZHJlc3NPYmplY3QuUHJpbWFyeUxpbmUpIHtcblx0XHRhZGRyZXNzQXJyYXlbYWRkcmVzc0FycmF5Lmxlbmd0aF0gPSBhZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lO1xuXHR9XG5cdGlmIChhZGRyZXNzT2JqZWN0LlNlY29uZGFyeUxpbmUpIHtcblx0XHRhZGRyZXNzQXJyYXlbYWRkcmVzc0FycmF5Lmxlbmd0aF0gPSBhZGRyZXNzT2JqZWN0LlNlY29uZGFyeUxpbmU7XG5cdH1cblx0aWYgKGFkZHJlc3NPYmplY3QuQ2l0eSB8fCBhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSB8fCBhZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUpIHtcblx0XHR2YXIgYWRkcmVzc0xpbmUgPSAnJztcblx0XHRpZiAoYWRkcmVzc09iamVjdC5DaXR5KSB7XG5cdFx0XHRhZGRyZXNzTGluZSArPSBhZGRyZXNzT2JqZWN0LkNpdHkgKyAnLCAnO1xuXHRcdH1cblx0XHRpZiAoYWRkcmVzc09iamVjdC5TdGF0ZUNvZGUpIHtcblx0XHRcdGFkZHJlc3NMaW5lICs9IGFkZHJlc3NPYmplY3QuU3RhdGVDb2RlO1xuXHRcdFx0aWYgKGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSkge1xuXHRcdFx0XHRhZGRyZXNzTGluZSArPSAnICc7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChhZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUpIHtcblx0XHRcdGFkZHJlc3NMaW5lICs9IGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZTtcblx0XHR9XG5cblx0XHRhZGRyZXNzQXJyYXlbYWRkcmVzc0FycmF5Lmxlbmd0aF0gPSBhZGRyZXNzTGluZTtcblx0fVxuXG5cdHJldHVybiBhZGRyZXNzQXJyYXkuam9pbignPGJyLz4nKTtcbn1cblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBwcm9ncmVzcyA9IHJlcXVpcmUoJy4vcHJvZ3Jlc3MnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbnZhciBjdXJyZW50UmVxdWVzdHMgPSBbXTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBBamF4IHJlcXVlc3QgdG8gZ2V0IGpzb24gcmVzcG9uc2VcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gYXN5bmMgIEFzeW5jaHJvbm91cyBvciBub3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgVVJJIGZvciB0aGUgcmVxdWVzdFxuICogQHBhcmFtIHtPYmplY3R9IGRhdGEgTmFtZS9WYWx1ZSBwYWlyIGRhdGEgcmVxdWVzdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuICovXG52YXIgZ2V0SnNvbiA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgb3B0aW9ucy51cmwgPSB1dGlsLnRvQWJzb2x1dGVVcmwob3B0aW9ucy51cmwpO1xuICAgIC8vIHJldHVybiBpZiBubyB1cmwgZXhpc3RzIG9yIHVybCBtYXRjaGVzIGEgY3VycmVudCByZXF1ZXN0XG4gICAgaWYgKCFvcHRpb25zLnVybCB8fCBjdXJyZW50UmVxdWVzdHNbb3B0aW9ucy51cmxdKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjdXJyZW50UmVxdWVzdHNbb3B0aW9ucy51cmxdID0gdHJ1ZTtcblxuICAgIC8vIG1ha2UgdGhlIHNlcnZlciBjYWxsXG4gICAgJC5hamF4KHtcbiAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgdXJsOiBvcHRpb25zLnVybCxcbiAgICAgICAgYXN5bmM6ICh0eXBlb2Ygb3B0aW9ucy5hc3luYyA9PT0gJ3VuZGVmaW5lZCcgfHwgb3B0aW9ucy5hc3luYyA9PT0gbnVsbCkgPyB0cnVlIDogb3B0aW9ucy5hc3luYyxcbiAgICAgICAgZGF0YTogb3B0aW9ucy5kYXRhIHx8IHt9XG4gICAgfSlcbiAgICAvLyBzdWNjZXNzXG4gICAgLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmIChvcHRpb25zLmNhbGxiYWNrKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLy8gZmFpbGVkXG4gICAgLmZhaWwoZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cykge1xuICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmNhbGxiYWNrKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAvLyBleGVjdXRlZCBvbiBzdWNjZXNzIG9yIGZhaWxcbiAgICAuYWx3YXlzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVtb3ZlIGN1cnJlbnQgcmVxdWVzdCBmcm9tIGhhc2hcbiAgICAgICAgaWYgKGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjdXJyZW50UmVxdWVzdHNbb3B0aW9ucy51cmxdO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBhamF4IHJlcXVlc3QgdG8gbG9hZCBodG1sIHJlc3BvbnNlIGluIGEgZ2l2ZW4gY29udGFpbmVyXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsIFVSSSBmb3IgdGhlIHJlcXVlc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIE5hbWUvVmFsdWUgcGFpciBkYXRhIHJlcXVlc3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrICBDYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSB0YXJnZXQgU2VsZWN0b3Igb3IgZWxlbWVudCB0aGF0IHdpbGwgcmVjZWl2ZSBjb250ZW50XG4gKi9cbnZhciBsb2FkID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zLnVybCA9IHV0aWwudG9BYnNvbHV0ZVVybChvcHRpb25zLnVybCk7XG4gICAgLy8gcmV0dXJuIGlmIG5vIHVybCBleGlzdHMgb3IgdXJsIG1hdGNoZXMgYSBjdXJyZW50IHJlcXVlc3RcbiAgICBpZiAoIW9wdGlvbnMudXJsIHx8IGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0gPSB0cnVlO1xuXG4gICAgLy8gbWFrZSB0aGUgc2VydmVyIGNhbGxcbiAgICAkLmFqYXgoe1xuICAgICAgICBkYXRhVHlwZTogJ2h0bWwnLFxuICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChvcHRpb25zLnVybCwgJ2Zvcm1hdCcsICdhamF4JyksXG4gICAgICAgIGRhdGE6IG9wdGlvbnMuZGF0YSxcbiAgICAgICAgeGhyRmllbGRzOiB7XG4gICAgICAgICAgICB3aXRoQ3JlZGVudGlhbHM6IHRydWVcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIC8vIHN1Y2Nlc3NcbiAgICAgICAgaWYgKG9wdGlvbnMudGFyZ2V0KSB7XG4gICAgICAgICAgICAkKG9wdGlvbnMudGFyZ2V0KS5lbXB0eSgpLmh0bWwocmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmNhbGxiYWNrKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLmZhaWwoZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cykge1xuICAgICAgICAvLyBmYWlsZWRcbiAgICAgICAgaWYgKHRleHRTdGF0dXMgPT09ICdwYXJzZXJlcnJvcicpIHtcbiAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQkFEX1JFU1BPTlNFKTtcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zLmNhbGxiYWNrKG51bGwsIHRleHRTdGF0dXMpO1xuICAgIH0pXG4gICAgLmFsd2F5cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHByb2dyZXNzLmhpZGUoKTtcbiAgICAgICAgLy8gcmVtb3ZlIGN1cnJlbnQgcmVxdWVzdCBmcm9tIGhhc2hcbiAgICAgICAgaWYgKGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjdXJyZW50UmVxdWVzdHNbb3B0aW9ucy51cmxdO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5leHBvcnRzLmdldEpzb24gPSBnZXRKc29uO1xuZXhwb3J0cy5sb2FkID0gbG9hZDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgYWxlcnQgd2lkZ2V0XG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICB2YXIgdHlwZSA9IG9wdGlvbnMudHlwZSA/IG9wdGlvbnMudHlwZSA6ICdhbGVydC1wcmltYXJ5JztcbiAgICB2YXIgdGltZXIgPSBvcHRpb25zLnRpbWVyID8gb3B0aW9ucy50aW1lciA6IDUwMDA7XG4gICAgdmFyIGFsZXJ0RWxlbWVudCA9ICc8ZGl2IGNsYXNzPVwiYWxlcnQgJyArIHR5cGUgKyAnXCI+PGRpdiBjbGFzcz1cImFsZXJ0LWNvbnRlbnRcIj4nICsgb3B0aW9ucy5jb250ZW50ICsgJzwvZGl2PjwvZGl2Pic7XG5cbiAgICAkKCdib2R5JykuYXBwZW5kKGFsZXJ0RWxlbWVudCkuZmFkZUluKCdzbG93Jyk7XG4gICAgdmFyIGFsZXJ0VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAkKCcuYWxlcnQnKS5mYWRlT3V0KCdzbG93JykucmVtb3ZlKCk7XG4gICAgfSwgdGltZXIpO1xuXG4gICAgJCgnYm9keScpLm9uKCdjbGljaycsICcuYWxlcnQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgJCh0aGlzKS5mYWRlT3V0KCdzbG93JykucmVtb3ZlKCk7XG4gICAgfSk7XG59O1xuIiwiLyoqXG4gKiAgICAoYykgMjAwOS0yMDE0IERlbWFuZHdhcmUgSW5jLlxuICogICAgU3ViamVjdCB0byBzdGFuZGFyZCB1c2FnZSB0ZXJtcyBhbmQgY29uZGl0aW9uc1xuICogICAgRm9yIGFsbCBkZXRhaWxzIGFuZCBkb2N1bWVudGF0aW9uOlxuICogICAgaHR0cHM6Ly9iaXRidWNrZXQuY29tL2RlbWFuZHdhcmUvc2l0ZWdlbmVzaXNcbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb3VudHJpZXMgPSByZXF1aXJlKCcuL2NvdW50cmllcycpLFxuICAgIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyksXG4gICAgbWluaWNhcnQgPSByZXF1aXJlKCcuL21pbmljYXJ0JyksXG4gICAgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpLFxuICAgIHJhdGluZyA9IHJlcXVpcmUoJy4vcmF0aW5nJyksXG4gICAgc2VhcmNocGxhY2Vob2xkZXIgPSByZXF1aXJlKCcuL3NlYXJjaHBsYWNlaG9sZGVyJyksXG4gICAgLy90b29sdGlwID0gcmVxdWlyZSgnLi90b29sdGlwJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIHZhbGlkYXRvciA9IHJlcXVpcmUoJy4vdmFsaWRhdG9yJyksXG4gICAgdGxzID0gcmVxdWlyZSgnLi90bHMnKSxcbiAgXHRUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKSxcbiAgXHRhamF4ID0gcmVxdWlyZSgnLi9hamF4JyksXG4gIFx0cm90YXRlM2QgPSByZXF1aXJlKCcuL3Byb2R1Y3RSb3RhdGUzZC5qcycpLFxuICAgIGNvdW50X2Rvd24gPSByZXF1aXJlKCcuL2NvdW50ZG93bicpLFxuICAgIGxhenlsb2FkUGFnZUVsZW1lbnRzID0gcmVxdWlyZSgnLi9sYXp5bG9hZFBhZ2VFbGVtZW50cycpLFxuICAgIGNvb2tpZU5vdGlmaWNhdGlvbiA9IHJlcXVpcmUoJy4vY29tcG9uZW50cy9Db29raWVOb3RpZmljYXRpb24nKSxcbiAgICBuYXZpZ2F0aW9uID0gcmVxdWlyZSgnLi9jb21wb25lbnRzL05hdmlnYXRpb25Db250cm9sbGVyJyksXG4gICAgZW1haWxGb3JtID0gcmVxdWlyZSgnLi9jb21wb25lbnRzL0VtYWlsRm9ybScpLFxuXHRzbGlja0hlbHBlcnMgPSByZXF1aXJlKCcuL3NsaWNrU2xpZGVySGVscGVycycpLFxuXHRxdWFudGl0eVN0ZXBwZXIgPSByZXF1aXJlKCcuL3F1YW50aXR5U3RlcHBlcicpLFxuXHR3aXNobGlzdCA9IHJlcXVpcmUoJy4vd2lzaGxpc3QnKSxcblx0bG9naW5EaWFsb2cgPSByZXF1aXJlKCcuL2xvZ2luRGlhbG9nJyksXG5cdGxvZ2luID0gcmVxdWlyZSgnLi9sb2dpbicpLFxuXHRyZWdpc3RlciA9IHJlcXVpcmUoJy4vcmVnaXN0ZXInKSxcblx0YWxlcnQgPSByZXF1aXJlKCcuL2FsZXJ0JyksXG5cdEdsb2JhbGUgPSByZXF1aXJlKCcuL2NvbXBvbmVudHMvR2xvYmFsZScpLFxuXHRzZWFyY2hiYXIgPSByZXF1aXJlKCcuL3NlYXJjaGJhcicpLFxuXHRzbGlkZXJzID0gcmVxdWlyZSgnLi9zbGlkZXJzJyk7XG5cbnZhciBFbWFpbFNpZ251cCA9IHJlcXVpcmUoJy4vY29tcG9uZW50cy9FbWFpbFNpZ251cCcpO1xudmFyIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlIZWxwZXIgPSByZXF1aXJlKCcuL2hlbHBlcnMvR2lmdENhcmRCYWxhbmNlSW5xdWlyeUhlbHBlcicpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFJlcXVlc3RIZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9oZWxwZXJzL1JlcXVlc3RIZWxwZXInKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbi8vIGlmIGpRdWVyeSBoYXMgbm90IGJlZW4gbG9hZGVkLCBsb2FkIGZyb20gZ29vZ2xlIGNkblxuaWYgKCF3aW5kb3cualF1ZXJ5KSB7XG4gICAgdmFyIHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICBzLnNldEF0dHJpYnV0ZSgnc3JjJywgJ2h0dHBzOi8vYWpheC5nb29nbGVhcGlzLmNvbS9hamF4L2xpYnMvanF1ZXJ5LzEuNy4xL2pxdWVyeS5taW4uanMnKTtcbiAgICBzLnNldEF0dHJpYnV0ZSgndHlwZScsICd0ZXh0L2phdmFzY3JpcHQnKTtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdLmFwcGVuZENoaWxkKHMpO1xufVxuXG5yZXF1aXJlKCcuL2pxdWVyeS1leHQnKSgpO1xucmVxdWlyZSgnLi9jb29raWVwcml2YWN5JykoKTtcbnJlcXVpcmUoJy4vY2FwdGNoYScpKCk7XG5yZXF1aXJlKCcuL3dhdGVybWFyaycpKCk7XG5cbnZhciBkYXRhQnVmZmVyID0ge307XG52YXIgc2l0ZU5hbWU7XG5cbnZhciAkc2xpZGVyTW9iaWxlO1xudmFyICRuYXZTZWNvbmRhcnk7XG52YXIgJG5hdlV0aWxpdGllcztcbnZhciAkbmF2VWw7XG52YXIgJHRvcEJhbm5lckJhcjtcbnZhciAkdG9wQmFubmVyQmFySW5uZXI7XG52YXIgJG5hdmlnYXRpb247XG52YXIgJHRvcEJhbm5lcklubmVyTGlua3M7XG52YXIgJHNlbGVjdFNvcnQ7XG52YXIgJHNlY29uZGFyeUhlYWQ7XG52YXIgJHNlYXJjaFJlc3VsdENvbnRhaW5lcjtcbnZhciAkcHJvZHVjdENvbnRhaW5lckltYWdlO1xudmFyICRwcm9kdWN0RGV0YWlsO1xudmFyICRzZWN0aW9uQ2hlY2tvdXQ7XG52YXIgJG1haW5Jbm5lckFsdDtcbnZhciAkc2VjdGlvbkVycm9yRmlndXJlO1xudmFyICRzZWN0aW9uRXJyb3JCb3g7XG52YXIgJGZvb3Rlck1lbnVJdGVtcztcbnZhciAkcHJvbW9NZXNzYWdlcztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcblx0Y29va2llTm90aWZpY2F0aW9uLmluaXRpYWxpemUoKTtcblx0dmFyIGNvbnRyb2xLZXlzID0gWyc4JywgJzEzJywgJzQ2JywgJzQ1JywgJzM2JywgJzM1JywgJzM4JywgJzM3JywgJzQwJywgJzM5J107XG5cdHZhciAkd2luID0gJCh3aW5kb3cpO1xuXHR2YXIgJGRvYyA9ICQoZG9jdW1lbnQpO1xuXHQkZG9jLm9uKCdhcHAucmVzaXplJywgZnVuY3Rpb24gKCkge1xuXHRcdHJlc2l6ZURldmljZUhlbHBlcigpO1xuXHR9KTtcblx0JHdpbi5vbignbG9hZCByZXNpemUnLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmVzaXplRGV2aWNlSGVscGVyKCk7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub2ZmKCdDYXRlZ29yeUhlYWRlclNsaWRlcnMuSW5pdGlhbGl6ZScpLm9uKCdDYXRlZ29yeUhlYWRlclNsaWRlcnMuSW5pdGlhbGl6ZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0c2xpZGVycy5pbml0aWFsaXplQ2F0ZWdvcnlTbGlkZXJzKCcuY2F0LWhlYWRlci1jb250ZW50LmNhdC1oZWFkZXItc2xpZGVyOm5vdCguc2xpY2staW5pdGlhbGl6ZWQpJyk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScpLm9uKCdQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplJywgZnVuY3Rpb24oZXZlbnQsIG9wdGlvbnMpIHtcblx0XHR2YXIgZGF0YSA9IG9wdGlvbnMucmVzdWx0cztcblx0XHR2YXIgaXNBY2NvdW50RGlhbG9nID0gb3B0aW9ucy5pc0FjY291bnREaWFsb2c7XG5cdFx0aWYgKGlzQWNjb3VudERpYWxvZykge1xuXHRcdFx0dmFyIGN1c3RvbWVyRmlyc3ROYW1lID0gZGF0YS5jdXN0b21lckZpcnN0TmFtZSA/ICcsICcgKyBkYXRhLmN1c3RvbWVyRmlyc3ROYW1lICsgJy4nIDogJy4nO1xuXHRcdFx0dmFyIGFsZXJ0TWVzc2FnZTtcblx0XHRcdGlmIChvcHRpb25zLmRpc3BsYXlNZXNzYWdlID09ICdsb2dpbicpIHtcblx0XHRcdFx0YWxlcnRNZXNzYWdlID0gJ1dlbGNvbWUgYmFjaycgKyBjdXN0b21lckZpcnN0TmFtZTtcblx0XHRcdH1cblx0XHRcdGlmIChvcHRpb25zLmRpc3BsYXlNZXNzYWdlID09ICdyZWdpc3RlcicpIHtcblx0XHRcdFx0YWxlcnRNZXNzYWdlID0gJ1RoYW5rcyBmb3IgY3JlYXRpbmcgYW4gYWNjb3VudCcgKyBjdXN0b21lckZpcnN0TmFtZTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5XSVNITElTVF9FTkFCTEVEKSB7IC8vIEZ1dHVyZS1mb3J3YXJkOiBpbiBjYXNlIHdlIGV2ZXIgaW1wbGVtZW50IGxvZ2luL3JlZ2lzdGVyIGRpYWxvZ3Mgb3RoZXIgdGhhbiB3aXRoIHdpc2hsaXN0XG5cdFx0XHRcdC8qKioqIFdpc2hsaXN0IGljb24gdXBkYXRlcyAqKioqL1xuXHRcdFx0XHR2YXIgd2lzaGxpc3RJdGVtcyA9IGRhdGEuY29udHJvbGxlclJlc3VsdHMgJiYgZGF0YS5jb250cm9sbGVyUmVzdWx0cy5hbGxXaXNobGlzdEl0ZW1zID8gZGF0YS5jb250cm9sbGVyUmVzdWx0cy5hbGxXaXNobGlzdEl0ZW1zIDogZGF0YS5hbGxXaXNobGlzdEl0ZW1zID8gZGF0YS5hbGxXaXNobGlzdEl0ZW1zIDogbnVsbDtcblx0XHRcdFx0dmFyIHJldHVybmVkUmVzdWx0ID0gZGF0YS5jb250cm9sbGVyUmVzdWx0cyAmJiBkYXRhLmNvbnRyb2xsZXJSZXN1bHRzLnJlc3VsdCA/IGRhdGEuY29udHJvbGxlclJlc3VsdHMucmVzdWx0IDogZGF0YS5yZXN1bHQgPyBkYXRhLnJlc3VsdCA6IG51bGw7XG5cdFx0XHRcdGlmICh3aXNobGlzdEl0ZW1zICE9IG51bGwpIHtcblx0XHRcdFx0XHR3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9IEpTT04uc3RyaW5naWZ5KHdpc2hsaXN0SXRlbXMpO1xuXHRcdFx0XHRcdHdpc2hsaXN0LnJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucygpO1xuXHRcdFx0XHRcdGlmIChyZXR1cm5lZFJlc3VsdCA9PSAnY29tcGxldGUnKSB7XG5cdFx0XHRcdFx0XHRhbGVydE1lc3NhZ2UgKz0gJyBUaGlzIGl0ZW0gaXMgYWxyZWFkeSBzYXZlZCB0byB5b3VyIFdpc2hsaXN0Lic7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGFsZXJ0TWVzc2FnZSArPSAnIEFuIGl0ZW0gaGFzIGJlZW4gYWRkZWQgdG8geW91ciBXaXNobGlzdC4nO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvKioqKiBTZWxlY3RlZCBzdG9yZSB1cGRhdGVzICoqKiovXG5cdFx0XHR2YXIgc3RvcmVGcm9tUHJvZmlsZSA9IGRhdGEuc3RvcmVGcm9tUHJvZmlsZSA/IGRhdGEuc3RvcmVGcm9tUHJvZmlsZSA6IG51bGw7XG5cdFx0XHR2YXIgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlSWQgPSAkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1zdG9yZS1zZWxlY3RvciAuc2VsZWN0ZWQtc3RvcmUnKS5sZW5ndGggPiAwID8gJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtc3RvcmUtc2VsZWN0b3IgLnNlbGVjdGVkLXN0b3JlJykuYXR0cignc3RvcmUtaWQnKSA6IG51bGw7XG5cdFx0XHR2YXIgbmF2U3RvcmVzRHJvcGRvd25TdG9yZUlkID0gJCgnLnN0b3Jlcy1kcm9wZG93biAuY3VycmVudC1zdG9yZSAubWFwLnN0b3JlJykubGVuZ3RoID4gMCA/ICQoJy5zdG9yZXMtZHJvcGRvd24gLmN1cnJlbnQtc3RvcmUgLm1hcC5zdG9yZScpLmF0dHIoJ2RhdGEtaWQnKSA6IG51bGw7XG5cdFx0XHR2YXIgc3RvcmVJRDtcblxuXHRcdFx0dmFyIGlzUHJvZHVjdFBhZ2UgPSAkKCcucHRfcHJvZHVjdC1kZXRhaWxzJykubGVuZ3RoO1xuXHRcdFx0dmFyIGlzQ2F0ZWdvcnkgPSAkKCcucHRfcHJvZHVjdC1zZWFyY2gtcmVzdWx0JykubGVuZ3RoO1xuXHRcdFx0aWYgKGlzUHJvZHVjdFBhZ2UpIHtcblx0XHRcdFx0c3RvcmVJRCA9IGFkZFRvQ2FydE9wdGlvbnNTdG9yZUlkID8gYWRkVG9DYXJ0T3B0aW9uc1N0b3JlSWQgOiBzdG9yZUZyb21Qcm9maWxlID8gc3RvcmVGcm9tUHJvZmlsZSA6IG51bGw7XG5cdFx0XHRcdGlmIChzdG9yZUlEKSB7XG5cdFx0XHRcdFx0Ly8gUmVkcmF3IHRoZSBcIk15IFN0b3JlXCIgcGllY2Ugb24gdGhlIFBEUFxuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0JvcGlzLlN0b3JlU2VhcmNoLlNlbGVjdCcsIHN0b3JlSUQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoaXNDYXRlZ29yeSkge1xuXHRcdFx0XHRzdG9yZUlEID0gbmF2U3RvcmVzRHJvcGRvd25TdG9yZUlkID8gbmF2U3RvcmVzRHJvcGRvd25TdG9yZUlkIDogc3RvcmVGcm9tUHJvZmlsZSA/IHN0b3JlRnJvbVByb2ZpbGUgOiBudWxsO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdGlmIChpc0NhdGVnb3J5KSB7XG5cdFx0XHRcdFx0aWYgKHN0b3JlSUQpIHtcblx0XHRcdFx0XHRcdC8vIE1ha2Ugc3VyZSB0byB1cGRhdGUgdGhlIHN0b3JlIG51bWJlciBpbiBjdXN0b21lciBwcm9maWxlIHdoZW4gb24gdGhlIFBMUFxuXHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQm9waXMuQXNzaWduU3RvcmVUb1Byb2ZpbGUnLCBzdG9yZUlEKTtcblx0XHRcdFx0XHR9IFxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChzdG9yZUlEKSB7XG5cdFx0XHRcdFx0Ly8gUmVkcmF3IHRoZSBzZWxlY3RlZCBzdG9yZSBwaWVjZXMgaW4gbmF2LCBTaG9wIFlvdXIgU3RvcmUgb24gUExQLCBNeSBBY2NvdW50IHN0b3JlIGRyb3AtZG93biwgYW5kIHN0b3JlIHNlYXJjaCBtb2RhbFxuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0JvcGlzLlNlbGVjdGVkU3RvcmUuUmVmcmVzaCcsIHN0b3JlSUQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8qKioqIE1pbmljYXJ0IHVwZGF0ZSAqKioqL1xuXHRcdFx0aWYgKGRhdGEuY2FydFF1YW50aXR5KSB7XG5cdFx0XHRcdHZhciAkbWluaUNhcnRFbG0gPSAkKCcubWluaS1jYXJ0IC5taW5pY2FydC1xdWFudGl0eScpLmxlbmd0aCA+IDAgPyAkKCcubWluaS1jYXJ0IC5taW5pY2FydC1xdWFudGl0eScpIDogJCgnLm1pbmktY2FydCAuYnRuLW1pbmljYXJ0IC5idG4tbWluaWNhcnQtcXR5Jyk7XG5cdFx0XHRcdCRtaW5pQ2FydEVsbS5odG1sKGRhdGEuY2FydFF1YW50aXR5KTtcblx0XHRcdH1cblxuXHRcdFx0LyoqKiogTXkgQWNjb3VudCBuYXZpZ2F0aW9uIHVwZGF0ZSAqKioqL1xuXHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdCQoJy5sb2dpbi1kcm9wZG93biAudXNlci1wYW5lbCAuZm9ybS1sb2dpbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0JCgnLmxvZ2luLWRyb3Bkb3duIC5sb2dpbi1kcm9wZG93bi1jdXN0b21lci1tZW51JykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIHByb2ZpbGVOYW1lID0gZGF0YS5jdXN0b21lckZpcnN0TmFtZSA/ICcgJyArIGRhdGEuY3VzdG9tZXJGaXJzdE5hbWUgOiAnJztcblx0XHRcdFx0JCgnLm1vYmlsZS1hY2NvdW50LW1haW4uZmlyc3QtbmFtZSBhJykuZmlyc3QoKS5maW5kKCdzcGFuJykuaHRtbCgnSGVsbG8nICsgcHJvZmlsZU5hbWUpO1xuXHRcdFx0fVxuXG5cdFx0XHQvKioqKiBDbGllbnQgV2luZG93ID4gQ3VzdG9tZXIgb2JqZWN0IHVwZGF0ZSAqKioqL1xuXHRcdFx0Q3VzdG9tZXIuYXV0aGVudGljYXRlZCA9IHRydWU7XG5cdFx0XHRDdXN0b21lci5yZWdpc3RlcmVkID0gdHJ1ZTtcblx0XHRcdFxuXHRcdFx0LyoqKiogQ2xvc2UgdGhlIGFjY291bnQgZGlhbG9nICoqKiovXG5cdFx0XHRkaWFsb2cuY2xvc2UoKTtcblxuXHRcdFx0LyoqKiogU2hvdyB0aGUgYWxlcnQgKioqKi9cblx0XHRcdGFsZXJ0LmluaXQoe1xuXHRcdFx0XHR0eXBlOiAnYWxlcnQtcHJpbWFyeScsXG5cdFx0XHRcdHRpbWVyOiAzMDAwLFxuXHRcdFx0XHRjb250ZW50OiBhbGVydE1lc3NhZ2Vcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IGRhdGEucmVnaXN0ZXJEaWFsb2dDb250aW51ZVVybCA/IGRhdGEucmVnaXN0ZXJEaWFsb2dDb250aW51ZVVybCA6IGRhdGEubG9naW5EaWFsb2dDb250aW51ZVVybCA/IGRhdGEubG9naW5EaWFsb2dDb250aW51ZVVybCA6IGxvY2F0aW9uLnJlbG9hZCgpO1xuXHRcdH1cblx0fSk7XG5cblx0Ly8gRG9tLVJlYWR5IFNsaWRlcnNcblx0c2xpZGVycy5pbml0KCcuYmFybi1zbGlkZXInLCB7ZG90czogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMX0sIDEwMjQ6IHtzbGlkZXNUb1Nob3c6IDJ9fX0pO1xuXHRpZiAoU2l0ZVByZWZlcmVuY2VzLkNPTlRFTlRfU0xPVF9TTElERVIgPT0gJ3N3aXBlckpTJykge1xuXHRcdHNsaWRlcnMuaW5pdCgnLmNvbGxlY3Rpb25zLWNvbnRlbnQuaGFzLXNsaWRlciAuY3VyYXRlZCcsIHtsb29wOiBmYWxzZSwgZG90czogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMX0sIDc2ODoge3NsaWRlc1RvU2hvdzogM319fSk7XG5cdH0gZWxzZSB7XG5cdFx0c2xpZGVycy5pbml0KCcuY29sbGVjdGlvbnMtY29udGVudC5oYXMtc2xpZGVyIC5jdXJhdGVkJywge2JyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMX0sIDc2ODoge3NsaWRlc1RvU2hvdzogM319fSk7XG5cdH1cblx0c2xpZGVycy5pbml0KCcuc2VjdGlvbi1vZmZlcnMudGlsZXMgLnNlY3Rpb24tYm9keScsIHtkb3RzOiBmYWxzZSwgYnJlYWtwb2ludHM6IHswOiB7c2xpZGVzVG9TaG93OiAxfSwgNDgwOiB7c2xpZGVzVG9TaG93OiAzfSwgNzY4OiB7c2xpZGVzVG9TaG93OiA0fX19KTtcblx0c2xpZGVycy5pbml0KCcuc2VjdGlvbi1vZmZlcnMuc2VjdGlvbi1icmFuZHMgLmJyYW5kLWxpc3QnLCB7ZG90czogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogNH0sIDQ4MDoge3NsaWRlc1RvU2hvdzogM30sIDc2ODoge3NsaWRlc1RvU2hvdzogNn19fSk7XG5cblx0aWYgKCQoZG9jdW1lbnQpLmZpbmQoJy5qdW1ib3Ryb24tbW9iaWxlJykubGVuZ3RoID4gMCAmJiB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHR2YXIganVtYm90cm9uRXhwYW5kZWRDb29raWUgPSBnZXRDb29raWUoJ2p1bWJvdHJvbkV4cGFuZGVkQ29va2llJyk7XG5cdFx0aWYgKGp1bWJvdHJvbkV4cGFuZGVkQ29va2llID09ICd0cnVlJyAmJiAkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5oYXNDbGFzcygnZmEtYW5nbGUtZG93bicpKSB7XG5cdFx0XHQkKCcuanVtYm90cm9uLW1vYmlsZScpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdCQoJyNqdW1ib3Ryb24tY3VycmVudC1vZmZlcnMtaWNvbicpLnJlbW92ZUNsYXNzKCdmYS1hbmdsZS1kb3duJyk7XG5cdFx0XHQkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5hZGRDbGFzcygnZmEtYW5nbGUtdXAnKTtcblx0XHR9IGVsc2UgaWYoanVtYm90cm9uRXhwYW5kZWRDb29raWUgPT0gJ2ZhbHNlJyAmJiAkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5oYXNDbGFzcygnZmEtYW5nbGUtdXAnKSkge1xuXHRcdFx0JCgnLmp1bWJvdHJvbi1tb2JpbGUnKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5yZW1vdmVDbGFzcygnZmEtYW5nbGUtdXAnKTtcblx0XHRcdCQoJyNqdW1ib3Ryb24tY3VycmVudC1vZmZlcnMtaWNvbicpLmFkZENsYXNzKCdmYS1hbmdsZS1kb3duJyk7XG5cdFx0fVxuXHR9XG5cdFx0XG5cdGlmKHdpbmRvdy5pbm5lcldpZHRoID4gNzY3ICkge1xuXHRcdCQoJy5tb2JpbGUtb25seSAuZ3Vlc3QtY2hlY2tvdXQtZm9ybScpLnJlbW92ZSgpO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5tb2JpbGUtaGlkZGVuIC5ndWVzdC1jaGVja291dC1mb3JtJykucmVtb3ZlKCk7XG5cdH1cblx0XG5cdFxuXHQkKCcjZ3Vlc3RfY2hlY2tvdXRfb3B0aW46Y2hlY2tib3gnKS5jaGFuZ2UoZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCQoJyNndWVzdF9jaGVja291dF9vcHRpbicpLnByb3AoXCJjaGVja2VkXCIpKSB7XG5cdFx0XHQkKCcub3B0aW4taW5wdXQnKS5hZGRDbGFzcygnY2hlY2tlZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcub3B0aW4taW5wdXQnKS5yZW1vdmVDbGFzcygnY2hlY2tlZCcpO1xuXHRcdH1cblx0fSk7XG5cblx0Ly8gc2VsZWN0ZWQgc3RhdGVzIGZvciBhY2NvdW50IG5hdmlnYXRpb25cblx0aWYgKCQoZG9jdW1lbnQpLmZpbmQoJy5wdF9hY2NvdW50LCAucHRfb3JkZXIsIC5wdF9jdXN0b21lci1zZXJ2aWNlLCAucHRfd2lzaC1saXN0JykubGVuZ3RoID4gMCkge1xuXHRcdHZhciBjdXJyZW50UGFnZSA9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG5cdFx0dmFyIGlzT25Ub3BMZXZlbFBhZ2UgPSBmYWxzZTtcblx0XHQkKCcjc2Vjb25kYXJ5IG5hdiBhJylcblx0XHRcdC5yZW1vdmVDbGFzcygnaXMtYWN0aXZlJylcblx0XHRcdC5lYWNoKGZ1bmN0aW9uKGluZGV4LCB2YWx1ZSkge1xuXHRcdFx0XHRpZiAodmFsdWUuaHJlZiA9PT0gY3VycmVudFBhZ2UpIHtcblx0XHRcdFx0XHQkKHRoaXMpLmFkZENsYXNzKCdpcy1hY3RpdmUnKTtcblx0XHRcdFx0XHRpc09uVG9wTGV2ZWxQYWdlID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdH0pO1xuXHRcdGlmICghaXNPblRvcExldmVsUGFnZSkge1xuXHRcdFx0JCgnI3NlY29uZGFyeSBuYXYgYScpLmVhY2goZnVuY3Rpb24oaW5kZXgsIHZhbHVlKSB7XG5cdFx0XHRcdGlmICh2YWx1ZS5ocmVmID09PSBkb2N1bWVudC5yZWZlcnJlcikge1xuXHRcdFx0XHRcdCQodGhpcykuYWRkQ2xhc3MoJ2lzLWFjdGl2ZScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHQvLyAtLS0gRG9jdW1lbnQuUmVhZHkoKTogQURBIENvbXBsaWFuY2UgRml4ZXMgLS0tXG5cdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NsaWNrU2xpZGVyQWNjZXNzaWJpbGl0eU1vZHMnKTtcblx0Ly8gVGhpcyB3b3JrLWFyb3VuZCB3aWxsIGhhdmUgdG8gZG8gdW50aWwgd2UgY2FuIGNvbnRhY3QgdGhlIHZlbmRvciB0byBmaXggdGhlaXIgdGFncy5cblx0dmFyIGFkYVRhZ0ludGVydmFsQ291bnRlciA9IDA7XG5cdHZhciBhZGFUYWdJbnRlcnZhbCA9IHNldEludGVydmFsKGZ1bmN0aW9uKCl7IFxuXHRcdGlmICghJCgnaW1nW3NyYyo9XCJhcnR0cmsuY29tXCJdJykuaXMoJ1thbHRdJykpIHtcblx0XHRcdCQoJ2ltZ1tzcmMqPVwiYXJ0dHJrLmNvbVwiXScpLmF0dHIoJ2FsdCcsJ1RyYWNraW5nIHBpeGVsJyk7XG5cdFx0fVxuXHRcdGlmICghJCgnI2ZpbGVVcGxvYWRGb3JtIGlucHV0I2ZpbGVTZWxlY3RvcicpLmlzKCdbYXJpYS1sYWJlbF0nKSkge1xuXHRcdFx0JCgnI2ZpbGVVcGxvYWRGb3JtIGlucHV0I2ZpbGVTZWxlY3RvcicpLmF0dHIoJ2FyaWEtbGFiZWwnLCAnU2VsZWN0IGZpbGUgdG8gdXBsb2FkJyk7XG5cdFx0fVx0XG5cdFx0aWYgKGFkYVRhZ0ludGVydmFsQ291bnRlciA+IDkgfHwgKCQoJ2ltZ1tzcmMqPVwiYXJ0dHJrLmNvbVwiXScpLmlzKCdbYWx0XScpICYmICQoJyNmaWxlVXBsb2FkRm9ybSBpbnB1dCNmaWxlU2VsZWN0b3InKS5pcygnW2FyaWEtbGFiZWxdJykpKSB7XG5cdFx0XHRjbGVhckludGVydmFsKGFkYVRhZ0ludGVydmFsKTtcblx0XHR9XG5cdFx0YWRhVGFnSW50ZXJ2YWxDb3VudGVyKys7XG5cdH0sIDEwMDApOyAvLyAxMDAwIG1zID0gc3RhcnQgYWZ0ZXIgMXNlYyBcblx0Ly8gU2tpcCBsaW5rIGZvciBwcm9kdWN0IHJlY29tbWVuZGF0aW9ucyBjb250YWluZXJcblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5Ta2lwLlJlY29tbWVuZGF0aW9ucycpLm9uKCdjbGljay5Ta2lwLlJlY29tbWVuZGF0aW9ucycsJy5za2lwLXByb2R1Y3QtcmVjb21tZW5kYXRpb25zLWNvbnRhaW5lcicsIGZ1bmN0aW9uKGUpIHtcblx0XHQkKHRoaXMpLnNpYmxpbmdzKCcucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMtY29udGFpbmVyLWRpdmUnKS5mb2N1cygpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlpvb20uU2tpcC5TZWN0aW9uJykub24oJ2NsaWNrLlpvb20uU2tpcC5TZWN0aW9uJywnLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyLW1vYmlsZSAuc2tpcC10by1uZXh0JywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgaXNTa2lwVG9XaXNobGlzdEJ1dHRvbiA9ICQodGhpcykuYXR0cignaHJlZicpLmluZGV4T2YoJ3BkcC13aXNobGlzdC1idXR0b24tY29udGFpbmVyJykgPiAtMTtcblx0XHRpZiAoaXNTa2lwVG9XaXNobGlzdEJ1dHRvbikge1xuXHRcdFx0JCgnI3BkcC13aXNobGlzdC1idXR0b24tY29udGFpbmVyIC53aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24nKS5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKS5mb2N1cygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cubG9jYXRpb24gPSAkKHRoaXMpLmF0dHIoJ2hyZWYnKTtcblx0XHR9XG5cdH0pO1xuXG5cdC8vIC0tLSBJbml0aWFsaXplIEV2ZW50czogQURBIENvbXBsaWFuY2UgS2V5Ym9hcmQgVGFiIFZpc3VhbCBJbmRpY2F0b3IgLS0tXG5cdCQoZG9jdW1lbnQpLm9uKCdrZXl1cCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGlmIChldmVudC53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5UYWIpIHtcblx0XHRcdCQoJzpmb2N1cycpLmFkZENsYXNzKCdmb2N1cy12aXNpYmxlLWluZGljYXRvcicpO1xuXHRcdFx0aWYgKCQoJzpmb2N1cycpLmhhc0NsYXNzKCd2aXN1YWxseS1oaWRkZW4nKSkge1xuXHRcdFx0XHQvLyBHZXQgdGhlIGlubmFyZHMgb2YgdGhlIGN1cnJlbnQgZm9jdXMgZWxlbWVudCBhbmQgY29weSB0aGVtIGludG8gdGhlIGhpZGRlbi1lbGVtZW50LW1lbW8gdGhhdCBpcyB0aGVuIHByZXBlbmRlZCB0byB0aGUgPGJvZHk+XG5cdFx0XHRcdHZhciBodG1sVGV4dCA9ICQoJzpmb2N1cycpLmh0bWwoKTtcblx0XHRcdFx0dmFyICRoaWRkZW5FbGVtZW50TWVtbyA9ICQoJzxkaXYvPicsIHtcImNsYXNzXCI6IFwiaGlkZGVuLWVsZW1lbnQtbWVtb1wifSkuaHRtbChodG1sVGV4dCk7XG5cdFx0XHRcdCQoJ2JvZHknKS5wcmVwZW5kKCRoaWRkZW5FbGVtZW50TWVtbyk7XG5cblx0XHRcdFx0Ly8gQ2xlYXIgbWVtbyBhZnRlciAzIHNlY29uZHMgaWYgaXQgaGFzIG5vdCBhbHJlYWR5IGJlZW4gY2xlYXJlZFxuXHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBcblx0XHRcdFx0XHQkKCcuaGlkZGVuLWVsZW1lbnQtbWVtbycpLnJlbW92ZSgpO1xuXHRcdFx0XHR9LCAzMDAwKTsgLy8gMzAwMCBtcyA9IHN0YXJ0IGFmdGVyIDFzZWMgXG5cdFx0XHR9XG5cdFx0fVxuXHR9KS5vbigna2V5ZG93biBrZXlwcmVzcyBtb3VzZW1vdmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHQkKCcuZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKS5yZW1vdmVDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKTtcblx0XHQkKCcuaGlkZGVuLWVsZW1lbnQtbWVtbycpLnJlbW92ZSgpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vbignaW5pdC5TbGlkZXIuQXJpYScsICcuc2xpZGVyJywgZnVuY3Rpb24oZXZlbnQsIHNsaWNrKSB7XG5cdFx0JCh0aGlzKS5maW5kKCcuc2xpY2stbGlzdCcpLnJlbW92ZUF0dHIoJ2FyaWEtbGl2ZScpO1xuXHR9KS5vbignY2xpY2suU2xpZGVyLkFyaWEga2V5dXAuU2xpZGVyLkFyaWEnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmIChldmVudC50YXJnZXQubWF0Y2hlcygnLnNsaWRlciwgLnNsaWRlciAqJykpIHtcblx0XHRcdGlmICghJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJy5zbGlkZXInKS5maW5kKCcuc2xpY2stbGlzdCcpLmF0dHIoJ2FyaWEtbGl2ZScpKSB7XG5cdFx0XHRcdCQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCcuc2xpZGVyJykuZmluZCgnLnNsaWNrLWxpc3QnKS5hdHRyKCdhcmlhLWxpdmUnLCAncG9saXRlJyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5zbGlkZXInKS5maW5kKCcuc2xpY2stbGlzdCcpLnJlbW92ZUF0dHIoJ2FyaWEtbGl2ZScpO1xuXHRcdH1cblx0fSk7XG5cbiAgICAkLmZuLmhhc0F0dHIgPSBmdW5jdGlvbihuYW1lKSB7XG5cdFx0cmV0dXJuIHRoaXMuYXR0cihuYW1lKSAhPT0gdW5kZWZpbmVkO1xuXHR9O1xuXHRcblx0ZnVuY3Rpb24gQ2hlY2tsb2dpbkNyZWF0ZSgpIHtcblx0XHR2YXIgbG9naW5DcmVhdGVDb3VudCA9ICQoXCIubG9naW4tY3JlYXRlLWFjY291bnRcIikubGVuZ3RoO1xuXHRcdGlmKGxvZ2luQ3JlYXRlQ291bnQgPT0gMCkge1xuXHRcdCQoXCIub3JkZXItY29uZmlybWF0aW9uLWRldGFpbHNcIikuYWRkQ2xhc3MoXCJmdWxsV2lkdGhcIik7XG5cdFx0fWVsc2Uge1xuXHRcdFx0JChcIi5vcmRlci1jb25maXJtYXRpb24tZGV0YWlsc1wiKS5yZW1vdmVDbGFzcyhcImZ1bGxXaWR0aFwiKTtcblx0XHR9XG5cdH1cblx0XG5cdC8vIHNldCBjdXN0b21lciBiaXJ0aGRheVxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcjZHdmcm1fYmlydGhkYXkgYnV0dG9uLmNvbmZpcm0nLCBmdW5jdGlvbihldmVudCl7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgZW1haWwgPSAkKCcuY3JlZGVudGlhbC1saXN0LS1lbWFpbCcpLnRleHQoKS50cmltKCk7XG5cdFx0dmFyIGJpcnRoZGF5RmllbGQgPSAkKCcjZHdmcm1fYmlydGhkYXknKTtcblx0XHR2YXIgYmlydGhtb250aCA9IGJpcnRoZGF5RmllbGQuZmluZCgnLmJpcnRobW9udGggc2VsZWN0Jyk7XG5cdFx0dmFyIGJpcnRoZGF5ID0gYmlydGhkYXlGaWVsZC5maW5kKCcuYmlydGhkYXkgc2VsZWN0Jyk7XG5cdFx0dmFyIGJpcnRoeWVhciA9IGJpcnRoZGF5RmllbGQuZmluZCgnLmJpcnRoeWVhciBzZWxlY3QnKTtcblx0XHR2YXIgbW9udGgsIGRheSwgeWVhciwgYmlydGhkYXRlO1xuXHRcdFxuXHRcdGlmICghYmlydGhtb250aC52YWwoKSkge1xuXHRcdFx0YmlydGhtb250aC5hZGRDbGFzcygnZXJyb3ItcmVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGJpcnRobW9udGgucmVtb3ZlQ2xhc3MoJ2Vycm9yLXJlZCcpO1xuXHRcdFx0bW9udGggPSBiaXJ0aG1vbnRoLmZpbmQoXCJvcHRpb246c2VsZWN0ZWRcIikudGV4dCgpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoIWJpcnRoZGF5LnZhbCgpKSB7XG5cdFx0XHRiaXJ0aGRheS5hZGRDbGFzcygnZXJyb3ItcmVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGJpcnRoZGF5LnJlbW92ZUNsYXNzKCdlcnJvci1yZWQnKTtcblx0XHRcdGRheSA9IGJpcnRoZGF5LmZpbmQoXCJvcHRpb246c2VsZWN0ZWRcIikudGV4dCgpO1xuXHRcdH1cblxuXHRcdGlmICghYmlydGh5ZWFyLnZhbCgpKSB7XG5cdFx0XHRiaXJ0aHllYXIuYWRkQ2xhc3MoJ2Vycm9yLXJlZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRiaXJ0aHllYXIucmVtb3ZlQ2xhc3MoJ2Vycm9yLXJlZCcpO1xuXHRcdFx0eWVhciA9IGJpcnRoeWVhci5maW5kKFwib3B0aW9uOnNlbGVjdGVkXCIpLnRleHQoKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKGJpcnRoZGF5RmllbGQuZmluZCgnLmVycm9yLXJlZCcpLmxlbmd0aCA+IDApe1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRcblx0XHRiaXJ0aGRhdGUgPSBtb250aCArICcvJyArIGRheSArICcvJyArIHllYXI7XG5cdFx0XG5cdFx0JC5hamF4KHtcblx0XHRcdHR5cGU6ICdwb3N0Jyxcblx0XHRcdHVybDogVXJscy5zZXRCaXJ0aGRheSxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdGVtYWlsOiBlbWFpbCxcblx0XHRcdFx0bW9udGg6IG1vbnRoLFxuXHRcdFx0XHRkYXk6IGRheSxcblx0XHRcdFx0eWVhcjogeWVhclxuXHRcdFx0fSksXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHQkKCcjZHdmcm1fYmlydGhkYXknKS5yZW1vdmUoKTtcblx0XHRcdFx0JCgnLmNyZWRlbnRpYWwtbGlzdC0tYmlydGhkYXRlJykudGV4dChiaXJ0aGRhdGUpO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCl7XHRcdFx0XHRcblx0XHRcdFx0XHR2YXIgYXV0aF9kYXRhID0ge1xuXHRcdFx0XHRcdFx0ZW1haWw6IGVtYWlsXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHZhciBjb250YWN0X2RhdGEgPSB7XG5cdFx0XHRcdFx0ICAgICdjaGFubmVscyc6IHtcblx0XHRcdFx0XHQgICAgICAgICdlbWFpbCc6IHtcblx0XHRcdFx0XHQgICAgICAgICAgICAnYWRkcmVzcyc6IGVtYWlsXG5cdFx0XHRcdFx0ICAgICAgICB9XG5cdFx0XHRcdFx0ICAgIH0sXG5cdFx0XHRcdFx0ICAgICdiaXJ0aGRheSc6IGJpcnRoZGF0ZVxuXHRcdFx0XHRcdH07XG5cdFxuXHRcdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRcdGNyZGwoJ2NvbnRhY3QnLCBhdXRoX2RhdGEsIGNvbnRhY3RfZGF0YSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXHRcblx0aWYoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgU2l0ZVByZWZlcmVuY2VzLlBJTlRFUkVTVF9FTkFCTEVEKXtcdFxuXHRcdGlmICgkKGRvY3VtZW50KS5maW5kKCcucHRfcHJvZHVjdC1kZXRhaWxzJykubGVuZ3RoID4gMCkge1xuXHRcdFx0c2V0VGltZW91dChmdW5jdGlvbigpeyAgIFx0XG5cdFx0XHRcdHZhciB0aGlzSXRlbSA9IEpTT04ucGFyc2UoJCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEucGRwLWJyb3dzZScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0XHRcdFx0dmFyIHByb2R1Y3RJRCA9IHRoaXNJdGVtW1wiaWRcIl07XG5cdFx0XHRcdHZhciBkYXRlVGltZSA9IE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApO1xuXHRcdFx0XHR2YXIgZXZlbnRJRCA9ICdwZHAtJyArIHByb2R1Y3RJRCArICctJyArIGRhdGVUaW1lO1xuXG5cdFx0XHQgIFx0cGludHJrKCd0cmFjaycsICdwYWdldmlzaXQnLCB7XG5cdFx0XHQgIFx0XHRldmVudF9pZDogZXZlbnRJRCxcblx0XHRcdCAgXHRcdGxpbmVfaXRlbXM6IFtcblx0XHRcdCAgXHRcdFx0e1xuXHRcdFx0XHRcdCAgXHRcdHByb2R1Y3RfbmFtZTogdGhpc0l0ZW1bXCJuYW1lXCJdLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XHRcdFx0ICBcdFx0cHJvZHVjdF9pZDogcHJvZHVjdElELFxuXHRcdFx0XHRcdCAgXHRcdHByb2R1Y3RfY2F0ZWdvcnk6IHRoaXNJdGVtW1wiY2F0ZWdvcnlcIl0ucmVwbGFjZSgvXFxcXC9nLCBcIlwiKSxcblx0XHRcdFx0XHQgIFx0XHRwcm9kdWN0X3ByaWNlOiB0aGlzSXRlbVtcInByaWNlXCJdLFxuXHRcdFx0XHRcdCAgXHRcdHByb2R1Y3RfYnJhbmQ6IHRoaXNJdGVtW1wiYnJhbmRcIl1cblx0XHRcdCAgXHRcdFx0fVxuXHRcdFx0ICBcdFx0XVxuXHRcdFx0ICBcdH0pO1xuXHRcdFx0fSwgMzAwMCk7XHRcdFx0XHRcdFxuXHRcdH1cblx0XHRcblx0XHQvLyBjaGVja291dCBldmVudCBjcmVhdGVkIG9uIGNvbmZpcm1hdGlvblx0XG5cdFx0aWYgKCQoZG9jdW1lbnQpLmZpbmQoJy5vcmRlci1jb25maXJtYXRpb24tZGV0YWlscycpLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBvcmRlcklEID0gJCgnLm9yZGVyZGV0YWlscyAuc2VjdGlvbmhlYWRlciBoMycpLnRleHQoKS5yZXBsYWNlKCdPcmRlciBOdW1iZXI6JywnJykudHJpbSgpO1xuXHRcdFx0dmFyIGRhdGVUaW1lID0gTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCk7XG5cdFx0XHR2YXIgZXZlbnRJRCA9ICdjaGVja291dC0nICsgb3JkZXJJRCArICctJyArIGRhdGVUaW1lO1xuXHRcdFx0dmFyIGN1cnJlbmN5ID0gJ1VTRCc7XG5cdFx0XHRcblx0XHRcdHZhciBpdGVtcyA9IFtdO1xuXHRcdFx0JCgnLm9yZGVyLWl0ZW0nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbCkge1xuXHRcdFx0XHR2YXIgX3RoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHRpdGVtc1tpbmRleF0gPSB7fTtcblx0XHRcdFx0X3RoaXMuZmluZCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEnKS5lYWNoKGZ1bmN0aW9uKGtleSwgdikge1xuXHRcdFx0XHRcdHZhciB0aGlzSXRlbSA9IEpTT04ucGFyc2UoJCh0aGlzKS5hdHRyKCdkYXRhLXByb2R1Y3QtZ3RtLWpzb24nKSk7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbmN5ID0gdGhpc0l0ZW1bXCJjdXJyZW5jeVwiXTtcblx0XHRcdFx0XHR2YXIgcHJvZHVjdCA9IHt9O1x0XG5cdFx0XHRcdFx0cHJvZHVjdC5wcm9kdWN0X25hbWUgPSB0aGlzSXRlbVtcImlkXCJdO1xuXHRcdFx0XHRcdHByb2R1Y3QucHJvZHVjdF92YXJpYW50X2lkID0gdGhpc0l0ZW1bXCJza3VpZFwiXTtcblx0XHRcdFx0XHRwcm9kdWN0LnByb2R1Y3RfbmFtZSA9IHRoaXNJdGVtW1wibmFtZVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpO1xuXHRcdFx0XHRcdHByb2R1Y3QucHJvZHVjdF9icmFuZCA9IHRoaXNJdGVtW1wiYnJhbmRcIl07XG5cdFx0XHRcdFx0cHJvZHVjdC5wcm9kdWN0X3F1YW50aXR5ID0gdGhpc0l0ZW1bXCJxdWFudGl0eVwiXTtcblx0XHRcdFx0XHRwcm9kdWN0LnByb2R1Y3RfcHJpY2UgPSB0aGlzSXRlbVtcInByaWNlXCJdO1xuXHRcdFx0XHRcdGl0ZW1zW2luZGV4XT0gcHJvZHVjdDtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0cGludHJrKCd0cmFjaycsICdjaGVja291dCcsIHtcblx0XHRcdFx0ZXZlbnRfaWQ6IGV2ZW50SUQsXG5cdFx0XHRcdHZhbHVlOiBwYXJzZUZsb2F0KCQoJy5vcmRlcmRldGFpbHMgLnRvdGFsIC5vcmRlci10b3RhbCcpLnRleHQoKS5yZXBsYWNlKCckJywnJykpLnRvRml4ZWQoMiksXG5cdFx0XHRcdG9yZGVyX3F1YW50aXR5OiBNYXRoLnJvdW5kKCQoJy5vcmRlcmRldGFpbHMgc3Bhbi5pdGVtLWNvdW50JykuZGF0YSgnY291bnQnKSksXG5cdFx0XHRcdGN1cnJlbmN5OiBjdXJyZW5jeSxcblx0XHRcdFx0b3JkZXJfaWQ6IG9yZGVySUQsXG5cdFx0XHRcdGxpbmVfaXRlbXM6IGl0ZW1zXG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblx0XG5cdC8vIENPUkRJQUwgQUNDT1VOVCBTSUdOLVVQLCBCUk9XU0UsIENBUlQsIE9SREVSXG5cdGlmKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpe1xuXHRcdC8vIGhvbWVwYWdlIGJyb3dzZVxuXHRcdGlmICgkKGRvY3VtZW50KS5maW5kKCdbY29udGVudC1zbG90LWlkPVwiaG9tZXBhZ2UtMDFcIl0nKS5sZW5ndGggPiAwKSB7XHRcdFxuXHRcdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRjcmRsKCdldmVudCcsICdob21lcGFnZV9icm93c2UnKTtcblx0XHRcdH1cdFx0XG5cdFx0fVxuXHRcdFxuXHRcdC8vIHBscCBicm93c2Vcblx0XHRpZiAoJChkb2N1bWVudCkuZmluZCgnLnB0X3Byb2R1Y3Qtc2VhcmNoLXJlc3VsdCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBtYXhUaWxlcyA9IDEwO1xuXHRcdFx0dmFyIHByb2R1Y3RzID0gW107XG5cdFx0XHQkKCcucHJvZHVjdC10aWxlJykuZWFjaChmdW5jdGlvbihpKSB7XG5cdFx0XHRcdGlmIChpIDwgbWF4VGlsZXMpIHtcblx0XHRcdFx0XHR2YXIgcHJvZHVjdCA9ICQodGhpcykuYXR0cignZGF0YS1pdGVtaWQnKTtcblx0XHRcdFx0XHRwcm9kdWN0cy5wdXNoKHByb2R1Y3QpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHQgICAgXCJjYXRlZ29yeVwiOiAkKCcjY2F0ZWdvcnlUaXRsZScpLnRleHQoKS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLnRyaW0oKSxcblx0XHRcdCAgICBcInVybFwiOiAkKGxvY2F0aW9uKS5hdHRyKFwiaHJlZlwiKS5zcGxpdChcIj91dG1cIilbMF0uc3BsaXQoXCIjdXRtXCIpWzBdLnNwbGl0KFwiJnV0bVwiKVswXSxcblx0XHRcdCAgICBcInByb2R1Y3RzXCI6IHByb2R1Y3RzXG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdGNyZGwoJ2V2ZW50JywgJ2NhdGVnb3J5X2Jyb3dzZScsIHByb3BlcnRpZXMpO1xuXHRcdFx0fVx0XHRcblx0XHR9XG5cdFx0XG5cdFx0Ly8gcGRwIGJyb3dzZVxuXHRcdGlmICgkKGRvY3VtZW50KS5maW5kKCcucHRfcHJvZHVjdC1kZXRhaWxzJykubGVuZ3RoID4gMCkge1xuXHRcdFx0c2V0VGltZW91dChmdW5jdGlvbigpeyAgIFx0XG5cdFx0XHRcdHZhciB0aGlzSXRlbSA9IEpTT04ucGFyc2UoJCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEucGRwLWJyb3dzZScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0XHRcdCAgXHR2YXIgaW1hZ2VzID0gW107XG5cdFx0XHRcdCQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2NsYXNzKj1cIi1zbGlkZVwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHZhciBpbWFnZSA9ICQodGhpcykuZmluZCgnYScpLmF0dHIoJ2hyZWYnKTtcblx0XHRcdFx0XHRpZiAoIWltYWdlIHx8IGltYWdlID09IHVuZGVmaW5lZCB8fCBpbWFnZSA9PSBudWxsKSB7XG5cdFx0XHRcdFx0XHRpbWFnZSA9ICQodGhpcykuZmluZCgnaW1nJykuYXR0cignc3JjJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChpbWFnZXMuaW5kZXhPZihpbWFnZSkgPT09IC0xKSB7XG5cdFx0XHRcdFx0XHRpbWFnZXMucHVzaChpbWFnZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0XG5cdFx0XHQgIFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHRcdFx0XCJwcm9kdWN0SURcIjogdGhpc0l0ZW1bXCJpZFwiXSxcblx0XHRcdFx0XHRcInByb2R1Y3ROYW1lXCI6IHRoaXNJdGVtW1wibmFtZVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFx0XHRcdFwiY2F0ZWdvcnlcIjogdGhpc0l0ZW1bXCJjYXRlZ29yeVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFx0XHRcdFwicHJpY2VcIjogdGhpc0l0ZW1bXCJwcmljZVwiXSxcblx0XHRcdFx0XHRcImltYWdlc1wiOiBpbWFnZXMsXG5cdFx0XHQgIFx0XHRcInVybFwiOiAkKGxvY2F0aW9uKS5hdHRyKFwiaHJlZlwiKS5zcGxpdChcIj91dG1cIilbMF0uc3BsaXQoXCIjdXRtXCIpWzBdLnNwbGl0KFwiJnV0bVwiKVswXSxcblx0XHRcdFx0XHRcImF0dHJcIjoge1xuXHRcdFx0ICAgICAgICAgICAgXCJtYW51ZmFjdHVyZXJcIjogdGhpc0l0ZW1bXCJicmFuZFwiXVxuXHRcdFx0ICAgICAgICB9LFxuXHRcdFx0XHR9O1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0ICBcdFx0Y3JkbCgnZXZlbnQnLCAncHJvZHVjdF9icm93c2UnLCBwcm9wZXJ0aWVzKTsgXG5cdFx0XHRcdH1cblx0XHRcdH0sIDMwMDApO1x0XHRcdFx0XHRcblx0XHR9XG5cdFx0XG5cdFx0Ly8gYWRkIENvcmRpYWwgY29udGFjdCBmcm9tIGNoZWNrb3V0XG5cdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKXtcblx0ICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHQgICAgXHRpZiAoJCgnLmJpbGwtYWRkcmVzcy1maWVsZHMgLmZpZWxkLmVycm9yJykubGVuZ3RoID09IDApIHtcblx0XHRcdFx0dmFyIGVtYWlsID0gJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2VtYWlsJykudmFsKCkudHJpbSgpO1xuXHRcdFx0XHR2YXIgZmlyc3ROYW1lID0gJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2ZpcnN0TmFtZScpLnZhbCgpO1xuXHRcdFx0XHR2YXIgbGFzdE5hbWUgPSAkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfbGFzdE5hbWUnKS52YWwoKTtcblx0XHRcdFx0dmFyIHBob25lID0gJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX3Bob25lJykudmFsKCk7XG5cdFx0XHRcdHZhciB6aXAgPSAkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfcG9zdGFsJykudmFsKCk7XG5cdFx0XHRcdHZhciBjb3VudHJ5ID0gJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2NvdW50cnknKS52YWwoKTtcblx0XHRcdFx0dmFyIHN0YXRlID0gJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLnZhbCgpO1xuXHRcdFx0XHR2YXIgY2l0eSA9ICQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19jaXR5JykudmFsKCk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0aWYgKCQoJ2lucHV0I25ld3NsZXR0ZXJzaWdudXAnKS5pcygnOmNoZWNrZWQnKSl7XG5cdFx0XHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0XHRcdGVtYWlsOiBlbWFpbFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHRcdCAgICAnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdFx0ICAgICAgICAnZW1haWwnOiB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbCxcblx0XHRcdFx0XHQgICAgICAgICAgICAnc3Vic2NyaWJlU3RhdHVzJzogJ3N1YnNjcmliZWQnXG5cdFx0XHRcdFx0ICAgICAgICB9XG5cdFx0XHRcdFx0ICAgIH0sXG5cdFx0XHRcdFx0XHQnZmlyc3RfbmFtZSc6IGZpcnN0TmFtZSxcblx0XHRcdFx0XHRcdCdsYXN0X25hbWUnOiBsYXN0TmFtZSxcblx0XHRcdFx0XHRcdCdwaG9uZSc6IHBob25lLFxuXHRcdFx0XHRcdFx0J3Bvc3RhbF9jb2RlJzogemlwLFxuXHRcdFx0XHRcdFx0J3NpZ251cF9zb3VyY2UnOiAnY2hlY2tvdXQnLFxuXHRcdFx0XHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZSxcblx0XHRcdFx0XHRcdCdnZW9fbG9jYXRpb24nOiB7XG5cdFx0XHRcdFx0XHQgICAgJ3Bvc3RhbF9jb2RlJzogemlwLFxuXHRcdFx0XHRcdFx0ICAgICdjb3VudHJ5JzogY291bnRyeSxcblx0XHRcdFx0XHRcdCAgICAnc3RhdGUnOiBzdGF0ZSxcblx0XHRcdFx0XHRcdCAgICAnY2l0eSc6IGNpdHlcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHRcdCAgICBcInNpZ251cF9zb3VyY2VcIjogJ2NoZWNrb3V0Jyxcblx0XHRcdFx0XHQgICAgXCJ3ZWxjb21lX3NpZ251cFwiOiB0cnVlXG5cdFx0XHRcdFx0fTtcblx0XHRcblx0XHRcdFx0XHRSZXF1ZXN0SGVscGVyLlZhbGlkYXRlKCdDb3JkaWFsLUVtYWlsU2lnbnVwJykudGhlbihmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRcdFx0Y3JkbChbXG5cdFx0XHRcdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFx0XHRcdFsnZXZlbnQnLCAnZW1haWxfc2lnbnVwJywgcHJvcGVydGllc11cblx0XHRcdFx0XHRcdFx0XSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSkuY2F0Y2goKTtcblx0XHRcdFx0fVxuXHQgICAgXHR9XG5cdFx0fSk7XG5cdFx0XG5cdFx0Ly8gdXBkYXRlIENhcnQgd2hlbiBxdHkgY2hhbmdlIG9yIHJlbW92YWwgaW4gY2FydFxuXHRcdGZ1bmN0aW9uIGNvcmRpYWxVcGRhdGVDYXJ0KCkge1xuXHRcdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuXHRcdFx0XHR2YXIgaXRlbXMgPSBbXTtcblx0XHRcdFx0JCgnLm9yZGVyLWl0ZW0nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbCkge1xuXHRcdFx0XHRcdHZhciBfdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdFx0aXRlbXNbaW5kZXhdID0ge307XG5cdFx0XHRcdFx0X3RoaXMuZmluZCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEnKS5lYWNoKGZ1bmN0aW9uKGtleSwgdikge1xuXHRcdFx0XHRcdFx0dmFyIHRoaXNJdGVtID0gSlNPTi5wYXJzZSgkKHRoaXMpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0XHRcdFx0XHRcdHZhciBwcm9kdWN0ID0ge307XHRcblx0XHRcdFx0XHRcdHByb2R1Y3QucHJvZHVjdElEID0gdGhpc0l0ZW1bXCJpZFwiXTtcblx0XHRcdFx0XHRcdHByb2R1Y3Quc2t1ID0gdGhpc0l0ZW1bXCJza3VpZFwiXTtcblx0XHRcdFx0XHRcdHByb2R1Y3QuY2F0ZWdvcnkgPSB0aGlzSXRlbVtcImNhdGVnb3J5XCJdLnJlcGxhY2UoL1xcXFwvZywgXCJcIik7XG5cdFx0XHRcdFx0XHRwcm9kdWN0Lm5hbWUgPSB0aGlzSXRlbVtcIm5hbWVcIl0ucmVwbGFjZSgvXFxcXC9nLCBcIlwiKTtcblx0XHRcdFx0XHRcdHByb2R1Y3QucXR5ID0gdGhpc0l0ZW1bXCJxdWFudGl0eVwiXTtcblx0XHRcdFx0XHRcdHByb2R1Y3QuaXRlbVByaWNlID0gdGhpc0l0ZW1bXCJwcmljZVwiXTtcblx0XHRcdFx0XHRcdHByb2R1Y3QuaW1hZ2VzID0gW190aGlzLmZpbmQoJ2ltZycpLmF0dHIoJ3NyYycpXTtcblx0XHRcdFx0XHRcdHByb2R1Y3QudXJsID0gd2luZG93LmxvY2F0aW9uLm9yaWdpbiArIF90aGlzLmZpbmQoJy5uYW1lJykuZmluZCgnYScpLmF0dHIoJ2hyZWYnKS5zcGxpdChcIj91dG1cIilbMF0uc3BsaXQoXCIjdXRtXCIpWzBdLnNwbGl0KFwiJnV0bVwiKVswXTtcblx0XHRcdFx0XHRcdHByb2R1Y3QuYXR0ciA9IHsnbWFudWZhY3R1cmVyJzogdGhpc0l0ZW1bXCJicmFuZFwiXSwgJ2NvbG9yJzogdGhpc0l0ZW1bXCJjb2xvclwiXSwgJ3NpemUnOiB0aGlzSXRlbVtcInNpemVcIl0gfTtcblx0XHRcdFx0XHRcdGl0ZW1zW2luZGV4XT0gcHJvZHVjdDtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgY2FydF9kYXRhID0gaXRlbXM7XG5cdFx0XG5cdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFsnY2FydCcsICdjbGVhciddLFxuXHRcdFx0XHRcdFx0WydjYXJ0aXRlbScsICdhZGQnICwgY2FydF9kYXRhXSwgXG5cdFx0XHRcdFx0XHRbJ2V2ZW50JywgJ2NhcnQnXVxuXHRcdFx0XHRcdF0pOyBcblx0XHRcdFx0fVxuXHRcdFx0fSwgMzAwMCk7XG5cdFx0fVxuXHRcdFxuXHRcdGZ1bmN0aW9uIGNvcmRpYWxDbGVhckNhcnQoKSB7XG5cdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHQgICAgJ3N0YXR1cyc6ICdlbXB0eSdcblx0XHRcdFx0fTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFsnY2FydCcsICdjbGVhciddLFxuXHRcdFx0XHRcdFx0WydldmVudCcsICdjYXJ0JywgcHJvcGVydGllc11cblx0XHRcdFx0XHRdKTsgXG5cdFx0XHRcdH1cblx0XHRcdH0sIDMwMDApO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoJChkb2N1bWVudCkuZmluZCgnLnB0X2NhcnQnKS5sZW5ndGggPiAwIHx8ICQoZG9jdW1lbnQpLmZpbmQoJy5wdF9vbmVwY2hlY2tvdXQnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRpZigkKCcub3JkZXItaXRlbScpLmxlbmd0aCA+IDApe1xuXHRcdFx0XHRjb3JkaWFsVXBkYXRlQ2FydCgpO1xuXHRcdCAgICB9IGVsc2Uge1x0XHQgICAgXHRcblx0XHQgICAgXHRjb3JkaWFsQ2xlYXJDYXJ0KCk7XG5cdFx0ICAgIH1cblx0XHR9XG5cdFx0XG5cdFx0JCgnYm9keScpLm9uKCdjaGFuZ2UnLCAnaW5wdXQub3BjLXF0eScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRjb3JkaWFsVXBkYXRlQ2FydCgpO1xuXHRcdH0pO1xuXHRcdFxuXHRcdCQoJ2JvZHknKS5vbignY2xpY2snLCAnLmNhcnQtY2hhbmdlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdFx0aWYoJCgnLm9yZGVyLWl0ZW0nKS5sZW5ndGggPT0gMCl7XG5cdFx0XHRcdFx0Y29yZGlhbENsZWFyQ2FydCgpO1xuXHRcdFx0ICAgIH0gZWxzZSB7XG5cdFx0XHQgICAgXHRjb3JkaWFsVXBkYXRlQ2FydCgpO1xuXHRcdFx0ICAgIH1cdFxuXHQgICAgXHR9LCAyMDAwKTtcblx0XHR9KTtcblx0XHRcblx0XHQvLyBvcmRlciBldmVudCBjcmVhdGVkIG9uIGNvbmZpcm1hdGlvbjsgbXlhY2NvdW50IHNpZ251cFx0XG5cdFx0aWYgKCQoZG9jdW1lbnQpLmZpbmQoJy5vcmRlci1jb25maXJtYXRpb24tZGV0YWlscycpLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBvcmRlcklEID0gJCgnLm9yZGVyLWhpc3RvcnktaW5mbyBzcGFuLnZhbHVlJykuZmlyc3QoKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdHZhciBvcmRlcklEID0gJCgnLm9yZGVyZGV0YWlscyAuc2VjdGlvbmhlYWRlciBoMycpLnRleHQoKS5yZXBsYWNlKCdPcmRlciBOdW1iZXI6JywnJykudHJpbSgpO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGVtYWlsID0gJCgnLm9yZGVyLWJpbGxpbmctZW1haWwnKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0dmFyIHNoaXBwaW5nTmFtZSA9ICQoJy5vcmRlci1zaGlwcGluZy1uYW1lJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBzaGlwcGluZ0FkZHJlc3MyID0gJCgnLm9yZGVyLXNoaXBwaW5nLWFkZHJlc3MyJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBzaGlwcGluZ0FkZHJlc3MzID0gJCgnLm9yZGVyLXNoaXBwaW5nLWFkZHJlc3MzJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBzaGlwcGluZ0FkZHJlc3MgPSAkKCcub3JkZXItc2hpcHBpbmctYWRkcmVzczEnKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0aWYoc2hpcHBpbmdBZGRyZXNzMikgeyBcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzICs9IFwiLCBcIiArIHNoaXBwaW5nQWRkcmVzczI7XG5cdFx0XHR9XG5cdFx0XHRpZihzaGlwcGluZ0FkZHJlc3MzKSB7IFxuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3MgKz0gXCIsIFwiICsgc2hpcHBpbmdBZGRyZXNzMztcblx0XHRcdH1cblx0XHRcdHZhciBzaGlwcGluZ0NpdHkgPSAkKCcub3JkZXItc2hpcHBpbmctZ2VvIC5jaXR5JykudGV4dCgpLnRyaW0oKS5yZXBsYWNlKCcsJywnJyk7XG5cdFx0XHR2YXIgc2hpcHBpbmdTdGF0ZSA9ICQoJy5vcmRlci1zaGlwcGluZy1nZW8gLnN0YXRlJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBzaGlwcGluZ1ppcCA9ICQoJy5vcmRlci1zaGlwcGluZy1nZW8gLnppcCcpLnRleHQoKS50cmltKCk7XG5cdFx0XHR2YXIgc2hpcHBpbmdDb3VudHJ5ID0gJCgnLm9yZGVyLXNoaXBwaW5nLWNvdW50cnknKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0dmFyIGJpbGxpbmdOYW1lID0gJCgnLm9yZGVyLWJpbGxpbmctbmFtZScpLnRleHQoKS50cmltKCk7XG5cdFx0XHR2YXIgYmlsbGluZ0FkZHJlc3MyID0gJCgnLm9yZGVyLWJpbGxpbmctYWRkcmVzczInKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0dmFyIGJpbGxpbmdBZGRyZXNzMyA9ICQoJy5vcmRlci1iaWxsaW5nLWFkZHJlc3MzJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBiaWxsaW5nQWRkcmVzcyA9ICQoJy5vcmRlci1iaWxsaW5nLWFkZHJlc3MxJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdGlmKGJpbGxpbmdBZGRyZXNzMikgeyBcblx0XHRcdFx0YmlsbGluZ0FkZHJlc3MgKz0gXCIsIFwiICsgYmlsbGluZ0FkZHJlc3MyO1xuXHRcdFx0fVxuXHRcdFx0aWYoYmlsbGluZ0FkZHJlc3MzKSB7IFxuXHRcdFx0XHRiaWxsaW5nQWRkcmVzcyArPSBcIiwgXCIgKyBiaWxsaW5nQWRkcmVzczM7XG5cdFx0XHR9XG5cdFx0XHR2YXIgYmlsbGluZ0NpdHkgPSAkKCcub3JkZXItYmlsbGluZy1nZW8gLmNpdHknKS50ZXh0KCkudHJpbSgpLnJlcGxhY2UoJywnLCcnKTtcblx0XHRcdHZhciBiaWxsaW5nU3RhdGUgPSAkKCcub3JkZXItYmlsbGluZy1nZW8gLnN0YXRlJykudGV4dCgpLnRyaW0oKTtcblx0XHRcdHZhciBiaWxsaW5nWmlwID0gJCgnLm9yZGVyLWJpbGxpbmctZ2VvIC56aXAnKS50ZXh0KCkudHJpbSgpO1xuXHRcdFx0dmFyIGJpbGxpbmdDb3VudHJ5ID0gJCgnLm9yZGVyLWJpbGxpbmctY291bnRyeScpLnRleHQoKS50cmltKCk7XG5cdFx0XHR2YXIgYmlsbGluZ1Bob25lID0gJCgnLm9yZGVyLWJpbGxpbmctcGhvbmUnKS50ZXh0KCkucmVwbGFjZSgnUGhvbmU6JywnJykudHJpbSgpO1xuXHRcdFx0XG5cdFx0XHR2YXIgbmFtZSA9IGJpbGxpbmdOYW1lLnNwbGl0KCcgJyk7XG5cdFx0XHR2YXIgZmlyc3ROYW1lID0gbmFtZVswXTtcblx0XHRcdHZhciBsYXN0TmFtZSA9IG5hbWVbbmFtZS5sZW5ndGgtMV07XG5cdFx0XHRcblx0XHRcdHZhciBpdGVtcyA9IFtdO1xuXHRcdFx0JCgnLm9yZGVyLWl0ZW0nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbCkge1xuXHRcdFx0XHR2YXIgX3RoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHRpdGVtc1tpbmRleF0gPSB7fTtcblx0XHRcdFx0X3RoaXMuZmluZCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEnKS5lYWNoKGZ1bmN0aW9uKGtleSwgdikge1xuXHRcdFx0XHRcdHZhciB0aGlzSXRlbSA9IEpTT04ucGFyc2UoJCh0aGlzKS5hdHRyKCdkYXRhLXByb2R1Y3QtZ3RtLWpzb24nKSk7XG5cdFx0XHRcdFx0dmFyIHByb2R1Y3QgPSB7fTtcdFxuXHRcdFx0XHRcdHByb2R1Y3QucHJvZHVjdElEID0gdGhpc0l0ZW1bXCJpZFwiXTtcblx0XHRcdFx0XHRwcm9kdWN0LnNrdSA9IHRoaXNJdGVtW1wic2t1aWRcIl07XG5cdFx0XHRcdFx0cHJvZHVjdC5jYXRlZ29yeSA9IHRoaXNJdGVtW1wiY2F0ZWdvcnlcIl0ucmVwbGFjZSgvXFxcXC9nLCBcIlwiKTtcblx0XHRcdFx0XHRwcm9kdWN0Lm5hbWUgPSB0aGlzSXRlbVtcIm5hbWVcIl0ucmVwbGFjZSgvXFxcXC9nLCBcIlwiKTtcblx0XHRcdFx0XHRwcm9kdWN0LnF0eSA9IHRoaXNJdGVtW1wicXVhbnRpdHlcIl07XG5cdFx0XHRcdFx0cHJvZHVjdC5pdGVtUHJpY2UgPSB0aGlzSXRlbVtcInByaWNlXCJdO1xuXHRcdFx0XHRcdHByb2R1Y3QuaW1hZ2VzID0gW190aGlzLmZpbmQoJ2ltZycpLmF0dHIoJ3NyYycpXTtcblx0XHRcdFx0XHRwcm9kdWN0LnVybCA9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyBfdGhpcy5maW5kKCcubmFtZScpLmZpbmQoJ2EnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdFx0cHJvZHVjdC5hdHRyID0geydtYW51ZmFjdHVyZXInOiB0aGlzSXRlbVtcImJyYW5kXCJdLCAnY29sb3InOiB0aGlzSXRlbVtcImNvbG9yXCJdLCAnc2l6ZSc6IHRoaXNJdGVtW1wic2l6ZVwiXSB9O1xuXHRcdFx0XHRcdGl0ZW1zW2luZGV4XT0gcHJvZHVjdDtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0dmFyIG9yZGVyX2RhdGEgPSB7XG5cdFx0XHQgIFwib3JkZXJJRFwiOiBvcmRlcklELFxuXHRcdFx0ICBcInNoaXBwaW5nQWRkcmVzc1wiOiB7XG5cdFx0XHQgICAgXCJuYW1lXCI6IHNoaXBwaW5nTmFtZSxcblx0XHRcdCAgICBcImFkZHJlc3NcIjogc2hpcHBpbmdBZGRyZXNzLFxuXHRcdFx0ICAgIFwiY2l0eVwiOiBzaGlwcGluZ0NpdHksXG5cdFx0XHQgICAgXCJzdGF0ZVwiOiBzaGlwcGluZ1N0YXRlLFxuXHRcdFx0ICAgIFwicG9zdGFsQ29kZVwiOiBzaGlwcGluZ1ppcCxcblx0XHRcdCAgICBcImNvdW50cnlcIjogc2hpcHBpbmdDb3VudHJ5XG5cdFx0XHQgIH0sXG5cdFx0XHQgIFwiYmlsbGluZ0FkZHJlc3NcIjoge1xuXHRcdFx0XHRcIm5hbWVcIjogYmlsbGluZ05hbWUsXG5cdFx0XHRcdFwiYWRkcmVzc1wiOiBiaWxsaW5nQWRkcmVzcyxcblx0XHRcdFx0XCJjaXR5XCI6IGJpbGxpbmdDaXR5LFxuXHRcdFx0XHRcInN0YXRlXCI6IGJpbGxpbmdTdGF0ZSxcblx0XHRcdFx0XCJwb3N0YWxDb2RlXCI6IGJpbGxpbmdaaXAsXG5cdFx0XHRcdFwiY291bnRyeVwiOiBiaWxsaW5nQ291bnRyeVxuXHRcdFx0ICB9LFxuXHRcdFx0ICBcIml0ZW1zXCI6IGl0ZW1zXG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHR2YXIgcHJvcGVydGllcyA9IHtcblx0XHRcdCAgICBcIm9yZGVySURcIjogb3JkZXJJRFxuXHRcdFx0fTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0ZW1haWw6IGVtYWlsXG5cdFx0XHR9XG5cdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0ICAgICdjaGFubmVscyc6IHtcblx0XHRcdCAgICAgICAgJ2VtYWlsJzoge1xuXHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbFxuXHRcdFx0ICAgICAgICB9XG5cdFx0XHQgICAgfSxcblx0XHRcdCAgICAnZmlyc3RfbmFtZSc6IGZpcnN0TmFtZSxcblx0XHRcdFx0J2xhc3RfbmFtZSc6IGxhc3ROYW1lLFxuXHRcdFx0XHQncGhvbmUnOiBiaWxsaW5nUGhvbmUsXG5cdFx0XHRcdCdwb3N0YWxfY29kZSc6IGJpbGxpbmdaaXAsXG5cdFx0XHRcdCdzb3VyY2VfY3JlYXRlJzogJ29yZGVyJyxcblx0XHRcdFx0J2dlb19sb2NhdGlvbic6IHtcblx0XHRcdFx0ICAgICdwb3N0YWxfY29kZSc6IGJpbGxpbmdaaXAsXG5cdFx0XHRcdCAgICAnY291bnRyeSc6IGJpbGxpbmdDb3VudHJ5LFxuXHRcdFx0XHQgICAgJ3N0YXRlJzogYmlsbGluZ1N0YXRlLFxuXHRcdFx0XHQgICAgJ2NpdHknOiBiaWxsaW5nQ2l0eVxuXHRcdFx0XHR9XG5cdFx0XHR9O1x0XHRcdFx0XG5cdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XHRcblx0XHRcdFx0Y3JkbChbXG5cdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFsnY2FydCcsICdjbGVhciddLFxuXHRcdFx0XHRcdFsnb3JkZXInLCAnYWRkJywgb3JkZXJfZGF0YV0sXG5cdFx0XHRcdFx0WydldmVudCcsICdvcmRlcicsIHByb3BlcnRpZXNdXG5cdFx0XHRcdF0pO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvLyBjcmVhdGUgQ29yZGlhbCBjb250YWN0IG9uIGNvbmZpcm1hdGlvbiBwYWdlXG5cdFx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcubGFyZ2VidXR0b25bbmFtZT1cImR3ZnJtX3Byb2ZpbGVfY29uZmlybVwiXScsIGZ1bmN0aW9uKCl7XG5cdFx0XHRcdHZhciBwYXNzd29yZCA9ICQoJy5wYXNzd29yZC1ob2xkZXIgLnBhc3N3b3JkJykudmFsKCk7XG5cdFx0XHRcdHZhciBwYXNzd29yZENvbmZpcm0gPSAkKCcucGFzc3dvcmQtaG9sZGVyIC5wYXNzd29yZC1jb25maXJtJykudmFsKCk7XG5cdFx0XHRcdHZhciBmb3JtVmFsaWRhdGlvbiA9IHRydWU7XG5cdFx0XHRcdHZhciBzaWdudXBFdmVudCA9IFwiXCI7XG5cblx0XHRcdFx0dmFyIHJlZ2V4UGFzc3dvcmQgPSAvXig/PS4qP1tBLXpdKSg/PS4qP1swLTldKSg/PS4qP1sjPyFcXD1cXC9cXCxcXC5cXH5cXGBcXChcXClcXHtcXH1cXFtcXF1cXFxcQF8kJV4mKi1dKS57NiwxNX0kL2c7XG5cdFx0XHRcdGlmICggU3RyaW5nKHBhc3N3b3JkKS5tYXRjaChyZWdleFBhc3N3b3JkKSA9PSBudWxsICkge1xuXHRcdFx0XHRcdGZvcm1WYWxpZGF0aW9uID0gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmIChwYXNzd29yZCAhPT0gcGFzc3dvcmRDb25maXJtKSB7XG5cdFx0XHRcdFx0Zm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCFwYXNzd29yZCB8fCAhcGFzc3dvcmRDb25maXJtKSB7XG5cdFx0XHRcdFx0Zm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKGZvcm1WYWxpZGF0aW9uICYmICQoJyNSZWdpc3RyYXRpb25Gb3JtIC5maWVsZC5lcnJvcicpLmxlbmd0aCA9PSAwKXtcdFx0XHRcdFx0XG5cdFx0XHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0XHRcdGVtYWlsOiBlbWFpbFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcblx0XHRcdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHRcdCAgICAnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdFx0ICAgICAgICAnZW1haWwnOiB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbFxuXHRcdFx0XHRcdCAgICAgICAgfVxuXHRcdFx0XHRcdCAgICB9LFxuXHRcdFx0XHRcdFx0J2ZpcnN0X25hbWUnOiBmaXJzdE5hbWUsXG5cdFx0XHRcdFx0XHQnbGFzdF9uYW1lJzogbGFzdE5hbWUsXG5cdFx0XHRcdFx0XHQncGhvbmUnOiBiaWxsaW5nUGhvbmUsXG5cdFx0XHRcdFx0XHQncG9zdGFsX2NvZGUnOiBiaWxsaW5nWmlwLFxuXHRcdFx0XHRcdFx0J3NvdXJjZV9jcmVhdGUnOiAnbXlhY2NvdW50Jyxcblx0XHRcdFx0XHRcdCdnZW9fbG9jYXRpb24nOiB7XG5cdFx0XHRcdFx0XHQgICAgJ3Bvc3RhbF9jb2RlJzogYmlsbGluZ1ppcCxcblx0XHRcdFx0XHRcdCAgICAnY291bnRyeSc6IGJpbGxpbmdDb3VudHJ5LFxuXHRcdFx0XHRcdFx0ICAgICdzdGF0ZSc6IGJpbGxpbmdTdGF0ZSxcblx0XHRcdFx0XHRcdCAgICAnY2l0eSc6IGJpbGxpbmdDaXR5XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHR2YXIgbG9naW5Qcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHRcdCAgICBcImVtYWlsXCI6IGVtYWlsXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiAoJCgnaW5wdXQjbmV3c2xldHRlcnNpZ251cCcpLmlzKCc6Y2hlY2tlZCcpKXtcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHRcdFx0ICAgICdjaGFubmVscyc6IHtcblx0XHRcdFx0XHRcdCAgICAgICAgJ2VtYWlsJzoge1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbCxcblx0XHRcdFx0XHRcdCAgICAgICAgICAgICdzdWJzY3JpYmVTdGF0dXMnOiAnc3Vic2NyaWJlZCdcblx0XHRcdFx0XHRcdCAgICAgICAgfVxuXHRcdFx0XHRcdFx0ICAgIH0sXG5cdFx0XHRcdFx0XHRcdCdmaXJzdF9uYW1lJzogZmlyc3ROYW1lLFxuXHRcdFx0XHRcdFx0XHQnbGFzdF9uYW1lJzogbGFzdE5hbWUsXG5cdFx0XHRcdFx0XHRcdCdwaG9uZSc6IGJpbGxpbmdQaG9uZSxcblx0XHRcdFx0XHRcdFx0J3Bvc3RhbF9jb2RlJzogYmlsbGluZ1ppcCxcblx0XHRcdFx0XHRcdFx0J3NpZ251cF9zb3VyY2UnOiAnbXlhY2NvdW50Jyxcblx0XHRcdFx0XHRcdFx0J3NvdXJjZV9jcmVhdGUnOiAnbXlhY2NvdW50Jyxcblx0XHRcdFx0XHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0J2dlb19sb2NhdGlvbic6IHtcblx0XHRcdFx0XHRcdFx0ICAgICdwb3N0YWxfY29kZSc6IGJpbGxpbmdaaXAsXG5cdFx0XHRcdFx0XHRcdCAgICAnY291bnRyeSc6IGJpbGxpbmdDb3VudHJ5LFxuXHRcdFx0XHRcdFx0XHQgICAgJ3N0YXRlJzogYmlsbGluZ1N0YXRlLFxuXHRcdFx0XHRcdFx0XHQgICAgJ2NpdHknOiBiaWxsaW5nQ2l0eVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHR2YXIgcHJvcGVydGllcyA9IHtcblx0XHRcdFx0XHRcdCAgICBcInNpZ251cF9zb3VyY2VcIjogJ215YWNjb3VudCcsXG5cdFx0XHRcdFx0XHQgICAgXCJwYWdlXCI6ICdjb25maXJtYXRpb24nLFxuXHRcdFx0XHRcdFx0ICAgIFwid2VsY29tZV9zaWdudXBcIjogdHJ1ZVxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0c2lnbnVwRXZlbnQgPSBbJ2V2ZW50JywgJ2VtYWlsX3NpZ251cCcsIHByb3BlcnRpZXNdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0UmVxdWVzdEhlbHBlci5WYWxpZGF0ZSgnQ29yZGlhbC1FbWFpbFNpZ251cCcpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0XHRcdGNyZGwoW1x0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFx0XHRcdFsnZXZlbnQnLCAnYWNjb3VudF9jcmVhdGUnXSxcblx0XHRcdFx0XHRcdFx0XHRbJ2V2ZW50JywgJ2xvZ2luJywgbG9naW5Qcm9wZXJ0aWVzXSxcblx0XHRcdFx0XHRcdFx0XHRzaWdudXBFdmVudFxuXHRcdFx0XHRcdFx0XHRdKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KS5jYXRjaCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0XG5cdFx0Ly8gUGFzc3dvcmQgUmVzZXQgLSBObyBBY2NvdW50XG5cdFx0aWYgKCQoZG9jdW1lbnQpLmZpbmQoJy5yZXNldC1wYXNzd29yZCAubm8tYWNjb3VudCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBlbWFpbCA9ICQoJy5uby1hY2NvdW50JykudGV4dCgpO1xuXHRcblx0XHRcdHZhciBhdXRoX2RhdGEgPSB7XG5cdFx0XHRcdGVtYWlsOiBlbWFpbFxuXHRcdFx0fVxuXHRcdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdCAgICAnY2hhbm5lbHMnOiB7XG5cdFx0XHQgICAgICAgICdlbWFpbCc6IHtcblx0XHRcdCAgICAgICAgICAgICdhZGRyZXNzJzogZW1haWxcblx0XHRcdCAgICAgICAgfVxuXHRcdFx0ICAgIH1cblx0XHRcdH07XG5cdFx0XHRcblx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0ICAgIFwiZW1haWxcIjogZW1haWxcblx0XHRcdH07XG5cblx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0Y3JkbChbXG5cdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFsnZXZlbnQnLCAncmVzZXQtcGFzc3dvcmQtbm8tYWNjb3VudCcsIHByb3BlcnRpZXNdXG5cdFx0XHRcdF0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHQvLyBQYXNzd29yZCBSZXNldCBDb25maXJtYXRpb25cblx0XHRpZiAoJChkb2N1bWVudCkuZmluZCgnI3Bhc3N3b3JkLXJlc2V0LWNvbmZpcm0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHR2YXIgZW1haWwgPSAkKCcjcGFzc3dvcmQtcmVzZXQtY29uZmlybScpLmF0dHIoJ2RhdGEtZW1haWwnKTtcblx0XHRcdHZhciBwYXNzd29yZEV2ZW50ID0gXCJyZXNldC1wYXNzd29yZFwiO1xuXHRcdFx0XG5cdFx0XHRpZiAoJChkb2N1bWVudCkuZmluZCgnLm5vQWNjb3VudCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0dmFyIHBhc3N3b3JkRXZlbnQgPSBcInJlc2V0LXBhc3N3b3JkLW5vLWFjY291bnRcIjtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0ZW1haWw6IGVtYWlsXG5cdFx0XHR9XG5cdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0ICAgICdjaGFubmVscyc6IHtcblx0XHRcdCAgICAgICAgJ2VtYWlsJzoge1xuXHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbFxuXHRcdFx0ICAgICAgICB9XG5cdFx0XHQgICAgfVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHQgICAgXCJlbWFpbFwiOiBlbWFpbFxuXHRcdFx0fTtcblxuXHRcdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRbJ2NvbnRhY3QnLCBhdXRoX2RhdGEsIGNvbnRhY3RfZGF0YV0sXG5cdFx0XHRcdFx0WydldmVudCcsIHBhc3N3b3JkRXZlbnQsIHByb3BlcnRpZXNdXG5cdFx0XHRcdF0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHQvL0VORCBDT1JESUFMXG5cblx0XG5cdC8vIFJlbG9hZGluZyBsb2dpbiBwYWdlIGFmdGVyIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0IHcvIGVycm9yIG1lc3NhZ2luZyxcblx0Ly8gYW5kIHJldGFpbmluZyB1c2VybmFtZSBpZiAnUmVtZW1iZXIgbWUnIHdhcyBjaGVja2VkXG5cdGlmICh3aW5kb3cubG9jYXRpb24uaHJlZi5pbmRleE9mKCdyZXRyeScpID49IDApIHtcbiAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1lcnJvciAuaW52YWxpZC1sb2dpbicpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRpZiAod2luZG93LmxvY2F0aW9uLmhyZWYuaW5kZXhPZignPScpID49IDApIHtcblx0XHRcdHZhciB1c2VybmFtZSA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmLnNwbGl0KCc9JylbMV07XG5cdFx0XHQkKCdpbnB1dFtuYW1lKj1cImR3ZnJtX2xvZ2luX3VzZXJuYW1lXCJdJykudmFsKHVzZXJuYW1lKTtcblx0XHRcdCQoJ2lucHV0W25hbWUqPVwiZHdmcm1fbG9naW5fcmVtZW1iZXJtZVwiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHR9XG5cdH1cblx0IFxuXHQvLyBNYWtlIHRoaXMgbXkgc3RvcmUgY2xpY2sgZGVsZWdhdGlvblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcuYXNzaWduLXN0b3JlLWNvbnRhaW5lciAuYXNzaWduLXN0b3JlJywgZnVuY3Rpb24oZSl7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciBzdG9yZUlEID0gJCh0aGlzKS5wYXJlbnRzKCcuc3RvcmUnKS5kYXRhKCdpZCcpO1xuXHRcdCQuYWpheCh7XG5cdFx0XHR1cmwgOiBVcmxzLmFzc2lnblN0b3JlSWQsXG5cdFx0XHRkYXRhIDogeyBzdG9yZV9pZCA6IHN0b3JlSUQgfSxcblx0XHRcdG1ldGhvZCA6IFwiUE9TVFwiLFxuXHRcdFx0ZGF0YVR5cGUgOiBcIkpTT05cIixcblx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdGlmICggJ3N1Y2Nlc3MnIGluIGRhdGEgJiYgZGF0YVsnc3VjY2VzcyddID09IHRydWUgKSB7XG5cdFx0XHRcdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLnJldmlldycsIGZ1bmN0aW9uKGUpe1xuXHRcdGlmICh0eXBlb2YgJEJWICE9PSAndW5kZWZpbmVkJykge1xuXHRcdFx0dmFyIHByb2R1Y3RJRCA9ICQodGhpcykuZGF0YSgncHJvZHVjdC1pZCcpO1xuXHRcdFx0dmFyIGNhbXBhaWduSUQgPSAkKHRoaXMpLmRhdGEoJ2NhbXBhaWduLWlkJyk7XG5cdFx0XHRpZiAodHlwZW9mIHByb2R1Y3RJRCAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdFx0cHJvZHVjdElEID0gcHJvZHVjdElELnRvU3RyaW5nKCk7XG5cdFx0XHRcdGlmIChwcm9kdWN0SUQubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiAodHlwZW9mICRCViAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdFx0XHRcdCRCVi51aShcInJyXCIsIFwic3VibWl0X3Jldmlld1wiLCB7cHJvZHVjdElkOiBwcm9kdWN0SUQsIGNhbXBhaWduSWQ6IGNhbXBhaWduSUR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXHRcblx0Ly9CYXphYXJWb2ljZSAtIGNsaWNrIG9uIHBkcCBpbmxpbmUgcmF0aW5nIHNjcm9sbHMgZG93biB0byByZXZpZXdzIHRhYlxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNjcm9sbFRvUmV2aWV3cycpLm9uKCdjbGljay5TY3JvbGxUb1Jldmlld3MnLCAnLnBkcC1tYWluIC5yYXRpbmctY29udGFpbmVyJywgJy5idi1jb250ZW50LXBhZ2luYXRpb24tYnV0dG9ucy1pdGVtIC5idi1jb250ZW50LWJ0bicsIGZ1bmN0aW9uKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyIHNjcm9sbFRvcCA9ICQoJy5wcm9kdWN0LXJldmlld3MtY29udGFpbmVyJykub2Zmc2V0KCkudG9wIC0gMTA7XG5cdFx0XG5cdFx0JCgnaHRtbCwgYm9keScpLmFuaW1hdGUoe1xuXHQgICAgICAgIHNjcm9sbFRvcDogc2Nyb2xsVG9wXG5cdCAgICB9LCAyNTApO1xuXHR9KTtcblxuXHQvL0JhemFhclZvaWNlIHN5bmRpY2F0aW9uIG1lc3NhZ2Vcblx0c2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0aWYoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRcdGlmKCQoJyNCVlJSQ29udGFpbmVyJykubGVuZ3RoKXtcblx0XHRcdFx0JCgnLmJ2LWNvbnRlbnQtaXRlbScpLmVhY2goZnVuY3Rpb24oKXtcblx0XHRcdFx0XHR2YXIgb3JpZ2luUG9zdCA9ICQodGhpcykuZmluZCgnLmJ2LWNvbnRlbnQtcmVmZXJlbmNlLWRhdGEgLmJ2LW9yaWdpbi1wb3N0Jyk7XG5cdFx0XHRcdFx0aWYob3JpZ2luUG9zdC5sZW5ndGggPCAxKXtcblx0XHRcdFx0ICAgIFx0dmFyIHJlZmVyZW5jZU1zZyA9ICQodGhpcykuZmluZCgnLmJ2LWJhZGdlLXN5bmRpY2F0ZWQnKS50ZXh0KCk7XG5cdFx0XHRcdCAgICBcdCQodGhpcykuZmluZCgnLmJ2LWNvbnRlbnQtcmVmZXJlbmNlLWRhdGEnKS5hcHBlbmQoJzxzcGFuIGNsYXNzPVwiYnYtb3JpZ2luLXBvc3RcIj4nICsgcmVmZXJlbmNlTXNnICsgJzwvc3Bhbj4nKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fSwgNTAwKTtcblx0XG5cdC8vQmF6YWFyVm9pY2UgLSBoaWRlIGVtcHR5IGlubGluZSByYXRpbmdzIGFuZCByZXZpZXdzXG5cdGlmIChwYWdlQ29udGV4dCAmJiAndHlwZScgaW4gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQudHlwZSA9PSAncHJvZHVjdCcpIHsgIFxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdCAgICBcdHZhciByZXZpZXdDb3VudCA9ICQoJy5idl9udW1SZXZpZXdzX2NvbXBvbmVudF9jb250YWluZXIgLmJ2X3RleHQnKS5maXJzdCgpLnRleHQoKS5yZXBsYWNlKC9bKCldL2csXCJcIik7XG5cdCAgICBcdGlmKHBhcnNlSW50KHJldmlld0NvdW50KSA9PSAwIHx8ICQoJy5yYXRpbmctY29udGFpbmVyIC5pbWctc2VwYXJhdG9yJykubGVuZ3RoKXtcblx0ICAgIFx0XHQkKCcucmF0aW5nLWNvbnRhaW5lcicpLmhpZGUoKTtcblx0ICAgIFx0XHQkKCcucHJvZHVjdC1yZXZpZXdzLWNvbnRhaW5lcicpLmhpZGUoKTtcblx0ICAgIFx0fVxuXHQgICAgfSwgMjUwMCk7XG5cdH1cblx0XG5cdC8vQmF6YWFyVm9pY2UgLSBpbmplY3Rpbmcgc3R5bGVzaGVldCB0aGF0IG92ZXJyaWRlcyB2MiBzaGFkb3cgZG9tIGVsZW1lbnRzXG5cdGZ1bmN0aW9uIGFkZFN0eWxlKHN0eWxlcykge1xuXHRcdHZhciBjc3MgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuXHRcdGNzcy50eXBlID0gJ3RleHQvY3NzJztcblx0ICBcblx0XHRpZiAoY3NzLnN0eWxlU2hlZXQpe1xuXHRcdFx0Y3NzLnN0eWxlU2hlZXQuY3NzVGV4dCA9IHN0eWxlcztcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3NzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHN0eWxlcykpO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgYnZFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZGl2W2RhdGEtYnYtc2hvdz1cInJldmlld3NcIl0nKTtcblx0XHRpZiAoYnZFbGVtZW50ICYmIGJ2RWxlbWVudC5zaGFkb3dSb290KSB7XG5cdFx0XHRidkVsZW1lbnQuc2hhZG93Um9vdC5hcHBlbmRDaGlsZChjc3MpO1xuXHRcdH1cblx0fVxuICAgICBcbiAgICB2YXIgc3R5bGVzID0gJy5qc1FlSFguV3d4VUksIC5oUnJjRnouV3d4VUksIC5pRmNFY3YsIC5jWFZkQUMsIC5qc0JzUXMgaDMsIC5qcWtkRCwgLmdQc09ORiwgLmRWTXFtdiwgLmVkWkpqUiwgLmhreVR2aywgLmRZTGp5RywgLmZ5ZUNjSCwgLmZGTnFXQiwgLmxwbldFdSwgLmRtY1dVTiB7IGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudCB9JztcbiAgICBzdHlsZXMgKz0gJy5idl9yYXRpbmdfY29udGVudDIsIC5idl9yYXRpbmdfY29udGVudDMsIGRpdltyb2xlPVwicHJlc2VudGF0aW9uXCJdIHsgZGlzcGxheTogbm9uZTsgZmxleDogbm9uZSB9Jztcblx0c3R5bGVzICs9ICcuY0F0Z25QIHsgaGVpZ2h0OiAxMDAlOyBtYXJnaW46IDAgMTBweDsgcGFkZGluZy10b3A6IDEwcHggfSc7XG5cdHN0eWxlcyArPSAnLmpzUWVIWC5qc0JzUXMgeyBtYXJnaW46IC0yMHB4IDAgNXB4IH0nO1xuXHRzdHlsZXMgKz0gJy5sVGZESywgLmVVYW9TSywgLmpkRVlZdSwgLmdwUmZGdSB7IHBhZGRpbmc6IDBweCAxNnB4OyBib3JkZXItcmFkaXVzOiB1bnNldCB9Jztcblx0c3R5bGVzICs9ICcuallDUmUgeyBib3JkZXItcmFkaXVzOiB1bnNldCB9Jztcblx0c3R5bGVzICs9ICcuZVVhb1NLOmZvY3VzIHsgYm9yZGVyLWNvbG9yOiAjMzkzOTM5IH0nO1xuXHRzdHlsZXMgKz0gJy5qVHNTV1ogeyB0b3A6IDJweCB9JzsgIFxuXHRzdHlsZXMgKz0gJy5ncmRscVguakhVc0NoIHsgY29sb3I6ICMzOTM5MzkgfSc7XG5cdHN0eWxlcyArPSAnLmV3UFBZIHsgYm9yZGVyLWJvdHRvbTogbm9uZSB9Jztcblx0c3R5bGVzICs9ICcuak9KVnJWLCAuaGlPU1dmLCAuaGlPU1dmOmhvdmVyIHsgY29sb3I6ICNmZmZmZmY7IGJvcmRlci1yYWRpdXM6IHVuc2V0IH0nO1xuXHRzdHlsZXMgKz0gJ2RpdltpdGVtcHJvcD1cInJldmlld1JhdGluZ1wiXSwgLmdhVm1rRiwgLmlzdWpEcCB7IGRpc3BsYXk6IGlubGluZS1mbGV4OyB2ZXJ0aWNhbC1hbGlnbjogdG9wOyBwYWRkaW5nOiA2cHggMTJweCAwIDAgfSc7XG5cdHN0eWxlcyArPSAnLmRwS0ZQZyAuZ2FWbWtGIHsgcGFkZGluZzogM3B4IDEycHggMCAwIH0nO1xuXHRzdHlsZXMgKz0gJ0BtZWRpYSAobWF4LXdpZHRoOiA3NjdweCkgeyBkaXZbaXRlbXByb3A9XCJyZXZpZXdSYXRpbmdcIl0sIC5nYVZta0YsIC5pc3VqRHAgeyBkaXNwbGF5OiBibG9jazsgb3ZlcmZsb3c6IGhpZGRlbiB9fSc7XG5cdHN0eWxlcyArPSAnLmVHZFNlSiwgLmVEZVFDTSwgLmJtQWpRYyB7IGJvcmRlci1yYWRpdXM6IHVuc2V0IH0nO1xuXHRzdHlsZXMgKz0gJy5nQ0ZwR04geyBib3JkZXItY29sb3I6ICM3YTdhN2E7IGJvcmRlci1yYWRpdXM6IHVuc2V0IH0nO1xuXHRzdHlsZXMgKz0gJyNyZXZpZXdzX2NvbnRhaW5lciB7IG1hcmdpbi1ib3R0b206IDI1cHggfSc7XG5cdHN0eWxlcyArPSAnZGl2W2RhdGEtYnYtdj1cImNvbnRlbnRJdGVtXCJdLCAuZVlTV3htLCAuaURNenNuLCAua3VBVVFuIHsgYm9yZGVyLXRvcDogMXB4IHNvbGlkICNkMmQyZDA7IGJvcmRlci1ib3R0b206IG5vbmU7IHBhZGRpbmc6IDVweCB9Jztcblx0c3R5bGVzICs9ICcuaXN1akRwLCAuaWpjRG9hIHsgZGlzcGxheTogaW5saW5lOyB3aWR0aDogYXV0byB9Jztcblx0c3R5bGVzICs9ICcubGpOS09BLCAuZURaZEROIHsgcGFkZGluZzogNXB4IDAgMCB9Jztcblx0c3R5bGVzICs9ICcua2l1Y0JwIHsgd2lkdGg6IDE0cHg7IGhlaWdodDogMTRweCB9Jztcblx0c3R5bGVzICs9ICdkaXZbZGF0YS1idi12PVwiY29udGVudEhlYWRlclwiXSwgLmhYYm5saywgLmtNWXpicywgLmh2ZmFXSSwgLmhzU1BBQiwgLmhqb2p5QiB7IHdpZHRoOiAxMDAlOyBwYWRkaW5nOiAwcHggfSc7XG5cdHN0eWxlcyArPSAnaDMuZlhIZUtmLCBoMy5mQ095ck0sIGgzLmlDbVl2TywgaDMua0NLYWdHLCBoMy5iZVhYalosIGgzLmVMb0NNdyB7IGRpc3BsYXk6IGlubGluZTsgZm9udC1zaXplOiAxNXB4OyBmb250LXdlaWdodDogYm9sZDsgbWFyZ2luOiAwfSc7XG5cdHN0eWxlcyArPSAnaDMua0NLYWdHIHsgbGluZS1oZWlnaHQ6IDMwcHggfSc7XG5cdHN0eWxlcyArPSAnQG1lZGlhIChtYXgtd2lkdGg6IDc2N3B4KSB7IGgzLmZYSGVLZiwgaDMuZkNPeXJNIHsgbGluZS1oZWlnaHQ6IDIwcHggfX0nO1xuXHRzdHlsZXMgKz0gJ0BtZWRpYSAobWF4LXdpZHRoOiA3NjdweCkgeyBoMy5pQ21Zdk8geyBsaW5lLWhlaWdodDogMjBweDsgZGlzcGxheTogYmxvY2s7IHBhZGRpbmc6IDRweCAwIH19JztcdFxuXHRzdHlsZXMgKz0gJy5qUExpRm0geyBtYXJnaW46IDEwcHggMHB4IH0nO1xuXHRzdHlsZXMgKz0gJy5ma3RVaGMgeyBtYXJnaW4tdG9wOiAwcHggfSc7XG5cdHN0eWxlcyArPSAnLmJTQnJyUSB7IGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IG1hcmdpbi1ib3R0b206IDE4cHggfSc7XG5cdHN0eWxlcyArPSAnLmJTQnJyUSAuREdmVlMsIC5iU0JyclEgLmVEUXFzTywgLmJTQnJyUSAuZnFvSlhkLCAuYlNCcnJRIGJ1dHRvbiB7IGRpc3BsYXk6IGlubGluZTsgZm9udC1zdHlsZTogbm9ybWFsICFpbXBvcnRhbnQgfSc7XG5cdHN0eWxlcyArPSAnLmJTQnJyUSAuREdmVlMgaDMsIC5iU0JyclEgLmVEUXFzTyBoMywgLmJTQnJyUSAuZnFvSlggaDMgeyBkaXNwbGF5OiBpbmxpbmU7IG1hcmdpbi1yaWdodDogMTBweDsgZm9udC13ZWlnaHQ6IG5vcm1hbCB9Jztcblx0c3R5bGVzICs9ICcuaFlmRVVLIHsgd2lkdGg6IGF1dG87IG1hcmdpbi1yaWdodDogMTBweCB9Jztcblx0c3R5bGVzICs9ICcuYlNCcnJRIGJ1dHRvbiB7IGRpc3BsYXk6IGlubGluZS1mbGV4OyB3aWR0aDogYXV0bzsgZm9udC13ZWlnaHQ6IHVuc2V0ICFpbXBvcnRhbnQ7IG1hcmdpbi1yaWdodDogMTBweCB9Jztcblx0c3R5bGVzICs9ICcuYlNCcnJRIGJ1dHRvbiBtZXRhIHsgZGlzcGxheTogaW5saW5lOyB9Jztcblx0c3R5bGVzICs9ICcuYlNCcnJRIC5mdEFZT2ksIC5iU0JyclEgLmR4UXREVSwgLmJTQnJyUSAuYk5LQXB1LCAuYlNCcnJRIC5keFF0RFUgeyBkaXNwbGF5OiBpbmxpbmU7IG1pbi13aWR0aDogdW5zZXQ7IG1heC13aWR0aDogdW5zZXQgfSc7XG5cdHN0eWxlcyArPSAnLmJTQnJyUSAuZHhRdERVLCAuYlNCcnJRIC5qV0docXIgeyBmb250LXN0eWxlOiBpdGFsaWMgfSc7XG5cdHN0eWxlcyArPSAnQG1lZGlhIChtYXgtd2lkdGg6IDc2N3B4KSB7IC5iU0JyclEgYnV0dG9uIHsgd2lkdGg6IGF1dG87IGZvbnQtc3R5bGU6IHVuc2V0ICFpbXBvcnRhbnQ7IG1hcmdpbi1yaWdodDogMTBweCB9fSc7XG5cdHN0eWxlcyArPSAnLkJkYmRZLCAuaGNuTGdhLCAua3RPbGtjIHsgbWFyZ2luOiAxNXB4IDBweCAxMHB4IH0nO1xuXHRzdHlsZXMgKz0gJy5CZGJkWSBkaXYsIC5oY25MZ2EgZGl2LCAua3RPbGtjIGRpdiB7IHBhZGRpbmc6IDVweCAxMHB4OyBib3JkZXItcmFkaXVzOiB1bnNldCB9Jztcblx0c3R5bGVzICs9ICdsaVtyb2xlPVwicHJlc2VudGF0aW9uXCJdIHsgZGlzcGxheTogaW5saW5lLWZsZXggfSc7XG5cdHN0eWxlcyArPSAnbGlbcm9sZT1cInByZXNlbnRhdGlvblwiXSBidXR0b24geyBoZWlnaHQ6IDQwcHg7IHdpZHRoOiA0MHB4OyBib3JkZXItcmFkaXVzOiB1bnNldCB9Jztcblx0c3R5bGVzICs9ICdsaVtyb2xlPVwicHJlc2VudGF0aW9uXCJdIGEgeyBoZWlnaHQ6IDQwcHg7IHdpZHRoOiA0MHB4OyBib3JkZXItcmFkaXVzOiB1bnNldDsgcGFkZGluZy10b3A6IDEwcHggfSc7XG5cdHN0eWxlcyArPSAnbGlbcm9sZT1cInByZXNlbnRhdGlvblwiXSBhOmhvdmVyIHsgYmFja2dyb3VuZC1jb2xvcjogI2VmZWZlZiB9Jztcblx0c3R5bGVzICs9ICcuZ29jd3VGIHsgYm9yZGVyLXJhZGl1czogdW5zZXQ7IG1hcmdpbi1ib3R0b206IDAgfSc7XG5cdHN0eWxlcyArPSAnLmt4VXludiwgLmtuZFBueCB7IGJvcmRlci1yYWRpdXM6IHVuc2V0OyBtYXJnaW4tYm90dG9tOiA1cHggfSc7XG5cdHN0eWxlcyArPSAnZGl2W2RhdGEtYnYtdj1cImNvbnRlbnRTdW1tYXJ5XCJdLCAuYkJ1SUZaLCAuRUZDeUgsIC5reU5KZ0IgeyBtYXJnaW46IDA7IHBhZGRpbmc6IDAgfSc7XG5cdHN0eWxlcyArPSAnQG1lZGlhIChtYXgtd2lkdGg6IDc2N3B4KSB7IC5FRkN5SCB7IHBhZGRpbmc6IDJweCAycHggMHB4OyB9fSc7XG5cdHN0eWxlcyArPSAnLmtzc0dvViB7IGJhY2tncm91bmQ6IG5vbmUgfSc7XG5cdHN0eWxlcyArPSAnLmpydUhFYyB7IG1hcmdpbjogMHB4IH0nO1xuXHRzdHlsZXMgKz0gJy5QTkN2cCB7IGNvbG9yOiAjZmZmZmZmIH0nO1xuXHRzdHlsZXMgKz0gJy5oUXpIYm0geyBoZWlnaHQ6IDUwMHB4IH0nO1xuXHRzdHlsZXMgKz0gJy5oUXpIYm0gLmNBdGduUCB7IG1hcmdpbjogMDsgcGFkZGluZy10b3A6IDAgfSc7XG5cdHN0eWxlcyArPSAnLmhRekhibSAuaHF1RHJ0IHsgaGVpZ2h0OiBjYWxjKDk1dmgpIH0nO1xuXHRzdHlsZXMgKz0gJy5oUXpIYm0gZGl2W2RhdGEtYnYtdj1cImNvbnRlbnRJdGVtXCJdIHsgYm9yZGVyOiBub25lOyBwYWRkaW5nOiA1cHggfSc7XG5cdHN0eWxlcyArPSAnLmhRekhibSAuaWN5dGwgeyBmb250LXNpemU6IDIwcHggfSc7XG5cdHN0eWxlcyArPSAnLmhRekhibSAuaWN5dGwgc3ZnIHsgd2lkdGg6IDIwcHg7IGhlaWdodDogMjBweCB9Jztcblx0c3R5bGVzICs9ICcuaFF6SGJtIGgzLmtDS2FnRywgLmhRekhibSBoMy5iZVhYalosIC5oUXpIYm0gaDMuZUxvQ013IHsgZm9udC1zaXplOiAyMHB4OyBsaW5lLWhlaWdodDogMjVweCB9JztcblxuXHRpZiAocGFnZUNvbnRleHQgJiYgJ3R5cGUnIGluIHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0LnR5cGUgPT0gJ3Byb2R1Y3QnKSB7ICBcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0YWRkU3R5bGUoc3R5bGVzKVxuXHRcdH0sIDI1MDApO1xuXHR9XG4gICAgXG4gICAgLyovL0JhemFhclZvaWNlIGFkZCBSZXZpZXcvUmV2aWV3cyB0ZXh0IHRvIGlubGluZSByYXRpbmdzIGNvdW50IFxuXHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgIFx0dmFyIHJldmlld0NvdW50ID0gJCgnLmJ2X251bVJldmlld3NfY29tcG9uZW50X2NvbnRhaW5lciAuYnZfdGV4dCcpLmZpcnN0KCkudGV4dCgpLnJlcGxhY2UoL1soKV0vZyxcIlwiKTtcbiAgICBcdHZhciByZXZpZXdUZXh0ID0gcGFyc2VJbnQocmV2aWV3Q291bnQpID4gMSA/IFJlc291cmNlcy5SRVZJRVdTIDogUmVzb3VyY2VzLlJFVklFV19URVhUO1xuICAgIFx0JCgnLmJ2X251bVJldmlld3NfY29tcG9uZW50X2NvbnRhaW5lciAuYnZfdGV4dCcpLnRleHQoJygnICsgcmV2aWV3Q291bnQgKyAnICcgKyByZXZpZXdUZXh0ICsgJyknKTtcbiAgICB9LCAzMDAwKTtcblxuXHRzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcblx0XHRDaGVja2xvZ2luQ3JlYXRlKCk7XG5cdH0sIDIwMDApOyovXG5cdFxuXHQkKCcuc2VjdGlvbi1ncm91cCAuc2VjdGlvbi1ib2R5Omxhc3QnKS5hcHBlbmQoJCgnLnNlY3Rpb24tcmV2aWV3cycpKTtcblxuXHQkKFwiLnB0X2N1c3RvbWVyLXNlcnZpY2UgI3NlY29uZGFyeSAubmF2LXRpdGxlXCIpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdCQodGhpcykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdCQoXCIucHRfY3VzdG9tZXItc2VydmljZSAjc2Vjb25kYXJ5ICNjdXN0b21lci1zZXJ2aWNlLW5hdlwiKS5zbGlkZVRvZ2dsZSgpO1xuXHR9KTtcdFxuXG5cdHNlYXJjaGJhci5pbml0KCk7XG5cdFx0XG5cdGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdHZhciBidG4gPSAkKCcjYmFjay10by10b3AnKSxcblx0XHRzY3JvbGxfcG9zaXRpb24gPSAyMTAwO1xuXHRcdFxuXHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRcdHNjcm9sbF9wb3NpdGlvbiA9IDI3NzE7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA+IDc2Nykge1xuICAgIFx0XHQkKCcjbWFpbicpLnByZXBlbmQoJzxkaXYgY2xhc3M9XCJtZW51LWhvdmVyLW92ZXJsYXlcIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj48L2Rpdj4nKTtcblx0ICAgIFx0XG5cdCAgICBcdCQoJy5oYXMtZHJvcGRvd24ubmF2LW1lbnUnKS5ob3Zlcihcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCgnI3dyYXBwZXInKS5hZGRDbGFzcygnbWVudS1hY3RpdmUnKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCgnI3dyYXBwZXInKS5yZW1vdmVDbGFzcygnbWVudS1hY3RpdmUnKTtcblx0XHRcdFx0fVxuICAgIFx0ICAgICk7XG4gICAgXHR9XG5cdFx0XG5cdFx0JCh3aW5kb3cpLnNjcm9sbChmdW5jdGlvbigpIHtcblx0XHQgIGlmICgkKHdpbmRvdykuc2Nyb2xsVG9wKCkgPiBzY3JvbGxfcG9zaXRpb24pIHtcblx0XHQgICAgYnRuLmFkZENsYXNzKCdzaG93Jyk7XG5cdFx0ICB9IGVsc2Uge1xuXHRcdCAgICBidG4ucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0XHQgIH1cblx0XHR9KTtcblxuXHRcdGJ0bi5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG5cdFx0ICBlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7c2Nyb2xsVG9wOjB9LCBzY3JvbGxfcG9zaXRpb24pO1xuXHRcdH0pO1xuXG5cdFx0aWYoJCgnLmhvbWVwYWdlLTAzIC5jb250ZW50LWFzc2V0LWJvZHknKS5sZW5ndGggPj0gMSkge1xuXHRcdFx0dmFyIHNsb3RfcG9zaXRpb24gPSAkKCcuaG9tZXBhZ2UtMDMgLmNvbnRlbnQtYXNzZXQtYm9keScpLmF0dHIoJ3Nsb3QtcG9zaXRpb24nKS50cmltKCk7XG5cdFx0XHRpZihzbG90X3Bvc2l0aW9uICE9ICczJyl7XG5cdFx0XHRcdHZhciBwcm9tb19zbG90ID0gJCgnLnNoZWxsLmhvbWVwYWdlLTAzJykuaHRtbCgpLFxuXHRcdFx0XHRiZWZvcmVfdGhpc19zbG90ID0gJy5ob21lcGFnZS0wJyArIHBhcnNlSW50KHNsb3RfcG9zaXRpb24sIDEwKTtcblx0XHRcdFx0JCgnLnNoZWxsLmhvbWVwYWdlLTAzJykucmVtb3ZlKCk7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZihzbG90X3Bvc2l0aW9uID4gMyAmJiBzbG90X3Bvc2l0aW9uIDwgOCl7XG5cdFx0XHRcdFx0YmVmb3JlX3RoaXNfc2xvdCA9ICcuaG9tZXBhZ2UtMCcgKyAocGFyc2VJbnQoc2xvdF9wb3NpdGlvbiwgMTApICsgMSk7XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYoc2xvdF9wb3NpdGlvbiA+IDcpe1xuXHRcdFx0XHRcdCQoJy5zaGVsbCcgKyBiZWZvcmVfdGhpc19zbG90KS5hZnRlcignPGRpdiBjbGFzcz1cInNoZWxsIGhvbWVwYWdlLTAzXCI+JyArIHByb21vX3Nsb3QgKyAnPC9kaXY+Jyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JCgnLnNoZWxsJyArIGJlZm9yZV90aGlzX3Nsb3QpLmJlZm9yZSgnPGRpdiBjbGFzcz1cInNoZWxsIGhvbWVwYWdlLTAzXCI+JyArIHByb21vX3Nsb3QgKyAnPC9kaXY+Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR2YXIgYnJhbmRzX2NvdW50ID0gJCgnLmJyYW5kJykubGVuZ3RoO1xuXHR2YXIgc3R5bGVzX2NvdW50ID0gJCgnLnN0eWxlJykubGVuZ3RoO1xuXHR2YXIgdG9lc3R5bGVfY291bnQgPSAkKCcudG9lLXN0eWxlJykubGVuZ3RoO1xuXG5cdGlmKGJyYW5kc19jb3VudCA8IDE2KSB7XG5cdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxicmFuZHMnKS5oaWRlKCk7XG5cdH1cblxuXHRpZihzdHlsZXNfY291bnQgPCA4KSB7XG5cdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxzdHlsZXMnKS5oaWRlKCk7XG5cdH1cblxuXHRpZih0b2VzdHlsZV9jb3VudCA8IDgpIHtcblx0XHQkKCcucHRfY29udGVudCAudmlld2FsbHRvZXMnKS5oaWRlKCk7XG5cdH1cblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcuY2EtaGVhZGVyLWNvbnRhY3QtaW5mbycsZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZih3aW5kb3cuaW5uZXJXaWR0aCA+IDc2Nykge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0pO1xuXHRcblx0LyppZih3aW5kb3cuaW5uZXJXaWR0aCA8IDc2NyApIHtcblx0XHRpZihzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdFx0JCgnLnByb2R1Y3QtbGlzdGluZy0xeDQgLmdyaWQtdGlsZScpLmVhY2goZnVuY3Rpb24oKXtcblx0XHRcdFx0JCh0aGlzKS5maW5kKCcucHJvZHVjdC1jb250ZW50JykuYmVmb3JlKCc8ZGl2IGNsYXNzPVwic2F2aW5ncy1iYXJcIj48L2Rpdj4nKTtcblx0XHRcdCAgICBpZigkKHRoaXMpLmZpbmQoJy5wcm9kdWN0LXNhbGVzLXByaWNlJykubGVuZ3RoICE9PSAwKXtcblx0XHRcdCAgICBcdHZhciAkcHJvbW9Nc2cgPSAkKHRoaXMpLmZpbmQoJy5wcm9kdWN0LXNhbGVzLXByaWNlJykudGV4dCgpLnRyaW0oKS5yZXBsYWNlKCdZb3UgU2F2ZTonLCAnU2F2ZScpO1xuXHRcdFx0ICAgIFx0JCh0aGlzKS5maW5kKCcuc2F2aW5ncy1iYXInKS5jc3MoJ2JhY2tncm91bmQtY29sb3InLCcjRTNFQ0VFJykudGV4dCgkcHJvbW9Nc2cpLnNob3coKTtcblx0XHRcdCAgICB9XHRcblx0XHRcdH0pO1xuXHRcdH1cblx0fSovXG5cblx0aWYod2luZG93LmlubmVyV2lkdGggPCA3NjcgKSB7XG5cdFx0aWYoYnJhbmRzX2NvdW50ID4gOCkge1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxicmFuZHMnKS5zaG93KCk7XG5cdFx0fVxuXG5cdFx0JCgnLnB0X2NvbnRlbnQgLnN0eWxlOm50aC1jaGlsZChuKzkpJykuY3NzKHsnZGlzcGxheSc6J25vbmUnfSk7XG5cdFx0JCgnLnB0X2NvbnRlbnQgLnRvZS1zdHlsZTpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidub25lJ30pO1xuXG5cdFx0aWYgKCQoJy50b3AtYmFubmVyLWJhcicpLmF0dHIoJ2RhdGEtaGVhZGVyLWZvcicpICE9ICdib290YmFybl91cycpIHtcblx0XHRcdCQoJy5wdF9zdG9yZWZyb250IC5saXN0LXJldmlldy1wcm9kdWN0cyBsaSAub2ZmZXItbGlzdCcpLnNsaWRlVXAoKTtcblx0XHRcdCQoJy5wdF9zdG9yZWZyb250IC5vZmZlci1oZWFkIGgyJykuYWRkQ2xhc3MoJ2Nsb3NlJyk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdCQoJy5wdF9jb250ZW50IC5zdHlsZTpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidibG9jayd9KTtcblx0XHQkKCcucHRfY29udGVudCAudG9lLXN0eWxlOm50aC1jaGlsZChuKzkpJykuY3NzKHsnZGlzcGxheSc6J2Jsb2NrJ30pO1xuXHR9XG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywnLnB0X2NvbnRlbnQgLnZpZXdhbGxicmFuZHMnLGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRpZigkKCcucHRfY29udGVudCAudmlld2FsbGJyYW5kcycpLmhhc0NsYXNzKFwiZXhwYW5kZWRcIikpIHtcblx0XHRcdCQoJy5wdF9jb250ZW50IC52aWV3YWxsYnJhbmRzJykucmVtb3ZlQ2xhc3MoXCJleHBhbmRlZFwiKTtcblx0XHRcdCQoJy5wdF9jb250ZW50IC5icmFuZDpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidub25lJ30pO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxicmFuZHMnKS5odG1sKFJlc291cmNlcy5TSE9XTU9SRUJSQU5EUyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5wdF9jb250ZW50IC52aWV3YWxsYnJhbmRzJykuYWRkQ2xhc3MoXCJleHBhbmRlZFwiKTtcblx0XHRcdCQoJy5wdF9jb250ZW50IC5icmFuZDpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidibG9jayd9KTtcblx0XHRcdCQoJy5wdF9jb250ZW50IC52aWV3YWxsYnJhbmRzJykuaHRtbChSZXNvdXJjZXMuQ0xPU0UpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywnLnB0X2NvbnRlbnQgLnZpZXdhbGxzdHlsZXMnLGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRpZigkKCcucHRfY29udGVudCAudmlld2FsbHN0eWxlcycpLmhhc0NsYXNzKFwiZXhwYW5kZWRcIikpIHtcblx0XHRcdCQoJy5wdF9jb250ZW50IC52aWV3YWxsc3R5bGVzJykucmVtb3ZlQ2xhc3MoXCJleHBhbmRlZFwiKTtcblx0XHRcdCQoJy5wdF9jb250ZW50IC5zdHlsZTpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidub25lJ30pO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxzdHlsZXMnKS5odG1sKFJlc291cmNlcy5TSE9XTU9SRVNUWUxFKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxzdHlsZXMnKS5hZGRDbGFzcyhcImV4cGFuZGVkXCIpO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnN0eWxlOm50aC1jaGlsZChuKzkpJykuY3NzKHsnZGlzcGxheSc6J2Jsb2NrJ30pO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGxzdHlsZXMnKS5odG1sKFJlc291cmNlcy5DTE9TRSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcucHRfY29udGVudCAudmlld2FsbHRvZXMnLGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRpZigkKCcucHRfY29udGVudCAudmlld2FsbHRvZXMnKS5oYXNDbGFzcyhcImV4cGFuZGVkXCIpKSB7XG5cdFx0XHQkKCcucHRfY29udGVudCAudmlld2FsbHRvZXMnKS5yZW1vdmVDbGFzcyhcImV4cGFuZGVkXCIpO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnRvZS1zdHlsZTpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidub25lJ30pO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnZpZXdhbGx0b2VzJykuaHRtbChSZXNvdXJjZXMuU0hPV01PUkVUT0UpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcucHRfY29udGVudCAudmlld2FsbHRvZXMnKS5hZGRDbGFzcyhcImV4cGFuZGVkXCIpO1xuXHRcdFx0JCgnLnB0X2NvbnRlbnQgLnRvZS1zdHlsZTpudGgtY2hpbGQobis5KScpLmNzcyh7J2Rpc3BsYXknOidibG9jayd9KTtcblx0XHRcdCQoJy5wdF9jb250ZW50IC52aWV3YWxsdG9lcycpLmh0bWwoUmVzb3VyY2VzLkNMT1NFKTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuc3dhdGNoLWxpc3QgLnN3YXRjaDpub3QoLnNlbGVjdGVkKSBbY2xhc3MqPVwic3dhdGNoLWltXCJdJywgZnVuY3Rpb24oKSB7XG5cdFx0dmFyICRwYXJlbnRCbG9jayA9ICQodGhpcykuY2xvc2VzdCgnLnNsaWRlLCAuc3dhdGNoLWxpc3QnKTtcblx0XHR2YXIgJG1haW5JbWcgPSAkcGFyZW50QmxvY2suZmluZCgnLnByb2R1Y3QtaW1hZ2UgaW1nOmZpcnN0Jyk7XG5cdFx0dmFyIHN3YXRjaERhdGEgPSAkKHRoaXMpLmRhdGEoJ3RodW1iJyk7XG5cdFx0XG5cdFx0aWYgKHN3YXRjaERhdGEpIHtcblx0XHRcdCRtYWluSW1nLmF0dHIoJ2FsdCcsIHN3YXRjaERhdGEuYWx0KTtcblx0XHRcdCRtYWluSW1nLmF0dHIoJ3RpdGxlJywgc3dhdGNoRGF0YS50aXRsZSk7XG5cdFx0XHQkbWFpbkltZy5hdHRyKCdzcmMnLCBzd2F0Y2hEYXRhLnNyYyk7XG5cdFx0XHRcblx0XHRcdCRwYXJlbnRCbG9jay5maW5kKCcuc3dhdGNoJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJy5zd2F0Y2gnKS5hZGRDbGFzcygnc2VsZWN0ZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSAkKHRoaXMpLmNsb3Nlc3QoJy5zd2F0Y2gnKS5hdHRyKCdocmVmJyk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsJy55ZXMtYWx0cyBidXR0b24uYWx0QnV0dG9uJywgZnVuY3Rpb24oZSl7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciBhbHRIaWRkZW5Db3VudCA9ICQodGhpcykuY2xvc2VzdCgnLnllcy1hbHRzIHVsLnN3YXRjaC1saXN0JykuZmluZCgnLmhpZGRlbi1jb250ZW50JykubGVuZ3RoO1xuXHRcdHZhciBhbHRIaWRkZW5Ub2dnbGUgPSAnKyAnICsgYWx0SGlkZGVuQ291bnQ7XG5cdFx0JCh0aGlzKS50ZXh0KCAkKHRoaXMpLnRleHQoKS5pbmRleE9mKCcrJykgPj0gMCA/IFwiLSBMZXNzXCIgOiBhbHRIaWRkZW5Ub2dnbGUpO1xuXHRcdCQodGhpcykuY2xvc2VzdCgnLnllcy1hbHRzIHVsLnN3YXRjaC1saXN0JykuZmluZCgnLmhpZGRlbi1jb250ZW50JykudG9nZ2xlKCk7XG5cdH0pO1xuXG5cdC8vVGVybXMgYW5kIENvbmRpdGlvbnMgUG9wdXAgb24gQ2hlY2tvdXRcblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICdbZGlhbG9nLWNvbnRlbnRdJykub24oJ2NsaWNrJywgJ1tkaWFsb2ctY29udGVudF0nLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBcbiAgICAgICAgdmFyICR0aGlzID0gJChldmVudC5jdXJyZW50VGFyZ2V0KTtcbiAgICAgICAgdmFyICRjb250ZW50Q29udGFpbmVyID0gJCgkdGhpcy5hdHRyKCdkaWFsb2ctY29udGVudCcpKTtcbiAgICAgICAgXG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIGh0bWw6ICRjb250ZW50Q29udGFpbmVyLmh0bWwoKSxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICB0aXRsZTogJGNvbnRlbnRDb250YWluZXIuYXR0cigndGl0bGUnKSxcbiAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ2ZpeGVkIGNoZWNrb3V0LXRlcm1zJyArICgkY29udGVudENvbnRhaW5lci5hdHRyKCdkaWFsb2ctY2xhc3MnKSA/ICcgJyArICRjb250ZW50Q29udGFpbmVyLmF0dHIoJ2RpYWxvZy1jbGFzcycpIDogJycpLFxuICAgICAgICAgICAgICAgIGRyYWdnYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgIFx0XG5cdCAgICAgICAgICAgIFx0JCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuXHQgICAgICAgICAgICBcdCR0aGlzLnNjcm9sbFRvcCgwKTtcblx0ICAgICAgICAgICAgXHRlbWFpbEZvcm0uaW5pdGlhbGl6ZSgkdGhpcyk7XG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0ICAgICAgICAgICAgXHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG5cdCAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cdH0pO1xuXG5cdC8vUGFnZSBUb3AgZnVuY3Rpb25hbGl0eSBmb3IgcG9wdXAgY29udGVudCBpbiB0ZXJtcyBhbmQgY29uZGl0aW9uc1xuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJy51aS1kaWFsb2cgW2hyZWY9XCIjcGdUb3BcIl0nKS5vbignY2xpY2snLCAnLnVpLWRpYWxvZyBbaHJlZj1cIiNwZ1RvcFwiXScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHR2YXIgJHRoaXMgPSAkKGV2ZW50LmN1cnJlbnRUYXJnZXQpO1xuICAgIFx0JHRoaXMuY2xvc2VzdCgnLnVpLWRpYWxvZy1jb250ZW50Jykuc2Nyb2xsVG9wKDApO1xuICAgIH0pO1xuXG5cdCQoJy52aWRlby1wbGF5LWJ0bicpXG5cdC5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHZpZGVvID0gJHRoaXMuY2xvc2VzdCgnLnZpZGVvJyk7XG5cdFx0dmFyICRpZnJhbWUgPSAkdmlkZW8uZmluZCgnaWZyYW1lJyk7XG5cdFx0dmFyIG9yaWdpbmFsU1JDID0gJHZpZGVvLmZpbmQoJ2lmcmFtZScpLmF0dHIoJ3NyYycpLnJlcGxhY2UoJz9hdXRvcGxheT0xJywnJyk7XG5cdFx0dmFyIHZpZGVvSHRtbCA9ICQodGhpcykubmV4dCgnaWZyYW1lJykucHJvcCgnb3V0ZXJIVE1MJyk7XG5cdFx0dmlkZW9IdG1sID0gdmlkZW9IdG1sLnJlcGxhY2UoL3NyYz1cIi4rP1wiLywgJ3NyYz1cIicgKyBvcmlnaW5hbFNSQyArICc/YXV0b3BsYXk9MVwiJyk7XG5cdFx0ZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgaHRtbDoodmlkZW9IdG1sKSxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIFx0d2lkdGg6IDU2MCxcbiAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ3ZpZGVvcG9wdXAnLFxuICAgICAgICAgICAgICAgIHRpdGxlOiAkdmlkZW8uZmluZCgnLnZpZGVvLWNhcHRpb24nKS50ZXh0KCksXG4gICAgICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIFx0JCgnLnVpLWRpYWxvZycpLmZpbmQoJ2lmcmFtZScpLmF0dHIoJ3NyYycsICcnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXHRcdH0pO1xuXG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHR9KVxuXG5cdFxuXHQvL1ByZXBhcmUgZm9yIHRvdWNoL21lbnVcblx0aWYgKHV0aWwuaXNUb3VjaERldmljZSgpKSB7XG5cdFx0JCgnYm9keScpLmFkZENsYXNzKCd0b3VjaERldmljZScpO1xuXHR9XG5cdGlmKHdpbmRvdy5uYXZpZ2F0b3IucGxhdGZvcm0ubWF0Y2goXCJpKFdpbilcIikpe1xuXHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnaXNXaW4nKVxuXHR9XG5cdFxuXHRpZiAoc2l0ZU5hbWUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgc2l0ZU5hbWUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHRpZih3aW5kb3cuaW5uZXJXaWR0aCA8IDc2Nykge1xuXHRcdFx0aWYgKCQoJy5oZWFkZXItYmFubmVyJykuY2hpbGRyZW4oKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0JCgnLnRvcC1iYW5uZXInKS5hZGRDbGFzcygnbm8tdG9wJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdFxuICAgICQoJ2JvZHknKVxuICAgICAgICAub24oJ2tleWRvd24nLCAndGV4dGFyZWFbZGF0YS1jaGFyYWN0ZXItbGltaXRdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0ID0gJC50cmltKCQodGhpcykudmFsKCkpLFxuICAgICAgICAgICAgICAgIGNoYXJzTGltaXQgPSAkKHRoaXMpLmRhdGEoJ2NoYXJhY3Rlci1saW1pdCcpLFxuICAgICAgICAgICAgICAgIGNoYXJzVXNlZCA9IHRleHQubGVuZ3RoO1xuXG4gICAgICAgICAgICBpZiAoKGNoYXJzVXNlZCA+PSBjaGFyc0xpbWl0KSAmJiAoY29udHJvbEtleXMuaW5kZXhPZihlLndoaWNoLnRvU3RyaW5nKCkpIDwgMCkpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignY2hhbmdlIGtleXVwIG1vdXNldXAnLCAndGV4dGFyZWFbZGF0YS1jaGFyYWN0ZXItbGltaXRdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRleHQgPSAkLnRyaW0oJCh0aGlzKS52YWwoKSksXG4gICAgICAgICAgICAgICAgY2hhcnNMaW1pdCA9ICQodGhpcykuZGF0YSgnY2hhcmFjdGVyLWxpbWl0JyksXG4gICAgICAgICAgICAgICAgY2hhcnNVc2VkID0gdGV4dC5sZW5ndGgsXG4gICAgICAgICAgICAgICAgY2hhcnNSZW1haW4gPSBjaGFyc0xpbWl0IC0gY2hhcnNVc2VkO1xuXG4gICAgICAgICAgICBpZiAoY2hhcnNSZW1haW4gPCAwKSB7XG4gICAgICAgICAgICAgICAgJCh0aGlzKS52YWwodGV4dC5zbGljZSgwLCBjaGFyc1JlbWFpbikpO1xuICAgICAgICAgICAgICAgIGNoYXJzUmVtYWluID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJCh0aGlzKS5uZXh0KCdkaXYuY2hhci1jb3VudCcpLmZpbmQoJy5jaGFyLXJlbWFpbi1jb3VudCcpLmh0bWwoY2hhcnNSZW1haW4pO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2NsaWNrJywnLnB0X3N0b3JlZnJvbnQgLm9mZmVyLWhlYWQgaDInLGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgXHRpZih3aW5kb3cuaW5uZXJXaWR0aCA8IDc2NyAmJiAkKCcudG9wLWJhbm5lci1iYXInKS5hdHRyKCdkYXRhLWhlYWRlci1mb3InKSAhPSAnYm9vdGJhcm5fdXMnKSB7XG5cdCAgICAgICAgXHQkKHRoaXMpXG5cdCAgICAgICAgXHRcdC50b2dnbGVDbGFzcygnY2xvc2UnKVxuXHQgICAgICAgIFx0XHQuY2xvc2VzdCgnbGknKVxuXHQgICAgICAgIFx0XHQuZmluZCgnLm9mZmVyLWxpc3QnKVxuXHQgICAgICAgIFx0XHQuc2xpZGVUb2dnbGUoMjAwKTtcblx0XHRcdH0gZWxzZSBpZiAoJCgnLnRvcC1iYW5uZXItYmFyJykuYXR0cignZGF0YS1oZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuXHRcdFx0XHQkKHRoaXMpXG5cdFx0XHRcdFx0LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdC5jbG9zZXN0KCdsaScpXG5cdFx0XHRcdFx0LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdC5maW5kKCcub2ZmZXItbGlzdCcpXG5cdFx0XHRcdFx0LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdC5zbGlkZVRvZ2dsZSgyMDApO1xuXHRcdFx0fVxuXHRcdH0pXG5cdFx0Lm9uKCdjbGljaycsICcuZm9vdGVyLWl0ZW0gLmNvbnRlbnQtYXNzZXQgaDMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFxuXHRcdFx0aWYod2luZG93LmlubmVyV2lkdGggPCAxMDI1KSB7XG5cdFx0XHRcdCQodGhpcylcblx0XHRcdFx0XHQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG5cdFx0XHRcdFx0LmNsb3Nlc3QoJy5mb290ZXItaXRlbScpXG5cdFx0XHRcdFx0LnNpYmxpbmdzKClcblx0XHRcdFx0XHQuZmluZCgnLmFjdGl2ZScpXG5cdFx0XHRcdFx0LnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblxuXHRcdFx0XHQkKHRoaXMpXG5cdFx0XHRcdFx0Lm5leHQoKVxuXHRcdFx0XHRcdC5zdG9wKClcblx0XHRcdFx0XHQuc2xpZGVUb2dnbGUoKVxuXHRcdFx0XHRcdC5jbG9zZXN0KCcuZm9vdGVyLWl0ZW0nKVxuXHRcdFx0XHRcdC5zaWJsaW5ncygpXG5cdFx0XHRcdFx0LmZpbmQoJy5tZW51LWZvb3RlcicpXG5cdFx0XHRcdFx0LnNsaWRlVXAoKTtcblx0XHRcdH1cblx0XHR9KVxuXHRcdC5vbignY2xpY2snLCAnLmJ0bi1leHBhbmQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHZhciBlbGVtZW50ID0gJCh0aGlzKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcblx0XHRcdGlmKCQoJy5zdGlja3ktbWVudScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0dmFyIGVsZW1lbnQgPSBlbGVtZW50ICArICBcIi5zZWFyY2gtbW9iaWxlXCI7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCQoZWxlbWVudCkudG9nZ2xlQ2xhc3MoJ3Nob3cnKTtcblx0XHRcdFxuICAgICAgICAgICAgaWYoJCgnLnN0aWNreS1tZW51JykubGVuZ3RoID4gMCkgeyBcbiAgICAgICAgICAgICAgICAkKCcjbWFpbicpLnRvZ2dsZUNsYXNzKCdzZWFyY2gtb3BlbicpO1xuICAgICAgICAgICAgfVxuXG5cdFx0XHRpZigkKCcubWVudS10b2dnbGUnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0bmF2aWdhdGlvbi5DbG9zZU5hdmlnYXRpb24oKTtcblx0XHRcdH1cblxuXHRcdFx0aWYoJCgnI21pbmktY2FydCcpLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0XHQkKCcjbWluaS1jYXJ0IC5taW5pLWNhcnQtbGluaycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnI21pbmktY2FydCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYoJCgnLnNlY29uZC1tb2JuYXYnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcdFx0XHRcdFxuXHRcdFx0XHQkKCcuc2Vjb25kLW1vYm5hdicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHQkKCcjc2Vjb25kLW1vYm5hdicpLnNsaWRlVXAoKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKGVsZW1lbnQgPT0gJyNzZWFyY2gnIHx8IGVsZW1lbnQgPT0gJyNzZWFyY2guc2VhcmNoLW1vYmlsZScpIHtcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2VhcmNoQmFyLkV4cGFuZCcpO1xuICAgICAgICAgICAgfVxuXHRcdH0pXG5cdFx0Lm9uKCdjbGljaycsICcuYnRuLWxvY2F0aW9uLXJlZGlyZWN0JywgZnVuY3Rpb24oZXZlbnQpe1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHZhciBsaW5rUmVkaXJlY3RTdG9yZSA9ICQodGhpcykuZmluZCgnc3BhbicpLmF0dHIoJ2xvYy1saW5rJyk7XG5cdFx0XHRpZiAobGlua1JlZGlyZWN0U3RvcmUgIT0gbnVsbCkge1xuXHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gbGlua1JlZGlyZWN0U3RvcmU7XG5cdFx0XHR9XG5cdFx0fSlcblx0XHQub24oJ2NsaWNrJywgJy5idG4tbG9jYXRpb24nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0aWYoJCgnI21pbmktY2FydCcpLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0XHQkKCcjbWluaS1jYXJ0IC5taW5pLWNhcnQtbGluaycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnI21pbmktY2FydCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH1cblxuXHRcdFx0JCgnI25hdmlnYXRpb24nKVxuXHRcdFx0XHQuc3RvcCgpXG5cdFx0XHRcdC5zbGlkZVRvZ2dsZSgpO1xuXG5cdFx0XHRuYXZpZ2F0aW9uLkNsb3NlTmF2aWdhdGlvbigpO1xuXHRcdFx0XG5cdFx0XHR2YXIgZWxlbWVudCA9ICQodGhpcykuYXR0cignaHJlZicpO1xuXG5cdFx0XHQkKGVsZW1lbnQpXG5cdFx0XHRcdC5maW5kKCcubmF2LXNlY29uZGFyeS1kcm9wZG93bicpXG5cdFx0XHRcdC5zdG9wKClcblx0XHRcdFx0LnNsaWRlVG9nZ2xlKClcblx0XHRcdFx0LnBhcmVudCgpXG5cdFx0XHRcdC5zaWJsaW5ncygpXG5cdFx0XHRcdC5maW5kKCcubmF2LXNlY29uZGFyeS1kcm9wZG93bicpXG5cdFx0XHRcdC5zbGlkZVVwKCk7XG5cdFx0fSlcblx0XHQub24oJ2NsaWNrJywgJy5qdW1ib3Ryb24tY3VycmVudC1vZmZlcnMnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdCQoJy5qdW1ib3Ryb24tbW9iaWxlJykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0aWYoJCgnI2p1bWJvdHJvbi1jdXJyZW50LW9mZmVycy1pY29uJykuaGFzQ2xhc3MoJ2ZhLWFuZ2xlLXVwJykpIHtcblx0XHRcdFx0JCgnI2p1bWJvdHJvbi1jdXJyZW50LW9mZmVycy1pY29uJykucmVtb3ZlQ2xhc3MoJ2ZhLWFuZ2xlLXVwJyk7XG5cdFx0XHRcdCQoJyNqdW1ib3Ryb24tY3VycmVudC1vZmZlcnMtaWNvbicpLmFkZENsYXNzKCdmYS1hbmdsZS1kb3duJyk7XG5cdFx0XHRcdHNldENvb2tpZSgnanVtYm90cm9uRXhwYW5kZWRDb29raWUnLCBmYWxzZSwgMik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5yZW1vdmVDbGFzcygnZmEtYW5nbGUtZG93bicpO1xuXHRcdFx0XHQkKCcjanVtYm90cm9uLWN1cnJlbnQtb2ZmZXJzLWljb24nKS5hZGRDbGFzcygnZmEtYW5nbGUtdXAnKTtcblx0XHRcdFx0c2V0Q29va2llKCdqdW1ib3Ryb25FeHBhbmRlZENvb2tpZScsIHRydWUsIDIpO1xuXHRcdFx0fVxuXHRcdH0pXG5cdFx0Lm9uKCdjbGljaycsICcuc2Vjb25kLW1vYm5hdicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFxuXHRcdFx0JCh0aGlzKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcblx0XHRcdCQoJyNzZWNvbmQtbW9ibmF2Jylcblx0XHRcdC5zdG9wKClcblx0XHRcdC5zbGlkZVRvZ2dsZSgxNTApO1xuXHRcdFx0XG5cdFx0XHRpZigkKCcubWVudS10b2dnbGUnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0JCgnLm1lbnUtdG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cdFx0XHR9XG5cdFx0XHQgXG5cdFx0XHRpZigkKCcjbWluaS1jYXJ0JykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHRcdCQoJyNtaW5pLWNhcnQgLm1pbmktY2FydC1saW5rJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCcjbWluaS1jYXJ0JykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2VhcmNoQmFyLkhpZGUnKTtcblx0XHR9KVxuXHRcdFxuXHRcdC5vbignY2xpY2snLCAnLmFjY29yZGlvbiA+IGEnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciAkY29udGFpbmVyID0gJCh0aGlzKS5jbG9zZXN0KCcuYWNjb3JkaW9uJyk7XG5cdFx0XHQkY29udGFpbmVyLmZpbmQoJ3VsJykuc2xpZGVUb2dnbGUoJ2Zhc3QnKTtcblx0XHR9KVxuLypcblx0XHQub24oJ3RvdWNoc3RhcnQnLCBmdW5jdGlvbihldmVudCkgIHtcbiAgICBcdFx0aWYgKCEkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgnI25hdmlnYXRpb24nKS5sZW5ndGggJiYgISQoZXZlbnQudGFyZ2V0KS5pcygnI25hdmlnYXRpb24nKSAmJiAkd2luLndpZHRoKCkgPiA3NjcgKSAge1xuICAgIFx0XHQgICAgJCgnLmxldmVsLTInKS5zdG9wKCkuc2xpZGVVcCg0MDApO1xuICAgIFx0XHR9ICBcbiAgICBcdH0pXG4qL1xuXHRcdFxuXHRcdC5vbignbW91c2VvdmVyJywgJyNtaW5pLWNhcnQnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZih3aW5kb3cuaW5uZXJXaWR0aCA+IDEwMjQpIHtcblx0XHRcdFx0JCh0aGlzKVxuXHRcdFx0XHRcdC5maW5kKCcubWluaS1jYXJ0LWxpbmsnKVxuXHRcdFx0XHRcdC5hZGRDbGFzcygnYWN0aXZlJyk7XG5cblx0XHRcdFx0JCh0aGlzKVxuXHRcdFx0XHRcdC5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9XG5cblx0XHRcdGlmKCQoJyNuYXZpZ2F0aW9uJykuaGFzQXR0cignc3R5bGUnKSkge1xuXHRcdFx0XHQkKCcubWVudS10b2dnbGUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdTZWFyY2hCYXIuSGlkZScpO1xuXHRcdH0pXG5cdFx0Lm9uKCdtb3VzZWxlYXZlJywgJyNtaW5pLWNhcnQnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG5cdFx0XHRpZih3aW5kb3cuaW5uZXJXaWR0aCA+IDEwMjQpIHtcblx0XHRcdFx0c2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0JHRoaXNcblx0XHRcdFx0XHRcdC5maW5kKCcubWluaS1jYXJ0LWxpbmsnKVxuXHRcdFx0XHRcdFx0LnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblxuXHRcdFx0XHRcdCR0aGlzXG5cdFx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHR9LCAxMDAwKTtcblx0XHRcdH1cblx0XHR9KVxuXHRcdC5vbignY2xpY2snLCAnLmVkaXQtc2VhcmNoLXF1ZXJ5JywgZnVuY3Rpb24gKCkge1xuXHRcdFx0JCgnLmNhdGVnb3J5LXBvcHVwLWxpc3Qtc3RvcmVzJykuZGlhbG9nKCdjbG9zZScpO1xuXHRcdFx0JCgnLmdyaWQtcGFnZS1zdG9yZXNlbGVjdG9yLXBvcHVwJykuZGlhbG9nKCdvcGVuJyk7XG5cdFx0fSlcblx0XHQub24oJ2NsaWNrJywgJy5wb3B1cC1saXN0LXN0b3JlcyBpbnB1dFtuYW1lPVwiYXBwbHlcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAoISQoJ2lucHV0W25hbWU9XCJzdG9yZVwiXTpjaGVja2VkJykudmFsKCkpIHtcblx0XHRcdFx0YWxlcnQoJ1NlbGVjdCBvbmUgb2Ygc3RvcmVzJyk7XG5cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR0eXBlOiAnZ2V0Jyxcblx0XHRcdFx0dXJsOiBVcmxzLnNldERlZmF1bHRTdG9yZSxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdHN0b3JlSWQ6ICQoJ2lucHV0W25hbWU9XCJzdG9yZVwiXTpjaGVja2VkJykudmFsKClcblx0XHRcdFx0fSxcblxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRcdCQoJy5jYXRlZ29yeS1wb3B1cC1saXN0LXN0b3JlcycpLmRpYWxvZygnY2xvc2UnKTtcblx0XHRcdFx0XHRkb2N1bWVudC5sb2NhdGlvbi5yZWxvYWQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSlcblx0XHRcblx0XHQub24oJ2NsaWNrJywgJy5wdF9wcm9kdWN0LXNlYXJjaC1yZXN1bHQgLmNhdGVnb3J5LXNsb3QgYScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJ1tkYXRhLWxpbmstYXR0cmlidXRlLXZhbHVlXScpLmRhdGEoJ2xpbmstYXR0cmlidXRlLXZhbHVlJyk7XG5cdFx0XHR2YXIgaXNSZWZpbmVtZW50TGluayA9IHJlZmluZW1lbnRWYWx1ZSAhPSB1bmRlZmluZWQ7XG5cblx0XHRcdGlmIChpc1JlZmluZW1lbnRMaW5rKSB7XHRcblx0XHRcdFx0dmFyICRzaWRlYmFyUmVmaW5lbWVudCA9ICQoJyNyZWZpbmVtZW50cy1pbm5lcicpLmZpbmQoJyNmaWVsZC0nICsgcmVmaW5lbWVudFZhbHVlKTtcblx0XHRcdFx0dmFyIHVybFJlZmluZW1lbnREYXRhID0gZ2V0VXJsUmVmaW5lbWVudERhdGEoKTtcblxuXHRcdFx0XHRpZiAoJHNpZGViYXJSZWZpbmVtZW50Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdCRzaWRlYmFyUmVmaW5lbWVudC50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHVybFJlZmluZW1lbnREYXRhLmhhc1JlZmluZW1lbnRzKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudElkID0gJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJ1tkYXRhLWxpbmstYXR0cmlidXRlLWlkXScpLmRhdGEoJ2xpbmstYXR0cmlidXRlLWlkJyk7XG5cdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRJc0FscmVhZHlTZWxlY3RlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdHZhciByZWRpcmVjdFVybDtcblxuXHRcdFx0XHRcdGZvciAodmFyIHJlZmluZW1lbnQgaW4gdXJsUmVmaW5lbWVudERhdGEucGFyYW1ldGVycykge1xuXHRcdFx0XHRcdFx0aWYgKHVybFJlZmluZW1lbnREYXRhLnBhcmFtZXRlcnNbcmVmaW5lbWVudF0gPT09IHJlZmluZW1lbnRWYWx1ZSkge1xuXHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50SXNBbHJlYWR5U2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICghcmVmaW5lbWVudElzQWxyZWFkeVNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHRyZWRpcmVjdFVybCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmICsgJyZwcmVmbicgKyB1cmxSZWZpbmVtZW50RGF0YS5uZXdSZWZpbmVtZW50U3RhcnROdW1iZXIgKyAnPScgKyByZWZpbmVtZW50SWQgKyAnJnByZWZ2JyArIHVybFJlZmluZW1lbnREYXRhLm5ld1JlZmluZW1lbnRTdGFydE51bWJlciArICc9JyArIHJlZmluZW1lbnRWYWx1ZTtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gcmVkaXJlY3RVcmw7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLnRodW1iLWxpbmssIC5uYW1lLWxpbmsnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnLmFjY29yZGlvbiwgLnNlY3Rpb24tb2ZmZXJzLCAudGlsZXMsIC5jYXQtaGVhZGVyLWNvbnRlbnQuY2F0LWhlYWRlci1zbGlkZXInKS5maXJzdCgpO1xuXHRcdFx0aWYgKCRjb250YWluZXIubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdGlmICgkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRpbGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0dmFyIGNvbnRhaW5lcklkID0gJGNvbnRhaW5lci5hdHRyKCdjb250ZW50LXNsb3QtaWQnKSB8fCAkY29udGFpbmVyLmF0dHIoJ2lkJyk7XG5cdFxuXHRcdFx0XHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0XHRcdFx0cHJvbW90aW9uX25hbWU6IGNvbnRhaW5lcklkXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIHBhZ2VUeXBlO1xuXHRcdFx0XHRcdHZhciAkd3JhcHBlciA9ICR0aGlzLmNsb3Nlc3QoJy5hZGQtdG8tY2FydC1tb2RhbCcpO1xuXHRcdFx0XHRcdGlmICgkd3JhcHBlci5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRwYWdlVHlwZSA9ICdhZGR0b2NhcnRtb2RhbCc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCFwYWdlVHlwZSkge1xuXHRcdFx0XHRcdFx0JHdyYXBwZXIgPSAkKCcjd3JhcHBlcicpO1xuXHRcdFx0XHRcdFx0aWYgKCR3cmFwcGVyLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0aWYgKHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0LnR5cGUpIHtcblx0XHRcdFx0XHRcdFx0XHRzd2l0Y2ggKHBhZ2VDb250ZXh0LnR5cGUpIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNhc2UgJ3N0b3JlZnJvbnQnOlxuXHRcdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnSG9tZXBhZ2UnO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdFx0Y2FzZSAnc2VhcmNoJzpcblx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ1BMUCc7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdwcm9kdWN0Jzpcblx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ1BEUCc7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdjYXJ0Jzpcblx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ0NhcnQnO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdFx0Y2FzZSAnb25lcGNoZWNrb3V0Jzpcblx0XHRcdFx0XHRcdFx0XHRcdGNhc2UgJ29uZXBjaGVja291dF9ncm91cHMnOlxuXHRcdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnQ2hlY2tvdXQnO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdFx0Y2FzZSAnb3JkZXJjb25maXJtYXRpb24nOlxuXHRcdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnT3JkZXIgQ29uZmlybWF0aW9uJztcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcblx0XHRcdFx0XHRcdFx0XHRcdGNhc2UgJ2N1c3RvbWVyc2VydmljZSc6XG5cdFx0XHRcdFx0XHRcdFx0XHRwYWdlVHlwZSA9ICdDdXN0b21lciBTZXJ2aWNlJztcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcblx0XHRcdFx0XHRcdFx0XHRcdGNhc2UgJ2FjY291bnQnOlxuXHRcdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnQWNjb3VudCc7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdjb250ZW50Jzpcblx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ0NvbnRlbnQgUGFnZSc7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdlcnJvcic6XG5cdFx0XHRcdFx0XHRcdFx0XHRwYWdlVHlwZSA9ICdFcnJvciBQYWdlJztcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1x0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChwYWdlVHlwZSkge1xuXHRcdFx0XHRcdFx0ZGF0YU9iamVjdC5wcm9tb3Rpb25faWQgPSBwYWdlVHlwZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgcmVkaXJlY3RIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gJHRoaXMuYXR0cignaHJlZicpO1xuXHRcdFx0XHRcdH07XG5cdFxuXHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1NlbGVjdFByb21vdGlvbicsIGRhdGFPYmplY3QsIHsgQ29udGFpbmVyOiAkdGhpcy5jbG9zZXN0KCcucHJvZHVjdC10aWxlJykgfSkudGhlbihyZWRpcmVjdEhhbmRsZXIpLmNhdGNoKHJlZGlyZWN0SGFuZGxlcik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICdbY29udGVudC1hc3NldC1pZF0gYSwgW2NvbnRlbnQtYXNzZXQtaWRdIGJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyIGlzTGluayA9ICR0aGlzLmF0dHIoJ2hyZWYnKSAmJiAkdGhpcy5hdHRyKCdocmVmJykubGVuZ3RoID4gMCAmJiAkdGhpcy5hdHRyKCdocmVmJykuaW5kZXhPZignLy8nKSA+PSAwO1xuXHRcdFx0dmFyIGlzQ2xvc2UgPSAkdGhpcy5hdHRyKCdjbGFzcycpICYmICR0aGlzLmF0dHIoJ2NsYXNzJykubGVuZ3RoID4gMCAmJiAkdGhpcy5hdHRyKCdjbGFzcycpLmluZGV4T2YoJ2Nsb3NlJykgPj0gMDtcblxuXHRcdFx0aWYgKCR0aGlzLmNsb3Nlc3QoJy5wcm9kdWN0LXRpbGUnKS5sZW5ndGggPT0gMCAmJiAhaXNDbG9zZSkge1xuXHRcdFx0XHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJ1tjb250ZW50LWFzc2V0LWlkXScpLmZpcnN0KCk7XG5cdFx0XHRcdGlmICgkY29udGFpbmVyLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRpZiAoaXNMaW5rKSB7XG5cdFx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0XHRcdFx0Y29udGVudF90eXBlOiAnY29udGVudCcsXG5cdFx0XHRcdFx0XHRpdGVtX2lkOiAkY29udGFpbmVyLmF0dHIoJ2NvbnRlbnQtYXNzZXQtaWQnKVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciByZWRpcmVjdEhhbmRsZXIgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdGlmIChpc0xpbmspIHtcblx0XHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9ICR0aGlzLmF0dHIoJ2hyZWYnKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFxuXHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1NlbGVjdENvbnRlbnQnLCBkYXRhT2JqZWN0KS50aGVuKHJlZGlyZWN0SGFuZGxlcikuY2F0Y2gocmVkaXJlY3RIYW5kbGVyKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0YWRkUHJvbW90aW9uRGF0YUxheWVycygpO1xuXHRcdCQoZG9jdW1lbnQpLm9mZignR29vZ2xlVGFnTWFuYWdlci5BZGRQcm9tb3Rpb25EYXRhTGF5ZXJzJykub24oJ0dvb2dsZVRhZ01hbmFnZXIuQWRkUHJvbW90aW9uRGF0YUxheWVycycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRhZGRQcm9tb3Rpb25EYXRhTGF5ZXJzKCk7XG5cdFx0fSk7XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogQWRkIGNsYXNzIHRvIGNvbnRlbnQgc2xvdCByZWZpbmVtZW50cyBpZiB0aGV5J3JlIGN1cnJlbnRseSBhY3RpdmVcblx0XHQgKiBhbmQgcmVtb3ZlIGFueSBzdGF0aWMgcmVmaW5lbWVudHMgaWYgdGhleSdyZSBub3QgZm91bmQgaW4gdGhlIHNpZGViYXJcblx0XHQgKiB0byBwcmV2ZW50IGVtcHR5IHNlYXJjaCByZXN1bHRzLlxuXHRcdCAqL1xuXHRcdGlmICgkKCdib2R5JykuZmluZCgnLnB0X3Byb2R1Y3Qtc2VhcmNoLXJlc3VsdCAuY2F0ZWdvcnktc2xvdCBhJykubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFyICRzbG90TGluayA9ICQoJ2JvZHknKS5maW5kKCcucHRfcHJvZHVjdC1zZWFyY2gtcmVzdWx0IC5jYXRlZ29yeS1zbG90IGEnKTtcblx0XHRcdHZhciB1cmxSZWZpbmVtZW50RGF0YSA9IGdldFVybFJlZmluZW1lbnREYXRhKCk7XG5cdFx0XHR2YXIgc2lkZWJhclJlZmluZW1lbnRzID0gZ2V0U2lkZWJhclJlZmluZW1lbnRzKCk7XG5cdFx0XHQkc2xvdExpbmsuZWFjaChmdW5jdGlvbihpbmRleCwgdmFsdWUpIHtcblx0XHRcdFx0dmFyIGxpbmtSZWZpbmVtZW50VHlwZSA9ICQodmFsdWUpLmRhdGEoJ2xpbmstYXR0cmlidXRlLXZhbHVlJyk7XG5cdFx0XHRcdGZvciAodmFyIHJlZmluZW1lbnQgaW4gdXJsUmVmaW5lbWVudERhdGEucGFyYW1ldGVycykge1xuXHRcdFx0XHRcdGlmIChyZWZpbmVtZW50Lm1hdGNoKC9eXFxwcmVmdi8pKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlcyA9IHVybFJlZmluZW1lbnREYXRhLnBhcmFtZXRlcnNbcmVmaW5lbWVudF0uc3BsaXQoJyU3QycpO1xuXHRcdFx0XHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IHJlZmluZW1lbnRWYWx1ZXMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChyZWZpbmVtZW50VmFsdWVzW2luZGV4XSA9PT0gbGlua1JlZmluZW1lbnRUeXBlKSB7XG5cdFx0XHRcdFx0XHRcdFx0JCh2YWx1ZSkuYWRkQ2xhc3MoJ3JlZmluZW1lbnQtYWN0aXZlJyk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGxpbmtSZWZpbmVtZW50VHlwZSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHR2YXIgZm91bmRJblNpZGViYXIgPSBmYWxzZTtcblx0XHRcdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgc2lkZWJhclJlZmluZW1lbnRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRcdFx0aWYgKHNpZGViYXJSZWZpbmVtZW50c1tpbmRleF0gPT09IGxpbmtSZWZpbmVtZW50VHlwZSkge1xuXHRcdFx0XHRcdFx0XHR2YXIgZm91bmRJblNpZGViYXIgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIWZvdW5kSW5TaWRlYmFyKSB7XG5cdFx0XHRcdFx0XHQkKHZhbHVlKS5jbG9zZXN0KCdsaScpLnJlbW92ZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHQkc2xvdExpbmsuY2xvc2VzdCgnLnNlY3Rpb24tYmxvY2snKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogaGVscGVyIGZ1bmN0aW9uIHRvIGdldCBhIGxpc3Qgb2YgZXhpc3RpbmcgcmVmaW5lbWVudHMgZnJvbSB0aGUgVVJMXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gZ2V0VXJsUmVmaW5lbWVudERhdGEoKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudHMgPSBsb2NhdGlvbi5zZWFyY2guc3Vic3RyKDEpLnNwbGl0KCcmJyk7XG5cdFx0XHR2YXIgdXJsUmVmaW5lbWVudERhdGEgPSB7XG5cdFx0XHRcdG5ld1JlZmluZW1lbnRTdGFydE51bWJlcjogMSxcblx0XHRcdFx0cGFyYW1ldGVyczoge30sXG5cdFx0XHRcdGhhc1JlZmluZW1lbnRzOiBmYWxzZVxuXHRcdFx0fTtcblx0XHRcdGlmIChyZWZpbmVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCByZWZpbmVtZW50cy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0XHR2YXIgcGFyYW1ldGVyID0gcmVmaW5lbWVudHNbaW5kZXhdLnNwbGl0KCc9Jyk7XG5cdFx0XHRcdFx0aWYgKHBhcmFtZXRlclswXS5tYXRjaCgvXlxccHJlZm4vKSkge1xuXHRcdFx0XHRcdFx0dXJsUmVmaW5lbWVudERhdGEubmV3UmVmaW5lbWVudFN0YXJ0TnVtYmVyKys7XG5cdFx0XHRcdFx0XHR1cmxSZWZpbmVtZW50RGF0YS5oYXNSZWZpbmVtZW50cyA9IHRydWU7XG5cdFx0XHRcdFx0XHR1cmxSZWZpbmVtZW50RGF0YS5wYXJhbWV0ZXJzW3BhcmFtZXRlclswXV0gPSBwYXJhbWV0ZXJbMV07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChwYXJhbWV0ZXJbMF0ubWF0Y2goL15cXHByZWZ2LykpIHtcblx0XHRcdFx0XHRcdHVybFJlZmluZW1lbnREYXRhLnBhcmFtZXRlcnNbcGFyYW1ldGVyWzBdXSA9IHBhcmFtZXRlclsxXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB1cmxSZWZpbmVtZW50RGF0YTtcblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBoZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IGEgbGlzdCBvZiByZWZpbmVtZW50IG5hbWVzIHByZXNlbnQgaW4gcmVmaW5lbWVudCBzaWRlYmFyXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gZ2V0U2lkZWJhclJlZmluZW1lbnRzKCkge1xuXHRcdFx0dmFyIHNpZGViYXJSZWZpbmVtZW50TGlzdCA9IFtdO1xuXHRcdFx0JCgnI3NlY29uZGFyeS5yZWZpbmVtZW50cyAuY2hlY2tib3ggaW5wdXQnKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCB2YWx1ZSkge1xuXHRcdFx0XHRpZiAoJCh2YWx1ZSkuYXR0cignaWQnKS5tYXRjaCgvXmZpZWxkLykpIHtcblx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudE5hbWUgPSAkKHZhbHVlKS5hdHRyKCdpZCcpLnNwbGl0KCctJylbMV07XG5cdFx0XHRcdFx0c2lkZWJhclJlZmluZW1lbnRMaXN0LnB1c2gocmVmaW5lbWVudE5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdHJldHVybiBzaWRlYmFyUmVmaW5lbWVudExpc3Q7XG5cdFx0fVxuIFxuICAgIFx0Ly9yZWFkeSAjbmF2aWdhdGlvbiBmb3IgaW50ZXJhY3Rpb24gKGFycmVzdHMgb2RkIGluaXRpYWwgaW50ZXJhY3Rpb24gb24gdG91Y2ggZGV2aWNlcylcbiAgICBcdCQoXCIjbmF2aWdhdGlvblwiKS5hZGRDbGFzcyhcImhvdmVyUmVhZHlcIik7XG5cblx0XHQvLyBTd2l0Y2ggc2hvdyB0ZXh0XG5cdFx0JCgnLnN3aXRjaCBpbnB1dCcpLmNoYW5nZShmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZigkKHRoaXMpLnByb3AoJ2NoZWNrZWQnKSkge1xuXHRcdFx0XHQkKHRoaXMpXG5cdFx0XHRcdFx0LmNsb3Nlc3QoJy5yZXN1bHQtb3B0aW9ucycpXG5cdFx0XHRcdFx0LmFkZENsYXNzKCdzaG93LWluZm8nKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQodGhpcylcblx0XHRcdFx0XHQuY2xvc2VzdCgnLnJlc3VsdC1vcHRpb25zJylcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ3Nob3ctaW5mbycpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0aWYoJCgnYm9keScpLmZpbmQoJy5yZXN1bHQtb3B0aW9ucyAuc3dpdGNoIGlucHV0W25hbWU9XCJmaWVsZC10cnVlXCJdJykucHJvcCgnY2hlY2tlZCcpKSB7XG5cdFx0XHR2YXIgdG9nZ2xlQnRuID0gJCgnYm9keScpLmZpbmQoJy5yZXN1bHQtb3B0aW9ucyAuc3dpdGNoIGlucHV0W25hbWU9XCJmaWVsZC1zd2l0Y2hcIl0nKTtcblxuXHRcdFx0aWYoIXRvZ2dsZUJ0bi5wcm9wKCdjaGVja2VkJykpIHtcblx0XHRcdFx0dG9nZ2xlQnRuLmNsb3Nlc3QoJy5yZXN1bHQtb3B0aW9ucycpLmFkZENsYXNzKCdzaG93LWluZm8nKTtcblx0XHRcdFx0dG9nZ2xlQnRuLmNsb3Nlc3QoJy5yZXN1bHQtb3B0aW9ucycpLmZpbmQoJ2lucHV0W25hbWU9XCJmaWVsZC1zd2l0Y2hcIl0nKS5hdHRyKCdjaGVja2VkJywgJ2NoZWNrZWQnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRvZ2dsZUJ0bi5jbG9zZXN0KCcucmVzdWx0LW9wdGlvbnMnKS5yZW1vdmVDbGFzcygnc2hvdy1pbmZvJyk7XG5cdFx0XHRcdHRvZ2dsZUJ0bi5jbG9zZXN0KCcucmVzdWx0LW9wdGlvbnMnKS5maW5kKCdpbnB1dFtuYW1lPVwiZmllbGQtc3dpdGNoXCJdJykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdCQoJy5zd2F0Y2hlcyA+IGxpID4gdWwnKS5vbignY2xpY2snLCAnYScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHQkKHRoaXMpXG5cdFx0XHRcdC50b2dnbGVDbGFzcygnY3VycmVudCcpXG5cdFx0XHRcdC5wYXJlbnQoKVxuXHRcdFx0XHQuc2libGluZ3MoKVxuXHRcdFx0XHQuZmluZCgnLmN1cnJlbnQnKVxuXHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2N1cnJlbnQnKTtcblx0XHR9KTtcblxuXHRcdC8vIEdlbmVyaWMgc2xpZGVyIGluaXRcblx0XHRzbGlkZXJzLmluaXQoJy5zbGlkZXIgLnNsaWRlcycpO1xuXHRcdFxuXHRcdCQoJy5zZXJ2aWNlLXRvZ2dsZS1pdGVtJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHQkKHRoaXMpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblxuXHRcdFx0JCh0aGlzKS5uZXh0KCcuY3VzdG9tZXItc2VydmljZS1pbm5lcicpLnRvZ2dsZUNsYXNzKCdvcGVuJyk7XG5cdFx0XHQkKHRoaXMpLm5leHQoJy5jdXN0b21lci1zZXJ2aWNlLWlubmVyJykuc2xpZGVUb2dnbGUoKTtcblx0XHR9KTtcblxuXHRcdCQoJy50b3AtYnJhbmRzIC5jYXRlZ29yeS1oZWFkJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHQkKHRoaXMpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblxuXHRcdFx0JCh0aGlzKS5uZXh0KCcuY2F0ZWdvcnktYm9keScpLnRvZ2dsZUNsYXNzKCdvcGVuJyk7XG5cdFx0XHQkKHRoaXMpLm5leHQoJy5jYXRlZ29yeS1ib2R5Jykuc2xpZGVUb2dnbGUoKTtcblx0XHR9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9uKCd1cGRhdGUnLCAnLnNsaWRlci1wcm9kdWN0cy1wcmltYXJ5JywgZnVuY3Rpb24oKSB7XG4gICAgXHRcdHNsaWRlcnMuaW5pdCgnLnNsaWRlci1wcm9kdWN0cy1wcmltYXJ5IC5zbGlkZXMnLCB7YnJlYWtwb2ludHM6IHswOiB7c2xpZGVzVG9TaG93OiAxLCBkb3RzOiB0cnVlfSwgNzY4OiB7c2xpZGVzVG9TaG93OiAzfSwgMTAyNDoge3NsaWRlc1RvU2hvdzogNH19fSk7XG5cdFx0fSk7XG5cblx0XHQvLyBtYWtlIHN1cmUgc2xpZGVyIGdldHMgaW5pdGlhbGl6ZWQgZm9yIHByb2R1Y3QgcmVjb21tZW5kYXRpb25zIHdoZW4gZHluYW1pY2FsbHkgYWRkZWRcblx0XHRpZiAoJCgnLnB0X3Byb2R1Y3QtZGV0YWlscycpLmxlbmd0aCA+IDAgfHwgJCgnLm5vLWhpdHMtYmFubmVyJykubGVuZ3RoID4gMCkge1xuXHRcdFx0c2xpZGVycy5pbml0aWFsaXplUmVjb21tZW5kYXRpb25TbGlkZXIoKTtcblx0XHR9XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ0VpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Jbml0aWFsaXplJykub24oJ0VpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Jbml0aWFsaXplJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRzbGlkZXJzLmluaXRpYWxpemVSZWNvbW1lbmRhdGlvblNsaWRlcigpO1xuXHRcdH0pO1xuXG5cdFx0JChkb2N1bWVudCkub24oJ2luaXQtc2xpZGVyJywgJy5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgIT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdHZhciBzaG93TW9iaWxlRG90cyA9IHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTID8gZmFsc2UgOiB0cnVlO1xuXHRcdFx0XHRzbGlkZXJzLmluaXQoJy5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucyAuc2xpZGVyLXByb2R1Y3RzLXByaW1hcnkgLnNsaWRlczpub3QoLnNsaWNrLXNsaWRlcik6bm90KC5zd2lwZXItZnVsbC13cmFwcGVyKTpoYXMobGkpJywge2xvb3A6IGZhbHNlLCBicmVha3BvaW50czogezA6IHtzbGlkZXNUb1Nob3c6IDEsIGRvdHM6IHNob3dNb2JpbGVEb3RzLCBhcnJvd3M6IHRydWV9LCA3Njg6IHtzbGlkZXNUb1Nob3c6IDMsIGRvdHM6IGZhbHNlLCBhcnJvd3M6IHRydWV9LCAxMDI0OiB7c2xpZGVzVG9TaG93OiA0LCBkb3RzOiBmYWxzZSwgYXJyb3dzOiB0cnVlfX19LCB0cnVlKTtcblx0XHRcdFx0c2xpZGVycy5pbml0KCcubGFzdC12aXNpdGVkIC5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeSAuc2xpZGVzOm5vdCguc2xpY2stc2xpZGVyKTpub3QoLnN3aXBlci1mdWxsLXdyYXBwZXIpOmhhcyhsaSknLCB7bG9vcDogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMSwgZG90czogc2hvd01vYmlsZURvdHMsIGFycm93czogdHJ1ZX0sIDc2ODoge3NsaWRlc1RvU2hvdzogMywgZG90czogZmFsc2UsIGFycm93czogdHJ1ZX0sICAxMDI0OiB7c2xpZGVzVG9TaG93OiA0LCBkb3RzOiBmYWxzZSwgYXJyb3dzOiB0cnVlfX19KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNsaWRlcnMuaW5pdCgnLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zIC5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeSAuc2xpZGVzOm5vdCguc2xpY2stc2xpZGVyKTpub3QoLnN3aXBlci1mdWxsLXdyYXBwZXIpOmhhcyhsaSknLCB7bG9vcDogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMSwgZG90czogdHJ1ZSwgYXJyb3dzOiB0cnVlfSwgNzY4OiB7c2xpZGVzVG9TaG93OiAzLCBkb3RzOiBmYWxzZSwgYXJyb3dzOiB0cnVlfX19LCB0cnVlKTtcblx0XHRcdFx0c2xpZGVycy5pbml0KCcubGFzdC12aXNpdGVkIC5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeSAuc2xpZGVzOm5vdCguc2xpY2stc2xpZGVyKTpub3QoLnN3aXBlci1mdWxsLXdyYXBwZXIpOmhhcyhsaSknLCB7bG9vcDogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMSwgZG90czogdHJ1ZSwgYXJyb3dzOiB0cnVlfSwgNzY4OiB7c2xpZGVzVG9TaG93OiA0LCBkb3RzOiBmYWxzZSwgYXJyb3dzOiB0cnVlfX19KTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHNsaWRlcnMuaW5pdCgnLnNsaWRlci1maWxtc3RyaXAgLnNsaWRlcycsIHtsb29wOiB0cnVlfSk7XG5cblx0XHRzbGlkZXJzLmluaXRpYWxpemVDYXRlZ29yeVNsaWRlcnMoJy5jYXQtaGVhZGVyLWNvbnRlbnQuY2F0LWhlYWRlci1zbGlkZXI6bm90KC5zbGljay1pbml0aWFsaXplZCknKTtcblxuXHRcdC8vIFdheXBvaW50c1xuXHRcdCQoJy53YXlwb2ludCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR2YXIgZWxlbWVudCA9ICQodGhpcykuYXR0cignaHJlZicpO1xuXG5cdFx0XHQkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7XG5cdFx0XHRcdHNjcm9sbFRvcDogJChlbGVtZW50KS5vZmZzZXQoKS50b3Bcblx0XHRcdH0sIDEwMDApO1xuXHRcdH0pO1xuXG5cdFx0Ly8gQnRuIEV4cGFuZCBBbHRcblx0XHQkKCcuYnRuLWV4cGFuZC1hbHQnKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHR2YXIgZWxlbWVudCA9ICQodGhpcykuYXR0cignaHJlZicpO1xuXG5cblx0XHRcdGlmICgkKGVsZW1lbnQpLmhhc0NsYXNzKCdncmlkLXBhZ2Utc3RvcmVzZWxlY3Rvci1wb3B1cCcpKSB7XG5cdFx0XHRcdCQoZWxlbWVudCkuZGlhbG9nKCdvcGVuJyk7XG5cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQkKGVsZW1lbnQpXG5cdFx0XHRcdC50b2dnbGVDbGFzcygnc2hvdycpO1xuXHRcdH0pO1xuXG5cdFx0JCgnLmdyaWQtcGFnZS1zdG9yZXNlbGVjdG9yLXBvcHVwJykuZGlhbG9nKHtcblx0XHRcdHdpZHRoOiA0NTAsXG5cdFx0XHRhdXRvT3BlbjogZmFsc2UsXG5cdFx0XHRtb2RhbDogdHJ1ZSxcblx0XHRcdHJlc2l6YWJsZTogZmFsc2Vcblx0XHR9KTtcblxuXHRcdC8vIFNpZGViYXIgQ2xvc2Vcblx0XHQkKCcjc2Vjb25kYXJ5IC5jbG9zZSwgI3NvcnQtYnkgLmNsb3NlLCAucG9wdXAtY2xvc2UnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdCQodGhpcylcblx0XHRcdFx0LmNsb3Nlc3QoJy5zaG93Jylcblx0XHRcdFx0LnJlbW92ZUNsYXNzKCdzaG93Jyk7XG5cdFx0fSk7XG5cblx0XHQkKCcubWVzc2FnZSAuY2xvc2UnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdCQodGhpcylcblx0XHRcdFx0LnBhcmVudCgpXG5cdFx0XHRcdC5zbGlkZVVwKCk7XG5cdFx0fSk7XG5cblx0XHRpZiAoJCgnI0dsb2JhbGVGcmVlU2hpcHBpbmdCYW5uZXJDb250YWluZXInKS5sZW5ndGggPiAwKSB7XG5cdFx0XHR2YXIgZ2xvYmFsZUZyZWVTaGlwcGluZ0Jhbm5lck9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoZnVuY3Rpb24obXV0YXRpb25zLCBvYnNlcnZlcikge1xuXHRcdFx0XHRmb3IgKHZhciBtdXRhdGlvbktleSBpbiBtdXRhdGlvbnMpIHtcblx0XHRcdFx0XHR2YXIgbXV0YXRpb24gPSBtdXRhdGlvbnNbbXV0YXRpb25LZXldO1xuXHRcdFx0XHRcdGlmIChtdXRhdGlvbi50eXBlID09PSAnY2hpbGRMaXN0Jykge1xuXHRcdFx0XHRcdFx0cmVzaXplRGV2aWNlSGVscGVyKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdGdsb2JhbGVGcmVlU2hpcHBpbmdCYW5uZXJPYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdHbG9iYWxlRnJlZVNoaXBwaW5nQmFubmVyQ29udGFpbmVyJyksIHthdHRyaWJ1dGVzOiBmYWxzZSwgY2hpbGRMaXN0OiB0cnVlLCBzdWJ0cmVlOiB0cnVlIH0pO1xuXHRcdH1cblxuXHRcdC8vIEJhY2sgdG8gVG9wIGJ1dHRvblxuXHRcdGZ1bmN0aW9uIHRvcEJ1dHRvblRvZ2dsZSgpIHtcblx0XHRcdHZhciAkc2Nyb2xsVG9wID0gJHdpbi5zY3JvbGxUb3AoKTtcblx0XHRcdGlmICgkc2Nyb2xsVG9wID4gIDEwMCApIHtcblx0XHRcdFx0JCgnYm9keScpLmFkZENsYXNzKCdidG4tZ28tdG9wLWFjdGl2ZScpO1xuXHRcdFx0XHQkKCAnLmJ0bi1nby10b3AnICkuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdidG4tZ28tdG9wLWFjdGl2ZScpO1xuXHRcdFx0XHQkKCAnLmJ0bi1nby10b3AnICkucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHQkd2luLm9uKCdzY3JvbGwnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHR0b3BCdXR0b25Ub2dnbGUoKTtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NlYXJjaEJhci5TY3JvbGxUb3AnKTtcblx0XHR9KTtcblxuXHRcdCR3aW4ub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcblx0XHRcdGFjY29yZGlvbk1vYmlsZSgpO1xuXHRcdFx0YWNjb3JkaW9uTW9iaWxlQWx0KCk7XG5cblx0XHRcdC8vIERpc2FibGVkIHBlciBCT09ULTM1MTdcblx0XHRcdC8vICQoICc8c3BhbiBjbGFzcz1cImJ0bi1nby10b3BcIj48aSBjbGFzcz1cImZhIGZhLWFuZ2xlLXVwXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPjxzcGFuPlRvcDwvc3Bhbj48L3NwYW4+JyApLmluc2VydEJlZm9yZSgkKCcuZm9vdGVyOm5vdCguZm9vdGVyLW1vYmlsZSknKSk7XG5cdFx0XHQvLyB0b3BCdXR0b25Ub2dnbGUoKTtcblx0XHR9KTtcblxuXHRcdCRkb2Mub24oJ2NsaWNrJywgJy5idG4tZ28tdG9wJywgZnVuY3Rpb24oZSl7XG5cdFx0XHQkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7c2Nyb2xsVG9wOiAwfSw4MDApO1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH0pXG5cblx0XHQvLyBSZWFkIE1vcmUgLyBMZXNzXG5cdFx0JGRvYy5vbignY2xpY2snLCAnLnNlY3Rpb24tb2ZmZXJzLXRleHQgLnJlYWQtbW9yZScsIGZ1bmN0aW9uKGUpIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdCQodGhpcykucGFyZW50cygnLnNlY3Rpb24tYm9keScpLmZpcnN0KCkuYWRkQ2xhc3MoJ2V4cGFuZCcpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0pO1xuXG5cdFx0JGRvYy5vbignY2xpY2snLCAnLnNlY3Rpb24tb2ZmZXJzLXRleHQgLnJlYWQtbGVzcycsIGZ1bmN0aW9uKGUpIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdCQodGhpcykucGFyZW50cygnLnNlY3Rpb24tYm9keScpLmZpcnN0KCkucmVtb3ZlQ2xhc3MoJ2V4cGFuZCcpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0pO1xuXHRcdFxuXHRcdFxuXHRcdC8vIEFjY29yZGlvblxuXHRcdGZ1bmN0aW9uIGFjY29yZGlvbk1vYmlsZSgpIHtcblx0XHRcdCQoJy5vZmZlciAub2ZmZXItaGVhZCBoNicpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdGlmKGV2ZW50LnRhcmdldC5ub2RlTmFtZSA9PSBcIkg2XCIpe1xuXHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRcdCQodGhpcykuZmluZCgnLmNoZXZyb24tY29sbGFwc2UnKS5jbGljaygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JCgnLm9mZmVyIC5vZmZlci1oZWFkIGg2IC5jaGV2cm9uLWNvbGxhcHNlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA+IDEwMjQpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcylcblx0XHRcdFx0dmFyICRwYXJlbnQgPSAkdGhpcy5jbG9zZXN0KCcub2ZmZXInKVxuXG5cdFx0XHRcdGlmICgkcGFyZW50Lmhhc0NsYXNzKFwiYWN0aXZlXCIpKSB7XG5cdFx0XHRcdFx0JHBhcmVudC5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLm9mZmVyLWJvZHknKS5zbGlkZVVwKCk7XG5cblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHQkcGFyZW50LmFkZENsYXNzKCdhY3RpdmUnKS5maW5kKCcub2ZmZXItYm9keScpLnNsaWRlRG93bigpO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0pO1xuXG5cdFx0XHQkd2luLnJlc2l6ZShmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYod2luZG93LmlubmVyV2lkdGggPiAxMDI0KSB7XG5cdFx0XHRcdFx0JCgnLm9mZmVyIC5vZmZlci1ib2R5Jykuc2hvdygpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5vZmZlciAub2ZmZXItYm9keScpLmhpZGUoKVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9O1xuXG5cdFx0ZnVuY3Rpb24gYWNjb3JkaW9uTW9iaWxlQWx0KCkge1xuXHRcdFx0JCgnLmFjY29yZGlvbi1tb2JpbGUgLmFjY29yZGlvbi1tb2JpbGUtaGVhZCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPiAxMDI0KSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKSxcblx0XHRcdFx0XHQkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgnLmFjY29yZGlvbi1tb2JpbGUnKTtcblxuXHRcdFx0XHQkdGhpc1xuXHRcdFx0XHQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG5cdFx0XHRcdC5uZXh0KClcblx0XHRcdFx0LnN0b3AoKVxuXHRcdFx0XHQuc2xpZGVUb2dnbGUoKTtcblx0XHRcdH0pO1xuXHRcdH07XG5cblx0XHQvLyBBY2NvcmRpb25cblx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLmFjY29yZGlvbi1zZWN0aW9uIC5hY2NvcmRpb24taGVhZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnLmFjY29yZGlvbicpO1xuXHRcdFx0JHRoaXMudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JHRoaXMubmV4dCgnLmFjY29yZGlvbi1ib2R5Jykuc3RvcCgpLnNsaWRlVG9nZ2xlKDQwMCk7XG5cblx0XHRcdGlmICgkdGhpcy5oYXNDbGFzcygnYWN0aXZlJykgJiYgJGNvbnRhaW5lci5maW5kKCcuc2xpZGVzJykubGVuZ3RoID4gMCAmJiAkY29udGFpbmVyLmZpbmQoJy5zbGljay1pbml0aWFsaXplZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCcuc2xpZGVzJykuc2xpY2soJ3JlZnJlc2gnKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuc2VjdGlvbi1vZmZlcnMuY29udGVudC1jb2x1bW5zIC5zZWN0aW9uLWNvbHVtbiBoNi5jb2x1bW4tdGl0bGUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTICYmIHdpbmRvdy5pbm5lcldpZHRoIDwgNzY4KSB7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdCQodGhpcykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKHRoaXMpLm5leHQoJy5jb2x1bW4tY29udGVudCcpLnN0b3AoKS5zbGlkZVRvZ2dsZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gUm90YXRlIFRleHRcblx0XHRmdW5jdGlvbiByb3RhdGVUZXh0KCRlbGVtZW50LCBkdXJhdGlvbikge1xuXHRcdFx0dmFyIGxlbmd0aFNsaWRlciA9ICRlbGVtZW50LmZpbmQoJy5yb3RhdGUtZWxlbWVudCcpLmxlbmd0aDtcblx0XHRcdHZhciAkcm90YXRlRWxlbWVudCA9ICRlbGVtZW50LmZpbmQoJy5yb3RhdGUtZWxlbWVudCcpO1xuXHRcdFx0XG5cdFx0XHRpZiAobGVuZ3RoU2xpZGVyID4gMCkge1xuXHRcdFx0XHR2YXIgaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dmFyICRyb3RhdGVFbGVtZW50QWN0aXZlIFx0PSAkZWxlbWVudC5maW5kKCcuYWN0aXZlJyk7XG5cdFx0XHRcdFx0dmFyICRuZXh0RWxlbWVudCA9ICRyb3RhdGVFbGVtZW50QWN0aXZlLm5leHQoKTtcblx0XG5cdFx0XHRcdFx0aWYoJG5leHRFbGVtZW50LmluZGV4KCkgPT09IC0xKSB7XG5cdFx0XHRcdFx0XHQkbmV4dEVsZW1lbnQgPSAkZWxlbWVudC5maW5kKCcucm90YXRlLWVsZW1lbnQ6Zmlyc3QtY2hpbGQnKTtcblx0XG5cdFx0XHRcdFx0XHQkbmV4dEVsZW1lbnRcblx0XHRcdFx0XHRcdFx0LmFkZENsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdFx0XHQuc2libGluZ3MoKVxuXHRcdFx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkbmV4dEVsZW1lbnRcblx0XHRcdFx0XHRcdFx0LmFkZENsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdFx0XHQuc2libGluZ3MoKVxuXHRcdFx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSwgZHVyYXRpb24pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyb3RhdGVUZXh0KCQoJy50b3AtYmFubmVyLW1lc3NhZ2UnKSwgJCgnLnRvcC1iYW5uZXItbWVzc2FnZScpLmRhdGEoJ2R1cmF0aW9uJykpO1xuXG4gICBcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcbiAgIFx0XHQkKCcucmVmaW5lbWVudCBoMy50b2dnbGUuZXhwYW5kZWQ6bm90KC5zZWxlY3RlZCksIC5yZWZpbmVtZW50IC5yZWZpbmVtZW50LWJvZHkudG9nZ2xlLWNvbnRlbnQuZXhwYW5kZWQ6bm90KC5zZWxlY3RlZCknKS5yZW1vdmVDbGFzcygnZXhwYW5kZWQnKTtcbiAgIFx0fVxuICAgXG4gICAgLy8gYWRkIGdlbmVyaWMgdG9nZ2xlIGZ1bmN0aW9uYWxpdHlcbiAgICAkKCcudG9nZ2xlOm5vdCguZGlzYWJsZWQpJykubm90KCcuZXhwYW5kZWQnKS5uZXh0KCcudG9nZ2xlLWNvbnRlbnQnKS5oaWRlKCk7XG4gICAgJCgnLnRvZ2dsZTpub3QoLmRpc2FibGVkKScpLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnZXhwYW5kZWQnKS5uZXh0KCcudG9nZ2xlLWNvbnRlbnQnKS50b2dnbGUoKTtcbiAgICB9KTtcblxuICAgIC8vIHN1YnNjcmliZSBlbWFpbCBib3hcbiAgICB2YXIgJHN1YnNjcmliZUVtYWlsID0gJCgnLnN1YnNjcmliZS1lbWFpbCcpO1xuICAgIGlmICgkc3Vic2NyaWJlRW1haWwubGVuZ3RoID4gMCkgICAge1xuICAgICAgICAkc3Vic2NyaWJlRW1haWwuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9ICQodGhpcy52YWwoKSk7XG4gICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+IDAgJiYgdmFsICE9PSBSZXNvdXJjZXMuU1VCU0NSSUJFX0VNQUlMX0RFRkFVTFQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIGRvIG5vdCBhbmltYXRlIHdoZW4gY29udGFpbnMgbm9uLWRlZmF1bHQgdmFsdWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJCh0aGlzKS5hbmltYXRlKHtjb2xvcjogJyM5OTk5OTknfSwgNTAwLCAnbGluZWFyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICQodGhpcykudmFsKCcnKS5jc3MoJ2NvbG9yJywgJyMzMzMzMzMnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KS5ibHVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciB2YWwgPSAkLnRyaW0oJCh0aGlzLnZhbCgpKSk7XG4gICAgICAgICAgICBpZiAodmFsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIGRvIG5vdCBhbmltYXRlIHdoZW4gY29udGFpbnMgdmFsdWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQodGhpcykudmFsKFJlc291cmNlcy5TVUJTQ1JJQkVfRU1BSUxfREVGQVVMVClcbiAgICAgICAgICAgICAgICAuY3NzKCdjb2xvcicsICcjOTk5OTk5JylcbiAgICAgICAgICAgICAgICAuYW5pbWF0ZSh7Y29sb3I6ICcjMzMzMzMzJ30sIDUwMCwgJ2xpbmVhcicpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAkKCcucHJpdmFjeS1wb2xpY3knKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIHVybDogJChlLnRhcmdldCkuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIGhlaWdodDogNjAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG5cdCQoXCIjTWFwbW9iaWxlIGFyZWFcIikuY2xpY2soZnVuY3Rpb24gKCkge1xuXHRcdCQoXCIjc3RvcmUtbmFtZVwiKS5yZW1vdmVDbGFzcygnc3RvcmVoZWFkaW5nJyk7XG5cdFx0dmFyIHZhbHVlID0gJCh0aGlzKS5hdHRyKFwiaHJlZlwiKTtcblx0XHR2YXIgdmFsdWVOYW1lID0gdmFsdWUucmVwbGFjZSgnIycsJycpO1xuXHRcdCQoJ2h0bWwsYm9keScpLmFuaW1hdGUoe1xuXHRcdFx0c2Nyb2xsVG9wOiAkKFwiYVtuYW1lPVwiKyB2YWx1ZU5hbWUgK1wiXVwiKS5vZmZzZXQoKS50b3AgLSAyMDBcblx0XHR9KVxuXHR9KTtcbiAgICBcbiAgICAkKCBcIi51c2VyLWluZm9cIiApLmhvdmVyKFxuICAgIFx0ICBmdW5jdGlvbigpIHtcbiAgICBcdFx0ICQodGhpcykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0ICB9LFxuICAgIFx0ICBmdW5jdGlvbigpIHtcbiAgICBcdFx0ICQodGhpcykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0ICB9XG5cbiAgICApO1xuXG4gICAgdmFyIHN0b3Jlc01lZGlhUXVlcnkgPSBtYXRjaE1lZGlhKCcobWF4LXdpZHRoOiAxMDI0cHgpJyk7XG5cdHN0b3Jlc01lZGlhUXVlcnkuYWRkTGlzdGVuZXIobW9iaWxlU3RvcmVzKTtcblx0JChtb2JpbGVTdG9yZXMpO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5kZXRhaWwtdG9nZ2xlLWl0ZW0nLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgXG4gICAgICAgICQodGhpcykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAkKCcuZGlzY291bnQtZGV0YWlscy1lbnRyeScpLnRvZ2dsZUNsYXNzKCdvcGVuJykuYW5pbWF0ZSh7ICdoZWlnaHQnOiAndG9nZ2xlJywgJ29wYWNpdHknOiAndG9nZ2xlJyB9LCAyNTAsIG51bGwsIGZ1bmN0aW9uKCkge1xuICAgICAgICBcdFxuICAgICAgICB9KTtcbiAgICB9KTtcblxuXHQvLyBhZGQgc2hvdy9oaWRlIHBhc3N3b3JkIGZ1bmN0aW9uYWxpdHlcblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbj1cInRvZ2dsZS1wYXNzd29yZC12aXNpYmlsaXR5XCJdJywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJGJ1dHRvbiA9ICQoZS50YXJnZXQpO1xuXHRcdHZhciAkcGFzc3dvcmRJbnB1dCA9ICRidXR0b24uY2xvc2VzdCgnLnBhc3N3b3JkLWhvbGRlcicpLmZpbmQoJ2lucHV0Jyk7XG5cdFx0dmFyIHBhc3N3b3JkSW5wdXRUeXBlID0gJHBhc3N3b3JkSW5wdXQuYXR0cigndHlwZScpO1xuXHRcdGlmIChwYXNzd29yZElucHV0VHlwZSA9PT0gJ3Bhc3N3b3JkJykge1xuXHRcdFx0JGJ1dHRvbi5hZGRDbGFzcygncGFzc3dvcmQtdmlzaWJpbGl0eS0tdmlzaWJsZScpO1xuXHRcdFx0JGJ1dHRvbi5yZW1vdmVDbGFzcygncGFzc3dvcmQtdmlzaWJpbGl0eS0taW52aXNpYmxlJyk7XG5cdFx0XHQkcGFzc3dvcmRJbnB1dC5hdHRyKCd0eXBlJywgJ3RleHQnKS5mb2N1cygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkYnV0dG9uLmFkZENsYXNzKCdwYXNzd29yZC12aXNpYmlsaXR5LS1pbnZpc2libGUnKTtcblx0XHRcdCRidXR0b24ucmVtb3ZlQ2xhc3MoJ3Bhc3N3b3JkLXZpc2liaWxpdHktLXZpc2libGUnKTtcblx0XHRcdCRwYXNzd29yZElucHV0LmF0dHIoJ3R5cGUnLCAncGFzc3dvcmQnKS5mb2N1cygpO1xuXHRcdH1cblx0fSk7XG5cdFxuXHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRpZiAoJCgnLmNzLXJld2FyZHMtcHJvZ3JhbScpLmxlbmd0aCA+PSAxKSB7XG5cdFx0XHRpZiAoJCgnLmN1c3RvbWVyLXJld2FyZHMtbnVtYmVyJykubGVuZ3RoID09IDApIHtcdFxuXHRcdFx0XHRCcmVhZFBheW1lbnRzLm9uKFwiQ0FSRDpSRUNFSVZFX0FQUExJQ0FUSU9OX1JFU1VMVFwiLCBmdW5jdGlvbihjYXJkUmVzdWx0KXtcblx0XHRcdFx0XHQvLyBIYW5kbGUgQXBwbGljYXRpb24gUmVzdWx0XG5cdFx0XHRcdFx0c3dpdGNoKGNhcmRSZXN1bHQucmVzdWx0KXtcblx0XHRcdFx0XHRcdGNhc2UgJ0FQUFJPVkVEJzpcblx0XHRcdFx0XHRcdGNhc2UgJ1BFTkRJTkcnOlx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHRcdFx0dHlwZTogJ3Bvc3QnLFxuXHRcdFx0XHRcdFx0XHRcdHVybDogVXJscy5jcmVhdGVSZXdhcmRzQWNjb3VudCxcblx0XHRcdFx0XHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRcdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRcdFx0XHRcdGVtYWlsQWRkcmVzczogY2FyZFJlc3VsdC5lbWFpbEFkZHJlc3MsXG5cdFx0XHRcdFx0XHRcdFx0XHRwaG9uZU51bWJlcjogY2FyZFJlc3VsdC5tb2JpbGVQaG9uZVxuXHRcdFx0XHRcdFx0XHRcdH0pLFxuXHRcdFx0XHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZygnUmV3YXJkcyBhY2NvdW50IGNyZWF0ZWQuJyk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBCT09ULTUzNjM6IHNob3cvaGlkZSB0b3RhbCBzYXZpbmdzIG1lc3NhZ2UgYmFzZWQgb24gcHJvbW90aW9uIGNhbGxvdXQgbWVzc2FnZXNcblx0JCgnLnByb2R1Y3QtdGlsZScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0dmFyICR0aWxlID0gJCh0aGlzKTtcblx0XHRpZiAoJHRpbGUuZmluZCgnLmhpZGUtdG90YWwtc2F2aW5ncycpLmxlbmd0aCA+IDApIHtcblx0XHRcdCR0aWxlLmZpbmQoJy5wcm9kdWN0LXRvdGFsLXNhdmluZ3MnKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cdFx0fVxuXHR9KTtcblx0aWYoJCgnLnByb2R1Y3QtZGV0YWlsJykuZmluZCgnLmhpZGUtdG90YWwtc2F2aW5ncycpLmxlbmd0aCA+IDApIHtcblx0XHQkKCcucHJvZHVjdC10b3RhbC1zYXZpbmdzJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXHR9XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEFkZHMgY2xhc3MgKCdqcycpIHRvIGh0bWwgZm9yIGNzcyB0YXJnZXRpbmcgYW5kIGxvYWRzIGpzIHNwZWNpZmljIHN0eWxlcy5cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZURvbSgpIHtcbiAgICAvLyBhZGQgY2xhc3MgdG8gaHRtbCBmb3IgY3NzIHRhcmdldGluZ1xuICAgICQoJ2h0bWwnKS5hZGRDbGFzcygnanMnKTtcbiAgICAvLyBsb2FkIGpzIHNwZWNpZmljIHN0eWxlc1xuICAgIHV0aWwubGltaXRDaGFyYWN0ZXJzKCk7XG5cbiAgICAvLyBET00gRVZFTlQgRk9SIEhFQURFUiBTVE9SRSBMT0NBVE9SXG5cdCQoJy5zdG9yZXMtbmVhci1jb250ZW50IC5saXN0LXN0b3JlcycpLmRlbGVnYXRlKCAnYS5tYWtlLXRoaXMtbXlzdG9yZScsICdjbGljaycsZnVuY3Rpb24oZSl7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciBwb3N0Q29kZSA9ICQodGhpcykuYXR0cignZGF0YS1wb3N0YWxjb2RlJyk7XG5cdFx0JCgnYS5pY28tY3Jvc3NoYWlycy11c2UtbXktbG9jYXRpb24nKS5kYXRhKCdwb3N0YWxjb2RlJyxwb3N0Q29kZSk7XG5cdFx0aGVhZGVyTmF2U3RvcmVTZWFyY2goKTtcblx0fSk7XG5cbn1cblxuLy8gUmVzaXplIEhlbHBlclxuZnVuY3Rpb24gcmVzaXplRGV2aWNlSGVscGVyKCkge1xuXHR2YXIgY291bnRyeU91dGZpdHRlcnMgPSAnY291bnRyeV9vdXRmaXR0ZXJzX3VzJztcblx0dmFyIGJvb3RCYXJuID0gJ2Jvb3RiYXJuX3VzJztcblx0dmFyIHNsaWRlck1vYmlsZVN3aXBlcjtcblxuXHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3NpemUtbW9iaWxlIHNpemUtdGFibGV0IHNpemUtZGVza3RvcCcpO1xuXHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gNzY3KSB7XG5cdFx0JCgnaHRtbCcpLmFkZENsYXNzKCdzaXplLW1vYmlsZScpO1xuXHR9IGVsc2UgaWYgKHdpbmRvdy5pbm5lcldpZHRoIDw9IDEwMjQpIHtcblx0XHQkKCdodG1sJykuYWRkQ2xhc3MoJ3NpemUtdGFibGV0Jyk7XG5cdH0gZWxzZSB7XG5cdFx0JCgnaHRtbCcpLmFkZENsYXNzKCdzaXplLWRlc2t0b3AnKTtcblx0fVxuXHRcblx0dmFyICRuYXZpZ2F0aW9uQ29udGFpbmVyID0gJCgnI25hdmlnYXRpb24nKTtcblx0XG5cdGlmICghJCgnLnNlY29uZC1tb2JuYXYnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHQkKCcubmF2LXV0aWxpdGllcycpLmhpZGUoKTtcblx0fVxuXHRcblx0JCgnLm5hdi11dGlsaXRpZXMsICNuYXZpZ2F0aW9uJykucmVtb3ZlQ2xhc3MoJ3ByZWxvYWQnKTtcblx0JCgnI25hdi11dGlscycpLnJlbW92ZUNsYXNzKCdsb2FkaGlkZScpO1xuXHRcblx0aWYgKChzaXRlTmFtZSAhPSBib290QmFybiAmJiB3aW5kb3cuaW5uZXJXaWR0aCA8PSAxMDI0KSB8fCB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRpZiAoc2l0ZU5hbWUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRcdCRuYXZTZWNvbmRhcnkuaW5zZXJ0QWZ0ZXIoJG5hdlVsKTtcblx0XHR9XG5cblx0XHQkc2VjdGlvbkVycm9yRmlndXJlLmluc2VydEJlZm9yZSgkc2VjdGlvbkVycm9yQm94KTtcblx0XHQkbmF2VXRpbGl0aWVzLmluc2VydEFmdGVyKCR0b3BCYW5uZXJJbm5lckxpbmtzKTtcblx0XHRpZiAoJHNsaWRlck1vYmlsZS5sZW5ndGggPiAwKSB7XG5cdFx0XHRzbGlkZXJNb2JpbGVTd2lwZXIgPSBzbGlkZXJzLmluaXQoJy5zbGlkZXItbW9iaWxlJywge2RvdHM6IHRydWUsIGxvb3A6IHRydWV9KTtcblx0XHR9XG5cblx0XHR2YXIgaW1hZ2UgPSAkKFwiLnNsaWRlci1zaW5nbGUtaW1hZ2UgaW1nXCIpO1xuXHRcdCQucmVtb3ZlRGF0YShpbWFnZSwgJ2VsZXZhdGVab29tJyk7XG5cdFx0JCgnLnpvb21Db250YWluZXInKS5yZW1vdmUoKTtcblx0XHRcblx0XHRpZigkKCcuc2VjdGlvbi1vZmZlcnMuYWxsLW9uLXNhbGUnKS5sZW5ndGgpe1xuXHRcdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuXHRcdFx0XHQkKCcuc2VjdGlvbi1vZmZlcnMuYWxsLW9uLXNhbGUgLmNoZXZyb24tY29sbGFwc2UnKS5lYWNoKGZ1bmN0aW9uKCl7XG5cdFx0XHRcdFx0JCh0aGlzKS5jbGljaygpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0sIDEzKTtcblx0XHRcdFxuXHRcdH1cblx0XHQkKCcuYWNjb3JkaW9uLW1vYmlsZScpLmVhY2goZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGFjY01vYmlsZSA9ICQodGhpcyk7XG5cblx0XHRcdGlmICghYWNjTW9iaWxlLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0XHRhY2NNb2JpbGUuZmluZCgnLmFjY29yZGlvbi1tb2JpbGUtYm9keScpLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHQkbmF2VWwuZmluZCgnLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cblx0XHQkbmF2VXRpbGl0aWVzLmluc2VydEJlZm9yZSgkdG9wQmFubmVyQmFySW5uZXIpO1xuXHRcdGlmIChzaXRlTmFtZSAhPSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0JG5hdlNlY29uZGFyeS5wcmVwZW5kVG8oJHRvcEJhbm5lckJhcik7XG5cdFx0fVxuXG5cdFx0JHNlY3Rpb25FcnJvckZpZ3VyZS5pbnNlcnRBZnRlcigkc2VjdGlvbkVycm9yQm94KTtcblx0XHQkbmF2aWdhdGlvbi5yZW1vdmVBdHRyKCdzdHlsZScpO1xuXG5cdFx0aWYgKCRzbGlkZXJNb2JpbGUubGVuZ3RoID4gMCkge1xuXHRcdFx0aWYgKCRzbGlkZXJNb2JpbGUuZmluZCgnLnN3aXBlci1pbml0aWFsaXplZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0c2xpZGVyTW9iaWxlU3dpcGVyLmRlc3Ryb3koKTtcblx0XHRcdH1cblx0XHRcdGlmICgkc2xpZGVyTW9iaWxlLmZpbmQoJy5zbGljay1pbml0aWFsaXplZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JHNsaWRlck1vYmlsZS5zbGljaygndW5zbGljaycpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQkKCcuYWNjb3JkaW9uLW1vYmlsZS1ib2R5Jykuc2hvdygpO1xuXHRcdFxuXHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnbWVudS1hY3RpdmUnKTtcblx0XHQkKCcubWVudS10b2dnbGUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0JCgnI25hdmlnYXRpb24gLmxldmVsLTInKS5oaWRlKCk7XG5cdH1cblx0XG5cdHJlc2l6ZUxheW91dEhlbHBlcigpO1xufVxuXG5mdW5jdGlvbiByZXNpemVMYXlvdXRIZWxwZXIoKSB7XG5cdHZhciBuZXdNYXJnaW5Ub3AgPSAwO1xuXHR2YXIgaW5uZXJXaWR0aFRocmVzaG9sZDtcdFxuXHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRpbm5lcldpZHRoVGhyZXNob2xkID0gMTAyMztcblx0fSBlbHNlIHtcblx0XHRpbm5lcldpZHRoVGhyZXNob2xkID0gNzY3O1xuXHR9XG5cdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSBpbm5lcldpZHRoVGhyZXNob2xkKSB7XG5cdFx0bmV3TWFyZ2luVG9wID0gcGFyc2VGbG9hdCgkKCcuaGVhZGVyLXdyYXBwZXInKS5vdXRlckhlaWdodCgpKTtcblx0fVxuXHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnbWVudS1hY3RpdmUnKSkge1xuXHRcdFx0JCgnI21haW4nKS5jc3MoJ21hcmdpbi10b3AnLCBuZXdNYXJnaW5Ub3ApO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnbWVudS1hY3RpdmUnKSkge1xuXHRcdFx0JCgnI3dyYXBwZXInKS5jc3MoJ21hcmdpbi10b3AnLCBuZXdNYXJnaW5Ub3ApO1xuXHRcdH1cblx0fVxuXHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnaW5pdGlhbGl6ZWQnKSkge1xuXHRcdCQoJ2h0bWwnKS5hZGRDbGFzcygnaW5pdGlhbGl6ZWQnKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1c2VteWxvY2F0aW9uKHN0b3JlaWQpIHtcblx0dmFyIHRfdXJsID0gVXJscy51c2VjdXJyZW50bG9jYXRpb247XG5cdGlmIChzdG9yZWlkID09PSB1bmRlZmluZWQpIHtcblx0XHRzdG9yZWlkID0gJ2dldGFsbCc7XG5cdH1cblxuXHQkLmFqYXgoe1xuXHQgICB1cmw6IHRfdXJsLFxuXHQgICB0eXBlOiAnUE9TVCcsXG5cdCAgIGRhdGE6IHsgJ3NvdXJjZScgOiAnYWpheCcgfSxcblx0ICAgZGF0YVR5cGU6ICdqc29uJyxcblx0ICAgZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdCAgIGNvbnNvbGUubG9nKCdlcnJvcicpO1xuXHQgICB9LFxuXHQgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhSnNvbikge1xuXHQgICAgICBpZiggJ3N0b3JlcycgaW4gZGF0YUpzb24gJiYgZGF0YUpzb25bJ3N0b3JlcyddLmxlbmd0aCA+IDAgKSB7XG5cdCAgICBcdCAgXHRpZihzdG9yZWlkID09ICdnZXRhbGwnKSB7XG5cdCAgICBcdCAgXHRcdCQoJy5zdG9yZXMtbmVhci1jb250ZW50IC5zdG9yZXMtbmVhci1ib2R5IHVsLmxpc3Qtc3RvcmVzJykuaHRtbCgnJyk7XG5cdCAgICBcdCAgXHR9XG5cdFx0XHRcdCQoJ2Rpdi5zdG9yZXMtbmVhci1hY3Rpb25zIGEuZ28tdG8tZmluZHN0b3JlJykuaHRtbChSZXNvdXJjZXMuRklORF9NT1JFX1NUT1JFUyk7XG5cdFx0XHRcdGlmICggZGF0YUpzb25bJ3N0b3JlcyddLmxlbmd0aCA9PSAxICkge1xuXHRcdFx0XHRcdCQoJy5zdG9yZXMtbmVhci1jb250ZW50Jykuc2xpZGVVcCgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFKc29uWydzdG9yZXMnXS5mb3JFYWNoKGZ1bmN0aW9uKGVsZW1lbnQsIGluZGV4KXtcblx0XHRcdFx0XHR2YXIgc3RvcmUgPSBlbGVtZW50O1xuXHRcdFx0XHRcdHZhciBodG1sRGlzcGxheSA9ICcnO1xuXHRcdFx0XHRcdHZhciBzdG9yZVBob25lTnVtYmVyID0gKCcnICsgZWxlbWVudFsncGhvbmUnXSkucmVwbGFjZSgvXFxEL2csJycpO1xuXHRcdFx0XHRcdHZhciBwb3N0YWxDb2RlVmFsID0gKCB0eXBlb2YgZWxlbWVudFsncG9zdGFsQ29kZSddICE9ICd1bmRlZmluZWQnID8gZWxlbWVudFsncG9zdGFsQ29kZSddICA6ICcnICk7XG5cblx0XHRcdFx0XHRpZihzdG9yZWlkID09ICdnZXRhbGwnKSB7XG5cdFx0XHRcdFx0XHRpZihpbmRleCA9PSAwKSB7XG5cdFx0XHRcdFx0XHRcdGh0bWxEaXNwbGF5ICs9ICc8c3BhbiBjbGFzcz1cInJlZCBzdG9yZS1uYW1lLXZhbHVlXCI+JytlbGVtZW50WyduYW1lJ10rJzwvc3Bhbj4nO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSBlbGVtZW50WydhZGRyZXNzMSddO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPGJyLz4nKyAoIHR5cGVvZiBlbGVtZW50WydjaXR5J10gIT0gJ3VuZGVmaW5lZCcgPyBlbGVtZW50WydjaXR5J10gKycsICcgOiAnJyApO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAoIHR5cGVvZiBlbGVtZW50WydzdGF0ZUNvZGUnXSAhPSAndW5kZWZpbmVkJyA/IGVsZW1lbnRbJ3N0YXRlQ29kZSddICsnICcgOiAnJyApO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSBwb3N0YWxDb2RlVmFsO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPGJyIC8+PGEgaHJlZj1cInRlbDonK3N0b3JlUGhvbmVOdW1iZXIrJ1wiPicrc3RvcmVbJ3Bob25lJ10rJzwvYT4nO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPHNwYW4+Jyt1bmVzY2FwZShzdG9yZVsnc3RvcmVIb3VycyddKSsnPC9zcGFuPic7XG5cdFx0XHRcdFx0XHRcdCQoJy5zdG9yZXMtZHJvcGRvd24gLmN1cnJlbnQtc3RvcmUgYWRkcmVzcycpLmh0bWwoaHRtbERpc3BsYXkpO1xuXHRcdFx0XHRcdFx0XHQkKCcuc3RvcmVzLWRyb3Bkb3duIC5jdXJyZW50LXN0b3JlJykuc2xpZGVEb3duKCk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPGxpPjxoNT48c3Bhbj4nK2VsZW1lbnRbJ25hbWUnXSsnPC9zcGFuPjxhIGhyZWY9XCIjXCIgY2xhc3M9XCJtYWtlLXRoaXMtbXlzdG9yZVwiIGlkPVwiJyArIGVsZW1lbnRbJ0lEJ10gKyAnXCIgZGF0YS1wb3N0YWxjb2RlPVwiJytwb3N0YWxDb2RlVmFsKydcIj4nK1Jlc291cmNlcy5NQUtFX1RISVNfTVlTVE9SRSsnPC9hPjwvaDU+Jztcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gJzxhZGRyZXNzPicrZWxlbWVudFsnYWRkcmVzczEnXTtcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gJzxici8+JysgKCB0eXBlb2YgZWxlbWVudFsnY2l0eSddICE9ICd1bmRlZmluZWQnID8gZWxlbWVudFsnY2l0eSddICsnLCAnIDogJycgKTtcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gKCB0eXBlb2YgZWxlbWVudFsnc3RhdGVDb2RlJ10gIT0gJ3VuZGVmaW5lZCcgPyBlbGVtZW50WydzdGF0ZUNvZGUnXSArJyAnIDogJycgKTtcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gcG9zdGFsQ29kZVZhbDtcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gJzxiciAvPjxhIGhyZWY9XCJ0ZWw6JytzdG9yZVBob25lTnVtYmVyKydcIj4nK3N0b3JlWydwaG9uZSddKyc8L2E+Jztcblx0XHRcdFx0XHRcdFx0aHRtbERpc3BsYXkgKz0gJy88YWRkcmVzcz4nICsgdW5lc2NhcGUoc3RvcmVbJ3N0b3JlSG91cnMnXSk7XG5cdFx0XHRcdFx0XHRcdGh0bWxEaXNwbGF5ICs9ICc8L2xpPic7XG5cdFx0XHRcdFx0XHRcdCQoJy5zdG9yZXMtbmVhci1jb250ZW50IC5zdG9yZXMtbmVhci1ib2R5IHVsLmxpc3Qtc3RvcmVzJykuYXBwZW5kKCQoaHRtbERpc3BsYXkpKTtcblx0XHRcdFx0XHRcdFx0JCgnLnN0b3Jlcy1uZWFyLWNvbnRlbnQnKS5zbGlkZURvd24oKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0aWYoc3RvcmVpZCA9PSBlbGVtZW50WydJRCddKSB7XG5cdFx0XHRcdFx0XHRcdGh0bWxEaXNwbGF5ICs9ICc8c3BhbiBjbGFzcz1cInJlZCBzdG9yZS1uYW1lLXZhbHVlXCI+JytlbGVtZW50WyduYW1lJ10rJzwvc3Bhbj4nO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSBlbGVtZW50WydhZGRyZXNzMSddO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPGJyLz4nKyAoIHR5cGVvZiBlbGVtZW50WydjaXR5J10gIT0gJ3VuZGVmaW5lZCcgPyBlbGVtZW50WydjaXR5J10gKycsICcgOiAnJyApO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAoIHR5cGVvZiBlbGVtZW50WydzdGF0ZUNvZGUnXSAhPSAndW5kZWZpbmVkJyA/IGVsZW1lbnRbJ3N0YXRlQ29kZSddICsnICcgOiAnJyApO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSBwb3N0YWxDb2RlVmFsO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPGJyIC8+PGEgaHJlZj1cInRlbDonK3N0b3JlUGhvbmVOdW1iZXIrJ1wiPicrc3RvcmVbJ3Bob25lJ10rJzwvYT4nO1xuXHRcdFx0XHRcdFx0XHRodG1sRGlzcGxheSArPSAnPHNwYW4+Jyt1bmVzY2FwZShzdG9yZVsnc3RvcmVIb3VycyddKSsnPC9zcGFuPic7XG5cdFx0XHRcdFx0XHRcdCQoJy5zdG9yZXMtZHJvcGRvd24gLmN1cnJlbnQtc3RvcmUgYWRkcmVzcycpLmh0bWwoaHRtbERpc3BsYXkpO1xuXHRcdFx0XHRcdFx0XHQkKCcuc3RvcmVzLWRyb3Bkb3duIC5jdXJyZW50LXN0b3JlJykuc2xpZGVEb3duKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnLnN0b3Jlcy1uZWFyLWNvbnRlbnQnKS5zbGlkZVVwKCk7XG5cdFx0XHRcdCQoJ2Rpdi5zdG9yZXMtbmVhci1hY3Rpb25zIGEuZ28tdG8tZmluZHN0b3JlJykuaHRtbChSZXNvdXJjZXMuRklORF9TVE9SRVMpO1xuXHRcdFx0XHQkKCcuc3RvcmVzLWRyb3Bkb3duIC5jdXJyZW50LXN0b3JlJykuc2xpZGVVcCgpO1xuXHRcdFx0XHRpZiAoICQoJy5zdG9yZXMtZHJvcGRvd24gaDMubm9fcmVzdWx0cycpLmxlbmd0aCA9PSAwICkge1xuXHRcdFx0XHRcdCQoJy5zdG9yZXMtZHJvcGRvd24nKS5wcmVwZW5kKCc8aDMgY2xhc3M9XCJub19yZXN1bHRzXCI+JytSZXNvdXJjZXMuTk9fU1RPUkVfUkVTVUxUUysnPC9oMz4nKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcuc3RvcmVzLWRyb3Bkb3duIGgzLm5vX3Jlc3VsdHMnKS5mYWRlSW4oKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkKCcuc3RvcmVzLWRyb3Bkb3duIGgzLm5vX3Jlc3VsdHMnKS5zaG93KCkuZGVsYXkoMjAwMCkuZmFkZU91dCgpO1xuXHRcdCAgfVxuXHQgICB9XG5cdH0pO1xufVxuXG5cbi8qKiBcbiAqXG4gKiBNb3ZlcyBjdXN0b21lciBzcGVjaWZpYyBzdG9yZXMgaW5mbyBpbiBtYWluIGhlYWRlciB0byBtb2JpbGUgdXRpbGl0eSBoZWFkZXIuXG4gKiBUaGlzIGlzIG5lZWRlZCBiZWNhdXNlIHRoZSBzdG9yZSBpbmZvIGlzIHBhcnQgb2YgYSByZW1vdGUgaW5jbHVkZSBpbiBhbm90aGVyIHNwb3Qgb24gZGVza3RvcC4gXG4gKlxuICovXG5mdW5jdGlvbiBtb2JpbGVTdG9yZXMoKSB7XHRcblx0dmFyICRtb2JpbGVTdG9yZU1ldGFkYXRhID0gJCgnI21vYmlsZS1zdG9yZU1ldGFkYXRhJyk7XG5cdHZhciAkbW9iaWxlU3RvcmVCYW5uZXJUZXh0ID0gJCgnI21vYmlsZS1iYW5uZXItc3RvcmUtdGV4dCcpO1xuXHRcblx0aWYgKCRtb2JpbGVTdG9yZU1ldGFkYXRhICE9PSB1bmRlZmluZWQgJiYgJG1vYmlsZVN0b3JlTWV0YWRhdGEgIT0gbnVsbCAmJiAkbW9iaWxlU3RvcmVNZXRhZGF0YS5sZW5ndGggID4gMCl7XG5cdFx0aWYgKCRtb2JpbGVTdG9yZUJhbm5lclRleHQgIT09IHVuZGVmaW5lZCAmJiAkbW9iaWxlU3RvcmVCYW5uZXJUZXh0ICE9IG51bGwgJiYgJG1vYmlsZVN0b3JlQmFubmVyVGV4dC5sZW5ndGggID4gMCl7XG5cdFx0XHR2YXIgaXNPcGVuID0gJG1vYmlsZVN0b3JlTWV0YWRhdGEuZGF0YSgnaXMtb3BlbicpO1xuXHRcdFx0aWYgKGlzT3Blbil7XG5cdFx0XHRcdHZhciBzdG9yZU5hbWUgPSAkbW9iaWxlU3RvcmVNZXRhZGF0YS5kYXRhKCdzdG9yZS1uYW1lJyk7XG5cdFx0XHRcdHZhciBvcGVuVW50aWwgPSAgJG1vYmlsZVN0b3JlTWV0YWRhdGEuZGF0YSgnb3Blbi11bnRpbCcpO1xuXHRcdFx0XHR2YXIgY2xvc2luZ1RpbWUgPSAgJG1vYmlsZVN0b3JlTWV0YWRhdGEuZGF0YSgnY2xvc2luZy10aW1lJyk7XG5cdFx0XHRcdHZhciBiYW5uZXJUZXh0ID0gc3RvcmVOYW1lICsgJyAmIzgyMjY7ICcgKyBvcGVuVW50aWwgKyAnICcgKyBjbG9zaW5nVGltZTtcblx0XHRcdFx0JG1vYmlsZVN0b3JlQmFubmVyVGV4dC5odG1sKGJhbm5lclRleHQpO1x0XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXIgY2xvc2VkVGV4dCA9ICAkbW9iaWxlU3RvcmVNZXRhZGF0YS5kYXRhKCdjbG9zZWQtdGV4dCcpO1xuXHRcdFx0XHQkbW9iaWxlU3RvcmVCYW5uZXJUZXh0Lmh0bWwoY2xvc2VkVGV4dCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHNldENvb2tpZShjbmFtZSwgY3ZhbHVlLCBleGRheXMpIHtcblx0dmFyIGQgPSBuZXcgRGF0ZSgpO1xuXHRkLnNldFRpbWUoZC5nZXRUaW1lKCkgKyAoZXhkYXlzICogMjQgKiA2MCAqIDYwICogMTAwMCkpO1xuXHR2YXIgZXhwaXJlcyA9IFwiZXhwaXJlcz1cIitkLnRvVVRDU3RyaW5nKCk7XG5cdGRvY3VtZW50LmNvb2tpZSA9IGNuYW1lICsgXCI9XCIgKyBjdmFsdWUgKyBcIjtcIiArIGV4cGlyZXMgKyBcIjtwYXRoPS9cIjtcbiAgfVxuICBcbiAgZnVuY3Rpb24gZ2V0Q29va2llKGNuYW1lKSB7XG5cdHZhciBuYW1lID0gY25hbWUgKyBcIj1cIjtcblx0dmFyIGNhID0gZG9jdW1lbnQuY29va2llLnNwbGl0KCc7Jyk7XG5cdGZvcih2YXIgaSA9IDA7IGkgPCBjYS5sZW5ndGg7IGkrKykge1xuXHQgIHZhciBjID0gY2FbaV07XG5cdCAgd2hpbGUgKGMuY2hhckF0KDApID09ICcgJykge1xuXHRcdGMgPSBjLnN1YnN0cmluZygxKTtcblx0ICB9XG5cdCAgaWYgKGMuaW5kZXhPZihuYW1lKSA9PSAwKSB7XG5cdFx0cmV0dXJuIGMuc3Vic3RyaW5nKG5hbWUubGVuZ3RoLCBjLmxlbmd0aCk7XG5cdCAgfVxuXHR9XG5cdHJldHVybiBcIlwiO1xuICB9XG5cblxuXG5mdW5jdGlvbiBhZGRQcm9tb3Rpb25EYXRhTGF5ZXJzKCkge1xuXHR2YXIgJGNvbnRhaW5lcnMgPSAkKCcuYWNjb3JkaW9uOnZpc2libGUsIC5zZWN0aW9uLW9mZmVyczp2aXNpYmxlLCAuY2F0LWhlYWRlci1jb250ZW50LmNhdC1oZWFkZXItc2xpZGVyOnZpc2libGUnKTtcblx0aWYgKCRjb250YWluZXJzLmxlbmd0aCA+IDApIHtcblx0XHQkY29udGFpbmVycy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyICRjb250YWluZXIgPSAkKHRoaXMpO1xuXHRcdFx0aWYgKCRjb250YWluZXIuYXR0cignZGF0YS1sYXllci1hZGRlZCcpICE9ICd0cnVlJyAmJiAkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRpbGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHZhciBjb250YWluZXJJZCA9ICRjb250YWluZXIuYXR0cignY29udGVudC1zbG90LWlkJykgfHwgJGNvbnRhaW5lci5hdHRyKCdpZCcpO1xuXG5cdFx0XHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0XHRcdHByb21vdGlvbl9uYW1lOiBjb250YWluZXJJZFxuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIHBhZ2VUeXBlO1xuXHRcdFx0XHR2YXIgJHdyYXBwZXIgPSAkY29udGFpbmVyLmNsb3Nlc3QoJy5hZGQtdG8tY2FydC1tb2RhbCcpO1xuXHRcdFx0XHRpZiAoJHdyYXBwZXIubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHBhZ2VUeXBlID0gJ2FkZHRvY2FydG1vZGFsJztcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICghcGFnZVR5cGUpIHtcblx0XHRcdFx0XHQkd3JhcHBlciA9ICQoJyN3cmFwcGVyJyk7XG5cdFx0XHRcdFx0aWYgKCR3cmFwcGVyLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdGlmIChwYWdlQ29udGV4dCAmJiBwYWdlQ29udGV4dC50eXBlKSB7XG5cdFx0XHRcdFx0XHRcdHN3aXRjaCAocGFnZUNvbnRleHQudHlwZSkge1xuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ3N0b3JlZnJvbnQnOlxuXHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ0hvbWVwYWdlJztcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ3NlYXJjaCc6XG5cdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnUExQJztcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ3Byb2R1Y3QnOlxuXHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ1BEUCc7XG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRcdFx0XHRjYXNlICdjYXJ0Jzpcblx0XHRcdFx0XHRcdFx0XHRwYWdlVHlwZSA9ICdDYXJ0Jztcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ29uZXBjaGVja291dCc6XG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAnb25lcGNoZWNrb3V0X2dyb3Vwcyc6XG5cdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnQ2hlY2tvdXQnO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAnb3JkZXJjb25maXJtYXRpb24nOlxuXHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ09yZGVyIENvbmZpcm1hdGlvbic7XG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRcdFx0XHRjYXNlICdjdXN0b21lcnNlcnZpY2UnOlxuXHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ0N1c3RvbWVyIFNlcnZpY2UnO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAnYWNjb3VudCc6XG5cdFx0XHRcdFx0XHRcdFx0cGFnZVR5cGUgPSAnQWNjb3VudCc7XG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRcdFx0XHRjYXNlICdjb250ZW50Jzpcblx0XHRcdFx0XHRcdFx0XHRwYWdlVHlwZSA9ICdDb250ZW50IFBhZ2UnO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAnZXJyb3InOlxuXHRcdFx0XHRcdFx0XHRcdHBhZ2VUeXBlID0gJ0Vycm9yIFBhZ2UnO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1x0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHBhZ2VUeXBlKSB7XG5cdFx0XHRcdFx0ZGF0YU9iamVjdC5wcm9tb3Rpb25faWQgPSBwYWdlVHlwZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1ZpZXdQcm9tb3Rpb24nLCBkYXRhT2JqZWN0LCB7IENvbnRhaW5lcjogJGNvbnRhaW5lciB9KTtcblx0XHRcdFx0JGNvbnRhaW5lci5hdHRyKCdkYXRhLWxheWVyLWFkZGVkJywgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxudmFyIHBhZ2VzID0ge1xuXHRzdG9yZWZyb250OiByZXF1aXJlKCcuL3BhZ2VzL3N0b3JlZnJvbnQnKSxcblx0YWNjb3VudDogcmVxdWlyZSgnLi9wYWdlcy9hY2NvdW50JyksXG5cdGJvb3RiYXJuZXhwcmVzczogcmVxdWlyZSgnLi9wYWdlcy9ib290YmFybmV4cHJlc3MnKSxcblx0Ym9vdGZpbmRlcjogcmVxdWlyZSgnLi9wYWdlcy9ib290ZmluZGVyJyksXG4gICAgY2FydDogcmVxdWlyZSgnLi9wYWdlcy9jYXJ0JyksXG5cdGNhcnRfZWNobzogcmVxdWlyZSgnLi9wYWdlcy9jYXJ0X2VjaG8nKSxcbiAgICBjaGVja291dDogcmVxdWlyZSgnLi9wYWdlcy9jaGVja291dCcpLFxuXHRjaGVja291dF9lY2hvOiByZXF1aXJlKCcuLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dF9lY2hvJyksXG4gICAgY29tcGFyZTogcmVxdWlyZSgnLi9wYWdlcy9jb21wYXJlJyksXG4gICAgcHJvZHVjdDogcmVxdWlyZSgnLi9wYWdlcy9wcm9kdWN0JyksXG4gICAgcmVnaXN0cnk6IHJlcXVpcmUoJy4vcGFnZXMvcmVnaXN0cnknKSxcbiAgICBzZWFyY2g6IHJlcXVpcmUoJy4vcGFnZXMvc2VhcmNoJyksXG4gICAgc3RvcmVsb2NhdG9yOiByZXF1aXJlKCcuL3BhZ2VzL3N0b3JlbG9jYXRvcicpLFxuICAgIG9uZXBjaGVja291dDogcmVxdWlyZSgnLi9wYWdlcy9vbmVwY2hlY2tvdXQnKSxcbiAgICBvbmVwY2hlY2tvdXRfZ3JvdXBzOiByZXF1aXJlKCcuL3BhZ2VzL29uZXBjaGVja291dF9ncm91cHMnKSxcblx0b3JkZXJjb25maXJtYXRpb246IHJlcXVpcmUoJy4vcGFnZXMvb3JkZXJjb25maXJtYXRpb24nKSxcbiAgICBjYXRlZ29yeWxhbmRpbmc6IHJlcXVpcmUoJy4vcGFnZXMvY2F0ZWdvcnlsYW5kaW5nJyksXG4gICAgY29udGVudDogcmVxdWlyZSgnLi9wYWdlcy9jb250ZW50JyksXG4gICAgYXV0aGVudGljYXRpb25fRW1haWxBZGRyZXNzQ2FwdHVyZTogcmVxdWlyZSgnLi9wYWdlcy9BdXRoZW50aWNhdGlvbi9FbWFpbEFkZHJlc3NDYXB0dXJlJykgXG59O1xuXG52YXIgbGFzdFNjcm9sbFRvcCA9IDA7IFxudmFyIHNjcm9sbERlbHRhID0gMTAwO1xudmFyIGZpeGVkSGVhZGVyTGltaXQgPSA4MDA7XG52YXIgaGVhZGVyV3JhcHBlciA9ICQoJy5oZWFkZXItd3JhcHBlcicpO1xuXG52YXIgYXBwID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcblx0XHQkLmV4dGVuZChwYWdlLCB3aW5kb3cucGFnZUNvbnRleHQpO1xuXG4gICAgXHQkc2xpZGVyTW9iaWxlID0gJCgnLnNsaWRlci1tb2JpbGUnKTtcblx0XHQkbmF2U2Vjb25kYXJ5IFx0XHRcdD0gJCgnLm5hdi1zZWNvbmRhcnknKTtcblx0XHQkbmF2VXRpbGl0aWVzIFx0XHRcdD0gJCgnLm5hdi11dGlsaXRpZXMnKTtcblx0XHQkbmF2VWwgXHRcdFx0XHRcdD0gJCgnI25hdmlnYXRpb24gPiB1bCcpO1xuXHRcdCR0b3BCYW5uZXJCYXIgXHRcdFx0PSAkKCcudG9wLWJhbm5lci1iYXInKTtcblx0XHQkdG9wQmFubmVyQmFySW5uZXJcdFx0PSAkKCcudG9wLWJhbm5lci1iYXItaW5uZXInKTtcblx0XHQkbmF2aWdhdGlvbiBcdFx0XHQ9ICQoJyNuYXZpZ2F0aW9uJyk7XG5cdFx0JHRvcEJhbm5lcklubmVyTGlua3MgXHQ9ICQoJy50b3AtYmFubmVyLWlubmVyLWxpbmtzJyk7XG5cdFx0JHNlbGVjdFNvcnQgXHRcdFx0PSAkKCcjc29ydC1ieScpO1xuXHRcdCRzZWNvbmRhcnlIZWFkIFx0XHRcdD0gJCgnI3NlY29uZGFyeSAucmVmaW5lbWVudHMtaGVhZCcpO1xuXHRcdCRzZWFyY2hSZXN1bHRDb250YWluZXIgXHQ9ICQoJyNzZWFyY2gtcmVzdWx0Jyk7XG5cdFx0JHByb2R1Y3RDb250YWluZXJJbWFnZVx0PSAkKCcjcGRwTWFpbiAucHJvZHVjdC1pbWFnZS1jb250YWluZXInKTtcblx0XHQkcHJvZHVjdERldGFpbFx0XHRcdD0gJCgnI3BkcE1haW4gLnByb2R1Y3QtZGV0YWlsJyk7XG5cdFx0JHNlY3Rpb25DaGVja291dCBcdFx0PSAkKCcuc2VjdGlvbi1jaGVja291dCcpO1xuXHRcdCRtYWluSW5uZXJBbHRcdFx0XHQ9ICQoJy5tYWluLWlubmVyLWFsdCcpO1xuXHRcdCRzZWN0aW9uRXJyb3JGaWd1cmUgXHQ9ICQoJy5zZWN0aW9uLWVycm9yIGZpZ3VyZScpO1xuXHRcdCRzZWN0aW9uRXJyb3JCb3ggXHRcdD0gJCgnLnNlY3Rpb24tZXJyb3IgLmJveCcpO1xuXHRcdCRmb290ZXJNZW51SXRlbXNcdFx0PSAkKCcuZm9vdGVyLWl0ZW0gLmNvbnRlbnQtYXNzZXQnKTtcblx0XHQkcHJvbW9NZXNzYWdlc1x0XHQ9ICRwcm9kdWN0Q29udGFpbmVySW1hZ2UuZmluZCgnLnByb21vLW1lc3NhZ2VzJyk7XG4gICAgXHRzaXRlTmFtZSA9IHBhZ2VDb250ZXh0LnNpdGUgfHwgJyc7XG4gICAgXHR3aW5kb3cuc2dEaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xuICAgIFx0d2luZG93LnNnVXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuICAgIFx0XG4gICAgICAgIGlmIChkb2N1bWVudC5jb29raWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnYnJvd3Nlci1jb21wYXRpYmlsaXR5LWFsZXJ0IGNvb2tpZXMnKS5hcHBlbmQoJCgnPHAvPicpLmFkZENsYXNzKCdicm93c2VyLWVycm9yJykuaHRtbChSZXNvdXJjZXMuQ09PS0lFU19ESVNBQkxFRCkpLmFwcGVuZFRvKCcjYnJvd3Nlci1jaGVjaycpO1xuICAgICAgICAgICAgJCgnLmJyb3dzZXItY29tcGF0aWJpbGl0eS1hbGVydC5jb29raWVzJykucHJlcGVuZCgnPGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS0zeCBwdWxsLWxlZnRcIj48L2k+Jyk7XG4gICAgICAgIH1cbiAgICAgICAgaW5pdGlhbGl6ZURvbSgpO1xuICAgICAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgICAgIFxuXHRcdGxvZ2luLmluaXQocGFnZS5vcHRpb25zKTtcblx0XHRyZWdpc3Rlci5pbml0KCk7XG4gICAgICAgIG5hdmlnYXRpb24uSW5pdGlhbGl6ZSgpO1xuICAgICAgICBjb3VudHJpZXMuaW5pdCgpO1xuICAgICAgICAvL3Rvb2x0aXAuaW5pdCgpO1xuICAgICAgICBtaW5pY2FydC5pbml0KCk7XG4gICAgICAgIHZhbGlkYXRvci5pbml0KCk7XG4gICAgICAgIHJhdGluZy5pbml0KCk7XG4gICAgICAgIHNlYXJjaHBsYWNlaG9sZGVyLmluaXQoKTtcblx0XHRyb3RhdGUzZC5pbml0KCk7XG4gICAgICAgIGNvdW50X2Rvd24uaW5pdCgpO1xuICAgICAgICBsYXp5bG9hZFBhZ2VFbGVtZW50cy5pbml0KCk7XG4gICAgICAgIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlIZWxwZXIuaW5pdGlhbGl6ZUFsbEZvdW5kQ29tcG9uZW50cygpO1xuXHRcdHNsaWNrSGVscGVycy5pbml0KCk7XG5cdFx0aWYgKHBhZ2VDb250ZXh0ICYmICd0eXBlJyBpbiBwYWdlQ29udGV4dCAmJiBwYWdlQ29udGV4dC50eXBlICE9ICdjYXJ0JyAmJiBwYWdlQ29udGV4dC50eXBlICE9ICdvbmVwY2hlY2tvdXQnICYmIHBhZ2VDb250ZXh0LnR5cGUgIT0gJ29uZXBjaGVja291dF9ncm91cHMnKSB7XG4gICAgICAgICAgICBxdWFudGl0eVN0ZXBwZXIuaW5pdCgpO1xuICAgICAgICB9XG5cdFx0d2lzaGxpc3QuaW5pdCgpO1xuXHRcdEdsb2JhbGUuaW5pdGlhbGl6ZSgpO1xuXHRcdFxuICAgICAgICAvLyBleGVjdXRlIHBhZ2Ugc3BlY2lmaWMgaW5pdGlhbGl6YXRpb25zXG4gICAgICAgIFxuICAgICAgICB2YXIgbnMgPSBwYWdlLm5zO1xuICAgICAgICBpZiAobnMgJiYgcGFnZXNbbnNdICYmIHBhZ2VzW25zXS5pbml0KSB7XG4gICAgICAgICAgICBwYWdlc1tuc10uaW5pdChwYWdlLm9wdGlvbnMgfHwge30pO1xuICAgICAgICB9XG5cbiAgICAgICAgR29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yUGFnZShwYWdlKTtcbiAgICAgICAgRW1haWxTaWdudXAuSW5pdGlhbGl6ZShwYWdlKTtcbiAgICAgICAgXG4gICAgICAgIC8vIENoZWNrIFRMUyBzdGF0dXMgaWYgaW5kaWNhdGVkIGJ5IHNpdGUgcHJlZmVyZW5jZVxuICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNIRUNLX1RMUyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGxzLmdldFVzZXJBZ2VudCgpO1xuXHRcdH1cblxuICAgICAgICAvLyBJbml0aWFsaXplIFN0aWNreSBoZWFkZXIgZXZlbnRzXG4gICAgICAgICQod2luZG93KS5zY3JvbGwoZnVuY3Rpb24oZXZlbnQpe1xuXHRcdFx0aWYgKChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyB8fCBzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykgJiYgd2luZG93LmlubmVyV2lkdGggPD0gMTAyMykge1xuXHRcdFx0XHRpZiAoJCh3aW5kb3cpLnNjcm9sbFRvcCgpID4gZml4ZWRIZWFkZXJMaW1pdCkge1xuXHRcdFx0XHRcdGhlYWRlcldyYXBwZXIuYWRkQ2xhc3MoJ2hlYWRlci1maXhlZCcpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGhlYWRlcldyYXBwZXIucmVtb3ZlQ2xhc3MoJ2hlYWRlci1maXhlZCcpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIG5vd1Njcm9sbFRvcCA9ICQodGhpcykuc2Nyb2xsVG9wKCk7XG5cdFx0XHRcdGlmKE1hdGguYWJzKGxhc3RTY3JvbGxUb3AgLSBub3dTY3JvbGxUb3ApID49IHNjcm9sbERlbHRhKXtcblx0XHRcdFx0XHRpZiAobm93U2Nyb2xsVG9wID4gbGFzdFNjcm9sbFRvcCl7XG5cdFx0XHRcdFx0XHRpZiAoaGVhZGVyV3JhcHBlci5oYXNDbGFzcygnaGVhZGVyLWZpeGVkLWFjdGl2ZScpKSB7XG5cdFx0XHRcdFx0XHRcdGhlYWRlcldyYXBwZXIucmVtb3ZlQ2xhc3MoJ2hlYWRlci1maXhlZC1hY3RpdmUnKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0aWYgKCQod2luZG93KS5zY3JvbGxUb3AoKSA+IGZpeGVkSGVhZGVyTGltaXQpIHtcblx0XHRcdFx0XHRcdFx0aWYgKCFoZWFkZXJXcmFwcGVyLmhhc0NsYXNzKCdoZWFkZXItZml4ZWQtYWN0aXZlJykpIHtcblx0XHRcdFx0XHRcdFx0XHRoZWFkZXJXcmFwcGVyLmFkZENsYXNzKCdoZWFkZXItZml4ZWQtYWN0aXZlJyk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGhlYWRlcldyYXBwZXIucmVtb3ZlQ2xhc3MoJ2hlYWRlci1maXhlZC1hY3RpdmUnKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bGFzdFNjcm9sbFRvcCA9IG5vd1Njcm9sbFRvcDtcblx0XHQgXHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSAmJiB3aW5kb3cuaW5uZXJXaWR0aCA9PSAxMDI0KSB7XG5cdFx0XHRcdHZhciBub3dTY3JvbGxUb3AgPSAkKHRoaXMpLnNjcm9sbFRvcCgpO1xuXHRcdFx0XHRpZihNYXRoLmFicyhub3dTY3JvbGxUb3ApID4gMzAwKSB7XG5cdFx0XHRcdFx0aWYgKCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0XHRcdCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cdFx0XHRcdFx0XHQkKCcuaGVhZGVyLXdyYXBwZXIgLnRvcC1iYW5uZXInKS5yZW1vdmVDbGFzcygnbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdkZXNrdG9wLW5hdi1hY3RpdmUnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKCAkKFwiLnRvcC1iYW5uZXItaW5uZXIgLnByaW1hcnktbG9nbyBhIGltZy5tb2JpbGUtbG9nb1tzcmMqPXNoZXBsZXJzX3VzXVwiKS5sZW5ndGggKSB7XG5cdCAgICAgICAgICAgIGlmICggJChcIi5zZWNvbmQtbW9ibmF2XCIpLmxlbmd0aCA+IDAgJiYgJChcIi5zZWNvbmQtbW9ibmF2XCIpLmlzKFwiOnZpc2libGVcIikgKSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgc3QgPSAkKHRoaXMpLnNjcm9sbFRvcCgpO1xuXHQgICAgICAgICAgICAgICAgXG5cdCAgICAgICAgICAgICAgICBpZiAoc3QgPiAwKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgJChcIi50b3AtYmFubmVyLWJhciAuc2hlbGxcIikuaGlkZSgpO1xuXHQgICAgICAgICAgICAgICAgICAgICQoXCIudG9wLWJhbm5lciBkaXYudG9wLWJhbm5lci1pbm5lclwiKS5jc3MoXCJtYXJnaW4tdG9wXCIsXCIwcHhcIik7XG5cdCAgICAgICAgICAgICAgICAgICAgJChcIi50b3AtYmFubmVyIGRpdi50b3AtYmFubmVyLWJhciAuaGVhZGVyLXNlYXJjaFwiKS5hdHRyKFwic3R5bGVcIixcInRvcDo1NXB4ICFpbXBvcnRhbnRcIik7XG5cdCAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgICAgICQoXCIudG9wLWJhbm5lci1iYXIgLnNoZWxsXCIpLnNob3coKTtcblx0ICAgICAgICAgICAgICAgICAgICAkKFwiLnRvcC1iYW5uZXIgZGl2LnRvcC1iYW5uZXItaW5uZXJcIikuY3NzKFwibWFyZ2luLXRvcFwiLFwiMjVweFwiKTtcblx0ICAgICAgICAgICAgICAgICAgICAkKFwiLnRvcC1iYW5uZXIgZGl2LnRvcC1iYW5uZXItYmFyIC5oZWFkZXItc2VhcmNoXCIpLmF0dHIoXCJzdHlsZVwiLFwidG9wOjgwcHggIWltcG9ydGFudFwiKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgXHRcdCQoXCIudG9wLWJhbm5lci1iYXIgLnNoZWxsXCIpLnNob3coKTtcblx0ICAgICAgICAgICAgXHRcdCQoXCIudG9wLWJhbm5lciBkaXYudG9wLWJhbm5lci1pbm5lclwiKS5jc3MoXCJtYXJnaW4tdG9wXCIsXCIwcHhcIik7XG5cdCAgICAgICAgICAgIFx0XHQkKFwiLnRvcC1iYW5uZXIgZGl2LnRvcC1iYW5uZXItYmFyIC5oZWFkZXItc2VhcmNoXCIpLmF0dHIoXCJzdHlsZVwiLFwidG9wOjgwcHggIWltcG9ydGFudFwiKTtcblx0ICAgICAgICAgICAgXHRcdGlmICggJChcIi50b3AtYmFubmVyLWJhci1hc2lkZSAjc2Vjb25kLW1vYm5hdlwiKS5sZW5ndGggKSB7XG5cdCAgICAgICAgICAgIFx0XHRcdCQoXCIudG9wLWJhbm5lci1iYXItYXNpZGUgI3NlY29uZC1tb2JuYXZcIikuc2hvdygpO1xuXHQgICAgICAgICAgICBcdFx0fVxuXHQgICAgICAgICAgICB9XG5cdFx0XHR9XG4gICAgICAgIH0pO1xuXG5cdFx0cmVzaXplRGV2aWNlSGVscGVyKCk7XG4gICAgfVxufTtcblxuLy8gZ2VuZXJhbCBleHRlbnNpb24gZnVuY3Rpb25zXG4oZnVuY3Rpb24gKCkge1xuICAgIFN0cmluZy5mb3JtYXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzID0gYXJndW1lbnRzWzBdO1xuICAgICAgICB2YXIgaSwgbGVuID0gYXJndW1lbnRzLmxlbmd0aCAtIDE7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdmFyIHJlZyA9IG5ldyBSZWdFeHAoJ1xcXFx7JyArIGkgKyAnXFxcXH0nLCAnZ20nKTtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UocmVnLCBhcmd1bWVudHNbaSArIDFdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcztcbiAgICB9O1xufSkoKTtcblxuLy8gaW5pdGlhbGl6ZSBhcHBcbiQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICBhcHAuaW5pdCgpO1xufSk7XG5cbihmdW5jdGlvbiAoKSB7XG4gU3RyaW5nLmZvcm1hdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgdmFyIHMgPSBhcmd1bWVudHNbMF07XG4gICAgIHZhciBpLCBsZW4gPSBhcmd1bWVudHMubGVuZ3RoIC0gMTtcbiAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICB2YXIgcmVnID0gbmV3IFJlZ0V4cCgnXFxcXHsnICsgaSArICdcXFxcfScsICdnbScpO1xuICAgICAgICAgcyA9IHMucmVwbGFjZShyZWcsIGFyZ3VtZW50c1tpICsgMV0pO1xuICAgICB9XG4gICAgIHJldHVybiBzO1xuIH07XG59KSgpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi9kaWFsb2cnKSxcbiAgICBwYWdlID0gcmVxdWlyZSgnLi9wYWdlJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG52YXIgc2VsZWN0ZWRMaXN0ID0gW107XG52YXIgbWF4SXRlbXMgPSAxO1xudmFyIGJsaVVVSUQgPSAnJztcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBkZXNjcmlwdGlvbiBHZXRzIGEgbGlzdCBvZiBib251cyBwcm9kdWN0cyByZWxhdGVkIHRvIGEgcHJvbW90ZWQgcHJvZHVjdFxuICovXG5mdW5jdGlvbiBnZXRCb251c1Byb2R1Y3RzKCkge1xuICAgIHZhciBib251c3Byb2R1Y3RzID0gW107XG5cbiAgICB2YXIgaSwgbGVuO1xuICAgIGZvciAoaSA9IDAsIGxlbiA9IHNlbGVjdGVkTGlzdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgcCA9IHtcbiAgICAgICAgICAgIHBpZDogc2VsZWN0ZWRMaXN0W2ldLnBpZCxcbiAgICAgICAgICAgIHF0eTogc2VsZWN0ZWRMaXN0W2ldLnF0eSxcbiAgICAgICAgICAgIG9wdGlvbnM6IHt9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBhLCBhbGVuLCBicCA9IHNlbGVjdGVkTGlzdFtpXTtcbiAgICAgICAgaWYgKGJwLm9wdGlvbnMpIHtcbiAgICAgICAgICAgIGZvciAoYSA9IDAsIGFsZW4gPSBicC5vcHRpb25zLmxlbmd0aDsgYSA8IGFsZW47IGErKykge1xuICAgICAgICAgICAgICAgIHZhciBvcHQgPSBicC5vcHRpb25zW2FdO1xuICAgICAgICAgICAgICAgIHAub3B0aW9ucyA9IHtvcHRpb25OYW1lOm9wdC5uYW1lLCBvcHRpb25WYWx1ZTpvcHQudmFsdWV9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJvbnVzcHJvZHVjdHMucHVzaCh7cHJvZHVjdDpwfSk7XG4gICAgfVxuICAgIHJldHVybiB7Ym9udXNwcm9kdWN0czogYm9udXNwcm9kdWN0c307XG59XG5cbnZhciBzZWxlY3RlZEl0ZW1UZW1wbGF0ZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyIGF0dHJpYnV0ZXMgPSAnJztcbiAgICBmb3IgKHZhciBhdHRySUQgaW4gZGF0YS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHZhciBhdHRyID0gZGF0YS5hdHRyaWJ1dGVzW2F0dHJJRF07XG4gICAgICAgIGF0dHJpYnV0ZXMgKz0gJzxsaSBkYXRhLWF0dHJpYnV0ZS1pZD1cIicgKyBhdHRySUQgKyAnXCI+XFxuJztcbiAgICAgICAgYXR0cmlidXRlcyArPSAnPHNwYW4gY2xhc3M9XCJkaXNwbGF5LW5hbWVcIj4nICsgYXR0ci5kaXNwbGF5TmFtZSArICc8L3NwYW4+OiAnO1xuICAgICAgICBhdHRyaWJ1dGVzICs9ICc8c3BhbiBjbGFzcz1cImRpc3BsYXktdmFsdWVcIj4nICsgYXR0ci5kaXNwbGF5VmFsdWUgKyAnPC9zcGFuPlxcbic7XG4gICAgICAgIGF0dHJpYnV0ZXMgKz0gJzwvbGk+JztcbiAgICB9XG4gICAgYXR0cmlidXRlcyArPSAnPGxpIGNsYXNzPVwiaXRlbS1xdHlcIj5cXG4nO1xuICAgIGF0dHJpYnV0ZXMgKz0gJzxzcGFuIGNsYXNzPVwiZGlzcGxheS1uYW1lXCI+UXR5PC9zcGFuPjogJztcbiAgICBhdHRyaWJ1dGVzICs9ICc8c3BhbiBjbGFzcz1cImRpc3BsYXktdmFsdWVcIj4nICsgZGF0YS5xdHkgKyAnPC9zcGFuPic7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJzxsaSBjbGFzcz1cInNlbGVjdGVkLWJvbnVzLWl0ZW1cIiBkYXRhLXV1aWQ9XCInICsgZGF0YS51dWlkICsgJ1wiIGRhdGEtcGlkPVwiJyArIGRhdGEucGlkICsgJ1wiPicsXG4gICAgICAgICc8aSBjbGFzcz1cInJlbW92ZS1saW5rIGZhIGZhLXJlbW92ZVwiIHRpdGxlPVwiUmVtb3ZlIHRoaXMgcHJvZHVjdFwiIGhyZWY9XCIjXCI+PC9pPicsXG4gICAgICAgICc8ZGl2IGNsYXNzPVwiaXRlbS1uYW1lXCI+JyArIGRhdGEubmFtZSArICc8L2Rpdj4nLFxuICAgICAgICAnPHVsIGNsYXNzPVwiaXRlbS1hdHRyaWJ1dGVzXCI+JyxcbiAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgJzx1bD4nLFxuICAgICAgICAnPGxpPidcbiAgICBdLmpvaW4oJ1xcbicpO1xufTtcblxuLy8gaGlkZSBzd2F0Y2hlcyB0aGF0IGFyZSBub3Qgc2VsZWN0ZWQgb3Igbm90IHBhcnQgb2YgYSBQcm9kdWN0IFZhcmlhdGlvbiBHcm91cFxudmFyIGhpZGVTd2F0Y2hlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcuYm9udXMtcHJvZHVjdC1pdGVtOm5vdChbZGF0YS1wcm9kdWN0dHlwZT1cIm1hc3RlclwiXSkgLnN3YXRjaGVzIGxpJykubm90KCcuc2VsZWN0ZWQnKS5ub3QoJy52YXJpYXRpb24tZ3JvdXAtdmFsdWUnKS5oaWRlKCk7XG4gICAgLy8gcHJldmVudCB1bnNlbGVjdGluZyB0aGUgc2VsZWN0ZWQgdmFyaWFudFxuICAgICQoJy5ib251cy1wcm9kdWN0LWl0ZW0gLnN3YXRjaGVzIC5zZWxlY3RlZCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gVXBkYXRlcyB0aGUgc3VtbWFyeSBwYWdlIHdpdGggdGhlIHNlbGVjdGVkIGJvbnVzIHByb2R1Y3RcbiAqL1xuZnVuY3Rpb24gdXBkYXRlU3VtbWFyeSgpIHtcbiAgICB2YXIgJGJvbnVzUHJvZHVjdExpc3QgPSAkKCcjYm9udXMtcHJvZHVjdC1saXN0Jyk7XG4gICAgaWYgKCFzZWxlY3RlZExpc3QubGVuZ3RoKSB7XG4gICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJ2xpLnNlbGVjdGVkLWJvbnVzLWl0ZW0nKS5yZW1vdmUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdWxMaXN0ID0gJGJvbnVzUHJvZHVjdExpc3QuZmluZCgndWwuc2VsZWN0ZWQtYm9udXMtaXRlbXMnKS5maXJzdCgpO1xuICAgICAgICB2YXIgaSwgbGVuO1xuICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBzZWxlY3RlZExpc3QubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gc2VsZWN0ZWRMaXN0W2ldO1xuICAgICAgICAgICAgdmFyIGxpID0gc2VsZWN0ZWRJdGVtVGVtcGxhdGUoaXRlbSk7XG4gICAgICAgICAgICAkKGxpKS5hcHBlbmRUbyh1bExpc3QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZ2V0IHJlbWFpbmluZyBpdGVtIGNvdW50XG4gICAgdmFyIHJlbWFpbiA9IG1heEl0ZW1zIC0gc2VsZWN0ZWRMaXN0Lmxlbmd0aDtcbiAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuYm9udXMtaXRlbXMtYXZhaWxhYmxlJykudGV4dChyZW1haW4pO1xuICAgIGlmIChyZW1haW4gPD0gMCkge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJy5zZWxlY3QtYm9udXMtaXRlbScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgfVxuICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VwZGF0ZS1zdW1tYXJ5Jyk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVHcmlkICgpIHtcbiAgICB2YXIgJGJvbnVzUHJvZHVjdCA9ICQoJyNib251cy1wcm9kdWN0LWRpYWxvZycpLFxuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdCA9ICQoJyNib251cy1wcm9kdWN0LWxpc3QnKSxcbiAgICAgICAgYmxpRGF0YSA9ICRib251c1Byb2R1Y3RMaXN0LmRhdGEoJ2xpbmUtaXRlbS1kZXRhaWwnKTtcbiAgICBtYXhJdGVtcyA9IGJsaURhdGEubWF4SXRlbXM7XG4gICAgYmxpVVVJRCA9IGJsaURhdGEudXVpZDtcblxuICAgIGlmIChibGlEYXRhLml0ZW1Db3VudCA+PSBtYXhJdGVtcykge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH1cblxuICAgIHZhciBjYXJ0SXRlbXMgPSAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0ZWQtYm9udXMtaXRlbScpO1xuICAgIGNhcnRJdGVtcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNpID0gJCh0aGlzKTtcbiAgICAgICAgdmFyIHByb2R1Y3QgPSB7XG4gICAgICAgICAgICB1dWlkOiBjaS5kYXRhKCd1dWlkJyksXG4gICAgICAgICAgICBwaWQ6IGNpLmRhdGEoJ3BpZCcpLFxuICAgICAgICAgICAgcXR5OiBjaS5maW5kKCcuaXRlbS1xdHknKS50ZXh0KCksXG4gICAgICAgICAgICBuYW1lOiBjaS5maW5kKCcuaXRlbS1uYW1lJykuaHRtbCgpLFxuICAgICAgICAgICAgYXR0cmlidXRlczoge31cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBjaS5maW5kKCd1bC5pdGVtLWF0dHJpYnV0ZXMgbGknKTtcbiAgICAgICAgYXR0cmlidXRlcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBsaSA9ICQodGhpcyk7XG4gICAgICAgICAgICBwcm9kdWN0LmF0dHJpYnV0ZXNbbGkuZGF0YSgnYXR0cmlidXRlSWQnKV0gPSB7XG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6bGkuY2hpbGRyZW4oJy5kaXNwbGF5LW5hbWUnKS5odG1sKCksXG4gICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOmxpLmNoaWxkcmVuKCcuZGlzcGxheS12YWx1ZScpLmh0bWwoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNlbGVjdGVkTGlzdC5wdXNoKHByb2R1Y3QpO1xuICAgIH0pO1xuXG4gICAgJGJvbnVzUHJvZHVjdExpc3Qub24oJ2NsaWNrJywgJy5ib251cy1wcm9kdWN0LWl0ZW0gYVtocmVmXS5zd2F0Y2hhbmNob3InLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciB1cmwgPSB0aGlzLmhyZWYsXG4gICAgICAgICAgICAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwodXJsLCB7XG4gICAgICAgICAgICAnc291cmNlJzogJ2JvbnVzJyxcbiAgICAgICAgICAgICdmb3JtYXQnOiAnYWpheCdcbiAgICAgICAgfSk7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICR0aGlzLmNsb3Nlc3QoJy5ib251cy1wcm9kdWN0LWl0ZW0nKS5lbXB0eSgpLmh0bWwocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGhpZGVTd2F0Y2hlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KVxuICAgIC5vbignY2hhbmdlJywgJy5pbnB1dC10ZXh0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAkKHRoaXMpLmNsb3Nlc3QoJy5ib251cy1wcm9kdWN0LWZvcm0nKS5maW5kKCcucXVhbnRpdHktZXJyb3InKS50ZXh0KCcnKTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnLnNlbGVjdC1ib251cy1pdGVtJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoc2VsZWN0ZWRMaXN0Lmxlbmd0aCA+PSBtYXhJdGVtcykge1xuICAgICAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJy5ib251cy1pdGVtcy1hdmFpbGFibGUnKS50ZXh0KCcwJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZm9ybSA9ICQodGhpcykuY2xvc2VzdCgnLmJvbnVzLXByb2R1Y3QtZm9ybScpLFxuICAgICAgICAgICAgZGV0YWlsID0gJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC1kZXRhaWwnKSxcbiAgICAgICAgICAgIHV1aWQgPSBmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwcm9kdWN0VVVJRFwiXScpLnZhbCgpLFxuICAgICAgICAgICAgcXR5VmFsID0gZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiUXVhbnRpdHlcIl0nKS52YWwoKSxcbiAgICAgICAgICAgIHF0eSA9IChpc05hTihxdHlWYWwpKSA/IDEgOiAoK3F0eVZhbCk7XG5cbiAgICAgICAgaWYgKHF0eSA+IG1heEl0ZW1zKSB7XG4gICAgICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZm9ybS5maW5kKCcucXVhbnRpdHktZXJyb3InKS50ZXh0KFJlc291cmNlcy5CT05VU19QUk9EVUNUX1RPT01BTlkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2R1Y3QgPSB7XG4gICAgICAgICAgICB1dWlkOiB1dWlkLFxuICAgICAgICAgICAgcGlkOiBmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwaWRcIl0nKS52YWwoKSxcbiAgICAgICAgICAgIHF0eTogcXR5LFxuICAgICAgICAgICAgbmFtZTogZGV0YWlsLmZpbmQoJy5wcm9kdWN0LW5hbWUnKS50ZXh0KCksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiBkZXRhaWwuZmluZCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLmRhdGEoJ2F0dHJpYnV0ZXMnKSxcbiAgICAgICAgICAgIG9wdGlvbnM6IFtdXG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9wdGlvblNlbGVjdHMgPSBmb3JtLmZpbmQoJy5wcm9kdWN0LW9wdGlvbicpO1xuXG4gICAgICAgIG9wdGlvblNlbGVjdHMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwcm9kdWN0Lm9wdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAkKHRoaXMpLnZhbCgpLFxuICAgICAgICAgICAgICAgIGRpc3BsYXk6ICQodGhpcykuY2hpbGRyZW4oJzpzZWxlY3RlZCcpLmZpcnN0KCkuaHRtbCgpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNlbGVjdGVkTGlzdC5wdXNoKHByb2R1Y3QpO1xuICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG4gICAgfSlcbiAgICAub24oJ2NsaWNrJywgJy5yZW1vdmUtbGluaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9ICQodGhpcykuY2xvc2VzdCgnLnNlbGVjdGVkLWJvbnVzLWl0ZW0nKTtcbiAgICAgICAgaWYgKCFjb250YWluZXIuZGF0YSgndXVpZCcpKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHZhciB1dWlkID0gY29udGFpbmVyLmRhdGEoJ3V1aWQnKTtcbiAgICAgICAgdmFyIGksIGxlbiA9IHNlbGVjdGVkTGlzdC5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlbGVjdGVkTGlzdFtpXS51dWlkID09PSB1dWlkKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRMaXN0LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG4gICAgfSlcbiAgICAub24oJ2NsaWNrJywgJy5hZGQtdG8tY2FydC1ib251cycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5hZGRCb251c1Byb2R1Y3QsIHtib251c0Rpc2NvdW50TGluZUl0ZW1VVUlEOiBibGlVVUlEfSk7XG4gICAgICAgIHZhciBib251c1Byb2R1Y3RzID0gZ2V0Qm9udXNQcm9kdWN0cygpO1xuICAgICAgICBpZiAoYm9udXNQcm9kdWN0cy5ib251c3Byb2R1Y3RzWzBdLnByb2R1Y3QucXR5ID4gbWF4SXRlbXMpIHtcbiAgICAgICAgICAgIGJvbnVzUHJvZHVjdHMuYm9udXNwcm9kdWN0c1swXS5wcm9kdWN0LnF0eSA9IG1heEl0ZW1zO1xuICAgICAgICB9XG4gICAgICAgIC8vIG1ha2UgdGhlIHNlcnZlciBjYWxsXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgY2FjaGU6IGZhbHNlLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoYm9udXNQcm9kdWN0cylcbiAgICAgICAgfSlcbiAgICAgICAgLmRvbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gc3VjY2Vzc1xuICAgICAgICAgICAgcGFnZS5yZWZyZXNoKCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5mYWlsKGZ1bmN0aW9uICh4aHIsIHRleHRTdGF0dXMpIHtcbiAgICAgICAgICAgIC8vIGZhaWxlZFxuICAgICAgICAgICAgaWYgKHRleHRTdGF0dXMgPT09ICdwYXJzZXJlcnJvcicpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkJBRF9SRVNQT05TRSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuU0VSVkVSX0NPTk5FQ1RJT05fRVJST1IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuYWx3YXlzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRib251c1Byb2R1Y3QuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICB9KTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnI21vcmUtYm9udXMtcHJvZHVjdHMnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciB1dWlkID0gJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmRhdGEoKS5saW5lSXRlbURldGFpbC51dWlkO1xuXG4gICAgICAgIC8vZ2V0IHRoZSBuZXh0IHBhZ2Ugb2YgY2hvaWNlIG9mIGJvbnVzIHByb2R1Y3RzXG4gICAgICAgIHZhciBsaW5lSXRlbURldGFpbCA9IEpTT04ucGFyc2UoJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmF0dHIoJ2RhdGEtbGluZS1pdGVtLWRldGFpbCcpKTtcbiAgICAgICAgbGluZUl0ZW1EZXRhaWwucGFnZVN0YXJ0ID0gbGluZUl0ZW1EZXRhaWwucGFnZVN0YXJ0ICsgbGluZUl0ZW1EZXRhaWwucGFnZVNpemU7XG4gICAgICAgICQoJyNib251cy1wcm9kdWN0LWxpc3QnKS5hdHRyKCdkYXRhLWxpbmUtaXRlbS1kZXRhaWwnLCBKU09OLnN0cmluZ2lmeShsaW5lSXRlbURldGFpbCkpO1xuXG4gICAgICAgIHZhciB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKFVybHMuZ2V0Qm9udXNQcm9kdWN0cywge1xuICAgICAgICAgICAgYm9udXNEaXNjb3VudExpbmVJdGVtVVVJRDogdXVpZCxcbiAgICAgICAgICAgIGZvcm1hdDogJ2FqYXgnLFxuICAgICAgICAgICAgbGF6eUxvYWQ6ICd0cnVlJyxcbiAgICAgICAgICAgIHBhZ2VTdGFydDogbGluZUl0ZW1EZXRhaWwucGFnZVN0YXJ0LFxuICAgICAgICAgICAgcGFnZVNpemU6ICQoJyNib251cy1wcm9kdWN0LWxpc3QnKS5kYXRhKCkubGluZUl0ZW1EZXRhaWwucGFnZVNpemUsXG4gICAgICAgICAgICBib251c1Byb2R1Y3RzVG90YWw6ICQoJyNib251cy1wcm9kdWN0LWxpc3QnKS5kYXRhKCkubGluZUl0ZW1EZXRhaWwuYnBUb3RhbFxuICAgICAgICB9KTtcblxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgdXJsOiB1cmxcbiAgICAgICAgfSlcbiAgICAgICAgLmRvbmUoZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIC8vYWRkIHRoZSBuZXcgcGFnZSB0byBET00gYW5kIHJlbW92ZSAnTW9yZScgbGluayBpZiBpdCBpcyB0aGUgbGFzdCBwYWdlIG9mIHJlc3VsdHNcbiAgICAgICAgICAgICQoJyNtb3JlLWJvbnVzLXByb2R1Y3RzJykuYmVmb3JlKGRhdGEpO1xuICAgICAgICAgICAgaWYgKChsaW5lSXRlbURldGFpbC5wYWdlU3RhcnQgKyBsaW5lSXRlbURldGFpbC5wYWdlU2l6ZSkgPj0gJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmRhdGEoKS5saW5lSXRlbURldGFpbC5icFRvdGFsKSB7XG4gICAgICAgICAgICAgICAgJCgnI21vcmUtYm9udXMtcHJvZHVjdHMnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmZhaWwoZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cykge1xuICAgICAgICAgICAgaWYgKHRleHRTdGF0dXMgPT09ICdwYXJzZXJlcnJvcicpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkJBRF9SRVNQT05TRSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuU0VSVkVSX0NPTk5FQ1RJT05fRVJST1IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxudmFyIGJvbnVzUHJvZHVjdHNWaWV3ID0ge1xuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBPcGVuIHRoZSBsaXN0IG9mIGJvbnVzIHByb2R1Y3RzIHNlbGVjdGlvbiBkaWFsb2dcbiAgICAgKi9cbiAgICBzaG93OiBmdW5jdGlvbiAodXJsKSB7XG4gICAgICAgIHZhciAkYm9udXNQcm9kdWN0ID0gJCgnI2JvbnVzLXByb2R1Y3QtZGlhbG9nJyk7XG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgZGlhbG9nXG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIHRhcmdldDogJGJvbnVzUHJvZHVjdCxcbiAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHdpZHRoOiA3OTUsXG4gICAgICAgICAgICAgICAgdGl0bGU6IFJlc291cmNlcy5CT05VU19QUk9EVUNUU1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaW5pdGlhbGl6ZUdyaWQoKTtcbiAgICAgICAgICAgICAgICBoaWRlU3dhdGNoZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gT3BlbiBib251cyBwcm9kdWN0IHByb21vIHByb21wdCBkaWFsb2dcbiAgICAgKi9cbiAgICBsb2FkQm9udXNPcHRpb246IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICAgIHNlbGYgPSB0aGlzLFxuICAgICAgICAgICAgYm9udXNEaXNjb3VudENvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5ib251cy1kaXNjb3VudC1jb250YWluZXInKTtcbiAgICAgICAgaWYgKCFib251c0Rpc2NvdW50Q29udGFpbmVyKSB7IHJldHVybjsgfVxuXG4gICAgICAgIC8vIGdldCB0aGUgaHRtbCBmcm9tIG1pbmljYXJ0LCB0aGVuIHRyYXNoIGl0XG4gICAgICAgIHZhciBib251c0Rpc2NvdW50Q29udGFpbmVySHRtbCA9IGJvbnVzRGlzY291bnRDb250YWluZXIub3V0ZXJIVE1MO1xuICAgICAgICBib251c0Rpc2NvdW50Q29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoYm9udXNEaXNjb3VudENvbnRhaW5lcik7XG5cbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgaHRtbDogYm9udXNEaXNjb3VudENvbnRhaW5lckh0bWwsXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IDQwMCxcbiAgICAgICAgICAgICAgICB0aXRsZTogUmVzb3VyY2VzLkJPTlVTX1BST0RVQ1QsXG4gICAgICAgICAgICAgICAgYnV0dG9uczogW3tcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogUmVzb3VyY2VzLlNFTEVDVF9CT05VU19QUk9EVUNUUyxcbiAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB1dWlkID0gJCgnLmJvbnVzLXByb2R1Y3QtcHJvbW8nKS5kYXRhKCdsaW5laXRlbWlkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmdldEJvbnVzUHJvZHVjdHMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9udXNEaXNjb3VudExpbmVJdGVtVVVJRDogdXVpZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnYm9udXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6ICdhamF4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF6eUxvYWQ6ICdmYWxzZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VTdGFydDogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVNpemU6IDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib251c1Byb2R1Y3RzVG90YWw6IC0xXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmRpYWxvZygnY2xvc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc2hvdyh1cmwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuTk9fVEhBTktTLFxuICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5kaWFsb2coJ2Nsb3NlJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gc2hvdyBoaWRlIHByb21vIGRldGFpbHNcbiAgICAgICAgICAgICAgICAkKCcuc2hvdy1wcm9tby1kZXRhaWxzJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcucHJvbW8tZGV0YWlscycpLnRvZ2dsZUNsYXNzKCd2aXNpYmxlJyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gYm9udXNQcm9kdWN0c1ZpZXc7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoID0gcmVxdWlyZSgnLi9BZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2gnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgTG9jYWxEZWxpdmVyeURpYWxvZyA9IHJlcXVpcmUoJy4vTG9jYWxEZWxpdmVyeURpYWxvZycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyIG9wdGlvbnM7XG52YXIgb3B0aW9uc1N0b3JlU2VhcmNoO1xudmFyIG9wdGlvbnNMb2NhbERlbGl2ZXJ5O1xudmFyIGRhdGFCdWZmZXI7XG52YXIgc3RvcmVTZWFyY2g7XG52YXIgbG9jYWxEZWxpdmVyeVN0b3JlU2VhcmNoO1xuXG52YXIgcmVzdWx0Q29udGFpbmVyVGVtcGxhdGU7XG52YXIgcmVzdWx0SXRlbVRlbXBsYXRlO1xudmFyIGxvY2FsRGVsaXZlcnlEZWNvcmF0b3I7XG5cbnZhciAkY29udGFpbmVyO1xudmFyICRzdG9yZVNlYXJjaEJ1dHRvbjtcbnZhciAkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXI7XG52YXIgJGFkZFRvQ2FydE9wdGlvbnM7XG52YXIgJGJvcGlzQnV0dG9uO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCRjb250YWluZXJQYXJhbWV0ZXIsIG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0ZGF0YUJ1ZmZlciA9IHt9O1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXG5cdHZhciBzZWxlY3RlZFNpemU7XG5cdHZhciAkc2VsZWN0ZWRTaXplSW5Ecm9wZG93biA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdHZhciAkc2VsZWN0ZWRMZW5ndGggPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKTtcblx0dmFyICRzZWxlY3RlZFdpZHRoID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHRpZiAoJHNlbGVjdGVkTGVuZ3RoLmxlbmd0aCAmJiAkc2VsZWN0ZWRXaWR0aC5sZW5ndGgpIHtcblx0XHRzZWxlY3RlZFNpemUgPSAkc2VsZWN0ZWRMZW5ndGguZmluZCgnW2RhdGEtbGVuZ3RoLW5hbWVdJykuYXR0cignZGF0YS1sZW5ndGgtbmFtZScpICsgJyAnICsgJHNlbGVjdGVkV2lkdGguZmluZCgnW2RhdGEtd2lkdGgtbmFtZV0nKS5hdHRyKCdkYXRhLXdpZHRoLW5hbWUnKTtcblx0fSBlbHNlIGlmICgkc2VsZWN0ZWRTaXplSW5Ecm9wZG93bi5sZW5ndGggPiAwKSB7XG5cdFx0c2VsZWN0ZWRTaXplID0gJHNlbGVjdGVkU2l6ZUluRHJvcGRvd24uZmluZCgnW2RhdGEtc2l6ZS1uYW1lXScpLmF0dHIoJ2RhdGEtc2l6ZS1uYW1lJyk7XG5cdH0gZWxzZSB7XG5cdFx0c2VsZWN0ZWRTaXplID0gdXRpbC5nZXRQcmVmZXJlbmNlVmFsdWVGcm9tV2luZG93TG9jYXRpb24oJ3NpemUnKTtcblx0fVxuXHRzdG9yZVNlYXJjaCA9IG5ldyBhZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2goKTtcblx0bG9jYWxEZWxpdmVyeVN0b3JlU2VhcmNoID0gbmV3IGFkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaCgpO1xuXHRvcHRpb25zU3RvcmVTZWFyY2ggPSBPYmplY3QuYXNzaWduKG9wdGlvbnMpO1xuXHRvcHRpb25zTG9jYWxEZWxpdmVyeSA9IE9iamVjdC5hc3NpZ24oe1xuXHRcdExvY2FsRGVsaXZlcnlPbmx5OiB0cnVlLFxuXHRcdEV2ZW50czoge1xuXHRcdFx0U2VsZWN0U3RvcmU6ICdCb3Bpcy5Mb2NhbERlbGl2ZXJ5LlN0b3JlU2VsZWN0J1xuXHRcdH0sXG5cdFx0RnVuY3Rpb25zOiB7XG5cdFx0XHRDbG9zZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCQoJy5kaWFsb2ctYm9waXMtb3B0aW9ucycpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnLnVpLXdpZGdldC1vdmVybGF5JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcuYm9waXMtbG9jYWwtZGVsaXZlcnktc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpLnJlbW92ZUNsYXNzKCdzaG93Jyk7XG5cdFx0XHR9XG5cdFx0fSxcblx0fSwgb3B0aW9ucyk7XG5cblx0cmVzdWx0Q29udGFpbmVyVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRyZXN1bHRJdGVtVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtaXRlbScpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0bG9jYWxEZWxpdmVyeURlY29yYXRvciA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLWxvY2FsZGVsaXZlcnktZGVjb3JhdG9yJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXG5cdCRjb250YWluZXIgPSAkY29udGFpbmVyUGFyYW1ldGVyO1xuXHQkc3RvcmVTZWFyY2hCdXR0b24gPSAkY29udGFpbmVyLmZpbmQoJy5idG4uc3RvcmUtc2VhcmNoJyk7XG5cdCRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lciA9ICRjb250YWluZXIuZmluZCgnLmJ0bi1zdG9yZS1zZWFyY2gtY29udGFpbmVyJyk7XG5cdCRib3Bpc0J1dHRvbiA9ICRjb250YWluZXIuZmluZCgnLmJ0bi5ib3BpcycpO1xuXG5cdCRhZGRUb0NhcnRPcHRpb25zID0gJGNvbnRhaW5lci5maW5kKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucycpO1xuXHQkYWRkVG9DYXJ0T3B0aW9ucy5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdGluaXRpYWxpemVUb29sdGlwcyhzZWxlY3RlZFNpemUpO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2VhcmNoQnlTdG9yZS5EaXNwbGF5Jykub24oJ2NsaWNrLlNlYXJjaEJ5U3RvcmUuRGlzcGxheScsICcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXIgLnNlYXJjaC1zdG9yZTpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblxuXHRcdHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdHZhciBjb2xvclNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuY29sb3IuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHR2YXIgaXNTaXplU2VsZWN0ZWQgPSAoc2l6ZVNlbGVjdGVkIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKSkgJiYgY29sb3JTZWxlY3RlZDtcblxuXHRcdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uICE9ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRpZiAoIWlzU2l6ZVNlbGVjdGVkICYmICFjb2xvclNlbGVjdGVkKSB7XG5cdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHRodG1sOiAnUGxlYXNlIHNlbGVjdCBhIHNpemUgYW5kIGNvbG9yLicsXG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0ZGlhbG9nQ2xhc3M6ICdkaWFsb2ctYWxlcnQnLFxuXHRcdFx0XHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH0gZWxzZSBpZiAoIWlzU2l6ZVNlbGVjdGVkKSB7XG5cdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHRodG1sOiAnUGxlYXNlIHNlbGVjdCBhIHNpemUnLFxuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGRpYWxvZ0NsYXNzOiAnZGlhbG9nLWFsZXJ0Jyxcblx0XHRcdFx0XHRcdGRyYWdnYWJsZTogZmFsc2Vcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCFjb2xvclNlbGVjdGVkKSB7XG5cdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHRodG1sOiAnUGxlYXNlIHNlbGVjdCBhIGNvbG9yJyxcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHRkaWFsb2dDbGFzczogJ2RpYWxvZy1hbGVydCcsXG5cdFx0XHRcdFx0XHRkcmFnZ2FibGU6IGZhbHNlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICgkY29udGFpbmVyLmZpbmQoJ2lucHV0W25hbWU9XCJBZGRUb0NhcnRPcHRpb25cIl06Y2hlY2tlZCcpLnZhbCgpID09ICdkZWxpdmVyeScpIHtcblx0XHRcdGxvY2FsRGVsaXZlcnlTdG9yZVNlYXJjaC5pbml0aWFsaXplKCQoJy5ib3Bpcy1sb2NhbC1kZWxpdmVyeS1zdG9yZS1zZWFyY2gtY29udGFpbmVyJyksIG9wdGlvbnNMb2NhbERlbGl2ZXJ5KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c3RvcmVTZWFyY2guaW5pdGlhbGl6ZSgkKCcuYm9waXMtYWRkLXRvLWNhcnQtc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpLCBvcHRpb25zU3RvcmVTZWFyY2gpO1xuXHRcdH1cbiAgICB9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNlYXJjaEJ5WmlwQ29kZS5EaXNwbGF5Jykub24oJ2NsaWNrLlNlYXJjaEJ5WmlwQ29kZS5EaXNwbGF5JywgJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zIC5zZWFyY2gtemlwY29kZTpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cblx0XHRsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2guaW5pdGlhbGl6ZSgkKCcuYm9waXMtbG9jYWwtZGVsaXZlcnktc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpLCBvcHRpb25zTG9jYWxEZWxpdmVyeSk7XG4gICAgfSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdCb3Bpcy5Mb2NhbERlbGl2ZXJ5LlN0b3JlU2VsZWN0Jykub24oJ0JvcGlzLkxvY2FsRGVsaXZlcnkuU3RvcmVTZWxlY3QnLCBmdW5jdGlvbiAoZXZlbnQsIHN0b3JlKSB7XG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0XHR1cmw6IFVybHMuQm9waXMuR2V0TG9jYWxEZWxpdmVyeUZvcm1EYXRhLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGxvY2FsRGVsaXZlcnlGb3JtRGF0YSkge1xuXHRcdFx0XHRMb2NhbERlbGl2ZXJ5RGlhbG9nLmluaXRpYWxpemUob3B0aW9uc0xvY2FsRGVsaXZlcnksIHN0b3JlLCBsb2NhbERlbGl2ZXJ5Rm9ybURhdGEpO1xuXHRcdFx0fSxcblx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0TG9jYWxEZWxpdmVyeURpYWxvZy5pbml0aWFsaXplKG9wdGlvbnNMb2NhbERlbGl2ZXJ5LCBzdG9yZSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignQm9waXMuTG9jYWxEZWxpdmVyeS5EaXNwbGF5Jykub24oJ0JvcGlzLkxvY2FsRGVsaXZlcnkuRGlzcGxheScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuXHRcdHZhciAkc3RvcmVEYXRhID0gJGNvbnRhaW5lci5maW5kKCcuc2VsZWN0ZWQtc3RvcmVbc3RvcmUtZGF0YV0nKTtcblx0XHRpZiAoJHN0b3JlRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHRpZiAoZGF0YSkge1xuXHRcdFx0XHRvcHRpb25zTG9jYWxEZWxpdmVyeSA9ICQuZXh0ZW5kKG9wdGlvbnNMb2NhbERlbGl2ZXJ5LCBkYXRhKTtcblx0XHRcdH1cblxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdFx0dXJsOiBVcmxzLkJvcGlzLkdldExvY2FsRGVsaXZlcnlGb3JtRGF0YSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24obG9jYWxEZWxpdmVyeUZvcm1EYXRhKSB7XG5cdFx0XHRcdFx0TG9jYWxEZWxpdmVyeURpYWxvZy5pbml0aWFsaXplKG9wdGlvbnNMb2NhbERlbGl2ZXJ5LCBKU09OLnBhcnNlKCRzdG9yZURhdGEuYXR0cignc3RvcmUtZGF0YScpKSwgbG9jYWxEZWxpdmVyeUZvcm1EYXRhKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdExvY2FsRGVsaXZlcnlEaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zTG9jYWxEZWxpdmVyeSwgSlNPTi5wYXJzZSgkc3RvcmVEYXRhLmF0dHIoJ3N0b3JlLWRhdGEnKSkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub2ZmKCdCb3Bpcy5TdG9yZVNlYXJjaC5TZWxlY3QnKS5vbignQm9waXMuU3RvcmVTZWFyY2guU2VsZWN0JywgZnVuY3Rpb24gKGV2ZW50LCBzdG9yZUlkKSB7XG5cdFx0ZGF0YUJ1ZmZlclsnU2VsZWN0ZWRMb2NhdGlvbiddID0gc3RvcmVJZDtcblx0XHRyZWRyYXcodHJ1ZSk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU3RvcmUuU2VsZWN0Jykub24oJ2NsaWNrLlN0b3JlLlNlbGVjdCcsICcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXIgLnNlbGVjdC1zdG9yZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZGF0YUJ1ZmZlclsnU2VsZWN0ZWRMb2NhdGlvbiddID0gJCh0aGlzKS5jbG9zZXN0KCdbc3RvcmUtaWRdJykuYXR0cignc3RvcmUtaWQnKTtcblx0XHRyZWRyYXcodHJ1ZSk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5BZGRUb0NhcnRPcHRpb25zJykub24oJ1Byb2R1Y3REZXRhaWxQYWdlLlZhcmlhbnQuQWRkVG9DYXJ0T3B0aW9ucycsIGZ1bmN0aW9uKCkge1xuXHRcdHJlZHJhdygpO1xuXHR9KTtcblxuXHRkYXRhQnVmZmVyWydTZWxlY3RlZExvY2F0aW9uJ10gPSBvcHRpb25zLlNlbGVjdGVkTG9jYXRpb25zO1xufVxuXG5mdW5jdGlvbiByZWRyYXcoc2F2ZVNlbGVjdGVkTG9jYXRpb24pIHtcblx0dmFyIHNlbGVjdGVkQ29sb3I7XG5cdHZhciAkc2VsZWN0ZWRDb2xvckluU3dhdGNoID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuY29sb3IuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RlZCcpOztcblx0aWYgKCRzZWxlY3RlZENvbG9ySW5Td2F0Y2gubGVuZ3RoID4gMCkge1xuXHRcdHNlbGVjdGVkQ29sb3IgPSAkc2VsZWN0ZWRDb2xvckluU3dhdGNoLmZpbmQoJ1tkYXRhLWNvbG9yLW5hbWVdJykuYXR0cignZGF0YS1jb2xvci1pZCcpO1xuXHR9IGVsc2Uge1xuXHRcdHNlbGVjdGVkQ29sb3IgPSB1dGlsLmdldFByZWZlcmVuY2VWYWx1ZUZyb21XaW5kb3dMb2NhdGlvbignY29sb3InKTtcblx0fVxuXG5cdHZhciBzZWxlY3RlZFNpemU7XG5cdHZhciAkc2VsZWN0ZWRTaXplSW5Ecm9wZG93biA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdHZhciAkc2VsZWN0ZWRMZW5ndGggPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKTtcblx0dmFyICRzZWxlY3RlZFdpZHRoID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHRpZiAoJHNlbGVjdGVkTGVuZ3RoLmxlbmd0aCAmJiAkc2VsZWN0ZWRXaWR0aC5sZW5ndGgpIHtcblx0XHRzZWxlY3RlZFNpemUgPSAkc2VsZWN0ZWRMZW5ndGguZmluZCgnW2RhdGEtbGVuZ3RoLW5hbWVdJykuYXR0cignZGF0YS1sZW5ndGgtbmFtZScpICsgJyAnICsgJHNlbGVjdGVkV2lkdGguZmluZCgnW2RhdGEtd2lkdGgtbmFtZV0nKS5hdHRyKCdkYXRhLXdpZHRoLW5hbWUnKTtcblx0fSBlbHNlIGlmICgkc2VsZWN0ZWRTaXplSW5Ecm9wZG93bi5sZW5ndGggPiAwKSB7XG5cdFx0c2VsZWN0ZWRTaXplID0gJHNlbGVjdGVkU2l6ZUluRHJvcGRvd24uZmluZCgnW2RhdGEtc2l6ZS1uYW1lXScpLmF0dHIoJ2RhdGEtc2l6ZS1uYW1lJyk7XG5cdH0gZWxzZSB7XG5cdFx0c2VsZWN0ZWRTaXplID0gdXRpbC5nZXRQcmVmZXJlbmNlVmFsdWVGcm9tV2luZG93TG9jYXRpb24oJ3NpemUnKTtcblx0fVxuXHRcblx0dmFyIHBheWxvYWQgPSB7XG5cdFx0Q2hhbm5lbDogb3B0aW9ucy5DaGFubmVsLFxuXHRcdFByb2R1Y3RJZDogb3B0aW9ucy5Qcm9kdWN0SWQsXG5cdFx0U2VsZWN0ZWRMb2NhdGlvbjogZGF0YUJ1ZmZlclsnU2VsZWN0ZWRMb2NhdGlvbiddLFxuXHRcdFNhdmVTZWxlY3RlZExvY2F0aW9uOiAhIXNhdmVTZWxlY3RlZExvY2F0aW9uLFxuXHRcdFNlbGVjdGVkT3B0aW9uOiAkY29udGFpbmVyLmZpbmQoJ2lucHV0W25hbWU9XCJBZGRUb0NhcnRPcHRpb25cIl06Y2hlY2tlZCcpLnZhbCgpXG5cdH1cblx0cGF5bG9hZFsnZHd2YXJfJyArIG9wdGlvbnMuUHJvZHVjdElkICsgJ19jb2xvciddID0gc2VsZWN0ZWRDb2xvcjtcblx0cGF5bG9hZFsnZHd2YXJfJyArIG9wdGlvbnMuUHJvZHVjdElkICsgJ19zaXplJ10gPSBzZWxlY3RlZFNpemU7XG5cblx0JC5hamF4KHtcblx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdHVybDogVXJscy5Cb3Bpcy5BZGRUb0NhcnRPcHRpb25zLFxuXHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdCRjb250YWluZXIuaHRtbCgkKGRhdGEpLmNoaWxkcmVuKCkpO1xuXHRcdFx0JGFkZFRvQ2FydE9wdGlvbnMgPSAkY29udGFpbmVyLmZpbmQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zJyk7XG5cdFx0XHRpbml0aWFsaXplVG9vbHRpcHMoc2VsZWN0ZWRTaXplKTtcblx0XHR9LFxuXHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVUb29sdGlwcyhzZWxlY3RlZFNpemUpIHtcblx0aWYgKCFzZWxlY3RlZFNpemUpIHtcblx0XHQkYWRkVG9DYXJ0T3B0aW9ucy5maW5kKCdsYWJlbC5kaXNhYmxlZCA+IHNwYW4nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG5cdFx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0XHRpdGVtczogJHRoaXMsXG5cdFx0XHRcdHRvb2x0aXBDbGFzczogJ3Rvb2x0aXAtc2VsZWN0LXNpemUnLFxuXHRcdFx0XHRjb250ZW50OiAnU2VsZWN0IGEgc2l6ZSB0bzxiciAvPnNlZSBhdmFpbGFiaWxpdHknXG5cdFx0XHR9LCAkdGhpcyk7XG5cdFx0fSk7XG5cdH1cblxuXHR2YXIgbG9jYWxEZWxpdmVyeVJhZGl1cztcblx0dmFyICRzdG9yZURhdGEgPSAkY29udGFpbmVyLmZpbmQoJy5zZWxlY3RlZC1zdG9yZVtzdG9yZS1kYXRhXScpO1xuXHRpZiAoJHN0b3JlRGF0YSAmJiAkc3RvcmVEYXRhLmxlbmd0aCA+IDApIHtcblx0XHR2YXIgc3RvcmVEYXRhID0gSlNPTi5wYXJzZSgkc3RvcmVEYXRhLmZpcnN0KCkuYXR0cignc3RvcmUtZGF0YScpKTtcblx0XHRpZiAoc3RvcmVEYXRhICYmIHN0b3JlRGF0YS5sb2NhdGlvbiAmJiBzdG9yZURhdGEubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yICYmIHN0b3JlRGF0YS5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV9yYWRpdXMpIHtcblx0XHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSBzdG9yZURhdGEubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfcmFkaXVzO1xuXHRcdH1cblx0fVxuXG5cdCQoJy5hZGQtdG8tY2FydC1vcHRpb25zLXRvb2x0aXAnKS5maW5kKCcuZGVsaXZlcnktcmFkaXVzJykuaHRtbChsb2NhbERlbGl2ZXJ5UmFkaXVzKTtcblx0dG9vbHRpcC5pbml0KHtcblx0XHRpdGVtczogJy5hZGQtdG8tY2FydC1vcHRpb25zLXRvb2x0aXAnLFxuXHRcdHRvb2x0aXBDbGFzczogJ2FkZC10by1jYXJ0LW9wdGlvbnMtdG9vbHRpcCdcblx0fSwgJCgnLmFkZC10by1jYXJ0LW9wdGlvbnMtdG9vbHRpcCcpKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIEdlb2xvY2F0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9HZW9sb2NhdGlvbi9HZW9sb2NhdGlvbkhlbHBlcicpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG52YXIgWmlwQ29kZVRvU3RhdGVNYXAgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2RhdGEvWmlwQ29kZVRvU3RhdGVNYXAuanNvbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaDtcblxuZnVuY3Rpb24gQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoKCkge1xuXHR0aGlzLm9wdGlvbnM7XG5cdHRoaXMudmFsaWRhdG9yO1xuXHR0aGlzLmxvYWRlZDtcblx0dGhpcy5kYXRhQnVmZmVyO1xuXG5cdHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGU7XG5cdHRoaXMucmVzdWx0SXRlbVRlbXBsYXRlO1xuXHR0aGlzLmxvY2FsRGVsaXZlcnlEZWNvcmF0b3I7XG5cblx0dGhpcy4kY29udGFpbmVyO1xuXHR0aGlzLiRmb3JtO1xuXHR0aGlzLiRyZXN1bHQ7XG5cdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGU7XG5cdHRoaXMuJGZvcm1JbnB1dFJhZGl1cztcblx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b247XG5cdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyO1xuXHR0aGlzLiRib3Bpc0J1dHRvbjtcblx0dGhpcy4kZXJyb3JNZXNzYWdlO1xuXHR0aGlzLiRpbnB1dFRvb2x0aXA7XG5cblx0dGhpcy5pbml0aWFsaXplID0gZnVuY3Rpb24oJGNvbnRhaW5lclBhcmFtZXRlciwgb3B0aW9uc1BhcmFtZXRlcikge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRpZiAoIXRoaXMuZGF0YUJ1ZmZlcikge1xuXHRcdFx0dGhpcy5kYXRhQnVmZmVyID0ge307XG5cdFx0fVxuXHRcdGlmICghdGhpcy5sb2FkZWQpIHtcblx0XHRcdHRoaXMubG9hZGVkID0ge307XG5cdFx0fVxuXHRcdHRoaXMub3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRcdGVycm9yQ2FsbGJhY2s6IG51bGxcblx0XHR9LCBvcHRpb25zUGFyYW1ldGVyKTtcblxuXHRcdHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtY29udGFpbmVyLWFkZHRvY2FydG9wdGlvbnMnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdFx0dGhpcy5yZXN1bHRJdGVtVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtaXRlbS1hZGR0b2NhcnRvcHRpb25zJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRcdHRoaXMubG9jYWxEZWxpdmVyeURlY29yYXRvciA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLWxvY2FsZGVsaXZlcnktZGVjb3JhdG9yJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyID0gJGNvbnRhaW5lclBhcmFtZXRlcjtcblx0XHR0aGlzLiRmb3JtID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJ2Zvcm0nKTtcblx0XHR0aGlzLiRyZXN1bHQgPSB0aGlzLiRjb250YWluZXIuZmluZCgnLnJlc3VsdCcpO1xuXHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUgPSB0aGlzLiRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbENvZGVcIl0nKTtcblx0XHR0aGlzLiRmb3JtSW5wdXRSYWRpdXMgPSB0aGlzLiRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9yYWRpdXNcIl0nKTtcblx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbiA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlYXJjaCcpO1xuXHRcdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5idG4tc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpO1xuXHRcdHRoaXMuJGJvcGlzQnV0dG9uID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5idG4uYm9waXMnKTtcblx0XHR0aGlzLiRlcnJvck1lc3NhZ2UgPSB0aGlzLiRmb3JtLmZpbmQoJ3NwYW4uZXJyb3InKTtcblx0XHR0aGlzLiRpbnB1dFRvb2x0aXAgPSB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnBhcmVudCgpO1xuXHRcdHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlbGVjdCcpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdCQoJ2h0bWwnKS5hZGRDbGFzcygnc2Nyb2xsLWxvY2snKTtcblxuXHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkgJiYgdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzKSB7XG5cdFx0XHR0aGlzLiRjb250YWluZXIuZmluZCgnLmRlbGl2ZXJ5LXJhZGl1cycpLmh0bWwodGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzKTtcblx0XHR9XG5cdFx0dGhpcy4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJywgJ2Zvcm0nKTtcblx0XHR0aGlzLnZhbGlkYXRvciA9IHRoaXMuJGZvcm0udmFsaWRhdGUoVmFsaWRhdGlvblNldHRpbmdzLkdsb2JhbCk7XG5cdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCd6aXBDb2RlJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVppcENvZGUsIFJlc291cmNlcy5JTlZBTElEX1BPU1RBTF9DT0RFKTtcblx0XHR0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuWmlwQ29kZSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIuYWRkQ2xhc3MoJ3Nob3cnKTtcblx0XHRpZiAodGhpcy4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJyAmJiB0aGlzLnZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAhdGhpcy4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHRcdH1cblxuXHRcdHRoaXMuJGZvcm0ub2ZmKCdjbGljay5hcHBseScpLm9uKCdjbGljay5hcHBseScsICcuYnRuLnN0b3JlLXNlYXJjaDpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmxvYWRpbmcoKTtcblx0XHRcdHNlbGYuc2VhcmNoKCk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5hcHBseScpLm9uKCdjbGljay5hcHBseScsICcuYnRuLmJvcGlzOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR2YXIgc2VsZWN0ZWRMb2NhdGlvbiA9IHNlbGYuZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ11bJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpLnZhbCgpXTtcblx0XHRcdGlmIChzZWxlY3RlZExvY2F0aW9uKSB7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIHsgYm9waXM6IHRydWUsIHNoaXBwaW5nT3B0aW9uOiAncGlja3VwJywgY2hhbm5lbDogc2VsZi5vcHRpb25zLkNoYW5uZWwgfSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCB7IGNoYW5uZWw6IHNlbGYub3B0aW9ucy5DaGFubmVsIH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2tleWRvd24uQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbigna2V5ZG93bi5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0aWYgKHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkubGVuZ3RoID09IDUgJiYgcGFyc2VJbnQoZXZlbnQua2V5LCAxMCkgPT0gZXZlbnQua2V5ICYmICF3aW5kb3cuZ2V0U2VsZWN0aW9uKCkudG9TdHJpbmcoKSkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2NoYW5nZS5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGlmIChzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLmxlbmd0aCA+IDUpIHtcblx0XHRcdFx0c2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5zdWJzdHIoMCwgNSkpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2tleXVwLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrLCBjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbigna2V5dXAuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2ssIGNoYW5nZS5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdGlmIChzZWxmLiRjb250YWluZXIuYXR0cignc3RhdGUnKSA9PT0gJ2Zvcm0nKSB7XG5cdFx0XHRcdGlmIChzZWxmLnZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAhc2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0XHRzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcblx0XHRcdFx0fSBlbHNlIGlmICghc2VsZi52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgc2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0XHRzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5yZW1vdmVDbGFzcygncmVhZHknKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoc2VsZi4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdyZXN1bHQnKSB7XG5cdFx0XHRcdHNlbGYuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdFx0XHRcdHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCcnKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNsZWFyJykub24oJ21vdXNlZG93bi5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DbGVhcicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0aWYgKHNlbGYudmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KHNlbGYuJGNvbnRhaW5lcikubGVuZ3RoID09IDApIHtcblx0XHRcdFx0c2VsZi52YWxpZGF0b3IucmVzZXRGb3JtKCk7XG5cdFx0XHRcdHNlbGYuJGVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ0JvcGlzLlN0b3JlU2VhcmNoLlJlc2V0Jykub24oJ0JvcGlzLlN0b3JlU2VhcmNoLlJlc2V0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRzZWxmLnJlc2V0KCk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlNlbGVjdGlvbicpLm9uKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlNlbGVjdGlvbicsICdpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfU3RvcmVJZFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0dmFyIGJvcGlzU3RvcmUgPSAkKCdpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfU3RvcmVJZFwiXTpjaGVja2VkJykudmFsKCk7XG5cblx0XHRcdGlmICghc2VsZi4kYm9waXNCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0c2VsZi4kYm9waXNCdXR0b24uYWRkQ2xhc3MoJ3JlYWR5Jyk7XG5cdFx0XHR9XG5cblx0XHRcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXG5cdFx0XHRpZiAoYm9waXNTdG9yZSkge1xuXHRcdFx0XHRzZWxmLiRib3Bpc0J1dHRvbi5hdHRyKCdzdGF0ZScsICdwaWNrdXAnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNlbGYuJGJvcGlzQnV0dG9uLmF0dHIoJ3N0YXRlJywgJ3NoaXAnKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvcGlzU3RvcmVTZWFyY2guTm9SZXN1bHRzU2hpcCcpLm9uKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLk5vUmVzdWx0c1NoaXAnLCAnLmJ0bi5uby1yZXN1bHRzLXNoaXAnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnc2Nyb2xsLWxvY2snKTtcblx0XHRcdHNlbGYuY2xvc2UoKTtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIHsgY2hhbm5lbDogc2VsZi5vcHRpb25zLkNoYW5uZWwgfSk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc0FkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaC5TZWxlY3QnKS5vbignY2xpY2suQm9waXNBZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2guU2VsZWN0JywgJ2xpW3N0b3JlXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFxuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdCR0aGlzLmZpbmQoJ2lucHV0JykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdFx0c2VsZi4kY29udGFpbmVyLmZpbmQoJy5idG4uc3RvcmUtc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc0FkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaC5Db25maXJtJykub24oJ2NsaWNrLkJvcGlzQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoLkNvbmZpcm0nLCAnLmJ0bi5zdG9yZS1zZWxlY3Q6bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciBzdG9yZSA9ICQodGhpcykuY2xvc2VzdCgnaW5wdXRbc3RvcmVdJykuYXR0cignc3RvcmUnKTtcblx0XHRcdHZhciBzdG9yZSA9IHNlbGYuJGNvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwiYm9waXMtc3RvcmVcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHRcdFx0dmFyIGV2ZW50TmFtZSA9ICdCb3Bpcy5TdG9yZVNlYXJjaC5TZWxlY3QnO1xuXG5cdFx0XHRpZiAoc2VsZi5vcHRpb25zLkV2ZW50cyAmJiBzZWxmLm9wdGlvbnMuRXZlbnRzLlNlbGVjdFN0b3JlKSB7XG5cdFx0XHRcdGV2ZW50TmFtZSA9IHNlbGYub3B0aW9ucy5FdmVudHMuU2VsZWN0U3RvcmU7XG5cdFx0XHRcdHN0b3JlID0gc2VsZi5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtzdG9yZV07XG5cdFx0XHR9XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKGV2ZW50TmFtZSwgc3RvcmUpO1xuXHRcdFx0c2VsZi5jbG9zZSgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suQm9waXNBZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2guQ2xvc2UnKS5vbignY2xpY2suQm9waXNBZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2guQ2xvc2UnLCAnLmNsb3NlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHRzZWxmLmNsb3NlKCk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Vc2VNeUxvY2F0aW9uJykub24oJ2NsaWNrLlVzZU15TG9jYXRpb24nLCAnLnVzZS1teS1sb2NhdGlvbicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFxuXHRcdFx0R2VvbG9jYXRpb25IZWxwZXIuR2V0UG9zaXRpb24oKS50aGVuKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0XHRcdHNlbGYuc2VhcmNoKHRydWUsIHBvc2l0aW9uKTtcblx0XHRcdH0pLmNhdGNoKCk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLnJlc2V0KCk7XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJyAmJiB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpKSB7XG5cdFx0XHR0aGlzLnNlYXJjaCgpO1xuXHRcdH1cblx0fVxuXG5cdHRoaXMucmVzZXQgPSBmdW5jdGlvbigpIHtcblx0XHR0aGlzLiRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgJzAnKTtcblx0XHR0aGlzLiRyZXN1bHQuaHRtbCgnJyk7XG5cdH1cblxuXHR0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG5cdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuRnVuY3Rpb25zICYmIHRoaXMub3B0aW9ucy5GdW5jdGlvbnMuQ2xvc2UpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5GdW5jdGlvbnMuQ2xvc2UoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmJvcGlzLWFkZC10by1jYXJ0LXN0b3JlLXNlYXJjaC1jb250YWluZXInKS5yZW1vdmVDbGFzcygnc2hvdycpO1xuXHRcdH1cblx0fVxuXG5cdHRoaXMuc2VhcmNoID0gZnVuY3Rpb24oaXNCeUdlb2xvY2F0aW9uLCBwb3NpdGlvbikge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgY29sb3JTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0dmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdFx0dmFyIGxlbmd0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAubGVuZ3RoLmxlbmd0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHR2YXIgaXNTaXplU2VsZWN0ZWQgPSBzaXplU2VsZWN0ZWQubGVuZ3RoIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKTtcblxuXHRcdGlmICh0aGlzLm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gIT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHRcdGlmICghaXNTaXplU2VsZWN0ZWQgJiYgIWNvbG9yU2VsZWN0ZWQpIHtcblx0XHRcdFx0dGhpcy4kZXJyb3JNZXNzYWdlLmh0bWwoJ1BsZWFzZSBzZWxlY3QgYSBzaXplIGFuZCBjb2xvci4nKS5zaG93KCk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH0gZWxzZSBpZiAoIWlzU2l6ZVNlbGVjdGVkKSB7XG5cdFx0XHRcdHRoaXMuJGVycm9yTWVzc2FnZS5odG1sKCdQbGVhc2Ugc2VsZWN0IGEgc2l6ZS4nKS5zaG93KCk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH0gZWxzZSBpZiAoIWNvbG9yU2VsZWN0ZWQpIHtcblx0XHRcdFx0dGhpcy4kZXJyb3JNZXNzYWdlLmh0bWwoJ1BsZWFzZSBzZWxlY3QgYSBjb2xvci4nKS5zaG93KCk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy4kZXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbi5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXG5cdFx0dmFyIGdlb2xvY2F0aW9uUG9zaXRpb247XG5cdFx0aWYgKGlzQnlHZW9sb2NhdGlvbiAmJiBwb3NpdGlvbiAmJiBwb3NpdGlvbi5jb29yZHMpIHtcblx0XHRcdGdlb2xvY2F0aW9uUG9zaXRpb24gPSB7XG5cdFx0XHRcdGNvb3Jkczoge1xuXHRcdFx0XHRcdGFjY3VyYWN5OiBwb3NpdGlvbi5jb29yZHMuYWNjdXJhY3ksXG5cdFx0XHRcdFx0bGF0aXR1ZGU6IHBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSxcblx0XHRcdFx0XHRsb25naXR1ZGU6IHBvc2l0aW9uLmNvb3Jkcy5sb25naXR1ZGVcblx0XHRcdFx0fSxcblx0XHRcdFx0dGltZXN0YW1wOiBwb3NpdGlvbi50aW1lc3RhbXBcblx0XHRcdH1cblx0XHR9XG5cblx0XHR2YXIgaXNWYWxpZCA9IGlzQnlHZW9sb2NhdGlvbiB8fCB0aGlzLnZhbGlkYXRvci52YWxpZCgpO1xuXHRcdGlmIChVcmxzICYmIFVybHMuQm9waXMuR2V0U3RvcmVJbnZlbnRvcnlGb3JQcm9kdWN0Rm9yUG9zdGFsQ29kZSAmJiBpc1ZhbGlkKSB7XG5cdFx0XHR0aGlzLiRyZXN1bHQuaHRtbCgnJyk7XG5cdFx0XHR0aGlzLiRyZXN1bHQubG9hZGluZygpO1xuXG5cdFx0XHR0aGlzLmxvYWRlZFsnTG9jYXRpb25EYXRhJ10gPSBmYWxzZTtcblx0XHRcdHRoaXMubG9hZGVkWydJbnZlbnRvcnlEYXRhJ10gPSBmYWxzZTtcblx0XHRcdHRoaXMuZGF0YUJ1ZmZlclsnTG9jYXRpb25EYXRhJ10gPSBudWxsO1xuXHRcdFx0dGhpcy5kYXRhQnVmZmVyWydJbnZlbnRvcnlEYXRhJ10gPSBudWxsO1xuXG5cdFx0XHR2YXIgZ2V0TG9jYXRpb25Vcmw7XG5cdFx0XHR2YXIgZ2V0TG9jYXRpb25EYXRhO1xuXHRcdFx0aWYgKGlzQnlHZW9sb2NhdGlvbikge1xuXHRcdFx0XHRnZXRMb2NhdGlvblVybCA9IFVybHMuQm9waXMuR2V0TG9jYXRpb25zRm9yR2VvbG9jYXRpb25Qb3NpdGlvbjtcblx0XHRcdFx0Z2V0TG9jYXRpb25EYXRhID0ge1xuXHRcdFx0XHRcdENoYW5uZWw6IHRoaXMub3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRcdFNvdXJjZTogdGhpcy5vcHRpb25zLlNvdXJjZSxcblx0XHRcdFx0XHRHZW9sb2NhdGlvblBvc2l0aW9uOiBnZW9sb2NhdGlvblBvc2l0aW9uLFxuXHRcdFx0XHRcdFJhZGl1czogcGFyc2VGbG9hdCh0aGlzLiRmb3JtSW5wdXRSYWRpdXMudmFsKCkpIHx8IDMwMDBcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Z2V0TG9jYXRpb25VcmwgPSBVcmxzLkJvcGlzLkdldExvY2F0aW9uc0ZvclBvc3RhbENvZGU7XG5cdFx0XHRcdGdldExvY2F0aW9uRGF0YSA9IHtcblx0XHRcdFx0XHRDaGFubmVsOiB0aGlzLm9wdGlvbnMuQ2hhbm5lbCxcblx0XHRcdFx0XHRTb3VyY2U6IHRoaXMub3B0aW9ucy5Tb3VyY2UsXG5cdFx0XHRcdFx0UG9zdGFsQ29kZTogdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKSxcblx0XHRcdFx0XHRSYWRpdXM6IHBhcnNlRmxvYXQodGhpcy4kZm9ybUlucHV0UmFkaXVzLnZhbCgpKSB8fCAzMDAwXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0XHR1cmw6IGdldExvY2F0aW9uVXJsLFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShnZXRMb2NhdGlvbkRhdGEpLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0dmFyIGxvY2F0aW9uRGF0YTtcblx0XHRcdFx0XHRpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uRGF0YSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhO1xuXG5cdFx0XHRcdFx0XHRpZiAobG9jYXRpb25EYXRhICYmIGxvY2F0aW9uRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdGxvY2F0aW9uRGF0YSA9IGxvY2F0aW9uRGF0YS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGxlZnQuZGlzdGFuY2UgLSByaWdodC5kaXN0YW5jZTtcblx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyWydMb2NhdGlvbkRhdGEnXSA9IGxvY2F0aW9uRGF0YTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzZWxmLmxvYWRlZFsnTG9jYXRpb25EYXRhJ10gPSB0cnVlO1xuXHRcdFx0XHRcdHNlbGYucmVuZGVyKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoc2VsZi5vcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcblx0XHRcdFx0XHRcdHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0dmFyIHByb2R1Y3RJZCA9ICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJwaWRcIl0nKS52YWwoKTtcblx0XHRcdHZhciBnZXRTdG9yZUludmVudG9yeVVybDtcblx0XHRcdHZhciBnZXRTdG9yZUludmVudG9yeURhdGE7XG5cdFx0XHRpZiAoaXNCeUdlb2xvY2F0aW9uKSB7XG5cdFx0XHRcdGdldFN0b3JlSW52ZW50b3J5VXJsID0gVXJscy5Cb3Bpcy5HZXRTdG9yZUludmVudG9yeUZvclByb2R1Y3RGb3JHZW9sb2NhdGlvblBvc2l0aW9uO1xuXHRcdFx0XHRnZXRTdG9yZUludmVudG9yeURhdGEgPSB7XG5cdFx0XHRcdFx0Q2hhbm5lbDogdGhpcy5vcHRpb25zLkNoYW5uZWwsXG5cdFx0XHRcdFx0U291cmNlOiB0aGlzLm9wdGlvbnMuU291cmNlLFxuXHRcdFx0XHRcdFByb2R1Y3RJZDogcHJvZHVjdElkLFxuXHRcdFx0XHRcdEdlb2xvY2F0aW9uUG9zaXRpb246IGdlb2xvY2F0aW9uUG9zaXRpb24sXG5cdFx0XHRcdFx0U3RvcmVTZWFyY2hSYWRpdXM6IHBhcnNlRmxvYXQodGhpcy4kZm9ybUlucHV0UmFkaXVzLnZhbCgpKSB8fCAzMDAwLFxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRnZXRTdG9yZUludmVudG9yeVVybCA9IFVybHMuQm9waXMuR2V0U3RvcmVJbnZlbnRvcnlGb3JQcm9kdWN0Rm9yUG9zdGFsQ29kZTtcblx0XHRcdFx0Z2V0U3RvcmVJbnZlbnRvcnlEYXRhID0ge1xuXHRcdFx0XHRcdENoYW5uZWw6IHRoaXMub3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRcdFNvdXJjZTogdGhpcy5vcHRpb25zLlNvdXJjZSxcblx0XHRcdFx0XHRQcm9kdWN0SWQ6IHByb2R1Y3RJZCxcblx0XHRcdFx0XHRQb3N0YWxDb2RlOiB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLFxuXHRcdFx0XHRcdFN0b3JlU2VhcmNoUmFkaXVzOiBwYXJzZUZsb2F0KHRoaXMuJGZvcm1JbnB1dFJhZGl1cy52YWwoKSkgfHwgMzAwMCxcblx0XHRcdFx0XHRTYXZlUG9zdGFsQ29kZTogdHJ1ZVxuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiBnZXRTdG9yZUludmVudG9yeVVybCxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoZ2V0U3RvcmVJbnZlbnRvcnlEYXRhKSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCAmJiBkYXRhLklucXVpcnlSZXN1bHQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGEgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGEubGVuZ3RoID4gMCAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YVswXS5pbnZlbnRvcnlfc3VwcGxpZXMpIHtcblx0XHRcdFx0XHRcdHZhciBpbnF1aXJ5UmVzdWx0ID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAoaW5xdWlyeVJlc3VsdCAmJiBpbnF1aXJ5UmVzdWx0Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyWydJbnZlbnRvcnlEYXRhJ10gPSBbXTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGZvciAodmFyIGludmVudG9yeVJlY29yZEVsZW1lbnQgaW4gaW5xdWlyeVJlc3VsdCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBpbnZlbnRvcnlSZWNvcmQgPSBpbnF1aXJ5UmVzdWx0W2ludmVudG9yeVJlY29yZEVsZW1lbnRdO1xuXHRcdFx0XHRcdFx0XHRcdHNlbGYuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSA9IGludmVudG9yeVJlY29yZDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHNlbGYubG9hZGVkWydJbnZlbnRvcnlEYXRhJ10gPSB0cnVlO1xuXHRcdFx0XHRcdHNlbGYucmVuZGVyKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoc2VsZi4kcmVzdWx0LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRcdFx0c2VsZi4kcmVzdWx0LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoc2VsZi5vcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcblx0XHRcdFx0XHRcdHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLnJlbmRlciA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICh0aGlzLmxvYWRlZFsnTG9jYXRpb25EYXRhJ10gJiYgdGhpcy5sb2FkZWRbJ0ludmVudG9yeURhdGEnXSkge1xuXHRcdFx0aWYgKHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lci5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy4kcmVzdWx0LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRyZXN1bHQubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLiRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG5cdFx0XHRpZiAodGhpcy5kYXRhQnVmZmVyWydMb2NhdGlvbkRhdGEnXSAmJiB0aGlzLmRhdGFCdWZmZXJbJ0xvY2F0aW9uRGF0YSddLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXSA9IFtdO1xuXG5cdFx0XHRcdHZhciAkYWRkVG9DYXJ0T3B0aW9ucyA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zJyk7XG5cdFx0XHRcdHZhciBxdWFudGl0eVNvdXJjZVR5cGU7XG5cdFx0XHRcdHZhciBkcm9wc2hpcExlYWREYXlzO1xuXHRcdFx0XHRpZiAoJGFkZFRvQ2FydE9wdGlvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZSA9ICRhZGRUb0NhcnRPcHRpb25zLmF0dHIoJ3F1YW50aXR5LXNvdXJjZS10eXBlJyk7XG5cdFx0XHRcdFx0ZHJvcHNoaXBMZWFkRGF5cyA9IHBhcnNlSW50KCRhZGRUb0NhcnRPcHRpb25zLmF0dHIoJ2Ryb3BzaGlwLWxlYWQtZGF5cycpLCAxMCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIHF1YW50aXR5U291cmNlVHlwZU9mZnNldCA9IDA7XG5cdFx0XHRcdGlmIChxdWFudGl0eVNvdXJjZVR5cGUgPT0gJ1dIUycpIHtcblx0XHRcdFx0XHRxdWFudGl0eVNvdXJjZVR5cGVPZmZzZXQgPSAtMTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBzdG9yZUxpc3RIdG1sID0gJyc7XG5cdFx0XHRcdHZhciBpc1N0b3JlU2VsZWN0ZWQgPSBmYWxzZTtcblx0XHRcdFx0dmFyIHN0YXR1cyA9ICcnO1xuXHRcdFx0XHR2YXIgc3RhdHVzRGlzcGxheSA9ICcnO1xuXHRcdFx0XHR2YXIgaXNMb2NhbERlbGl2ZXJ5U3VwcG9ydGVkID0gZmFsc2U7XG5cdFx0XHRcdHZhciBsb2NhbERlbGl2ZXJ5SHRtbCA9ICcnO1xuXHRcdFx0XHR2YXIgc3RvcmVzRGlzcGxheWVkQ291bnQgPSAwO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZTtcblx0XHRcdFx0dmFyIHF1YW50aXR5QXZhaWxhYmxlID0gZmFsc2U7XG5cdFx0XHRcdGZvciAodmFyIGxvY2F0aW9uS2V5IGluIHRoaXMuZGF0YUJ1ZmZlclsnTG9jYXRpb25EYXRhJ10pIHtcblx0XHRcdFx0XHR2YXIgbG9jYXRpb24gPSB0aGlzLmRhdGFCdWZmZXJbJ0xvY2F0aW9uRGF0YSddW2xvY2F0aW9uS2V5XTtcblxuXHRcdFx0XHRcdHZhciBpbnZlbnRvcnlSZWNvcmQ7XG5cdFx0XHRcdFx0aWYgKHRoaXMuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddICYmIHRoaXMuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddW2xvY2F0aW9uLmNvZGVdKSB7XG5cdFx0XHRcdFx0XHRpbnZlbnRvcnlSZWNvcmQgPSB0aGlzLmRhdGFCdWZmZXJbJ0ludmVudG9yeURhdGEnXVtsb2NhdGlvbi5jb2RlXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzdGF0dXMgPSAndW5hdmFpbGFibGUnO1xuXHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnVW5hdmFpbGFibGUnO1xuXHRcdFx0XHRcdGlzTG9jYWxEZWxpdmVyeVN1cHBvcnRlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdGxvY2FsRGVsaXZlcnlIdG1sID0gJyc7XG5cdFx0XHRcdFx0aWYgKGludmVudG9yeVJlY29yZCAmJiBpbnZlbnRvcnlSZWNvcmQuZGV0YWlsICYmIGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHkgPiAwICYmICF0aGlzLmRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSAmJiAoIXRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSB8fCAoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X2VuYWJsZWQgJiYgdGhpcy5pc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKGludmVudG9yeVJlY29yZC5sb2NhdGlvbikpKSkge1xuXHRcdFx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuU2VsZWN0ZWRMb2NhdGlvbnMgPT0gaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmNvZGUpIHtcblx0XHRcdFx0XHRcdFx0aXNTdG9yZVNlbGVjdGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9J2NoZWNrZWQnO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9ICcnO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuRW5hYmxlZCAmJiB0aGlzLmlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uKSAmJiBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfZW5hYmxlZCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhbERlbGl2ZXJ5SHRtbCA9IHRoaXMubG9jYWxEZWxpdmVyeURlY29yYXRvcigpO1xuXHRcdFx0XHRcdFx0XHRpc0xvY2FsRGVsaXZlcnlTdXBwb3J0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoaXNMb2NhbERlbGl2ZXJ5U3VwcG9ydGVkICYmIGludmVudG9yeVJlY29yZC5kZXRhaWwgJiYgaW52ZW50b3J5UmVjb3JkLmRldGFpbC5xdWFudGl0eSA+IDApIHtcblx0XHRcdFx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnU2FtZS1EYXkgRGVsaXZlcnk8YnIvPkF2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gJ2F2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIXRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIHN0YXR1c0Rpc3BsYXkgPSAnUGlja3VwICYgU2FtZS1EYXk8YnIvPkRlbGl2ZXJ5IEF2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzRGlzcGxheSA9ICdBdmFpbGFibGUgVG9kYXknO1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1cyA9ICdhdmFpbGFibGUnO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCF0aGlzLm9wdGlvbnMuTG9jYWxEZWxpdmVyeU9ubHkgJiYgaW52ZW50b3J5UmVjb3JkLmRldGFpbCAmJiBpbnZlbnRvcnlSZWNvcmQuZGV0YWlsLnF1YW50aXR5ID4gMCkge1xuXHRcdFx0XHRcdFx0XHRzdGF0dXNEaXNwbGF5ID0gJ0F2YWlsYWJsZSBUb2RheSc7XG5cdFx0XHRcdFx0XHRcdHN0YXR1cyA9ICdhdmFpbGFibGUnO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRxdWFudGl0eUF2YWlsYWJsZSA9IGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICghdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnlPbmx5ICYmIHBhZ2VDb250ZXh0LnNpdGUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMpIHtcblx0XHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnQXJyaXZlcyBpbiAnICsgKHRoaXMub3B0aW9ucy5TaGlwcGluZ01ldGhvZHMuU2hpcFRvU3RvcmUuRGF5UmFuZ2VTdGFydCArIGRyb3BzaGlwTGVhZERheXMgKyBxdWFudGl0eVNvdXJjZVR5cGVPZmZzZXQpICsgJy0nICsgKHRoaXMub3B0aW9ucy5TaGlwcGluZ01ldGhvZHMuU2hpcFRvU3RvcmUuRGF5UmFuZ2VFbmQgKyBkcm9wc2hpcExlYWREYXlzICsgcXVhbnRpdHlTb3VyY2VUeXBlT2Zmc2V0KSArICc8YnIvPkJ1c2luZXNzIERheXMnO1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gJ2F2YWlsYWJsZSc7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHF1YW50aXR5QXZhaWxhYmxlID0gZmFsc2Vcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgbG9jYXRpb25OYW1lO1xuXHRcdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbk5hbWUgPSAnPHN0cm9uZz4nICsgbG9jYXRpb24uU3RvcmVJbmZvLk5hbWUgKyAnIC0gJyArIGxvY2F0aW9uLlN0b3JlSW5mby5TdG9yZUlkICsgJzwvc3Ryb25nPic7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uTmFtZSA9ICc8c3Ryb25nPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uTmFtZSArICc8L3N0cm9uZz4nO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5BZ2VudFN0b3JlSUQgPT0gbG9jYXRpb24uY29kZSkge1xuXHRcdFx0XHRcdFx0bG9jYXRpb25OYW1lICs9ICc8YnIvPihZb3VyIFN0b3JlKSc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0c3RvcmVMaXN0SHRtbCArPSB0aGlzLnJlc3VsdEl0ZW1UZW1wbGF0ZSh7XG5cdFx0XHRcdFx0XHRTdG9yZUlkOiBsb2NhdGlvbi5jb2RlLFxuXHRcdFx0XHRcdFx0UXVhbnRpdHlBdmFpbGFibGU6IHF1YW50aXR5QXZhaWxhYmxlLFxuXHRcdFx0XHRcdFx0SHRtbDogJzxzcGFuIGNsYXNzPVwic3RvcmUtbmFtZVwiPicgKyBsb2NhdGlvbk5hbWUgKyAnPC9zcGFuPjxici8+JyArIGxvY2F0aW9uLlN0b3JlSW5mby5BZGRyZXNzMSArICc8YnIvPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uQ2l0eSArICcsICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uU3RhdGVDb2RlUGFyc2VkICsgJywgJyArIGxvY2F0aW9uLlN0b3JlSW5mby5Qb3N0YWxDb2RlLnN1YnN0cigwLCA1KSxcblx0XHRcdFx0XHRcdFNlbGVjdGVkOiBzZWxlY3RlZFN0b3JlQXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0TG9jYWxEZWxpdmVyeTogbG9jYWxEZWxpdmVyeUh0bWwsXG5cdFx0XHRcdFx0XHRTdGF0dXM6IHN0YXR1cyxcblx0XHRcdFx0XHRcdFN0YXR1c0Rpc3BsYXk6IHN0YXR1c0Rpc3BsYXlcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdHN0b3Jlc0Rpc3BsYXllZENvdW50ICs9IDE7XG5cdFx0XHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtsb2NhdGlvbi5jb2RlXSA9IGludmVudG9yeVJlY29yZCA/IGludmVudG9yeVJlY29yZCA6IHsgbG9jYXRpb246IGxvY2F0aW9uIH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgcmVzdWx0SHRtbCA9IHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGUoe1xuXHRcdFx0XHRcdEh0bWw6IHN0b3JlTGlzdEh0bWxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aWYgKGlzU3RvcmVTZWxlY3RlZCkge1xuXHRcdFx0XHRcdHRoaXMuJGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHN0b3Jlc0Rpc3BsYXllZENvdW50ID4gMCkge1xuXHRcdFx0XHRcdHRoaXMuJHJlc3VsdC5odG1sKHJlc3VsdEh0bWwpO1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCBzdG9yZXNEaXNwbGF5ZWRDb3VudCk7XG5cdFx0XHRcdFx0dGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQtY29udGFpbmVyJykuc2hvdygpO1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5maW5kKCcucmVzdWx0LWVtcHR5JykuaGlkZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCAwKTtcblx0XHRcdFx0XHR0aGlzLiRjb250YWluZXIuZmluZCgnLnJlc3VsdC1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHRcdFx0dGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQtZW1wdHknKS5zaG93KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0XHRcdGl0ZW1zOiAnLnRvb2x0aXAnXG5cdFx0XHRcdH0sIHRoaXMuJHJlc3VsdCk7XG5cblx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2spIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuc3VjY2Vzc0NhbGxiYWNrKGlucXVpcnlSZXN1bHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0dGhpcy5yZXNldCgpO1x0XHRcdFx0XHRcdFxuXHRcdFx0XHR0aGlzLiRyZXN1bHQuY2xvc2VzdCgnLnJlc3VsdC1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5maW5kKCcucmVzdWx0LWVtcHR5Jykuc2hvdygpO1xuXG5cdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR0aGlzLmlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMgPSBmdW5jdGlvbihsb2NhdGlvbikge1xuXHRcdHZhciBsb2NhbERlbGl2ZXJ5UmFkaXVzO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkpIHtcblx0XHRcdGlmIChsb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgJiYgbG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yID09ICdHb0xvY2FsJykge1xuXHRcdFx0XHRsb2NhbERlbGl2ZXJ5UmFkaXVzID0gdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzRm9yR29Mb2NhbDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSB0aGlzLm9wdGlvbnMuTG9jYWxEZWxpdmVyeS5SYWRpdXNGb3JSb2FkaWU7XG5cdFx0XHR9XG5cdFx0fVx0XG5cblx0XHRpZiAobG9jYWxEZWxpdmVyeVJhZGl1cyAmJiBsb2NhdGlvbiAmJiBsb2NhdGlvbi5kaXN0YW5jZSAmJiBsb2NhbERlbGl2ZXJ5UmFkaXVzID49IGxvY2F0aW9uLmRpc3RhbmNlKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoID0gcmVxdWlyZSgnLi9BZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2gnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKTtcbnZhciBWYWxpZGF0aW9uU2V0dGluZ3MgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5TZXR0aW5ncztcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFppcENvZGVUb1N0YXRlTWFwID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9kYXRhL1ppcENvZGVUb1N0YXRlTWFwLmpzb24nKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcbmV4cG9ydHMucmVtb3ZlID0gcmVtb3ZlO1xuXG52YXIgb3B0aW9ucztcbnZhciBvcHRpb25zTG9jYWxEZWxpdmVyeTtcbnZhciB2YWxpZGF0b3I7XG52YXIgZGF0YUJ1ZmZlcjtcbnZhciBsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2g7XG52YXIgbG9jYWxEZWxpdmVyeVJhZGl1cztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyLCBzZWxlY3RlZExvY2F0aW9uLCBsb2NhbERlbGl2ZXJ5Rm9ybURhdGEpIHtcblx0ZGF0YUJ1ZmZlciA9IHt9O1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXG5cdGlmIChzZWxlY3RlZExvY2F0aW9uICYmIHNlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24gJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgPT0gJ0dvTG9jYWwnKSB7XG5cdFx0bG9jYWxEZWxpdmVyeVJhZGl1cyA9IG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5SYWRpdXNGb3JHb0xvY2FsO1xuXHR9IGVsc2UgaWYgKHNlbGVjdGVkTG9jYXRpb24gJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbiAmJiBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X3ZlbmRvciAmJiBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X3ZlbmRvciA9PSAnUm9hZGllJykge1xuXHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSBvcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzRm9yUm9hZGllO1xuXHR9XG5cblx0YnVpbGRBZGRyZXNzSHRtbEZvckxvY2F0aW9uKHNlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24pO1xuXHQkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5maW5kKCcuZGVsaXZlcnktcmFkaXVzJykuaHRtbChsb2NhbERlbGl2ZXJ5UmFkaXVzKTtcblx0dmFyICRvcHRpb25hbE1lc3NhZ2UgPSAkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMgaGVhZGVyIC5vcHRpb25hbC1tZXNzYWdlJyk7XG5cdFxuXHRpZiAob3B0aW9ucy5PcHRpb25hbE1lc3NhZ2UpIHtcblx0XHRpZiAoJG9wdGlvbmFsTWVzc2FnZS5sZW5ndGggPT0gMCkge1xuXHRcdFx0JCgnI2RpYWxvZy1ib3Bpcy1vcHRpb25zIGhlYWRlcicpLmFwcGVuZCgnPHAgY2xhc3M9XCJvcHRpb25hbC1tZXNzYWdlXCI+JyArIG9wdGlvbnMuT3B0aW9uYWxNZXNzYWdlICsgJzwvcD4nKVxuXHRcdH1cblx0fSBlbHNlIGlmICgkb3B0aW9uYWxNZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHQkb3B0aW9uYWxNZXNzYWdlLnJlbW92ZSgpO1xuXHR9XG5cdFxuXHRsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2ggPSBuZXcgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoKCk7XG5cdG9wdGlvbnNMb2NhbERlbGl2ZXJ5ID0gT2JqZWN0LmFzc2lnbihvcHRpb25zLCB7XG5cdFx0TG9jYWxEZWxpdmVyeU9ubHk6IHRydWUsXG5cdFx0RXZlbnRzOiB7XG5cdFx0XHRTZWxlY3RTdG9yZTogJ0JvcGlzLlN0b3JlU2VhcmNoU2VsZWN0TG9jYWxEZWxpdmVyeSdcblx0XHR9LFxuXHRcdEZ1bmN0aW9uczoge1xuXHRcdFx0Q2xvc2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJy51aS13aWRnZXQtb3ZlcmxheScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnLmJvcGlzLWxvY2FsLWRlbGl2ZXJ5LXN0b3JlLXNlYXJjaC1jb250YWluZXInKS5yZW1vdmVDbGFzcygnc2hvdycpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRXZlbnQoJ3JvYWRpZUZvcm1EaXNwbGF5Jyk7XG5cdGRpYWxvZy5vcGVuKHtcblx0XHRodG1sOiAkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5odG1sKCksXG5cdFx0b3B0aW9uczoge1xuXHRcdFx0ZGlhbG9nQ2xhc3M6ICdkaWFsb2ctYm9waXMtb3B0aW9ucycsXG5cdFx0XHR3aWR0aDogMzIwLFxuXHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdHJlc2l6YWJsZTogZmFsc2UsXG5cdFx0XHRvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0dmFyICRhZGRyZXNzRm9ybSA9ICR0aGlzLmZpbmQoJ2Zvcm0uYm9waXMtZGVsaXZlcnktYWRkcmVzcycpO1xuXHRcdFx0XHRhcHBlbmRDU1JGVG9rZW4oJGFkZHJlc3NGb3JtKTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEpIHtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5FbWFpbCB8fCAnJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwaG9uZVwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuUGhvbmUgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiZmlyc3ROYW1lXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5GaXJzdE5hbWUgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwibGFzdE5hbWVcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkxhc3ROYW1lIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFkZHJlc3MxXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5BZGRyZXNzMSB8fCAnJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhZGRyZXNzMlwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuQWRkcmVzczIgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWRkcmVzczNcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkFkZHJlc3MzIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImNpdHlcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkNpdHkgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbbmFtZT1cInN0YXRlQ29kZVwiXSBvcHRpb25bdmFsdWU9XCInICsgbG9jYWxEZWxpdmVyeUZvcm1EYXRhLlN0YXRlICsgJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwb3N0YWxDb2RlXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5Qb3N0YWxDb2RlIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgndGV4dGFyZWFbbmFtZT1cImRlbGl2ZXJ5Tm90ZVwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuRGVsaXZlcnlOb3RlIHx8ICcnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBhZGRyZXNzVmFsaWRhdG9yID0gJGFkZHJlc3NGb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3JlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24nLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbiwgUmVzb3VyY2VzLklOVkFMSURfVkFMVUUpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc3RPZmZpY2VCb3gnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3gsIFJlc291cmNlcy5JTlZBTElEX0FERFJFU1NfUE9CT1gpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ppcENvZGUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlWmlwQ29kZSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVEFMX0NPREUpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3N0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlU3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZSwgUmVzb3VyY2VzLklOVkFMSURfQ0FMSUZPUk5JQV9TVEFURV9MSU5FX0xPQ0FMX0RFTElWRVJZKTtcblx0XHRcdFx0XG5cdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWRkcmVzczFcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3gpO1xuXHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFkZHJlc3MyXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94KTtcblx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhZGRyZXNzM1wiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveCk7XG5cdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbbmFtZT1cInN0YXRlQ29kZVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuU3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZSk7XG5cdFx0XHQgICAgJGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwb3N0YWxDb2RlXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5aaXBDb2RlKTtcblx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLCBzZWxlY3QucmVxdWlyZWQnKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5FbWFpbCk7XG5cdFx0XHRcdCR0aGlzLmF0dHIoJ2xvY2FsLWRlbGl2ZXJ5LXZlbmRvcicsICQoJyNkaWFsb2ctYm9waXMtb3B0aW9ucycpLmF0dHIoJ2xvY2FsLWRlbGl2ZXJ5LXZlbmRvcicpKTtcblx0XHRcdFx0JHRoaXMuYXR0cignbG9jYWwtZGVsaXZlcnktcmFkaXVzJywgaXNMb2NhbERlbGl2ZXJ5VmFsaWQoc2VsZWN0ZWRMb2NhdGlvbikpO1xuXHRcdFx0XHQkdGhpcy5hdHRyKCdzdG9yZS1zdGF0ZScsIHNlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24ucG9zdGFsX2FkZHJlc3MucHJvdmluY2Vfb3Jfc3RhdGUpO1xuXHRcdFx0XHRcblx0XHRcdFx0JHRoaXMub2ZmKCdjbGljay5TZWxlY3REZWxpdmVyeU9wdGlvbicpLm9uKCdjbGljay5TZWxlY3REZWxpdmVyeU9wdGlvbicsICcuZGVsaXZlcnktb3B0aW9uIGxhYmVsJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdFx0dmFyIGRlbGl2ZXJ5T3B0aW9uID0gJCh0aGlzKS5maW5kKCdpbnB1dCcpLnZhbCgpO1xuXG5cdFx0XHRcdFx0aWYgKGRlbGl2ZXJ5T3B0aW9uID09ICdwaWNrdXAnKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5maW5kKCcuYWRkcmVzcy1mb3JtJykuaGlkZSgpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZGVsaXZlcnlPcHRpb24gPT0gJ2RlbGl2ZXJ5Jykge1xuXHRcdFx0XHRcdFx0JHRoaXMuZmluZCgnLmFkZHJlc3MtZm9ybScpLnNob3coKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suQXBwbHknKS5vbignY2xpY2suQXBwbHknLCAnLmJ0bi5ib3Bpcy1vcHRpb246bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0JHRoaXMuZmluZCgnLnVpLWRpYWxvZy1mb290ZXIgLmVycm9yJykucmVtb3ZlKCk7XG5cblx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRCb3Bpc09wdGlvbjtcblx0XHRcdFx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLk1vZGUgPT0gJ0FkZFRvQ2FydE9wdGlvbnMnKSB7XG5cdFx0XHRcdFx0XHRzZWxlY3RlZEJvcGlzT3B0aW9uID0gJ2RlbGl2ZXJ5Jztcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0c2VsZWN0ZWRCb3Bpc09wdGlvbiA9ICR0aGlzLmZpbmQoJ2lucHV0W25hbWU9XCJib3Bpcy1vcHRpb25cIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR2YXIgZXZlbnREYXRhID0ge2JvcGlzOiB0cnVlLCBib3Bpc1N0b3JlOiBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLmNvZGUsIHNoaXBwaW5nT3B0aW9uOiBzZWxlY3RlZEJvcGlzT3B0aW9uLCBjaGFubmVsOiBvcHRpb25zLkNoYW5uZWwsIHF1YW50aXR5QXZhaWxhYmxlOiBzZWxlY3RlZExvY2F0aW9uLmRldGFpbC5xdWFudGl0eX07XG5cdFx0XHRcdFx0aWYgKHNlbGVjdGVkQm9waXNPcHRpb24gPT0gJ2RlbGl2ZXJ5Jykge1xuXHRcdFx0XHRcdFx0dmFyIGRlbGl2ZXJ5QWRkcmVzc09iamVjdCA9IHt9O1xuXHRcdFx0XHRcdFx0dmFyICRkZWxpdmVyeUFkZHJlc3NGb3JtID0gJHRoaXMuZmluZCgnLmJvcGlzLWRlbGl2ZXJ5LWFkZHJlc3MnKTtcblx0XHRcdFx0XHRcdHZhciBkZWxpdmVyeUFkZHJlc3NBcnJheSA9ICRkZWxpdmVyeUFkZHJlc3NGb3JtLnNlcmlhbGl6ZUFycmF5KCk7XG5cdFx0XHRcdFx0XHQkKGRlbGl2ZXJ5QWRkcmVzc0FycmF5KS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRcdGlmIChlbGVtZW50LnZhbHVlICE9ICdkaXNhYmxlZCcgJiYgJGRlbGl2ZXJ5QWRkcmVzc0Zvcm0uZmluZCgnW25hbWU9XCInICsgZWxlbWVudC5uYW1lICsgJ1wiXScpLmF0dHIoJ3R5cGUnKSAhPSAnaGlkZGVuJykge1xuXHRcdFx0XHRcdFx0XHRcdGRlbGl2ZXJ5QWRkcmVzc09iamVjdFtlbGVtZW50Lm5hbWVdID0gZWxlbWVudC52YWx1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRldmVudERhdGEuZGVsaXZlcnlBZGRyZXNzID0gSlNPTi5zdHJpbmdpZnkoZGVsaXZlcnlBZGRyZXNzT2JqZWN0KTtcblx0XHRcdFx0XHRcdCRkZWxpdmVyeUFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W3R5cGU9XCJoaWRkZW5cIl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0XHRcdFx0ZXZlbnREYXRhWyR0aGlzLmF0dHIoJ25hbWUnKV0gPSAkdGhpcy52YWwoKTtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChzZWxlY3RlZEJvcGlzT3B0aW9uICE9ICdkZWxpdmVyeScgfHwgJGFkZHJlc3NGb3JtLnZhbGlkKCkpIHtcblx0XHRcdFx0XHRcdGlmIChzZWxlY3RlZEJvcGlzT3B0aW9uID09ICdkZWxpdmVyeScpIHtcblx0XHRcdFx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHQgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0XHQgICAgICAgICAgICB1cmw6IFVybHMuQm9waXMuVmFsaWRhdGVQb3N0YWxDb2RlRm9yTG9jYXRpb25zLFxuXHRcdFx0XHRcdCAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRcdFx0ICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBQb3N0YWxDb2RlOiAkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cInBvc3RhbENvZGVcIl0nKS52YWwoKSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgTG9jYXRpb25zOiBbc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5jb2RlXVxuXHRcdFx0XHRcdCAgICAgICAgICAgIH0pLFxuXHRcdFx0XHRcdCAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdFx0ICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0aWYgKGRhdGEpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRXZlbnQoJ3JvYWRpZUZvcm1TdWJtaXQnKTtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuQm9waXMuQWRkVG9DYXJ0JywgZXZlbnREYXRhKTtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgXHRcdHZhciBlcnJvck1lc3NhZ2UgPSAnPGRpdiBjbGFzcz1cImVycm9yXCI+VGhlIHppcCBjb2RlIHlvdSBlbnRlcmVkIGlzIGRpZmZlcmVudCB0aGFuIHRoZSBvbmUgeW91IHNlYXJjaGVkIHdpdGgsIGFuZCB0aGUgc2VsZWN0ZWQgbG9jYXRpb24gaXMgbm90IGluIHJhbmdlLiBQbGVhc2UgdXBkYXRlIHlvdXIgYWRkcmVzcyBhbmQgdHJ5IGFnYWluLjwvZGl2PidcblxuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0XHQkdGhpcy5maW5kKCcudWktZGlhbG9nLWZvb3RlcicpLnByZXBlbmQoZXJyb3JNZXNzYWdlKTtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdH1cblx0XHRcdFx0XHQgICAgICAgICAgICB9XG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuQm9waXMuQWRkVG9DYXJ0JywgZXZlbnREYXRhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suQ2hhbmdlWmlwJykub24oJ2NsaWNrLkNoYW5nZVppcCcsICcuYnRuLmNoYW5nZS16aXAnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdCb3Bpcy5TdG9yZVNlYXJjaC5SZXNldCcpO1xuXHRcdFx0XHRcdGRpYWxvZy5jbG9zZSgpO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQkdGhpcy5vZmYoJ2NsaWNrLkNoYW5nZVN0b3JlJykub24oJ2NsaWNrLkNoYW5nZVN0b3JlJywgJy5idG4uY2hhbmdlLXN0b3JlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdFx0ZGlhbG9nLmNsb3NlKCk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suU2VhcmNoU3RvcmUnKS5vbignY2xpY2suU2VhcmNoU3RvcmUnLCAnLnNlYXJjaC1zdG9yZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdFx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0JCgnLnVpLXdpZGdldC1vdmVybGF5JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdGxvY2FsRGVsaXZlcnlTdG9yZVNlYXJjaC5pbml0aWFsaXplKCQoJy5ib3Bpcy1sb2NhbC1kZWxpdmVyeS1zdG9yZS1zZWFyY2gtY29udGFpbmVyJyksIG9wdGlvbnNMb2NhbERlbGl2ZXJ5KTtcblx0XHRcdFx0fSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXG4gICAgICAgICAgICB9XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ0JvcGlzLlN0b3JlU2VhcmNoU2VsZWN0TG9jYWxEZWxpdmVyeScpLm9uKCdCb3Bpcy5TdG9yZVNlYXJjaFNlbGVjdExvY2FsRGVsaXZlcnknLCBmdW5jdGlvbiAoZXZlbnQsIHN0b3JlKSB7XG5cdFx0YnVpbGRBZGRyZXNzSHRtbEZvckxvY2F0aW9uKHN0b3JlLmxvY2F0aW9uKTtcblx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0JCgnLnVpLXdpZGdldC1vdmVybGF5JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdCQoJy5ib3Bpcy1sb2NhbC1kZWxpdmVyeS1zdG9yZS1zZWFyY2gtY29udGFpbmVyJykucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5maW5kKCcuZGlhbG9nLWNvbnRlbnQnKS5hdHRyKCdsb2NhbC1kZWxpdmVyeS1yYWRpdXMnLCBpc0xvY2FsRGVsaXZlcnlWYWxpZChzdG9yZSkpO1xuXHRcdCQoJy5kaWFsb2ctYm9waXMtb3B0aW9ucycpLmZpbmQoJy5kaWFsb2ctY29udGVudCcpLmF0dHIoJ3N0b3JlLXN0YXRlJywgc3RvcmUubG9jYXRpb24ucG9zdGFsX2FkZHJlc3MucHJvdmluY2Vfb3Jfc3RhdGUpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKCkge1xuXHR2YWxpZGF0b3IuZGVzdHJveSgpO1xuXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRBZGRyZXNzSHRtbEZvckxvY2F0aW9uKGxvY2F0aW9uKSB7XG5cdHZhciBsb2NhdGlvbkh0bWw7XG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTW9kZSA9PSAnQWRkVG9DYXJ0T3B0aW9ucycpIHtcblx0XHRsb2NhdGlvbkh0bWwgPSAnPHAgY2xhc3M9XCJzZWxlY3RlZC1sb2NhdGlvbi1uYW1lXCI+JyArIGxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLm5hbWUgKyAnPC9wPicgKyBcblx0XHRcdFx0XHRcdFx0XHQnPHAgY2xhc3M9XCJzZWxlY3RlZC1sb2NhdGlvbi1hZGRyZXNzXCI+JyArIGxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLmFkZHJlc3NfbGluZTEgKyAnPGJyLz4nICtcblx0XHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5jaXR5ICsgJywgJyArIGxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLnByb3ZpbmNlX29yX3N0YXRlICsgJzwvcD4nICtcblx0XHRcdFx0XHRcdFx0XHQnPGEgY2xhc3M9XCJzZWFyY2gtc3RvcmVcIj5DaGFuZ2UgU3RvcmU8L2E+Jztcblx0fSBlbHNlIHtcblx0XHRsb2NhdGlvbkh0bWwgPSBsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5hZGRyZXNzX2xpbmUxICsgJzxici8+JyArXG5cdFx0bG9jYXRpb24ucG9zdGFsX2FkZHJlc3MuY2l0eSArICcsICcgKyBsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5wcm92aW5jZV9vcl9zdGF0ZTtcblx0fVxuXG5cdCQoJy51aS1kaWFsb2cuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5maW5kKCcuc2VsZWN0ZWQtbG9jYXRpb24tZGV0YWlscycpLmh0bWwobG9jYXRpb25IdG1sKTtcblx0JCgnI2RpYWxvZy1ib3Bpcy1vcHRpb25zJykuZmluZCgnLnNlbGVjdGVkLWxvY2F0aW9uLWRldGFpbHMnKS5odG1sKGxvY2F0aW9uSHRtbCk7XG59XG5cbmZ1bmN0aW9uIGlzTG9jYWxEZWxpdmVyeVZhbGlkKHJlY29yZCkge1xuXHRpZiAob3B0aW9ucy5Mb2NhbERlbGl2ZXJ5ICYmIG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5FbmFibGVkICYmIGlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMocmVjb3JkLmxvY2F0aW9uKSAmJiByZWNvcmQubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfZW5hYmxlZCAmJiByZWNvcmQuZGV0YWlsICYmIHJlY29yZC5kZXRhaWwucXVhbnRpdHkgPiAwKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMobG9jYXRpb24pIHtcblx0aWYgKGxvY2FsRGVsaXZlcnlSYWRpdXMgJiYgbG9jYXRpb24uZGlzdGFuY2UgJiYgbG9jYWxEZWxpdmVyeVJhZGl1cyA+PSBsb2NhdGlvbi5kaXN0YW5jZSkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0cmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRDU1JGVG9rZW4oJGZvcm0pIHtcblx0JC5hamF4KHtcblx0XHRtZXRob2Q6ICdnZXQnLFxuXHRcdHVybDogVXJscy5DU1JGVG9rZW4uR2V0LFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdCRmb3JtLmFwcGVuZCgnPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJyArIHJlc3BvbnNlLm5hbWUgKyAnXCIgdmFsdWU9XCInICsgcmVzcG9uc2UudG9rZW4gKyAnXCIvPicpO1xuXHRcdH1cblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHZW9sb2NhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvR2VvbG9jYXRpb24vR2VvbG9jYXRpb25IZWxwZXInKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBMb2NhdGlvblNlYXJjaDtcblxuZnVuY3Rpb24gTG9jYXRpb25TZWFyY2goKSB7XG5cdHRoaXMuJGNvbnRhaW5lcjtcblx0dGhpcy4kZm9ybTtcblx0dGhpcy5kYXRhQnVmZmVyO1xuXHR0aGlzLm9wdGlvbnM7XG5cdHRoaXMudmFsaWRhdG9yO1xuXHRcblx0dGhpcy5yZXN1bHRDb250YWluZXJUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1jb250YWluZXInKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdHRoaXMucmVzdWx0SXRlbVRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWl0ZW0nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cblx0dGhpcy4kcmVzdWx0O1xuXHR0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlO1xuXHR0aGlzLiRmb3JtSW5wdXRSYWRpdXM7XG5cdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uO1xuXHR0aGlzLiRzdG9yZVNlbGVjdEJ1dHRvbjtcblx0dGhpcy4kYm9waXNCdXR0b247XG5cdHRoaXMuJGVycm9yTWVzc2FnZTtcblx0XG5cdHRoaXMuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uICgkY29udGFpbmVyLCBvcHRpb25zKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHRoaXMuJGNvbnRhaW5lciA9ICRjb250YWluZXI7XG5cdFx0dGhpcy4kZm9ybSA9ICRjb250YWluZXIuZmluZCgnZm9ybScpO1xuXHRcdHRoaXMub3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRcdGVycm9yQ2FsbGJhY2s6IG51bGxcblx0XHR9LCBvcHRpb25zKTtcblx0XHR0aGlzLmRhdGFCdWZmZXIgPSB7XG5cdFx0XHRsaW1pdDogdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5Cb3BpcyAmJiB0aGlzLm9wdGlvbnMuQm9waXMuU3RvcmVTZWFyY2hMaW1pdCA/IHRoaXMub3B0aW9ucy5Cb3Bpcy5TdG9yZVNlYXJjaExpbWl0IDogNVxuXHRcdH07XG5cdFx0dGhpcy4kcmVzdWx0ID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQnKTtcblx0XHR0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlID0gdGhpcy4kZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxDb2RlXCJdJyk7XG5cdFx0dGhpcy4kZm9ybUlucHV0UmFkaXVzID0gdGhpcy4kZm9ybS5maW5kKCdbbmFtZSQ9XCJfcmFkaXVzXCJdJyk7XG5cdFx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b24gPSB0aGlzLiRjb250YWluZXIuZmluZCgnLmJ0bi5zdG9yZS1zZWFyY2gnKTtcblx0XHR0aGlzLiRzdG9yZVNlbGVjdEJ1dHRvbiA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlbGVjdCcpO1xuXHRcdHRoaXMuJGJvcGlzQnV0dG9uID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5idG4uYm9waXMnKTtcblx0ICAgIHRoaXMuJGVycm9yTWVzc2FnZSA9IHRoaXMuJGZvcm0uZmluZCgnc3Bhbi5lcnJvcicpO1xuXHRcdCQoJ2h0bWwnKS5hZGRDbGFzcygnc2Nyb2xsLWxvY2snKTtcblxuXHRcdGlmICh0aGlzLm9wdGlvbnMuRGVmYXVsdFppcENvZGUpIHtcblx0XHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKHRoaXMub3B0aW9ucy5EZWZhdWx0WmlwQ29kZSk7XG5cdFx0fVxuXG5cdCAgICB0aGlzLiRjb250YWluZXIuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHQgICAgdGhpcy52YWxpZGF0b3IgPSB0aGlzLiRmb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnemlwQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVaaXBDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdCAgICB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuWmlwQ29kZSk7XG5cdFxuXHQgICAgaWYgKHRoaXMudmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmIHRoaXMuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScpID09PSAnZm9ybScgJiYgIXRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHQgICAgfVxuXHRcdHRoaXMuJGNvbnRhaW5lci5zaG93KCk7XG5cdCAgICBcblx0ICAgIHRoaXMuJGZvcm0ub2ZmKCdjbGljay5BcHBseScpLm9uKCdjbGljay5BcHBseScsICcuYnRuLnN0b3JlLXNlYXJjaDpub3QoW2xvYWRpbmddKScsICcuYnRuLnN0b3JlLXNlYXJjaDpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHQgICAgXHQkKCcuYm9waXMtc3RvcmUtc2VhcmNoJykuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHQgICAgXHRzZWxmLiRjb250YWluZXIudHJpZ2dlcignTG9jYXRpb25TZWFyY2guRm9ybVN1Ym1pdCcpO1xuXHQgICAgfSk7XG5cdCAgICBcblx0ICAgIHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkRpYWxvZ0Nsb3NlJykub24oJ2NsaWNrLkRpYWxvZ0Nsb3NlJywgJy5jbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHQgICAgXHQkKCcuYm9waXMtc3RvcmUtc2VhcmNoJykuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHRcdFx0JCgnLmxvY2F0aW9uLXNlYXJjaC1kaWFsb2cnKS5oaWRlKCk7XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgdGhpcy4kY29udGFpbmVyLm9mZignTG9jYXRpb25TZWFyY2guRm9ybVN1Ym1pdCcpLm9uKCdMb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdCAgICAgICAgc2VsZi4kZXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0ICAgICAgICBpZiAoVXJscyAmJiBVcmxzLkJvcGlzLkdldExvY2F0aW9uc0ZvclBvc3RhbENvZGUgJiYgc2VsZi52YWxpZGF0b3IudmFsaWQoKSAmJiBzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpKSB7XG5cdFx0XHRcdHNlbGYuZGF0YUJ1ZmZlci5sb2FkTW9yZSA9ICdwb3N0YWxDb2RlJztcblx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyLm9mZnNldCA9IDA7XG5cdFx0XHRcdHNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uLmxvYWRpbmcoKTtcblx0XHRcdFx0c2VsZi4kcmVzdWx0Lmh0bWwoJycpO1xuXHRcdFx0XHRzZWxmLiRyZXN1bHQubG9hZGluZygpO1xuXHRcdFx0XHRzZWxmLmdldFN0b3JlTGlzdEZvclBvc3RhbENvZGUoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdCAgICBcblx0ICAgIHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLlNlbGVjdFN0b3JlJykub24oJ2NsaWNrLlNlbGVjdFN0b3JlJywgJy5idG4uc2VsZWN0LXN0b3JlOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHQkKHRoaXMpLmxvYWRpbmcoe1xuXHRcdFx0XHRDb250ZW50OiAnPGg2PkhvbGQgWW91ciBIb3JzZXMhPC9oNj48cD5Zb3VyIHNlbGVjdGlvbnMgYXJlIGxvYWRpbmcuLi48L3A+Jyxcblx0XHRcdFx0Q3NzQ2xhc3M6ICdib290YmFybmV4cHJlc3MnLFxuXHRcdFx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0XHRcdH0pO1xuXHQgICAgfSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5TZWxlY3RTdG9yZScpLm9uKCdjbGljay5TZWxlY3RTdG9yZScsICcuYnRuLnNldC1teS1zdG9yZTpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdHZhciAkc3RvcmVJbnB1dCA9ICR0aGlzLmNsb3Nlc3QoJ2xpJykuZmluZCgnaW5wdXQnKTtcblx0XHRcdHZhciBzdG9yZUlkO1xuXHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHRcdFx0aWYgKCRzdG9yZUlucHV0ICYmICRzdG9yZUlucHV0Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0c3RvcmVJZCA9ICRzdG9yZUlucHV0LnZhbCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoc3RvcmVJZCkge1xuXHRcdFx0XHRzZWxmLnVwZGF0ZVN0b3JlRGV0YWlscyhzdG9yZUlkKTtcblx0XHRcdH1cblx0ICAgIH0pO1xuXHQgICAgXG5cdCAgICB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLm9mZigna2V5cHJlc3MuTG9jYXRpb25TZWFyY2guRm9ybVN1Ym1pdCcpLm9uKCdrZXlwcmVzcy5Mb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGlmIChldmVudC5rZXkgPT0gJ0VudGVyJykge1xuXHQgICAgXHRcdHNlbGYuJGNvbnRhaW5lci50cmlnZ2VyKCdMb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0Jyk7XG5cdCAgICBcdFx0cmV0dXJuIGZhbHNlO1xuXHQgICAgXHR9XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2tleWRvd24uTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNoZWNrJykub24oJ2tleWRvd24uTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGlmIChzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLmxlbmd0aCA9PSA1ICYmIHBhcnNlSW50KGV2ZW50LmtleSwgMTApID09IGV2ZW50LmtleSAmJiAhd2luZG93LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCkpIHtcblx0ICAgIFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHQkKGRvY3VtZW50KS5maW5kKCcuYm9waXMtc3RvcmUtc2VhcmNoJykuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHQgICAgfSk7XG5cdCAgICBcblx0ICAgIFxuXHQgICAgdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2NoYW5nZS5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbignY2hhbmdlLkxvY2F0aW9uU2VhcmNoLlZhbGlkYXRpb25DaGVjaycsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgXHRpZiAoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5sZW5ndGggPiA1KSB7XG5cdCAgICBcdFx0c2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5zdWJzdHIoMCwgNSkpO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHQkKGRvY3VtZW50KS5maW5kKCcuYm9waXMtc3RvcmUtc2VhcmNoJykuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHQgICAgfSk7XG5cdCAgICBcblx0ICAgIHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXl1cC5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2ssIGNoYW5nZS5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbigna2V5dXAuTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNoZWNrLCBjaGFuZ2UuTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHQgICAgXHRcblx0XHRcdGlmICgkY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJykge1xuXHRcdFx0XHRpZiAoc2VsZi52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgIXNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHRcdFx0c2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uYWRkQ2xhc3MoJ3JlYWR5JykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHRcdFx0fSBlbHNlIGlmICghc2VsZi52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgc2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0XHRzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5yZW1vdmVDbGFzcygncmVhZHknKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNsZWFyJykub24oJ21vdXNlZG93bi5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2xlYXInLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgICAgICBpZiAoc2VsZi52YWxpZGF0b3IgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3Qoc2VsZi4kY29udGFpbmVyKS5sZW5ndGggPT0gMCkge1xuXHQgICAgICAgICAgICBzZWxmLiRlcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHQgICAgICAgIH1cblx0ICAgIH0pO1xuXHQgXG5cdCAgICB0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Mb2NhdGlvblNlYXJjaC5SZXNldCcpLm9uKCdjbGljay5Mb2NhdGlvblNlYXJjaC5SZXNldCcsICcucmVzZXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgIFx0c2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoJycpO1xuXHQgICAgICAgIHNlbGYuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdCAgICAgICAgc2VsZi4kc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQ2xhc3MoJ3JlYWR5JykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0ICAgICAgICAkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHQgICAgICAgIHNlbGYuJGJvcGlzQnV0dG9uLnJlbW92ZUNsYXNzKCdyZWFkeScpO1xuXHQgICAgfSk7XG4gICBcblx0ICAgIHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkxvY2F0aW9uU2VhcmNoLlNlbGVjdGlvbicpLm9uKCdjbGljay5Mb2NhdGlvblNlYXJjaC5TZWxlY3Rpb24nLCAnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgICAgICB2YXIgYm9waXNTdG9yZSA9ICQoJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0ICAgICAgICBcblx0ICAgICAgICBpZiAoIXNlbGYuJGJvcGlzQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdCAgICAgICAgXHRzZWxmLiRib3Bpc0J1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcblx0ICAgICAgICB9XG5cblx0XHRcdGlmIChzZWxmLiRzdG9yZVNlbGVjdEJ1dHRvbi5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHNlbGYuJHN0b3JlU2VsZWN0QnV0dG9uLmF0dHIoJ2hyZWYnLCBVcmxzLnN0b3JlTGFuZGluZ1BhZ2UgKyAnP1N0b3JlPScgKyBib3Bpc1N0b3JlKS5hZGRDbGFzcygncmVhZHknKTs7IFxuXHRcdFx0fVxuXHQgICAgICAgIFxuXHQgICAgICAgICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG5cdCAgICAgICAgXG5cdCAgICAgICAgaWYgKGJvcGlzU3RvcmUpIHtcblx0ICAgICAgICBcdHNlbGYuJGJvcGlzQnV0dG9uLmF0dHIoJ3N0YXRlJywgJ3BpY2t1cCcpO1xuXHQgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgXHRzZWxmLiRib3Bpc0J1dHRvbi5hdHRyKCdzdGF0ZScsICdzaGlwJyk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Vc2VNeUxvY2F0aW9uJykub24oJ2NsaWNrLlVzZU15TG9jYXRpb24nLCAnLnVzZS1teS1sb2NhdGlvbicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHNlbGYuZ2VvbG9jYXRpb25TZWFyY2goKTtcblx0XHR9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9mZignTG9jYXRpb25TZWFyY2guR2VvbG9jYXRpb25TZWFyY2gnKS5vbignTG9jYXRpb25TZWFyY2guR2VvbG9jYXRpb25TZWFyY2gnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHNlbGYuZ2VvbG9jYXRpb25TZWFyY2goKTtcblx0XHR9KTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkxvYWRNb3JlJykub24oJ2NsaWNrLkxvYWRNb3JlJywgJy5sb2FkLW1vcmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdCQodGhpcykubG9hZGluZyh7IElzTGFiZWxTaG93bjogZmFsc2UgfSk7XG5cdFx0XHRzZWxmLmRhdGFCdWZmZXIub2Zmc2V0ICs9IHNlbGYuZGF0YUJ1ZmZlci5saW1pdDtcblx0XHRcdGlmIChzZWxmLmRhdGFCdWZmZXIubG9hZE1vcmUgPT0gJ2dlb2xvY2F0aW9uUG9zaXRpb24nKSB7XG5cdFx0XHRcdHNlbGYuZ2V0U3RvcmVMaXN0Rm9yR2VvbG9jYXRpb25Qb3NpdGlvbihzZWxmLmRhdGFCdWZmZXIuZ2VvbG9jYXRpb25Qb3NpdGlvbiwgdHJ1ZSk7XG5cdFx0XHR9IGVsc2UgaWYgKHNlbGYuZGF0YUJ1ZmZlci5sb2FkTW9yZSA9PSAncG9zdGFsQ29kZScpIHtcblx0XHRcdFx0c2VsZi5nZXRTdG9yZUxpc3RGb3JQb3N0YWxDb2RlKHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCksIHRydWUpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dGhpcy5nZW9sb2NhdGlvblNlYXJjaCA9IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRzZWxmLmRhdGFCdWZmZXIubG9hZE1vcmUgPSAnZ2VvbG9jYXRpb25Qb3NpdGlvbic7XG5cdFx0c2VsZi5kYXRhQnVmZmVyLm9mZnNldCA9IDA7XG5cdFx0dGhpcy4kcmVzdWx0Lmh0bWwoJycpO1xuXHRcdHRoaXMuJHJlc3VsdC5sb2FkaW5nKCk7XG5cdFx0R2VvbG9jYXRpb25IZWxwZXIuR2V0UG9zaXRpb24oKS50aGVuKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0XHRzZWxmLmRhdGFCdWZmZXIuZ2VvbG9jYXRpb25Qb3NpdGlvbiA9IHBvc2l0aW9uO1xuXHRcdFx0c2VsZi5nZXRTdG9yZUxpc3RGb3JHZW9sb2NhdGlvblBvc2l0aW9uKHNlbGYuZGF0YUJ1ZmZlci5nZW9sb2NhdGlvblBvc2l0aW9uKTtcblx0XHR9KS5jYXRjaChmdW5jdGlvbigpIHtcblx0XHRcdGlmIChzZWxmLiRyZXN1bHQuYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHRcdHNlbGYuJHJlc3VsdC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHR0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdHRoaXMudmFsaWRhdG9yLmRlc3Ryb3koKTtcblx0XHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHR9XG5cdFxuXHR0aGlzLmdldFN0b3JlTGlzdEZvckdlb2xvY2F0aW9uUG9zaXRpb24gPSBmdW5jdGlvbihwb3NpdGlvbiwgaXNMb2FkTW9yZSkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgZ2VvbG9jYXRpb25Qb3NpdGlvbjtcblx0XHRpZiAocG9zaXRpb24gJiYgcG9zaXRpb24uY29vcmRzKSB7XG5cdFx0XHRnZW9sb2NhdGlvblBvc2l0aW9uID0ge1xuXHRcdFx0XHRjb29yZHM6IHtcblx0XHRcdFx0XHRhY2N1cmFjeTogcG9zaXRpb24uY29vcmRzLmFjY3VyYWN5LFxuXHRcdFx0XHRcdGxhdGl0dWRlOiBwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGUsXG5cdFx0XHRcdFx0bG9uZ2l0dWRlOiBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRpbWVzdGFtcDogcG9zaXRpb24udGltZXN0YW1wXG5cdFx0XHR9O1xuXHRcdH1cblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuQm9waXMuR2V0TG9jYXRpb25zRm9yR2VvbG9jYXRpb25Qb3NpdGlvbixcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdENoYW5uZWw6IHRoaXMub3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRTb3VyY2U6IHRoaXMub3B0aW9ucy5Tb3VyY2UsXG5cdFx0XHRcdEdlb2xvY2F0aW9uUG9zaXRpb246IGdlb2xvY2F0aW9uUG9zaXRpb24sXG5cdFx0XHRcdFJhZGl1czogcGFyc2VGbG9hdCh0aGlzLiRmb3JtSW5wdXRSYWRpdXMudmFsKCkpIHx8IDMwMDAsXG5cdFx0XHRcdExpbWl0OiB0aGlzLmRhdGFCdWZmZXIubGltaXQsXG5cdFx0XHRcdE9mZnNldDogdGhpcy5kYXRhQnVmZmVyLm9mZnNldFxuXHRcdFx0fSksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRzZWxmLnJlbmRlclN0b3JlTGlzdChkYXRhLCBpc0xvYWRNb3JlKTtcblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFxuXHRcdFx0fVxuXHRcdH0pO1x0XHRcblx0fVxuXG5cdHRoaXMuZ2V0U3RvcmVMaXN0Rm9yUG9zdGFsQ29kZSA9IGZ1bmN0aW9uKHBvc3RhbENvZGUsIGlzTG9hZE1vcmUpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLkJvcGlzLkdldFN0b3Jlc0J5Q2l0eVN0YXRlUG9zdGFsU2VhcmNoS2V5QWpheCxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdENoYW5uZWw6IHNlbGYub3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRTb3VyY2U6IHNlbGYub3B0aW9ucy5Tb3VyY2UsXG5cdFx0XHRcdFNlYXJjaEtleTogcG9zdGFsQ29kZSxcblx0XHRcdFx0UmFkaXVzOiBzZWxmLiRmb3JtSW5wdXRSYWRpdXMudmFsKCkgfHwgMzAwMCxcblx0XHRcdFx0TGltaXQ6IHNlbGYuZGF0YUJ1ZmZlci5saW1pdCxcblx0XHRcdFx0T2Zmc2V0OiBzZWxmLmRhdGFCdWZmZXIub2Zmc2V0XG5cdFx0XHR9KSxcblx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdHNlbGYucmVuZGVyU3RvcmVMaXN0KGRhdGEsIGlzTG9hZE1vcmUpO1xuXHRcdFx0fSxcblx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG5cdFx0XHRcdFx0c2VsZi5vcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dGhpcy5yZW5kZXJTdG9yZUxpc3QgPSBmdW5jdGlvbihkYXRhLCBpc0xvYWRNb3JlKSB7XG5cdFx0dmFyIGxvY2F0aW9uRGF0YTtcblx0XHRpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhLmxlbmd0aCA+IDApIHtcblx0XHRcdGxvY2F0aW9uRGF0YSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhO1xuXHRcdH1cblxuXHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdyZXN1bHQnKTtcblx0XHRpZiAobG9jYXRpb25EYXRhICYmIGxvY2F0aW9uRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHR2YXIgbG9jYXRpb25zRGlzcGxheWVkID0gMDtcblx0XHRcdGxvY2F0aW9uRGF0YSA9IGxvY2F0aW9uRGF0YS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG5cdFx0XHRcdHJldHVybiBsZWZ0LmRpc3RhbmNlIC0gcmlnaHQuZGlzdGFuY2U7XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXSA9IFtdO1xuXHRcdFx0dGhpcy4kY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsIGxvY2F0aW9uRGF0YS5sZW5ndGgpO1xuXHRcdFx0XG5cdFx0XHR2YXIgc3RvcmVMaXN0SHRtbCA9ICcnO1xuXHRcdFx0Zm9yICh2YXIgbG9jYXRpb25FbGVtZW50IGluIGxvY2F0aW9uRGF0YSkge1xuXHRcdFx0XHR2YXIgbG9jYXRpb24gPSBsb2NhdGlvbkRhdGFbbG9jYXRpb25FbGVtZW50XTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChsb2NhdGlvbiAmJiAhdGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtsb2NhdGlvbi5jb2RlXSkge1xuXHRcdFx0XHRcdHZhciBzdG9yZVBob25lID0gJyc7XG5cdFx0XHRcdFx0dmFyIHN0b3JlT3BlblVudGlsID0gJyc7XG5cdFx0XHRcdFx0aWYgKGxvY2F0aW9uLlN0b3JlSW5mbykge1xuXHRcdFx0XHRcdFx0aWYgKGxvY2F0aW9uLlN0b3JlSW5mby5QaG9uZSkge1xuXHRcdFx0XHRcdFx0XHRzdG9yZVBob25lID0gbG9jYXRpb24uU3RvcmVJbmZvLlBob25lO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKGxvY2F0aW9uLlN0b3JlSW5mby5PcGVuVW50aWwpIHtcblx0XHRcdFx0XHRcdFx0c3RvcmVPcGVuVW50aWwgPSBsb2NhdGlvbi5TdG9yZUluZm8uT3BlblVudGlsO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciBsb2NhdGlvbk5hbWU7XG5cdFx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uTmFtZSA9ICc8c3Ryb25nPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uTmFtZSArICcgLSAnICsgbG9jYXRpb24uU3RvcmVJbmZvLlN0b3JlSWQgKyAnPC9zdHJvbmc+Jztcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0bG9jYXRpb25OYW1lID0gJzxzdHJvbmc+JyArIGxvY2F0aW9uLlN0b3JlSW5mby5OYW1lICsgJzwvc3Ryb25nPic7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLkFnZW50U3RvcmVJRCA9PSBsb2NhdGlvbi5jb2RlKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbk5hbWUgKz0gJzxici8+KFlvdXIgU3RvcmUpJztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIGh0bWwgPSBsb2NhdGlvbk5hbWUgKyAnPGJyLz4nICtcblx0XHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5TdG9yZUluZm8uQWRkcmVzczEgKyAnPGJyIC8+JyArIFxuXHRcdFx0XHRcdFx0XHRcdGxvY2F0aW9uLlN0b3JlSW5mby5DaXR5ICsgJywgJyArIGxvY2F0aW9uLlN0b3JlSW5mby5TdGF0ZUNvZGVQYXJzZWQgKyAnICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uUG9zdGFsQ29kZS5zdWJzdHIoMCwgNSkgKyAnPGJyIC8+JyArXG5cdFx0XHRcdFx0XHRcdFx0c3RvcmVQaG9uZTtcblx0XHRcdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZUlkID09IFNpdGVDb25zdGFudHMuQm9vdEJhcm5Sc3BVUyAmJiBzdG9yZU9wZW5VbnRpbCkge1xuXHRcdFx0XHRcdFx0aHRtbCArPSAnPGJyIC8+JyArIHN0b3JlT3BlblVudGlsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHN0b3JlTGlzdEh0bWwgKz0gdGhpcy5yZXN1bHRJdGVtVGVtcGxhdGUoe1xuXHRcdFx0XHRcdFx0U3RvcmVJZDogbG9jYXRpb24uY29kZSxcblx0XHRcdFx0XHRcdERpc3RhbmNlOiBsb2NhdGlvbi5TdG9yZUluZm8uRGlzdGFuY2UudG9GaXhlZCgxKSArICc8YnIvPm1pJyxcblx0XHRcdFx0XHRcdFNlbGVjdGVkOiAnJyxcblx0XHRcdFx0XHRcdExhbmRpbmdDYXRlZ29yeTogdGhpcy5vcHRpb25zLkxhbmRpbmdDYXRlZ29yeSxcblx0XHRcdFx0XHRcdFN0YXR1c0Rpc3BsYXk6IHN0b3JlT3BlblVudGlsLFxuXHRcdFx0XHRcdFx0SHRtbDogaHRtbFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRsb2NhdGlvbnNEaXNwbGF5ZWQrKztcblx0XHRcdFx0aWYgKGxvY2F0aW9uc0Rpc3BsYXllZCA+PSB0aGlzLmRhdGFCdWZmZXIubGltaXQpIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLmRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2xvY2F0aW9uLmNvZGVdID0gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0dmFyIHJlc3VsdEh0bWwgPSB0aGlzLnJlc3VsdENvbnRhaW5lclRlbXBsYXRlKHtcblx0XHRcdFx0SHRtbDogc3RvcmVMaXN0SHRtbFxuXHRcdFx0fSk7XG5cdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZUlkID09IFNpdGVDb25zdGFudHMuQm9vdEJhcm5Sc3BVUyAmJiBkYXRhLklucXVpcnlSZXN1bHQubWV0YS5wYWdlIDwgZGF0YS5JbnF1aXJ5UmVzdWx0Lm1ldGEucGFnZXMpIHtcblx0XHRcdFx0cmVzdWx0SHRtbCArPSAnPGEgaHJlZj1cIiNcIiBjbGFzcz1cImxvYWQtbW9yZVwiPkxvYWQgTW9yZTwvYT4nO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy4kcmVzdWx0LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRyZXN1bHQubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGlzTG9hZE1vcmUpIHtcblx0XHRcdFx0dGhpcy4kcmVzdWx0LmZpbmQoJy5sb2FkLW1vcmUnKS5yZW1vdmUoKTtcblx0XHRcdFx0dGhpcy4kcmVzdWx0LmFwcGVuZChyZXN1bHRIdG1sKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuJHJlc3VsdC5odG1sKHJlc3VsdEh0bWwpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoIWlzTG9hZE1vcmUpIHtcblx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCAnMCcpO1xuXHRcdFx0dGhpcy4kcmVzdWx0Lmh0bWwoJycpO1xuXHRcdH1cblx0fVxuXG5cdHRoaXMudXBkYXRlU3RvcmVEZXRhaWxzID0gZnVuY3Rpb24oc3RvcmVJZCkge1xuXHRcdGlmIChzdG9yZUlkKSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiBVcmxzLlN0b3Jlcy5TZXRNeVN0b3JlLFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0U3RvcmVJZDogc3RvcmVJZFxuXHRcdFx0XHR9KSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdCQoJy5teS1zdG9yZS1wYW5lbCcpLnJlcGxhY2VXaXRoKGRhdGEpO1xuXHRcdFx0XHRcdCQoJy5teS1zdG9yZS1tb2RhbCcpLmhpZGUoKTtcblx0XHRcdFx0XHQkKCcubG9jYXRpb24tc2VhcmNoLWRpYWxvZycpLmhpZGUoKTtcblxuXHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdFx0XHRcdFx0dXJsOiBVcmxzLlN0b3Jlcy5HZXRNeVN0b3JlUGFuZWwsXG5cdFx0XHRcdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0XHQkKCcubXktc3RvcmUtcGFuZWwnKS5yZXBsYWNlV2l0aChkYXRhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdFx0XHRcdFx0dXJsOiBVcmxzLlN0b3Jlcy5HZXRNeVN0b3JlTW9kYWwsXG5cdFx0XHRcdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0XHQkKCcubXktc3RvcmUtbW9kYWwnKS5yZXBsYWNlV2l0aChkYXRhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdFx0XHRcdFx0dXJsOiBVcmxzLmdldFN0b3Jlc1BhbmVsLFxuXHRcdFx0XHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdFx0JCgnI2xvY2F0aW9uJykuaHRtbChkYXRhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Nob3BNeVN0b3JlLlVwZGF0ZScsIHN0b3JlSWQpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCgnLm15LXN0b3JlLW1vZGFsJykuaGlkZSgpO1xuXHRcdFx0XHRcdCQoJy5sb2NhdGlvbi1zZWFyY2gtZGlhbG9nJykuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLmFzc2lnblN0b3JlSWQgPSBmdW5jdGlvbihzdG9yZUlkKSB7XG5cdFx0aWYgKHN0b3JlSWQpIHtcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHVybCA6IFVybHMuYXNzaWduU3RvcmVJZCxcblx0XHRcdFx0ZGF0YSA6IHsgc3RvcmVfaWQgOiBzdG9yZUlkIH0sXG5cdFx0XHRcdG1ldGhvZCA6IFwiUE9TVFwiLFxuXHRcdFx0XHRkYXRhVHlwZSA6IFwiSlNPTlwiLFxuXHRcdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmICgnc3VjY2VzcycgaW4gZGF0YSAmJiBkYXRhWydzdWNjZXNzJ10gPT0gdHJ1ZSkge1xuXHRcdFx0XHRcdFx0Ly8gVE9ETzogYW55IGZvbGxvdy11cCBuZWVkZWQgY2xpZW50LXNpZGU/XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblx0XG5cdHJldHVybiB0aGlzO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlZhbGlkYXRlUHJvZHVjdExpbmVJdGVtcyA9IHZhbGlkYXRlUHJvZHVjdExpbmVJdGVtcztcblxudmFyIG9wdGlvbnM7XG52YXIgYnVmZmVyID0ge307XG5cbmZ1bmN0aW9uIHZhbGlkYXRlUHJvZHVjdExpbmVJdGVtcygkYm9waXNQcm9kdWN0TGluZUl0ZW1zLCBvcHRpb25zUGFyYW1ldGVyKSB7XG5cdGlmIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdFx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdH1cblx0XG5cdGJ1ZmZlclsnVG90YWxDb3VudCddID0gJGJvcGlzUHJvZHVjdExpbmVJdGVtcy5sZW5ndGg7XG5cdGJ1ZmZlclsnTG9hZGVkQ291bnQnXSA9IDA7XG5cdGJ1ZmZlclsnUHJvZHVjdExpbmVJdGVtcyddID0ge307XG5cdFxuXHQkYm9waXNQcm9kdWN0TGluZUl0ZW1zLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciB1dWlkID0gJHRoaXMuYXR0cigndXVpZCcpO1xuXHRcdHZhciBwcm9kdWN0SWQgPSAkdGhpcy5hdHRyKCdza3UnKTtcblx0XHR2YXIgc3RvcmVJZCA9ICR0aGlzLmF0dHIoJ3N0b3JlJyk7XG5cdFx0dmFyIHF1YW50aXR5UmVxdWVzdGVkID0gJHRoaXMuY2xvc2VzdCgnLm9yZGVyLWl0ZW0nKS5maW5kKCcucXR5LWVkaXQgaW5wdXRbdHlwZT1cInRleHRcIl0nKS52YWwoKTtcblx0XHRcblx0XHQkLmFqYXgoe1xuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6IFVybHMuQm9waXMuR2V0U3RvcmVJbnZlbnRvcnlGb3JQcm9kdWN0Rm9yU3RvcmUsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgYXN5bmM6IHRydWUsXG4gICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgUHJvZHVjdElkOiBwcm9kdWN0SWQsXG4gICAgICAgICAgICAgICAgU3RvcmVJZDogc3RvcmVJZFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBpbnF1aXJ5UmVzdWx0O1xuICAgICAgICAgICAgICAgIGlmIChkYXRhICYmIGRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCAmJiBkYXRhLklucXVpcnlSZXN1bHQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucXVpcnlSZXN1bHQgPSBkYXRhLklucXVpcnlSZXN1bHQuZGF0YVswXS5pbnZlbnRvcnlfc3VwcGxpZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGlmIChpbnF1aXJ5UmVzdWx0ICYmIGlucXVpcnlSZXN1bHQgJiYgaW5xdWlyeVJlc3VsdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgXHRidWZmZXJbJ1Byb2R1Y3RMaW5lSXRlbXMnXVt1dWlkXSA9IHtcbiAgICAgICAgICAgICAgICBcdFx0UXVhbnRpdHlSZXF1ZXN0ZWQ6IHBhcnNlSW50KHF1YW50aXR5UmVxdWVzdGVkLCAxMCksXG4gICAgICAgICAgICAgICAgXHRcdElucXVpcnlSZXN1bHQ6IGlucXVpcnlSZXN1bHRcbiAgICAgICAgICAgICAgICBcdH07XG4gICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyWydMb2FkZWRDb3VudCddICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlUHJvZHVjdExpbmVJdGVtc1N1Y2Nlc3MoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFx0JHJlc3VsdC5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLkVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cdH0pO1xuXHRcblx0cmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXNTdWNjZXNzKCkge1xuXHRpZiAoYnVmZmVyWydMb2FkZWRDb3VudCddID09IGJ1ZmZlclsnVG90YWxDb3VudCddKSB7XG5cdFx0dmFyIGlzQm9waXNJbnZlbnRvcnlWYWxpZCA9IHRydWU7XG5cdFx0Zm9yICh2YXIgcHJvZHVjdExpbmVJdGVtVVVJRCBpbiBidWZmZXJbJ1Byb2R1Y3RMaW5lSXRlbXMnXSkge1xuXHRcdFx0dmFyIHByb2R1Y3RMaW5lSXRlbVx0PSBidWZmZXJbJ1Byb2R1Y3RMaW5lSXRlbXMnXVtwcm9kdWN0TGluZUl0ZW1VVUlEXTtcblx0XHRcdFxuXHRcdFx0aWYgKHByb2R1Y3RMaW5lSXRlbS5RdWFudGl0eVJlcXVlc3RlZCA+IHByb2R1Y3RMaW5lSXRlbS5JbnF1aXJ5UmVzdWx0WzBdLmRldGFpbC5xdWFudGl0eSkge1xuXHRcdFx0XHRpc0JvcGlzSW52ZW50b3J5VmFsaWQgPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5TdWNjZXNzRXZlbnQpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIob3B0aW9ucy5TdWNjZXNzRXZlbnQsIHtcblx0XHRcdFx0U3VibWl0UGF5bWVudEZvckJvcGlzOiB0cnVlLFxuXHRcdFx0XHRJc0JvcGlzSW52ZW50b3J5VmFsaWQ6IGlzQm9waXNJbnZlbnRvcnlWYWxpZFxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vZGlhbG9nJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0ZGF0YUJ1ZmZlciA9IHt9O1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXG5cdCQoJyNzaG9wLXlvdXItc3RvcmUtZGlhbG9nJykuZmluZCgnLnN0b3JlLW5hbWUnKS50ZXh0KG9wdGlvbnMuU3RvcmVOYW1lKTtcblx0JCgnI3Nob3AteW91ci1zdG9yZS1kaWFsb2cnKS5maW5kKCcuY2F0ZWdvcnktbGlua3MgYScpLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBocmVmID0gJHRoaXMuYXR0cignaHJlZicpO1xuXHRcdGlmIChocmVmLmluZGV4T2YoJz8nKSA+IC0xKSB7XG5cdFx0XHRocmVmID0gaHJlZi5zdWJzdHIoMCwgaHJlZi5pbmRleE9mKCc/JykpO1xuXHRcdH1cblx0XHQkdGhpcy5hdHRyKCdocmVmJywgaHJlZiArICc/cHJlZm4xPWF2YWlsYWJsZVN0b3JlcyZwcmVmdjE9JyArIG9wdGlvbnMuU3RvcmVJZCArICcmc2hvcG15c3RvcmU9dHJ1ZScpO1xuXHR9KVxuXHRcblx0Ly8gR29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRXZlbnQoJ3JvYWRpZUZvcm1EaXNwbGF5Jyk7XG5cdGRpYWxvZy5vcGVuKHtcblx0XHRodG1sOiAkKCcjc2hvcC15b3VyLXN0b3JlLWRpYWxvZycpLmh0bWwoKSxcblx0XHRvcHRpb25zOiB7XG5cdFx0XHRkaWFsb2dDbGFzczogJ3Nob3AteW91ci1zdG9yZS1kaWFsb2cnLFxuXHRcdFx0d2lkdGg6IDM4MCxcblx0XHRcdGRyYWdnYWJsZTogZmFsc2UsXG5cdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0b3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciAkc2hvcFlvdXJTdG9yZVRvZ2dsZSA9ICR0aGlzLmZpbmQoJy5zaG9wLW15LXN0b3JlLXRvZ2dsZSAuY2hlY2tib3gtdG9nZ2xlJyk7XG5cdFx0XHRcdGRhdGFCdWZmZXJbJ3RvZ2dsZVRpbWVyJ10gPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkc2hvcFlvdXJTdG9yZVRvZ2dsZS5jbGljaygpO1xuXHRcdFx0XHR9LCAyMDAwKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdGNsZWFySW50ZXJ2YWwoZGF0YUJ1ZmZlclsndG9nZ2xlVGltZXInXSk7XG5cdFx0XHRcdCQodGhpcykuZmluZCgnLnNob3AtbXktc3RvcmUtdG9nZ2xlIC5jaGVja2JveC10b2dnbGUgaW5wdXQnKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuICAgICAgICAgICAgfVxuXHRcdH1cblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBMb2NhbERlbGl2ZXJ5RGlhbG9nID0gcmVxdWlyZSgnLi9Mb2NhbERlbGl2ZXJ5RGlhbG9nJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKTtcbnZhciBWYWxpZGF0aW9uU2V0dGluZ3MgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5TZXR0aW5ncztcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFppcENvZGVUb1N0YXRlTWFwID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9kYXRhL1ppcENvZGVUb1N0YXRlTWFwLmpzb24nKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcbmV4cG9ydHMuc2VhcmNoID0gc2VhcmNoO1xuZXhwb3J0cy5yZW1vdmUgPSByZW1vdmU7XG5cbnZhciBvcHRpb25zO1xudmFyIHZhbGlkYXRvcjtcbnZhciBkYXRhQnVmZmVyO1xuXG52YXIgcmVzdWx0Q29udGFpbmVyVGVtcGxhdGU7XG52YXIgcmVzdWx0SXRlbVRlbXBsYXRlO1xudmFyIGxvY2FsRGVsaXZlcnlEZWNvcmF0b3I7XG5cbnZhciAkY29udGFpbmVyO1xudmFyICRmb3JtO1xudmFyICRyZXN1bHQ7XG52YXIgJGZvcm1JbnB1dFBvc3RhbENvZGU7XG52YXIgJHN0b3JlU2VhcmNoQnV0dG9uO1xudmFyICRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lcjtcbnZhciAkYm9waXNCdXR0b247XG52YXIgJGVycm9yTWVzc2FnZTtcbnZhciAkaW5wdXRUb29sdGlwO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCRjb250YWluZXJQYXJhbWV0ZXIsIG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0ZGF0YUJ1ZmZlciA9IHt9O1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXG5cdHJlc3VsdENvbnRhaW5lclRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWNvbnRhaW5lcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0cmVzdWx0SXRlbVRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWl0ZW0nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdGxvY2FsRGVsaXZlcnlEZWNvcmF0b3IgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1sb2NhbGRlbGl2ZXJ5LWRlY29yYXRvcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblxuXHQkY29udGFpbmVyID0gJGNvbnRhaW5lclBhcmFtZXRlcjtcblx0JGZvcm0gPSAkY29udGFpbmVyLmZpbmQoJ2Zvcm0nKTtcblx0JHJlc3VsdCA9ICRjb250YWluZXIuZmluZCgnLnJlc3VsdCcpO1xuXHQkZm9ybUlucHV0UG9zdGFsQ29kZSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbENvZGVcIl0nKTtcblx0JHN0b3JlU2VhcmNoQnV0dG9uID0gJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlYXJjaCcpO1xuXHQkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIgPSAkY29udGFpbmVyLmZpbmQoJy5idG4tc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpO1xuXHQkYm9waXNCdXR0b24gPSAkY29udGFpbmVyLmZpbmQoJy5idG4uYm9waXMnKTtcbiAgICAkZXJyb3JNZXNzYWdlID0gJGZvcm0uZmluZCgnc3Bhbi5lcnJvcicpO1xuXHQkaW5wdXRUb29sdGlwID0gJGZvcm1JbnB1dFBvc3RhbENvZGUucGFyZW50KCk7XG5cbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLklzVmFyaWFudFNlbGVjdGVkKSB7XG5cdFx0JCgnLmJ0bi5zdG9yZS1zZWFyY2gnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdCRpbnB1dFRvb2x0aXAucmVtb3ZlQ2xhc3MoJ3Rvb2x0aXAnKTtcbiAgICB9XG5cblx0dG9vbHRpcC5pbml0KHtcblx0XHRpdGVtczogJy5zdG9yZS1zZWFyY2gtdG9vbHRpcCcsXG5cdFx0dG9vbHRpcENsYXNzOiAnc3RvcmUtc2VhcmNoLXRvb2x0aXAnXG5cdH0sICQoJy5zdG9yZS1zZWFyY2gtdG9vbHRpcCcpKTtcblxuICAgICRjb250YWluZXIuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuICAgIHZhbGlkYXRvciA9ICRmb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ppcENvZGUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlWmlwQ29kZSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVEFMX0NPREUpO1xuICAgICRmb3JtSW5wdXRQb3N0YWxDb2RlLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuWmlwQ29kZSk7XG5cblx0aWYgKCRjb250YWluZXIuYXR0cignc3RhdGUnKSA9PT0gJ2Zvcm0nICYmIHZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAhJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0JHN0b3JlU2VhcmNoQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuICAgIH1cblxuICAgICRmb3JtLm9mZignY2xpY2suYXBwbHknKS5vbignY2xpY2suYXBwbHknLCAnLmJ0bi5zdG9yZS1zZWFyY2g6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNlYXJjaCgpO1xuXHR9KTtcblxuICAgICRjb250YWluZXIub2ZmKCdjbGljay5hcHBseScpLm9uKCdjbGljay5hcHBseScsICcuYnRuLmJvcGlzOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciBzZWxlY3RlZExvY2F0aW9uID0gZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ11bJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpLnZhbCgpXTtcblx0XHRpZiAoc2VsZWN0ZWRMb2NhdGlvbikge1xuXHRcdFx0aWYgKG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5FbmFibGVkKSB7XG5cdFx0XHRcdExvY2FsRGVsaXZlcnlEaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCBzZWxlY3RlZExvY2F0aW9uKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIHsgYm9waXM6IHRydWUsIHNoaXBwaW5nT3B0aW9uOiAncGlja3VwJywgY2hhbm5lbDogb3B0aW9ucy5DaGFubmVsIH0pO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCB7IGNoYW5uZWw6IG9wdGlvbnMuQ2hhbm5lbCB9KTtcblx0XHR9XG5cdH0pO1xuXG4gICAgJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXlkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJykub24oJ2tleWRvd24uQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBcdGlmICgkZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5sZW5ndGggPT0gNSAmJiBwYXJzZUludChldmVudC5rZXksIDEwKSA9PSBldmVudC5rZXkgJiYgIXdpbmRvdy5nZXRTZWxlY3Rpb24oKS50b1N0cmluZygpKSB7XG4gICAgXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHR9XG4gICAgfSk7XG5cbiAgICAkZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2NoYW5nZS5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBcdGlmICgkZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5sZW5ndGggPiA1KSB7XG4gICAgXHRcdCRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgkZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5zdWJzdHIoMCwgNSkpO1xuICAgIFx0fVxuICAgIH0pO1xuXG4gICAgJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXl1cC5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaywgY2hhbmdlLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJykub24oJ2tleXVwLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrLCBjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXG5cdFx0aWYgKCRjb250YWluZXIuYXR0cignc3RhdGUnKSA9PT0gJ2Zvcm0nKSB7XG5cdFx0XHRpZiAodmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICEkc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0JHN0b3JlU2VhcmNoQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHRcdFx0fSBlbHNlIGlmICghdmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICRzdG9yZVNlYXJjaEJ1dHRvbi5oYXNDbGFzcygncmVhZHknKSkge1xuXHRcdFx0XHQkc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQ2xhc3MoJ3JlYWR5Jyk7XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgXHRpZiAoJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScpID09PSAncmVzdWx0Jykge1xuXHRcdFx0JGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG4gICAgICAgIFx0JGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCcnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2xlYXInKS5vbignbW91c2Vkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNsZWFyJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICh2YWxpZGF0b3IgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJGNvbnRhaW5lcikubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHZhbGlkYXRvci5yZXNldEZvcm0oKTtcbiAgICAgICAgICAgICRlcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ0JvcGlzLlN0b3JlU2VhcmNoLlJlc2V0Jykub24oJ0JvcGlzLlN0b3JlU2VhcmNoLlJlc2V0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0cmVzZXQoKTtcbiAgICB9KTtcblxuICAgICRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlJlc2V0Jykub24oJ2NsaWNrLkJvcGlzU3RvcmVTZWFyY2guUmVzZXQnLCAnLnJlc2V0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0cmVzZXQoKTtcbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5TdG9yZVNlYXJjaCcpLm9uKCdQcm9kdWN0RGV0YWlsUGFnZS5WYXJpYW50LlN0b3JlU2VhcmNoJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChvcHRpb25zLlNlbGVjdGVkTG9jYXRpb25zKSB7XG5cdFx0XHR2YXIgc2l6ZVNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuc2l6ZS5zaXplLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKTtcblx0XHRcdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHRcdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHRcdHZhciBpc1NpemVTZWxlY3RlZCA9IHNpemVTZWxlY3RlZC5sZW5ndGggfHwgKGxlbmd0aFNlbGVjdGVkICYmIHdpZHRoU2VsZWN0ZWQpO1xuXHRcdFx0dmFyIGlzQ29sb3JTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cblx0XHRcdGlmIChpc1NpemVTZWxlY3RlZCAmJiBpc0NvbG9yU2VsZWN0ZWQpIHtcblx0XHRcdFx0c2VhcmNoKCk7XG5cdFx0XHR9XG5cdFx0fVxuICAgIH0pO1xuXG4gICAgJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvcGlzU3RvcmVTZWFyY2guU2VsZWN0aW9uJykub24oJ2NsaWNrLkJvcGlzU3RvcmVTZWFyY2guU2VsZWN0aW9uJywgJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBib3Bpc1N0b3JlID0gJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXG4gICAgICAgIGlmICghJGJvcGlzQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG4gICAgICAgIFx0JGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuICAgICAgICB9XG5cbiAgICAgICAgJCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cbiAgICAgICAgaWYgKGJvcGlzU3RvcmUpIHtcbiAgICAgICAgXHQkYm9waXNCdXR0b24uYXR0cignc3RhdGUnLCAncGlja3VwJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgIFx0JGJvcGlzQnV0dG9uLmF0dHIoJ3N0YXRlJywgJ3NoaXAnKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiByZXNldCgpIHtcblx0JGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCcnKTtcbiAgICAkY29udGFpbmVyLmF0dHIoJ3N0YXRlJywgJ2Zvcm0nKTtcbiAgICAkc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQ2xhc3MoJ3JlYWR5Jyk7XG4gICAgJCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgJGJvcGlzQnV0dG9uLnJlbW92ZUNsYXNzKCdyZWFkeScpO1xufVxuXG5mdW5jdGlvbiBzZWFyY2goKSB7XG5cdHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cdHZhciBpc0NvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXG4gICAgaWYgKCFpc1NpemVTZWxlY3RlZCAmJiAhaXNDb2xvclNlbGVjdGVkKSB7XG4gICAgXHQkZXJyb3JNZXNzYWdlLmh0bWwoJ1BsZWFzZSBzZWxlY3QgYSBzaXplIGFuZCBjb2xvciBmaXJzdC4nKS5zaG93KCk7XG4gICAgXHRyZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIGlmICghaXNTaXplU2VsZWN0ZWQpIHtcbiAgICBcdCRlcnJvck1lc3NhZ2UuaHRtbCgnUGxlYXNlIHNlbGVjdCBhIHNpemUgZmlyc3QuJykuc2hvdygpO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSBpZiAoIWlzQ29sb3JTZWxlY3RlZCkge1xuICAgIFx0JGVycm9yTWVzc2FnZS5odG1sKCdQbGVhc2Ugc2VsZWN0IGEgY29sb3IgZmlyc3QuJykuc2hvdygpO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgXHQkZXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICBcdCRzdG9yZVNlYXJjaEJ1dHRvbi5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgIH1cblxuICAgIGlmIChVcmxzICYmIFVybHMuQm9waXMuR2V0U3RvcmVJbnZlbnRvcnlGb3JQcm9kdWN0Rm9yUG9zdGFsQ29kZSAmJiB2YWxpZGF0b3IudmFsaWQoKSkge1xuICAgICAgICAkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIubG9hZGluZyh7XG4gICAgICAgICAgICBJc0ltYWdlU2hvd246IGZhbHNlLFxuXHRcdFx0TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkxvYWRpbmcsXG5cdFx0XHRCYWNrZ3JvdW5kQ29sb3I6ICRzdG9yZVNlYXJjaEJ1dHRvbi5jc3MoJ2JhY2tncm91bmQtY29sb3InKVxuICAgICAgICB9KTtcblxuXHRcdCQuYWpheCh7XG4gICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIHVybDogVXJscy5Cb3Bpcy5HZXRTdG9yZUludmVudG9yeUZvclByb2R1Y3RGb3JQb3N0YWxDb2RlLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0Q2hhbm5lbDogb3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRTb3VyY2U6IG9wdGlvbnMuU291cmNlLFxuICAgICAgICAgICAgICAgIFByb2R1Y3RJZDogJCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cInBpZFwiXScpLnZhbCgpLFxuICAgICAgICAgICAgICAgIFBvc3RhbENvZGU6ICRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdGlmICgkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIuYXR0cignbG9hZGluZycpKSB7XG4gICAgICAgICAgICAgICAgXHQkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgJCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5xdWlyeVJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhLmxlbmd0aCA+IDAgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucXVpcnlSZXN1bHQgPSBkYXRhLklucXVpcnlSZXN1bHQuZGF0YVswXS5pbnZlbnRvcnlfc3VwcGxpZXM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdyZXN1bHQnKTtcbiAgICAgICAgICAgICAgICBpZiAoaW5xdWlyeVJlc3VsdCAmJiBpbnF1aXJ5UmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBcdGRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddID0gW107XG4gICAgICAgICAgICAgICAgICAgICRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgaW5xdWlyeVJlc3VsdC5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBzdG9yZUxpc3RIdG1sID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc1N0b3JlU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkU3RvcmVBdHRyaWJ1dGU7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGludmVudG9yeVJlY29yZEVsZW1lbnQgaW4gaW5xdWlyeVJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBcdHZhciBpbnZlbnRvcnlSZWNvcmQgPSBpbnF1aXJ5UmVzdWx0W2ludmVudG9yeVJlY29yZEVsZW1lbnRdO1xuXG4gICAgICAgICAgICAgICAgICAgIFx0aWYgKGludmVudG9yeVJlY29yZC5kZXRhaWwgJiYgaW52ZW50b3J5UmVjb3JkLmRldGFpbC5xdWFudGl0eSA+IDAgJiYgIWRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSkge1xuICAgICAgICAgICAgICAgICAgICBcdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5TZWxlY3RlZExvY2F0aW9ucyA9PSBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24uY29kZSkge1xuICAgICAgICAgICAgICAgICAgICBcdFx0XHRpc1N0b3JlU2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBcdFx0XHRzZWxlY3RlZFN0b3JlQXR0cmlidXRlID0nY2hlY2tlZCc7XG4gICAgICAgICAgICAgICAgICAgIFx0XHR9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBcdFx0XHRzZWxlY3RlZFN0b3JlQXR0cmlidXRlID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIFx0XHR9XG5cbiAgICAgICAgICAgICAgICAgICAgXHRcdHZhciBsb2NhbERlbGl2ZXJ5SHRtbCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBcdFx0aWYgKG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5FbmFibGVkICYmIGlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uKSAmJiBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfZW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICBcdFx0XHRsb2NhbERlbGl2ZXJ5SHRtbCA9IGxvY2FsRGVsaXZlcnlEZWNvcmF0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgXHRcdH1cblxuXHRcdFx0XHRcdFx0XHR2YXIgbGFiZWxQcmVmaXg7XG5cdFx0XHRcdFx0XHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuSXNTdG9yZUhvbGlkYXkpIHtcblx0XHRcdFx0XHRcdFx0XHRsYWJlbFByZWZpeCA9ICdBdmFpbGFibGUgQXQgJztcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRsYWJlbFByZWZpeCA9ICdBdmFpbGFibGUgVE9EQVkgQXQgJztcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmIChpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ucG9zdGFsX2FkZHJlc3MubmFtZVByZWZpeCkge1xuXHRcdFx0XHRcdFx0XHRcdGxhYmVsUHJlZml4ICs9ICc8c3BhbiBjbGFzcz1cIm5vd3JhcFwiPicgKyBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ucG9zdGFsX2FkZHJlc3MubmFtZVByZWZpeCArICc8L3NwYW4+ICc7XG5cdFx0XHRcdFx0XHRcdH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgXHRzdG9yZUxpc3RIdG1sICs9IHJlc3VsdEl0ZW1UZW1wbGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdFx0U3RvcmVJZDogaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBcdFx0UXVhbnRpdHlBdmFpbGFibGU6IGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHksXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIFx0SHRtbDogbGFiZWxQcmVmaXggKyBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ucG9zdGFsX2FkZHJlc3MubmFtZSArICcsPGJyLz4nICsgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLmFkZHJlc3NfbGluZTEgKyAnLCAnICsgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLmNpdHkgKyAnLCAnICsgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLnByb3ZpbmNlX29yX3N0YXRlLFxuXHQgICAgICAgICAgICAgICAgICAgICAgICBcdFNlbGVjdGVkOiBzZWxlY3RlZFN0b3JlQXR0cmlidXRlLFxuXHQgICAgICAgICAgICAgICAgICAgICAgICBcdExvY2FsRGVsaXZlcnk6IGxvY2FsRGVsaXZlcnlIdG1sXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBcdH1cblxuICAgICAgICAgICAgICAgICAgICBcdGRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSA9IGludmVudG9yeVJlY29yZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzdG9yZUxpc3RIdG1sICs9IHJlc3VsdEl0ZW1UZW1wbGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIFx0U3RvcmVJZDogJycsXG4gICAgICAgICAgICAgICAgICAgIFx0UXVhbnRpdHlBdmFpbGFibGU6ICcnLFxuICAgICAgICAgICAgICAgICAgICBcdEh0bWw6ICdTaGlwIEluc3RlYWQnLFxuICAgICAgICAgICAgICAgICAgICBcdFNlbGVjdGVkOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgXHRMb2NhbERlbGl2ZXJ5OiAnJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0SHRtbCA9IHJlc3VsdENvbnRhaW5lclRlbXBsYXRlKHtcbiAgICAgICAgICAgICAgICAgICAgXHRIdG1sOiBzdG9yZUxpc3RIdG1sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1N0b3JlU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgXHQkYm9waXNCdXR0b24uYWRkQ2xhc3MoJ3JlYWR5Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAkcmVzdWx0Lmh0bWwocmVzdWx0SHRtbCk7XG5cblx0XHRcdFx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0ICAgICAgICBcdGl0ZW1zOiAnLnRvb2x0aXAnXG4gICAgICAgICAgICAgICAgXHR9LCAkcmVzdWx0KTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgXHRvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjayhpbnF1aXJ5UmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdFx0XHRcdFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgICAgICAgICAgICAgICAgICRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgJzAnKTtcbiAgICAgICAgICAgICAgICBcdCRyZXN1bHQuaHRtbCgnJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lci5hdHRyKCdsb2FkaW5nJykpIHtcbiAgICAgICAgICAgIFx0XHQkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSgpIHtcblx0dmFsaWRhdG9yLmRlc3Ryb3koKTtcblx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG59XG5cbmZ1bmN0aW9uIGlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMobG9jYXRpb24pIHtcblx0dmFyIGxvY2FsRGVsaXZlcnlSYWRpdXM7XG5cdGlmIChsb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgJiYgbG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yID09ICdHb0xvY2FsJykge1xuXHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSBvcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzRm9yR29Mb2NhbDtcblx0fSBlbHNlIHtcblx0XHRsb2NhbERlbGl2ZXJ5UmFkaXVzID0gb3B0aW9ucy5Mb2NhbERlbGl2ZXJ5LlJhZGl1c0ZvclJvYWRpZTtcblx0fVx0XG5cblx0aWYgKGxvY2FsRGVsaXZlcnlSYWRpdXMgJiYgbG9jYXRpb24gJiYgbG9jYXRpb24uZGlzdGFuY2UgJiYgbG9jYWxEZWxpdmVyeVJhZGl1cyA+PSBsb2NhdGlvbi5kaXN0YW5jZSkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0cmV0dXJuIGZhbHNlO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIFNlc3Npb25BdHRyaWJ1dGVzID0gd2luZG93LlNlc3Npb25BdHRyaWJ1dGVzO1xuXG4vKipcbiAqIEBmdW5jdGlvbiBjYXB0Y2hhICAgIFVzZWQgdG8gZGlzcGxheS9jb250cm9sIHRoZSBzY3JpbSBjb250YWluaW5nIHRoZSBzaW11bGF0ZWQgY2FwdGNoYSBjb2RlXG4gKiovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcblx0LyoqXG5cdCAqIGlmIHRoZSBzZXNzaW9uLnByaXZhY3kucmF0ZWxpbWl0ZWQgZWxlbWVudCBpcyBwcmVzZW50IHRoZW4gc2hvdyB0aGUgbm90aWZpY2F0aW9uXG5cdCAqIE5PVEU6IFlvdSB3aWxsIHByb2JhYmx5IHdhbnQgdG8gcmVwbGFjZSB0aGlzIHdpdGggYSBjYWxsIHRvIGFuIGFjdHVhbCBDQVBUQ0hBIHN5c3RlbSB0byByZXBsYWNlIHRoZSBzaW1wbGUgb25lIGhlcmVcblx0ICovXG5cdGlmIChTZXNzaW9uQXR0cmlidXRlcy5TSE9XX0NBUFRDSEEpIHtcblx0XHRkaWFsb2cub3Blbih7XG5cdFx0XHRodG1sOiAnPHA+JyArIFJlc291cmNlcy5QQVNTV09SRF9USVBfMSArICc8L3A+PHA+JyArIFJlc291cmNlcy5QQVNTV09SRF9USVBfMiArICc8L3A+Jyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0dGl0bGU6IFJlc291cmNlcy5BUkVfWU9VX0hVTUFOLFxuXHRcdFx0XHRjbG9zZU9uRXNjYXBlOiBmYWxzZSxcblx0XHRcdFx0ZGlhbG9nQ2xhc3M6ICduby1jbG9zZSBwYXNzd29yZC1lcnJvcicsXG5cdFx0XHRcdHdpZHRoOiA0MDAsXG5cdFx0XHRcdGJ1dHRvbnM6IFt7XG5cdFx0XHRcdFx0dGV4dDogUmVzb3VyY2VzLk9LLFxuXHRcdFx0XHRcdGNsaWNrOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHR2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLnJhdGVMaW1pdGVyUmVzZXQsIHtmb3JtYXQ6ICdhamF4J30pO1xuXHRcdFx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHRcdFx0dXJsOiB1cmxcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0JCh0aGlzKS5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKSxcbiAgICBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcblxudmFyIF9jdXJyZW50Q2F0ZWdvcnkgPSAnJyxcbiAgICBNQVhfQUNUSVZFID0gNjtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gVmVyaWZpZXMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgY29tcGFyZSBjb250YWluZXIgYW5kIHVwZGF0ZXMgaXQgd2l0aCBzZXF1ZW50aWFsIGNsYXNzZXMgZm9yIHVpIHRhcmdldGluZ1xuICovXG5mdW5jdGlvbiByZWZyZXNoQ29udGFpbmVyKCkge1xuICAgIHZhciAkY29tcGFyZUNvbnRhaW5lciA9ICQoJy5jb21wYXJlLWl0ZW1zJyk7XG4gICAgdmFyICRjb21wYXJlSXRlbXMgPSAkY29tcGFyZUNvbnRhaW5lci5maW5kKCcuY29tcGFyZS1pdGVtJyk7XG4gICAgdmFyIG51bUFjdGl2ZSA9ICRjb21wYXJlSXRlbXMuZmlsdGVyKCcuYWN0aXZlJykubGVuZ3RoO1xuXG4gICAgaWYgKG51bUFjdGl2ZSA8IDIpIHtcbiAgICAgICAgJCgnI2NvbXBhcmUtaXRlbXMtYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAkKCcjY29tcGFyZS1pdGVtcy1idXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgIH1cblxuICAgICRjb21wYXJlQ29udGFpbmVyLnRvZ2dsZShudW1BY3RpdmUgPiAwKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEFkZHMgYW4gaXRlbSB0byB0aGUgY29tcGFyZSBjb250YWluZXIgYW5kIHJlZnJlc2hlcyBpdFxuICovXG5mdW5jdGlvbiBhZGRUb0xpc3QoZGF0YSkge1xuICAgIC8vIGdldCB0aGUgZmlyc3QgY29tcGFyZS1pdGVtIG5vdCBjdXJyZW50bHkgYWN0aXZlXG4gICAgdmFyICRpdGVtID0gJCgnLmNvbXBhcmUtaXRlbXMgLmNvbXBhcmUtaXRlbScpLm5vdCgnLmFjdGl2ZScpLmZpcnN0KCksXG4gICAgICAgICRwcm9kdWN0VGlsZSA9ICQoJyMnICsgZGF0YS51dWlkKTtcblxuICAgIGlmICgkaXRlbS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgaWYgKCRwcm9kdWN0VGlsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkcHJvZHVjdFRpbGUuZmluZCgnLmNvbXBhcmUtY2hlY2snKVswXS5jaGVja2VkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5DT01QQVJFX0FERF9GQUlMKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGlmIGFscmVhZHkgYWRkZWQgc29tZWhvdywgcmV0dXJuXG4gICAgaWYgKCQoJ1tkYXRhLXV1aWQ9XCInICsgZGF0YS51dWlkICsgJ1wiXScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBzZXQgYXMgYWN0aXZlIGl0ZW1cbiAgICAkaXRlbS5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgICAgLmF0dHIoJ2RhdGEtdXVpZCcsIGRhdGEudXVpZClcbiAgICAgICAgLmF0dHIoJ2RhdGEtaXRlbWlkJywgZGF0YS5pdGVtaWQpXG4gICAgICAgIC5kYXRhKCd1dWlkJywgZGF0YS51dWlkKVxuICAgICAgICAuZGF0YSgnaXRlbWlkJywgZGF0YS5pdGVtaWQpXG4gICAgICAgIC5hcHBlbmQoJChkYXRhLmltZykuY2xvbmUoKS5hZGRDbGFzcygnY29tcGFyZS1pdGVtLWltYWdlJykpO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBkZXNjcmlwdGlvbiBSZW1vdmVzIGFuIGl0ZW0gZnJvbSB0aGUgY29tcGFyZSBjb250YWluZXIgYW5kIHJlZnJlc2hlcyBpdFxuICovXG5mdW5jdGlvbiByZW1vdmVGcm9tTGlzdCgkaXRlbSkge1xuICAgIGlmICgkaXRlbS5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG4gICAgLy8gcmVtb3ZlIGNsYXNzLCBkYXRhIGFuZCBpZCBmcm9tIGl0ZW1cbiAgICAkaXRlbS5yZW1vdmVDbGFzcygnYWN0aXZlJylcbiAgICAgICAgLnJlbW92ZUF0dHIoJ2RhdGEtdXVpZCcpXG4gICAgICAgIC5yZW1vdmVBdHRyKCdkYXRhLWl0ZW1pZCcpXG4gICAgICAgIC5kYXRhKCd1dWlkJywgJycpXG4gICAgICAgIC5kYXRhKCdpdGVtaWQnLCAnJylcbiAgICAgICAgLy8gcmVtb3ZlIHRoZSBpbWFnZVxuICAgICAgICAuZmluZCgnLmNvbXBhcmUtaXRlbS1pbWFnZScpLnJlbW92ZSgpO1xufVxuXG5mdW5jdGlvbiBhZGRQcm9kdWN0QWpheChhcmdzKSB7XG4gICAgdmFyIHByb21pc2UgPSBuZXcgVFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLmNvbXBhcmVBZGQsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgcGlkOiBhcmdzLml0ZW1pZCxcbiAgICAgICAgICAgICAgICBjYXRlZ29yeTogX2N1cnJlbnRDYXRlZ29yeVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbidcbiAgICAgICAgfSkuZG9uZShmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2UgfHwgIXJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFJlc291cmNlcy5DT01QQVJFX0FERF9GQUlMKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5mYWlsKGZ1bmN0aW9uIChqcXhociwgc3RhdHVzLCBlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoZXJyKSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG5mdW5jdGlvbiByZW1vdmVQcm9kdWN0QWpheChhcmdzKSB7XG4gICAgdmFyIHByb21pc2UgPSBuZXcgVFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLmNvbXBhcmVSZW1vdmUsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgcGlkOiBhcmdzLml0ZW1pZCxcbiAgICAgICAgICAgICAgICBjYXRlZ29yeTogX2N1cnJlbnRDYXRlZ29yeVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbidcbiAgICAgICAgfSkuZG9uZShmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2UgfHwgIXJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFJlc291cmNlcy5DT01QQVJFX1JFTU9WRV9GQUlMKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5mYWlsKGZ1bmN0aW9uIChqcXhociwgc3RhdHVzLCBlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoZXJyKSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG5mdW5jdGlvbiBzaGlmdEltYWdlcygpIHtcbiAgICByZXR1cm4gbmV3IFRQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgIHZhciAkaXRlbXMgPSAkKCcuY29tcGFyZS1pdGVtcyAuY29tcGFyZS1pdGVtJyk7XG4gICAgICAgICRpdGVtcy5lYWNoKGZ1bmN0aW9uIChpLCBpdGVtKSB7XG4gICAgICAgICAgICB2YXIgJGl0ZW0gPSAkKGl0ZW0pO1xuICAgICAgICAgICAgLy8gbGFzdCBpdGVtXG4gICAgICAgICAgICBpZiAoaSA9PT0gJGl0ZW1zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlRnJvbUxpc3QoJGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyICRuZXh0ID0gJGl0ZW1zLmVxKGkgKyAxKTtcbiAgICAgICAgICAgIGlmICgkbmV4dC5oYXNDbGFzcygnYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRzIG93biBpbWFnZVxuICAgICAgICAgICAgICAgICRuZXh0LmZpbmQoJy5jb21wYXJlLWl0ZW0taW1hZ2UnKS5kZXRhY2goKS5hcHBlbmRUbygkaXRlbSk7XG4gICAgICAgICAgICAgICAgJGl0ZW0uYWRkQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCdkYXRhLXV1aWQnLCAkbmV4dC5kYXRhKCd1dWlkJykpXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCdkYXRhLWl0ZW1pZCcsICRuZXh0LmRhdGEoJ2l0ZW1pZCcpKVxuICAgICAgICAgICAgICAgICAgICAuZGF0YSgndXVpZCcsICRuZXh0LmRhdGEoJ3V1aWQnKSlcbiAgICAgICAgICAgICAgICAgICAgLmRhdGEoJ2l0ZW1pZCcsICRuZXh0LmRhdGEoJ2l0ZW1pZCcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBBZGRzIHByb2R1Y3QgdG8gdGhlIGNvbXBhcmUgdGFibGVcbiAqL1xuZnVuY3Rpb24gYWRkUHJvZHVjdChhcmdzKSB7XG4gICAgdmFyIHByb21pc2U7XG4gICAgdmFyICRpdGVtcyA9ICQoJy5jb21wYXJlLWl0ZW1zIC5jb21wYXJlLWl0ZW0nKTtcbiAgICB2YXIgJGNiID0gJChhcmdzLmNiKTtcbiAgICB2YXIgbnVtQWN0aXZlID0gJGl0ZW1zLmZpbHRlcignLmFjdGl2ZScpLmxlbmd0aDtcbiAgICBpZiAobnVtQWN0aXZlID09PSBNQVhfQUNUSVZFKSB7XG4gICAgICAgIGlmICghd2luZG93LmNvbmZpcm0oUmVzb3VyY2VzLkNPTVBBUkVfQ09ORklSTUFUSU9OKSkge1xuICAgICAgICAgICAgJGNiWzBdLmNoZWNrZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbW92ZSBwcm9kdWN0IHVzaW5nIGlkXG4gICAgICAgIHZhciAkZmlyc3RJdGVtID0gJGl0ZW1zLmZpcnN0KCk7XG4gICAgICAgIHByb21pc2UgPSByZW1vdmVJdGVtKCRmaXJzdEl0ZW0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNoaWZ0SW1hZ2VzKCk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHByb21pc2UgPSBUUHJvbWlzZS5yZXNvbHZlKDApO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGFkZFByb2R1Y3RBamF4KGFyZ3MpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYWRkVG9MaXN0KGFyZ3MpO1xuICAgICAgICAgICAgaWYgKCRjYiAmJiAkY2IubGVuZ3RoID4gMCkgeyAkY2JbMF0uY2hlY2tlZCA9IHRydWU7IH1cbiAgICAgICAgICAgIHJlZnJlc2hDb250YWluZXIoKTtcbiAgICAgICAgfSk7XG4gICAgfSkudGhlbihudWxsLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgkY2IgJiYgJGNiLmxlbmd0aCA+IDApIHsgJGNiWzBdLmNoZWNrZWQgPSBmYWxzZTsgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFJlbW92ZXMgcHJvZHVjdCBmcm9tIHRoZSBjb21wYXJlIHRhYmxlXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIHRoZSBhcmd1bWVudHMgb2JqZWN0IHNob3VsZCBoYXZlIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczogaXRlbWlkLCB1dWlkIGFuZCBjYiAoY2hlY2tib3gpXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZVByb2R1Y3QoYXJncykge1xuICAgIHZhciAkY2IgPSBhcmdzLmNiID8gJChhcmdzLmNiKSA6IG51bGw7XG4gICAgcmV0dXJuIHJlbW92ZVByb2R1Y3RBamF4KGFyZ3MpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGl0ZW0gPSAkKCdbZGF0YS11dWlkPVwiJyArIGFyZ3MudXVpZCArICdcIl0nKTtcbiAgICAgICAgcmVtb3ZlRnJvbUxpc3QoJGl0ZW0pO1xuICAgICAgICBpZiAoJGNiICYmICRjYi5sZW5ndGggPiAwKSB7ICRjYlswXS5jaGVja2VkID0gZmFsc2U7IH1cbiAgICAgICAgcmVmcmVzaENvbnRhaW5lcigpO1xuICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCRjYiAmJiAkY2IubGVuZ3RoID4gMCkgeyAkY2JbMF0uY2hlY2tlZCA9IHRydWU7IH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlSXRlbSgkaXRlbSkge1xuICAgIHZhciB1dWlkID0gJGl0ZW0uZGF0YSgndXVpZCcpLFxuICAgICAgICAkcHJvZHVjdFRpbGUgPSAkKCcjJyArIHV1aWQpO1xuICAgIHJldHVybiByZW1vdmVQcm9kdWN0KHtcbiAgICAgICAgaXRlbWlkOiAkaXRlbS5kYXRhKCdpdGVtaWQnKSxcbiAgICAgICAgdXVpZDogdXVpZCxcbiAgICAgICAgY2I6ICgkcHJvZHVjdFRpbGUubGVuZ3RoID09PSAwKSA/IG51bGwgOiAkcHJvZHVjdFRpbGUuZmluZCgnLmNvbXBhcmUtY2hlY2snKVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgRE9NLU9iamVjdCBvZiB0aGUgY29tcGFyZSBjb250YWluZXJcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZURvbSgpIHtcbiAgICB2YXIgJGNvbXBhcmVDb250YWluZXIgPSAkKCcuY29tcGFyZS1pdGVtcycpO1xuICAgIF9jdXJyZW50Q2F0ZWdvcnkgPSAkY29tcGFyZUNvbnRhaW5lci5kYXRhKCdjYXRlZ29yeScpIHx8ICcnO1xuICAgIHZhciAkYWN0aXZlID0gJGNvbXBhcmVDb250YWluZXIuZmluZCgnLmNvbXBhcmUtaXRlbScpLmZpbHRlcignLmFjdGl2ZScpO1xuICAgICRhY3RpdmUuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkcHJvZHVjdFRpbGUgPSAkKCcjJyArICAkKHRoaXMpLmRhdGEoJ3V1aWQnKSk7XG4gICAgICAgIGlmICgkcHJvZHVjdFRpbGUubGVuZ3RoID09PSAwKSB7cmV0dXJuO31cbiAgICAgICAgJHByb2R1Y3RUaWxlLmZpbmQoJy5jb21wYXJlLWNoZWNrJylbMF0uY2hlY2tlZCA9IHRydWU7XG4gICAgfSk7XG4gICAgLy8gc2V0IGNvbnRhaW5lciBzdGF0ZVxuICAgIHJlZnJlc2hDb250YWluZXIoKTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIGV2ZW50cyBvbiB0aGUgY29tcGFyZSBjb250YWluZXJcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcbiAgICAvLyBhZGQgZXZlbnQgdG8gYnV0dG9ucyB0byByZW1vdmUgcHJvZHVjdHNcbiAgICAkKCcuY29tcGFyZS1pdGVtJykub24oJ2NsaWNrJywgJy5jb21wYXJlLWl0ZW0tcmVtb3ZlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICByZW1vdmVJdGVtKCQodGhpcykuY2xvc2VzdCgnLmNvbXBhcmUtaXRlbScpKTtcbiAgICB9KTtcblxuICAgIC8vIEJ1dHRvbiB0byBnbyB0byBjb21wYXJlIHBhZ2VcbiAgICAkKCcjY29tcGFyZS1pdGVtcy1idXR0b24nKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHBhZ2UucmVkaXJlY3QodXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMuY29tcGFyZVNob3csICdjYXRlZ29yeScsIF9jdXJyZW50Q2F0ZWdvcnkpKTtcbiAgICB9KTtcblxuICAgIC8vIEJ1dHRvbiB0byBjbGVhciBhbGwgY29tcGFyZWQgaXRlbXNcbiAgICAvLyByZWx5IG9uIHJlZnJlc2hDb250YWluZXIgdG8gdGFrZSBjYXJlIG9mIGhpZGluZyB0aGUgY29udGFpbmVyXG4gICAgJCgnI2NsZWFyLWNvbXBhcmVkLWl0ZW1zJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKCcuY29tcGFyZS1pdGVtcyAuYWN0aXZlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZW1vdmVJdGVtKCQodGhpcykpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRpYWxpemVEb20oKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG59O1xuXG5leHBvcnRzLmFkZFByb2R1Y3QgPSBhZGRQcm9kdWN0O1xuZXhwb3J0cy5yZW1vdmVQcm9kdWN0ID0gcmVtb3ZlUHJvZHVjdDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2pzL2RpYWxvZycpO1xuXG52YXIgb3BlbkNhcm91c2VsVmlkZW9Nb2RhbCA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgdmFyICR2aWRlb0VsZW1lbnQgPSAkKCdbZGF0YS1jYXJvdXNlbC12aWRlby1lbGVtZW50XScpLndyYXAoJzxkaXYgY2xhc3M9XCJ2aWRlby1jb250YWluZXJcIj48L2Rpdj4nKS5wYXJlbnQoKTtcbiAgICBcbiAgICBkaWFsb2cub3Blbih7XG4gICAgICAgIGh0bWw6ICR2aWRlb0VsZW1lbnRbMF0ub3V0ZXJIVE1MLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBkaWFsb2dDbGFzczogJ2ZpeGVkIGNhcm91c2VsLXZpZGVvLW1vZGFsJyxcbiAgICAgICAgICAgIHdpZHRoOiAnMTAwJScsXG4gICAgICAgICAgICBoZWlnaHQ6ICcxMDAlJyxcblx0XHRcdGRyYWdnYWJsZTogZmFsc2UsXG5cdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5maW5kKCcuY2Fyb3VzZWwtdmlkZW8tZWxlbWVudCcpWzBdLnBsYXkoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5maW5kKCcuY2Fyb3VzZWwtdmlkZW8tZWxlbWVudCcpWzBdLnBhdXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5DYXJvdXNlbFZpZGVvLlBsYXknKS5vbignY2xpY2suQ2Fyb3VzZWxWaWRlby5QbGF5JywgJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2RhdGEtY2Fyb3VzZWwtdmlkZW9dJywgb3BlbkNhcm91c2VsVmlkZW9Nb2RhbCk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5DYXJvdXNlbFZpZGVvLkNhdGNoJykub24oJ2NsaWNrLkNhcm91c2VsVmlkZW8uQ2F0Y2gnLCAnLnByb2R1Y3QtcHJpbWFyeS1pbWFnZSAuY2Fyb3VzZWwtdmlkZW8tbGluaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0fSk7XG59XG5cbm1vZHVsZS5leHBvcnRzLmluaXQgPSBpbml0aWFsaXplO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCkge1xuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkhlYWRlckJhbm5lci5DbG9zZScpLm9uKCdjbGljay5IZWFkZXJCYW5uZXIuQ2xvc2UnLCAnLmhlYWRlci1iYW5uZXIgLmNsb3NlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XG5cdFx0dmFyIGNvbnRlbnRBc3NldElkID0gJHRoaXMuY2xvc2VzdCgnW2NvbnRlbnQtYXNzZXQtaWRdJykuYXR0cignY29udGVudC1hc3NldC1pZCcpO1xuXHRcdGlmIChjb250ZW50QXNzZXRJZCkge1xuXHRcdFx0YWNrbm93bGVkZ2UoY29udGVudEFzc2V0SWQsICdZZXMnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0JCgnLmhlYWRlci1iYW5uZXInKS5oaWRlKCk7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2FwcC5yZXNpemUnKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5Db29raWVOb3RpZmljYXRpb24uWWVzJykub24oJ2NsaWNrLkNvb2tpZU5vdGlmaWNhdGlvbi5ZZXMnLCAnLm5vdGlmaWNhdGlvbi5jcHJhLWNvb2tpZS1ub3RpZmljYXRpb24gLmFjdGlvbnMgLnllcycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFxuXHRcdCR0aGlzLmNsb3Nlc3QoJy5ub3RpZmljYXRpb24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0YWNrbm93bGVkZ2UoJ0Nvb2tpZXMnLCAnWWVzJyk7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5Db29raWVOb3RpZmljYXRpb24uTm8nKS5vbignY2xpY2suQ29va2llTm90aWZpY2F0aW9uLk5vJywgJy5ub3RpZmljYXRpb24uY3ByYS1jb29raWUtbm90aWZpY2F0aW9uIC5hY3Rpb25zIC5ubycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFxuXHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gJHRoaXMuYXR0cignaHJlZicpO1xuXHRcdGFja25vd2xlZGdlKCdDb29raWVzJywgJ05vJyk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBhY2tub3dsZWRnZShub3RpZmljYXRpb24sIGFja25vd2xlZGdlbWVudCwgY2FsbGJhY2tTdWNjZXNzUGFyYW1ldGVyLCBjYWxsYmFja0Vycm9yUGFyYW1ldGVyKSB7XG5cdHZhciBjYWxsYmFja1N1Y2Nlc3MgPSBjYWxsYmFja1N1Y2Nlc3NQYXJhbWV0ZXIgfHwgZnVuY3Rpb24oKSB7IH07XG5cdHZhciBjYWxsYmFja0Vycm9yID0gY2FsbGJhY2tFcnJvclBhcmFtZXRlciB8fCBmdW5jdGlvbigpIHsgfTtcblxuXHRpZiAobm90aWZpY2F0aW9uICYmIGFja25vd2xlZGdlbWVudCkge1xuXHRcdCQuYWpheCh7XG5cdFx0XHR1cmw6IFVybHMuQ29va2llTm90aWZpY2F0aW9uLkFja25vd2xlZGdlLFxuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0ZGF0YToge1xuXHRcdFx0XHROb3RpZmljYXRpb246IG5vdGlmaWNhdGlvbixcblx0XHRcdFx0QWNrbm93bGVkZ2VtZW50OiBhY2tub3dsZWRnZW1lbnRcblx0XHRcdH0sXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogY2FsbGJhY2tTdWNjZXNzLFxuXHRcdFx0ZXJyb3I6IGNhbGxiYWNrRXJyb3Jcblx0XHR9KTtcblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpO1xuXG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgkY29udGFpbmVyKSB7XG5cdCRjb250YWluZXIuZmluZCgnW2VtYWlsLWZvcm1dJykuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJGZvcm0gPSAkKGVsZW1lbnQpO1xuXHRcdHZhciBmb3JtVHlwZSA9ICRmb3JtLmF0dHIoJ2VtYWlsLWZvcm0nKTtcblx0XHRhcHBlbmRDU1JGVG9rZW4oJGZvcm0pO1xuXG5cdFx0aWYgKGZvcm1UeXBlICYmIHR5cGVvZiBoYW5kbGVyc1tmb3JtVHlwZV0gPT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0aGFuZGxlcnNbZm9ybVR5cGVdKCRmb3JtKTtcblx0XHR9XG5cdH0pO1xufVxuXG52YXIgaGFuZGxlcnMgPSB7XG5cdCdjcHJhJzogZnVuY3Rpb24oJGZvcm0pIHtcblx0XHR2YXIgJHJlcXVpcmVkRmllbGRzID0gJGZvcm0uZmluZCgnaW5wdXQucmVxdWlyZWQnKTtcblx0XHR2YXIgJGZvcm1OYW1lRmlyc3QgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIm5hbWVfZmlyc3RcIl0nKTtcblx0XHR2YXIgJGZvcm1OYW1lTGFzdCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwibmFtZV9sYXN0XCJdJyk7XG5cdFx0dmFyICRmb3JtRW1haWwgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cImVtYWlsXCJdJyk7XG5cdFx0dmFyICRmb3JtUGhvbmUgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cInBob25lXCJdJyk7XG5cdFx0dmFyICRmb3JtUmVxdWVzdFR5cGUgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cInJlcXVlc3RUeXBlXCJdJyk7XG5cdFx0XG5cdFx0dmFyIGZvcm1WYWxpZGF0b3IgPSAkZm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3JlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24nLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbiwgUmVzb3VyY2VzLklOVkFMSURfVkFMVUUpO1xuXHRcdCRyZXF1aXJlZEZpZWxkcy5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHRcdCRmb3JtRW1haWwucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5FbWFpbCk7XG5cdFx0JGZvcm0uZmluZCgnc3Bhbi5lcnJvcicpLnJlbW92ZSgpO1xuXHRcdFxuXHRcdCRmb3JtLmZpbmQoJ2lucHV0W3R5cGU9XCJzdWJtaXRcIl0nKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0aWYgKGZvcm1WYWxpZGF0b3IuZm9ybSgpKSB7XG5cdFx0XHRcdHZhciBkYXRhID0ge1xuXHRcdFx0XHRcdCdmb3JtX3R5cGUnOiAkZm9ybS5hdHRyKCdlbWFpbC1mb3JtJyksXG5cdFx0XHRcdFx0J25hbWVfZmlyc3QnOiAkZm9ybU5hbWVGaXJzdC52YWwoKSxcblx0XHRcdFx0XHQnbmFtZV9sYXN0JzogJGZvcm1OYW1lTGFzdC52YWwoKSxcblx0XHRcdFx0XHQnZW1haWwnOiAkZm9ybUVtYWlsLnZhbCgpLFxuXHRcdFx0XHRcdCdwaG9uZSc6ICRmb3JtUGhvbmUudmFsKCksXG4vL1x0XHRcdFx0XHQncmVxdWVzdF90eXBlJzogJGZvcm1SZXF1ZXN0VHlwZS5maWx0ZXIoJzpjaGVja2VkJykubWFwKGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy52YWx1ZTsgfSkuZ2V0KCkuam9pbignIGFuZCAnKVxuXHRcdFx0XHRcdCdyZXF1ZXN0X3R5cGUnOiAkZm9ybVJlcXVlc3RUeXBlLnZhbCgpXG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkZm9ybS5maW5kKCdpbnB1dFt0eXBlPVwiaGlkZGVuXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0XHRkYXRhWyR0aGlzLmF0dHIoJ25hbWUnKV0gPSAkdGhpcy52YWwoKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR1cmw6IFVybHMuRW1haWxGb3JtLlNlbmQsXG5cdFx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5FbWFpbFNlbnQpIHtcblx0XHRcdFx0XHRcdFx0dmFyICRzdWNjZXNzQ29udGVudCA9ICQoJy5jb250ZW50LmNwcmEtZm9ybS1zdWNjZXNzJyk7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRkaWFsb2cub3Blbih7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgaHRtbDogJHN1Y2Nlc3NDb250ZW50Lmh0bWwoKSxcblx0XHRcdFx0XHQgICAgICAgICAgICBvcHRpb25zOiB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIHRpdGxlOiAkc3VjY2Vzc0NvbnRlbnQuYXR0cigndGl0bGUnKSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgZGlhbG9nQ2xhc3M6ICdmaXhlZCBjaGVja291dC10ZXJtcycgKyAoJHN1Y2Nlc3NDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpID8gJyAnICsgJHN1Y2Nlc3NDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpIDogJycpLFxuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHRcdCAgICAgICAgXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIFx0JHRoaXMuc2Nyb2xsVG9wKDApO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfVxuXHRcdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0XHQgICAgICAgIH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dmFyICRlcnJvckNvbnRlbnQgPSAkKCcuY29udGVudC5jcHJhLWZvcm0tZXJyb3InKTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHQgICAgICAgICAgICBodG1sOiAkZXJyb3JDb250ZW50Lmh0bWwoKSxcblx0XHRcdFx0XHQgICAgICAgICAgICBvcHRpb25zOiB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIHRpdGxlOiAkZXJyb3JDb250ZW50LmF0dHIoJ3RpdGxlJyksXG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnZml4ZWQgY2hlY2tvdXQtdGVybXMnICsgKCRlcnJvckNvbnRlbnQuYXR0cignZGlhbG9nLWNsYXNzJykgPyAnICcgKyAkZXJyb3JDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpIDogJycpLFxuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHRcdCAgICAgICAgXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIFx0JHRoaXMuc2Nyb2xsVG9wKDApO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfVxuXHRcdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0XHQgICAgICAgIH0pO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0dmFyICRlcnJvckNvbnRlbnQgPSAkKCcuY29udGVudC5jcHJhLWZvcm0tZXJyb3InKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0XHQgICAgICAgICAgICBodG1sOiAkZXJyb3JDb250ZW50Lmh0bWwoKSxcblx0XHRcdFx0ICAgICAgICAgICAgb3B0aW9uczoge1xuXHRcdFx0XHQgICAgICAgICAgICAgICAgdGl0bGU6ICRlcnJvckNvbnRlbnQuYXR0cigndGl0bGUnKSxcblx0XHRcdFx0ICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnZml4ZWQgY2hlY2tvdXQtdGVybXMnICsgKCRlcnJvckNvbnRlbnQuYXR0cignZGlhbG9nLWNsYXNzJykgPyAnICcgKyAkZXJyb3JDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpIDogJycpLFxuXHRcdFx0XHQgICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdFx0ICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHQgICAgICAgICAgICAgICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHQgICAgICAgIFxuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0JCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0JHRoaXMuc2Nyb2xsVG9wKDApO1xuXHRcdFx0XHRcdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdFx0ICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuXHRcdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0ICAgICAgICAgICAgfVxuXHRcdFx0XHQgICAgICAgIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gYXBwZW5kQ1NSRlRva2VuKCRmb3JtKSB7XG5cdCQuYWpheCh7XG5cdFx0bWV0aG9kOiAnZ2V0Jyxcblx0XHR1cmw6IFVybHMuQ1NSRlRva2VuLkdldCxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHQkZm9ybS5hcHBlbmQoJzxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cIicgKyByZXNwb25zZS5uYW1lICsgJ1wiIHZhbHVlPVwiJyArIHJlc3BvbnNlLnRva2VuICsgJ1wiLz4nKTtcblx0XHR9XG5cdH0pO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIFJlY2FwdGNoYSA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvUmVjYXB0Y2hhJyk7XG52YXIgUmVxdWVzdEhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2hlbHBlcnMvUmVxdWVzdEhlbHBlcicpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcblxuZXhwb3J0cy5Jbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyICRmb290ZXJFbWFpbEZvcm07XG52YXIgdmFsaWRhdG9yO1xudmFyIGRhdGFCdWZmZXIgPSB7fTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShwYWdlKSB7XG5cdGlmIChwYWdlICYmIHBhZ2Uub3B0aW9ucykge1xuXHRcdG9wdGlvbnMgPSBwYWdlLm9wdGlvbnM7XG5cdH1cblxuXHR2YXIgZm9vdGVyRW1haWxGb3JtU2VsZWN0b3I7XG5cdGlmIChwYWdlLnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRmb290ZXJFbWFpbEZvcm1TZWxlY3RvciA9ICdmb3JtI2VtYWlsLWFsZXJ0LXNpZ251cCc7XG5cdH0gZWxzZSBpZiAocGFnZS5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0Zm9vdGVyRW1haWxGb3JtU2VsZWN0b3IgPSAnZm9ybSNib290YmFybi1mb290ZXItZW1haWwtYWxlcnQtc2lnbnVwJztcblx0fSBlbHNlIHtcblx0XHRmb290ZXJFbWFpbEZvcm1TZWxlY3RvciA9ICdmb3JtI2Zvb3Rlci1lbWFpbC1zaWdudXAnO1xuXHR9XG5cdFxuXHQkZm9vdGVyRW1haWxGb3JtID0gJChmb290ZXJFbWFpbEZvcm1TZWxlY3Rvcik7XG5cdGlmICgkZm9vdGVyRW1haWxGb3JtLmxlbmd0aCA+IDApIHtcdFx0XG5cdFx0dmFyICR2YWxpZGF0b3JFcnJvck1lc3NhZ2UgPSAkZm9vdGVyRW1haWxGb3JtLmZpbmQoJ3NwYW4uZXJyb3InKTtcblx0XHRcblx0XHQkZm9vdGVyRW1haWxGb3JtLm9uKCdzdWJtaXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLlJlY2FwdGNoYSB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckZvb3RlckVtYWlsU2lnbnVwKSB7XG5cdFx0XHRcdHN1Ym1pdEVtYWlsU2lnbnVwKCk7XG5cdFx0XHR9XHRcdFx0XG5cdFx0fSk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uRW1haWxTaWduVXAuVmFsaWRhdGlvbkNsZWFyJykub24oJ21vdXNlZG93bi5FbWFpbFNpZ25VcC5WYWxpZGF0aW9uQ2xlYXInLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0aWYgKHZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdChmb290ZXJFbWFpbEZvcm1TZWxlY3RvcikucGFyZW50KCkubGVuZ3RoID09IDApIHtcblx0XHRcdFx0dmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuXHRcdFx0XHQkdmFsaWRhdG9yRXJyb3JNZXNzYWdlLnJlbW92ZUNsYXNzKCdzaWdudXAtc3VjY2VzcycpLmh0bWwoJycpLmhpZGUoKTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHRcdCQoZG9jdW1lbnQpLm9uKCdHbG9iYWwuRW1haWxTaWdudXAnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGEpIHtcblx0XHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JGb290ZXJFbWFpbFNpZ251cCkge1xuXHRcdFx0XHRzdWJtaXRFbWFpbFNpZ251cCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckZvb3RlckVtYWlsU2lnbnVwICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcblx0XHRcdFJlY2FwdGNoYS5pbml0aWFsaXplKCk7XG5cdFx0XHRyZW5kZXJSZWNhcHRjaGFGb3JFbWFpbFNpZ251cCgpO1xuXHRcdFx0JChkb2N1bWVudCkub24oJ1JlY2FwdGNoYS5Mb2FkZWQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdFx0XHRsb2FkZWQuUmVjYXB0Y2hhID0gdHJ1ZTtcblx0XHRcdFx0XHRyZW5kZXJSZWNhcHRjaGFGb3JFbWFpbFNpZ251cCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gc3VibWl0RW1haWxTaWdudXAoKSB7XG5cdHZhciAkZW1haWxBZGRyZXNzID0gJGZvb3RlckVtYWlsRm9ybS5maW5kKCdpbnB1dCNlbWFpbC1hbGVydC1hZGRyZXNzJyk7XHRcdFxuXHR2YWxpZGF0b3IgPSAkZm9vdGVyRW1haWxGb3JtLnZhbGlkYXRlKCk7XG5cdCRlbWFpbEFkZHJlc3MucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5FbWFpbCk7XG5cdHZhbGlkYXRvci5mb3JtKCk7XG5cblx0aWYgKHZhbGlkYXRvci52YWxpZCgpKSB7XG5cdFx0aWYoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCl7XG5cdFx0XHR2YXIgYXV0aF9kYXRhID0ge1xuXHRcdFx0XHRlbWFpbDogJGVtYWlsQWRkcmVzcy52YWwoKVxuXHRcdFx0fVxuXHRcdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdFx0J2NoYW5uZWxzJzoge1xuXHRcdFx0XHRcdCdlbWFpbCc6IHtcblx0XHRcdFx0XHRcdCdhZGRyZXNzJzogJGVtYWlsQWRkcmVzcy52YWwoKSxcblx0XHRcdFx0XHRcdCdzdWJzY3JpYmVTdGF0dXMnOiAnc3Vic2NyaWJlZCdcdFx0XHRcdCAgICAgICAgICAgIFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcdFx0XHRcdCAgICBcblx0XHRcdFx0J3NpZ251cF9zb3VyY2UnOiAnZm9vdGVyJyxcblx0XHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHRcdFwic2lnbnVwX3NvdXJjZVwiOiAnZm9vdGVyJyxcblx0XHRcdFx0XCJ3ZWxjb21lX3NpZ251cFwiOiB0cnVlXG5cdFx0XHR9O1xuXG5cdFx0XHRSZXF1ZXN0SGVscGVyLlZhbGlkYXRlKCdDb3JkaWFsLUVtYWlsU2lnbnVwJykudGhlbihmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRcdGNyZGwoW1xuXHRcdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFx0WydldmVudCcsICdlbWFpbF9zaWdudXAnLCBwcm9wZXJ0aWVzXVxuXHRcdFx0XHRcdF0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KS5jYXRjaCgpO1xuXHRcdH1cblx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLlJFVEVOVElPTl9DT01fRU5BQkxFRCkge1xuXHRcdFx0Z2VxLnN1cHByZXNzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCQoJyNlbWFpbC1hbGVydC1hZGRyZXNzLnZhbGlkJykubGVuZ3RoID4gMCAmJiAkKCcjZW1haWwtYWxlcnQtYWRkcmVzcycpLnZhbCgpICE9ICcnKSB7XG5cdFx0XHQkKCdpbnB1dCNlbWFpbC1hbGVydC1hZGRyZXNzJykudmFsKCcnKTtcblx0XHRcdCQoJy5zaWdudXAtc3VjY2VzcycpLnNob3coKTtcblx0XHR9XG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdCQoJy5zaWdudXAtc3VjY2VzcycpLmhpZGUoKTtcblx0XHR9LCA1MDAwKTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW5kZXJSZWNhcHRjaGFGb3JFbWFpbFNpZ251cCgpIHtcbiAgICBpZiAobG9hZGVkLlJlY2FwdGNoYSAmJiAkZm9vdGVyRW1haWxGb3JtLmxlbmd0aCA+IDAgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yRm9vdGVyRW1haWxTaWdudXAgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuICAgICAgICBpZiAoZGF0YUJ1ZmZlci5FbWFpbFNpZ251cFJlY2FwdGNoYSkge1xuICAgICAgICAgICAgZ3JlY2FwdGNoYS5yZXNldChkYXRhQnVmZmVyLkVtYWlsU2lnbnVwUmVjYXB0Y2hhKTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhQnVmZmVyLkVtYWlsU2lnbnVwUmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ2Zvb3Rlci1lbWFpbC1hbGVydC1zaWdudXAtc3VibWl0Jywge1xuICAgICAgICAgICAgJ3NpdGVrZXknOiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuICAgICAgICAgICAgJ2NhbGxiYWNrJzogZW1haWxTaWdudXAsXG4gICAgICAgICAgICAnYmFkZ2UnOiAnaW5saW5lJ1xuICAgICAgICB9KTtcbiAgICB9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4vTG9hZGluZ0luZGljYXRvcicpO1xudmFyIFJldHVybkNvZGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vaW50X3N2cy9jYXJ0cmlkZ2Uvc2NyaXB0cy9HaWZ0Q2FyZENvbnN0YW50cycpLlJldHVybkNvZGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5leHBvcnRzLnJlbW92ZSA9IHJlbW92ZTtcblxudmFyIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlWYWxpZGF0b3I7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoJGNvbnRhaW5lciwgb3B0aW9uc1BhcmFtZXRlcikge1xuXHR2YXIgb3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRzdWNjZXNzQ2FsbGJhY2s6IG51bGwsXG5cdFx0ZXJyb3JDYWxsYmFjazogbnVsbFxuXHR9LCBvcHRpb25zUGFyYW1ldGVyKTtcblx0XG5cdHZhciAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudCA9ICRjb250YWluZXIuZmluZCgnLmdpZnQtY2FyZC1iYWxhbmNlLWlucXVpcnktY29tcG9uZW50Jyk7XG5cdFxuXHR2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlGb3JtID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDb21wb25lbnQuZmluZCgnZm9ybScpO1xuXHR2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlSZXN1bHQgPSAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5maW5kKCcuYmFsYW5jZS1pbnF1aXJ5LXJlc3VsdCcpO1xuXHR2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlSZXN1bHRBbW91bnQgPSAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5maW5kKCcuYW1vdW50Jyk7XG5cdHZhciAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIgPSAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJnaWZ0Q2FyZF9udW1iZXJcIl0nKTtcbiAgICB2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlQaW5OdW1iZXIgPSAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJnaWZ0Q2FyZF9waW5cIl0nKTtcbiAgICB2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlFcnJvck1lc3NhZ2UgPSAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUZvcm0uZmluZCgnc3Bhbi5lcnJvcicpO1xuXHRcbiAgICAkY29udGFpbmVyLmF0dHIoJ2JhbGFuY2UtaW5xdWlyeS1zdGF0ZScsICdmb3JtJyk7XG5cdFxuICAgICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50Lm9mZignY2xpY2suYXBwbHknKS5vbignY2xpY2suYXBwbHknLCAnLmJ0bi5iYWxhbmNlLWlucXVpcnk6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0JGdpZnRDYXJkQmFsYW5jZUlucXVpcnlFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5VmFsaWRhdG9yID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlGb3JtLnZhbGlkYXRlKCk7XG5cdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdnaWZ0Q2FyZE51bWJlckxlbmd0aCcsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVHaWZ0Q2FyZE51bWJlckxlbmd0aCwgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuR2lmdENhcmQuTnVtYmVyLkxlbmd0aCk7XG5cdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdnaWZ0Q2FyZE51bWJlclZhbHVlcycsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVHaWZ0Q2FyZE51bWJlclZhbHVlcywgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuR2lmdENhcmQuTnVtYmVyLlZhbHVlcyk7XG5cdFx0JGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuR2lmdENhcmQuTnVtYmVyKTtcblx0XHQkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVBpbk51bWJlci5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLkdpZnRDYXJkLlBpbik7XG4gICAgICAgIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlWYWxpZGF0b3IuZm9ybSgpO1xuXG4gICAgICAgIGlmIChVcmxzICYmIFVybHMuR2lmdENhcmQuQmFsYW5jZUlucXVpcnkgJiYgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVZhbGlkYXRvci52YWxpZCgpKSB7XG4gICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG4gICAgICAgICAgICAkdGhpcy5sb2FkaW5nKHtcbiAgICAgICAgICAgICAgICBJc0ltYWdlU2hvd246IGZhbHNlLFxuICAgICAgICAgICAgICAgIExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb2FkaW5nXG4gICAgICAgICAgICB9KTtcblxuXHRcdFx0dmFyIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyLnZhbCgpLm1hdGNoKC8oXFxkKS9nKTtcblx0XHRcdGlmIChnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlciAmJiBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlci5sZW5ndGgpIHtcblx0XHRcdFx0Z2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIgPSBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlci5qb2luKCcnKTtcblx0XHRcdH1cblxuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICB1cmw6IFVybHMuR2lmdENhcmQuQmFsYW5jZUlucXVpcnksXG4gICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgIGNhcmROdW1iZXI6IGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICBwaW46ICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UGluTnVtYmVyLnZhbCgpXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucXVpcnlSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhICYmIGRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCAmJiBkYXRhLklucXVpcnlSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucXVpcnlSZXN1bHQgPSBkYXRhLklucXVpcnlSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5xdWlyeVJlc3VsdCAmJiBpbnF1aXJ5UmVzdWx0LlJldHVybkNvZGUuUmV0dXJuQ29kZSA9PSBSZXR1cm5Db2Rlcy5BcHByb3ZhbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci5hdHRyKCdiYWxhbmNlLWlucXVpcnktc3RhdGUnLCAncmVzdWx0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UmVzdWx0QW1vdW50LnRleHQoaW5xdWlyeVJlc3VsdC5CYWxhbmNlQW1vdW50LkFtb3VudEZvcm1hdHRlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgXHRvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjayhpbnF1aXJ5UmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgXHRpZiAoaW5xdWlyeVJlc3VsdC5SZXR1cm5Db2RlLlJldHVybkRlc2NyaXB0aW9uID09ICdJbnZhbGlkIE1lc3NhZ2UnKSB7XG4gICAgICAgICAgICAgICAgICAgIFx0XHRpbnF1aXJ5UmVzdWx0LlJldHVybkNvZGUuUmV0dXJuRGVzY3JpcHRpb24gPSBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYztcdFxuICAgICAgICAgICAgICAgICAgICBcdH1cbiAgICAgICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RXJyb3JNZXNzYWdlLmh0bWwoaW5xdWlyeVJlc3VsdC5SZXR1cm5Db2RlLlJldHVybkRlc2NyaXB0aW9uIHx8IFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0b3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblx0XHR9XG5cdH0pO1xuICAgIFxuICAgICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlci5vZmYoJ2tleWRvd24uR2lmdENhcmRCYWxhbmNlSW5xdWlyeS5WYWxpZGF0aW9uQ2xlYXIsIGNoYW5nZS5HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5LlZhbGlkYXRpb25DbGVhcicpLm9uKCdrZXlkb3duLkdpZnRDYXJkQmFsYW5jZUlucXVpcnkuVmFsaWRhdGlvbkNsZWFyLCBjaGFuZ2UuR2lmdENhcmRCYWxhbmNlSW5xdWlyeS5WYWxpZGF0aW9uQ2xlYXInLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRpZiAoJGNvbnRhaW5lci5hdHRyKCdiYWxhbmNlLWlucXVpcnktc3RhdGUnKSA9PT0gJ3Jlc3VsdCcpIHtcblx0XHRcdCRjb250YWluZXIuYXR0cignYmFsYW5jZS1pbnF1aXJ5LXN0YXRlJywgJ2Zvcm0nKTtcbiAgICAgICAgXHQkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVBpbk51bWJlci52YWwoJycpO1xuICAgICAgICBcdCRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UmVzdWx0QW1vdW50LnRleHQoJycpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uR2lmdENhcmRCYWxhbmNlSW5xdWlyeS5WYWxpZGF0aW9uQ2xlYXInKS5vbignbW91c2Vkb3duLkdpZnRDYXJkQmFsYW5jZUlucXVpcnkuVmFsaWRhdGlvbkNsZWFyJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5VmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCcuZ2lmdC1jYXJkLWJhbGFuY2UtaW5xdWlyeS1jb21wb25lbnQnKS5wYXJlbnQoKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVZhbGlkYXRvci5yZXNldEZvcm0oKTtcbiAgICAgICAgICAgICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiByZW1vdmUoKSB7XG5cdGdpZnRDYXJkQmFsYW5jZUlucXVpcnlWYWxpZGF0b3IuZGVzdHJveSgpO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCkge1xuICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgaHRtbDogJCgnI2RpYWxvZy1jb250ZW50LWdpZnQtY2FyZC1iYWxhbmNlLWlucXVpcnknKS5odG1sKCksXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIHRpdGxlOiAnR2lmdCBDYXJkIEJhbGFuY2UgQ2hlY2snLFxuICAgICAgICAgICAgZGlhbG9nQ2xhc3M6ICdnaWZ0LWNhcmQtYmFsYW5jZS1pbnF1aXJ5JyxcbiAgICAgICAgICAgIHJlc2l6YWJsZTogZmFsc2UsXG4gICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuL0xvYWRpbmdJbmRpY2F0b3InKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyIG9wdGlvbnM7XG52YXIgZGF0YUJ1ZmZlcjtcbnZhciBsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MgPSB7XG4gICAgSXNMYWJlbFNob3duOiBmYWxzZSxcbiAgICBDc3NDbGFzczogJ2Z1bGxzY3JlZW4nLFxuICAgIEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xufTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSAkLmV4dGVuZCh7XG5cdFx0c3VjY2Vzc0NhbGxiYWNrOiBudWxsLFxuXHRcdGVycm9yQ2FsbGJhY2s6IG51bGxcblx0fSwgb3B0aW9uc1BhcmFtZXRlcik7XG5cdGRhdGFCdWZmZXIgPSB7XG5cdFx0aW5pdGlhbGl6ZWQ6IGZhbHNlXG5cdH07XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5HbG9iYWxlSW5pdGlhbGl6ZScpLm9uKCdjbGljay5HbG9iYWxlSW5pdGlhbGl6ZScsICcuY291bnRyeS1zZWxlY3RvcicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCQoJ2RpdiNnbG9iYWxlLXNjcmlwdC1sb2FkZXItZGF0YScpLmxlbmd0aCA+IDAgJiYgIWRhdGFCdWZmZXIuaW5pdGlhbGl6ZWQpIHtcblx0XHRcdGRhdGFCdWZmZXIuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cdFx0XHQkKCdib2R5JykuYXBwZW5kKCc8c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIiBpZD1cImdsb2JhbGUtc2NyaXB0LWxvYWRlclwiIHNyYz1cIicgKyBVcmxzLkdsb2JhbGUuU2NyaXB0TG9hZGVyICsgJ1wiPjwvc2NyaXB0PicpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdHbG9iYWxlLkluaXRpYWxpemVkJykub24oJ0dsb2JhbGUuSW5pdGlhbGl6ZWQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmIChkYXRhQnVmZmVyLmluaXRpYWxpemVkICYmICQoJy5wdF9jaGVja291dF9nbG9iYWxlJykubGVuZ3RoID09IDApIHtcblx0XHRcdGRhdGFCdWZmZXIuc2hvd1NoaXBwaW5nU3dpdGNoZXJJbnRlcnZhbCA9IHNldEludGVydmFsKHNob3dTaGlwcGluZ1N3aXRjaGVyLCAyNTApO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHNob3dTaGlwcGluZ1N3aXRjaGVyKCkge1xuXHRpZiAoR2xvYmFsRSAmJiBHbG9iYWxFLlNoaXBwaW5nU3dpdGNoZXIgJiYgR2xvYmFsRS5TaGlwcGluZ1N3aXRjaGVyLlNob3cgJiYgdHlwZW9mIEdsb2JhbEUuU2hpcHBpbmdTd2l0Y2hlci5TaG93ID09ICdmdW5jdGlvbicpIHtcblx0XHRpZiAoJCgnYm9keScpLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHR9XG5cdFx0Y2xlYXJJbnRlcnZhbChkYXRhQnVmZmVyLnNob3dTaGlwcGluZ1N3aXRjaGVySW50ZXJ2YWwpO1xuXHRcdEdsb2JhbEUuU2hpcHBpbmdTd2l0Y2hlci5TaG93KCk7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciBJbWFnZUNvbnN0YW50cztcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBjYXJvdXNlbFZpZGVvID0gcmVxdWlyZSgnLi8uLi9DYXJvdXNlbFZpZGVvJyk7XG5cbnZhciBzaW5nbGVJbWFnZVNsaWNrT3B0aW9ucztcbnZhciBwcm9kdWN0VGh1bWJuYWlsU2xpY2tPcHRpb25zO1xuXG52YXIgaHRtbCA9IFtdO1xudmFyIGRhdGEgPSBbXTtcbnZhciBsb2FkZWQgPSBbXTtcbnZhciBvcHRpb25zO1xuXG52YXIgJHNpbmdsZUltYWdlU2xpZGVzO1xudmFyICR0aHVtYm5haWxJbWFnZUNvbnRhaW5lcjtcbnZhciAkdGh1bWJuYWlsSW1hZ2VTbGlkZXM7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUocGFyYW1zKSB7XG5cdGlmIChwYXJhbXMpIHtcbiAgICBcdG9wdGlvbnMgPSBwYXJhbXM7XG5cdH1cbiAgICB2YXIgJHBkcE1haW4gPSAkKCcjcGRwTWFpbicpO1xuXG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdEltYWdlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYXBwX3N0b3JlZnJvbnRfY291bnRyeW91dGZpdHRlcnMvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzJyk7XG5cdH0gZWxzZSBpZiAocGFnZUNvbnRleHQuaXNzdG9yZXNpdGUpIHtcblx0XHRJbWFnZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2Jvb3RiYXJuX3JzcC9jYXJ0cmlkZ2UvanMvSW1hZ2VDb25zdGFudHMnKTtcblx0fSBlbHNlIHsgXG5cdFx0SW1hZ2VDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzJyk7XG5cdH1cblx0c2luZ2xlSW1hZ2VTbGlja09wdGlvbnMgPSBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlNpbmdsZTtcblx0cHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucyA9IEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuVGh1bWJuYWlsO1xuXG4gICAgJHNpbmdsZUltYWdlU2xpZGVzID0gJCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpO1xuICAgICR0aHVtYm5haWxJbWFnZUNvbnRhaW5lciA9ICQoJy5wcm9kdWN0LXRodW1ibmFpbHMtY29udGFpbmVyJyk7XG5cdCR0aHVtYm5haWxJbWFnZVNsaWRlcyA9ICR0aHVtYm5haWxJbWFnZUNvbnRhaW5lci5maW5kKCcuc2xpZGVzJyk7XG5cbiAgICAkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuTGVhZmxldC5ab29tLkluJykub24oJ2NsaWNrLlZhcmlhbnQuTGVhZmxldC5ab29tLkluJywgJy5jdXN0b20ubGVhZmxldC1jb250cm9sLXpvb20taW4nLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkc2xpZGVzID0gJCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpO1xuXHRcdHZhciBzbGljayA9ICRzbGlkZXMuc2xpY2soJ2dldFNsaWNrJyk7XG5cdFx0JHNsaWRlcy5maW5kKCdbZGF0YS1zbGljay1pbmRleD1cIicgKyBzbGljay5jdXJyZW50U2xpZGUgKyAnXCJdIGltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdnZXRNYXAnKS56b29tSW4oKTtcbiAgICB9KTtcbiAgICBcbiAgICAkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuTGVhZmxldC5ab29tLk91dCcpLm9uKCdjbGljay5WYXJpYW50LkxlYWZsZXQuWm9vbS5PdXQnLCAnLmN1c3RvbS5sZWFmbGV0LWNvbnRyb2wtem9vbS1vdXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkc2xpZGVzID0gJCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpO1xuXHRcdHZhciBzbGljayA9ICRzbGlkZXMuc2xpY2soJ2dldFNsaWNrJyk7XG5cdFx0JHNsaWRlcy5maW5kKCdbZGF0YS1zbGljay1pbmRleD1cIicgKyBzbGljay5jdXJyZW50U2xpZGUgKyAnXCJdIGltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdnZXRNYXAnKS56b29tT3V0KCk7XG4gICAgfSk7XG5cdFxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgfHwgcGFnZUNvbnRleHQub3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdCQod2luZG93KS5vZmYoJ3Jlc2l6ZS5QRFAuU2xpZGVyLlByaW1hcnknKS5vbigncmVzaXplLlBEUC5TbGlkZXIuUHJpbWFyeScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0aWYgKGRhdGFbJ21hcFJlc2l6ZVRpbWVyJ10pIHtcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KGRhdGFbJ21hcFJlc2l6ZVRpbWVyJ10pO1xuXHRcdFx0fVxuXHRcdFx0ZGF0YVsnbWFwUmVzaXplVGltZXInXSA9IHNldFRpbWVvdXQobWFwUmVzaXplVGltZXJIYW5kbGVyLCAyNTApO1xuXHRcdH0pO1xuXHR9XG5cdFxuXHQkc2luZ2xlSW1hZ2VTbGlkZXMub24oJ2luaXQnLCBmdW5jdGlvbihldmVudCwgc2xpY2spIHtcblx0XHQvLyBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRcdHZhciAkaW5pdGlhbFNsaWRlID0gJHNpbmdsZUltYWdlU2xpZGVzLmZpbmQoJy5zbGljay1zbGlkZS5zbGljay1hY3RpdmUnKTtcblx0XHRcdGRhdGFbJ3NpbmdsZUltYWdlU2xpZGVzSW5pdGlhbFNsaWRlJ10gPSAkaW5pdGlhbFNsaWRlLmF0dHIoJ2RhdGEtc2xpY2staW5kZXgnKTtcblx0XHRcdGRhdGFbJ3NpbmdsZUltYWdlU2xpZGVzQ3VycmVudFNsaWRlJ10gPSBkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0luaXRpYWxTbGlkZSddO1xuXG5cdFx0XHRpbml0aWFsaXplSW1hZ2VWaWV3ZXJPblNsaWRlKCRpbml0aWFsU2xpZGUpO1xuXHRcdFx0Ly8gc2V0VGltZW91dChmdW5jdGlvbigpe3Jlc2l6ZVNsaWRlclRvTWF0Y2hTbGlkZSgkaW5pdGlhbFNsaWRlKTt9LCAyNTApO1xuXHRcdC8vIH1cblx0fSk7XG5cdFxuXHQkc2luZ2xlSW1hZ2VTbGlkZXMub24oJ2JlZm9yZUNoYW5nZScsIGZ1bmN0aW9uKGV2ZW50LCBzbGljaywgY3VycmVudFNsaWRlLCBuZXh0U2xpZGUpIHtcblx0XHRpZiAobmV4dFNsaWRlICE9IGRhdGFbJ3NpbmdsZUltYWdlU2xpZGVzQ3VycmVudFNsaWRlJ10pIHtcblx0XHRcdCR0aHVtYm5haWxJbWFnZVNsaWRlcy5maW5kKCcuc2xpY2stY3VycmVudCcpLnJlbW92ZUNsYXNzKCdzbGljay1jdXJyZW50Jyk7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWRlW2RhdGEtc2xpY2staW5kZXg9XCInICsgbmV4dFNsaWRlICsgJ1wiXScpLmFkZENsYXNzKCdzbGljay1jdXJyZW50Jyk7XG5cdFx0XHRzZXRUaHVtYm5haWxQYWdlQnlTbGlkZShuZXh0U2xpZGUgKyAxKTtcblxuXHRcdFx0Ly8gdmFyICRjdXJyZW50U2xpZGUgPSAkc2luZ2xlSW1hZ2VTbGlkZXMuZmluZCgnW2RhdGEtc2xpY2staW5kZXg9XCInICsgY3VycmVudFNsaWRlICsgJ1wiXScpO1xuXHRcdFx0Ly8gcmVtb3ZlSW1hZ2VWaWV3ZXJPblNsaWRlKCRjdXJyZW50U2xpZGUpO1xuXG5cdFx0XHR2YXIgJG5leHRTbGlkZSA9ICRzaW5nbGVJbWFnZVNsaWRlcy5maW5kKCdbZGF0YS1zbGljay1pbmRleD1cIicgKyBuZXh0U2xpZGUgKyAnXCJdJyk7XG5cdFx0XHQvLyB0dXJuIG9mZiB6b29tIG9uIHZpZGVvIHNsaWRlXG5cdFx0XHRpZiAoISRuZXh0U2xpZGUuaGFzQ2xhc3MoJ2Nhcm91c2VsLXZpZGVvLXNsaWRlJykpIHtcblx0XHRcdFx0aW5pdGlhbGl6ZUltYWdlVmlld2VyT25TbGlkZSgkbmV4dFNsaWRlKTtcblx0XHRcdH1cblx0XHRcdC8vIGluaXRpYWxpemVTbGlkZXNUb1NpZGUoJG5leHRTbGlkZSk7XG5cblx0XHRcdGRhdGFbJ3NpbmdsZUltYWdlU2xpZGVzQ3VycmVudFNsaWRlJ10gPSBuZXh0U2xpZGU7XG5cdFx0fVxuXHR9KTtcblxuICAgIHZhciBzaW5nbGVJbWFnZVNsaWNrT3B0aW9ucyA9IEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuU2luZ2xlO1xuICAgIGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUyB8fCBwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuICAgIFx0c2luZ2xlSW1hZ2VTbGlja09wdGlvbnMuZG90cyA9IHRydWU7XG5cdFx0c2luZ2xlSW1hZ2VTbGlja09wdGlvbnMucmVzcG9uc2l2ZVswXS5zZXR0aW5ncy5hcnJvd3MgPSBmYWxzZTtcblx0fVxuXG5cdCRzaW5nbGVJbWFnZVNsaWRlcy5ub3QoJy5zbGljay1pbml0aWFsaXplZCcpLnNsaWNrKHNpbmdsZUltYWdlU2xpY2tPcHRpb25zKTtcblxuICAgIHZhciBwcm9kdWN0VGh1bWJuYWlsU2xpY2tPcHRpb25zID0gSW1hZ2VDb25zdGFudHMuU2xpY2tTbGlkZXIuT3B0aW9ucy5UaHVtYm5haWw7XG4gICAgaWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0cHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucy52ZXJ0aWNhbCA9IHRydWU7XG5cdH1cblx0JHRodW1ibmFpbEltYWdlU2xpZGVzLm5vdCgnLnNsaWNrLWluaXRpYWxpemVkJykuc2xpY2socHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucyk7XG5cblx0ZGF0YVsndGh1bWJuYWlsc0N1cnJlbnRQYWdlJ10gPSAxO1xuXHRkYXRhWyd0aHVtYm5haWxzTWF4aW11bVNsaWRlJ10gPSAkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWRlJykubGVuZ3RoO1xuXHRkYXRhWyd0aHVtYm5haWxzTWF4aW11bVBhZ2UnXSA9IE1hdGguY2VpbChkYXRhWyd0aHVtYm5haWxzTWF4aW11bVNsaWRlJ10gLyBwcm9kdWN0VGh1bWJuYWlsU2xpY2tPcHRpb25zLnNsaWRlc1RvU2hvdyk7XG5cblx0aWYgKGRhdGFbJ3RodW1ibmFpbHNNYXhpbXVtUGFnZSddIDw9IDEpIHtcblx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5uZXh0JykuYWRkQ2xhc3MoJ2Rpc2FibGUnKTtcblx0fSBlbHNlIHtcblx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5uZXh0JykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGUnKTtcblx0fVxuXG5cdCQoJy5wcm9kdWN0LXRodW1ibmFpbHMtY29udGFpbmVyIC5wcm9kdWN0LXRodW1ibmFpbHMtYXJyb3cnKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBwYWdlRGVsdGEgPSAwO1xuXHRcdGlmICgkdGhpcy5oYXNDbGFzcygnbmV4dCcpKSB7XG5cdFx0XHRwYWdlRGVsdGEgPSAxO1xuXHRcdH0gZWxzZSBpZiAoJHRoaXMuaGFzQ2xhc3MoJ3ByZXZpb3VzJykpIHtcblx0XHRcdHBhZ2VEZWx0YSA9IC0xO1xuXHRcdH1cblxuXHRcdHNldFRodW1ibmFpbFBhZ2UoZGF0YVsndGh1bWJuYWlsc0N1cnJlbnRQYWdlJ10gKyBwYWdlRGVsdGEpO1xuXHR9KTtcblxuXHQkKCcucHJvZHVjdC10aHVtYm5haWxzIC5zbGlkZSBhJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGN1cnJlbnRTbGlkZSA9ICR0aGlzLmNsb3Nlc3QoJy5zbGljay10cmFjaycpLmZpbmQoJy5zbGljay1jdXJyZW50Jyk7XG5cdFx0dmFyIGN1cnJlbnRTbGlkZSA9ICRjdXJyZW50U2xpZGUuZGF0YSgnc2xpY2staW5kZXgnKTtcblx0XHR2YXIgJG5leHRTbGlkZSA9ICR0aGlzLmNsb3Nlc3QoJy5zbGlkZScpO1xuXHRcdHZhciBuZXh0U2xpZGUgPSAkbmV4dFNsaWRlLmRhdGEoJ3NsaWNrLWluZGV4Jyk7XG5cblx0XHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLWN1cnJlbnQnKS5yZW1vdmVDbGFzcygnc2xpY2stY3VycmVudCcpO1xuXHRcdCRuZXh0U2xpZGUuYWRkQ2xhc3MoJ3NsaWNrLWN1cnJlbnQnKTtcblx0XHQkc2luZ2xlSW1hZ2VTbGlkZXMuc2xpY2soJ3NsaWNrR29UbycsIG5leHRTbGlkZSk7XG5cdH0pO1xuXG5cdGNhcm91c2VsVmlkZW8uaW5pdCgpO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplU2xpZGVzVG9TaWRlKCRzbGlkZSkge1xuXHR2YXIgJGxlZnRTbGlkZSA9ICRzbGlkZS5wcmV2KCk7XG5cdGlmICgkbGVmdFNsaWRlLmxlbmd0aCA+IDApIHtcblx0XHRpbml0aWFsaXplSW1hZ2VWaWV3ZXJPblNsaWRlKCRsZWZ0U2xpZGUpO1xuXHR9XG5cblx0dmFyICRyaWdodFNsaWRlID0gJHNsaWRlLm5leHQoKTtcblx0aWYgKCRyaWdodFNsaWRlLmxlbmd0aCA+IDApIHtcblx0XHRpbml0aWFsaXplSW1hZ2VWaWV3ZXJPblNsaWRlKCRyaWdodFNsaWRlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBzZXRUaHVtYm5haWxQYWdlQnlTbGlkZShzZWxlY3RlZFNsaWRlKSB7XG5cdGlmIChzZWxlY3RlZFNsaWRlID49IDEgJiYgc2VsZWN0ZWRTbGlkZSA8PSBkYXRhWyd0aHVtYm5haWxzTWF4aW11bVNsaWRlJ10pIHtcblx0XHRzZXRUaHVtYm5haWxQYWdlKE1hdGguY2VpbChzZWxlY3RlZFNsaWRlIC8gSW1hZ2VDb25zdGFudHMuU2xpY2tTbGlkZXIuT3B0aW9ucy5UaHVtYm5haWwuc2xpZGVzVG9TaG93KSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc2V0VGh1bWJuYWlsUGFnZShzZWxlY3RlZFBhZ2UpIHtcblx0aWYgKHNlbGVjdGVkUGFnZSA+PSAxICYmIHNlbGVjdGVkUGFnZSA8PSBkYXRhWyd0aHVtYm5haWxzTWF4aW11bVBhZ2UnXSkge1xuXHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdFx0dmFyIG9mZnNldFggPSAkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrJykub2Zmc2V0KCkubGVmdCAtICR0aHVtYm5haWxJbWFnZVNsaWRlcy5maW5kKCcuc2xpY2stdHJhY2sgLnNsaWRlW2RhdGEtc2xpY2staW5kZXg9XCInICsgKHNlbGVjdGVkUGFnZSAqIEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuVGh1bWJuYWlsLnNsaWRlc1RvU2hvdyAtIEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuVGh1bWJuYWlsLnNsaWRlc1RvU2hvdykgKyAnXCJdJykub2Zmc2V0KCkubGVmdCArICdweCc7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrJykuY3NzKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlM2QoJyArIG9mZnNldFggKyAnLCAwLCAwKScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgb2Zmc2V0WSA9ICR0aHVtYm5haWxJbWFnZVNsaWRlcy5maW5kKCcuc2xpY2stdHJhY2snKS5vZmZzZXQoKS50b3AgLSAkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrIC5zbGlkZVtkYXRhLXNsaWNrLWluZGV4PVwiJyArIChzZWxlY3RlZFBhZ2UgKiBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlRodW1ibmFpbC5zbGlkZXNUb1Nob3cgLSBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlRodW1ibmFpbC5zbGlkZXNUb1Nob3cpICsgJ1wiXScpLm9mZnNldCgpLnRvcCArICdweCc7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrJykuY3NzKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlM2QoMCwgJyArIG9mZnNldFkgKyAnLCAwKScpO1xuXHRcdH1cblxuXHRcdGlmIChzZWxlY3RlZFBhZ2UgPiAxKSB7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5wcmV2aW91cycpLnJlbW92ZUNsYXNzKCdkaXNhYmxlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCR0aHVtYm5haWxJbWFnZUNvbnRhaW5lci5maW5kKCcucHJvZHVjdC10aHVtYm5haWxzLWFycm93LnByZXZpb3VzJykuYWRkQ2xhc3MoJ2Rpc2FibGUnKTtcblx0XHR9XG5cblx0XHRpZiAoc2VsZWN0ZWRQYWdlIDwgZGF0YVsndGh1bWJuYWlsc01heGltdW1QYWdlJ10pIHtcblx0XHRcdCR0aHVtYm5haWxJbWFnZUNvbnRhaW5lci5maW5kKCcucHJvZHVjdC10aHVtYm5haWxzLWFycm93Lm5leHQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5uZXh0JykuYWRkQ2xhc3MoJ2Rpc2FibGUnKTtcblx0XHR9XG5cblx0XHRkYXRhWyd0aHVtYm5haWxzQ3VycmVudFBhZ2UnXSA9IHNlbGVjdGVkUGFnZTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW1vdmVJbWFnZVZpZXdlck9uU2xpZGUoJHNsaWRlKSB7XG5cdGlmICgkc2xpZGUuZmluZCgnaW1nLmhpZ2gtcmVzb2x1dGlvbicpLmxlbmd0aCA+IDApIHtcblx0XHQkc2xpZGUuZmluZCgnaW1nJykucmVtb3ZlQ2xhc3MoJ2hpZ2gtcmVzb2x1dGlvbicpLmltZ1ZpZXdlcjIoJ2Rlc3Ryb3knKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplSW1hZ2VWaWV3ZXJPblNsaWRlKCRzbGlkZVRvSW5pdGlhbGl6ZSkge1xuXHRpZiAoJHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5sZW5ndGggPT0gMCkge1xuXHRcdCRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcnKS5hdHRyKCdzcmMnLCAkc2xpZGVUb0luaXRpYWxpemUuZmluZCgnYS56b29tZWRJbWFnZScpLmF0dHIoJ2hyZWYnKSkuYWRkQ2xhc3MoJ2hpZ2gtcmVzb2x1dGlvbicpLmltZ1ZpZXdlcjIoe1xuXHRcdFx0em9vbU1heDogNCxcblx0XHRcdGRyYWdhYmxlOiBmYWxzZSxcblx0XHRcdG9uUmVhZHk6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgaW1nVmlld2VyMiA9IHRoaXM7XG5cdFx0XHRcdHZhciBtYXAgPSB0aGlzLm1hcDtcblxuXHRcdFx0XHRpbWdWaWV3ZXIyLnNldFpvb20oMSk7XG5cdFx0XHRcdGlmIChtYXAgJiYgbWFwLnRhcCkge1xuXHRcdFx0XHRcdG1hcC50YXAuZGlzYWJsZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChtYXAgJiYgbWFwLmRyYWdnaW5nKSB7XG5cdFx0XHRcdFx0bWFwLmRyYWdnaW5nLmRpc2FibGUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQobWFwLmdldENvbnRhaW5lcigpKS5vZmYoJ3doZWVsJykub24oJ3doZWVsJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0XHR2YXIgd2hlZWxTY3JvbGxBbmltYXRpb25UYXJnZXREZWx0YSA9IDA7XG5cblx0XHRcdFx0XHRpZiAoZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb24nXSkge1xuXHRcdFx0XHRcdFx0d2hlZWxTY3JvbGxBbmltYXRpb25UYXJnZXREZWx0YSA9IGRhdGFbJ3doZWVsU2Nyb2xsQW5pbWF0aW9uVGFyZ2V0J10gLSAkKHdpbmRvdykuc2Nyb2xsVG9wKCk7XG5cdFx0XHRcdFx0XHRkYXRhWyd3aGVlbFNjcm9sbEFuaW1hdGlvbiddLnN0b3AoKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgem9vbUxldmVsID0gaW1nVmlld2VyMi5nZXRab29tKCk7XG5cdFx0XHRcdFx0dmFyIHpvb21NYXhpbXVtID0gJHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdvcHRpb24nLCAnem9vbU1heCcpO1xuXHRcdFx0XHRcdGlmICgoem9vbUxldmVsID09IDEgJiYgZXZlbnQub3JpZ2luYWxFdmVudC5kZWx0YVkgPiAwKSB8fCAoem9vbUxldmVsID4gKHpvb21NYXhpbXVtIC0gMC41KSkgJiYgZXZlbnQub3JpZ2luYWxFdmVudC5kZWx0YVkgPCAwKSB7XG5cdFx0XHRcdFx0XHRkYXRhWyd3aGVlbFNjcm9sbEFuaW1hdGlvblRhcmdldCddID0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpICsgZXZlbnQub3JpZ2luYWxFdmVudC5kZWx0YVkgKyB3aGVlbFNjcm9sbEFuaW1hdGlvblRhcmdldERlbHRhO1xuXHRcdFx0XHRcdFx0ZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb24nXSA9ICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHtcblx0XHRcdFx0XHRcdFx0c2Nyb2xsVG9wOiBkYXRhWyd3aGVlbFNjcm9sbEFuaW1hdGlvblRhcmdldCddXG5cdFx0XHRcdFx0XHR9LCB7XG5cdFx0XHRcdFx0XHRcdGR1cmF0aW9uOiAnZmFzdCcsXG5cdFx0XHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbigpIHsgXG5cdFx0XHRcdFx0XHRcdFx0ZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb24nXSA9IG51bGw7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0bWFwLm9uKCd6b29tJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0XHR2YXIgem9vbUxldmVsID0gaW1nVmlld2VyMi5nZXRab29tKCk7XG5cblx0XHRcdFx0XHRpZiAoem9vbUxldmVsID4gMS4wNSkge1xuXHRcdFx0XHRcdFx0JHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdvcHRpb24nLCAnZHJhZ2FibGUnLCB0cnVlKTtcblxuXHRcdFx0XHRcdFx0aWYgKG1hcCAmJiBtYXAudGFwKSB7XG5cdFx0XHRcdFx0XHRcdG1hcC50YXAuZW5hYmxlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAobWFwICYmIG1hcC5kcmFnZ2luZykge1xuXHRcdFx0XHRcdFx0XHRtYXAuZHJhZ2dpbmcuZW5hYmxlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQkKCcuc2xpZGVyLXNpbmdsZS1pbWFnZSAuc2xpZGVzJykuc2xpY2soJ3NsaWNrU2V0T3B0aW9uJywgJ2RyYWdnYWJsZScsIGZhbHNlLCB0cnVlKTtcblx0XHRcdFx0XHRcdCQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKS5zbGljaygnc2xpY2tTZXRPcHRpb24nLCAnc3dpcGUnLCBmYWxzZSwgdHJ1ZSk7XG5cdFx0XHRcdFx0XHQkKCcuc2xpZGVyLXNpbmdsZS1pbWFnZSAuc2xpZGVzJykuc2xpY2soJ3NsaWNrU2V0T3B0aW9uJywgJ3RvdWNoTW92ZScsIGZhbHNlLCB0cnVlKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdvcHRpb24nLCAnZHJhZ2FibGUnLCBmYWxzZSk7XG5cblx0XHRcdFx0XHRcdGlmIChtYXAgJiYgbWFwLnRhcCkge1xuXHRcdFx0XHRcdFx0XHRtYXAudGFwLmRpc2FibGUoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChtYXAgJiYgbWFwLmRyYWdnaW5nKSB7XG5cdFx0XHRcdFx0XHRcdG1hcC5kcmFnZ2luZy5kaXNhYmxlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQkKCcuc2xpZGVyLXNpbmdsZS1pbWFnZSAuc2xpZGVzJykuc2xpY2soJ3NsaWNrU2V0T3B0aW9uJywgJ2RyYWdnYWJsZScsIHRydWUsIHRydWUpO1xuXHRcdFx0XHRcdFx0JCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLnNsaWNrKCdzbGlja1NldE9wdGlvbicsICdzd2lwZScsIHRydWUsIHRydWUpO1xuXHRcdFx0XHRcdFx0JCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLnNsaWNrKCdzbGlja1NldE9wdGlvbicsICd0b3VjaE1vdmUnLCB0cnVlLCB0cnVlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdHZhciBzbGlkZUltYWdlTWFwID0gJHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdnZXRNYXAnKTtcblx0XHRpZiAoc2xpZGVJbWFnZU1hcCkge1xuXHRcdFx0c2xpZGVJbWFnZU1hcC5pbnZhbGlkYXRlU2l6ZSgpO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBtYXBSZXNpemVUaW1lckhhbmRsZXIoKSB7XG5cdGlmIChkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0luaXRpYWxTbGlkZSddICE9IHVuZGVmaW5lZCkge1xuXHRcdHZhciAkaW5pdGlhbFNsaWRlID0gJCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLmZpbmQoJ1tkYXRhLXNsaWNrLWluZGV4PVwiJyArIGRhdGFbJ3NpbmdsZUltYWdlU2xpZGVzSW5pdGlhbFNsaWRlJ10gKyAnXCJdJyk7XG5cdFx0cmVzaXplU2xpZGVyVG9NYXRjaFNsaWRlKCRpbml0aWFsU2xpZGUpO1xuXG4gICAgICAgIHZhciBzbGljayA9ICRzaW5nbGVJbWFnZVNsaWRlcy5zbGljaygnZ2V0U2xpY2snKTtcbiAgICAgICAgdmFyICRjdXJyZW50U2xpZGUgPSAkc2luZ2xlSW1hZ2VTbGlkZXMuZmluZCgnW2RhdGEtc2xpY2staW5kZXg9XCInICsgc2xpY2suY3VycmVudFNsaWRlICsgJ1wiXScpO1xuXHRcdHZhciBjdXJyZW50U2xpZGVJbWFnZU1hcCA9ICRjdXJyZW50U2xpZGUuZmluZCgnaW1nLmhpZ2gtcmVzb2x1dGlvbicpLmltZ1ZpZXdlcjIoJ2dldE1hcCcpO1xuXHRcdGlmIChjdXJyZW50U2xpZGVJbWFnZU1hcCkge1xuXHRcdFx0Y3VycmVudFNsaWRlSW1hZ2VNYXAuaW52YWxpZGF0ZVNpemUoKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVzaXplU2xpZGVyVG9NYXRjaFNsaWRlKCRzbGlkZSkge1xuXHR2YXIgJHNsaWRlVHJhY2sgPSAkc2xpZGUuY2xvc2VzdCgnLnNsaWNrLXRyYWNrJyk7XG5cdCRzbGlkZVRyYWNrLmNzcygnaGVpZ2h0JywgJ2F1dG8nKTtcblxuXHR2YXIgJHNsaWRlSW1hZ2UgPSAkc2xpZGUuZmluZCgnLnNsaWRlLWltYWdlID4gaW1nJyk7XG5cdHZhciBzbGlkZUltYWdlSGVpZ2h0ID0gJHNsaWRlLmhlaWdodCgpO1xuXHR2YXIgc2xpZGVJbWFnZVdpZHRoID0gJHNsaWRlLndpZHRoKCk7XG5cdHZhciBzbGlkZUFzcGVjdFJhdGlvID0gc2xpZGVJbWFnZVdpZHRoIC8gc2xpZGVJbWFnZUhlaWdodDtcblxuXHQkc2xpZGVUcmFjay5jc3MoJ2hlaWdodCcsIHNsaWRlSW1hZ2VIZWlnaHQpO1xuXHQkc2xpZGVUcmFjay5maW5kKCcuc2xpY2stc2xpZGUnKS5ub3QoJHNsaWRlKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICR0aGlzSW1hZ2UgPSAkdGhpcy5maW5kKCcuc2xpZGUtaW1hZ2UgPiBpbWcnKTtcblx0XHR2YXIgdGhpc0ltYWdlQXNwZWN0UmF0aW8gPSAkdGhpc0ltYWdlLndpZHRoKCkgLyAkdGhpc0ltYWdlLmhlaWdodCgpO1xuXG5cdFx0aWYgKCR0aGlzSW1hZ2UuaGVpZ2h0KCkgPiBzbGlkZUltYWdlSGVpZ2h0ICYmIHRoaXNJbWFnZUFzcGVjdFJhdGlvIDw9IHNsaWRlQXNwZWN0UmF0aW8pIHtcblx0XHRcdCR0aGlzLmFkZENsYXNzKCdjb25zdHJhaW4taGVpZ2h0Jyk7XG5cdFx0fVxuXHR9KTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjYXJvdXNlbFZpZGVvID0gcmVxdWlyZSgnLi4vQ2Fyb3VzZWxWaWRlbycpO1xuXG4vLyBHbG9iYWwgdmFyc1xudmFyIG9wdGlvbnM7XG52YXIgaXNNb2JpbGUgPSB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3Njc7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUocGFyYW1zKSB7XG5cdGlmIChwYXJhbXMpIHtcblx0XHRvcHRpb25zID0gcGFyYW1zO1xuXHR9XG5cdHZhciB0aHVtYkdhbGxlcnlTd2lwZXIsIGxhcmdlU3dpcGVyLFxuXHRcdHRodW1iR2FsbGVyeUJyZWFrcG9pbnRzID0gb3B0aW9ucyAmJiBvcHRpb25zLnRodW1iR2FsbGVyeUJyZWFrcG9pbnRzID8gb3B0aW9ucy50aHVtYkdhbGxlcnlCcmVha3BvaW50cyA6IG51bGwsXG5cdFx0dGh1bWJHYWxsZXJ5QnJlYWtwb2ludFNldHRpbmdzID0gdGh1bWJHYWxsZXJ5QnJlYWtwb2ludHMgPyAoaXNNb2JpbGUgPyB0aHVtYkdhbGxlcnlCcmVha3BvaW50c1snMCddIDogdGh1bWJHYWxsZXJ5QnJlYWtwb2ludHNbJzc2OCddKSA6IG51bGwsXG5cdFx0ZW5hYmxlVGh1bWJHYWxsZXJ5Rm9yQ3VycmVudEJyZWFrcG9pbnQgPSB0aHVtYkdhbGxlcnlCcmVha3BvaW50U2V0dGluZ3MgJiYgdGh1bWJHYWxsZXJ5QnJlYWtwb2ludFNldHRpbmdzLmVuYWJsZWQsXG5cdFx0aXNUaHVtYm5haWxzRWxtID0gJCgnLnRodW1icy1wcm9kdWN0LXN3aXBlcicpLmxlbmd0aCA+IDA7XG5cblx0Ly8gQ2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYW55IHRodW1ibmFpbHMgYXQgYWxsXG5cdGlmIChpc1RodW1ibmFpbHNFbG0pIHtcblx0XHQvLyBJbml0aWFsaXplIHRodW1ibmFpbHMgZ2FsbGVyeSBhbmQgYXNzaWduIGluc3RhbmNlIHRvICd0aHVtYkdhbGxlcnlTd2lwZXInXG5cdFx0aWYgKGVuYWJsZVRodW1iR2FsbGVyeUZvckN1cnJlbnRCcmVha3BvaW50KSB7XG5cdFx0XHR0aHVtYkdhbGxlcnlTd2lwZXIgPSB0aHVtYkdhbGxlcnlTd2lwZXJJbml0KG9wdGlvbnMpO1xuXHRcdFx0Ly8gVGh1bWJuYWlsIHNsaWRlciBtb2RpZmljYXRpb25zIC0gY2FuIG9ubHkgbWFrZSBtb2RzIGFmdGVyIHRodW1icyBnYWxsZXJ5IHNsaWRlciBoYXMgYmVlbiBpbml0aWFsaXplZC5cblx0XHRcdC8vIE5vIGRlZmF1bHQgYXJyb3cgbmF2aWdhdGlvbiBleGlzdHMgZm9yIHRodW1ibmFpbHMgZ2FsbGVyeSBpbiBzd2lwZXIsIHNvIHdlIGFkZCBvdXIgb3duLlxuXHRcdFx0dGh1bWJHYWxsZXJ5TmF2aWdhdGlvbihvcHRpb25zLCB0aHVtYkdhbGxlcnlTd2lwZXIsIHRodW1iR2FsbGVyeUJyZWFrcG9pbnRTZXR0aW5ncyk7XG5cdFx0XHRpZiAoaXNNb2JpbGUpIHtcblx0XHRcdFx0JCgnLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyLW1vYmlsZScpLmFkZENsYXNzKCdzd2lwZXItdGh1bWJzLW1vYmlsZS1lZGl0cycpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcudGh1bWJzLXByb2R1Y3Qtc3dpcGVyJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdH1cblx0XHQvLyBJbml0aWFsaXplIFBEUCBtYWluIGltYWdlIHN3aXBlciBhbmQgcGFzcyBpbiB0aHVtYm5haWxzIGdhbGxlcnkgaWYgaXQgZXhpc3RzXG5cdFx0bGFyZ2VTd2lwZXIgPSBsYXJnZVN3aXBlckluaXQob3B0aW9ucywgdGh1bWJHYWxsZXJ5U3dpcGVyKTtcblx0fSBlbHNlIHtcblx0XHRsYXJnZVN3aXBlciA9IGxhcmdlU3dpcGVySW5pdChvcHRpb25zLCBudWxsKTtcblx0fVxuXG5cdGlmIChvcHRpb25zLnpvb20pIHtcblx0XHQkKCcjcGRwTWFpbicpLm9mZignY2xpY2suVmFyaWFudC5Td2lwZXIuWm9vbS5JbicpLm9uKCdjbGljay5WYXJpYW50LlN3aXBlci5ab29tLkluJywgJy5jdXN0b20ubGVhZmxldC1jb250cm9sLXpvb20taW4nLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0bGFyZ2VTd2lwZXIuem9vbS5pbigpO1xuXHRcdH0pO1xuXHRcdFxuXHRcdCQoJyNwZHBNYWluJykub2ZmKCdjbGljay5WYXJpYW50LlN3aXBlci5ab29tLk91dCcpLm9uKCdjbGljay5WYXJpYW50LlN3aXBlci5ab29tLk91dCcsICcuY3VzdG9tLmxlYWZsZXQtY29udHJvbC16b29tLW91dCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRsYXJnZVN3aXBlci56b29tLm91dCgpO1xuXHRcdH0pO1xuXHR9XG5cblx0Y2Fyb3VzZWxWaWRlby5pbml0KCk7XG59XG5cbmZ1bmN0aW9uIHRodW1iR2FsbGVyeVN3aXBlckluaXQob3B0aW9ucykge1xuXHQvLyBUaHVtYm5haWxzIHN3aXBlciBvcHRpb25zXG5cdHZhciB0aHVtYm5haWxzU3dpcGVyT3B0aW9ucyA9IHtcblx0XHRkaXJlY3Rpb246IGlzTW9iaWxlID8gJ2hvcml6b250YWwnIDondmVydGljYWwnLFxuXHRcdHNsaWRlc1BlclZpZXc6IDcsXG5cdFx0c2xpZGVzUGVyR3JvdXA6IDcsXG5cdFx0bG9vcDogZmFsc2UsXG5cdFx0c2xpZGVUb0NsaWNrZWRTbGlkZTogdHJ1ZSxcblx0XHRhbGxvd1RvdWNoTW92ZTogdHJ1ZSxcblx0XHRhMTF5OiB7XG4gICAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgZmlyc3RTbGlkZU1lc3NhZ2U6ICdUaGlzIGlzIHRoZSBmaXJzdCBzbGlkZScsXG4gICAgICAgICAgICBsYXN0U2xpZGVNZXNzYWdlOiAnVGhpcyBpcyB0aGUgbGFzdCBzbGlkZSdcbiAgICAgICAgfSxcblx0XHRrZXlib2FyZDoge1xuXHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdHBhZ2VVcERvd246IHRydWVcblx0XHR9XG5cdH07XG5cblx0aWYgKG9wdGlvbnMudGh1bWJHYWxsZXJ5U2Nyb2xsRGlyZWN0aW9uKSB7XG5cdFx0dGh1bWJuYWlsc1N3aXBlck9wdGlvbnMuZGlyZWN0aW9uID0gaXNNb2JpbGUgPyAnaG9yaXpvbnRhbCcgOiBvcHRpb25zLnRodW1iR2FsbGVyeVNjcm9sbERpcmVjdGlvbjtcblx0fVxuXG5cdC8vIEluaXRpYXRlIHRodW1ibmFpbHMgc3dpcGVyXG5cdHJldHVybiBuZXcgU3dpcGVyICgnLnRodW1icy1wcm9kdWN0LXN3aXBlcicsIHRodW1ibmFpbHNTd2lwZXJPcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gbGFyZ2VTd2lwZXJJbml0KG9wdGlvbnMsIHRodW1ibmFpbHNTd2lwZXIpIHtcblx0dmFyIGxhcmdlU3dpcGVyT3B0aW9ucztcblx0dmFyIG1vYmlsZURvdHMgPSBvcHRpb25zLmJyZWFrcG9pbnRzICYmIG9wdGlvbnMuYnJlYWtwb2ludHNbJzAnXSAmJiBvcHRpb25zLmJyZWFrcG9pbnRzWycwJ10uZG90cyA/IG9wdGlvbnMuYnJlYWtwb2ludHNbJzAnXS5kb3RzIDogdHJ1ZTtcblx0dmFyIGRlc2t0b3BEb3RzID0gb3B0aW9ucy5icmVha3BvaW50cyAmJiBvcHRpb25zLmJyZWFrcG9pbnRzWyc3NjgnXSAmJiBvcHRpb25zLmJyZWFrcG9pbnRzWyc3NjgnXS5kb3RzID8gb3B0aW9ucy5icmVha3BvaW50c1snNzY4J10uZG90cyA6IGZhbHNlO1xuXG5cdC8vIExhcmdlIHByb2R1Y3Qgc3dpcGVyIG9wdGlvbnNcblx0bGFyZ2VTd2lwZXJPcHRpb25zID0ge1xuXHRcdHNsaWRlc1BlclZpZXc6IDEsXG5cdFx0Y2VudGVyZWRTbGlkZXM6IHRydWUsXG5cdFx0bG9vcDogZmFsc2UsXG5cdFx0YTExeToge1xuICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgIGZpcnN0U2xpZGVNZXNzYWdlOiAnVGhpcyBpcyB0aGUgZmlyc3Qgc2xpZGUnLFxuICAgICAgICAgICAgbGFzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGxhc3Qgc2xpZGUnXG4gICAgICAgIH0sXG5cdFx0a2V5Ym9hcmQ6IHtcblx0XHRcdGVuYWJsZWQ6IHRydWUsXG5cdFx0XHRwYWdlVXBEb3duOiB0cnVlXG5cdFx0fSxcblx0XHRicmVha3BvaW50czoge1xuXHRcdFx0MDoge1xuXHRcdFx0XHRwYWdpbmF0aW9uOiB7XG5cdFx0XHRcdFx0ZW5hYmxlZDogbW9iaWxlRG90cyxcblx0XHRcdFx0XHRlbDogJy5zd2lwZXItcGFnaW5hdGlvbicsXG5cdFx0XHRcdFx0Y2xpY2thYmxlOiB0cnVlXG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHQ3Njg6IHtcblx0XHRcdFx0cGFnaW5hdGlvbjoge1xuXHRcdFx0XHRcdGVuYWJsZWQ6IGRlc2t0b3BEb3RzLFxuXHRcdFx0XHRcdGVsOiAnLnN3aXBlci1wYWdpbmF0aW9uJyxcblx0XHRcdFx0XHRjbGlja2FibGU6IHRydWVcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHRpZiAoZGVza3RvcERvdHMgfHwgbW9iaWxlRG90cykge1xuXHRcdHZhciBtb2RpZmllckNsYXNzO1xuXHRcdGlmICghZGVza3RvcERvdHMgJiYgbW9iaWxlRG90cykge1xuXHRcdFx0bW9kaWZpZXJDbGFzcyA9ICdzd2lwZXItcGFnaW5hdGVkLW1vYmlsZS0nO1xuXHRcdH1cblx0XHRpZiAoZGVza3RvcERvdHMgJiYgIW1vYmlsZURvdHMpIHtcblx0XHRcdG1vZGlmaWVyQ2xhc3MgPSAnc3dpcGVyLXBhZ2luYXRlZC1kZXNrdG9wLSc7XG5cdFx0fVxuXHRcdGlmIChkZXNrdG9wRG90cyAmJiBtb2JpbGVEb3RzKSB7XG5cdFx0XHRtb2RpZmllckNsYXNzID0gJ3N3aXBlci1wYWdpbmF0ZWQtYm90aC0nO1xuXHRcdH1cblx0XHRpZiAobW9kaWZpZXJDbGFzcykge1xuXHRcdFx0bGFyZ2VTd2lwZXJPcHRpb25zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3MgPSBtb2RpZmllckNsYXNzO1xuXHRcdH1cblx0fVxuXG5cdGlmIChvcHRpb25zLnpvb20pIHtcblx0XHRsYXJnZVN3aXBlck9wdGlvbnMuem9vbSA9IHtcblx0XHRcdG1heFJhdGlvOiAzLFxuXHRcdFx0bWluUmF0aW86IDFcblx0XHR9XG5cdH1cblxuXHRpZiAodGh1bWJuYWlsc1N3aXBlcikge1xuXHRcdGxhcmdlU3dpcGVyT3B0aW9ucy50aHVtYnMgPSB7XG5cdFx0XHRzd2lwZXI6IHRodW1ibmFpbHNTd2lwZXJcblx0XHR9XG5cdH1cblxuXHQvLyBJbml0aWF0ZSBsYXJnZSBwcm9kdWN0IHN3aXBlclxuXHRyZXR1cm4gbmV3IFN3aXBlciAoJy5sYXJnZS1wcm9kdWN0LXN3aXBlcicsIGxhcmdlU3dpcGVyT3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIHRodW1iR2FsbGVyeU5hdmlnYXRpb24ob3B0aW9ucywgc3dpcGVySW5zdGFuY2UsIGJyZWFrcG9pbnRTZXR0aW5ncykge1xuXHR2YXIgJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50ID0gJCgnLnRodW1icy1wcm9kdWN0LXN3aXBlcicpO1xuXHRpZiAoISRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudCB8fCAhc3dpcGVySW5zdGFuY2UgfHwgIWJyZWFrcG9pbnRTZXR0aW5ncyB8fCAkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuZmluZCgnLnN3aXBlci1zbGlkZScpLmxlbmd0aCA8IDgpIHtcblx0XHRyZXR1cm47XG5cdH0gZWxzZSB7XG5cdFx0dmFyIGFkZE5hdmlnYXRpb24gPSBicmVha3BvaW50U2V0dGluZ3MgPyAoYnJlYWtwb2ludFNldHRpbmdzLmFycm93cyA/IGJyZWFrcG9pbnRTZXR0aW5ncy5hcnJvd3MgOiBmYWxzZSkgOiBudWxsLFxuXHRcdFx0aXNWZXJ0aWNhbCA9ICRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudC5oYXNDbGFzcygnc3dpcGVyLXZlcnRpY2FsJyksXG5cdFx0XHRpc0hvcml6b250YWwgPSAkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuaGFzQ2xhc3MoJ3N3aXBlci1ob3Jpem9udGFsJyksXG5cdFx0XHR0aHVtYkdhbGxlcnlTbGlkZXMgPSAkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuZmluZCgnLnN3aXBlci1zbGlkZScpLFxuXHRcdFx0dGh1bWJzRGlyZWN0aW9uQ2xhc3MgPSBpc1ZlcnRpY2FsID8gJ3RodW1icy12ZXJ0aWNhbCcgOiAndGh1bWJzLWhvcml6b250YWwnLCBcblx0XHRcdCR0aHVtYm5haWxzTmF2aWdhdGlvbiA9ICQoJzxkaXYgLz4nLCB7ICdjbGFzcyc6ICd0aHVtYnMtcHJvZHVjdC1uYXZpZ2F0aW9uJyB9KSxcblx0XHRcdGNhcmV0cztcblxuXHRcdFx0aWYgKGFkZE5hdmlnYXRpb24pIHtcblx0XHRcdFx0aWYgKGlzVmVydGljYWwpIHtcblx0XHRcdFx0XHRjYXJldHMgPSAnPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1hbmdsZS11cCBkLW5vbmVcIj48L2k+PGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1hbmdsZS1kb3duXCI+PC9pPic7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGlzSG9yaXpvbnRhbCkge1xuXHRcdFx0XHRcdGNhcmV0cyA9ICc8aSBjbGFzcz1cImZhLXNvbGlkIGZhLWFuZ2xlLWxlZnQgZC1ub25lXCI+PC9pPjxpIGNsYXNzPVwiZmEtc29saWQgZmEtYW5nbGUtcmlnaHRcIj48L2k+Jztcblx0XHRcdFx0fVxuXHRcdFx0XHQkdGh1bWJuYWlsc05hdmlnYXRpb24uaHRtbChjYXJldHMpLmFkZENsYXNzKHRodW1ic0RpcmVjdGlvbkNsYXNzKS5pbnNlcnRCZWZvcmUoJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50KTtcblx0XHRcdFx0dmFyIHByZXZJY29ucyA9ICcudGh1bWJzLXByb2R1Y3QtbmF2aWdhdGlvbiAuZmEtYW5nbGUtdXAsIC50aHVtYnMtcHJvZHVjdC1uYXZpZ2F0aW9uIC5mYS1hbmdsZS1sZWZ0Jztcblx0XHRcdFx0dmFyIG5leHRJY29ucyA9ICcudGh1bWJzLXByb2R1Y3QtbmF2aWdhdGlvbiAuZmEtYW5nbGUtZG93biwgLnRodW1icy1wcm9kdWN0LW5hdmlnYXRpb24gLmZhLWFuZ2xlLXJpZ2h0Jztcblx0XHRcdFx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgcHJldkljb25zLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRzd2lwZXJJbnN0YW5jZS5zbGlkZVByZXYoNTAwKTtcblx0XHRcdFx0XHR2YXIgcHJldkljb25zRmlyc3RWaXNpYmxlSW5kZXggPSB0aHVtYkdhbGxlcnlTbGlkZXMuaW5kZXgoJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50LmZpbmQoJy5zd2lwZXItc2xpZGUtdmlzaWJsZTpmaXJzdCcpKTtcblx0XHRcdFx0XHR2YXIgcHJldkljb25zTGFzdFZpc2libGVJbmRleCA9IHRodW1iR2FsbGVyeVNsaWRlcy5pbmRleCgkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuZmluZCgnLnN3aXBlci1zbGlkZS12aXNpYmxlOmxhc3QnKSk7XG5cdFx0XHRcdFx0aWYgKHByZXZJY29uc0ZpcnN0VmlzaWJsZUluZGV4ID09IDApIHtcblx0XHRcdFx0XHRcdCQocHJldkljb25zKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQocHJldkljb25zKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChwcmV2SWNvbnNMYXN0VmlzaWJsZUluZGV4IDwgNykge1xuXHRcdFx0XHRcdFx0JChuZXh0SWNvbnMpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JChuZXh0SWNvbnMpLmFkZENsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCBuZXh0SWNvbnMsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHN3aXBlckluc3RhbmNlLnNsaWRlTmV4dCg1MDApO1xuXHRcdFx0XHRcdHZhciBuZXh0SWNvbnNMYXN0VmlzaWJsZUluZGV4ID0gdGh1bWJHYWxsZXJ5U2xpZGVzLmluZGV4KCRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudC5maW5kKCcuc3dpcGVyLXNsaWRlLXZpc2libGU6bGFzdCcpKTtcblx0XHRcdFx0XHRpZiAobmV4dEljb25zTGFzdFZpc2libGVJbmRleCA9PSAodGh1bWJHYWxsZXJ5U2xpZGVzLmxlbmd0aCAtIDEpKSB7XG5cdFx0XHRcdFx0XHQkKG5leHRJY29ucykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkKG5leHRJY29ucykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAobmV4dEljb25zTGFzdFZpc2libGVJbmRleCA+IDYpIHtcblx0XHRcdFx0XHRcdCQocHJldkljb25zKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQocHJldkljb25zKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcdFxuXHRcdFx0fVxuXHR9XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG5cbiQud2lkZ2V0KCdib290YmFybi5sb2FkaW5nJywge1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgSXNJbWFnZVNob3duOiB0cnVlLFxuICAgICAgICBJc0xhYmVsU2hvd246IHRydWUsXG4gICAgICAgIExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb2FkaW5nLFxuICAgICAgICBDb250ZW50OiAnJyxcbiAgICAgICAgQ3NzQ2xhc3M6ICcnLFxuICAgICAgICBCYWNrZ3JvdW5kQ29sb3I6IG51bGxcbiAgICB9LFxuXG4gICAgX2NyZWF0ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5hdHRyKCdsb2FkaW5nJywgJ2xvYWRpbmcnKTtcblxuICAgICAgICB2YXIgbG9hZGluZ0luZGljYXRvclRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtbG9hZGluZy1pbmRpY2F0b3InKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgICAgIHZhciAkbG9hZGluZ0luZGljYXRvckNvbnRhaW5lciA9ICQobG9hZGluZ0luZGljYXRvclRlbXBsYXRlKHtcbiAgICAgICAgXHRDb250ZW50OiB0aGlzLm9wdGlvbnMuQ29udGVudFxuICAgICAgICB9KSk7XG4gICAgICAgIHZhciAkbG9hZGluZ0luZGljYXRvciA9ICRsb2FkaW5nSW5kaWNhdG9yQ29udGFpbmVyLmZpbmQoJy5sb2FkaW5nLWluZGljYXRvcicpO1xuICAgICAgICAkbG9hZGluZ0luZGljYXRvckNvbnRhaW5lci5jc3MoJ2JhY2tncm91bmQtY29sb3InLCB0aGlzLm9wdGlvbnMuQmFja2dyb3VuZENvbG9yID8gdGhpcy5vcHRpb25zLkJhY2tncm91bmRDb2xvciA6IHRoaXMuZWxlbWVudC5jc3MoJ2JhY2tncm91bmQtY29sb3InKSk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5Dc3NDbGFzcykge1xuICAgICAgICAgICAgJGxvYWRpbmdJbmRpY2F0b3JDb250YWluZXIuYWRkQ2xhc3ModGhpcy5vcHRpb25zLkNzc0NsYXNzKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5Jc0xhYmVsU2hvd24gJiYgIXRoaXMub3B0aW9ucy5Db250ZW50KSB7XG4gICAgICAgICAgICAkbG9hZGluZ0luZGljYXRvci5hZGRDbGFzcygnbGFiZWwnKTtcbiAgICAgICAgICAgICRsb2FkaW5nSW5kaWNhdG9yLmF0dHIoJ2xhYmVsJywgdGhpcy5vcHRpb25zLkxhYmVsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuSXNJbWFnZVNob3duKSB7XG4gICAgICAgICAgICAkbG9hZGluZ0luZGljYXRvci5hZGRDbGFzcygnaW1hZ2UnKTtcbiAgICAgICAgfVxuXG5cdFx0JGxvYWRpbmdJbmRpY2F0b3JDb250YWluZXIuYXBwZW5kVG8odGhpcy5lbGVtZW50KTtcblx0fSxcbiAgICBcbiAgICBfZGVzdHJveTogZnVuY3Rpb24oKSB7XG5cdFx0dGhpcy5lbGVtZW50LnJlbW92ZUF0dHIoJ2xvYWRpbmcnKS5maW5kKCcubG9hZGluZy1pbmRpY2F0b3ItY29udGFpbmVyJykucmVtb3ZlKCk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbmV4cG9ydHMuSW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5leHBvcnRzLkNsb3NlTmF2aWdhdGlvbiA9IGNsb3NlTmF2aWdhdGlvbjtcblxudmFyIG5hdkRhdGFCdWZmZXIgPSB7fTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcblx0dmFyIHNpdGVOYW1lID0gJCgnLnRvcC1iYW5uZXItYmFyJykuZGF0YSgnaGVhZGVyLWZvcicpIHx8IFwiXCI7XG5cdHZhciAkbmF2U2Vjb25kYXJ5ID0gJCgnLm5hdi1zZWNvbmRhcnknKTtcblx0XG5cdCQoJy5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykucGFyZW50KCkuYWRkQ2xhc3MoJ2hhcy1kcm9wZG93bicpO1xuXHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPCAxMDI0KSB7XG5cdFx0XHQkbmF2U2Vjb25kYXJ5LmZpbmQoJ2xpI2xvY2F0aW9uJykucmVtb3ZlQ2xhc3MoJ2hhcy1kcm9wZG93bicpO1xuXHRcdH1cblx0fVxuXG5cdC8vIEJvb3RCYXJuIDIwMjAgRnVsbCB3aWR0aCBuYXYgZHJvcCBkb3duIGhlbHBlclxuXHRpZiAoJCgnLnRvcC1iYW5uZXItYmFyJykuZGF0YSgnaGVhZGVyLWZvcicpID09ICdib290YmFybl91cycpIHtcblx0XHQvLyBtYWluIG5hdiBob3ZlciBlZmZlY3RzXHRcdFxuXHRcdCQoJ2h0bWwgI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bicpLmhvdmVyKGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmICghJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpKSB7XG5cdFx0XHRcdCQodGhpcykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJy50b3AtYmFubmVyJykuYWRkQ2xhc3MoJ25hdi1hY3RpdmUnKTtcblx0XHRcdFx0JCgnaHRtbCcpLmFkZENsYXNzKCdkZXNrdG9wLW5hdi1hY3RpdmUnKTtcblx0XHRcdFx0JCgnLm5hdi1jb3ZlcicpLnNob3coKTtcblx0XHRcdH1cblx0XHR9LCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuXHRcdFx0XHQkKCcubmF2LWNvdmVyJykuaGlkZSgpO1xuXHRcdFx0XHQkKCcudG9wLWJhbm5lcicpLnJlbW92ZUNsYXNzKCduYXYtYWN0aXZlJyk7XG5cdFx0XHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnZGVza3RvcC1uYXYtYWN0aXZlJyk7XG5cdFx0XHRcdCQodGhpcykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdFxuXHRpZiAoJG5hdlNlY29uZGFyeS5maW5kKCcjbG9jYXRpb24tZGlzcGxheS1jYXB0aW9uJykubGVuZ3RoID4gMCAmJiAkbmF2U2Vjb25kYXJ5LmZpbmQoJyNsb2NhdGlvbi1kaXNwbGF5LWNhcHRpb24nKS5oYXNDbGFzcygnbm8tc3RvcmUtdG8tZGlzcGxheScpKSB7XG5cdFx0aWYgKCRuYXZTZWNvbmRhcnkuZmluZCgnI2xvY2F0aW9uLWRpc3BsYXktY2FwdGlvbicpLnBhcmVudHMoJyNsb2NhdGlvbicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCRuYXZTZWNvbmRhcnkuZmluZCgnI2xvY2F0aW9uLWRpc3BsYXktY2FwdGlvbicpLnBhcmVudHMoJyNsb2NhdGlvbicpLnJlbW92ZUNsYXNzKCdoYXMtZHJvcGRvd24nKTtcblx0XHR9XG5cdH1cdFxuXHRcblx0Ly8gY29sbGlzaW9uIGRldGVjdGlvbiBhbmQgYWRqdXN0bWVudCBmb3IgaWYgbWVudSBvZmYtc2NyZWVuXG5cdC8vIHRoaXMgaXMgYm91bmQgdG8gZG9jdW1lbnQgYW5kIC5zaXplLWRlc2t0b3AgdG8gYXZvaWQgaU9TIGlzc3VlIHdpdGggZmlyc3QgdGFwIHRyaWdnZXJpbmcgbW91c2VvdmVyIGluc3RlYWQgb2YgY2xpY2sgLSBkYW5AcmVkdmFuXG5cdCQoZG9jdW1lbnQpLm9uKCdtb3VzZW92ZXInLCAnaHRtbC5zaXplLWRlc2t0b3AgI25hdmlnYXRpb24gLmhhcy1kcm9wZG93biA+IGEnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdG5hdmlnYXRpb25Db2xsaXNpb25EZXRlY3Rpb24oJChldmVudC5jdXJyZW50VGFyZ2V0KSk7XG5cdH0pO1xuXHRcblx0JCgnYm9keScpLm9uKCdjbGljaycsICcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duID4gYSwgLm5hdi1zZWNvbmRhcnkgLmhhcy1kcm9wZG93biA+IGEnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHBhcmVudCA9ICR0aGlzLmNsb3Nlc3QoJy5oYXMtZHJvcGRvd24nKTtcblx0XHR2YXIgJGNvbnRhaW5lciA9ICRwYXJlbnQuY2xvc2VzdCgnI25hdmlnYXRpb24sIC5uYXYtc2Vjb25kYXJ5Jyk7XG5cdFx0XG5cdFx0aWYgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuXHRcdFx0dmFyICRzY3JvbGxpbmdDb250YWluZXIgPSAkKCcjbmF2aWdhdGlvbicpO1xuXHRcdFx0dmFyIG9mZnNldE9wZW5NZW51ID0gMDtcblx0XHRcdHZhciBzY3JvbGxUb3BOZXcgPSAwO1xuXHRcdFx0XG5cdFx0XHRpZiAoJCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5maXJzdCgpLmxlbmd0aCA+IDAgJiYgKCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykuZmlyc3QoKS5vZmZzZXQoKS50b3AgPCAkdGhpcy5vZmZzZXQoKS50b3ApKSB7XG5cdFx0XHRcdG9mZnNldE9wZW5NZW51ID0gJCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5maXJzdCgpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLm91dGVySGVpZ2h0KCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHNjcm9sbFRvcE5ldyA9ICR0aGlzLm9mZnNldCgpLnRvcCAtICRzY3JvbGxpbmdDb250YWluZXIub2Zmc2V0KCkudG9wICsgJHNjcm9sbGluZ0NvbnRhaW5lci5zY3JvbGxUb3AoKSAtIG9mZnNldE9wZW5NZW51O1xuXG5cdFx0XHQkc2Nyb2xsaW5nQ29udGFpbmVyLmFuaW1hdGUoe1xuXHRcdFx0XHRzY3JvbGxUb3A6IHNjcm9sbFRvcE5ld1xuXHRcdFx0fSwgMTUwKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSkge1xuXHRcdFx0aWYgKCRwYXJlbnQuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHRcdCRwYXJlbnQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fSBlbHNlIGlmICghJHBhcmVudC5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0JCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JHBhcmVudC5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCghJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLWRlc2t0b3AnKSAmJiBwYWdlQ29udGV4dC5zaXRlICE9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykgfHwgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSAmJiBwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykpIHtcblx0XHRcdC8vY2xvc2Ugb3RoZXIgaGVhZGVyIG1lbnVzXG5cdFx0XHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItYmFyIC5uYXYtc2Vjb25kYXJ5IC5oYXMtZHJvcGRvd24gLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5oaWRlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcudG9wLWJhbm5lci1iYXIgLm5hdi1zZWNvbmRhcnkgLmhhcy1kcm9wZG93biAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnN0b3AoKS5zbGlkZVVwKDE1MCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICgkcGFyZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0XHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRcdFx0XHQkcGFyZW50LnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcubGV2ZWwtMiwgLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5oaWRlKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHBhcmVudC5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLmxldmVsLTIsIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuc3RvcCgpLnNsaWRlVXAoMTUwKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0XHRcdFx0JCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLmxldmVsLTIsIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuaGlkZSgpO1xuXHRcdFx0XHRcdCRwYXJlbnQuYWRkQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnNob3coKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcubGV2ZWwtMiwgLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5zdG9wKCkuc2xpZGVVcCgxNTApO1xuXHRcdFx0XHRcdCRwYXJlbnQuYWRkQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnN0b3AoKS5zbGlkZURvd24oMTUwKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoJCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmU6bm90KC5hY2NvcmRpb24pJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkY29udGFpbmVyLmF0dHIoJ2FjdGl2ZS1tZW51LWxldmVsJywgJzEnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRjb250YWluZXIucmVtb3ZlQXR0cignYWN0aXZlLW1lbnUtbGV2ZWwnKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkKCcubWVudS10b2dnbGUnKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCQoJ2h0bWwnKS5hZGRDbGFzcygnbWVudS1hY3RpdmUnKTtcblxuXHRcdFx0XHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLXRhYmxldCcpICYmIHdpbmRvdy5pbm5lcldpZHRoID09IDEwMjQpIHtcblx0XHRcdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJy50b3AtYmFubmVyJykuYWRkQ2xhc3MoJ25hdi1hY3RpdmUnKTtcblx0XHRcdFx0XHQkKCdodG1sJykuYWRkQ2xhc3MoJ2Rlc2t0b3AtbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKHdpbmRvdy5pbm5lcldpZHRoID49IDEwMjQpIHtcblx0XHRcdFx0JCgnLm1lbnUtdG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cblx0XHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSAmJiB3aW5kb3cuaW5uZXJXaWR0aCA9PSAxMDI0KSB7XG5cdFx0XHRcdFx0JCh0aGlzKS5jbG9zZXN0KCcudG9wLWJhbm5lcicpLnJlbW92ZUNsYXNzKCduYXYtYWN0aXZlJyk7XG5cdFx0XHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdkZXNrdG9wLW5hdi1hY3RpdmUnKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICghJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpKSB7XG5cdFx0XHRuYXZpZ2F0aW9uQ29sbGlzaW9uRGV0ZWN0aW9uKCR0aGlzKTtcblx0XHR9XG5cdFx0XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9KVxuXHQub24oJ2NsaWNrJywgJy5tZW51LXRvZ2dsZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdGlmICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykgfHwgJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLXRhYmxldCcpKSB7XG5cdFx0XHR2YXIgJGh0bWwgPSAkKCdodG1sJyk7XG5cdFx0XHR2YXIgJGJvZHkgPSAkKCdib2R5Jyk7XG5cdFx0XHR2YXIgJGNvbnRhaW5lciA9ICQoJyN3cmFwcGVyJyk7XG5cdFx0XHR2YXIgaGVhZGVyV3JhcHBlciA9ICQoJy5oZWFkZXItd3JhcHBlcicpO1xuXHRcdFx0dmFyIGp1bWJvdHJvbkNvbnRhaW5lciA9IGhlYWRlcldyYXBwZXIuZmluZCgnLmp1bWJvdHJvbi1hamF4Jyk7XG5cdFx0XHR2YXIgbG9nb0FuZExpbmtzID0gaGVhZGVyV3JhcHBlci5maW5kKCcubG9nby1hbmQtbGlua3MtY29udGFpbmVyJyk7XG5cdFx0XHR2YXIgbmF2Rml4ZWRIZWFkZXJMaW1pdCA9IDgwMDtcblx0XHRcdHZhciB0b3BCYW5uZXJCYXIgPSBoZWFkZXJXcmFwcGVyLmZpbmQoJy50b3AtYmFubmVyLWJhcicpO1xuXHRcblx0XHRcdHZhciB0b2JCYW5uZXJJbm5lckhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIChwYXJzZUZsb2F0KHRvcEJhbm5lckJhci5vdXRlckhlaWdodCgpKSArIHBhcnNlRmxvYXQoanVtYm90cm9uQ29udGFpbmVyLm91dGVySGVpZ2h0KCkpKTtcblx0XHRcdHZhciBuYXZDb250YWluZXJIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSAocGFyc2VGbG9hdCh0b3BCYW5uZXJCYXIub3V0ZXJIZWlnaHQoKSkgKyBwYXJzZUZsb2F0KGxvZ29BbmRMaW5rcy5vdXRlckhlaWdodCgpKSArIHBhcnNlRmxvYXQoanVtYm90cm9uQ29udGFpbmVyLm91dGVySGVpZ2h0KCkpKTsgXG5cdFxuXHRcdFx0aWYgKCEkaHRtbC5oYXNDbGFzcygnbWVudS1hY3RpdmUnKSkge1xuXHRcdFx0XHR2YXIgc2Nyb2xsVG9wID0gZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcDtcblx0XHRcdFx0bmF2RGF0YUJ1ZmZlclsnd3JhcHBlclNjcm9sbFRvcCddID0gc2Nyb2xsVG9wO1xuXHRcdFx0XHRuYXZEYXRhQnVmZmVyWyd3cmFwcGVyTWFyZ2luVG9wJ10gPSAkY29udGFpbmVyLmNzcygnbWFyZ2luLXRvcCcpO1xuXHRcdFx0XHQkY29udGFpbmVyLmF0dHIoJ2J1ZmZlci1zY3JvbGxUb3AnLCBzY3JvbGxUb3ApO1xuXHRcdFx0XHRcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItaW5uZXInKS5jc3MoJ2hlaWdodCcsIHRvYkJhbm5lcklubmVySGVpZ2h0KTtcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItaW5uZXIgLm5hdmlnYXRpb24tYW5kLWp1bWJvdHJvbi1jb250YWluZXInKS5jc3MoJ2hlaWdodCcsIG5hdkNvbnRhaW5lckhlaWdodCk7XG5cdFx0XHRcdFxuXHRcdFx0XHQkaHRtbC5hZGRDbGFzcygnbWVudS1hY3RpdmUnKTtcblx0XHRcdFx0JHRoaXMuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkdGhpcy5hdHRyKCdhcmlhLWxhYmVsJywgJHRoaXMuYXR0cignZGF0YS1jbG9zZScpKTsgLy8gQ2hhbmdlIHRoZSBhcmlhLWxhYmVsIG9uIHRoZSBtZW51LXRvZ2dsZSBmb3Igc2NyZWVuIHJlYWRlcnNcblxuXHRcdFx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gMTAyMyAmJiBzY3JvbGxUb3AgPiBuYXZGaXhlZEhlYWRlckxpbWl0KSB7XG5cdFx0XHRcdFx0JCgnLmhlYWRlci13cmFwcGVyJykuY3NzKCdtYXgtaGVpZ2h0Jywgd2luZG93LmlubmVySGVpZ2h0KTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkKCcubXktc3RvcmUtcGFuZWwubW9iaWxlLW9ubHkgLnNob3ctc3RvcmUtc2VhcmNoJykuZm9jdXMoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRodG1sLnJlbW92ZUNsYXNzKCdtZW51LWFjdGl2ZScpO1xuXHRcdFx0XHQkdGhpcy5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCR0aGlzLmF0dHIoJ2FyaWEtbGFiZWwnLCAkdGhpcy5hdHRyKCdkYXRhLW9wZW4nKSk7IC8vIENoYW5nZSB0aGUgYXJpYS1sYWJlbCBvbiB0aGUgbWVudS10b2dnbGUgZm9yIHNjcmVlbiByZWFkZXJzXG5cdFxuXHRcdFx0XHRpZiAobmF2RGF0YUJ1ZmZlclsnd3JhcHBlclNjcm9sbFRvcCddID4gMCkge1xuXHRcdFx0XHRcdGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCA9IG5hdkRhdGFCdWZmZXJbJ3dyYXBwZXJTY3JvbGxUb3AnXTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkKCcjbmF2aWdhdGlvbicpLnJlbW92ZUF0dHIoJ2FjdGl2ZS1tZW51LWxldmVsJyk7XG5cdFxuXHRcdFx0XHQkKCcudG9wLWJhbm5lci1pbm5lcicpLmNzcygnaGVpZ2h0JywgJycpO1xuXHRcdFx0XHQkKCcudG9wLWJhbm5lci1pbm5lciAubmF2aWdhdGlvbi1hbmQtanVtYm90cm9uLWNvbnRhaW5lcicpLmNzcygnaGVpZ2h0JywgJ2F1dG8nKTtcblx0XG5cdFx0XHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSAxMDIzKSB7XG5cdFx0XHRcdFx0JCgnLmhlYWRlci13cmFwcGVyJykuY3NzKCd0cmFuc2Zvcm0nLCAnbm9uZScpO1xuXHRcdFx0XHRcdCQoJy5oZWFkZXItd3JhcHBlcicpLmNzcygnbWF4LWhlaWdodCcsICdhdXRvJyk7XG5cdFx0XHRcdFx0JCgnaHRtbCwgYm9keScpLmFuaW1hdGUoeyBzY3JvbGxUb3A6IDAgfSwgMzAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdCQoJyNuYXZpZ2F0aW9uIC5sZXZlbC0yJykuaGlkZSgpO1xuXHRcdCQoJyNuYXZpZ2F0aW9uIC5sZXZlbC0xJykuc2xpZGVEb3duKCk7XG5cdFx0JCgnI25hdmlnYXRpb24gLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcdFx0XHRcblx0XHQkKCcubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnNsaWRlVXAoMTUwKTtcblxuXHRcdGlmICgkKCcjbWluaS1jYXJ0JykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHQkKCcjbWluaS1jYXJ0IC5taW5pLWNhcnQtbGluaycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdCQoJyNtaW5pLWNhcnQnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0fVxuXG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2VhcmNoQmFyLkhpZGUnKTtcblx0XHRcblx0XHRpZiAoJCgnLnNlY29uZC1tb2JuYXYnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcdFx0XHRcdFxuXHRcdFx0JCgnLnNlY29uZC1tb2JuYXYnKS5yZW1vdmVDbGFzcygnYWN0aXZlJylcblx0XHRcdCQoJyNzZWNvbmQtbW9ibmF2Jykuc3RvcCgpLnNsaWRlVXAoMTUwKTtcblx0XHR9XG5cdH0pXG5cdC5vbignY2xpY2suTWVudUl0ZW1Ub2dnbGUnLCAnLm1lbnUtY2F0ZWdvcnkgbGkgLm1lbnUtaXRlbS10b2dnbGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciAkcGFyZW50TGkgPSAkKGUudGFyZ2V0KS5jbG9zZXN0KCdsaScpO1xuXHRcdCRwYXJlbnRMaS5zaWJsaW5ncygnbGknKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLm1lbnUtaXRlbS10b2dnbGUnKS5yZW1vdmVDbGFzcygnZmEtY2hldnJvbi11cCBhY3RpdmUnKS5hZGRDbGFzcygnZmEtY2hldnJvbi1yaWdodCcpO1xuXHRcdCRwYXJlbnRMaS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0JChlLnRhcmdldCkudG9nZ2xlQ2xhc3MoJ2ZhLWNoZXZyb24tcmlnaHQgZmEtY2hldnJvbi11cCBhY3RpdmUnKTtcblx0fSk7XG5cblx0LyogLS0tIEFEQSBDb21wbGlhbmNlOiBLZXlib2FyZCBtYWluIG1lbnUgbmF2aWdhdGlvbiAtLS1cblx0ICogQVJST1cgRE9XTjogV2lsbCBvcGVuIGZseW91dHM7IGZvY3VzIGdvZXMgdG8gZmlyc3QgY2xpY2thYmxlIGxpbmsgaW4gZmx5b3V0XG5cdCAqIEFSUk9XIFVQOiBXaWxsIGNsb3NlIGZseW91dHM7IGZvY3VzIHJldHVybnMgdG8gdGhlIHBhcmVudCBvZiB0aGUgZmx5b3V0XG5cdCAqIFRBQjogQSBmb2N1cyBpbmRpY2F0b3Igd2lsbCBzaG93IHVwIGF0IHRpbWUgb2YgZWFjaCB0YWJcblx0ICogRU5URVI6IEJ5IGRlZmF1bHQsIGhpdHRpbmcgZW50ZXIgd2lsbCBlbmdhZ2UgYW55IGxpbmsgdGhhdCBoYXMgY3VycmVudCBmb2N1c1xuXHQgKi9cblx0JChkb2N1bWVudCkub24oJ2tleXVwJywgJ3VsLm1lbnUtY2F0ZWdvcnkgbGkuaGFzLWRyb3Bkb3duJywgZnVuY3Rpb24gKGV2ZW50KSB7IFxuXHRcdC8vIERvd24gQXJyb3c6IElmIHN1Yi1tZW51IGhhcyBiZWVuIG9wZW5lZC4uLlxuXHRcdGlmIChldmVudC53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5BcnJvd0Rvd24pIHtcblx0XHRcdC8vIEJvb3RCYXJuLXNwZWNpZmljIG5hdiBmZWF0dXJlc1xuXHRcdFx0aWYgKCQoJy50b3AtYmFubmVyLWJhcicpLmRhdGEoJ2hlYWRlci1mb3InKSA9PSAnYm9vdGJhcm5fdXMnKSB7XG5cdFx0XHRcdCQodGhpcykudHJpZ2dlcignbW91c2VlbnRlcicpO1xuXHRcdFx0fVxuXHRcdFx0JCh0aGlzKS5maW5kKCd1bCcpLmZpbmQoJ2FbaHJlZiE9XCJcIl1baHJlZl0nKS5yZW1vdmVBdHRyKCd0YWJpbmRleCcpOyAvLyBSZW1vdmUgdGFiaW5kZXggdG8gYWxsb3cgbmF0dXJhbCB0YWIgZmxvdyBvZiBuYXYgbGlzdFxuXHRcdFx0dmFyIG5hdkxpbmtzUG9wdWxhdGVkID0gJCh0aGlzKS5maW5kKCcubGV2ZWwtMiB1bDpmaXJzdC1vZi10eXBlIGxpOmZpcnN0LW9mLXR5cGUnKS5maW5kKCdhJykuZmlsdGVyKGZ1bmN0aW9uKHgsIG5hdkxpbmspIHtcblx0XHRcdFx0aWYgKCQobmF2TGluaykuYXR0cignaHJlZicpICYmICQobmF2TGluaykuYXR0cignaHJlZicpLnRyaW0oKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG5hdkxpbms7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdFx0JChuYXZMaW5rc1BvcHVsYXRlZFswXSkuZm9jdXMoKS5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKTsgLy8gRm9jdXMgb24gZmlyc3QgcG9wdWxhdGVkIDxhPiB3aXRoaW4gb3BlbmVkIHN1Yi1tZW51IGFuZCBhZGQgdmlzdWFsIGluZGljYXRvclxuXHRcdFx0JCh0aGlzKS5hdHRyKCdhcmlhLWV4cGFuZGVkJywndHJ1ZScpLmFkZENsYXNzKCdhY3RpdmUga2V5Ym9hcmQtYWN0aXZhdGVkJyk7IC8vIFVwZGF0ZSBleHBhbmRlZCBhdHRyaWJ1dGUgYW5kIGFkZCBrZXlib2FyZCBjbGFzc1xuXHRcdH1cblx0XHQvLyBVcCBBcnJvdzogSWYgc3ViLW1lbnUgaGFzIGJlZW4gY2xvc2VkLi4uXG5cdFx0aWYgKGV2ZW50LndoaWNoID09PSBTaXRlQ29uc3RhbnRzLktleUNvZGVzLkFycm93VXApIHtcblx0XHRcdC8vIEJvb3RCYXJuLXNwZWNpZmljIG5hdiBmZWF0dXJlc1xuXHRcdFx0aWYgKCQoJy50b3AtYmFubmVyLWJhcicpLmRhdGEoJ2hlYWRlci1mb3InKSA9PSAnYm9vdGJhcm5fdXMnKSB7XG5cdFx0XHRcdCQodGhpcykudHJpZ2dlcignbW91c2VsZWF2ZScpO1xuXHRcdFx0fVxuXHRcdFx0JCh0aGlzKS5maW5kKCd1bCcpLmZpbmQoJ2FbaHJlZiE9XCJcIl1baHJlZl0nKS5hdHRyKCd0YWJpbmRleCcsJy0xJyk7IC8vIEFkZCBuZWdhdGl2ZSB0YWJpbmRleCB0byBza2lwIG5lc3RlZCBhbmNob3JzXG5cdFx0XHQkKHRoaXMpLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCdmYWxzZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUga2V5Ym9hcmQtYWN0aXZhdGVkJykuZm9jdXMoKS5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKTsgLy8gVXBkYXRlIGV4cGFuZGVkIGF0dHJpYnV0ZSwgcmVtb3ZlIGtleWJvYXJkIGNsYXNzIGFuZCByZXBvc2l0aW9uIGZvY3VzIGluZGljYXRvclxuXHRcdH1cblx0XHQvLyBUYWI6IEtleWJvYXJkIGxvZ2ljIGZvciBuYXYgdGFiYmluZy4uLlxuXHRcdGlmIChldmVudC53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5UYWIpIHtcblx0XHRcdGlmICghJChkb2N1bWVudC5hY3RpdmVFbGVtZW50KS5oYXNDbGFzcygna2V5Ym9hcmQtYWN0aXZhdGVkJykgJiYgKCQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuY2xvc2VzdCgnbGkuaGFzLWRyb3Bkb3duJykgJiYgISQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuY2xvc2VzdCgnbGkuaGFzLWRyb3Bkb3duJykuaGFzQ2xhc3MoJ2tleWJvYXJkLWFjdGl2YXRlZCcpKSkgeyAvLyBJZiB1c2VyIHRhYmJlZCBhd2F5IGZyb20gYWN0aXZhdGVkIHN1Yi1tZW51LCBjbG9zZSB0aGUgc3ViLW1lbnVcblx0XHRcdFx0Ly8gQm9vdEJhcm4tc3BlY2lmaWMgbmF2IGZlYXR1cmVzXG5cdFx0XHRcdGlmICgkKCcudG9wLWJhbm5lci1iYXInKS5kYXRhKCdoZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuXHRcdFx0XHRcdCQoJ2xpLmhhcy1kcm9wZG93bi5rZXlib2FyZC1hY3RpdmF0ZWQnKS50cmlnZ2VyKCdtb3VzZWxlYXZlJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0JCgnbGkuaGFzLWRyb3Bkb3duLmtleWJvYXJkLWFjdGl2YXRlZCcpLmZpbmQoJ3VsJykuZmluZCgnYVtocmVmIT1cIlwiXVtocmVmXScpLmF0dHIoJ3RhYmluZGV4JywnLTEnKTsgLy8gQWRkIG5lZ2F0aXZlIHRhYmluZGV4IHRvIHNraXAgbmVzdGVkIGFuY2hvcnMgd2hlbiBzdWJtZW51IGlzIGNsb3NlZFxuXHRcdFx0XHQkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykuYXR0cignYXJpYS1leHBhbmRlZCcsJ2ZhbHNlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZSBrZXlib2FyZC1hY3RpdmF0ZWQnKTsgLy8gVXBkYXRlIGV4cGFuZGVkIGF0dHJpYnV0ZSBhbmQgcmVtb3ZlIGtleWJvYXJkIGNsYXNzXG5cdFx0XHR9XG5cdFx0fVxuXHR9KVxuXHQub24oJ2tleWRvd24nLCAnLm1lbnUtdG9nZ2xlJywgZnVuY3Rpb24gKGV2ZW50KSB7IFxuXHRcdGlmICgoJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpIHx8ICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSkgJiYgZXZlbnQud2hpY2ggPT09IFNpdGVDb25zdGFudHMuS2V5Q29kZXMuRW50ZXIpIHtcblx0XHRcdCQoJy5teS1zdG9yZS1wYW5lbC5tb2JpbGUtb25seSBhJykuZm9jdXMoKS5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKTtcblx0XHR9XG5cdH0pXG5cdC5vbignbW91c2VvdmVyJywgJ3VsLm1lbnUtY2F0ZWdvcnkgbGkuaGFzLWRyb3Bkb3duJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0JCh0aGlzKS5hdHRyKCdhcmlhLWV4cGFuZGVkJywndHJ1ZScpOyAvLyBDU1MtZXhwYW5lZCBzdWItbWVudSBvY2N1cnMgb24gaG92ZXIuIFVzZSBKUyB0byB1cGRhdGUgdGhlIGV4cGFuZGVkIGF0dHJpYnV0ZSBmb3IgbW91c2UgdXNlcnMuXG5cdH0pXG5cdC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0JCgnLmZvY3VzLXZpc2libGUtaW5kaWNhdG9yJykucmVtb3ZlQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJyk7XG5cdFx0aWYgKCQoJ2xpLmhhcy1kcm9wZG93bi5rZXlib2FyZC1hY3RpdmF0ZWQnKSkge1xuXHRcdFx0aWYgKCQoJy50b3AtYmFubmVyLWJhcicpLmRhdGEoJ2hlYWRlci1mb3InKSA9PSAnYm9vdGJhcm5fdXMnKSB7XG5cdFx0XHRcdCQoJ2xpLmhhcy1kcm9wZG93bi5rZXlib2FyZC1hY3RpdmF0ZWQnKS50cmlnZ2VyKCdtb3VzZWxlYXZlJyk7XG5cdFx0XHR9XG5cdFx0XHQkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykuZmluZCgndWwnKS5maW5kKCdhW2hyZWYhPVwiXCJdW2hyZWZdJykuYXR0cigndGFiaW5kZXgnLCctMScpOyAvLyBBZGQgbmVnYXRpdmUgdGFiaW5kZXggdG8gc2tpcCBuZXN0ZWQgYW5jaG9ycyB3aGVuIHN1Ym1lbnUgaXMgY2xvc2VkXG5cdFx0XHQkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykuYXR0cignYXJpYS1leHBhbmRlZCcsJ2ZhbHNlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZSBrZXlib2FyZC1hY3RpdmF0ZWQnKTsgLy8gVXBkYXRlIGV4cGFuZGVkIGF0dHJpYnV0ZSBhbmQgcmVtb3ZlIGtleWJvYXJkIGNsYXNzXG5cdFx0fVxuXHR9KTtcblxuXHQvKiAtLS0gRG9jdW1lbnQgUmVhZHkgLS0tICovXG5cdCQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdHZhciBhZGFTdWJNZW51QXR0cmlidXRlcyA9IHtcblx0XHRcdCdyb2xlJzogJ21lbnVpdGVtJyxcblx0XHRcdCdhcmlhLWhhc3BvcHVwJzogJ3RydWUnLFxuXHRcdFx0J2FyaWEtZXhwYW5kZWQnOiAnZmFsc2UnXG5cdFx0fVxuXHRcdCQoJ3VsLm1lbnUtY2F0ZWdvcnkubGV2ZWwtMSB1bCcpLmF0dHIoJ3JvbGUnLCdtZW51JykuYXR0cignYXJpYS1sYWJlbCcsIGZ1bmN0aW9uKG4sIHgpIHtcblx0XHRcdHJldHVybiAkKHRoaXMpLmNsb3Nlc3QoJ2xpJykuZmluZCgnLmhhcy1zdWItbWVudScpLmZpcnN0KCkuaHRtbCgpO1xuXHRcdH0pO1xuXHRcdCQoJ3VsLm1lbnUtY2F0ZWdvcnkubGV2ZWwtMScpLmZpbmQoJ2EnKS5maWx0ZXIoZnVuY3Rpb24obiwgbmF2TGluaykge1xuXHRcdFx0Ly8gQWRkIHJvbGU9XCJub25lXCIgdG8gYWxsIGxpc3QgaXRlbXMsIGFuZCB0aGVuIHVzZSBzcGVjaWZpY2l0eSBmdXJ0aGVyIGRvd24gdG8gb3ZlcnJpZGUgaWYgbmVlZGVkXG5cdFx0XHQkKG5hdkxpbmspLnBhcmVudHMoJ3VsOm5vdCgubGV2ZWwtMSknKS5maW5kKCdsaScpLmF0dHIoJ3JvbGUnLCdub25lJyk7XG5cdFx0XHQvLyBBZGQgdGFiaW5kZXg9XCItMVwiIHRvIGFsbCBuZXN0ZWQgYW5jaG9yIHRhZ3MgdG8gZm9yY2UgdGFiIG9yZGVyIHVzaW5nIGFycm93IHVwIGFuZCBkb3duIGV2ZW50c1xuXHRcdFx0JChuYXZMaW5rKS5hdHRyKCd0YWJpbmRleCcsJy0xJyk7XG5cdFx0XHQvLyBJRiB0aGUgaHJlZiBhdHRyaWJ1dGUgaXMgbm90IGVtcHR5LCBhcHBseSBBREEgYXR0cmlidXRlcyBjb3JyZWN0bHkgZm9yIGEgbWVudWl0ZW1cblx0XHRcdGlmICgkKG5hdkxpbmspLmF0dHIoJ2hyZWYnKSAmJiAkKG5hdkxpbmspLmF0dHIoJ2hyZWYnKS50cmltKCkubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkKG5hdkxpbmspLmF0dHIoJ3JvbGUnLCdtZW51aXRlbScpO1xuXHRcdFx0Ly8gRUxTRSwgaWYgaHJlZiBhdHRyaWJ1dGUgaXMgZW1wdHksIHRoZW4gZW5zdXJlIDxhPiBnZXRzIHNraXBwZWQgaW4ga2V5Ym9hcmQgbmF2aWdhdGlvbiBhbmQgc2NyZWVuIHJlYWRlcnNcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQobmF2TGluaykucGFyZW50KCkuYXR0cihhZGFTdWJNZW51QXR0cmlidXRlcyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyAmJiB3aW5kb3cuaW5uZXJXaWR0aCA9PSAxMDI0KSB7XHRcdFxuXHRcdCQoJ2JvZHknKS5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRpZiAoJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLXRhYmxldCcpICYmICQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0aWYoZS50YXJnZXQuaWQgPT0gJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCAkKGUudGFyZ2V0KS5jbG9zZXN0KCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duJykubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkKCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cdFx0XHRcdCQoJy5oZWFkZXItd3JhcHBlciAudG9wLWJhbm5lcicpLnJlbW92ZUNsYXNzKCduYXYtYWN0aXZlJyk7XG5cdFx0XHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnZGVza3RvcC1uYXYtYWN0aXZlJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblx0XG5cdFxuXHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyNuYXZpZ2F0aW9uIC5sZXZlbC0zID4gbGkgPiBhLm9mZmVyLXByaW1hcnknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUyAmJiAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHR2YXIgJHBhcmVudCA9ICR0aGlzLmNsb3Nlc3QoJ2xpJyk7XG5cdFx0XHR2YXIgJGNvbnRhaW5lciA9ICRwYXJlbnQuY2xvc2VzdCgnLmxldmVsLTInKTtcblx0XHRcdFxuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcubGV2ZWwtMyBsaScpLm5vdCgkcGFyZW50KS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkcGFyZW50LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBuYXZpZ2F0aW9uQ29sbGlzaW9uRGV0ZWN0aW9uKCRuYXZpZ2F0aW9uRXZlbnRUYXJnZXQpIHtcblx0dmFyICRjb250YWluZXIgPSAkbmF2aWdhdGlvbkV2ZW50VGFyZ2V0LmNsb3Nlc3QoJy5oYXMtZHJvcGRvd24nKTtcblx0XG5cdCRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2NvbGxpc2lvbi1yaWdodCBjb2xsaXNpb24tYm90aCcpO1xuXHRcdFxuXHR2YXIgJG1lbnUgPSAkY29udGFpbmVyLmZpbmQoJz4gLmxldmVsLTInKTtcblx0XG5cdGlmICgkbWVudS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIG1lbnVMZWZ0ID0gJG1lbnUub2Zmc2V0KCkubGVmdDtcblx0XHR2YXIgbWVudVJpZ2h0ID0gbWVudUxlZnQgKyAkbWVudS5vdXRlcldpZHRoKCk7XG5cdFx0XG5cdFx0dmFyICRib3VuZGFyeUNvbnRhaW5lciA9ICQoJy50b3AtYmFubmVyLWlubmVyJyk7XG5cdFx0XG5cdFx0aWYgKCRib3VuZGFyeUNvbnRhaW5lci5maW5kKCc+IC5zaGVsbCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdCRib3VuZGFyeUNvbnRhaW5lciA9ICRib3VuZGFyeUNvbnRhaW5lci5maW5kKCc+IC5zaGVsbCcpO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgYm91bmRhcnlMZWZ0ID0gJGJvdW5kYXJ5Q29udGFpbmVyLm9mZnNldCgpLmxlZnQ7XG5cdFx0dmFyIGJvdW5kYXJ5UmlnaHQgPSBib3VuZGFyeUxlZnQgKyAkYm91bmRhcnlDb250YWluZXIub3V0ZXJXaWR0aCgpO1xuXHRcdFxuXHRcdHZhciBib3VuZGFyeUJ1ZmZlciA9IDMwO1xuXG5cdFx0aWYgKG1lbnVSaWdodCA+PSAoYm91bmRhcnlSaWdodCArIGJvdW5kYXJ5QnVmZmVyKSkge1xuXHRcdFx0dmFyIGJ1dHRvblJpZ2h0ID0gJG5hdmlnYXRpb25FdmVudFRhcmdldC5vZmZzZXQoKS5sZWZ0ICsgJG5hdmlnYXRpb25FdmVudFRhcmdldC5vdXRlcldpZHRoKCk7XG5cdFx0XHRcblx0XHRcdGlmIChidXR0b25SaWdodCAtICRtZW51Lm91dGVyV2lkdGgoKSA8PSAoYm91bmRhcnlMZWZ0IC0gYm91bmRhcnlCdWZmZXIpKSB7XG5cdFx0XHRcdCRjb250YWluZXIuYWRkQ2xhc3MoJ2NvbGxpc2lvbi1ib3RoJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkY29udGFpbmVyLmFkZENsYXNzKCdjb2xsaXNpb24tcmlnaHQnKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gY2xvc2VOYXZpZ2F0aW9uKCkge1xuXHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cdCQoJy5tZW51LXRvZ2dsZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0JCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLmxldmVsLTIsIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuc3RvcCgpLnNsaWRlVXAoMTUwKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBWYWxpZGF0aW9uU2V0dGluZ3MgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5TZXR0aW5ncztcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCRvcmRlclN0YXR1c0Zvcm0pIHtcblx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdvcmRlck51bWJlcicsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVPcmRlck51bWJlciwgUmVzb3VyY2VzLklOVkFMSURfT1JERVJfTlVNQkVSKTtcblx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdwb3N0YWxDb2RlJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVBvc3RhbENvZGUsIFJlc291cmNlcy5JTlZBTElEX1BPU1RBTF9DT0RFKTtcblx0XG5cdHZhciAkb3JkZXJTdGF0dXNGb3JtT3JkZXJOdW1iZXIgPSAkb3JkZXJTdGF0dXNGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX29yZGVyTnVtYmVyXCJdJyk7XG5cdHZhciAkb3JkZXJTdGF0dXNGb3JtT3JkZXJFbWFpbCA9ICRvcmRlclN0YXR1c0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfb3JkZXJFbWFpbFwiXScpO1xuXHR2YXIgJG9yZGVyU3RhdHVzRm9ybU9yZGVyUG9zdGFsQ29kZSA9ICRvcmRlclN0YXR1c0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsQ29kZVwiXScpO1xuXHRcblx0dmFyIGZvcm1WYWxpZGF0b3IgPSAkb3JkZXJTdGF0dXNGb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHQkb3JkZXJTdGF0dXNGb3JtT3JkZXJOdW1iZXIucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5PcmRlck51bWJlcik7XG5cdCRvcmRlclN0YXR1c0Zvcm1PcmRlckVtYWlsLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuRW1haWwpO1xuXHQkb3JkZXJTdGF0dXNGb3JtT3JkZXJQb3N0YWxDb2RlLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUG9zdGFsQ29kZSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcbmV4cG9ydHMudmVyaWZ5ID0gdmVyaWZ5O1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCkge1xuXHR3aW5kb3cucmVjYXB0Y2hhTG9hZGVkID0gZnVuY3Rpb24gKCkge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1JlY2FwdGNoYS5Mb2FkZWQnKTtcblx0fTtcblxuXHR3aW5kb3cuZW1haWxTaWdudXAgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnR2xvYmFsLkVtYWlsU2lnbnVwJyk7XG5cdH07XG5cblx0d2luZG93LmFjY291bnRMb2dpbiA9IGZ1bmN0aW9uICh0b2tlbikge1xuXHRcdHJldHVybiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sICdBY2NvdW50LlN1Ym1pdExvZ2luJyk7XG5cdH07XG5cblx0d2luZG93LnJlc2V0UGFzc3dvcmQgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnQWNjb3VudC5SZXNldFBhc3N3b3JkJyk7XG5cdH07XG5cblx0d2luZG93LnN1Ym1pdE9QQ1BheW1lbnQgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnQ2hlY2tvdXQuU3VibWl0UGF5bWVudCcpO1xuXHR9O1xuXHRcblx0d2luZG93LnN1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnQ2hlY2tvdXQuU3VibWl0UGF5bWVudFByaXZhdGVMYWJlbCcpO1xuXHR9O1xuXG5cdHdpbmRvdy5zdWJtaXRNZXJyeU1haWwgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnTWVycnlNYWlsLlNlbmQnKTtcblx0fTtcblx0XG5cdHdpbmRvdy5zdWJtaXRSZXdhcmRzQ3JlZGl0ID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ1Jld2FyZHNDcmVkaXQuQWRkJyk7XG5cdH07XG5cdFxuXHR3aW5kb3cuc3VibWl0TG95YWx0eUNyZWRpdCA9IGZ1bmN0aW9uICh0b2tlbikge1xuXHRcdHJldHVybiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sICdMb3lhbHR5Q3JlZGl0LkFkZCcpO1xuXHR9O1xuXHRcblx0d2luZG93LnN1Ym1pdEdpZnRDYXJkID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ0dpZnRDYXJkLkFwcGx5Jyk7XG5cdH07XG5cblx0d2luZG93LnN1Ym1pdFBheW1lbnRWb3VjaGVyID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ1BheW1lbnRWb3VjaGVyLkFwcGx5Jyk7XG5cdH07XG59O1xuXG5mdW5jdGlvbiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sIGV2ZW50TmFtZSkge1xuXHRyZXR1cm4gJC53aGVuKHZlcmlmeSh0b2tlbikpLnRoZW4oZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywgeG1sSHR0cFJlcXVlc3QpIHtcblx0XHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0XHRpZiAoZGF0YS5zdWNjZXNzKSB7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoZXZlbnROYW1lKTtcblx0XHRcdFx0cmVzb2x2ZSgpO1x0XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZWplY3QoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XHRcbn1cblxuZnVuY3Rpb24gdmVyaWZ5KHRva2VuKSB7XG5cdHJldHVybiAkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdHVybDogVXJscy52ZXJpZnlSZWNhcHRjaGEsXG5cdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHR0b2tlbjogdG9rZW5cblx0XHR9KVxuXHR9KTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgcHJvZHVjdFRpbGVDb250YWluZXJzID0gW107XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9ucykge1xuXHRpZiAob3B0aW9ucy5VcmwgJiYgb3B0aW9ucy5Db250YWluZXJzICYmIG9wdGlvbnMuQ29udGFpbmVycy5sZW5ndGggPiAwKSB7XG5cdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IG9wdGlvbnMuQ29udGFpbmVycy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdHZhciBjb250YWluZXIgPSBvcHRpb25zLkNvbnRhaW5lcnNbaW5kZXhdO1xuXHRcdFx0XG5cdFx0XHRwcm9kdWN0VGlsZUNvbnRhaW5lcnNbcHJvZHVjdFRpbGVDb250YWluZXJzLmxlbmd0aF0gPSBuZXcgUHJvZHVjdFRpbGVDb250YWluZXIob3B0aW9ucy5VcmwsIGNvbnRhaW5lcikubG9hZCgpO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBQcm9kdWN0VGlsZUNvbnRhaW5lcih1cmwsIGNvbnRhaW5lciwgcmVxdWVzdERhdGEpIHtcblx0dmFyICRjb250YWluZXI7XG5cdHZhciAkY29udGFpbmVyQm9keTtcblx0dmFyIGRhdGFCdWZmZXIgPSB7fTtcblx0dmFyIGh0bWxCdWZmZXIgPSB7fTtcblx0dmFyIGN1cnJlbnRIdG1sQnVmZmVyQ291bnQgPSAwO1xuXHR2YXIgZXhwZWN0ZWRIdG1sQnVmZmVyQ291bnQgPSAwO1xuXG5cdHRoaXMubG9hZCA9IGZ1bmN0aW9uKCkge1xuXHRcdCRjb250YWluZXIgPSAkKGNvbnRhaW5lci5TZWxlY3Rvcik7XG5cdFx0JGNvbnRhaW5lckJvZHkgPSAkY29udGFpbmVyLmZpbmQoJy5hY2NvcmRpb24tYm9keScpO1xuXHRcdCRjb250YWluZXIuaGlkZSgpO1xuXHRcdFxuXHRcdGlmICgkY29udGFpbmVyLmxlbmd0aCA+IDApIHtcblx0XHRcdCRjb250YWluZXJCb2R5LmxvYWRpbmcoKTtcblx0XHRcdCRjb250YWluZXIuc2hvdygpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiB1cmwsXG5cdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRhZGRQcm9kdWN0SWQ6IGNvbnRhaW5lci5hZGRQcm9kdWN0SWQsXG5cdFx0XHRcdFx0ZXhjbHVkZVByb2R1Y3RJZDogY29udGFpbmVyLmV4Y2x1ZGVQcm9kdWN0SWRcblx0XHRcdFx0fSksXG5cdFx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRpZiAoZGF0YSAmJiBkYXRhLlByb2R1Y3RJZHMgJiYgZGF0YS5Qcm9kdWN0SWRzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdGRhdGFCdWZmZXIgPSBkYXRhO1xuXHRcdFx0XHRcdFx0ZXhwZWN0ZWRIdG1sQnVmZmVyQ291bnQgPSBkYXRhLlByb2R1Y3RJZHMubGVuZ3RoO1xuXG5cdFx0XHRcdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgZGF0YS5Qcm9kdWN0SWRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRcdFx0XHRnZXRQcm9kdWN0SGl0VGlsZShkYXRhLlByb2R1Y3RJZHNbaW5kZXhdKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmVjZW50bHlWaWV3ZWRQcm9kdWN0cy5Eb25lJywgJGNvbnRhaW5lcik7XG5cdFx0XHRcdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcdFx0XHRcdGZpbmlzaCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCRjb250YWluZXIuaGlkZSgpO1xuXHRcdFx0XHRcdGZpbmlzaCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmVjZW50bHlWaWV3ZWRQcm9kdWN0cy5Eb25lJywgJGNvbnRhaW5lcik7XG5cdFx0fVxuXHR9XG5cblx0dmFyIGdldFByb2R1Y3RIaXRUaWxlID0gZnVuY3Rpb24ocHJvZHVjdElkKSB7XG5cdFx0dmFyIHJlcXVlc3REYXRhID0ge1xuXHRcdFx0cGlkOiBwcm9kdWN0SWQsXG5cdFx0XHRzaG93c3dhdGNoZXM6ICd0cnVlJyxcblx0XHRcdHNob3dwcmljaW5nOiAndHJ1ZScsXG5cdFx0XHRzaG93cHJvbW90aW9uOiAndHJ1ZScsXG5cdFx0XHRzaG93cmF0aW5nOiAndHJ1ZScsXG5cdFx0XHRzaG93YmFkZ2VzOiAnZmFsc2UnLFxuXHRcdFx0c2hvd2FmZmlybTogJ2ZhbHNlJyxcblx0XHR9XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdHVybDogVXJscy5oaXRUaWxlLFxuXHRcdFx0ZGF0YTogcmVxdWVzdERhdGEsXG5cdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0aWYgKGRhdGEpIHtcblx0XHRcdFx0XHRodG1sQnVmZmVyW3Byb2R1Y3RJZF0gPSAnPGxpIGNsYXNzPVwic2xpZGVcIj4nICsgZGF0YSArICc8L2xpPic7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRjdXJyZW50SHRtbEJ1ZmZlckNvdW50Kys7XG5cdFx0XHRcdHJlbmRlcigpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dmFyIHJlbmRlciA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmIChjdXJyZW50SHRtbEJ1ZmZlckNvdW50ID09IGV4cGVjdGVkSHRtbEJ1ZmZlckNvdW50KSB7XG5cdFx0XHR2YXIgaHRtbCA9ICcnO1xuXG5cdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgZGF0YUJ1ZmZlci5Qcm9kdWN0SWRzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRpZiAoaHRtbEJ1ZmZlcltkYXRhQnVmZmVyLlByb2R1Y3RJZHNbaW5kZXhdXSkge1xuXHRcdFx0XHRcdGh0bWwgKz0gaHRtbEJ1ZmZlcltkYXRhQnVmZmVyLlByb2R1Y3RJZHNbaW5kZXhdXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgJGh0bWwgPSAkKGh0bWwpO1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRcdFx0JGh0bWwuZmluZCgnLnByb2R1Y3QtdGlsZScpLmFkZENsYXNzKCdwcm9kdWN0Jyk7XG5cdFx0XHR9XG5cdFx0XHQkY29udGFpbmVyLmZpbmQoJy5zbGlkZXMnKS5odG1sKCRodG1sKTtcblx0XHRcdCRjb250YWluZXIuZmluZCgnLnNsaWRlci1wcm9kdWN0cy1wcmltYXJ5JykudHJpZ2dlcignaW5pdC1zbGlkZXInKTtcblx0XHRcdGZpbmlzaCgpO1xuXG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkpIHtcblx0XHRcdCAgICBhZmZpcm0udWkucmVmcmVzaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHZhciBmaW5pc2ggPSBmdW5jdGlvbigpIHtcblx0XHQkY29udGFpbmVyQm9keS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmVjZW50bHlWaWV3ZWRQcm9kdWN0cy5Eb25lJywgJGNvbnRhaW5lcik7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ3VycmVuY3kuVXBkYXRlJywgJGNvbnRhaW5lcik7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi9Mb2FkaW5nSW5kaWNhdG9yJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciByZWNvbW1lbmRhdGlvbnNDb250YWluZXJzID0gW107XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9ucykge1xuXHRpZiAob3B0aW9ucy5VcmwgJiYgb3B0aW9ucy5Db250YWluZXJzICYmIG9wdGlvbnMuQ29udGFpbmVycy5sZW5ndGggPiAwKSB7XG5cdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IG9wdGlvbnMuQ29udGFpbmVycy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdHJlY29tbWVuZGF0aW9uc0NvbnRhaW5lcnNbcmVjb21tZW5kYXRpb25zQ29udGFpbmVycy5sZW5ndGhdID0gbmV3IFJlY29tbWVuZGF0aW9uc0NvbnRhaW5lcihvcHRpb25zLlVybCwgb3B0aW9ucy5Db250YWluZXJzW2luZGV4XSkubG9hZCgpO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBSZWNvbW1lbmRhdGlvbnNDb250YWluZXIodXJsLCBjb250YWluZXIpIHtcblx0dmFyICRjb250YWluZXI7XG5cdHZhciAkY29udGFpbmVyQm9keTtcblx0dmFyIGRhdGFCdWZmZXIgPSB7fTtcblx0dmFyIGh0bWxCdWZmZXIgPSB7fTtcblx0dmFyIGN1cnJlbnRIdG1sQnVmZmVyQ291bnQgPSAwO1xuXHR2YXIgZXhwZWN0ZWRIdG1sQnVmZmVyQ291bnQgPSAwO1xuXG5cdHRoaXMubG9hZCA9IGZ1bmN0aW9uKCkge1xuXHRcdCRjb250YWluZXIgPSAkKGNvbnRhaW5lci5TZWxlY3Rvcik7XG5cdFx0JGNvbnRhaW5lckJvZHkgPSAkY29udGFpbmVyLmZpbmQoJy5hY2NvcmRpb24tYm9keScpO1xuXHRcdFxuXHRcdCRjb250YWluZXIuaGlkZSgpO1xuXHRcdFxuXHRcdGlmICgkY29udGFpbmVyLmxlbmd0aCA+IDAgJiYgY29udGFpbmVyLlByb2R1Y3RJZCAmJiBjb250YWluZXIuUmVsYXRpb25UeXBlKSB7XG5cdFx0XHQkY29udGFpbmVyQm9keS5sb2FkaW5nKCk7XG5cdFx0XHQkY29udGFpbmVyLnNob3coKTtcblx0XHRcdFxuXHRcdFx0dmFyIHJlcXVlc3REYXRhID0ge1xuXHRcdFx0XHQnc3R5bGVzJzogY29udGFpbmVyLlByb2R1Y3RJZCxcblx0XHRcdFx0J3JlbGF0aW9udHlwZSc6IGNvbnRhaW5lci5SZWxhdGlvblR5cGVcblx0XHRcdH1cblxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdFx0dXJsOiB1cmwsXG5cdFx0XHRcdGRhdGE6IHJlcXVlc3REYXRhLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5wcm9kdWN0cyAmJiBkYXRhLnByb2R1Y3RzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdGRhdGFCdWZmZXIgPSBkYXRhO1xuXHRcdFx0XHRcdFx0ZXhwZWN0ZWRIdG1sQnVmZmVyQ291bnQgPSBkYXRhLnByb2R1Y3RzLmxlbmd0aDtcblxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGRhdGEucHJvZHVjdHMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdFx0XHRcdGdldFByb2R1Y3RIaXRUaWxlKChpbmRleCArIDEpLCBkYXRhLnByb2R1Y3RzW2luZGV4XS5wcm9kdWN0aWQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcdFx0XHRcdGZpbmlzaCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCRjb250YWluZXIuaGlkZSgpO1xuXHRcdFx0XHRcdGZpbmlzaCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHR2YXIgZ2V0UHJvZHVjdEhpdFRpbGUgPSBmdW5jdGlvbihwb3NpdGlvbiwgcHJvZHVjdElkKSB7XG5cdFx0dmFyIHJlcXVlc3REYXRhID0ge1xuXHRcdFx0J3Bvc2l0aW9uJzogcG9zaXRpb24sXG5cdFx0XHQncGlkJzogcHJvZHVjdElkLFxuXHRcdFx0J3Nob3dzd2F0Y2hlcyc6ICd0cnVlJyxcblx0XHRcdCdzaG93cHJpY2luZyc6ICd0cnVlJyxcblx0XHRcdCdzaG93cHJvbW90aW9uJzogJ3RydWUnLFxuXHRcdFx0J3Nob3dyYXRpbmcnOiAndHJ1ZScsXG5cdFx0XHQnc2hvd2JhZGdlcyc6ICdmYWxzZScsXG5cdFx0XHQnc2hvd2FmZmlybSc6ICdmYWxzZScsXG5cdFx0fVxuXG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0XHR1cmw6IFVybHMuaGl0VGlsZSxcblx0XHRcdGRhdGE6IHJlcXVlc3REYXRhLFxuXHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRcdGlmIChkYXRhKSB7XG5cdFx0XHRcdFx0aHRtbEJ1ZmZlcltwcm9kdWN0SWRdID0gJzxsaSBjbGFzcz1cInNsaWRlXCI+JyArIGRhdGEgKyAnPC9saT4nO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0Y3VycmVudEh0bWxCdWZmZXJDb3VudCsrO1xuXHRcdFx0XHRyZW5kZXIoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHZhciByZW5kZXIgPSBmdW5jdGlvbigpIHtcblx0XHRpZiAoY3VycmVudEh0bWxCdWZmZXJDb3VudCA9PSBleHBlY3RlZEh0bWxCdWZmZXJDb3VudCkge1xuXHRcdFx0dmFyIGh0bWwgPSAnJztcblxuXHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGRhdGFCdWZmZXIucHJvZHVjdHMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdGlmIChodG1sQnVmZmVyW2RhdGFCdWZmZXIucHJvZHVjdHNbaW5kZXhdLnByb2R1Y3RpZF0pIHtcblx0XHRcdFx0XHRodG1sICs9IGh0bWxCdWZmZXJbZGF0YUJ1ZmZlci5wcm9kdWN0c1tpbmRleF0ucHJvZHVjdGlkXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgJGh0bWwgPSAkKGh0bWwpO1xuXHRcdFx0JGh0bWwuZmluZCgnLnByb2R1Y3QtdGlsZScpLmFkZENsYXNzKCdwcm9kdWN0Jyk7XG5cblx0XHRcdCRjb250YWluZXIuZmluZCgnLnNsaWRlcycpLmh0bWwoJGh0bWwpO1xuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcuc2xpZGVyLXByb2R1Y3RzLXByaW1hcnknKS50cmlnZ2VyKCdpbml0LXNsaWRlcicpO1xuXHRcdFx0ZmluaXNoKCk7XG5cblx0XHRcdGlmICgnYWZmaXJtJyBpbiB3aW5kb3cgJiYgJ3VpJyBpbiBhZmZpcm0gJiYgJ3JlZnJlc2gnIGluIGFmZmlybS51aSkge1xuXHRcdFx0ICAgIGFmZmlybS51aS5yZWZyZXNoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0dmFyIGZpbmlzaCA9IGZ1bmN0aW9uKCkge1xuXHRcdCRjb250YWluZXJCb2R5LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdSZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuRG9uZScsICRjb250YWluZXIpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0N1cnJlbmN5LlVwZGF0ZScsICRjb250YWluZXIpO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuZXhwb3J0cy5yZW5kZXIgPSByZW5kZXI7XG5cbnZhciBkYXRhO1xudmFyIGxvYWRlZDtcbnZhciBvcHRpb25zO1xudmFyICRjb250YWluZXI7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoJGNvbnRhaW5lck9iamVjdCwgb3B0aW9uc09iamVjdCkge1xuXHRpZiAoVXJscyAmJiBVcmxzLmdldFNhbWVEYXlTaGlwcGluZ0NvdW50ZG93bkRhdGEgJiYgVXJscy5nZXRTYW1lRGF5U2hpcHBpbmdDb3VudGRvd25Db250ZW50U2xvdCkge1xuXHRcdCRjb250YWluZXIgPSAkY29udGFpbmVyT2JqZWN0O1xuXHRcdG9wdGlvbnMgPSBvcHRpb25zT2JqZWN0O1xuXHRcdGRhdGEgPSB7fTtcblx0XHRsb2FkZWQgPSB7XG5cdFx0XHRDb250ZW50U2xvdDogZmFsc2UsXG5cdFx0XHREYXRhOiBmYWxzZVxuXHRcdH1cblx0XHRcblx0XHQkKGRvY3VtZW50KS5vZmYoJ1NhbWVEYXlTaGlwcGluZ0NvdW50ZG93bi5VcGRhdGUnKS5vbignU2FtZURheVNoaXBwaW5nQ291bnRkb3duLlVwZGF0ZScsIHVwZGF0ZSk7XG5cdFx0XG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLmdldFNhbWVEYXlTaGlwcGluZ0NvdW50ZG93bkRhdGEsXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRcdGxvYWRlZC5EYXRhID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5SZXNwb25zZSA9IHJlc3BvbnNlO1xuXHRcdFx0XHRyZW5kZXIoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRcblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuZ2V0U2FtZURheVNoaXBwaW5nQ291bnRkb3duQ29udGVudFNsb3QsXG5cdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKGh0bWwpIHtcblx0XHRcdFx0bG9hZGVkLkNvbnRlbnRTbG90ID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5IdG1sID0gaHRtbDtcblx0XHRcdFx0cmVuZGVyKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyKCkge1xuXHRpZiAobG9hZGVkICYmIGxvYWRlZC5Db250ZW50U2xvdCAmJiBsb2FkZWQuRGF0YSAmJiBkYXRhKSB7XG5cdFx0dmFyIGNvdW50ZG93blRleHQgPSAnJztcblx0XHRcblx0XHRpZiAoZGF0YS5SZXNwb25zZSAmJiBkYXRhLlJlc3BvbnNlLlRpbWVMZWZ0KSB7XG5cdFx0XHRpZiAoZGF0YS5SZXNwb25zZS5UaW1lTGVmdC5Ib3VycyA+IDApIHtcblx0XHRcdFx0Y291bnRkb3duVGV4dCArPSBkYXRhLlJlc3BvbnNlLlRpbWVMZWZ0LkhvdXJzICsgJyAnICsgKGRhdGEuUmVzcG9uc2UuVGltZUxlZnQuSG91cnMgPiAxID8gUmVzb3VyY2VzLkhPVVJTX0FCQlJFVklBVEVEIDogUmVzb3VyY2VzLkhPVVJfQUJCUkVWSUFURUQpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoZGF0YS5SZXNwb25zZS5UaW1lTGVmdC5NaW51dGVzID4gMCkge1xuXHRcdFx0XHRpZiAoY291bnRkb3duVGV4dCAhPSAnJykge1xuXHRcdFx0XHRcdGNvdW50ZG93blRleHQgKz0gJyAnO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRjb3VudGRvd25UZXh0ICs9IGRhdGEuUmVzcG9uc2UuVGltZUxlZnQuTWludXRlcyArICcgJyArIChkYXRhLlJlc3BvbnNlLlRpbWVMZWZ0Lk1pbnV0ZXMgPiAxID8gUmVzb3VyY2VzLk1JTlVURVNfQUJCUkVWSUFURUQgOiBSZXNvdXJjZXMuTUlOVVRFX0FCQlJFVklBVEVEKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZGF0YS5IdG1sKSB7XG5cdFx0XHQkY29udGFpbmVyLmh0bWwoZGF0YS5IdG1sKS5maW5kKCdpbnB1dFtuYW1lPVwiaW5pdFRpbWVcIl0nKS5yZW1vdmUoKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKGNvdW50ZG93blRleHQpIHtcblx0XHRcdCRjb250YWluZXIuaHRtbChfLnRlbXBsYXRlKCRjb250YWluZXIuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpKHtcblx0XHRcdFx0Y291bnRkb3duOiBjb3VudGRvd25UZXh0XG5cdFx0XHR9KSk7XG5cdFx0XHRcblx0XHRcdHVwZGF0ZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKGRvY3VtZW50KS5vZmYoJ1NhbWVEYXlTaGlwcGluZ0NvdW50ZG93bi5VcGRhdGUnKTtcblx0XHR9XG5cdH1cbn07XG5cbmZ1bmN0aW9uIHVwZGF0ZSgpIHtcblx0aWYgKCRjb250YWluZXIuaHRtbCgpLnJlcGxhY2UoLzwhLS0oW15cXGRdKiktLT4vZywgJycpLnRyaW0oKS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyICRzZWxlY3RlZFZhcmlhdGlvbiA9ICQoJy5wcm9kdWN0LXZhcmlhdGlvbnMgLmF0dHJpYnV0ZS1zaXplIC5zZWxlY3QtdGV4dCBbc2FtZS1kYXktc2hpcHBpbmddJyk7XG5cdFx0XG5cdFx0aWYgKCRzZWxlY3RlZFZhcmlhdGlvbi5sZW5ndGggPiAwKSB7XG5cdFx0XHRpZiAoJHNlbGVjdGVkVmFyaWF0aW9uLmF0dHIoJ3NhbWUtZGF5LXNoaXBwaW5nJykudG9Mb3dlckNhc2UoKSA9PSAndHJ1ZScpIHtcblx0XHRcdFx0JGNvbnRhaW5lci5zaG93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHBhcnNlRmxvYXQob3B0aW9ucy5wZXJjZW50YWdlT2ZWYXJpYW50c0Zyb21XYXJlaG91c2UpID49IHBhcnNlRmxvYXQob3B0aW9ucy5zYW1lRGF5U2hpcHBpbmdXaW5kb3dXYXJlaG91c2VQZXJjZW50YWdlKSkge1xuXHRcdFx0JGNvbnRhaW5lci5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRjb250YWluZXIuaGlkZSgpO1xuXHRcdH1cblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG5cbi8qKlxuICogQGZ1bmN0aW9uIGNvb2tpZXByaXZhY3kgICAgVXNlZCB0byBkaXNwbGF5L2NvbnRyb2wgdGhlIHNjcmltIGNvbnRhaW5pbmcgdGhlIGNvb2tpZSBwcml2YWN5IGNvZGVcbiAqKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgIC8qKlxuICAgICAqIElmIHdlIGhhdmUgbm90IGFjY2VwdGVkIGNvb2tpZXMgQU5EIHdlJ3JlIG5vdCBvbiB0aGUgUHJpdmFjeSBQb2xpY3kgcGFnZSwgdGhlbiBzaG93IHRoZSBub3RpZmljYXRpb25cbiAgICAgKiBOT1RFOiBZb3Ugd2lsbCBwcm9iYWJseSB3YW50IHRvIGFkanVzdCB0aGUgUHJpdmFjeSBQYWdlIHRlc3QgdG8gbWF0Y2ggeW91ciBzaXRlJ3Mgc3BlY2lmaWMgcHJpdmFjeSAvIGNvb2tpZSBwYWdlXG4gICAgICovXG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT09LSUVfSElOVCA9PT0gdHJ1ZSAmJiBkb2N1bWVudC5jb29raWUuaW5kZXhPZignZHdfY29va2llc19hY2NlcHRlZCcpIDwgMCkge1xuICAgICAgICAvLyBjaGVjayBmb3IgcHJpdmFjeSBwb2xpY3kgcGFnZVxuICAgICAgICBpZiAoJCgnLnByaXZhY3ktcG9saWN5JykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICAgICAgdXJsOiBVcmxzLmNvb2tpZUhpbnQsXG4gICAgICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBjbG9zZU9uRXNjYXBlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgZGlhbG9nQ2xhc3M6ICduby1jbG9zZScsXG4gICAgICAgICAgICAgICAgICAgIGJ1dHRvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuSV9BR1JFRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5kaWFsb2coJ2Nsb3NlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5hYmxlQ29va2llcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gT3RoZXJ3aXNlLCB3ZSBkb24ndCBuZWVkIHRvIHNob3cgdGhlIGFzc2V0LCBqdXN0IGVuYWJsZSB0aGUgY29va2llc1xuICAgICAgICBlbmFibGVDb29raWVzKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW5hYmxlQ29va2llcygpIHtcbiAgICAgICAgaWYgKGRvY3VtZW50LmNvb2tpZS5pbmRleE9mKCdkdz0xJykgPCAwKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSAnZHc9MTsgcGF0aD0vJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoZG9jdW1lbnQuY29va2llLmluZGV4T2YoJ2R3X2Nvb2tpZXNfYWNjZXB0ZWQnKSA8IDApIHtcbiAgICAgICAgICAgIGRvY3VtZW50LmNvb2tpZSA9ICdkd19jb29raWVzX2FjY2VwdGVkPTE7IHBhdGg9Lyc7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiBpbml0ICgpIHtcblxuICAgICQoJy5jb3VudGRvd24td3JhcHBlcicpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXG4gICAgICAgICAgY291bnRkb3duU3RyID0gJHRoaXMuZGF0YSgnY291bnRkb3duLWRhdGUnKSxcbiAgICAgICAgICBjb3VudGRvd25EYXRlID0gbmV3IERhdGUoY291bnRkb3duU3RyKTtcblxuICAgICAgICB2YXIgdHMgPSBjb3VudGRvd24obmV3IERhdGUoKSwgY291bnRkb3duRGF0ZSwgY291bnRkb3duLkRBWVMgfCBjb3VudGRvd24uSE9VUlMgfCBjb3VudGRvd24uTUlOVVRFUyk7XG4gICAgICAgIHZhciBzaG93Q291bnRkb3duID0gdHMudmFsdWUgPiAwO1xuXG4gICAgICAgIGlmIChzaG93Q291bnRkb3duKSB7XG4gICAgICAgICAgJHRoaXMuZmluZCgnLmNvdW50ZG93bi10ZXh0JykudGV4dCh0cy50b1N0cmluZygpKTtcbiAgICAgICAgfVxuXG5cbiAgICB9KTtcblxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gaW5pdCAoKSB7XG4gICAgJCgnLmNvdW50cnktc2VsZWN0b3IgLmN1cnJlbnQtY291bnRyeScpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnLmNvdW50cnktc2VsZWN0b3IgLnNlbGVjdG9yJykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAkKHRoaXMpLnRvZ2dsZUNsYXNzKCdzZWxlY3Rvci1hY3RpdmUnKTtcbiAgICB9KTtcbiAgICAvLyBzZXQgY3VycmVuY3kgZmlyc3QgYmVmb3JlIHJlbG9hZFxuICAgICQoJy5jb3VudHJ5LXNlbGVjdG9yIC5zZWxlY3RvciAubG9jYWxlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdXJsID0gdGhpcy5ocmVmO1xuICAgICAgICB2YXIgY3VycmVuY3kgPSB0aGlzLmdldEF0dHJpYnV0ZSgnZGF0YS1jdXJyZW5jeScpO1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgIHVybDogVXJscy5zZXRTZXNzaW9uQ3VycmVuY3ksXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgZm9ybWF0OiAnYWpheCcsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lNbmVtb25pYzogY3VycmVuY3lcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBzZXQgY3VycmVuY3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi9hamF4JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcbiAgICBpbWFnZXNMb2FkZWQgPSByZXF1aXJlKCdpbWFnZXNsb2FkZWQnKTtcblxudmFyIGRpYWxvZyA9IHtcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQXBwZW5kcyBhIGRpYWxvZyB0byBhIGdpdmVuIGNvbnRhaW5lciAodGFyZ2V0KVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgIHBhcmFtcy50YXJnZXQgY2FuIGJlIGFuIGlkIHNlbGVjdG9yIG9yIGFuIGpxdWVyeSBvYmplY3RcbiAgICAgKi9cbiAgICBjcmVhdGU6IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyICR0YXJnZXQsIGlkO1xuXG4gICAgICAgIGlmIChfLmlzU3RyaW5nKHBhcmFtcy50YXJnZXQpKSB7XG4gICAgICAgICAgICBpZiAocGFyYW1zLnRhcmdldC5jaGFyQXQoMCkgPT09ICcjJykge1xuICAgICAgICAgICAgICAgICR0YXJnZXQgPSAkKHBhcmFtcy50YXJnZXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJCgnIycgKyBwYXJhbXMudGFyZ2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMudGFyZ2V0IGluc3RhbmNlb2YgalF1ZXJ5KSB7XG4gICAgICAgICAgICAkdGFyZ2V0ID0gcGFyYW1zLnRhcmdldDtcbiAgICAgICAgfSBlbHNlIGlmICgkKCcjZGlhbG9nLWNvbnRhaW5lcicpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICR0YXJnZXQgPSAkKCcjZGlhbG9nLWNvbnRhaW5lcicpO1xuICAgICAgICB9IGVsc2Uge1xuXHRcdFx0JHRhcmdldCA9ICQoJzxkaXYgaWQ9XCJkaWFsb2ctY29udGFpbmVyXCIvPicpLmFwcGVuZFRvKCdib2R5Jyk7XG5cdFx0fVxuXG4gICAgICAgIC8vIGlmIG5vIGVsZW1lbnQgZm91bmQsIGNyZWF0ZSBvbmVcbiAgICAgICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBpZiAoJHRhcmdldC5zZWxlY3RvciAmJiAkdGFyZ2V0LnNlbGVjdG9yLmNoYXJBdCgwKSA9PT0gJyMnKSB7XG4gICAgICAgICAgICAgICAgaWQgPSAkdGFyZ2V0LnNlbGVjdG9yLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJCgnPGRpdj4nKS5hdHRyKCdpZCcsIGlkKS5hZGRDbGFzcygnZGlhbG9nLWNvbnRlbnQnKS5hcHBlbmRUbygnYm9keScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChwYXJhbXMub3B0aW9ucyAhPSB1bmRlZmluZWQgJiYgcGFyYW1zLm9wdGlvbnMgIT0gbnVsbCkgJiYgKHBhcmFtcy5vcHRpb25zLnRpdGxlID09IHVuZGVmaW5lZCB8fCAoJ3RpdGxlJyBpbiBwYXJhbXMub3B0aW9ucyAmJiBwYXJhbXMub3B0aW9ucy50aXRsZS5sZW5ndGggPT0gMCkpKSB7XG4gICAgICAgICAgICBwYXJhbXMub3B0aW9ucy5kaWFsb2dDbGFzcyArPSAnIHVpLWRpYWxvZy10aXRsZS1jb2xsYXBzZSc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgdGhlIGRpYWxvZ1xuICAgICAgICB0aGlzLiRjb250YWluZXIgPSAkdGFyZ2V0O1xuICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKF8ubWVyZ2Uoe30sIHRoaXMuc2V0dGluZ3MsIHBhcmFtcy5vcHRpb25zIHx8IHt9KSk7XG5cbiAgICAgICAgLyogLS0tIEJPT1QtNTM4NiAtLS1cbiAgICAgICAgICogVGhpcyBpcyBhIHdvcmthcm91bmQgZm9yIGEga25vd24ganF1ZXJ5IERpYWxvZyBVSSBidWcgd2l0aCB0aGUgbWF4V2lkdGggb3B0aW9uLiBCeSBzZXR0aW5nIHRoZSBEaWFsb2cgd2lkdGggb3B0aW9uIHRvIDEwMCUgYW5kIHNldHRpbmcgdGhlIENTUyBtYXgtd2lkdGhcbiAgICAgICAgICogdG8gODAwcHgsIHRoaXMgYWxsb3dzIHRoZSBkaWFsb2dzIHRvIGJlIHJlc3BvbnNpdmUgd2lkdGguIFRoaXMgZml4IGlzIG5lY2Vzc2FyeSB0byBjcmVhdGUgcmVzcG9uc2l2ZSBEaWFsb2dzIGZvciBzbWFsbGVyIHNjcmVlbnMsIGJ1dCBhbHNvIGJlIGJhY2t3YXJkcyBcbiAgICAgICAgICogY29tcGF0aWJsZSB3aXRoIGV4aXN0aW5nIGRpYWxvZ3Mgb24gdGhlIHNpdGUgdGhhdCBoYXZlIGJlZW4gcHJldmlvdXNseSBzZXQgdG8gdGhlIGRlZmF1bHQgc2l6ZSBvZiA4MDBweC5cbiAgICAgICAgICogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTY0NzE4OTAvcmVzcG9uc2l2ZS1qcXVlcnktdWktZGlhbG9nLWFuZC1hLWZpeC1mb3ItbWF4d2lkdGgtYnVnXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLiRjb250YWluZXIucGFyZW50KCkuY3NzKFwibWF4LXdpZHRoXCIsIFwiODAwcHhcIik7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gT3BlbnMgYSBkaWFsb2cgdXNpbmcgdGhlIGdpdmVuIHVybCAocGFyYW1zLnVybCkgb3IgaHRtbCAocGFyYW1zLmh0bWwpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMudXJsIHNob3VsZCBjb250YWluIHRoZSB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLmh0bWwgY29udGFpbnMgdGhlIGh0bWwgb2YgdGhlIGRpYWxvZyBjb250ZW50XG4gICAgICovXG4gICAgb3BlbjogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAvLyBjbG9zZSBhbnkgb3BlbiBkaWFsb2dcbiAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICB0aGlzLmNyZWF0ZShwYXJhbXMpO1xuICAgICAgICB0aGlzLnJlcGxhY2UocGFyYW1zKTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBwb3B1bGF0ZSB0aGUgZGlhbG9nIHdpdGggaHRtbCBjb250ZW50LCB0aGVuIG9wZW4gaXRcbiAgICAgKiovXG4gICAgb3BlbldpdGhDb250ZW50OiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBjb250ZW50LCBwb3NpdGlvbiwgY2FsbGJhY2s7XG5cbiAgICAgICAgaWYgKCF0aGlzLiRjb250YWluZXIpIHsgcmV0dXJuOyB9XG4gICAgICAgIGNvbnRlbnQgPSBwYXJhbXMuY29udGVudCB8fCBwYXJhbXMuaHRtbDtcbiAgICAgICAgaWYgKCFjb250ZW50KSB7IHJldHVybjsgfVxuICAgICAgICB0aGlzLiRjb250YWluZXIuZW1wdHkoKS5odG1sKGNvbnRlbnQpO1xuICAgICAgICBpZiAoIXRoaXMuJGNvbnRhaW5lci5kaWFsb2coJ2lzT3BlbicpKSB7XG4gICAgICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKCdvcGVuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLm9wdGlvbnMpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gcGFyYW1zLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFwb3NpdGlvbikge1xuICAgICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnNldHRpbmdzLnBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlc0xvYWRlZCh0aGlzLiRjb250YWluZXIpLm9uKCdkb25lJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyLmRpYWxvZygnb3B0aW9uJywgJ3Bvc2l0aW9uJywgcG9zaXRpb24pO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgICAgIGNhbGxiYWNrID0gKHR5cGVvZiBwYXJhbXMuY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpID8gcGFyYW1zLmNhbGxiYWNrIDogZnVuY3Rpb24gKCkge307XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gUmVwbGFjZSB0aGUgY29udGVudCBvZiBjdXJyZW50IGRpYWxvZ1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwYXJhbXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1zLnVybCAtIElmIHRoZSB1cmwgcHJvcGVydHkgaXMgcHJvdmlkZWQsIGFuIGFqYXggY2FsbCBpcyBwZXJmb3JtZWQgdG8gZ2V0IHRoZSBjb250ZW50IHRvIHJlcGxhY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1zLmh0bWwgLSBJZiBubyB1cmwgcHJvcGVydHkgaXMgcHJvdmlkZWQsIHVzZSBodG1sIHByb3ZpZGVkIHRvIHJlcGxhY2VcbiAgICAgKi9cbiAgICByZXBsYWNlOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmICghdGhpcy4kY29udGFpbmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy51cmwpIHtcbiAgICAgICAgICAgIHBhcmFtcy51cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwocGFyYW1zLnVybCwgJ2Zvcm1hdCcsICdhamF4Jyk7XG4gICAgICAgICAgICBhamF4LmxvYWQoe1xuICAgICAgICAgICAgICAgIHVybDogcGFyYW1zLnVybCxcbiAgICAgICAgICAgICAgICBkYXRhOiBwYXJhbXMuZGF0YSxcbiAgICAgICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtcy5jb250ZW50ID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbldpdGhDb250ZW50KHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuaHRtbCkge1xuICAgICAgICAgICAgdGhpcy5vcGVuV2l0aENvbnRlbnQocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgZGlhbG9nXG4gICAgICovXG4gICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLiRjb250YWluZXIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKCdjbG9zZScpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFN1Ym1pdHMgdGhlIGRpYWxvZyBmb3JtIHdpdGggdGhlIGdpdmVuIGFjdGlvblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBUaGUgYWN0aW9uIHdoaWNoIHdpbGwgYmUgdHJpZ2dlcmVkIHVwb24gZm9ybSBzdWJtaXRcbiAgICAgKi9cbiAgICBzdWJtaXQ6IGZ1bmN0aW9uIChhY3Rpb24sIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciAkZm9ybSA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCdmb3JtOmZpcnN0Jyk7XG4gICAgICAgIC8vIHNldCB0aGUgYWN0aW9uXG4gICAgICAgICQoJzxpbnB1dC8+JykuYXR0cih7XG4gICAgICAgICAgICBuYW1lOiBhY3Rpb24sXG4gICAgICAgICAgICB0eXBlOiAnaGlkZGVuJ1xuICAgICAgICB9KS5hcHBlbmRUbygkZm9ybSk7XG4gICAgICAgIC8vIHNlcmlhbGl6ZSB0aGUgZm9ybSBhbmQgZ2V0IHRoZSBwb3N0IHVybFxuICAgICAgICB2YXIgZGF0YSA9ICRmb3JtLnNlcmlhbGl6ZSgpO1xuICAgICAgICB2YXIgdXJsID0gJGZvcm0uYXR0cignYWN0aW9uJyk7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSB0aGUgc2VydmVyIGtub3dzIHRoaXMgaXMgYW4gYWpheCByZXF1ZXN0XG4gICAgICAgIGlmIChkYXRhLmluZGV4T2YoJ2FqYXgnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIGRhdGEgKz0gJyZmb3JtYXQ9YWpheCc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcG9zdCB0aGUgZGF0YSBhbmQgcmVwbGFjZSBjdXJyZW50IGNvbnRlbnQgd2l0aCByZXNwb25zZSBjb250ZW50XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2h0bWwnLFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGh0bWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjb250YWluZXIuaHRtbChodG1sKTtcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LmJpbmQodGhpcyksXG4gICAgICAgICAgICBmYWlsdXJlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5TRVJWRVJfRVJST1IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGV4aXN0czogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kY29udGFpbmVyICYmICh0aGlzLiRjb250YWluZXIubGVuZ3RoID4gMCk7XG4gICAgfSxcbiAgICBpc0FjdGl2ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5leGlzdHMoKSAmJiAodGhpcy4kY29udGFpbmVyLmNoaWxkcmVuLmxlbmd0aCA+IDApO1xuICAgIH0sXG4gICAgc2V0dGluZ3M6IHtcbiAgICAgICAgYXV0b09wZW46IGZhbHNlLFxuICAgICAgICBoZWlnaHQ6ICdhdXRvJyxcbiAgICAgICAgbW9kYWw6IHRydWUsXG4gICAgICAgIG92ZXJsYXk6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuNSxcbiAgICAgICAgICAgIGJhY2tncm91bmQ6ICdibGFjaydcbiAgICAgICAgfSxcbiAgICAgICAgcmVzaXphYmxlOiBmYWxzZSxcbiAgICAgICAgdGl0bGU6ICcnLFxuICAgICAgICB3aWR0aDogJzEwMCUnLFxuXHRcdG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XG5cdFx0fSxcbiAgICAgICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICB9LFxuICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgbXk6ICdjZW50ZXInLFxuICAgICAgICAgICAgYXQ6ICdjZW50ZXInLFxuICAgICAgICAgICAgb2Y6IHdpbmRvdyxcbiAgICAgICAgICAgIGNvbGxpc2lvbjogJ2ZsaXBmaXQnXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRpYWxvZztcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcblx0ZGlhbG9nID0gcmVxdWlyZSgnLi9kaWFsb2cnKTtcblxudmFyICRkaWFsb2dDb250ZW50LFxuXHRzdGF0ZSA9IHt9LFxuXHRyZWFkeSA9IHt9LFxuXHR0ZW1wbGF0ZXMgPSB7fSxcblx0aHRtbCA9IHt9O1xuXG52YXIgdGVtcGxhdGVTZXR0aW5ncyA9IHsgaW50ZXJwb2xhdGU6IC97eyhbXFxzXFxTXSs/KX19L2cgfTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zKSB7XG5cdHN0YXRlWydvcHRpb25zJ10gPSBvcHRpb25zIHx8IHt9O1xuXHRcblx0bG9hZFRlbXBsYXRlcygpO1xuXHRsb2FkU3RvcmVzKCk7XG5cdGxvYWRTdGF0ZXMoKTtcblx0XG5cdG9wZW5EaWFsb2coKTtcdFxufVxuXG5mdW5jdGlvbiBvcGVuRGlhbG9nKCkge1xuXHRyZWFkeVsnZGlhbG9nJ10gPSBmYWxzZTtcblx0XG5cdGRpYWxvZy5vcGVuKHtcblx0XHRodG1sOiAnPGRpdiBjbGFzcz1cImRpYWxvZy1sb2FkaW5nXCI+PC9kaXY+Jyxcblx0XHRvcHRpb25zOiB7XG5cdFx0XHR0aXRsZTogUmVzb3VyY2VzLkZJTkRfTU9SRV9TVE9SRVMsXG5cdFx0XHRkaWFsb2dDbGFzczogJ2RpYWxvZy1maW5kLW1vcmUtc3RvcmVzJyxcblx0XHRcdHJlc2l6YWJsZTogZmFsc2UsXG5cdFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0b3BlbjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRkaWFsb2dDb250ZW50ID0gJCh0aGlzKTtcblx0XHRcdFx0cmVhZHlbJ2RpYWxvZyddID0gdHJ1ZTtcblx0XHRcdFx0XG5cdFx0XHRcdGV2ZW50cygpO1xuXHRcdFx0XHRyZW5kZXIoKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBldmVudHMoKSB7XG5cdCRkaWFsb2dDb250ZW50Lm9mZignY2xpY2suZmluZE1vcmVTdG9yZXMuZ28nKS5vbignY2xpY2suZmluZE1vcmVTdG9yZXMuZ28nLCAnLnNlYXJjaCBidXR0b24nLCBmdW5jdGlvbiAoKSB7XG5cdFx0bG9hZFN0b3Jlcyh0cnVlKTtcblx0fSk7XG5cdFxuXHQkZGlhbG9nQ29udGVudC5vZmYoJ2NsaWNrLmZpbmRNb3JlU3RvcmVzLnN1Ym1pdCcpLm9uKCdjbGljay5maW5kTW9yZVN0b3Jlcy5zdWJtaXQnLCAnLnN1Ym1pdCcsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZWN0ZWRTdG9yZSA9ICRkaWFsb2dDb250ZW50LmZpbmQoJy5zdG9yZXMtbGlzdCBpbnB1dDpjaGVja2VkJykudmFsKCk7XG5cdFx0XG5cdFx0aWYgKHNlbGVjdGVkU3RvcmUpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ29wYy5TZXRTaGlwcGluZ0FkZHJlc3MnLCBzdGF0ZVsnc3RvcmVzJ10uYWRkcmVzc2VzW3NlbGVjdGVkU3RvcmVdKTtcblx0XHRcdGRpYWxvZy5jbG9zZSgpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGxvYWRTdGF0ZXMoKSB7XG5cdHJlYWR5WydzdGF0ZXMnXSA9IGZhbHNlO1xuXHRcblx0JC5hamF4KHsgbWV0aG9kOiAnUE9TVCcsIHVybDogVXJscy5nZXRDb3VudHJ5U3RhdGVzLCBkYXRhOiAnY291bnRyeUNvZGU9VVMnLCBkYXRhVHlwZTogJ2pzb24nLCBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1x0XHRcblx0XHRzdGF0ZVsnc3RhdGVzJ10gPSBKU09OLnBhcnNlKGRhdGEuc3RhdGVzTGlzdCk7XG5cdFx0cmVhZHlbJ3N0YXRlcyddID0gdHJ1ZTtcblx0XHRcdFx0XG5cdFx0cmVuZGVyKCk7XG5cdH19KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU3RhdGVzKCkge1xuXHRodG1sWydzdGF0ZXMnXSA9ICc8b3B0aW9uIGNsYXNzPVwicGxhY2Vob2xkZXJcIj48L29wdGlvbj4nO1xuXHRcblx0Zm9yICh2YXIgc3RhdGVFbGVtZW50IGluIHN0YXRlWydzdGF0ZXMnXSkge1xuXHRcdHZhciBzdGF0ZU9wdGlvbiA9IHN0YXRlLnN0YXRlc1tzdGF0ZUVsZW1lbnRdO1xuXHRcdFxuXHRcdGh0bWxbJ3N0YXRlcyddICs9ICc8b3B0aW9uIHZhbHVlPVwiJyArIHN0YXRlT3B0aW9uLmxhYmVsICsgJ1wiPicgKyBzdGF0ZU9wdGlvbi5sYWJlbCArICc8L29wdGlvbj4nO1xuXHR9XG5cdFxuXHQkZGlhbG9nQ29udGVudC5maW5kKCdzZWxlY3RbbmFtZT1cIlN0YXRlQ29kZVwiXScpLmh0bWwoaHRtbFsnc3RhdGVzJ10pO1xufVxuXG5mdW5jdGlvbiBsb2FkU3RvcmVzKHVwZGF0ZSkge1xuXHRyZWFkeVsnc3RvcmVzJ10gPSBmYWxzZTtcblx0XG5cdHZhciBwYXlsb2FkID0ge307XG5cdFxuXHRpZiAoJGRpYWxvZ0NvbnRlbnQpIHtcblx0XHRwYXlsb2FkLlBvc3RhbENvZGUgPSAkZGlhbG9nQ29udGVudC5maW5kKCcuc2VhcmNoIFtuYW1lPVwiUG9zdGFsQ29kZVwiXScpLnZhbCgpO1xuXHRcdHBheWxvYWQuU3RhdGVDb2RlID0gJGRpYWxvZ0NvbnRlbnQuZmluZCgnLnNlYXJjaCBbbmFtZT1cIlN0YXRlQ29kZVwiXScpLnZhbCgpO1xuXHR9XG5cdFxuXHRwYXlsb2FkLnN0b3JlUXVlcnkgPSBzdGF0ZS5vcHRpb25zWydzdG9yZVF1ZXJ5J10gPyBzdGF0ZS5vcHRpb25zWydzdG9yZVF1ZXJ5J10gOiB7fTtcblx0XG5cdCQuYWpheCh7IG1ldGhvZDogJ1BPU1QnLCB1cmw6IFVybHMuZ2V0TW9yZVN0b3Jlc0FkZHJlc3NMaXN0LCBkYXRhOiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSwgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJywgZGF0YVR5cGU6ICdqc29uJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcdFx0XG5cdFx0c3RhdGVbJ3N0b3JlcyddID0gZGF0YTtcblx0XHRyZWFkeVsnc3RvcmVzJ10gPSB0cnVlO1xuXHRcdFxuXHRcdGlmICh1cGRhdGUpIHtcblx0XHRcdHJlbmRlclN0b3JlcygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZW5kZXIoKTtcblx0XHR9XG5cdH19KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU3RvcmVzKCkge1xuXHRodG1sWydzdG9yZXMnXSA9ICcnO1xuXHRcblx0aWYgKHN0YXRlWydzdG9yZXMnXS5hZGRyZXNzZXMubGVuZ3RoID4gMCkge1xuXHRcdHZhciBpbmRleCA9IDA7XG5cdFx0Zm9yICh2YXIgc3RvcmVBZGRyZXNzZXNFbGVtZW50IGluIHN0YXRlWydzdG9yZXMnXS5hZGRyZXNzZXMpIHtcblx0XHRcdHZhciBzdG9yZUFkZHJlc3MgPSBzdGF0ZVsnc3RvcmVzJ10uYWRkcmVzc2VzW3N0b3JlQWRkcmVzc2VzRWxlbWVudF07XG5cdFx0XHRcblx0XHRcdHZhciBzdHJlZXRBZGRyZXNzID0gc3RvcmVBZGRyZXNzLmFkZHJlc3MxO1xuXHRcdFx0aWYgKHN0b3JlQWRkcmVzcy5hZGRyZXNzMikge1xuXHRcdFx0XHRzdHJlZXRBZGRyZXNzICs9IHN0b3JlQWRkcmVzcy5hZGRyZXNzMjtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aHRtbFsnc3RvcmVzJ10gKz0gdGVtcGxhdGVzWydsb2NhdGlvbiddKHtcblx0XHRcdFx0aWQ6IGluZGV4LFxuXHRcdFx0XHRuYW1lOiBzdG9yZUFkZHJlc3MuZnVsbE5hbWUgKyAnICcgKyBzdG9yZUFkZHJlc3MubGFzdE5hbWUsXG5cdFx0XHRcdGFkZHJlc3M6IHN0cmVldEFkZHJlc3MsXG5cdFx0XHRcdGNpdHk6IHN0b3JlQWRkcmVzcy5jaXR5LFxuXHRcdFx0XHRzdGF0ZTogc3RvcmVBZGRyZXNzLnN0YXRlQ29kZSxcblx0XHRcdFx0cG9zdGFsOiBzdG9yZUFkZHJlc3MucG9zdGFsQ29kZSxcblx0XHRcdFx0cGhvbmU6IHN0b3JlQWRkcmVzcy5waG9uZVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdGluZGV4Kys7XG5cdFx0fVxuXHRcdFxuXHRcdCRkaWFsb2dDb250ZW50LmZpbmQoJy5uby1yZXN1bHRzJykuaGlkZSgpO1xuXHRcdCRkaWFsb2dDb250ZW50LmZpbmQoJy5zdG9yZXMtbGlzdCcpLmh0bWwoaHRtbFsnc3RvcmVzJ10pLnNob3coKTtcblx0fSBlbHNlIHtcblx0XHQkZGlhbG9nQ29udGVudC5maW5kKCcubm8tcmVzdWx0cycpLnNob3coKTtcblx0XHQkZGlhbG9nQ29udGVudC5maW5kKCcuc3RvcmVzLWxpc3QnKS5oaWRlKCk7XG5cdH1cblx0XG5cdFxufVxuXG5mdW5jdGlvbiBsb2FkVGVtcGxhdGVzKCkge1xuXHR0ZW1wbGF0ZXMgPSB7fTtcblx0XG5cdCQuYWpheCh7IG1ldGhvZDogJ1BPU1QnLCB1cmw6IFVybHMuZ2V0TW9yZVN0b3Jlc0RpYWxvZ1RlbXBsYXRlLCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdHRlbXBsYXRlc1snZGlhbG9nJ10gPSBfLnRlbXBsYXRlKGRhdGEsIHRlbXBsYXRlU2V0dGluZ3MpO1xuXHRcdHJlbmRlcigpO1xuXHR9fSk7XG5cdFxuXHQkLmFqYXgoeyBtZXRob2Q6ICdQT1NUJywgdXJsOiBVcmxzLmdldE1vcmVTdG9yZXNMb2NhdGlvblRlbXBsYXRlLCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdHRlbXBsYXRlc1snbG9jYXRpb24nXSA9IF8udGVtcGxhdGUoZGF0YSwgdGVtcGxhdGVTZXR0aW5ncyk7XG5cdFx0cmVuZGVyKCk7XG5cdH19KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyKHVwZGF0ZSkge1xuXHRpZiAocmVhZHlbJ2RpYWxvZyddICYmIHJlYWR5WydzdG9yZXMnXSAmJiByZWFkeVsnc3RhdGVzJ10gJiYgdGVtcGxhdGVzWydkaWFsb2cnXSAmJiB0ZW1wbGF0ZXNbJ2xvY2F0aW9uJ10pIHtcblx0XHQkZGlhbG9nQ29udGVudC5odG1sKHRlbXBsYXRlc1snZGlhbG9nJ10oKSk7XG5cdFx0XG5cdFx0aWYgKHN0YXRlLm9wdGlvbnMgJiYgc3RhdGUub3B0aW9ucy52aWV3KSB7XG5cdFx0XHQkZGlhbG9nQ29udGVudC5hdHRyKCd2aWV3Jywgc3RhdGUub3B0aW9ucy52aWV3KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JGRpYWxvZ0NvbnRlbnQucmVtb3ZlQXR0cigndmlldycpO1xuXHRcdH1cblx0XHRcblx0XHRyZW5kZXJTdG9yZXMoKTtcblx0XHRyZW5kZXJTdGF0ZXMoKTtcblx0fVx0XG59XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4vYWpheCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gTG9hZCBkZXRhaWxzIHRvIGEgZ2l2ZW4gZ2lmdCBjZXJ0aWZpY2F0ZVxuICogQHBhcmFtIHtTdHJpbmd9IGlkIFRoZSBJRCBvZiB0aGUgZ2lmdCBjZXJ0aWZpY2F0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgQSBmdW5jdGlvbiB0byBjYWxsZWRcbiAqL1xuZXhwb3J0cy5jaGVja0JhbGFuY2UgPSBmdW5jdGlvbiAoaWQsIGNhbGxiYWNrKSB7XG4gICAgLy8gbG9hZCBnaWZ0IGNlcnRpZmljYXRlIGRldGFpbHNcbiAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMuZ2lmdENhcmRDaGVja0JhbGFuY2UsICdnaWZ0Q2VydGlmaWNhdGVJRCcsIGlkKTtcblxuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogY2FsbGJhY2tcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi9hamF4JyksXG4gICAgbWluaWNhcnQgPSByZXF1aXJlKCcuL21pbmljYXJ0JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG52YXIgc2V0QWRkVG9DYXJ0SGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciBmb3JtID0gJCh0aGlzKS5jbG9zZXN0KCdmb3JtJyk7XG5cbiAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoZm9ybS5hdHRyKCdhY3Rpb24nKSksXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgIGRhdGE6IGZvcm0uc2VyaWFsaXplKClcbiAgICB9O1xuICAgICQuYWpheChvcHRpb25zKS5kb25lKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICBpZiAocmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgYWpheC5sb2FkKHtcbiAgICAgICAgICAgICAgICB1cmw6IFVybHMubWluaWNhcnRHQyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7bGluZUl0ZW1JZDogcmVzcG9uc2UucmVzdWx0LmxpbmVJdGVtSWR9LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluaWNhcnQuc2hvdyhyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgICAgIGZvcm0uZmluZCgnaW5wdXQsdGV4dGFyZWEnKS52YWwoJycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9ybS5maW5kKCdzcGFuLmVycm9yJykuaGlkZSgpO1xuICAgICAgICAgICAgZm9yICh2YXIgaWQgaW4gcmVzcG9uc2UuZXJyb3JzLkZvcm1FcnJvcnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVycm9yRWwgPSAkKCcjJyArIGlkKS5hZGRDbGFzcygnZXJyb3InKS5yZW1vdmVDbGFzcygndmFsaWQnKS5uZXh0KCcuZXJyb3InKTtcbiAgICAgICAgICAgICAgICBpZiAoISRlcnJvckVsIHx8ICRlcnJvckVsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAkZXJyb3JFbCA9ICQoJzxzcGFuIGZvcj1cIicgKyBpZCArICdcIiBnZW5lcmF0ZWQ9XCJ0cnVlXCIgY2xhc3M9XCJlcnJvclwiIHN0eWxlPVwiXCI+PC9zcGFuPicpO1xuICAgICAgICAgICAgICAgICAgICAkKCcjJyArIGlkKS5hZnRlcigkZXJyb3JFbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRlcnJvckVsLnRleHQocmVzcG9uc2UuZXJyb3JzLkZvcm1FcnJvcnNbaWRdLnJlcGxhY2UoL1xcXFwnL2csICdcXCcnKSkuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSkuZmFpbChmdW5jdGlvbiAoeGhyLCB0ZXh0U3RhdHVzKSB7XG4gICAgICAgIC8vIGZhaWxlZFxuICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5TRVJWRVJfQ09OTkVDVElPTl9FUlJPUik7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcjQWRkVG9CYXNrZXRCdXR0b24nKS5vbignY2xpY2snLCBzZXRBZGRUb0NhcnRIYW5kbGVyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50ID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50Jyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZUFsbEZvdW5kQ29tcG9uZW50cyA9IGluaXRpYWxpemVBbGxGb3VuZENvbXBvbmVudHM7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVBbGxGb3VuZENvbXBvbmVudHMoJGNvbnRhaW5lclBhcmFtZXRlcikge1xuXHR2YXIgJGNvbnRhaW5lciA9ICRjb250YWluZXJQYXJhbWV0ZXIgfHwgJChkb2N1bWVudCk7XG5cdFxuXHR2YXIgJGJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50cyA9ICRjb250YWluZXIuZmluZCgnLmdpZnQtY2FyZC1iYWxhbmNlLWlucXVpcnktY29tcG9uZW50Jyk7XG5cdGlmICgkYmFsYW5jZUlucXVpcnlDb21wb25lbnRzLmxlbmd0aCA+IDApIHtcblx0XHQkYmFsYW5jZUlucXVpcnlDb21wb25lbnRzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50LmluaXRpYWxpemUoJCh0aGlzKS5wYXJlbnQoKSk7XG5cdFx0fSk7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuVmFsaWRhdGUgPSB2YWxpZGF0ZTtcblxuZnVuY3Rpb24gdmFsaWRhdGUoYWN0aW9uKSB7XG5cdHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAncG9zdCcsXG5cdFx0XHR1cmw6IFVybHMuUmVxdWVzdC5WYWxpZGF0ZSxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdEFjdGlvbjogYWN0aW9uXG5cdFx0XHR9KSxcblx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdGlmIChkYXRhKSB7XG5cdFx0XHRcdFx0cmVzb2x2ZShkYXRhKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZWplY3QoZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJlamVjdChkYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn0iLCIndXNlIHN0cmljdCc7XG4vLyBqUXVlcnkgZXh0ZW5zaW9uc1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBwYXJhbXNcbiAgICAvLyB0b2dnbGVDbGFzcyAtIHJlcXVpcmVkXG4gICAgLy8gdHJpZ2dlclNlbGVjdG9yIC0gb3B0aW9uYWwuIHRoZSBzZWxlY3RvciBmb3IgdGhlIGVsZW1lbnQgdGhhdCB0cmlnZ2VycyB0aGUgZXZlbnQgaGFuZGxlci4gZGVmYXVsdHMgdG8gdGhlIGNoaWxkIGVsZW1lbnRzIG9mIHRoZSBsaXN0LlxuICAgIC8vIGV2ZW50TmFtZSAtIG9wdGlvbmFsLiBkZWZhdWx0cyB0byAnY2xpY2snXG4gICAgJC5mbi50b2dnbGVkTGlzdCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIGlmICghb3B0aW9ucy50b2dnbGVDbGFzcykgeyByZXR1cm4gdGhpczsgfVxuICAgICAgICB2YXIgbGlzdCA9IHRoaXM7XG4gICAgICAgIHJldHVybiBsaXN0Lm9uKG9wdGlvbnMuZXZlbnROYW1lIHx8ICdjbGljaycsIG9wdGlvbnMudHJpZ2dlclNlbGVjdG9yIHx8IGxpc3QuY2hpbGRyZW4oKSwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHZhciBjbGFzc1RhcmdldCA9IG9wdGlvbnMudHJpZ2dlclNlbGVjdG9yID8gJCh0aGlzKS5wYXJlbnQoKSA6ICQodGhpcyk7XG4gICAgICAgICAgICBjbGFzc1RhcmdldC50b2dnbGVDbGFzcyhvcHRpb25zLnRvZ2dsZUNsYXNzKTtcbiAgICAgICAgICAgIC8vIGV4ZWN1dGUgY2FsbGJhY2sgaWYgZXhpc3RzXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5jYWxsYmFjaykge29wdGlvbnMuY2FsbGJhY2soKTt9XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAkLmZuLnN5bmNIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5oZWlnaHQoJ2F1dG8nKTtcbiAgICAgICAgdmFyIGFyciA9ICQubWFrZUFycmF5KHRoaXMpO1xuICAgICAgICBhcnIuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuICQoYSkuaGVpZ2h0KCkgLSAkKGIpLmhlaWdodCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGVpZ2h0KCQoYXJyW2Fyci5sZW5ndGggLSAxXSkuaGVpZ2h0KCkpO1xuICAgIH07XG5cblx0JC5mbi5zeW5jSGVpZ2h0VG9NaW5pbXVtID0gZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuaGVpZ2h0KCdhdXRvJyk7XG4gICAgICAgIHZhciBhcnIgPSAkLm1ha2VBcnJheSh0aGlzKTtcbiAgICAgICAgYXJyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAkKGEpLmhlaWdodCgpIC0gJChiKS5oZWlnaHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmhlaWdodCgkKGFyclswXSkuaGVpZ2h0KCkpO1xuICAgIH07XG5cblx0JC5mbi5zeW5jSGVpZ2h0VG9BdmVyYWdlID0gZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuaGVpZ2h0KCdhdXRvJyk7XG4gICAgICAgIHZhciBhcnIgPSAkLm1ha2VBcnJheSh0aGlzKTtcbiAgICAgICAgYXJyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAkKGEpLmhlaWdodCgpIC0gJChiKS5oZWlnaHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmhlaWdodCgkKGFycltwYXJzZUludChhcnIubGVuZ3RoLzIsIDEwKV0pLmhlaWdodCgpKTtcbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBzbGlkZXJzID0gcmVxdWlyZSgnLi9zbGlkZXJzJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiBpbml0ICgpIHtcblx0c2xpY2tTbGlkZUp1bWJvdHJvbigpO1xuXG5cdC8vICQoJy5qdW1ib3Ryb24tYWpheCcpLnJlYWR5KGZ1bmN0aW9uKCl7XG5cdC8vIFx0cmVuZGVySnVtYm90cm9uU2xvdCgpO1xuXHQvLyB9KTtcblx0XG5cdHZhciByZW5kZXJKdW1ib3Ryb25TbG90ID0gZnVuY3Rpb24oKXtcblx0XHRpZiAoVXJscyAmJiBVcmxzLmdldEp1bWJvdHJvblNsb3QpIHtcblx0XHRcdCQuYWpheCh7IG1ldGhvZDogJ1BPU1QnLCB1cmw6IFVybHMuZ2V0SnVtYm90cm9uU2xvdCwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0dmFyIGh0bWwgPSAnJztcblx0XHRcdFx0dmFyIGNvbnRlbnRTbG90O1xuXHRcdFx0XHR2YXIgaXNKc29uID0gZmFsc2U7XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgdGVtcGxhdGVTZXR0aW5ncyA9IHtcblx0XHRcdCAgICBcdGludGVycG9sYXRlOiAve3soW1xcc1xcU10rPyl9fS9nXG5cdFx0XHQgICAgfTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciB0ZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWp1bWJvdHJvbicpLmh0bWwoKSwgdGVtcGxhdGVTZXR0aW5ncyk7XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgZGF0YVBheWxvYWQgPSBkYXRhLnN1YnN0cihkYXRhLmluZGV4T2YoJ3snKSwgZGF0YS5sZW5ndGgpO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIGVuZFBheWxvYWRJbmRleCA9IGRhdGFQYXlsb2FkLmxlbmd0aDtcblx0XHRcdFx0aWYgKGRhdGFQYXlsb2FkLmluZGV4T2YoJzwhLS0gZHdNYXJrZXInKSA+IDApIHtcblx0XHRcdFx0XHRlbmRQYXlsb2FkSW5kZXggPSBkYXRhUGF5bG9hZC5pbmRleE9mKCc8IS0tIGR3TWFya2VyJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGF0YVBheWxvYWQgPSBkYXRhUGF5bG9hZC5zdWJzdHIoMCwgZW5kUGF5bG9hZEluZGV4KTtcblx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb250ZW50U2xvdCA9IEpTT04ucGFyc2UoZGF0YVBheWxvYWQpO1xuXHRcdFx0XHRcdGlzSnNvbiA9IHRydWU7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRjb25zb2xlLndhcm4oJ0NvbnRlbnRTbG90IHRlbXBsYXRlIG5vdCBzZXQgdG8gSlNPTicpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoY29udGVudFNsb3QpIHtcblx0XHRcdFx0XHRpZiAoY29udGVudFNsb3QuY29udGVudCkge1xuXHRcdFx0XHRcdFx0aHRtbCA9IHRlbXBsYXRlKHsganVtYm90cm9uOiBidWlsZENvbnRlbnRTbG90RnJvbUpTT04oY29udGVudFNsb3QpIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmICghaXNKc29uKSB7XG5cdFx0XHRcdFx0aHRtbCA9IHRlbXBsYXRlKHsganVtYm90cm9uOiBkYXRhIH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQkKCcuanVtYm90cm9uLWFqYXgnKS5hZGRDbGFzcygnYWN0aXZlJykuaHRtbChodG1sKTtcblx0XHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG5cdFx0XHRcdFx0c2xpY2tTbGlkZUp1bWJvdHJvbigpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2FwcC5yZXNpemUnKTtcblx0XHRcdH19KTtcblx0XHR9XG5cdH1cblxuXHQvL2Zpc2h0YWcgcmlnZ2luZyBjb250ZW50IGFzc2V0ICdjYXQtZ2xvYmFsLWhlYWRlcidcblx0Ly8kKCcuY2F0LWdsb2JhbC1oZWFkZXInKS5yZWFkeShmdW5jdGlvbigpe1xuXHQvL1x0cmVuZGVyRmlzaHRhZygpO1xuXHQvL30pO1xuXHRcblx0ZnVuY3Rpb24gcmVuZGVyRmlzaHRhZygpe1xuXHRcdGlmIChVcmxzICYmIFVybHMuZ2V0RmlzaHRhZykge1xuXHRcdFx0JC5hamF4KHsgbWV0aG9kOiAnUE9TVCcsIHVybDogVXJscy5nZXRGaXNodGFnLCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKXtcblx0XHRcdFx0dmFyIGh0bWwgPSAnJztcblx0XHRcdFx0dmFyIGNvbnRlbnRTbG90O1xuXHRcdFx0XHR2YXIgaXNKc29uID0gZmFsc2U7XG5cdFx0XHRcdFxuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGNvbnRlbnRTbG90ID0gSlNPTi5wYXJzZShkYXRhLnN1YnN0cihkYXRhLmluZGV4T2YoJ3snKSwgZGF0YS5sZW5ndGgpKTtcblx0XHRcdFx0XHRpc0pzb24gPSB0cnVlO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0Y29uc29sZS53YXJuKCdDb250ZW50U2xvdCB0ZW1wbGF0ZSBub3Qgc2V0IHRvIEpTT04nKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKGNvbnRlbnRTbG90ICYmIGNvbnRlbnRTbG90LmNvbnRlbnQpIHtcblx0XHRcdFx0XHRodG1sID0gYnVpbGRDb250ZW50U2xvdEZyb21KU09OKGNvbnRlbnRTbG90KTtcblx0XHRcdFx0fSBlbHNlIGlmICghaXNKc29uKSB7XG5cdFx0XHRcdFx0aHRtbCA9IGRhdGE7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdCQoJy5maXNodGFnLXNsb3QnKS5odG1sKGh0bWwpO1xuICAgICAgICAgICAgICAgIHJvdGF0ZVRleHQoJCgnLnRvcC1iYW5uZXItbWVzc2FnZScpLCAkKCcudG9wLWJhbm5lci1tZXNzYWdlJykuZGF0YSgnZHVyYXRpb24nKSk7XG5cdFx0XHR9fSk7XG5cdFx0fVxuXHR9XG5cdFxuXHRmdW5jdGlvbiBidWlsZENvbnRlbnRTbG90RnJvbUpTT04oY29udGVudFNsb3RKU09OKSB7XG5cdFx0dmFyIGJvZHkgPSAnJztcblx0XHRcblx0XHRpZiAoY29udGVudFNsb3RKU09OICYmIGNvbnRlbnRTbG90SlNPTi5jb250ZW50KSB7XG5cdFx0XHRmb3IgKHZhciBjb250ZW50U2xvdEl0ZW0gaW4gY29udGVudFNsb3RKU09OLmNvbnRlbnQpIHtcblx0XHRcdFx0Ym9keSArPSBjb250ZW50U2xvdEpTT04uY29udGVudFtjb250ZW50U2xvdEl0ZW1dLmJvZHk7XG5cdFx0XHR9XG5cdFx0XG5cdFx0XHRpZiAoY29udGVudFNsb3RKU09OLmNvdW50ZG93blRvKSB7XG5cdFx0XHRcdGJvZHkgPSAnPGRpdiBjbGFzcz1cImNvdW50ZG93bi13cmFwcGVyXCIgZGF0YS1jb3VudGRvd24tZGF0ZT1cIicgKyBjb250ZW50U2xvdEpTT04uY291bnRkb3duVG8gKyAnXCI+JyArIGJvZHkgKyAnPC9kaXY+JzsgXG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBib2R5O1xuXHR9XG5cdFxuXHQvLyBSb3RhdGUgVGV4dCBmb3IgZmlzaHRhZ1xuXHRmdW5jdGlvbiByb3RhdGVUZXh0KCRlbGVtZW50LCBkdXJhdGlvbikge1xuXHRcdHZhciBsZW5ndGhTbGlkZXIgXHRcdFx0PSAkZWxlbWVudC5maW5kKCcucm90YXRlLWVsZW1lbnQnKS5sZW5ndGg7XG5cdFx0dmFyICRyb3RhdGVFbGVtZW50IFx0XHRcdD0gJGVsZW1lbnQuZmluZCgnLnJvdGF0ZS1lbGVtZW50Jyk7XG5cblx0XHRzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcblx0XHRcdHZhciAkcm90YXRlRWxlbWVudEFjdGl2ZSBcdD0gJGVsZW1lbnQuZmluZCgnLmFjdGl2ZScpO1xuXHRcdFx0dmFyICRuZXh0RWxlbWVudCA9ICRyb3RhdGVFbGVtZW50QWN0aXZlLm5leHQoKTtcblxuXHRcdFx0aWYoJG5leHRFbGVtZW50LmluZGV4KCkgPT09IC0xKSB7XG5cdFx0XHRcdCRuZXh0RWxlbWVudCA9ICRlbGVtZW50LmZpbmQoJy5yb3RhdGUtZWxlbWVudDpmaXJzdC1jaGlsZCcpO1xuXG5cdFx0XHRcdCRuZXh0RWxlbWVudFxuXHRcdFx0XHRcdC5hZGRDbGFzcygnYWN0aXZlJylcblx0XHRcdFx0XHQuc2libGluZ3MoKVxuXHRcdFx0XHRcdC5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkbmV4dEVsZW1lbnRcblx0XHRcdFx0XHQuYWRkQ2xhc3MoJ2FjdGl2ZScpXG5cdFx0XHRcdFx0LnNpYmxpbmdzKClcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH0sIGR1cmF0aW9uKTtcblx0fVxuXG5cdGZ1bmN0aW9uIHNsaWNrU2xpZGVKdW1ib3Ryb24oKSB7XG5cdFx0dmFyIHNsaWRlc01vYmlsZSA9ICQoJy5nYmNvbHVtbnMnKS5jbG9zZXN0KCdbZGF0YS1zbGlkZXMtbW9iaWxlXScpLmxlbmd0aCA+IDAgPyBwYXJzZUludCgkKCcuZ2Jjb2x1bW5zJykuY2xvc2VzdCgnW2RhdGEtc2xpZGVzLW1vYmlsZV0nKS5hdHRyKCdkYXRhLXNsaWRlcy1tb2JpbGUnKSkgOiAxO1xuXHRcdHZhciBzbGlkZXNEZXNrdG9wID0gJCgnLmdiY29sdW1ucycpLmNsb3Nlc3QoJ1tkYXRhLXNsaWRlcy1kZXNrdG9wXScpLmxlbmd0aCA+IDAgPyBwYXJzZUludCgkKCcuZ2Jjb2x1bW5zJykuY2xvc2VzdCgnW2RhdGEtc2xpZGVzLWRlc2t0b3BdJykuYXR0cignZGF0YS1zbGlkZXMtZGVza3RvcCcpKSA6IDQ7XG5cdFxuXHRcdHNsaWRlcnMuaW5pdCgnLmdiY29sdW1ucycsIHtkb3RzOiBmYWxzZSwgYnJlYWtwb2ludHM6IHswOiB7c2xpZGVzVG9TaG93OiBzbGlkZXNNb2JpbGUsIGFycm93czogdHJ1ZX0sIDc2ODoge3NsaWRlc1RvU2hvdzogc2xpZGVzRGVza3RvcH19fSk7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIExPR0lOXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG52YXIgbG9naW5EaWFsb2cgPSByZXF1aXJlKCcuL2xvZ2luRGlhbG9nJyk7XG52YXIgcmVjYXB0Y2hhID0gcmVxdWlyZSgnLi9jb21wb25lbnRzL1JlY2FwdGNoYScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTsgLy91dGlsIHJlZmVyZW5jZVxudmFyXHR2YWxpZGF0b3IgPSByZXF1aXJlKCcuL3ZhbGlkYXRvcicpO1xuXG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xuXG52YXIgZGF0YUJ1ZmZlciA9IHt9O1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MgPSB7XG4gICAgSXNMYWJlbFNob3duOiBmYWxzZSxcbiAgICBDc3NDbGFzczogJ2Z1bGxzY3JlZW4nLFxuICAgIEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xufTtcbnZhciBvcGNMb2dnZWRJbkN1c3RvbWVyQWRkcmVzc2VzID0gW107XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGluaXQgZXZlbnRzIGZvciB0aGUgbG9naW5QYWdlXG4gKi9cbmZ1bmN0aW9uIGluaXRMb2dpbkV2ZW50cygpIHtcbiAgICAvL3RvZ2dsZSB0aGUgdmFsdWUgb2YgdGhlIHJlbWVtYmVybWUgY2hlY2tib3hcbiAgICAkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJy5sb2dpbi1yZW1lbWJlcm1lIGlucHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoJCh0aGlzKS5wcm9wKCdjaGVja2VkJykpIHtcbiAgICAgICAgICAgICQoJyNyZW1lbWJlcm1lJykudmFsKCd0cnVlJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkKCcjcmVtZW1iZXJtZScpLnZhbCgnZmFsc2UnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjb3B0aW4tcHJpdmFjeS1wb2xpY3knLCBmdW5jdGlvbihlKSB7IFxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IFxuICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5wcml2YWN5UGFnZTsgXG4gICAgfSk7XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNyZXdhcmQtbGVhcm4tbW9yZScsIGZ1bmN0aW9uKGUpIHsgXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgXG4gICAgICAgIGxvY2F0aW9uLmhyZWYgPSBVcmxzLmxlYXJuRkFROyBcbiAgICB9KTtcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLm1vdmV0b2FkZHInLCBmdW5jdGlvbihlKXtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7IFxuICAgICAgICAgICAgc2Nyb2xsVG9wOiAkKCcuYmlsbGluZy1hZGRyZXNzLWZvcm0nKS5lcSgwKS5vZmZzZXQoKS50b3BcbiAgICAgICAgfSwgMTAwMCk7XG4gICAgfSk7XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNhdHRhY2gtcmV3YXJkcy1mb3JtIGxhYmVsJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICQoJyNhdHRhY2gtcmV3YXJkcy1mb3JtIGlucHV0JykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuICAgICAgICAkKHRoaXMpLnNpYmxpbmdzKCdbbmFtZT1cImF0dGFjaC1yZXdhcmRzLW9wdGlvbnNcIl0nKS5hdHRyKCdjaGVja2VkJywgJ2NoZWNrZWQnKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVMb2dpbkZvcm0oJGZvcm0sIGNoZWNrRmllbGRzKSB7XHRcbiAgICBpZiAoISRmb3JtIHx8ICFjaGVja0ZpZWxkcykgeyByZXR1cm4gZmFsc2UgfVxuXG4gICAgdmFyICRlbWFpbEZpZWxkID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJfdXNlcm5hbWVcIl0nKTtcdFxuICAgIHZhciAkcGFzc3dvcmRGaWVsZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3Bhc3N3b3JkXCJdJyk7XG4gICAgdmFyICRwYXNzY29kZUZpZWxkID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJfcGFzc2NvZGVcIl0nKTtcbiAgICB2YXIgZW1haWxWYWx1ZSA9ICRlbWFpbEZpZWxkLmxlbmd0aCA+IDAgPyAkZW1haWxGaWVsZC52YWwoKS50cmltKCkgOiBudWxsO1xuXHR2YXIgcGFzc3dvcmRWYWx1ZSA9ICRwYXNzd29yZEZpZWxkLmxlbmd0aCA+IDAgPyAkcGFzc3dvcmRGaWVsZC52YWwoKS50cmltKCkgOiBudWxsO1xuICAgIHZhciBwYXNzY29kZVZhbHVlID0gJHBhc3Njb2RlRmllbGQubGVuZ3RoID4gMCA/ICRwYXNzY29kZUZpZWxkLnZhbCgpLnRyaW0oKSA6IG51bGw7XG5cdHZhciBmb3JtVmFsaWRhdGlvbiA9IHRydWU7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoZWNrRmllbGRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjdXJyZW50RmllbGQgPSBjaGVja0ZpZWxkc1tpXTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgaWYgKGN1cnJlbnRGaWVsZC50b1VwcGVyQ2FzZSgpID09ICdFTUFJTCcgJiYgKCFlbWFpbFZhbHVlIHx8IGVtYWlsVmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBmb3JtVmFsaWRhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJfdXNlcm5hbWVcIl0nKS5hZGRDbGFzcygnZXJyb3InKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudEZpZWxkLnRvVXBwZXJDYXNlKCkgPT0gJ1BBU1NXT1JEJyAmJiAoIXBhc3N3b3JkVmFsdWUgfHwgcGFzc3dvcmRWYWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cIl9wYXNzd29yZFwiXScpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjdXJyZW50RmllbGQudG9VcHBlckNhc2UoKSA9PSAnUEFTU0NPREUnICYmICghcGFzc2NvZGVWYWx1ZSB8fCBwYXNzY29kZVZhbHVlLmxlbmd0aCA9PSAwKSkge1xuICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3Bhc3Njb2RlXCJdJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgIH1cbiAgICB9XG5cdFx0XHRcblx0aWYgKCFmb3JtVmFsaWRhdGlvbikge1xuICAgICAgICAkZm9ybS5maW5kKCcubG9naW4tZGlhbG9nLWVycm9yIC5pbnZhbGlkLW1pc3NpbmctZmllbGRzJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJGZvcm0uZmluZCgnLmxvZ2luLWRpYWxvZy1lcnJvciBzcGFuJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGVycm9ySGFuZGxpbmcoZGF0YSwgZGlhbG9nVGl0bGUsIGRpYWxvZ0h0bWwpIHtcbiAgICBpZiAoZGF0YSAmJiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgJ21lc3NhZ2UnIGluIGRhdGEpIHtcbiAgICAgICAgY29uc29sZS5sb2coZGF0YS5tZXNzYWdlKTtcbiAgICB9XG4gICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICBodG1sOiBkaWFsb2dIdG1sLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICB0aXRsZTogZGlhbG9nVGl0bGUsXG4gICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcbiAgICAgICAgICAgICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLy8gQ29yZGlhbCB0cmFja2luZyBmb3IgbG9naW5QYWdlIGFuZCBsb2dpbkRpYWxvZ1xuZnVuY3Rpb24gbG9naW5Db3JkaWFsQWNjb3VudEV2ZW50KCRmb3JtLCBpc0xvZ2luRGlhbG9nKSB7XG4gICAgdmFyIHVzZXJuYW1lID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJfdXNlcm5hbWVcIl0nKS52YWwoKS50cmltKCk7XG4gICAgICAgIFxuICAgIHZhciBhdXRoX2RhdGEgPSB7XG4gICAgICAgIGVtYWlsOiB1c2VybmFtZVxuICAgIH1cbiAgICAgICAgXG4gICAgdmFyIGNvbnRhY3RfZGF0YSA9IHtcbiAgICAgICAgJ2NoYW5uZWxzJzoge1xuICAgICAgICAgICAgJ2VtYWlsJzoge1xuICAgICAgICAgICAgICAgICdhZGRyZXNzJzogdXNlcm5hbWUgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgXG4gICAgdmFyIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIFwiZW1haWxcIjogdXNlcm5hbWUsXG4gICAgICAgIFwibG9naW5UeXBlXCI6IGlzTG9naW5EaWFsb2cgPyBcImxvZ2luLWRpYWxvZ1wiIDogXCJsb2dpblwiXG4gICAgfTtcbiAgICAgICAgXG4gICAgaWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjcmRsKFtcdFx0XHRcdFxuICAgICAgICAgICAgWydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuICAgICAgICAgICAgWydldmVudCcsICdsb2dpbicsIHByb3BlcnRpZXNdXG4gICAgICAgIF0pO1xuICAgIH1cbn1cblxuLy8gQ29yZGlhbCBwYXNzd29yZCByZXNldCAtIG5vIGFjY291bnQgZXZlbnRcbmZ1bmN0aW9uIHBhc3N3b3JkUmVzZXROb0FjY291bnRDb3JkaWFsRXZlbnQoY29udGFpbmVyKSB7XG4gICAgaWYgKGNvbnRhaW5lciAmJiAkKGNvbnRhaW5lcikuZmluZCgnLnJlc2V0LXBhc3N3b3JkIC5uby1hY2NvdW50JykubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgZW1haWwgPSAkKCcubm8tYWNjb3VudCcpLnRleHQoKTtcblx0XG5cdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdGVtYWlsOiBlbWFpbFxuXHRcdH1cblx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0J2NoYW5uZWxzJzoge1xuXHRcdFx0ICAgICdlbWFpbCc6IHtcblx0XHRcdCAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbFxuXHRcdFx0ICAgIH1cblx0XHRcdH1cblx0XHR9O1xuXHRcdFx0XG5cdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHRcImVtYWlsXCI6IGVtYWlsXG5cdFx0fTtcblxuXHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdGNyZGwoW1xuXHRcdFx0XHRbJ2NvbnRhY3QnLCBhdXRoX2RhdGEsIGNvbnRhY3RfZGF0YV0sXG5cdFx0XHRcdFsnZXZlbnQnLCAncmVzZXQtcGFzc3dvcmQtbm8tYWNjb3VudCcsIHByb3BlcnRpZXNdXG5cdFx0XHRdKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVJlY2FwdGNoYUZvckxvZ2luKCkge1xuXHRyZW5kZXJSZWNhcHRjaGFGb3JMb2dpbigpO1xuXHQkKGRvY3VtZW50KS5vbignQWNjb3VudC5TdWJtaXRMb2dpbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0JCgnI2FjY291bnRMb2dpbkJ1dHRvbicpLmNsaWNrKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZW5kZXJSZWNhcHRjaGFGb3JMb2dpbigpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI2FjY291bnRMb2dpbkJ1dHRvbicpLmxlbmd0aCA+IDAgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yQWNjb3VudExvZ2luICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcblx0XHRkYXRhQnVmZmVyLkxvZ2luUmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ2FjY291bnRMb2dpbkJ1dHRvbicsIHtcblx0ICAgICAgICAnc2l0ZWtleSc6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgJ2NhbGxiYWNrJzogYWNjb3VudExvZ2luLFxuXHQgICAgICAgICdiYWRnZSc6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhRm9yUGFzc3dvcmRSZXNldCgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI3JlcXVlc3QtcGFzc3dvcmQtc2VuZC1idG4nKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBhc3N3b3JkUmVzZXQgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdGlmIChkYXRhQnVmZmVyLlJlc2V0UGFzc3dvcmRSZWNhcHRjaGEpIHtcblx0XHRcdGdyZWNhcHRjaGEucmVzZXQoZGF0YUJ1ZmZlci5SZXNldFBhc3N3b3JkUmVjYXB0Y2hhKTtcblx0XHR9XG5cblx0XHRkYXRhQnVmZmVyLlJlc2V0UGFzc3dvcmRSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcigncmVxdWVzdC1wYXNzd29yZC1zZW5kLWJ0bicsIHtcblx0ICAgICAgICAnc2l0ZWtleSc6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgJ2NhbGxiYWNrJzogd2luZG93LnJlc2V0UGFzc3dvcmQsXG5cdCAgICAgICAgJ2JhZGdlJzogJ2JvdHRvbWxlZnQnXG5cdCAgICB9KTtcblx0fVxufVxuXG52YXIgdXBkYXRlQ3VzdG9tZXJEZXRhaWxzID0gZnVuY3Rpb24gKGZvcm0sIG5hbWUpIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm0pO1xuIFxuICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5vbmVQYWdlTG9naW4pLFxuICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lXG4gICAgfSkpO1xuIH1cblxuZnVuY3Rpb24gc2hvd05vdGlmaWNhdGlvbih0ZXh0LCBzZWxlY3RvciwgbXNnVHlwZSkge1xuICAgIHZhciAkc2VsZWN0b3IgPSAkKHNlbGVjdG9yKTtcblx0aWYgKCRzZWxlY3Rvci5sZW5ndGggPT0gMCkge1xuICAgICAgICB2YXIgJGZvcm0gPSAkKCdmb3JtLm9wYy1sb2dpbicpLFxuICAgICAgICAgICAgJHNlbGVjdG9yID0gJCgnPHNwYW4vPicsIHsnY2xhc3MnOiAnbG9naW4tbm90aWZpY2F0aW9uJywgJ3RhYmluZGV4JzogJzAnfSkud3JhcCgnPGRpdiBjbGFzcz1cImZvcm1maWVsZCBjbGVhcmZpeCBlcnJvci1ib3hcIj48ZGl2IGNsYXNzPVwiZm9ybS1yb3cgcmVxdWlyZWRcIj48ZGl2IGNsYXNzPVwiZmllbGQtd3JhcHBlclwiPjwvZGl2PjwvZGl2PjwvZGl2PicpO1xuXG4gICAgICAgICRzZWxlY3Rvci5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5pbnNlcnRCZWZvcmUoJ2Zvcm0ub3BjLWxvZ2luIC5mb3JtLXJvdy1idXR0b24nKTtcbiAgICAgICAgJHNlbGVjdG9yID0gJChzZWxlY3Rvcik7XG4gICAgfVxuXG4gICAgJHNlbGVjdG9yLnJlbW92ZUNsYXNzKCdzdWNjZXNzIGVycm9yJykuYWRkQ2xhc3MobXNnVHlwZSkudGV4dCh0ZXh0KS5mb2N1cygpO1xufVxuIFxuZnVuY3Rpb24gY2xlYXJOb3RpZmljYXRpb24oc2VsZWN0b3IpIHtcbiAgICAgaWYoc2VsZWN0b3IubGVuZ3RoKXtcbiAgICAgICAgJCgnLmZvcm1maWVsZC5lcnJvci1ib3gnKS5yZW1vdmUoKTtcblx0XHRzZWxlY3Rvci5yZW1vdmVDbGFzcygnc3VjY2VzcyBlcnJvcicpO1xuICAgICB9XG59XG4gXG4vLyBHVE0gYW5kIENvcmRpYWwgdGFnZ2luZyBmb3IgY2FydCBvcGMtbG9naW5cbmZ1bmN0aW9uIG9wY0xvZ2luVGFnZ2luZygkZm9ybSwgY2FsbGJhY2spIHtcbiAgICB2YXIgZW1haWwgPSAgJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJ1c2VybmFtZVwiXScpLnZhbCgpO1xuICAgIHZhciBhdXRoX2RhdGEgPSB7XG4gICAgICAgIGVtYWlsOiBlbWFpbFxuICAgIH1cbiAgICB2YXIgY29udGFjdF9kYXRhID0ge1xuICAgICAgICAnY2hhbm5lbHMnOiB7XG4gICAgICAgICAgICAnZW1haWwnOiB7XG4gICAgICAgICAgICAgICAgJ2FkZHJlc3MnOiBlbWFpbCAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICB2YXIgcHJvcGVydGllcyA9IHtcbiAgICAgICAgXCJlbWFpbFwiOiBlbWFpbFxuICAgIH07XG4gICAgR29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQ3VzdG9tZXJMb2dpbicsIHsgbWV0aG9kOiAnY2FydCcgfSkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBjcmRsKFtcbiAgICAgICAgICAgICAgICAgICAgWydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFsnZXZlbnQnLCAnbG9naW4nLCBwcm9wZXJ0aWVzXVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcGFzc3dvcmRsZXNzTG9naW5TZXF1ZW5jZShpc0NoZWNrb3V0TG9naW4pIHtcbiAgICBpZiAoIWlzQ2hlY2tvdXRMb2dpbikge1xuICAgICAgICAkKCcjb3RwLXRvZ2dsZS1idXR0b24nKS5oaWRlKCk7XG4gICAgfVxuICAgICQoJy5sb2dpbi1kaWFsb2ctc2lnbmluLWNvbnRhaW5lciwgLmxvZ2luLWRpYWxvZy1yZWdpc3Rlci1tZXNzYWdlLCAjdG9nZ2xlLXJlZ2lzdHJhdGlvbicpLmhpZGUoKTtcbiAgICAkKCcubG9naW4tZGlhbG9nLXBhc3Njb2RlLWNvbnRhaW5lcicpLmFkZENsYXNzKCdwYXNzY29kZS1mb3JtLXNob3cnKTtcbiAgICAkKCcub3RwLXBhc3Njb2RlLWZpZWxkLWNvbnRhaW5lciwgLm90cC1yZXNlbmQtY29kZS1jb250YWluZXInKS5oaWRlKCk7XG4gICAgJCgnLm90cC1lbWFpbC1maWVsZC1jb250YWluZXInKS5zaG93KCk7XG4gICAgJCgnLmxvZ2luLWRpYWxvZy1wYXNzY29kZS1jb250YWluZXIgaW5wdXRbbmFtZSo9XCJkd2ZybV9vdHBsb2dpblwiXScpLnZhbCgnJyk7IC8vIGNsZWFyIHByZXZpb3VzIGZvcm0gaW5wdXQgdmFsdWVzXG59XG5cbi8qKlxuICogTG9naW4gcmVwb3J0aW5nIC0gaW5jcmVtZW50cyBjb3VudGVycyBpbiBjdXN0b20gb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZSAtIEVpdGhlciAnbm9ybWFsJyBmb3IgdHJhZGl0aW9uYWwgbG9naW4gdHlwZSwgb3IgJ3Bhc3N3b3JkbGVzcycgZm9yIG5ldyBsb2dpbiB0eXBlXG4gKiBAcGFyYW0ge1N0cmluZ30gc291cmNlIC0gU291cmNlIG9mIGxvZ2luLCB3aGljaCBjYW4gYmUgb3JpZ2luYWwsIGNhcnQsIGNhcnQtbW9kYWwsIG9yIHdpc2hsaXN0LW1vZGFsXG4gKi9cbmZ1bmN0aW9uIHRyYWNrTG9naW5BY3Rpb25zKHR5cGUsIHNvdXJjZSkge1xuICAgIGlmICghdHlwZSB8fCAhc291cmNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogVXJscy5sb2dpblRyYWNraW5nLFxuICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgfSksXG4gICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdMb2dpbi1UcmFja0FjdGlvbnM6IEVycm9yIGluIGluY3JlbWVudGluZyBsb2dpbiBhY3Rpb24gY291bnRlcnMuIEVSUk9SIFRFWFQ6ICcrdGV4dFN0YXR1cysnLCBFUlJPUiBUSFJPV046ICcrZXJyb3JUaHJvd24rJy4nKTtcbiAgICAgICAgfSxcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmIChyZXNwb25zZSkge31cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBpbml0IGxvZ2luIGJ1dHRvbiBldmVudCBmb3IgdGhlIGxvZ2luUGFnZSwgbG9naW5EaWFsb2cgYW5kIGNoZWNrb3V0IGxvZ2luXG4gKi9cbmZ1bmN0aW9uIGluaXRMb2dpbkJ1dHRvbnMoKSB7XG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjYWNjb3VudExvZ2luQnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgZGlhbG9nSHRtbCA9ICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+T29wcywgc29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCBsb2dpbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+JztcbiAgICAgICAgdmFyICRhY2NvdW50TG9naW5CdXR0b24gPSAkKHRoaXMpO1xuICAgICAgICB2YXIgJGFjY291bnRMb2dpbkZvcm0gPSAkYWNjb3VudExvZ2luQnV0dG9uLmNsb3Nlc3QoJ2Zvcm0jZHdmcm1fbG9naW4nKTtcbiAgICAgICAgdmFyIGZvcm1SZW1lbWJlck1lID0gJGFjY291bnRMb2dpbkZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJkd2ZybV9sb2dpbl9yZW1lbWJlcm1lXCJdJykuaXMoJzpjaGVja2VkJyk7XG4gICAgICAgIHZhciBmb3JtVXNlcm5hbWUgPSBmb3JtUmVtZW1iZXJNZSA/ICc9JyArICRhY2NvdW50TG9naW5Gb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fbG9naW5fdXNlcm5hbWVcIl0nKS52YWwoKSA6ICcnO1xuICAgICAgICB2YXIgZm9ybVVybCA9ICRhY2NvdW50TG9naW5Gb3JtLmF0dHIoJ2FjdGlvbicpO1xuXG4gICAgICAgIC8vIENsZWFyIHByZXZpb3VzIGZvcm0gZXJyb3JzXG4gICAgICAgICRhY2NvdW50TG9naW5Gb3JtLmZpbmQoJ2lucHV0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICRhY2NvdW50TG9naW5Gb3JtLmZpbmQoJy5sb2dpbi1kaWFsb2ctZXJyb3Igc3BhbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblxuICAgICAgICB2YXIgaXNWYWxpZEZvcm0gPSB2YWxpZGF0ZUxvZ2luRm9ybSgkYWNjb3VudExvZ2luRm9ybSwgWydlbWFpbCcsJ3Bhc3N3b3JkJ10pO1xuICAgICAgICB2YXIgaXNMb2dpbkRpYWxvZyA9IGZvcm1VcmwuaW5kZXhPZignbG9naW5EaWFsb2cnKSA+PSAwO1xuICAgICAgICB2YXIgZm9ybURhdGEgPSAkYWNjb3VudExvZ2luRm9ybS5zZXJpYWxpemUoKTtcblxuICAgICAgICBpZiAoIWlzTG9naW5EaWFsb2cpIHtcbiAgICAgICAgICAgICQoJ1tkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScsICdvcmlnaW5hbCcpOyAvLyBGb3IgcmVwb3J0aW5nIFxuICAgICAgICB9XG5cdFx0XG4gICAgICAgIC8vIFVzaW5nIEFKQVggaW5zdGVhZCBvZiBkZWZhdWx0IEhUTUwgYnV0dG9uIHN1Ym1pdCBmb3IgbG9naW4gcGFnZSBhbmQgZGlhbG9nXG4gICAgICAgIGlmIChpc1ZhbGlkRm9ybSkgeyAgICAgICAgXG4gICAgICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgdXJsOiBmb3JtVXJsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGZvcm1EYXRhLFxuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgJ3Jlc3VsdCcgaW4gZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEucmVzdWx0ID09ICdlcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRhY2NvdW50TG9naW5Gb3JtLmZpbmQoJy5sb2dpbi1kaWFsb2ctZXJyb3IgLmludmFsaWQtbG9naW4nKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBkYXRhLmxvZ2luRGlhbG9nQ29udGludWVVcmwgKyAnP3JldHJ5JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEucmVzdWx0ID09ICdzdWNjZXNzJyB8fCBkYXRhLnJlc3VsdCA9PSAnY29tcGxldGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAndmFsaWRhdGVDdXN0b21lcicgcHJvcGVydHkgb25seSByZXR1cm5zIGluIHRoZSBkYXRhIGlmIHRoaXMgaXMgYSBkaWFsb2cuIE90aGVyd2lzZSwgcmV3YXJkcyB2YWxpZGF0aW9uIGhhcHBlbnMgdGhyb3VnaCB0aGUgVVJMIHVzaW5nIGxvZ2luRGlhbG9nQ29udGludWVVcmwuIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYSByZXdhcmRzIGN1c3RvbWVyLCBhbmQgdGhlIGN1c29tdGVyIGFjY291bnQgcmVxdWlyZXMgdmFsaWRhdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgndmFsaWRhdGVDdXN0b21lcicgaW4gZGF0YSAmJiBkYXRhLnZhbGlkYXRlQ3VzdG9tZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2luQ29yZGlhbEFjY291bnRFdmVudCgkYWNjb3VudExvZ2luRm9ybSwgaXNMb2dpbkRpYWxvZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0F0dHJpYnV0ZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtbW9kYWwtdHlwZVwiOiBcImxvZ2luXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY29udGludWUtdXJsXCI6ICdsb2dpbkRpYWxvZ0NvbnRpbnVlVXJsJyBpbiBkYXRhID8gZGF0YS5sb2dpbkRpYWxvZ0NvbnRpbnVlVXJsIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtZmlyc3QtbmFtZVwiOiAnY3VzdG9tZXJGaXJzdE5hbWUnIGluIGRhdGEgPyBkYXRhLmN1c3RvbWVyRmlyc3ROYW1lIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtc3RvcmUtbnVtYmVyXCI6ICdzdG9yZUZyb21Qcm9maWxlJyBpbiBkYXRhID8gZGF0YS5zdG9yZUZyb21Qcm9maWxlIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY2FydC1xdWFudGl0eVwiOiAnY2FydFF1YW50aXR5JyBpbiBkYXRhID8gZGF0YS5jYXJ0UXVhbnRpdHkgOiAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5odG1sKGRhdGEudmFsaWRhdGVDdXN0b21lcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5hZGRDbGFzcygndmFsaWRhdGUtY3VzdG9tZXItc2hvdyBmb2xsb3ctYWNjb3VudC1kaWFsb2ctcGF0aCcpLmF0dHIobmV3QXR0cmlidXRlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvIHRoaXMgaW4gdHdvIHBsYWNlczogXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICgxKSBmb3IgbG9naW4tZGlhbG9nIGhlcmUgYmVjYXVzZSB0aGUgZWxlbWVudCBpcyBvbmx5IGxvYWRlZCBpbnRvIHBhZ2UgdmlhIEFKQVgsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoMikgaW5pdCBvZiBwYWdlIGxvYWQgZm9yIHJlZ3VsYXIgcmV3YXJkcyB2ZXJpZmljYXRpb24gcGFnZXMgdGhyb3VnaCBub3JtYWwgbG9naW4gZmxvd1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0QWRkUnVsZXNGb3JDb2RlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIHRoZSBjb3JkaWFsIGxvZ2luIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpbkNvcmRpYWxBY2NvdW50RXZlbnQoJGFjY291bnRMb2dpbkZvcm0sIGlzTG9naW5EaWFsb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrTG9naW5BY3Rpb25zKCdwYXNzd29yZCcsICQoJ1tkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgZm9sbG93LXVwIGFjdGlvbnMgYWNjb3JkaW5nbHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScsIHsgcmVzdWx0czogZGF0YSwgaXNBY2NvdW50RGlhbG9nOiBpc0xvZ2luRGlhbG9nLCBkaXNwbGF5TWVzc2FnZTogJ2xvZ2luJyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnTG9naW4gLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnTG9naW4gLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWYuc3BsaXQoJz8nKVswXSsnP3JldHJ5JztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzTG9naW5EaWFsb2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gbG9jYXRpb24uaHJlZi5zcGxpdCgnPycpWzBdKyc/cmV0cnknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gIFxuXHR9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcub3BjLWxvZ2luLXN1Ym1pdC1idXR0b24nLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgJG9wY0xvZ2luQnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRvcGNMb2dpbkZvcm0gPSAkb3BjTG9naW5CdXR0b24uY2xvc2VzdCgnZm9ybS5vcGMtbG9naW4nKTtcbiAgICAgICAgdmFyIG5vdGlmaWNhdGlvblNlbGVjdG9yID0gJCgnLmxvZ2luLW5vdGlmaWNhdGlvbicpO1xuXG4gICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cbiAgICAgICAgJCgnW2RhdGEtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtbG9naW4tc291cmNlJywgJ2NhcnQnKTsgLy8gRm9yIHJlcG9ydGluZ1xuICAgICAgICAkb3BjTG9naW5Gb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgICAgICBjbGVhck5vdGlmaWNhdGlvbihub3RpZmljYXRpb25TZWxlY3Rvcik7XG4gICAgICAgIHVwZGF0ZUN1c3RvbWVyRGV0YWlscygkb3BjTG9naW5Gb3JtLCAkKHRoaXMpLmF0dHIoJ25hbWUnKSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgIT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJ3ZpZXdNb2RlbCcgaW4gcmVzcG9uc2UgJiYgJ0N1c3RvbWVyJyBpbiByZXNwb25zZS52aWV3TW9kZWwgJiYgcmVzcG9uc2Uudmlld01vZGVsLkN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQgPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQgPSByZXNwb25zZS52aWV3TW9kZWwuQ3VzdG9tZXIuYXV0aGVudGljYXRlZDtcbiAgICAgICAgICAgICAgICBvcGNMb2dnZWRJbkN1c3RvbWVyQWRkcmVzc2VzID0gcmVzcG9uc2Uudmlld01vZGVsLkFkZHJlc3NlcztcbiAgICAgICAgICAgICAgICBpZiAoJ3ZhbGlkYXRlQ3VzdG9tZXInIGluIHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHVybDogVXJscy5yZW5kZXJEaWFsb2dUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGVycm9yVGhyb3duKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BjTG9naW5UYWdnaW5nKCRvcGNMb2dpbkZvcm0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3BjTG9naW5Db250aW51ZVVybCA9ICQoJyNjYXJ0LWl0ZW1zLWZvcm0nKS5sZW5ndGggPyBVcmxzLm9uZVBhZ2UgOiBVcmxzLmFjY291bnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbDogZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ2xvZ2luLWRpYWxvZycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IDYwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnNjcm9sbFRvcCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2luQ29yZGlhbEFjY291bnRFdmVudCgkb3BjTG9naW5Gb3JtLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcudWktZGlhbG9nLmxvZ2luLWRpYWxvZycpLmNzcygnaGVpZ2h0JywgJzQzMHB4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy51aS1kaWFsb2cubG9naW4tZGlhbG9nIC5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyJykuY3NzKCdtYXJnaW4nLCAnMCAtOHB4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctcGFzc2NvZGUtY29udGFpbmVyLCAubG9naW4tZGlhbG9nLXJlZ2lzdGVyLWNvbnRhaW5lcicpLmhpZGUoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3QXR0cmlidXRlcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1tb2RhbC10eXBlXCI6IFwibG9naW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1jb250aW51ZS11cmxcIjogb3BjTG9naW5Db250aW51ZVVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1maXJzdC1uYW1lXCI6ICdjdXN0b21lckZpcnN0TmFtZScgaW4gcmVzcG9uc2UgPyByZXNwb25zZS5jdXN0b21lckZpcnN0TmFtZSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLXN0b3JlLW51bWJlclwiOiAnc3RvcmVGcm9tUHJvZmlsZScgaW4gcmVzcG9uc2UgPyByZXNwb25zZS5zdG9yZUZyb21Qcm9maWxlIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY2FydC1xdWFudGl0eVwiOiAnY2FydFF1YW50aXR5JyBpbiByZXNwb25zZSA/IHJlc3BvbnNlLmNhcnRRdWFudGl0eSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLW9wYy1sb2dpblwiOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpLmh0bWwocmVzcG9uc2UudmFsaWRhdGVDdXN0b21lcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5hZGRDbGFzcygndmFsaWRhdGUtY3VzdG9tZXItc2hvdyBmb2xsb3ctYWNjb3VudC1kaWFsb2ctcGF0aCcpLmF0dHIobmV3QXR0cmlidXRlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdEFkZFJ1bGVzRm9yQ29kZUlucHV0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRwYXNzd29yZFJlc2V0ID0gJCh0aGlzKS5maW5kKCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lciAjcGFzc3dvcmQtcmVzZXQtYnV0dG9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXNzd29yZFJlc2V0LmF0dHIoJ2RhdGEtdGFyZ2V0JywgJHBhc3N3b3JkUmVzZXQuYXR0cignZGF0YS10YXJnZXQnKSArICc/bG9naW5EaWFsb2c9dHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgIG9wY0xvZ2luVGFnZ2luZygkb3BjTG9naW5Gb3JtKTtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2tMb2dpbkFjdGlvbnMoJ3Bhc3N3b3JkJywgJCgnW2RhdGEtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtbG9naW4tc291cmNlJykpO1xuICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5vbmVQYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAkKCcub3BjLWxvZ2luIC5maWVsZC13cmFwcGVyIGlucHV0JykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICAgICAgICAgc2hvd05vdGlmaWNhdGlvbihSZXNvdXJjZXMuUFdEX0VNQUlMX0VSUk9SLCAnLmxvZ2luLW5vdGlmaWNhdGlvbicsICdlcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpOyAgICBcbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjb3RwLXRvZ2dsZS1idXR0b24nLCBmdW5jdGlvbihlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgaXNBY2NvdW50RGlhbG9nID0gJCh0aGlzKS5jbG9zZXN0KCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lcicpLmxlbmd0aDtcbiAgICAgICAgdmFyIGlzQ2hlY2tvdXRMb2dpbiA9ICQodGhpcykuaGFzQ2xhc3MoJ29wYy1wYXNzd29yZGxlc3MtbG9naW4nKTtcbiAgICAgICAgaWYgKGlzQWNjb3VudERpYWxvZykge1xuICAgICAgICAgICAgcGFzc3dvcmRsZXNzTG9naW5TZXF1ZW5jZShmYWxzZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNDaGVja291dExvZ2luKSB7XG4gICAgICAgICAgICBsb2dpbkRpYWxvZy5zaG93KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHBhc3N3b3JkbGVzc0xvZ2luU2VxdWVuY2UodHJ1ZSk7XG4gICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgW2RhdGEtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtbG9naW4tc291cmNlJywgJ2NhcnQtbW9kYWwnKTsgXG4gICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgW2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLXBhc3N3b3JkbGVzcy1sb2dpbi1zb3VyY2UnLCAnY2FydC1tb2RhbCcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMucGFzc3dvcmRsZXNzTG9naW47XG4gICAgICAgIH1cblx0fSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI290cENhbmNlbEJ1dHRvbicsIGZ1bmN0aW9uKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBpc0FjY291bnREaWFsb2cgPSAkKHRoaXMpLmNsb3Nlc3QoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyJykubGVuZ3RoO1xuICAgICAgICB2YXIgaXNDaGVja291dCA9ICQoJ1tkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScpICE9IHVuZGVmaW5lZCAmJiAkKCdbZGF0YS1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1sb2dpbi1zb3VyY2UnKS5pbmRleE9mKCdjYXJ0JykgPiAtMTtcbiAgICAgICAgaWYgKGlzQWNjb3VudERpYWxvZykge1xuICAgICAgICAgICAgaWYgKGlzQ2hlY2tvdXQpIHtcbiAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyICRvdHBIZWFkZXIgPSAkKCdmb3JtI2R3ZnJtX290cGxvZ2luIC5wcm9maWxlLWhlYWRlcicpO1xuICAgICAgICAgICAgICAgIHZhciAkb3RwSW5zdHJ1Y3Rpb25zID0gJCgnZm9ybSNkd2ZybV9vdHBsb2dpbiAub3RwLWluc3RydWN0aW9ucycpO1xuICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctc2lnbmluLWNvbnRhaW5lciwgLmxvZ2luLWRpYWxvZy1yZWdpc3Rlci1tZXNzYWdlLCAjb3RwLXRvZ2dsZS1idXR0b24sICN0b2dnbGUtcmVnaXN0cmF0aW9uJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctcGFzc2NvZGUtY29udGFpbmVyJykucmVtb3ZlQ2xhc3MoJ3Bhc3Njb2RlLWZvcm0tc2hvdycpO1xuICAgICAgICAgICAgICAgICRvdHBIZWFkZXIuaHRtbCgkb3RwSGVhZGVyLmF0dHIoJ2RhdGEtZW1haWwnKSk7XG4gICAgICAgICAgICAgICAgJG90cEluc3RydWN0aW9ucy5odG1sKCRvdHBJbnN0cnVjdGlvbnMuYXR0cignZGF0YS1lbWFpbCcpKTtcbiAgICAgICAgICAgICAgICAkKCcjZHdmcm1fb3RwbG9naW5fdXNlcm5hbWUnKS5zaG93KCk7IC8vIGRvbid0IGNsZWFyIHByZXZpb3VzIGVtYWlsIHZhbHVlIGZvciBmb3JtIHZhbGlkYXRpb25cbiAgICAgICAgICAgICAgICAkKCcjb3RwQ29udGludWVCdXR0b24nKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgJCgnI2R3ZnJtX290cGxvZ2luX3Bhc3Njb2RlJykuaGlkZSgpLnZhbCgnJyk7IC8vIGNsZWFyIHByZXZpb3VzIHBhc3Njb2RlIHZhbHVlIGZvciBmb3JtXG4gICAgICAgICAgICAgICAgJCgnI290cFZlcmlmeUJ1dHRvbicpLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5hY2NvdW50O1xuICAgICAgICB9XG5cdH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNvdHBDb250aW51ZUJ1dHRvbiwgLm90cC1yZXNlbmQtY29kZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPlNvcnJ5LCB3ZSB3ZXJlIHVuYWJsZSB0byBzZW5kIGEgb25lLXRpbWUgcGFzc2NvZGUgYXQgdGhpcyB0aW1lLiBQbGVhc2UgbG9naW4gdXNpbmcgeW91ciBjcmVkZW50aWFscyBpbnN0ZWFkLjwvcD4nO1xuICAgICAgICB2YXIgJG90cENvbnRpbnVlQnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRvdHBMb2dpbkZvcm0gPSAkb3RwQ29udGludWVCdXR0b24uY2xvc2VzdCgnZm9ybSNkd2ZybV9vdHBsb2dpbicpO1xuICAgICAgICB2YXIgaXNSZXNlbmQgPSAkKHRoaXMpLmhhc0NsYXNzKCdvdHAtcmVzZW5kLWNvZGUnKTtcblxuICAgICAgICAvLyBDbGVhciBwcmV2aW91cyBmb3JtIGVycm9yc1xuICAgICAgICAkb3RwTG9naW5Gb3JtLmZpbmQoJ2lucHV0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICRvdHBMb2dpbkZvcm0uZmluZCgnLmxvZ2luLWRpYWxvZy1lcnJvciBzcGFuJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXG4gICAgICAgIHZhciBpc1ZhbGlkRm9ybSA9IHZhbGlkYXRlTG9naW5Gb3JtKCRvdHBMb2dpbkZvcm0sIFsnZW1haWwnXSk7XG4gICAgICAgIHZhciBlbWFpbEFkZHJlc3MgPSAkb3RwTG9naW5Gb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3VzZXJuYW1lXCJdJykudmFsKCk7XG5cbiAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1wYXNzY29kZS1jb250YWluZXIsIC5vdHAtbG9naW4tZm9ybS1jb250YWluZXInKS5hdHRyKCdkYXRhLWVtYWlsJywgZW1haWxBZGRyZXNzKTtcblxuICAgICAgICAvLyBVc2luZyBBSkFYIGluc3RlYWQgb2YgZGVmYXVsdCBIVE1MIGJ1dHRvbiBzdWJtaXQgZm9yIGxvZ2luIHBhZ2UgYW5kIGRpYWxvZ1xuICAgICAgICBpZiAoaXNWYWxpZEZvcm0pIHtcbiAgICAgICAgICAgIGlmIChpc1Jlc2VuZCkge1xuICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7IFxuICAgICAgICAgICAgfSAgICAgXG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICB1cmw6IFVybHMuZ2V0UGFzc2NvZGUsXG4gICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICBlbWFpbEFkZHJlc3M6IGVtYWlsQWRkcmVzc1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyAmJiBkYXRhLmxlbmd0aCA9PSAwKSB7IFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzUmVzZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTsgXG4gICAgICAgICAgICAgICAgICAgICAgICB9IFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUGFzc3dvcmRsZXNzIExvZ2luIC0gRXJyb3InLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzUmVzZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTsgXG4gICAgICAgICAgICAgICAgICAgICAgICB9ICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodGV4dFN0YXR1cyAmJiB0ZXh0U3RhdHVzICE9ICdzdWNjZXNzJykgfHwgKGRhdGEgJiYgJ3N0YXR1cycgaW4gZGF0YSAmJiBkYXRhLnN0YXR1cyA9PSAnRVJST1InKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Bhc3N3b3JkbGVzcyBMb2dpbiAtIEVycm9yJywgZXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhICYmICdzdGF0dXMnIGluIGRhdGEgJiYgKGRhdGEuc3RhdHVzID09ICdPSycgfHwgIGRhdGEuc3RhdHVzID09ICdOT1RfRk9VTkQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvdHBMb2dpbkZvcm0uYXR0cignZGF0YS11c2lkJywgZGF0YS51c2lkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJG90cEhlYWRlciA9ICRvdHBMb2dpbkZvcm0uZmluZCgnLnByb2ZpbGUtaGVhZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRvdHBJbnN0cnVjdGlvbnMgPSAkb3RwTG9naW5Gb3JtLmZpbmQoJy5vdHAtaW5zdHJ1Y3Rpb25zJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJG90cEhlYWRlci5odG1sKCRvdHBIZWFkZXIuYXR0cignZGF0YS12ZXJpZnknKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJG90cEluc3RydWN0aW9ucy5odG1sKCRvdHBJbnN0cnVjdGlvbnMuYXR0cignZGF0YS12ZXJpZnknKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJG90cEluc3RydWN0aW9ucy5hcHBlbmQoJzxzcGFuPicrZW1haWxBZGRyZXNzKyc8L3NwYW4+Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLm90cC1lbWFpbC1maWVsZC1jb250YWluZXIsICNvdHBDb250aW51ZUJ1dHRvbicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcub3RwLXBhc3Njb2RlLWZpZWxkLWNvbnRhaW5lcicpLmNzcygnZGlzcGxheScsICdmbGV4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnI2R3ZnJtX290cGxvZ2luX3Bhc3Njb2RlJykuc2hvdygpLnZhbCgnJykucmVtb3ZlQXR0cigncGxhY2Vob2xkZXInKS5hdHRyKCdpbnB1dG1vZGUnLCdudW1lcmljJyk7IC8vIGNsZWFyIHByZXZpb3VzIHBhc3Njb2RlIHZhbHVlIGZyb20gZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJyNvdHBWZXJpZnlCdXR0b24sIC5vdHAtcmVzZW5kLWNvZGUtY29udGFpbmVyJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSAgICBcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdQYXNzd29yZGxlc3MgTG9naW4gLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjb3RwVmVyaWZ5QnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9ICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+U29ycnksIHdlIHdlcmUgdW5hYmxlIHRvIHNlbmQgYSBwYXNzY29kZSBhdCB0aGlzIHRpbWUuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG4gICAgICAgIHZhciAkb3RwVmVyaWZ5QnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRvdHBMb2dpbkZvcm0gPSAkb3RwVmVyaWZ5QnV0dG9uLmNsb3Nlc3QoJ2Zvcm0jZHdmcm1fb3RwbG9naW4nKTtcbiAgICAgICAgdmFyIGZvcm1VcmwgPSAkb3RwTG9naW5Gb3JtLmF0dHIoJ2FjdGlvbicpO1xuXG4gICAgICAgIC8vIENsZWFyIHByZXZpb3VzIGZvcm0gZXJyb3JzXG4gICAgICAgICRvdHBMb2dpbkZvcm0uZmluZCgnaW5wdXQnKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICAgICAgJG90cExvZ2luRm9ybS5maW5kKCcubG9naW4tZGlhbG9nLWVycm9yIHNwYW4nKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cbiAgICAgICAgdmFyIGlzTG9naW5EaWFsb2cgPSBmb3JtVXJsLmluZGV4T2YoJ2xvZ2luRGlhbG9nJykgPj0gMDtcbiAgICAgICAgdmFyIGlzVmFsaWRGb3JtID0gdmFsaWRhdGVMb2dpbkZvcm0oJG90cExvZ2luRm9ybSwgWydlbWFpbCcsJ3Bhc3Njb2RlJ10pO1xuICAgICAgICB2YXIgZm9ybURhdGEgPSAkb3RwTG9naW5Gb3JtLnNlcmlhbGl6ZSgpO1xuICAgICAgICBmb3JtRGF0YSArPSAnJnVzaWQ9JyArICRvdHBMb2dpbkZvcm0uYXR0cignZGF0YS11c2lkJyk7XG4gICAgICAgIGZvcm1EYXRhICs9ICcmJyArICRvdHBWZXJpZnlCdXR0b24uYXR0cignbmFtZScpICsgJz0nICsgJG90cFZlcmlmeUJ1dHRvbi5hdHRyKCduYW1lJyk7XG5cbiAgICAgICAgLy8gVXNpbmcgQUpBWCBpbnN0ZWFkIG9mIGRlZmF1bHQgSFRNTCBidXR0b24gc3VibWl0IGZvciBsb2dpbiBwYWdlIGFuZCBkaWFsb2dcbiAgICAgICAgaWYgKGlzVmFsaWRGb3JtKSB7ICAgXG4gICAgICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpOyAgXG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICB1cmw6IGZvcm1VcmwsXG4gICAgICAgICAgICAgICAgZGF0YTogZm9ybURhdGEsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyAmJiBkYXRhLnN0YXR1cyAhPSAnRVJST1InKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAndmFsaWRhdGVDdXN0b21lcicgcHJvcGVydHkgb25seSByZXR1cm5zIGluIHRoZSBkYXRhIGlmIHRoaXMgaXMgYSBkaWFsb2cuIE90aGVyd2lzZSwgcmV3YXJkcyB2YWxpZGF0aW9uIGhhcHBlbnMgdGhyb3VnaCB0aGUgVVJMIHVzaW5nIGxvZ2luRGlhbG9nQ29udGludWVVcmwuIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBhIHJld2FyZHMgY3VzdG9tZXIsIGFuZCB0aGUgY3Vzb210ZXIgYWNjb3VudCByZXF1aXJlcyB2YWxpZGF0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ3ZhbGlkYXRlQ3VzdG9tZXInIGluIGRhdGEgJiYgZGF0YS52YWxpZGF0ZUN1c3RvbWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9naW5Db3JkaWFsQWNjb3VudEV2ZW50KCRvdHBMb2dpbkZvcm0sIGlzTG9naW5EaWFsb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3QXR0cmlidXRlcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLW1vZGFsLXR5cGVcIjogXCJsb2dpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY29udGludWUtdXJsXCI6ICdsb2dpbkRpYWxvZ0NvbnRpbnVlVXJsJyBpbiBkYXRhID8gZGF0YS5sb2dpbkRpYWxvZ0NvbnRpbnVlVXJsIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1maXJzdC1uYW1lXCI6ICdjdXN0b21lckZpcnN0TmFtZScgaW4gZGF0YSA/IGRhdGEuY3VzdG9tZXJGaXJzdE5hbWUgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLXN0b3JlLW51bWJlclwiOiAnc3RvcmVGcm9tUHJvZmlsZScgaW4gZGF0YSA/IGRhdGEuc3RvcmVGcm9tUHJvZmlsZSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY2FydC1xdWFudGl0eVwiOiAnY2FydFF1YW50aXR5JyBpbiBkYXRhID8gZGF0YS5jYXJ0UXVhbnRpdHkgOiAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyLCAub3RwLWxvZ2luLWZvcm0tY29udGFpbmVyJykuaHRtbChkYXRhLnZhbGlkYXRlQ3VzdG9tZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXIsIC5vdHAtbG9naW4tZm9ybS1jb250YWluZXInKS5hZGRDbGFzcygndmFsaWRhdGUtY3VzdG9tZXItc2hvdyBmb2xsb3ctYWNjb3VudC1kaWFsb2ctcGF0aCcpLmF0dHIobmV3QXR0cmlidXRlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmUgdGhlIGNvcmRpYWwgbG9naW4gZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpbkNvcmRpYWxBY2NvdW50RXZlbnQoJG90cExvZ2luRm9ybSwgaXNMb2dpbkRpYWxvZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrTG9naW5BY3Rpb25zKCdwYXNzd29yZGxlc3MnLCAkKCdbZGF0YS1wYXNzd29yZGxlc3MtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZScpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhpcyB2YWx1ZSB0byBQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplIGZvciB0aGUgaXNBY2NvdW50RGlhbG9nIGR1ZSB0byBzY29wZSBvZiBCT09ULTYxMDAuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIG5vdCB1c2luZyB0aGlzIHRpY2tldCB0byBwcmV2ZW50IGNhcnQgcmVmcmVzaCBmb3IgbW9kYWwuIFdpbGwgbmVlZCBhZGRpdGlvbmFsIHRpY2tldCB3aXRoIHNjb3BlIHRvIGNoYW5nZSBjYXJ0IGJlaGF2aW9yLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc0NhcnRQYXNzd29yZGxlc3MgPSAkKCdbZGF0YS1wYXNzd29yZGxlc3MtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZScpID09ICdjYXJ0LW1vZGFsJyA/IGZhbHNlIDogaXNMb2dpbkRpYWxvZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBmb2xsb3ctdXAgYWN0aW9ucyBhY2NvcmRpbmdseVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Bvc3RBamF4QXV0aGVudGljYXRpb25BY3Rpb25zLkluaXRpYWxpemUnLCB7IHJlc3VsdHM6IGRhdGEsIGlzQWNjb3VudERpYWxvZzogaXNDYXJ0UGFzc3dvcmRsZXNzLCBkaXNwbGF5TWVzc2FnZTogJ2xvZ2luJyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gICAgXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3JzRm91bmQ7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YS52YWxpZGF0aW9uRXJyb3JzKSB7XG5cdFx0XHRcdFx0XHRcdGVycm9yc0ZvdW5kID0gSlNPTi5wYXJzZShkYXRhLnZhbGlkYXRpb25FcnJvcnMpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKGVycm9yc0ZvdW5kICYmIE9iamVjdC5rZXlzKGVycm9yc0ZvdW5kKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdGZvciAodmFyIGZpZWxkTmFtZSBpbiBlcnJvcnNGb3VuZCkge1xuXHRcdFx0XHRcdFx0XHRcdCQoZXJyb3JzRm91bmRbZmllbGROYW1lXSkucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJlc3BvbnNlRGF0YSAmJiBkYXRhLnJlc3BvbnNlRGF0YS5FcnJvckNvZGUgPT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5pbnZhbGlkLXdyb25nLXBhc3Njb2RlJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdQYXNzd29yZGxlc3MgTG9naW4gLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXHRcdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Bhc3N3b3JkbGVzcyBMb2dpbiAtIEVycm9yJywgZXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjYWxsTmV4dENvbnRyb2xsZXIodXJsLCBjYWxsYmFjaykge1xuICAgICQuYWpheCh7XG4gICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICB9LFxuICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjayhyZXNwb25zZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcdFxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiByZWdpc3RlciBvbi1jbGljayBldmVudCBmb3IgcmV3YXJkcyB2YWxpZGF0aW9uID4gc2VuZCBjb2RlIGJ1dHRvblxuICogQG5vdGVzIGNoYW5nZWQgdGhlIGJ1dHRvbi5vbignY2xpY2snKSB0byBhIGRvY3VtZW50Lm9uKCdjbGljaycpIGZvciBIVE1MIHRoYXQgaXMgZHluYW1pY2FsbHkgbG9hZGVkIGluIHBhZ2Ugd2l0aCBBSkFYIHdlbGwgYWZ0ZXIgaW5pdGlhbCBwYWdlIGxvYWRcbiAqL1xuZnVuY3Rpb24gaW5pdFZhbGlkYXRlUmV3YXJkc0FjY291bnQoKSB7XHRcblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJyN2YWxpZGF0ZS1hY2NvdW50IGJ1dHRvbiNzZW5kLWNvZGUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgdmFyICR2YWxpZGF0ZUFjY291bnRGb3JtID0gJCgnI3ZhbGlkYXRlLWFjY291bnQnKTtcbiAgICAgICAgdmFyIGlzQWNjb3VudERpYWxvZyA9ICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5oYXNDbGFzcygnZm9sbG93LWFjY291bnQtZGlhbG9nLXBhdGgnKTtcbiAgICAgICAgdmFyIHNlbmRUeXBlID0gJHZhbGlkYXRlQWNjb3VudEZvcm0uZmluZCgnaW5wdXRbbmFtZT12YWxpZGF0ZS1hY2NvdW50XTpjaGVja2VkJykuYXR0cignaWQnKS5pbmRleE9mKCdub25lJykgPiAtMSA/ICdub25lJyA6ICdvdGhlcic7XG5cblx0XHRpZiAoc2VuZFR5cGUgPT0gXCJub25lXCIpIHtcdFx0XHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dHlwZTogJ3Bvc3QnLFxuXHRcdFx0XHR1cmw6IFVybHMuY3JlYXRlUmV3YXJkc0FjY291bnQsXG5cdFx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRmaXJzdE5hbWU6ICQoJy5jdXN0b21lci1hY2NvdW50IC5maXJzdC1uYW1lJykudGV4dCgpLFxuXHRcdFx0XHRcdGxhc3ROYW1lOiAkKCcuY3VzdG9tZXItYWNjb3VudCAubGFzdC1uYW1lJykudGV4dCgpLFxuXHRcdFx0XHRcdGVtYWlsQWRkcmVzczogJCgnLmN1c3RvbWVyLWFjY291bnQgLmVtYWlsLWFkZHJlc3MnKS50ZXh0KCksXG5cdFx0XHRcdFx0cGhvbmVOdW1iZXI6ICQoJy5jdXN0b21lci1hY2NvdW50IC5waG9uZS1udW1iZXInKS50ZXh0KCksXG5cdFx0XHRcdFx0emlwQ29kZTogJCgnLmN1c3RvbWVyLWFjY291bnQgLnppcC1jb2RlJykudGV4dCgpXG5cdFx0XHRcdH0pLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRcdGNvbnNvbGUubG9nKCdSZXdhcmRzIGFjY291bnQgY3JlYXRlZC4nKTtcblx0XHRcdFx0XHRpbml0VmVyaWZpY2F0aW9uRGlyZWN0aW9uKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1x0XHRcdFxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMuc2VuZFZhbGlkYXRpb25Db2RlLFxuXHRcdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdCdzZW5kTWV0aG9kJzogJHZhbGlkYXRlQWNjb3VudEZvcm0uZmluZCgnaW5wdXRbbmFtZT12YWxpZGF0ZS1hY2NvdW50XTpjaGVja2VkJykudmFsKCksXG5cdFx0XHRcdFx0J3NlbmRUbyc6ICR2YWxpZGF0ZUFjY291bnRGb3JtLmZpbmQoJ2lucHV0W25hbWU9dmFsaWRhdGUtYWNjb3VudF06Y2hlY2tlZCcpLmF0dHIoJ2RhdGEtdmFsdWUnKVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdHZhciByZXN1bHRTdGF0dXMgPSAnc3RhdHVzJyBpbiBkYXRhICYmIGRhdGEuc3RhdHVzICE9ICdwZW5kaW5nJyA/IHRydWUgOiAncmVzdWx0JyBpbiBkYXRhICYmICdzdGF0dXMnIGluIGRhdGEucmVzdWx0ICYmIGRhdGEucmVzdWx0LnN0YXR1cyAhPSAncGVuZGluZycgPyB0cnVlIDogZmFsc2U7XG5cdFx0XHRcdFx0aWYgKCgnZXJyb3InIGluIGRhdGEgJiYgZGF0YS5lcnJvcikgfHwgcmVzdWx0U3RhdHVzKSB7XG5cdFx0XHRcdFx0XHQkKCcuZnVydGhlci1pbmZvJykuaGlkZSgpO1xuXHRcdFx0XHRcdFx0JCgnLnZlcmlmeS1mb3JtJykuaGlkZSgpO1xuXHRcdFx0XHRcdFx0JCgnLnZlcmlmeS1mYWlsJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdH1cdFxuXHRcdFx0XHRcdCQoJy5hY2NvdW50LXJlY29nbml6ZWQnKS5oaWRlKCk7XG5cdFx0XHRcdFx0aWYgKGlzQWNjb3VudERpYWxvZykge1xuXHRcdFx0XHRcdFx0JCgnLnZlcmlmeS1hY2NvdW50JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpLmFkZENsYXNzKCd2YWxpZGF0ZS1jdXN0b21lci1zaG93Jyk7XHRcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JCgnLnZlcmlmeS1hY2NvdW50JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1x0XG5cdFx0XHRcdFx0fVx0XHRcdFxuXHRcdFx0XHRcdCQoJy4nICsgc2VuZFR5cGUgKyAnLW1ldGhvZCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKGRhdGEsIHN0YXR1cywgeGhyKSB7XG5cdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblx0XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNhdHRhY2gtcmV3YXJkcy1idXR0b24nLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgZXJyb3JNZXNzYWdlID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Tb3JyeSwgd2Ugd2VyZSB1bmFibGUgdG8gZmluYWxpemUgeW91ciByZXdhcmRzIGFjY291bnQgdXBkYXRlcy48L3A+JztcbiAgICAgICAgdmFyICRhdHRhY2hSZXdhcmRzRm9ybSA9ICQoJyNhdHRhY2gtcmV3YXJkcy1mb3JtJyk7XG4gICAgICAgIHZhciAkc2VsZWN0ZWRPcHRpb24gPSAkYXR0YWNoUmV3YXJkc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1hdHRhY2gtcmV3YXJkcy1vcHRpb25zXTpjaGVja2VkJyk7XG4gICAgICAgIHZhciBzdWJtaXR0ZWRFbWFpbCA9ICQoJy5sb2dpbi1kaWFsb2ctcGFzc2NvZGUtY29udGFpbmVyLCAub3RwLWxvZ2luLWZvcm0tY29udGFpbmVyJykuYXR0cignZGF0YS1lbWFpbCcpO1xuXG4gICAgICAgIGlmICghJHNlbGVjdGVkT3B0aW9uKSB7XG4gICAgICAgICAgICAkKCcuYXR0YWNoLXJld2FyZHMtZm9ybS1lcnJvcnMnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLmF0dGFjaFJld2FyZHMsXG4gICAgICAgICAgICBkYXRhVHlwZTogJ0pTT04nLFxuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgJ29wdGlvbic6ICRzZWxlY3RlZE9wdGlvbi52YWwoKSxcbiAgICAgICAgICAgICAgICAnZW1haWwnOiBzdWJtaXR0ZWRFbWFpbFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5yZXN1bHQgJiYgZGF0YS5yZXN1bHQgPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdSZXdhcmRzIGF0dGFjaG1lbnQgY29tcGxldGUuJyk7XG4gICAgICAgICAgICAgICAgICAgIGluaXRWZXJpZmljYXRpb25EaXJlY3Rpb24oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdSZXdhcmRzIEFjY291bnQgLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdSZXdhcmRzIEFjY291bnQgLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiByZWdpc3RlciBvbi1jbGljayBldmVudCBmb3IgcmV3YXJkcyB2YWxpZGF0aW9uID4gdmVyaWZ5IGNvZGUgYnV0dG9uXG4gKi9cbmZ1bmN0aW9uIGluaXRWZXJpZnlDb2RlU2VudCgpIHsgICBcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI3ZlcmlmeS1jb2RlIGJ1dHRvbiN2ZXJpZnktdXNlcicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgdmFyICR2ZXJpZnlDb2RlRm9ybSA9ICQoJyN2ZXJpZnktY29kZScpO1xuICAgICAgICBpZiAoISR2ZXJpZnlDb2RlRm9ybS52YWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLnZlcmlmeVN1Ym1pdHRlZENvZGUsXG4gICAgICAgICAgICBkYXRhVHlwZTogJ0pTT04nLFxuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgJ2NvZGUnOiAgJHZlcmlmeUNvZGVGb3JtLmZpbmQoJ2lucHV0W25hbWU9ZW50ZXItY29kZV0nLCAnI3ZlcmlmeS1jb2RlJykudmFsKCksXG4gICAgICAgICAgICAgICAgJ3NlbmRUbyc6ICQoJyN2YWxpZGF0ZS1hY2NvdW50JykuZmluZCgnaW5wdXRbbmFtZT12YWxpZGF0ZS1hY2NvdW50XTpjaGVja2VkJykuYXR0cignZGF0YS12YWx1ZScpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhLmVycm9yKSB8fCAoJ3N0YXR1cycgaW4gZGF0YSAmJiBkYXRhLnN0YXR1cyAhPSAnYXBwcm92ZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICAkKCcuZnVydGhlci1pbmZvJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAkKCcudmVyaWZ5LWZvcm0nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICQoJy52ZXJpZnktZmFpbCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcdFx0XHRcdFx0XHRcdFxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdSZXdhcmRzIHZlcmlmaWNhdGlvbiBjb21wbGV0ZS4nKTtcbiAgICAgICAgICAgICAgICAgICAgaW5pdFZlcmlmaWNhdGlvbkRpcmVjdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBkaXJlY3RzIHRoZSBwYWdlIGxvYWQgb3IgdGhlIHBhZ2UgcmVkcmF3IGFmdGVyIHJld2FyZHMgdmVyaWZpY2F0aW9uIHNjcmVlblxuICovXG5mdW5jdGlvbiBpbml0VmVyaWZpY2F0aW9uRGlyZWN0aW9uKCkge1xuICAgIHZhciAkdmFsaWRhdGVEaWFsb2cgPSAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJyk7XG4gICAgdmFyIGlzQWNjb3VudERpYWxvZyA9ICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5oYXNDbGFzcygnZm9sbG93LWFjY291bnQtZGlhbG9nLXBhdGgnKTtcbiAgICB2YXIgZGF0YU1vZGFsVHlwZSwgZGF0YU5leHRDb250cm9sbGVyVXJsLCBkYXRhQ29udGludWVVcmwsIGRhdGFGaXJzdE5hbWUsIGRhdGFTdG9yZSwgZGF0YUNhcnRRdWFudGl0eSwgaXNPcGNMb2dpbjtcblxuICAgIGlmICgkdmFsaWRhdGVEaWFsb2cubGVuZ3RoKSB7XG4gICAgICAgIGRhdGFNb2RhbFR5cGUgPSAkdmFsaWRhdGVEaWFsb2cuYXR0cignZGF0YS1tb2RhbC10eXBlJyk7XG4gICAgICAgIGRhdGFOZXh0Q29udHJvbGxlclVybCA9ICR2YWxpZGF0ZURpYWxvZy5hdHRyKCdkYXRhLW5leHQtY29udHJvbGxlci11cmwnKTtcbiAgICAgICAgZGF0YUNvbnRpbnVlVXJsID0gJHZhbGlkYXRlRGlhbG9nLmF0dHIoJ2RhdGEtY29udGludWUtdXJsJyk7XG4gICAgICAgIGRhdGFGaXJzdE5hbWUgPSAkdmFsaWRhdGVEaWFsb2cuYXR0cignZGF0YS1maXJzdC1uYW1lJyk7XG4gICAgICAgIGRhdGFTdG9yZSA9ICR2YWxpZGF0ZURpYWxvZy5hdHRyKCdkYXRhLXN0b3JlLW51bWJlcicpO1xuICAgICAgICBkYXRhQ2FydFF1YW50aXR5ID0gJHZhbGlkYXRlRGlhbG9nLmF0dHIoJ2RhdGEtY2FydC1xdWFudGl0eScpO1xuICAgICAgICBpc09wY0xvZ2luID0gJHZhbGlkYXRlRGlhbG9nLmF0dHIoJ2RhdGEtb3BjLWxvZ2luJykgPT0gJ3RydWUnO1xuXG4gICAgICAgIGlmIChpc09wY0xvZ2luKSB7XG4gICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIGxvY2F0aW9uLmhyZWYgPSBVcmxzLm9uZVBhZ2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQWNjb3VudERpYWxvZykge1xuICAgICAgICAgICAgaWYgKGRhdGFOZXh0Q29udHJvbGxlclVybCkge1xuICAgICAgICAgICAgICAgIGNhbGxOZXh0Q29udHJvbGxlcihkYXRhTmV4dENvbnRyb2xsZXJVcmwsIGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSAmJiAncmVzdWx0JyBpbiByZXNwb25zZSAmJiAocmVzcG9uc2UucmVzdWx0ID09ICdzdWNjZXNzJyB8fCByZXNwb25zZS5yZXN1bHQgPT0gJ2NvbXBsZXRlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLmN1c3RvbWVyRmlyc3ROYW1lID0gZGF0YUZpcnN0TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLnN0b3JlRnJvbVByb2ZpbGUgPSBkYXRhU3RvcmU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5jYXJ0UXVhbnRpdHkgPSBkYXRhQ2FydFF1YW50aXR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIGZvbGxvdy11cCBhY3Rpb25zIGFjY29yZGluZ2x5XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplJywgeyByZXN1bHRzOiByZXNwb25zZSwgaXNBY2NvdW50RGlhbG9nOiBpc0FjY291bnREaWFsb2csIGRpc3BsYXlNZXNzYWdlOiBkYXRhTW9kYWxUeXBlIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhQ29udGludWVVcmwpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IGRhdGFDb250aW51ZVVybDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5hY2NvdW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvY2F0aW9uLmhyZWYgPSBVcmxzLmFjY291bnQ7XG4gICAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBhZGQgcnVsZXMgdG8gY29kZSBpbnB1dCBmaWVsZFxuICovXG5mdW5jdGlvbiBpbml0QWRkUnVsZXNGb3JDb2RlSW5wdXQoKSB7XG4gICAgJCgnZm9ybSN2ZXJpZnktY29kZScpLnZhbGlkYXRlKCk7XG4gICAgJCgnI3ZlcmlmeS1jb2RlICNlbnRlci1jb2RlJykucnVsZXMoJ2FkZCcsIHtcbiAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgIGRpZ2l0czogdHJ1ZSxcbiAgICAgICAgbWlubGVuZ3RoOiA2LFxuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgICAgcmVxdWlyZWQ6IFJlc291cmNlcy5WQUxJREFURV9DT0RFLFxuICAgICAgICAgICAgbWlubGVuZ3RoOiBSZXNvdXJjZXMuVkFMSURBVEVfQ09ERVxuICAgICAgICB9LFxuICAgICAgICBub3JtYWxpemVyOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuICQudHJpbSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gcmVnaXN0ZXIgb24tY2xpY2sgZXZlbnQgZm9yIHJld2FyZHMgdmFsaWRhdGlvbiA+IHZlcmlmeSBjb2RlID4gcmVzZW5kIGNvZGUgbGlua1xuICovXG5mdW5jdGlvbiBpbml0UmVzZW5kVmFsaWRhdGlvbkNvZGUoKSB7XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy52ZXJpZnktYWNjb3VudCBhLnJlc2VuZC1jb2RlJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcdFx0XG4gICAgICAgIGlmICgkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuaGFzQ2xhc3MoJ2ZvbGxvdy1hY2NvdW50LWRpYWxvZy1wYXRoJykpIHtcbiAgICAgICAgICAgICQoJy52ZXJpZnktYWNjb3VudCwgLmZ1cnRoZXItaW5mbyBzcGFuJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1x0XG4gICAgICAgICAgICAkKCcuYWNjb3VudC1yZWNvZ25pemVkJykuY3NzKCdsZWZ0JywnLTk5OTlweCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKS5zaG93KCkuYWRkQ2xhc3MoJ3ZhbGlkYXRlLWN1c3RvbWVyLXNob3cnKTtcdFx0XHRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvY2F0aW9uLnJlbG9hZCgpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHJlZ2lzdGVyIG9uLWNsaWNrIGV2ZW50cyBmb3IgcmVzZXQtcGFzc3dvcmQgZmxvd1xuICovXG5mdW5jdGlvbiBpbml0UmVzZXRQYXNzd29yZEV2ZW50cygpIHtcdFxuICAgIC8vIFNob3cgcmVzZXQgcGFzc3dvcmQgZm9ybVxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI3Bhc3N3b3JkLXJlc2V0LWJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciAkcmVzZXRQYXNzd29yZEJ1dHRvbiA9ICQodGhpcyk7XG4gICAgICAgIHZhciByZXNldERpYWxvZ1VybCA9ICRyZXNldFBhc3N3b3JkQnV0dG9uLmF0dHIoJ2RhdGEtdGFyZ2V0Jyk7XG4gICAgICAgIHZhciBpc0xvZ2luRGlhbG9nID0gcmVzZXREaWFsb2dVcmwuaW5kZXhPZignbG9naW5EaWFsb2cnKSA+PSAwO1xuXG4gICAgICAgIGlmIChpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuICAgICAgICAgICAgdmFyIGRpYWxvZ0h0bWwgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggUGFzc3dvcmQgUmVzZXQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG5cbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICAgICAgdXJsOiByZXNldERpYWxvZ1VybCxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdyZXN1bHQnIGluIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJlc3VsdCA9PSAnY29tcGxldGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSByZWNlaXZlZCBIVE1MIGluIHRoZSBkYXRhIGZvciBkaXNwbGF5aW5nIHRoZSByZXNldCBwYXNzd29yZCBmb3JtLCB0aGVuIGRpc3BsYXkgaXQuLi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ3Jlc2V0UGFzc3dvcmRGb3JtJyBpbiBkYXRhICYmIGRhdGEucmVzZXRQYXNzd29yZEZvcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1yZXNldC1wYXNzd29yZCcpLmh0bWwoZGF0YS5yZXNldFBhc3N3b3JkRm9ybSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctcmVzZXQtcGFzc3dvcmQnKS5hZGRDbGFzcygncmVzZXQtcGFzc3dvcmQtc2hvdycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXJlc2V0LXBhc3N3b3JkJykuZmluZCgnI1Bhc3N3b3JkUmVzZXRGb3JtJykuYXR0cignYWN0aW9uJywgJCgnLmxvZ2luLWRpYWxvZy1yZXNldC1wYXNzd29yZCcpLmZpbmQoJyNQYXNzd29yZFJlc2V0Rm9ybScpLmF0dHIoJ2FjdGlvbicpICsgJz9sb2dpbkRpYWxvZz10cnVlJyk7XG5cdFx0XHRcdFx0XHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yUGFzc3dvcmRSZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVzZXQgUGFzc3dvcmQgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVzZXQgUGFzc3dvcmQgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWY7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChTaXRlUHJlZmVyZW5jZXMuUkVTRVRfUE9QVVBfRU5BQkxFRCkge1xuXHRcdFx0ZGlhbG9nLm9wZW4oe1xuXHQgICAgICAgICAgICB1cmw6IHJlc2V0RGlhbG9nVXJsLFxuXHQgICAgICAgICAgICBvcHRpb25zOiB7XG5cdCAgICAgICAgICAgIFx0ZGlhbG9nQ2xhc3M6ICdyZXNldHB3ZHBvcHVwJyxcblx0ICAgICAgICAgICAgXHR3aWR0aDogMzg1LFxuXHQgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yUGFzc3dvcmRSZXNldCgpO1xuXHQgICAgICAgICAgICAgICAgICAgICQoXCIucmVzZXQtcGFzc3dvcmQtaGVhZGluZy1jbG9zZS1idG4sIC51aS13aWRnZXQtb3ZlcmxheVwiKS5vbignY2xpY2snLGZ1bmN0aW9uKCl7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgICQoXCJidXR0b24udWktZGlhbG9nLXRpdGxlYmFyLWNsb3NlXCIpLmNsaWNrKCk7XG5cdCAgICAgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0XHRcdH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSByZXNldERpYWxvZ1VybDtcbiAgICAgICAgfVxuXHR9KTtcblx0XG4gICAgLy8gU3VibWl0IHJlc2V0IHBhc3N3b3JkIGZvcm1cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2suUmVzZXRQYXNzd29yZCcsICcjcmVxdWVzdC1wYXNzd29yZC1zZW5kLWJ0biwgW25hbWUkPVwiX3JlcXVlc3RwYXNzd29yZF9zZW5kXCJdJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICBcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQYXNzd29yZFJlc2V0KSB7XG5cdFx0XHRyZXNldFBhc3N3b3JkKGV2ZW50LCAkKHRoaXMpKTtcblx0XHR9XG5cdH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdBY2NvdW50LlJlc2V0UGFzc3dvcmQnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGEpIHtcblx0XHRyZXNldFBhc3N3b3JkKGV2ZW50LCBudWxsLCB0cnVlKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlc2V0UGFzc3dvcmQoZXZlbnQsICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbiwgaXNSZWNhcHRjaGFFdmVudCkge1xuXHRpZiAoISRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbikge1xuXHRcdCRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbiA9ICQoJyNyZXF1ZXN0LXBhc3N3b3JkLXNlbmQtYnRuJyk7XG5cdH1cblxuXHR2YXIgJHJlc2V0UGFzc3dvcmRTZW5kRm9ybSA9ICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi5jbG9zZXN0KCdmb3JtI1Bhc3N3b3JkUmVzZXRGb3JtJyk7XG5cdHZhciBpc0xvZ2luRGlhbG9nID0gJHJlc2V0UGFzc3dvcmRTZW5kRm9ybS5hdHRyKCdhY3Rpb24nKS5pbmRleE9mKCdsb2dpbkRpYWxvZycpID49IDA7XG5cblx0Ly8gVHJ5IHRvIHByZXZlbnQgdGhlIGZvcm0gc3VibWlzc2lvbiBhcyBxdWlja2x5IGFzIHBvc3NpYmxlIGJlZm9yZSBkb2luZyBhbGwgb2YgdGhlIG90aGVyIGxvZ2ljXG5cdGlmIChpc0xvZ2luRGlhbG9nIHx8IChTaXRlUHJlZmVyZW5jZXMuUkVTRVRfUE9QVVBfRU5BQkxFRCAmJiBkaWFsb2cuaXNBY3RpdmUoKSkpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHR9XG5cblx0dmFsaWRhdG9yLmluaXQoKTtcblx0dmFyIGlzVmFsaWRGb3JtID0gJHJlc2V0UGFzc3dvcmRTZW5kRm9ybS52YWxpZCgpO1xuXG5cdGlmIChpc1ZhbGlkRm9ybSkgeyAgIFxuXHRcdGlmIChpc0xvZ2luRGlhbG9nKSB7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdFx0dmFyIGRpYWxvZ0h0bWwgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggUGFzc3dvcmQgUmVzZXQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG5cdFx0XHR2YXIgZm9ybURhdGEgPSAkcmVzZXRQYXNzd29yZFNlbmRGb3JtLnNlcmlhbGl6ZSgpO1xuXHRcdFx0Zm9ybURhdGEgKz0gJyYnICsgJHJlc2V0UGFzc3dvcmRTZW5kQnV0dG9uLmF0dHIoJ25hbWUnKSArICc9JyArICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi5hdHRyKCduYW1lJyk7ICBcblxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHR1cmw6ICRyZXNldFBhc3N3b3JkU2VuZEZvcm0uYXR0cignYWN0aW9uJyksXG5cdFx0XHRcdGRhdGE6IGZvcm1EYXRhLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuXHRcdFx0XHRcdGlmICh0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgJ3Jlc3VsdCcgaW4gZGF0YSkge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEucmVzdWx0ID09ICdjb21wbGV0ZScpIHtcblx0XHRcdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdFx0Ly8gSWYgcmVzZXQgcGFzc3dvcmQgZW1haWwgd2FzIHNlbnQsIHNob3cgY29uZmlybWF0aW9uIHdpdGhpbiB0aGUgZGlhbG9nXG5cdFx0XHRcdFx0XHRcdGlmICgncmVzZXRQYXNzd29yZENvbmZpcm1hdGlvbicgaW4gZGF0YSAmJiBkYXRhLnJlc2V0UGFzc3dvcmRDb25maXJtYXRpb24pIHtcblx0XHRcdFx0XHRcdFx0XHQkKCcubG9naW4tZGlhbG9nLXJlc2V0LXBhc3N3b3JkJykuaHRtbChkYXRhLnJlc2V0UGFzc3dvcmRDb25maXJtYXRpb24pO1xuXHRcdFx0XHRcdFx0XHRcdCQoJy5sb2dpbi1kaWFsb2ctcmVzZXQtcGFzc3dvcmQnKS5hZGRDbGFzcygncmVzZXQtcGFzc3dvcmQtc2hvdycpO1xuXHRcdFx0XHRcdFx0XHRcdHBhc3N3b3JkUmVzZXROb0FjY291bnRDb3JkaWFsRXZlbnQoJy5sb2dpbi1kaWFsb2ctcmVzZXQtcGFzc3dvcmQnKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0XHRcdGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdFx0ZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVzZXQgUGFzc3dvcmQgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0aWYgKGlzTG9naW5EaWFsb2cpIHtcblx0XHRcdFx0XHRcdFx0ZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVzZXQgUGFzc3dvcmQgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuXHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0aWYgKCFpc0xvZ2luRGlhbG9nKSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWY7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGVsc2UgaWYgKFNpdGVQcmVmZXJlbmNlcy5SRVNFVF9QT1BVUF9FTkFCTEVEICYmIGRpYWxvZy5pc0FjdGl2ZSgpKSB7XG5cdFx0XHRkaWFsb2cuc3VibWl0KCRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi5hdHRyKCduYW1lJyksIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRwYXNzd29yZFJlc2V0Tm9BY2NvdW50Q29yZGlhbEV2ZW50KCcucmVzZXRwd2Rwb3B1cCcpO1xuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIGlmIChpc1JlY2FwdGNoYUV2ZW50KSB7XG5cdFx0XHQkcmVzZXRQYXNzd29yZFNlbmRGb3JtLmFwcGVuZCgnPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwiJyArICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi5hdHRyKCduYW1lJykgKyAnXCIgdmFsdWU9XCInICsgJHJlc2V0UGFzc3dvcmRTZW5kQnV0dG9uLnZhbCgpICsgJ1wiLz4nKVxuXHRcdFx0JHJlc2V0UGFzc3dvcmRTZW5kRm9ybS5zdWJtaXQoKTtcblx0XHR9XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0XHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblxuICAgICAgICBpbml0TG9naW5FdmVudHMoKTtcblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiAob3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckFjY291bnRMb2dpbiB8fCBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGFzc3dvcmRSZXNldCkpIHtcblx0XHRcdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRcdFx0bG9hZGVkLlJlY2FwdGNoYSA9IHRydWU7XG5cdFx0XHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yTG9naW4oKTtcblx0XHRcdFx0XHRyZW5kZXJSZWNhcHRjaGFGb3JQYXNzd29yZFJlc2V0KCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0XHRyZWNhcHRjaGEuaW5pdGlhbGl6ZSgpO1xuXHRcdFx0aW5pdGlhbGl6ZVJlY2FwdGNoYUZvckxvZ2luKCk7XG5cdFx0XHRyZW5kZXJSZWNhcHRjaGFGb3JQYXNzd29yZFJlc2V0KCk7XG5cdFx0fVxuXHRcdGluaXRMb2dpbkJ1dHRvbnMoKTtcbiAgICAgICAgaW5pdFZhbGlkYXRlUmV3YXJkc0FjY291bnQoKTtcbiAgICAgICAgaW5pdFZlcmlmeUNvZGVTZW50KCk7XG4gICAgICAgIGluaXRSZXNlbmRWYWxpZGF0aW9uQ29kZSgpO1xuICAgICAgICBpbml0QWRkUnVsZXNGb3JDb2RlSW5wdXQoKTtcbiAgICAgICAgaW5pdFJlc2V0UGFzc3dvcmRFdmVudHMoKTtcbiAgICB9XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIExPR0lOIE1PREFMXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIGxvZ2luRGlhbG9nID0ge1xuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBTaG93cyB0aGUgYWNjb3VudC1sb2dpbiBmb3JtIGluIGEgZGlhbG9nXG4gICAgICovXG4gICAgc2hvdzogZnVuY3Rpb24oY2FsbGJhY2ssIGNvbnRyb2xsZXIsIGFjdGlvbiwgcHJvZHVjdElELCBwYXJhbXMsIGNvbXBsZXRlVXJsKSB7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6IFVybHMubG9naW5EaWFsb2csXG4gICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogY29udHJvbGxlcixcbiAgICAgICAgICAgICAgICBhY3Rpb246IGFjdGlvbixcbiAgICAgICAgICAgICAgICBwYXNzZWRRdWVyeVN0cmluZzogcGFyYW1zXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRcdGlmIChyZXNwb25zZSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0bWw6IHJlc3BvbnNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnbG9naW4tZGlhbG9nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykuYWRkQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuc2Nyb2xsVG9wKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmZpbmQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyJykuYXR0cignZGF0YS1jb250cm9sbGVyJywgY29udHJvbGxlcikuYXR0cignZGF0YS1hY3Rpb24nLCBhY3Rpb24pLmF0dHIoJ2RhdGEtcHJvZHVjdCcsIHByb2R1Y3RJRCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuZmluZCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgZm9ybScpLmVhY2goZnVuY3Rpb24oaSwgZm9ybSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFjdGlvblVybCA9ICQoZm9ybSkuYXR0cignYWN0aW9uJykgKyAnP2xvZ2luRGlhbG9nPXRydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChmb3JtKS5hdHRyKCdhY3Rpb24nLCBhY3Rpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5maW5kKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuYXR0cignZGF0YS1uZXh0LWNvbnRyb2xsZXItdXJsJywgY29tcGxldGVVcmwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHBhc3N3b3JkUmVzZXQgPSAkKHRoaXMpLmZpbmQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyICNwYXNzd29yZC1yZXNldC1idXR0b24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhc3N3b3JkUmVzZXQuYXR0cignZGF0YS10YXJnZXQnLCAkcGFzc3dvcmRSZXNldC5hdHRyKCdkYXRhLXRhcmdldCcpICsgJz9sb2dpbkRpYWxvZz10cnVlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cdFx0XHR9XG5cdFx0fSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQ2xvc2VzIHRoZSBhY2NvdW50LWxvZ2luIGRpYWxvZ1xuICAgICAqL1xuICAgIGNsb3NlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGxvZ2luRGlhbG9nOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKSxcbiAgICBib251c1Byb2R1Y3RzVmlldyA9IHJlcXVpcmUoJy4vYm9udXMtcHJvZHVjdHMtdmlldycpO1xuXG52YXIgdGltZXIgPSB7XG4gICAgaWQ6IG51bGwsXG4gICAgY2xlYXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5pZCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pZDtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgc3RhcnQ6IGZ1bmN0aW9uIChkdXJhdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5pZCA9IHNldFRpbWVvdXQoY2FsbGJhY2ssIGR1cmF0aW9uKTtcbiAgICB9XG59O1xuXG52YXIgbWluaWNhcnQgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRlbCA9ICQoJyNtaW5pLWNhcnQnKTtcbiAgICAgICAgdGhpcy4kY29udGVudCA9IHRoaXMuJGVsLmZpbmQoJy5taW5pLWNhcnQtY29udGVudCcpO1xuXG4gICAgICAgICQoJy5taW5pLWNhcnQtcHJvZHVjdCcpLmVxKDApLmZpbmQoJy5taW5pLWNhcnQtdG9nZ2xlJykuYWRkQ2xhc3MoJ2ZhLWNhcmV0LWRvd24nKTtcbiAgICAgICAgJCgnLm1pbmktY2FydC1wcm9kdWN0Jykubm90KCc6Zmlyc3QnKS5hZGRDbGFzcygnY29sbGFwc2VkJylcbiAgICAgICAgICAgIC5maW5kKCcubWluaS1jYXJ0LXRvZ2dsZScpLmFkZENsYXNzKCdmYS1jYXJldC1yaWdodCcpO1xuXG4gICAgICAgICQoJy5taW5pLWNhcnQtdG9nZ2xlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnZmEtY2FyZXQtZG93biBmYS1jYXJldC1yaWdodCcpO1xuICAgICAgICAgICAgJCh0aGlzKS5jbG9zZXN0KCcubWluaS1jYXJ0LXByb2R1Y3QnKS50b2dnbGVDbGFzcygnY29sbGFwc2VkJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGV2ZW50c1xuICAgICAgICB0aGlzLiRlbC5maW5kKCcubWluaS1jYXJ0LXRvdGFsJykub24oJ21vdXNlZW50ZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy4kY29udGVudC5ub3QoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNsaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgdGhpcy4kY29udGVudC5vbignbW91c2VlbnRlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRpbWVyLmNsZWFyKCk7XG4gICAgICAgIH0pLm9uKCdtb3VzZWxlYXZlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGltZXIuY2xlYXIoKTtcbiAgICAgICAgICAgIHRpbWVyLnN0YXJ0KDMwLCB0aGlzLmNsb3NlLmJpbmQodGhpcykpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICBcbiAgICAgICAgJChkb2N1bWVudCkub24oJ21pbmljYXJ0OnVwZGF0ZScsIGZ1bmN0aW9uKCl7XG4gICAgICAgIFx0Ly9pbXBsZW1lbnQgbWluaWNhcnQgdXBkYXRlIGhlcmVcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gU2hvd3MgdGhlIGdpdmVuIGNvbnRlbnQgaW4gdGhlIG1pbmkgY2FydFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBBIEhUTUwgc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgd2hpY2ggd2lsbCBiZSBzaG93blxuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uIChodG1sKSB7XG4gICAgICAgIHRoaXMuJGVsLmh0bWwoaHRtbCk7XG4gICAgICAgIHV0aWwuc2Nyb2xsQnJvd3NlcigwKTtcbiAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgIHRoaXMuc2xpZGUoKTtcbiAgICAgICAgYm9udXNQcm9kdWN0c1ZpZXcubG9hZEJvbnVzT3B0aW9uKCk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gU2xpZGVzIGRvd24gYW5kIHNob3cgdGhlIGNvbnRlbnRzIG9mIHRoZSBtaW5pIGNhcnRcbiAgICAgKi9cbiAgICBzbGlkZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aW1lci5jbGVhcigpO1xuICAgICAgICAvLyBzaG93IHRoZSBpdGVtXG4gICAgICAgIHRoaXMuJGNvbnRlbnQuc2xpZGVEb3duKCdzbG93Jyk7XG4gICAgICAgIC8vIGFmdGVyIGEgdGltZSBvdXQgYXV0b21hdGljYWxseSBjbG9zZSBpdFxuICAgICAgICB0aW1lci5zdGFydCg2MDAwLCB0aGlzLmNsb3NlLmJpbmQodGhpcykpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgbWluaSBjYXJ0IHdpdGggZ2l2ZW4gZGVsYXlcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gZGVsYXkgVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kc1xuICAgICAqL1xuICAgIGNsb3NlOiBmdW5jdGlvbiAoZGVsYXkpIHtcbiAgICAgICAgdGltZXIuY2xlYXIoKTtcbiAgICAgICAgdGhpcy4kY29udGVudC5zbGlkZVVwKGRlbGF5KTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG1pbmljYXJ0O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG52YXIgcGFnZSA9IHtcbiAgICB0aXRsZTogJycsXG4gICAgdHlwZTogJycsXG4gICAgcGFyYW1zOiB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyKDEpKSxcbiAgICByZWRpcmVjdDogZnVuY3Rpb24gKG5ld1VSTCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gbmV3VVJMO1xuICAgICAgICB9LCAwKTtcbiAgICB9LFxuICAgIHJlZnJlc2g6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uYXNzaWduKHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbiAgICAgICAgfSwgNTAwKTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHBhZ2U7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG5cbnZhciAkYXV0aGVudGljYXRpb25Db250YWluZXIgPSAkKCcuYXV0aGVudGljYXRpb24tZm9ybS1jb250YWluZXInKTtcbnZhciAkYXV0aGVudGljYXRpb25Gb3JtID0gJGF1dGhlbnRpY2F0aW9uQ29udGFpbmVyLmNsb3Nlc3QoJ2Zvcm0nKTtcbnZhciAkYXV0aGVudGljYXRpb25FbWFpbEFkZHJlc3MgPSAkYXV0aGVudGljYXRpb25Gb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJBdXRoZW50aWNhdGlvbkVtYWlsQWRkcmVzc1wiXScpO1xudmFyIGF1dGhlbnRpY2F0aW9uVmFsaWRhdG9yO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbihvcHRpb25zKSB7XG5cdCRhdXRoZW50aWNhdGlvbkNvbnRhaW5lci5vbignY2xpY2snLCAnaW5wdXRbdHlwZT1cInN1Ym1pdFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFxuXHQgICAgYXV0aGVudGljYXRpb25WYWxpZGF0b3IgPSAkYXV0aGVudGljYXRpb25Gb3JtLnZhbGlkYXRlKCk7XG5cdCAgICAkYXV0aGVudGljYXRpb25FbWFpbEFkZHJlc3MucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5FbWFpbCk7XG5cdCAgICBhdXRoZW50aWNhdGlvblZhbGlkYXRvci5mb3JtKCk7XG5cdCAgICBcblx0ICAgIGlmIChhdXRoZW50aWNhdGlvblZhbGlkYXRvci52YWxpZCgpKSB7XG5cdCAgICBcdCQoJzxpbnB1dCAvPicpLmF0dHIoJ3R5cGUnLCAnaGlkZGVuJykuYXR0cignbmFtZScsICdpc01vYmlsZScpLmF0dHIoJ3ZhbHVlJywgJCgnaHRtbC5zaXplLW1vYmlsZScpLmxlbmd0aCA+IDApLmFwcGVuZFRvKCRhdXRoZW50aWNhdGlvbkZvcm0pO1xuXHQgICAgXHQkYXV0aGVudGljYXRpb25Gb3JtLnN1Ym1pdCgpO1xuXHQgICAgfVx0XG4gICAgfSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2c7XG52YXIgQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZztcbnZhciBBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9BZGRyZXNzVmVyaWZpY2F0aW9uL0FkZHJlc3NWZXJpZmljYXRpb25IZWxwZXInKTtcbnZhclx0ZGlhbG9nID0gcmVxdWlyZSgnLi4vZGlhbG9nJyk7XG52YXJcdGZpbmRNb3JlU3RvcmVzID0gcmVxdWlyZSgnLi4vZmluZE1vcmVTdG9yZXMnKTtcbnZhclx0b3JkZXJTdGF0dXNGb3JtID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9PcmRlclN0YXR1c0Zvcm0nKTtcbnZhclx0Z2lmdGNlcnQgPSByZXF1aXJlKCcuLi9naWZ0Y2VydCcpO1xudmFyXHRwYWdlID0gcmVxdWlyZSgnLi4vcGFnZScpO1xudmFyIHJlY2FwdGNoYSA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvUmVjYXB0Y2hhJyk7XG52YXJcdHRvb2x0aXAgPSByZXF1aXJlKCcuLi90b29sdGlwJyk7XG52YXJcdHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXJcdHZhbGlkYXRvciA9IHJlcXVpcmUoJy4uL3ZhbGlkYXRvcicpO1xuXG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBkYXRhQnVmZmVyID0ge307XG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBldmVudHMgb24gdGhlIGFkZHJlc3MgZm9ybSAoYXBwbHksIGNhbmNlbCwgZGVsZXRlKVxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIHdoaWNoIHdpbGwgYmUgaW5pdGlhbGl6ZWRcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUFkZHJlc3NGb3JtKCkge1xuICAgIHZhciAkYWRkcmVzc0VkaXRGb3JtID0gJCgnI2VkaXQtYWRkcmVzcy1mb3JtJyk7XG5cdCRhZGRyZXNzRWRpdEZvcm0ub24oJ2NsaWNrJywgJy5zdWJtaXQtc2hpcHBpbmcnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgYWRkcmVzc1R5cGUgPSAkYWRkcmVzc0VkaXRGb3JtLmF0dHIoJ2FkZHJlc3MtdHlwZScpID8gJGFkZHJlc3NFZGl0Rm9ybS5hdHRyKCdhZGRyZXNzLXR5cGUnKSA6ICdzYXZlZCc7XG5cdFx0dmFyIGFkZHJlc3NEZWxpdmVyYWJsZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdCRhZGRyZXNzRWRpdEZvcm0uc3VibWl0KCk7XG5cdFx0fVxuXHRcdHZhciBhZGRyZXNzTm90RGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoYWRkcmVzc1ZlcmlmeURhdGEpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCBhZGRyZXNzVHlwZSwgYWRkcmVzc1ZlcmlmeURhdGEpO1x0XHRcdFxuXHRcdH1cblx0XHR2YXIgY291bnRyeSA9ICRhZGRyZXNzRWRpdEZvcm0uZmluZCgnW2lkKj1cIl9jb3VudHJ5XCJdJykudmFsKCk7XG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc1ZlcmlmaWNhdGlvbi5FbmFibGVkICYmIGNvdW50cnkudG9VcHBlckNhc2UoKSA9PSAnVVMnICYmICRhZGRyZXNzRWRpdEZvcm0uZmluZCgnLnN1Ym1pdC1zaGlwcGluZycpLmF0dHIoJ3ZlcmlmaWVkJykgIT0gJ3RydWUnKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlZlcmlmeUFkZHJlc3MoJGFkZHJlc3NFZGl0Rm9ybSwgb3B0aW9ucykudGhlbihhZGRyZXNzRGVsaXZlcmFibGUsIGFkZHJlc3NOb3REZWxpdmVyYWJsZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFkZHJlc3NEZWxpdmVyYWJsZSgpO1xuXHRcdH1cbiAgICB9KTtcblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzQXV0b2NvbXBsZXRlLkVuYWJsZWQpIHtcblx0XHQkKGRvY3VtZW50KS5vbigna2V5dXAuQWRkcmVzc0F1dG9jb21wbGV0ZScsICcjZWRpdC1hZGRyZXNzLWZvcm0gaW5wdXRbdHlwZT1cInRleHRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHR2YXIgZm9ybVZhbGlkYXRvciA9ICRhZGRyZXNzRWRpdEZvcm0udmFsaWRhdGUoKTtcblxuXHRcdFx0aWYgKGV2ZW50LmtleUNvZGUgPT0gOCB8fCBldmVudC5rZXlDb2RlID09IDQ2KSB7XG5cdFx0XHRcdCR0aGlzLnBhcmVudCgpLmZpbmQoJy5hZGRyZXNzLWF1dG9jb21wbGV0ZS1kaWFsb2cnKS5yZW1vdmUoKTtcblx0XHRcdH0gZWxzZSBpZiAoIWZvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgKCR0aGlzLmF0dHIoJ2lkJykuaW5kZXhPZignX2FkZHJlc3MxJykgPj0gMCB8fCAkdGhpcy5hdHRyKCdpZCcpLmluZGV4T2YoJ19hZGRyZXNzMicpID49IDAgfHwgJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfY2l0eScpID49IDAgfHwgJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfcG9zdGFsJykgPj0gMCkpIHtcblx0XHRcdFx0dmFyIGFkZHJlc3NBdXRvY29tcGxldGVIYW5kbGVyID0gZnVuY3Rpb24gKGFkZHJlc3NBdXRvY29tcGxldGVEYXRhKSB7XG5cdFx0XHRcdFx0QWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZy5pbml0aWFsaXplKG9wdGlvbnMsIGFkZHJlc3NBdXRvY29tcGxldGVEYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuQXV0b2NvbXBsZXRlQWRkcmVzcygkYWRkcmVzc0VkaXRGb3JtLCAkdGhpcywgb3B0aW9ucykudGhlbihhZGRyZXNzQXV0b2NvbXBsZXRlSGFuZGxlcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub24oJ1NldEFkZHJlc3NGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coZGF0YS4kZm9ybSwgZGF0YS5BZGRyZXNzKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdCQoZG9jdW1lbnQpLm9uKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoZXZlbnQsIGFkZHJlc3NEYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZygkYWRkcmVzc0VkaXRGb3JtLCBhZGRyZXNzRGF0YSk7XG5cdFx0XHQkYWRkcmVzc0VkaXRGb3JtLnN1Ym1pdCgpO1xuXHRcdH0pO1xuXHR9XG5cbiAgICB2YWxpZGF0b3IuaW5pdCgpO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gVG9nZ2xlcyB0aGUgbGlzdCBvZiBPcmRlcnNcbiAqL1xuZnVuY3Rpb24gdG9nZ2xlRnVsbE9yZGVyICgpIHtcbiAgICAkKCcub3JkZXItaXRlbXMnKVxuICAgICAgICAuZmluZCgnbGkuaGlkZGVuOmZpcnN0JylcbiAgICAgICAgLnByZXYoJ2xpJylcbiAgICAgICAgLmFwcGVuZCgnPGEgY2xhc3M9XCJ0b2dnbGVcIj5WaWV3IEFsbDwvYT4nKVxuICAgICAgICAuY2hpbGRyZW4oJy50b2dnbGUnKVxuICAgICAgICAuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS5wYXJlbnQoKS5zaWJsaW5ncygnbGkuaGlkZGVuJykuc2hvdygpO1xuICAgICAgICAgICAgJCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgfSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBCaW5kcyB0aGUgZXZlbnRzIG9uIHRoZSBhZGRyZXNzIGZvcm0gKGVkaXQsIGNyZWF0ZSwgZGVsZXRlKVxuICovXG5mdW5jdGlvbiBpbml0QWRkcmVzc0V2ZW50cygpIHtcbiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpe1xuICAgIFx0aWYgKCAkKCcuYWRkcmVzcy1maWVsZC1jb250YWluZXIgZm9ybSBzZWxlY3QnKS5sZW5ndGggPiAwICkge1xuICAgICAgICBcdCQoJy5hZGRyZXNzLWZpZWxkLWNvbnRhaW5lciBmb3JtIHNlbGVjdCcpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgXHRcdCQodGhpcykuc2VsZWN0bWVudSh7fSk7XG4gICAgICAgIFx0fSk7XG4gICAgICAgIH1cbiAgICBcdFxuICAgIFx0JChcIiNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2JlcmV3YXJkZWRcIikub24oXCJjbGlja1wiLGZ1bmN0aW9uKCl7XG4gICAgICAgIFx0aWYgKCAkKHRoaXMpLmlzKCc6Y2hlY2tlZCcpICkge1xuICAgICAgICBcdFx0JCgnLnJld2FyZHNOdW1iZXJDb250YWluZXInKS5zbGlkZURvd24oKTtcbiAgICAgICAgXHR9IGVsc2Uge1xuICAgICAgICBcdFx0JCgnLnJld2FyZHNOdW1iZXJDb250YWluZXInKS5zbGlkZVVwKCk7XG4gICAgICAgIFx0fVxuICAgIFx0fSk7XG5cblx0XHRpZiAoJCgnI2VkaXQtYWRkcmVzcy1mb3JtJykubGVuZ3RoID4gMCkge1xuXHRcdFx0aW5pdGlhbGl6ZUFkZHJlc3NGb3JtKCk7XG5cdFx0fVxuICAgIH0pO1xuICAgIFxuICAgICQod2luZG93KS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuICAgIFx0JCgnI3ByaW1hcnkgI2VkaXQtYWRkcmVzcy1mb3JtIGlucHV0W25hbWU9XCJkd2ZybV9wcm9maWxlX2FkZHJlc3NfcmVtb3ZlXCJdJykub2ZmKCdjbGljaycpO1xuICAgIFx0JCgnI3ByaW1hcnkgI2VkaXQtYWRkcmVzcy1mb3JtIGlucHV0W25hbWU9XCJkd2ZybV9wcm9maWxlX2FkZHJlc3NfcmVtb3ZlXCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG4gICAgXHRcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFx0dmFyICRmb3JtID0gJCh0aGlzKS5wYXJlbnRzKCdmb3JtJyk7XG4gICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0oU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ09ORklSTV9ERUxFVEUsIFJlc291cmNlcy5USVRMRV9BRERSRVNTKSkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmRlbGV0ZUFkZHJlc3MsIHtcbiAgICAgICAgICAgICAgICAgICAgQWRkcmVzc0lEOiAkZm9ybS5maW5kKCcjYWRkcmVzc2lkJykudmFsKCksXG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdDogJ2FqYXgnXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nXG4gICAgICAgICAgICAgICAgfSkuZG9uZShmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdGF0dXMudG9Mb3dlckNhc2UoKSA9PT0gJ29rJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcVBhcmFtcyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaC5zdWJzdHIoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocVBhcmFtcy5jaWQgIT09IG51bGwgJiYgcVBhcmFtcy5jaWQgPT0gJ2JpbGxpbmcnKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0bG9jYXRpb24uaHJlZiA9IFVybHMucGF5bWVudHNMaXN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0bG9jYXRpb24uaHJlZiA9IFVybHMuYWRkcmVzc2VzTGlzdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YS5tZXNzYWdlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChkYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5hZGRyZXNzZXNMaXN0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgXHR9KTtcbiAgICB9KTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBldmVudHMgb2YgdGhlIHBheW1lbnQgbWV0aG9kcyBsaXN0IChkZWxldGUgY2FyZClcbiAqL1xuZnVuY3Rpb24gaW5pdFBheW1lbnRFdmVudHMoKSB7XG5cdHZhciAkY3JlZGl0Q2FyZFR5cGVTZWxlY3QgPSAkKCdzZWxlY3RbaWQqPVwiY3JlZGl0Y2FyZF90eXBlXCJdJyk7XG5cdFxuXHQvLyBSZW1vdmUgZGlhbG9nIHBheW1lbnQgYWRkL2VkaXQgaW1wbGVtZW50YXRpb24gdG8gdXNlIHBhZ2UgcmVkaXJlY3QgaW5zdGVhZFxuICAgIC8qJCgnLmFkZC1jYXJkJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICB1cmw6ICQoZS50YXJnZXQpLmF0dHIoJ2hyZWYnKVxuICAgICAgICB9KTtcbiAgICB9KTsqL1xuXG5cdCRjcmVkaXRDYXJkVHlwZVNlbGVjdC5vZmYoJ2NoYW5nZS5DcmVkaXRDYXJkVHlwZURldGVjdGlvbicpLm9uKCdjaGFuZ2UuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50VHlwZSA9ICR0aGlzLnZhbCgpO1xuXHRcdHZhciAkYWxsaWFuY2VEYXRhRmllbGREZWx0YSA9ICQoJ2lucHV0W25hbWUqPVwiX293bmVyXCJdLCBzZWxlY3RbbmFtZSo9XCJfbW9udGhcIl0sIHNlbGVjdFtuYW1lKj1cIl95ZWFyXCJdLCBsYWJlbC5leHBpcmF0aW9uLWRhdGUnKTtcblx0XHR2YXIgJGFsbGlhbmNlRGF0YURpc3BsYXlEZWx0YSA9ICQoJ2xhYmVsLmV4cGlyYXRpb24tZGF0ZScpO1xuXHRcdFxuXHQgICAgc3dpdGNoIChwYXltZW50SW5zdHJ1bWVudFR5cGUpIHtcblx0XHRcdGNhc2UgUGF5bWVudE1ldGhvZENvbnN0YW50cy5BbGxpYW5jZURhdGE6XG5cdFx0XHRcdCRhbGxpYW5jZURhdGFGaWVsZERlbHRhLnJlbW92ZUNsYXNzKCdyZXF1aXJlZCcpLmNsb3Nlc3QoJy5mb3JtZmllbGQnKS5oaWRlKCk7XG5cdFx0XHRcdCRhbGxpYW5jZURhdGFEaXNwbGF5RGVsdGEuaGlkZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdFx0XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHQkYWxsaWFuY2VEYXRhRmllbGREZWx0YS5hZGRDbGFzcygncmVxdWlyZWQnKS5jbG9zZXN0KCcuZm9ybWZpZWxkJykuc2hvdygpO1xuXHRcdFx0XHQkYWxsaWFuY2VEYXRhRGlzcGxheURlbHRhLnNob3coKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9KTtcblx0XG5cdCQoJy5jYy1udW1iZXItY29udGFpbmVyIGlucHV0W3R5cGU9XCJ0ZXh0XCJdJykub2ZmKCdrZXl1cC5DcmVkaXRDYXJkVHlwZURldGVjdGlvbicpLm9uKCdrZXl1cC5DcmVkaXRDYXJkVHlwZURldGVjdGlvbicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHNlbGVjdGVkQ3JlZGl0Q2FyZFR5cGUgPSB1dGlsLmdldENyZWRpdENhcmRUeXBlKCQodGhpcykudmFsKCkpO1xuXHRcdFxuXHRcdGlmIChzZWxlY3RlZENyZWRpdENhcmRUeXBlKSB7XG5cdFx0XHQkY3JlZGl0Q2FyZFR5cGVTZWxlY3QudmFsKHNlbGVjdGVkQ3JlZGl0Q2FyZFR5cGUuUGF5bWVudENhcmREaXNwbGF5S2V5KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JGNyZWRpdENhcmRUeXBlU2VsZWN0LnZhbCgnJyk7XG5cdFx0fVxuXHRcdFxuXHRcdCRjcmVkaXRDYXJkVHlwZVNlbGVjdC50cmlnZ2VyKCdjaGFuZ2UuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nKTtcblx0fSk7XG4gICAgXG4gICAgJGNyZWRpdENhcmRUeXBlU2VsZWN0LnRyaWdnZXIoJ2NoYW5nZS5DcmVkaXRDYXJkVHlwZURldGVjdGlvbicpO1xuXHRcblx0dmFyIHBheW1lbnRMaXN0ID0gJCgnLnBheW1lbnQtbGlzdCcpO1xuICAgIGlmIChwYXltZW50TGlzdC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG5cdFxuICAgICQoJ2Zvcm1bbmFtZT1cInBheW1lbnQtcmVtb3ZlXCJdIGJ1dHRvblt0eXBlPVwic3VibWl0XCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBcbiAgICAgICAgLy8gb3ZlcnJpZGUgZm9ybSBzdWJtaXNzaW9uIGluIG9yZGVyIHRvIHByZXZlbnQgcmVmcmVzaCBpc3N1ZXNcbiAgICAgICAgdmFyICRidXR0b24gPSAkKGUudGFyZ2V0KTtcbiAgICAgICAgXG4gICAgICAgIC8vIGNvbmZpcm0gZGVsZXRlXG4gICAgICAgIGlmICgkYnV0dG9uLmhhc0NsYXNzKCdkZWxldGUnKSkge1xuICAgICAgICBcdGlmICghd2luZG93LmNvbmZpcm0oU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ09ORklSTV9ERUxFVEUsIFJlc291cmNlcy5USVRMRV9DUkVESVRDQVJEKSkpIHtcbiAgICAgICAgXHRcdHJldHVybiBmYWxzZTtcbiAgICAgICAgXHR9XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHZhciAkZm9ybSA9ICQodGhpcykuY2xvc2VzdCgnZm9ybScpOyBcbiAgICAgICAgXG4gICAgICAgICQoJzxpbnB1dC8+JykuYXR0cih7XG4gICAgICAgICAgICB0eXBlOiAnaGlkZGVuJyxcbiAgICAgICAgICAgIG5hbWU6ICRidXR0b24uYXR0cignbmFtZScpLFxuICAgICAgICAgICAgdmFsdWU6ICRidXR0b24uYXR0cigndmFsdWUnKSB8fCAnZGVsZXRlIGNhcmQnXG4gICAgICAgIH0pLmFwcGVuZFRvKCRmb3JtKTtcbiAgICAgICAgdmFyIGRhdGEgPSAkZm9ybS5zZXJpYWxpemUoKTtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgIHVybDogJGZvcm0uYXR0cignYWN0aW9uJyksXG4gICAgICAgICAgICBkYXRhOiBkYXRhXG4gICAgICAgIH0pXG4gICAgICAgIC5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBhZ2UucmVkaXJlY3QoVXJscy5wYXltZW50c0xpc3QpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGluaXQgZXZlbnRzIGZvciB0aGUgbG9naW5QYWdlXG4gKi9cbmZ1bmN0aW9uIGluaXRMb2dpblBhZ2UoKSB7XG4gICAgLy9vLWF1dGggYmluZGluZyBmb3Igd2hpY2ggaWNvbiBpcyBjbGlja2VkXG4gICAgJCgnLm9BdXRoSWNvbicpLmJpbmQoJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKCcjT0F1dGhQcm92aWRlcicpLnZhbCh0aGlzLmlkKTtcbiAgICB9KTtcbiAgICAkKCcuYnRuLWxvb2t1cC1vcmRlcicpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgJCgnZGl2LmNoZWNrLW9yZGVyLWNvbnRlbnQnKS5zbGlkZURvd24oKTtcbiAgICAgICAgJCh0aGlzKS5zbGlkZVVwKCk7XG4gICAgfSk7XG4gICAgJCgnI3Bhc3N3b3JkLXJlc2V0LXJld2FyZHMnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIHVybDogJChlLnRhcmdldCkuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgdGFyZ2V0IDogJChcIi5wYXNzd29yZC1yZXNldC1kaWFsb2ctY29udGFpbmVyXCIpLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgXHRkaWFsb2dDbGFzczogJ3NlbGVjdC1yZXdhcmRzLW51bWJlci1wb3B1cCcsXG4gICAgICAgICAgICBcdHdpZHRoOiAzODUsXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3IuaW5pdCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgJHJlcXVlc3RQYXNzd29yZEZvcm0gPSAkKCdbbmFtZSQ9XCJfcmVxdWVzdHBhc3N3b3JkXCJdJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAkc3VibWl0ID0gJHJlcXVlc3RQYXNzd29yZEZvcm0uZmluZCgnW25hbWUkPVwiX3JlcXVlc3RwYXNzd29yZF9zZW5kXCJdJyksXG4gICAgICAgICAgICAgICAgICAgIFx0JHJlc2V0UGFzc3dvcmRGb3JtID0gJCgnW25hbWUkPVwiX3Jlc2V0cGFzc3dvcmRcIl0nKTtcbiAgICAgICAgICAgICAgICAgICAgJCgkc3VibWl0KS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkcmVxdWVzdFBhc3N3b3JkRm9ybS52YWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCAkcmVzZXRQYXNzd29yZEZvcm0ubGVuZ3RoID4gMCApIHtcbiAgICAgICAgICAgICAgICAgICAgXHQkcmVzZXRQYXNzd29yZEZvcm0uZmluZChcImJ1dHRvblt0eXBlPXN1Ym1pdF1cIikub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgXHRcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgXHRcdHZhciBuYW1lQXR0ciA9ICQodGhpcykuYXR0cignbmFtZScpO1xuICAgICAgICAgICAgICAgICAgICBcdFx0ZGlhbG9nLnN1Ym1pdChuYW1lQXR0cik7XG4gICAgICAgICAgICAgICAgICAgIFx0fSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJChcIi5yZXNldC1wYXNzd29yZC1oZWFkaW5nLWNsb3NlLWJ0blwiKS5vbignY2xpY2snLGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKFwiYnV0dG9uLnVpLWRpYWxvZy10aXRsZWJhci1jbG9zZVwiKS5jbGljaygpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgZXhlY0JhckNvZGVHZW5lcmF0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICBpZiAoICQoJyNwYXNzd29yZC1yZXNldC1yZXdhcmRzJykubGVuZ3RoID4gMCApIHtcbiAgICBcdHZhciBjdCA9IDA7XG4gICAgXHR3aGlsZShjdCA8IDIpIHtcbiAgICBcdFx0Y3QrKztcbiAgICBcdFx0JCgnI3Bhc3N3b3JkLXJlc2V0LXJld2FyZHMnKS5jbGljaygpO1xuICAgIFx0fVxuICAgIH1cbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGV2ZW50cyBvZiB0aGUgb3JkZXIsIGFkZHJlc3MgYW5kIHBheW1lbnQgcGFnZXNcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcbiAgICB0b2dnbGVGdWxsT3JkZXIoKTtcbiAgICBpbml0QWRkcmVzc0V2ZW50cygpO1xuICAgIGluaXRQYXltZW50RXZlbnRzKCk7XG4gICAgaW5pdExvZ2luUGFnZSgpO1xuXHRpbml0Q3JlYXRlQWNjb3VudEV2ZW50SGFuZGxlcnMoKTtcbiAgICBpZiAodXRpbC5pc01vYmlsZSgpKSB7XG4gICAgXHR1dGlsLmxpbWl0SW5wdXRUb0xlbmd0aCgnI0NyZWRpdENhcmRGb3JtIGlucHV0W25hbWUqPVwiX251bWJlclwiXScsIDE2KTtcbiAgICB9XG5cblx0dmFyIGJsdXJGaWVsZHMgPSBcIiNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2VtYWlsLCAjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9lbWFpbGNvbmZpcm0sIGlucHV0W2lkKj1kd2ZybV9wcm9maWxlX2xvZ2luX3Bhc3N3b3JkX10sIGlucHV0W2lkKj1kd2ZybV9wcm9maWxlX2xvZ2luX3Bhc3N3b3JkY29uZmlybV9dXCI7XG4gICAgJChibHVyRmllbGRzKS5ibHVyKGZ1bmN0aW9uKCl7XG4gICAgICAgIGlmICggJCh0aGlzKS52YWwoKSA9PSAnJyApIHtcbiAgICAgICAgICAgIGlmICggJCh0aGlzKS5wYXJlbnRzKCcuZm9ybS1yb3cnKS5maW5kKCAnLmZvcm0tY2FwdGlvbi5lcnJvci1tZXNzYWdlJyApLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLnBhcmVudHMoJy5mb3JtLXJvdycpLmZpbmQoICcuZm9ybS1jYXB0aW9uLmVycm9yLW1lc3NhZ2UnICkuaHRtbCgnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZXhlY0JhckNvZGVHZW5lcmF0aW9uKCkge1xuXHRpZiAoJCgnLnJld2FyZHNyZWdpc3RyYXRpb25jb25maXJtYXRpb24nKS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIGJhcmNvZGVOdW1iZXIgPSBcIlwiKyQoJy5yZXdhcmRzcmVnaXN0cmF0aW9uY29uZmlybWF0aW9uJykuZmluZChcIltkYXRhLXJld2FyZHNudW1iZXJdXCIpLmRhdGEoJ3Jld2FyZHNudW1iZXInKTtcblx0XHR2YXIgYmFyY29kZVR5cGUgPSAnY29kZTEyOCc7XG5cdFx0XG5cdFx0JChcIiNiYXJjb2RlVGFyZ2V0XCIpLmJhcmNvZGUoYmFyY29kZU51bWJlciwgYmFyY29kZVR5cGUsIHtcblx0XHRcdGJhckhlaWdodDonNzUnLFxuXHRcdFx0YmFyV2lkdGg6JzInLFxuXHRcdFx0Zm9udFNpemU6JzE0Jyxcblx0XHRcdGZvbnRXZWlnaHQ6J2JvbGQnLFxuXHRcdFx0b3V0cHV0OidibXAnXG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdFJld2FyZHNQYWdlKCkge1xuXHQkKHdpbmRvdykub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcblx0XHRleGVjQmFyQ29kZUdlbmVyYXRpb24oKTtcblx0fSk7XG59XG5cbiQod2luZG93KS5vbihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24oZSkge1xuICAgIHZhciBkYXRhID0gZS5vcmlnaW5hbEV2ZW50LmRhdGE7XG4gICAgaWYoZGF0YSA9PSBcImVycm9yXCIpe1xuICAgIFx0JChcIi5tZW51LXV0aWxpdHktdXNlclwiKS5hZGRDbGFzcyhcImxvZ2luRXJyb3JcIik7XG4gICAgfVxufSk7XG5cbmZ1bmN0aW9uIHJlbmRlck9wdGlvbnMob3B0aW9uUGFyZW50LCBvcHRpb25zU3RvcmVJZCkge1xuXHR2YXIgb3B0aW9ucyA9ICcnO1xuXHR2YXIgc3RhdGVzTGlzdCA9IEpTT04ucGFyc2UoJChvcHRpb25zU3RvcmVJZCArICcgb3B0aW9uOnNlbGVjdGVkJykuZGF0YSgnb3B0aW9ucycpLnJlcGxhY2UoL1xcJy9nLCAnXFxcIicpKTtcblx0XG5cdHN0YXRlc0xpc3QuZm9yRWFjaChmdW5jdGlvbihzdGF0ZSl7XG5cdFx0b3B0aW9ucyArPSAnPG9wdGlvbiBjbGFzcz1cInNlbGVjdC1vcHRpb25cIiBsYWJlbD1cIicrc3RhdGUubGFiZWwrJ1wiIHZhbHVlPVwiJytzdGF0ZS5jb2RlKydcIj4nK3N0YXRlLmxhYmVsKyc8L29wdGlvbj4nO1xuXHR9KTtcblx0JChvcHRpb25QYXJlbnQpLmVtcHR5KCkuYXBwZW5kKG9wdGlvbnMpO1xuXHRcblx0aWYgKHN0YXRlc0xpc3QubGVuZ3RoIDw9IDEpIHtcblx0XHQkKG9wdGlvblBhcmVudCkucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuaGlkZSgpO1xuXHRcdCQob3B0aW9uUGFyZW50ICsgJ19zYm0nKS52YWwoJChvcHRpb25QYXJlbnQpLnZhbCgpKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0fSBlbHNlIHtcblx0XHQkKG9wdGlvblBhcmVudCkucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuc2hvdygpO1xuXHRcdCQob3B0aW9uUGFyZW50ICsgJ19zYm0nKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRSZXdhcmRSZWdpc3RlckZvcm0oKSB7XG5cdCQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkcmV3YXJkUmVnaXN0ZXJGb3JtID0gJCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb24nKTtcblx0XHRpZiAoJHJld2FyZFJlZ2lzdGVyRm9ybS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkcmV3YXJkUmVnaXN0ZXJGb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9waG9uZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBob25lOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRyZXdhcmRSZWdpc3RlckZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyYWRkcmVzc196aXBjb2RlJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cG9zdGFsOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRyZXdhcmRSZWdpc3RlckZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2VtYWlsJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cmVxdWlyZUVtYWlsRXh0ZW5zaW9uOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRyZXdhcmRSZWdpc3RlckZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2VtYWlsY29uZmlybScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHJlcXVpcmVFbWFpbEV4dGVuc2lvbjogdHJ1ZSxcblx0XHRcdFx0ZXF1YWxUbzogJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9lbWFpbCdcblx0XHRcdH0pO1xuXG5cdFx0XHQkcmV3YXJkUmVnaXN0ZXJGb3JtLm9uKCdrZXl1cCcsICcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfZW1haWwnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHR2YXIgc2VydmVyRXJyb3JNZXNzYWdlID0gJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJy5mb3JtLXJvdycpLmZpbmQoJy5lcnJvci1tZXNzYWdlJyk7XG5cdFx0XHRcdGlmIChzZXJ2ZXJFcnJvck1lc3NhZ2UubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHNlcnZlckVycm9yTWVzc2FnZS5yZW1vdmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdFJld2FyZHNBdHRhY2hlZCgpIHtcblx0JCh3aW5kb3cpLm9uKCdsb2FkJywgZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlICNmaWVsZFJld2FyZHNOdW1iZXInKS52YWwoKSAhPSAnJykge1xuXHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgaW5wdXRbdHlwZT1cInN1Ym1pdFwiXScpLnRyaWdnZXIoJ2NsaWNrJyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gcGFzc0JyZWFkU2V0dXAocmV3YXJkc051bWJlcikge1xuXHRCcmVhZFBheW1lbnRzLnNldHVwKHtcblx0XHRsb3lhbHR5SUQ6IHJld2FyZHNOdW1iZXIsXG5cdFx0c3RvcmVOdW1iZXI6IHV0aWwuaXNNb2JpbGUoKSA/IFNpdGVQcmVmZXJlbmNlcy5QTENDX1NUT1JFX05VTUJFUl9NT0JJTEUgOiBTaXRlUHJlZmVyZW5jZXMuUExDQ19TVE9SRV9OVU1CRVJfV0VCLFxuXHRcdGV4aXN0aW5nQ2FyZEhvbGRlcjogZmFsc2UsXG5cdFx0ZW52OiBTaXRlUHJlZmVyZW5jZXMuUExDQ19FTlZJUk9OTUVOVCxcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXREaXNwbGF5UmV3YXJkc0RhdGEoKSB7XG5cdCQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLmdldFJld2FyZEluZm9Gb3JSZWdpc3RlcmVkLFxuXHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0ZGF0YSA6IHtcblx0XHRcdCdjc3JmX3Rva2VuJzogICQoJy5hY2NvdW50LW92ZXJ2aWV3IGlucHV0W25hbWU9XCJjc3JmX3Rva2VuXCJdJykudmFsKCksXG5cdFx0XHQncmV3YXJkc051bWJlcic6ICQoJy5hdHRhY2hlZC1yZXdhcmRzLWFjY291bnQgLnJld2FyZHMtbnVtYmVyJykudGV4dCgpLFx0XHRcdFxuXHRcdFx0J2VtYWlsJzogJCgnLmF0dGFjaGVkLXJld2FyZHMtYWNjb3VudC5lbWFpbC1hZGRyZXNzJykudGV4dCgpLFxuXHRcdFx0J3ppcGNvZGUnOiAkKCcuYXR0YWNoZWQtcmV3YXJkcy1hY2NvdW50LnppcC1jb2RlJykudGV4dCgpLFxuXHRcdFx0J3Bob25lJzogJCgnLmF0dGFjaGVkLXJld2FyZHMtYWNjb3VudC5waG9uZS1udW1iZXInKS50ZXh0KClcblx0XHR9LFxuXHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRpZiAoJ2Vycm9yJyBpbiBkYXRhICYmIGRhdGFbJ2Vycm9yJ10pIHtcblx0XHRcdFx0JCgnLm15YWNjb3VudC1jb250YWN0LWN1c3RzZXJ2JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1x0XHRcdFx0XG5cdFx0XHR9IGVsc2Uge1x0XHRcdFxuXHRcdFx0XHRpZiAoZGF0YS5zZWN1cml0eVJpc2spIHtcdFx0XHRcdFx0XG5cdFx0XHRcdFx0JCgnLm15YWNjb3VudC1jb250YWN0LWN1c3RzZXJ2JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJyNhY3RpdmUtcmV3YXJkcycpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0XHQkKCcuYXR0YWNoZWQtcmV3YXJkcy1hY2NvdW50LmF2YWlsYWJsZS1yZXdhcmRzJykuaHRtbChcIiRcIiArIHBhcnNlRmxvYXQoZGF0YS5jcmVkaXRBbW91bnQpLnRvRml4ZWQoMCkpO1xuXHRcdFx0XHRcdCQoJy5hdHRhY2hlZC1yZXdhcmRzLWFjY291bnQuY3VycmVudC1wb2ludHMnKS5odG1sKGRhdGEucG9pbnRCYWxhbmNlKTtcblx0XHRcdFx0fVx0XHRcblx0XHRcdH1cblx0XHRcdGlmICgkKCcjYWN0aXZlLXJld2FyZHMnKS5sZW5ndGggPj0gMSkge1xuXHRcdFx0XHRwYXNzQnJlYWRTZXR1cChkYXRhLnJld2FyZHNOdW1iZXIpO1xuXHRcdFx0XHRCcmVhZFBheW1lbnRzLnJlZ2lzdGVyUGxhY2VtZW50cyhbZGFzaGJvYXJkUGxhY2VtZW50XSk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRSZXdhcmRDaGVja0Zvcm0oKSB7XG5cdCQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCQoJyNyZXdhcmRzU2VsZWN0MScpLnNlbGVjdG1lbnUoKTtcblx0XHQkKCcjcmV3YXJkc1NlbGVjdDInKS5zZWxlY3RtZW51KCk7XG5cdFx0JCgnYm9keScpLm9uKCdjbGljaycsICcjcmV3YXJkc1NlbGVjdDEtbWVudSAudWktbWVudS1pdGVtLXdyYXBwZXInLCBmdW5jdGlvbigpe1xuXHRcdFx0dmFyIHNlbGVjdDF0ZXh0ID0gJCh0aGlzKS50ZXh0KCk7XG5cdFx0XHRcblx0XHRcdGlmIChzZWxlY3QxdGV4dCA9PSBcIkIgUmV3YXJkZWRcIiB8fCBzZWxlY3QxdGV4dCA9PSBcIlJld2FyZHMgTnVtYmVyXCIgKSB7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5icmV3YXJkZWQtbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAucmV3YXJkcy1udW1iZXInKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5lbWFpbC1hZGRyZXNzJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc1NlbGVjdDEtYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MXRleHQgPT0gXCJFbWFpbCBBZGRyZXNzXCIpIHtcblx0XHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgLmVtYWlsLWFkZHJlc3MnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5icmV3YXJkZWQtbnVtYmVyJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAucmV3YXJkcy1udW1iZXInKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzU2VsZWN0MS1idXR0b24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XHRcblx0XHR9KTtcblx0XHRcblx0XHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyNyZXdhcmRzU2VsZWN0Mi1tZW51IC51aS1tZW51LWl0ZW0td3JhcHBlcicsIGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgc2VsZWN0MnRleHQgPSAkKHRoaXMpLnRleHQoKTtcblx0XHRcdFxuXHRcdFx0aWYgKHNlbGVjdDJ0ZXh0ID09IFwiWmlwIENvZGVcIikge1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuemlwLWNvZGUnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5waG9uZS1udW1iZXInKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzU2VsZWN0Mi1idXR0b24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChzZWxlY3QydGV4dCA9PSBcIlBob25lIE51bWJlclwiKSB7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5waG9uZS1udW1iZXInKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC56aXAtY29kZScpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNTZWxlY3QyLWJ1dHRvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cdFxuXHRcdH0pO1xuXHRcdFxuXHRcdHZhciAkcmV3YXJkQ2hlY2tGb3JtID0gJCgnI3Jld2FyZHNDaGVja0JhbGFuY2UnKTtcblx0XHRpZiAoJHJld2FyZENoZWNrRm9ybS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNOdW1iZXInKS5ydWxlcygnYWRkJywge1xuXHRcdFx0XHRwb3NpdGl2ZW51bWJlcjogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNFbWFpbCcpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHJlcXVpcmVFbWFpbEV4dGVuc2lvbjogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNaaXBjb2RlJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cG9zdGFsOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRyZXdhcmRDaGVja0Zvcm0uZmluZCgnI2ZpZWxkUmV3YXJkc1Bob25lJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cGhvbmU6IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0XG5cdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAjcmVzZXRSZXdhcmRzSW5xdWlyeScpLm9uKCdjbGljaycsICBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHQkKCcudWktc2VsZWN0bWVudS10ZXh0JykudGV4dCgnU2VsZWN0IE9uZScpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc1NlbGVjdDEtYnV0dG9uJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc1NlbGVjdDItYnV0dG9uJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuZm9ybS1yb3cnKS5hZGRDbGFzcygnaGlkZGVuJykuZmluZCgnaW5wdXQuaW5wdXQtdGV4dCcpLnZhbCgnJyk7XG5cdFx0XHRcdCQoJyNzZW5kUmV3YXJkc0lucXVpcnknKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXHRcdFx0XHQkKCcucmV3YXJkcy1yZXN1bHRzJykuaHRtbCgnJyk7XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UnKS5vbignY2hhbmdlJywgJ2lucHV0LmlucHV0LXRleHQnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCAkKCcjZmllbGRSZXdhcmRzTnVtYmVyJykudmFsKCkgfHwgJCgnI2ZpZWxkUmV3YXJkc0VtYWlsJykudmFsKCkgKSB7XG5cdFx0XHRcdFx0aWYgKCAkKCcjZmllbGRSZXdhcmRzWmlwY29kZScpLnZhbCgpIHx8ICQoJyNmaWVsZFJld2FyZHNQaG9uZScpLnZhbCgpICl7XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0JCgnI3NlbmRSZXdhcmRzSW5xdWlyeScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0JHJld2FyZENoZWNrRm9ybS5maW5kKCdpbnB1dCNzZW5kUmV3YXJkc0lucXVpcnknKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHR2YXIgJHJlc3VsdHNDb250YWluZXIgPSAkKCcucmV3YXJkcy1yZXN1bHRzJyk7XG5cblx0XHRcdFx0JHJlc3VsdHNDb250YWluZXIuaHRtbCgnJyk7XG5cblx0XHRcdFx0aWYgKCEkcmV3YXJkQ2hlY2tGb3JtLnZhbGlkKCkpIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHR1cmw6IFVybHMuZ2V0UmV3YXJkSW5mbyxcblx0XHRcdFx0XHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0XHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdFx0J2NzcmZfdG9rZW4nOiAgJHJld2FyZENoZWNrRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0XHQncmV3YXJkc051bWJlcic6ICRyZXdhcmRDaGVja0Zvcm0uZmluZCgnI2ZpZWxkUmV3YXJkc051bWJlcicpLnZhbCgpLFxuXHRcdFx0XHRcdFx0XHQnZW1haWwnOiAkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNFbWFpbCcpLnZhbCgpLFxuXHRcdFx0XHRcdFx0XHQnemlwY29kZSc6ICRyZXdhcmRDaGVja0Zvcm0uZmluZCgnI2ZpZWxkUmV3YXJkc1ppcGNvZGUnKS52YWwoKSxcblx0XHRcdFx0XHRcdFx0J3Bob25lJzogJHJld2FyZENoZWNrRm9ybS5maW5kKCcjZmllbGRSZXdhcmRzUGhvbmUnKS52YWwoKVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHRcdGlmICgnZXJyb3InIGluIGRhdGEgJiYgZGF0YVsnZXJyb3InXSkge1xuXHRcdFx0XHRcdFx0XHRcdCRyZXN1bHRzQ29udGFpbmVyLmFwcGVuZCgnPHAgY2xhc3M9XCJlcnJvci1ibG9ja1wiPicrZGF0YVsnbWVzc2FnZSddKyc8L3A+Jyk7XG5cdFx0XHRcdFx0XHRcdFx0JCgnLnJld2FyZHMtY29udGFjdC1jdXN0c2VydicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdCQoJyNyZXdhcmRzLWRhc2hib2FyZCcpLnNob3coKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoZGF0YS5zZWN1cml0eVJpc2spIHtcblx0XHRcdFx0XHRcdFx0XHRcdCQoJy5yZXdhcmRzLWNvbnRhY3QtY3VzdHNlcnYnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdCQoJy5kaXNwbGF5LXJld2FyZHMnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoICQoJyNnb1RvQ3JlZGl0VHdvJykubGVuZ3RoIDwgMSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmVuZGVyUmV3YXJkQ2hlY2tSZXN1bHRzKGRhdGEsICRyZXN1bHRzQ29udGFpbmVyKTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0JCgnLnJld2FyZHMtZGV0YWlscycpLmhpZGUoKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJld2FyZENoZWNrUmVzdWx0cyhkYXRhLCAkcmVzdWx0c0NvbnRhaW5lcikge1xuXHR2YXIgcmV3YXJkc0NyZWRpdEFtb3VudCA9ICQoJy5hdmFpbGFibGUtcmV3YXJkcycpLmRhdGEoJ2NyZWRpdCcpO1xuXHR2YXIgcG9pbnRzUmVxdWlyZWQgPSAkKCcuYXZhaWxhYmxlLXJld2FyZHMnKS5kYXRhKCdyZXF1aXJlZCcpO1xuXHR2YXIgcG9pbnRzTmVlZGVkID0gcG9pbnRzUmVxdWlyZWQtZGF0YS5wb2ludEJhbGFuY2U7XG5cdHZhciBwb2ludHNUZXh0ID0gZGF0YS5wb2ludEJhbGFuY2UgPT0gMSA/ICcgUFQgJyA6ICcgUFRTICc7XG5cdFxuXHQkKCcjcmV3YXJkcy1udW1iZXInKS50ZXh0KFwiI1wiICsgZGF0YS5yZXdhcmRzTnVtYmVyKS5yZW1vdmVDbGFzcygnbG9hZGVyJyk7XG5cdCQoJyNyZXdhcmRzLWVhcm5lZCcpLnRleHQoXCIkXCIgKyAoTWF0aC5mbG9vcihwYXJzZUZsb2F0KGRhdGEucG9pbnRzRWFybmVkSW5MYXN0WWVhci9wb2ludHNSZXF1aXJlZCkpKjE1KS50b0ZpeGVkKDIpKTtcblx0JCgnLnJld2FyZHMtbWVzc2FnZSBkaXYnKS5yZW1vdmVDbGFzcygnbG9hZGVyJyk7XG5cdCQoJyNyZXdhcmRzLWNyZWRpdCcpLnNob3coKS5odG1sKFwiJFwiICsgcGFyc2VGbG9hdChkYXRhLmNyZWRpdEFtb3VudCkudG9GaXhlZCgwKSkucmVtb3ZlQ2xhc3MoJ2xvYWRlcicpO1xuXHRpZiAoZGF0YS5jcmVkaXRBbW91bnQgIT0gMCl7XHRcdFxuXHRcdCQoJyNyZXdhcmRzLWV4cGlyYXRpb24nKS5zaG93KCkuZmluZCgnc3BhbicpLnRleHQoZGF0YS5jcmVkaXRFeHBpcmF0aW9uRGF0ZSk7XHRcdFxuXHR9IGVsc2Uge1xuXHRcdCQoJy5yZXdhcmRzLXplcm8tbWVzc2FnZScpLnNob3coKTtcblx0fVxuXHQkKCcuYXZhaWxhYmxlLXBvaW50cyBkaXYnKS5yZW1vdmVDbGFzcygnbG9hZGVyJyk7XG5cdCQoJy5wb2ludHMtYWNjcnVlZCcpLnJlbW92ZUNsYXNzKCdsb2FkZXInKS5odG1sKGRhdGEucG9pbnRCYWxhbmNlKTtcblx0XG5cdHBhc3NCcmVhZFNldHVwKGRhdGEucmV3YXJkc051bWJlcik7XG5cdEJyZWFkUGF5bWVudHMucmVnaXN0ZXJQbGFjZW1lbnRzKFtsb3lhbHR5UGxhY2VtZW50XSk7XG59XG5cbmZ1bmN0aW9uIGluaXREaXNwbGF5TG95YWx0eURhdGEoKSB7XG5cdGlmICgkKCcucHRfYWNjb3VudCcpLmxlbmd0aCA+IDApIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLmxveWFsdHlDaGVjayxcblx0XHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0J2xveWFsdHlOdW1iZXInOiAkKCcuc2V0dGluZ3MtLWxveWFsdHknKS5hdHRyKCdkYXRhLW51bWJlcicpLFxuXHRcdFx0XHQnbG95YWx0eVppcCc6ICQoJy5zZXR0aW5ncy0tbG95YWx0eScpLmF0dHIoJ2RhdGEtemlwJylcblx0XHRcdH0sXHRcdFx0XHRcdFx0XG5cdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhWydlcnJvciddKSkge1xuXHRcdFx0XHRcdCQoJy5sb3lhbHR5LWVycm9yJykudGV4dChkYXRhLm1lc3NhZ2UpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJlbmRlckxveWFsdHlJbmZvKGRhdGEuc3RhdHVzKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyTG95YWx0eUluZm8oZGF0YSkge1xuXHR2YXIgb3B0aW5TdGF0dXMgPSBkYXRhLm9wdEluO1xuXHRcblx0aWYgKG9wdGluU3RhdHVzKXtcblx0XHQkKCcubG95YWx0eS1udW1iZXIgc3Bhbi52YWx1ZScpLnRleHQoZGF0YS5sb3lhbHR5TWVtYmVyTnVtYmVyKTtcblx0XHQkKCcuY3VycmVudC1wb2ludHMgc3Bhbi52YWx1ZScpLnRleHQoTWF0aC5mbG9vcihkYXRhLnBvaW50cykpO1xuXHRcdCQoJy5hdmFpbGFibGUtcmV3YXJkcyBzcGFuLnZhbHVlJykudGV4dChcIiRcIiArIGRhdGEudG90YWxSZXdhcmRzKTtcblx0fSBlbHNlIHtcblx0XHQkKCcuc2V0dGluZ3MtLWxveWFsdHknKS5oaWRlKCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gY2xlYXJMb3lhbHR5Rm9ybSgpIHtcblx0JCgnLmNoZWNrLW15LWJhbGFuY2UnKS5zaG93KCk7XG5cdCQoJy5teS1iYWxhbmNlJykuaGlkZSgpO1xuXHQkKCcudWktc2VsZWN0bWVudS10ZXh0JykudGV4dCgnU2VsZWN0IE9uZScpO1xuXHQkKCcjbG95YWx0eVNlbGVjdDEtYnV0dG9uJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHQkKCcjbG95YWx0eVNlbGVjdDItYnV0dG9uJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuZm9ybS1yb3cnKS5hZGRDbGFzcygnaGlkZGVuJykuZmluZCgnaW5wdXQuaW5wdXQtdGV4dCcpLnZhbCgnJyk7XG5cdCQoJyNzZW5kTG95YWx0eUlucXVpcnknKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXHQkKCcubG95YWx0eS1yZXN1bHRzIHNwYW4nKS50ZXh0KCcnKTtcblx0JCgnLmxveWFsdHktZXJyb3InKS5odG1sKCcnKTtcbn1cblxuZnVuY3Rpb24gaW5pdExveWFsdHlDaGVja0Zvcm0oKSB7XG5cdGlmICgkKCcucHRfbG95YWx0eScpLmxlbmd0aCA+IDApIHtcblx0XHQkKCcjbG95YWx0eVNlbGVjdDEnKS5zZWxlY3RtZW51KCk7XG5cdFx0JCgnI2xveWFsdHlTZWxlY3QyJykuc2VsZWN0bWVudSgpO1xuXHRcdFxuXHRcdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI2xveWFsdHlTZWxlY3QxLW1lbnUgLnVpLW1lbnUtaXRlbS13cmFwcGVyJywgZnVuY3Rpb24oKXtcblx0XHRcdHZhciBzZWxlY3QxdGV4dCA9ICQodGhpcykudGV4dCgpO1xuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MXRleHQgPT0gXCJMb3lhbHR5IE51bWJlclwiICkge1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuYnJld2FyZGVkLW51bWJlcicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmxveWFsdHktbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuZW1haWwtYWRkcmVzcycpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlTZWxlY3QxLWJ1dHRvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHNlbGVjdDF0ZXh0ID09IFwiRW1haWwgQWRkcmVzc1wiKSB7XG5cdFx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlIC5lbWFpbC1hZGRyZXNzJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuYnJld2FyZGVkLW51bWJlcicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmxveWFsdHktbnVtYmVyJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eVNlbGVjdDEtYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVx0XG5cdFx0fSk7XG5cdFx0XG5cdFx0JCgnYm9keScpLm9uKCdjbGljaycsICcjbG95YWx0eVNlbGVjdDItbWVudSAudWktbWVudS1pdGVtLXdyYXBwZXInLCBmdW5jdGlvbigpe1xuXHRcdFx0dmFyIHNlbGVjdDJ0ZXh0ID0gJCh0aGlzKS50ZXh0KCk7XG5cdFx0XHRcblx0XHRcdGlmIChzZWxlY3QydGV4dCA9PSBcIlppcCBDb2RlXCIpIHtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLnppcC1jb2RlJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAucGhvbmUtbnVtYmVyJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eVNlbGVjdDItYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MnRleHQgPT0gXCJQaG9uZSBOdW1iZXJcIikge1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAucGhvbmUtbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuemlwLWNvZGUnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNsb3lhbHR5U2VsZWN0Mi1idXR0b24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XHRcblx0XHR9KTtcblx0XHRcblx0XHR2YXIgJGxveWFsdHlDaGVja0Zvcm0gPSAkKCcjbG95YWx0eUNoZWNrQmFsYW5jZScpO1xuXHRcdGlmICgkbG95YWx0eUNoZWNrRm9ybS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5TnVtYmVyJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cG9zaXRpdmVudW1iZXI6IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0JGxveWFsdHlDaGVja0Zvcm0uZmluZCgnI2ZpZWxkTG95YWx0eUVtYWlsJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cmVxdWlyZUVtYWlsRXh0ZW5zaW9uOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRsb3lhbHR5Q2hlY2tGb3JtLmZpbmQoJyNmaWVsZExveWFsdHlaaXBjb2RlJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cG9zdGFsOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRsb3lhbHR5Q2hlY2tGb3JtLmZpbmQoJyNmaWVsZExveWFsdHlQaG9uZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBob25lOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgI3Jlc2V0TG95YWx0eUlucXVpcnknKS5vbignY2xpY2snLCAgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0Y2xlYXJMb3lhbHR5Rm9ybSgpO1x0XHRcdFxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdHZhciBzY3JvbGxNaW51cyA9IDA7XG5cdFx0XHRpZiAoJCgnLnZvdWNoZXInKS5sZW5ndGggPiA4ICl7XG5cdFx0XHRcdHNjcm9sbE1pbnVzID0gMTAwO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCQod2luZG93KS53aWR0aCgpIDwgNzY3KSB7XG5cdFx0XHRcdHNjcm9sbE1pbnVzID0gMTkwO1xuXHRcdFx0fVx0XHRcblx0XHRcdFxuXHRcdFx0JCgnLm15LWJhbGFuY2UgI3N0YXJ0T3ZlckxveWFsdHknKS5vbignY2xpY2snLCAgZnVuY3Rpb24oKSB7XHRcdFx0XHRcdFx0XG5cdFx0XHRcdGNsZWFyTG95YWx0eUZvcm0oKTtcblx0XHRcdFx0aWYgKHNjcm9sbE1pbnVzID4gMCkge1xuXHRcdFx0XHRcdCQoJ2h0bWwsYm9keScpLmFuaW1hdGUoe3Njcm9sbFRvcDogJChcIi50YWJcIikub2Zmc2V0KCkudG9wIC0gc2Nyb2xsTWludXN9LCAyMDApO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UnKS5vbignY2hhbmdlJywgJ2lucHV0LmlucHV0LXRleHQnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCAkKCcjZmllbGRMb3lhbHR5TnVtYmVyJykudmFsKCkgfHwgJCgnI2ZpZWxkTG95YWx0eUVtYWlsJykudmFsKCkgKSB7XG5cdFx0XHRcdFx0aWYgKCAkKCcjZmllbGRMb3lhbHR5WmlwY29kZScpLnZhbCgpIHx8ICQoJyNmaWVsZExveWFsdHlQaG9uZScpLnZhbCgpICl7XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0JCgnI3NlbmRMb3lhbHR5SW5xdWlyeScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XG5cdFx0XHQkbG95YWx0eUNoZWNrRm9ybS5maW5kKCdpbnB1dCNzZW5kTG95YWx0eUlucXVpcnknKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcblx0XHRcdFx0aWYgKCEkbG95YWx0eUNoZWNrRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybDogVXJscy5sb3lhbHR5Q2hlY2ssXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0XHQnbG95YWx0eU51bWJlcic6ICRsb3lhbHR5Q2hlY2tGb3JtLmZpbmQoJyNmaWVsZExveWFsdHlOdW1iZXInKS52YWwoKSxcblx0XHRcdFx0XHRcdCdsb3lhbHR5RW1haWwnOiAkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5RW1haWwnKS52YWwoKSxcblx0XHRcdFx0XHRcdCdsb3lhbHR5WmlwJzogJGxveWFsdHlDaGVja0Zvcm0uZmluZCgnI2ZpZWxkTG95YWx0eVppcGNvZGUnKS52YWwoKSxcblx0XHRcdFx0XHRcdCdsb3lhbHR5UGhvbmUnOiAkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5UGhvbmUnKS52YWwoKVxuXHRcdFx0XHRcdH0sXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdGlmICgoJ2Vycm9yJyBpbiBkYXRhICYmIGRhdGFbJ2Vycm9yJ10pKSB7XG5cdFx0XHRcdFx0XHRcdCQoJy5sb3lhbHR5LWVycm9yJykudGV4dChkYXRhLm1lc3NhZ2UpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRyZW5kZXJMb3lhbHR5Q2hlY2tSZXN1bHRzKGRhdGEuc3RhdHVzKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiByZW5kZXJMb3lhbHR5Q2hlY2tSZXN1bHRzKGRhdGEpIHtcblx0dmFyIG9wdGluU3RhdHVzID0gZGF0YS5vcHRJbjtcblx0dmFyIGN1cnJlbnRTaXRlID0gJyc7XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuICAgIFx0Y3VycmVudFNpdGUgPSBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob3RPcHRlZEluU0hFUDtcbiAgICB9XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuICAgIFx0Y3VycmVudFNpdGUgPSBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob3RPcHRlZEluQ087XG4gICAgfVxuXHRcblx0aWYgKG9wdGluU3RhdHVzKXtcblx0XHQkKCcuY2hlY2stbXktYmFsYW5jZScpLmhpZGUoKTtcblx0XHQkKCcubXktYmFsYW5jZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKS5zaG93KCk7XG5cdFx0JCgnLmxveWFsdHktbnVtYmVyIHNwYW4nKS50ZXh0KGRhdGEubG95YWx0eU1lbWJlck51bWJlcik7XG5cdFx0JCgnLmN1cnJlbnQtcG9pbnRzIHNwYW4nKS50ZXh0KE1hdGguZmxvb3IoZGF0YS5wb2ludHMpKTtcblx0XHQkKCcuYXZhaWxhYmxlLXJld2FyZHMgc3BhbicpLnRleHQoXCIkXCIgKyBkYXRhLnRvdGFsUmV3YXJkcyk7XG5cdFx0dmFyIGRldGFpbHMgPSAnJztcblx0XHR2YXIgdm91Y2hlcnMgPSBkYXRhLnJld2FyZEluZm87XG5cdFx0XG5cdFx0dm91Y2hlcnMuZm9yRWFjaChmdW5jdGlvbih2b3VjaGVyKXtcblx0XHRcdGRldGFpbHMgKz0gJzxkaXYgY2xhc3M9XCJ2b3VjaGVyXCI+PHNwYW4gY2xhc3M9XCJyZXdhcmQtYW1vdW50XCI+UmV3YXJkIEFtb3VudDogPGI+JCcrdm91Y2hlci5yZXdhcmRBbW91bnQrJzwvYj48L3NwYW4+PHNwYW4gY2xhc3M9XCJleHBpcmF0aW9uXCI+RXhwaXJhdGlvbiBEYXRlOiA8Yj4nK3ZvdWNoZXIuZXhwaXJhdGlvbkRhdGUrJzwvYj48L3NwYW4+PC9kaXY+Jztcblx0XHR9KTtcblx0XHRcblx0XHQkKCcuZGV0YWlscycpLmh0bWwoZGV0YWlscyk7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLmxveWFsdHktZXJyb3InKS50ZXh0KGN1cnJlbnRTaXRlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0TG95YWx0eVNvY2lhbCgpIHtcblx0dmFyIGhhbmRsZSA9ICcnO1xuXHRcblx0JCgnYm9keScpLm9uKCdmb2N1cycsICcjZmllbGRMb3lhbHR5U29jaWFsSGFuZGxlSW5zdGFncmFtJywgZnVuY3Rpb24oKSB7XG5cdFx0JCgnLmhhbmRsZS1lcnJvcicpLnRleHQoJycpO1xuXHR9KTtcblxuXHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyN1cGRhdGVJbnN0YWdyYW1IYW5kbGUnLCBmdW5jdGlvbigpe1xuXHRcdCQoJy5oYW5kbGUtZGlzcGxheScpLnJlbW92ZUNsYXNzKCdzaG93LWhhbmRsZScpLmFkZENsYXNzKCdzaG93LWZvcm0nKTtcblx0XHQkKCcuZm9ybS1kaXNwbGF5JykucmVtb3ZlQ2xhc3MoJ3Nob3ctaGFuZGxlJykuYWRkQ2xhc3MoJ3Nob3ctZm9ybScpO1xuXHR9KTtcblx0XG5cdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI2FkZEluc3RhZ3JhbUhhbmRsZScsIGZ1bmN0aW9uKCl7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcblx0XHR2YXIgZm9ybVZhbGlkYXRpb24gPSB0cnVlO1xuXHRcdHZhciBoYW5kbGUgPSAkKCcjZmllbGRMb3lhbHR5U29jaWFsSGFuZGxlSW5zdGFncmFtJykudmFsKCk7XG5cdFx0dmFyIHJlZ2V4SGFuZGxlID0gL15AKFthLXpBLVowLTldfFsuX10oPyFbLl9dKSl7MiwzMH0kLztcblx0XHRpZiAoU3RyaW5nKGhhbmRsZSkubWF0Y2gocmVnZXhIYW5kbGUpID09IG51bGwgKSB7XG5cdFx0XHRmb3JtVmFsaWRhdGlvbiA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmIChmb3JtVmFsaWRhdGlvbikge1x0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMubG95YWx0eU9wdGluLFxuXHRcdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdCdlbWFpbCc6ICQoJy5zZXR0aW5ncy0tbG95YWx0eScpLmF0dHIoJ2RhdGEtZW1haWwnKSxcblx0XHRcdFx0XHQnZHdDdXN0b21lcklEJzogJCgnLnNldHRpbmdzLS1sb3lhbHR5JykuYXR0cignZGF0YS1kd2lkJyksXG5cdFx0XHRcdFx0J2luc3RhSGFuZGxlJzogaGFuZGxlLFxuXHRcdFx0XHRcdCdvcHRTdGF0dXMnOiAkKCcuc2V0dGluZ3MtLWxveWFsdHknKS5hdHRyKCdkYXRhLW9wdGluJylcblx0XHRcdFx0fSxcdFx0XHRcdFx0XHRcblx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRpZiAoKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhWydlcnJvciddKSkge1xuXHRcdFx0XHRcdFx0JCgnLmhhbmRsZS1lcnJvcicpLnRleHQoZGF0YS5tZXNzYWdlKTtcblx0XHRcdFx0XHR9IGVsc2Uge1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHQkKCcuaGFuZGxlLWRpc3BsYXknKS5yZW1vdmVDbGFzcygnc2hvdy1mb3JtJykuYWRkQ2xhc3MoJ3Nob3ctaGFuZGxlJyk7XG5cdFx0XHRcdFx0XHQkKCcuaGFuZGxlLWRpc3BsYXkgLnZhbHVlJykudGV4dChoYW5kbGUpO1xuXHRcdFx0XHRcdFx0JCgnLmZvcm0tZGlzcGxheScpLnJlbW92ZUNsYXNzKCdzaG93LWZvcm0nKS5hZGRDbGFzcygnc2hvdy1oYW5kbGUnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcuaGFuZGxlLWVycm9yJykudGV4dCgnUGxlYXNlIGVudGVyIGEgdmFsaWQgc29jaWFsIGhhbmRsZS4nKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBpbml0QWRkcmVzc0Zvcm1FdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCl7XG5cdFx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICcjZHdmcm1fcHJvZmlsZV9hZGRyZXNzX2NvdW50cnknLCBmdW5jdGlvbigpe1xuXHRcdFx0cmVuZGVyT3B0aW9ucygnI2R3ZnJtX3Byb2ZpbGVfYWRkcmVzc19zdGF0ZXNfc3RhdGUnLCAnI2R3ZnJtX3Byb2ZpbGVfYWRkcmVzc19jb3VudHJ5Jyk7XG5cdFx0XHR2YXIgJGluaXRpYWxTdGF0ZSA9ICQoJyNkd2ZybV9wcm9maWxlX2FkZHJlc3Nfc3RhdGVzX3N0YXRlX3NibScpO1xuXHRcdFx0XG5cdFx0XHRpZiAoJGluaXRpYWxTdGF0ZS5sZW5ndGggPiAwICYmICRpbml0aWFsU3RhdGUudmFsKCkgIT0gJycpIHtcblx0XHRcdFx0JCgnI2R3ZnJtX3Byb2ZpbGVfYWRkcmVzc19zdGF0ZXNfc3RhdGUnKS52YWwoJGluaXRpYWxTdGF0ZS52YWwoKSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0JCgnI2R3ZnJtX3Byb2ZpbGVfYWRkcmVzc19jb3VudHJ5JykudHJpZ2dlcignY2hhbmdlJyk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5maW5kLW1vcmUtc3RvcmVzIGEnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRmaW5kTW9yZVN0b3Jlcy5pbml0aWFsaXplKHsgdmlldzogJ2FjY291bnQnIH0pO1xuXHRcdH0pO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLm9uKCdvcGMuU2V0U2hpcHBpbmdBZGRyZXNzJywgZnVuY3Rpb24gKGUsIGFkZHJlc3MpIHtcblx0XHRcdHZhciAkY2xvc2VzdFN0b3JlcyA9ICQoJyNjbG9zZXN0U3RvcmVzJyk7XG5cdFx0XHR2YXIgJG1ha2VUaGlzTXlzdG9yZSA9ICQoJyNzdG9yZUNvbnRyb2xzJykuZmluZCgnW2RhdGEtYWN0aW9uPVwibWFrZXRoaXNteXN0b3JlXCJdJyk7XG5cdFx0XHRcblx0XHRcdCRjbG9zZXN0U3RvcmVzLmZpbmQoJ29wdGlvbi5maW5kLW1vcmUtc3RvcmVzJykucmVtb3ZlKCk7XG5cdFx0XHRpZiAoJGNsb3Nlc3RTdG9yZXMuZmluZCgnb3B0aW9uW3ZhbHVlPVwiJyArIGFkZHJlc3Muc3RvcmVJZCArICdcIl0nKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHQkY2xvc2VzdFN0b3Jlcy5maW5kKCdvcHRpb24nKS5maXJzdCgpLmFmdGVyKCc8b3B0aW9uIGNsYXNzPVwiZmluZC1tb3JlLXN0b3Jlc1wiIHZhbHVlPVwiJyArIGFkZHJlc3Muc3RvcmVJZCArICdcIj4nICsgYWRkcmVzcy5maXJzdE5hbWUgKyAnIC0gJyArIGFkZHJlc3MubGFiZWxUZXh0ICsgJzwvb3B0aW9uPicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkY2xvc2VzdFN0b3Jlcy52YWwoYWRkcmVzcy5zdG9yZUlkKTtcblx0XHRcdCRjbG9zZXN0U3RvcmVzLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0aWYgKCRtYWtlVGhpc015c3RvcmUubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkbWFrZVRoaXNNeXN0b3JlLnRyaWdnZXIoJ2NsaWNrJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLmFkZHJlc3MtdGlsZSAuYWRkcmVzcy1kZWxldGUnLCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICghY29uZmlybShTdHJpbmcuZm9ybWF0KFJlc291cmNlcy5DT05GSVJNX0RFTEVURSwgUmVzb3VyY2VzLlRJVExFX0FERFJFU1MpKSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB2ZXJpZnlBY2NvdW50Q29kZSgpIHsgIFxuXHQvLyAnZW50ZXItY29kZScgcnVsZXMgd2lsbCBiZSBhcHBsaWVkIHRvIHJld2FyZHMgdmVyaWZpY2F0aW9uIHBhZ2Ugd2l0aCB0aGlzIGNvZGUuIFNlZSBsb2dpbkRpYWxvZy5qcyBmb3IgdGhlIHJ1bGVzIGFkZGVkIGFmdGVyIGFjY291bnQgZGlhbG9nIGlzIG9wZW5lZC5cdFxuXHQkKCcjdmVyaWZ5LWNvZGUnKS5maW5kKCcjZW50ZXItY29kZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0ZGlnaXRzOiB0cnVlLFxuXHRcdG1pbmxlbmd0aDogNixcblx0XHRtZXNzYWdlczoge1xuXHRcdFx0cmVxdWlyZWQ6IFJlc291cmNlcy5WQUxJREFURV9DT0RFLFxuXHRcdFx0bWlubGVuZ3RoOiBSZXNvdXJjZXMuVkFMSURBVEVfQ09ERVxuXHRcdH0sXG5cdFx0bm9ybWFsaXplcjogZnVuY3Rpb24odmFsdWUpIHtcblx0XHRcdHJldHVybiAkLnRyaW0odmFsdWUpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qIE9uIHRoZSBBY2NvdW50IHJlZ2lzdHJhdGlvbiAoYWthIHNldHRpbmdzKSBwYWdlLCBob29rIHVwIHRoZSBldmVudCBoYW5kbGVyIHRvIHVwZGF0ZSB0aGUgaGlkZGVuIGZvcm0gZmllbGRcbiAqIGZvciAnTXkgU3RvcmUgTnVtYmVyJyB3aGVuIHRoZSAoZHluYW1pY2FsbHkgcG9wdWxhdGVkKSBDbG9zZXN0IFN0b3JlcyBkcm9wIGRvd24gaXMgY2hhbmdlZC4gXG4gKiBBbHNvLCBzZXQgdGhlIHZhbHVlIG9mIHRoZSBzZWxlY3RlZCBvcHRpb24gaW4gdGhlIGRyb3AgZG93biwgb3IgdGhlIHZhbHVlIGluICdNeSBTdG9yZSBOdW1iZXInXG4gKiBhcHByb3ByaWF0ZWx5IG9uIGxvYWQgKGJhc2VkIG9uIGlmIGNyZWF0aW5nIGFuIEFjY291bnQgb3IgZWRpdGluZyBvbmUuIFxuICovXG5mdW5jdGlvbiBpbml0Q3JlYXRlQWNjb3VudEV2ZW50SGFuZGxlcnMoKXtcblx0dmFyICRjbG9zZXN0U3RvcmVzID0gJCgnI2Nsb3Nlc3RTdG9yZXMnKTtcblx0dmFyICRzdG9yZUNvbnRyb2xzID0gJCgnI3N0b3JlQ29udHJvbHMnKTtcblx0aWYgKCRjbG9zZXN0U3RvcmVzICE9IHVuZGVmaW5lZCAmJiAkY2xvc2VzdFN0b3JlcyAhPSBudWxsKXtcblx0XHR2YXIgbGVuZ3RoU3RvcmVzID0gJGNsb3Nlc3RTdG9yZXMuZmluZCgnb3B0aW9uJykubGVuZ3RoO1xuXHRcdGlmIChsZW5ndGhTdG9yZXMgPiAwKSB7XG5cdFx0XHR2YXIgc3RvcmVkVmFsdWUgPSAkKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9teVN0b3JlTnVtYmVyJykudmFsKCk7XG5cdFx0XHQkY2xvc2VzdFN0b3Jlcy5vbignY2hhbmdlJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0XHR2YXIgbmV3VmFsdWUgPSAkKHRoaXMpLnZhbCgpO1xuXHRcdFx0XHQkKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9teVN0b3JlTnVtYmVyJykudmFsKG5ld1ZhbHVlKTtcblx0XHRcdFx0dXBkYXRlU2VsZWN0ZWRTdG9yZVByZXZpZXcoJChlLnRhcmdldCkuZmluZCgnOnNlbGVjdGVkJykpO1xuXG5cdFx0XHRcdGlmIChzdG9yZWRWYWx1ZSAhPT0gbmV3VmFsdWUpIHtcblx0XHRcdFx0XHQkc3RvcmVDb250cm9scy5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHN0b3JlQ29udHJvbHMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0c2V0U2VsZWN0ZWRTdG9yZURyb3Bkb3duT3JNeVN0b3JlTnVtYmVyKCk7XG5cdFx0fVxuXHRcdCRzdG9yZUNvbnRyb2xzLm9uKCdjbGljaycsICdhJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dmFyIHN0b3JlSWQgPSAkKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9teVN0b3JlTnVtYmVyJykudmFsKCk7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmwgOiBVcmxzLmFzc2lnblN0b3JlSWQsXG5cdFx0XHRcdGRhdGEgOiB7IHN0b3JlX2lkIDogc3RvcmVJZCB9LFxuXHRcdFx0XHRtZXRob2QgOiBcIlBPU1RcIixcblx0XHRcdFx0ZGF0YVR5cGUgOiBcIkpTT05cIixcblx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRpZiAoICdzdWNjZXNzJyBpbiBkYXRhICYmIGRhdGFbJ3N1Y2Nlc3MnXSA9PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxufVxuXG4vKiBDaGVjayBhbmQgc2VlIGlmIHRoZSBwcm9maWxlIGhhcyBhIHZhbHVlIGZvciAnTXkgU3RvcmUgTnVtYmVyJywgd2hpY2ggaXQgbWlnaHQgaWYgb24gdGhlIEFjY291bnQgRWRpdCBwYWdlLlxuICogSWYgc28sIHRoZW4gc2V0IHRoZSBzdG9yZSBkcm9wIGRvd24gdG8gdGhlIHN0b3JlIG9uIHRoZSBwcm9maWxlLlxuICogSWYgbm90LCB0aGVuIHNldCB0aGUgaGlkZGVuIGZvcm0gZmllbGQgZm9yICdNeSBTdG9yZSBOdW1iZXInIHRvIHRoZSBzZWxlY3RlZCBzdG9yZSBpbiB0aGUgZHJvcCBkb3duLCB3aGljaCB3aWxsIGJlIHRoZSBmaXJzdCBvbmUgd2hlbiBvbiB0aGUgQ3JlYXRlIEFjY291bnQgcGFnZS4gIFxuICovXG5mdW5jdGlvbiBzZXRTZWxlY3RlZFN0b3JlRHJvcGRvd25Pck15U3RvcmVOdW1iZXIoKSB7XG5cdHZhciAkbXlTdG9yZU51bWJlclNlbGVjdGVkID0gJCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbXlTdG9yZU51bWJlcicpO1xuXHRpZiAoJG15U3RvcmVOdW1iZXJTZWxlY3RlZCAhPSB1bmRlZmluZWQgJiYgJG15U3RvcmVOdW1iZXJTZWxlY3RlZCAhPSBudWxsKXtcblx0XHR2YXIgY3VycmVudE15U3RvcmVWYWx1ZSA9ICRteVN0b3JlTnVtYmVyU2VsZWN0ZWQudmFsKCk7IFxuXHRcdGlmIChjdXJyZW50TXlTdG9yZVZhbHVlID09IHVuZGVmaW5lZCB8fCBjdXJyZW50TXlTdG9yZVZhbHVlID09IG51bGwgfHwgY3VycmVudE15U3RvcmVWYWx1ZS5sZW5ndGggPT0gMCl7XG5cdFx0XHQkbXlTdG9yZU51bWJlclNlbGVjdGVkLnZhbCgkKCcjY2xvc2VzdFN0b3JlcycpLnZhbCgpKTtcdFxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcjY2xvc2VzdFN0b3JlcyBvcHRpb25bdmFsdWU9JyArIGN1cnJlbnRNeVN0b3JlVmFsdWUgKyAnXScpLmF0dHIoJ3NlbGVjdGVkJywnc2VsZWN0ZWQnKTtcblx0XHRcdHVwZGF0ZVNlbGVjdGVkU3RvcmVQcmV2aWV3KCQoJyNjbG9zZXN0U3RvcmVzIG9wdGlvblt2YWx1ZT0nICsgY3VycmVudE15U3RvcmVWYWx1ZSArICddJykpO1xuXHRcdH1cbiAgICAgICAgJCgnI3N0b3JlU2VjdGlvbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVTZWxlY3RlZFN0b3JlUHJldmlldygkc3RvcmUpIHtcblx0aWYgKCQoJyNzZWxlY3RlZFN0b3JlJykubGVuZ3RoID4gMCkge1xuXHRcdCQoJyNzZWxlY3RlZFN0b3JlIC5uYW1lJykudGV4dCgkc3RvcmUuZGF0YSgnbmFtZScpKTtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAuYWRkcmVzczEnKS50ZXh0KCRzdG9yZS5kYXRhKCdhZGRyZXNzMScpKTtcblx0XHRpZiAoJHN0b3JlLmRhdGEoJ2FkZHJlc3MyJykgJiYgJHN0b3JlLmRhdGEoJ2FkZHJlc3MyJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnI3NlbGVjdGVkU3RvcmUgLmFkZHJlc3MyJykudGV4dCgkc3RvcmUuZGF0YSgnYWRkcmVzczInKSkucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAuYWRkcmVzczInKS50ZXh0KCcnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0fVxuXHRcdFxuXHRcdCQoJyNzZWxlY3RlZFN0b3JlIC5jaXR5JykudGV4dCgkc3RvcmUuZGF0YSgnY2l0eScpKTtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAuc3RhdGVDb2RlJykudGV4dCgkc3RvcmUuZGF0YSgnc3RhdGVjb2RlJykpO1xuXHRcdCQoJyNzZWxlY3RlZFN0b3JlIC5wb3N0YWxDb2RlJykudGV4dCgkc3RvcmUuZGF0YSgncG9zdGFsY29kZScpKTtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAuY291bnRyeUNvZGUnKS50ZXh0KCRzdG9yZS5kYXRhKCdjb3VudHJ5Y29kZScpKTtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAucGhvbmUnKS50ZXh0KCRzdG9yZS5kYXRhKCdwaG9uZScpKTtcblx0fVxufVxuXG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0XHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZyA9IHJlcXVpcmUoJy4uL0xvYi9BZGRyZXNzVmVyaWZpY2F0aW9uL0FkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cnKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzQXV0b2NvbXBsZXRlLkVuYWJsZWQpIHtcblx0XHRcdEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cgPSByZXF1aXJlKCcuLi9Mb2IvQWRkcmVzc0F1dG9jb21wbGV0ZS9BZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nJyk7XG5cdFx0fVxuXG4gICAgICAgIGluaXRpYWxpemVFdmVudHMoKTtcbiAgICAgICAgZ2lmdGNlcnQuaW5pdCgpO1xuICAgICAgICBpbml0QWRkcmVzc0Zvcm1FdmVudHMoKTtcbiAgICAgICAgaW5pdFJld2FyZFJlZ2lzdGVyRm9ybSgpO1xuICAgICAgICBpbml0UmV3YXJkQ2hlY2tGb3JtKCk7XG4gICAgICAgIGluaXRMb3lhbHR5Q2hlY2tGb3JtKCk7XG4gICAgICAgIGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuICAgICAgICBcdGluaXREaXNwbGF5UmV3YXJkc0RhdGEoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSAmJiBTaXRlUHJlZmVyZW5jZXMuTE9ZQUxUWV9FTkFCTEVEKSB7XG4gICAgICAgIFx0aW5pdERpc3BsYXlMb3lhbHR5RGF0YSgpO1xuICAgICAgICBcdGluaXRMb3lhbHR5U29jaWFsKCk7XG4gICAgICAgIH1cbiAgICAgICAgaW5pdFJld2FyZHNBdHRhY2hlZCgpO1xuXHRcdHZlcmlmeUFjY291bnRDb2RlKCk7XG4gICAgICAgIG9yZGVyU3RhdHVzRm9ybS5pbml0aWFsaXplKCQoJyNkd2ZybV9vcmRlcnRyYWNrJykpOyAgICAgIFxuICAgIH0sXG4gICAgaW5pdENhcnRMb2dpbjogZnVuY3Rpb24gKCkge1xuICAgICAgICBpbml0TG9naW5QYWdlKCk7XG4gICAgICAgIGluaXRSZXdhcmRzUGFnZSgpO1xuICAgIH1cbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYm9waXMgPSByZXF1aXJlKCcuLi9ib3Bpcy9jb21wb25lbnRzL0xvY2F0aW9uU2VhcmNoJyk7XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdHZhciBib3Bpc1dheXNUb1Nob3AgPSBuZXcgYm9waXMoKTtcblx0dmFyIGJvcGlzRm9vdGVyID0gbmV3IGJvcGlzKCk7XG5cdFxuXHRpZiAoJCgnLndheXN0b3Nob3AgLmJvcGlzLXN0b3JlLXNlYXJjaCcpLmxlbmd0aCA+IDApIHtcblx0XHRib3Bpc1dheXNUb1Nob3AuaW5pdGlhbGl6ZSgkKCcud2F5c3Rvc2hvcCAuYm9waXMtc3RvcmUtc2VhcmNoJyksICQuZXh0ZW5kKG9wdGlvbnMuQm9waXMsIHsgQ2hhbm5lbDogb3B0aW9ucy5DaGFubmVsIH0pKTtcblx0fVxuXHRpZiAoJCgnLmJvcGlzLXN0b3JlLXNlYXJjaC1jb250YWluZXIgLmJvcGlzLXN0b3JlLXNlYXJjaCcpLmxlbmd0aCA+IDApIHtcblx0XHRib3Bpc0Zvb3Rlci5pbml0aWFsaXplKCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gtY29udGFpbmVyIC5ib3Bpcy1zdG9yZS1zZWFyY2gnKSwgJC5leHRlbmQob3B0aW9ucy5Cb3BpcywgeyBDaGFubmVsOiBvcHRpb25zLkNoYW5uZWwgfSkpO1xuXHR9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG5cbnZhciBvcHRpb25zO1xudmFyIGRhdGFCdWZmZXI7XG52YXIgJGNvbnRhaW5lcjtcbnZhciAkc3RlcDtcbnZhciB0ZW1wbGF0ZXM7XG52YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRpZiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRcdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXHR9IGVsc2Uge1xuXHRcdG9wdGlvbnMgPSB7fTtcblx0fVxuXHQkY29udGFpbmVyID0gJCgnLmJvb3RmaW5kZXInKTtcblx0JHN0ZXAgPSAkY29udGFpbmVyLmZpbmQoJ1tzdGVwXScpO1xuXHRkYXRhQnVmZmVyID0ge1xuXHRcdHN0ZXA6IDAsXG5cdFx0c3RlcERhdGE6IHt9XG5cdH07XG5cdHRlbXBsYXRlcyA9IHtcblx0XHRzZWN0aW9uQ29udGFpbmVyOiBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib290ZmluZGVyLXNlY3Rpb24tY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpLFxuXHRcdHNlY3Rpb246IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvb3RmaW5kZXItc2VjdGlvbicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSxcblx0XHRvcHRpb246IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvb3RmaW5kZXItb3B0aW9uJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpLFxuXHRcdG9wdGlvbkltYWdlOiBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib290ZmluZGVyLW9wdGlvbi1pbWFnZScpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSxcblx0XHRyZXN1bHRzOiBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib290ZmluZGVyLXJlc3VsdHMnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncylcblx0fVxuXHRsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MgPSB7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZVxuXHR9O1xuXHRcblx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJTdGVwRGVsdGEnKS5vbignY2xpY2suQm9vdEZpbmRlclN0ZXBEZWx0YScsICdbc3RlcC1kZWx0YV0nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIHN0ZXBEZWx0YSA9IHBhcnNlSW50KCR0aGlzLmF0dHIoJ3N0ZXAtZGVsdGEnKSwgMTApO1xuXHRcdGRhdGFCdWZmZXIuc3RlcERlbHRhID0gc3RlcERlbHRhO1xuXHRcdHZhciBzdGVwID0gZGF0YUJ1ZmZlci5zdGVwICsgZGF0YUJ1ZmZlci5zdGVwRGVsdGE7XG5cdFx0aWYgKHN0ZXAgPj0gMCAmJiBzdGVwIDw9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcy5sZW5ndGgpIHtcblx0XHRcdGRhdGFCdWZmZXIuc3RlcCA9IHN0ZXA7XG5cdFx0fVxuXHRcdHJlbmRlcigpO1xuXHR9KTtcblxuXHQvLyAkY29udGFpbmVyLm9mZignY2xpY2suQm9vdEZpbmRlclN0ZXBJbmRleCcpLm9uKCdjbGljay5Cb290RmluZGVyU3RlcEluZGV4JywgJ1tzdGVwLWluZGV4XScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdC8vIFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0Ly8gXHR2YXIgc3RlcCA9IHBhcnNlSW50KCR0aGlzLmF0dHIoJ3N0ZXAtaW5kZXgnKSwgMTApO1xuXHQvLyBcdGlmIChzdGVwID49IDAgJiYgc3RlcCA8PSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMubGVuZ3RoKSB7XG5cdC8vIFx0XHRkYXRhQnVmZmVyLnN0ZXAgPSBzdGVwO1xuXHQvLyBcdH1cblx0Ly8gXHRyZW5kZXIoKTtcblx0Ly8gfSk7XG5cblx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJTdGVwT3B0aW9ucycpLm9uKCdjbGljay5Cb290RmluZGVyU3RlcE9wdGlvbnMnLCAnW3N0ZXBdIC5vcHRpb25zIC5vcHRpb24nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIHNlY3Rpb25JbmRleCA9IHBhcnNlSW50KCR0aGlzLmNsb3Nlc3QoJ1tzZWN0aW9uXScpLmF0dHIoJ3NlY3Rpb24nKSwgMTApO1xuXHRcdGlmICgkdGhpcy5oYXNDbGFzcygnc2VsZWN0ZWQnKSAmJiAhb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5TZWxlY3RSZXF1aXJlZCkge1xuXHRcdFx0JHRoaXMucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHRpZiAoZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXVtzZWN0aW9uSW5kZXhdKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZEluZGV4ID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdW3NlY3Rpb25JbmRleF0uaW5kZXhPZigkdGhpcy5hdHRyKCd2YWx1ZScpKTtcblx0XHRcdFx0aWYgKHNlbGVjdGVkSW5kZXggPiAtMSkge1xuXHRcdFx0XHRcdGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXVtzZWN0aW9uSW5kZXhdLnNwbGljZShzZWxlY3RlZEluZGV4LCAxKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uUmVmaW5lbWVudCA9PSAnc2l6ZScgfHwgb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5SZWZpbmVtZW50ID09ICd3aWR0aCcpIHtcblx0XHRcdFx0dXBkYXRlU2l6ZXMoc2VjdGlvbkluZGV4LCBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCFvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlNlbGVjdE11bHRpcGxlKSB7XG5cdFx0XHRcdCR0aGlzLmNsb3Nlc3QoJy5vcHRpb25zJykuZmluZCgnLm9wdGlvbicpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uU2VsZWN0UmVzZXQgJiYgKGRhdGFCdWZmZXIuc3RlcCArIDEpIDw9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcy5sZW5ndGgpIHtcblx0XHRcdFx0Zm9yICh2YXIgc3RlcEluZGV4ID0gKGRhdGFCdWZmZXIuc3RlcCArIDEpOyBzdGVwSW5kZXggPD0gb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzLmxlbmd0aDsgc3RlcEluZGV4KyspIHtcblx0XHRcdFx0XHRkYXRhQnVmZmVyLnN0ZXBEYXRhW3N0ZXBJbmRleF0gPSB7fTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0JHRoaXMuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHRpZiAoIWRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF0gPSB7fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCFkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF1bc2VjdGlvbkluZGV4XSB8fCAhb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5TZWxlY3RNdWx0aXBsZSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF1bc2VjdGlvbkluZGV4XSA9IFtdO1xuXHRcdFx0fVxuXHRcdFx0dmFyIHNlY3Rpb25EYXRhID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdW3NlY3Rpb25JbmRleF07XG5cdFx0XHRzZWN0aW9uRGF0YVtzZWN0aW9uRGF0YS5sZW5ndGhdID0gJHRoaXMuYXR0cigndmFsdWUnKTtcblx0XHRcdGlmIChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlJlZmluZW1lbnQgPT0gJ3NpemUnIHx8IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uUmVmaW5lbWVudCA9PSAnd2lkdGgnKSB7XG5cdFx0XHRcdHVwZGF0ZVNpemVzKHNlY3Rpb25JbmRleCwgc2VjdGlvbkRhdGEpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICghb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5TZWxlY3RNdWx0aXBsZSAmJiAkdGhpcy5jbG9zZXN0KCcub3B0aW9ucycpLmZpbmQoJy5zZWxlY3RlZCcpLmxlbmd0aCA+IDAgJiYgZGF0YUJ1ZmZlci5zdGVwIDwgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcy5sZW5ndGggLSAxKSkge1xuXHRcdFx0ZGF0YUJ1ZmZlci5zdGVwRGVsdGEgPSAxO1xuXHRcdFx0ZGF0YUJ1ZmZlci5zdGVwICs9IGRhdGFCdWZmZXIuc3RlcERlbHRhO1xuXHRcdFx0cmVuZGVyKCk7XG5cdFx0fVxuXHR9KTtcblxuXHQkY29udGFpbmVyLm9mZignY2xpY2suQm9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWwnKS5vbignY2xpY2suQm9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWwnLCAnLnNlbmQtcmVzdWx0cy1lbWFpbCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkZm9ybSA9ICR0aGlzLmNsb3Nlc3QoJ2Zvcm0nKTtcblx0XHRpZiAoZGF0YUJ1ZmZlci4kZW1haWxGb3JtICYmIGRhdGFCdWZmZXIuJGVtYWlsRm9ybS52YWxpZCgpKSB7XG5cdFx0XHR2YXIgdXJsID0gYnVpbGRVcmwoKTtcblx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdib290ZmluZGVyZW1haWwnKTtcblxuXHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdGVtYWlsOiAkZm9ybS5maW5kKCdpbnB1dFt0eXBlPVwiZW1haWxcIl0nKS52YWwoKSxcblx0XHRcdFx0dXJsOiB1cmxcblx0XHRcdH1cblx0XHRcdCRzdGVwLmxvYWRpbmcoJC5leHRlbmQobG9hZGluZ0luZGljYXRvclNldHRpbmdzLCB7XG5cdFx0XHRcdElzTGFiZWxTaG93bjogdHJ1ZSxcblx0XHRcdFx0Q29udGVudDogJ1NlbmRpbmcgRW1haWwuLi4nXG5cdFx0XHR9KSk7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR0eXBlOiAncG9zdCcsXG5cdFx0XHRcdGRhdGE6IHBheWxvYWQsXG5cdFx0XHRcdHVybDogYnVpbGRVcmwoVXJscy5Cb290RmluZGVyLlNlbmRSZXN1bHRzRW1haWwpLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5zdWNjZXNzKSB7XG5cdFx0XHRcdFx0XHQkc3RlcC5maW5kKCcubG9hZGluZy1pbmRpY2F0b3InKS5maW5kKCcuY29udGVudCcpLmh0bWwoJ0VtYWlsIFNlbnQhPGJyLz5Mb2FkaW5nIFJlc3VsdHMuLi4nKTtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbiA9ICQoJy52aWV3LXJlc3VsdHMnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykuaHRtbCgnPHNwYW4gY2xhc3M9XCJlcnJvclwiPkFuIGVycm9yIG9jY3VycmVkIHNlbmRpbmcgdGhlIGVtYWlsLiBQbGVhc2UgdHJ5IGFnYWluLjwvc3Bhbj4nKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cblx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJWaWV3UmVzdWx0cycpLm9uKCdjbGljay5Cb290RmluZGVyVmlld1Jlc3VsdHMnLCAnLnZpZXctcmVzdWx0cycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCEkc3RlcC5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdCRzdGVwLmxvYWRpbmcoJC5leHRlbmQobG9hZGluZ0luZGljYXRvclNldHRpbmdzLCB7XG5cdFx0XHRcdENvbnRlbnQ6ICdMb2FkaW5nIFJlc3VsdHMuLi4nXG5cdFx0XHR9KSk7XG5cdFx0XHR2YXIgdXJsID0gYnVpbGRVcmwoKTtcblx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdib290ZmluZGVydmlld3Jlc3VsdHMnKTtcblx0XHRcdHdpbmRvdy5sb2NhdGlvbiA9IHVybDtcblx0XHR9XG5cdH0pO1xuXG5cdCQod2luZG93KS5vZmYoJ2xvYWQuQm9vdEZpbmRlciByZXNpemUuQm9vdEZpbmRlcicpLm9uKCdsb2FkLkJvb3RGaW5kZXIgcmVzaXplLkJvb3RGaW5kZXInLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICgkKHdpbmRvdykub3V0ZXJXaWR0aCgpIDw9IDc2OCkge1xuXHRcdFx0JGNvbnRhaW5lci5jc3MoJ21pbi1oZWlnaHQnLCAkKHdpbmRvdykub3V0ZXJIZWlnaHQoKSAtICQoJy5oZWFkZXItd3JhcHBlcicpLmhlaWdodCgpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JGNvbnRhaW5lci5jc3MoJ21pbi1oZWlnaHQnLCAwKTtcblx0XHR9XG5cdH0pO1xuXG5cdHZhciBzdGVwTGlzdEh0bWwgPSAnJztcblx0Zm9yICh2YXIgc3RlcEluZGV4IGluIG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcykge1xuXHRcdHN0ZXBMaXN0SHRtbCArPSAnPGEgc3RlcC1pbmRleD1cIicgKyBzdGVwSW5kZXggKyAnXCI+PC9hPic7XG5cdH1cblx0JGNvbnRhaW5lci5maW5kKCcuc3RlcC1saXN0JykuaHRtbChzdGVwTGlzdEh0bWwpO1xuXHRyZW5kZXIoKTtcbn07XG5cbmZ1bmN0aW9uIHJlbmRlcigpIHtcblx0JHN0ZXAuaGVpZ2h0KCRzdGVwLm91dGVySGVpZ2h0KCkpO1xuXHQkc3RlcC5odG1sKCcnKTtcblx0JHN0ZXAubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHQkKCdodG1sJykuYW5pbWF0ZSh7IHNjcm9sbFRvcDogMCB9LCAyNTApO1xuXHRpZiAoZGF0YUJ1ZmZlci5zdGVwID09IChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMubGVuZ3RoIC0gMSkpIHtcblx0XHQkY29udGFpbmVyLmZpbmQoJy5uZXh0JykuaGlkZSgpO1xuXHRcdCRjb250YWluZXIuZmluZCgnLnZpZXctcmVzdWx0cycpLnNob3coKTtcblx0fSBlbHNlIHtcblx0XHQkY29udGFpbmVyLmZpbmQoJy5uZXh0Jykuc2hvdygpO1xuXHRcdCRjb250YWluZXIuZmluZCgnLnZpZXctcmVzdWx0cycpLmhpZGUoKTtcblx0fVxuXHRyZW5kZXJTdGVwKCk7XG5cdHNlbmREYXRhTGF5ZXIoKTtcblx0aWYgKCRjb250YWluZXIuaGFzQ2xhc3MoJ3Jlc3VsdHMnKSkge1xuXHRcdCRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ3Jlc3VsdHMnKTtcblx0fVxuXG5cdCRjb250YWluZXIuZmluZCgnLnN0ZXAtbGlzdCBhJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHQkY29udGFpbmVyLmZpbmQoJy5zdGVwLWxpc3QgYTpudGgtY2hpbGQoJyArIChkYXRhQnVmZmVyLnN0ZXAgKyAxKSArICcpJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwXScpLmF0dHIoJ3N0ZXAnLCBkYXRhQnVmZmVyLnN0ZXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaXplcyhzZWN0aW9uSW5kZXgsIHNlY3Rpb25EYXRhKSB7XG5cdHJldHVybiBnZXRSZWZpbmVtZW50Q291bnRzRm9yU2VjdGlvbihzZWN0aW9uSW5kZXgsIHNlY3Rpb25EYXRhKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRpZiAob3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XSAmJiBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlJlZmluZW1lbnQgPT0gJ3NpemUnKSB7XG5cdFx0XHR2YXIgJHNlbGVjdGVkTGVuZ3RocyA9ICQoJ1tzZWN0aW9uPVwiJyArIHNlY3Rpb25JbmRleCArICdcIl0gLm9wdGlvbnMnKS5maW5kKCcub3B0aW9uLnNlbGVjdGVkJyk7XG5cdFx0XHR2YXIgJHdpZHRocyA9ICQoJ1tzZWN0aW9uPVwiJyArIChzZWN0aW9uSW5kZXggKyAxKSArICdcIl0gLm9wdGlvbnMgLm9wdGlvbicpO1xuXHRcdFx0aWYgKCRzZWxlY3RlZExlbmd0aHMgJiYgJHNlbGVjdGVkTGVuZ3Rocy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCR3aWR0aHMuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdCRzZWxlY3RlZExlbmd0aHMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRMZW5ndGggPSAkKHRoaXMpLmF0dHIoJ3ZhbHVlJyk7XG5cdFx0XHRcdFx0JHdpZHRocy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0dmFyIHdpZHRoID0gJCh0aGlzKS5hdHRyKCd2YWx1ZScpO1xuXHRcdFx0XHRcdFx0dmFyIHNpemUgPSBzZWxlY3RlZExlbmd0aCArICcgJyArIHdpZHRoO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGFCdWZmZXIuUmVmaW5lbWVudHMgJiYgZGF0YUJ1ZmZlci5SZWZpbmVtZW50cy5zaXplICYmIGRhdGFCdWZmZXIuUmVmaW5lbWVudHMuc2l6ZVtzaXplXSkge1xuXHRcdFx0XHRcdFx0XHQkd2lkdGhzLmZpbHRlcignW3ZhbHVlPVwiJyArIHdpZHRoICsgJ1wiXScpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCR3aWR0aHMucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdICYmIG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uUmVmaW5lbWVudCA9PSAnd2lkdGgnKSB7XG5cdFx0XHR2YXIgJHNlbGVjdGVkV2lkdGhzID0gJCgnW3NlY3Rpb249XCInICsgc2VjdGlvbkluZGV4ICsgJ1wiXSAub3B0aW9ucycpLmZpbmQoJy5vcHRpb24uc2VsZWN0ZWQnKTtcblx0XHRcdHZhciAkbGVuZ3RocyA9ICQoJ1tzZWN0aW9uPVwiJyArIChzZWN0aW9uSW5kZXggLSAxKSArICdcIl0gLm9wdGlvbnMgLm9wdGlvbicpO1xuXHRcdFx0aWYgKCRzZWxlY3RlZFdpZHRocyAmJiAkc2VsZWN0ZWRXaWR0aHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkbGVuZ3Rocy5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0XHRcdFx0JHNlbGVjdGVkV2lkdGhzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0dmFyIHNlbGVjdGVkV2lkdGggPSAkKHRoaXMpLmF0dHIoJ3ZhbHVlJyk7XG5cdFx0XHRcdFx0JGxlbmd0aHMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHZhciBsZW5ndGggPSAkKHRoaXMpLmF0dHIoJ3ZhbHVlJyk7XG5cdFx0XHRcdFx0XHR2YXIgc2l6ZSA9IGxlbmd0aCArICcgJyArIHNlbGVjdGVkV2lkdGg7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YUJ1ZmZlci5SZWZpbmVtZW50cyAmJiBkYXRhQnVmZmVyLlJlZmluZW1lbnRzLnNpemUgJiYgZGF0YUJ1ZmZlci5SZWZpbmVtZW50cy5zaXplW3NpemVdKSB7XG5cdFx0XHRcdFx0XHRcdCRsZW5ndGhzLmZpbHRlcignW3ZhbHVlPVwiJyArIGxlbmd0aCArICdcIl0nKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkbGVuZ3Rocy5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZW5kZXJTdGVwKCkge1xuXHR2YXIgc3RlcCA9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdO1xuXHR2YXIgc3RlcERhdGE7XG5cdGlmIChkYXRhQnVmZmVyLnN0ZXBEYXRhICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXSkge1xuXHQgXHRzdGVwRGF0YSA9IGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXTtcblx0fVxuXHRkYXRhQnVmZmVyLnNlY3Rpb25SZW5kZXJDb3VudCA9IDA7XG5cdGZvciAodmFyIHNlY3Rpb25JbmRleCBpbiBzdGVwLlNlY3Rpb25zKSB7XG5cdFx0dmFyIHNlY3Rpb24gPSBzdGVwLlNlY3Rpb25zW3NlY3Rpb25JbmRleF07XG5cdFx0dmFyIGNvbHVtbnMgPSAxO1xuXHRcdGlmIChzZWN0aW9uLkNvbHVtbnMpIHtcblx0XHRcdGNvbHVtbnMgPSBzZWN0aW9uLkNvbHVtbnM7XG5cdFx0fVxuXHRcdCRjb250YWluZXIuZmluZCgnW3N0ZXBdJykuYXBwZW5kKHRlbXBsYXRlcy5zZWN0aW9uQ29udGFpbmVyKHtcblx0XHRcdFNlY3Rpb246IHNlY3Rpb25JbmRleCxcblx0XHRcdENvbHVtbnM6IGNvbHVtbnNcblx0XHR9KSk7XG5cblx0XHR2YXIgb3B0aW9uc0h0bWwgPSAnJztcblx0XHRpZiAoc2VjdGlvbi5PcHRpb25zKSB7XG5cdFx0XHR2YXIgc2VjdGlvbk9wdGlvbnM7XG5cdFx0XHRpZiAodHlwZW9mIHNlY3Rpb24uT3B0aW9ucyA9PSAnb2JqZWN0JyAmJiBzZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU3RlcCAhPSB1bmRlZmluZWQgJiYgc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblNlY3Rpb24gIT0gdW5kZWZpbmVkICYmIGRhdGFCdWZmZXIuc3RlcERhdGEgJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtzZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU3RlcF0gJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtzZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU3RlcF1bc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblNlY3Rpb25dKSB7XG5cdFx0XHRcdHZhciBvcHRpb25zUmVsYXRlZFNlbGVjdGlvblZhbHVlID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtzZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU3RlcF1bc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblNlY3Rpb25dO1xuXHRcdFx0XHRzZWN0aW9uT3B0aW9ucyA9IHNlY3Rpb24uT3B0aW9uc1tvcHRpb25zUmVsYXRlZFNlbGVjdGlvblZhbHVlXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNlY3Rpb25PcHRpb25zID0gc2VjdGlvbi5PcHRpb25zO1xuXHRcdFx0fVxuXHRcdFx0Zm9yICh2YXIgb3B0aW9uSW5kZXggaW4gc2VjdGlvbk9wdGlvbnMpIHtcblx0XHRcdFx0dmFyIG9wdGlvbiA9IHNlY3Rpb25PcHRpb25zW29wdGlvbkluZGV4XTtcblx0XHRcdFx0aWYgKG9wdGlvbi5UZXh0KSB7XG5cdFx0XHRcdFx0dmFyIGNzc0NsYXNzID0gJyc7XG5cdFx0XHRcdFx0aWYgKHN0ZXBEYXRhICYmIHN0ZXBEYXRhW3NlY3Rpb25JbmRleF0gJiYgJ2luZGV4T2YnIGluIHN0ZXBEYXRhW3NlY3Rpb25JbmRleF0gJiYgc3RlcERhdGFbc2VjdGlvbkluZGV4XS5pbmRleE9mKG9wdGlvbi5UZXh0KSA+IC0xKSB7XG5cdFx0XHRcdFx0XHRjc3NDbGFzcyA9ICdzZWxlY3RlZCc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0b3B0aW9uc0h0bWwgKz0gdGVtcGxhdGVzLm9wdGlvbih7XG5cdFx0XHRcdFx0XHRJbWFnZTogJycsXG5cdFx0XHRcdFx0XHRUZXh0OiBvcHRpb24uVGV4dCxcblx0XHRcdFx0XHRcdFZhbHVlOiBvcHRpb24uVGV4dCxcblx0XHRcdFx0XHRcdENzc0NsYXNzOiBjc3NDbGFzc1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZW5kZXJTZWN0aW9uKHNlY3Rpb25JbmRleCwgc2VjdGlvbi5IZWFkZXIsIHNlY3Rpb24uVGV4dCwgb3B0aW9uc0h0bWwpO1xuXHRcdH0gZWxzZSBpZiAoc2VjdGlvbi5SZWZpbmVtZW50ICYmIHNlY3Rpb24uUmVmaW5lbWVudCAhPSAnd2lkdGgnKSB7XG5cdFx0XHRnZXRSZWZpbmVtZW50Q291bnRzRm9yU2VjdGlvbihzZWN0aW9uSW5kZXgsIHNlY3Rpb24pLnRoZW4oZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHR2YXIgb3B0aW9uc0h0bWxJbm5lciA9ICcnO1xuXHRcdFx0XHRpZiAoZGF0YS5TZWN0aW9uLlJlZmluZW1lbnQgPT0gJ3NpemUnKSB7XG5cdFx0XHRcdFx0dmFyIGxlbmd0aHMgPSBbXTtcblx0XHRcdFx0XHR2YXIgd2lkdGhzID0gW107XG5cdFx0XHRcdFx0dmFyIHdpZHRoUmVnZXggPSAvIFtcXHdcXC9dKy9naTtcblx0XHRcdFx0XHRmb3IgKHZhciByZWZpbmVtZW50S2V5IGluIGRhdGEuUmVmaW5lbWVudHMpIHtcblx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50Q291bnQgPSBkYXRhLlJlZmluZW1lbnRzW3JlZmluZW1lbnRLZXldO1xuXHRcdFx0XHRcdFx0aWYgKHJlZmluZW1lbnRDb3VudCkge1xuXHRcdFx0XHRcdFx0XHR2YXIgd2lkdGhSZWdleFJlc3VsdCA9IHJlZmluZW1lbnRLZXkubWF0Y2god2lkdGhSZWdleCk7XG5cdFx0XHRcdFx0XHRcdHZhciBsZW5ndGg7XG5cdFx0XHRcdFx0XHRcdHZhciB3aWR0aDtcblx0XHRcdFx0XHRcdFx0aWYgKHdpZHRoUmVnZXhSZXN1bHQgJiYgd2lkdGhSZWdleFJlc3VsdC5sZW5ndGgpIHtcblx0XHRcdFx0XHRcdFx0XHR3aWR0aCA9IHdpZHRoUmVnZXhSZXN1bHRbd2lkdGhSZWdleFJlc3VsdC5sZW5ndGggLSAxXS50cmltKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0aWYgKHdpZHRoKSB7XG5cdFx0XHRcdFx0XHRcdFx0bGVuZ3RoID0gcmVmaW5lbWVudEtleS5yZXBsYWNlKHdpZHRoLCAnJykudHJpbSgpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmIChsZW5ndGggJiYgbGVuZ3Rocy5pbmRleE9mKGxlbmd0aCkgPCAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0bGVuZ3Roc1tsZW5ndGhzLmxlbmd0aF0gPSBsZW5ndGg7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0aWYgKHdpZHRoICYmIHdpZHRocy5pbmRleE9mKHdpZHRoKSA8IDApIHtcblx0XHRcdFx0XHRcdFx0XHR3aWR0aHNbd2lkdGhzLmxlbmd0aF0gPSB3aWR0aDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRsZW5ndGhzLnNvcnQoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcblx0XHRcdFx0XHRcdHZhciBsZWZ0VmFsdWUgPSBsZWZ0LnJlcGxhY2UoLyAqMVxcLzIvLCAnLjUnKTtcblx0XHRcdFx0XHRcdHZhciByaWdodFZhbHVlID0gcmlnaHQucmVwbGFjZSgvICoxXFwvMi8sICcuNScpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQobGVmdFZhbHVlKSAtIHBhcnNlRmxvYXQocmlnaHRWYWx1ZSk7XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHR3aWR0aHMuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuXHRcdFx0XHRcdFx0dmFyIGxlZnRWYWx1ZSA9IHBhcnNlSW50KGxlZnQsIDEwKTtcblx0XHRcdFx0XHRcdHZhciByaWdodFZhbHVlID0gcGFyc2VJbnQocmlnaHQsIDEwKTtcblx0XHRcdFx0XHRcdGlmIChsZWZ0VmFsdWUpIHtcblx0XHRcdFx0XHRcdFx0bGVmdFZhbHVlID0gJycucGFkU3RhcnQobGVmdFZhbHVlLCBsZWZ0LnJlcGxhY2UoL1xcZC9nLCAnJylbMF0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0bGVmdFZhbHVlID0gbGVmdDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChyaWdodFZhbHVlKSB7XG5cdFx0XHRcdFx0XHRcdHJpZ2h0VmFsdWUgPSAnJy5wYWRTdGFydChyaWdodFZhbHVlLCByaWdodC5yZXBsYWNlKC9cXGQvZywgJycpWzBdKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJpZ2h0VmFsdWUgPSByaWdodDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0dmFyIGxlZnRXaWR0aERlc2NyaXB0aW9uO1xuXHRcdFx0XHRcdFx0aWYgKG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb24gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXSAmJiBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dWydCb290J10gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddW2xlZnRdKSB7XG5cdFx0XHRcdFx0XHRcdGxlZnRXaWR0aERlc2NyaXB0aW9uID0gb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddW2xlZnRdO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHR2YXIgcmlnaHRXaWR0aERlc2NyaXB0aW9uO1xuXHRcdFx0XHRcdFx0aWYgKG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb24gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXSAmJiBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dWydCb290J10gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddW3JpZ2h0XSkge1xuXHRcdFx0XHRcdFx0XHRyaWdodFdpZHRoRGVzY3JpcHRpb24gPSBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dWydCb290J11bcmlnaHRdO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAobGVmdFdpZHRoRGVzY3JpcHRpb24gPT0gJ01lZGl1bScgJiYgcmlnaHRXaWR0aERlc2NyaXB0aW9uICE9ICdNZWRpdW0nKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAobGVmdFdpZHRoRGVzY3JpcHRpb24gIT0gJ01lZGl1bScgJiYgcmlnaHRXaWR0aERlc2NyaXB0aW9uID09ICdNZWRpdW0nKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKGxlZnRXaWR0aERlc2NyaXB0aW9uID09ICdXaWRlJyAmJiByaWdodFdpZHRoRGVzY3JpcHRpb24gIT0gJ1dpZGUnKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAobGVmdFdpZHRoRGVzY3JpcHRpb24gIT0gJ1dpZGUnICYmIHJpZ2h0V2lkdGhEZXNjcmlwdGlvbiA9PSAnV2lkZScpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRyZXR1cm4gbGVmdFZhbHVlLmxvY2FsZUNvbXBhcmUocmlnaHRWYWx1ZSk7XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRmb3IgKHZhciBsZW5ndGhJbmRleCBpbiBsZW5ndGhzKSB7XG5cdFx0XHRcdFx0XHR2YXIgbGVuZ3RoID0gbGVuZ3Roc1tsZW5ndGhJbmRleF07XG5cdFx0XHRcdFx0XHR2YXIgY3NzQ2xhc3MgPSAnJztcblx0XHRcdFx0XHRcdGlmIChzdGVwRGF0YSAmJiBzdGVwRGF0YVtkYXRhLlNlY3Rpb25JbmRleF0gJiYgJ2luZGV4T2YnIGluIHN0ZXBEYXRhW2RhdGEuU2VjdGlvbkluZGV4XSAmJiBzdGVwRGF0YVtkYXRhLlNlY3Rpb25JbmRleF0uaW5kZXhPZihsZW5ndGgpID4gLTEpIHtcblx0XHRcdFx0XHRcdFx0Y3NzQ2xhc3MgPSAnc2VsZWN0ZWQnO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0b3B0aW9uc0h0bWxJbm5lciArPSB0ZW1wbGF0ZXMub3B0aW9uKHtcblx0XHRcdFx0XHRcdFx0SW1hZ2U6ICcnLFxuXHRcdFx0XHRcdFx0XHRUZXh0OiBsZW5ndGgsXG5cdFx0XHRcdFx0XHRcdFZhbHVlOiBsZW5ndGgsXG5cdFx0XHRcdFx0XHRcdENzc0NsYXNzOiBjc3NDbGFzc1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFCdWZmZXIubGVuZ3RocyA9IGxlbmd0aHM7XG5cdFx0XHRcdFx0cmVuZGVyU2VjdGlvbihkYXRhLlNlY3Rpb25JbmRleCwgZGF0YS5TZWN0aW9uLkhlYWRlciwgZGF0YS5TZWN0aW9uLlRleHQsIG9wdGlvbnNIdG1sSW5uZXIpO1xuXG5cdFx0XHRcdFx0dmFyIHdpZHRoc0h0bWwgPSAnJztcblx0XHRcdFx0XHR2YXIgd2lkdGhTZWN0aW9uSW5kZXggPSBwYXJzZUludChkYXRhLlNlY3Rpb25JbmRleCwgMTApICsgMTtcblx0XHRcdFx0XHRmb3IgKHZhciB3aWR0aEluZGV4IGluIHdpZHRocykge1xuXHRcdFx0XHRcdFx0dmFyIHdpZHRoID0gd2lkdGhzW3dpZHRoSW5kZXhdO1xuXHRcdFx0XHRcdFx0dmFyIGNzc0NsYXNzID0gJyc7XG5cdFx0XHRcdFx0XHRpZiAoc3RlcERhdGEgJiYgc3RlcERhdGFbd2lkdGhTZWN0aW9uSW5kZXhdICYmICdpbmRleE9mJyBpbiBzdGVwRGF0YVt3aWR0aFNlY3Rpb25JbmRleF0gJiYgc3RlcERhdGFbd2lkdGhTZWN0aW9uSW5kZXhdLmluZGV4T2Yod2lkdGgpID4gLTEpIHtcblx0XHRcdFx0XHRcdFx0Y3NzQ2xhc3MgPSAnc2VsZWN0ZWQnO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0dmFyIHdpZHRoRGVzY3JpcHRpb24gPSAnJztcblx0XHRcdFx0XHRcdGlmIChvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV0gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV1bJ0Jvb3QnXVt3aWR0aF0pIHtcblx0XHRcdFx0XHRcdFx0d2lkdGhEZXNjcmlwdGlvbiA9ICcgKCcgKyBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dWydCb290J11bd2lkdGhdICsgJyknO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0d2lkdGhzSHRtbCArPSB0ZW1wbGF0ZXMub3B0aW9uKHtcblx0XHRcdFx0XHRcdFx0SW1hZ2U6ICcnLFxuXHRcdFx0XHRcdFx0XHRUZXh0OiB3aWR0aCArIHdpZHRoRGVzY3JpcHRpb24sXG5cdFx0XHRcdFx0XHRcdFZhbHVlOiB3aWR0aCxcblx0XHRcdFx0XHRcdFx0Q3NzQ2xhc3M6IGNzc0NsYXNzXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZGF0YUJ1ZmZlci53aWR0aHMgPSB3aWR0aHM7XG5cdFx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCdbc2VjdGlvbj1cIicgKyB3aWR0aFNlY3Rpb25JbmRleCArICdcIl0gLm9wdGlvbnMnKS5odG1sKHdpZHRoc0h0bWwpO1xuXHRcdFx0XHRcdHVwZGF0ZVNpemVzKHNlY3Rpb25JbmRleCwgb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Zm9yICh2YXIgcmVmaW5lbWVudEtleSBpbiBkYXRhLlJlZmluZW1lbnRzKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudENvdW50ID0gZGF0YS5SZWZpbmVtZW50c1tyZWZpbmVtZW50S2V5XTtcblx0XHRcdFx0XHRcdGlmIChyZWZpbmVtZW50Q291bnQpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRUZXh0O1xuXHRcdFx0XHRcdFx0XHRpZiAoZGF0YUJ1ZmZlci5EaXNwbGF5VmFsdWVzW2RhdGEuU2VjdGlvbi5SZWZpbmVtZW50XSAmJiBkYXRhQnVmZmVyLkRpc3BsYXlWYWx1ZXNbZGF0YS5TZWN0aW9uLlJlZmluZW1lbnRdW3JlZmluZW1lbnRLZXldKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVmaW5lbWVudFRleHQgPSBkYXRhQnVmZmVyLkRpc3BsYXlWYWx1ZXNbZGF0YS5TZWN0aW9uLlJlZmluZW1lbnRdW3JlZmluZW1lbnRLZXldO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRUZXh0ID0gcmVmaW5lbWVudEtleTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHZhciBjc3NDbGFzcyA9ICcnO1xuXHRcdFx0XHRcdFx0XHRpZiAoc3RlcERhdGEgJiYgc3RlcERhdGFbZGF0YS5TZWN0aW9uSW5kZXhdICYmICdpbmRleE9mJyBpbiBzdGVwRGF0YVtkYXRhLlNlY3Rpb25JbmRleF0gJiYgc3RlcERhdGFbZGF0YS5TZWN0aW9uSW5kZXhdLmluZGV4T2YocmVmaW5lbWVudEtleSkgPiAtMSkge1xuXHRcdFx0XHRcdFx0XHRcdGNzc0NsYXNzID0gJ3NlbGVjdGVkJztcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHZhciBzZWN0aW9uSW1hZ2VzO1xuXHRcdFx0XHRcdFx0XHRpZiAodHlwZW9mIHNlY3Rpb24uSW1hZ2VzID09ICdvYmplY3QnICYmIHNlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblN0ZXAgIT0gdW5kZWZpbmVkICYmIHNlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblNlY3Rpb24gIT0gdW5kZWZpbmVkICYmIGRhdGFCdWZmZXIuc3RlcERhdGEgJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtzZWN0aW9uLkltYWdlc1JlbGF0ZWRTZWxlY3Rpb25TdGVwXSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW3NlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblN0ZXBdW3NlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblNlY3Rpb25dKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIGltYWdlc1JlbGF0ZWRTZWxlY3Rpb25WYWx1ZSA9IGRhdGFCdWZmZXIuc3RlcERhdGFbc2VjdGlvbi5JbWFnZXNSZWxhdGVkU2VsZWN0aW9uU3RlcF1bc2VjdGlvbi5JbWFnZXNSZWxhdGVkU2VsZWN0aW9uU2VjdGlvbl07XG5cdFx0XHRcdFx0XHRcdFx0c2VjdGlvbkltYWdlcyA9IHNlY3Rpb24uSW1hZ2VzW2ltYWdlc1JlbGF0ZWRTZWxlY3Rpb25WYWx1ZV07XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0c2VjdGlvbkltYWdlcyA9IHNlY3Rpb24uSW1hZ2VzO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHZhciBpbWFnZUh0bWwgPSAnJztcblx0XHRcdFx0XHRcdFx0aWYgKHNlY3Rpb25JbWFnZXMgJiYgc2VjdGlvbkltYWdlc1tyZWZpbmVtZW50S2V5XSkge1xuXHRcdFx0XHRcdFx0XHRcdGltYWdlSHRtbCA9IHRlbXBsYXRlcy5vcHRpb25JbWFnZSh7XG5cdFx0XHRcdFx0XHRcdFx0XHRJbWFnZVVybDogc2VjdGlvbkltYWdlc1tyZWZpbmVtZW50S2V5XVxuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHR9XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0b3B0aW9uc0h0bWxJbm5lciArPSB0ZW1wbGF0ZXMub3B0aW9uKHtcblx0XHRcdFx0XHRcdFx0XHRJbWFnZTogaW1hZ2VIdG1sLFxuXHRcdFx0XHRcdFx0XHRcdFRleHQ6IHJlZmluZW1lbnRUZXh0LFxuXHRcdFx0XHRcdFx0XHRcdFZhbHVlOiByZWZpbmVtZW50S2V5LFxuXHRcdFx0XHRcdFx0XHRcdENzc0NsYXNzOiBjc3NDbGFzc1xuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmVuZGVyU2VjdGlvbihkYXRhLlNlY3Rpb25JbmRleCwgZGF0YS5TZWN0aW9uLkhlYWRlciwgZGF0YS5TZWN0aW9uLlRleHQsIG9wdGlvbnNIdG1sSW5uZXIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KS5jYXRjaCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZW5kZXJTZWN0aW9uKHNlY3Rpb25JbmRleCwgc2VjdGlvbi5IZWFkZXIsIHNlY3Rpb24uVGV4dCwgb3B0aW9uc0h0bWwpO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiByZW5kZXJTZWN0aW9uKGluZGV4LCBoZWFkZXIsIHRleHRQYXJhbWV0ZXIsIHNlY3Rpb25PcHRpb25zKSB7XG5cdGRhdGFCdWZmZXIuc2VjdGlvblJlbmRlckNvdW50Kys7XG5cdHZhciB0ZXh0ID0gJyc7XG5cdGlmICh0ZXh0UGFyYW1ldGVyKSB7XG5cdFx0dGV4dCA9ICc8cD4nICsgdGV4dFBhcmFtZXRlciArICc8L3A+Jztcblx0fVxuXHQkY29udGFpbmVyLmZpbmQoJ1tzZWN0aW9uPVwiJyArIGluZGV4ICsgJ1wiXScpLmh0bWwodGVtcGxhdGVzLnNlY3Rpb24oe1xuXHRcdEhlYWRlcjogaGVhZGVyLFxuXHRcdFRleHQ6IHRleHQsXG5cdFx0T3B0aW9uczogc2VjdGlvbk9wdGlvbnNcblx0fSkpO1xuXG5cdGlmIChkYXRhQnVmZmVyLnNlY3Rpb25SZW5kZXJDb3VudCA9PSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9ucy5sZW5ndGgpIHtcblx0XHRpZiAoJHN0ZXAuYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHQkc3RlcC5jc3MoJ2hlaWdodCcsICcnKTtcblx0XHRcdCRzdGVwLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdCQoJ2h0bWwnKS5hbmltYXRlKHsgc2Nyb2xsVG9wOiAwIH0sIDI1MCk7XG5cdFx0fVxuXHRcdCRjb250YWluZXIuZmluZCgnW3N0ZXAtZGVsdGFdJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0aWYgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW2luZGV4XS5TZWxlY3RSZXF1aXJlZCAmJiAkKCcub3B0aW9ucycpLmxlbmd0aCAhPSAkKCcub3B0aW9ucycpLmZpbmQoJy5zZWxlY3RlZCcpLmxlbmd0aCkge1xuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcubmV4dCcpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdH1cdFxuXHRcdGlmIChkYXRhQnVmZmVyLnN0ZXAgPT0gMCkge1xuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcuYmFjaycpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdH1cblx0XHRpZiAoJGNvbnRhaW5lci5maW5kKCcub3B0aW9uJykubGVuZ3RoID09IDApIHtcblx0XHRcdGlmIChkYXRhQnVmZmVyLnN0ZXAgPCAob3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzLmxlbmd0aCAtIDEpKSB7XG5cdFx0XHRcdGRhdGFCdWZmZXIuc3RlcCArPSBkYXRhQnVmZmVyLnN0ZXBEZWx0YTtcblx0XHRcdFx0cmVuZGVyKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCdzZWN0aW9uIGhlYWRlciBoMicpLnRleHQoJ05vIG1vcmUgb3B0aW9ucyB0byBjaG9vc2UgZnJvbSwgY2xpY2sgdGhlIFZpZXcgUmVzdWx0cyBidXR0b24hJylcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVzdWx0cygpIHtcblx0dmFyIHVybCA9IGJ1aWxkVXJsKCk7XG5cdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdib290ZmluZGVydmlld3Jlc3VsdHMnKTtcblxuXHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwXScpLmh0bWwodGVtcGxhdGVzLnJlc3VsdHMoe1xuXHRcdFVybDogdXJsXG5cdH0pKTtcblxuXHRkYXRhQnVmZmVyLiRlbWFpbEZvcm0gPSAkY29udGFpbmVyLmZpbmQoJ2Zvcm0uZW1haWwnKTtcblx0ZGF0YUJ1ZmZlci5lbWFpbFZhbGlkYXRvciA9IGRhdGFCdWZmZXIuJGVtYWlsRm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0ZGF0YUJ1ZmZlci4kZW1haWxGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJlbWFpbFwiXScpLnJ1bGVzKCdhZGQnLCAkLmV4dGVuZChWYWxpZGF0aW9uUnVsZXMuRW1haWwsIHtcblx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRtZXNzYWdlczoge1xuXHRcdFx0cmVxdWlyZWQ6ICQudmFsaWRhdG9yLmZvcm1hdCgnUGxlYXNlIGVudGVyIGFuIGVtYWlsIGFkZHJlc3MuJylcblx0XHR9XG5cdH0pKTtcblx0ZGF0YUJ1ZmZlci4kZW1haWxGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJ1c2VyYWdyZWVtZW50XCJdJykucnVsZXMoJ2FkZCcsIHtcblx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRtZXNzYWdlczoge1xuXHRcdFx0cmVxdWlyZWQ6ICQudmFsaWRhdG9yLmZvcm1hdCgnUGxlYXNlIGFncmVlIHRvIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucy4nKVxuXHRcdH1cblx0fSk7XG5cblx0aWYgKCRzdGVwLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdCRzdGVwLmNzcygnaGVpZ2h0JywgJycpO1xuXHRcdCRzdGVwLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHQkKCdodG1sJykuYW5pbWF0ZSh7IHNjcm9sbFRvcDogMCB9LCAyNTApO1xuXHR9XG5cdCRjb250YWluZXIuZmluZCgnW3N0ZXAtZGVsdGFdJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdCRjb250YWluZXIuZmluZCgnLm5leHQnKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRVcmwodXJsUGFyYW1ldGVyLCBpbmNsdWRlQWRkaXRpb25hbERhdGEpIHtcblx0dmFyIHVybDtcblx0aWYgKGRhdGFCdWZmZXIgJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TdGVwXSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW29wdGlvbnMuQ29uZmlndXJhdGlvbi5DYXRlZ29yeVNlbGVjdGlvblN0ZXBdW29wdGlvbnMuQ29uZmlndXJhdGlvbi5DYXRlZ29yeVNlbGVjdGlvblNlY3Rpb25dKSB7XG5cdFx0dmFyIGNhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbiA9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TdGVwXS5TZWN0aW9uc1tvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uXTtcblx0XHR2YXIgb3B0aW9uUmVsYXRlZFNlbGVjdGlvbiA9IGRhdGFCdWZmZXIuc3RlcERhdGFbY2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU3RlcF1bY2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uLk9wdGlvbnNSZWxhdGVkU2VsZWN0aW9uU2VjdGlvbl1bMF07XG5cdFx0dmFyIGNhdGVnb3J5U2VsZWN0aW9uID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TdGVwXVtvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uXVswXTtcblxuXHRcdHZhciBjYXRlZ29yeVNlbGVjdGlvbkluZGV4O1xuXHRcdHZhciBvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uSW5kZXggPSAwO1xuXHRcdHZhciBvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9ucyA9IGNhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbi5PcHRpb25zW29wdGlvblJlbGF0ZWRTZWxlY3Rpb25dO1xuXHRcdHdoaWxlICghY2F0ZWdvcnlTZWxlY3Rpb25JbmRleCAmJiBvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uSW5kZXggPD0gb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbnMubGVuZ3RoKSB7XG5cdFx0XHRpZiAob3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbnNbb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbkluZGV4XSAmJiBvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uc1tvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uSW5kZXhdLlRleHQgPT0gY2F0ZWdvcnlTZWxlY3Rpb24pIHtcblx0XHRcdFx0Y2F0ZWdvcnlTZWxlY3Rpb25JbmRleCA9IG9wdGlvblJlbGF0ZWRTZWxlY3Rpb25PcHRpb25JbmRleDtcblx0XHRcdH1cblx0XHRcdG9wdGlvblJlbGF0ZWRTZWxlY3Rpb25PcHRpb25JbmRleCsrO1xuXHRcdH1cblxuXHRcdHZhciBjYXRlZ29yeVNlbGVjdGlvbkRhdGEgPSBjYXRlZ29yeVNlbGVjdGlvblNlY3Rpb24uT3B0aW9uc1tvcHRpb25SZWxhdGVkU2VsZWN0aW9uXVtjYXRlZ29yeVNlbGVjdGlvbkluZGV4XTtcblx0XHRpZiAodXJsUGFyYW1ldGVyKSB7XG5cdFx0XHR1cmwgPSB1cmxQYXJhbWV0ZXI7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHVybCA9IGNhdGVnb3J5U2VsZWN0aW9uRGF0YS5Vcmw7XG5cdFx0fVxuXHRcdHZhciBwYXJhbWV0ZXJJbmRleCA9IDE7XG5cdFx0Zm9yICh2YXIgY2F0ZWdvcnlTZWxlY3Rpb25EYXRhS2V5IGluIGNhdGVnb3J5U2VsZWN0aW9uRGF0YSkge1xuXHRcdFx0dmFyIGNhdGVnb3J5U2VsZWN0aW9uRGF0YVZhbHVlID0gY2F0ZWdvcnlTZWxlY3Rpb25EYXRhW2NhdGVnb3J5U2VsZWN0aW9uRGF0YUtleV07XG5cdFx0XHRpZiAodXJsUGFyYW1ldGVyICYmIGNhdGVnb3J5U2VsZWN0aW9uRGF0YUtleSA9PSAnY2dpZCcpIHtcblx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ2NnaWQnLCBjYXRlZ29yeVNlbGVjdGlvbkRhdGFWYWx1ZSk7XG5cdFx0XHR9IGVsc2UgaWYgKGNhdGVnb3J5U2VsZWN0aW9uRGF0YUtleSAhPSAnVGV4dCcgJiYgY2F0ZWdvcnlTZWxlY3Rpb25EYXRhS2V5ICE9ICdVcmwnICYmIGNhdGVnb3J5U2VsZWN0aW9uRGF0YUtleSAhPSAnY2dpZCcpIHtcblx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuJyArIHBhcmFtZXRlckluZGV4LCBjYXRlZ29yeVNlbGVjdGlvbkRhdGFLZXkpO1xuXHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncHJlZnYnICsgcGFyYW1ldGVySW5kZXgsIGNhdGVnb3J5U2VsZWN0aW9uRGF0YVZhbHVlKTtcblx0XHRcdFx0cGFyYW1ldGVySW5kZXgrKztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmb3IgKHZhciBzdGVwSW5kZXhJbm5lciBpbiBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMpIHtcblx0XHRcdGlmIChzdGVwSW5kZXhJbm5lciA8PSBkYXRhQnVmZmVyLnN0ZXApIHtcblx0XHRcdFx0dmFyIHN0ZXBJbm5lciA9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tzdGVwSW5kZXhJbm5lcl07XG5cdFx0XHRcdGZvciAodmFyIHNlY3Rpb25JbmRleElubmVyIGluIHN0ZXBJbm5lci5TZWN0aW9ucykge1xuXHRcdFx0XHRcdHZhciBzZWN0aW9uSW5uZXIgPSBzdGVwSW5uZXIuU2VjdGlvbnNbc2VjdGlvbkluZGV4SW5uZXJdO1xuXHRcdFx0XHRcdGlmIChzZWN0aW9uSW5uZXIuUmVmaW5lbWVudCAmJiBzZWN0aW9uSW5uZXIuUmVmaW5lbWVudCAhPSAnd2lkdGgnKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlcztcblx0XHRcdFx0XHRcdGlmIChkYXRhQnVmZmVyLnN0ZXBEYXRhICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbc3RlcEluZGV4SW5uZXJdICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbc3RlcEluZGV4SW5uZXJdW3NlY3Rpb25JbmRleElubmVyXSkge1xuXHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50VmFsdWVzID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtzdGVwSW5kZXhJbm5lcl1bc2VjdGlvbkluZGV4SW5uZXJdO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlcyA9IFtdO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoc2VjdGlvbklubmVyLlJlZmluZW1lbnQgPT0gJ3NpemUnKSB7XG5cdFx0XHRcdFx0XHRcdHZhciB3aWR0aFNlY3Rpb25JbmRleCA9IHBhcnNlSW50KHNlY3Rpb25JbmRleElubmVyLCAxMCkgKyAxO1xuXHRcdFx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRXaWR0aHMgPSBkYXRhQnVmZmVyLnN0ZXBEYXRhW3N0ZXBJbmRleElubmVyXVt3aWR0aFNlY3Rpb25JbmRleF07XG5cdFx0XHRcdFx0XHRcdHZhciBpc0RhdGFidWZmZXJXaWR0aHMgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0aWYgKCFzZWxlY3RlZFdpZHRocyB8fCAhc2VsZWN0ZWRXaWR0aHMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRXaWR0aHMgPSBkYXRhQnVmZmVyLndpZHRocztcblx0XHRcdFx0XHRcdFx0XHRpc0RhdGFidWZmZXJXaWR0aHMgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHZhciBpc0RhdGFidWZmZXJMZW5ndGhzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdGlmICghcmVmaW5lbWVudFZhbHVlcyB8fCAhcmVmaW5lbWVudFZhbHVlcy5sZW5ndGgpIHtcblx0XHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50VmFsdWVzID0gZGF0YUJ1ZmZlci5sZW5ndGhzO1xuXHRcdFx0XHRcdFx0XHRcdGlzRGF0YWJ1ZmZlckxlbmd0aHMgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHZhciBzZWxlY3RlZFNpemVzID0gW107XG5cdFx0XHRcdFx0XHRcdGlmICghaXNEYXRhYnVmZmVyV2lkdGhzIHx8ICFpc0RhdGFidWZmZXJMZW5ndGhzKSB7XG5cdFx0XHRcdFx0XHRcdFx0Zm9yICh2YXIgcmVmaW5lbWVudEluZGV4IGluIHJlZmluZW1lbnRWYWx1ZXMpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhciBzZWxlY3RlZExlbmd0aCA9IHJlZmluZW1lbnRWYWx1ZXNbcmVmaW5lbWVudEluZGV4XTtcblx0XHRcdFx0XHRcdFx0XHRcdGZvciAodmFyIHdpZHRoSW5kZXggaW4gc2VsZWN0ZWRXaWR0aHMpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIHNlbGVjdGVkV2lkdGggPSBzZWxlY3RlZFdpZHRoc1t3aWR0aEluZGV4XTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIHNlbGVjdGVkU2l6ZSA9IHNlbGVjdGVkTGVuZ3RoICsgJyAnICsgc2VsZWN0ZWRXaWR0aDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKHNlbGVjdGVkU2l6ZXMuaW5kZXhPZihzZWxlY3RlZFNpemUpIDwgMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkU2l6ZXNbc2VsZWN0ZWRTaXplcy5sZW5ndGhdID0gc2VsZWN0ZWRTaXplO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRWYWx1ZXMgPSBzZWxlY3RlZFNpemVzO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAocmVmaW5lbWVudFZhbHVlcyAmJiByZWZpbmVtZW50VmFsdWVzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0aWYgKHNlY3Rpb25Jbm5lci5SZWZpbmVtZW50ID09ICdQcmljZScpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoZGF0YUJ1ZmZlci5UaHJlc2hvbGRzICYmIGRhdGFCdWZmZXIuVGhyZXNob2xkc1tzZWN0aW9uSW5uZXIuUmVmaW5lbWVudF0gJiYgZGF0YUJ1ZmZlci5UaHJlc2hvbGRzW3NlY3Rpb25Jbm5lci5SZWZpbmVtZW50XVtyZWZpbmVtZW50VmFsdWVzXSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIHRocmVzaG9sZCA9IGRhdGFCdWZmZXIuVGhyZXNob2xkc1tzZWN0aW9uSW5uZXIuUmVmaW5lbWVudF1bcmVmaW5lbWVudFZhbHVlc1swXV07XG5cdFx0XHRcdFx0XHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncG1pbicsIHRocmVzaG9sZC52YWx1ZUZyb20pO1xuXHRcdFx0XHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3BtYXgnLCB0aHJlc2hvbGQudmFsdWVUbyk7XHRcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuJyArIHBhcmFtZXRlckluZGV4LCBzZWN0aW9uSW5uZXIuUmVmaW5lbWVudCk7XG5cdFx0XHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZ2JyArIHBhcmFtZXRlckluZGV4LCByZWZpbmVtZW50VmFsdWVzLmpvaW4oJ3wnKSk7XG5cdFx0XHRcdFx0XHRcdFx0cGFyYW1ldGVySW5kZXgrKztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoaW5jbHVkZUFkZGl0aW9uYWxEYXRhKSB7XG5cdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnZGlzcGxheXZhbHVlcycsICdQcmljZScpO1xuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3RocmVzaG9sZHMnLCAnUHJpY2UnKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdXJsO1xufVxuXG5mdW5jdGlvbiBnZXRSZWZpbmVtZW50Q291bnRzRm9yU2VjdGlvbihzZWN0aW9uSW5kZXgsIHNlY3Rpb24pIHtcblx0dmFyIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ2dldCcsXG5cdFx0XHR1cmw6IGJ1aWxkVXJsKFVybHMuZ2V0UmVmaW5lbWVudENvdW50cywgdHJ1ZSksXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdGRhdGFCdWZmZXIgPSAkLmV4dGVuZChkYXRhQnVmZmVyLCBkYXRhKTtcblxuXHRcdFx0XHR2YXIgcGF5bG9hZCA9IHtcblx0XHRcdFx0XHRTZWN0aW9uSW5kZXg6IHNlY3Rpb25JbmRleCxcblx0XHRcdFx0XHRTZWN0aW9uOiBzZWN0aW9uXG5cdFx0XHRcdH07XG5cdFx0XHRcdGlmIChzZWN0aW9uICYmIHNlY3Rpb24uUmVmaW5lbWVudCkge1xuXHRcdFx0XHRcdHBheWxvYWQuUmVmaW5lbWVudHMgPSBkYXRhLlJlZmluZW1lbnRzW3NlY3Rpb24uUmVmaW5lbWVudF07XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVzb2x2ZShwYXlsb2FkKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cblx0cmV0dXJuIHByb21pc2U7XG59XG5cbmZ1bmN0aW9uIHNlbmREYXRhTGF5ZXIoKSB7XG5cdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckV2ZW50KCdib290ZmluZGVycXVpeicsIHtcblx0XHRzdGVwOiBkYXRhQnVmZmVyLnN0ZXAsXG5cdFx0c3RlcERhdGE6IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZGF0YUJ1ZmZlci5zdGVwRGF0YSkpXG5cdH0sIG51bGwsICdHb29nbGVBbmFseXRpY3M0Jyk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcXVhbnRpdHlTdGVwcGVyID0gcmVxdWlyZSgnLi4vcXVhbnRpdHlTdGVwcGVyJyk7XG52YXIgYWNjb3VudCA9IHJlcXVpcmUoJy4vYWNjb3VudCcpO1xudmFyIEFwcGxlUGF5ID0gcmVxdWlyZSgnLi9jaGVja291dC9BcHBsZVBheScpO1xudmFyIGJvbnVzUHJvZHVjdHNWaWV3ID0gcmVxdWlyZSgnLi4vYm9udXMtcHJvZHVjdHMtdmlldycpO1xudmFyIHF1aWNrdmlldyA9IHJlcXVpcmUoJy4uL3F1aWNrdmlldycpO1xudmFyIGNhcnRTdG9yZUludmVudG9yeSA9IHJlcXVpcmUoJy4uL3N0b3JlaW52ZW50b3J5L2NhcnQnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vYWpheCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXIgZm9ybVByZXBhcmUgPSByZXF1aXJlKCcuL2NoZWNrb3V0L2Zvcm1QcmVwYXJlJyk7XG52YXIgcGFnZSA9IHJlcXVpcmUoJy4uL3BhZ2UnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vdG9vbHRpcCcpO1xudmFyIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xudmFyIENoZWNrb3V0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9DaGVja291dENvbnN0YW50cycpO1xudmFyIERhdGFMYXllckNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvRGF0YUxheWVyQ29uc3RhbnRzJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgUmVxdWVzdEhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2hlbHBlcnMvUmVxdWVzdEhlbHBlcicpO1xuXG52YXIgaXNDYXJ0UGFnZSA9IGZhbHNlO1xudmFyIGRhdGFCdWZmZXIgPSB7fTtcbnZhciBvcHRpb25zO1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBCaW5kcyBldmVudHMgdG8gdGhlIGNhcnQgcGFnZSAoZWRpdCBpdGVtJ3MgZGV0YWlscywgYm9udXMgaXRlbSdzIGFjdGlvbnMsIGNvdXBvbiBjb2RlIGVudHJ5KVxuICovIFxuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcdFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnI2NhcnQtdGFibGUgLml0ZW0tZWRpdC1kZXRhaWxzIGEnKS5vbignY2xpY2snLCAnI2NhcnQtdGFibGUgLml0ZW0tZWRpdC1kZXRhaWxzIGEnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIFxuICAgICAgICBxdWlja3ZpZXcuc2hvdyh7XG4gICAgICAgICAgICB1cmw6IGUudGFyZ2V0LmhyZWYsXG4gICAgICAgICAgICBzb3VyY2U6ICdjYXJ0J1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJyNjYXJ0LXRhYmxlIC5ib251cy1pdGVtLWFjdGlvbnMgYSwgI2NhcnQtdGFibGUgLml0ZW0tZGV0YWlscyAuYm9udXNwcm9kdWN0cyBhJykub24oJ2NsaWNrJywgJyNjYXJ0LXRhYmxlIC5ib251cy1pdGVtLWFjdGlvbnMgYSwgI2NhcnQtdGFibGUgLml0ZW0tZGV0YWlscyAuYm9udXNwcm9kdWN0cyBhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBcbiAgICAgICAgYm9udXNQcm9kdWN0c1ZpZXcuc2hvdyh0aGlzLmhyZWYpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZigna2V5ZG93bicsICdmb3JtIGlucHV0W25hbWUkPVwiX2NvdXBvbkNvZGVcIl0nKS5vbigna2V5ZG93bicsICdmb3JtIGlucHV0W25hbWUkPVwiX2NvdXBvbkNvZGVcIl0nLCBmdW5jdGlvbiAoZSkgeyAgIFx0XG4gICAgXHRpZiAoZS53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5FbnRlcikge1xuICAgIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcdFxuICAgIFx0XHQkKCcuZXJyb3IuY291cG9uLWVycm9yJykucmVtb3ZlKCk7XG4gICAgXHRcdGlmICgkKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpLnZhbCgpLmxlbmd0aCA9PT0gMCB8fCBlLndoaWNoID09PSBTaXRlQ29uc3RhbnRzLktleUNvZGVzLkVudGVyICYmICQodGhpcykudmFsKCkubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdCQoJzxzcGFuLz4nLCB7XCJjbGFzc1wiOlwiZXJyb3IgY291cG9uLWVycm9yXCIsIHRleHQgOiBSZXNvdXJjZXMuQ09VUE9OX0FERF9FUlJPUn0pLmluc2VydEFmdGVyKCcuY2FydC1jb3Vwb24tY29kZSAucGNvZGUtY291cG9uJyk7XG5cdFx0XHRcdFxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQgJCgnYnV0dG9uW25hbWUkPVwiYWRkQ291cG9uXCJdJykudHJpZ2dlcignY2xpY2snKTtcblx0XHRcdH1cbiAgICBcdH0gICBcdCBcbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiZGVsZXRlUHJvZHVjdFwiXScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJkZWxldGVQcm9kdWN0XCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFxuICAgIFx0dXBkYXRlQ2FydCgkKHRoaXMpLmF0dHIoJ25hbWUnKSk7XG4gICAgfSk7XG4gICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiYWRkQ291cG9uXCJdJykub24oJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImFkZENvdXBvblwiXScsIGZ1bmN0aW9uIChlKSB7XG5cdCAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHQgICBcdFxuXHQgICBcdCQoJy5lcnJvci5jb3Vwb24tZXJyb3InKS50ZXh0KCcnKTtcblx0ICAgXHR2YXIgJGZvcm0gPSAkKCdmb3JtI2NhcnQtaXRlbXMtZm9ybScpO1xuXHRcdHZhciBuYW1lID0gJCh0aGlzKS5hdHRyKCduYW1lJyk7XG5cdFx0XG5cdFx0KGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcblx0ICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuXHQgICAgICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLm9uZVBhZ2VTdWJtaXQpLFxuXHQgICAgICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lICsgJyZyZXNwVHlwZT1qc29uJ1xuXHQgICAgICAgIH0pKVxuXHRcdH0oKSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdGlmIChyZXNwb25zZS5zdWNjZXNzICYmIHJlc3BvbnNlLnN1Y2Nlc3MgIT09IENoZWNrb3V0Q29uc3RhbnRzLlJlc3BvbnNlQ29kZXMuQWxyZWFkeUluQmFza2V0KSB7XHRcdFx0XHRcblx0XHRcdFx0dmFyIGNvdXBvbkNvZGUgPSAkKCcucGNvZGUtY291cG9uIGlucHV0W25hbWUqPVwiX2NvdXBvbkNvZGVcIl0nKS52YWwoKTtcblxuXHRcdFx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFx0XHRjcmVhdGl2ZV9uYW1lOiBjb3Vwb25Db2RlLFxuXHRcdFx0XHRcdGNyZWF0aXZlX3Nsb3Q6ICdjb3Vwb25jb2RlJyxcblx0XHRcdFx0XHRwcm9tb3Rpb25faWQ6IHJlc3BvbnNlLlByb21vdGlvbiAmJiByZXNwb25zZS5Qcm9tb3Rpb24uSUQgPyByZXNwb25zZS5Qcm9tb3Rpb24uSUQgOiAnJyxcblx0XHRcdFx0XHRwcm9tb3Rpb25fbmFtZTogcmVzcG9uc2UuUHJvbW90aW9uICYmIHJlc3BvbnNlLlByb21vdGlvbi5OYW1lID8gcmVzcG9uc2UuUHJvbW90aW9uLk5hbWUgOiAnJ1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnU2VsZWN0UHJvbW90aW9uJywgZGF0YU9iamVjdCk7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0XHR9IGVsc2UgezFcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSByZXNwb25zZS5zdWNjZXNzID09IENoZWNrb3V0Q29uc3RhbnRzLlJlc3BvbnNlQ29kZXMuQWxyZWFkeUluQmFza2V0ID8gUmVzb3VyY2VzLkNPVVBPTl9BRERfRVJST1JfRFVQIDogUmVzb3VyY2VzLkNPVVBPTl9BRERfRVJST1I7XG5cdFx0XHRcdCQoJzxzcGFuLz4nLCB7J2NsYXNzJzogJ2Vycm9yIGNvdXBvbi1lcnJvcicsICd0ZXh0JzogbWVzc2FnZX0pLmluc2VydEFmdGVyKCcuY2FydC1jb3Vwb24tY29kZSAucGNvZGUtY291cG9uJyk7XG5cdFx0XHR9XG5cdCAgICB9LmJpbmQodGhpcykpO1xuXHR9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiZGVsZXRlQ291cG9uXCJdJykub24oJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImRlbGV0ZUNvdXBvblwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcblx0XHR2YXIgbmFtZSA9ICQodGhpcykuYXR0cignbmFtZScpO1xuXHRcdChmdW5jdGlvbigpe1xuXHRcdFx0cmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcblx0ICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuXHQgICAgICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLm9uZVBhZ2VTdWJtaXQpLFxuXHQgICAgICAgICAgICBkYXRhOiAkKCdmb3JtI2NhcnQtaXRlbXMtZm9ybScpLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWUgKyAnJnJlc3BUeXBlPWpzb24nXG5cdCAgICAgICAgfSkpXG5cdFx0fSgpKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0ICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdyZWZyZXNoLXJlcXVpcmVkJykub24oJ3JlZnJlc2gtcmVxdWlyZWQnLCBmdW5jdGlvbigpe1xuICAgIFx0aWYgKCQoJ2Zvcm0jY2FydC1pdGVtcy1mb3JtIGlucHV0W25hbWUkPVwiX3F1YW50aXR5XCJdJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc2V0VGltZW91dCggZnVuY3Rpb24oKXsgXG4gICAgICAgICAgICAgICAgJCgnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0gaW5wdXRbbmFtZSQ9XCJfcXVhbnRpdHlcIl06Zmlyc3QnKS50cmlnZ2VyKCdmb2N1cycpLnRyaWdnZXIoJ2JsdXInKTtcbiAgICAgICAgICAgIH0sIDMwMCk7XG4gICAgXHR9XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignZm9jdXMnLCAnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKHRoaXMpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuXHRcdCQoJyNkd2ZybV9ndWVzdGNoZWNrb3V0IHNwYW4uZXJyb3InKS5yZW1vdmUoKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2tleWRvd24nLCAnZm9ybSBpbnB1dFtuYW1lXj1cImR3ZnJtX2d1ZXN0Y2hlY2tvdXRfdXNlcm5hbWVfXCJdJykub24oJ2tleWRvd24nLCAnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXScsIGZ1bmN0aW9uIChlKSB7ICAgXHRcbiAgICBcdGlmIChlLndoaWNoID09PSBTaXRlQ29uc3RhbnRzLktleUNvZGVzLkVudGVyKSB7XHRcdFxuICAgIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcdCQoJyNkd2ZybV9ndWVzdGNoZWNrb3V0IHNwYW4uZXJyb3InKS5yZW1vdmUoKTtcbiAgICBcdFx0XG4gICAgXHRcdHZhciAkZm9ybSA9ICQoJ2Zvcm0uZ3Vlc3QtY2hlY2tvdXQnKTtcbiAgICBcdFx0JGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgXHRcdFxuICAgIFx0XHR2YXIgZW1haWwgPSAkKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpLnZhbCgpO1xuICAgIFx0XHR2YXIgaXNFbWFpbFZhbGlkID0gdmFsaWRhdGVFbWFpbChlbWFpbCk7XG4gICAgXHRcdFxuICAgIFx0XHRpZiAoJGZvcm0udmFsaWQoKSAmJiBpc0VtYWlsVmFsaWQgJiYgJCgnI2R3ZnJtX2d1ZXN0Y2hlY2tvdXQgc3Bhbi5lcnJvcicpLmxlbmd0aCA8IDEgKSB7XG4gICAgXHRcdFx0cmVuZGVyR3Vlc3RDaGVja291dChlbWFpbClcbiAgICBcdFx0fSBlbHNlIHtcbiAgICBcdFx0XHRpZiAoJCgnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXS5lcnJvcicpLmxlbmd0aCA9PSAwKSB7XG4gICAgXHRcdFx0XHRpbnZhbGlkYXRlR3Vlc3RDaGVja291dCgpO1xuICAgIFx0XHRcdH1cbiAgICBcdFx0fVxuICAgIFx0fSAgIFx0IFxuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uI2d1ZXN0Q2hlY2tvdXQnKS5vbignY2xpY2snLCAnYnV0dG9uI2d1ZXN0Q2hlY2tvdXQnLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdCQoJyNkd2ZybV9ndWVzdGNoZWNrb3V0IHNwYW4uZXJyb3InKS5yZW1vdmUoKTtcblx0XHRcblx0XHR2YXIgJGZvcm0gPSAkKCdmb3JtLmd1ZXN0LWNoZWNrb3V0Jyk7XG5cdFx0JGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0XG5cdFx0dmFyIGVtYWlsID0gJCgnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXScpLnZhbCgpO1xuXHRcdGlmICgkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2d1ZXN0Y2hlY2tvdXRfdXNlcm5hbWVfXCJdLnZhbGlkJykubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFyIGVtYWlsID0gJCgnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXS52YWxpZCcpLnZhbCgpO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgaXNFbWFpbFZhbGlkID0gdmFsaWRhdGVFbWFpbChlbWFpbCk7XG4gICAgXHRcblx0XHRpZiAoJGZvcm0udmFsaWQoKSAmJiBpc0VtYWlsVmFsaWQgJiYgJCgnI2R3ZnJtX2d1ZXN0Y2hlY2tvdXQgc3Bhbi5lcnJvcicpLmxlbmd0aCA8IDEgKSB7XHRcdFx0XG5cdFx0XHRyZW5kZXJHdWVzdENoZWNrb3V0KGVtYWlsKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCQoJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0uZXJyb3InKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHRpbnZhbGlkYXRlR3Vlc3RDaGVja291dCgpO1xuXHRcdFx0fVxuXHRcdH1cbiAgICB9KTtcbiAgIFxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJy5vcmRlci10b3RhbC1wYXltZW50cyBbcGF5bWVudC1tZXRob2RdIC5yZW1vdmUnKS5vbignY2xpY2snLCAnLm9yZGVyLXRvdGFsLXBheW1lbnRzIFtwYXltZW50LW1ldGhvZF0gLnJlbW92ZScsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50VVVJRCA9ICQoZS5jdXJyZW50VGFyZ2V0KS5jbG9zZXN0KCdbcGF5bWVudC1tZXRob2QnKS5hdHRyKCd1dWlkJyk7XG5cdFxuXHRcdGlmIChwYXltZW50SW5zdHJ1bWVudFVVSUQpIHtcblx0XHRcdHZhciByZXF1ZXN0UGF5bG9hZCA9IHtcblx0XHRcdFx0VVVJRDogcGF5bWVudEluc3RydW1lbnRVVUlEXG5cdFx0XHR9XG5cdFx0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMucmVtb3ZlUGF5bWVudEluc3RydW1lbnQsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdFBheWxvYWQpLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0dXBkYXRlQ2FydCgnZHdmcm1fY2FydF91cGRhdGVDYXJ0Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ0NhcnQuVXBkYXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG4gICAgXHR1cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnLCBkYXRhKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVFbWFpbChlbWFpbCkge1xuXHR2YXIgaXNFbWFpbFZhbGlkID0gdHJ1ZTtcblx0XG5cdGlmIChlbWFpbC5sZW5ndGggPT0gMCl7XG5cdFx0aXNFbWFpbFZhbGlkID0gdHJ1ZTtcblx0fVxuXHRcblx0dmFyIHJlZ2V4RW1haWwgPSAvXig/OlthLXowLTkhIyQlJicqKy89P15fYHt8fX4tXSsoPzpcXC5bYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKSp8XCIoPzpbXFx4MDEtXFx4MDhcXHgwYlxceDBjXFx4MGUtXFx4MWZcXHgyMVxceDIzLVxceDViXFx4NWQtXFx4N2ZdfFxcXFxbXFx4MDEtXFx4MDlcXHgwYlxceDBjXFx4MGUtXFx4N2ZdKSpcIilAKD86KD86W2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP1xcLikrW2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP3xcXFsoPzooPzooMig1WzAtNV18WzAtNF1bMC05XSl8MVswLTldWzAtOV18WzEtOV0/WzAtOV0pKVxcLil7M30oPzooMig1WzAtNV18WzAtNF1bMC05XSl8MVswLTldWzAtOV18WzEtOV0/WzAtOV0pfFthLXowLTktXSpbYS16MC05XTooPzpbXFx4MDEtXFx4MDhcXHgwYlxceDBjXFx4MGUtXFx4MWZcXHgyMS1cXHg1YVxceDUzLVxceDdmXXxcXFxcW1xceDAxLVxceDA5XFx4MGJcXHgwY1xceDBlLVxceDdmXSkrKVxcXSkkLztcblx0aWYgKGVtYWlsLmxlbmd0aCA+IDAgJiYgZW1haWwubWF0Y2gocmVnZXhFbWFpbCkgPT0gbnVsbCkge1xuXHRcdGlzRW1haWxWYWxpZCA9IGZhbHNlO1xuXHRcdGludmFsaWRhdGVHdWVzdENoZWNrb3V0KCk7XG5cdH1cblx0XG5cdHJldHVybiBpc0VtYWlsVmFsaWQ7XG59XG5cbmZ1bmN0aW9uIGludmFsaWRhdGVHdWVzdENoZWNrb3V0KCkge1xuXHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2d1ZXN0Y2hlY2tvdXRfdXNlcm5hbWVfXCJdJykucmVtb3ZlQ2xhc3MoJ3ZhbGlkJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdCQoJy5ndWVzdC1jaGVja291dCAuZmllbGQtd3JhcHBlcicpLmFwcGVuZCgnPHNwYW4gY2xhc3M9XCJlcnJvciBjdXN0b20tZ3Vlc3RjaGVja291dC1lcnJvclwiIHN0eWxlPVwiZGlzcGxheTpibG9jayAhaW1wb3J0YW50O1wiPicgKyBSZXNvdXJjZXMuVkFMSURBVEVfRU1BSUwgKyAnPC9zcGFuPicpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJHdWVzdENoZWNrb3V0KGVtYWlsKSB7XG5cdFxuXHRpZihlbWFpbC5sZW5ndGggPiAwKXtcblx0XHR2YXIgb3B0SW4gPSBmYWxzZTtcblx0XHRcblx0XHRpZihTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKXtcblx0XHRcdHZhciBzaWdudXBFdmVudCA9ICcnO1xuXHRcdFx0XG5cdFx0XHR2YXIgYXV0aF9kYXRhID0ge1xuXHRcdFx0XHRlbWFpbDogZW1haWxcblx0XHRcdH1cblx0XHRcdHZhciBjb250YWN0X2RhdGEgPSB7XG5cdFx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdFx0XHQnYWRkcmVzcyc6IGVtYWlsLFxuXHRcdFx0XHRcdFx0J3N1YnNjcmliZVN0YXR1cyc6ICdub25lJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcdFx0XHRcdCAgICBcblx0XHRcdFx0J3dvcmtmbG93X2NoZWNrb3V0X2FiYW5kb24nOiB0cnVlXG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHR2YXIgZ3Vlc3RQcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHQnZW1haWwnOiBlbWFpbCxcblx0XHRcdFx0J3dvcmtmbG93X2NoZWNrb3V0X2FiYW5kb24nOiB0cnVlXG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHRpZiAoJCgnI2d1ZXN0X2NoZWNrb3V0X29wdGluJykucHJvcChcImNoZWNrZWRcIikpIHtcblx0XHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0XHRlbWFpbDogZW1haWxcblx0XHRcdFx0fVxuXHRcdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdFx0XHRcdCdlbWFpbCc6IHtcblx0XHRcdFx0XHRcdFx0J2FkZHJlc3MnOiBlbWFpbCxcblx0XHRcdFx0XHRcdFx0J3N1YnNjcmliZVN0YXR1cyc6ICdzdWJzY3JpYmVkJ1x0XHRcdFx0ICAgICAgICAgICAgXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcdFx0XHRcdCAgICBcblx0XHRcdFx0XHQnc2lnbnVwX3NvdXJjZSc6ICdjaGVja291dCcsXG5cdFx0XHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZSxcblx0XHRcdFx0XHQnd29ya2Zsb3dfY2hlY2tvdXRfYWJhbmRvbic6IHRydWVcblx0XHRcdFx0fTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHRcdCdzaWdudXBfc291cmNlJzogJ2NoZWNrb3V0Jyxcblx0XHRcdFx0XHQnd2VsY29tZV9zaWdudXAnOiB0cnVlLFxuXHRcdFx0XHRcdCd3b3JrZmxvd19jaGVja291dF9hYmFuZG9uJzogdHJ1ZVxuXHRcdFx0XHR9O1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIHNpZ251cEV2ZW50ID0gWydldmVudCcsICdlbWFpbF9zaWdudXAnLCBwcm9wZXJ0aWVzXTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0UmVxdWVzdEhlbHBlci5WYWxpZGF0ZSgnQ29yZGlhbC1FbWFpbFNpZ251cCcpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxcblx0XHRcdFx0XHRcdFsnZXZlbnQnLCAnZ3Vlc3RfY2hlY2tvdXQnLCBndWVzdFByb3BlcnRpZXNdLFxuXHRcdFx0XHRcdFx0c2lnbnVwRXZlbnRcblx0XHRcdFx0XHRdKTtcblx0XHRcdFx0fVxuXHRcdFx0fSkuY2F0Y2goKTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0dmFyIG9wdEluID0gJCgnI2d1ZXN0X2NoZWNrb3V0X29wdGluJykucHJvcChcImNoZWNrZWRcIik7XG5cdH1cblx0XG5cdCQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLnNldEVtYWlsT25DYXJ0LFxuXHRcdHR5cGU6IFwiZ2V0XCIsXG5cdFx0ZGF0YToge2VtYWlsOiBlbWFpbH0sXG5cdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXHRcdFx0XHRcblx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLm9uZVBhZ2UgKyAoKHdpbmRvdy5pbm5lcldpZHRoIDwgU2l0ZUNvbnN0YW50cy5SZXNwb25zaXZlLldpZHRocy5Nb2JpbGUpID8gJyNhZGRyZXNzaW5mbycgOiAnJyk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRjb25zb2xlLmxvZyh0ZXh0U3RhdHVzLCBlcnJvclRocm93bik7XG5cdFx0fVxuXHR9KTtcblx0XG5cdCQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLnNldEVtYWlsT3B0aW4sXG5cdFx0dHlwZTogXCJnZXRcIixcblx0XHRkYXRhOiB7b3B0SW46IG9wdElufSxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdHZhciBkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cdFx0XHRcdFxuXHRcdFx0aWYgKGRhdGEuc3RhdHVzID09ICdzdWNjZXNzJykge1xuXHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMub25lUGFnZSArICgod2luZG93LmlubmVyV2lkdGggPCBTaXRlQ29uc3RhbnRzLlJlc3BvbnNpdmUuV2lkdGhzLk1vYmlsZSkgPyAnI2FkZHJlc3NpbmZvJyA6ICcnKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcblx0XHRcdGNvbnNvbGUubG9nKHRleHRTdGF0dXMsIGVycm9yVGhyb3duKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB0cmlnZ2VyUmVhY3RXZWJ2aWV3RXZlbnQoKSB7XG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cpIHtcblx0XHR3aW5kb3cuUmVhY3ROYXRpdmVXZWJWaWV3LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHsgYWN0aW9uOiAnY2FydC1yZWZyZXNoJyB9KSk7XG5cdH1cbn1cblxudmFyIHVwZGF0ZUNhcnRCdWZmZXI7XG52YXIgdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyO1xuZnVuY3Rpb24gdXBkYXRlQ2FydCh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdGlmICh1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXIpIHtcblx0XHRmb3IgKHZhciB1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RLZXkgaW4gdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyKSB7XG5cdFx0XHR2YXIgdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0ID0gdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyW3VwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEtleV07XG5cdFx0XHRcblx0XHRcdGlmICh1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3QucmVhZHlTdGF0ZSAhPT0gNCkgeyBcblx0XHRcdFx0dXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0LmFib3J0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlciA9IFtdO1xuXHR1cGRhdGVDYXJ0QnVmZmVyID0gW107XG5cblx0Z2V0Q2FydEh0bWwodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdGlmICghaXNDYXJ0UGFnZSkge1xuXHRcdGdldE9yZGVyU3VtbWFyeUNhbGxvdXRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGdldENhcnRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcbiAgICB2YXIgZm9ybSA9ICQoXCIudXBkYXRlLWNhcnQtYnV0dG9uXCIpLnBhcmVudHMoJ2Zvcm0nKTtcbiAgICB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gPSBudWxsO1xuXG5cdGlmIChmb3JtLmF0dHIoJ2FjdGlvbicpKSB7XG5cdFx0aWYgKGlzQ2FydFBhZ2UgPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRpc0NhcnRQYWdlID0gJCgnLnB0X2NhcnQnKS5sZW5ndGggPiAwO1xuXHRcdH1cblxuXHRcdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0Q2FydEh0bWwnXSA9ICQuYWpheCh7XG5cdCAgICAgICAgdXJsIDogZm9ybS5hdHRyKCdhY3Rpb24nKSxcblx0XHQgICAgdHlwZSA6IFwiUE9TVFwiLFxuXHQgICAgICAgIGRhdGEgOiB0cmlnZ2VyRWxlbWVudE5hbWUgKyAnPScgKyB0cmlnZ2VyRWxlbWVudE5hbWUgKyAnJnNlbGVjdGVkUGF5bWVudE1ldGhvZD0nICsgJCgnaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoKSArICcmZm9ybWF0PWFqYXgnLFxuXHRcdCAgICBzdWNjZXNzIDogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHQgICAgXHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gPSBkYXRhO1xuXHRcdFx0XHRnZXRDYXJ0RGF0YSh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0XHRcdFx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0XHQgICAgfVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGdldE9yZGVyU3VtbWFyeUNhbGxvdXRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcbiAgICB1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10gPSBudWxsO1xuXG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0T3JkZXJTdW1tYXJ5Q2FsbG91dEh0bWwnXSA9ICQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLmdldE9yZGVyU3VtbWFyeUNhbGxvdXRDb250ZW50U2xvdCxcblx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10gPSBkYXRhO1xuXHRcdFx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRDYXJ0RGF0YSh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gPSBudWxsO1xuXG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0Q2FydERhdGEnXSA9ICQuYWpheCh7XG5cdCAgICB1cmwgOiBVcmxzLmdldENhcnREYXRhLFxuXHRcdHR5cGUgOiBcIlBPU1RcIixcblx0XHRkYXRhOiB7XG5cdFx0XHRpc0NhcnQ6IGlzQ2FydFBhZ2Vcblx0XHR9LFxuXHQgICAgc3VjY2VzcyA6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdCAgICBcdCQoJ1toYXMtbG9jYWwtZGVsaXZlcnktc2hpcG1lbnRdJykuYXR0cignaGFzLWxvY2FsLWRlbGl2ZXJ5LXNoaXBtZW50JywgZGF0YS5IYXNMb2NhbERlbGl2ZXJ5U2hpcG1lbnQgfHwgZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLXBoeXNpY2FsLXNoaXBtZW50XScpLmF0dHIoJ2hhcy1waHlzaWNhbC1zaGlwbWVudCcsIGRhdGEuSGFzUGh5c2ljYWxTaGlwbWVudCB8fCBmYWxzZSk7XG5cdFx0XHQkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtd2FyZWhvdXNlLXNoaXBtZW50JywgZGF0YS5IYXNXYXJlaG91c2VTaGlwbWVudCB8fCBmYWxzZSk7XG5cdFx0XHQkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtc2hpcHBpbmctbWV0aG9kcycsIGRhdGEuU2hpcHBpbmdNZXRob2RzID8gZGF0YS5TaGlwcGluZ01ldGhvZHMuam9pbignICcpIDogZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLWdpZnQtY2FyZHNdJykuYXR0cignaGFzLWdpZnQtY2FyZHMnLCBkYXRhLkhhc0dpZnRDYXJkcyB8fCBmYWxzZSk7XG5cdCAgICBcdCQoJ1toYXMtZ2lmdC1jYXJkcy1vbmx5XScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzLW9ubHknLCBkYXRhLkhhc0dpZnRDYXJkc09ubHkgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnRdJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudCcsIChkYXRhLkJvcGlzICYmIGRhdGEuQm9waXMuSGFzU3RvcmVQaWNrdXBTaGlwbWVudCkgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQtb25seV0nKS5hdHRyKCdoYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHknLCAoZGF0YS5Cb3BpcyAmJiBkYXRhLkJvcGlzLkhhc1N0b3JlUGlja3VwU2hpcG1lbnRPbmx5KSB8fCBmYWxzZSk7XG5cblx0XHRcdGlmIChkYXRhLkJvcGlzICYmIGRhdGEuQm9waXMuSGFzU3RvcmVQaWNrdXBTaGlwbWVudE9ubHkpIHtcblx0XHRcdFx0JCgnI2lzU2hpcHBpbmdBZGRyZXNzU2FtZUFzQmlsbGluZ0FkZHJlc3MnKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdFx0fVxuXG5cdCAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnREYXRhLlVwZGF0ZScsIGRhdGEpO1xuXG5cdCAgICBcdHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gPSBkYXRhO1xuXHQgICAgXHRpZiAoZGF0YS5Cb3Bpcykge1xuXHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ0JvcGlzJ10gPSBkYXRhLkJvcGlzO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHRpZiAoIWRhdGEuSXNHbG9iYWxlVmFsaWRPckluYWN0aXZlKSB7XG5cdCAgICBcdFx0JCgnLnNlY3Rpb24tY2hlY2tvdXQnKS5hZGRDbGFzcygnZ2xvYmFsLWUtdmFsaWRhdGlvbi1lcnJvcicpO1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykuZmluZCgnLmNhcnQtZXJyb3JzJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykucmVtb3ZlQ2xhc3MoJ2dsb2JhbC1lLXZhbGlkYXRpb24tZXJyb3InKTtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLmZpbmQoJy5jYXJ0LWVycm9ycycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0ICAgIFx0fVxuXG5cdCAgICBcdGlmICgoIWRhdGEuT3JkZXJUb3RhbCB8fCAhZGF0YS5PcmRlclRvdGFsLmJhbGFuY2VBdmFpbGFibGUpIHx8IChkYXRhLlNoaXBwaW5nUmVzdHJpY3Rpb25zICYmIGRhdGEuU2hpcHBpbmdSZXN0cmljdGlvbnMuU3RhdHVzID09ICdzaGlwcGluZ1Jlc3RyaWN0aW9uc0Vycm9yJykpIHtcblx0XHRcdFx0aWYgKCFpc0NhcnRQYWdlKSB7XG5cdFx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kcy1zZWN0aW9uJykuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoaXNDYXJ0UGFnZSkge1xuXHRcdFx0XHRcdCQoJy5ndWVzdC1jaGVja291dCAuZXJyb3ItZm9ybScpLnJlbW92ZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZHMtc2VjdGlvbicpLnNob3coKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aGFuZGxlT3JkZXJUb3RhbCh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0ICAgIH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU9yZGVyVG90YWwodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHR1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSA9IG51bGw7XG5cdHZhciByZW1vdmVBY3Rpb24gPSAnPGEgY2xhc3M9XCJyZW1vdmVcIj5SZW1vdmU8L2E+Jztcblx0dmFyIHJld2FyZHNQcm9ncmFtID0gJyc7XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0cmV3YXJkc1Byb2dyYW0gPSAnQ2x1YiBDTyc7XG5cdH1cblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHRyZXdhcmRzUHJvZ3JhbSA9ICdTaGVwbGVycyc7XG5cdH1cblx0XG5cdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzLmxlbmd0aCA+IDApIHtcblx0XHR1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSA9ICcnO1xuXHRcblx0XHRmb3IgKHZhciBwYXltZW50SW5zdHJ1bWVudEtleSBpbiB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzKSB7XG5cdFx0XHR2YXIgcGF5bWVudEluc3RydW1lbnQgPSB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzW3BheW1lbnRJbnN0cnVtZW50S2V5XTtcblx0XHRcdHZhciBwYXltZW50SW5zdHJ1bWVudFVVSURBdHRyaWJ1dGUgPSAndXVpZD1cIicgKyBwYXltZW50SW5zdHJ1bWVudC5VVUlEICsgJ1wiJztcblx0XHRcdFxuXHRcdFx0c3dpdGNoIChwYXltZW50SW5zdHJ1bWVudC5wYXltZW50TWV0aG9kLklkKSB7XG5cdFx0XHRcdGNhc2UgUGF5bWVudE1ldGhvZENvbnN0YW50cy5SZXdhcmRzQ3JlZGl0OlxuXHRcdCAgICBcdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gKz0gJzxkaXYgJyArIHBheW1lbnRJbnN0cnVtZW50VVVJREF0dHJpYnV0ZSArICcgcGF5bWVudC1tZXRob2Q9XCInICsgcGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCArICdcIiBhbGxvdy1yZW1vdmU9XCInICsgcGF5bWVudEluc3RydW1lbnQuYWxsb3dSZW1vdmUgKyAnXCI+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cImxhYmVsXCI+PHNwYW4gY2xhc3M9XCJuYW1lXCI+QiBSZXdhcmRlZDwvc3Bhbj4mbmJzcDs8c3BhbiBjbGFzcz1cIm51bWJlclwiPlJld2FyZDwvc3Bhbj48L3NwYW4+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LmFtb3VudERpc3BsYXkgKyAnPC9zcGFuPicgK1xuXHRcdCAgICBcdFx0JzwvZGl2Pic7XG5cdFx0ICAgIFx0YnJlYWs7XG5cdFx0ICAgIFx0XG5cdFx0XHRcdGNhc2UgUGF5bWVudE1ldGhvZENvbnN0YW50cy5Mb3lhbHR5Q3JlZGl0OlxuXHRcdCAgICBcdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gKz0gJzxkaXYgJyArIHBheW1lbnRJbnN0cnVtZW50VVVJREF0dHJpYnV0ZSArICcgcGF5bWVudC1tZXRob2Q9XCInICsgcGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCArICdcIiBhbGxvdy1yZW1vdmU9XCInICsgcGF5bWVudEluc3RydW1lbnQuYWxsb3dSZW1vdmUgKyAnXCI+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cImxhYmVsXCI+PHNwYW4gY2xhc3M9XCJuYW1lXCI+JytyZXdhcmRzUHJvZ3JhbSsnPC9zcGFuPiZuYnNwOzxzcGFuIGNsYXNzPVwibnVtYmVyXCI+UmV3YXJkPC9zcGFuPjwvc3Bhbj4nICtcblx0XHQgICAgXHRcdFx0JzxzcGFuIGNsYXNzPVwidmFsdWVcIj4nICsgcGF5bWVudEluc3RydW1lbnQuYW1vdW50RGlzcGxheSArICc8L3NwYW4+JyArXG5cdFx0ICAgIFx0XHQnPC9kaXY+Jztcblx0XHQgICAgXHRicmVhaztcblx0XHRcdFxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdCAgICBcdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gKz0gJzxkaXYgJyArIHBheW1lbnRJbnN0cnVtZW50VVVJREF0dHJpYnV0ZSArICcgcGF5bWVudC1tZXRob2Q9XCInICsgcGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCArICdcIiBhbGxvdy1yZW1vdmU9XCInICsgcGF5bWVudEluc3RydW1lbnQuYWxsb3dSZW1vdmUgKyAnXCI+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cImxhYmVsXCI+PHNwYW4gY2xhc3M9XCJuYW1lXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuTmFtZSArICc8L3NwYW4+Jm5ic3A7PHNwYW4gY2xhc3M9XCJudW1iZXJcIj4nICsgcGF5bWVudEluc3RydW1lbnQubnVtYmVyICsgJzwvc3Bhbj4nICsgcmVtb3ZlQWN0aW9uICsgJzwvc3Bhbj4nICtcblx0XHQgICAgXHRcdFx0JzxzcGFuIGNsYXNzPVwidmFsdWVcIj4nICsgcGF5bWVudEluc3RydW1lbnQuYW1vdW50RGlzcGxheSArICc8L3NwYW4+JyArXG5cdFx0ICAgIFx0XHQnPC9kaXY+Jztcblx0XHQgICAgXHRicmVhaztcblx0XHQgICAgfVxuXHRcdH1cblx0fSBlbHNlIHtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdHaWZ0Q2FyZC5DbGVhcicpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Jld2FyZHNDcmVkaXQuQ2xlYXInKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdMb3lhbHR5Q3JlZGl0LkNsZWFyJyk7XG5cdH1cblx0XG5cdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA8IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC50b3RhbCkge1xuXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10gPSAnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPkJhbGFuY2UgRHVlPC9zcGFuPicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwidmFsdWVcIj4nICsgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2VEaXNwbGF5ICsgJzwvc3Bhbj4nO1xuXHR9XG5cdFxuXHR1cGRhdGVDYXJ0UmVuZGVyKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVDYXJ0UmVuZGVyKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcblx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnQnXSAmJiAoaXNDYXJ0UGFnZSB8fCAodXBkYXRlQ2FydEJ1ZmZlclsnT3JkZXJTdW1tYXJ5Q2FsbG91dCddICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10pKSkge1xuXHRcdHZhciAkYmFza2V0Q29udGFpbmVySHRtbCA9ICQodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydCddKTtcblx0XG5cdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gJiYgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsKSB7XG5cdFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItdG90YWwtcHJpY2UgLnZhbHVlJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwudG90YWxEaXNwbGF5KTtcblx0ICAgIFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItdG90YWwtcHJpY2UgLnZhbHVlJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwudG90YWxEaXNwbGF5KTtcblx0XHRcblx0XHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFscy10YWJsZScpLmF0dHIoJ3BheW1lbnRzLWFwcGxpZWQnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzLmxlbmd0aCk7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmF0dHIoJ3BheW1lbnRzLWFwcGxpZWQnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwucGF5bWVudEluc3RydW1lbnRzLmxlbmd0aCk7XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFscy10YWJsZScpLnJlbW92ZUF0dHIoJ3BheW1lbnRzLWFwcGxpZWQnKTtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykucmVtb3ZlQXR0cigncGF5bWVudHMtYXBwbGllZCcpO1xuXHQgICAgXHR9XG5cdFx0XG5cdFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItdG90YWxzLXRhYmxlJykuYXR0cignYmFsYW5jZS1kdWUnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSk7XG5cdCAgICBcdCQoJ2JvZHknKS5hdHRyKCdiYWxhbmNlLWR1ZScsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlKTtcblx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hdHRyKCdiYWxhbmNlLWR1ZScsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlKTtcblx0XHRcblx0XHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA+IDApIHtcblx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbnMnKS5zaG93KCk7XG5cdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24tZm9vdGVyW2RhdGEtbWV0aG9kPVwiUGF5UGFsXCJdIGJ1dHRvbicpLmhpZGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZC1vcHRpb25zJykuaGlkZSgpO1xuXHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uLWZvb3RlcltkYXRhLW1ldGhvZD1cIlBheVBhbFwiXSBidXR0b24nKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0XG5cdCAgICBcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddKSB7XHRcblx0ICAgIFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItYmFsYW5jZS1kdWUnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10pO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddKTsgICAgXHRcdFxuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCgnJyk7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSkge1xuXHQgICAgXHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbC1wYXltZW50cycpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10pO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLXRvdGFsLXBheW1lbnRzJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSk7XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItdG90YWwtcGF5bWVudHMnKS5odG1sKCcnKTtcblx0ICAgIFx0fVxuXHRcdH1cblxuXHRcdCQoJy5iYXNrZXQtY29udGFpbmVyJykuaHRtbCgkYmFza2V0Q29udGFpbmVySHRtbCk7XG5cdFx0XG5cdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10pIHtcblx0XHRcdHZhciBvcmRlclRvdGFsRm9yQWZmaXJtID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2U7XG5cdFx0XHRpZiAoIW9yZGVyVG90YWxGb3JBZmZpcm0gJiYgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlKSB7XG5cdFx0XHRcdG9yZGVyVG90YWxGb3JBZmZpcm0gPSB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYWRqdXN0ZWRNZXJjaGFuZGl6ZVRvdGFsUHJpY2U7XG5cdFx0XHR9XG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkgJiYgb3JkZXJUb3RhbEZvckFmZmlybSA+PSB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLkFmZmlybU1pbmltdW1PcmRlclRvdGFsKSB7XG5cdFx0XHRcdCQoJy5hZmZpcm0tcHJvZHVjdC1tb2RhbCcpLmF0dHIoJ2RhdGEtYW1vdW50Jywgb3JkZXJUb3RhbEZvckFmZmlybSAqIDEwMCk7XG5cdFx0XHRcdGFmZmlybS51aS5yZWZyZXNoKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcuYWZmaXJtLXByb2R1Y3QtbW9kYWwnKS5hdHRyKCdkYXRhLWFtb3VudCcsIDUwMDApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICgkKCcuYmFza2V0LWNvbnRhaW5lcicpLmZpbmQoJy5wcm9kdWN0LWF2YWlsYWJpbGl0eS1saXN0IC5ub3QtYXZhaWxhYmxlJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQsICNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0XHRcdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQnKS5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwLTIgbXQtMlwiIHJvbGU9XCJhbGVydFwiIHRhYmluZGV4PVwiMFwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPicgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5Qcm9kdWN0cy5BdmFpbGFiaWxpdHkgKyAnOjwvYj4gJyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLlByb2R1Y3RzLkF2YWlsYWJpbGl0eUV4Y2VlZGVkICsgJzwvZGl2PicpO1xuXHRcdH0gZWxzZSBpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQm9waXMnXSAmJiB1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddLk51bWJlck9mQm9waXNTdG9yZXNJbkNhcnQgPiB1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddLk1heGltdW1OdW1iZXJPZkJvcGlzU3RvcmVzSW5DYXJ0KSB7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCwgI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdFx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCcpLmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+JyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkdlbmVyYWwuQ2FydExpbWl0ICsgJzo8L2I+ICcgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5Cb3Bpcy5NYXhpbXVtU3RvcmVzRXhjZWVkZWQgKyAnPC9kaXY+Jyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50LCAjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHQkKCcjZXJyb3JCb3hPUEMnKS5yZW1vdmUoKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSkge1x0XG5cdFx0XHQkKCcuY2FsbG91dC1vcmRlcnN1bW1hcnknKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSk7XG5cdFx0fVxuXHRcdFxuXHQgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcblx0ICAgICAgICBjYXJ0U3RvcmVJbnZlbnRvcnkuaW5pdCgpO1xuXHQgICAgfVxuXHQgICAgXG5cdCAgICBhY2NvdW50LmluaXRDYXJ0TG9naW4oKTtcblx0ICAgIGNoZWNrQ2hlY2tvdXRBY2Nlc3NpYmlsaXR5KCk7XG5cblx0XHR2YXIgJGNhcnRNaW5pQ2FydEJ1dHRvbiA9ICQoJy5iYW5uZXItY2FydC1ob2xkZXIgLmJ0bi1taW5pY2FydCcpO1xuXHQgICAgaWYgKCRjYXJ0TWluaUNhcnRCdXR0b24ubGVuZ3RoID4gMCkge1xuXHRcdFx0JC5hamF4KHt1cmwgOiBVcmxzLmNhcnRNaW5pQ2FydCwgZGF0YSA6IHtkZXNrdG9wOiAnMSd9LCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHQgICAgICAgICAgICAkKCcuYmFubmVyLWNhcnQtaG9sZGVyJykuaHRtbChkYXRhKTtcblx0ICAgICAgICB9fSk7XG5cdFx0XHRcblx0ICAgIFx0JC5hamF4KHt1cmwgOiBVcmxzLmNhcnRNaW5pQ2FydCwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0ICAgIFx0XHR2YXIgcGFyZW50TWluaUNhcnQgPSAkKFwiLnRvcC1iYW5uZXItaW5uZXItbGlua3MgI21pbmktY2FydFwiKTtcblx0ICAgIFx0XHRcblx0ICAgIFx0XHRpZiAocGFyZW50TWluaUNhcnQubGVuZ3RoID4gMCkge1xuXHQgICAgXHRcdFx0cGFyZW50TWluaUNhcnQuaHRtbChkYXRhKTtcblx0ICAgIFx0XHR9XG5cdCAgICAgICAgfX0pO1xuXHRcdH1cblx0ICAgIFxuICAgICAgICAkLmFqYXgoe3VybDogVXJscy5jYXJ0SXRlbVF1YW50aXR5LCBkYXRhOiB7ZGVza3RvcDogJzEnfSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgXHQkKCcuY29uZmlybWF0aW9uLW1lc3NhZ2UgLml0ZW0tY291bnQnKS5odG1sKGRhdGEpO1xuXHQgICAgICAgIFxuXHQgICAgICAgIHZhciBxdWFudGl0eSA9IHBhcnNlSW50KCQoJy5jb25maXJtYXRpb24tbWVzc2FnZSAuaXRlbS1jb3VudCcpLmZpbmQoJ3NwYW4nKS50ZXh0KCksIDEwKTtcblx0ICAgICAgICBpZiAoIXF1YW50aXR5KSB7XG5cdCAgICAgICAgICAgICQoJy5jaGVja291dC1idXR0b25zLm1vYmlsZS1vbmx5JykuaGlkZSgpO1x0ICAgICAgICAgICAgXG5cdFx0XHR9XG5cdFx0fX0pO1xuXHRcdFxuXHQgICAgXG5cdCAgICBpZiAodHJpZ2dlckVsZW1lbnROYW1lLmluZGV4T2YoJ2RlbGV0ZVByb2R1Y3QnKSA+IC0xKSB7XG5cdCAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ3JlZnJlc2gtcmVxdWlyZWQnKTtcblx0ICAgIH1cblxuXHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5FdmVudFRyaWdnZXJzIHx8IG9wdGlvbnMuRXZlbnRUcmlnZ2Vyc1sndXBkYXRlLXN1bW1hcnknXSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXN1bW1hcnknKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLkV2ZW50VHJpZ2dlcnMgfHwgb3B0aW9ucy5FdmVudFRyaWdnZXJzWyd1cGRhdGUtc2hpcHBpbmcnXSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXNoaXBwaW5nJyk7XG5cdFx0fVxuXHQgICAgXG5cdCAgICAkKCdbbWluaW11bS1jYXJ0LXRvdGFsXSwgW21heGltdW0tY2FydC10b3RhbF0nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdCAgICBcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdCAgICBcdHZhciBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWluaW11bSA9IHBhcnNlRmxvYXQoJHRoaXMuYXR0cignbWluaW11bS1jYXJ0LXRvdGFsJykpO1xuXHQgICAgXHR2YXIgcGF5bWVudE1ldGhvZENhcnRUb3RhbE1heGltdW0gPSBwYXJzZUZsb2F0KCR0aGlzLmF0dHIoJ21heGltdW0tY2FydC10b3RhbCcpKTtcblx0ICAgIFxuXHQgICAgXHR2YXIgaXNDYXJ0VG90YWxNaW5pbXVtVmFsaWQgPSBmYWxzZTtcblx0ICAgIFx0aWYgKGlzTmFOKHBheW1lbnRNZXRob2RDYXJ0VG90YWxNaW5pbXVtKSB8fCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA+PSBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWluaW11bSkge1xuXHQgICAgXHRcdGlzQ2FydFRvdGFsTWluaW11bVZhbGlkID0gdHJ1ZTtcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0dmFyIGlzQ2FydFRvdGFsTWF4aW11bVZhbGlkID0gZmFsc2U7XG5cdCAgICBcdGlmIChpc05hTihwYXltZW50TWV0aG9kQ2FydFRvdGFsTWF4aW11bSkgfHwgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPD0gcGF5bWVudE1ldGhvZENhcnRUb3RhbE1heGltdW0pIHtcblx0ICAgIFx0XHRpc0NhcnRUb3RhbE1heGltdW1WYWxpZCA9IHRydWU7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdGlmIChpc0NhcnRUb3RhbE1pbmltdW1WYWxpZCAmJiBpc0NhcnRUb3RhbE1heGltdW1WYWxpZCkge1xuXHQgICAgXHRcdCR0aGlzLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5hdHRyKCd2YWxpZC1mb3ItYmFsYW5jZS1kdWUnLCAndHJ1ZScpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCR0aGlzLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5hdHRyKCd2YWxpZC1mb3ItYmFsYW5jZS1kdWUnLCAnZmFsc2UnKTtcblx0ICAgIFx0fVxuXHQgICAgfSk7XG5cdFx0XG5cdCAgICBpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXSAmJiAhdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5IYXNQaHlzaWNhbFNoaXBtZW50ICYmICQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0OmNoZWNrZWQnKS52YWwoKSAhPSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikge1xuXHQgICAgXHQkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT1cIicgKyBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lciArICdcIl0nKS5jbGljaygpO1xuXHQgICAgfVxuXHRcdFxuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy5zaGlwcGluZy1tZXRob2QtdG9vbHRpcCcsXG5cdFx0XHR0b29sdGlwQ2xhc3M6ICdzaGlwcGluZy1tZXRob2QtdG9vbHRpcCdcblx0XHR9LCAkKCdbc2hpcHBpbmctbWV0aG9kXScpKTtcblxuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy50b29sdGlwJ1xuXHRcdH0pO1xuXG5cdFx0dHJpZ2dlclJlYWN0V2Vidmlld0V2ZW50KCk7XG5cdFx0dHJpZ2dlclNyRm9jdXMoKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdRdWFudGl0eVN0ZXBwZXIuVGFyZ2V0Rm9jdXMnKTtcblx0ICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlU3VjY2VzcycpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHRyaWdnZXJTckZvY3VzKCkge1xuXHQkKCdbcm9sZT1cImFsZXJ0XCJdOnZpc2libGUnKS5sYXN0KCkuZm9jdXMoKS5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tDaGVja291dEFjY2Vzc2liaWxpdHkoKSB7XG5cdGlmICgkKCcub3JkZXItaXRlbScpLmxlbmd0aCA9PSAwKSB7XG5cdFx0JCgnLnNlY3Rpb24tY2hlY2tvdXQgPiBkaXYnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1mb3JtLCAuc2hpcHBpbmctYWRkcmVzcy1jb250LCAuc2hpcHBpbmctcGF5bWVudC1jb250JykuaGlkZSgpO1xuXHRcdCQoJy5mb3JtLWNoZWNrb3V0LmxvZ2luLWVsZW1lbnQsIC5zZWN0aW9uLWNoZWNrb3V0JykuYWRkQ2xhc3MoJ2VtcHR5LWNhcnQnKTtcblx0fVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gZ2V0IGN1c3RvbWVyIGRhdGFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGl0ZW0gcXVhbnRpdHkgYW5kIElEIGRhdGFcbiAqIEBwYXJhbSB7RWxlbWVudH0gQWN0aW9uIG5hbWUgdG8gYXBwbHkgdG8gZm9ybVxuICogQHJldHVybnMge1Byb21pc2V9XG4gKi9cbnZhciB1cGRhdGVDdXN0b21lckRldGFpbHMgPSBmdW5jdGlvbiAoZm9ybSwgbmFtZSkge1xuICAgIHZhciAkZm9ybSA9ICQoZm9ybSk7XG5cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMub25lUGFnZUxvZ2luKSxcbiAgICAgICAgZGF0YTogJGZvcm0uc2VyaWFsaXplKCkgKyAnJicgKyBuYW1lICsgJz0nICsgbmFtZVxuICAgIH0pKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ha2UgdGhlIEFKQVggcmVxdWVzdCB0byByZXNldCBjdXN0b21lciBwYXNzd29yZFxuICogQHBhcmFtIHtTdHJpbmd9IHJlZ2lzdGVyZWQgY3VzdG9tZXIgZW1haWxcbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgcmVzZXRDdXN0b21lclBhc3N3b3JkID0gZnVuY3Rpb24gKGVtYWlsKSB7XG5cdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5yZXNldE9QQ1Bhc3MpLFxuICAgICAgICBkYXRhOiAnZW1haWw9JysgZW1haWxcbiAgICB9KSk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gcmVzZXQgY3VzdG9tZXIgcGFzc3dvcmRcbiAqIEBwYXJhbSB7U3RyaW5nfSBlcnJvciBtZXNzYWdlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgdG8gYWRkIGVycm9yIGFmdGVyXG4gKiBAcmV0dXJucyB7Vm9pZH1cbiAqL1xudmFyIHNob3dFcnJvciA9IGZ1bmN0aW9uKG1lc3NhZ2UsIHNlbGVjdG9yKXtcblx0dmFyICRlcnJvckNvbnRhaW5lciA9IHNlbGVjdG9yLmNsb3Nlc3QoJ2ZpZWxkLXdyYXBwZXInKS5uZXh0KCcuZXJyb3InKTtcblxuXHRpZiAoISRlcnJvckNvbnRhaW5lci5wcm9wKCdkZWZhdWx0VGV4dCcpIHx8ICRlcnJvckNvbnRhaW5lci50ZXh0KCkgIT0gbWVzc2FnZSkge1xuXHRcdHNlbGVjdG9yLnByb3AoJ2RlZmF1bHRUZXh0JywgJGVycm9yQ29udGFpbmVyLnRleHQoKSk7XG5cdH1cblx0XG5cdCRlcnJvckNvbnRhaW5lci50ZXh0KG1lc3NhZ2UpLnNob3coKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ha2UgdGhlIEFKQVggcmVxdWVzdCB0byByZXNldCBjdXN0b21lciBwYXNzd29yZFxuICogQHBhcmFtIHtTdHJpbmd9IG5vdGlmaWNhdGlvbiB0ZXh0XG4gKiBAcGFyYW0ge0VsZW1lbnR9IHNlbGVjdG9yIHRvIGFwcGx5IG1lc3NhZ2VcbiAqIEBwYXJhbSB7U3RyaW5nfSBub3RpZmljYXRpb24gdHlwZTogZXJyb3Igb3Igc3VjY2Vzc1xuICogQHJldHVybnMge1ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNob3dOb3RpZmljYXRpb24odGV4dCwgc2VsZWN0b3IsIG1zZ1R5cGUpIHtcblx0dmFyICRzZWxlY3RvciA9ICQoc2VsZWN0b3IpO1xuXHRpZiAoJHNlbGVjdG9yLmxlbmd0aCA9PSAwKSB7XG5cdFx0dmFyICRmb3JtID0gJCgnZm9ybS5vcGMtbG9naW4nKTtcblx0XHQkc2VsZWN0b3IgPSAkKCc8c3Bhbi8+JywgeydjbGFzcyc6ICdsb2dpbi1ub3RpZmljYXRpb24nfSkud3JhcCgnPGRpdiBjbGFzcz1cImZvcm1maWVsZCBjbGVhcmZpeCBlcnJvci1ib3hcIj48ZGl2IGNsYXNzPVwiZm9ybS1yb3cgcmVxdWlyZWRcIj48ZGl2IGNsYXNzPVwiZmllbGQtd3JhcHBlclwiPjwvZGl2PjwvZGl2PjwvZGl2PicpO1xuXG5cdFx0JHNlbGVjdG9yLnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpLmluc2VydEJlZm9yZSgnZm9ybS5vcGMtbG9naW4gLmZvcm0tcm93LWJ1dHRvbicpO1xuXHRcdCRzZWxlY3RvciA9ICQoc2VsZWN0b3IpO1xuXHR9XG5cblx0JHNlbGVjdG9yLnJlbW92ZUNsYXNzKCdzdWNjZXNzIGVycm9yJykuYWRkQ2xhc3MobXNnVHlwZSkudGV4dCh0ZXh0KTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ha2UgdGhlIEFKQVggcmVxdWVzdCB0byByZXNldCBjdXN0b21lciBwYXNzd29yZFxuICogQHBhcmFtIHtFbGVtZW50fSBzZWxlY3RvciB0byBjbGVhciBub3RpZmljYXRpb24gdHlwZTogZXJyb3Igb3Igc3VjY2Vzc1xuICogQHJldHVybnMge1ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGNsZWFyTm90aWZpY2F0aW9uKHNlbGVjdG9yKXtcblx0aWYgKHNlbGVjdG9yLmxlbmd0aCkge1xuXHRcdCQoJy5mb3JtZmllbGQuZXJyb3ItYm94JykucmVtb3ZlKCk7XG5cdFx0c2VsZWN0b3IucmVtb3ZlQ2xhc3MoJ3N1Y2Nlc3MgZXJyb3InKTtcblx0fVxufTtcblxuZXhwb3J0cy51cGRhdGVDYXJ0ID0gdXBkYXRlQ2FydDtcbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLmlzQ2FydFBhZ2UpIHtcbiAgICBcdGlzQ2FydFBhZ2UgPSB0cnVlO1xuICAgIH1cbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgY2FydFN0b3JlSW52ZW50b3J5LmluaXQoKTtcbiAgICB9XG5cdEFwcGxlUGF5LmluaXRpYWxpemUob3B0aW9ucyk7XG4gICAgYWNjb3VudC5pbml0Q2FydExvZ2luKCk7XG5cdHF1YW50aXR5U3RlcHBlci5pbml0KHVwZGF0ZUNhcnQpO1xuICAgIHVwZGF0ZUNhcnQoJ2R3ZnJtX2NhcnRfdXBkYXRlQ2FydCcsIG51bGwsIG9wdGlvbnMuaXNDYXJ0UGFnZSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZFRvQ2FydCA9IHJlcXVpcmUoJy4vcHJvZHVjdC9hZGRUb0NhcnQnKTtcbnZhciBxdWFudGl0eVN0ZXBwZXIgPSByZXF1aXJlKCcuLi9xdWFudGl0eVN0ZXBwZXInKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG52YXIgaHRtbCA9IHt9O1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBkYXRhID0ge307XG52YXIgdGVtcGxhdGVzID0ge307XG5cbnZhciB2aWRlbztcbnZhciBzdHJlYW07XG52YXIgYmFyY29kZURldGVjdG9yO1xudmFyIGJhcmNvZGVEZXRlY3RvckludGVydmFsO1xudmFyIGJhcmNvZGVTY2FuSW5wdXRBZGRQcm9kdWN0VGltZXI7XG52YXIgYmFyY29kZVNjYW5JbnB1dEZvY3VzSW50ZXJ2YWw7XG52YXIgcHJvZHVjdFNlYXJjaElucHV0Rm9jdXNJbnRlcnZhbDtcblxudmFyICRwcm9kdWN0RmluZGVyO1xudmFyICRiYXJjb2RlU2Nhbm5lcjtcbnZhciAkYmFyY29kZVNjYW5uZXJJbnB1dENvbnRhaW5lcjtcbnZhciAkYmFyY29kZVNjYW5uZXJJbnB1dDtcbnZhciAkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lcjtcbnZhciAkYmFyY29kZVNjYW5uZXJBZGRCdXR0b247XG52YXIgJGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uVGV4dDtcbnZhciAkYmFyY29kZVNjYW5uZXJTdGFydEJ1dHRvbjtcbnZhciAkYmFyY29kZVNjYW5uZXJTdGFydEJ1dHRvblRleHQ7XG52YXIgJGJhcmNvZGVTY2FubmVyTW9kYWw7XG52YXIgJHByb2R1Y3RTZWFyY2g7XG52YXIgJHByb2R1Y3RTZWFyY2hJbnB1dENvbnRhaW5lcjtcbnZhciAkcHJvZHVjdFNlYXJjaElucHV0O1xudmFyICRwcm9kdWN0U2VhcmNoRXJyb3JDb250YWluZXI7XG52YXIgJHByb2R1Y3RTZWFyY2hTZWFyY2hCdXR0b247XG52YXIgJHByb2R1Y3RTZWFyY2hTZWFyY2hCdXR0b25UZXh0O1xudmFyICRwcm9kdWN0U2VhcmNoUmVzdWx0c0NvbnRhaW5lcjtcbnZhciAkcHJvZHVjdFNlYXJjaFJlc3VsdHM7XG52YXIgJHByb2R1Y3RTZWFyY2hSZXN1bHRzRm9vdGVyO1xudmFyICRwcm9kdWN0U2VhcmNoUmVzdWx0c0xvYWRNb3JlO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnMpIHtcblx0JHByb2R1Y3RGaW5kZXIgPSAkKCcucHJvZHVjdC1maW5kZXInKTtcblx0JGJhcmNvZGVTY2FubmVyID0gJHByb2R1Y3RGaW5kZXIuZmluZCgnLnNlY3Rpb24uc2NhbicpO1xuXHQkYmFyY29kZVNjYW5uZXJJbnB1dENvbnRhaW5lciA9ICRiYXJjb2RlU2Nhbm5lci5maW5kKCcuaW5wdXQnKTtcblx0JGJhcmNvZGVTY2FubmVySW5wdXQgPSAkYmFyY29kZVNjYW5uZXJJbnB1dENvbnRhaW5lci5maW5kKCdpbnB1dCcpO1xuXHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lciA9ICRiYXJjb2RlU2Nhbm5lci5maW5kKCcuZXJyb3InKTtcblx0JGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uID0gJGJhcmNvZGVTY2FubmVyLmZpbmQoJy5hY3Rpb24uYWRkJyk7XG5cdCRiYXJjb2RlU2Nhbm5lckFkZEJ1dHRvblRleHQgPSAkYmFyY29kZVNjYW5uZXJBZGRCdXR0b24uZmluZCgnc3BhbicpO1xuXHQkYmFyY29kZVNjYW5uZXJTdGFydEJ1dHRvbiA9ICRiYXJjb2RlU2Nhbm5lci5maW5kKCcuYWN0aW9uLnN0YXJ0Jyk7XG5cdCRiYXJjb2RlU2Nhbm5lclN0YXJ0QnV0dG9uVGV4dCA9ICRiYXJjb2RlU2Nhbm5lclN0YXJ0QnV0dG9uLmZpbmQoJ3NwYW4nKTtcblx0JGJhcmNvZGVTY2FubmVyTW9kYWwgPSAkYmFyY29kZVNjYW5uZXIuZmluZCgnLm1vZGFsJyk7XG5cdCRwcm9kdWN0U2VhcmNoID0gJHByb2R1Y3RGaW5kZXIuZmluZCgnLnNlY3Rpb24uc2VhcmNoJyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIgPSAkcHJvZHVjdFNlYXJjaC5maW5kKCcuaW5wdXQnKTtcblx0JHByb2R1Y3RTZWFyY2hJbnB1dCA9ICRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIuZmluZCgnaW5wdXQnKTtcblx0JHByb2R1Y3RTZWFyY2hFcnJvckNvbnRhaW5lciA9ICRwcm9kdWN0U2VhcmNoLmZpbmQoJy5lcnJvcicpO1xuXHQkcHJvZHVjdFNlYXJjaFNlYXJjaEJ1dHRvbiA9ICRwcm9kdWN0U2VhcmNoLmZpbmQoJy5hY3Rpb24uc2VhcmNoJyk7XG5cdCRwcm9kdWN0U2VhcmNoU2VhcmNoQnV0dG9uVGV4dCA9ICRwcm9kdWN0U2VhcmNoU2VhcmNoQnV0dG9uLmZpbmQoJ3NwYW4nKTtcblx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzQ29udGFpbmVyID0gJHByb2R1Y3RTZWFyY2guZmluZCgnLnJlc3VsdHMtY29udGFpbmVyJyk7XG5cdCRwcm9kdWN0U2VhcmNoUmVzdWx0cyA9ICRwcm9kdWN0U2VhcmNoUmVzdWx0c0NvbnRhaW5lci5maW5kKCcucmVzdWx0cycpO1xuXHQkcHJvZHVjdFNlYXJjaFJlc3VsdHNGb290ZXIgPSAkcHJvZHVjdFNlYXJjaFJlc3VsdHNDb250YWluZXIuZmluZCgnZm9vdGVyJyk7XG5cdCRwcm9kdWN0U2VhcmNoUmVzdWx0c0xvYWRNb3JlID0gJHByb2R1Y3RTZWFyY2hSZXN1bHRzQ29udGFpbmVyLmZpbmQoJy5sb2FkLW1vcmUnKTtcblxuXHRpZiAoKCdCYXJjb2RlRGV0ZWN0b3InIGluIHdpbmRvdykpIHtcblx0XHQkYmFyY29kZVNjYW5uZXIuYWRkQ2xhc3MoJ2JhcmNvZGUtZGV0ZWN0b3InKTtcblx0fVxuXG5cdGRhdGFbJ1Byb2R1Y3RTZWFyY2hQYWdlU2l6ZSddID0gNTtcblxuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9ucyddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHR0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yQXR0cmlidXRlR3VpZGUnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtYXR0cmlidXRlLWd1aWRlJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93biddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1kcm9wZG93bicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3ItZHJvcGRvd24tb3B0aW9uJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvblNlbGVjdGVkJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLWRyb3Bkb3duLW9wdGlvbi1zZWxlY3RlZCcpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLXN3YXRjaCcpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoT3B0aW9uJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLXN3YXRjaC1vcHRpb24nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaE9wdGlvblVuc2VsZWN0YWJsZSddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1zd2F0Y2gtb3B0aW9uLXVuc2VsZWN0YWJsZScpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblxuXHQvLyAkKGRvY3VtZW50KS5vZmYoJ2tleXVwLkJhcmNvZGVTY2FubmVySW5wdXQnKS5vbigna2V5dXAuQmFyY29kZVNjYW5uZXJJbnB1dCcsICcuaW5wdXQnLCBmdW5jdGlvbihldmVudCkge1xuXHQvLyBcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cblx0Ly8gXHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5odG1sKCcnKTtcblx0Ly8gXHRpZiAoYmFyY29kZVNjYW5JbnB1dEFkZFByb2R1Y3RUaW1lcikge1xuXHQvLyBcdFx0Y2xlYXJUaW1lb3V0KGJhcmNvZGVTY2FuSW5wdXRBZGRQcm9kdWN0VGltZXIpO1xuXHQvLyBcdH1cblxuXHQvLyBcdGJhcmNvZGVTY2FuSW5wdXRBZGRQcm9kdWN0VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHQvLyBcdFx0YWRkUHJvZHVjdFdpdGhVcGMoJHRoaXMudmFsKCkpO1xuXHQvLyBcdH0sIDI1MCk7XG5cdC8vIH0pO1xuXG5cdCRwcm9kdWN0RmluZGVyLm9mZignY2xpY2suQWRkJykub24oJ2NsaWNrLkFkZCcsICcuYWN0aW9uLmFkZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRhZGRQcm9kdWN0V2l0aFVwYygkYmFyY29kZVNjYW5uZXJJbnB1dC52YWwoKSk7XG5cdH0pO1xuXG5cdCRwcm9kdWN0RmluZGVyLm9mZignY2xpY2suT3B0aW9uc1RvZ2dsZScpLm9uKCdjbGljay5PcHRpb25zVG9nZ2xlJywgJy5hY3Rpb24ub3B0aW9ucycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0JCh0aGlzKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdH0pO1xuXG5cdCRwcm9kdWN0RmluZGVyLm9mZignY2xpY2suTW9kZVNldCcpLm9uKCdjbGljay5Nb2RlU2V0JywgJy5vcHRpb25zIFtzZXQtbW9kZV0nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdCRiYXJjb2RlU2Nhbm5lckVycm9yQ29udGFpbmVyLmh0bWwoJycpO1xuXHRcdCRwcm9kdWN0U2VhcmNoRXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG5cdFx0JCgnLnByb2R1Y3QtZmluZGVyJykuYXR0cignbW9kZScsICQodGhpcykuYXR0cignc2V0LW1vZGUnKSk7XG5cdFx0JCgnLmFjdGlvbi5vcHRpb25zJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLk9wdGlvbnNDbG9zZScpLm9uKCdjbGljay5PcHRpb25zQ2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGFyZ2V0ID0gJChldmVudC50YXJnZXQpO1xuXHRcdGlmICghJHRhcmdldC5oYXNDbGFzcygnb3B0aW9ucycpICYmICR0YXJnZXQuY2xvc2VzdCgnLm9wdGlvbnMnKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0JCgnLmFjdGlvbi5vcHRpb25zJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH1cblx0fSk7XG5cblx0JGJhcmNvZGVTY2FubmVyLm9mZignY2xpY2suS2V5Ym9hcmRUb2dnbGUnKS5vbignY2xpY2suS2V5Ym9hcmRUb2dnbGUnLCAnLm9wdGlvbnMgLmtleWJvYXJkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoJCh0aGlzKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdCQodGhpcykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXQuYXR0cignaW5wdXRtb2RlJywgJ25vbmUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCh0aGlzKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkYmFyY29kZVNjYW5uZXJJbnB1dC5hdHRyKCdpbnB1dG1vZGUnLCAkYmFyY29kZVNjYW5uZXJJbnB1dC5hdHRyKCd0eXBlJykpO1xuXHRcdH1cblx0XHQkKCcuYWN0aW9uLm9wdGlvbnMnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdH0pO1xuXG5cdCRiYXJjb2RlU2Nhbm5lci5vZmYoJ2NsaWNrLkJhcmNvZGVTY2FubmVyU3RhcnQnKS5vbignY2xpY2suQmFyY29kZVNjYW5uZXJTdGFydCcsICcuYWN0aW9uLnN0YXJ0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoISgnQmFyY29kZURldGVjdG9yJyBpbiB3aW5kb3cpKSB7XG5cdFx0XHRhbGVydCgnQmFyY29kZSBEZXRlY3RvciBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgYnJvd3Nlci4nKTtcbiAgXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcuc2VjdGlvbi5zY2FuJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXG5cdFx0XHRpZiAoIWJhcmNvZGVEZXRlY3Rvcikge1xuXHRcdFx0XHRiYXJjb2RlRGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKCk7XG5cdFx0XHR9XG5cblx0XHRcdHZpZGVvID0gJGJhcmNvZGVTY2FubmVyTW9kYWwuZmluZCgndmlkZW8nKVswXTtcblx0XHRcdHZpZGVvLnNldEF0dHJpYnV0ZSgncGxheXNpbmxpbmUnLCAnJyk7XG5cdFx0XHR2aWRlby5zZXRBdHRyaWJ1dGUoJ2F1dG9wbGF5JywgJycpO1xuXHRcdFx0dmlkZW8uc2V0QXR0cmlidXRlKCdtdXRlZCcsICcnKTtcblx0XHRcdHZpZGVvLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuXHRcdFx0dmlkZW8uc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuXG5cdFx0XHR2YXIgY29uc3RyYWludHMgPSB7XG5cdFx0XHRcdGF1ZGlvOiBmYWxzZSxcblx0XHRcdFx0dmlkZW86IHtcblx0XHRcdFx0XHRmYWNpbmdNb2RlOiAnZW52aXJvbm1lbnQnXG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0XHRcblx0XHRcdG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKS50aGVuKGZ1bmN0aW9uIHN1Y2Nlc3MobWVkaWFTdHJlYW0pIHtcblx0XHRcdFx0c3RyZWFtID0gbWVkaWFTdHJlYW07XG5cdFx0XHRcdHZpZGVvLnNyY09iamVjdCA9IHN0cmVhbTtcblx0XHRcdH0pO1xuXG5cdFx0XHR2aWRlby5vbmxvYWRlZG1ldGFkYXRhID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0YmFyY29kZURldGVjdG9ySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChkZXRlY3RCYXJjb2RlLCA1MDApO1xuXHRcdFx0fTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQmFyY29kZVNjYW5uZXJTdG9wJykub24oJ2NsaWNrLkJhcmNvZGVTY2FubmVyU3RvcCcsICcubW9kYWwgLmNsb3NlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRjbG9zZUJhcmNvZGVTY2FubmVyKCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZigncGFzdGUuVVBDJykub24oJ3Bhc3RlLlVQQycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCEkYmFyY29kZVNjYW5uZXJJbnB1dC5pcyhcIjpmb2N1c1wiKSAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgnLnByb2R1Y3QtZmluZGVyJykubGVuZ3RoID4gMCkge1xuXHRcdFx0Z2V0Q2xpcGJvYXJkVmFsdWUoZXZlbnQsIHRoaXMsIGZ1bmN0aW9uKHVwYykge1xuXHRcdFx0XHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5odG1sKCcnKTtcblx0XHRcdFx0YWRkUHJvZHVjdFdpdGhVcGModXBjKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2hJbnB1dC5vZmYoJ2tleXVwLlByb2R1Y3RTZWFyY2hDaGFuZ2UnKS5vbigna2V5dXAuUHJvZHVjdFNlYXJjaENoYW5nZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dXBkYXRlUHJvZHVjdFNlYXJjaEFjdGlvbigpO1xuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NsaWNrLlByb2R1Y3RTZWFyY2hTdGFydCcpLm9uKCdjbGljay5Qcm9kdWN0U2VhcmNoU3RhcnQnLCAnLmFjdGlvbi5zZWFyY2gnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyIHF1ZXJ5ID0gJHByb2R1Y3RTZWFyY2hJbnB1dC52YWwoKTtcblx0XHRpZiAocXVlcnkpIHtcblx0XHRcdGlmICgkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ2FjdGlvbicpID09ICdzZWFyY2gnKSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VhcmNoUmVzdWx0cy5odG1sKCcnKTtcblx0XHRcdFx0JHByb2R1Y3RTZWFyY2gucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHRkYXRhWydQcm9kdWN0U2VhcmNoUGFnZSddID0gMTtcblx0XHRcdFx0c2VhcmNoUHJvZHVjdHNXaXRoUXVlcnkocXVlcnkpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVzZXRQcm9kdWN0U2VhcmNoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NsaWNrLlByb2R1Y3RTZWFyY2hMb2FkTW9yZScpLm9uKCdjbGljay5Qcm9kdWN0U2VhcmNoTG9hZE1vcmUnLCAnLmxvYWQtbW9yZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIHF1ZXJ5ID0gJHByb2R1Y3RTZWFyY2hJbnB1dC52YWwoKTtcblx0XHRpZiAocXVlcnkpIHtcblx0XHRcdGRhdGFbJ1Byb2R1Y3RTZWFyY2hQYWdlJ10gKz0gMTtcblx0XHRcdHNlYXJjaFByb2R1Y3RzV2l0aFF1ZXJ5KHF1ZXJ5KTtcblx0XHR9XG5cdH0pO1xuXG5cdCRwcm9kdWN0U2VhcmNoLm9mZignY2xpY2suUHJvZHVjdFNlYXJjaFByb2R1Y3RTZWxlY3QnKS5vbignY2xpY2suUHJvZHVjdFNlYXJjaFByb2R1Y3RTZWxlY3QnLCAnLmdyaWQtdGlsZSAucHJvZHVjdC10aWxlIGEnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkZ3JpZFRpbGUgPSAkdGhpcy5jbG9zZXN0KCcuZ3JpZC10aWxlJyk7XG5cdFx0dmFyICRwcm9kdWN0VGlsZSA9ICR0aGlzLmNsb3Nlc3QoJy5wcm9kdWN0LXRpbGUnKTtcblx0XHRpZiAoJGdyaWRUaWxlLmZpbmQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkZ3JpZFRpbGUuZmluZCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLnJlbW92ZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRnZXRTdHlsZXNGb3JQcm9kdWN0KCRwcm9kdWN0VGlsZS5kYXRhKCdpdGVtaWQnKSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NoYW5nZS5Qcm9kdWN0U2VhcmNoQXR0cmlidXRlU2VsZWN0Jykub24oJ2NoYW5nZS5Qcm9kdWN0U2VhcmNoQXR0cmlidXRlU2VsZWN0JywgJy5ncmlkLXRpbGUgLnByb2R1Y3QtdmFyaWF0aW9ucyBzZWxlY3QnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkcHJvZHVjdFRpbGUgPSAkKHRoaXMpLmNsb3Nlc3QoJy5ncmlkLXRpbGUnKS5maW5kKCcucHJvZHVjdC10aWxlJyk7XG5cdFx0Z2V0U3R5bGVzRm9yUHJvZHVjdCgkcHJvZHVjdFRpbGUuZGF0YSgnaXRlbWlkJykpO1xuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NsaWNrLlByb2R1Y3RTZWFyY2hQcm9kdWN0QWRkJykub24oJ2NsaWNrLlByb2R1Y3RTZWFyY2hQcm9kdWN0QWRkJywgJy5ncmlkLXRpbGUgLnByb2R1Y3QtdmFyaWF0aW9ucyAuYnRuLmFkZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRpZiAoJHRoaXMuYXR0cigncGlkJykpIHtcblx0XHRcdGFkZFByb2R1Y3RXaXRoUHJvZHVjdElkKCR0aGlzLmF0dHIoJ3BpZCcpLCAkdGhpcyk7XG5cdFx0fVxuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NsaWNrLlByb2R1Y3RTZWFyY2hDbG9zZScpLm9uKCdjbGljay5Qcm9kdWN0U2VhcmNoQ2xvc2UnLCAnLnJlc3VsdHMtY29udGFpbmVyIC5jbG9zZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdwcm9kdWN0LXNlYXJjaCcpO1xuXHR9KTtcblxuXHRpZiAoIW9wdGlvbnMgfHwgb3B0aW9ucy5TdG9yZVVJVmVyc2lvbiAhPSAnMjAyNFJlZGVzaWduJykge1xuXHRcdGJhcmNvZGVTY2FuSW5wdXRGb2N1c0ludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoISRiYXJjb2RlU2Nhbm5lcklucHV0LmlzKCc6dmlzaWJsZTpmb2N1cycpICYmICRiYXJjb2RlU2Nhbm5lci5maW5kKCc6Zm9jdXMnKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHQkYmFyY29kZVNjYW5uZXJJbnB1dC5mb2N1cygpO1xuXHRcdFx0fVxuXHRcdH0sIDUwMCk7XG5cdFxuXHRcdHByb2R1Y3RTZWFyY2hJbnB1dEZvY3VzSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcblx0XHRcdGlmICghJHByb2R1Y3RTZWFyY2hJbnB1dC5pcygnOnZpc2libGU6Zm9jdXMnKSAmJiAhJHByb2R1Y3RTZWFyY2guaGFzQ2xhc3MoJ2FjdGl2ZScpICYmICRwcm9kdWN0U2VhcmNoLmZpbmQoJzpmb2N1cycpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VhcmNoSW5wdXQuZm9jdXMoKTtcblx0XHRcdH1cblx0XHR9LCA1MDApO1xuXG5cdFx0JChkb2N1bWVudCkub2ZmKCdjbGljay5DaGVja291dCcpLm9uKCdjbGljay5DaGVja291dCcsICcuY2hlY2tvdXQgLmJ0bi5idG4tY2hlY2tvdXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdCQodGhpcykubG9hZGluZyh7XG5cdFx0XHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHRxdWFudGl0eVN0ZXBwZXIuaW5pdChudWxsLCByZW5kZXJDYXJ0KTtcblx0XHRhZGRUb0NhcnQoKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVQcm9kdWN0U2VhcmNoQWN0aW9uKCkge1xuXHR2YXIgcHJvZHVjdFNlYXJjaElucHV0VmFsdWUgPSAkcHJvZHVjdFNlYXJjaElucHV0LnZhbCgpO1xuXHRpZiAocHJvZHVjdFNlYXJjaElucHV0VmFsdWUpIHtcblx0XHRwcm9kdWN0U2VhcmNoSW5wdXRWYWx1ZSA9IHByb2R1Y3RTZWFyY2hJbnB1dFZhbHVlLnRvTG93ZXJDYXNlKCk7XG5cdH1cblx0dmFyIHByb2R1Y3RTZWFyY2hRdWVyeVZhbHVlID0gJHByb2R1Y3RTZWFyY2hJbnB1dENvbnRhaW5lci5hdHRyKCdxdWVyeScpO1xuXHRpZiAocHJvZHVjdFNlYXJjaFF1ZXJ5VmFsdWUpIHtcblx0XHRwcm9kdWN0U2VhcmNoUXVlcnlWYWx1ZSA9IHByb2R1Y3RTZWFyY2hRdWVyeVZhbHVlLnRvTG93ZXJDYXNlKCk7XG5cdH1cblxuXHRpZiAocHJvZHVjdFNlYXJjaElucHV0VmFsdWUgJiYgcHJvZHVjdFNlYXJjaFF1ZXJ5VmFsdWUgJiYgcHJvZHVjdFNlYXJjaElucHV0VmFsdWUgPT0gcHJvZHVjdFNlYXJjaFF1ZXJ5VmFsdWUpIHtcblx0XHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ2FjdGlvbicsICdyZXNldCcpO1xuXHR9IGVsc2Uge1xuXHRcdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIuYXR0cignYWN0aW9uJywgJ3NlYXJjaCcpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHNlYXJjaFByb2R1Y3RzV2l0aFF1ZXJ5KHF1ZXJ5KSB7XG5cdCRwcm9kdWN0U2VhcmNoRXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIuYXR0cigncXVlcnknLCBxdWVyeSk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRJc0xhYmVsU2hvd246IGZhbHNlXG5cdH0pO1xuXHQkcHJvZHVjdFNlYXJjaFNlYXJjaEJ1dHRvbi5sb2FkaW5nKHtcblx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHR9KTtcblx0aWYgKCRwcm9kdWN0U2VhcmNoUmVzdWx0c0xvYWRNb3JlLmlzKCc6dmlzaWJsZScpKSB7XG5cdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzTG9hZE1vcmUubG9hZGluZyh7XG5cdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0fSk7XG5cdH1cblx0JHByb2R1Y3RTZWFyY2hJbnB1dC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXG5cdCQuYWpheCh7XG5cdFx0dHlwZTogJ0dFVCcsXG5cdFx0dXJsOiBVcmxzLlNlYXJjaC5TaG93LFxuXHRcdGRhdGE6IHtcblx0XHRcdGZvcm1hdDogJ2FqYXgnLFxuXHRcdFx0cTogcXVlcnksXG5cdFx0XHQvLyBwcmVmbjE6ICdhdmFpbGFibGVTdG9yZXMnLFxuXHRcdFx0Ly8gcHJlZnYxOiBvcHRpb25zLkFnZW50U3RvcmVJRCxcblx0XHRcdHN0YXJ0OiBwYXJzZUludCgoZGF0YVsnUHJvZHVjdFNlYXJjaFBhZ2UnXSAtIDEpICogZGF0YVsnUHJvZHVjdFNlYXJjaFBhZ2VTaXplJ10sIDEwKSxcblx0XHRcdHN6OiBkYXRhWydQcm9kdWN0U2VhcmNoUGFnZVNpemUnXVxuXHRcdH0sXG5cdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdHZhciAkaHRtbCA9ICQocmVzcG9uc2UpO1xuXHRcdFx0dmFyICRwcm9kdWN0R3JpZCA9ICRodG1sLmZpbmQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zJyk7XG5cdFx0XHR2YXIgJHBhZ2luYXRpb24gPSAkaHRtbC5maW5kKCcuc2VhcmNoLXJlc3VsdC1vcHRpb25zIC5wYWdpbmF0aW9uW2NvdW50XScpLmZpcnN0KCk7XG5cdFx0XHR2YXIgcHJvZHVjdFRpbGVDb3VudCA9ICRwcm9kdWN0R3JpZC5maW5kKCcuZ3JpZC10aWxlJykubGVuZ3RoICsgJCgnLnNlY3Rpb24uc2VhcmNoIC5yZXN1bHRzLWNvbnRhaW5lcicpLmZpbmQoJy5ncmlkLXRpbGUnKS5sZW5ndGg7XG5cdFx0XHR2YXIgcHJvZHVjdFRvdGFsQ291bnQgPSAwO1xuXHRcdFx0aWYgKCRwYWdpbmF0aW9uLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0cHJvZHVjdFRvdGFsQ291bnQgPSBwYXJzZUludCgkaHRtbC5maW5kKCcuc2VhcmNoLXJlc3VsdC1vcHRpb25zIC5wYWdpbmF0aW9uW2NvdW50XScpLmZpcnN0KCkuYXR0cignY291bnQnKS5yZXBsYWNlKC9cXEQvZywgJycpLCAxMCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChwcm9kdWN0VGlsZUNvdW50ID4gMCkge1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHMuYXBwZW5kKCRwcm9kdWN0R3JpZC5odG1sKCkpO1xuXHRcdFx0XHRpZiAocHJvZHVjdFRpbGVDb3VudCA8IHByb2R1Y3RUb3RhbENvdW50KSB7XG5cdFx0XHRcdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzRm9vdGVyLnNob3coKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHNGb290ZXIuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHMuYXBwZW5kKCQoJzxsaSBjbGFzcz1cIm5vLXJlc3VsdHNcIj5ObyBwcm9kdWN0cyBmb3VuZCBmb3IgeW91ciBzZWFyY2guPC9saT4nKSk7XG5cdFx0XHRcdCRwcm9kdWN0U2VhcmNoUmVzdWx0c0Zvb3Rlci5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0XHQkcHJvZHVjdFNlYXJjaC5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cdFx0XHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ3VwYycsICcnKTtcblx0XHRcdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0JHByb2R1Y3RTZWFyY2hTZWFyY2hCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0aWYgKCRwcm9kdWN0U2VhcmNoUmVzdWx0c0xvYWRNb3JlLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHNMb2FkTW9yZS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0XHQkcHJvZHVjdFNlYXJjaElucHV0LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHR1cGRhdGVQcm9kdWN0U2VhcmNoQWN0aW9uKCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZ2V0U3R5bGVzRm9yUHJvZHVjdChwcm9kdWN0SWQpIHtcblx0dmFyICRwcm9kdWN0VGlsZSA9ICRwcm9kdWN0U2VhcmNoUmVzdWx0cy5maW5kKCcucHJvZHVjdC10aWxlW2RhdGEtaXRlbWlkPVwiJyArIHByb2R1Y3RJZCArICdcIl0nKTtcblxuXHRpZiAoJHByb2R1Y3RUaWxlLmxlbmd0aCA+IDApIHtcblx0XHR2YXIgJGdyaWRUaWxlID0gJHByb2R1Y3RUaWxlLmNsb3Nlc3QoJy5ncmlkLXRpbGUnKTtcblxuXHRcdGlmICgkZ3JpZFRpbGUubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFyIGlzRmlyc3RMb2FkID0gZmFsc2U7XG5cdFx0XHR2YXIgJHByb2R1Y3RWYXJpYXRpb25zO1xuXHRcdFx0aWYgKCRncmlkVGlsZS5maW5kKCcucHJvZHVjdC12YXJpYXRpb25zJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkcHJvZHVjdFZhcmlhdGlvbnMgPSAkZ3JpZFRpbGUuZmluZCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aXNGaXJzdExvYWQgPSB0cnVlO1xuXHRcdFx0XHQkcHJvZHVjdFZhcmlhdGlvbnMgPSAkZ3JpZFRpbGUuYXBwZW5kKCc8ZGl2IGNsYXNzPVwicHJvZHVjdC12YXJpYXRpb25zXCI+PC9kaXY+JykuZmluZCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpO1xuXHRcdFx0fVxuXHRcdFx0JHByb2R1Y3RWYXJpYXRpb25zLmxvYWRpbmcoe1xuXHRcdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0XHRcdH0pO1xuXHRcdFx0aWYgKCRncmlkVGlsZS5maW5kKCcuYnRuLmFkZCcpLmlzKCc6dmlzaWJsZScpKSB7XG5cdFx0XHRcdCRncmlkVGlsZS5maW5kKCcuYnRuLmFkZCcpLmxvYWRpbmcoe1xuXHRcdFx0XHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0XHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0ZGF0YVsnYXR0cmlidXRlR3VpZGVzJ10gPSB7fTtcblxuXHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdHBpZDogJHByb2R1Y3RUaWxlLmRhdGEoJ2l0ZW1pZCcpXG5cdFx0XHR9XG5cblx0XHRcdGlmICghaXNGaXJzdExvYWQpIHtcblx0XHRcdFx0dmFyICRwcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlc1NlbGVjdGVkID0gJHByb2R1Y3RWYXJpYXRpb25zLmZpbmQoJ1thdHRyaWJ1dGVdIG9wdGlvbi5zZWxlY3RhYmxlOmNoZWNrZWQnKTtcblx0XHRcdFx0JHByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGVzU2VsZWN0ZWQuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHRcdHZhciBwcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlSWQgPSAkdGhpcy5jbG9zZXN0KCdbYXR0cmlidXRlXScpLmF0dHIoJ2F0dHJpYnV0ZScpO1xuXHRcdFx0XHRcdHZhciBwcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlVmFsdWUgPSAkdGhpcy52YWwoKTtcblx0XHRcdFx0XHRwYXlsb2FkWydkd3Zhcl8nICsgcGF5bG9hZC5waWQgKyAnXycgKyBwcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlSWRdID0gcHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZVZhbHVlO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0bWV0aG9kOiAncG9zdCcsXG5cdFx0XHRcdHVybDogVXJscy5nZXRWYXJpYXRpb25BdHRyaWJ1dGVzLFxuXHRcdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9ycyddID0gJyc7XG5cdFx0XHRcdFx0Zm9yICh2YXIgdmFyaWF0aW9uIGluIHJlc3BvbnNlLnZhcmlhdGlvbnMpIHtcblx0XHRcdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhID0gcmVzcG9uc2UudmFyaWF0aW9uc1t2YXJpYXRpb25dO1xuXHRcdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkID0gbnVsbDtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ10gPSAnJztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRmb3IgKHZhciB2YXJpYXRpb25WYWx1ZSBpbiB2YXJpYXRpb25EYXRhLnZhbHVlcykge1xuXHRcdFx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YVZhbHVlID0gdmFyaWF0aW9uRGF0YS52YWx1ZXNbdmFyaWF0aW9uVmFsdWVdO1xuXHRcdFx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGU7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YVZhbHVlUGF5bG9hZCA9IHtcblx0XHRcdFx0XHRcdFx0XHRhdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5hdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHRcdFx0dmFsdWVJZDogdmFyaWF0aW9uRGF0YVZhbHVlLnZhbHVlSWQsXG5cdFx0XHRcdFx0XHRcdFx0dmFsdWU6IHZhcmlhdGlvbkRhdGFWYWx1ZS52YWx1ZSxcblx0XHRcdFx0XHRcdFx0XHR0aXRsZTogdmFyaWF0aW9uRGF0YVZhbHVlLnRpdGxlLFxuXHRcdFx0XHRcdFx0XHRcdHRleHQ6IHZhcmlhdGlvbkRhdGFWYWx1ZS50ZXh0LFxuXHRcdFx0XHRcdFx0XHRcdHN0b2NrOiB2YXJpYXRpb25EYXRhVmFsdWUuc3RvY2ssXG5cdFx0XHRcdFx0XHRcdFx0c2hpcHBpbmc6IHZhcmlhdGlvbkRhdGFWYWx1ZS5zaGlwcGluZyxcblx0XHRcdFx0XHRcdFx0XHRpc1NhbWVEYXlTaGlwcGluZ1dpbmRvdzogdmFyaWF0aW9uRGF0YVZhbHVlLmlzU2FtZURheVNoaXBwaW5nV2luZG93LFxuXHRcdFx0XHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZTogdmFyaWF0aW9uRGF0YVZhbHVlLnF1YW50aXR5U291cmNlVHlwZSxcblx0XHRcdFx0XHRcdFx0XHRocmVmOiB2YXJpYXRpb25EYXRhVmFsdWUuaHJlZixcblx0XHRcdFx0XHRcdFx0XHRzZWxlY3RhYmxlOiB2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0YWJsZSA/ICdzZWxlY3RhYmxlJyA6ICd1bnNlbGVjdGFibGUnLFxuXHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkOiAhaXNGaXJzdExvYWQgJiYgdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGVkID8gJ3NlbGVjdGVkJyA6ICcnLFxuXHRcdFx0XHRcdFx0XHRcdHN3YXRjaEltYWdlVXJsOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLnN3YXRjaC51cmwsXG5cdFx0XHRcdFx0XHRcdFx0bGFyZ2VTd2F0Y2hJbWFnZVVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZVN3YXRjaC51cmwsXG5cdFx0XHRcdFx0XHRcdFx0aHJlZkF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGFibGUgPyAnaHJlZicgOiAneGhyZWYnXG5cdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YS50eXBlID09ICdzd2F0Y2gnKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZS5zZWxlY3RhYmxlKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb24nXTtcblx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHRcdHZhcmlhdGlvbkRhdGFWYWx1ZVBheWxvYWQuaW1hZ2VMYXJnZSA9IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dXJsOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmxhcmdlLnVybCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGl0bGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2UudGl0bGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGFsdDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZS5hbHQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGhpcmVzOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmhpcmVzLnVybFxuXHRcdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaE9wdGlvblVuc2VsZWN0YWJsZSddO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvbiddO1xuXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkID0gdmFyaWF0aW9uRGF0YVZhbHVlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0T3B0aW9ucyddICs9IHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlKHZhcmlhdGlvbkRhdGFWYWx1ZVBheWxvYWQpO1xuXHRcdFx0XHRcdFx0fVx0XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhLnR5cGUgPT0gJ3N3YXRjaCcpIHtcblx0XHRcdFx0XHRcdFx0aHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXQnXSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2gnXSh7XG5cdFx0XHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHRcdFx0b3B0aW9uczogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ11cblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR2YXIgcGxhY2Vob2xkZXIgPSB2YXJpYXRpb25EYXRhLmxhYmVsLnBsYWNlaG9sZGVyO1xuXHRcdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRcdFx0XHRwbGFjZWhvbGRlciA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvblNlbGVjdGVkJ10oe1xuXHRcdFx0XHRcdFx0XHRcdFx0dGV4dDogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQudGV4dCxcblx0XHRcdFx0XHRcdFx0XHRcdHN0b2NrOiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5zdG9jayxcblx0XHRcdFx0XHRcdFx0XHRcdHNoaXBwaW5nOiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5zaGlwcGluZyxcblx0XHRcdFx0XHRcdFx0XHRcdGlzU2FtZURheVNoaXBwaW5nV2luZG93OiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5pc1NhbWVEYXlTaGlwcGluZ1dpbmRvdyxcblx0XHRcdFx0XHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZTogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQucXVhbnRpdHlTb3VyY2VUeXBlXG5cdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0J10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd24nXSh7XG5cdFx0XHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHRcdFx0dGV4dDogcGxhY2Vob2xkZXIsXG5cdFx0XHRcdFx0XHRcdFx0b3B0aW9uczogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ11cblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGh0bWxbJ2F0dHJpYnV0ZUd1aWRlJ10gPSAnJztcblx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhLmF0dHJpYnV0ZUd1aWRlKSB7XG5cdFx0XHRcdFx0XHRcdGRhdGFbJ2F0dHJpYnV0ZUd1aWRlcyddW3ZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZV0gPSB2YXJpYXRpb25EYXRhLmF0dHJpYnV0ZUd1aWRlO1xuXHRcdFx0XHRcdFx0XHRodG1sWydhdHRyaWJ1dGVHdWlkZSddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckF0dHJpYnV0ZUd1aWRlJ10oXy5leHRlbmQodmFyaWF0aW9uRGF0YS5hdHRyaWJ1dGVHdWlkZSwgeyBBdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSB9KSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yJ10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yJ10oe1xuXHRcdFx0XHRcdFx0XHRhdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSxcblx0XHRcdFx0XHRcdFx0bGFiZWw6IHtcblx0XHRcdFx0XHRcdFx0XHR0ZXh0OiB2YXJpYXRpb25EYXRhLmxhYmVsLnRleHQsXG5cdFx0XHRcdFx0XHRcdFx0bWVzc2FnZTogdmFyaWF0aW9uRGF0YS5sYWJlbC5tZXNzYWdlXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdHNlbGVjdG9yOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldCddLFxuXHRcdFx0XHRcdFx0XHRndWlkZTogaHRtbFsnYXR0cmlidXRlR3VpZGUnXVxuXHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9ycyddICs9IGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yJ107XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdGh0bWxbJ3NlbGVjdG9ycyddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25zJ10oe1xuXHRcdFx0XHRcdFx0c2VsZWN0b3JzOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcnMnXVxuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0JHByb2R1Y3RWYXJpYXRpb25zLmh0bWwoaHRtbFsnc2VsZWN0b3JzJ10pLmFkZENsYXNzKCdsb2FkZWQnKTtcblx0XHRcdFx0XHRpZiAocmVzcG9uc2UucGlkKSB7XG5cdFx0XHRcdFx0XHQkZ3JpZFRpbGUuZmluZCgnLmJ0bi5hZGQnKS5hdHRyKCdwaWQnLCByZXNwb25zZS5waWQpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkZ3JpZFRpbGUuZmluZCgnLmJ0bi5hZGQnKS5yZW1vdmVBdHRyKCdwaWQnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbih4aHIpIHtcblx0XHRcdFx0XHQkcHJvZHVjdFZhcmlhdGlvbnMubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVzZXRQcm9kdWN0U2VhcmNoKCkge1xuXHQkcHJvZHVjdFNlYXJjaC5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIuYXR0cigncXVlcnknLCAnJyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXQudmFsKCcnKTtcblx0JHByb2R1Y3RTZWFyY2hJbnB1dC5mb2N1cygpO1xuXHR1cGRhdGVQcm9kdWN0U2VhcmNoQWN0aW9uKCk7XG59XG5cbmZ1bmN0aW9uIGFkZFByb2R1Y3RXaXRoUHJvZHVjdElkKHByb2R1Y3RJZCwgJGdyaWRUaWxlQWRkQnV0dG9uKSB7XG5cdGlmICgkZ3JpZFRpbGVBZGRCdXR0b24pIHtcblx0XHQkZ3JpZFRpbGVBZGRCdXR0b24ubG9hZGluZyh7XG5cdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0fSk7XG5cdH1cblx0JHByb2R1Y3RTZWFyY2hFcnJvckNvbnRhaW5lci5odG1sKCcnKTtcblxuXHRhZGRQcm9kdWN0KHtcblx0XHRwYXlsb2FkOiB7XG5cdFx0XHRwaWQ6IHByb2R1Y3RJZFxuXHRcdH0sXG5cdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0aWYgKCRncmlkVGlsZUFkZEJ1dHRvbiAmJiAkZ3JpZFRpbGVBZGRCdXR0b24uYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHRcdCRncmlkVGlsZUFkZEJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0XHRyZXNldFByb2R1Y3RTZWFyY2goKTtcblx0XHRcdHJlbmRlckNhcnQoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RCYXJjb2RlKCkge1xuXHR2YXIgY2FudmFzID0gJGJhcmNvZGVTY2FubmVyTW9kYWwuZmluZCgnY2FudmFzJylbMF07XG5cdGNhbnZhcy53aWR0aCA9IHZpZGVvLnZpZGVvV2lkdGg7XG5cdGNhbnZhcy5oZWlnaHQgPSB2aWRlby52aWRlb0hlaWdodDtcblxuXHR2YXIgY2FudmFzQ29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXHRjYW52YXNDb250ZXh0LmRyYXdJbWFnZSh2aWRlbywgMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuXHR2YXIgYmFyY29kZURldGVjdG9yID0gbmV3IEJhcmNvZGVEZXRlY3RvcigpO1xuXHRiYXJjb2RlRGV0ZWN0b3IuZGV0ZWN0KGNhbnZhc0NvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCkpLnRoZW4oYmFyY29kZXMgPT4ge1xuXHRcdCRiYXJjb2RlU2Nhbm5lck1vZGFsLmFkZENsYXNzKCdzY2FubmVkJyk7XG5cdFx0XG5cdFx0YmFyY29kZXMuZm9yRWFjaChmdW5jdGlvbihiYXJjb2RlKSB7XG5cdFx0XHR2YXIgYmFyY29kZVZhbHVlO1xuXHRcdFx0aWYgKCdyYXdWYWx1ZScgaW4gYmFyY29kZSkge1xuXHRcdFx0XHRiYXJjb2RlVmFsdWUgPSBiYXJjb2RlLnJhd1ZhbHVlO1xuXHRcdFx0fSBlbHNlIGlmICgncmF3RGF0YScgaW4gYmFyY29kZSkge1xuXHRcdFx0XHRiYXJjb2RlVmFsdWUgPSBiYXJjb2RlLnJhd0RhdGE7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGNsb3NlQmFyY29kZVNjYW5uZXIoKTtcblx0XHRcdGFkZFByb2R1Y3RXaXRoVXBjKGJhcmNvZGVWYWx1ZSk7XG5cdFx0fSk7XG5cdH0pLmNhdGNoKGVycm9yID0+IHtcblx0XHQvLyBhbGVydChlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBjbG9zZUJhcmNvZGVTY2FubmVyKCkge1xuXHQkKCcuc2VjdGlvbi5zY2FuJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRpZiAoYmFyY29kZURldGVjdG9ySW50ZXJ2YWwpIHtcblx0XHRiYXJjb2RlRGV0ZWN0b3JJbnRlcnZhbCA9IGNsZWFySW50ZXJ2YWwoYmFyY29kZURldGVjdG9ySW50ZXJ2YWwpO1xuXHR9XG5cdHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG5cdFx0dHJhY2suc3RvcCgpO1xuXHR9KTtcblx0dmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZ2V0Q2xpcGJvYXJkVmFsdWUoZXZlbnQsIGVsZW1lbnQsIGNhbGxiYWNrKSB7XG5cdGlmIChuYXZpZ2F0b3IuY2xpcGJvYXJkICYmIG5hdmlnYXRvci5jbGlwYm9hcmQucmVhZFRleHQpIHtcblx0ICBcdC8vIG1vZGVybiBhcHByb2FjaCB3aXRoIENsaXBib2FyZCBBUElcblx0ICBcdG5hdmlnYXRvci5jbGlwYm9hcmQucmVhZFRleHQoKS50aGVuKGNhbGxiYWNrKTtcblx0fSBlbHNlIGlmIChldmVudC5vcmlnaW5hbEV2ZW50ICYmIGV2ZW50Lm9yaWdpbmFsRXZlbnQuY2xpcGJvYXJkRGF0YSkge1xuXHQgIFx0Ly8gT3JpZ2luYWxFdmVudCBpcyBhIHByb3BlcnR5IGZyb20galF1ZXJ5LCBub3JtYWxpemluZyB0aGUgZXZlbnQgb2JqZWN0XG5cdCAgXHRjYWxsYmFjayhldmVudC5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEuZ2V0RGF0YSgndGV4dCcpKTtcblx0fSBlbHNlIGlmIChldmVudC5jbGlwYm9hcmREYXRhKSB7XG5cdCAgXHQvLyB1c2VkIGluIHNvbWUgYnJvd3NlcnMgZm9yIGNsaXBib2FyZERhdGFcblx0ICBcdGNhbGxiYWNrKGV2ZW50LmNsaXBib2FyZERhdGEuZ2V0RGF0YSgndGV4dC9wbGFpbicpKTtcblx0fSBlbHNlIGlmICh3aW5kb3cuY2xpcGJvYXJkRGF0YSkge1xuXHQgIFx0Ly8gT2xkZXIgY2xpcGJvYXJkRGF0YSB2ZXJzaW9uIGZvciBJbnRlcm5ldCBFeHBsb3JlciBvbmx5XG5cdCAgXHRjYWxsYmFjayh3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCdUZXh0JykpO1xuXHR9IGVsc2Uge1xuXHQgIFx0Ly8gTGFzdCByZXNvcnQgZmFsbGJhY2ssIHVzaW5nIGEgdGltZXJcblx0ICBcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRjYWxsYmFjayhlbGVtZW50LnZhbHVlKVxuXHQgIFx0fSwgMTAwKTtcblx0fVxufVxuXG5mdW5jdGlvbiBhZGRQcm9kdWN0V2l0aFVwYyh1cGMpIHtcblx0JGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIuYXR0cigndXBjJywgdXBjKTtcblx0JGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRJc0xhYmVsU2hvd246IGZhbHNlXG5cdH0pO1xuXHQkYmFyY29kZVNjYW5uZXJBZGRCdXR0b24ubG9hZGluZyh7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fSk7XG5cdCRiYXJjb2RlU2Nhbm5lcklucHV0LnZhbCgnJyk7XG5cdCRiYXJjb2RlU2Nhbm5lckVycm9yQ29udGFpbmVyLmh0bWwoJycpO1xuXHQkYmFyY29kZVNjYW5uZXJJbnB1dC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXG5cdGFkZFByb2R1Y3Qoe1xuXHRcdHBheWxvYWQ6IHtcblx0XHRcdHVwYzogdXBjXG5cdFx0fSxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0aWYgKHJlc3BvbnNlICYmICFyZXNwb25zZS5Jc1Byb2R1Y3RJblByb2R1Y3RTZXJ2aWNlKSB7XG5cdFx0XHRcdCRiYXJjb2RlU2Nhbm5lckVycm9yQ29udGFpbmVyLmFwcGVuZCgnPHA+UHJvZHVjdCBub3QgZm91bmQgaW4gc2VydmljZSE8L3A+Jyk7XHRcblx0XHRcdH0gZWxzZSBpZiAocmVzcG9uc2UgJiYgIXJlc3BvbnNlLklzUHJvZHVjdEluQ2F0YWxvZykge1xuXHRcdFx0XHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5hcHBlbmQoJzxwPlByb2R1Y3Qgbm90IGZvdW5kIGluIGNhdGFsb2chPC9wPicpO1x0XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cdFx0XHQkYmFyY29kZVNjYW5uZXJJbnB1dENvbnRhaW5lci5hdHRyKCd1cGMnLCAnJyk7XG5cdFx0XHQkYmFyY29kZVNjYW5uZXJJbnB1dENvbnRhaW5lci5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHQkYmFyY29kZVNjYW5uZXJBZGRCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHRcdHJlbmRlckNhcnQoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBhZGRQcm9kdWN0KHBhcmFtZXRlcnMpIHtcblx0dmFyIHBheWxvYWQgPSAkLmV4dGVuZChwYXJhbWV0ZXJzLnBheWxvYWQgfHwge30sIHtcblx0XHRmb3JtYXQ6ICdhamF4Jyxcblx0XHRRdWFudGl0eTogMSxcblx0XHRjYXJ0QWN0aW9uOiAnYWRkJyxcblx0XHRjc3JmX3Rva2VuOiBvcHRpb25zLlRva2VuLFxuXHRcdGNoYW5uZWw6ICdFY2hvJyxcblx0XHRib3Bpc19zdG9yZTogJycsXG5cdFx0Ym9waXNfcXVhbnRpdHlfYXZhaWxhYmxlOiAnJyxcblx0XHRib3Bpc19zaGlwcGluZ19vcHRpb246ICcnXG5cdH0pO1xuXG5cdGlmIChwYXlsb2FkLnBpZCB8fCBwYXlsb2FkLnVwYykge1xuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuYWRkUHJvZHVjdCxcblx0XHRcdGRhdGE6IHBheWxvYWQsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0XHRpZiAocGFyYW1ldGVycy5zdWNjZXNzICYmIHR5cGVvZiBwYXJhbWV0ZXJzLnN1Y2Nlc3MgPT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRcdHBhcmFtZXRlcnMuc3VjY2VzcyhyZXNwb25zZSk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cdFx0XHRcdGlmIChwYXJhbWV0ZXJzLmNvbXBsZXRlICYmIHR5cGVvZiBwYXJhbWV0ZXJzLmNvbXBsZXRlID09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRwYXJhbWV0ZXJzLmNvbXBsZXRlKHhocik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW5kZXJDYXJ0KCkge1xuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdH0gZWxzZSB7XG5cdFx0JC5hamF4KHtcblx0XHRcdHR5cGU6ICdHRVQnLFxuXHRcdFx0dXJsOiBVcmxzLkNhcnQuR2V0Q2FydEJvZHlQcm9kdWN0TGluZUl0ZW1zLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdFx0JCgnI3dyYXBwZXIgPiAuY2FydCA+IGZvcm0nKS5odG1sKHJlc3BvbnNlKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuZ2V0Q2FydERhdGEsXG5cdFx0XHRkYXRhOiB7XG5cdFx0XHRcdGlzQ2FydDogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRcdGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5PcmRlclRvdGFsICYmIHJlc3BvbnNlLk9yZGVyVG90YWwuYWRqdXN0ZWRNZXJjaGFuZGl6ZVRvdGFsUHJpY2UpIHtcblx0XHRcdFx0XHQkKCcub3JkZXItc3VidG90YWwgLm9yZGVyLXZhbHVlJykudGV4dChyZXNwb25zZS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlRGlzcGxheSk7XG5cdFx0XHRcdFx0JCgnLm9yZGVyLXRvdGFscy10YWJsZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcub3JkZXItdG90YWxzLXRhYmxlJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHR1cGRhdGVDU1JGVG9rZW4oKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlQ1NSRlRva2VuKCkge1xuICAgICQuYWpheCh7XG4gICAgXHRtZXRob2Q6ICdnZXQnLFxuICAgIFx0dXJsOiBVcmxzLkNTUkZUb2tlbi5HZXQsXG5cdFx0ZGF0YVR5cGU6ICdqc29uJyxcbiAgICBcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgXHRcdG9wdGlvbnMuVG9rZW4gPSByZXNwb25zZS50b2tlbjtcbiAgICBcdH1cbiAgICB9KTtcbn1cblxuZXhwb3J0cy5yZW5kZXJDYXJ0ID0gcmVuZGVyQ2FydDtcbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXHRpbml0aWFsaXplKG9wdGlvbnMpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgc2l6ZVJlZmluZW1lbnRzID0gcmVxdWlyZSgnLi4vc2l6ZS1yZWZpbmVtZW50cycpO1xudmFyIHNsaWRlcnMgPSByZXF1aXJlKCcuLi9zbGlkZXJzJyk7XG52YXIgc3R5bGVDb3VudHMgPSByZXF1aXJlKCcuLi9zdHlsZS1jb3VudHMnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbihvcHRpb25zKSB7XG5cdHN0eWxlQ291bnRzLnJlbmRlcihvcHRpb25zLlN0eWxlQ291bnRDYWNoZSk7XG5cdHNpemVSZWZpbmVtZW50cy5pbml0KCk7XG5cdHNsaWRlcnMuaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycygnLm1haW4tY29udGVudCAuY2F0ZWdvcnktbGFuZGluZy1zbGlkZXI6bm90KC5zbGljay1pbml0aWFsaXplZCknKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgYXBwbGVQYXlTZXNzaW9uO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBidWZmZXIgPSB7fTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXG5cdCQoJ1twYXltZW50LW1ldGhvZC1jb250YWluZXI9XCJEV19BUFBMRV9QQVlcIl0nKS5hdHRyKCdjYW4tbWFrZS1wYXltZW50cycsICdBcHBsZVBheVNlc3Npb24nIGluIHdpbmRvdyAmJiAnY2FuTWFrZVBheW1lbnRzJyBpbiBBcHBsZVBheVNlc3Npb24gJiYgQXBwbGVQYXlTZXNzaW9uLmNhbk1ha2VQYXltZW50cygpKTtcblx0JCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwLWNvbnRhaW5lcj1cIkRXX0FQUExFX1BBWVwiXScpLmF0dHIoJ2Nhbi1tYWtlLXBheW1lbnRzJywgJ0FwcGxlUGF5U2Vzc2lvbicgaW4gd2luZG93ICYmICdjYW5NYWtlUGF5bWVudHMnIGluIEFwcGxlUGF5U2Vzc2lvbiAmJiBBcHBsZVBheVNlc3Npb24uY2FuTWFrZVBheW1lbnRzKCkpO1xuXHRcblx0Z2V0QXBwbGVQYXlQYXltZW50UmVxdWVzdCgpO1xuXHQkKGRvY3VtZW50KS5vZmYoJ0FwcGxlUGF5LkdldFBheW1lbnRSZXF1ZXN0Jykub24oJ0FwcGxlUGF5LkdldFBheW1lbnRSZXF1ZXN0IENhcnQuVXBkYXRlU3VjY2VzcycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0Z2V0QXBwbGVQYXlQYXltZW50UmVxdWVzdCgpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkFwcGxlUGF5Jykub24oJ2NsaWNrLkFwcGxlUGF5JywgJy5zdWJtaXQtYXBwbGVwYXktYnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRhcHBsZVBheVNlc3Npb24gPSBuZXcgQXBwbGVQYXlTZXNzaW9uKDEsIGJ1ZmZlclsnYXBwbGVQYXlSZXF1ZXN0J10pO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbnZhbGlkYXRlbWVyY2hhbnQgPSB2YWxpZGF0ZU1lcmNoYW50O1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbnNoaXBwaW5nY29udGFjdHNlbGVjdGVkID0gc2hpcHBpbmdDb250YWN0U2VsZWN0ZWQ7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLm9uc2hpcHBpbmdtZXRob2RzZWxlY3RlZCA9IHNoaXBwaW5nTWV0aG9kU2VsZWN0ZWQ7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLm9ucGF5bWVudG1ldGhvZHNlbGVjdGVkID0gcGF5bWVudE1ldGhvZFNlbGVjdGVkO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbmNvdXBvbmNvZGVjaGFuZ2VkID0gY291cG9uQ29kZUNoYW5nZWQ7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLm9ucGF5bWVudGF1dGhvcml6ZWQgPSBwYXltZW50QXV0aG9yaXplZDtcblx0XHRhcHBsZVBheVNlc3Npb24ub25jYW5jZWwgPSBjYW5jZWw7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmJlZ2luKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZU1lcmNoYW50KGV2ZW50KSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuVmFsaWRhdGVNZXJjaGFudCwgZ2V0RmV0Y2hPcHRpb25zKCdQT1NUJywgZXZlbnQpKVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkgeyBcblx0XHRyZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuXHR9KVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5jb21wbGV0ZU1lcmNoYW50VmFsaWRhdGlvbihyZXNwb25zZSk7XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LVZhbGlkYXRlTWVyY2hhbnQnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzaGlwcGluZ0NvbnRhY3RTZWxlY3RlZChldmVudCkge1xuXHRmZXRjaChVcmxzLkFwcGxlUGF5LlNoaXBwaW5nQ29udGFjdFNlbGVjdGVkLCBnZXRGZXRjaE9wdGlvbnMoJ1BPU1QnLCBldmVudCkpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmNvbXBsZXRlU2hpcHBpbmdDb250YWN0U2VsZWN0aW9uKHJlc3BvbnNlKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHR9KVxuXHQuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKCdBcHBsZVBheS1TaGlwcGluZ0NvbnRhY3RTZWxlY3RlZCcsIGVycm9yKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHNoaXBwaW5nTWV0aG9kU2VsZWN0ZWQoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5TaGlwcGluZ01ldGhvZFNlbGVjdGVkLCBnZXRGZXRjaE9wdGlvbnMoJ1BPU1QnLCBldmVudCkpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmNvbXBsZXRlU2hpcHBpbmdNZXRob2RTZWxlY3Rpb24ocmVzcG9uc2UpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LVNoaXBwaW5nTWV0aG9kU2VsZWN0ZWQnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBwYXltZW50TWV0aG9kU2VsZWN0ZWQoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5QYXltZW50TWV0aG9kU2VsZWN0ZWQsIGdldEZldGNoT3B0aW9ucygnUE9TVCcsIGV2ZW50KSlcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsgXG5cdFx0cmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcblx0fSlcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRhcHBsZVBheVNlc3Npb24uY29tcGxldGVQYXltZW50TWV0aG9kU2VsZWN0aW9uKHJlc3BvbnNlKTtcblx0fSlcblx0LmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcignQXBwbGVQYXktUGF5bWVudE1ldGhvZFNlbGVjdGVkJywgZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gY291cG9uQ29kZUNoYW5nZWQoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5Db3Vwb25Db2RlQ2hhbmdlZClcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsgXG5cdFx0cmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcblx0fSlcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRhcHBsZVBheVNlc3Npb24uY29tcGxldGVDb3Vwb25Db2RlQ2hhbmdlKHJlc3BvbnNlKTtcblx0fSlcblx0LmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcignQXBwbGVQYXktQ291cG9uQ29kZUNoYW5nZWQnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBwYXltZW50QXV0aG9yaXplZChldmVudCkge1xuXHRmZXRjaChVcmxzLkFwcGxlUGF5LlBheW1lbnRBdXRob3JpemVkLCBnZXRGZXRjaE9wdGlvbnMoJ1BPU1QnLCBldmVudCkpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmNvbXBsZXRlUGF5bWVudChyZXNwb25zZSk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0aWYgKGV2ZW50LnBheW1lbnQpIHtcblx0XHRcdGlmIChldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0KSB7XG5cdFx0XHRcdHZhciBiaWxsaW5nQWRkcmVzc09iamVjdCA9IHt9O1xuXHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5GaXJzdE5hbWUgPSBldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0LmdpdmVuTmFtZTtcblx0XHRcdFx0YmlsbGluZ0FkZHJlc3NPYmplY3QuTGFzdE5hbWUgPSBldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0LmZhbWlseU5hbWU7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5hZGRyZXNzTGluZXNbMF0gfHwgJyc7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LlNlY29uZGFyeUxpbmUgPSBldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0LmFkZHJlc3NMaW5lc1sxXSB8fCAnJztcblx0XHRcdFx0YmlsbGluZ0FkZHJlc3NPYmplY3QuU3RhdGVDb2RlID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5hZG1pbmlzdHJhdGl2ZUFyZWE7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUgPSBldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0LnBvc3RhbENvZGU7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LkNpdHkgPSBldmVudC5wYXltZW50LmJpbGxpbmdDb250YWN0LmxvY2FsaXR5O1xuXG5cdFx0XHRcdGlmIChldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdCAmJiBldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdC5waG9uZSkge1xuXHRcdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LlBob25lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QucGhvbmUucmVwbGFjZSgnKycsJycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKG9wdGlvbnMuaXNDaGVja291dFBhZ2UpIHtcblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nLCAkLmV4dGVuZChiaWxsaW5nQWRkcmVzc09iamVjdCwgeyBBZGRyZXNzVHlwZTogJ2JpbGxpbmcnIH0pKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QpIHtcblx0XHRcdFx0dmFyIHNoaXBwaW5nQWRkcmVzc09iamVjdCA9IHt9O1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuRmlyc3ROYW1lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QuZ2l2ZW5OYW1lO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuTGFzdE5hbWUgPSBldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdC5mYW1pbHlOYW1lO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuUHJpbWFyeUxpbmUgPSBldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdC5hZGRyZXNzTGluZXNbMF0gfHwgJyc7XG5cdFx0XHRcdHNoaXBwaW5nQWRkcmVzc09iamVjdC5TZWNvbmRhcnlMaW5lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QuYWRkcmVzc0xpbmVzWzFdIHx8ICcnO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuU3RhdGVDb2RlID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QuYWRtaW5pc3RyYXRpdmVBcmVhO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LnBvc3RhbENvZGU7XG5cdFx0XHRcdHNoaXBwaW5nQWRkcmVzc09iamVjdC5DaXR5ID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QubG9jYWxpdHk7XG5cblx0XHRcdFx0aWYgKGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LnBob25lKSB7XG5cdFx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0LlBob25lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QucGhvbmUucmVwbGFjZSgnKycsJycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKG9wdGlvbnMuaXNDaGVja291dFBhZ2UpIHtcblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nLCAkLmV4dGVuZChzaGlwcGluZ0FkZHJlc3NPYmplY3QsIHsgQWRkcmVzc1R5cGU6ICdzaGlwcGluZycgfSkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuaXNDaGVja291dFBhZ2UpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpbmRvdy5sb2NhdGlvbiA9IFVybHMub25lUGFnZTtcblx0XHR9XG5cblx0fSlcblx0LmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcignQXBwbGVQYXktUGF5bWVudEF1dGhvcml6ZWQnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBjYW5jZWwoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5DYW5jZWwsIGdldEZldGNoT3B0aW9ucygnUE9TVCcpKVxuXHQudGhlbihmdW5jdGlvbigpIHtcblx0XHQvLyBhcHBsZVBheVNlc3Npb24uYWJvcnQoKTtcblx0XHRpZiAob3B0aW9ucy5pc0NoZWNrb3V0UGFnZSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHR9XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LUNhbmNlbCcsIGVycm9yKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldEFwcGxlUGF5UGF5bWVudFJlcXVlc3QoKSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuR2V0UmVxdWVzdClcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsgXG5cdFx0cmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcblx0fSlcblx0LnRoZW4oZnVuY3Rpb24oYXBwbGVQYXlSZXF1ZXN0KSB7XG5cdFx0YnVmZmVyWydhcHBsZVBheVJlcXVlc3QnXSA9IGFwcGxlUGF5UmVxdWVzdDtcblx0fSlcblx0LmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcignQXBwbGVQYXktR2V0UmVxdWVzdCcsIGVycm9yKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldEZldGNoT3B0aW9ucyhtZXRob2QsIGJvZHkpIHtcblx0dmFyIGZldGNoT3B0aW9ucyA9IHtcblx0XHRjcmVkZW50aWFsczogJ2luY2x1ZGUnXG5cdH07XG5cdGlmIChtZXRob2QpIHtcblx0XHRmZXRjaE9wdGlvbnMubWV0aG9kID0gbWV0aG9kO1xuXHR9XG5cdGlmIChib2R5KSB7XG5cdFx0ZmV0Y2hPcHRpb25zLmhlYWRlcnMgPSB7XG5cdFx0XHQnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0J0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uJ1xuXHRcdH1cblx0XHRmZXRjaE9wdGlvbnMuYm9keSA9IEpTT04uc3RyaW5naWZ5KGZpbHRlckV2ZW50KGJvZHkpKTtcblx0fVxuXG5cdHJldHVybiBmZXRjaE9wdGlvbnM7XG59XG5cbmZ1bmN0aW9uIGZpbHRlckV2ZW50KGV2ZW50KSB7XG5cdHZhciBldmVudEZpbHRlcmVkID0ge307XG5cdGZvciAodmFyIHByb3BlcnR5IGluIGV2ZW50KSB7XG5cdFx0aWYgKCFFdmVudC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7XG5cdFx0XHRldmVudEZpbHRlcmVkW3Byb3BlcnR5XSA9IGV2ZW50W3Byb3BlcnR5XTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGV2ZW50RmlsdGVyZWQ7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RGlhbG9nJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBvcGNwYXltZW50ID0gcmVxdWlyZSgnLi9vcGNwYXltZW50Jyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyID0gJCgnW3BheW1lbnQtbWV0aG9kPVwiU1ZTX0dpZnRfQ2FyZFwiXScpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRGb3JtID0gJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5maW5kKCdmb3JtJyk7XG52YXIgJGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIgPSAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmZpbmQoJ2lucHV0W25hbWUkPVwiZ2lmdENhcmRfbnVtYmVyXCJdJyk7XG52YXIgJGdpZnRDYXJkUGF5bWVudFBpbk51bWJlciA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnaW5wdXRbbmFtZSQ9XCJnaWZ0Q2FyZF9waW5cIl0nKTtcbnZhciAkZ2lmdENhcmRQYXltZW50TWVzc2FnZSA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnLm1lc3NhZ2VzJyk7XG52YXIgJGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZSA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnc3Bhbi5lcnJvcicpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkID0gJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5maW5kKCcuZm9ybS1naWZ0Y2FyZHMtYXBwbGllZCcpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRBcHBseUJ1dHRvbiA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnLmFwcGx5Jyk7XG52YXIgZ2lmdENhcmRWYWxpZGF0b3I7XG52YXIgZ2lmdENhcmRSZWNhcHRjaGE7XG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xuXG5mdW5jdGlvbiByZW5kZXJSZWNhcHRjaGEoKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmICRnaWZ0Q2FyZFBheW1lbnRBcHBseUJ1dHRvbi5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckdpZnRDYXJkcyAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0Z2lmdENhcmRSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcignc3ZzLWdpZnQtY2FyZC1hcHBseS1idXR0b24nLCB7XG5cdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0ICAgICAgICBjYWxsYmFjazogc3VibWl0R2lmdENhcmQsXG5cdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXHRcblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcblx0XG4gICAgJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLmFwcGx5Om5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuICAgICAgICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yR2lmdENhcmRzIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdHaWZ0Q2FyZC5BcHBseScpO1xuICAgICAgICB9XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ0dpZnRDYXJkLkFwcGx5JywgZnVuY3Rpb24oZXZlbnQpIHtcdFx0XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgaWYgKHBhcnNlRmxvYXQoJCgnW2JhbGFuY2UtZHVlXScpLmZpcnN0KCkuYXR0cignYmFsYW5jZS1kdWUnKSkgPD0gMCkge1xuICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5SZXdhcmRzQ3JlZGl0Lk5vQmFsYW5jZUR1ZSkuc2hvdygpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAoZ2lmdENhcmRSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQoZ2lmdENhcmRSZWNhcHRjaGEpO1xuXHRcdFx0fVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG4gICAgICAgICAgICBnaWZ0Q2FyZFZhbGlkYXRvciA9ICRnaWZ0Q2FyZFBheW1lbnRGb3JtLnZhbGlkYXRlKCk7XG5cdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ2dpZnRDYXJkTnVtYmVyTGVuZ3RoJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZUdpZnRDYXJkTnVtYmVyTGVuZ3RoLCBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5HaWZ0Q2FyZC5OdW1iZXIuTGVuZ3RoKTtcblx0XHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnZ2lmdENhcmROdW1iZXJWYWx1ZXMnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlR2lmdENhcmROdW1iZXJWYWx1ZXMsIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkdpZnRDYXJkLk51bWJlci5WYWx1ZXMpO1xuICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5HaWZ0Q2FyZC5OdW1iZXIpO1xuICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudFBpbk51bWJlci5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLkdpZnRDYXJkLlBpbik7XG4gICAgICAgICAgICBnaWZ0Q2FyZFZhbGlkYXRvci5mb3JtKCk7XG5cbiAgICAgICAgICAgIC8vIEFkZGluZyBBREEgY29tcGxpYW5jZSBlcnJvciBtZXNzYWdlcyBmb3IgZ2lmdENhcmRQYXltZW50IHNlY3Rpb25cbiAgICAgICAgICAgIGlmICgkZ2lmdENhcmRQYXltZW50Rm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgJCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB2YXIgZ2lmdENhcmRQYXltZW50Rm9ybUVycm9yTWVzc2FnZXMgPSBvcGNwYXltZW50LmdldEVycm9yTWVzc2FnZXMoJGdpZnRDYXJkUGF5bWVudEZvcm0pO1xuICAgICAgICAgICAgICAgIHZhciBnaWZ0Q2FyZFBheW1lbnRGb3JtRXJyb3JCb3ggPSBvcGNwYXltZW50LmVycm9yQm94KCdDYW5ub3QgUHJvY2VlZCcsICdQbGVhc2UgZml4IHRoZSBmb2xsb3dpbmcgZXJyb3JzOicsIGdpZnRDYXJkUGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcbiAgICAgICAgICAgICAgICBpZiAoZ2lmdENhcmRQYXltZW50Rm9ybUVycm9yQm94KSB7XG4gICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkLmFmdGVyKGdpZnRDYXJkUGF5bWVudEZvcm1FcnJvckJveCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoVXJscyAmJiBVcmxzLkdpZnRDYXJkLkFwcGx5ICYmIGdpZnRDYXJkVmFsaWRhdG9yLnZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ2lmdENhcmRSb3dDb250YWluZXJIdG1sID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtZ2lmdC1jYXJkLXJvdy1jb250YWluZXInKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncykoKTtcbiAgICAgICAgICAgICAgICB2YXIgJGdpZnRDYXJkUGF5bWVudEFwcGxpZWRHaWZ0Q2FyZCA9ICQoZ2lmdENhcmRSb3dDb250YWluZXJIdG1sKS5hcHBlbmRUbygkZ2lmdENhcmRQYXltZW50QXBwbGllZCk7XG5cbiAgICAgICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50QXBwbHlCdXR0b24ubG9hZGluZyhvcHRpb25zLkxvYWRpbmdJbmRpY2F0b3IgfHwge1xuICAgICAgICAgICAgICAgICAgICBJc0ltYWdlU2hvd246IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuUHJvY2Vzc2luZ1xuICAgICAgICAgICAgICAgIH0pO1xuXHRcdFx0XHRpZiAoIW9wdGlvbnMuTG9hZGluZ0luZGljYXRvcikge1xuXHRcdFx0XHRcdCRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQubG9hZGluZyhvcHRpb25zLkxvYWRpbmdJbmRpY2F0b3IgfHwge1xuXHRcdFx0XHRcdFx0TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkdpZnRDYXJkLkFwcGx5aW5nXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlciA9ICRnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyLnZhbCgpLm1hdGNoKC8oXFxkKS9nKTtcblx0XHRcdFx0aWYgKGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIgJiYgZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlci5sZW5ndGgpIHtcblx0XHRcdFx0XHRnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyID0gZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlci5qb2luKCcnKTtcblx0XHRcdFx0fVxuXG4gICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgIHVybDogVXJscy5HaWZ0Q2FyZC5BcHBseSxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyOiBnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGluOiAkZ2lmdENhcmRQYXltZW50UGluTnVtYmVyLnZhbCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYW1vdW50OiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRcdFx0aWYgKCRnaWZ0Q2FyZFBheW1lbnRBcHBseUJ1dHRvbi5hdHRyKCdsb2FkaW5nJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0JGdpZnRDYXJkUGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmICgkZ2lmdENhcmRQYXltZW50QXBwbGllZEdpZnRDYXJkLmF0dHIoJ2xvYWRpbmcnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgXHQkZ2lmdENhcmRQYXltZW50QXBwbGllZEdpZnRDYXJkLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyLnZhbCgnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudFBpbk51bWJlci52YWwoJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmFtb3VudEFwcGxpZWQgJiYgZGF0YS5hbW91bnRBcHBsaWVkLnZhbHVlID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0JGdpZnRDYXJkUGF5bWVudEFwcGxpZWQuZmluZCgnW2RhdGEtaWQ9XCInICsgZGF0YS5pZCArICdcIl0nKS5yZW1vdmUoKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEFwcGxpZWRHaWZ0Q2FyZC5hdHRyKCdkYXRhLWlkJywgZGF0YS5pZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGdpZnRDYXJkUm93Q29udGVudEh0bWwgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1naWZ0LWNhcmQtcm93LWNvbnRlbnQnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncykoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZE51bWJlcjogZGF0YS5udW1iZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbW91bnRBcHBsaWVkOiBkYXRhLmFtb3VudEFwcGxpZWQuZGlzcGxheVZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQuaHRtbChnaWZ0Q2FyZFJvd0NvbnRlbnRIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0JGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEubWVzc2FnZSkuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuXHRcdFx0XHRcdFx0XHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdFx0XHRcdFx0XHRcdGxvY2F0aW9uLnJlbG9hZCgpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0aWYgKGRhdGEubWVzc2FnZSA9PSAnSW52YWxpZCBNZXNzYWdlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgXHRcdGRhdGEubWVzc2FnZSA9IFJlc291cmNlcy5FcnJvci5HZW5lcmljO1x0XG4gICAgICAgICAgICAgICAgICAgICAgICBcdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEFwcGxpZWRHaWZ0Q2FyZC5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5tZXNzYWdlIHx8IFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcblx0XHRcdFx0XHRcdGlmIChnaWZ0Q2FyZFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChnaWZ0Q2FyZFJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0XHRcdFx0XHR2YWx1ZTogZGF0YS5hbW91bnRBcHBsaWVkLnZhbHVlLFxuXHRcdFx0XHRcdFx0XHRwYXltZW50X3R5cGU6ICdHaWZ0IENhcmQgU1ZTJ1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQWRkUGF5bWVudEluZm8nLCBkYXRhT2JqZWN0KTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0JGdpZnRDYXJkUGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdCRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHQkZ2lmdENhcmRQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYgKGdpZnRDYXJkUmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGdpZnRDYXJkUmVjYXB0Y2hhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFx0aWYgKGdpZnRDYXJkUmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQoZ2lmdENhcmRSZWNhcHRjaGEpO1xuXHRcdFx0XHR9XHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uR2lmdENhcmRQYXltZW50UGFuZWwnKS5vbignbW91c2Vkb3duLkdpZnRDYXJkUGF5bWVudFBhbmVsJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChnaWZ0Q2FyZFZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgZ2lmdENhcmRWYWxpZGF0b3IucmVzZXRGb3JtKCk7XG4gICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ0NhcnREYXRhLlVwZGF0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuICAgIFx0JCgnW2hhcy1naWZ0LWNhcmRzXScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzJywgZGF0YS5IYXNHaWZ0Q2FyZHMgfHwgZmFsc2UpO1xuXHQgICAgJCgnW2hhcy1naWZ0LWNhcmRzLW9ubHldJykuYXR0cignaGFzLWdpZnQtY2FyZHMtb25seScsIGRhdGEuSGFzR2lmdENhcmRzT25seSB8fCBmYWxzZSk7XG5cdCAgICBcblx0ICAgIGlmIChkYXRhLkhhc0dpZnRDYXJkcyAmJiAhZGF0YS5BbGxvd0dpZnRDYXJkUHVyY2hhc2VXaXRoR2lmdENhcmQpIHtcblx0ICAgIFx0JGdpZnRDYXJkUGF5bWVudE1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuR2lmdENhcmQuR2lmdENhcmRQdXJjaGFzZVdpdGhHaWZ0Q2FyZE5vdEFsbG93ZWQpO1xuXHQgICAgXHQkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmF0dHIoJ3N0YXR1cycsICdsb2NrZWQnKTtcblx0ICAgIH0gZWxzZSB7XG5cdCAgICBcdCRnaWZ0Q2FyZFBheW1lbnRNZXNzYWdlLmh0bWwoJycpO1xuXHQgICAgXHQkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmF0dHIoJ3N0YXR1cycsICdhY3RpdmUnKTtcblx0ICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignR2lmdENhcmQuQ2xlYXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkLmh0bWwoJycpO1xuICAgICAgICAkKCcub3JkZXItYmFsYW5jZS1kdWUnKS5odG1sKCcnKTtcbiAgICB9KTtcblxuICAgICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5yZW1vdmU6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB2YXIgJGdpZnRDYXJkUm93ID0gJCh0aGlzKS5jbG9zZXN0KCcuZm9ybS1naWZ0Y2FyZC1hcHBsaWVkJyk7XG4gICAgICAgICRnaWZ0Q2FyZFJvdy5sb2FkaW5nKG9wdGlvbnMuTG9hZGluZ0luZGljYXRvciB8fCB7XG4gICAgICAgICAgICBMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuR2lmdENhcmQuUmVtb3ZpbmdcbiAgICAgICAgfSk7XG4gICAgICAgICRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmwgOiBVcmxzLkdpZnRDYXJkLlJlbW92ZSxcbiAgICAgICAgICAgIHR5cGUgOiAnUE9TVCcsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGlkOiAkZ2lmdENhcmRSb3cuZGF0YSgnaWQnKVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkYXRhVHlwZSA6ICdqc29uJyxcbiAgICAgICAgICAgIHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICBcdCRnaWZ0Q2FyZFJvdy5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgJGdpZnRDYXJkUm93LnJlbW92ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbi5yZWxvYWQoKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBcdCRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLmVycm9yIHx8IFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JGdpZnRDYXJkUm93LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0JGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHR9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrLkJhbGFuY2VJbnF1aXJ5JywgJ1twYXltZW50LW1ldGhvZD1cIlNWU19HaWZ0X0NhcmRcIl0gLmJhbGFuY2UtaW5xdWlyeSBhJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlEaWFsb2cuaW5pdGlhbGl6ZSgpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuZm9ybS1sYWJlbC5leHBhbmRlcicsIGZ1bmN0aW9uKCl7XG4gICAgXHQkKCdmb3JtLnN2cy1naWZ0LWNhcmQtaW5mb3JtYXRpb24nKS5zbGlkZVRvZ2dsZSgpO1xuICAgIFx0JGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci50b2dnbGVDbGFzcygnc3ZzLWNvbGxhcHNlZCcpO1xuICAgIH0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuLyogZ2xvYmFsIFJlc291cmNlcywgVXJscyAqL1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIG9wY3BheW1lbnQgPSByZXF1aXJlKCcuL29wY3BheW1lbnQnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyICRsb3lhbHR5UGF5bWVudENvbnRhaW5lciA9ICQoJ1twYXltZW50LW1ldGhvZD1cIkxPWUFMVFlfQ1JFRElUXCJdJyk7XG52YXIgJGxveWFsdHlQYXltZW50c0Zvcm0gPSAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnZm9ybScpO1xudmFyICRsb3lhbHR5UGF5bWVudHNBcHBsaWVkID0gJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmZpbmQoJy5sb3lhbHR5LWFwcGxpZWQnKTtcbnZhciAkbG95YWx0eVBheW1lbnRJbnB1dCA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcjZHdmcm1fYmlsbGluZ19sb3lhbHR5X2xveWFsdHlOdW1iZXInKTtcbnZhciAkbG95YWx0eVBob25lTnVtYmVySW5wdXQgPSAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfbG95YWx0eV9sb3lhbHR5UGhvbmVOdW1iZXInKTtcbnZhciAkbG95YWx0eVppcENvZGVJbnB1dCA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcjZHdmcm1fYmlsbGluZ19sb3lhbHR5X2xveWFsdHlaaXBDb2RlJyk7XG52YXIgJGxveWFsdHlQYXltZW50U2Vjb25kYXJ5Q29udGFpbmVyID0gJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmZpbmQoJy5sb3lhbHR5LXNlY29uZGFyeScpO1xudmFyICRsb3lhbHR5UGF5bWVudFNlY29uZGFyeVNlbGVjdCA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcjbG95YWx0eS1zZWNvbmRhcnktc2VsZWN0Jyk7XG52YXIgJGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlID0gJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmZpbmQoJ3NwYW4uZXJyb3InKTtcbnZhciBsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yO1xudmFyIGxveWFsdHlDcmVkaXRSb3dUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWxveWFsdHktY3JlZGl0LXJvdycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbnZhciBsb3lhbHR5Q3JlZGl0UmVjYXB0Y2hhO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhKCkge1xuXHRpZiAobG9hZGVkLlJlY2FwdGNoYSAmJiAkKCcjbG95YWx0eS1jcmVkaXQtYWRkLWJ1dHRvbicpLmxlbmd0aCA+IDAgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9ybG95YWx0eUNyZWRpdCAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0bG95YWx0eUNyZWRpdFJlY2FwdGNoYSA9IGdyZWNhcHRjaGEucmVuZGVyKCdsb3lhbHR5LWNyZWRpdC1hZGQtYnV0dG9uJywge1xuXHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgY2FsbGJhY2s6IHN1Ym1pdExveWFsdHlDcmVkaXQsXG5cdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXHR2YXIgY3VycmVudFNpdGUgPSAnJztcblx0aWYgKCQoXCIubG9nby5zaGVwXCIpLmxlbmd0aCA+IDApe1xuICAgIFx0Y3VycmVudFNpdGUgPSBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob3RPcHRlZEluU0hFUDtcbiAgICB9XG5cdGlmICgkKFwiLmxvZ28uY29cIikubGVuZ3RoID4gMCl7XG4gICAgXHRjdXJyZW50U2l0ZSA9IFJlc291cmNlcy5Mb3lhbHR5Q3JlZGl0Lk5vdE9wdGVkSW5DTztcbiAgICB9XG5cdFxuXHRyZW5kZXJSZWNhcHRjaGEoKTtcblx0JChkb2N1bWVudCkub24oJ1JlY2FwdGNoYS5Mb2FkZWQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICghbG9hZGVkLlJlY2FwdGNoYSkge1xuXHRcdFx0bG9hZGVkLlJlY2FwdGNoYSA9IHRydWU7XG5cdCAgICAgICAgcmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCAgICB9XG5cdH0pO1xuXHRcblx0aWYgKCQoXCIubG95YWx0eS1yb3dbc3RhdHVzPSdhcHBsaWVkJ11cIikubGVuZ3RoID4gMCl7XG5cdFx0JGxveWFsdHlQYXltZW50c0Zvcm0uaGlkZSgpO1xuXHR9XG5cblx0aWYgKCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeVNlbGVjdC5jbG9zZXN0KCcub3BjLXN1bW1hcnknKS5sZW5ndGggPiAwKSB7XG5cdFx0JGxveWFsdHlQYXltZW50U2Vjb25kYXJ5U2VsZWN0LnNlbGVjdG1lbnUoe1xuXHRcdFx0d2lkdGg6ICcxMDAlJyxcblx0XHRcdGFwcGVuZFRvOiAnW3BheW1lbnQtbWV0aG9kPVwiTE9ZQUxUWV9DUkVESVRcIl0gLmxveWFsdHktc2Vjb25kYXJ5Jyxcblx0XHRcdGNoYW5nZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknLCB1aSAmJiB1aS5pdGVtICYmIHVpLml0ZW0udmFsdWUgPyB1aS5pdGVtLnZhbHVlIDogJycpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdFxuXHQkbG95YWx0eVBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5yZXNldCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRyZXNldFNlY29uZGFyeVNlbGVjdCgpO1xuXHR9KTtcblxuXHQkbG95YWx0eVBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5hZGQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG4gICAgICAgIGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JSZXdhcmRzQ3JlZGl0IHx8ICFvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdMb3lhbHR5Q3JlZGl0LkFkZCcpOyBcbiAgICAgICAgfVxuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdMb3lhbHR5Q3JlZGl0LkFkZCcsIGZ1bmN0aW9uKGV2ZW50LCBkYXRhKSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdGlmIChwYXJzZUZsb2F0KCQoJ1tiYWxhbmNlLWR1ZV0nKS5maXJzdCgpLmF0dHIoJ2JhbGFuY2UtZHVlJykpIDw9IDApIHtcblx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5Mb3lhbHR5Q3JlZGl0Lk5vQmFsYW5jZUR1ZSkuc2hvdygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgbG95YWx0eVNlY29uZGFyeUZhY3RvciA9ICRsb3lhbHR5UGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknKTtcblx0XHRcdGxveWFsdHlDcmVkaXRWYWxpZGF0b3IgPSAkbG95YWx0eVBheW1lbnRzRm9ybS52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgJGxveWFsdHlQYXltZW50SW5wdXQucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5Mb3lhbHR5Q3JlZGl0Lk51bWJlcik7XG5cblx0XHRcdHN3aXRjaCAobG95YWx0eVNlY29uZGFyeUZhY3Rvcikge1xuXHRcdFx0XHRjYXNlIFwiemlwY29kZVwiOlxuXHRcdFx0XHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnemlwQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVaaXBDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdFx0XHRcdFx0JGxveWFsdHlaaXBDb2RlSW5wdXQucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5aaXBDb2RlKTtcblx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG4gICAgICAgICAgICBsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yLmZvcm0oKTtcblxuXHRcdFx0Ly8gQWRkaW5nIEFEQSBjb21wbGlhbmNlIGVycm9yIG1lc3NhZ2VzIGZvciBnaWZ0Q2FyZFBheW1lbnQgc2VjdGlvblxuICAgICAgICAgICAgaWYgKCRsb3lhbHR5UGF5bWVudHNGb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB2YXIgbG95YWx0eVBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyA9IG9wY3BheW1lbnQuZ2V0RXJyb3JNZXNzYWdlcygkbG95YWx0eVBheW1lbnRzRm9ybSk7XG4gICAgICAgICAgICAgICAgdmFyIGxveWFsdHlQYXltZW50Rm9ybUVycm9yQm94ID0gb3BjcGF5bWVudC5lcnJvckJveCgnQ2Fubm90IFByb2NlZWQnLCAnUGxlYXNlIGZpeCB0aGUgZm9sbG93aW5nIGVycm9yczonLCBsb3lhbHR5UGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcbiAgICAgICAgICAgICAgICBpZiAobG95YWx0eVBheW1lbnRGb3JtRXJyb3JCb3gpIHtcbiAgICAgICAgICAgICAgICAgICAgJGxveWFsdHlQYXltZW50c0FwcGxpZWQuYWZ0ZXIobG95YWx0eVBheW1lbnRGb3JtRXJyb3JCb3gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblx0XHRcdFxuICAgICAgICAgICAgaWYgKFVybHMgJiYgVXJscy5jaGVja0xveWFsdHkgJiYgbG95YWx0eUNyZWRpdFZhbGlkYXRvci52YWxpZCgpKSB7XG4gICAgICAgICAgICBcdCRsb3lhbHR5UGF5bWVudHNGb3JtLmhpZGUoKTtcbiAgICAgICAgICAgIFx0XG5cdFx0XHRcdHZhciAkbG95YWx0eUNyZWRpdFJvdyA9ICQobG95YWx0eUNyZWRpdFJvd1RlbXBsYXRlKCkpO1xuXHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdyA9ICRsb3lhbHR5Q3JlZGl0Um93LmFwcGVuZFRvKCRsb3lhbHR5UGF5bWVudHNBcHBsaWVkKTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ3BlbmRpbmcnKTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJhc2tldExveWFsdHlOdW1iZXInKS5odG1sKHV0aWwuZ2V0TWFza2VkTnVtYmVyKCRsb3lhbHR5UGF5bWVudElucHV0LnZhbCgpLCA0LCAneHh4eC4uLiAnKSk7XG5cdFxuXHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZyh7SXNMYWJlbFNob3duOiBmYWxzZX0pO1xuXHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoe0xhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb3lhbHR5Q3JlZGl0LkxvYWRpbmd9KTtcblx0XG5cdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0dXJsOiBVcmxzLmNoZWNrTG95YWx0eSxcblx0XHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0Y3NyZl90b2tlbjogICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0bG95YWx0eU51bWJlcjogJGxveWFsdHlQYXltZW50SW5wdXQudmFsKCksXG5cdFx0XHRcdFx0XHRsb3lhbHR5UGhvbmVOdW1iZXI6ICRsb3lhbHR5UGhvbmVOdW1iZXJJbnB1dC52YWwoKSxcblx0XHRcdFx0XHRcdGxveWFsdHlaaXBDb2RlOiAkbG95YWx0eVppcENvZGVJbnB1dC52YWwoKVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHRcblx0XHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XG5cdFx0XHRcdFx0XHRpZiAoZGF0YS5lcnJvciAhPT0gJ3VuZGVmaW5lZCcgJiYgZGF0YS5lcnJvciA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLmVycm9yTXNnKS5zaG93KCk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCFkYXRhLm9wdGluU3RhdHVzKSB7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicsICdmYWxzZScpO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnbWVzc2FnZScpO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcubWVzc2FnZScpLmh0bWwoY3VycmVudFNpdGUpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChwYXJzZUZsb2F0KGRhdGEuY3JlZGl0QW1vdW50KSA8PSAwKSB7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicsICd0cnVlJyk7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdtZXNzYWdlJyk7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5tZXNzYWdlJykuaHRtbChSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob0JhbGFuY2VBdmFpbGFibGUpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1sb3lhbHR5bnVtYmVyJywgJ3RydWUnKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLmF0dHIoJ2RhdGEtbG95YWx0eScsIGRhdGEub3B0SW4pO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLmh0bWwoZGF0YS5jcmVkaXRBbW91bnRGb3JtYXR0ZWQpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0dmFyIGRldGFpbHMgPSAnJztcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdHZhciB2b3VjaGVycyA9IGRhdGEuY3JlZGl0Vm91Y2hlcnM7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHR2b3VjaGVycy5yZXZlcnNlKCkuZm9yRWFjaChmdW5jdGlvbih2b3VjaGVyKXtcblx0XHRcdFx0XHRcdFx0XHRkZXRhaWxzICs9ICc8ZGl2IGNsYXNzPVwidm91Y2hlclwiPjxzcGFuIGNsYXNzPVwicmV3YXJkLWFtb3VudFwiPjxiPiQnK3ZvdWNoZXIucmV3YXJkQW1vdW50Kyc8L2I+PC9zcGFuPjxzcGFuIGNsYXNzPVwiZXhwaXJhdGlvblwiPjxpPkV4cGlyZXMgJyt2b3VjaGVyLmV4cGlyYXRpb25EYXRlKyc8L2k+PC9zcGFuPjwvZGl2Pic7XG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLnZvdWNoZXJzJykuaHRtbChkZXRhaWxzKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYgKGxveWFsdHlDcmVkaXRSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQobG95YWx0eUNyZWRpdFJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmIChsb3lhbHR5Q3JlZGl0UmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGxveWFsdHlDcmVkaXRSZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKGRhdGEsIHN0YXR1cywgeGhyKSB7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuICAgICAgICAgICAgfVxuXHRcdH1cblx0fSk7XG5cblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcuYXBwbHknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJGxveWFsdHlDcmVkaXRSb3cgPSAkKHRoaXMpLmNsb3Nlc3QoJy5sb3lhbHR5LXJvdycpO1xuXHRcdFxuXHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5QW1vdW50JykuYWRkQ2xhc3MoJ2hpZGUnKTtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcudm91Y2hlcicpLmFkZENsYXNzKCdoaWRlJyk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoe0xhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb3lhbHR5Q3JlZGl0LkFwcGx5aW5nfSk7XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLmFwcGx5TG95YWx0eSxcblx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0Y3NyZl90b2tlbjogICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0XHRsb3lhbHR5TnVtYmVyOiAkbG95YWx0eVBheW1lbnRJbnB1dC52YWwoKSxcblx0XHRcdFx0bG95YWx0eVBob25lTnVtYmVyOiAkbG95YWx0eVBob25lTnVtYmVySW5wdXQudmFsKCksXG5cdFx0XHRcdGxveWFsdHlaaXBDb2RlOiAkbG95YWx0eVppcENvZGVJbnB1dC52YWwoKVxuXHRcdFx0fSxcblx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cblx0XHRcdFx0aWYgKGRhdGEuZXJyb3IgIT09ICd1bmRlZmluZWQnICYmIGRhdGEuZXJyb3IgPT09IHRydWUpIHtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnbWVzc2FnZScpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudElucHV0LnZhbCgnJyk7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cucmVtb3ZlKCk7XG5cdFx0XHRcdFx0JGxveWFsdHlQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEuZXJyb3JNc2cpLnNob3coKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnYXBwbGllZCcpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLmhpZGUoKTtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcudm91Y2hlcicpLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJhc2tldExveWFsdHlOdW1iZXInKS5odG1sKHV0aWwuZ2V0TWFza2VkTnVtYmVyKGRhdGEubG95YWx0eU51bWJlciwgNCwgJ3h4eHguLi4gJykpO1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5QW1vdW50JykucmVtb3ZlQ2xhc3MoJ2hpZGUnKS5odG1sKGRhdGEubG95YWx0eUNyZWRpdFVzZWRGb3JtYXR0ZWQpLmF0dHIoJ2xhYmVsJywgUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuUmV3YXJkQXBwbGllZCk7XG5cblx0XHRcdFx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFx0XHRcdHZhbHVlOiBkYXRhLnJld2FyZHNDcmVkaXRVc2VkLFxuXHRcdFx0XHRcdFx0cGF5bWVudF90eXBlOiAnTG95YWx0eSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQWRkUGF5bWVudEluZm8nLCBkYXRhT2JqZWN0KTtcblxuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdtZXNzYWdlJyk7XG5cdFx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHRcdHJlc2V0Rm9ybSh0cnVlKTtcblx0XHRcdH0sXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHQkbG95YWx0eVBheW1lbnRDb250YWluZXIub24oJ2NsaWNrIExveWFsdHlDcmVkaXQuUmVtb3ZlJywgJy5yZW1vdmUnLCBmdW5jdGlvbihldmVudCwgZGF0YSkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJGxveWFsdHlDcmVkaXRSb3cgPSAkKHRoaXMpLmNsb3Nlc3QoJy5sb3lhbHR5LXJvdycpO1xuXHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5QW1vdW50JykuYWRkQ2xhc3MoJ2hpZGUnKTtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcudm91Y2hlcicpLmFkZENsYXNzKCdoaWRlJyk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoe0xhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb3lhbHR5Q3JlZGl0LlJlbW92aW5nfSk7XG5cblx0XHR2YXIgcGF5bG9hZCA9IHtcblx0XHRcdGxveWFsdHlOdW1iZXI6ICQoJ2lucHV0I2R3ZnJtX2JpbGxpbmdfbG95YWx0eV9sb3lhbHR5TnVtYmVyJykudmFsKClcblx0XHR9XG5cblx0XHRpZiAoZGF0YSAmJiBkYXRhLlJlc2V0U2Vzc2lvbkRhdGEpIHtcblx0XHRcdHBheWxvYWQucmVzZXRTZXNzaW9uRGF0YSA9IHRydWVcblx0XHR9XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLnJlbW92ZUxveWFsdHksXG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXG5cdFx0XHRcdGlmICgkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYnRuW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicpICE9PSAndHJ1ZScpIHtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnZm9ybScpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNBcHBsaWVkLmh0bWwoJycpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdwZW5kaW5nJyk7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLnZvdWNoZXInKS5yZW1vdmVDbGFzcygnaGlkZScpO1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5QW1vdW50JykucmVtb3ZlQ2xhc3MoJ2hpZGUnKS5hdHRyKCdsYWJlbCcsIFJlc291cmNlcy5Mb3lhbHR5Q3JlZGl0LlJld2FyZCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdFx0fSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cblx0XHRcdFx0JGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdFxuXHQkbG95YWx0eVBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5jaGFuZ2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1sb3lhbHR5bnVtYmVyJywgJ2ZhbHNlJyk7XG5cdFx0aWYgKCRsb3lhbHR5UGF5bWVudHNBcHBsaWVkLmZpbmQoJy5sb3lhbHR5LXJvdycpLmF0dHIoJ3N0YXR1cycpID09PSAnYXBwbGllZCcpIHtcblx0XHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcucmVtb3ZlJykudHJpZ2dlcignTG95YWx0eUNyZWRpdC5SZW1vdmUnKTtcblx0XHR9XG5cdFx0cmVzZXRGb3JtKCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkxveWFsdHlDcmVkaXRQYXltZW50UGFuZWwnKS5vbignbW91c2Vkb3duLkxveWFsdHlDcmVkaXRQYXltZW50UGFuZWwnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGxveWFsdHlDcmVkaXRWYWxpZGF0b3IgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJGxveWFsdHlQYXltZW50Q29udGFpbmVyKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgbG95YWx0eUNyZWRpdFZhbGlkYXRvci5yZXNldEZvcm0oKTtcbiAgICAgICAgICAgICRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdMb3lhbHR5Q3JlZGl0LkNsZWFyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHJlc2V0Rm9ybSgpO1xuXHR9KTtcblxuXHQkbG95YWx0eVBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5yZXNldCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHQkbG95YWx0eVBheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0JGxveWFsdHlQaG9uZU51bWJlcklucHV0LnZhbCgnJyk7XG5cdFx0JGxveWFsdHlaaXBDb2RlSW5wdXQudmFsKCcnKTtcblx0fSk7XG5cdFxuXHRpZiAoJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1sb3lhbHR5bnVtYmVyJykgPT09ICd0cnVlJyAmJiAkbG95YWx0eVBheW1lbnRzQXBwbGllZC5maW5kKCcubG95YWx0eS1yb3cnKS5sZW5ndGggPT0gMCAmJiAkKCdbY2hlY2tvdXQtbW9kZV0nKS5hdHRyKCdjaGVja291dC1tb2RlJykgIT0gJ2VjaG8nKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignTG95YWx0eUNyZWRpdC5BZGQnLCB7IFJlZ2lzdGVyZWQ6IHRydWUgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVzZXRGb3JtKHNob3dFcnJvck1lc3NhZ2UpIHtcblx0aWYgKGxveWFsdHlDcmVkaXRWYWxpZGF0b3IpIHtcblx0XHRsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuXHR9XG5cdFxuXHRpZiAoIXNob3dFcnJvck1lc3NhZ2UpIHtcblx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHR9XG5cdFxuXHR2YXIgJGxveWFsdHlDcmVkaXRSb3cgPSAkbG95YWx0eVBheW1lbnRzQXBwbGllZC5maW5kKCcubG95YWx0eS1yb3cnKTtcblx0aWYgKCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicpICE9PSAndHJ1ZScpIHtcblx0XHQkbG95YWx0eVBheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdCRsb3lhbHR5UGhvbmVOdW1iZXJJbnB1dC52YWwoJycpO1xuXHRcdCRsb3lhbHR5WmlwQ29kZUlucHV0LnZhbCgnJyk7XG5cdFx0XG5cdFx0JGxveWFsdHlQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdCRsb3lhbHR5UGF5bWVudHNBcHBsaWVkLmh0bWwoJycpO1xuXHR9IGVsc2Uge1xuXHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5QW1vdW50JykuYXR0cignbGFiZWwnLCBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5SZXdhcmQpO1xuXHR9XG5cblx0cmVzZXRTZWNvbmRhcnlTZWxlY3QoKTtcbn1cblxuZnVuY3Rpb24gcmVzZXRTZWNvbmRhcnlTZWxlY3QoKSB7XG5cdCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeVNlbGVjdC5wcm9wKCdzZWxlY3RlZEluZGV4JywgMCk7XG5cdGlmICgkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlTZWxlY3QuY2xvc2VzdCgnLm9wYy1zdW1tYXJ5JykubGVuZ3RoID4gMCkge1xuXHRcdCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeVNlbGVjdC5zZWxlY3RtZW51KCdyZWZyZXNoJyk7XG5cdH1cblx0JGxveWFsdHlQYXltZW50U2Vjb25kYXJ5Q29udGFpbmVyLmF0dHIoJ3NlY29uZGFyeScsICcnKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgJHBheW1lbnRDb250YWluZXIgPSAkKCdbcGF5bWVudC1tZXRob2Q9XCJCMkJfUGF5bWVudF9Wb3VjaGVyXCJdJyk7XG52YXIgJHBheW1lbnRGb3JtID0gJHBheW1lbnRDb250YWluZXIuZmluZCgnZm9ybScpO1xudmFyICRwYXltZW50Vm91Y2hlck51bWJlciA9ICRwYXltZW50Q29udGFpbmVyLmZpbmQoJ2lucHV0W25hbWU9XCJwYXltZW50dm91Y2hlcmNvZGVcIl0nKTtcbnZhciAkcGF5bWVudE1lc3NhZ2UgPSAkcGF5bWVudENvbnRhaW5lci5maW5kKCcubWVzc2FnZXMnKTtcbnZhciAkcGF5bWVudEVycm9yTWVzc2FnZSA9ICRwYXltZW50Q29udGFpbmVyLmZpbmQoJ3NwYW4uZXJyb3InKTtcbnZhciAkcGF5bWVudHNBcHBsaWVkID0gJHBheW1lbnRDb250YWluZXIuZmluZCgnLmZvcm0tcGF5bWVudHMtYXBwbGllZCcpO1xudmFyICRwYXltZW50QXBwbHlCdXR0b24gPSAkcGF5bWVudENvbnRhaW5lci5maW5kKCcuYXBwbHknKTtcbnZhciB2YWxpZGF0b3I7XG52YXIgcmVjYXB0Y2hhO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhKCkge1xuXHRpZiAobG9hZGVkLlJlY2FwdGNoYSAmJiAkcGF5bWVudEFwcGx5QnV0dG9uLmxlbmd0aCA+IDAgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGF5bWVudFZvdWNoZXJzICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcblx0XHRyZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcigncGF5bWVudC12b3VjaGVyLWFwcGx5LWJ1dHRvbicsIHtcblx0ICAgICAgICBzaXRla2V5OiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRQYXltZW50Vm91Y2hlcixcblx0ICAgICAgICBiYWRnZTogJ2JvdHRvbWxlZnQnXG5cdCAgICB9KTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXIgfHwge307XG5cblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcblx0XG4gICAgJHBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5hcHBseTpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG4gICAgICAgIGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQYXltZW50Vm91Y2hlcnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcbiAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ1BheW1lbnRWb3VjaGVyLkFwcGx5Jyk7XG4gICAgICAgIH1cblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignUGF5bWVudFZvdWNoZXIuQXBwbHknLCBmdW5jdGlvbihldmVudCkge1x0XHRcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBpZiAocGFyc2VGbG9hdCgkKCdbYmFsYW5jZS1kdWVdJykuZmlyc3QoKS5hdHRyKCdiYWxhbmNlLWR1ZScpKSA8PSAwKSB7XG4gICAgICAgICAgICAkcGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5QYXltZW50Vm91Y2hlci5Ob0JhbGFuY2VEdWUpLnNob3coKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKHJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZWNhcHRjaGEpO1xuXHRcdFx0fVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICAgICAgdmFsaWRhdG9yID0gJHBheW1lbnRGb3JtLnZhbGlkYXRlKCk7XG4gICAgICAgICAgICAkcGF5bWVudFZvdWNoZXJOdW1iZXIucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5QYXltZW50Vm91Y2hlci5OdW1iZXIpO1xuICAgICAgICAgICAgdmFsaWRhdG9yLmNoZWNrRm9ybSgpO1xuXG4gICAgICAgICAgICBpZiAoVXJscyAmJiBVcmxzLlBheW1lbnRWb3VjaGVyLkFwcGx5ICYmIHZhbGlkYXRvci52YWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvd0NvbnRhaW5lckh0bWwgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1wYXltZW50dm91Y2hlci1yb3ctY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpKCk7XG4gICAgICAgICAgICAgICAgdmFyICRwYXltZW50QXBwbGllZCA9ICQocm93Q29udGFpbmVySHRtbCkuYXBwZW5kVG8oJHBheW1lbnRzQXBwbGllZCk7XG5cbiAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcoe1xuICAgICAgICAgICAgICAgICAgICBJc0ltYWdlU2hvd246IHRydWUsXG5cdFx0XHRcdFx0SXNMYWJlbFNob3duOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICRwYXltZW50QXBwbGllZC5sb2FkaW5nKHtcbiAgICAgICAgICAgICAgICAgICAgTGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLlBheW1lbnRWb3VjaGVyLkFwcGx5aW5nXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiBVcmxzLlBheW1lbnRWb3VjaGVyLkFwcGx5LFxuICAgICAgICAgICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBudW1iZXI6ICRwYXltZW50Vm91Y2hlck51bWJlci52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFtb3VudDogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRwYXltZW50QXBwbHlCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJHBheW1lbnRBcHBsaWVkLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXltZW50Vm91Y2hlck51bWJlci52YWwoJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmFtb3VudEFwcGxpZWQgJiYgZGF0YS5hbW91bnRBcHBsaWVkLnZhbHVlID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0JHBheW1lbnRzQXBwbGllZC5maW5kKCdbZGF0YS1pZD1cIicgKyBkYXRhLmlkICsgJ1wiXScpLnJlbW92ZSgpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGxpZWQuYXR0cignZGF0YS1pZCcsIGRhdGEuaWQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByb3dDb250ZW50SHRtbCA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXBheW1lbnR2b3VjaGVyLXJvdy1jb250ZW50JykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBheW1lbnROdW1iZXI6IGRhdGEubnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW1vdW50QXBwbGllZDogZGF0YS5hbW91bnRBcHBsaWVkLmRpc3BsYXlWYWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGxpZWQuaHRtbChyb3dDb250ZW50SHRtbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdCRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5tZXNzYWdlKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdGlmIChkYXRhLm1lc3NhZ2UgPT0gJ0ludmFsaWQgTWVzc2FnZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0XHRkYXRhLm1lc3NhZ2UgPSBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYztcdFxuICAgICAgICAgICAgICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICAgICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXltZW50QXBwbGllZC5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEubWVzc2FnZSB8fCBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG5cdFx0XHRcdFx0XHRpZiAocmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCRwYXltZW50QXBwbHlCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0JHBheW1lbnRBcHBsaWVkLnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0JHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAocmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFx0aWYgKHJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHJlY2FwdGNoYSk7XG5cdFx0XHRcdH1cdFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlZG93bi5wYXltZW50UGFuZWwnKS5vbignbW91c2Vkb3duLnBheW1lbnRQYW5lbCcsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAodmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCRwYXltZW50Q29udGFpbmVyKS5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgdmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuICAgICAgICAgICAgJHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignQ2FydERhdGEuVXBkYXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG4gICAgXHQkKCdbaGFzLWdpZnQtY2FyZHNdJykuYXR0cignaGFzLWdpZnQtY2FyZHMnLCBkYXRhLkhhc0dpZnRDYXJkcyB8fCBmYWxzZSk7XG5cdCAgICAkKCdbaGFzLWdpZnQtY2FyZHMtb25seV0nKS5hdHRyKCdoYXMtZ2lmdC1jYXJkcy1vbmx5JywgZGF0YS5IYXNHaWZ0Q2FyZHNPbmx5IHx8IGZhbHNlKTtcblx0ICAgIFxuXHQgICAgaWYgKGRhdGEuSGFzR2lmdENhcmRzICYmICFkYXRhLkFsbG93cHVyY2hhc2VXaXRoR2lmdENhcmQpIHtcblx0ICAgIFx0JHBheW1lbnRNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkdpZnRDYXJkLnB1cmNoYXNlV2l0aEdpZnRDYXJkTm90QWxsb3dlZCk7XG5cdCAgICBcdCRwYXltZW50Q29udGFpbmVyLmF0dHIoJ3N0YXR1cycsICdsb2NrZWQnKTtcblx0ICAgIH0gZWxzZSB7XG5cdCAgICBcdCRwYXltZW50TWVzc2FnZS5odG1sKCcnKTtcblx0ICAgIFx0JHBheW1lbnRDb250YWluZXIuYXR0cignc3RhdHVzJywgJ2FjdGl2ZScpO1xuXHQgICAgfVxuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdHaWZ0Q2FyZC5DbGVhcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJHBheW1lbnRzQXBwbGllZC5odG1sKCcnKTtcbiAgICAgICAgJCgnLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCgnJyk7XG4gICAgfSk7XG5cbiAgICAkcGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLnJlbW92ZTpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHZhciAkcm93ID0gJCh0aGlzKS5jbG9zZXN0KCcuZm9ybS1wYXltZW50LWFwcGxpZWQnKTtcbiAgICAgICAgJHJvdy5sb2FkaW5nKHtcbiAgICAgICAgICAgIExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5HaWZ0Q2FyZC5SZW1vdmluZ1xuICAgICAgICB9KTtcbiAgICAgICAgJHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmwgOiBVcmxzLlBheW1lbnRWb3VjaGVyLlJlbW92ZSxcbiAgICAgICAgICAgIHR5cGUgOiAnUE9TVCcsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGlkOiAkcm93LmRhdGEoJ2lkJylcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgZGF0YVR5cGUgOiAnanNvbicsXG4gICAgICAgICAgICBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgXHQkcm93LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICAkcm93LnJlbW92ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBcdCRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5lcnJvciB8fCBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRyb3cubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHQkcGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHR9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuLyogZ2xvYmFsIFJlc291cmNlcywgVXJscyAqL1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIG9wY3BheW1lbnQgPSByZXF1aXJlKCcuL29wY3BheW1lbnQnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgJHJld2FyZHNQYXltZW50Q29udGFpbmVyID0gJCgnW3BheW1lbnQtbWV0aG9kPVwiUkVXQVJEU19DUkVESVRcIl1baGFzLXJld2FyZHNudW1iZXJdJyk7XG52YXIgJHJld2FyZHNQYXltZW50c0Zvcm0gPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnZm9ybScpO1xudmFyICRyZXdhcmRzUGF5bWVudHNBcHBsaWVkID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJy5yZXdhcmRzLWFwcGxpZWQnKTtcbnZhciAkcmV3YXJkc1BheW1lbnRJbnB1dCA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNOdW1iZXInKTtcbnZhciAkcmV3YXJkc0VtYWlsSW5wdXQgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzRW1haWwnKTtcbnZhciAkcmV3YXJkc1Bob25lTnVtYmVySW5wdXQgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzUGhvbmVOdW1iZXInKTtcbnZhciAkcmV3YXJkc1ppcENvZGVJbnB1dCA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNaaXBDb2RlJyk7XG52YXIgJHJld2FyZHNQYXltZW50U2Vjb25kYXJ5Q29udGFpbmVyID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJy5yZXdhcmRzLXNlY29uZGFyeScpO1xudmFyICRyZXdhcmRzUGF5bWVudFNlY29uZGFyeVNlbGVjdCA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcjcmV3YXJkcy1zZWNvbmRhcnktc2VsZWN0Jyk7XG52YXIgJHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJ3NwYW4uZXJyb3InKTtcbnZhciByZXdhcmRzQ3JlZGl0VmFsaWRhdG9yO1xudmFyIHJld2FyZHNDcmVkaXRSb3dUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXJld2FyZHMtY3JlZGl0LXJvdycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbnZhciByZXdhcmRzQ3JlZGl0UmVjYXB0Y2hhO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhKCkge1xuXHRpZiAobG9hZGVkLlJlY2FwdGNoYSAmJiAkKCcjcmV3YXJkcy1jcmVkaXQtYWRkLWJ1dHRvbicpLmxlbmd0aCA+IDAgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUmV3YXJkc0NyZWRpdCAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0cmV3YXJkc0NyZWRpdFJlY2FwdGNoYSA9IGdyZWNhcHRjaGEucmVuZGVyKCdyZXdhcmRzLWNyZWRpdC1hZGQtYnV0dG9uJywge1xuXHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgY2FsbGJhY2s6IHN1Ym1pdFJld2FyZHNDcmVkaXQsXG5cdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXHRcblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcblxuXHRpZiAoJHJld2FyZHNQYXltZW50U2Vjb25kYXJ5U2VsZWN0LmNsb3Nlc3QoJy5vcGMtc3VtbWFyeScpLmxlbmd0aCA+IDApIHtcblx0XHQkcmV3YXJkc1BheW1lbnRTZWNvbmRhcnlTZWxlY3Quc2VsZWN0bWVudSh7XG5cdFx0XHR3aWR0aDogJzEwMCUnLFxuXHRcdFx0YXBwZW5kVG86ICdbcGF5bWVudC1tZXRob2Q9XCJSRVdBUkRTX0NSRURJVFwiXSAucmV3YXJkcy1zZWNvbmRhcnknLFxuXHRcdFx0Y2hhbmdlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0JHJld2FyZHNQYXltZW50U2Vjb25kYXJ5Q29udGFpbmVyLmF0dHIoJ3NlY29uZGFyeScsIHVpICYmIHVpLml0ZW0gJiYgdWkuaXRlbS52YWx1ZSA/IHVpLml0ZW0udmFsdWUgOiAnJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblx0XG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLnJlc2V0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHJlc2V0U2Vjb25kYXJ5U2VsZWN0KCk7XG5cdH0pO1xuXG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLmFkZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcbiAgICAgICAgaWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLlJlY2FwdGNoYSB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclJld2FyZHNDcmVkaXQgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcbiAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Jld2FyZHNDcmVkaXQuQWRkJyk7IFxuICAgICAgICB9XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ1Jld2FyZHNDcmVkaXQuQWRkJywgZnVuY3Rpb24oZXZlbnQsIGRhdGEpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0aWYgKHBhcnNlRmxvYXQoJCgnW2JhbGFuY2UtZHVlXScpLmZpcnN0KCkuYXR0cignYmFsYW5jZS1kdWUnKSkgPD0gMCkge1xuXHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLlJld2FyZHNDcmVkaXQuTm9CYWxhbmNlRHVlKS5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciByZXdhcmRzU2Vjb25kYXJ5RmFjdG9yID0gJHJld2FyZHNQYXltZW50U2Vjb25kYXJ5Q29udGFpbmVyLmF0dHIoJ3NlY29uZGFyeScpO1xuXHRcdFx0cmV3YXJkc0NyZWRpdFZhbGlkYXRvciA9ICRyZXdhcmRzUGF5bWVudHNGb3JtLnZhbGlkYXRlKCk7XG4gICAgICAgICAgICAkcmV3YXJkc1BheW1lbnRJbnB1dC5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJld2FyZHNDcmVkaXQuTnVtYmVyKTtcblxuXHRcdFx0c3dpdGNoIChyZXdhcmRzU2Vjb25kYXJ5RmFjdG9yKSB7XG5cdFx0XHRcdGNhc2UgXCJ6aXBjb2RlXCI6XG5cdFx0XHRcdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCd6aXBDb2RlJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVppcENvZGUsIFJlc291cmNlcy5JTlZBTElEX1BPU1RBTF9DT0RFKTtcblx0XHRcdFx0XHQkcmV3YXJkc1ppcENvZGVJbnB1dC5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlppcENvZGUpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cbiAgICAgICAgICAgIHJld2FyZHNDcmVkaXRWYWxpZGF0b3IuZm9ybSgpO1xuXG5cdFx0XHQvLyBBZGRpbmcgQURBIGNvbXBsaWFuY2UgZXJyb3IgbWVzc2FnZXMgZm9yIGdpZnRDYXJkUGF5bWVudCBzZWN0aW9uXG4gICAgICAgICAgICBpZiAoJHJld2FyZHNQYXltZW50c0Zvcm0uZmluZCgnLmZpZWxkLmVycm9yJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkKCcucGF5bWVudC1kZWNsaW5lZCcpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHZhciByZXdhcmRzUGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzID0gb3BjcGF5bWVudC5nZXRFcnJvck1lc3NhZ2VzKCRyZXdhcmRzUGF5bWVudHNGb3JtKTtcbiAgICAgICAgICAgICAgICB2YXIgcmV3YXJkc1BheW1lbnRGb3JtRXJyb3JCb3ggPSBvcGNwYXltZW50LmVycm9yQm94KCdDYW5ub3QgUHJvY2VlZCcsICdQbGVhc2UgZml4IHRoZSBmb2xsb3dpbmcgZXJyb3JzOicsIHJld2FyZHNQYXltZW50Rm9ybUVycm9yTWVzc2FnZXMpO1xuICAgICAgICAgICAgICAgIGlmIChyZXdhcmRzUGF5bWVudEZvcm1FcnJvckJveCkge1xuICAgICAgICAgICAgICAgICAgICAkcmV3YXJkc1BheW1lbnRzQXBwbGllZC5hZnRlcihyZXdhcmRzUGF5bWVudEZvcm1FcnJvckJveCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXHRcdFx0XG4gICAgICAgICAgICBpZiAoVXJscyAmJiBVcmxzLmNoZWNrUmV3YXJkcyAmJiByZXdhcmRzQ3JlZGl0VmFsaWRhdG9yLnZhbGlkKCkpIHtcbiAgICAgICAgICAgIFx0JHJld2FyZHNQYXltZW50c0Zvcm0uaGlkZSgpO1xuICAgICAgICAgICAgXHRcblx0XHRcdFx0dmFyICRyZXdhcmRzQ3JlZGl0Um93ID0gJChyZXdhcmRzQ3JlZGl0Um93VGVtcGxhdGUoKSk7XG5cdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93ID0gJHJld2FyZHNDcmVkaXRSb3cuYXBwZW5kVG8oJHJld2FyZHNQYXltZW50c0FwcGxpZWQpO1xuXHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAncGVuZGluZycpO1xuXHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYmFza2V0UmV3YXJkTnVtYmVyJykuaHRtbCh1dGlsLmdldE1hc2tlZE51bWJlcigkcmV3YXJkc1BheW1lbnRJbnB1dC52YWwoKSwgNCwgJ3h4eHguLi4gJykpO1xuXHRcblx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKHtMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuUmV3YXJkc0NyZWRpdC5Mb2FkaW5nfSk7XG5cdFxuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybDogZGF0YSAmJiBkYXRhLlJlZ2lzdGVyZWQgPyBVcmxzLmNoZWNrUmV3YXJkc0ZvclJlZ2lzdGVyZWQgOiBVcmxzLmNoZWNrUmV3YXJkcyxcblx0XHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0Y3NyZl90b2tlbjogICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0cmV3YXJkc051bWJlcjogJHJld2FyZHNQYXltZW50SW5wdXQudmFsKCksXG5cdFx0XHRcdFx0XHRyZXdhcmRzRW1haWw6ICRyZXdhcmRzRW1haWxJbnB1dC52YWwoKSxcblx0XHRcdFx0XHRcdHJld2FyZHNQaG9uZU51bWJlcjogJHJld2FyZHNQaG9uZU51bWJlcklucHV0LnZhbCgpLFxuXHRcdFx0XHRcdFx0cmV3YXJkc1ppcENvZGU6ICRyZXdhcmRzWmlwQ29kZUlucHV0LnZhbCgpXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cdFxuXHRcdFx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG5bbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoJHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHNbbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEuZXJyb3IgIT09ICd1bmRlZmluZWQnICYmIGRhdGEuZXJyb3IgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5lcnJvck1zZykuc2hvdygpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhICYmIHBhcnNlRmxvYXQoZGF0YS5jcmVkaXRBbW91bnQpIDw9IDApIHtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1yZXdhcmRzbnVtYmVyJywgJ3RydWUnKTtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ21lc3NhZ2UnKTtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLm1lc3NhZ2UnKS5odG1sKFJlc291cmNlcy5SZXdhcmRzQ3JlZGl0Lk5vQmFsYW5jZUF2YWlsYWJsZSk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGRhdGEgJiYgZGF0YS5jcmVkaXRBbW91bnRGb3JtYXR0ZWQpIHtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1yZXdhcmRzbnVtYmVyJywgJ3RydWUnKTtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZEFtb3VudCcpLmh0bWwoZGF0YS5jcmVkaXRBbW91bnRGb3JtYXR0ZWQucmVwbGFjZSgnLjAwJywgJycpKTtcblx0XHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmV4cGlyYXRpb24tZGF0ZScpLmh0bWwoZGF0YS5jcmVkaXRFeHBpcmF0aW9uRGF0ZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmIChyZXdhcmRzQ3JlZGl0UmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHJld2FyZHNDcmVkaXRSZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAocmV3YXJkc0NyZWRpdFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZXdhcmRzQ3JlZGl0UmVjYXB0Y2hhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcbiAgICAgICAgICAgIH1cblx0XHR9XG5cdH0pO1xuXG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLmFwcGx5JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICRyZXdhcmRzQ3JlZGl0Um93ID0gJCh0aGlzKS5jbG9zZXN0KCcucmV3YXJkLXJvdycpO1xuXG5cdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoe0xhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5SZXdhcmRzQ3JlZGl0LkFwcGx5aW5nfSk7XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLmFwcGx5UmV3YXJkcyxcblx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0Y3NyZl90b2tlbjogICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0XHRyZXdhcmRzTnVtYmVyOiAkcmV3YXJkc1BheW1lbnRJbnB1dC52YWwoKSxcblx0XHRcdFx0cmV3YXJkc0VtYWlsOiAkcmV3YXJkc0VtYWlsSW5wdXQudmFsKCksXG5cdFx0XHRcdHJld2FyZHNQaG9uZU51bWJlcjogJHJld2FyZHNQaG9uZU51bWJlcklucHV0LnZhbCgpLFxuXHRcdFx0XHRyZXdhcmRzWmlwQ29kZTogJHJld2FyZHNaaXBDb2RlSW5wdXQudmFsKClcblx0XHRcdH0sXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHRcdFx0XHRpZiAoJHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bltsb2FkaW5nXScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICgkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9sc1tsb2FkaW5nXScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChkYXRhLmVycm9yICE9PSAndW5kZWZpbmVkJyAmJiBkYXRhLmVycm9yID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ21lc3NhZ2UnKTtcblx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LnJlbW92ZSgpO1xuXHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLmVycm9yTXNnKS5zaG93KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ2FwcGxpZWQnKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYmFza2V0UmV3YXJkTnVtYmVyJykuaHRtbCh1dGlsLmdldE1hc2tlZE51bWJlcihkYXRhLnJld2FyZHNOdW1iZXIsIDQsICd4eHh4Li4uICcpKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYmFza2V0UmV3YXJkQW1vdW50JykuaHRtbChkYXRhLnJld2FyZHNDcmVkaXRVc2VkRm9ybWF0dGVkKS5hdHRyKCdsYWJlbCcsIFJlc291cmNlcy5SZXdhcmRzQ3JlZGl0LlJld2FyZEFwcGxpZWQpO1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5leHBpcmF0aW9uLWRhdGUnKS5odG1sKGRhdGEuY3JlZGl0RXhwaXJhdGlvbkRhdGUpO1xuXG5cdFx0XHRcdFx0dmFyIGRhdGFPYmplY3QgPSB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogZGF0YS5yZXdhcmRzQ3JlZGl0VXNlZCxcblx0XHRcdFx0XHRcdHBheW1lbnRfdHlwZTogJ0IgUmV3YXJkZWQnXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFBheW1lbnRJbmZvJywgZGF0YU9iamVjdCk7XG5cdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ21lc3NhZ2UnKTtcblx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdFx0cmVzZXRGb3JtKHRydWUpO1xuXHRcdFx0fSxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2sgUmV3YXJkc0NyZWRpdC5SZW1vdmUnLCAnLnJlbW92ZScsIGZ1bmN0aW9uKGV2ZW50LCBkYXRhKSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkcmV3YXJkc0NyZWRpdFJvdyA9ICQodGhpcykuY2xvc2VzdCgnLnJld2FyZC1yb3cnKTtcblx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZyh7SXNMYWJlbFNob3duOiBmYWxzZX0pO1xuXHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZyh7TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLlJld2FyZHNDcmVkaXQuUmVtb3Zpbmd9KTtcblxuXHRcdHZhciBwYXlsb2FkID0ge1xuXHRcdFx0cmV3YXJkc051bWJlcjogJCgnaW5wdXQjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNOdW1iZXInKS52YWwoKVxuXHRcdH1cblxuXHRcdGlmIChkYXRhICYmIGRhdGEuUmVzZXRTZXNzaW9uRGF0YSkge1xuXHRcdFx0cGF5bG9hZC5yZXNldFNlc3Npb25EYXRhID0gdHJ1ZVxuXHRcdH1cblxuXHRcdCQuYWpheCh7XG5cdFx0XHR1cmw6IFVybHMucmVtb3ZlUmV3YXJkcyxcblx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cblx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG5bbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoJHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHNbbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1yZXdhcmRzbnVtYmVyJykgIT09ICd0cnVlJykge1xuXHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudElucHV0LnZhbCgnJyk7XG5cdFx0XHRcdFx0JHJld2FyZHNQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdmb3JtJyk7XG5cdFx0XHRcdFx0JHJld2FyZHNQYXltZW50c0FwcGxpZWQuaHRtbCgnJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ3BlbmRpbmcnKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYmFza2V0UmV3YXJkQW1vdW50JykuYXR0cignbGFiZWwnLCBSZXNvdXJjZXMuUmV3YXJkc0NyZWRpdC5SZXdhcmQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdFx0fSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG5bbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoJHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHNbbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblx0XG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLmNoYW5nZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcblx0XHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIuYXR0cignaGFzLXJld2FyZHNudW1iZXInLCAnZmFsc2UnKTtcblx0XHRpZiAoJHJld2FyZHNQYXltZW50c0FwcGxpZWQuZmluZCgnLnJld2FyZC1yb3cnKS5hdHRyKCdzdGF0dXMnKSA9PT0gJ2FwcGxpZWQnKSB7XG5cdFx0XHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnLnJlbW92ZScpLnRyaWdnZXIoJ1Jld2FyZHNDcmVkaXQuUmVtb3ZlJyk7XG5cdFx0fVxuXHRcdHJlc2V0Rm9ybSgpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ21vdXNlZG93bi5SZXdhcmRzQ3JlZGl0UGF5bWVudFBhbmVsJykub24oJ21vdXNlZG93bi5SZXdhcmRzQ3JlZGl0UGF5bWVudFBhbmVsJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChyZXdhcmRzQ3JlZGl0VmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCRyZXdhcmRzUGF5bWVudENvbnRhaW5lcikubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJld2FyZHNDcmVkaXRWYWxpZGF0b3IucmVzZXRGb3JtKCk7XG4gICAgICAgICAgICAkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignUmV3YXJkc0NyZWRpdC5DbGVhcicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRyZXNldEZvcm0oKTtcblx0fSk7XG5cblx0JHJld2FyZHNQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcucmVzZXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JHJld2FyZHNQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdCRyZXdhcmRzUGhvbmVOdW1iZXJJbnB1dC52YWwoJycpO1xuXHRcdCRyZXdhcmRzWmlwQ29kZUlucHV0LnZhbCgnJyk7XG5cdH0pO1xuXHRcblx0aWYgKCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtcmV3YXJkc251bWJlcicpID09PSAndHJ1ZScgJiYgJHJld2FyZHNQYXltZW50c0FwcGxpZWQuZmluZCgnLnJld2FyZC1yb3cnKS5sZW5ndGggPT0gMCAmJiAkKCdbY2hlY2tvdXQtbW9kZV0nKS5hdHRyKCdjaGVja291dC1tb2RlJykgIT0gJ2VjaG8nKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmV3YXJkc0NyZWRpdC5BZGQnLCB7IFJlZ2lzdGVyZWQ6IHRydWUgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVzZXRGb3JtKHNob3dFcnJvck1lc3NhZ2UpIHtcblx0aWYgKHJld2FyZHNDcmVkaXRWYWxpZGF0b3IpIHtcblx0XHRyZXdhcmRzQ3JlZGl0VmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuXHR9XG5cdFxuXHRpZiAoIXNob3dFcnJvck1lc3NhZ2UpIHtcblx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHR9XG5cdFxuXHR2YXIgJHJld2FyZHNDcmVkaXRSb3cgPSAkcmV3YXJkc1BheW1lbnRzQXBwbGllZC5maW5kKCcucmV3YXJkLXJvdycpO1xuXHRpZiAoJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1yZXdhcmRzbnVtYmVyJykgIT09ICd0cnVlJykge1xuXHRcdCRyZXdhcmRzUGF5bWVudElucHV0LnZhbCgnJyk7XG5cdFx0JHJld2FyZHNQaG9uZU51bWJlcklucHV0LnZhbCgnJyk7XG5cdFx0JHJld2FyZHNaaXBDb2RlSW5wdXQudmFsKCcnKTtcblx0XHRcblx0XHQkcmV3YXJkc1BheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0JHJld2FyZHNQYXltZW50c0FwcGxpZWQuaHRtbCgnJyk7XG5cdH0gZWxzZSB7XG5cdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZEFtb3VudCcpLmF0dHIoJ2xhYmVsJywgUmVzb3VyY2VzLlJld2FyZHNDcmVkaXQuUmV3YXJkKTtcblx0fVxuXG5cdHJlc2V0U2Vjb25kYXJ5U2VsZWN0KCk7XG59XG5cbmZ1bmN0aW9uIHJlc2V0U2Vjb25kYXJ5U2VsZWN0KCkge1xuXHQkcmV3YXJkc1BheW1lbnRTZWNvbmRhcnlTZWxlY3QucHJvcCgnc2VsZWN0ZWRJbmRleCcsIDApO1xuXHRpZiAoJHJld2FyZHNQYXltZW50U2Vjb25kYXJ5U2VsZWN0LmNsb3Nlc3QoJy5vcGMtc3VtbWFyeScpLmxlbmd0aCA+IDApIHtcblx0XHQkcmV3YXJkc1BheW1lbnRTZWNvbmRhcnlTZWxlY3Quc2VsZWN0bWVudSgncmVmcmVzaCcpO1xuXHR9XG5cdCRyZXdhcmRzUGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknLCAnJyk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBzaGlwcGluZyA9IHJlcXVpcmUoJy4vc2hpcHBpbmcnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBTZWxlY3RzIHRoZSBmaXJzdCBhZGRyZXNzIGZyb20gdGhlIGxpc3Qgb2YgYWRkcmVzc2VzXG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGZvcm0gPSAkKCcuYWRkcmVzcycpO1xuICAgIC8vIHNlbGVjdCBhZGRyZXNzIGZyb20gbGlzdFxuICAgICQoJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzTGlzdFwiXScsICRmb3JtKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSAkKHRoaXMpLmNoaWxkcmVuKCc6c2VsZWN0ZWQnKS5maXJzdCgpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzID0gJChzZWxlY3RlZCkuZGF0YSgnYWRkcmVzcycpO1xuICAgICAgICBpZiAoIXNlbGVjdGVkQWRkcmVzcykgeyByZXR1cm47IH1cbiAgICAgICAgdXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3MsICRmb3JtKTtcbiAgICAgICAgc2hpcHBpbmcudXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCk7XG4gICAgICAgIC8vIHJlLXZhbGlkYXRlIHRoZSBmb3JtXG4gICAgICAgICRmb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4Jyk7XG52YXIgZm9ybVByZXBhcmUgPSByZXF1aXJlKCcuL2Zvcm1QcmVwYXJlJyk7XG52YXIgZ2lmdGNhcmQgPSByZXF1aXJlKCcuLi8uLi9naWZ0Y2FyZCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbnZhciBQYXltZW50TWV0aG9kQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9QYXltZW50SW5zdHJ1bWVudENvbnN0YW50cycpLlBheW1lbnRNZXRob2RzO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEZpbGxzIHRoZSBDcmVkaXQgQ2FyZCBmb3JtIHdpdGggdGhlIHBhc3NlZCBkYXRhLXBhcmFtZXRlciBhbmQgY2xlYXJzIHRoZSBmb3JtZXIgY3ZuIGlucHV0XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSBUaGUgQ3JlZGl0IENhcmQgZGF0YSAoaG9sZGVyLCB0eXBlLCBtYXNrZWQgbnVtYmVyLCBleHBpcmF0aW9uIG1vbnRoL3llYXIpXG4gKi9cbmZ1bmN0aW9uIHNldENDRmllbGRzKGRhdGEpIHtcbiAgICB2YXIgJGNyZWRpdENhcmQgPSAkKCdbZGF0YS1tZXRob2Q9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXScpO1xuICAgICRjcmVkaXRDYXJkLmZpbmQoJ2lucHV0W25hbWUkPVwiY3JlZGl0Q2FyZF9vd25lclwiXScpLnZhbChkYXRhLmhvbGRlcikudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnc2VsZWN0W25hbWUkPVwiX3R5cGVcIl0nKS52YWwoZGF0YS50eXBlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAkY3JlZGl0Q2FyZC5maW5kKCdpbnB1dFtuYW1lKj1cIl9jcmVkaXRDYXJkX251bWJlclwiXScpLnZhbChkYXRhLm1hc2tlZE51bWJlcikudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnW25hbWUkPVwiX21vbnRoXCJdJykudmFsKGRhdGEuZXhwaXJhdGlvbk1vbnRoKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAkY3JlZGl0Q2FyZC5maW5kKCdbbmFtZSQ9XCJfeWVhclwiXScpLnZhbChkYXRhLmV4cGlyYXRpb25ZZWFyKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAkY3JlZGl0Q2FyZC5maW5kKCdpbnB1dFtuYW1lJD1cIl9jdm5cIl0nKS52YWwoJycpLnRyaWdnZXIoJ2NoYW5nZScpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIGNyZWRpdCBjYXJkIGZvcm0gd2l0aCB0aGUgYXR0cmlidXRlcyBvZiBhIGdpdmVuIGNhcmRcbiAqIEBwYXJhbSB7U3RyaW5nfSBjYXJkSUQgdGhlIGNyZWRpdCBjYXJkIElEIG9mIGEgZ2l2ZW4gY2FyZFxuICovXG5mdW5jdGlvbiBwb3B1bGF0ZUNyZWRpdENhcmRGb3JtKGNhcmRJRCkge1xuICAgIC8vIGxvYWQgY2FyZCBkZXRhaWxzXG4gICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChVcmxzLmJpbGxpbmdTZWxlY3RDQywgJ2NyZWRpdENhcmRVVUlEJywgY2FyZElEKTtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkNDX0xPQURfRVJST1IpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldENDRmllbGRzKGRhdGEpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cblxuZnVuY3Rpb24gcG9wdWxhdGVQcml2YXRlTGFiZWxDYXJkRm9ybShjYXJkSUQpIHtcbiAgICAvLyBsb2FkIGNhcmQgZGV0YWlsc1xuICAgIHZhciB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoVXJscy5iaWxsaW5nU2VsZWN0UHJpdmF0ZUxhYmVsLCAnY3JlZGl0Q2FyZFVVSUQnLCBjYXJkSUQpO1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQ0NfTE9BRF9FUlJPUik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyICRwcml2YXRlTGFiZWxDYXJkID0gJCgnW2RhdGEtbWV0aG9kPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQWxsaWFuY2VEYXRhICsgJ1wiXScpO1xuICAgICAgICAgICAgJHByaXZhdGVMYWJlbENhcmQuZmluZCgnaW5wdXRbbmFtZSo9XCJfcHJpdmF0ZUxhYmVsQ3JlZGl0X251bWJlclwiXScpLnZhbChkYXRhLm1hc2tlZE51bWJlcikudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIENoYW5nZXMgdGhlIHBheW1lbnQgbWV0aG9kIGZvcm0gZGVwZW5kaW5nIG9uIHRoZSBwYXNzZWQgcGF5bWVudE1ldGhvZElEXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF5bWVudE1ldGhvZElEIHRoZSBJRCBvZiB0aGUgcGF5bWVudCBtZXRob2QsIHRvIHdoaWNoIHRoZSBwYXltZW50IG1ldGhvZCBmb3JtIHNob3VsZCBiZSBjaGFuZ2VkIHRvXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVBheW1lbnRNZXRob2QocGF5bWVudE1ldGhvZElEKSB7XG4gICAgdmFyICRwYXltZW50TWV0aG9kcyA9ICQoJy5wYXltZW50LW1ldGhvZCcpO1xuICAgICRwYXltZW50TWV0aG9kcy5yZW1vdmVDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKTtcblxuICAgIHZhciAkc2VsZWN0ZWRQYXltZW50TWV0aG9kID0gJHBheW1lbnRNZXRob2RzLmZpbHRlcignW2RhdGEtbWV0aG9kPVwiJyArIHBheW1lbnRNZXRob2RJRCArICdcIl0nKTtcbiAgICBpZiAoJHNlbGVjdGVkUGF5bWVudE1ldGhvZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgJHNlbGVjdGVkUGF5bWVudE1ldGhvZCA9ICQoJ1tkYXRhLW1ldGhvZD1cIkN1c3RvbVwiXScpO1xuICAgIH1cbiAgICAkc2VsZWN0ZWRQYXltZW50TWV0aG9kLmFkZENsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpO1xuXG4gICAgLy8gZW5zdXJlIGNoZWNrYm94IG9mIHBheW1lbnQgbWV0aG9kIGlzIGNoZWNrZWRcbiAgICAkKCdpbnB1dFtuYW1lJD1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKTtcbiAgICAkKCdpbnB1dFt2YWx1ZT0nICsgcGF5bWVudE1ldGhvZElEICsgJ10nKS5wcm9wKCdjaGVja2VkJywgJ2NoZWNrZWQnKTtcblxuICAgIGZvcm1QcmVwYXJlLnZhbGlkYXRlRm9ybSgpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGxvYWRzIGJpbGxpbmcgYWRkcmVzcywgR2lmdCBDZXJ0aWZpY2F0ZXMsIENvdXBvbiBhbmQgUGF5bWVudCBtZXRob2RzXG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGNoZWNrb3V0Rm9ybSA9ICQoJy5jaGVja291dC1iaWxsaW5nJyk7XG4gICAgdmFyICRhZGRHaWZ0Q2VydCA9ICQoJyNhZGQtZ2lmdGNlcnQnKTtcbiAgICB2YXIgJGdpZnRDZXJ0Q29kZSA9ICQoJ2lucHV0W25hbWUkPVwiX2dpZnRDZXJ0Q29kZVwiXScpO1xuICAgIHZhciAkYWRkQ291cG9uID0gJCgnI2FkZC1jb3Vwb24nKTtcbiAgICB2YXIgJGNvdXBvbkNvZGUgPSAkKCdpbnB1dFtuYW1lJD1cIl9jb3Vwb25Db2RlXCJdJyk7XG4gICAgdmFyICRzZWxlY3RQYXltZW50TWV0aG9kID0gJCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbnMnKTtcbiAgICB2YXIgc2VsZWN0ZWRQYXltZW50TWV0aG9kID0gJHNlbGVjdFBheW1lbnRNZXRob2QuZmluZCgnOmNoZWNrZWQnKS52YWwoKTtcblxuICAgIGZvcm1QcmVwYXJlLmluaXQoe1xuICAgICAgICBmb3JtU2VsZWN0b3I6ICdmb3JtW2lkJD1cImJpbGxpbmdcIl0nLFxuICAgICAgICBjb250aW51ZVNlbGVjdG9yOiAnW25hbWUkPVwiYmlsbGluZ19zYXZlXCJdJ1xuICAgIH0pO1xuXG4gICAgLy8gZGVmYXVsdCBwYXltZW50IG1ldGhvZCB0byAnQ1JFRElUX0NBUkQnXG4gICAgdXBkYXRlUGF5bWVudE1ldGhvZCgoc2VsZWN0ZWRQYXltZW50TWV0aG9kKSA/IHNlbGVjdGVkUGF5bWVudE1ldGhvZCA6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCk7XG4gICAgJHNlbGVjdFBheW1lbnRNZXRob2Qub24oJ2NsaWNrJywgJ2lucHV0W3R5cGU9XCJyYWRpb1wiXScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdXBkYXRlUGF5bWVudE1ldGhvZCgkKHRoaXMpLnZhbCgpKTtcbiAgICB9KTtcblxuICAgIC8vIHNlbGVjdCBjcmVkaXQgY2FyZCBmcm9tIGxpc3RcbiAgICB2YXIgJGNyZWRpdENhcmRMaXN0ID0gJCgnI2NyZWRpdENhcmRMaXN0Jyk7XG4gICAgJGNyZWRpdENhcmRMaXN0Lm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYXJkVVVJRCA9ICQodGhpcykudmFsKCk7XG4gICAgICAgIGlmICghY2FyZFVVSUQpIHtyZXR1cm47fVxuICAgICAgICBwb3B1bGF0ZUNyZWRpdENhcmRGb3JtKGNhcmRVVUlEKTtcblxuICAgICAgICAvLyByZW1vdmUgc2VydmVyIHNpZGUgZXJyb3JcbiAgICAgICAgJCgnLnJlcXVpcmVkLmVycm9yJykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICQoJy5lcnJvci1tZXNzYWdlJykucmVtb3ZlKCk7XG4gICAgfSk7XG4gICAgXG4gICAgLy9wcmVzZWxlY3QgZGVmYXVsdCBjcmVkaXQgY2FyZFxuICAgIGlmKCRjcmVkaXRDYXJkTGlzdC5sZW5ndGggPiAwKXtcblx0XHQkY3JlZGl0Q2FyZExpc3QuZmluZCgnb3B0aW9uJykuZXEoMSkucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHQkY3JlZGl0Q2FyZExpc3QudHJpZ2dlcignY2hhbmdlJyk7XG5cdH1cblxuICAgIFxuICAgIC8vIHNlbGVjdCBwcml2YXRlIGxhYmVsIGNhcmQgZnJvbSBsaXN0XG4gICAgdmFyICRwcml2YXRlTGFiZWxDYXJkTGlzdCA9ICQoJyNwcml2YXRlTGFiZWxDYXJkTGlzdCcpO1xuICAgICRwcml2YXRlTGFiZWxDYXJkTGlzdC5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2FyZFVVSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoIWNhcmRVVUlEKSB7cmV0dXJuO31cbiAgICAgICAgcG9wdWxhdGVQcml2YXRlTGFiZWxDYXJkRm9ybShjYXJkVVVJRCk7XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNlcnZlciBzaWRlIGVycm9yXG4gICAgICAgICQoJy5yZXF1aXJlZC5lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgICAgICAkKCcuZXJyb3ItbWVzc2FnZScpLnJlbW92ZSgpO1xuICAgIH0pO1xuXG4gICAgLy8gcHJlc2VsZWN0IGRlZmF1bHQgcHJpdmF0ZSBsYWJlbCBjYXJkXG4gICAgaWYoJHByaXZhdGVMYWJlbENhcmRMaXN0Lmxlbmd0aCA+IDApe1xuICAgIFx0JHByaXZhdGVMYWJlbENhcmRMaXN0LmZpbmQoJ29wdGlvbicpLmVxKDEpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG4gICAgXHQkcHJpdmF0ZUxhYmVsQ2FyZExpc3QudHJpZ2dlcignY2hhbmdlJyk7XG5cdH0gXG4gICAgXG4gICAgJCgnI2NoZWNrLWdpZnRjZXJ0Jykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgJGJhbGFuY2UgPSAkKCcuYmFsYW5jZScpO1xuICAgICAgICBpZiAoJGdpZnRDZXJ0Q29kZS5sZW5ndGggPT09IDAgfHwgJGdpZnRDZXJ0Q29kZS52YWwoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHZhciBlcnJvciA9ICRiYWxhbmNlLmZpbmQoJ3NwYW4uZXJyb3InKTtcbiAgICAgICAgICAgIGlmIChlcnJvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBlcnJvciA9ICQoJzxzcGFuPicpLmFkZENsYXNzKCdlcnJvcicpLmFwcGVuZFRvKCRiYWxhbmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVycm9yLmh0bWwoUmVzb3VyY2VzLkdJRlRfQ0VSVF9NSVNTSU5HKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGdpZnRjYXJkLmNoZWNrQmFsYW5jZSgkZ2lmdENlcnRDb2RlLnZhbCgpLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmdpZnRDZXJ0aWZpY2F0ZSkge1xuICAgICAgICAgICAgICAgICRiYWxhbmNlLmh0bWwoUmVzb3VyY2VzLkdJRlRfQ0VSVF9JTlZBTElEKS5yZW1vdmVDbGFzcygnc3VjY2VzcycpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRiYWxhbmNlLmh0bWwoUmVzb3VyY2VzLkdJRlRfQ0VSVF9CQUxBTkNFICsgJyAnICsgZGF0YS5naWZ0Q2VydGlmaWNhdGUuYmFsYW5jZSkucmVtb3ZlQ2xhc3MoJ2Vycm9yJykuYWRkQ2xhc3MoJ3N1Y2Nlc3MnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAkYWRkR2lmdENlcnQub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgY29kZSA9ICRnaWZ0Q2VydENvZGUudmFsKCksXG4gICAgICAgICAgICAkZXJyb3IgPSAkY2hlY2tvdXRGb3JtLmZpbmQoJy5naWZ0Y2VydC1lcnJvcicpO1xuICAgICAgICBpZiAoY29kZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICRlcnJvci5odG1sKFJlc291cmNlcy5HSUZUX0NFUlRfTUlTU0lORyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLnJlZGVlbUdpZnRDZXJ0LCB7Z2lmdENlcnRDb2RlOiBjb2RlLCBmb3JtYXQ6ICdhamF4J30pO1xuICAgICAgICAkLmdldEpTT04odXJsLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgdmFyIGZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBtc2cgPSAnJztcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIG1zZyA9IFJlc291cmNlcy5CQURfUkVTUE9OU0U7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSBkYXRhLm1lc3NhZ2Uuc3BsaXQoJzwnKS5qb2luKCcmbHQ7Jykuc3BsaXQoJz4nKS5qb2luKCcmZ3Q7Jyk7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmFpbCkge1xuICAgICAgICAgICAgICAgICRlcnJvci5odG1sKG1zZyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uYXNzaWduKFVybHMuYmlsbGluZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGFkZENvdXBvbi5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciAkZXJyb3IgPSAkY2hlY2tvdXRGb3JtLmZpbmQoJy5jb3Vwb24tZXJyb3InKSxcbiAgICAgICAgICAgIGNvZGUgPSAkY291cG9uQ29kZS52YWwoKTtcbiAgICAgICAgaWYgKGNvZGUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAkZXJyb3IuaHRtbChSZXNvdXJjZXMuQ09VUE9OX0NPREVfTUlTU0lORyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmFkZENvdXBvbiwge2NvdXBvbkNvZGU6IGNvZGUsIGZvcm1hdDogJ2FqYXgnfSk7XG4gICAgICAgICQuZ2V0SlNPTih1cmwsIGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICB2YXIgZmFpbCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIG1zZyA9ICcnO1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gUmVzb3VyY2VzLkJBRF9SRVNQT05TRTtcbiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIG1zZyA9IGRhdGEubWVzc2FnZS5zcGxpdCgnPCcpLmpvaW4oJyZsdDsnKS5zcGxpdCgnPicpLmpvaW4oJyZndDsnKTtcbiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmYWlsKSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmh0bWwobXNnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vYmFza2V0IGNoZWNrIGZvciBkaXNwbGF5aW5nIHRoZSBwYXltZW50IHNlY3Rpb24sIGlmIHRoZSBhZGp1c3RlZCB0b3RhbCBvZiB0aGUgYmFza2V0IGlzIDAgYWZ0ZXIgYXBwbHlpbmcgdGhlIGNvdXBvblxuICAgICAgICAgICAgLy90aGlzIHdpbGwgZm9yY2UgYSBwYWdlIHJlZnJlc2ggdG8gZGlzcGxheSB0aGUgY291cG9uIG1lc3NhZ2UgYmFzZWQgb24gYSBwYXJhbWV0ZXIgbWVzc2FnZVxuICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2VzcyAmJiBkYXRhLmJhc2tldHRvdGFsID09PSAwKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmFzc2lnbihVcmxzLmJpbGxpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIHRyaWdnZXIgZXZlbnRzIG9uIGVudGVyXG4gICAgJGNvdXBvbkNvZGUub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS53aGljaCA9PT0gMTMpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICRhZGRDb3Vwb24uY2xpY2soKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgICRnaWZ0Q2VydENvZGUub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS53aGljaCA9PT0gMTMpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICRhZGRHaWZ0Q2VydC5jbGljaygpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xuXG52YXIgJGZvcm0sICRjb250aW51ZSwgJHJlcXVpcmVkSW5wdXRzLCB2YWxpZGF0b3I7XG5cbnZhciBoYXNFbXB0eVJlcXVpcmVkID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIGZpbHRlciBvdXQgb25seSB0aGUgdmlzaWJsZSBmaWVsZHNcbiAgICB2YXIgcmVxdWlyZWRWYWx1ZXMgPSAkcmVxdWlyZWRJbnB1dHMuZmlsdGVyKCc6dmlzaWJsZScpLm1hcChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAkKHRoaXMpLnZhbCgpO1xuICAgIH0pO1xuICAgIHJldHVybiBfKHJlcXVpcmVkVmFsdWVzKS5jb250YWlucygnJyk7XG59O1xuXG52YXIgdmFsaWRhdGVGb3JtID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIG9ubHkgdmFsaWRhdGUgZm9ybSB3aGVuIGFsbCByZXF1aXJlZCBmaWVsZHMgYXJlIGZpbGxlZCB0byBhdm9pZFxuICAgIC8vIHRocm93aW5nIGVycm9ycyBvbiBlbXB0eSBmb3JtXG4gICAgaWYgKCF2YWxpZGF0b3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWhhc0VtcHR5UmVxdWlyZWQoKSkge1xuICAgICAgICBpZiAodmFsaWRhdG9yLmZvcm0oKSkge1xuICAgICAgICAgICAgJGNvbnRpbnVlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICAkY29udGludWUuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9XG59O1xuXG52YXIgdmFsaWRhdGVFbCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoJCh0aGlzKS52YWwoKSA9PT0gJycpIHtcbiAgICAgICAgJGNvbnRpbnVlLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZW5hYmxlIGNvbnRpbnVlIGJ1dHRvbiBvbiBsYXN0IHJlcXVpcmVkIGZpZWxkIHRoYXQgaXMgdmFsaWRcbiAgICAgICAgLy8gb25seSB2YWxpZGF0ZSBzaW5nbGUgZmllbGRcbiAgICAgICAgaWYgKHZhbGlkYXRvci5lbGVtZW50KHRoaXMpICYmICFoYXNFbXB0eVJlcXVpcmVkKCkpIHtcbiAgICAgICAgICAgICRjb250aW51ZS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGNvbnRpbnVlLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgaW5pdCA9IGZ1bmN0aW9uIChvcHRzKSB7XG4gICAgaWYgKCFvcHRzLmZvcm1TZWxlY3RvciB8fCAhb3B0cy5jb250aW51ZVNlbGVjdG9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBmb3JtIGFuZCBjb250aW51ZSBhY3Rpb24gc2VsZWN0b3JzLicpO1xuICAgIH1cbiAgICAkZm9ybSA9ICQob3B0cy5mb3JtU2VsZWN0b3IpO1xuICAgICRjb250aW51ZSA9ICQob3B0cy5jb250aW51ZVNlbGVjdG9yKTtcbiAgICB2YWxpZGF0b3IgPSAkZm9ybS52YWxpZGF0ZSgpO1xuICAgICRyZXF1aXJlZElucHV0cyA9ICQoJy5yZXF1aXJlZCcsICRmb3JtKS5maW5kKCc6aW5wdXQnKTtcbiAgICB2YWxpZGF0ZUZvcm0oKTtcbiAgICAvLyBzdGFydCBsaXN0ZW5pbmdcbiAgICAkcmVxdWlyZWRJbnB1dHMub24oJ2NoYW5nZScsIHZhbGlkYXRlRWwpO1xuICAgICRyZXF1aXJlZElucHV0cy5maWx0ZXIoJ2lucHV0Jykub24oJ2tleXVwJywgXy5kZWJvdW5jZSh2YWxpZGF0ZUVsLCAyMDApKTtcbn07XG5cbmV4cG9ydHMuaW5pdCA9IGluaXQ7XG5leHBvcnRzLnZhbGlkYXRlRm9ybSA9IHZhbGlkYXRlRm9ybTtcbmV4cG9ydHMudmFsaWRhdGVFbCA9IHZhbGlkYXRlRWw7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhZGRyZXNzID0gcmVxdWlyZSgnLi9hZGRyZXNzJyksXG4gICAgYmlsbGluZyA9IHJlcXVpcmUoJy4vYmlsbGluZycpLFxuICAgIG11bHRpc2hpcCA9IHJlcXVpcmUoJy4vbXVsdGlzaGlwJyksXG4gICAgc2hpcHBpbmcgPSByZXF1aXJlKCcuL3NoaXBwaW5nJyk7XG5cbi8qKlxuICogQGZ1bmN0aW9uIEluaXRpYWxpemVzIHRoZSBwYWdlIGV2ZW50cyBkZXBlbmRpbmcgb24gdGhlIGNoZWNrb3V0IHN0YWdlIChzaGlwcGluZy9iaWxsaW5nKVxuICovXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgYWRkcmVzcy5pbml0KCk7XG4gICAgaWYgKCQoJy5jaGVja291dC1zaGlwcGluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc2hpcHBpbmcuaW5pdCgpO1xuICAgIH0gZWxzZSBpZiAoJCgnLmNoZWNrb3V0LW11bHRpLXNoaXBwaW5nJykubGVuZ3RoID4gMCkge1xuICAgICAgICBtdWx0aXNoaXAuaW5pdCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGJpbGxpbmcuaW5pdCgpO1xuICAgIH1cblxuICAgIC8vaWYgb24gdGhlIG9yZGVyIHJldmlldyBwYWdlIGFuZCB0aGVyZSBhcmUgcHJvZHVjdHMgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBkaWFibGUgdGhlIHN1Ym1pdCBvcmRlciBidXR0b25cbiAgICBpZiAoJCgnLm9yZGVyLXN1bW1hcnktZm9vdGVyJykubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAoJCgnLm5vdGF2YWlsYWJsZScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICQoJy5vcmRlci1zdW1tYXJ5LWZvb3RlciAuc3VibWl0LW9yZGVyIC5idXR0b24tZmFuY3ktbGFyZ2UnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZHJlc3MgPSByZXF1aXJlKCcuL2FkZHJlc3MnKSxcbiAgICBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vZm9ybVByZXBhcmUnKSxcbiAgICBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGdpZnQgbWVzc2FnZSBib3ggZm9yIG11bHRpc2hpcCBzaGlwcGluZywgdGhlIG1lc3NhZ2UgYm94IHN0YXJ0cyBvZmYgYXMgaGlkZGVuIGFuZCB0aGlzIHdpbGwgZGlzcGxheSBpdCBpZiB0aGUgcmFkaW8gYnV0dG9uIGlzIGNoZWNrZWQgdG8geWVzLCBhbHNvIGFkZGVkIGV2ZW50IGhhbmRsZXIgdG8gbGlzdGVuIGZvciB3aGVuIGEgcmFkaW8gYnV0dG9uIGlzIHByZXNzZWQgdG8gZGlzcGxheSB0aGUgbWVzc2FnZSBib3hcbiAqL1xuZnVuY3Rpb24gaW5pdE11bHRpR2lmdE1lc3NhZ2VCb3goKSB7XG4gICAgJC5lYWNoKCQoJy5pdGVtLWxpc3QnKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICB2YXIgJGdpZnRNZXNzYWdlID0gJHRoaXMuZmluZCgnLmdpZnQtbWVzc2FnZS10ZXh0Jyk7XG5cbiAgICAgICAgLy9oYW5kbGUgaW5pdGlhbCBsb2FkXG4gICAgICAgICRnaWZ0TWVzc2FnZS50b2dnbGVDbGFzcygnaGlkZGVuJywgJCgnaW5wdXRbbmFtZSQ9XCJfaXNHaWZ0XCJdOmNoZWNrZWQnLCB0aGlzKS52YWwoKSAhPT0gJ3RydWUnKTtcblxuICAgICAgICAvL3NldCBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgJHRoaXMub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRnaWZ0TWVzc2FnZS50b2dnbGVDbGFzcygnaGlkZGVuJywgJCgnaW5wdXRbbmFtZSQ9XCJfaXNHaWZ0XCJdOmNoZWNrZWQnLCB0aGlzKS52YWwoKSAhPT0gJ3RydWUnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBjYXB0dXJlIGFkZCBlZGl0IGFkZGRyZXNzIGZvcm0gZXZlbnRzXG4gKi9cbmZ1bmN0aW9uIGFkZEVkaXRBZGRyZXNzKHRhcmdldCkge1xuICAgIHZhciAkYWRkcmVzc0Zvcm0gPSAkKCdmb3JtW25hbWUkPVwibXVsdGlzaGlwcGluZ19lZGl0QWRkcmVzc1wiXScpLFxuICAgICAgICAkYWRkcmVzc0Ryb3Bkb3duID0gJGFkZHJlc3NGb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1fYWRkcmVzc0xpc3RdJyksXG4gICAgICAgICRhZGRyZXNzTGlzdCA9ICRhZGRyZXNzRm9ybS5maW5kKCcuYWRkcmVzcy1saXN0JyksXG4gICAgICAgIGFkZCA9IHRydWUsXG4gICAgICAgIHNlbGVjdGVkQWRkcmVzc1VVSUQgPSAkKHRhcmdldCkucGFyZW50KCkuc2libGluZ3MoJy5zZWxlY3QtYWRkcmVzcycpLnZhbCgpO1xuXG4gICAgJGFkZHJlc3NEcm9wZG93bi5vbignY2hhbmdlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzID0gJGFkZHJlc3NMaXN0LmZpbmQoJ3NlbGVjdCcpLnZhbCgpO1xuICAgICAgICBpZiAoc2VsZWN0ZWRBZGRyZXNzICE9PSAnbmV3QWRkcmVzcycpIHtcbiAgICAgICAgICAgIHNlbGVjdGVkQWRkcmVzcyA9ICQuZ3JlcCgkYWRkcmVzc0xpc3QuZGF0YSgnYWRkcmVzc2VzJyksIGZ1bmN0aW9uIChhZGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWRkLlVVSUQgPT09IHNlbGVjdGVkQWRkcmVzcztcbiAgICAgICAgICAgIH0pWzBdO1xuICAgICAgICAgICAgYWRkID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBwcm9jZWVkIHRvIGZpbGwgdGhlIGZvcm0gd2l0aCB0aGUgc2VsZWN0ZWQgYWRkcmVzc1xuICAgICAgICAgICAgdXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3MsICRhZGRyZXNzRm9ybSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvL3Jlc2V0IHRoZSBmb3JtIGlmIHRoZSB2YWx1ZSBvZiB0aGUgb3B0aW9uIGlzIG5vdCBhIFVVSURcbiAgICAgICAgICAgICRhZGRyZXNzRm9ybS5maW5kKCcuaW5wdXQtdGV4dCwgLmlucHV0LXNlbGVjdCcpLnZhbCgnJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICRhZGRyZXNzRm9ybS5vbignY2xpY2snLCAnLmNhbmNlbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgfSk7XG5cbiAgICAkYWRkcmVzc0Zvcm0ub24oJ3N1Ym1pdCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgJC5nZXRKU09OKFVybHMuYWRkRWRpdEFkZHJlc3MsICRhZGRyZXNzRm9ybS5zZXJpYWxpemUoKSwgZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAvLyBAVE9ETzogZmlndXJlIG91dCBhIHdheSB0byBoYW5kbGUgZXJyb3Igb24gdGhlIGZvcm1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYWRkcmVzcyA9IHJlc3BvbnNlLmFkZHJlc3MsXG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nQWRkcmVzcyA9ICQodGFyZ2V0KS5jbG9zZXN0KCcuc2hpcHBpbmdhZGRyZXNzJyksXG4gICAgICAgICAgICAgICAgJHNlbGVjdCA9ICRzaGlwcGluZ0FkZHJlc3MuZmluZCgnLnNlbGVjdC1hZGRyZXNzJyksXG4gICAgICAgICAgICAgICAgJHNlbGVjdGVkID0gJHNlbGVjdC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKSxcbiAgICAgICAgICAgICAgICBuZXdPcHRpb24gPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBhZGRyZXNzLlVVSUQgKyAnXCI+JyArXG4gICAgICAgICAgICAgICAgICAgICgoYWRkcmVzcy5JRCkgPyAnKCcgKyBhZGRyZXNzLklEICsgJyknIDogYWRkcmVzcy5maXJzdE5hbWUgKyAnICcgKyBhZGRyZXNzLmxhc3ROYW1lKSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhZGRyZXNzLmFkZHJlc3MxICsgJywgJyArIGFkZHJlc3MuY2l0eSArICcsICcgKyBhZGRyZXNzLnN0YXRlQ29kZSArICcsICcgKyBhZGRyZXNzLnBvc3RhbENvZGUgK1xuICAgICAgICAgICAgICAgICAgICAnPC9vcHRpb24+JztcbiAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgaWYgKGFkZCkge1xuICAgICAgICAgICAgICAgICQoJy5zaGlwcGluZ2FkZHJlc3Mgc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ25vLW9wdGlvbicpLmFwcGVuZChuZXdPcHRpb24pO1xuICAgICAgICAgICAgICAgICQoJy5uby1hZGRyZXNzJykuaGlkZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKCcuc2hpcHBpbmdhZGRyZXNzIHNlbGVjdCcpLmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBhZGRyZXNzLlVVSUQgKyAnXCJdJykuaHRtbChuZXdPcHRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgdGhlcmUncyBubyBwcmV2aW91c2x5IHNlbGVjdGVkIG9wdGlvbiwgc2VsZWN0IGl0XG4gICAgICAgICAgICBpZiAoJHNlbGVjdGVkLmxlbmd0aCA9PT0gMCB8fCAkc2VsZWN0ZWQudmFsKCkgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgJHNlbGVjdC5maW5kKCdvcHRpb25bdmFsdWU9XCInICsgYWRkcmVzcy5VVUlEICsgJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgJ3NlbGVjdGVkJykudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy9wcmVzZXJ2ZSB0aGUgdXVpZCBvZiB0aGUgb3B0aW9uIGZvciB0aGUgaG9wIHVwIGZvcm1cbiAgICBpZiAoc2VsZWN0ZWRBZGRyZXNzVVVJRCkge1xuICAgICAgICAvL3VwZGF0ZSB0aGUgZm9ybSB3aXRoIHNlbGVjdGVkIGFkZHJlc3NcbiAgICAgICAgJGFkZHJlc3NMaXN0LmZpbmQoJ29wdGlvbicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy9jaGVjayB0aGUgdmFsdWVzIG9mIHRoZSBvcHRpb25zXG4gICAgICAgICAgICBpZiAoJCh0aGlzKS5hdHRyKCd2YWx1ZScpID09PSBzZWxlY3RlZEFkZHJlc3NVVUlEKSB7XG4gICAgICAgICAgICAgICAgJCh0aGlzKS5wcm9wKCdzZWxlY3RlZCcsICdzZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgICRhZGRyZXNzRHJvcGRvd24udHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBzaG93cyBnaWZ0IG1lc3NhZ2UgYm94IGluIG11bHRpc2hpcCwgYW5kIGlmIHRoZSBwYWdlIGlzIHRoZSBtdWx0aSBzaGlwcGluZyBhZGRyZXNzIHBhZ2UgaXQgd2lsbCBjYWxsIGluaXRtdWx0aXNoaXBzaGlwYWRkcmVzcygpIHRvIGluaXRpYWxpemUgdGhlIGZvcm1cbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRNdWx0aUdpZnRNZXNzYWdlQm94KCk7XG4gICAgaWYgKCQoJy5jYXJ0LXJvdyAuc2hpcHBpbmdhZGRyZXNzIC5zZWxlY3QtYWRkcmVzcycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZm9ybVByZXBhcmUuaW5pdCh7XG4gICAgICAgICAgICBjb250aW51ZVNlbGVjdG9yOiAnW25hbWUkPVwiYWRkcmVzc1NlbGVjdGlvbl9zYXZlXCJdJyxcbiAgICAgICAgICAgIGZvcm1TZWxlY3RvcjogJ1tpZCQ9XCJtdWx0aXNoaXBwaW5nX2FkZHJlc3NTZWxlY3Rpb25cIl0nXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAkKCcuZWRpdC1hZGRyZXNzJykub24oJ2NsaWNrJywgJ2EnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBkaWFsb2cub3Blbih7dXJsOiB0aGlzLmhyZWYsIG9wdGlvbnM6IHtvcGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhZGRyZXNzLmluaXQoKTtcbiAgICAgICAgICAgIGFkZEVkaXRBZGRyZXNzKGUudGFyZ2V0KTtcbiAgICAgICAgfX19KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpLFxuXHRmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vZm9ybVByZXBhcmUnKSxcblx0cHJvZ3Jlc3MgPSByZXF1aXJlKCcuLi8uLi9wcm9ncmVzcycpLFxuICAgIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyksXG5cdFx0dXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKSxcblx0XHRjYXJ0ID0gcmVxdWlyZSgnLi4vY2FydCcpLFxuXHRzaGlwcGluZyA9IHJlcXVpcmUoJy4vc2hpcHBpbmcnKSxcblx0VFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG5cbnZhciBzaGlwcGluZ01ldGhvZHM7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2NvdW50cnknLCBmdW5jdGlvbigpe1xuXHRcdHJlbmRlck9wdGlvbnMoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnLCAnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2NvdW50cnknKTtcblx0XHR2YXIgJGluaXRpYWxTdGF0ZSA9ICQoJy5iaWxsLWFkZHJlc3MtZmllbGRzIC5pbml0aWFsLXN0YXRlJyk7XG5cdFx0aWYgKCRpbml0aWFsU3RhdGUubGVuZ3RoID4gMCAmJiAkaW5pdGlhbFN0YXRlLnZhbCgpICE9ICcnKSB7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykudmFsKCRpbml0aWFsU3RhdGUudmFsKCkpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLnZhbHVlICE9PSAnVVMnICYmIHRoaXMudmFsdWUgIT09ICdDQScpIHtcblx0XHRcdCQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnKS5wYXJlbnRzKCcuZm9ybWZpZWxkJykuaGlkZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykucGFyZW50cygnLmZvcm1maWVsZCcpLnNob3coKTtcblx0XHR9XG5cdH0pO1xuXHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfY291bnRyeScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19jb3VudHJ5JywgZnVuY3Rpb24oKXtcblx0XHRyZW5kZXJPcHRpb25zKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScsICcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2NvdW50cnknKTtcblx0XHR2YXIgJGluaXRpYWxTdGF0ZSA9ICQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZyAuaW5pdGlhbC1zdGF0ZScpO1xuXHRcdGlmICgkaW5pdGlhbFN0YXRlLmxlbmd0aCA+IDAgJiYgJGluaXRpYWxTdGF0ZS52YWwoKSAhPSAnJykge1xuXHRcdFx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnKS52YWwoJGluaXRpYWxTdGF0ZS52YWwoKSk7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMudmFsdWUgIT09ICdVUycgJiYgdGhpcy52YWx1ZSAhPT0gJ0NBJykge1xuXHRcdFx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnKS5wYXJlbnRzKCcuZm9ybWZpZWxkJykuaGlkZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLnBhcmVudHMoJy5mb3JtZmllbGQnKS5zaG93KCk7XG5cdFx0fVxuXG5cdFx0aWYoJCh0aGlzKS52YWwoKS50b1VwcGVyQ2FzZSgpID09ICdVUycpe1xuXHRcdFx0JCgnI3NoaXBwaW5nLWludGVybmF0aW9uYWwtaW5mbycpLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI3NoaXBwaW5nLWludGVybmF0aW9uYWwtaW5mbycpLnNob3coKTtcblx0XHR9XG5cdH0pO1xuXHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblxuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJ2Zvcm0gW2lkKj1cIl9wb3N0YWxcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHQkdGhpcy52YWwoJHRoaXMudmFsKCkudG9VcHBlckNhc2UoKSk7XG5cdH0pO1xuXG5cdCQoJy5hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cblx0JCgnLnNoaXBwaW5nLXNhbWUnKS5vbignY2xpY2snLCBmdW5jdGlvbigpe1xuXHRcdC8vJCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHQvLyQoJyNzdWJtaXRCaWxsaW5nJykuc2hvdygpO1xuXHRcdGlmKCQoJy5zaGlwcGluZy1zYW1lJykuaXMoJzpjaGVja2VkJykpe1xuXHRcdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHR9XG5cblx0fSk7XG5cblx0JCgnLmFkZC1kaWZmJykub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcblx0XHQvLyQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0Ly8kKCcjc3VibWl0QmlsbGluZycpLmhpZGUoKTtcblx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdH0pO1xuXG5cdC8qQk9PVC0xMTg2IGV4cGxhaW5zIGJlaGF2aW9yIGNoZWNrIGJlZm9yZSB1cGRhdGUqL1xuXHQkKCcuYmlsbGluZy1hZGRyZXNzLWZvcm0nKS5vbignY2xpY2snLCAnLmVkaXQtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdGlmKCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dDpjaGVja2VkJykudmFsKCkgPT0gMSl7XG5cdFx0XHQkKCcuYmlsbGluZy1zZWxlY3QtYWRkcmVzcycpLnNob3coKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmJpbGwtYWRkcmVzcy1maWVsZHMnKS5zaG93KCk7XG5cdFx0XHQkKCcuYmlsbGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0XHR9XG5cblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLXByZXZpZXcnKS5oaWRlKCk7XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWZvcm0nKS5zaG93KCk7XG5cdFx0JCgnI2JpbGxpbmdBZGRyZXNzRm9ybScpLnNob3coKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1mb3JtJykuZGF0YSgnaGlkZGVuLWVkaXRhYmxlJywgJCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5odG1sKCkubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlKS5oaWRlKCk7XG5cdFx0JCgnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdH0pO1xuXG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5vbignY2xpY2snLCAnLmVkaXQtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWZvcm0nKS5kYXRhKCdoaWRkZW4tZWRpdGFibGUnLCB0cnVlKS5oaWRlKCk7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLmhpZGUoKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1mb3JtJykuc2hvdygpO1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5jc3MoJ2Rpc3BsYXknLCAnYmxvY2snKTtcblx0XHQkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0fSk7XG5cblx0JCgnLmJpbGxpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSwgc2F2ZUZvcm1WYWxzKXtcblx0XHR2YXIgdiA9ICQodGhpcykudmFsKCk7XG5cdFx0dmFyICRiaWxsaW5nQWRkcmVzc0Zvcm1GaWVsZHMgPSAkKCcjYmlsbGluZ0FkZHJlc3NGb3JtIC5iaWxsLWFkZHJlc3MtZmllbGRzJyk7XG5cdFx0aWYodiA9PSAxKXtcblx0XHRcdCQoJy5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcsICRiaWxsaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZGF0YSgnc2FtZS1jaGVja2VkJykgfHwgZmFsc2UpO1xuXHRcdFx0JCgnLmJpbGxpbmctc2VsZWN0LWFkZHJlc3MnKS5zaG93KCk7XG5cdFx0XHQkKCcuYmlsbC1hZGRyZXNzLWZpZWxkcycpLmFkZENsYXNzKCdjb2xsYXBzZWQnKTtcblx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtcHJldmlldycpLnNob3coKTtcblx0XHRcdCQoJyNkd2ZybV9iaWxsaW5nX2FkZHJlc3NMaXN0JykuaHRtbCgkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCBvcHRpb246bnRoKDApJykpO1xuXHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1wcmV2aWV3JykuaGlkZSgpO1xuXHRcdFx0dmFyICRmb3JtID0gJCgnI2JpbGxpbmdBZGRyZXNzRm9ybScpO1xuXHRcdFx0dmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoJyNkd2ZybV9iaWxsaW5nX2FkZHJlc3NMaXN0IG9wdGlvbjpudGgoMCknKS5kYXRhKCdhZGRyZXNzJyk7XG5cdFx0XHR1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJGZvcm0pO1xuXG5cdFx0fSBlbHNlIGlmKHYgPT0gMil7XG5cdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzLmRhdGEoJ3NhbWUtY2hlY2tlZCcsICQoJy5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcpKTtcblx0XHRcdCQoJy5iaWxsLWFkZHJlc3MtZmllbGRzIC5pbml0aWFsLXN0YXRlJykudmFsKCcnKTtcblx0XHRcdCQoJy5iaWxsaW5nLXNlbGVjdC1hZGRyZXNzJykuaGlkZSgpO1xuXHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1wcmV2aWV3JykuaGlkZSgpO1xuXHRcdFx0JCgnLmJpbGwtYWRkcmVzcy1maWVsZHMnKS5yZW1vdmVDbGFzcygnY29sbGFwc2VkJyk7XG5cdFx0XHRpZih0eXBlb2Ygc2F2ZUZvcm1WYWxzID09ICd1bmRlZmluZWQnIHx8ICFzYXZlRm9ybVZhbHMpe1xuXHRcdFx0XHQkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpLnZhbCgnJyk7XG5cdFx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnaW5wdXQ6dGV4dCwgaW5wdXQ6cGFzc3dvcmQsIGlucHV0OmZpbGUsIHRleHRhcmVhJykubm90KCdpbnB1dFtuYW1lKj1cIl9lbWFpbFwiXScpLnZhbCgnJyk7XG5cdFx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnc2VsZWN0IG9wdGlvbjpzZWxlY3RlZCcpLnJlbW92ZUF0dHIoJ3NlbGVjdGVkJyk7XG5cdFx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnaW5wdXQ6Y2hlY2tib3gsIGlucHV0OnJhZGlvJykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuXHRcdFx0fVxuXHRcdFx0JCgnLnNoaXBwaW5nLXNhbWUnKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfY291bnRyeScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdH1cblx0XHRpZigkKCcuc2hpcHBpbmctc2FtZScpLmlzKCc6Y2hlY2tlZCcpKXtcblx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcblx0XHR2YXIgdiA9ICQodGhpcykudmFsKCk7XG5cdFx0dmFyICRzaGlwcGluZ0FkZHJlc3NGb3JtRmllbGRzID0gJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0gLmVkaXRhZGRyZXNzLXNoaXBwaW5nJyk7XG5cdFx0aWYodiA9PSAxKXtcblx0XHRcdCQoJy5zaGlwcGluZy1zZWxlY3QtYWRkcmVzcycpLnNob3coKTtcblx0XHRcdCQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZycpLmFkZENsYXNzKCdjb2xsYXBzZWQnKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXByZXZpZXcnKS5odG1sKCcnKS5zaG93KCk7XG5cdFx0fSBlbHNlIGlmKHYgPT0gMil7XG5cdFx0XHQkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcgLmluaXRpYWwtc3RhdGUnKS52YWwoJycpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLXNlbGVjdC1hZGRyZXNzJykuaGlkZSgpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtcHJldmlldycpLmhpZGUoKTtcblx0XHRcdCQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZycpLnJlbW92ZUNsYXNzKCdjb2xsYXBzZWQnKTtcblx0XHRcdCQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnZhbCgnJyk7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcy5maW5kKCdpbnB1dDp0ZXh0LCBpbnB1dDpwYXNzd29yZCwgaW5wdXQ6ZmlsZSwgdGV4dGFyZWEnKS52YWwoJycpO1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnc2VsZWN0IG9wdGlvbjpzZWxlY3RlZCcpLnJlbW92ZUF0dHIoJ3NlbGVjdGVkJyk7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcy5maW5kKCdpbnB1dDpjaGVja2JveCwgaW5wdXQ6cmFkaW8nKS5yZW1vdmVBdHRyKCdjaGVja2VkJyk7XG5cdFx0XHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblxuXHRcdH1cblx0fSk7XG5cdC8qKlxuXHQgKiBAZnVuY3Rpb25cblx0ICogQGRlc2NyaXB0aW9uIFNlbGVjdHMgdGhlIGZpcnN0IGFkZHJlc3MgZnJvbSB0aGUgbGlzdCBvZiBhZGRyZXNzZXNcblx0ICovXG5cdHZhciAkZm9ybSA9ICQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKTtcbiAgICAvLyBzZWxlY3QgYWRkcmVzcyBmcm9tIGxpc3RcbiAgICAkKCdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0xpc3RcIl0nLCAkZm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoc2VsZWN0ZWQpLmRhdGEoJ2FkZHJlc3MnKTtcbiAgICAgICAgaWYgKCFzZWxlY3RlZEFkZHJlc3MpIHsgcmV0dXJuOyB9XG4gICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCAkZm9ybSk7XG5cbiAgICAgICAgJGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgfSk7XG5cbiAgICB2YXIgc2hpcHBpbmdBZGRyRm9ybSA9ICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgJCgnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NMaXN0XCJdJywgc2hpcHBpbmdBZGRyRm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoc2VsZWN0ZWQpLmRhdGEoJ2FkZHJlc3MnKTtcbiAgICAgICAgaWYgKCFzZWxlY3RlZEFkZHJlc3MpIHsgcmV0dXJuOyB9XG4gICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCBzaGlwcGluZ0FkZHJGb3JtKTtcblxuICAgICAgICBzaGlwcGluZ0FkZHJGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgIH0pO1xuXG4gICAgLy9hZGRyZXNzIHN1Ym1pc3Npb25cbiAgICAkKCcjc3VibWl0QmlsbGluZycpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgIFx0cHJvZ3Jlc3Muc2hvdygpO1xuXG4gICAgXHQvLyBwcmV2ZW50IHN1Ym1pdHRpbmcgc2F2ZWQgYWRkcmVzcyB3L291dCBhIHNlbGVjdGlvblxuICAgIFx0aWYgKCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT0xXScpLnByb3AoJ2NoZWNrZWQnKSAmJiAkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpLnZhbCgpID09ICcnKSB7XG4gICAgXHRcdCQoJyNzdWJtaXRCaWxsaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgXHRcdHJldHVybjtcbiAgICBcdH1cblxuICAgIFx0aWYoJCgnLnNoaXBwaW5nLXNhbWUnKS5pcygnOmNoZWNrZWQnKSl7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdH1cblxuICAgIFx0dmFyICRmb3JtID0gJCgnI2JpbGxpbmdBZGRyZXNzRm9ybScpLFxuICAgIFx0XHRhY3Rpb25OYW1lID0gJCgnI3NlbGVjdE9wY0FkZHJlc3MnKS5hdHRyKCduYW1lJyk7XG4gICAgXHQkZm9ybS52YWxpZGF0ZSgpLnNldHRpbmdzLmlnbm9yZSA9IFtcIjpub3QoLnJlcXVpcmVkKVwiXTtcbiAgICBcdCRmb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXG4gICAgXHQkKCcuY3VzdG9tLWVtYWlsLWVycm9yJykucmVtb3ZlKCk7XG5cbiAgICBcdHZhciBpc0VtYWlsVmFsaWQgPSB1dGlsLnZhbGlkYXRlRW1haWwoJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2VtYWlsJykudmFsKCkpO1xuXG4gICAgXHRpZigkZm9ybS52YWxpZCgpICYmIGlzRW1haWxWYWxpZCl7XG4gICAgXHRcdC8vc2V0IGJpbGxpbmcgYWRkcmVzc1xuICAgIFx0XHRzZXRPUENBZGRyZXNzKCcjYmlsbGluZ0FkZHJlc3NGb3JtJywgYWN0aW9uTmFtZSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICBcdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXG4gICAgXHRcdFx0aWYoZGF0YS5zdGF0dXMgPT0gJ3N1Y2Nlc3MnKXtcbiAgICBcdFx0XHRcdHVwZGF0ZVN1bW1hcnkoKTtcbiAgICBcdFx0XHRcdCQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKS5oaWRlKCk7XG5cdCAgICAgICAgXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YScpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9jaygnI2JpbGxpbmdBZGRyZXNzRm9ybScpKS5zaG93KCk7XG5cbiAgICBcdFx0XHRcdGlmKCQoJy5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcpKXtcbiAgICBcdFx0XHRcdFx0cG9wdWxhdGVCaWxsaW5nVG9TaGlwcGluZygnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nLCAnI2JpbGxpbmdBZGRyZXNzRm9ybScpO1xuICAgICAgICBcdCAgICBcdH1cbiAgICBcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cbiAgICBcdFx0XHRcdHZhciAkc2hpcHBpbmdBZGRyZXNzRm9ybSA9ICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgXHRcdFx0XHRpZihTaXRlUHJlZmVyZW5jZXMuQllQQVNTX1NISVBQSU5HICYmICQoJy5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcpKXtcbiAgICBcdFx0XHRcdFx0dXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCcjYmlsbGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2soJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykpLnNob3coKTtcbiAgICBcdFx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuICAgIFx0XHRcdFx0XHQkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcsIHRydWUpO1xuICAgIFx0XHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0XHRcdFx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICBcdCAgICAgICAgXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0XHRcdFx0fSBlbHNlIHtcbiAgICBcdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICBcdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLnNob3coKTtcbiAgICBcdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZm9ybScpLnNob3coKTtcbiAgICBcdFx0XHRcdH1cblxuICAgIFx0XHRcdFx0aWYoJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKS5kYXRhKCdzaGlwcGluZy1maWxsZWQnKSA9PSB0cnVlKXtcbiAgICBcdFx0XHRcdFx0JCgnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgXHRcdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcbiAgICBcdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLnNob3coKTtcbiAgICBcdFx0XHRcdH1cblxuICAgIFx0XHRcdH0gZWxzZSBpZihkYXRhLnN0YXR1cyA9PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpIHtcblx0XHRcdFx0XHRvcGVuUmVzdHJpY3Rpb25zUG9wdXAoZGF0YSk7XG4gICAgXHRcdFx0fSBlbHNlIHtcbiAgICBcdFx0XHRcdGNvbnNvbGUubG9nKCdzdWJtaXNzaW9uIGVycm9yJyk7XG4gICAgXHRcdFx0fVxuXG4gICAgXHRcdFx0cHJvZ3Jlc3MuaGlkZSgpO1xuICAgIFx0XHRcdCQoJyNzdWJtaXRCaWxsaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgXHQgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0cHJvZ3Jlc3MuaGlkZSgpO1xuICAgIFx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXG4gICAgXHRcdGlmICghaXNFbWFpbFZhbGlkICYmICRmb3JtLnZhbGlkKCkpIHtcbiAgICBcdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfZW1haWwnKS5wYXJlbnQoKS5hcHBlbmQoJzxzcGFuIGNsYXNzPVwiZXJyb3IgY3VzdG9tLWVtYWlsLWVycm9yXCI+JyArIFJlc291cmNlcy5WQUxJREFURV9FTUFJTCArICc8L3NwYW4+Jyk7XG4gICAgXHRcdH1cbiAgICBcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0W3ZhbHVlPVwiMlwiXScpLnRyaWdnZXIoJ2NsaWNrJywgW3RydWVdKTtcbiAgICBcdH1cbiAgICB9KTtcblxuICAgICQoJyNzdWJtaXRTaGlwcGluZycpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0dmFyICRmb3JtID0gJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSxcblx0XHRcdGFjdGlvbk5hbWUgPSAkKHRoaXMpLmF0dHIoJ25hbWUnKTtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdCQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgXHRwcm9ncmVzcy5zaG93KCk7XG5cbiAgICBcdC8vIHByZXZlbnQgc3VibWl0dGluZyBzYXZlZCBhZGRyZXNzIHcvb3V0IGEgc2VsZWN0aW9uXG4gICAgXHRpZiAoJCgnLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT0xXScpLnByb3AoJ2NoZWNrZWQnKSAmJiAkKCcjZHdmcm1fc2luZ2xlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS52YWwoKSA9PSAnJykge1xuICAgIFx0XHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuXG4gICAgXHQkZm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcbiAgICBcdGlmKCRmb3JtLnZhbGlkKCkpe1xuICAgIFx0XHRzZXRPUENBZGRyZXNzKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScsIGFjdGlvbk5hbWUpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgXHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblxuICAgIFx0XHRcdGlmKGRhdGEuc3RhdHVzID09ICdzdWNjZXNzJyl7XG4gICAgXHRcdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgXHRcdFx0XHQkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcsIHRydWUpO1xuICAgICAgICBcdFx0XHQkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpLmhpZGUoKTtcbiAgICAgICAgICAgIFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpKS5zaG93KCk7XG4gICAgICAgICAgICBcdFx0Ly9iZWZvcmUgcHJvY2VlZCB0byBwYXltZW50IGNoZWNrIGlmIGJpbGxpbmcgYWRkcmVzcyBpcyBjb3JyZWN0XG4gICAgICAgICAgICBcdFx0dmFyIGJpbEZvcm0gPSAkKCcjYmlsbGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgICAgICAgICBcdFx0YmlsRm9ybS52YWxpZGF0ZSgpLnNldHRpbmdzLmlnbm9yZSA9IFtcIjpub3QoLnJlcXVpcmVkKVwiXTtcblxuICAgICAgICAgICAgXHRcdGlmKGJpbEZvcm0udmFsaWQoKSl7XG4gICAgICAgICAgICBcdFx0XHRpZigkKCcjaXNTaGlwcGluZ0FkZHJlc3NTYW1lQXNCaWxsaW5nQWRkcmVzcycpLmlzKFwiOmNoZWNrZWRcIikpIHsgJCgnI2lzU2hpcHBpbmdBZGRyZXNzU2FtZUFzQmlsbGluZ0FkZHJlc3MnKS5jbGljaygpOyB9XG4gICAgICAgICAgICBcdFx0XHQkKCcjc3VibWl0QmlsbGluZycpLmNsaWNrKCk7XG5cdCAgICAgICAgICAgIFx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHQgICAgICAgICAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgICAgICBcdH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgXHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdCAgICAgICAgICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHQgICAgICAgICAgICBcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblx0ICAgICAgICAgICAgXHRcdHZhciBmb3JtQm9keSA9ICQoJy5iaWxsaW5nLWFkZHJlc3MtZm9ybScpO1xuXHQgICAgICAgICAgICBcdFx0Zm9ybUJvZHkuc2hvdygpO1xuXHQgICAgICAgICAgICBcdFx0Zm9ybUJvZHkuZmluZCgnaW5wdXQucmVxdWlyZWQuZmllbGQuZXJyb3InKS5lcSgwKS5mb2N1cygpO1xuICAgICAgICAgICAgICAgIFx0fVxuICAgICAgICBcdFx0XHR1cGRhdGVTdW1tYXJ5KCk7XG4gICAgXHRcdFx0fSBlbHNlIHtcbiAgICBcdFx0XHRcdGNvbnNvbGUubG9nKCdzdWJtaXNzaW9uIGVycm9yJyk7XG4gICAgXHRcdFx0XHRzd2l0Y2ggKGRhdGEuc3RhdHVzKSB7XG4gICAgXHRcdFx0XHRcdGNhc2UgJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InOiB7XG4gICAgXHRcdFx0XHRcdFx0b3BlblJlc3RyaWN0aW9uc1BvcHVwKGRhdGEpO1xuICAgIFx0XHRcdFx0XHR9XG4gICAgXHRcdFx0XHR9XG4gICAgXHRcdFx0fVxuICAgIFx0XHRcdHByb2dyZXNzLmhpZGUoKTtcbiAgICBcdFx0XHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcbiAgICBcdCAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgXHR9IGVsc2Uge1xuICAgIFx0XHRwcm9ncmVzcy5oaWRlKCk7XG4gICAgXHRcdCQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuICAgIFx0fVxuXG4gICAgfSk7XG5cblx0JCgnLnRvZ2dsZS50b3AsIC50b2dnbGUuYm90dG9tJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHQkKCcjaW50ZXJuYXRpb25hbGluZm8nKS5zbGlkZVRvZ2dsZSgpO1xuXHR9KTtcblxuXG5cdHZhciBiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24gPSAkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpO1xuXHQvL3ByZXNldCBkZWZhdWx0IGFkZHJlc3MgaWYgZXhpc3RzXG5cdGlmKGJpbGxpbmdTYXZlZEFkZHJEcm9wZG93bi5sZW5ndGggPiAwICYmIGJpbGxpbmdTYXZlZEFkZHJEcm9wZG93bi52YWwoKSAhPT0gJycpe1xuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdC8vcGFzcyBjdXN0b21lciB0byBzZWNvbmQgc3RlcCBpbiB0aGlzIGNhc2Vcblx0XHRcdCQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKS5oaWRlKCk7XG4gICAgXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YScpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9jaygnI2JpbGxpbmdBZGRyZXNzRm9ybScpKS5zaG93KCk7XG4gICAgXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0fSwgMTMpO1xuXG5cdH1cblxuXHR2YXIgc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93biA9ICQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpO1xuXHRpZihzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLmxlbmd0aCA+IDAgJiYgc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi52YWwoKSAhPT0gJycpe1xuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKTtcblx0XHRcdC8vcGFzcyBjdXN0b21lciB0byB0aGlyZCBzdGVwIGluIHRoaXMgY2FzZVxuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9jaygnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSkuc2hvdygpO1xuXHQgICAgICAgICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykuaGlkZSgpO1xuXHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0JCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcblx0ICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG5cdFx0fSwgMTMpO1xuXHR9XG5cblx0Ly9kcmF3IGFkZHJlc3MgcHJldmlldyBvbiBjaGFuZ2Vcblx0YmlsbGluZ1NhdmVkQWRkckRyb3Bkb3duLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpe1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyksXG5cdFx0XHR1cGQgPSBmdW5jdGlvbigpe1xuXHRcdFx0XHR2YXIgZWwgPSAkKCcuYmlsbGluZy1hZGRyZXNzLXByZXZpZXcnKS5odG1sKCcnKTtcblx0XHRcdFx0JHRoaXMudmFsKCkgJiYgZWwuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrKCcjYmlsbGluZ0FkZHJlc3NGb3JtJywgdHJ1ZSkpLnNob3coKTtcblx0XHRcdH07XG5cblx0XHRzZXRUaW1lb3V0KHVwZCwgMTMpO1xuXG5cdH0pO1xuXHRiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24udHJpZ2dlcignY2hhbmdlJyk7XG5cblx0Ly9kcmF3IGFkZHJlc3MgcHJldmlldyBvbiBjaGFuZ2Vcblx0c2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5vbignY2hhbmdlJywgZnVuY3Rpb24oKXtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpLFxuXHRcdFx0dXBkID0gZnVuY3Rpb24oKXtcblx0XHRcdFx0dmFyIGVsID0gJCgnLnNoaXBwaW5nLWFkZHJlc3MtcHJldmlldycpLmh0bWwoJycpO1xuXHRcdFx0XHQkdGhpcy52YWwoKSAmJiBlbC5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2soJyNzaGlwcGluZ0FkZHJlc3NGb3JtJywgdHJ1ZSkpLnNob3coKTtcblx0XHRcdH07XG5cblx0XHRzZXRUaW1lb3V0KHVwZCwgMTMpO1xuXHR9KTtcblxuXHRpZiAoc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5sZW5ndGggJiYgc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5wYXJlbnRzKCdmb3JtJykuZmluZCgnaW5wdXRbaWQqPV9hZGRyZXNzMV0nKS52YWwoKSA9PSAnJykge1xuXHRcdHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24udHJpZ2dlcignY2hhbmdlJyk7XG5cdH1cblxuXHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0aWYoJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0gaW5wdXRbaWQqPV9maXJzdE5hbWVdJykudmFsKCkgIT0gJycpe1xuXHRcdFx0dmFyICRmb3JtID0gJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSxcblx0XHRcdGFjdGlvbk5hbWUgPSBcImR3ZnJtX3NoaXBwaW5nYWRkcmVzc19zYXZlb3BjYWRkcmVzc1wiO1xuXG5cdFx0XHQkZm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0XHRcdGlmKCRmb3JtLnZhbGlkKCkpe1xuXHRcdFx0XHRzZXRPUENBZGRyZXNzKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScsIGFjdGlvbk5hbWUpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblxuXHRcdFx0XHRcdGlmKGRhdGEuc3RhdHVzICE9ICdzdWNjZXNzJyl7XG5cdFx0XHRcdFx0XHRjb25zb2xlLmxvZygnc3VibWlzc2lvbiBlcnJvcicpO1xuXHRcdFx0XHRcdH1cblx0XHRcdCAgICB9LmJpbmQodGhpcykpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSwgMzApO1xuXG59XG5cbi8qKlxuICogY3JlYXRlIGFkZHJlc3Mgb2JqZWN0IGZyb20gZm9ybVxuICogQHBhcmFtIGZvcm1TZWxlY3RvclxuICogQHJldHVybnMgQWRkcmVzcyBPYmplY3RcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQWRkcmVzc09iaihmb3JtU2VsZWN0b3Ipe1xuXHR2YXIgJGZvcm0gPSAkKGZvcm1TZWxlY3Rvcik7XG5cdHJldHVybiB7XG5cdFx0Zmlyc3ROYW1lOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykudmFsKCkpLFxuXHRcdGxhc3ROYW1lOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoKSksXG5cdFx0YWRkcmVzczE6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgpKSxcblx0XHRhZGRyZXNzMjogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCkpLFxuXHRcdGFkZHJlc3MzOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczNcIl0nKS52YWwoKSksXG5cdFx0Y291bnRyeUNvZGU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX2NvdW50cnlcIl0nKS52YWwoKSksXG5cdFx0c3RhdGVDb2RlOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9zdGF0ZVwiXScpLnZhbCgpKSxcblx0XHRwb3N0YWxDb2RlOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCkudG9VcHBlckNhc2UoKSksXG5cdFx0Y2l0eTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoKSksXG5cdFx0cGhvbmU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9waG9uZVwiXScpLnZhbCgpKSxcblx0XHRlbWFpbDogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2VtYWlsXCJdJykudmFsKCkpXG5cdH07XG59XG5cbmZ1bmN0aW9uIHBvcHVsYXRlQmlsbGluZ1RvU2hpcHBpbmcoc2hpcHBpbmdBZGRyRm9ybVNlbGVjdG9yLCBiaWxsaW5nQWRkckZvcm1TZWxlY3Rvcil7XG5cdHZhciBzaGlwcGluZ0FkZHJGb3JtID0gJChzaGlwcGluZ0FkZHJGb3JtU2VsZWN0b3IpO1xuXHR2YXIgYmlsbGluZ0FkZHJPYmogPSBjcmVhdGVBZGRyZXNzT2JqKGJpbGxpbmdBZGRyRm9ybVNlbGVjdG9yKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2ZpcnN0TmFtZVwiXScpLnZhbChiaWxsaW5nQWRkck9iai5maXJzdE5hbWUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmoubGFzdE5hbWUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmouYWRkcmVzczEpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmouYWRkcmVzczIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczNcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmouYWRkcmVzczMpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLnBvc3RhbENvZGUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbChiaWxsaW5nQWRkck9iai5jaXR5KS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9Y291bnRyeV0nKS52YWwoYmlsbGluZ0FkZHJPYmouY291bnRyeUNvZGUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIHNoaXBwaW5nQWRkckZvcm0uZmluZCgnc2VsZWN0W2lkJD1zdGF0ZV0nKS52YWwoYmlsbGluZ0FkZHJPYmouc3RhdGVDb2RlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bob25lXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLnBob25lKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbn1cblxuZnVuY3Rpb24gYnVpbGREZXRhaWxzQmxvY2soZm9ybVNlbGVjdG9yLCBjb21wYWN0KXtcblx0dmFyICRmb3JtID0gJChmb3JtU2VsZWN0b3IpLFxuICAgIFx0ZGF0YSA9IGNyZWF0ZUFkZHJlc3NPYmooJGZvcm0pLFxuICAgIFx0aHRtbFRleHQgPSAkKCc8ZGl2Lz4nLCB7XCJjbGFzc1wiOiBcImFkZHJlc3MtZGV0YWlscy1zdFwifSksXG4gICAgXHRpc0NvbXBhY3QgPSB0eXBlb2YgY29tcGFjdCAhPSB1bmRlZmluZWQgJiYgY29tcGFjdCA9PSB0cnVlLFxuICAgIFx0aGVhZGVyID0gaXNDb21wYWN0ID8gJycgOiAkZm9ybS5hdHRyKCdpZCcpID09ICdiaWxsaW5nQWRkcmVzc0Zvcm0nPyAnPGg2PkJpbGxpbmcgUmVjaXBpZW50PC9oNj4nIDogJzxoNj5TaGlwIFRvOjwvaDY+JyxcbiAgICBcdGVkaXRCdXR0b24gPSBpc0NvbXBhY3QgPyAnJyA6ICc8cCBjbGFzcz1cInRleHQtcmlnaHRcIj48YSBocmVmPVwiI1wiIGNsYXNzPVwiZWRpdC1hZGRyZXNzLWRldFwiIHRhYmluZGV4PVwiMFwiPkVkaXQ8c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPiZuYnNwO0FkZHJlc3MgSW5mb3JtYXRpb248L3NwYW4+PC9hPjwvcD4nO1xuXG4gICAgaWYoIWlzQ29tcGFjdCAmJiAkZm9ybS5hdHRyKCdpZCcpID09ICdzaGlwcGluZ0FkZHJlc3NGb3JtJykge1xuICAgIFx0JCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICB9XG4gICAgZm9yICggdmFyIF9rIGluIGRhdGEgKSB7XG4gICAgXHRpZiAoIGRhdGFbX2tdICE9IG51bGwgJiYgZGF0YVtfa10uc2VhcmNoKC9cXF4vKSAhPSAtMSApIHtcbiAgICBcdFx0ZGF0YVtfa10gPSBkYXRhW19rXS5yZXBsYWNlKC9cXF4vZ2ksXCInXCIpO1xuICAgIFx0fVxuICAgIH1cbiAgICBpZiAoZGF0YS5lbWFpbCkge1xuXG4gICAgXHR2YXIgaHRtbGNvbnRlbnQgPSBoZWFkZXI7XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicrZGF0YS5maXJzdE5hbWUgKyAnICcgKyBkYXRhLmxhc3ROYW1lICsgJyA8L2Rpdj4nO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5hZGRyZXNzMSArICcgPC9kaXY+JztcbiAgICBcdFx0aWYgKGRhdGEuYWRkcmVzczIgIT09ICcnKSB7XG4gICAgXHRcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEuYWRkcmVzczIgKyAnIDwvZGl2Pic7XG4gICAgXHRcdH1cbiAgICBcdFx0aWYgKGRhdGEuYWRkcmVzczMgIT09ICcnKSB7XG4gICAgXHRcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEuYWRkcmVzczMgKyAnIDwvZGl2Pic7XG4gICAgXHRcdH1cblxuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5jaXR5O1xuXG5cbiAgICBcdFx0aWYoZGF0YS5zdGF0ZUNvZGUgIT0gbnVsbCAmJiBkYXRhLnN0YXRlQ29kZSAhPSAnJyAmJiBkYXRhLnN0YXRlQ29kZSAhPSB1bmRlZmluZWQgJiYgZGF0YS5zdGF0ZUNvZGUudG9VcHBlckNhc2UoKSAhPSAnT1RIRVInKSB7XG4gICAgXHRcdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgZGF0YS5zdGF0ZUNvZGU7XG4gICAgXHRcdH1cblxuICAgIFx0XHRodG1sY29udGVudCArPSAnICcgKyBkYXRhLnBvc3RhbENvZGU7XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICcgJyArIGRhdGEuY291bnRyeUNvZGUgKyAnPC9kaXY+JztcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEucGhvbmUgKyAnPC9kaXY+JztcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JytkYXRhLmVtYWlsKyc8L2Rpdj4nICsgZWRpdEJ1dHRvbjtcblxuICAgIFx0aHRtbFRleHQuaHRtbChodG1sY29udGVudCk7XG5cbiAgICB9IGVsc2Uge1xuICAgIFx0dmFyIGh0bWxjb250ZW50ID0gaGVhZGVyO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nK2RhdGEuZmlyc3ROYW1lICsgJyAnICsgZGF0YS5sYXN0TmFtZSArICcgPC9kaXY+JztcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEuYWRkcmVzczEgKyAnIDwvZGl2Pic7XG4gICAgXHRcdGlmIChkYXRhLmFkZHJlc3MyICE9PSAnJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmFkZHJlc3MyICsgJyA8L2Rpdj4nO1xuICAgIFx0XHR9XG4gICAgXHRcdGlmIChkYXRhLmFkZHJlc3MzICE9PSAnJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmFkZHJlc3MzICsgJyA8L2Rpdj4nO1xuICAgIFx0XHR9XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmNpdHk7XG5cbiAgICBcdFx0aWYoZGF0YS5zdGF0ZUNvZGUgIT0gbnVsbCAmJiBkYXRhLnN0YXRlQ29kZSAhPSAnJyAmJiBkYXRhLnN0YXRlQ29kZSAhPSB1bmRlZmluZWQgJiYgZGF0YS5zdGF0ZUNvZGUudG9VcHBlckNhc2UoKSAhPSAnT1RIRVInKSB7XG4gICAgXHRcdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgZGF0YS5zdGF0ZUNvZGU7XG4gICAgXHRcdH1cbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgZGF0YS5wb3N0YWxDb2RlO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnICcgKyBkYXRhLmNvdW50cnlDb2RlICsgICc8L2Rpdj4nO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5waG9uZSArICc8L2Rpdj4nICsgZWRpdEJ1dHRvbjtcblxuICAgIFx0aHRtbFRleHQuaHRtbChodG1sY29udGVudCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGh0bWxUZXh0O1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEhlbHBlciBtZXRob2Qgd2hpY2ggY29uc3RydWN0cyBhIFVSTCBmb3IgYW4gQUpBWCByZXF1ZXN0IHVzaW5nIHRoZVxuICogZW50ZXJlZCBhZGRyZXNzIGluZm9ybWF0aW9uIGFzIFVSTCByZXF1ZXN0IHBhcmFtZXRlcnMuXG4gKi9cbmZ1bmN0aW9uIGdldFNoaXBwaW5nTWV0aG9kVVJMKGZvcm1TZWxlY3RvciwgdXJsLCBleHRyYVBhcmFtcykge1xuICAgIHZhciAkZm9ybSA9ICQoZm9ybVNlbGVjdG9yKTtcblxuICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgIGFkZHJlc3MxOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgpLFxuICAgICAgICBhZGRyZXNzMjogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoKSxcbiAgICAgICAgYWRkcmVzczM6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MzXCJdJykudmFsKCksXG4gICAgICAgIGNvdW50cnlDb2RlOiAkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX2NvdW50cnlcIl0nKS52YWwoKSxcbiAgICAgICAgc3RhdGVDb2RlOiAkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX3N0YXRlXCJdJykudmFsKCksXG4gICAgICAgIHBvc3RhbENvZGU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgpLFxuICAgICAgICBjaXR5OiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykudmFsKClcbiAgICB9O1xuICAgIHJldHVybiB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKHVybCwgJC5leHRlbmQocGFyYW1zLCBleHRyYVBhcmFtcykpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3Qoc2VsKSB7XG4gICAgdmFyICRzaGlwcGluZ01ldGhvZExpc3QgPSAkKCcjc2hpcHBpbmctbWV0aG9kLWxpc3QnKTtcbiAgICBpZiAoISRzaGlwcGluZ01ldGhvZExpc3QgfHwgJHNoaXBwaW5nTWV0aG9kTGlzdC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG4gICAgdmFyIHVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKHNlbCwgVXJscy5zaGlwcGluZ01ldGhvZHNKU09OKTtcblxuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydCgnQ291bGRuXFwndCBnZXQgbGlzdCBvZiBhcHBsaWNhYmxlIHNoaXBwaW5nIG1ldGhvZHMuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHVwZGF0ZSB0aGUgVUkuICBUaGUgbGlzdCBoYXMgY2hhbmdlZC5cbiAgICAgICAgICAgIC8vIENhY2hlIHRoZSBhcnJheSBvZiByZXR1cm5lZCBzaGlwcGluZyBtZXRob2RzLlxuICAgICAgICAgICAgc2hpcHBpbmdNZXRob2RzID0gZGF0YTtcbiAgICAgICAgICAgIC8vIGluZGljYXRlIHByb2dyZXNzXG4gICAgICAgICAgICBwcm9ncmVzcy5zaG93KCRzaGlwcGluZ01ldGhvZExpc3QpO1xuXG4gICAgICAgICAgICB2YXIgc2hpcHBpbmdNZXRob2RMaXN0RGF0YSA9IHtcbiAgICAgICAgXHRcdHNlbGVjdGVkUGF5bWVudE1ldGhvZDogJCgnI3BheW1lbnRTZWN0aW9uIGlucHV0OmNoZWNrZWQnKS52YWwoKVxuICAgICAgICBcdH1cblxuICAgICAgICAgICAgLy8gbG9hZCB0aGUgc2hpcHBpbmcgbWV0aG9kIGZvcm1cbiAgICAgICAgICAgIHZhciBzbWxVcmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChzZWwsIFVybHMuc2hpcHBpbmdNZXRob2RzTGlzdCk7XG5cbiAgICAgICAgICAgICRzaGlwcGluZ01ldGhvZExpc3QubG9hZChzbWxVcmwsIHNoaXBwaW5nTWV0aG9kTGlzdERhdGEsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmZhZGVJbignZmFzdCcpO1xuICAgICAgICAgICAgICAgIC8vIHJlYmluZCB0aGUgcmFkaW8gYnV0dG9ucyBvbmNsaWNrIGZ1bmN0aW9uIHRvIGEgaGFuZGxlci5cbiAgICAgICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJ1tuYW1lJD1cIl9zaGlwcGluZ01ldGhvZElEXCJdJykuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIFx0JCgnW25hbWUkPVwiX3NoaXBwaW5nTWV0aG9kSURcIl0nKS5wcm9wKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgIFx0c2VsZWN0U2hpcHBpbmdNZXRob2QoJCh0aGlzKS52YWwoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBwcm9ncmVzcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdG9vbHRpcC5pbml0KCk7XG4gICAgICAgICAgICAgICAgLy9pZiBub3RoaW5nIGlzIHNlbGVjdGVkIGluIHRoZSBzaGlwcGluZyBtZXRob2RzIHNlbGVjdCB0aGUgZmlyc3Qgb25lXG4gICAgICAgICAgICAgICAgaWYgKCRzaGlwcGluZ01ldGhvZExpc3QuZmluZCgnLmlucHV0LXJhZGlvOmNoZWNrZWQnKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCcuaW5wdXQtcmFkaW86Zmlyc3QnKS5wcm9wKCdjaGVja2VkJywgJ2NoZWNrZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHVwZGF0ZXMgdGhlIG9yZGVyIHN1bW1hcnkgYmFzZWQgb24gYSBwb3NzaWJseSByZWNhbGN1bGF0ZWQgYmFza2V0IGFmdGVyIGEgc2hpcHBpbmcgcHJvbW90aW9uIGhhcyBiZWVuIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gdXBkYXRlU3VtbWFyeSgpIHtcbiAgICBjYXJ0LnVwZGF0ZUNhcnQoJ2R3ZnJtX2NhcnRfdXBkYXRlQ2FydCcpO1xuXG4gICAgcmV0dXJuO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHNlbGVjdHMgYSBzaGlwcGluZyBtZXRob2QgZm9yIHRoZSBkZWZhdWx0IHNoaXBtZW50IGFuZCB1cGRhdGVzIHRoZSBzdW1tYXJ5IHNlY3Rpb24gb24gdGhlIHJpZ2h0IGhhbmQgc2lkZVxuICogQHBhcmFtXG4gKi9cbmZ1bmN0aW9uIHNlbGVjdFNoaXBwaW5nTWV0aG9kKHNoaXBwaW5nTWV0aG9kSUQpIHtcbiAgICAvLyBub3RoaW5nIGVudGVyZWRcbiAgICBpZiAoIXNoaXBwaW5nTWV0aG9kSUQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGF0dGVtcHQgdG8gc2V0IHNoaXBwaW5nIG1ldGhvZFxuICAgIHZhciB1cmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nLCBVcmxzLnNlbGVjdFNoaXBwaW5nTWV0aG9kc0xpc3QsIHtzaGlwcGluZ01ldGhvZElEOiBzaGlwcGluZ01ldGhvZElEfSk7XG4gICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoZGF0YSkge1xuXG4gICAgICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG4gICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuc2hpcHBpbmdNZXRob2RJRCkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydCgnQ291bGRuXFwndCBzZWxlY3Qgc2hpcHBpbmcgbWV0aG9kLicpO1xuICAgICAgICAgICAgICAgICQoJ1tuYW1lJD1cIl9zaGlwcGluZ01ldGhvZElEXCJdJykucHJvcCgnZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZGlzcGxheSBwcm9tb3Rpb24gaW4gVUkgYW5kIHVwZGF0ZSB0aGUgc3VtbWFyeSBzZWN0aW9uLFxuICAgICAgICAgICAgLy8gaWYgc29tZSBwcm9tb3Rpb25zIHdlcmUgYXBwbGllZFxuICAgICAgICAgICAgJCgnLnNoaXBwaW5ncHJvbW90aW9ucycpLmVtcHR5KCk7XG5cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gc2V0IGFkZHJlc3MgZGF0YVxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIGVsZW1lbnQgdGhhdCBwcmVzZW50IGFkZHJlc3Mgb2JqZWN0XG4gKiBAcGFyYW0ge0VsZW1lbnR9IEFjdGlvbiBuYW1lIHRvIGFwcGx5IHRvIGZvcm1cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgc2V0T1BDQWRkcmVzcyA9IGZ1bmN0aW9uIChmb3JtLCBuYW1lKSB7XG4gICAgdmFyICRmb3JtID0gJChmb3JtKSxcbiAgICBcdHVybCA9IChmb3JtID09ICcjYmlsbGluZ0FkZHJlc3NGb3JtJykgPyBVcmxzLnNldE9wY0FkZHJlc3MgOiAgJGZvcm0uYXR0cignYWN0aW9uJyk7XG5cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKHVybCksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWVcbiAgICB9KSk7XG59O1xuXG52YXIgb3BlblJlc3RyaWN0aW9uc1BvcHVwID0gZnVuY3Rpb24gKGRhdGEpIHtcblx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cdHZhciBwb3B1cCA9IHJlcXVpcmUoJy4uLy4uL3BvcHVwJyk7XG5cblx0dmFyIGxpc3QgPSAkLm1hcChwYXlsb2FkLmxpc3QsIGZ1bmN0aW9uIChlbCkge1xuXHRcdHJldHVybiAnPGxpPicgKyBlbC5uYW1lICsgJzo8YnI+JyArIGVsLm1lc3NhZ2UgKyAnPC9saT4nO1xuXHR9KS5qb2luKCcnKTtcblxuXHRwb3B1cC5pbml0KHtcblx0XHR0aXRsZTogcGF5bG9hZC50aXRsZSxcblx0XHRjb250ZW50OiBwYXlsb2FkLm1lc3NhZ2UgKyAnPHVsIGNsYXNzPVwic2hpcHBpbmctcmVzdHJpY3Rpb25zLXBvcHVwX19saXN0XCI+JyArIGxpc3QgKyAnPC91bD4nLFxuXHR9KS5zaG93UG9wdXAoKTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyT3B0aW9ucyhvcHRpb25QYXJlbnQsIG9wdGlvbnNTdG9yZUlkKSB7XG5cdHZhciBvcHRpb25zID0gJyc7XG5cdHZhciBvcHRpb25zU3RvcmVPcHRpb25zID0gJChvcHRpb25zU3RvcmVJZCArICcgb3B0aW9uOnNlbGVjdGVkJykuZGF0YSgnb3B0aW9ucycpO1xuXHR2YXIgc3RhdGVzTGlzdDtcblxuXHRpZiAob3B0aW9uc1N0b3JlT3B0aW9ucykge1xuXHRcdHN0YXRlc0xpc3QgPSBKU09OLnBhcnNlKG9wdGlvbnNTdG9yZU9wdGlvbnMucmVwbGFjZSgvXFwnL2csICdcXFwiJykpO1xuXG5cdFx0c3RhdGVzTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChzdGF0ZSkge1xuXHRcdFx0b3B0aW9ucyArPSAnPG9wdGlvbiBjbGFzcz1cInNlbGVjdC1vcHRpb25cIiBsYWJlbD1cIicgKyBzdGF0ZS5sYWJlbCArICdcIiB2YWx1ZT1cIicgKyBzdGF0ZS5jb2RlICsgJ1wiPicgKyBzdGF0ZS5sYWJlbCArICc8L29wdGlvbj4nO1xuXHRcdH0pO1xuXG5cdFx0JChvcHRpb25QYXJlbnQpLmVtcHR5KCkuYXBwZW5kKG9wdGlvbnMpO1xuXG5cdFx0aWYgKHN0YXRlc0xpc3QubGVuZ3RoIDw9IDEpIHtcblx0XHRcdCQob3B0aW9uUGFyZW50KS5yZW1vdmVDbGFzcygncmVxdWlyZWQnKTtcblx0XHRcdCQob3B0aW9uUGFyZW50KS5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQob3B0aW9uUGFyZW50KS5hZGRDbGFzcygncmVxdWlyZWQnKTtcblx0XHRcdCQob3B0aW9uUGFyZW50KS5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5zaG93KCk7XG5cdFx0fVxuXHR9XG59XG5cbiQoZG9jdW1lbnQpLm9uKCd1cGRhdGUtc2hpcHBpbmcnLCBmdW5jdGlvbigpIHtcblx0aWYoJCgnLnNoaXBwaW5nLW1ldGhvZHMtc2VjdGlvbicpLmxlbmd0aCA9PSAwKXsgcmV0dXJuOyB9XG5cblx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuXHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKTtcblx0fSwgMTAwKTtcbn0pO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG5cdGluaXRpYWxpemVFdmVudHMoKTtcbn07XG5cbmV4cG9ydHMudXBkYXRlU3VtbWFyeSA9IHVwZGF0ZVN1bW1hcnk7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4Jyk7XG52YXIgZmluZE1vcmVTdG9yZXMgPSByZXF1aXJlKCcuLi8uLi9maW5kTW9yZVN0b3JlcycpO1xudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcbnZhciBBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nO1xudmFyIEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2c7XG52YXIgQWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyJyk7XG52YXIgQ2hlY2tvdXRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0NoZWNrb3V0Q29uc3RhbnRzJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG5cbnZhciBzaGlwcGluZ01ldGhvZHM7XG52YXIgaXNTdG9yZVNoaXBwaW5nQWRkcmVzc09ubHk7XG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGRhdGFCdWZmZXIgPSB7fTtcblxudmFyIGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lclNlbGVjdG9yID0gJy5iaWxsaW5nLWFkZHJlc3MtZm9ybSc7XG52YXIgJGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lciA9ICQoYmlsbGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyU2VsZWN0b3IpO1xudmFyIGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yID0gJyNiaWxsaW5nQWRkcmVzc0Zvcm0nO1xudmFyICRiaWxsaW5nQWRkcmVzc0Zvcm0gPSAkKGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcbnZhciBzaGlwcGluZ0FkZHJlc3NTZWN0aW9uU2VsZWN0b3IgPSAnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJztcbnZhciAkc2hpcHBpbmdBZGRyZXNzU2VjdGlvbiA9ICQoc2hpcHBpbmdBZGRyZXNzU2VjdGlvblNlbGVjdG9yKTtcbnZhciBzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyU2VsZWN0b3IgPSAnLnNoaXBwaW5nLWFkZHJlc3MtZm9ybSc7XG52YXIgJHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIgPSAkKHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXJTZWxlY3Rvcik7XG52YXIgc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yID0gJyNzaGlwcGluZ0FkZHJlc3NGb3JtJztcbnZhciAkc2hpcHBpbmdBZGRyZXNzRm9ybSA9ICQoc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcbnZhciBwYXltZW50Rm9ybUNvbnRhaW5lclNlbGVjdG9yID0gJy5wYXltZW50LXNlY3Rpb24nO1xudmFyICRwYXltZW50Rm9ybUNvbnRhaW5lciA9ICQocGF5bWVudEZvcm1Db250YWluZXJTZWxlY3Rvcik7XG52YXIgcGF5bWVudEZvcm1TZWxlY3RvciA9ICcjcGF5bWVudFNlY3Rpb24nO1xudmFyICRwYXltZW50Rm9ybSA9ICQocGF5bWVudEZvcm1TZWxlY3Rvcik7XG52YXIgJHNlY3Rpb25DaGVja291dCA9ICQoJy5zZWN0aW9uLWNoZWNrb3V0Jyk7XG52YXIgJHNoaXBwaW5nTWV0aG9kTGlzdCA9ICQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbiAjc2hpcHBpbmctbWV0aG9kLWxpc3QnKTtcblxudmFyIHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3I7XG52YXIgYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuXHQkc2VjdGlvbkNoZWNrb3V0Lm9uKCdjbGljaycsICcuZmluZC1tb3JlLXN0b3JlcyBhJywgZnVuY3Rpb24gKCkge1xuXHRcdGZpbmRNb3JlU3RvcmVzLmluaXRpYWxpemUoeyB2aWV3OiAnY2hlY2tvdXQnLCBzdG9yZVF1ZXJ5OiBTdG9yZVF1ZXJ5RmlsdGVycy5TaGlwVG9TdG9yZUVuYWJsZWQgfSk7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5pbnRlcm5hdGlvbmFsLWNoZWNrb3V0JywgZnVuY3Rpb24oKSB7XG5cdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICdmb3JtIFtpZCo9XCJfY291bnRyeVwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkZm9ybSA9ICR0aGlzLmNsb3Nlc3QoJ2Zvcm0nKTtcblx0XHR2YXIgJHN0YXRlRHJvcGRvd24gPSAkZm9ybS5maW5kKCdbaWQqPVwic3RhdGVzX3N0YXRlXCJdJyk7XG5cblx0XHRyZW5kZXJPcHRpb25zKCcjJyArICRzdGF0ZURyb3Bkb3duLmF0dHIoJ2lkJyksICcjJyArICR0aGlzLmF0dHIoJ2lkJykpO1xuXG5cdFx0dmFyICRpbml0aWFsU3RhdGUgPSAkZm9ybS5maW5kKCcuaW5pdGlhbC1zdGF0ZScpO1xuXHRcdHZhciBpbml0aWFsU3RhdGVWYWx1ZSA9ICRpbml0aWFsU3RhdGUudmFsKCk7XG5cdFx0dmFyICRzZWxlY3RlZFN0YXRlT3B0aW9uID0gJHN0YXRlRHJvcGRvd24uZmluZCgnb3B0aW9uW3ZhbHVlPVwiJyArIGluaXRpYWxTdGF0ZVZhbHVlICsgJ1wiXScpO1xuXHRcdGlmICgkc2VsZWN0ZWRTdGF0ZU9wdGlvbi5sZW5ndGggPiAwKSB7XG5cdFx0XHQkc3RhdGVEcm9wZG93bi52YWwoaW5pdGlhbFN0YXRlVmFsdWUpO1xuXHRcdFx0JHNlbGVjdGVkU3RhdGVPcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHR9XG5cblx0XHRpZiAoJGZvcm0uYXR0cignaWQnKSA9PSAkc2hpcHBpbmdBZGRyZXNzRm9ybS5hdHRyKCdpZCcpICYmICR0aGlzLnZhbCgpKSB7XG5cdFx0XHRpZiAoJHRoaXMudmFsKCkudG9VcHBlckNhc2UoKSA9PSBTaXRlQ29uc3RhbnRzLkNvdW50cnlDb2Rlcy5Vbml0ZWRTdGF0ZXMpIHtcblx0XHRcdFx0JCgnI3NoaXBwaW5nLWludGVybmF0aW9uYWwtaW5mbycpLmhpZGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoJyNzaGlwcGluZy1pbnRlcm5hdGlvbmFsLWluZm8nKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJ2Zvcm0gW2lkKj1cIl9wb3N0YWxcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHQkdGhpcy52YWwoJHRoaXMudmFsKCkudG9VcHBlckNhc2UoKSk7XG5cdH0pO1xuXG5cdCQoJy5zaGlwcGluZy1zYW1lJykub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcblx0XHRpZigkKCcuc2hpcHBpbmctc2FtZScpLmlzKCc6Y2hlY2tlZCcpKXtcblx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKCcuYWRkLWRpZmYnKS5vbignY2xpY2snLCBmdW5jdGlvbigpe1xuXHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0fSk7XG5cblx0JGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5vbignY2xpY2snLCAnLmVkaXQtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRlZGl0QmlsbGluZ0FkZHJlc3MoKTtcblx0fSk7XG5cblx0JGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5vbignY2xpY2snLCAnLmNhbmNlbC1hZGRyZXNzLWRldCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0JCgnLmJpbGwtYWRkcmVzcy1maWVsZHMnKS5hZGRDbGFzcygnY29sbGFwc2VkJykuaGlkZSgpO1xuXHRcdCQoJy5iaWxsaW5nLXNlbGVjdC1hZGRyZXNzJykuc2hvdygpO1xuXG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1wcmV2aWV3Jykuc2hvdygpO1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5zaG93KCk7XG5cblx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5zaG93KCk7XG5cblx0XHQkc2hpcHBpbmdBZGRyZXNzU2VjdGlvbi5hZGRDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblxuXHRcdGlmICgkc2hpcHBpbmdBZGRyZXNzU2VjdGlvbi5hdHRyKCdwYW5lbC1tb2RlJykgIT0gJ3ZpZXcnKSB7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0XHRcdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoJCgnLnNoaXBwaW5nLW1ldGhvZHMtc2VjdGlvbiAuc2hpcHBpbmctcmVzdHJpY3Rpb25zJykubGVuZ3RoID09IDApIHtcblx0XHRcdCQoJy5wYXltZW50LW1ldGhvZHMtc2VjdGlvbicpLnNob3coKTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5vbignY2xpY2snLCAnLmVkaXQtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRlZGl0U2hpcHBpbmdBZGRyZXNzKCk7XG5cdH0pO1xuXG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5vbignY2xpY2snLCAnLmFkZC1hZGRyZXNzLWRldCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0d3JpdGVTaGlwcGluZ0FkZHJlc3NGb3JtVG9CdWZmZXIoKTtcblxuXHRcdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAnYWRkJyk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZGF0YSgnaGlkZGVuLWVkaXRhYmxlJywgdHJ1ZSkuaGlkZSgpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5oaWRlKCk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuc2hvdygpO1xuXG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0ucmVtb3ZlQ2xhc3MoJ2FkZCBlZGl0JykuYWRkQ2xhc3MoJ2FkZCcpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhY3Rpb25cIl0nKS52YWwoJ2FkZCcpO1xuXG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmNzcygnZGlzcGxheScsICdibG9jaycpO1xuXHRcdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXG5cdFx0dmFyICRzaGlwcGluZ0FkZHJlc3NGb3JtRmllbGRzID0gJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nJyk7XG5cdFx0JCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nIC5pbml0aWFsLXN0YXRlJykudmFsKCcnKTtcblxuXHRcdCQoJy5zaGlwcGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0XHQkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcnKS5yZW1vdmVDbGFzcygnY29sbGFwc2VkJyk7XG5cdFx0JCgnI2R3ZnJtX3NpbmdsZXNoaXBwaW5nX2FkZHJlc3NMaXN0JykudmFsKCcnKTtcblxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ2lucHV0OnRleHQsIGlucHV0OnBhc3N3b3JkLCBpbnB1dDpmaWxlLCB0ZXh0YXJlYScpLnZhbCgnJyk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnb3B0aW9uW2RlZmF1bHRdJykucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcy5maW5kKCdpbnB1dDpjaGVja2JveCwgaW5wdXQ6cmFkaW8nKS5yZW1vdmVBdHRyKCdjaGVja2VkJyk7XG5cblx0XHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fSk7XG5cblx0JCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLm9uKCdjbGljaycsICcuY2FuY2VsLWFkZHJlc3MtZGV0JywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR3cml0ZUJ1ZmZlclRvU2hpcHBpbmdBZGRyZXNzRm9ybSgpO1xuICAgXHRcdHN1Ym1pdFNoaXBwaW5nKHRydWUpO1xuXHR9KTtcblxuICAgICQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0Jykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzaGlwcGluZ0FkZHJlc3NUeXBlID0gJCh0aGlzKS52YWwoKTtcbiAgICAgICAgc2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5mb3JtKCk7XG5cdFx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICdibGFuaycpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc3Bhbi5lcnJvcicpLnJlbW92ZSgpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgaW5wdXQsIC5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XG4gICAgICAgIGlmIChzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyKSB7XG4gICAgICAgIFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZCBpbnB1dFt0eXBlPVwidGV4dFwiXSwgLmZvcm1maWVsZCBzZWxlY3QnKS5ub3QoJ1tkaXNhYmxlZF0nKS5ub3QoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfbXlTdG9yZUlEJykudmFsKCcnKTtcbiAgICAgICAgXHQkKCcuZm9ybS1jaGVja291dC5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdzaGlwcGluZy1hZGRyZXNzLXR5cGUnLCAnbXktYWRkcmVzcycpLmF0dHIoJ3ZhbHVlJywgJ2ZhbHNlJyk7XG4gICAgICAgIFx0XG4gICAgICAgIFx0aWYgKCQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0IG9wdGlvbicpLmxlbmd0aCA+IDAgfHwgZGF0YUJ1ZmZlci5zaGlwcGluZ0FkZHJlc3NGaWVsZHMgJiYgZGF0YUJ1ZmZlci5zaGlwcGluZ0FkZHJlc3NGaWVsZHNbJ2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19maXJzdE5hbWUnXSkge1xuXHRcdFx0XHR3cml0ZUJ1ZmZlclRvU2hpcHBpbmdBZGRyZXNzRm9ybSgpO1xuICAgICAgICBcdFx0XG5cdFx0XHRcdGlmICgkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2tGb3JGb3JtKCRzaGlwcGluZ0FkZHJlc3NGb3JtKSk7XG5cdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLnNob3coKTtcblx0XHRcdFx0XG5cdFx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpOyBcblx0XHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0IG9wdGlvbicpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkIG9wdGlvbltkZWZhdWx0XScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcsIGZhbHNlKTtcblx0XHRcdFx0JCgnLmZvcm0tY2hlY2tvdXQuYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICd2aWV3Jyk7XG5cblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZGF0YSgnaGlkZGVuLWVkaXRhYmxlJywgdHJ1ZSkuaGlkZSgpO1xuXHRcdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuc2hvdygpO1xuXHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5yZW1vdmVDbGFzcygnYWRkIGVkaXQnKS5hZGRDbGFzcygnZWRpdCcpO1xuXHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWN0aW9uXCJdJykudmFsKCdlZGl0Jyk7XG5cblx0XHRcdFx0JCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nJykucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlZCcpO1xuXHRcdFx0XHRzZXRTaGlwVG9TdG9yZShmYWxzZSk7XG5cdFx0XHR9XG5cblx0XHRcdHNldFNoaXBUb1N0b3JlKGlzU2hpcFRvU3RvcmVFbmFibGVkKCkpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblxuXHRcdFx0aWYgKHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkpIHtcblx0XHRcdFx0c2V0T1BDQWRkcmVzcyhzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IsICdkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc2F2ZW9wY2FkZHJlc3MnKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgXHRcdFx0XHRoYW5kbGVTaGlwcGluZ1Jlc3RyaWN0aW9ucyhkYXRhKTtcdFxuXHRcdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblxuXHRcdFx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgdHJ1ZSwgbnVsbCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCRzaGlwcGluZ0FkZHJlc3NGb3JtLCB0cnVlLCBudWxsKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cblxuXHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmNzcygnZGlzcGxheScsICdibG9jaycpO1xuXG4gICAgICAgICAgICBpZiAoJCgnLm11bHRpcGxlLnNlbGVjdC1hZGRyZXNzIG9wdGlvbicpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIFx0JCgnLm11bHRpcGxlLnNlbGVjdC1hZGRyZXNzJykuc2hvdygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFx0JCgnLm11bHRpcGxlLnNlbGVjdC1hZGRyZXNzJykuaGlkZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIFx0JCgnLnNpbmdsZS5zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcbiAgICAgICAgfSBlbHNlIGlmIChzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLlN0b3JlKSB7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG4gICAgICAgICAgICAkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcnKS5hZGRDbGFzcygnY29sbGFwc2VkJyk7XG4gICAgICAgICAgICAkKCcubXVsdGlwbGUuc2VsZWN0LWFkZHJlc3MnKS5oaWRlKCk7XG5cbiAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuRU5BQkxFX1NISVBfVE9fU1RPUkVfU0VMRUNUSU9OKSB7XG4gICAgICAgICAgICAgICAgJCgnLnNpbmdsZS5zZWxlY3QtYWRkcmVzcycpLnNob3coKTtcblx0XHRcdH1cblx0XHRcdCQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkKCdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0xpc3RcIl0nLCAkYmlsbGluZ0FkZHJlc3NGb3JtKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSAkKHRoaXMpLmNoaWxkcmVuKCc6c2VsZWN0ZWQnKS5maXJzdCgpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzID0gJChzZWxlY3RlZCkuZGF0YSgnYWRkcmVzcycpO1xuXG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCAkYmlsbGluZ0FkZHJlc3NGb3JtKTtcbiAgICAgICAgYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmZvcm0oKTtcbiAgICB9KTtcblxuICAgICQoJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzTGlzdFwiXScsICRzaGlwcGluZ0FkZHJlc3NGb3JtKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSAkKHRoaXMpLmNoaWxkcmVuKCc6c2VsZWN0ZWQnKS5maXJzdCgpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzID0gJChzZWxlY3RlZCkuZGF0YSgnYWRkcmVzcycpO1xuXG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7IHJldHVybjsgfVxuXG4gICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCAkc2hpcHBpbmdBZGRyZXNzRm9ybSk7XG4gICAgICAgIHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuZm9ybSgpO1xuICAgIH0pO1xuXG4gICAgJCgnI3N1Ym1pdEJpbGxpbmcnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKXtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdHN1Ym1pdEJpbGxpbmcoKTtcbiAgICB9KTtcblxuICAgICQoJyNzdWJtaXRTaGlwcGluZycpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdHN1Ym1pdFNoaXBwaW5nKCk7XG4gICAgfSk7XG5cblx0JCgnLnRvZ2dsZS50b3AsIC50b2dnbGUuYm90dG9tJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHQkKCcjaW50ZXJuYXRpb25hbGluZm8nKS5zbGlkZVRvZ2dsZSgpO1xuXHR9KTtcblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzQXV0b2NvbXBsZXRlLkVuYWJsZWQpIHtcblx0XHQkKGRvY3VtZW50KS5vZmYoJ2tleXVwLkFkZHJlc3NBdXRvY29tcGxldGUnKS5vbigna2V5dXAuQWRkcmVzc0F1dG9jb21wbGV0ZScsIGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yICsgJyBpbnB1dFt0eXBlPVwidGV4dFwiXSwgJyArIHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciArICcgaW5wdXRbdHlwZT1cInRleHRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHR2YXIgJGZvcm0gPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG5cdFx0XHR2YXIgZm9ybVZhbGlkYXRvciA9ICRmb3JtLnZhbGlkYXRlKCk7XG5cblx0XHRcdGlmIChldmVudC5rZXlDb2RlID09IDggfHwgZXZlbnQua2V5Q29kZSA9PSA0Nikge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKCFmb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICgkdGhpcy5hdHRyKCdpZCcpLmluZGV4T2YoJ19hZGRyZXNzMScpID49IDAgfHwgJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfYWRkcmVzczInKSA+PSAwKSkge1xuXHRcdFx0XHR2YXIgYWRkcmVzc0F1dG9jb21wbGV0ZUhhbmRsZXIgPSBmdW5jdGlvbiAoYWRkcmVzc0F1dG9jb21wbGV0ZURhdGEpIHtcblx0XHRcdFx0XHRBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgYWRkcmVzc0F1dG9jb21wbGV0ZURhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHRcblx0XHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5BdXRvY29tcGxldGVBZGRyZXNzKCRmb3JtLCAkdGhpcywgb3B0aW9ucykudGhlbihhZGRyZXNzQXV0b2NvbXBsZXRlSGFuZGxlcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub2ZmKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NBdXRvY29tcGxldGUnKS5vbignU2V0QWRkcmVzc0Zyb21BZGRyZXNzQXV0b2NvbXBsZXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZyhkYXRhLiRmb3JtLCBkYXRhLkFkZHJlc3MpO1xuXHRcdH0pO1xuXHR9XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc1ZlcmlmaWNhdGlvbi5FbmFibGVkKSB7XG5cdFx0JChkb2N1bWVudCkub2ZmKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nKS5vbignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJywgZnVuY3Rpb24gKGV2ZW50LCBhZGRyZXNzRGF0YSkge1xuXHRcdFx0aWYgKGFkZHJlc3NEYXRhLkFkZHJlc3NUeXBlID09ICdiaWxsaW5nJykge1xuXHRcdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZygkYmlsbGluZ0FkZHJlc3NGb3JtLCBhZGRyZXNzRGF0YSk7XG5cdFx0XHRcdHN1Ym1pdEJpbGxpbmcodHJ1ZSk7XG5cdFx0XHR9IGVsc2UgaWYgKGFkZHJlc3NEYXRhLkFkZHJlc3NUeXBlID09ICdzaGlwcGluZycpIHtcblx0XHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIGFkZHJlc3NEYXRhKTtcblx0XHRcdFx0c3VibWl0U2hpcHBpbmcoZmFsc2UsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0JChkb2N1bWVudCkub24oJ29wYy5TZXRTaGlwcGluZ0FkZHJlc3MnLCBmdW5jdGlvbiAoZSwgYWRkcmVzcykge1xuXHRcdHZhciB0ZW1wbGF0ZVNldHRpbmdzID0ge1xuXHRcdFx0XHRpbnRlcnBvbGF0ZTogL3t7KFtcXHNcXFNdKz8pfX0vZ1xuXHQgICAgXHR9O1xuXG5cdFx0dmFyIHRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYWRkcmVzcy1zZWxlY3Rvci1vcHRpb24nKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuXG5cdFx0YWRkcmVzcy5JRCA9IGFkZHJlc3Mua2V5O1xuXHRcdGlmIChhZGRyZXNzLmlzTXlTdG9yZSAmJiAhYWRkcmVzcy5teVN0b3JlSUQgJiYgYWRkcmVzcy5zdG9yZUlkKSB7XG5cdFx0XHRhZGRyZXNzLm15U3RvcmVJRCA9IGFkZHJlc3Muc3RvcmVJZDtcblx0XHR9XG5cblx0XHR2YXIgdGVtcGxhdGVEYXRhID0gXy5leHRlbmQoYWRkcmVzcywge1xuXHRcdFx0aWQ6IGFkZHJlc3MuVVVJRCxcblx0XHRcdGNzc0NsYXNzOiAnZmluZC1tb3JlLXN0b3JlLW9wdGlvbicsXG5cdFx0XHRzZWxlY3RlZDogJ3NlbGVjdGVkJyxcblx0XHRcdHRleHQ6IGFkZHJlc3MubGFiZWxUZXh0XG5cdFx0fSk7XG5cblx0XHR2YXIgJGFkZHJlc3NMaXN0ID0gJCgnI215c3RvcmVzX2FkZHJlc3NMaXN0Jyk7XG5cblx0XHR2YXIgYWRkcmVzc0luZGV4SW5MaXN0ID0gbnVsbDtcblx0XHQkYWRkcmVzc0xpc3QuZmluZCgnb3B0aW9uJykuZWFjaChmdW5jdGlvbiAoaW5kZXgsIG9iamVjdCkge1xuXHRcdFx0aWYgKGFkZHJlc3MuSUQgPT0gJChvYmplY3QpLnZhbCgpKSB7XG5cdFx0XHRcdGFkZHJlc3NJbmRleEluTGlzdCA9IGluZGV4O1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0ICAgIGlmIChhZGRyZXNzSW5kZXhJbkxpc3QpIHtcblx0XHRcdCRhZGRyZXNzTGlzdC5wcm9wKCdzZWxlY3RlZEluZGV4JywgYWRkcmVzc0luZGV4SW5MaXN0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGF0YUJ1ZmZlclsnbXlzdG9yZXNfYWRkcmVzc0xpc3QnXSA9IGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10uZmlsdGVyKGZ1bmN0aW9uIChhZGRyZXNzKSB7XG5cdFx0XHRcdHJldHVybiAhYWRkcmVzcy5pc1RlbXBvcmFyeTtcblx0XHRcdH0pO1xuXG5cdFx0XHRhZGRyZXNzLmlzVGVtcG9yYXJ5ID0gdHJ1ZTtcblx0XHRcdGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10ucHVzaChhZGRyZXNzKTtcblx0XHRcdGRhdGFCdWZmZXJbJ3N0b3JlX25hbWVfbG9va3VwJ11bYWRkcmVzcy5maXJzdE5hbWVdID0gYWRkcmVzcy5mdWxsTmFtZTtcblx0XHRcdFxuXHRcdFx0JGFkZHJlc3NMaXN0LmZpbmQoJy5maW5kLW1vcmUtc3RvcmUtb3B0aW9uJykucmVtb3ZlKCk7XG5cdFx0XHQkYWRkcmVzc0xpc3QucHJlcGVuZCh0ZW1wbGF0ZSh0ZW1wbGF0ZURhdGEpKS5wcm9wKCdzZWxlY3RlZEluZGV4JywgMCk7XG5cdFx0fVxuXG5cdCAgICAkKCcjbXlzdG9yZXNfYWRkcmVzc0xpc3QnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCwgI215c3RvcmVzX2FkZHJlc3NMaXN0JywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBhY3Rpb25OYW1lID0gJ2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zYXZlb3BjYWRkcmVzcyc7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCBzcGFuLmVycm9yJykucmVtb3ZlKCk7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCBpbnB1dCwgLnNoaXBwaW5nLWFkZHJlc3MtY29udCBzZWxlY3QnKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcblxuXHRcdHZhciAkdGFyZ2V0ID0gJChlLmN1cnJlbnRUYXJnZXQpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzO1xuXHRcdGlmICgkdGFyZ2V0ICYmICR0YXJnZXQuYXR0cignaWQnKSkge1xuXHRcdFx0dmFyIGRhdGFCdWZmZXJGb3JBZGRyZXNzTGlzdCA9IGRhdGFCdWZmZXJbJHRhcmdldC5hdHRyKCdpZCcpXTtcblx0XHRcdGlmIChkYXRhQnVmZmVyRm9yQWRkcmVzc0xpc3QpIHtcblx0XHRcdFx0c2VsZWN0ZWRBZGRyZXNzID0gZGF0YUJ1ZmZlckZvckFkZHJlc3NMaXN0LmZpbHRlcihmdW5jdGlvbiAoYWRkcmVzcykge1xuXHRcdFx0XHRcdHJldHVybiBhZGRyZXNzLlVVSUQgPT0gJHRhcmdldC52YWwoKTtcblx0XHRcdFx0fSlbMF07XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7XG4gICAgICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cblx0XHR2YXIgaXNTdG9yZUFkZHJlc3MgPSBmYWxzZTtcblx0XHR2YXIgc3RvcmVJZDtcbiAgICAgICAgaWYgKHNlbGVjdGVkQWRkcmVzcy5oYXNPd25Qcm9wZXJ0eSgnaXNNeVN0b3JlJykgJiYgc2VsZWN0ZWRBZGRyZXNzLm15U3RvcmVJRCkge1xuXHRcdFx0aXNTdG9yZUFkZHJlc3MgPSBzZWxlY3RlZEFkZHJlc3MuaXNNeVN0b3JlO1xuXHRcdFx0c3RvcmVJZCA9IHNlbGVjdGVkQWRkcmVzcy5teVN0b3JlSUQ7XG4gICAgICAgIH1cblxuXHRcdHNldFNoaXBUb1N0b3JlKGlzU3RvcmVBZGRyZXNzKTtcblxuXHRcdGlmIChpc1N0b3JlQWRkcmVzcykge1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZC5teVN0b3JlSUQgaW5wdXQnKS52YWwoc3RvcmVJZCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQgaW5wdXRbdHlwZT1cInRleHRcIl0sIC5mb3JtZmllbGQgc2VsZWN0Jykubm90KCdbZGlzYWJsZWRdJykubm90KCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX215U3RvcmVJRCcpLnZhbCgnJyk7XG5cdFx0XHR1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJHNoaXBwaW5nQWRkcmVzc0Zvcm0pO1xuXHRcdH1cblx0XHQkdGhpcy5maW5kKCdvcHRpb24ucGxhY2Vob2xkZXInKS5yZW1vdmUoKTtcblxuXHRcdHNldE9QQ0FkZHJlc3Moc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yLCBhY3Rpb25OYW1lKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRoYW5kbGVTaGlwcGluZ1Jlc3RyaWN0aW9ucyhkYXRhKTtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcsIHRydWUpO1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2tGb3JBZGRyZXNzKHNlbGVjdGVkQWRkcmVzcywgZmFsc2UsIGZhbHNlLCAnc2hpcHBpbmdBZGRyZXNzRm9ybScpKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG5cblx0XHRcdGlmIChiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IudmFsaWQoKSkge1xuXHRcdFx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblxuXHRcdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLnNob3coKTtcblx0XHRcdFx0JGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgdHJ1ZSwgaXNTdG9yZUFkZHJlc3MpO1xuXHRcdH0uYmluZCh0aGlzKSk7XG5cdH0pO1xuXG5cdCQoJyNkd2ZybV9iaWxsaW5nX2FkZHJlc3NMaXN0Jykub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCkge1xuICAgIFx0JCgnLmN1c3RvbS1lbWFpbC1lcnJvcicpLnJlbW92ZSgpO1xuICAgIFx0dmFyIGlzRW1haWxWYWxpZCA9IHV0aWwudmFsaWRhdGVFbWFpbCgkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfZW1haWwnKS52YWwoKSk7XG5cblx0XHRpZiAoJCh0aGlzKS52YWwoKSAmJiBiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IudmFsaWQoKSAmJiBpc0VtYWlsVmFsaWQpIHtcblx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkYmlsbGluZ0FkZHJlc3NGb3JtKSkuc2hvdygpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkKCcuZm9ybS1jaGVja291dC5hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdwYW5lbC1tb2RlJywgJ3ZpZXcnKS5hdHRyKCd2YWx1ZScsICd0cnVlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGVkaXRCaWxsaW5nQWRkcmVzcygpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNoaXBUb1N0b3JlLkNoYW5nZScpLm9uKCdjbGljay5TaGlwVG9TdG9yZS5DaGFuZ2UnLCAnW3NoaXBwaW5nLW1ldGhvZF0gLnN0b3JlLWRldGFpbHMgLmNoYW5nZScsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyICRzaGlwcGluZ01ldGhvZCA9ICQodGhpcykuY2xvc2VzdCgnW3NoaXBwaW5nLW1ldGhvZF0nKTtcblx0XHQkc2hpcHBpbmdNZXRob2QuZmluZCgnLnN0b3JlLWRldGFpbHMnKS5oaWRlKCk7XG5cdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1zZWxlY3RvcicpLnNob3coKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjaGFuZ2UuU2hpcFRvU3RvcmUuQXBwbHknKS5vbignY2hhbmdlLlNoaXBUb1N0b3JlLkFwcGx5JywgJ1tzaGlwcGluZy1tZXRob2RdIC5zdG9yZS1zZWxlY3RvciBzZWxlY3QnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkKHRoaXMpLmNsb3Nlc3QoJ1tzaGlwcGluZy1tZXRob2RdJyk7XG5cdFx0dmFyICRzZWxlY3RlZFN0b3JlID0gJHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1zZWxlY3RvciBvcHRpb246Y2hlY2tlZCcpO1xuXHRcdHZhciBzdG9yZUlkID0gJHNlbGVjdGVkU3RvcmUudmFsKCk7XG5cdFx0XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZC5teVN0b3JlSUQgaW5wdXQnKS52YWwoc3RvcmVJZCk7XG5cblx0XHRzZXRPUENBZGRyZXNzKHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciwgJ2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zYXZlb3BjYWRkcmVzcycpLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHsgXG5cdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUpO1xuXHRcdH0pO1xuXG5cdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1kZXRhaWxzJykuc2hvdygpO1xuXHRcdCRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3InKS5oaWRlKCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2hpcFRvU3RvcmUuQ2FuY2VsJykub24oJ2NsaWNrLlNoaXBUb1N0b3JlLkNhbmNlbCcsICdbc2hpcHBpbmctbWV0aG9kXSAuc3RvcmUtc2VsZWN0b3IgLmNhbmNlbCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyICRzaGlwcGluZ01ldGhvZCA9ICQodGhpcykuY2xvc2VzdCgnW3NoaXBwaW5nLW1ldGhvZF0nKTtcblx0XHQkc2hpcHBpbmdNZXRob2QuZmluZCgnLnN0b3JlLWRldGFpbHMnKS5zaG93KCk7XG5cdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1zZWxlY3RvcicpLmhpZGUoKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5TaGlwcGluZ01ldGhvZC5TZWxlY3QnKS5vbignY2xpY2suU2hpcHBpbmdNZXRob2QuU2VsZWN0JywgJ2lucHV0W25hbWUqPVwiX3NoaXBwaW5nTWV0aG9kSURcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkdGhpcy5jbG9zZXN0KCdbc2hpcHBpbmctbWV0aG9kXScpO1xuXHRcdHZhciAkc2hpcG1lbnQgPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG5cblx0XHRpZiAoJHNoaXBwaW5nTWV0aG9kLmF0dHIoJ3N0YXR1cycpID09ICdkaXNhYmxlZCcpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNlbGVjdFNoaXBwaW5nTWV0aG9kKCRzaGlwbWVudC5hdHRyKCdzaGlwbWVudCcpLCAkdGhpcy52YWwoKSwgJHNoaXBwaW5nTWV0aG9kLmF0dHIoJ2lzLXNoaXAtdG8tc3RvcmUnKSA9PSAndHJ1ZScsICRzaGlwcGluZ01ldGhvZCk7IFxuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdmb2N1cy5BdXRvZmlsbEhhbmRsZXInKS5vbignZm9jdXMuQXV0b2ZpbGxIYW5kbGVyJywgJ2Rpdi5iaWxsaW5nLWFkZHJlc3MtZm9ybSBpbnB1dFt0eXBlPVwidGV4dFwiXSwgZGl2LnNoaXBwaW5nLWFkZHJlc3MtZm9ybSBpbnB1dFt0eXBlPVwidGV4dFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRmb3JtID0gJHRoaXMuY2xvc2VzdCgnZm9ybScpO1xuXHRcdHZhciBhdXRvZmlsbENvdW50ID0gJGZvcm0uZmluZCgnaW5wdXQ6LXdlYmtpdC1hdXRvZmlsbCcpLmxlbmd0aDtcblxuXHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjgpIHtcblx0XHRcdGlmIChhdXRvZmlsbENvdW50ID09IDApIHtcblx0XHRcdFx0JGZvcm0uYXR0cignYXV0by1maWxsZWQnLCBmYWxzZSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICgkZm9ybS5hdHRyKCdhdXRvLWZpbGxlZCcpICE9ICd0cnVlJykge1xuXHRcdFx0XHRkYXRhQnVmZmVyLkF1dG9maWxsRGV0ZWN0b3JJbnRlcnZhbCA9IHNldEludGVydmFsKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGF1dG9maWxsQ291bnQgPSAkZm9ybS5maW5kKCdpbnB1dDotd2Via2l0LWF1dG9maWxsJykubGVuZ3RoO1xuXHRcdFx0XHRcdGlmIChhdXRvZmlsbENvdW50ID4gMCAmJiAkZm9ybS5hdHRyKCdhdXRvLWZpbGxlZCcpICE9ICd0cnVlJykge1xuXHRcdFx0XHRcdFx0JGZvcm0uYXR0cignYXV0by1maWxsZWQnLCB0cnVlKTtcblx0XHRcdFx0XHRcdCR0aGlzLmF0dHIoJ2lucHV0bW9kZScsICdub25lJyk7XG5cdFx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCdibHVyJyk7XG5cdFx0XHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5yZW1vdmVBdHRyKCdpbnB1dG1vZGUnKTtcblx0XHRcdFx0XHRcdH0sIDI1MCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LCAyNTApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbiQoZG9jdW1lbnQpLm9mZignYmx1ci5BdXRvZmlsbEhhbmRsZXInKS5vbignYmx1ci5BdXRvZmlsbEhhbmRsZXInLCAnZGl2LmJpbGxpbmctYWRkcmVzcy1mb3JtIGlucHV0W3R5cGU9XCJ0ZXh0XCJdLCBkaXYuc2hpcHBpbmctYWRkcmVzcy1mb3JtIGlucHV0W3R5cGU9XCJ0ZXh0XCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdGlmIChkYXRhQnVmZmVyICYmIGRhdGFCdWZmZXIuQXV0b2ZpbGxEZXRlY3RvckludGVydmFsKSB7XG5cdFx0Y2xlYXJJbnRlcnZhbChkYXRhQnVmZmVyLkF1dG9maWxsRGV0ZWN0b3JJbnRlcnZhbCk7XG5cdH1cbn0pO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplVXNlckludGVyZmFjZSgpIHtcblx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19JRCcpLnZhbCgnJyk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LmFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAnYmxhbmsnKTtcblx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICdibGFuaycpLmF0dHIoJ3ZhbHVlJywgJ2ZhbHNlJyk7XG5cblx0dmFyIGJpbGxpbmdBZGRyZXNzID0gZ2V0QWRkcmVzc0Zyb21Gb3JtKCRiaWxsaW5nQWRkcmVzc0Zvcm0pO1xuXHR2YXIgc2hpcHBpbmdBZGRyZXNzID0gZ2V0QWRkcmVzc0Zyb21Gb3JtKCRzaGlwcGluZ0FkZHJlc3NGb3JtKTtcblx0dmFyICRiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24gPSAkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpO1xuXHR2YXIgZGlkQmlsbGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlclJ1biA9IGZhbHNlO1xuXHR2YXIgZGlkU2hpcHBpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXJSdW4gPSBmYWxzZTtcblx0XG5cdCQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19jb3VudHJ5JykudHJpZ2dlcignY2hhbmdlJyk7XG5cdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfY291bnRyeScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXG5cdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgncmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbicsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVSZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uLCBSZXNvdXJjZXMuSU5WQUxJRF9WQUxVRSk7XG5cdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgncG9zdGFsQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVQb3N0YWxDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgncG9zdE9mZmljZUJveE9ubHknLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5LCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUX09GRklDRV9CT1hfT05MWSk7XG5cdFxuXHRiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IgPSAkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCk7XG5cdGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5zZXR0aW5ncy5pZ25vcmUgPSBbXCI6bm90KC5yZXF1aXJlZClcIl07XG5cdGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5zZXR0aW5ncy5vbmZvY3Vzb3V0ID0gVmFsaWRhdGlvblNldHRpbmdzLkNoZWNrb3V0Lm9uZm9jdXNvdXQ7XG5cdGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5zZXR0aW5ncy5lcnJvclBsYWNlbWVudCA9IFZhbGlkYXRpb25TZXR0aW5ncy5DaGVja291dC5lcnJvclBsYWNlbWVudDtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9maXJzdE5hbWVcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2xhc3ROYW1lXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbik7XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5KTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHkpO1xuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbik7XG5cblx0c2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvciA9ICRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCk7XG5cdHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3Iuc2V0dGluZ3MuaWdub3JlID0gW1wiOm5vdCgucmVxdWlyZWQpXCJdO1xuXHRzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnNldHRpbmdzLm9uZm9jdXNvdXQgPSBWYWxpZGF0aW9uU2V0dGluZ3MuQ2hlY2tvdXQub25mb2N1c291dDtcblx0c2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5zZXR0aW5ncy5lcnJvclBsYWNlbWVudCA9IFZhbGlkYXRpb25TZXR0aW5ncy5DaGVja291dC5lcnJvclBsYWNlbWVudDtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbik7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seSk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seSk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXG5cdGlmICghYmlsbGluZ0FkZHJlc3MuYWRkcmVzczEgJiYgJGJpbGxpbmdTYXZlZEFkZHJEcm9wZG93bi5maW5kKCdvcHRpb24nKS5sZW5ndGggJiYgJGJpbGxpbmdTYXZlZEFkZHJEcm9wZG93bi52YWwoKSkge1xuXHRcdCRiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24udHJpZ2dlcignY2hhbmdlJyk7XG5cdH0gZWxzZSB7XG5cdFx0aWYgKGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5jaGVja0Zvcm0oKSkge1xuXHRcdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXQuc2hpcHBpbmctbmV3c2xldHRlci1zaWdudXAnKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0ZGlkQmlsbGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlclJ1biA9IGJpbGxpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXIobnVsbCwgdHJ1ZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGVkaXRCaWxsaW5nQWRkcmVzcygpO1xuXHRcdH1cblx0fVxuXG5cdHJlbmRlck15U3RvcmVzQWRkcmVzc1NlbGVjdG9yKCk7XG5cdHZhciAkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93biA9ICQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0Jyk7XG5cdGlmIChiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgIWRpZEJpbGxpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXJSdW4pIHtcblx0XHRpZiAoIXNoaXBwaW5nQWRkcmVzcy5hZGRyZXNzMSAmJiAkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5maW5kKCdvcHRpb24nKS5sZW5ndGggJiYgJHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24udmFsKCkpIHtcblx0XHRcdCRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoc2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5jaGVja0Zvcm0oKSkge1xuXHRcdFx0XHRkaWRTaGlwcGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlclJ1biA9IHNoaXBwaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyKHRydWUpO1xuXHRcdFx0XHR2ZXJpZnlTaGlwcGluZygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWRpdFNoaXBwaW5nQWRkcmVzcygpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRcblx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uIC5zZWxlY3QtYWRkcmVzcy5tdWx0aXBsZScpLnNob3coKTtcblx0JCgnLmFkZHJlc3Mtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XG5cdGlmIChkaWRCaWxsaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyUnVuICYmIHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgd2luZG93LmlubmVyV2lkdGggPD0gNzY3KSB7XG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdCQoW2RvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgZG9jdW1lbnQuYm9keV0pLnNjcm9sbFRvcCgkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcuaGVhZGVyLXdyYXBwZXInKS5oZWlnaHQoKSArIDIwKTtcblx0XHR9LCAxMDAwKTtcblx0fVxufVxuXG5mdW5jdGlvbiBiaWxsaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyKHJlc3BvbnNlRGF0YSwgc2tpcFVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCwgaXNWZXJpZmllZCkge1xuXHR2YXIgJHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24gPSAkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpO1xuXHR2YXIgc2hpcHBpbmdBZGRyZXNzID0gZ2V0QWRkcmVzc0Zyb21Gb3JtKCRzaGlwcGluZ0FkZHJlc3NGb3JtKTtcblxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0JCgnLmZvcm0tY2hlY2tvdXQuYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICd2aWV3JykuYXR0cigndmFsdWUnLCAndHJ1ZScpO1xuXHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEnKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2tGb3JGb3JtKCRiaWxsaW5nQWRkcmVzc0Zvcm0pKS5zaG93KCk7XG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cblx0aWYgKHJlc3BvbnNlRGF0YSAmJiByZXNwb25zZURhdGEuc3RhdHVzID09ICdzdWNjZXNzJyAmJiAoJCgnI2lzU2hpcHBpbmdBZGRyZXNzU2FtZUFzQmlsbGluZ0FkZHJlc3MnKS5wcm9wKCdjaGVja2VkJykgfHwgJCgnW2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQtb25seV0nKS5hdHRyKCdoYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHknKSA9PSAndHJ1ZScpKSB7XG5cdFx0cG9wdWxhdGVCaWxsaW5nQWRkcmVzc0Zvcm1Ub1NoaXBwaW5nQWRkcmVzc0Zvcm0oKTtcblx0fVxuXHRcblx0aWYgKHJlc3BvbnNlRGF0YSAmJiByZXNwb25zZURhdGEuc3RhdHVzID09ICdzaGlwcGluZ0FkZHJlc3NWYWxpZGF0aW9uRXJyb3InKSB7XG5cdFx0ZWRpdFNoaXBwaW5nQWRkcmVzcygpO1xuXHR9IGVsc2UgaWYgKFNpdGVQcmVmZXJlbmNlcy5CWVBBU1NfU0hJUFBJTkcgJiYgKCQoJyNpc1NoaXBwaW5nQWRkcmVzc1NhbWVBc0JpbGxpbmdBZGRyZXNzJykucHJvcCgnY2hlY2tlZCcpIHx8ICQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHldJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5JykgPT0gJ3RydWUnKSkge1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkc2hpcHBpbmdBZGRyZXNzRm9ybSkpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG5cblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZGF0YSgnc2hpcHBpbmctZmlsbGVkJywgdHJ1ZSk7XG5cdFx0JHBheW1lbnRGb3JtQ29udGFpbmVyLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdHN1Ym1pdFNoaXBwaW5nKG51bGwsIGlzVmVyaWZpZWQpO1xuXHR9IGVsc2UgaWYgKHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkpIHtcblx0XHRzaGlwcGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlcihza2lwVXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KTtcblx0fSBlbHNlIGlmICghc2hpcHBpbmdBZGRyZXNzLmFkZHJlc3MxICYmICRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLmZpbmQoJ29wdGlvbicpLmxlbmd0aCAmJiAkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi52YWwoKSkge1xuXHRcdCRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9IGVsc2Uge1xuXHRcdGVkaXRTaGlwcGluZ0FkZHJlc3MoKTtcblx0fVxuXG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJykuc2hvdygpO1xuXG5cdGlmICghc2tpcFVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCkge1xuXHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgdHJ1ZSk7XG5cdH1cblxuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZGF0YSgnc2hpcHBpbmctZmlsbGVkJykgPT0gdHJ1ZSkge1xuXHRcdCRwYXltZW50Rm9ybUNvbnRhaW5lci5hZGRDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLnNob3coKTtcblx0fVxuXG5cdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHQkKHdpbmRvdykuc2Nyb2xsVG9wKCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcuaGVhZGVyLXdyYXBwZXInKS5oZWlnaHQoKSk7XG5cdH1cblx0XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBzaGlwcGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlcihza2lwVXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0LCBpc0NhbmNlbCwgaXNWZXJpZmllZCkge1xuXHR2YXIgc2VsZWN0ZWRBZGRyZXNzSUQ7XG5cdHZhciBjdXJyZW50QWRkcmVzc0lEcyA9IFtdO1xuXG5cdCQoJy5zZWxlY3QtYWRkcmVzcy5hZGRyZXNzLXNlbGVjdG9yIHNlbGVjdCBvcHRpb24nKS5tYXAoZnVuY3Rpb24oKSB7IGN1cnJlbnRBZGRyZXNzSURzLnB1c2goJCh0aGlzKS52YWwoKSk7IH0pO1xuXG5cdGlmICgkc2hpcHBpbmdBZGRyZXNzRm9ybS5oYXNDbGFzcygnYWRkJykgfHwgKCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhhc0NsYXNzKCdlZGl0JykgJiYgISRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5zZXQtZGVmYXVsdC1zaGlwcGluZyBpbnB1dCcpLnByb3AoJ2NoZWNrZWQnKSkpIHtcblx0XHRzZWxlY3RlZEFkZHJlc3NJRCA9IFwibmV3XCI7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfSURcIl0nKS52YWwoJycpO1xuXG5cdFx0aWYgKCQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0JykuZmluZCgnb3B0aW9uLnBsYWNlaG9sZGVyJykubGVuZ3RoID09IDApIHtcblx0XHRcdCQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0JykucHJlcGVuZCgnPG9wdGlvbiBjbGFzcz1cInBsYWNlaG9sZGVyXCI+JyArIFJlc291cmNlcy5PUENfU0VMRUNUX0FERFIgKyAnPC9vcHRpb24+JykucHJvcCgnc2VsZWN0ZWRJbmRleCcsIDApO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRzZWxlY3RlZEFkZHJlc3NJRCA9ICQoJy5zZWxlY3QtYWRkcmVzcy5hZGRyZXNzLXNlbGVjdG9yIHNlbGVjdCcpLnZhbCgpO1xuXHR9XG5cblx0d3JpdGVTaGlwcGluZ0FkZHJlc3NGb3JtVG9CdWZmZXIoKTtcblx0dmFyIHBhbmVsTW9kZSA9ICRzaGlwcGluZ0FkZHJlc3NTZWN0aW9uLmF0dHIoJ3BhbmVsLW1vZGUnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0ucmVtb3ZlQ2xhc3MoJ2FkZCBlZGl0Jyk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAndmlldycpO1xuXG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5hZGQtdG8tYWRkcmVzcy1ib29rIGlucHV0JykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLnNldC1kZWZhdWx0LXNoaXBwaW5nIGlucHV0JykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XG5cdHZhciByZW5kZXJBZGRyZXNzU2VsZWN0b3JDYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFjdGlvblwiXScpLnZhbCgnJyk7XG5cblx0XHRpZiAoIWlzQ2FuY2VsICYmIChwYW5lbE1vZGUgPT0gJ2FkZCcgfHwgcGFuZWxNb2RlID09ICdlZGl0JykpIHtcblx0XHRcdCQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0JykucHJvcCgnc2VsZWN0ZWRJbmRleCcsIDApO1xuXHRcdH1cblxuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkc2hpcHBpbmdBZGRyZXNzRm9ybSkpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG5cdFx0aWYgKCFpc1ZlcmlmaWVkKSB7XG5cdFx0XHR2ZXJpZnlTaGlwcGluZyhpc0NhbmNlbCwgaXNWZXJpZmllZCk7XG5cdFx0fVxuXG5cdFx0aWYgKGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5jaGVja0Zvcm0oKSkge1xuXHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbiAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXG5cdFx0XHR2YXIgZm9ybUJvZHkgPSAkKCcuYmlsbGluZy1hZGRyZXNzLWZvcm0nKTtcblx0XHRcdGZvcm1Cb2R5LnNob3coKTtcblx0XHRcdGZvcm1Cb2R5LmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcblx0XHR9XG5cblx0XHRpZiAoIXNraXBVcGRhdGVTaGlwcGluZ01ldGhvZExpc3QpIHtcblx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgdHJ1ZSwgbnVsbCwgdHJ1ZSk7XG5cdFx0fVxuXHR9XG5cblx0dmFyIGlzQXV0aGVudGljYXRlZCA9ICRzZWN0aW9uQ2hlY2tvdXQuYXR0cignaXMtYXV0aGVudGljYXRlZCcpID09IFwidHJ1ZVwiO1xuXHRpZiAoaXNBdXRoZW50aWNhdGVkKSB7XG5cdFx0cmVuZGVyQWRkcmVzc1NlbGVjdG9yKHtcblx0XHRcdGNvbnRhaW5lcjogJy5zZWxlY3QtYWRkcmVzcy5hZGRyZXNzLXNlbGVjdG9yJyxcblx0XHRcdGVsOiAnLnNlbGVjdC1hZGRyZXNzLmFkZHJlc3Mtc2VsZWN0b3IgLmZpZWxkLXdyYXBwZXInLFxuXHRcdFx0aWQ6ICdkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0Jyxcblx0XHRcdHNlbGVjdGVkOiBzZWxlY3RlZEFkZHJlc3NJRCxcblx0XHRcdGN1cnJlbnRBZGRyZXNzZXM6IGN1cnJlbnRBZGRyZXNzSURzLFxuXHRcdFx0Y2FsbGJhY2s6IHJlbmRlckFkZHJlc3NTZWxlY3RvckNhbGxiYWNrXG5cdFx0fSk7XG5cdH0gZWxzZSB7XG5cdFx0cmVuZGVyQWRkcmVzc1NlbGVjdG9yQ2FsbGJhY2soKTtcblx0fVxuXG5cdGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHQkKHdpbmRvdykuc2Nyb2xsVG9wKCQoJy5wYXltZW50LXNlY3Rpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcuaGVhZGVyLXdyYXBwZXInKS5oZWlnaHQoKSk7XG5cdH1cblx0XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBzdWJtaXRCaWxsaW5nKGlzVmVyaWZpZWQpIHtcblx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXHRpZiAoJCgnLmJpbGxpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0W3ZhbHVlPTFdJykucHJvcCgnY2hlY2tlZCcpICYmICQoJyNkd2ZybV9iaWxsaW5nX2FkZHJlc3NMaXN0JykudmFsKCkgPT0gJycpIHtcblx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmICgkKCcjaXNTaGlwcGluZ0FkZHJlc3NTYW1lQXNCaWxsaW5nQWRkcmVzcycpLmlzKCc6Y2hlY2tlZCcpIHx8ICQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHldJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5JykgPT0gJ3RydWUnKSB7XG5cdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdH0gZWxzZSB7XG5cdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHR9XG5cblx0YmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmZvcm0oKTtcblx0JCgnLmN1c3RvbS1lbWFpbC1lcnJvcicpLnJlbW92ZSgpO1xuXG5cdHZhciBpc0VtYWlsVmFsaWQgPSB1dGlsLnZhbGlkYXRlRW1haWwoJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2VtYWlsJykudmFsKCkpO1xuXHRpZiAoYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnZhbGlkKCkgJiYgaXNFbWFpbFZhbGlkKSB7XG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybSA9ICQoYmlsbGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IpO1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykucmVtb3ZlQXR0cigncm9sZScpLmhpZGUoKTtcblx0XHR2ZXJpZnlCaWxsaW5nKG51bGwsIGlzVmVyaWZpZWQpO1xuXHR9IGVsc2Uge1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykuYXR0cigncm9sZScsJ2FsZXJ0Jykuc2hvdygpO1xuXHRcdCQoJyNzdWJtaXRCaWxsaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdFx0aWYgKCFpc0VtYWlsVmFsaWQgJiYgYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnZhbGlkKCkpIHtcblx0XHRcdCQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19lbWFpbCcpLmFkZENsYXNzKCdlcnJvcicpLnBhcmVudCgpLmFwcGVuZCgnPHNwYW4gY2xhc3M9XCJlcnJvciBjdXN0b20tZW1haWwtZXJyb3JcIj4nICsgUmVzb3VyY2VzLlZBTElEQVRFX0VNQUlMICsgJzwvc3Bhbj4nKTtcblx0XHR9XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0W3ZhbHVlPVwiMlwiXScpLnRyaWdnZXIoJ2NsaWNrJywgW3RydWVdKTtcblx0fVxufVxuXG5mdW5jdGlvbiB2ZXJpZnlCaWxsaW5nKGlzQ2FuY2VsLCBpc1ZlcmlmaWVkKSB7XG5cdHZhciBhZGRyZXNzRGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0c2V0T1BDQWRkcmVzcyhiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciwgJCgnI3NlbGVjdE9wY0FkZHJlc3MnKS5hdHRyKCduYW1lJykpLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdGJpbGxpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXIoZGF0YSwgbnVsbCwgdHJ1ZSk7XG5cdFx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdH0pO1xuXHR9XG5cblx0dmFyIGFkZHJlc3NOb3REZWxpdmVyYWJsZSA9IGZ1bmN0aW9uIChhZGRyZXNzVmVyaWZ5RGF0YSkge1xuXHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCAnYmlsbGluZycsIGFkZHJlc3NWZXJpZnlEYXRhKTtcblx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHR9XG5cblx0dmFyIGNvdW50cnkgPSAkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ1tpZCo9XCJfY291bnRyeVwiXScpLnZhbCgpO1xuXHRpZiAoIWlzVmVyaWZpZWQgJiYgb3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQgJiYgY291bnRyeS50b1VwcGVyQ2FzZSgpID09ICdVUycpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlZlcmlmeUFkZHJlc3MoJGJpbGxpbmdBZGRyZXNzRm9ybSwgb3B0aW9ucykudGhlbihhZGRyZXNzRGVsaXZlcmFibGUsIGFkZHJlc3NOb3REZWxpdmVyYWJsZSk7XG5cdH0gZWxzZSB7XG5cdFx0YWRkcmVzc0RlbGl2ZXJhYmxlKCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc3VibWl0U2hpcHBpbmcoaXNDYW5jZWwsIGlzVmVyaWZpZWQpIHtcblx0JCgnI3N1Ym1pdFNoaXBwaW5nJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCBzcGFuLmVycm9yJykucmVtb3ZlKCk7XG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgaW5wdXQsIC5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG5cblx0c2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5mb3JtKCk7XG5cdGlmICgkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykucmVtb3ZlQXR0cigncm9sZScpLmhpZGUoKTtcblx0XHR2ZXJpZnlTaGlwcGluZyhpc0NhbmNlbCwgaXNWZXJpZmllZCk7XG5cdH0gZWxzZSB7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykuYXR0cigncm9sZScsJ2FsZXJ0Jykuc2hvdygpO1xuXHRcdCQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHZlcmlmeVNoaXBwaW5nKGlzQ2FuY2VsLCBpc1ZlcmlmaWVkKSB7XG5cdHZhciBhZGRyZXNzRGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0c2V0T1BDQWRkcmVzcyhzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IsICQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ25hbWUnKSkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0dmFyIGlzU2hpcHBpbmdSZXN0cmljdGVkID0gaGFuZGxlU2hpcHBpbmdSZXN0cmljdGlvbnMoZGF0YSk7XG5cdFx0XHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHRcdGlmICghaXNTaGlwcGluZ1Jlc3RyaWN0ZWQpIHtcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXIoZmFsc2UsIGlzQ2FuY2VsLCB0cnVlKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kcy1zZWN0aW9uJykuc2hvdygpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dmFyIGFkZHJlc3NOb3REZWxpdmVyYWJsZSA9IGZ1bmN0aW9uIChhZGRyZXNzVmVyaWZ5RGF0YSkge1xuXHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCAnc2hpcHBpbmcnLCBhZGRyZXNzVmVyaWZ5RGF0YSk7XG5cdFx0JCgnI3N1Ym1pdFNoaXBwaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdH1cblxuXHR2YXIgY291bnRyeSA9ICRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ1tpZCo9XCJfY291bnRyeVwiXScpLnZhbCgpO1xuXHRpZiAoIWlzVmVyaWZpZWQgJiYgb3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQgJiYgY291bnRyeS50b1VwcGVyQ2FzZSgpID09ICdVUycpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlZlcmlmeUFkZHJlc3MoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0RlbGl2ZXJhYmxlLCBhZGRyZXNzTm90RGVsaXZlcmFibGUpO1xuXHR9IGVsc2Uge1xuXHRcdGFkZHJlc3NEZWxpdmVyYWJsZSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHdyaXRlQnVmZmVyVG9BZGRyZXNzRm9ybShuYW1lLCAkc2VsZWN0b3IpIHtcblx0aWYgKGRhdGFCdWZmZXJbbmFtZV0pIHtcblx0XHQkc2VsZWN0b3IuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRcdHZhciAkZmllbGQgPSAkKGVsZW1lbnQpO1xuXHRcdFx0JGZpZWxkLnZhbChkYXRhQnVmZmVyW25hbWVdWyRmaWVsZC5hdHRyKCduYW1lJyldIHx8ICcnKTtcblx0XHR9KTtcblx0XHRcblx0XHRpZiAobmFtZSA9PSAnc2hpcHBpbmdBZGRyZXNzRmllbGRzJykge1xuXHRcdFx0dmFyICRmb3JtID0gJCgnLnNoaXBwaW5nLWFkZHJlc3MtZm9ybScpO1xuXHRcdFx0dmFyICRjb3VudHJ5RHJvcGRvd24gPSAkZm9ybS5maW5kKCdbaWQqPVwiX2NvdW50cnlcIl0nKTtcblx0XHRcdHZhciAkc3RhdGVEcm9wZG93biA9ICRmb3JtLmZpbmQoJ1tpZCo9XCJzdGF0ZXNfc3RhdGVcIl0nKTtcblx0XHRcdHJlbmRlck9wdGlvbnMoJyMnICsgJHN0YXRlRHJvcGRvd24uYXR0cignaWQnKSwgJyMnICsgJGNvdW50cnlEcm9wZG93bi5hdHRyKCdpZCcpKTtcblx0XHRcdFxuXHRcdFx0aWYgKCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykubGVuZ3RoID4gMCAmJiBkYXRhQnVmZmVyWydzaGlwcGluZ0FkZHJlc3NGaWVsZHMnXVsnZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZSddKSB7XG5cdFx0XHRcdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykudmFsKGRhdGFCdWZmZXJbJ3NoaXBwaW5nQWRkcmVzc0ZpZWxkcyddWydkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJ10pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiB3cml0ZUJ1ZmZlclRvU2hpcHBpbmdBZGRyZXNzRm9ybSgpIHtcblx0dmFyICRzaGlwcGluZ0FkZHJlc3NGaWVsZHMgPSAkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkIGlucHV0W3R5cGU9XCJ0ZXh0XCJdLCAuZm9ybWZpZWxkIHNlbGVjdCcpLm5vdCgnW2Rpc2FibGVkXScpLm5vdCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19teVN0b3JlSUQnKTtcblx0d3JpdGVCdWZmZXJUb0FkZHJlc3NGb3JtKCdzaGlwcGluZ0FkZHJlc3NGaWVsZHMnLCAkc2hpcHBpbmdBZGRyZXNzRmllbGRzKTtcbn1cblxuZnVuY3Rpb24gd3JpdGVBZGRyZXNzRm9ybVRvQnVmZmVyKG5hbWUsICRzZWxlY3RvciwgZG9DbGVhcikge1xuXHQkc2VsZWN0b3IuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJGZpZWxkID0gJChlbGVtZW50KTtcblxuXHRcdGlmICgkZmllbGQudmFsKCkpIHtcblx0XHRcdGlmICghZGF0YUJ1ZmZlcltuYW1lXSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyW25hbWVdID0ge307XG5cdFx0XHR9XG5cblx0XHRcdGRhdGFCdWZmZXJbbmFtZV1bJGZpZWxkLmF0dHIoJ25hbWUnKV0gPSAkZmllbGQudmFsKCk7XG5cdFx0fVxuXHR9KTtcblxuXHRpZiAoZG9DbGVhcikge1xuXHRcdCRzZWxlY3Rvci52YWwoJycpO1xuXHRcdCRzZWxlY3Rvci5maW5kKCdvcHRpb25bZGVmYXVsdF0nKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHdyaXRlU2hpcHBpbmdBZGRyZXNzRm9ybVRvQnVmZmVyKGRvQ2xlYXIpIHtcblx0dmFyICRzaGlwcGluZ0FkZHJlc3NGaWVsZHMgPSAkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkIGlucHV0W3R5cGU9XCJ0ZXh0XCJdLCAuZm9ybWZpZWxkIHNlbGVjdCcpLm5vdCgnW2Rpc2FibGVkXScpLm5vdCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19teVN0b3JlSUQnKTtcblx0d3JpdGVBZGRyZXNzRm9ybVRvQnVmZmVyKCdzaGlwcGluZ0FkZHJlc3NGaWVsZHMnLCAkc2hpcHBpbmdBZGRyZXNzRmllbGRzLCBkb0NsZWFyKTtcbn1cblxuLyoqXG4gKiBjcmVhdGUgYWRkcmVzcyBvYmplY3QgZnJvbSBmb3JtXG4gKiBAcGFyYW0gJGZvcm1cbiAqIEByZXR1cm5zIEFkZHJlc3MgT2JqZWN0XG4gKi9cbmZ1bmN0aW9uIGdldEFkZHJlc3NGcm9tRm9ybSgkZm9ybSkge1xuXHRyZXR1cm4ge1xuXHRcdElEOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfSURcIl0nKS52YWwoKSksXG5cdFx0aXNTdG9yZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2lzU3RvcmVcIl0nKS5wcm9wKCdjaGVja2VkJykpLFxuXHRcdGZpcnN0TmFtZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2ZpcnN0TmFtZVwiXScpLnZhbCgpKSxcblx0XHRsYXN0TmFtZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2xhc3ROYW1lXCJdJykudmFsKCkpLFxuXHRcdGFkZHJlc3MxOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSksXG5cdFx0YWRkcmVzczI6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpKSxcblx0XHRhZGRyZXNzMzogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MzXCJdJykudmFsKCkpLFxuXHRcdGNvdW50cnlDb2RlOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9jb3VudHJ5XCJdJykudmFsKCkpLFxuXHRcdHN0YXRlQ29kZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKSksXG5cdFx0cG9zdGFsQ29kZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCkgPyB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCkudG9VcHBlckNhc2UoKSkgOiAnJyxcblx0XHRjaXR5OiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpKSxcblx0XHRwaG9uZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bob25lXCJdJykudmFsKCkpLFxuXHRcdGVtYWlsOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZW1haWxcIl0nKS52YWwoKSlcblx0fTtcbn1cblxuZnVuY3Rpb24gcG9wdWxhdGVCaWxsaW5nQWRkcmVzc0Zvcm1Ub1NoaXBwaW5nQWRkcmVzc0Zvcm0oKSB7XG5cdHZhciBiaWxsaW5nQWRkcmVzcyA9IGdldEFkZHJlc3NGcm9tRm9ybSgkYmlsbGluZ0FkZHJlc3NGb3JtKTtcblxuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9JRFwiXScpLnZhbCgnJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2ZpcnN0TmFtZVwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5maXJzdE5hbWUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9sYXN0TmFtZVwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5sYXN0TmFtZSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKGJpbGxpbmdBZGRyZXNzLmFkZHJlc3MxKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MuYWRkcmVzczIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzM1wiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5hZGRyZXNzMykudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5wb3N0YWxDb2RlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5jaXR5KS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnc2VsZWN0W2lkJD1jb3VudHJ5XScpLnZhbChiaWxsaW5nQWRkcmVzcy5jb3VudHJ5Q29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9c3RhdGVdJykudmFsKGJpbGxpbmdBZGRyZXNzLnN0YXRlQ29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bob25lXCJdJykudmFsKGJpbGxpbmdBZGRyZXNzLnBob25lKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblxuICAgIGlmICgkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLmZpbmQoJ29wdGlvbi5wbGFjZWhvbGRlcicpLmxlbmd0aCA9PSAwKSB7XG4gICAgXHQkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnByZXBlbmQoJzxvcHRpb24gY2xhc3M9XCJwbGFjZWhvbGRlclwiPicgKyBSZXNvdXJjZXMuT1BDX1NFTEVDVF9BRERSICsgJzwvb3B0aW9uPicpLnByb3AoJ3NlbGVjdGVkSW5kZXgnLCAwKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkZm9ybSwgaXNDb21wYWN0LCBoaWRlTmlja25hbWUpIHtcblx0dmFyIGFkZHJlc3MgPSBnZXRBZGRyZXNzRnJvbUZvcm0oJGZvcm0pO1xuXHRmb3IgKHZhciBhZGRyZXNzS2V5IGluIGFkZHJlc3MpIHtcbiAgICBcdGlmIChhZGRyZXNzW2FkZHJlc3NLZXldICE9IG51bGwgJiYgYWRkcmVzc1thZGRyZXNzS2V5XS5zZWFyY2goL1xcXi8pICE9IC0xKSB7XG4gICAgXHRcdGFkZHJlc3NbYWRkcmVzc0tleV0gPSBhZGRyZXNzW2FkZHJlc3NLZXldLnJlcGxhY2UoL1xcXi9naSxcIidcIik7XG4gICAgXHR9XG4gICAgfVxuXG5cdHJldHVybiBidWlsZERldGFpbHNCbG9ja0ZvckFkZHJlc3MoYWRkcmVzcywgaXNDb21wYWN0LCBoaWRlTmlja25hbWUsICRmb3JtLmF0dHIoJ2lkJykpO1xufVxuXG5mdW5jdGlvbiBidWlsZERldGFpbHNCbG9ja0ZvckFkZHJlc3MoYWRkcmVzcywgaXNDb21wYWN0LCBoaWRlTmlja25hbWUsIGZvcm1JZCkge1xuXHR2YXIgc2hpcHBpbmdBZGRyZXNzVHlwZSA9IGdldFNoaXBwaW5nQWRkcmVzc1R5cGUoKTtcbiAgICB2YXIgaHRtbFRleHQgPSAkKCc8ZGl2Lz4nLCB7XCJjbGFzc1wiOiBcImFkZHJlc3MtZGV0YWlscy1zdFwifSk7XG4gICAgdmFyIGhlYWRlciA9IGlzQ29tcGFjdCA/ICcnIDogZm9ybUlkID09ICdiaWxsaW5nQWRkcmVzc0Zvcm0nID8gJzxoNj5CaWxsaW5nIFJlY2lwaWVudDwvaDY+JyA6IGZvcm1JZCA9PSAnc2hpcHBpbmdBZGRyZXNzRm9ybScgPyAnPGg2PlNoaXAgVG86PC9oNj4nIDogJyc7XG4gICAgdmFyIGVkaXRCdXR0b24gPSAoIWlzQ29tcGFjdCAmJiAhc2hpcHBpbmdBZGRyZXNzVHlwZSB8fCBzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyKSA/ICc8cCBjbGFzcz1cInRleHQtcmlnaHQgZWRpdC1hZGRyZXNzLWNvbnRhaW5lclwiPjxhIGNsYXNzPVwiZWRpdC1hZGRyZXNzLWRldFwiIHRhYmluZGV4PVwiMFwiPkVkaXQ8c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPiZuYnNwO0FkZHJlc3MgSW5mb3JtYXRpb248L3NwYW4+PC9hPjwvcD4nIDogJyc7XG4gICAgdmFyIGFkZE5ld0J1dHRvbiA9ICcnO1xuXHR2YXIgYWRkcmVzc05pY2tuYW1lID0gJyc7XG5cdFxuXHRpZiAoZm9ybUlkID09ICdzaGlwcGluZ0FkZHJlc3NGb3JtJykge1xuXHRcdGlmIChhZGRyZXNzLmFkZHJlc3MxICYmICFoaWRlTmlja25hbWUpIHtcblx0XHRcdGlmIChhZGRyZXNzLklEICYmICFhZGRyZXNzLm15U3RvcmVJRCkge1xuXHRcdFx0XHRhZGRyZXNzTmlja25hbWUgPSBhZGRyZXNzLklEO1xuXHRcdFx0fSBlbHNlIGlmIChmb3JtSWQgPT0gJ3NoaXBwaW5nQWRkcmVzc0Zvcm0nICYmIHNoaXBwaW5nQWRkcmVzc1R5cGUgPT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuQ3VzdG9tZXIgJiYgZGF0YUJ1ZmZlclsnZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCddKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZEFkZHJlc3NGcm9tRHJvcGRvd24gPSBkYXRhQnVmZmVyWydkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0J10uZmlsdGVyKGZ1bmN0aW9uIChhZGRyZXNzT3B0aW9uKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGFkZHJlc3NPcHRpb24uVVVJRCA9PSAkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnZhbCgpO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChzZWxlY3RlZEFkZHJlc3NGcm9tRHJvcGRvd24ubGVuZ3RoID4gMCAmJiBzZWxlY3RlZEFkZHJlc3NGcm9tRHJvcGRvd25bMF0uZGlzcGxheVZhbHVlICYmICQoJ1toYXMtd2FyZWhvdXNlLXNoaXBtZW50XScpLmF0dHIoJ2hhcy13YXJlaG91c2Utc2hpcG1lbnQnKSA9PSAndHJ1ZScpIHtcblx0XHRcdFx0XHR1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzc0Zyb21Ecm9wZG93blswXSwgJCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSk7XG5cdFx0XHRcdFx0d3JpdGVTaGlwcGluZ0FkZHJlc3NGb3JtVG9CdWZmZXIoKTtcblx0XHRcdFx0XHRhZGRyZXNzTmlja25hbWUgPSBzZWxlY3RlZEFkZHJlc3NGcm9tRHJvcGRvd25bMF0uZGlzcGxheVZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChhZGRyZXNzTmlja25hbWUpIHtcblx0XHRcdFx0YWRkcmVzc05pY2tuYW1lID0gJzxzcGFuIGNsYXNzPVwiYWRkcmVzcy1uaWNrbmFtZVwiPicgKyBhZGRyZXNzTmlja25hbWUgKyAnPC9zcGFuPic7XG5cdFx0XHR9XG5cblx0XHRcdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAndmlldycpLmF0dHIoJ3ZhbHVlJywgJ3RydWUnKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCFpc0NvbXBhY3QgJiYgc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikge1xuXHRcdFx0YWRkTmV3QnV0dG9uID0gJzxwIGNsYXNzPVwiYWRkLWFkZHJlc3MtY29udGFpbmVyXCI+PGEgY2xhc3M9XCJhZGQtYWRkcmVzcy1kZXRcIiB0YWJpbmRleD1cIjBcIj4rIEFkZCBOZXcgQWRkcmVzczwvYT48L3A+Jztcblx0XHR9XG5cdH1cblx0XG4gICAgdmFyIGh0bWxjb250ZW50ID0gJyc7XG4gICAgaWYgKGFkZHJlc3MuYWRkcmVzczEpIHtcblx0ICAgIGh0bWxjb250ZW50ICs9IGhlYWRlcjtcblx0ICAgIGh0bWxjb250ZW50ICs9ICc8ZGl2IGNsYXNzPVwiYWRkcmVzc1wiIHRhYmluZGV4PVwiMFwiPjxkaXY+JyArIChhZGRyZXNzLm15U3RvcmVJRCA/IGFkZHJlc3MuZnVsbE5hbWUgOiBhZGRyZXNzLmZpcnN0TmFtZSkgKyAnICcgKyBhZGRyZXNzLmxhc3ROYW1lICsgYWRkcmVzc05pY2tuYW1lICsgJyA8L2Rpdj4nO1xuXHQgICAgaHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGFkZHJlc3MuYWRkcmVzczEgKyAnIDwvZGl2Pic7XG5cdCAgICBpZiAoYWRkcmVzcy5hZGRyZXNzMikge1xuXHQgICAgXHRodG1sY29udGVudCArPSAnPGRpdj4nICsgYWRkcmVzcy5hZGRyZXNzMiArICcgPC9kaXY+Jztcblx0ICAgIH1cblxuXHQgICAgaWYgKGFkZHJlc3MuYWRkcmVzczMpIHtcblx0ICAgIFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGFkZHJlc3MuYWRkcmVzczMgKyAnIDwvZGl2Pic7XG5cdCAgICB9XG5cblx0ICAgIGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBhZGRyZXNzLmNpdHk7XG5cblx0ICAgIGlmIChhZGRyZXNzLnN0YXRlQ29kZSAmJiBhZGRyZXNzLnN0YXRlQ29kZS50b1VwcGVyQ2FzZSgpICE9ICdPVEhFUicpIHtcblx0ICAgIFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgYWRkcmVzcy5zdGF0ZUNvZGU7XG5cdCAgICB9XG5cblx0ICAgIGh0bWxjb250ZW50ICs9ICcgJyArIGFkZHJlc3MucG9zdGFsQ29kZTtcblx0XHRodG1sY29udGVudCArPSAnICcgKyBhZGRyZXNzLmNvdW50cnlDb2RlICsgJzwvZGl2Pic7XG5cdFx0aWYgKGFkZHJlc3MucGhvbmUpIHtcblx0XHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBhZGRyZXNzLnBob25lICsgJzwvZGl2Pic7XG5cdFx0fVxuXG5cdCAgICBpZiAoYWRkcmVzcy5lbWFpbCkge1xuXHQgICAgXHRodG1sY29udGVudCArPSAnPGRpdiBjbGFzcz1cImJpbGxpbmctZW1haWwtYWRkcmVzc1wiPicgKyBhZGRyZXNzLmVtYWlsICsgJzwvZGl2Pic7XG5cdFx0fVxuXHRcdGh0bWxjb250ZW50ICs9ICc8L2Rpdj4nO1xuXG5cdCAgICBodG1sY29udGVudCArPSBlZGl0QnV0dG9uO1xuXHQgICAgaHRtbGNvbnRlbnQgKz0gYWRkTmV3QnV0dG9uO1xuICAgIH1cblxuICAgIGh0bWxUZXh0Lmh0bWwoaHRtbGNvbnRlbnQpO1xuXG4gICAgcmV0dXJuIGh0bWxUZXh0O1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEhlbHBlciBtZXRob2Qgd2hpY2ggY29uc3RydWN0cyBhIFVSTCBmb3IgYW4gQUpBWCByZXF1ZXN0IHVzaW5nIHRoZVxuICogZW50ZXJlZCBhZGRyZXNzIGluZm9ybWF0aW9uIGFzIFVSTCByZXF1ZXN0IHBhcmFtZXRlcnMuXG4gKi9cbmZ1bmN0aW9uIGdldFNoaXBwaW5nTWV0aG9kVVJMKCRmb3JtLCB1cmwsIGV4dHJhUGFyYW1zKSB7XG4gICAgdmFyIHBhcmFtcyA9IHtcblx0XHRpc1N0b3JlOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9pc1N0b3JlXCJdJykucHJvcCgnY2hlY2tlZCcpLFxuXHRcdG15U3RvcmVJRDogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbXlTdG9yZUlEXCJdJykudmFsKCksXG4gICAgXHRhZGRyZXNzMTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSxcbiAgICAgICAgYWRkcmVzczI6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCksXG4gICAgICAgIGFkZHJlc3MzOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzM1wiXScpLnZhbCgpLFxuICAgICAgICBjb3VudHJ5Q29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9jb3VudHJ5XCJdJykudmFsKCksXG4gICAgICAgIHN0YXRlQ29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9zdGF0ZVwiXScpLnZhbCgpLFxuICAgICAgICBwb3N0YWxDb2RlOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoKSxcbiAgICAgICAgY2l0eTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpXG4gICAgfTtcblxuICAgIHJldHVybiB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKHVybCwgJC5leHRlbmQocGFyYW1zLCBleHRyYVBhcmFtcykpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJGZvcm0sIGRvVXBkYXRlU3VtbWFyeSwgaXNNeVN0b3JlLCBkb0RhdGFMYXllclB1c2gsICRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kKSB7XG5cdGlmICghJHNoaXBwaW5nTWV0aG9kTGlzdCB8fCAkc2hpcHBpbmdNZXRob2RMaXN0Lmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblx0XG5cdHZhciBzaGlwcGluZ01ldGhvZExpc3REYXRhID0ge1xuXHRcdHNlbGVjdGVkUGF5bWVudE1ldGhvZDogJHBheW1lbnRGb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKClcblx0fVxuXG5cdHZhciAkc2hpcFRvU3RvcmVPcHRpb25JbkFkZHJlc3NQYW5lbCA9ICQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yJyk7XG5cdGlmICgkc2hpcFRvU3RvcmVPcHRpb25JbkFkZHJlc3NQYW5lbC5sZW5ndGggPiAwKSB7XG5cdFx0aWYgKCRzaGlwVG9TdG9yZU9wdGlvbkluQWRkcmVzc1BhbmVsLmZpbmQoJ2lucHV0OmNoZWNrZWQnKS52YWwoKSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5TdG9yZSkge1xuXHRcdFx0c2hpcHBpbmdNZXRob2RMaXN0RGF0YS5TaGlwVG9TdG9yZU9ubHkgPSB0cnVlO1xuXG5cdFx0XHRpZiAoZGF0YUJ1ZmZlcltDaGVja291dENvbnN0YW50cy5Vc2VyLlNlbGVjdGVkU3RvcmVTaGlwcGluZ01ldGhvZF0pIHtcblx0XHRcdFx0c2hpcHBpbmdNZXRob2RMaXN0RGF0YS5TZWxlY3RTaGlwcGluZ01ldGhvZCA9IGRhdGFCdWZmZXJbQ2hlY2tvdXRDb25zdGFudHMuVXNlci5TZWxlY3RlZFN0b3JlU2hpcHBpbmdNZXRob2RdO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoJHNoaXBUb1N0b3JlT3B0aW9uSW5BZGRyZXNzUGFuZWwuZmluZCgnaW5wdXQ6Y2hlY2tlZCcpLnZhbCgpID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyKSB7XG5cdFx0XHRzaGlwcGluZ01ldGhvZExpc3REYXRhLlNoaXBUb1N0b3JlRXhjbHVkZSA9IHRydWU7XG5cblx0XHRcdGlmIChkYXRhQnVmZmVyW0NoZWNrb3V0Q29uc3RhbnRzLlVzZXIuU2VsZWN0ZWRDdXN0b21lclNoaXBwaW5nTWV0aG9kXSkge1xuXHRcdFx0XHRzaGlwcGluZ01ldGhvZExpc3REYXRhLlNlbGVjdFNoaXBwaW5nTWV0aG9kID0gZGF0YUJ1ZmZlcltDaGVja291dENvbnN0YW50cy5Vc2VyLlNlbGVjdGVkQ3VzdG9tZXJTaGlwcGluZ01ldGhvZF07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aWYgKGlzTXlTdG9yZSkge1xuXHRcdHNoaXBwaW5nTWV0aG9kTGlzdERhdGEuU2hpcFRvU3RvcmVPbmx5ID0gdHJ1ZTtcblx0fVxuXG5cdHZhciBzaGlwcGluZ01ldGhvZExpc3RVcmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTCgkZm9ybSwgVXJscy5zaGlwcGluZ01ldGhvZHNMaXN0KTtcblx0JHNoaXBwaW5nTWV0aG9kTGlzdC5sb2FkKHNoaXBwaW5nTWV0aG9kTGlzdFVybCwgc2hpcHBpbmdNZXRob2RMaXN0RGF0YSwgZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxlY3RlZFN0b3JlID0gJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZC5teVN0b3JlSUQgaW5wdXQnKS52YWwoKTtcblx0XHR2YXIgJHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzO1xuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuQWdlbnRTdG9yZSAmJiBvcHRpb25zLkFnZW50U3RvcmUuU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5KSB7XG5cdFx0XHQkc2hpcFRvU3RvcmVTaGlwcGluZ01ldGhvZHMgPSAkKCdbc2hpcHBpbmctbWV0aG9kXScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkc2hpcFRvU3RvcmVTaGlwcGluZ01ldGhvZHMgPSAkKCdbc2hpcHBpbmctbWV0aG9kXVtpcy1zaGlwLXRvLXN0b3JlPVwidHJ1ZVwiXScpO1xuXHRcdH1cblxuXHRcdGlmICgkc2hpcFRvU3RvcmVTaGlwcGluZ01ldGhvZHMubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFyIHNlbGVjdGVkU3RvcmVGcm9tU2hpcHBpbmdNZXRob2QgPSAkc2hpcFRvU3RvcmVTaGlwcGluZ01ldGhvZHMuZmluZCgnLnN0b3JlLXNlbGVjdG9yIHNlbGVjdCcpLnZhbCgpO1xuXG5cdFx0XHRpZiAoc2VsZWN0ZWRTdG9yZUZyb21TaGlwcGluZ01ldGhvZCAmJiBzZWxlY3RlZFN0b3JlRnJvbVNoaXBwaW5nTWV0aG9kICE9IHNlbGVjdGVkU3RvcmUgJiYgJHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzLmZpbmQoJy5pbnB1dC1yYWRpbycpLmlzKCc6Y2hlY2tlZCcpKSB7XG5cdFx0XHRcdHNlbGVjdGVkU3RvcmUgPSBzZWxlY3RlZFN0b3JlRnJvbVNoaXBwaW5nTWV0aG9kO1xuXHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkLm15U3RvcmVJRCBpbnB1dCcpLnZhbChzZWxlY3RlZFN0b3JlKTtcblx0XHRcdFx0c2V0T1BDQWRkcmVzcyhzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IsICdkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc2F2ZW9wY2FkZHJlc3MnKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7IH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRidWlsZFNoaXBUb1N0b3JlRGV0YWlscygkc2hpcFRvU3RvcmVTaGlwcGluZ01ldGhvZHMpO1xuXHRcdH1cblxuXHRcdGlmIChzZWxlY3RlZFN0b3JlICYmIGRhdGFCdWZmZXIgJiYgZGF0YUJ1ZmZlclsnbXlzdG9yZXNfYWRkcmVzc0xpc3QnXSkge1xuXHRcdFx0dmFyIHNlbGVjdGVkU3RvcmVJbkJ1ZmZlciA9IGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10uZmlsdGVyKGZ1bmN0aW9uIChhZGRyZXNzKSB7XG5cdFx0XHRcdHJldHVybiBhZGRyZXNzLm15U3RvcmVJRCA9PSBzZWxlY3RlZFN0b3JlO1xuXHRcdFx0fSlbMF07XG5cblx0XHRcdGlmIChzZWxlY3RlZFN0b3JlSW5CdWZmZXIgJiYgc2VsZWN0ZWRTdG9yZUluQnVmZmVyLlVVSUQgIT0gJCgnI215c3RvcmVzX2FkZHJlc3NMaXN0JykudmFsKCkpIHtcblx0XHRcdFx0JCgnI215c3RvcmVzX2FkZHJlc3NMaXN0JykudmFsKHNlbGVjdGVkU3RvcmVJbkJ1ZmZlci5VVUlEKTtcblx0XHRcdFx0dmFyIHNoaXBwaW5nQWRkcmVzc1R5cGUgPSBnZXRTaGlwcGluZ0FkZHJlc3NUeXBlKCk7XG5cdFx0XHRcdGlmIChzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLlN0b3JlKSB7XG5cdFx0XHRcdFx0JCgnI215c3RvcmVzX2FkZHJlc3NMaXN0JykudHJpZ2dlcignY2hhbmdlJyk7XG5cdFx0XHRcdFx0ZG9VcGRhdGVTdW1tYXJ5ID0gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0JHNoaXBwaW5nTWV0aG9kTGlzdC5mYWRlSW4oJ2Zhc3QnKTtcblxuXHRcdGlmIChkb1VwZGF0ZVN1bW1hcnkpIHtcblx0XHRcdHVwZGF0ZVN1bW1hcnkoKTtcblx0XHR9XG5cdFx0XG5cdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdGl0ZW1zOiAnLnNoaXBwaW5nLW1ldGhvZC10b29sdGlwJyxcblx0XHRcdHRvb2x0aXBDbGFzczogJ3NoaXBwaW5nLW1ldGhvZC10b29sdGlwJ1xuXHRcdH0sICQoJ1tzaGlwcGluZy1tZXRob2RdJykpO1xuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy50b29sdGlwLlJld2FyZHNDcmVkaXQnLFxuXHRcdFx0dG9vbHRpcENsYXNzOiAnUmV3YXJkc0NyZWRpdCdcblx0XHR9LCAkKCdbcGF5bWVudC1tZXRob2Q9XCJSRVdBUkRTX0NSRURJVFwiXScpKTtcblx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0aXRlbXM6ICcudG9vbHRpcC5Mb3lhbHR5Q3JlZGl0Jyxcblx0XHRcdHRvb2x0aXBDbGFzczogJ0xveWFsdHlDcmVkaXQnXG5cdFx0fSwgJCgnW3BheW1lbnQtbWV0aG9kPVwiTE9ZQUxUWV9DUkVESVRcIl0nKSk7XG5cdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdGl0ZW1zOiAnLnRvb2x0aXAnXG5cdFx0fSwgJCgnLmZvcm0tcm93LmN2bicpKTtcblxuXHRcdHZhciBpc1N0b3JlQWRkcmVzcyA9IGlzU2hpcFRvU3RvcmVFbmFibGVkKCk7XG5cdFx0c2V0U2hpcFRvU3RvcmUoaXNTdG9yZUFkZHJlc3MpO1xuXG5cdFx0aWYgKGRvRGF0YUxheWVyUHVzaCkge1xuXHRcdFx0cHVzaERhdGFMYXllckZvclNoaXBwaW5nTWV0aG9kcygkc2hpcHBpbmdNZXRob2RMaXN0LCAkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGVzIHRoZSBvcmRlciBzdW1tYXJ5IGJhc2VkIG9uIGEgcG9zc2libHkgcmVjYWxjdWxhdGVkIGJhc2tldCBhZnRlciBhIHNoaXBwaW5nIHByb21vdGlvbiBoYXMgYmVlbiBhcHBsaWVkXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVN1bW1hcnkoKSB7XG4gICAgJChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnLCB7XG5cdFx0J0V2ZW50VHJpZ2dlcnMnOiB7XG5cdFx0XHQndXBkYXRlLXNoaXBwaW5nJzogZmFsc2Vcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRTaGlwcGluZ0FkZHJlc3NUeXBlKCkge1xuXHR2YXIgc2hpcHBpbmdBZGRyZXNzVHlwZSA9ICQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0OmNoZWNrZWQnKS52YWwoKTtcblx0aWYgKCFzaGlwcGluZ0FkZHJlc3NUeXBlKSB7XG5cdFx0c2hpcHBpbmdBZGRyZXNzVHlwZSA9IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyO1xuXHR9XG5cdHJldHVybiBzaGlwcGluZ0FkZHJlc3NUeXBlO1xufVxuXG5mdW5jdGlvbiByZW5kZXJNeVN0b3Jlc0FkZHJlc3NTZWxlY3RvcihwYXJhbWV0ZXJzKSB7XG5cdHZhciB0ZW1wbGF0ZVNldHRpbmdzID0ge1xuICAgIFx0aW50ZXJwb2xhdGU6IC97eyhbXFxzXFxTXSs/KX19L2dcbiAgICB9O1xuXG4gICAgdmFyIHRlbXBsYXRlcyA9IFtdO1xuXHR0ZW1wbGF0ZXNbJ29wdGlvbiddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYWRkcmVzcy1zZWxlY3Rvci1vcHRpb24nKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuXG5cdCQuYWpheCh7XG5cdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0dXJsOiBVcmxzLmdldE15U3RvcmVzQWRkcmVzc0xpc3QsXG5cdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7IHN0b3JlUXVlcnk6IFN0b3JlUXVlcnlGaWx0ZXJzLlNoaXBUb1N0b3JlRW5hYmxlZCB9KSxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdHZhciBodG1sID0gW107XG5cdFx0XHRodG1sWydvcHRpb25zJ10gPSAnJztcblxuXHRcdFx0ZGF0YUJ1ZmZlclsnbXlzdG9yZXNfYWRkcmVzc0xpc3QnXSA9IGRhdGEuYWRkcmVzc2VzO1xuXHRcdFx0ZGF0YUJ1ZmZlclsnc3RvcmVfbmFtZV9sb29rdXAnXSA9IHt9O1xuXHRcdFx0ZGF0YS5hZGRyZXNzZXMubWFwKGZ1bmN0aW9uIChlbGVtZW50KSB7XG5cdFx0XHRcdGRhdGFCdWZmZXJbJ3N0b3JlX25hbWVfbG9va3VwJ11bZWxlbWVudC5teVN0b3JlSURdID0gZWxlbWVudC5mdWxsTmFtZTtcblx0XHRcdH0pO1xuXG5cdFx0XHR2YXIgaXNTdG9yZUFkZHJlc3NTZWxlY3RlZCA9IGZhbHNlO1xuXHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGRhdGEuYWRkcmVzc2VzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHR2YXIgYWRkcmVzcyA9IGRhdGEuYWRkcmVzc2VzW2luZGV4XTtcblxuXHRcdFx0XHRpZiAoYWRkcmVzcy5pc1NlbGVjdGVkKSB7XG5cdFx0XHRcdFx0aXNTdG9yZUFkZHJlc3NTZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdHZhciBvcHRpb25EYXRhID0gXy5leHRlbmQoYWRkcmVzcywge1xuXHRcdFx0XHRcdGlkOiBhZGRyZXNzLlVVSUQsXG5cdFx0XHRcdFx0Y3NzQ2xhc3M6ICcnLFxuXHRcdFx0XHRcdHNlbGVjdGVkOiBhZGRyZXNzLmlzU2VsZWN0ZWQgPyAnc2VsZWN0ZWQnIDogJycsXG5cdFx0XHRcdFx0dGV4dDogYWRkcmVzcy5sYWJlbFRleHRcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0b3B0aW9uRGF0YS5JRCA9IGFkZHJlc3MubXlTdG9yZUlEO1xuXHRcdFx0XHRodG1sWydvcHRpb25zJ10gKz0gdGVtcGxhdGVzWydvcHRpb24nXShvcHRpb25EYXRhKTtcblx0XHRcdH1cblxuXHRcdFx0JCgnI215c3RvcmVzX2FkZHJlc3NMaXN0JykuaHRtbChodG1sWydvcHRpb25zJ10pO1xuXG5cdFx0XHRpZiAoaXNTdG9yZUFkZHJlc3NTZWxlY3RlZCkge1xuXHRcdFx0XHRzZXRTaGlwVG9TdG9yZSh0cnVlKTtcblx0XHRcdFx0JCgnLnNpbmdsZS5zaGlwcGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXRbdmFsdWU9XCInICsgU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuU3RvcmUgKyAnXCJdJykuY2xpY2soKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHBhcmFtZXRlcnMgJiYgcGFyYW1ldGVycy5jYWxsYmFjaykge1xuXHRcdFx0XHRwYXJhbWV0ZXJzLmNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQWRkcmVzc1NlbGVjdG9yKHBhcmFtZXRlcnMpIHtcblx0dmFyIHRlbXBsYXRlU2V0dGluZ3MgPSB7XG4gICAgXHRpbnRlcnBvbGF0ZTogL3t7KFtcXHNcXFNdKz8pfX0vZ1xuICAgIH07XG5cbiAgICB2YXIgdGVtcGxhdGVzID0gW107XG4gICAgdGVtcGxhdGVzWydzZWxlY3RvciddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYWRkcmVzcy1zZWxlY3RvcicpLmh0bWwoKSwgdGVtcGxhdGVTZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWydvcHRpb24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3Mtc2VsZWN0b3Itb3B0aW9uJykuaHRtbCgpLCB0ZW1wbGF0ZVNldHRpbmdzKTtcblxuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdHVybDogVXJscy5nZXRBZGRyZXNzTGlzdCxcblx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHsgc3RvcmVRdWVyeTogU3RvcmVRdWVyeUZpbHRlcnMuU2hpcFRvU3RvcmVFbmFibGVkIH0pLFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0dmFyIGh0bWwgPSBbXTtcblx0XHRcdHZhciBoYXNBZGRyZXNzQm9va0FkZHJlc3NlcyA9IGZhbHNlO1xuXHRcdFx0dmFyIHNlbGVjdGVkQWRkcmVzc0lEID0gbnVsbDtcblxuXHRcdFx0ZGF0YUJ1ZmZlcltwYXJhbWV0ZXJzLmlkXSA9IGRhdGEuYWRkcmVzc2VzO1xuXG5cdFx0XHR2YXIgaXNBZGRyZXNzU2VsZWN0ZWRJbkRhdGEgPSBmYWxzZTtcblx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBkYXRhLmFkZHJlc3Nlcy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0dmFyIGFkZHJlc3MgPSBkYXRhLmFkZHJlc3Nlc1tpbmRleF07XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoYWRkcmVzcy5pc1NlbGVjdGVkKSB7XG5cdFx0XHRcdFx0aXNBZGRyZXNzU2VsZWN0ZWRJbkRhdGEgPSB0cnVlO1xuXHRcdFx0XHRcdHNlbGVjdGVkQWRkcmVzc0lEID0gYWRkcmVzcy5JRDtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRodG1sWydvcHRpb25zJ10gPSAnJztcblx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBkYXRhLmFkZHJlc3Nlcy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0dmFyIGFkZHJlc3MgPSBkYXRhLmFkZHJlc3Nlc1tpbmRleF07XG5cblx0XHRcdFx0aWYgKGFkZHJlc3MuaXNTaGlwcGluZ0FkZHJlc3MpIHtcblx0XHRcdFx0XHR2YXIgYWRkcmVzc0lkID0gYWRkcmVzcy5rZXkgPyBhZGRyZXNzLmtleSA6IGFkZHJlc3MuSUQ7XG5cdFx0XHRcdFx0dmFyIGlzU2VsZWN0ZWQgPSBmYWxzZTtcblxuXHRcdFx0XHRcdGlmICghJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSAmJiAkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtd2FyZWhvdXNlLXNoaXBtZW50JykgPT0gJ3RydWUnKSB7XG5cdFx0XHRcdFx0XHRpZiAoIWlzQWRkcmVzc1NlbGVjdGVkSW5EYXRhKSB7XG5cdFx0XHRcdFx0XHRcdGlmICghc2VsZWN0ZWRBZGRyZXNzSUQgJiYgcGFyYW1ldGVycy5jdXJyZW50QWRkcmVzc2VzICYmIHBhcmFtZXRlcnMuY3VycmVudEFkZHJlc3Nlcy5sZW5ndGggPiAwICYmIHBhcmFtZXRlcnMuY3VycmVudEFkZHJlc3Nlcy5pbmRleE9mKGFkZHJlc3MuVVVJRCkgPj0gMCkge1xuXHRcdFx0XHRcdFx0XHRcdGlzU2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkQWRkcmVzc0lEID0gYWRkcmVzcy5JRDtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICghc2VsZWN0ZWRBZGRyZXNzSUQgJiYgcGFyYW1ldGVycy5zZWxlY3RlZCAmJiBhZGRyZXNzLklEID09IHBhcmFtZXRlcnMuc2VsZWN0ZWQgJiYgcGFyYW1ldGVycy5zZWxlY3RlZCAhPSBcIm5ld1wiKSB7XG5cdFx0XHRcdFx0XHRcdFx0aXNTZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRBZGRyZXNzSUQgPSBhZGRyZXNzLklEO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCFzZWxlY3RlZEFkZHJlc3NJRCAmJiBhZGRyZXNzLklEID09ICQoJyNkd2ZybV9tdWx0aXBsZXNoaXBwaW5nX2FkZHJlc3NMaXN0OnZpc2libGUgb3B0aW9uJykudmFsKCkgJiYgcGFyYW1ldGVycy5zZWxlY3RlZCAhPSBcIm5ld1wiKSB7XG5cdFx0XHRcdFx0XHRcdFx0aXNTZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRBZGRyZXNzSUQgPSBhZGRyZXNzLklEO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCFzZWxlY3RlZEFkZHJlc3NJRCAmJiBhZGRyZXNzLmlzRGVmYXVsdCAmJiBwYXJhbWV0ZXJzLnNlbGVjdGVkICE9IFwibmV3XCIpIHtcblx0XHRcdFx0XHRcdFx0XHRpc1NlbGVjdGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZEFkZHJlc3NJRCA9IGFkZHJlc3MuSUQ7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgb3B0aW9uRGF0YSA9IF8uZXh0ZW5kKGFkZHJlc3MsIHtcblx0XHRcdFx0XHRcdGlkOiBhZGRyZXNzLlVVSUQsXG5cdFx0XHRcdFx0XHRjc3NDbGFzczogJycsXG5cdFx0XHRcdFx0XHRzZWxlY3RlZDogaXNTZWxlY3RlZCB8fCBhZGRyZXNzLmlzU2VsZWN0ZWQgPyAnc2VsZWN0ZWQnIDogJycsXG5cdFx0XHRcdFx0XHR0ZXh0OiAnKCcgKyAoIWFkZHJlc3MuZGlzcGxheVZhbHVlID8gYWRkcmVzc0lkIDogYWRkcmVzcy5kaXNwbGF5VmFsdWUpICsgJykgJyArIGFkZHJlc3MubGFiZWxUZXh0XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRpZiAoIWFkZHJlc3MuaXNNeVN0b3JlKSB7XG5cdFx0XHRcdFx0XHRoYXNBZGRyZXNzQm9va0FkZHJlc3NlcyA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aHRtbFsnb3B0aW9ucyddICs9IHRlbXBsYXRlc1snb3B0aW9uJ10ob3B0aW9uRGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKGhhc0FkZHJlc3NCb29rQWRkcmVzc2VzKSB7XG5cdFx0XHRcdGh0bWxbJ3NlbGVjdG9yJ10gPSB0ZW1wbGF0ZXNbJ3NlbGVjdG9yJ10oe1xuXHRcdFx0XHRcdGlkOiBwYXJhbWV0ZXJzLmlkLFxuXHRcdFx0XHRcdG9wdGlvbnM6IGh0bWxbJ29wdGlvbnMnXVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHR2YXIgJGh0bWwgPSAkKGh0bWxbJ3NlbGVjdG9yJ10pO1xuXG5cdFx0XHRcdGlmIChpc1NlbGVjdGVkIHx8IGFkZHJlc3MuaXNTZWxlY3RlZCkge1xuXHRcdFx0XHRcdCRodG1sLmZpbmQoJ29wdGlvbi5wbGFjZWhvbGRlcicpLnJlbW92ZSgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JChwYXJhbWV0ZXJzLmVsKS5odG1sKCRodG1sKTtcblx0XHRcdFx0JChwYXJhbWV0ZXJzLmNvbnRhaW5lcikuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JChwYXJhbWV0ZXJzLmNvbnRhaW5lcikuaGlkZSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAocGFyYW1ldGVycyAmJiBwYXJhbWV0ZXJzLmNhbGxiYWNrKSB7XG5cdFx0XHRcdHBhcmFtZXRlcnMuY2FsbGJhY2soKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1x0XG59XG5cbmZ1bmN0aW9uIGVkaXRCaWxsaW5nQWRkcmVzcygpIHtcblx0JCgnLmJpbGwtYWRkcmVzcy1maWVsZHMnKS5yZW1vdmVDbGFzcygnY29sbGFwc2VkJykuc2hvdygpO1xuXHQkKCcuYmlsbGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0XG5cdCQoJy5iaWxsaW5nLWFkZHJlc3MtcHJldmlldycpLmhpZGUoKTtcblx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblx0XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuc2hvdygpO1xuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLnNob3coKTtcblx0XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmRhdGEoJ2hpZGRlbi1lZGl0YWJsZScsICQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgpLmxlbmd0aCA/IHRydWUgOiBmYWxzZSkuaGlkZSgpO1xuXHRcblx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xufVxuXG5mdW5jdGlvbiBlZGl0U2hpcHBpbmdBZGRyZXNzKCkge1xuXHR3cml0ZVNoaXBwaW5nQWRkcmVzc0Zvcm1Ub0J1ZmZlcigpO1xuXHRvcGVuU2hpcHBpbmdBZGRyZXNzRm9ybSgpO1xufVxuXG5mdW5jdGlvbiBvcGVuU2hpcHBpbmdBZGRyZXNzRm9ybSgpIHtcblx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICdlZGl0Jyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmRhdGEoJ2hpZGRlbi1lZGl0YWJsZScsIHRydWUpLmhpZGUoKTtcblx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLmhpZGUoKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuc2hvdygpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5yZW1vdmVDbGFzcygnYWRkIGVkaXQnKS5hZGRDbGFzcygnZWRpdCcpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWN0aW9uXCJdJykudmFsKCdlZGl0Jyk7XG5cdFx0XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuY3NzKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcblx0JCgnLnNoaXBwaW5nLXNlbGVjdC1hZGRyZXNzJykuaGlkZSgpO1xuXHQkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcnKS5yZW1vdmVDbGFzcygnY29sbGFwc2VkJyk7XG59XG5cbmZ1bmN0aW9uIHNldFNoaXBUb1N0b3JlKGlzU3RvcmVBZGRyZXNzKSB7XG5cdCRzZWN0aW9uQ2hlY2tvdXQuYXR0cignaXMtbXktc3RvcmUnLCBpc1N0b3JlQWRkcmVzcyk7XG5cdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfaXNTdG9yZScpLnByb3AoJ2NoZWNrZWQnLCBpc1N0b3JlQWRkcmVzcyk7XG59XG5cbmZ1bmN0aW9uIGlzU2hpcFRvU3RvcmVFbmFibGVkKCkge1xuXHRyZXR1cm4gJCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19pc1N0b3JlJykucHJvcCgnY2hlY2tlZCcpO1xufVxuXG5mdW5jdGlvbiBidWlsZFNoaXBUb1N0b3JlRGV0YWlscygkc2hpcHBpbmdNZXRob2RzKSB7XG5cdCRzaGlwcGluZ01ldGhvZHMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkKGVsZW1lbnQpO1xuXHRcdHZhciAkc2VsZWN0ZWRTdG9yZSA9ICRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3Igb3B0aW9uOmNoZWNrZWQnKTtcblx0XHR2YXIgc3RvcmVTZWxlY3RvckNvdW50ID0gJHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1zZWxlY3RvciBvcHRpb24nKS5sZW5ndGg7XG5cdFx0dmFyIHN0b3JlRGF0YSA9ICRzZWxlY3RlZFN0b3JlLmRhdGEoJ2FkZHJlc3MnKTtcblx0XHRpZiAoc3RvcmVEYXRhICYmIHN0b3JlRGF0YS5hZGRyZXNzMSkge1xuXHRcdFx0dmFyIHN0b3JlSHRtbCA9ICc8cD4nICsgc3RvcmVEYXRhLm5hbWUgKyAnPC9wPicgK1xuXHRcdFx0XHRcdFx0XHQnPHA+JyArIHN0b3JlRGF0YS5hZGRyZXNzMSArICc8L3A+Jztcblx0XHRcdGlmIChzdG9yZURhdGEuYWRkcmVzczIpIHtcblx0XHRcdFx0c3RvcmVIdG1sICs9ICc8cD4nICsgc3RvcmVEYXRhLmFkZHJlc3MyICsgJzwvcD4nO1xuXHRcdFx0fVxuXHRcdFx0c3RvcmVIdG1sICs9ICc8cD4nICsgc3RvcmVEYXRhLmNpdHkgKyAnLCAnICsgc3RvcmVEYXRhLnN0YXRlICsgJyAnICsgc3RvcmVEYXRhLnBvc3RhbENvZGUgKyAnPC9wPic7XG5cdFxuXHRcdFx0aWYgKHN0b3JlU2VsZWN0b3JDb3VudCA+IDEgJiYgU2l0ZVByZWZlcmVuY2VzLkVOQUJMRV9TSElQX1RPX1NUT1JFX1NFTEVDVElPTiAmJiAhaXNTdG9yZVNoaXBwaW5nQWRkcmVzc09ubHkpIHtcblx0XHRcdFx0c3RvcmVIdG1sICs9ICc8YSBjbGFzcz1cImFjdGlvbiBjaGFuZ2VcIiB0YWJpbmRleD1cIjBcIj5DaGFuZ2UgU3RvcmU8L2E+Jztcblx0XHRcdH1cblxuXHRcdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1kZXRhaWxzJykuaHRtbChzdG9yZUh0bWwpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gc2VsZWN0cyBhIHNoaXBwaW5nIG1ldGhvZCBmb3IgdGhlIGRlZmF1bHQgc2hpcG1lbnQgYW5kIHVwZGF0ZXMgdGhlIHN1bW1hcnkgc2VjdGlvbiBvbiB0aGUgcmlnaHQgaGFuZCBzaWRlXG4gKiBAcGFyYW1cbiAqL1xuZnVuY3Rpb24gc2VsZWN0U2hpcHBpbmdNZXRob2Qoc2hpcG1lbnRJRCwgc2hpcHBpbmdNZXRob2RJRCwgaXNTaGlwVG9TdG9yZSwgJHNlbGVjdGVkU2hpcHBpbmdNZXRob2QpIHtcbiAgICB2YXIgc2hpcHBpbmdBZGRyZXNzVHlwZSA9IGdldFNoaXBwaW5nQWRkcmVzc1R5cGUoKTtcblx0aWYgKHNoaXBwaW5nQWRkcmVzc1R5cGUgPT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuQ3VzdG9tZXIpIHtcblx0XHRkYXRhQnVmZmVyW0NoZWNrb3V0Q29uc3RhbnRzLlVzZXIuU2VsZWN0ZWRDdXN0b21lclNoaXBwaW5nTWV0aG9kXSA9IHNoaXBwaW5nTWV0aG9kSUQ7XG5cdH0gZWxzZSBpZiAoc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5TdG9yZSkge1xuXHRcdGRhdGFCdWZmZXJbQ2hlY2tvdXRDb25zdGFudHMuVXNlci5TZWxlY3RlZFN0b3JlU2hpcHBpbmdNZXRob2RdID0gc2hpcHBpbmdNZXRob2RJRDtcblx0fVxuXG5cdGlmIChpc1NoaXBUb1N0b3JlIHx8IGlzU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5KSB7XG5cdFx0c2V0U2hpcFRvU3RvcmUodHJ1ZSk7IFxuXHR9IGVsc2Uge1xuXHRcdHNldFNoaXBUb1N0b3JlKGZhbHNlKTtcblx0fVxuXG4gICAgLy8gYXR0ZW1wdCB0byBzZXQgc2hpcHBpbmcgbWV0aG9kXG4gICAgdmFyIHVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKCRzaGlwcGluZ0FkZHJlc3NGb3JtLCBVcmxzLnNlbGVjdFNoaXBwaW5nTWV0aG9kc0xpc3QsIHtzaGlwbWVudElEOiBzaGlwbWVudElELCBzaGlwcGluZ01ldGhvZElEOiBzaGlwcGluZ01ldGhvZElEfSk7XG4gICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgLy8gZGlzcGxheSBwcm9tb3Rpb24gaW4gVUkgYW5kIHVwZGF0ZSB0aGUgc3VtbWFyeSBzZWN0aW9uLFxuICAgICAgICAgICAgLy8gaWYgc29tZSBwcm9tb3Rpb25zIHdlcmUgYXBwbGllZFxuICAgICAgICAgICAgJCgnLnNoaXBwaW5ncHJvbW90aW9ucycpLmVtcHR5KCk7XG5cbiAgICAgICAgICAgICQoJ1tuYW1lKj1cIl9zaGlwcGluZ01ldGhvZElEXCJdJykucHJvcCgnZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgICAgICAgICB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUsIG51bGwsIHRydWUsICRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gc2V0IGFkZHJlc3MgZGF0YVxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIGVsZW1lbnQgdGhhdCBwcmVzZW50IGFkZHJlc3Mgb2JqZWN0XG4gKiBAcGFyYW0ge0VsZW1lbnR9IEFjdGlvbiBuYW1lIHRvIGFwcGx5IHRvIGZvcm1cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgc2V0T1BDQWRkcmVzcyA9IGZ1bmN0aW9uIChmb3JtLCBuYW1lKSB7XG5cdHZhciAkZm9ybSA9ICQoZm9ybSk7XG5cdHZhciB1cmwgPSAoZm9ybSA9PSAnI2JpbGxpbmdBZGRyZXNzRm9ybScpID8gVXJscy5zZXRPcGNBZGRyZXNzIDogJGZvcm0uYXR0cignYWN0aW9uJyk7XG5cdHZhciBzYW5pdGl6ZWRGb3JtRGF0YSA9IHt9O1xuXHR2YXIgc2VyaWFsaXplZEZvcm1EYXRhQXJyYXkgPSAkZm9ybS5zZXJpYWxpemVBcnJheSgpO1xuXHR2YXIgaGFzQ291bnRyeUZpZWxkID0gZmFsc2U7XG5cdGZvciAodmFyIHNlcmlhbGl6ZWRGb3JtRGF0YUtleSBpbiBzZXJpYWxpemVkRm9ybURhdGFBcnJheSkge1xuXHRcdHZhciBzZXJpYWxpemVkRm9ybUVsZW1lbnQgPSBzZXJpYWxpemVkRm9ybURhdGFBcnJheVtzZXJpYWxpemVkRm9ybURhdGFLZXldO1xuXHRcdGlmIChzZXJpYWxpemVkRm9ybUVsZW1lbnQgJiYgc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWUgJiYgc2FuaXRpemVkRm9ybURhdGFbc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWVdKSB7XG5cdFx0XHRzYW5pdGl6ZWRGb3JtRGF0YVtzZXJpYWxpemVkRm9ybUVsZW1lbnQubmFtZV0gKz0gJywnICsgc2VyaWFsaXplZEZvcm1FbGVtZW50LnZhbHVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzYW5pdGl6ZWRGb3JtRGF0YVtzZXJpYWxpemVkRm9ybUVsZW1lbnQubmFtZV0gPSBzZXJpYWxpemVkRm9ybUVsZW1lbnQudmFsdWU7XG5cdFx0fVxuXHRcdGlmIChzZXJpYWxpemVkRm9ybUVsZW1lbnQgJiYgc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWUgJiYgc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWUuaW5kZXhPZignX2NvdW50cnknKSA8IDApIHtcblx0XHRcdGhhc0NvdW50cnlGaWVsZCA9IHRydWU7XG5cdFx0fVxuXHR9XG5cdGlmIChoYXNDb3VudHJ5RmllbGQpIHtcblx0XHR2YXIgJGNvdW50cnlGaWVsZCA9ICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9jb3VudHJ5XCJdJyk7XG5cdFx0c2FuaXRpemVkRm9ybURhdGFbJGNvdW50cnlGaWVsZC5hdHRyKCduYW1lJyldID0gJGNvdW50cnlGaWVsZC52YWwoKTtcblx0fVxuXHRzYW5pdGl6ZWRGb3JtRGF0YVtuYW1lXSA9IG5hbWU7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHR1cmw6IHV0aWwuYWpheFVybCh1cmwpLFxuXHRcdFx0ZGF0YTogc2FuaXRpemVkRm9ybURhdGEsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHR9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0cmVqZWN0KGRhdGEpO1xuXHRcdFx0fVxuXHRcdH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gcHVzaERhdGFMYXllckZvclNoaXBwaW5nTWV0aG9kcygkc2hpcHBpbmdNZXRob2RMaXN0LCAkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZCkge1xuXHR2YXIgJHNlbGVjdGVkU2hpcHBpbmdNZXRob2RzO1xuXHRpZiAoJHNlbGVjdGVkU2hpcHBpbmdNZXRob2QpIHtcblx0XHQkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZHMgPSAkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZDtcblx0fSBlbHNlIHtcblx0XHQkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZHMgPSAkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJ2lucHV0W3R5cGU9XCJyYWRpb1wiXTpjaGVja2VkJyk7XG5cdH1cblx0JHNlbGVjdGVkU2hpcHBpbmdNZXRob2RzLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkdGhpcy5jbG9zZXN0KCdbc2hpcHBpbmctbWV0aG9kXScpO1xuXHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0dmFsdWU6IHBhcnNlRmxvYXQoJHNoaXBwaW5nTWV0aG9kLmF0dHIoJ2Ftb3VudCcpKSxcblx0XHRcdHNoaXBwaW5nX3RpZXI6ICRzaGlwcGluZ01ldGhvZC5hdHRyKCdzaGlwcGluZy1tZXRob2QnKVxuXHRcdH1cblxuXHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFNoaXBwaW5nSW5mbycsIGRhdGFPYmplY3QsIHsgQ29udGFpbmVyU2VsZWN0b3I6ICcub3JkZXItaXRlbVtzaGlwbWVudD1cIicgKyAkc2hpcHBpbmdNZXRob2QuY2xvc2VzdCgnZm9ybScpLmF0dHIoJ3NoaXBtZW50JykgKyAnXCJdJyB9KS5jYXRjaChmdW5jdGlvbigpIHt9KTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVNoaXBwaW5nUmVzdHJpY3Rpb25zKGRhdGEpIHtcblx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLmZpbmQoJz4gLmVycm9yJykucmVtb3ZlKCk7XG5cdHZhciBoYXNTaGlwcGluZ1Jlc3RyaWN0aW9ucyA9IGRhdGEuc3RhdHVzID09ICdzaGlwcGluZ1Jlc3RyaWN0aW9uc0Vycm9yJztcblx0aWYgKGhhc1NoaXBwaW5nUmVzdHJpY3Rpb25zKSB7XG5cdFx0b3BlblJlc3RyaWN0aW9uc1BvcHVwKGRhdGEpO1xuXHR9XG5cblx0cmV0dXJuIGhhc1NoaXBwaW5nUmVzdHJpY3Rpb25zO1xufVxuXG5mdW5jdGlvbiBvcGVuUmVzdHJpY3Rpb25zUG9wdXAoZGF0YSkge1xuXHR2YXIgcGF5bG9hZCA9IEpTT04ucGFyc2UoZGF0YS5wYXlsb2FkKTtcblx0dmFyIHBvcHVwID0gcmVxdWlyZSgnLi4vLi4vcG9wdXAnKTtcblx0XG5cdHZhciByZXN0cmljdGlvbkxpc3QgPSAnJztcblx0aWYgKHBheWxvYWQubGlzdCAmJiBwYXlsb2FkLmxpc3QubGVuZ3RoID4gMCkge1xuXHRcdHZhciBsaXN0ID0gJC5tYXAocGF5bG9hZC5saXN0LCBmdW5jdGlvbiAoZWwpIHtcblx0XHRcdHZhciByZXN0cmljdGlvbk5hbWUgPSBlbC5uYW1lID8gZWwubmFtZSArICc6PGJyLz4nIDogJyc7XG5cdFx0XHRcblx0XHRcdHJldHVybiAnPGxpPicgKyByZXN0cmljdGlvbk5hbWUgKyBlbC5tZXNzYWdlICsgJzwvbGk+Jztcblx0XHR9KS5qb2luKCcnKTtcblx0XHRcblx0XHRyZXN0cmljdGlvbkxpc3QgPSAnPHVsIGNsYXNzPVwic2hpcHBpbmctcmVzdHJpY3Rpb25zLXBvcHVwX19saXN0XCI+JyArIGxpc3QgKyAnPC91bD4nO1xuXHR9XG5cdFxuXHRwb3B1cC5pbml0KHtcblx0XHR0aXRsZTogcGF5bG9hZC50aXRsZSxcblx0XHRjb250ZW50OiBwYXlsb2FkLm1lc3NhZ2UgKyByZXN0cmljdGlvbkxpc3Rcblx0fSkuc2hvd1BvcHVwKCk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlck9wdGlvbnMob3B0aW9uUGFyZW50LCBvcHRpb25zU3RvcmVJZCkge1xuXHR2YXIgb3B0aW9uc0h0bWw7XG5cdHZhciBvcHRpb25zU3RvcmVPcHRpb25zID0gJChvcHRpb25zU3RvcmVJZCArICcgb3B0aW9uOnNlbGVjdGVkJykuZGF0YSgnb3B0aW9ucycpO1xuXHR2YXIgc3RhdGVzTGlzdDtcblx0XG5cdGlmIChvcHRpb25zU3RvcmVPcHRpb25zKSB7XG5cdFx0c3RhdGVzTGlzdCA9IEpTT04ucGFyc2Uob3B0aW9uc1N0b3JlT3B0aW9ucy5yZXBsYWNlKC9cXCcvZywgJ1xcXCInKSk7XG5cdFx0XG5cdFx0aWYgKHN0YXRlc0xpc3QubGVuZ3RoID4gMSkge1xuXHRcdFx0b3B0aW9uc0h0bWwgKz0gJzxvcHRpb24gdmFsdWU9XCJcIj4nICsgUmVzb3VyY2VzLlNlbGVjdFBsYWNlaG9sZGVyICsgJzwvb3B0aW9uPic7XG5cdFx0fVxuXHRcdFxuXHRcdHN0YXRlc0xpc3QuZm9yRWFjaChmdW5jdGlvbiAoc3RhdGUpIHtcblx0XHRcdG9wdGlvbnNIdG1sICs9ICc8b3B0aW9uIGNsYXNzPVwic2VsZWN0LW9wdGlvblwiIGxhYmVsPVwiJyArIHN0YXRlLmxhYmVsICsgJ1wiIHZhbHVlPVwiJyArIHN0YXRlLmNvZGUgKyAnXCI+JyArIHN0YXRlLmxhYmVsICsgJzwvb3B0aW9uPic7XG5cdFx0fSk7XG5cblx0XHR2YXIgJG9wdGlvblBhcmVudCA9ICQob3B0aW9uUGFyZW50KTtcblx0XHQkb3B0aW9uUGFyZW50LmVtcHR5KCkuYXBwZW5kKG9wdGlvbnNIdG1sKTtcblxuXHRcdGlmIChzdGF0ZXNMaXN0Lmxlbmd0aCA8PSAxKSB7XG5cdFx0XHQkb3B0aW9uUGFyZW50LnByb3AoJ3NlbGVjdGVkSW5kZXgnLCBzdGF0ZXNMaXN0Lmxlbmd0aCAtIDEpO1xuXHRcdFx0JG9wdGlvblBhcmVudC5yZW1vdmVDbGFzcygncmVxdWlyZWQnKTtcblx0XHRcdCRvcHRpb25QYXJlbnQuY2xvc2VzdCgnLmZvcm1maWVsZCcpLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JG9wdGlvblBhcmVudC5hZGRDbGFzcygncmVxdWlyZWQnKTtcblx0XHRcdCRvcHRpb25QYXJlbnQuY2xvc2VzdCgnLmZvcm1maWVsZCcpLnNob3coKTtcblx0XHR9XG5cdH1cbn1cblxuJChkb2N1bWVudCkub24oJ3VwZGF0ZS1zaGlwcGluZycsIGZ1bmN0aW9uKCkge1xuXHRpZiAoJCgnLnNoaXBwaW5nLW1ldGhvZHMtc2VjdGlvbicpLmxlbmd0aCA9PSAwKSB7IHJldHVybjsgfVxuXHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0pO1xufSk7XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9Mb2IvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nJyk7XG5cdH1cblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzQXV0b2NvbXBsZXRlLkVuYWJsZWQpIHtcblx0XHRBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vTG9iL0FkZHJlc3NBdXRvY29tcGxldGUvQWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZycpO1xuXHR9XG5cblx0aXNTdG9yZVNoaXBwaW5nQWRkcmVzc09ubHkgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuQWdlbnRTdG9yZSAmJiBvcHRpb25zLkFnZW50U3RvcmUuU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5KTtcblx0aWYgKGlzU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5KSB7XG5cdFx0c2V0U2hpcFRvU3RvcmUodHJ1ZSk7XG5cdH1cblx0aW5pdGlhbGl6ZUV2ZW50cygpO1xuXHRpbml0aWFsaXplVXNlckludGVyZmFjZSgpO1xufTtcblxuZXhwb3J0cy51cGRhdGVTdW1tYXJ5ID0gdXBkYXRlU3VtbWFyeTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciAkZXJyb3JCb3ggPSAkKCc8ZGl2IC8+JywgeyAnaWQnOiAnZXJyb3JCb3hPUEMnLCAnY2xhc3MnOiAncGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMicsICdyb2xlJzogJ2FsZXJ0JywgJ3RhYmluZGV4JzogJzAnIH0pO1xudmFyICRlcnJvckJveEljb24gPSAkKCc8aSAvPicsIHsgJ2NsYXNzJzogJ2ZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlJywgJ3JvbGUnOiAncHJlc2VudGF0aW9uJyB9KTtcbnZhciAkZXJyb3JCb3hIZWFkbGluZSA9ICQoJzxzcGFuIC8+JywgeyAnY2xhc3MnOiAnb3BjLWVycm9yLWJveC1oZWFkbGluZScgfSk7XG52YXIgJGVycm9yQm94TWVzc2FnZSA9ICQoJzxzcGFuIC8+JywgeyAnY2xhc3MnOiAnb3BjLWVycm9yLWJveC1tZXNzYWdlJyB9KTtcblxuZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGZpZWxkVHlwZSkge1xuXHR2YXIgZXJyb3JNZXNzYWdlO1xuXHRzd2l0Y2ggKHRydWUpIHtcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2xveWFsdHlOdW1iZXInKSA+IC0xKTpcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX0xPWUFMVFlfTlVNQkVSX0VSUk9SO1xuICAgICAgICAgICAgYnJlYWs7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19sb3lhbHR5WmlwQ29kZScpID4gLTEpOlxuXHRcdFx0ZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfTE9ZQUxUWV9aSVBfRVJST1I7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2xveWFsdHlQaG9uZU51bWJlcicpID4gLTEpOlxuXHRcdFx0ZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfTE9ZQUxUWV9QSE9ORV9FUlJPUjtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfcmV3YXJkc051bWJlcicpID4gLTEpOlxuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfUkVXQVJEU19OVU1CRVJfRVJST1I7XG4gICAgICAgICAgICBicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX3Jld2FyZHNaaXBDb2RlJykgPiAtMSk6XG5cdFx0XHRlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19SRVdBUkRTX1pJUF9FUlJPUjtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfcmV3YXJkc1Bob25lTnVtYmVyJykgPiAtMSk6XG5cdFx0XHRlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19SRVdBUkRTX1BIT05FX0VSUk9SO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19naWZ0Q2FyZF9udW1iZXInKSA+IC0xKTpcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX0dJRlRfQ0FSRF9FUlJPUjtcbiAgICAgICAgICAgIGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfZ2lmdENhcmRfcGluJykgPiAtMSk6XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19HSUZUX0NBUkRfUElOX0VSUk9SO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfcHJpdmF0ZUxhYmVsQ3JlZGl0X251bWJlcicpID4gLTEpOlxuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfUFJJVkFURV9MQUJFTF9FUlJPUjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2NyZWRpdENhcmRfb3duZXInKSA+IC0xKTpcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX0NBUkRfT1dORVJfRVJST1I7XG4gICAgICAgICAgICBicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2NyZWRpdENhcmRfbnVtYmVyJykgPiAtMSk6XG5cdFx0XHRlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19DQVJEX05VTUJFUl9FUlJPUjtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfY3JlZGl0Q2FyZF9jdm4nKSA+IC0xKTpcblx0XHRcdGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX1NFQ1VSSVRZX0NPREVfRVJST1I7XG5cdFx0XHRicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybjtcbiAgICB9XG5cdHJldHVybiBlcnJvck1lc3NhZ2U7XG59XG5cbmZ1bmN0aW9uIGdldFBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcygkZm9ybSkge1xuXHRpZiAoISRmb3JtIHx8ICRmb3JtLmxlbmd0aCA9PSAwIHx8ICRmb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA9PSAwKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHZhciBlcnJvcnNMaXN0ID0gbmV3IEFycmF5KCk7XG5cdCRmb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyIGVycm9yTWVzc2FnZSA9IGdldEVycm9yTWVzc2FnZSgkKGVsZW1lbnQpLmF0dHIoJ25hbWUnKSk7XG5cdFx0aWYgKGVycm9yTWVzc2FnZSkge1xuXHRcdFx0ZXJyb3JzTGlzdC5wdXNoKGVycm9yTWVzc2FnZSk7XG5cdFx0fVxuXHR9KTtcblx0cmV0dXJuIGVycm9yc0xpc3Q7XG59XG5cbmZ1bmN0aW9uIHBheW1lbnRFcnJvckJveChoZWFkbGluZSwgbWVzc2FnZSwgZXJyb3JJdGVtcykge1xuXHQkZXJyb3JCb3guaHRtbCgnJyk7XG5cblx0aWYgKCFoZWFkbGluZSB8fCAhbWVzc2FnZSkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdCRlcnJvckJveEhlYWRsaW5lLmh0bWwoJyZuYnNwOycgKyBoZWFkbGluZSArICc6Jm5ic3A7Jyk7XG5cdCRlcnJvckJveE1lc3NhZ2UuaHRtbChtZXNzYWdlICsgJyZuYnNwOycpO1xuXHQkZXJyb3JCb3guYXBwZW5kKCRlcnJvckJveEljb24pLmFwcGVuZCgkZXJyb3JCb3hIZWFkbGluZSkuYXBwZW5kKCRlcnJvckJveE1lc3NhZ2UpO1xuXG5cdGlmIChlcnJvckl0ZW1zICYmIGVycm9ySXRlbXMubGVuZ3RoID4gMCkge1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgZXJyb3JJdGVtcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyICRuZXdFcnJvckl0ZW0gPSBlcnJvckxpc3RJdGVtKGVycm9ySXRlbXNbaV0pO1xuXHRcdFx0JGVycm9yQm94LmFwcGVuZCgkbmV3RXJyb3JJdGVtKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gJGVycm9yQm94O1xufVxuXG5mdW5jdGlvbiBlcnJvckxpc3RJdGVtKGVycm9yTXNnKSB7XG5cdHZhciAkZXJyb3JMaXN0SXRlbSA9ICQoJzxzcGFuIC8+JywgeyAnY2xhc3MnOiAnb3BjLWVycm9yLWJveC1pdGVtJyB9KTtcblx0XHQkZXJyb3JMaXN0SXRlbS5odG1sKGVycm9yTXNnICsgJyZuYnNwOycpO1xuXG5cdHJldHVybiAkZXJyb3JMaXN0SXRlbTtcbn1cblxuZXhwb3J0cy5nZXRFcnJvck1lc3NhZ2VzID0gZ2V0UGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzO1xuZXhwb3J0cy5lcnJvckJveCA9IHBheW1lbnRFcnJvckJveDsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpLFxuICAgIGZvcm1QcmVwYXJlID0gcmVxdWlyZSgnLi9mb3JtUHJlcGFyZScpLFxuICAgIHByb2dyZXNzID0gcmVxdWlyZSgnLi4vLi4vcHJvZ3Jlc3MnKSxcbiAgICB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbnZhciBzaGlwcGluZ01ldGhvZHM7XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGdpZnQgbWVzc2FnZSBib3gsIGlmIHNoaXBtZW50IGlzIGdpZnRcbiAqL1xuZnVuY3Rpb24gZ2lmdE1lc3NhZ2VCb3goKSB7XG4gICAgLy8gc2hvdyBnaWZ0IG1lc3NhZ2UgYm94LCBpZiBzaGlwbWVudCBpcyBnaWZ0XG4gICAgJCgnLmdpZnQtbWVzc2FnZS10ZXh0JykudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsICQoJ2lucHV0W25hbWUkPVwiX3NoaXBwaW5nQWRkcmVzc19pc0dpZnRcIl06Y2hlY2tlZCcpLnZhbCgpICE9PSAndHJ1ZScpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHVwZGF0ZXMgdGhlIG9yZGVyIHN1bW1hcnkgYmFzZWQgb24gYSBwb3NzaWJseSByZWNhbGN1bGF0ZWQgYmFza2V0IGFmdGVyIGEgc2hpcHBpbmcgcHJvbW90aW9uIGhhcyBiZWVuIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gdXBkYXRlU3VtbWFyeSgpIHtcbiAgICB2YXIgJHN1bW1hcnkgPSAkKCcjc2Vjb25kYXJ5LnN1bW1hcnknKTtcbiAgICAvLyBpbmRpY2F0ZSBwcm9ncmVzc1xuICAgIHByb2dyZXNzLnNob3coJHN1bW1hcnkpO1xuXG4gICAgLy8gbG9hZCB0aGUgdXBkYXRlZCBzdW1tYXJ5IGFyZWFcbiAgICAkc3VtbWFyeS5sb2FkKFVybHMuc3VtbWFyeVJlZnJlc2hVUkwsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gaGlkZSBlZGl0IHNoaXBwaW5nIG1ldGhvZCBsaW5rXG4gICAgICAgICRzdW1tYXJ5LmZhZGVJbignZmFzdCcpO1xuICAgICAgICAkc3VtbWFyeS5maW5kKCcuY2hlY2tvdXQtbWluaS1jYXJ0IC5taW5pc2hpcG1lbnQgLmhlYWRlciBhJykuaGlkZSgpO1xuICAgICAgICAkc3VtbWFyeS5maW5kKCcub3JkZXItdG90YWxzLXRhYmxlIC5vcmRlci1zaGlwcGluZyAubGFiZWwgYScpLmhpZGUoKTtcbiAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXN1bW1hcnknKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBIZWxwZXIgbWV0aG9kIHdoaWNoIGNvbnN0cnVjdHMgYSBVUkwgZm9yIGFuIEFKQVggcmVxdWVzdCB1c2luZyB0aGVcbiAqIGVudGVyZWQgYWRkcmVzcyBpbmZvcm1hdGlvbiBhcyBVUkwgcmVxdWVzdCBwYXJhbWV0ZXJzLlxuICovXG5mdW5jdGlvbiBnZXRTaGlwcGluZ01ldGhvZFVSTCh1cmwsIGV4dHJhUGFyYW1zKSB7XG4gICAgdmFyICRmb3JtID0gJCgnLmFkZHJlc3MnKTtcbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBhZGRyZXNzMTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSxcbiAgICAgICAgYWRkcmVzczI6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCksXG4gICAgICAgIGFkZHJlc3MzOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzM1wiXScpLnZhbCgpLFxuICAgICAgICBjb3VudHJ5Q29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9jb3VudHJ5XCJdJykudmFsKCksXG4gICAgICAgIHN0YXRlQ29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9zdGF0ZVwiXScpLnZhbCgpLFxuICAgICAgICBwb3N0YWxDb2RlOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoKSxcbiAgICAgICAgY2l0eTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpXG4gICAgfTtcbiAgICByZXR1cm4gdXRpbC5hcHBlbmRQYXJhbXNUb1VybCh1cmwsICQuZXh0ZW5kKHBhcmFtcywgZXh0cmFQYXJhbXMpKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBzZWxlY3RzIGEgc2hpcHBpbmcgbWV0aG9kIGZvciB0aGUgZGVmYXVsdCBzaGlwbWVudCBhbmQgdXBkYXRlcyB0aGUgc3VtbWFyeSBzZWN0aW9uIG9uIHRoZSByaWdodCBoYW5kIHNpZGVcbiAqIEBwYXJhbVxuICovXG5mdW5jdGlvbiBzZWxlY3RTaGlwcGluZ01ldGhvZChzaGlwcGluZ01ldGhvZElEKSB7XG4gICAgLy8gbm90aGluZyBlbnRlcmVkXG4gICAgaWYgKCFzaGlwcGluZ01ldGhvZElEKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gYXR0ZW1wdCB0byBzZXQgc2hpcHBpbmcgbWV0aG9kXG4gICAgdmFyIHVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKFVybHMuc2VsZWN0U2hpcHBpbmdNZXRob2RzTGlzdCwge3NoaXBwaW5nTWV0aG9kSUQ6IHNoaXBwaW5nTWV0aG9kSUR9KTtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG4gICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuc2hpcHBpbmdNZXRob2RJRCkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydCgnQ291bGRuXFwndCBzZWxlY3Qgc2hpcHBpbmcgbWV0aG9kLicpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRpc3BsYXkgcHJvbW90aW9uIGluIFVJIGFuZCB1cGRhdGUgdGhlIHN1bW1hcnkgc2VjdGlvbixcbiAgICAgICAgICAgIC8vIGlmIHNvbWUgcHJvbW90aW9ucyB3ZXJlIGFwcGxpZWRcbiAgICAgICAgICAgICQoJy5zaGlwcGluZ3Byb21vdGlvbnMnKS5lbXB0eSgpO1xuXG4gICAgICAgICAgICAvLyBUT0RPIHRoZSBmb3IgbG9vcCBiZWxvdyBpc24ndCBkb2luZyBhbnl0aGluZz9cbiAgICAgICAgICAgIC8vIGlmIChkYXRhLnNoaXBwaW5nUHJpY2VBZGp1c3RtZW50cyAmJiBkYXRhLnNoaXBwaW5nUHJpY2VBZGp1c3RtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyAgICAgdmFyIGxlbiA9IGRhdGEuc2hpcHBpbmdQcmljZUFkanVzdG1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vICAgICBmb3IgKHZhciBpPTA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgLy8gICAgICAgICB2YXIgc3BhID0gZGF0YS5zaGlwcGluZ1ByaWNlQWRqdXN0bWVudHNbaV07XG4gICAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgICAgLy8gfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gTWFrZSBhbiBBSkFYIHJlcXVlc3QgdG8gdGhlIHNlcnZlciB0byByZXRyaWV2ZSB0aGUgbGlzdCBvZiBhcHBsaWNhYmxlIHNoaXBwaW5nIG1ldGhvZHNcbiAqIGJhc2VkIG9uIHRoZSBtZXJjaGFuZGlzZSBpbiB0aGUgY2FydCBhbmQgdGhlIGN1cnJlbnRseSBlbnRlcmVkIHNoaXBwaW5nIGFkZHJlc3NcbiAqICh0aGUgYWRkcmVzcyBtYXkgYmUgb25seSBwYXJ0aWFsbHkgZW50ZXJlZCkuICBJZiB0aGUgbGlzdCBvZiBhcHBsaWNhYmxlIHNoaXBwaW5nIG1ldGhvZHNcbiAqIGhhcyBjaGFuZ2VkIGJlY2F1c2UgbmV3IGFkZHJlc3MgaW5mb3JtYXRpb24gaGFzIGJlZW4gZW50ZXJlZCwgdGhlbiBpc3N1ZSBhbm90aGVyIEFKQVhcbiAqIHJlcXVlc3Qgd2hpY2ggdXBkYXRlcyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNoaXBwaW5nIG1ldGhvZCAoaWYgbmVlZGVkKSBhbmQgYWxzbyB1cGRhdGVzXG4gKiB0aGUgVUkuXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgpIHtcbiAgICB2YXIgJHNoaXBwaW5nTWV0aG9kTGlzdCA9ICQoJyNzaGlwcGluZy1tZXRob2QtbGlzdCcpO1xuICAgIGlmICghJHNoaXBwaW5nTWV0aG9kTGlzdCB8fCAkc2hpcHBpbmdNZXRob2RMaXN0Lmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICB2YXIgdXJsID0gZ2V0U2hpcHBpbmdNZXRob2RVUkwoVXJscy5zaGlwcGluZ01ldGhvZHNKU09OKTtcblxuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydCgnQ291bGRuXFwndCBnZXQgbGlzdCBvZiBhcHBsaWNhYmxlIHNoaXBwaW5nIG1ldGhvZHMuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNoaXBwaW5nTWV0aG9kcyAmJiBzaGlwcGluZ01ldGhvZHMudG9TdHJpbmcoKSA9PT0gZGF0YS50b1N0cmluZygpKSB7XG4gICAgICAgICAgICAgICAgLy8gTm8gbmVlZCB0byB1cGRhdGUgdGhlIFVJLiAgVGhlIGxpc3QgaGFzIG5vdCBjaGFuZ2VkLlxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHVwZGF0ZSB0aGUgVUkuICBUaGUgbGlzdCBoYXMgY2hhbmdlZC5cbiAgICAgICAgICAgIC8vIENhY2hlIHRoZSBhcnJheSBvZiByZXR1cm5lZCBzaGlwcGluZyBtZXRob2RzLlxuICAgICAgICAgICAgc2hpcHBpbmdNZXRob2RzID0gZGF0YTtcbiAgICAgICAgICAgIC8vIGluZGljYXRlIHByb2dyZXNzXG4gICAgICAgICAgICBwcm9ncmVzcy5zaG93KCRzaGlwcGluZ01ldGhvZExpc3QpO1xuXG4gICAgICAgICAgICAvLyBsb2FkIHRoZSBzaGlwcGluZyBtZXRob2QgZm9ybVxuICAgICAgICAgICAgdmFyIHNtbFVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKFVybHMuc2hpcHBpbmdNZXRob2RzTGlzdCk7XG4gICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmxvYWQoc21sVXJsLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5mYWRlSW4oJ2Zhc3QnKTtcbiAgICAgICAgICAgICAgICAvLyByZWJpbmQgdGhlIHJhZGlvIGJ1dHRvbnMgb25jbGljayBmdW5jdGlvbiB0byBhIGhhbmRsZXIuXG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCdbbmFtZSQ9XCJfc2hpcHBpbmdNZXRob2RJRFwiXScpLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0U2hpcHBpbmdNZXRob2QoJCh0aGlzKS52YWwoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHN1bW1hcnlcbiAgICAgICAgICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRvb2x0aXAuaW5pdCgpO1xuICAgICAgICAgICAgICAgIC8vaWYgbm90aGluZyBpcyBzZWxlY3RlZCBpbiB0aGUgc2hpcHBpbmcgbWV0aG9kcyBzZWxlY3QgdGhlIGZpcnN0IG9uZVxuICAgICAgICAgICAgICAgIGlmICgkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJy5pbnB1dC1yYWRpbzpjaGVja2VkJykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICRzaGlwcGluZ01ldGhvZExpc3QuZmluZCgnLmlucHV0LXJhZGlvOmZpcnN0JykucHJvcCgnY2hlY2tlZCcsICdjaGVja2VkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGZvcm1QcmVwYXJlLmluaXQoe1xuICAgICAgICBjb250aW51ZVNlbGVjdG9yOiAnW25hbWUkPVwic2hpcHBpbmdBZGRyZXNzX3NhdmVcIl0nLFxuICAgICAgICBmb3JtU2VsZWN0b3I6J1tpZCQ9XCJzaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3NcIl0nXG4gICAgfSk7XG4gICAgJCgnaW5wdXRbbmFtZSQ9XCJfc2hpcHBpbmdBZGRyZXNzX2lzR2lmdFwiXScpLm9uKCdjbGljaycsIGdpZnRNZXNzYWdlQm94KTtcblxuICAgICQoJy5hZGRyZXNzJykub24oJ2NoYW5nZScsXG4gICAgICAgICdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX2FkZHJlc3MxXCJdLCBpbnB1dFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX2FkZHJlc3MyXCJdLCBpbnB1dFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX2FkZHJlc3MzXCJdLCBzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc19zdGF0ZXNfc3RhdGVcIl0sIGlucHV0W25hbWUkPVwiX2FkZHJlc3NGaWVsZHNfY2l0eVwiXSwgaW5wdXRbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc196aXBcIl0nLFxuICAgICAgICB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3RcbiAgICApO1xuXG4gICAgZ2lmdE1lc3NhZ2VCb3goKTtcbiAgICB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoKTtcbn07XG5cbmV4cG9ydHMudXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0ID0gdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2c7XG52YXIgQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZztcbnZhciBBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9BZGRyZXNzVmVyaWZpY2F0aW9uL0FkZHJlc3NWZXJpZmljYXRpb25IZWxwZXInKTtcbnZhciBBcHBsZVBheSA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvQXBwbGVQYXknKTtcbnZhciBDaGVja291dENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQ2hlY2tvdXRDb25zdGFudHMnKTtcbnZhciBHaWZ0Q2FyZCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvR2lmdENhcmRQYXltZW50UGFuZWwnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcbnZhciBSZXdhcmRzQ3JlZGl0ID0gcmVxdWlyZSgnLi9jaGVja291dC9SZXdhcmRzQ3JlZGl0Jyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi90b29sdGlwJyk7XG52YXIgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxudmFyIGNoZWNrb3V0Rm9ybVNlbGVjdG9yID0gJyNjaGVja291dC1mb3JtJztcbnZhciAkY2hlY2tvdXRGb3JtID0gJChjaGVja291dEZvcm1TZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZFR5cGVMaXN0U2VsZWN0b3IgPSAnLnBheW1lbnQtY2FyZC1saXN0JztcbnZhciAkY3JlZGl0Q2FyZFR5cGVMaXN0ID0gJChjcmVkaXRDYXJkVHlwZUxpc3RTZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZE51bWJlcklucHV0U2VsZWN0b3IgPSAnLmZvcm1maWVsZC5jYXJkLW51bWJlciBpbnB1dCc7XG52YXIgJGNyZWRpdENhcmROdW1iZXJJbnB1dCA9ICQoY3JlZGl0Q2FyZE51bWJlcklucHV0U2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRFeHBpcmF0aW9uTW9udGhJbnB1dFNlbGVjdG9yID0gJy5tb250aGZpZWxkIGlucHV0JztcbnZhciAkY3JlZGl0Q2FyZEV4cGlyYXRpb25Nb250aElucHV0ID0gJChjcmVkaXRDYXJkRXhwaXJhdGlvbk1vbnRoSW5wdXRTZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZEV4cGlyYXRpb25ZZWFySW5wdXRTZWxlY3RvciA9ICcueWVhcmZpZWxkIGlucHV0JztcbnZhciAkY3JlZGl0Q2FyZEV4cGlyYXRpb25ZZWFySW5wdXQgPSAkKGNyZWRpdENhcmRFeHBpcmF0aW9uWWVhcklucHV0U2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRDVlZJbnB1dFNlbGVjdG9yID0gJy5mb3JtLXJvdy5jdm4gaW5wdXQnO1xudmFyICRjcmVkaXRDYXJkQ1ZWSW5wdXQgPSAkKGNyZWRpdENhcmRDVlZJbnB1dFNlbGVjdG9yKTtcbnZhciBhZGRyZXNzSW5wdXRTZWxlY3RvciA9ICcuZm9ybWZpZWxkLmFkZHJlc3MxIGlucHV0JztcbnZhciAkYWRkcmVzc0lucHV0ID0gJChhZGRyZXNzSW5wdXRTZWxlY3Rvcik7XG52YXIgc3VibWl0UGF5bWVudFNlbGVjdG9yID0gJyNzdWJtaXRPUENQYXltZW50JztcbnZhciAkc3VibWl0UGF5bWVudCA9ICQoc3VibWl0UGF5bWVudFNlbGVjdG9yKTtcbnZhciAkcmV3YXJkc0FjY29yZGlvbiA9ICQoJy5yZXdhcmRzJyk7XG52YXIgJHJld2FyZHNQYXltZW50Q29udGFpbmVyID0gJHJld2FyZHNBY2NvcmRpb24uZmluZCgnW3BheW1lbnQtbWV0aG9kPVwiUkVXQVJEU19DUkVESVRcIl0nKTtcbnZhciAkcmV3YXJkc0Zvcm0gPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnLnJld2FyZHMtZm9ybScpO1xudmFyICRyZXdhcmRzQXBwbGllZCA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcucmV3YXJkcy1hcHBsaWVkJyk7XG5cbnZhciBvcHRpb25zID0ge307XG52YXIgZGF0YUJ1ZmZlciA9IHt9O1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnMpIHtcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCBzdWJtaXRQYXltZW50U2VsZWN0b3IsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyIGFkZHJlc3NEZWxpdmVyYWJsZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdHN1Ym1pdFBheW1lbnQoKTtcblx0XHR9XG5cdFxuXHRcdHZhciBhZGRyZXNzTm90RGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoYWRkcmVzc1ZlcmlmeURhdGEpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCAnYmlsbGluZycsIGFkZHJlc3NWZXJpZnlEYXRhKTtcblx0XHR9XG5cdFxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5WZXJpZnlBZGRyZXNzKCRjaGVja291dEZvcm0sIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0RlbGl2ZXJhYmxlLCBhZGRyZXNzTm90RGVsaXZlcmFibGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhZGRyZXNzRGVsaXZlcmFibGUoKTtcblx0XHR9XG4gICAgfSk7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0JGNoZWNrb3V0Rm9ybS5vZmYoJ2tleXVwLkFkZHJlc3NBdXRvY29tcGxldGUnKS5vbigna2V5dXAuQWRkcmVzc0F1dG9jb21wbGV0ZScsICdpbnB1dFt0eXBlPVwidGV4dFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdHZhciAkZm9ybSA9ICR0aGlzLmNsb3Nlc3QoJ2Zvcm0nKTtcblx0XHRcdHZhciBmb3JtVmFsaWRhdG9yID0gJGZvcm0udmFsaWRhdGUoKTtcblxuXHRcdFx0aWYgKGV2ZW50LmtleUNvZGUgPT0gOCB8fCBldmVudC5rZXlDb2RlID09IDQ2KSB7XG5cdFx0XHRcdCR0aGlzLnBhcmVudCgpLmZpbmQoJy5hZGRyZXNzLWF1dG9jb21wbGV0ZS1kaWFsb2cnKS5yZW1vdmUoKTtcblx0XHRcdH0gZWxzZSBpZiAoIWZvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgKCR0aGlzLmF0dHIoJ2lkJykuaW5kZXhPZignX2FkZHJlc3MxJykgPj0gMCB8fCAkdGhpcy5hdHRyKCdpZCcpLmluZGV4T2YoJ19hZGRyZXNzMicpID49IDApKSB7XG5cdFx0XHRcdHZhciBhZGRyZXNzQXV0b2NvbXBsZXRlSGFuZGxlciA9IGZ1bmN0aW9uIChhZGRyZXNzQXV0b2NvbXBsZXRlRGF0YSkge1xuXHRcdFx0XHRcdEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCBhZGRyZXNzQXV0b2NvbXBsZXRlRGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdFxuXHRcdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLkF1dG9jb21wbGV0ZUFkZHJlc3MoJGZvcm0sICR0aGlzLCBvcHRpb25zKS50aGVuKGFkZHJlc3NBdXRvY29tcGxldGVIYW5kbGVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCR0aGlzLnBhcmVudCgpLmZpbmQoJy5hZGRyZXNzLWF1dG9jb21wbGV0ZS1kaWFsb2cnKS5yZW1vdmUoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRcblx0XHQkKGRvY3VtZW50KS5vZmYoJ1NldEFkZHJlc3NGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZScpLm9uKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NBdXRvY29tcGxldGUnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGEpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nKGRhdGEuJGZvcm0sIGRhdGEuQWRkcmVzcyk7XG5cdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX2JpbGxpbmdBZGRyZXNzX2VtYWlsX2VtYWlsQWRkcmVzcywgaW5wdXQucGhvbmUsIGlucHV0LnBvc3RhbCcpLnRyaWdnZXIoJ2JsdXIuUmV3YXJkc0FjY291bnRTZWFyY2gnKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdCQoZG9jdW1lbnQpLm9mZignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJykub24oJ1NldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbicsIGZ1bmN0aW9uIChldmVudCwgYWRkcmVzc0RhdGEpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nKCRjaGVja291dEZvcm0sIGFkZHJlc3NEYXRhKTtcblx0XHRcdHN1Ym1pdFBheW1lbnQoKTtcblx0XHR9KTtcblx0fVxuXG5cdCRjaGVja291dEZvcm0ub2ZmKCdibHVyLlJld2FyZHNBY2NvdW50U2VhcmNoJykub24oJ2JsdXIuUmV3YXJkc0FjY291bnRTZWFyY2gnLCAnI2R3ZnJtX2JpbGxpbmdfYmlsbGluZ0FkZHJlc3NfZW1haWxfZW1haWxBZGRyZXNzLCBpbnB1dC5waG9uZSwgaW5wdXQucG9zdGFsJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10gJiYgZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10ucmVhZHlTdGF0ZSAhPT0gNCkge1xuXHRcdFx0ZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10uYWJvcnQoKTtcblx0XHRcdGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddID0gbnVsbDtcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBmaWVsZCA9ICR0aGlzLmNsb3Nlc3QoJ1tmaWVsZF0nKS5hdHRyKCdmaWVsZCcpO1xuXHRcdHZhciB2YWx1ZSA9ICR0aGlzLnZhbCgpO1xuXHRcdGlmIChmaWVsZCAmJiB2YWx1ZSkge1xuXHRcdFx0aWYgKCFkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddKSB7XG5cdFx0XHRcdGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ10gPSB7fTtcblx0XHRcdH1cblx0XHRcdGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ11bZmllbGRdID0gdmFsdWU7XG5cblx0XHRcdHN3aXRjaCAoZmllbGQpIHtcblx0XHRcdFx0Y2FzZSAnZW1haWxBZGRyZXNzJzpcblx0XHRcdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzRW1haWwnKS52YWwodmFsdWUpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdwaG9uZSc6XG5cdFx0XHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC5waG9uZW51bWJlcicpLnZhbCh2YWx1ZSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3Bvc3RhbCc6XG5cdFx0XHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC56aXBjb2RlJykudmFsKHZhbHVlKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0dmFyIGlzUmV3YXJkc0RhdGFSZWFkeSA9IGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ11bJ2VtYWlsQWRkcmVzcyddICYmIGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ11bJ3Bob25lJ10gJiYgZGF0YUJ1ZmZlclsnUmV3YXJkc0RhdGEnXVsncG9zdGFsJ107XG5cdFx0XHR2YXIgaXNSZXdhcmRzTnVtYmVyRmllbGRFbXB0eSA9ICEkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKCk7XG5cdFx0XHRpZiAoaXNSZXdhcmRzRGF0YVJlYWR5ICYmIGlzUmV3YXJkc051bWJlckZpZWxkRW1wdHkpIHtcblx0XHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdFx0RW1haWxBZGRyZXNzOiBkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddWydlbWFpbEFkZHJlc3MnXSxcblx0XHRcdFx0XHRQaG9uZU51bWJlcjogZGF0YUJ1ZmZlclsnUmV3YXJkc0RhdGEnXVsncGhvbmUnXSxcblx0XHRcdFx0XHRaaXBDb2RlOiBkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddWydwb3N0YWwnXSxcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICgkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKCkpIHtcblx0XHRcdFx0XHRwYXlsb2FkLlJld2FyZHNOdW1iZXIgPSAkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkYXRhQnVmZmVyWydSZXdhcmRzQWNjb3VudFNlYXJjaFJlcXVlc3QnXSA9ICQuYWpheCh7XG5cdFx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRcdHVybDogVXJscy5zZWFyY2hGb3JSZXdhcmRzLFxuXHRcdFx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHRyZW5kZXJSZXdhcmRzRGF0YShkYXRhKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbih4aHIpIHtcblxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcblxuXHQkcmV3YXJkc0Zvcm0ub2ZmKCdrZXl1cC5SZXdhcmRzUmVzZXQgY2hhbmdlLlJld2FyZHNSZXNldCcpLm9uKCdrZXl1cC5SZXdhcmRzUmVzZXQgY2hhbmdlLlJld2FyZHNSZXNldCcsICdpbnB1dCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIGlzUmV3YXJkc0Zvcm1Qb3B1bGF0ZWQgPSBmYWxzZTtcblx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnaW5wdXQnKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCQodGhpcykudmFsKCkpIHtcblx0XHRcdFx0aXNSZXdhcmRzRm9ybVBvcHVsYXRlZCA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0aWYgKGlzUmV3YXJkc0Zvcm1Qb3B1bGF0ZWQpIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuYnRuLnJlc2V0LWVjaG8nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmJ0bi5yZXNldC1lY2hvJykuYXR0cignZGlzYWJsZWQnLCAndHJ1ZScpO1xuXHRcdH1cblx0fSk7XG5cblx0JHJld2FyZHNGb3JtLm9mZignY2xpY2suUmV3YXJkc1Jlc2V0Jykub24oJ2NsaWNrLlJld2FyZHNSZXNldCcsICcuYnRuLnJlc2V0LWVjaG8nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRpZiAoJHJld2FyZHNBcHBsaWVkLmZpbmQoJy5yZXdhcmQtcm93W3N0YXR1cz1cImFwcGxpZWRcIl0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkcmV3YXJkc0FwcGxpZWQuZmluZCgnLnJld2FyZC1yb3dbc3RhdHVzPVwiYXBwbGllZFwiXSAuYnRuLnJlbW92ZScpLnRyaWdnZXIoJ1Jld2FyZHNDcmVkaXQuUmVtb3ZlJywgeyBSZXNldFNlc3Npb25EYXRhOiB0cnVlIH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMucmVzZXRSZXdhcmRzU2Vzc2lvbkRhdGEsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJ1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdCRyZXdhcmRzQXBwbGllZC5odG1sKCcnKTtcblx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnaW5wdXQnKS52YWwoJycpO1xuXHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuYnRuLnJlc2V0LWVjaG8nKS5hdHRyKCdkaXNhYmxlZCcsICd0cnVlJyk7XG5cdFx0JHJld2FyZHNGb3JtLmZpbmQoJ1ttYXRjaF0nKS5yZW1vdmVBdHRyKCdtYXRjaCcpO1xuXHRcdCRyZXdhcmRzQWNjb3JkaW9uLnJlbW92ZUF0dHIoJ3Jld2FyZHMtZm91bmQnKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdSZXdhcmRzQWNjb3VudFNlYXJjaCcpLm9uKCdSZXdhcmRzQWNjb3VudFNlYXJjaCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0c2VhcmNoUmV3YXJkcygpO1xuXHR9KTtcblxuXHR1cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnKTtcblxuXHQkcmV3YXJkc0Zvcm0ub2ZmKCdjbGljay5SZXdhcmRzQWNjb3VudFNlYXJjaCcpLm9uKCdjbGljay5SZXdhcmRzQWNjb3VudFNlYXJjaCcsICcuYnRuLnNlYXJjaC1lY2hvJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNlYXJjaFJld2FyZHMoKTtcblx0fSk7XG5cblx0JGNyZWRpdENhcmROdW1iZXJJbnB1dC5vZmYoJ2tleWRvd24uQ3JlZGl0Q2FyZE51bWJlckhhbmRsZXInKS5vbigna2V5ZG93bi5DcmVkaXRDYXJkTnVtYmVySGFuZGxlcicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0JGNyZWRpdENhcmRUeXBlTGlzdC52YWwoJycpO1xuXHR9KTtcblxuXHQkY3JlZGl0Q2FyZE51bWJlcklucHV0Lm9mZigna2V5dXAuQ3JlZGl0Q2FyZE51bWJlckhhbmRsZXInKS5vbigna2V5dXAuQ3JlZGl0Q2FyZE51bWJlckhhbmRsZXInLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIGNyZWRpdENhcmROdW1iZXIgPSAkdGhpcy52YWwoKTtcblx0XHRcblx0XHR2YXIgc2VsZWN0ZWRDYXJkID0gdXRpbC5nZXRDcmVkaXRDYXJkVHlwZShjcmVkaXRDYXJkTnVtYmVyKTtcblx0XHRpZiAoc2VsZWN0ZWRDYXJkKSB7XG5cdFx0XHRpZiAoJGNyZWRpdENhcmROdW1iZXJJbnB1dC5maWx0ZXIoJzp2aXNpYmxlJykubGVuZ3RoIDwgMSkge1xuXHRcdFx0XHQkY3JlZGl0Q2FyZE51bWJlcklucHV0LnZhbChjcmVkaXRDYXJkTnVtYmVyKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JCgnaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykudmFsKHNlbGVjdGVkQ2FyZC5QYXltZW50Q2FyZCk7XG5cdFx0XHQkKCdpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbChzZWxlY3RlZENhcmQuUGF5bWVudE1ldGhvZCk7XG5cdFx0XHQkY3JlZGl0Q2FyZFR5cGVMaXN0LmZpbmQoJ2lucHV0W3R5cGU9XCJyYWRpb1wiXVt2YWx1ZT1cIicgKyBzZWxlY3RlZENhcmQuUGF5bWVudENhcmREaXNwbGF5S2V5ICsgJ1wiXScpLmZpcnN0KCkucHJvcCgnY2hlY2tlZCcsIHRydWUpLnRyaWdnZXIoJ2NoYW5nZScsIHsgZG9SZXNldDogZmFsc2UgfSk7XG5cdFx0XHR2YXIgJHBheW1lbnRDYXJkSW1hZ2UgPSAkY3JlZGl0Q2FyZFR5cGVMaXN0LmZpbmQoJ2lucHV0W3ZhbHVlPVwiJyArIHNlbGVjdGVkQ2FyZC5QYXltZW50Q2FyZERpc3BsYXlLZXkgKyAnXCJdJyk7XG5cdFx0XHR2YXIgcGF5bWVudENhcmRJbWFnZVVybDtcblx0XHRcdGlmICgkcGF5bWVudENhcmRJbWFnZSAmJiAkcGF5bWVudENhcmRJbWFnZS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHBheW1lbnRDYXJkSW1hZ2VVcmwgPSAkcGF5bWVudENhcmRJbWFnZS5hdHRyKCdwYXltZW50LWNhcmQtaW1hZ2UnKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHBheW1lbnRDYXJkSW1hZ2VVcmwpIHtcblx0XHRcdFx0JGNyZWRpdENhcmROdW1iZXJJbnB1dC5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAndXJsKCcgKyBwYXltZW50Q2FyZEltYWdlVXJsICsgJyknKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNyZWRpdENhcmROdW1iZXIubGVuZ3RoID49IDE2KSB7XG5cdFx0XHRcdCRjcmVkaXRDYXJkRXhwaXJhdGlvbk1vbnRoSW5wdXQuZm9jdXMoKTtcblx0XHRcdH1cblx0XHRcdGlmIChzZWxlY3RlZENhcmQuUGF5bWVudE1ldGhvZCA9PSAnQWxsaWFuY2VfRGF0YScpIHtcblx0XHRcdFx0JCgnLmZvcm1maWVsZC5jYXJkLW5hbWUnKS5oaWRlKCk7XG5cdFx0XHRcdCQoJy5mb3JtZmllbGQuY2FyZC1uYW1lIGlucHV0JykucmVtb3ZlQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHRcdCQoJy5jYXJkLWV4cGlyYXRpb24tYW5kLWN2bicpLmFkZENsYXNzKCdudW1iZXItb25seScpO1xuXHRcdFx0XHQkKCcuY2FyZC1leHBpcmF0aW9uLWFuZC1jdm4gaW5wdXQnKS5yZW1vdmVDbGFzcygncmVxdWlyZWQnKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0JGNyZWRpdENhcmRUeXBlTGlzdC5maW5kKCdpbnB1dCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0XHQkY3JlZGl0Q2FyZFR5cGVMaXN0LmZpbmQoJ29wdGlvbicpLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xuXHRcdFx0JGNyZWRpdENhcmROdW1iZXJJbnB1dC5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAnJyk7XG5cdFx0XHQkKCcuZm9ybWZpZWxkLmNhcmQtbmFtZScpLnNob3coKTtcblx0XHRcdCQoJy5mb3JtZmllbGQuY2FyZC1uYW1lIGlucHV0JykuYWRkQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHQkKCcuY2FyZC1leHBpcmF0aW9uLWFuZC1jdm4nKS5yZW1vdmVDbGFzcygnbnVtYmVyLW9ubHknKTtcblx0XHRcdCQoJy5jYXJkLWV4cGlyYXRpb24tYW5kLWN2biBpbnB1dCcpLmFkZENsYXNzKCdyZXF1aXJlZCcpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNyZWRpdENhcmRFeHBpcmF0aW9uTW9udGhJbnB1dC5vZmYoJ2tleWRvd24uRmllbGRCbG9jaycpLm9uKCdrZXlwcmVzcy5GaWVsZEJsb2NrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoJCh0aGlzKS52YWwoKS5sZW5ndGggPj0gMikge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNyZWRpdENhcmRFeHBpcmF0aW9uTW9udGhJbnB1dC5vZmYoJ2tleXVwLkZpZWxkU2hpZnQnKS5vbigna2V5dXAuRmllbGRTaGlmdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCQodGhpcykudmFsKCkubGVuZ3RoID49IDIpIHtcblx0XHRcdCRjcmVkaXRDYXJkRXhwaXJhdGlvblllYXJJbnB1dC5mb2N1cygpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNyZWRpdENhcmRFeHBpcmF0aW9uWWVhcklucHV0Lm9mZigna2V5ZG93bi5GaWVsZEJsb2NrJykub24oJ2tleXByZXNzLkZpZWxkQmxvY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICgkKHRoaXMpLnZhbCgpLmxlbmd0aCA+PSAyKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9KTtcblxuXHQkY3JlZGl0Q2FyZEV4cGlyYXRpb25ZZWFySW5wdXQub2ZmKCdrZXl1cC5GaWVsZFNoaWZ0Jykub24oJ2tleXVwLkZpZWxkU2hpZnQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICgkKHRoaXMpLnZhbCgpLmxlbmd0aCA+PSAyKSB7XG5cdFx0XHQkY3JlZGl0Q2FyZENWVklucHV0LmZvY3VzKCk7XG5cdFx0fVxuXHR9KTtcblxuXHQkY3JlZGl0Q2FyZENWVklucHV0Lm9mZigna2V5dXAuRmllbGRTaGlmdCcpLm9uKCdrZXl1cC5GaWVsZFNoaWZ0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgY3Z2TGVuZ3RoID0gJCgnaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykudmFsKCkgPT0gJ0FtZXgnID8gNCA6IDM7XG5cblx0XHRpZiAoJCh0aGlzKS52YWwoKS5sZW5ndGggPj0gY3Z2TGVuZ3RoKSB7XG5cdFx0XHQkYWRkcmVzc0lucHV0LmZvY3VzKCk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLmFjY29yZGlvbi1oZWFkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHQkKHRoaXMpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJhZGRDb3Vwb25cIl0nKS5vbignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiYWRkQ291cG9uXCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnLmNhcnQtY291cG9uLWNvZGUnKTtcblx0XHR2YXIgJGFwcGx5QnV0dG9uID0gJGNvbnRhaW5lci5maW5kKCcuYnRuLWNvdXBvbi1jb2RlJyk7XG5cdFx0JCgnLmVycm9yLmNvdXBvbi1lcnJvcicpLnRleHQoJycpO1xuXHRcdFxuXHRcdChmdW5jdGlvbigpIHtcblx0XHRcdCRhcHBseUJ1dHRvbi5sb2FkaW5nKHtcblx0XHRcdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0XHR9KTtcblxuXHRcdFx0cmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcblx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHR1cmw6IHV0aWwuYWpheFVybChVcmxzLm9uZVBhZ2VTdWJtaXQpLFxuXHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0ZHdmcm1fY2FydF9hZGRDb3Vwb246ICdkd2ZybV9jYXJ0X2FkZENvdXBvbicsXG5cdFx0XHRcdFx0ZHdmcm1fY2FydF9jb3Vwb25Db2RlOiAkKCcuYWNjb3JkaW9uLmNvdXBvbiAjZHdmcm1fY2FydF9jb3Vwb25Db2RlJykudmFsKCksXG5cdFx0XHRcdFx0cmVzcFR5cGU6ICdqc29uJ1xuXHRcdFx0XHR9XG5cdFx0XHR9KSk7XG5cdFx0fSgpKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0aWYgKHJlc3BvbnNlLnN1Y2Nlc3MgJiYgcmVzcG9uc2Uuc3VjY2VzcyAhPT0gQ2hlY2tvdXRDb25zdGFudHMuUmVzcG9uc2VDb2Rlcy5BbHJlYWR5SW5CYXNrZXQpIHtcdFx0XHRcdFxuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSByZXNwb25zZS5zdWNjZXNzID09IENoZWNrb3V0Q29uc3RhbnRzLlJlc3BvbnNlQ29kZXMuQWxyZWFkeUluQmFza2V0ID8gUmVzb3VyY2VzLkNPVVBPTl9BRERfRVJST1JfRFVQIDogUmVzb3VyY2VzLkNPVVBPTl9BRERfRVJST1I7XG5cdFx0XHRcdCQoJzxzcGFuLz4nLCB7J2NsYXNzJzogJ2Vycm9yIGNvdXBvbi1lcnJvcicsICd0ZXh0JzogbWVzc2FnZX0pLmluc2VydEFmdGVyKCcuYWNjb3JkaW9uLmNvdXBvbiAuY2FydC1jb3Vwb24tY29kZSAucGNvZGUtY291cG9uJyk7XG5cdFx0XHRcdGlmICgkYXBwbHlCdXR0b24uYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHRcdFx0JGFwcGx5QnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImRlbGV0ZUNvdXBvblwiXScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJkZWxldGVDb3Vwb25cIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJy5jb3Vwb24nKTtcblx0XHR2YXIgbmFtZSA9ICR0aGlzLmF0dHIoJ25hbWUnKTtcblx0XHQoZnVuY3Rpb24oKXtcblx0XHRcdCRjb250YWluZXIubG9hZGluZyh7XG5cdFx0XHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiB1dGlsLmFqYXhVcmwoVXJscy5vbmVQYWdlU3VibWl0KSxcblx0XHRcdFx0ZGF0YTogJCgnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0nKS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lICsgJyZyZXNwVHlwZT1qc29uJ1xuXHRcdFx0fSkpO1xuXHRcdH0oKSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnLm9yZGVyLXRvdGFsLXBheW1lbnRzIFtwYXltZW50LW1ldGhvZF0gLnJlbW92ZScpLm9uKCdjbGljaycsICcub3JkZXItdG90YWwtcGF5bWVudHMgW3BheW1lbnQtbWV0aG9kXSAucmVtb3ZlJywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgcGF5bWVudEluc3RydW1lbnRVVUlEID0gJChlLmN1cnJlbnRUYXJnZXQpLmNsb3Nlc3QoJ1twYXltZW50LW1ldGhvZCcpLmF0dHIoJ3V1aWQnKTtcblx0XG5cdFx0aWYgKHBheW1lbnRJbnN0cnVtZW50VVVJRCkge1xuXHRcdFx0dmFyIHJlcXVlc3RQYXlsb2FkID0ge1xuXHRcdFx0XHRVVUlEOiBwYXltZW50SW5zdHJ1bWVudFVVSURcblx0XHRcdH1cblx0XHRcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHVybDogVXJscy5yZW1vdmVQYXltZW50SW5zdHJ1bWVudCxcblx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShyZXF1ZXN0UGF5bG9hZCksXG5cdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRsb2NhdGlvbi5yZWxvYWQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ0NhcnQuVXBkYXRlJykub24oJ0NhcnQuVXBkYXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG4gICAgXHR1cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnLCBkYXRhKTtcbiAgICB9KTtcblxuXHRzZWFyY2hSZXdhcmRzKCk7XG5cdHVwZGF0ZUNhcnQoJ2R3ZnJtX2NhcnRfdXBkYXRlQ2FydCcpO1xufVxuXG52YXIgdXBkYXRlQ2FydEJ1ZmZlcjtcbnZhciB1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXI7XG5mdW5jdGlvbiB1cGRhdGVDYXJ0KHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHRpZiAodXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyKSB7XG5cdFx0Zm9yICh2YXIgdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0S2V5IGluIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlcikge1xuXHRcdFx0dmFyIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdCA9IHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclt1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RLZXldO1xuXHRcdFx0XG5cdFx0XHRpZiAodXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0LnJlYWR5U3RhdGUgIT09IDQpIHsgXG5cdFx0XHRcdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdC5hYm9ydCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXIgPSBbXTtcblx0dXBkYXRlQ2FydEJ1ZmZlciA9IFtdO1xuXG5cdGdldENhcnRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdGlmICghaXNDYXJ0UGFnZSkge1xuXHRcdGdldE9yZGVyU3VtbWFyeUNhbGxvdXRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gZ2V0Q2FydEh0bWwodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKSB7XG4gICAgdmFyICRmb3JtID0gJCgnI2NoZWNrb3V0LWZvcm0nKTtcbiAgICB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gPSBudWxsO1xuXG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0Q2FydEh0bWwnXSA9ICQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLm9uZVBhZ2VTdWJtaXQsXG5cdFx0dHlwZTogXCJQT1NUXCIsXG5cdFx0ZGF0YTogdHJpZ2dlckVsZW1lbnROYW1lICsgJz0nICsgdHJpZ2dlckVsZW1lbnROYW1lICsgJyZzZWxlY3RlZFBheW1lbnRNZXRob2Q9JyArICQoJ2lucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCkgKyAnJmZvcm1hdD1hamF4Jyxcblx0XHRzdWNjZXNzIDogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnQnXSA9IGRhdGE7XG5cdFx0XHRnZXRDYXJ0RGF0YSh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHRcdFx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldE9yZGVyU3VtbWFyeUNhbGxvdXRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuICAgIHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSA9IG51bGw7XG5cblx0dXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyWydnZXRPcmRlclN1bW1hcnlDYWxsb3V0SHRtbCddID0gJC5hamF4KHtcblx0XHR1cmw6IFVybHMuZ2V0T3JkZXJTdW1tYXJ5Q2FsbG91dENvbnRlbnRTbG90LFxuXHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0c3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSA9IGRhdGE7XG5cdFx0XHR1cGRhdGVDYXJ0UmVuZGVyKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2FydERhdGEodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gPSBudWxsO1xuXG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0Q2FydERhdGEnXSA9ICQuYWpheCh7XG5cdCAgICB1cmwgOiBVcmxzLmdldENhcnREYXRhLFxuXHRcdHR5cGUgOiBcIlBPU1RcIixcblx0XHRkYXRhOiB7XG5cdFx0XHRpc0NhcnQ6IGlzQ2FydFBhZ2Vcblx0XHR9LFxuXHQgICAgc3VjY2VzcyA6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdCAgICBcdCQoJ1toYXMtbG9jYWwtZGVsaXZlcnktc2hpcG1lbnRdJykuYXR0cignaGFzLWxvY2FsLWRlbGl2ZXJ5LXNoaXBtZW50JywgZGF0YS5IYXNMb2NhbERlbGl2ZXJ5U2hpcG1lbnQgfHwgZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLXBoeXNpY2FsLXNoaXBtZW50XScpLmF0dHIoJ2hhcy1waHlzaWNhbC1zaGlwbWVudCcsIGRhdGEuSGFzUGh5c2ljYWxTaGlwbWVudCB8fCBmYWxzZSk7XG5cdFx0XHQkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtd2FyZWhvdXNlLXNoaXBtZW50JywgZGF0YS5IYXNXYXJlaG91c2VTaGlwbWVudCB8fCBmYWxzZSk7XG5cdFx0XHQkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtc2hpcHBpbmctbWV0aG9kcycsIGRhdGEuU2hpcHBpbmdNZXRob2RzID8gZGF0YS5TaGlwcGluZ01ldGhvZHMuam9pbignICcpIDogZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLWdpZnQtY2FyZHNdJykuYXR0cignaGFzLWdpZnQtY2FyZHMnLCBkYXRhLkhhc0dpZnRDYXJkcyB8fCBmYWxzZSk7XG5cdCAgICBcdCQoJ1toYXMtZ2lmdC1jYXJkcy1vbmx5XScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzLW9ubHknLCBkYXRhLkhhc0dpZnRDYXJkc09ubHkgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnRdJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudCcsIChkYXRhLkJvcGlzICYmIGRhdGEuQm9waXMuSGFzU3RvcmVQaWNrdXBTaGlwbWVudCkgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQtb25seV0nKS5hdHRyKCdoYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHknLCAoZGF0YS5Cb3BpcyAmJiBkYXRhLkJvcGlzLkhhc1N0b3JlUGlja3VwU2hpcG1lbnRPbmx5KSB8fCBmYWxzZSk7XG5cdCAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnREYXRhLlVwZGF0ZScsIGRhdGEpO1xuXG5cdCAgICBcdHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gPSBkYXRhO1xuXHQgICAgXHRpZiAoZGF0YS5Cb3Bpcykge1xuXHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ0JvcGlzJ10gPSBkYXRhLkJvcGlzO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHRpZiAoIWRhdGEuSXNHbG9iYWxlVmFsaWRPckluYWN0aXZlKSB7XG5cdCAgICBcdFx0JCgnLnNlY3Rpb24tY2hlY2tvdXQnKS5hZGRDbGFzcygnZ2xvYmFsLWUtdmFsaWRhdGlvbi1lcnJvcicpO1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykuZmluZCgnLmNhcnQtZXJyb3JzJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykucmVtb3ZlQ2xhc3MoJ2dsb2JhbC1lLXZhbGlkYXRpb24tZXJyb3InKTtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLmZpbmQoJy5jYXJ0LWVycm9ycycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0ICAgIFx0fVxuXG5cdCAgICBcdGlmIChkYXRhLlNoaXBwaW5nUmVzdHJpY3Rpb25zICYmIGRhdGEuU2hpcHBpbmdSZXN0cmljdGlvbnMuU3RhdHVzID09ICdzaGlwcGluZ1Jlc3RyaWN0aW9uc0Vycm9yJykge1xuXHRcdFx0XHRpZiAoaXNDYXJ0UGFnZSkge1xuXHRcdFx0XHRcdCQoJy5vcGNsb2dpbi1idXR0b25zJykuYWRkQ2xhc3MoJ2hpZGUnKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2RzLXNlY3Rpb24nKS5oaWRlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmIChpc0NhcnRQYWdlKSB7XG5cdFx0XHRcdFx0JCgnLm9wY2xvZ2luLWJ1dHRvbnMnKS5yZW1vdmVDbGFzcygnaGlkZScpO1xuXHRcdFx0XHRcdCQoJy5ndWVzdC1jaGVja291dCAuZXJyb3ItZm9ybScpLnJlbW92ZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZHMtc2VjdGlvbicpLnNob3coKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aGFuZGxlT3JkZXJUb3RhbCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHQgICAgfVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlT3JkZXJUb3RhbCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcblx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gPSBudWxsO1xuXHR2YXIgcmVtb3ZlQWN0aW9uID0gJzxhIGNsYXNzPVwicmVtb3ZlXCI+UmVtb3ZlPC9hPic7XG5cdFxuXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gPSAnJztcblx0XG5cdFx0Zm9yICh2YXIgcGF5bWVudEluc3RydW1lbnRLZXkgaW4gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cykge1xuXHRcdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50ID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50c1twYXltZW50SW5zdHJ1bWVudEtleV07XG5cdFx0XHR2YXIgcGF5bWVudEluc3RydW1lbnRVVUlEQXR0cmlidXRlID0gJ3V1aWQ9XCInICsgcGF5bWVudEluc3RydW1lbnQuVVVJRCArICdcIic7XG5cdFx0XHRcblx0XHRcdHN3aXRjaCAocGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCkge1xuXHRcdFx0XHRjYXNlIFBheW1lbnRNZXRob2RDb25zdGFudHMuUmV3YXJkc0NyZWRpdDpcblx0XHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddICs9ICc8ZGl2ICcgKyBwYXltZW50SW5zdHJ1bWVudFVVSURBdHRyaWJ1dGUgKyAnIHBheW1lbnQtbWV0aG9kPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuSWQgKyAnXCIgYWxsb3ctcmVtb3ZlPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LmFsbG93UmVtb3ZlICsgJ1wiPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPjxzcGFuIGNsYXNzPVwibmFtZVwiPkIgUmV3YXJkZWQ8L3NwYW4+Jm5ic3A7PHNwYW4gY2xhc3M9XCJudW1iZXJcIj5SZXdhcmQ8L3NwYW4+PC9zcGFuPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiPicgKyBwYXltZW50SW5zdHJ1bWVudC5hbW91bnREaXNwbGF5ICsgJzwvc3Bhbj4nICtcblx0XHQgICAgXHRcdCc8L2Rpdj4nO1xuXHRcdCAgICBcdGJyZWFrO1xuXHRcdFx0XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0ICAgIFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSArPSAnPGRpdiAnICsgcGF5bWVudEluc3RydW1lbnRVVUlEQXR0cmlidXRlICsgJyBwYXltZW50LW1ldGhvZD1cIicgKyBwYXltZW50SW5zdHJ1bWVudC5wYXltZW50TWV0aG9kLklkICsgJ1wiIGFsbG93LXJlbW92ZT1cIicgKyBwYXltZW50SW5zdHJ1bWVudC5hbGxvd1JlbW92ZSArICdcIj4nICtcblx0XHQgICAgXHRcdFx0JzxzcGFuIGNsYXNzPVwibGFiZWxcIj48c3BhbiBjbGFzcz1cIm5hbWVcIj4nICsgcGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5OYW1lICsgJzwvc3Bhbj4mbmJzcDs8c3BhbiBjbGFzcz1cIm51bWJlclwiPicgKyBwYXltZW50SW5zdHJ1bWVudC5udW1iZXJMYXN0Rm91ciArICc8L3NwYW4+JyArIHJlbW92ZUFjdGlvbiArICc8L3NwYW4+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LmFtb3VudERpc3BsYXkgKyAnPC9zcGFuPicgK1xuXHRcdCAgICBcdFx0JzwvZGl2Pic7XG5cdFx0ICAgIFx0YnJlYWs7XG5cdFx0ICAgIH1cblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignR2lmdENhcmQuQ2xlYXInKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdSZXdhcmRzQ3JlZGl0LkNsZWFyJyk7XG5cdH1cblx0XG5cdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA8IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC50b3RhbCkge1xuXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10gPSAnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPkJhbGFuY2UgRHVlPC9zcGFuPicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwidmFsdWVcIj4nICsgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2VEaXNwbGF5ICsgJzwvc3Bhbj4nO1xuXHR9XG5cdFxuXHR1cGRhdGVDYXJ0UmVuZGVyKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNhcnRSZW5kZXIodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gJiYgKGlzQ2FydFBhZ2UgfHwgKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSAmJiB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddKSkpIHtcblx0XHR2YXIgJGJhc2tldENvbnRhaW5lckh0bWwgPSAkKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnQnXSk7XG5cdFxuXHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbCkge1xuXHRcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFsLXByaWNlIC52YWx1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnRvdGFsRGlzcGxheSk7XG5cdCAgICBcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLXRvdGFsLXByaWNlIC52YWx1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnRvdGFsRGlzcGxheSk7XG5cdFx0XG5cdFx0XHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5hdHRyKCdwYXltZW50cy1hcHBsaWVkJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGgpO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hdHRyKCdwYXltZW50cy1hcHBsaWVkJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGgpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5yZW1vdmVBdHRyKCdwYXltZW50cy1hcHBsaWVkJyk7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUF0dHIoJ3BheW1lbnRzLWFwcGxpZWQnKTtcblx0ICAgIFx0fVxuXHRcdFxuXHRcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFscy10YWJsZScpLmF0dHIoJ2JhbGFuY2UtZHVlJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UpO1xuXHRcdFx0JCgnI3dyYXBwZXInKS5hdHRyKCdiYWxhbmNlLWR1ZScsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlKTtcblx0ICAgIFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmF0dHIoJ2JhbGFuY2UtZHVlJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UpO1xuXHRcdFxuXHRcdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlID4gMCkge1xuXHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2Qtb3B0aW9ucycpLnNob3coKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbi1mb290ZXJbZGF0YS1tZXRob2Q9XCJQYXlQYWxcIl0gYnV0dG9uJykuaGlkZSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbnMnKS5oaWRlKCk7XG5cdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24tZm9vdGVyW2RhdGEtbWV0aG9kPVwiUGF5UGFsXCJdIGJ1dHRvbicpLnNob3coKTtcblx0XHRcdH1cblx0XHRcblx0ICAgIFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10pIHtcdFxuXHQgICAgXHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci1iYWxhbmNlLWR1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQmFsYW5jZUR1ZUh0bWwnXSk7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItYmFsYW5jZS1kdWUnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10pOyAgICBcdFx0XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItYmFsYW5jZS1kdWUnKS5odG1sKCcnKTtcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddKSB7XG5cdCAgICBcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFsLXBheW1lbnRzJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSk7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItdG90YWwtcGF5bWVudHMnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uIC5vcmRlci10b3RhbC1wYXltZW50cycpLmh0bWwoJycpO1xuXHQgICAgXHR9XG5cdFx0fVxuXG5cdFx0JCgnLmFjY29yZGlvbi5jb3Vwb24gLmNhcnQtY291cG9uLWNvZGUnKS5odG1sKCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5jYXJ0LWNvdXBvbi1jb2RlJykuZmlyc3QoKS5odG1sKCkpO1xuXHRcdCQoJy5iYXNrZXQtY29udGFpbmVyJykuaHRtbCgkYmFza2V0Q29udGFpbmVySHRtbCk7XG5cdFx0XG5cdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10pIHtcblx0XHRcdHZhciBvcmRlclRvdGFsRm9yQWZmaXJtID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2U7XG5cdFx0XHRpZiAoIW9yZGVyVG90YWxGb3JBZmZpcm0gJiYgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlKSB7XG5cdFx0XHRcdG9yZGVyVG90YWxGb3JBZmZpcm0gPSB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYWRqdXN0ZWRNZXJjaGFuZGl6ZVRvdGFsUHJpY2U7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmICgnYWZmaXJtJyBpbiB3aW5kb3cgJiYgJ3VpJyBpbiBhZmZpcm0gJiYgJ3JlZnJlc2gnIGluIGFmZmlybS51aSAmJiBvcmRlclRvdGFsRm9yQWZmaXJtID49IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uQWZmaXJtTWluaW11bU9yZGVyVG90YWwpIHtcblx0XHRcdFx0JCgnLmFmZmlybS1wcm9kdWN0LW1vZGFsJykuYXR0cignZGF0YS1hbW91bnQnLCBvcmRlclRvdGFsRm9yQWZmaXJtICogMTAwKTtcblx0XHRcdFx0YWZmaXJtLnVpLnJlZnJlc2goKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoJy5hZmZpcm0tcHJvZHVjdC1tb2RhbCcpLmF0dHIoJ2RhdGEtYW1vdW50JywgNTAwMCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCQoJy5iYXNrZXQtY29udGFpbmVyJykuZmluZCgnLnByb2R1Y3QtYXZhaWxhYmlsaXR5LWxpc3QgLm5vdC1hdmFpbGFibGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCwgI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdFx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCcpLmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+JyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLlByb2R1Y3RzLkF2YWlsYWJpbGl0eSArICc6PC9iPiAnICsgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuUHJvZHVjdHMuQXZhaWxhYmlsaXR5RXhjZWVkZWQgKyAnPC9kaXY+Jyk7XG5cdFx0fSBlbHNlIGlmICh1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0JvcGlzJ10uTnVtYmVyT2ZCb3Bpc1N0b3Jlc0luQ2FydCA+IHVwZGF0ZUNhcnRCdWZmZXJbJ0JvcGlzJ10uTWF4aW11bU51bWJlck9mQm9waXNTdG9yZXNJbkNhcnQpIHtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50LCAjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG5cdFx0XHQkKCcjZXJyb3JCb3hPUEMnKS5yZW1vdmUoKTtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50JykuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj4nICsgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuR2VuZXJhbC5DYXJ0TGltaXQgKyAnOjwvYj4gJyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkJvcGlzLk1heGltdW1TdG9yZXNFeGNlZWRlZCArICc8L2Rpdj4nKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQsICNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHRcdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnT3JkZXJTdW1tYXJ5Q2FsbG91dCddKSB7XHRcblx0XHRcdCQoJy5jYWxsb3V0LW9yZGVyc3VtbWFyeScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnT3JkZXJTdW1tYXJ5Q2FsbG91dCddKTtcblx0XHR9XG5cblx0ICAgIGlmICgkKCcuYmFubmVyLWNhcnQtaG9sZGVyIC5idG4tbWluaWNhcnQnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkLmFqYXgoe3VybCA6IFVybHMuY2FydE1pbmlDYXJ0LCBkYXRhIDoge2Rlc2t0b3A6ICcxJ30sIGRhdGFUeXBlOiAnaHRtbCcsIHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdCAgICAgICAgICAgICQoJy5iYW5uZXItY2FydC1ob2xkZXInKS5odG1sKGRhdGEpO1xuXHQgICAgICAgIH19KTtcblx0XHRcdFxuXHQgICAgXHQkLmFqYXgoe3VybCA6IFVybHMuY2FydE1pbmlDYXJ0LCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHQgICAgXHRcdHZhciBwYXJlbnRNaW5pQ2FydCA9ICQoXCIudG9wLWJhbm5lci1pbm5lci1saW5rcyAjbWluaS1jYXJ0XCIpO1xuXHQgICAgXHRcdFxuXHQgICAgXHRcdGlmIChwYXJlbnRNaW5pQ2FydC5sZW5ndGggPiAwKSB7XG5cdCAgICBcdFx0XHRwYXJlbnRNaW5pQ2FydC5odG1sKGRhdGEpO1xuXHQgICAgXHRcdH1cblx0ICAgICAgICB9fSk7XG5cdFx0fVxuXHQgICAgXG4gICAgICAgICQuYWpheCh7dXJsOiBVcmxzLmNhcnRJdGVtUXVhbnRpdHksIGRhdGE6IHtkZXNrdG9wOiAnMSd9LCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBcdCQoJy5jb25maXJtYXRpb24tbWVzc2FnZSAuaXRlbS1jb3VudCcpLmh0bWwoZGF0YSk7XG5cdCAgICAgICAgXG5cdCAgICAgICAgdmFyIHF1YW50aXR5ID0gcGFyc2VJbnQoJCgnLmNvbmZpcm1hdGlvbi1tZXNzYWdlIC5pdGVtLWNvdW50JykuZmluZCgnc3BhbicpLnRleHQoKSwgMTApO1xuXHQgICAgICAgIGlmICghcXVhbnRpdHkpIHtcblx0ICAgICAgICAgICAgJCgnLmNoZWNrb3V0LWJ1dHRvbnMubW9iaWxlLW9ubHknKS5oaWRlKCk7XHQgICAgICAgICAgICBcblx0XHRcdH1cblx0XHR9fSk7XG5cdFx0XG5cdCAgICBcblx0ICAgIGlmICh0cmlnZ2VyRWxlbWVudE5hbWUuaW5kZXhPZignZGVsZXRlUHJvZHVjdCcpID4gLTEpIHtcblx0ICAgIFx0JChkb2N1bWVudCkudHJpZ2dlcigncmVmcmVzaC1yZXF1aXJlZCcpO1xuXHQgICAgfVxuXG5cdFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLkV2ZW50VHJpZ2dlcnMgfHwgb3B0aW9ucy5FdmVudFRyaWdnZXJzWyd1cGRhdGUtc3VtbWFyeSddKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCd1cGRhdGUtc3VtbWFyeScpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuRXZlbnRUcmlnZ2VycyB8fCBvcHRpb25zLkV2ZW50VHJpZ2dlcnNbJ3VwZGF0ZS1zaGlwcGluZyddKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCd1cGRhdGUtc2hpcHBpbmcnKTtcblx0XHR9XG5cdCAgICBcblx0ICAgICQoJ1ttaW5pbXVtLWNhcnQtdG90YWxdLCBbbWF4aW11bS1jYXJ0LXRvdGFsXScpLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0ICAgIFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0ICAgIFx0dmFyIHBheW1lbnRNZXRob2RDYXJ0VG90YWxNaW5pbXVtID0gcGFyc2VGbG9hdCgkdGhpcy5hdHRyKCdtaW5pbXVtLWNhcnQtdG90YWwnKSk7XG5cdCAgICBcdHZhciBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWF4aW11bSA9IHBhcnNlRmxvYXQoJHRoaXMuYXR0cignbWF4aW11bS1jYXJ0LXRvdGFsJykpO1xuXHQgICAgXG5cdCAgICBcdHZhciBpc0NhcnRUb3RhbE1pbmltdW1WYWxpZCA9IGZhbHNlO1xuXHQgICAgXHRpZiAoaXNOYU4ocGF5bWVudE1ldGhvZENhcnRUb3RhbE1pbmltdW0pIHx8IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlID49IHBheW1lbnRNZXRob2RDYXJ0VG90YWxNaW5pbXVtKSB7XG5cdCAgICBcdFx0aXNDYXJ0VG90YWxNaW5pbXVtVmFsaWQgPSB0cnVlO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHR2YXIgaXNDYXJ0VG90YWxNYXhpbXVtVmFsaWQgPSBmYWxzZTtcblx0ICAgIFx0aWYgKGlzTmFOKHBheW1lbnRNZXRob2RDYXJ0VG90YWxNYXhpbXVtKSB8fCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA8PSBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWF4aW11bSkge1xuXHQgICAgXHRcdGlzQ2FydFRvdGFsTWF4aW11bVZhbGlkID0gdHJ1ZTtcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aWYgKGlzQ2FydFRvdGFsTWluaW11bVZhbGlkICYmIGlzQ2FydFRvdGFsTWF4aW11bVZhbGlkKSB7XG5cdCAgICBcdFx0JHRoaXMuY2xvc2VzdCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbicpLmF0dHIoJ3ZhbGlkLWZvci1iYWxhbmNlLWR1ZScsICd0cnVlJyk7XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0JHRoaXMuY2xvc2VzdCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbicpLmF0dHIoJ3ZhbGlkLWZvci1iYWxhbmNlLWR1ZScsICdmYWxzZScpO1xuXHQgICAgXHR9XG5cdCAgICB9KTtcblx0XHRcblx0ICAgIGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddICYmICF1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLkhhc1BoeXNpY2FsU2hpcG1lbnQgJiYgJCgnLnNpbmdsZS5zaGlwcGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXQ6Y2hlY2tlZCcpLnZhbCgpICE9IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyKSB7XG5cdCAgICBcdCQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0W3ZhbHVlPVwiJyArIFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyICsgJ1wiXScpLmNsaWNrKCk7XG5cdCAgICB9XG5cdFx0XG5cdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdGl0ZW1zOiAnLnNoaXBwaW5nLW1ldGhvZC10b29sdGlwJyxcblx0XHRcdHRvb2x0aXBDbGFzczogJ3NoaXBwaW5nLW1ldGhvZC10b29sdGlwJ1xuXHRcdH0sICQoJ1tzaGlwcGluZy1tZXRob2RdJykpO1xuXG5cdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdGl0ZW1zOiAnLnRvb2x0aXAnXG5cdFx0fSk7XG5cblx0XHR0cmlnZ2VyU3JGb2N1cygpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1F1YW50aXR5U3RlcHBlci5UYXJnZXRGb2N1cycpO1xuXHQgICAgJChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGVTdWNjZXNzJyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJpZ2dlclNyRm9jdXMoKSB7XG5cdCQoJ1tyb2xlPVwiYWxlcnRcIl0nKS5sYXN0KCkuZm9jdXMoKTtcbn1cblxuZnVuY3Rpb24gc3VibWl0UGF5bWVudChkYXRhKSB7XG5cdCRzdWJtaXRQYXltZW50LmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2UsXG5cdFx0TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkNoZWNrb3V0LlBsYWNpbmdPcmRlclxuXHR9KTtcblx0JHN1Ym1pdFBheW1lbnQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cblx0JGNoZWNrb3V0Rm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcdFxuXHQkY2hlY2tvdXRGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdFxuXHRpZiAoJGNoZWNrb3V0Rm9ybS52YWxpZCgpKSB7XG5cdFx0c2V0T1BDUGF5bWVudERhdGEoJGNoZWNrb3V0Rm9ybSwgJHN1Ym1pdFBheW1lbnQuYXR0cignbmFtZScpKS50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0ZGF0YSA9IHJlc3BvbnNlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdzdWNjZXNzJykge1xuXHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdhZmZpcm1SZWRpcmVjdCcpIHtcblx0XHRcdFx0dmFyIF9hZmZpcm1fY29uZmlnID0ge1xuXHRcdFx0XHRcdHB1YmxpY19hcGlfa2V5OiBkYXRhLmFmZmlybS5QdWJsaWNBcGlLZXksXG5cdFx0XHRcdFx0c2NyaXB0OiBkYXRhLmFmZmlybS5TY3JpcHRcblx0XHRcdFx0fTtcblx0XHRcdFx0KGZ1bmN0aW9uKGwsZyxtLGUsYSxmLGIpe3ZhciBkLGM9bFttXXx8e30saD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KGYpLG49ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZilbMF0saz1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGZ1bmN0aW9uKCl7YVtiXS5fLnB1c2goW2MsYXJndW1lbnRzXSl9fTtjW2VdPWsoYyxlLFwic2V0XCIpO2Q9Y1tlXTtjW2FdPXt9O2NbYV0uXz1bXTtkLl89W107Y1thXVtiXT1rKGMsYSxiKTthPTA7Zm9yKGI9XCJzZXQgYWRkIHNhdmUgcG9zdCBvcGVuIGVtcHR5IHJlc2V0IG9uIG9mZiB0cmlnZ2VyIHJlYWR5IHNldFByb2R1Y3RcIi5zcGxpdChcIiBcIik7YTxiLmxlbmd0aDthKyspZFtiW2FdXT1rKGMsZSxiW2FdKTthPTA7Zm9yKGI9W1wiZ2V0XCIsXCJ0b2tlblwiLFwidXJsXCIsXCJpdGVtc1wiXTthPGIubGVuZ3RoO2ErKylkW2JbYV1dPWZ1bmN0aW9uKCl7fTtoLmFzeW5jPSEwO2guc3JjPWdbZl07bi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShoLG4pO2RlbGV0ZSBnW2ZdO2QoZyk7bFttXT1jfSkod2luZG93LF9hZmZpcm1fY29uZmlnLFwiYWZmaXJtXCIsXCJjaGVja291dFwiLFwidWlcIixcInNjcmlwdFwiLFwicmVhZHlcIik7XG5cdFx0XHRcdFxuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQoSlNPTi5wYXJzZShkYXRhLmFmZmlybS5BZmZpcm1DaGVja291dCkpO1xuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQucG9zdCgpO1xuXHRcdFx0XHRhZmZpcm0udWkucmVhZHkoXG5cdFx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRhZmZpcm0udWkuZXJyb3Iub24oXCJjbG9zZVwiLCBmdW5jdGlvbigpe1xuXHRcdFx0XHRcdFx0XHQvLyB3aW5kb3cubG9jYXRpb24ucmVwbGFjZShkYXRhLmFmZmlybS5SZWRpcmVjdFVybCk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpe1xuXHRcdFx0XHR2YXIgcG9wdXAgPSByZXF1aXJlKCcuLi9wb3B1cCcpO1xuXHRcdFx0XHR2YXIgcGF5bG9hZCA9IEpTT04ucGFyc2UoZGF0YS5wYXlsb2FkKTtcblxuXHRcdFx0XHR2YXIgbGlzdCA9ICQubWFwKHBheWxvYWQubGlzdCwgZnVuY3Rpb24gKGVsKSB7XG5cdFx0XHRcdFx0cmV0dXJuICc8bGk+JyArIGVsLm5hbWUgKyAnOjxicj4nICsgZWwubWVzc2FnZSArICc8L2xpPic7XG5cdFx0XHRcdH0pLmpvaW4oJycpO1xuXHRcdFx0XHRcblx0XHRcdFx0cG9wdXAuaW5pdCh7XG5cdFx0XHRcdFx0dGl0bGU6IHBheWxvYWQudGl0bGUsXG5cdFx0XHRcdFx0Y29udGVudDogcGF5bG9hZC5tZXNzYWdlICsgJzx1bCBjbGFzcz1cInNoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cF9fbGlzdFwiPicgKyBsaXN0ICsgJzwvdWw+Jyxcblx0XHRcdFx0fSkuc2hvd1BvcHVwKCk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnVmFsaWRhdGlvbkVycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5WYWxpZGF0aW9uIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5QYXltZW50IERlY2xpbmVkOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCRzdWJtaXRQYXltZW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdCRzdWJtaXRQYXltZW50LmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRpZiAocmVzcG9uc2Uuc3RhdHVzID09IDMwMiAmJiByZXNwb25zZS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IHJlc3BvbnNlLnJlc3BvbnNlVGV4dDtcblx0XHRcdH1cblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0JHN1Ym1pdFBheW1lbnQuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdH1cbn1cblxudmFyIHNldE9QQ1BheW1lbnREYXRhID0gZnVuY3Rpb24gKCRmb3JtLCBuYW1lKSB7XG5cdHZhciBwYXlsb2FkID0gJGZvcm0uc2VyaWFsaXplKCkgKyAnJicgKyBuYW1lICsgJz0nICsgbmFtZTtcblx0dmFyICRjaGVja291dFZhcmlhYmxlcyA9ICQoJy5idXR0b24tYW5kLXRlcm1zIGlucHV0W3R5cGU9XCJoaWRkZW5cIl0nKTtcblx0JGNoZWNrb3V0VmFyaWFibGVzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRwYXlsb2FkICs9ICcmJyArICR0aGlzLmF0dHIoJ25hbWUnKSArICc9JyArICR0aGlzLnZhbCgpO1xuXHR9KTtcblxuICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5zZXRPcGNBZGRyZXNzKSxcbiAgICAgICAgZGF0YTogcGF5bG9hZFxuICAgIH0pKTtcbn07XG5cbmZ1bmN0aW9uIHNlYXJjaFJld2FyZHMoKSB7XG5cdGlmIChkYXRhQnVmZmVyWydSZXdhcmRzQWNjb3VudFNlYXJjaFJlcXVlc3QnXSAmJiBkYXRhQnVmZmVyWydSZXdhcmRzQWNjb3VudFNlYXJjaFJlcXVlc3QnXS5yZWFkeVN0YXRlICE9PSA0KSB7XG5cdFx0ZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10uYWJvcnQoKTtcblx0XHRkYXRhQnVmZmVyWydSZXdhcmRzQWNjb3VudFNlYXJjaFJlcXVlc3QnXSA9IG51bGw7XG5cdH1cblx0JHJld2FyZHNBcHBsaWVkLmh0bWwoJycpO1xuXG5cdHZhciBwYXlsb2FkID0ge1xuXHRcdEVtYWlsQWRkcmVzczogJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc0VtYWlsJykudmFsKCksXG5cdFx0UGhvbmVOdW1iZXI6ICRyZXdhcmRzRm9ybS5maW5kKCcuZmllbGQucGhvbmVudW1iZXInKS52YWwoKSxcblx0XHRaaXBDb2RlOiAkcmV3YXJkc0Zvcm0uZmluZCgnLmZpZWxkLnppcGNvZGUnKS52YWwoKSxcblx0fVxuXG5cdGlmICgkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKCkpIHtcblx0XHRwYXlsb2FkLlJld2FyZHNOdW1iZXIgPSAkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKCk7XG5cdH1cblxuXHQkKCcuYnRuLnNlYXJjaC1lY2hvJykubG9hZGluZyh7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fSk7XG5cblx0ZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10gPSAkLmFqYXgoe1xuXHRcdHR5cGU6ICdQT1NUJyxcblx0XHR1cmw6IFVybHMuc2VhcmNoRm9yUmV3YXJkcyxcblx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksXG5cdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0cmVuZGVyUmV3YXJkc0RhdGEoZGF0YSk7XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cdFx0XHRpZiAoJCgnLmJ0bi5zZWFyY2gtZWNobycpLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHQkKCcuYnRuLnNlYXJjaC1lY2hvJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJld2FyZHNEYXRhKGRhdGEpIHtcblx0aWYgKGRhdGEuTWF0Y2ggJiYgZGF0YS5SZXdhcmRzKSB7XG5cdFx0aWYgKGRhdGEuUmV3YXJkcy5yZXdhcmRzTnVtYmVyKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKGRhdGEuUmV3YXJkcy5yZXdhcmRzTnVtYmVyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgnJyk7XG5cdFx0fVxuXHRcdGlmIChkYXRhLlJld2FyZHMuZW1haWwpIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNFbWFpbCcpLnZhbChkYXRhLlJld2FyZHMuZW1haWwpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzRW1haWwnKS52YWwoJycpO1xuXHRcdH1cblx0XHRpZiAoZGF0YS5SZXdhcmRzLnBob25lKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmZpZWxkLnBob25lbnVtYmVyJykudmFsKGRhdGEuUmV3YXJkcy5waG9uZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuZmllbGQucGhvbmVudW1iZXInKS52YWwoJycpO1xuXHRcdH1cblx0XHRpZiAoZGF0YS5SZXdhcmRzLnppcFZhbHVlKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmZpZWxkLnppcGNvZGUnKS52YWwoZGF0YS5SZXdhcmRzLnppcFZhbHVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC56aXBjb2RlJykudmFsKCcnKTtcblx0XHR9XG5cblx0XHRpZiAoZGF0YS5NYXRjaC5SZXdhcmRzRW1haWwpIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcucmV3YXJkcy1lbWFpbC1jb250YWluZXInKS5hdHRyKCdtYXRjaCcsICd0cnVlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcucmV3YXJkcy1lbWFpbC1jb250YWluZXInKS5hdHRyKCdtYXRjaCcsICdmYWxzZScpO1xuXHRcdH1cblx0XHRpZiAoZGF0YS5NYXRjaC5SZXdhcmRzUGhvbmUpIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuaW5wdXQtY29udGFpbmVyLnBob25lJykuYXR0cignbWF0Y2gnLCAndHJ1ZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmlucHV0LWNvbnRhaW5lci5waG9uZScpLmF0dHIoJ21hdGNoJywgJ2ZhbHNlJyk7XG5cdFx0fVxuXHRcdGlmIChkYXRhLk1hdGNoLlJld2FyZHNaaXApIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuaW5wdXQtY29udGFpbmVyLnppcCcpLmF0dHIoJ21hdGNoJywgJ3RydWUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5pbnB1dC1jb250YWluZXIuemlwJykuYXR0cignbWF0Y2gnLCAnZmFsc2UnKTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIHJld2FyZHNSb3dUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXJld2FyZHMtY3JlZGl0LXJvdy1lY2hvJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRcdHZhciBzdGF0dXMgPSAnJztcblx0XHR2YXIgbWVzc2FnZSA9ICcnO1xuXHRcdGlmIChwYXJzZUZsb2F0KGRhdGEuUmV3YXJkcy5jcmVkaXRBbW91bnQpIDw9IDApIHtcblx0XHRcdHN0YXR1cyA9ICdtZXNzYWdlJztcblx0XHRcdG1lc3NhZ2UgPSAnbm8gcmV3YXJkcyBhdmFpbGFibGUnO1xuXHRcdH0gZWxzZSBpZiAoJHJld2FyZHNGb3JtLmNsb3Nlc3QoJ1tpcy1hcHBsaWVkXScpLmF0dHIoJ2lzLWFwcGxpZWQnKSA9PSAndHJ1ZScpIHtcblx0XHRcdHN0YXR1cyA9ICdhcHBsaWVkJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0c3RhdHVzID0gJ3BlbmRpbmcnO1xuXHRcdH1cblxuXHRcdHZhciBhZGRpdGlvbmFsRGF0YSA9ICc8dGFibGUgY2xhc3M9XCJyZXdhcmRzLWluZm9ybWF0aW9uXCI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+QWRkcmVzczwvdGQ+PHRkPicgKyBkYXRhLlJld2FyZHMuYWRkcmVzcyArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+Q2l0eTwvdGQ+PHRkPicgKyBkYXRhLlJld2FyZHMuY2l0eSArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+U3RhdGU8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLnN0YXRlICsgJzwvdGQ+PC90cj4nICtcblx0XHRcdFx0XHRcdFx0XHQnPHRyPjx0ZD5aaXA8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLnppcFZhbHVlICsgJzwvdGQ+PC90cj4nICtcblx0XHRcdFx0XHRcdFx0XHQnPHRyPjx0ZD5Db3VudHJ5PC90ZD48dGQ+JyArIGRhdGEuUmV3YXJkcy5jb3VudHJ5ICsgJzwvdGQ+PC90cj4nICtcblx0XHRcdFx0XHRcdFx0XHQnPHRyPjx0ZD5QaG9uZTwvdGQ+PHRkPicgKyBkYXRhLlJld2FyZHMucGhvbmUgKyAnPC90ZD48L3RyPicgK1xuXHRcdFx0XHRcdFx0XHQnPC90YWJsZT48dGFibGUgY2xhc3M9XCJyZXdhcmRzLXBvaW50c1wiPicgK1xuXHRcdFx0XHRcdFx0XHRcdCc8dHI+PHRkPlBvaW50czwvdGQ+PHRkPicgKyBkYXRhLlJld2FyZHMucG9pbnRCYWxhbmNlICsgJzwvdGQ+PC90cj4nICtcblx0XHRcdFx0XHRcdFx0JzwvdGFibGU+JztcblxuXHRcdCRyZXdhcmRzQXBwbGllZC5odG1sKHJld2FyZHNSb3dUZW1wbGF0ZSh7XG5cdFx0XHRTdGF0dXM6IHN0YXR1cyxcblx0XHRcdFJld2FyZHNOdW1iZXI6IGRhdGEuUmV3YXJkcy5yZXdhcmRzTnVtYmVyLFxuXHRcdFx0TmFtZTogZGF0YS5SZXdhcmRzLmZ1bGxOYW1lLFxuXHRcdFx0RW1haWw6IGRhdGEuUmV3YXJkcy5lbWFpbCxcblx0XHRcdFJld2FyZHNBdmFpbGFibGU6IGRhdGEuUmV3YXJkcy5jcmVkaXRBbW91bnRGb3JtYXR0ZWQucmVwbGFjZSgnLjAwJywgJycpLFxuXHRcdFx0UmV3YXJkc0V4cGlyYXRpb25EYXRlOiBkYXRhLlJld2FyZHMuY3JlZGl0RXhwaXJhdGlvbkRhdGUgfHwgJ24vYScsXG5cdFx0XHRNZXNzYWdlOiBtZXNzYWdlLFxuXHRcdFx0QWRkaXRpb25hbERhdGE6IGFkZGl0aW9uYWxEYXRhXG5cdFx0fSkpO1xuXHRcdGlmICgkcmV3YXJkc0FjY29yZGlvbi5maW5kKCdoZWFkZXIgLnJld2FyZHMtcG9pbnRzJykubGVuZ3RoKSB7XG5cdFx0XHQkcmV3YXJkc0FjY29yZGlvbi5maW5kKCdoZWFkZXIgLnJld2FyZHMtcG9pbnRzJykudGV4dChkYXRhLlJld2FyZHMucG9pbnRCYWxhbmNlKTtcblx0XHR9XG5cblx0XHQkcmV3YXJkc0FjY29yZGlvbi5hdHRyKCdyZXdhcmRzLWZvdW5kJywgJ3RydWUnKTtcblx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmJ0bi5yZXNldC1lY2hvJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHRpZiAoISQoJy5hY2NvcmRpb24ucmV3YXJkcyAuYWNjb3JkaW9uLWhlYWQnKS5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdCQoJy5hY2NvcmRpb24ucmV3YXJkcyAuYWNjb3JkaW9uLWhlYWQnKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdCRyZXdhcmRzQWNjb3JkaW9uLnJlbW92ZUF0dHIoJ3Jld2FyZHMtZm91bmQnKTtcblx0XHQkcmV3YXJkc0FwcGxpZWQuaHRtbCgnPHAgY2xhc3M9XCJuby1yZXN1bHRzXCI+bm8gcmV3YXJkcyBmb3VuZDwvcD4nKTtcblx0fVxufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvTG9iL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZycpO1xuXHR9XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0QWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL0xvYi9BZGRyZXNzQXV0b2NvbXBsZXRlL0FkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cnKTtcblx0fVxuXG5cdEdpZnRDYXJkLmluaXRpYWxpemUoJC5leHRlbmQoeyBMb2FkaW5nSW5kaWNhdG9yOiB7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fX0sIG9wdGlvbnMpKTtcblxuXHRSZXdhcmRzQ3JlZGl0LmluaXRpYWxpemUoJC5leHRlbmQoeyBMb2FkaW5nSW5kaWNhdG9yOiB7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fX0sIG9wdGlvbnMpKTtcblxuXHRBcHBsZVBheS5pbml0aWFsaXplKG9wdGlvbnMpO1xuXG4gICAgaW5pdGlhbGl6ZShvcHRpb25zKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRkUHJvZHVjdFRvQ2FydCA9IHJlcXVpcmUoJy4vcHJvZHVjdC9hZGRUb0NhcnQnKSxcbiAgICBhamF4ID0gcmVxdWlyZSgnLi4vYWpheCcpLFxuICAgIHBhZ2UgPSByZXF1aXJlKCcuLi9wYWdlJyksXG4gICAgcHJvZHVjdFRpbGUgPSByZXF1aXJlKCcuLi9wcm9kdWN0LXRpbGUnKSxcbiAgICBxdWlja3ZpZXcgPSByZXF1aXJlKCcuLi9xdWlja3ZpZXcnKTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGNsaWNrIGV2ZW50cyB0byB0aGUgcmVtb3ZlLWxpbmsgYW5kIHF1aWNrLXZpZXcgYnV0dG9uXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgJCgnI2NvbXBhcmUtdGFibGUnKS5vbignY2xpY2snLCAnLnJlbW92ZS1saW5rJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBhamF4LmdldEpzb24oe1xuICAgICAgICAgICAgdXJsOiB0aGlzLmhyZWYsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHBhZ2UucmVmcmVzaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnLm9wZW4tcXVpY2stdmlldycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHVybCA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3QnKS5maW5kKCcudGh1bWItbGluaycpLmF0dHIoJ2hyZWYnKTtcbiAgICAgICAgcXVpY2t2aWV3LnNob3coe1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBzb3VyY2U6ICdxdWlja3ZpZXcnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJCgnI2NvbXBhcmUtY2F0ZWdvcnktbGlzdCcpLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQodGhpcykuY2xvc2VzdCgnZm9ybScpLnN1Ym1pdCgpO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcHJvZHVjdFRpbGUuaW5pdCgpO1xuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbiAgICBhZGRQcm9kdWN0VG9DYXJ0KCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXJcdHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXIgcGFnZSA9IHJlcXVpcmUoJy4uL3BhZ2UnKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKXtcblx0XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyAmJiAncGFnZVBhdGgnIGluIHBhZ2VDb250ZXh0ICYmIChwYWdlQ29udGV4dC5wYWdlUGF0aCA9PSAnQlJld2FyZGVkQmFsYW5jZUNoZWNrJyB8fCBwYWdlQ29udGV4dC5wYWdlUGF0aCA9PSAnQWNjb3VudFZpZXcnIHx8IHBhZ2VDb250ZXh0LnBhZ2VQYXRoID09ICdSZXdhcmRzUHJvZ3JhbScpKSB7XG4gICAgXHRwYXNzQnJlYWRTZXR1cCgpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBhc3NCcmVhZFNldHVwKCkge1xuXHR2YXIgcmV3YXJkc051bWJlciA9ICQoJy5jdXN0b21lci1yZXdhcmRzLW51bWJlcicpLnRleHQoKTtcblxuXHRCcmVhZFBheW1lbnRzLnNldHVwKHtcblx0XHRsb3lhbHR5SUQ6IHJld2FyZHNOdW1iZXIsXG5cdFx0c3RvcmVOdW1iZXI6IHV0aWwuaXNNb2JpbGUoKSA/IFNpdGVQcmVmZXJlbmNlcy5QTENDX1NUT1JFX05VTUJFUl9NT0JJTEUgOiBTaXRlUHJlZmVyZW5jZXMuUExDQ19TVE9SRV9OVU1CRVJfV0VCLFxuXHRcdGV4aXN0aW5nQ2FyZEhvbGRlcjogZmFsc2UsXG5cdFx0ZW52OiBTaXRlUHJlZmVyZW5jZXMuUExDQ19FTlZJUk9OTUVOVCxcblx0fSk7XG5cblx0QnJlYWRQYXltZW50cy5yZWdpc3RlclBsYWNlbWVudHMoW2xhbmRpbmdQbGFjZW1lbnRdKTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRpYWxpemVFdmVudHMoKTsgICAgXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcXVpY2t2aWV3ID0gcmVxdWlyZSgnLi4vcXVpY2t2aWV3Jyk7XG52YXIgYm9udXNQcm9kdWN0c1ZpZXcgPSByZXF1aXJlKCcuLi9ib251cy1wcm9kdWN0cy12aWV3Jyk7XG52YXIgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcbnZhciBhZGRyZXNzZXMgPSBTaXRlUHJlZmVyZW5jZXMuRU5BQkxFX0VOSEFOQ0VEX0NIRUNLT1VUID8gcmVxdWlyZSgnLi9jaGVja291dC9vcGNhZGRyZXNzX2VuaGFuY2VkJykgOiByZXF1aXJlKCcuL2NoZWNrb3V0L29wY2FkZHJlc3MnKTtcbnZhciBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvZm9ybVByZXBhcmUnKTtcbnZhciBjYXJ0ID0gcmVxdWlyZSgnLi9jYXJ0Jyk7XG52YXIgb3BjcGF5bWVudCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvb3BjcGF5bWVudCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHaWZ0Q2FyZCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvR2lmdENhcmRQYXltZW50UGFuZWwnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciByZWNhcHRjaGEgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL1JlY2FwdGNoYScpO1xudmFyIFJld2FyZHNDcmVkaXQgPSByZXF1aXJlKCcuL2NoZWNrb3V0L1Jld2FyZHNDcmVkaXQnKTtcbnZhciBMb3lhbHR5Q3JlZGl0ID0gcmVxdWlyZSgnLi9jaGVja291dC9Mb3lhbHR5Q3JlZGl0Jyk7XG52YXIgQ2hlY2tvdXRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0NoZWNrb3V0Q29uc3RhbnRzJyk7XG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBjYXJ0SXRlbXNGb3JtU2VsZWN0b3IgPSAnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0nO1xudmFyIGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yID0gJyNiaWxsaW5nQWRkcmVzc0Zvcm0nO1xudmFyICRiaWxsaW5nQWRkcmVzc0Zvcm0gPSAkKGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcbnZhciBzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IgPSAnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nO1xudmFyICRzaGlwcGluZ0FkZHJlc3NGb3JtID0gJChzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IpO1xudmFyIHBheW1lbnRTZWN0aW9uU2VsZWN0b3IgPSAnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJztcbnZhciAkcGF5bWVudFNlY3Rpb24gPSAkKHBheW1lbnRTZWN0aW9uU2VsZWN0b3IpO1xudmFyIHBheW1lbnRGb3JtU2VsZWN0b3IgPSAnI3BheW1lbnRTZWN0aW9uJztcbnZhciAkcGF5bWVudEZvcm0gPSAkKHBheW1lbnRGb3JtU2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRMaXN0U2VsZWN0b3IgPSAnI2NyZWRpdENhcmRMaXN0JztcbnZhciAkY3JlZGl0Q2FyZExpc3QgPSAkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpO1xudmFyIHN1Ym1pdFBheW1lbnRTZWxlY3RvciA9ICcucGF5bWVudC1zZWN0aW9uLWZvb3RlciBidXR0b25bbmFtZSo9XCJfc3VibWl0UGF5bWVudFwiXTpub3QoI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwpJztcbnZhciAkc3VibWl0UGF5bWVudCA9ICQoc3VibWl0UGF5bWVudFNlbGVjdG9yKTtcbnZhciBzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50U2VsZWN0b3IgPSAnI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwnO1xudmFyICRzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50ID0gJChzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50U2VsZWN0b3IpO1xudmFyIGJhc2tldENvbnRhaW5lclNlbGVjdG9yID0gJy5iYXNrZXQtY29udGFpbmVyJztcbnZhciAkYmFza2V0Q29udGFpbmVyID0gJChiYXNrZXRDb250YWluZXJTZWxlY3Rvcik7XG5cbnZhciBwbGFjZU9yZGVyUmVjYXB0Y2hhO1xudmFyIHBsYWNlT3JkZXJSZWNhcHRjaGFQYXlwYWw7XG52YXIgcGxhY2VPcmRlclJlY2FwdGNoYUFmZmlybTtcbnZhciBwbGFjZU9yZGVyUmVjYXB0Y2hhUHJpdmF0ZUxhYmVsO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXZlbnRzIHNob3VsZCBiZSBkaXZpZGVkIHRvIG1vZHVsZXMuIFRoaXMgYWxsb3dzIHJlaW5pdGlhbGl6ZSBldmVudHMgYnkgc2VjdGlvbnMgYWZ0ZXIgcGFydGlhbCByZWxvYWRcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBldmVudHMgZm9yIHRoZSBnaWZ0IHJlZ2lzdHJhdGlvblxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKG9wdGlvbnMpIHtcblx0aW5pdGlhbGl6ZUNhcnRFdmVudHMob3B0aW9ucyk7XG5cdGluaXRpYWxpemVQYXltZW50TWV0aG9kc0V2ZW50cygpO1xuXHRcblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUNhcnRFdmVudHMob3B0aW9ucykge1xuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICdhLmFkZC10by13aXNobGlzdCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHQvKnJlbW92ZSBuZXh0IGxpbmUgdG8gdXNlIGRlZmF1bHQgZHcgd2lzaGxpc3QgZnVuY3Rpb25hbGl0eSovXG4gICAgXHRyZXR1cm4gZmFsc2U7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBcdGlmKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQgPT0gdHJ1ZSl7XG4gICAgXHRcdC8vcG9zdCBmb3JtIGhlcmVcbiAgICBcdH0gZWxzZSB7XG4gICAgXHRcdCQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHsgc2Nyb2xsVG9wOiAkKCcubG9naW4tZm9ybScpLmVxKDApLm9mZnNldCgpLnRvcH0sIDEwMDApO1xuICAgIFx0fVxuICAgIH0pO1xuICAgIFxuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQUxURVJOQVRFX1BJQ0tVUF9FTkFCTEVEKSB7XG5cdFx0cmVuZGVyQWx0ZXJuYXRlUGlja3VwKCk7XG5cdH1cblxuXHQkcGF5bWVudEZvcm0ub24oJ2NoYW5nZScsICdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJywgZnVuY3Rpb24oKSB7XG5cdFx0c2V0UGxhY2VPcmRlckJ1dHRvbnNEaXNhYmxlZChmYWxzZSk7XG5cdFx0JCh0aGlzKS5jbG9zZXN0KCdkaXYuZm9ybS1yb3cnKS5maW5kKCdkaXYuZmllbGQtd3JhcHBlci5lcnJvcicpLnJlbW92ZSgpO1xuXHR9KTtcblxuXHQkc3VibWl0UGF5bWVudC5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuXHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyKSB7XG5cdFx0XHRzdWJtaXRQYXltZW50KCk7XG5cdFx0fVxuICAgIH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdDaGVja291dC5TdWJtaXRQYXltZW50JywgZnVuY3Rpb24gKCkge1xuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyKSB7XG5cdFx0XHRzdWJtaXRQYXltZW50KCk7XG5cdFx0fVxuXHR9KTtcblx0XG4gICAgJHN1Ym1pdFByaXZhdGVMYWJlbFBheW1lbnQub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcbiAgICBcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyKSB7XG5cdFx0XHRzdWJtaXRQYXltZW50UHJpdmF0ZUxhYmVsKCk7XHRcblx0XHR9XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ0NoZWNrb3V0LlN1Ym1pdFBheW1lbnRQcml2YXRlTGFiZWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikge1xuXHRcdFx0c3VibWl0UGF5bWVudFByaXZhdGVMYWJlbCgpO1xuXHRcdH1cblx0fSk7XG4gICAgXG4gICAgdmFyIGdldENyZWRpdENhcmRJbmZvID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuYmlsbGluZ1NlbGVjdENDKSxcbiAgICAgICAgICAgIGRhdGE6IHtjY0lEOiBpZH1cbiAgICAgICAgfSkpO1xuICAgIH07XG5cbiAgICAkY3JlZGl0Q2FyZExpc3Qub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCkge1xuICAgIFx0dmFyIGNjSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgIFx0aWYgKGNjSUQubGVuZ3RoIDw9IDApIHtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuICAgIFx0Z2V0Q3JlZGl0Q2FyZEluZm8oY2NJRCkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdHZhciBkYXRhID0gcmVzcG9uc2U7XG5cdFx0XHRpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWFza2VkTnVtYmVyJykpIHtcblx0XHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9vd25lcicpLnZhbChkYXRhLmhvbGRlcikudmFsaWQoKTtcblx0XHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF90eXBlW3ZhbHVlPVwiJytkYXRhLnR5cGUrJ1wiXScpXG5cdFx0XHRcdFx0LmZpcnN0KClcblx0XHRcdFx0XHQucHJvcCgnY2hlY2tlZCcsIHRydWUpXG5cdFx0XHRcdFx0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHQkKFwiW2lkXj0nZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX251bWJlciddXCIpLmZpcnN0KCkudmFsKGRhdGEubWFza2VkTnVtYmVyKS52YWxpZCgpO1xuXHRcdFx0XHQkKCcjZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2V4cGlyYXRpb25fbW9udGgnKS52YWwoZGF0YS5leHBpcmF0aW9uTW9udGgpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHQkKCcjZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2V4cGlyYXRpb25feWVhcicpLnZhbChkYXRhLmV4cGlyYXRpb25ZZWFyKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdFx0JCgnaW5wdXRbbmFtZV49ZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2N2bl0nKS52YWwoJycpO1xuXHRcdFx0fVxuXHRcdH0uYmluZCh0aGlzKSk7XG5cbiAgICB9KTtcblxuICAgIC8vcHJlc2VsZWN0IGRlZmF1bHQgY3JlZGl0IGNhcmRcblx0aWYoJGNyZWRpdENhcmRMaXN0Lmxlbmd0aCA+IDAgJiYgJCgnLnB0X29uZXBjaGVja291dCBpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbCgpID09IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCkge1xuXHRcdCRjcmVkaXRDYXJkTGlzdC5maW5kKCdvcHRpb24nKS5lcSgxKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXHRcdCRjcmVkaXRDYXJkTGlzdC50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fVxuXG4gICAgdmFyIGdldFByaXZhdGVMYWJlbENhcmRJbmZvID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuYmlsbGluZ1NlbGVjdFByaXZhdGVMYWJlbCksXG4gICAgICAgICAgICBkYXRhOiB7Y2FyZElkOiBpZH1cbiAgICAgICAgfSkpO1xuICAgIH07XG5cbiAgICB2YXIgJHByaXZhdGVMYWJlbENhcmRMaXN0ID0gJCgnI3ByaXZhdGVMYWJlbENhcmRMaXN0Jyk7XG4gICAgJHByaXZhdGVMYWJlbENhcmRMaXN0Lm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpIHtcbiAgICBcdHZhciBjYXJkSWQgPSAkKCcjcHJpdmF0ZUxhYmVsQ2FyZExpc3QnKS52YWwoKTtcbiAgICBcdGlmIChjYXJkSWQubGVuZ3RoIDw9IDApIHtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuICAgIFx0Z2V0UHJpdmF0ZUxhYmVsQ2FyZEluZm8oY2FyZElkKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0dmFyIGRhdGEgPSByZXNwb25zZTtcblx0XHRcdGlmIChkYXRhLmhhc093blByb3BlcnR5KCdtYXNrZWROdW1iZXInKSkge1xuXHRcdFx0XHQkKFwiW2lkXj0nZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19wcml2YXRlTGFiZWxDYXJkX251bWJlciddXCIpLmZpcnN0KCkudmFsKGRhdGEubWFza2VkTnVtYmVyKS52YWxpZCgpO1xuXHRcdFx0fVxuXHRcdH0uYmluZCh0aGlzKSk7XG5cbiAgICB9KTtcblxuXHQvLyBwcmVzZWxlY3QgZGVmYXVsdCBwcml2YXRlIGxhYmVsIGNhcmRcblx0aWYgKCRwcml2YXRlTGFiZWxDYXJkTGlzdC5sZW5ndGggPiAwKSB7XG5cdFx0JHByaXZhdGVMYWJlbENhcmRMaXN0LmZpbmQoJ29wdGlvbicpLmVxKDEpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0JHByaXZhdGVMYWJlbENhcmRMaXN0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9XG5cbiAgICBhZGRyZXNzZXMuaW5pdChvcHRpb25zKTtcbiAgICBjYXJ0LmluaXQob3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckFsdGVybmF0ZVBpY2t1cCgpIHtcblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICdidXR0b24uYWx0LXBpY2t1cC1idXR0b24nKS5vbignY2xpY2snLCAnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLmFkZENsYXNzKCdhY3RpdmUtbW9kYWwnKS5zaG93KCk7XG5cdFx0JCgnZmllbGRzZXQgc3BhbicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcblx0XHQkKCcub25lLXJlcXVpcmVkJykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljaycsICcjYWx0LXBpY2t1cC1tb2RhbCAuY2xvc2UtbW9kYWwnKS5vbignY2xpY2snLCAnI2FsdC1waWNrdXAtbW9kYWwgLmNsb3NlLW1vZGFsJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUtbW9kYWwnKS5oaWRlKCk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJmaXJzdE5hbWVcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCgnLmZpcnN0bmFtZS1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignZm9jdXMnLCAnaW5wdXRbbmFtZT1cImxhc3ROYW1lXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5sYXN0bmFtZS1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignZm9jdXMnLCAnaW5wdXRbbmFtZT1cImVtYWlsXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5lbWFpbC1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcblx0XHQkKCcub25lLXJlcXVpcmVkJykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJwaG9uZVwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcucGhvbmUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uI2FsdFBpY2t1cFN1Ym1pdCcpLm9uKCdjbGljaycsICdidXR0b24jYWx0UGlja3VwU3VibWl0JywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcbiAgICBcdHZhciBpc0ZpcnN0TmFtZVZhbGlkID0gdHJ1ZTtcblx0XHR2YXIgZmlyc3ROYW1lID0gJCgnaW5wdXRbbmFtZT1cImZpcnN0TmFtZVwiXScpLnZhbCgpO1xuXHRcdHZhciByZWdleE5hbWUgPSAvXlthLXogLC4nLV0rJC9pO1xuXHRcdGlmIChmaXJzdE5hbWUubGVuZ3RoID09IDAgfHwgZmlyc3ROYW1lLm1hdGNoKHJlZ2V4TmFtZSkgPT0gbnVsbCkge1xuXHRcdFx0aXNGaXJzdE5hbWVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLmZpcnN0bmFtZS1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIGlzTGFzdE5hbWVWYWxpZCA9IHRydWU7XHRcdFxuXHRcdHZhciBsYXN0TmFtZSA9JCgnaW5wdXRbbmFtZT1cImxhc3ROYW1lXCJdJykudmFsKCk7XG5cdFx0aWYgKGxhc3ROYW1lLmxlbmd0aCA9PSAwIHx8IGxhc3ROYW1lLm1hdGNoKHJlZ2V4TmFtZSkgPT0gbnVsbCkge1xuXHRcdFx0aXNMYXN0TmFtZVZhbGlkID0gZmFsc2U7XG5cdFx0XHQkKCcubGFzdG5hbWUtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciBpc0VtYWlsVmFsaWQgPSB0cnVlO1x0XHRcblx0XHR2YXIgZW1haWwgPSAkKCdpbnB1dFtuYW1lPVwiZW1haWxcIl0nKS52YWwoKTtcblx0XHR2YXIgcmVnZXhFbWFpbCA9IC9eW2EtekEtWjAtOS4hIyQlJicqKy89P15fYHt8fX4tXStAW2EtekEtWjAtOS1dKyg/OlxcLlthLXpBLVowLTktXSspKiQvZztcblx0XHRpZiAoZW1haWwubGVuZ3RoID4gMCAmJiBlbWFpbC5tYXRjaChyZWdleEVtYWlsKSA9PSBudWxsKSB7XG5cdFx0XHRpc0VtYWlsVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5lbWFpbC1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cblx0XHR2YXIgaXNQaG9uZVZhbGlkID0gdHJ1ZTtcblx0XHR2YXIgcGhvbmUgPSAkKCdpbnB1dFtuYW1lPVwicGhvbmVcIl0nKS52YWwoKS5yZXBsYWNlKC9cXEQvZywgJycpO1xuXHRcdHZhciByZWdleFBob25lID0gL15cXCs/XFwoPyhbMC05XVswLThdWzAtOV0pXFwpP1tcXC1cXC4gXT8oWzItOV1bMC05XXsyfSlbXFwtXFwuIF0/KFswLTldezR9KShcXHMqeFswLTldKyk/JC9nO1xuXHRcdGlmIChwaG9uZS5sZW5ndGggPiAwICYmIHBob25lLm1hdGNoKHJlZ2V4UGhvbmUpID09IG51bGwpIHtcblx0XHRcdGlzUGhvbmVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLnBob25lLWVycm9yJykuYWRkQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdH1cblx0XHRcbiAgICBcdGlmIChlbWFpbC5sZW5ndGggPT0gMCAmJiBwaG9uZS5sZW5ndGggPT0gMCkge1xuICAgIFx0XHQkKCcub25lLXJlcXVpcmVkJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgXHRcdGlzRW1haWxWYWxpZCA9IGZhbHNlO1xuICAgIFx0XHRpc1Bob25lVmFsaWQgPSBmYWxzZTtcbiAgICBcdH1cbiAgICBcdFxuICAgIFx0aWYgKCFpc0VtYWlsVmFsaWQgfHwgIWlzUGhvbmVWYWxpZCkge1xuICAgIFx0XHRyZXR1cm47XG4gICAgXHR9XG4gICAgXHRcblx0XHRpZiAoaXNGaXJzdE5hbWVWYWxpZCAmJiBpc0xhc3ROYW1lVmFsaWQgJiYgKGlzRW1haWxWYWxpZCB8fCBpc1Bob25lVmFsaWQpKSB7XG5cdFx0XHR2YXIgY2xlYW5QaG9uZSA9IHBob25lLnJlcGxhY2UoL1xcRC9nLCAnJyk7XG5cdFx0XHR2YXIgc2hpcG1lbnRJRCA9ICQoJy5hbHRlcm5hdGUtcGlja3VwJykuY2xvc2VzdChcImZvcm1cIikuYXR0cignc2hpcG1lbnQnKTtcblx0XHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLnNldEFsdGVybmF0ZVBpY2t1cCxcblx0XHRcdFx0dHlwZTogXCJnZXRcIixcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdHNoaXBtZW50SUQ6IHNoaXBtZW50SUQsXG5cdFx0XHRcdFx0YWx0UGlja3VwRmlyc3ROYW1lOiBmaXJzdE5hbWUsXG5cdFx0XHRcdFx0YWx0UGlja3VwTGFzdE5hbWU6IGxhc3ROYW1lLFxuXHRcdFx0XHRcdGFsdFBpY2t1cEVtYWlsOiBlbWFpbCxcblx0XHRcdFx0XHRhbHRQaWNrdXBQaG9uZTogY2xlYW5QaG9uZVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09ICdzdWNjZXNzJykge1xuXHRcdFx0XHRcdFx0JCgnc3Bhbi5hbHQtcGVyc29uJykuYXR0cignZGF0YS1maXJzdG5hbWUnLCBmaXJzdE5hbWUpLmF0dHIoJ2RhdGEtbGFzdG5hbWUnLCBsYXN0TmFtZSkuYXR0cignZGF0YS1lbWFpbCcsIGVtYWlsKS5hdHRyKCdkYXRhLXBob25lJywgY2xlYW5QaG9uZSk7XG5cdFx0XHRcdFx0XHRkaXNwbGF5QWx0ZXJuYXRlUGlja3VwIChmaXJzdE5hbWUgKyAnICcgKyBsYXN0TmFtZSlcblx0XHRcdFx0XHRcdCQoJyNhbHQtcGlja3VwLW1vZGFsJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZS1tb2RhbCcpLmhpZGUoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcblx0XHRcdFx0XHRjb25zb2xlLmxvZyh0ZXh0U3RhdHVzLCBlcnJvclRocm93bik7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZGlzcGxheUFsdGVybmF0ZVBpY2t1cCAoZnVsbE5hbWUpIHtcblx0JCgnLmFsdGVybmF0ZS1waWNrdXAgc3Bhbi5hbHQtcGVyc29uJykudGV4dChmdWxsTmFtZSk7XG5cdCQoJ3NwYW4uYWx0LWhlYWRlcicpLnNob3coKTtcblx0JCgnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJykudGV4dCgnVVBEQVRFJyk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYSgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgb3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlciAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0aWYgKCQoJyNzdWJtaXRPUENQYXltZW50JykubGVuZ3RoID4gMCkge1xuXHRcdFx0cGxhY2VPcmRlclJlY2FwdGNoYSA9IGdyZWNhcHRjaGEucmVuZGVyKCdzdWJtaXRPUENQYXltZW50Jywge1xuXHRcdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0XHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRQYXltZW50LFxuXHRcdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHRcdCAgICB9KTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCQoJyNzdWJtaXRPUENQYXltZW50UGF5cGFsJykubGVuZ3RoID4gMCkge1xuXHRcdFx0cGxhY2VPcmRlclJlY2FwdGNoYVBheXBhbCA9IGdyZWNhcHRjaGEucmVuZGVyKCdzdWJtaXRPUENQYXltZW50UGF5cGFsJywge1xuXHRcdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0XHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRQYXltZW50LFxuXHRcdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHRcdCAgICB9KTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCQoJyNzdWJtaXRPUENQYXltZW50Rm9yQWZmaXJtJykubGVuZ3RoID4gMCkge1xuXHRcdFx0cGxhY2VPcmRlclJlY2FwdGNoYUFmZmlybSA9IGdyZWNhcHRjaGEucmVuZGVyKCdzdWJtaXRPUENQYXltZW50Rm9yQWZmaXJtJywge1xuXHRcdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0XHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRQYXltZW50LFxuXHRcdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHRcdCAgICB9KTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCQoJyNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykubGVuZ3RoID4gMCkge1xuXHRcdFx0cGxhY2VPcmRlclJlY2FwdGNoYVByaXZhdGVMYWJlbCA9IGdyZWNhcHRjaGEucmVuZGVyKCdzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJywge1xuXHRcdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0XHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRQYXltZW50UHJpdmF0ZUxhYmVsLFxuXHRcdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHRcdCAgICB9KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gbG95YWx0eU9wdGluKCkge1xuXHRpZiAoU2l0ZVByZWZlcmVuY2VzLkxPWUFMVFlfRU5BQkxFRCkge1xuXHRcdHZhciBvcHRfZW1haWwgPSAkKCcuYmlsbGluZy1lbWFpbC1hZGRyZXNzJykudGV4dCgpO1xuXHRcdHZhciBvcHRfc3RhdHVzID0gJCgnI2xveWFsdHlfb3B0aW4nKS5wcm9wKCdjaGVja2VkJyk7XG5cdFx0dmFyIGR3X2N1c3RvbWVyX2lkID0gKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQgPT0gdHJ1ZSkgPyAkKCcuc2VjdGlvbi1jaGVja291dCcpLmF0dHIoJ2RhdGEtY3VzdG9tZXJpZCcpIDogJyc7XG5cdFx0XG5cdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcblx0XHRcdGlmIChvcHRfc3RhdHVzID09IGZhbHNlKSB7XG5cdFx0XHRcdC8vIHRyYWNrIENvcmRpYWwgbG95YWx0eSBvcHRvdXQgZXZlbnRcblx0XHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0XHRlbWFpbDogb3B0X2VtYWlsXG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdHZhciBjb250YWN0X2RhdGEgPSB7XG5cdFx0XHRcdCAgICAnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdCAgICAgICAgJ2VtYWlsJzoge1xuXHRcdFx0XHQgICAgICAgICAgICAnYWRkcmVzcyc6IG9wdF9lbWFpbCAgICAgICAgIFxuXHRcdFx0XHQgICAgICAgIH1cblx0XHRcdFx0ICAgIH1cblx0XHRcdFx0fTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHQgICAgJ2VtYWlsJzogb3B0X2VtYWlsXG5cdFx0XHRcdH07XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0Y3JkbChbXG5cdFx0XHRcdFx0XHRbJ2NvbnRhY3QnLCBhdXRoX2RhdGEsIGNvbnRhY3RfZGF0YV0sXG5cdFx0XHRcdFx0XHRbJ2V2ZW50JywgJ2xveWFsdHlfb3B0b3V0JywgcHJvcGVydGllc11cblx0XHRcdFx0XHRdKTtcdFxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG5cdFx0XHR1cmw6IFVybHMubG95YWx0eU9wdGluLFxuXHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0ZGF0YToge1xuXHRcdFx0XHQnZW1haWwnOiBvcHRfZW1haWwsXG5cdFx0XHRcdCdkd0N1c3RvbWVySUQnOiBkd19jdXN0b21lcl9pZCxcblx0XHRcdFx0J29wdFN0YXR1cyc6IG9wdF9zdGF0dXNcblx0XHRcdH0sXHRcdFx0XHRcdFx0XG5cdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhWydlcnJvciddKSkge1xuXHRcdFx0XHRcdGNvbnNvbGUubG9nKGRhdGEubWVzc2FnZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KSk7XG5cdH0gZWxzZSB7XG5cdFx0VFByb21pc2UucmVzb2x2ZSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdFBheW1lbnQoKSB7XG5cdHZhciBiYWxhbmNlRHVlID0gcGFyc2VGbG9hdCgkcGF5bWVudFNlY3Rpb24uYXR0cignYmFsYW5jZS1kdWUnKSk7XG5cdCRzdWJtaXRQYXltZW50LmZpbHRlcignOnZpc2libGUnKS5sb2FkaW5nKHtcblx0XHRJc0ltYWdlU2hvd246IGZhbHNlLFxuXHRcdExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5DaGVja291dC5QbGFjaW5nT3JkZXJcblx0fSk7XG5cdFxuXHRzZXRQbGFjZU9yZGVyQnV0dG9uc0Rpc2FibGVkKHRydWUpO1xuXHRcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFxuXHR2YXIgJGNyZWRpdENhcmRUeXBlID0gJHBheW1lbnRGb3JtLmZpbmQoJ1tuYW1lJD1cIl9jcmVkaXRDYXJkX3R5cGVcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHRpZiAoYmFsYW5jZUR1ZSA+IDApIHtcblx0XHQkcGF5bWVudEZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0XG5cdFx0aWYgKHR5cGVvZiAkY3JlZGl0Q2FyZFR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgXHRcdCRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuZmluZCgnZGl2LmZpZWxkLXdyYXBwZXIuZXJyb3InKS5yZW1vdmUoKTtcbiAgICBcdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgIFx0XHRcdCRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuYXBwZW5kKCc8ZGl2IGNsYXNzPVwiZmllbGQtd3JhcHBlciBlcnJvclwiIHN0eWxlPVwiaGVpZ2h0OjBweDtcIj48c3BhbiBjbGFzcz1cImVycm9yXCI+JyArIFJlc291cmNlcy5SRVFVSVJFRF9GSUVMRCArICc8L3NwYW4+PC9kaXY+Jyk7XG4gICAgXHRcdH0sIDUwKTtcbiAgICBcdH1cblx0fVxuXHRcblx0Ly9jaGVjayBmaXJzdCBpZiBhZGRyZXNzZXMgYXJlIHZhbGlkXG5cdHZhciBpc0JpbGxpbmdBZGRyZXNzVmFsaWQgPSBmYWxzZTtcblx0dmFyIGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgPSBmYWxzZTtcblx0XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXTtcblx0XG5cdGlmICgkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkKCkpIHtcblx0XHRpc0JpbGxpbmdBZGRyZXNzVmFsaWQgPSB0cnVlO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5zaG93KCk7XG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdH1cblx0XG5cdGlmICgkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0aXNTaGlwcGluZ0FkZHJlc3NWYWxpZCA9IHRydWU7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcblx0fVxuXHRcblx0aWYgKGlzQmlsbGluZ0FkZHJlc3NWYWxpZCAmJiBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkICYmICQoJyNzaGlwcGluZy1tZXRob2QtbGlzdCBpbnB1dDpjaGVja2VkJykubGVuZ3RoICYmIChiYWxhbmNlRHVlID09IDAgfHwgJHBheW1lbnRGb3JtLnZhbGlkKCkpKSB7XG5cdFx0JCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcblx0XHRcblx0XHR2YXIgYWN0aW9uTmFtZSA9ICRzdWJtaXRQYXltZW50LmZpbHRlcignOnZpc2libGUnKS5hdHRyKCduYW1lJyk7XG5cdFx0c2V0T1BDUGF5bWVudERhdGEoJHBheW1lbnRGb3JtLCBhY3Rpb25OYW1lKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0dmFyIGRhdGE7XG4gICAgICAgICAgICB0cnkge1xuXHRcdFx0XHRkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGRhdGEgPSByZXNwb25zZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQWRkUGF5bWVudEluZm8nKS50aGVuKGxveWFsdHlPcHRpbikudGhlbihmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAob3B0aW9ucy5DaGVja291dE1vZGUgPT0gJ01vYmlsZUFwcCcpIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlRm9yTW9iaWxlQXBwO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmIChvcHRpb25zLkNoZWNrb3V0TW9kZSA9PSAnTW9iaWxlQXBwJykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2VGb3JNb2JpbGVBcHA7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnYWZmaXJtUmVkaXJlY3QnKSB7XG5cdFx0XHRcdHZhciBfYWZmaXJtX2NvbmZpZyA9IHtcblx0XHRcdFx0XHRwdWJsaWNfYXBpX2tleTogZGF0YS5hZmZpcm0uUHVibGljQXBpS2V5LFxuXHRcdFx0XHQgICAgc2NyaXB0OiBkYXRhLmFmZmlybS5TY3JpcHRcblx0XHRcdFx0fTtcblx0XHRcdFx0KGZ1bmN0aW9uKGwsZyxtLGUsYSxmLGIpe3ZhciBkLGM9bFttXXx8e30saD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KGYpLG49ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZilbMF0saz1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGZ1bmN0aW9uKCl7YVtiXS5fLnB1c2goW2MsYXJndW1lbnRzXSl9fTtjW2VdPWsoYyxlLFwic2V0XCIpO2Q9Y1tlXTtjW2FdPXt9O2NbYV0uXz1bXTtkLl89W107Y1thXVtiXT1rKGMsYSxiKTthPTA7Zm9yKGI9XCJzZXQgYWRkIHNhdmUgcG9zdCBvcGVuIGVtcHR5IHJlc2V0IG9uIG9mZiB0cmlnZ2VyIHJlYWR5IHNldFByb2R1Y3RcIi5zcGxpdChcIiBcIik7YTxiLmxlbmd0aDthKyspZFtiW2FdXT1rKGMsZSxiW2FdKTthPTA7Zm9yKGI9W1wiZ2V0XCIsXCJ0b2tlblwiLFwidXJsXCIsXCJpdGVtc1wiXTthPGIubGVuZ3RoO2ErKylkW2JbYV1dPWZ1bmN0aW9uKCl7fTtoLmFzeW5jPSEwO2guc3JjPWdbZl07bi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShoLG4pO2RlbGV0ZSBnW2ZdO2QoZyk7bFttXT1jfSkod2luZG93LF9hZmZpcm1fY29uZmlnLFwiYWZmaXJtXCIsXCJjaGVja291dFwiLFwidWlcIixcInNjcmlwdFwiLFwicmVhZHlcIik7XG5cdFx0XHRcdFxuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQoSlNPTi5wYXJzZShkYXRhLmFmZmlybS5BZmZpcm1DaGVja291dCkpO1xuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQucG9zdCgpO1xuXHRcdFx0XHRhZmZpcm0udWkucmVhZHkoXG5cdFx0XHRcdCAgICBmdW5jdGlvbigpIHtcblx0XHRcdFx0ICAgICAgICBhZmZpcm0udWkuZXJyb3Iub24oXCJjbG9zZVwiLCBmdW5jdGlvbigpe1xuXHRcdFx0XHQgICAgICAgICAgICAvLyB3aW5kb3cubG9jYXRpb24ucmVwbGFjZShkYXRhLmFmZmlybS5SZWRpcmVjdFVybCk7XG5cdFx0XHRcdCAgICAgICAgfSk7XG5cdFx0XHRcdCAgICB9XG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpe1xuXHRcdFx0XHR2YXIgcG9wdXAgPSByZXF1aXJlKCcuLi9wb3B1cCcpO1xuXHRcdFx0XHR2YXIgcGF5bG9hZCA9IEpTT04ucGFyc2UoZGF0YS5wYXlsb2FkKTtcblxuXHRcdFx0XHR2YXIgbGlzdCA9ICQubWFwKHBheWxvYWQubGlzdCwgZnVuY3Rpb24gKGVsKSB7XG5cdFx0XHRcdFx0cmV0dXJuICc8bGk+JyArIGVsLm5hbWUgKyAnOjxicj4nICsgZWwubWVzc2FnZSArICc8L2xpPic7XG5cdFx0XHRcdH0pLmpvaW4oJycpO1xuXHRcdFx0XHRcblx0XHRcdFx0cG9wdXAuaW5pdCh7XG5cdFx0XHRcdFx0dGl0bGU6IHBheWxvYWQudGl0bGUsXG5cdFx0XHRcdFx0Y29udGVudDogcGF5bG9hZC5tZXNzYWdlICsgJzx1bCBjbGFzcz1cInNoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cF9fbGlzdFwiPicgKyBsaXN0ICsgJzwvdWw+Jyxcblx0XHRcdFx0fSkuc2hvd1BvcHVwKCk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnQmlsbGluZ0FkZHJlc3NFcnJvcicpIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+QmlsbGluZyBBZGRyZXNzIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnU2hpcHBpbmdBZGRyZXNzRXJyb3InKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpID8gZGF0YS5tZXNzYWdlIDogUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPlNoaXBwaW5nIEFkZHJlc3MgRXJyb3I6PC9iPiAnICsgbWVzc2FnZSArICc8L2Rpdj4nKTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdWYWxpZGF0aW9uRXJyb3InKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpID8gZGF0YS5tZXNzYWdlIDogUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPlZhbGlkYXRpb24gRXJyb3I6PC9iPiAnICsgbWVzc2FnZSArICc8L2Rpdj4nKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpID8gZGF0YS5tZXNzYWdlIDogUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiIHJvbGU9XCJhbGVydFwiIHRhYmluZGV4PVwiMFwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPlBheW1lbnQgRGVjbGluZWQ6PC9iPiAnICsgbWVzc2FnZSArICc8L2Rpdj4nKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JHN1Ym1pdFBheW1lbnQuZmlsdGVyKCc6dmlzaWJsZScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoZmFsc2UpO1xuXHRcdFx0aWYgKHBsYWNlT3JkZXJSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYSk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhUGF5cGFsICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGFQYXlwYWwpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAocGxhY2VPcmRlclJlY2FwdGNoYUFmZmlybSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChwbGFjZU9yZGVyUmVjYXB0Y2hhQWZmaXJtKTtcblx0XHRcdH1cblx0XHR9KS5jYXRjaChmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyA9PSAzMDIgJiYgcmVzcG9uc2UucmVzcG9uc2VUZXh0KSB7IFxuXHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gcmVzcG9uc2UucmVzcG9uc2VUZXh0O1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdCRzdWJtaXRQYXltZW50LmZpbHRlcignOnZpc2libGUnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0c2V0UGxhY2VPcmRlckJ1dHRvbnNEaXNhYmxlZChmYWxzZSk7XG5cblx0XHQvLyBBZGRpbmcgQURBIGNvbXBsaWFuY2UgZXJyb3IgbWVzc2FnZXMgZm9yIHN1Ym1pdFBheW1lbnQgc2VjdGlvblxuXHRcdCRwYXltZW50Rm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0XHRpZiAoJHBheW1lbnRGb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzID0gb3BjcGF5bWVudC5nZXRFcnJvck1lc3NhZ2VzKCRwYXltZW50Rm9ybSk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvckJveCA9IG9wY3BheW1lbnQuZXJyb3JCb3goJ0Nhbm5vdCBQcm9jZWVkJywgJ1BsZWFzZSBmaXggdGhlIGZvbGxvd2luZyBlcnJvcnM6JywgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcblx0XHRcdGlmIChwYXltZW50Rm9ybUVycm9yQm94KSB7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKHBheW1lbnRGb3JtRXJyb3JCb3gpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHRpZiAocGxhY2VPcmRlclJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhUGF5cGFsICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0Z3JlY2FwdGNoYS5yZXNldChwbGFjZU9yZGVyUmVjYXB0Y2hhUGF5cGFsKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKHBsYWNlT3JkZXJSZWNhcHRjaGFBZmZpcm0gIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGFBZmZpcm0pO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBzdWJtaXRQYXltZW50UHJpdmF0ZUxhYmVsKCkge1xuXHR2YXIgYmFsYW5jZUR1ZSA9IHBhcnNlRmxvYXQoJHBheW1lbnRGb3JtLmZpbmQoJ1tiYWxhbmNlLWR1ZV0nKS5hdHRyKCdiYWxhbmNlLWR1ZScpKTtcblx0JHN1Ym1pdFByaXZhdGVMYWJlbFBheW1lbnQubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuQ2hlY2tvdXQuUGxhY2luZ09yZGVyXG5cdH0pO1xuXHRcblx0c2V0UGxhY2VPcmRlckJ1dHRvbnNEaXNhYmxlZCh0cnVlKTtcblx0XG5cdHZhciBpc0JpbGxpbmdBZGRyZXNzVmFsaWQgPSBmYWxzZTtcblx0dmFyIGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgPSBmYWxzZTtcblx0XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXTtcblx0XG5cdGlmICgkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkKCkpIHtcblx0XHRpc0JpbGxpbmdBZGRyZXNzVmFsaWQgPSB0cnVlO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5zaG93KCk7XG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdH1cblx0XG5cdGlmICgkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0aXNTaGlwcGluZ0FkZHJlc3NWYWxpZCA9IHRydWU7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcblx0fVxuXHRcblx0aWYgKGlzQmlsbGluZ0FkZHJlc3NWYWxpZCAmJiBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkICYmICQoJyNzaGlwcGluZy1tZXRob2QtbGlzdCBpbnB1dDpjaGVja2VkJykubGVuZ3RoICYmIChiYWxhbmNlRHVlID09IDAgfHwgJHBheW1lbnRGb3JtLnZhbGlkKCkpKSB7XG5cdFx0JCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcblx0XHRcblx0XHR2YXIgYWN0aW9uTmFtZSA9ICQoJyNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYXR0cignbmFtZScpO1xuXHRcdHNldE9QQ1BheW1lbnREYXRhKCRwYXltZW50Rm9ybSwgYWN0aW9uTmFtZSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdHZhciBkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cblx0XHRcdGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3N1Y2Nlc3MnKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKCdwYXltZW50IGRhdGFsYXllcicpO1xuXHRcdFx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdBZGRQYXltZW50SW5mbycpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKG9wdGlvbnMuQ2hlY2tvdXRNb2RlID09ICdNb2JpbGVBcHAnKSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZUZvck1vYmlsZUFwcDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KS5jYXRjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAob3B0aW9ucy5DaGVja291dE1vZGUgPT0gJ01vYmlsZUFwcCcpIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlRm9yTW9iaWxlQXBwO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InKXtcblx0XHRcdFx0dmFyIHBvcHVwID0gcmVxdWlyZSgnLi4vcG9wdXAnKTtcblx0XHRcdFx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cblx0XHRcdFx0dmFyIGxpc3QgPSAkLm1hcChwYXlsb2FkLmxpc3QsIGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0XHRcdHJldHVybiAnPGxpPicgKyBlbC5uYW1lICsgJzo8YnI+JyArIGVsLm1lc3NhZ2UgKyAnPC9saT4nO1xuXHRcdFx0XHR9KS5qb2luKCcnKTtcblxuXHRcdFx0XHRwb3B1cC5pbml0KHtcblx0XHRcdFx0XHR0aXRsZTogcGF5bG9hZC50aXRsZSxcblx0XHRcdFx0XHRjb250ZW50OiBwYXlsb2FkLm1lc3NhZ2UgKyAnPHVsIGNsYXNzPVwic2hpcHBpbmctcmVzdHJpY3Rpb25zLXBvcHVwX19saXN0XCI+JyArIGxpc3QgKyAnPC91bD4nLFxuXHRcdFx0XHR9KS5zaG93UG9wdXAoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0aWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ2Vycm9yTWVzc2FnZScpKSB7XG5cdFx0XHRcdFx0bWVzc2FnZSA9IGRhdGEuZXJyb3JNZXNzYWdlO1xuXHRcdFx0XHR9IGVsc2UgaWYoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpKSB7XG5cdFx0XHRcdFx0bWVzc2FnZSA9IGRhdGEubWVzc2FnZTtcblx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICQoJyNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiIHJvbGU9XCJhbGVydFwiIHRhYmluZGV4PVwiMFwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPlBheW1lbnQgRGVjbGluZWQ6PC9iPiAnICsgbWVzc2FnZSArICc8L2Rpdj4nKTtcblx0XHRcdH1cblx0XHRcdCRzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoZmFsc2UpO1xuXHRcdFx0aWYgKHBsYWNlT3JkZXJSZWNhcHRjaGFQcml2YXRlTGFiZWwgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYVByaXZhdGVMYWJlbCk7XG5cdFx0XHR9XG5cdFx0fS5iaW5kKHRoaXMpKTtcblx0fSBlbHNlIHtcblx0XHQkc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0c2V0UGxhY2VPcmRlckJ1dHRvbnNEaXNhYmxlZChmYWxzZSk7XG5cblx0XHQvLyBBZGRpbmcgQURBIGNvbXBsaWFuY2UgZXJyb3IgbWVzc2FnZXMgZm9yIHN1Ym1pdFBheW1lbnQgc2VjdGlvblxuXHRcdCRwYXltZW50Rm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0XHRpZiAoJHBheW1lbnRGb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzID0gb3BjcGF5bWVudC5nZXRFcnJvck1lc3NhZ2VzKCRwYXltZW50Rm9ybSk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvckJveCA9IG9wY3BheW1lbnQuZXJyb3JCb3goJ0Nhbm5vdCBQcm9jZWVkJywgJ1BsZWFzZSBmaXggdGhlIGZvbGxvd2luZyBlcnJvcnM6JywgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcblx0XHRcdGlmIChwYXltZW50Rm9ybUVycm9yQm94KSB7XG5cdFx0XHRcdCRzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50LmFmdGVyKHBheW1lbnRGb3JtRXJyb3JCb3gpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhUHJpdmF0ZUxhYmVsICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0Z3JlY2FwdGNoYS5yZXNldChwbGFjZU9yZGVyUmVjYXB0Y2hhUHJpdmF0ZUxhYmVsKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVBheW1lbnRNZXRob2RzRXZlbnRzICgpIHtcblx0dmFyIGNjTGlzdFNlbGVjdG9yID0gJyNvcGMtY2MtbGlzdCBpbnB1dFt0eXBlPVwicmFkaW9cIl0nLFxuXHRcdGNjTnVtYmVyU2VsZWN0b3IgPSAnaW5wdXRbbmFtZV49XCJkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfbnVtYmVyXCJdJztcblxuXHQkKGNjTnVtYmVyU2VsZWN0b3IpLnBhcmVudCgpLmFwcGVuZCgnPGRpdiBjbGFzcz1cImNjLWltYWdlXCI+PC9kaXY+Jyk7XG5cdCQoJ2lucHV0W25hbWVePVwiZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19wcml2YXRlTGFiZWxDcmVkaXRfbnVtYmVyXCJdJykucGFyZW50KCkuYXBwZW5kKCc8ZGl2IGNsYXNzPVwiY2MtaW1hZ2VcIj48L2Rpdj4nKTtcblx0XG5cdCRwYXltZW50Rm9ybS5hdHRyKCdzZWxlY3RlZC1wYXltZW50LW1ldGhvZCcsICQoJy5pbnB1dC1yYWRpby5wYXltZW50LW1ldGhvZC1zZWxlY3RvcjpjaGVja2VkJykudmFsKCkpO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCBjY0xpc3RTZWxlY3RvciwgZnVuY3Rpb24gKCkge1xuXHRcdCQoY2NOdW1iZXJTZWxlY3Rvcilcblx0XHRcdC5wYXJlbnQoKVxuXHRcdFx0LmZpbmQoJy5jYy1pbWFnZScpXG5cdFx0XHQuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ3VybCgnICsgJCh0aGlzKS5uZXh0KCkuYXR0cignc3JjJykgKyAnKScpO1xuXHR9KTtcblxuXHRpZiAoJChjY0xpc3RTZWxlY3RvciArICc6Y2hlY2tlZCcpLnZhbCgpKSB7XG5cdFx0JChjY0xpc3RTZWxlY3RvciArICc6Y2hlY2tlZCcpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9XG5cdFxuXHQkcGF5bWVudEZvcm0ub24oJ2NsaWNrJywgJy5wYXltZW50LW1ldGhvZC1zZWxlY3RvcicsIGZ1bmN0aW9uIChlKSB7XG5cdCAgICB2YXIgcGF5bWVudE1ldGhvZElkID0gKCcnICsgJCh0aGlzKS5hdHRyKCdpZCcpKS5yZXBsYWNlKCdpcy0nLCcnKTtcblx0XHRcblx0XHQvLyBSZXNldCBwYXltZW50Rm9ybSBlcnJvcnMgd2hlbiBjaGFuZ2luZyBwYXltZW50IG1ldGhvZCBncm91cHMgXG5cdFx0JHBheW1lbnRGb3JtLnZhbGlkYXRlKCkucmVzZXRGb3JtKCk7XG5cdCAgICBcblx0ICAgIGlmIChwYXltZW50TWV0aG9kSWQpIHtcblx0ICAgIFx0JCgnLnB0X29uZXBjaGVja291dCBpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbChwYXltZW50TWV0aG9kSWQpO1xuXHRcdFx0JHBheW1lbnRGb3JtLmF0dHIoJ3NlbGVjdGVkLXBheW1lbnQtbWV0aG9kJywgcGF5bWVudE1ldGhvZElkKTtcblx0ICAgIFx0XG5cdFx0ICAgICRwYXltZW50Rm9ybS5maW5kKCcucGF5bWVudC1tZXRob2QnKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdCAgICAgICAgJCh0aGlzKS5yZW1vdmVDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKTtcblx0XHQgICAgICAgIFxuXHRcdCAgICAgICAgaWYgKCQodGhpcykuYXR0cignZGF0YS1tZXRob2QnKSA9PSBwYXltZW50TWV0aG9kSWQpIHtcblx0XHQgICAgICAgICAgICAkKHRoaXMpLmFkZENsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpO1xuXHRcdCAgICAgICAgfVxuXHRcdCAgICB9KTtcblx0XHQgICAgXG5cdFx0ICAgIHZhciAkcGF5bWVudE1ldGhvZFBhbmVsID0gJCgnLnBheW1lbnQtbWV0aG9kW2RhdGEtbWV0aG9kPVwiJyArIHBheW1lbnRNZXRob2RJZCArICdcIl0nKTtcblx0XHQgICAgaWYgKCRwYXltZW50TWV0aG9kUGFuZWwuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJykpIHtcblx0XHQgICAgXHQkcGF5bWVudE1ldGhvZFBhbmVsLmZpbmQoJy5jYy1pbWFnZScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICd1cmwoJyArICRwYXltZW50TWV0aG9kUGFuZWwuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJykgKyAnKScpO1xuXHQgICAgXHR9XG5cdCAgICB9XG5cdCAgICBcblx0ICAgIGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRcdCQoW2RvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgZG9jdW1lbnQuYm9keV0pLmFuaW1hdGUoe1xuXHRcdFx0XHQvLyBzY3JvbGxUb3A6ICQoJy5wYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcudG9wLWJhbm5lcicpLmhlaWdodCgpICsgMjBcblx0XHRcdFx0c2Nyb2xsVG9wOiAkKCcjcGF5bWVudFNlY3Rpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcudG9wLWJhbm5lcicpLmhlaWdodCgpIC0gMTVcblx0XHRcdH0sIDI1MCk7XG5cdCAgICB9XG5cdCAgICBcblx0ICAgIGFkZHJlc3Nlcy51cGRhdGVTdW1tYXJ5KCk7XG5cdH0pO1xuXG5cdCQoY2NOdW1iZXJTZWxlY3Rvcikub24oJ2tleWRvd24nLCBmdW5jdGlvbihlKSB7XG5cdFx0JGNyZWRpdENhcmRMaXN0LnZhbCgnJyk7XG5cdH0pO1xuXHRcblx0JChjY051bWJlclNlbGVjdG9yKS5vbigna2V5dXAnLCBmdW5jdGlvbihlKXtcblx0XHR2YXIgY3JlZGl0Q2FyZE51bWJlciA9ICQodGhpcykudmFsKCk7XG5cdFx0XG5cdFx0dmFyIHNlbGVjdGVkQ2FyZCA9IHV0aWwuZ2V0Q3JlZGl0Q2FyZFR5cGUoY3JlZGl0Q2FyZE51bWJlcik7XG5cdFx0aWYgKHNlbGVjdGVkQ2FyZCkge1xuXHRcdFx0JChjY0xpc3RTZWxlY3RvcikuZmlsdGVyKFwiW3ZhbHVlPSdcIisgc2VsZWN0ZWRDYXJkLlBheW1lbnRDYXJkRGlzcGxheUtleSArXCInXVwiKS5lcSgwKS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcuY2MtY2FyZGxpc3Qtc2VsZWN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpLnZhbCgnJyk7XG5cdFx0XHQkKGNjTGlzdFNlbGVjdG9yKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0JHBheW1lbnRGb3JtLmZpbmQoJy5wYXltZW50LW1ldGhvZFtkYXRhLW1ldGhvZD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgKyAnXCJdIC5jYy1pbWFnZScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICcnKTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoJy5hZGQtbmV3LWNhcmQnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKXtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9vd25lclwiXScpLnZhbCgnJyk7XG5cdFx0JCgnaW5wdXRbbmFtZV49XCJkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfbnVtYmVyXCJdJykudmFsKCcnKTtcblx0XHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9jdm5cIl0nKS52YWwoJycpO1xuXHRcdCQoJ2lucHV0W25hbWVePVwiZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2V4cGlyYXRpb25fbW9udGhcIl0nKS52YWwoJycpO1xuXHRcdCQoJ2lucHV0W25hbWVePVwiZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2V4cGlyYXRpb25feWVhclwiXScpLnZhbCgnJyk7XG5cdFx0JCgnI29wYy1jYy1saXN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKTtcblx0XHQkKCcuY2MtY2FyZGxpc3Qtc2VsZWN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpLnZhbCgnJyk7XG5cdFx0JCgnLmNjLWltYWdlJykuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ25vbmUnKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoaXNEaXNhYmxlZCkge1xuXHQkc3VibWl0UGF5bWVudC5hdHRyKCdkaXNhYmxlZCcsIGlzRGlzYWJsZWQpO1x0XG5cdCQoJyNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYXR0cignZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcdFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gc2V0IGNhcnQgZGF0YVxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIGVsZW1lbnQgdGhhdCBwcmVzZW50IGFkZHJlc3Mgb2JqZWN0XG4gKiBAcGFyYW0ge0VsZW1lbnR9IEFjdGlvbiBuYW1lIHRvIGFwcGx5IHRvIGZvcm1cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgc2V0T1BDUGF5bWVudERhdGEgPSBmdW5jdGlvbiAoZm9ybSwgbmFtZSkge1xuICAgIHZhciAkZm9ybSA9ICQoZm9ybSk7XG5cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuc2V0T3BjQWRkcmVzcyksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWVcbiAgICB9KSk7XG59O1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0XG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIChvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlciB8fCBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUmV3YXJkc0NyZWRpdCB8fCBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yR2lmdENhcmRzKSkge1xuICAgIFx0cmVjYXB0Y2hhLmluaXRpYWxpemUoKTtcblx0fVxuXHRHaWZ0Q2FyZC5pbml0aWFsaXplKG9wdGlvbnMpO1xuXHRSZXdhcmRzQ3JlZGl0LmluaXRpYWxpemUob3B0aW9ucyk7XG5cdExveWFsdHlDcmVkaXQuaW5pdGlhbGl6ZShvcHRpb25zKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKG9wdGlvbnMpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBxdWlja3ZpZXcgPSByZXF1aXJlKCcuLi9xdWlja3ZpZXcnKTtcbnZhciBib251c1Byb2R1Y3RzVmlldyA9IHJlcXVpcmUoJy4uL2JvbnVzLXByb2R1Y3RzLXZpZXcnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIGFkZHJlc3NlcyA9IFNpdGVQcmVmZXJlbmNlcy5FTkFCTEVfRU5IQU5DRURfQ0hFQ0tPVVQgPyByZXF1aXJlKCcuL2NoZWNrb3V0L29wY2FkZHJlc3NfZW5oYW5jZWQnKSA6IHJlcXVpcmUoJy4vY2hlY2tvdXQvb3BjYWRkcmVzcycpO1xudmFyIGZvcm1QcmVwYXJlID0gcmVxdWlyZSgnLi9jaGVja291dC9mb3JtUHJlcGFyZScpO1xudmFyIGNhcnQgPSByZXF1aXJlKCcuL2NhcnQnKTtcbnZhciBvcGNwYXltZW50ID0gcmVxdWlyZSgnLi9jaGVja291dC9vcGNwYXltZW50Jyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIEdpZnRDYXJkID0gcmVxdWlyZSgnLi9jaGVja291dC9HaWZ0Q2FyZFBheW1lbnRQYW5lbCcpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFBheW1lbnRWb3VjaGVyUGFuZWw7XG52YXIgcmVjYXB0Y2hhID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9SZWNhcHRjaGEnKTtcbnZhciBSZXdhcmRzQ3JlZGl0ID0gcmVxdWlyZSgnLi9jaGVja291dC9SZXdhcmRzQ3JlZGl0Jyk7XG52YXIgTG95YWx0eUNyZWRpdCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvTG95YWx0eUNyZWRpdCcpO1xudmFyIENoZWNrb3V0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9DaGVja291dENvbnN0YW50cycpO1xudmFyIFBheW1lbnRNZXRob2RDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuUGF5bWVudE1ldGhvZHM7XG52YXIgQm9waXNQcm9kdWN0TGluZUl0ZW1IZWxwZXIgPSByZXF1aXJlKCcuLi9ib3Bpcy9jb21wb25lbnRzL1Byb2R1Y3RMaW5lSXRlbUhlbHBlcicpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxudmFyIGNhcnRJdGVtc0Zvcm1TZWxlY3RvciA9ICdmb3JtI2NhcnQtaXRlbXMtZm9ybSc7XG52YXIgYmlsbGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IgPSAnI2JpbGxpbmdBZGRyZXNzRm9ybSc7XG52YXIgJGJpbGxpbmdBZGRyZXNzRm9ybSA9ICQoYmlsbGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IpO1xudmFyIHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciA9ICcjc2hpcHBpbmdBZGRyZXNzRm9ybSc7XG52YXIgJHNoaXBwaW5nQWRkcmVzc0Zvcm0gPSAkKHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3Rvcik7XG52YXIgcGF5bWVudFNlY3Rpb25TZWxlY3RvciA9ICcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nO1xudmFyICRwYXltZW50U2VjdGlvbiA9ICQocGF5bWVudFNlY3Rpb25TZWxlY3Rvcik7XG52YXIgcGF5bWVudEZvcm1TZWxlY3RvciA9ICcjcGF5bWVudFNlY3Rpb24nO1xudmFyICRwYXltZW50Rm9ybSA9ICQocGF5bWVudEZvcm1TZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZExpc3RTZWxlY3RvciA9ICcjY3JlZGl0Q2FyZExpc3QnO1xudmFyICRjcmVkaXRDYXJkTGlzdCA9ICQoY3JlZGl0Q2FyZExpc3RTZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZFNhdmVDaGVja2JveENvbnRhaW5lclNlbGVjdG9yID0gJ2RpdltmaWVsZD1cInNhdmVDYXJkXCJdJztcbnZhciAkY3JlZGl0Q2FyZFNhdmVDaGVja2JveENvbnRhaW5lciA9ICQoY3JlZGl0Q2FyZFNhdmVDaGVja2JveENvbnRhaW5lclNlbGVjdG9yKTtcbnZhciBjcmVkaXRDYXJkU2F2ZUNoZWNrYm94U2VsZWN0b3IgPSAnI2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9zYXZlQ2FyZCc7XG52YXIgJGNyZWRpdENhcmRTYXZlQ2hlY2tib3ggPSAkKGNyZWRpdENhcmRTYXZlQ2hlY2tib3hTZWxlY3Rvcik7XG52YXIgc3VibWl0UGF5bWVudFNlbGVjdG9yID0gJyNzdWJtaXRPUENQYXltZW50JztcbnZhciAkc3VibWl0UGF5bWVudCA9ICQoc3VibWl0UGF5bWVudFNlbGVjdG9yKTtcbnZhciBiYXNrZXRDb250YWluZXJTZWxlY3RvciA9ICcuYmFza2V0LWNvbnRhaW5lcic7XG52YXIgJGJhc2tldENvbnRhaW5lciA9ICQoYmFza2V0Q29udGFpbmVyU2VsZWN0b3IpO1xuXG52YXIgcGxhY2VPcmRlclJlY2FwdGNoYTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEV2ZW50cyBzaG91bGQgYmUgZGl2aWRlZCB0byBtb2R1bGVzLiBUaGlzIGFsbG93cyByZWluaXRpYWxpemUgZXZlbnRzIGJ5IHNlY3Rpb25zIGFmdGVyIHBhcnRpYWwgcmVsb2FkIFxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGV2ZW50cyBmb3IgdGhlIGdpZnQgcmVnaXN0cmF0aW9uXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMob3B0aW9ucykge1xuXHRpbml0aWFsaXplQ2FydEV2ZW50cyhvcHRpb25zKTtcblx0aW5pdGlhbGl6ZVBheW1lbnRNZXRob2RzRXZlbnRzKCk7XG5cdFxuXHRyZW5kZXJSZWNhcHRjaGEoKTtcblx0JChkb2N1bWVudCkub24oJ1JlY2FwdGNoYS5Mb2FkZWQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICghbG9hZGVkLlJlY2FwdGNoYSkge1xuXHRcdFx0bG9hZGVkLlJlY2FwdGNoYSA9IHRydWU7XG5cdCAgICAgICAgcmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCAgICB9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplQ2FydEV2ZW50cyhvcHRpb25zKSB7XG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICdhLmFkZC10by13aXNobGlzdCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHQvKnJlbW92ZSBuZXh0IGxpbmUgdG8gdXNlIGRlZmF1bHQgZHcgd2lzaGxpc3QgZnVuY3Rpb25hbGl0eSovXG4gICAgXHRyZXR1cm4gZmFsc2U7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcbiAgICBcdGlmIChDdXN0b21lci5hdXRoZW50aWNhdGVkID09IHRydWUpIHtcbiAgICBcdFx0Ly8gcG9zdCBmb3JtIGhlcmVcbiAgICBcdH0gZWxzZSB7XG4gICAgXHRcdCQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHsgc2Nyb2xsVG9wOiAkKCcubG9naW4tZm9ybScpLmVxKDApLm9mZnNldCgpLnRvcH0sIDEwMDApO1xuICAgIFx0fVxuICAgIH0pO1xuXHRcblx0aWYgKFNpdGVQcmVmZXJlbmNlcy5BTFRFUk5BVEVfUElDS1VQX0VOQUJMRUQpIHtcblx0XHRyZW5kZXJBbHRlcm5hdGVQaWNrdXAoKTtcblx0fVxuXG4gICAgJHBheW1lbnRGb3JtLm9uKCdjaGFuZ2UnLCAnW25hbWUkPVwiX2NyZWRpdENhcmRfdHlwZVwiXScsIGZ1bmN0aW9uKCkge1xuICAgIFx0JHN1Ym1pdFBheW1lbnQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICBcdCQodGhpcykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuZmluZCgnZGl2LmZpZWxkLXdyYXBwZXIuZXJyb3InKS5yZW1vdmUoKTtcbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsIHN1Ym1pdFBheW1lbnRTZWxlY3RvciwgZnVuY3Rpb24oZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgXHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikge1xuXHRcdFx0c3VibWl0UGF5bWVudCgpO1x0XG5cdFx0fVxuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdDaGVja291dC5TdWJtaXRQYXltZW50JywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG5cdFx0aWYgKChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyKSB8fCAoZGF0YSAmJiBkYXRhLlN1Ym1pdFBheW1lbnRGb3JCb3BpcykpIHtcblx0XHRcdHN1Ym1pdFBheW1lbnQoZGF0YSk7XG5cdFx0fVxuXHR9KTtcbiAgICBcbiAgICB2YXIgZ2V0Q3JlZGl0Q2FyZEluZm8gPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5iaWxsaW5nR2V0Q3JlZGl0Q2FyZCksXG4gICAgICAgICAgICBkYXRhOiB7IGNyZWRpdENhcmRVVUlEOiBpZCB9XG4gICAgICAgIH0pKTtcbiAgICB9O1xuICAgIFxuICAgICRjcmVkaXRDYXJkTGlzdC5vbignY2hhbmdlJywgZnVuY3Rpb24oKSB7XG4gICAgXHR2YXIgY3JlZGl0Q2FyZFVVSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgIFx0XG4gICAgXHRpZiAoY3JlZGl0Q2FyZFVVSUQubGVuZ3RoIDw9IDApIHtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuICAgIFx0XG4gICAgXHRnZXRDcmVkaXRDYXJkSW5mbyhjcmVkaXRDYXJkVVVJRCkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWFza2VkTnVtYmVyJykpIHtcblx0XHRcdFx0dmFyICRwYXltZW50TWV0aG9kR3JvdXAgPSAkKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXScpO1xuXHRcdFx0XHR2YXIgJHBheW1lbnRNZXRob2QgPSAkcGF5bWVudE1ldGhvZEdyb3VwLmZpbmQoJy5wYXltZW50LW1ldGhvZFtwYXltZW50LW1ldGhvZD1cIicgKyBkYXRhLnBheW1lbnRNZXRob2QgKyAnXCJdJyk7XG5cblx0XHRcdFx0dmFyIHBheW1lbnRNZXRob2RSYWRpb1RvU2VsZWN0ID0gZGF0YS5wYXltZW50TWV0aG9kID09IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCA/IGRhdGEudHlwZSA6IGRhdGEucGF5bWVudE1ldGhvZDtcblx0XHRcdFx0JHBheW1lbnRNZXRob2RHcm91cC5maW5kKCdpbnB1dFt0eXBlPVwicmFkaW9cIl1bdmFsdWU9XCInICsgcGF5bWVudE1ldGhvZFJhZGlvVG9TZWxlY3QgKyAnXCJdJykuZmlyc3QoKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSkudHJpZ2dlcignY2hhbmdlJywgeyBkb1Jlc2V0OiBmYWxzZSB9KTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmICgkcGF5bWVudE1ldGhvZC5maW5kKCdbaWQqPVwiX2NyZWRpdENhcmRfb3duZXJcIl0nKS5sZW5ndGggPiAwICYmIGRhdGEuaGFzT3duUHJvcGVydHkoJ2hvbGRlcicpKSB7XG5cdFx0XHRcdFx0JHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX293bmVyXCJdJykudmFsKGRhdGEuaG9sZGVyKS52YWxpZCgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JCgnLnB0X29uZXBjaGVja291dCBpbnB1dFtuYW1lKj1cIl9jcmVkaXRDYXJkX3R5cGVcIl0nKS52YWwoZGF0YS50eXBlKTtcblx0XHRcdFx0JHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9udW1iZXJcIl0nKS52YWwoZGF0YS5tYXNrZWROdW1iZXIpLnZhbGlkKCk7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoJHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX2V4cGlyYXRpb25fbW9udGhcIl0nKS5sZW5ndGggPiAwICYmIGRhdGEuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25Nb250aCcpKSB7XG5cdFx0XHRcdFx0JHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX2V4cGlyYXRpb25fbW9udGhcIl0nKS52YWwoZGF0YS5leHBpcmF0aW9uTW9udGgpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoJHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX2V4cGlyYXRpb25feWVhclwiXScpLmxlbmd0aCA+IDAgJiYgZGF0YS5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJhdGlvblllYXInKSkge1xuXHRcdFx0XHRcdCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX3llYXJcIl0nKS52YWwoZGF0YS5leHBpcmF0aW9uWWVhcikudHJpZ2dlcignY2hhbmdlJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmICgkcGF5bWVudE1ldGhvZC5maW5kKCdbaWQqPVwiX2NyZWRpdENhcmRfY3ZuXCJdJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9jdm5cIl0nKS52YWwoJycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JGNyZWRpdENhcmRTYXZlQ2hlY2tib3hDb250YWluZXIuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdH0uYmluZCh0aGlzKSk7XHRcbiAgICB9KTtcbiAgICBcblx0aWYgKCRjcmVkaXRDYXJkTGlzdC5sZW5ndGggPiAwICYmICgkKCcucHRfb25lcGNoZWNrb3V0IGlucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCkgPT0gUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkIHx8ICQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoKSA9PSBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkFsbGlhbmNlRGF0YSkpIHtcblx0XHQkY3JlZGl0Q2FyZExpc3QuZmluZCgnb3B0aW9uJykuZXEoMSkucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHQkY3JlZGl0Q2FyZExpc3QudHJpZ2dlcignY2hhbmdlJyk7XG5cdFx0JGNyZWRpdENhcmRTYXZlQ2hlY2tib3hDb250YWluZXIuaGlkZSgpO1xuXHR9IGVsc2Uge1xuXHRcdCRjcmVkaXRDYXJkU2F2ZUNoZWNrYm94Q29udGFpbmVyLnNob3coKTtcblx0fVxuXHRcbiAgICBhZGRyZXNzZXMuaW5pdChvcHRpb25zKTtcbiAgICBjYXJ0LmluaXQob3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckFsdGVybmF0ZVBpY2t1cCgpIHtcblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICdidXR0b24uYWx0LXBpY2t1cC1idXR0b24nKS5vbignY2xpY2snLCAnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLmFkZENsYXNzKCdhY3RpdmUtbW9kYWwnKS5zaG93KCk7XG5cdFx0JCgnZmllbGRzZXQgc3BhbicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcblx0XHQkKCcub25lLXJlcXVpcmVkJykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljaycsICcjYWx0LXBpY2t1cC1tb2RhbCAuY2xvc2UtbW9kYWwnKS5vbignY2xpY2snLCAnI2FsdC1waWNrdXAtbW9kYWwgLmNsb3NlLW1vZGFsJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUtbW9kYWwnKS5oaWRlKCk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJmaXJzdE5hbWVcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCgnLmZpcnN0bmFtZS1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignZm9jdXMnLCAnaW5wdXRbbmFtZT1cImxhc3ROYW1lXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5sYXN0bmFtZS1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignZm9jdXMnLCAnaW5wdXRbbmFtZT1cImVtYWlsXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5lbWFpbC1lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvci1tc2cnKTtcblx0XHQkKCcub25lLXJlcXVpcmVkJykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJwaG9uZVwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcucGhvbmUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uI2FsdFBpY2t1cFN1Ym1pdCcpLm9uKCdjbGljaycsICdidXR0b24jYWx0UGlja3VwU3VibWl0JywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcbiAgICBcdHZhciBpc0ZpcnN0TmFtZVZhbGlkID0gdHJ1ZTtcblx0XHR2YXIgZmlyc3ROYW1lID0gJCgnaW5wdXRbbmFtZT1cImZpcnN0TmFtZVwiXScpLnZhbCgpO1xuXHRcdHZhciByZWdleE5hbWUgPSAvXlthLXogLC4nLV0rJC9pO1xuXHRcdGlmIChmaXJzdE5hbWUubGVuZ3RoID09IDAgfHwgZmlyc3ROYW1lLm1hdGNoKHJlZ2V4TmFtZSkgPT0gbnVsbCkge1xuXHRcdFx0aXNGaXJzdE5hbWVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLmZpcnN0bmFtZS1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIGlzTGFzdE5hbWVWYWxpZCA9IHRydWU7XHRcdFxuXHRcdHZhciBsYXN0TmFtZSA9JCgnaW5wdXRbbmFtZT1cImxhc3ROYW1lXCJdJykudmFsKCk7XG5cdFx0aWYgKGxhc3ROYW1lLmxlbmd0aCA9PSAwIHx8IGxhc3ROYW1lLm1hdGNoKHJlZ2V4TmFtZSkgPT0gbnVsbCkge1xuXHRcdFx0aXNMYXN0TmFtZVZhbGlkID0gZmFsc2U7XG5cdFx0XHQkKCcubGFzdG5hbWUtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciBpc0VtYWlsVmFsaWQgPSB0cnVlO1x0XHRcblx0XHR2YXIgZW1haWwgPSAkKCdpbnB1dFtuYW1lPVwiZW1haWxcIl0nKS52YWwoKTtcblx0XHR2YXIgcmVnZXhFbWFpbCA9IC9eW2EtekEtWjAtOS4hIyQlJicqKy89P15fYHt8fX4tXStAW2EtekEtWjAtOS1dKyg/OlxcLlthLXpBLVowLTktXSspKiQvZztcblx0XHRpZiAoZW1haWwubGVuZ3RoID4gMCAmJiBlbWFpbC5tYXRjaChyZWdleEVtYWlsKSA9PSBudWxsKSB7XG5cdFx0XHRpc0VtYWlsVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5lbWFpbC1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cblx0XHR2YXIgaXNQaG9uZVZhbGlkID0gdHJ1ZTtcblx0XHR2YXIgcGhvbmUgPSAkKCdpbnB1dFtuYW1lPVwicGhvbmVcIl0nKS52YWwoKS5yZXBsYWNlKC9cXEQvZywgJycpO1xuXHRcdHZhciByZWdleFBob25lID0gL15cXCs/XFwoPyhbMC05XVswLThdWzAtOV0pXFwpP1tcXC1cXC4gXT8oWzItOV1bMC05XXsyfSlbXFwtXFwuIF0/KFswLTldezR9KShcXHMqeFswLTldKyk/JC9nO1xuXHRcdGlmIChwaG9uZS5sZW5ndGggPiAwICYmIHBob25lLm1hdGNoKHJlZ2V4UGhvbmUpID09IG51bGwpIHtcblx0XHRcdGlzUGhvbmVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLnBob25lLWVycm9yJykuYWRkQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdH1cblx0XHRcbiAgICBcdGlmIChlbWFpbC5sZW5ndGggPT0gMCAmJiBwaG9uZS5sZW5ndGggPT0gMCkge1xuICAgIFx0XHQkKCcub25lLXJlcXVpcmVkJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgXHRcdGlzRW1haWxWYWxpZCA9IGZhbHNlO1xuICAgIFx0XHRpc1Bob25lVmFsaWQgPSBmYWxzZTtcbiAgICBcdH1cbiAgICBcdFxuICAgIFx0aWYgKCFpc0VtYWlsVmFsaWQgfHwgIWlzUGhvbmVWYWxpZCkge1xuICAgIFx0XHRyZXR1cm47XG4gICAgXHR9XG4gICAgXHRcblx0XHRpZiAoaXNGaXJzdE5hbWVWYWxpZCAmJiBpc0xhc3ROYW1lVmFsaWQgJiYgKGlzRW1haWxWYWxpZCB8fCBpc1Bob25lVmFsaWQpKSB7XG5cdFx0XHR2YXIgY2xlYW5QaG9uZSA9IHBob25lLnJlcGxhY2UoL1xcRC9nLCAnJyk7XG5cdFx0XHR2YXIgc2hpcG1lbnRJRCA9ICQoJy5hbHRlcm5hdGUtcGlja3VwJykuY2xvc2VzdChcImZvcm1cIikuYXR0cignc2hpcG1lbnQnKTtcblx0XHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLnNldEFsdGVybmF0ZVBpY2t1cCxcblx0XHRcdFx0dHlwZTogXCJnZXRcIixcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdHNoaXBtZW50SUQ6IHNoaXBtZW50SUQsXG5cdFx0XHRcdFx0YWx0UGlja3VwRmlyc3ROYW1lOiBmaXJzdE5hbWUsXG5cdFx0XHRcdFx0YWx0UGlja3VwTGFzdE5hbWU6IGxhc3ROYW1lLFxuXHRcdFx0XHRcdGFsdFBpY2t1cEVtYWlsOiBlbWFpbCxcblx0XHRcdFx0XHRhbHRQaWNrdXBQaG9uZTogY2xlYW5QaG9uZVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09ICdzdWNjZXNzJykge1xuXHRcdFx0XHRcdFx0JCgnc3Bhbi5hbHQtcGVyc29uJykuYXR0cignZGF0YS1maXJzdG5hbWUnLCBmaXJzdE5hbWUpLmF0dHIoJ2RhdGEtbGFzdG5hbWUnLCBsYXN0TmFtZSkuYXR0cignZGF0YS1lbWFpbCcsIGVtYWlsKS5hdHRyKCdkYXRhLXBob25lJywgY2xlYW5QaG9uZSk7XG5cdFx0XHRcdFx0XHRkaXNwbGF5QWx0ZXJuYXRlUGlja3VwIChmaXJzdE5hbWUgKyAnICcgKyBsYXN0TmFtZSlcblx0XHRcdFx0XHRcdCQoJyNhbHQtcGlja3VwLW1vZGFsJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZS1tb2RhbCcpLmhpZGUoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcblx0XHRcdFx0XHRjb25zb2xlLmxvZyh0ZXh0U3RhdHVzLCBlcnJvclRocm93bik7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZGlzcGxheUFsdGVybmF0ZVBpY2t1cCAoZnVsbE5hbWUpIHtcblx0JCgnLmFsdGVybmF0ZS1waWNrdXAgc3Bhbi5hbHQtcGVyc29uJykudGV4dChmdWxsTmFtZSk7XG5cdCQoJ3NwYW4uYWx0LWhlYWRlcicpLnNob3coKTtcblx0JCgnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJykudGV4dCgnVVBEQVRFJyk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYSgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI3N1Ym1pdE9QQ1BheW1lbnQnKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSAmJiBwbGFjZU9yZGVyUmVjYXB0Y2hhID09IHVuZGVmaW5lZCkge1xuXHRcdHBsYWNlT3JkZXJSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcignc3VibWl0T1BDUGF5bWVudCcsIHtcblx0ICAgICAgICAnc2l0ZWtleSc6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgJ2NhbGxiYWNrJzogc3VibWl0UGF5bWVudCxcblx0ICAgICAgICAnYmFkZ2UnOiAnYm90dG9tbGVmdCdcblx0ICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdFBheW1lbnRSZWNhcHRjaGFFcnJvcigpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI3N1Ym1pdE9QQ1BheW1lbnQnKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSAmJiBwbGFjZU9yZGVyUmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYSk7XG5cdFx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc3VibWl0UGF5bWVudChkYXRhKSB7XG5cdHZhciBiYWxhbmNlRHVlID0gcGFyc2VGbG9hdCgkcGF5bWVudFNlY3Rpb24uYXR0cignYmFsYW5jZS1kdWUnKSk7XG5cdCRzdWJtaXRQYXltZW50LmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2UsXG5cdFx0TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkNoZWNrb3V0LlBsYWNpbmdPcmRlclxuXHR9KTtcblx0JHN1Ym1pdFBheW1lbnQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cblx0JGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFxuXHR2YXIgJGNyZWRpdENhcmRUeXBlID0gJHBheW1lbnRGb3JtLmZpbmQoJ1tuYW1lJD1cIl9jcmVkaXRDYXJkX3R5cGVcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHRpZiAoYmFsYW5jZUR1ZSA+IDApIHtcblx0XHQkcGF5bWVudEZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0XG5cdFx0aWYgKHR5cGVvZiAkY3JlZGl0Q2FyZFR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgXHRcdCRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuZmluZCgnZGl2LmZpZWxkLXdyYXBwZXIuZXJyb3InKS5yZW1vdmUoKTtcblxuICAgIFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgXHRcdFx0JHBheW1lbnRGb3JtLmZpbmQoJ1tuYW1lJD1cIl9jcmVkaXRDYXJkX3R5cGVcIl0nKS5jbG9zZXN0KCdkaXYuZm9ybS1yb3cnKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJmaWVsZC13cmFwcGVyIGVycm9yXCIgc3R5bGU9XCJoZWlnaHQ6MHB4O1wiPjxzcGFuIGNsYXNzPVwiZXJyb3JcIj4nICsgUmVzb3VyY2VzLlJFUVVJUkVEX0ZJRUxEICsgJzwvc3Bhbj48L2Rpdj4nKTtcbiAgICBcdFx0fSwgNTApO1xuXHRcdH1cblx0fVxuXHRcblx0Ly8gY2hlY2sgZmlyc3QgaWYgYWRkcmVzc2VzIGFyZSB2YWxpZFxuXHR2YXIgaXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdHZhciBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdFxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdFxuXHRpZiAoJGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0aXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gdHJ1ZTtcblx0fSBlbHNlIHtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXQucmVxdWlyZWQuZmllbGQuZXJyb3InKS5lcSgwKS5mb2N1cygpO1xuXHR9XG5cdFxuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSB8fCAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZC5pc1N0b3JlIGlucHV0JykucHJvcCgnY2hlY2tlZCcpICYmICRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQubXlTdG9yZUlEIGlucHV0JykudmFsKCkpKSB7XG5cdFx0aXNTaGlwcGluZ0FkZHJlc3NWYWxpZCA9IHRydWU7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcblx0fVxuXHRcblx0dmFyIGlzQm9waXNWYWxpZCA9IGZhbHNlO1xuXHRpZiAoZGF0YSAmJiBkYXRhLlN1Ym1pdFBheW1lbnRGb3JCb3Bpcykge1xuXHRcdGlzQm9waXNWYWxpZCA9IGRhdGEuSXNCb3Bpc0ludmVudG9yeVZhbGlkO1xuXHR9IGVsc2Uge1xuXHRcdHZhciAkYm9waXNQcm9kdWN0TGluZUl0ZW1zID0gJChjYXJ0SXRlbXNGb3JtU2VsZWN0b3IpLmZpbmQoJy5ib3Bpcy1wcm9kdWN0LWxpbmUtaXRlbVtza3VdW3N0b3JlXScpO1xuXHRcdFxuXHRcdGlmICgkYm9waXNQcm9kdWN0TGluZUl0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdEJvcGlzUHJvZHVjdExpbmVJdGVtSGVscGVyLlZhbGlkYXRlUHJvZHVjdExpbmVJdGVtcygkKGNhcnRJdGVtc0Zvcm1TZWxlY3RvcikuZmluZCgnLmJvcGlzLXByb2R1Y3QtbGluZS1pdGVtW3NrdV1bc3RvcmVdJyksIHsgU3VjY2Vzc0V2ZW50OiAnQ2hlY2tvdXQuU3VibWl0UGF5bWVudCcgfSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlzQm9waXNWYWxpZCA9IHRydWU7XG5cdFx0fVxuXHR9XG5cdFxuXHRpZiAoaXNCaWxsaW5nQWRkcmVzc1ZhbGlkICYmIGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgJiYgaXNCb3Bpc1ZhbGlkICYmICQoJyNzaGlwcGluZy1tZXRob2QtbGlzdCBpbnB1dDpjaGVja2VkJykubGVuZ3RoICYmIChiYWxhbmNlRHVlID09IDAgfHwgJHBheW1lbnRGb3JtLnZhbGlkKCkpKSB7XG5cdFx0dmFyICRwYXltZW50Rm9ybVRvU2V0ID0gJHBheW1lbnRGb3JtLmNsb25lKCk7XG5cdFx0dmFyIGFjdGlvbk5hbWUgPSAkc3VibWl0UGF5bWVudC5hdHRyKCduYW1lJyk7XG5cdFx0XG5cdFx0dmFyIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkID0gJHBheW1lbnRGb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwic2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoKTtcblx0XHQkcGF5bWVudEZvcm1Ub1NldC5maW5kKCdkaXZbcGF5bWVudC1tZXRob2RdJykubm90KCdkaXZbcGF5bWVudC1tZXRob2Q9XCInICsgc2VsZWN0ZWRQYXltZW50TWV0aG9kSWQgKyAnXCJdJykucmVtb3ZlKCk7XG5cdFx0XG5cdFx0JHBheW1lbnRGb3JtVG9TZXQuZmluZCgnc2VsZWN0JykuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcblx0XHRcdCQodGhpcykudmFsKCRwYXltZW50Rm9ybS5maW5kKCcjJyArICQodGhpcykuYXR0cignaWQnKSkudmFsKCkpO1xuXHRcdH0pO1xuXHRcdFxuXHRcdHNldE9QQ1BheW1lbnREYXRhKCRwYXltZW50Rm9ybVRvU2V0LCBhY3Rpb25OYW1lKS50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0ZGF0YSA9IHJlc3BvbnNlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdzdWNjZXNzJykge1xuXHRcdFx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFx0XHR2YWx1ZTogYmFsYW5jZUR1ZSxcblx0XHRcdFx0XHRwYXltZW50X3R5cGU6IHNlbGVjdGVkUGF5bWVudE1ldGhvZElkXG5cdFx0XHRcdH1cblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQWRkUGF5bWVudEluZm8nLCBkYXRhT2JqZWN0KS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmIChvcHRpb25zLkNoZWNrb3V0TW9kZSA9PSAnTW9iaWxlQXBwJykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2VGb3JNb2JpbGVBcHA7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSkuY2F0Y2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKG9wdGlvbnMuQ2hlY2tvdXRNb2RlID09ICdNb2JpbGVBcHAnKSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZUZvck1vYmlsZUFwcDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdhZmZpcm1SZWRpcmVjdCcpIHtcblx0XHRcdFx0dmFyIF9hZmZpcm1fY29uZmlnID0ge1xuXHRcdFx0XHRcdHB1YmxpY19hcGlfa2V5OiBkYXRhLmFmZmlybS5QdWJsaWNBcGlLZXksXG5cdFx0XHRcdFx0c2NyaXB0OiBkYXRhLmFmZmlybS5TY3JpcHRcblx0XHRcdFx0fTtcblx0XHRcdFx0KGZ1bmN0aW9uKGwsZyxtLGUsYSxmLGIpe3ZhciBkLGM9bFttXXx8e30saD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KGYpLG49ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZilbMF0saz1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGZ1bmN0aW9uKCl7YVtiXS5fLnB1c2goW2MsYXJndW1lbnRzXSl9fTtjW2VdPWsoYyxlLFwic2V0XCIpO2Q9Y1tlXTtjW2FdPXt9O2NbYV0uXz1bXTtkLl89W107Y1thXVtiXT1rKGMsYSxiKTthPTA7Zm9yKGI9XCJzZXQgYWRkIHNhdmUgcG9zdCBvcGVuIGVtcHR5IHJlc2V0IG9uIG9mZiB0cmlnZ2VyIHJlYWR5IHNldFByb2R1Y3RcIi5zcGxpdChcIiBcIik7YTxiLmxlbmd0aDthKyspZFtiW2FdXT1rKGMsZSxiW2FdKTthPTA7Zm9yKGI9W1wiZ2V0XCIsXCJ0b2tlblwiLFwidXJsXCIsXCJpdGVtc1wiXTthPGIubGVuZ3RoO2ErKylkW2JbYV1dPWZ1bmN0aW9uKCl7fTtoLmFzeW5jPSEwO2guc3JjPWdbZl07bi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShoLG4pO2RlbGV0ZSBnW2ZdO2QoZyk7bFttXT1jfSkod2luZG93LF9hZmZpcm1fY29uZmlnLFwiYWZmaXJtXCIsXCJjaGVja291dFwiLFwidWlcIixcInNjcmlwdFwiLFwicmVhZHlcIik7XG5cdFx0XHRcdFxuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQoSlNPTi5wYXJzZShkYXRhLmFmZmlybS5BZmZpcm1DaGVja291dCkpO1xuXHRcdFx0XHRhZmZpcm0uY2hlY2tvdXQucG9zdCgpO1xuXHRcdFx0XHRhZmZpcm0udWkucmVhZHkoXG5cdFx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRhZmZpcm0udWkuZXJyb3Iub24oXCJjbG9zZVwiLCBmdW5jdGlvbigpe1xuXHRcdFx0XHRcdFx0XHQvLyB3aW5kb3cubG9jYXRpb24ucmVwbGFjZShkYXRhLmFmZmlybS5SZWRpcmVjdFVybCk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpIHtcblx0XHRcdFx0dmFyIHBvcHVwID0gcmVxdWlyZSgnLi4vcG9wdXAnKTtcblx0XHRcdFx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cblx0XHRcdFx0dmFyIGxpc3QgPSAkLm1hcChwYXlsb2FkLmxpc3QsIGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0XHRcdHJldHVybiAnPGxpPicgKyBlbC5uYW1lICsgJzo8YnI+JyArIGVsLm1lc3NhZ2UgKyAnPC9saT4nO1xuXHRcdFx0XHR9KS5qb2luKCcnKTtcblx0XHRcdFx0XG5cdFx0XHRcdHBvcHVwLmluaXQoe1xuXHRcdFx0XHRcdHRpdGxlOiBwYXlsb2FkLnRpdGxlLFxuXHRcdFx0XHRcdGNvbnRlbnQ6IHBheWxvYWQubWVzc2FnZSArICc8dWwgY2xhc3M9XCJzaGlwcGluZy1yZXN0cmljdGlvbnMtcG9wdXBfX2xpc3RcIj4nICsgbGlzdCArICc8L3VsPicsXG5cdFx0XHRcdH0pLnNob3dQb3B1cCgpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ0JpbGxpbmdBZGRyZXNzRXJyb3InKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpID8gZGF0YS5tZXNzYWdlIDogUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPkJpbGxpbmcgQWRkcmVzcyBFcnJvcjo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ1NoaXBwaW5nQWRkcmVzc0Vycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5TaGlwcGluZyBBZGRyZXNzIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnVmFsaWRhdGlvbkVycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5WYWxpZGF0aW9uIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5QYXltZW50IERlY2xpbmVkOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCRzdWJtaXRQYXltZW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdCRzdWJtaXRQYXltZW50LmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdFx0c3VibWl0UGF5bWVudFJlY2FwdGNoYUVycm9yKCk7XG5cdFx0fSkuY2F0Y2goZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdGlmIChyZXNwb25zZS5zdGF0dXMgPT0gMzAyICYmIHJlc3BvbnNlLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gcmVzcG9uc2UucmVzcG9uc2VUZXh0O1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdCRzdWJtaXRQYXltZW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHQkc3VibWl0UGF5bWVudC5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuXHRcdC8vIEFkZGluZyBBREEgY29tcGxpYW5jZSBlcnJvciBtZXNzYWdlcyBmb3Igc3VibWl0UGF5bWVudCBzZWN0aW9uXG5cdFx0JHBheW1lbnRGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcdGlmICgkcGF5bWVudEZvcm0uZmluZCgnLmZpZWxkLmVycm9yJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcblx0XHRcdHZhciBwYXltZW50Rm9ybUVycm9yTWVzc2FnZXMgPSBvcGNwYXltZW50LmdldEVycm9yTWVzc2FnZXMoJHBheW1lbnRGb3JtKTtcblx0XHRcdHZhciBwYXltZW50Rm9ybUVycm9yQm94ID0gb3BjcGF5bWVudC5lcnJvckJveCgnQ2Fubm90IFByb2NlZWQnLCAnUGxlYXNlIGZpeCB0aGUgZm9sbG93aW5nIGVycm9yczonLCBwYXltZW50Rm9ybUVycm9yTWVzc2FnZXMpO1xuXHRcdFx0aWYgKHBheW1lbnRGb3JtRXJyb3JCb3gpIHtcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIocGF5bWVudEZvcm1FcnJvckJveCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0c3VibWl0UGF5bWVudFJlY2FwdGNoYUVycm9yKCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVBheW1lbnRNZXRob2RzRXZlbnRzKCkge1xuXHR2YXIgY3JlZGl0Q2FyZExpc3RTZWxlY3RvciA9ICcucGF5bWVudC1jYXJkLWxpc3Qgc2VsZWN0LCAucGF5bWVudC1jYXJkLWxpc3QgaW5wdXRbdHlwZT1cInJhZGlvXCJdJztcblx0dmFyIGNyZWRpdENhcmROdW1iZXJJbnB1dCA9ICdpbnB1dFtuYW1lKj1cIl9jcmVkaXRDYXJkX251bWJlclwiXSwgaW5wdXRbbmFtZSo9XCJfcHJpdmF0ZUxhYmVsQ3JlZGl0X251bWJlclwiXSc7XG5cdFxuXHQkKGNyZWRpdENhcmROdW1iZXJJbnB1dCkucGFyZW50KCkuYXBwZW5kKCc8ZGl2IGNsYXNzPVwiY2MtaW1hZ2VcIj48L2Rpdj4nKTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCBjcmVkaXRDYXJkTGlzdFNlbGVjdG9yLCBmdW5jdGlvbiAoZSwgb3B0aW9ucykge1x0XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblxuXHRcdG9wdGlvbnMgPSBvcHRpb25zICE9IHVuZGVmaW5lZCA/IG9wdGlvbnMgOiB7fTtcblx0XHRvcHRpb25zLmRvUmVzZXQgPSBvcHRpb25zLmRvUmVzZXQgIT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kb1Jlc2V0IDogdHJ1ZTtcblx0XHRcblx0XHR2YXIgc2VsZWN0ZWRDcmVkaXRDYXJkVHlwZSA9ICR0aGlzLnZhbCgpO1xuXHRcdFxuXHRcdGlmIChzZWxlY3RlZENyZWRpdENhcmRUeXBlKSB7XG5cdFx0XHR2YXIgc2VsZWN0ZWRQYXltZW50TWV0aG9kSWQgPSAkdGhpcy5hdHRyKCdwYXltZW50LW1ldGhvZCcpIHx8ICR0aGlzLmZpbmQoJzpzZWxlY3RlZCcpLmF0dHIoJ3BheW1lbnQtbWV0aG9kJyk7XG5cdFx0XHR2YXIgc2VsZWN0ZWRQYXltZW50Q2FyZEltYWdlVXJsID0gJHRoaXMuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJykgfHwgJHRoaXMuZmluZCgnOnNlbGVjdGVkJykuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJyk7XG5cdFx0XHRcblx0XHRcdCRwYXltZW50Rm9ybS5hdHRyKCdzZWxlY3RlZC1wYXltZW50LW1ldGhvZCcsIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkKTtcblx0XHRcdCR0aGlzLmNsb3Nlc3QoJ1twYXltZW50LW1ldGhvZC1ncm91cF0nKS5hdHRyKCdwYXltZW50LW1ldGhvZCcsIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkKTtcblx0XHRcdFxuXHRcdFx0JCgnLnB0X29uZXBjaGVja291dCBpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbChzZWxlY3RlZFBheW1lbnRNZXRob2RJZCk7XG5cblx0XHRcdGlmICghJCgnW3BheW1lbnQtbWV0aG9kPVwiJyArIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkICsgJ1wiXS5wYXltZW50LW1ldGhvZCcpLmhhc0NsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpKSB7XG5cdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZCcpLnJlbW92ZUNsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLmhpZGUoKTtcblx0XHRcdFx0JCgnW3BheW1lbnQtbWV0aG9kPVwiJyArIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkICsgJ1wiXS5wYXltZW50LW1ldGhvZCcpLmFkZENsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLnNob3coKTtcdFxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkKCcucGF5bWVudC1jYXJkLWxpc3QuZ3JpZCcpLmZpbmQoJ1twYXltZW50LWNhcmRdJykuaGlkZSgpO1xuXHRcdFx0JCgnLnBheW1lbnQtY2FyZC1saXN0LmdyaWQnKS5maW5kKCdbcGF5bWVudC1jYXJkPVwiJyArIHNlbGVjdGVkQ3JlZGl0Q2FyZFR5cGUgKyAnXCJdJykuc2hvdygpO1xuXHRcdFx0XG5cdFx0XHQkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpLmZpbHRlcignaW5wdXRbdmFsdWU9XCInICsgc2VsZWN0ZWRDcmVkaXRDYXJkVHlwZSArICdcIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0XHQkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpLmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBzZWxlY3RlZENyZWRpdENhcmRUeXBlICsgJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cblx0XHRcdCRwYXltZW50Rm9ybS5maW5kKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXSAuY2MtaW1hZ2UnKS5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAndXJsKCcgKyBzZWxlY3RlZFBheW1lbnRDYXJkSW1hZ2VVcmwgKyAnKScpO1xuXHRcdFx0XG5cdFx0XHRpZiAob3B0aW9ucy5kb1Jlc2V0KSB7XG5cdFx0XHRcdHJlc2V0Q3JlZGl0Q2FyZEZpZWxkcygkKCdbcGF5bWVudC1tZXRob2Q9XCInICsgc2VsZWN0ZWRQYXltZW50TWV0aG9kSWQgKyAnXCJdLnBheW1lbnQtbWV0aG9kJykpO1xuXHRcdFx0XHQkY3JlZGl0Q2FyZExpc3QudmFsKCcnKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXHRcblx0JHBheW1lbnRGb3JtLm9uKCdjbGljaycsICcucGF5bWVudC1tZXRob2QtZ3JvdXAtc2VsZWN0b3InLCBmdW5jdGlvbiAoZSkge1xuXHQgICAgdmFyIHBheW1lbnRNZXRob2RHcm91cElkID0gJCh0aGlzKS52YWwoKTtcblx0ICAgIFxuXHQgICAgaWYgKHBheW1lbnRNZXRob2RHcm91cElkKSB7XG5cdCAgICBcdCRwYXltZW50Rm9ybS5hdHRyKCdzZWxlY3RlZC1wYXltZW50LW1ldGhvZC1ncm91cCcsIHBheW1lbnRNZXRob2RHcm91cElkKTtcblx0XHQgICAgXG5cdFx0ICAgICQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIHBheW1lbnRNZXRob2RHcm91cElkICsgJ1wiXScpLmF0dHIoJ3BheW1lbnQtbWV0aG9kJykpO1xuXHRcdCAgICBcblx0XHQgICAgJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwXScpLmhpZGUoKS5yZW1vdmVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHQgICAgJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIHBheW1lbnRNZXRob2RHcm91cElkICsgJ1wiXScpLnNob3coKS5hZGRDbGFzcygnZXhwYW5kZWQnKTtcblx0XHQgICAgXG5cdFx0ICAgIGlmICgkKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgcGF5bWVudE1ldGhvZEdyb3VwSWQgKyAnXCJdJykuZmluZCgnLnBheW1lbnQtbWV0aG9kLWV4cGFuZGVkJykubGVuZ3RoIDwgMSkge1xuXHRcdCAgICBcdHZhciAkZGVmYXVsdFBheW1lbnRNZXRob2QgPSAkKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgcGF5bWVudE1ldGhvZEdyb3VwSWQgKyAnXCJdJykuZmluZCgnLnBheW1lbnQtbWV0aG9kJykuZmlyc3QoKTtcblx0XHQgICAgXHRcblx0XHQgICAgXHQkZGVmYXVsdFBheW1lbnRNZXRob2QuYWRkQ2xhc3MoJ3BheW1lbnQtbWV0aG9kLWV4cGFuZGVkJykuc2hvdygpO1xuXHRcdCAgICBcdFxuXHRcdCAgICBcdGlmICgkZGVmYXVsdFBheW1lbnRNZXRob2QuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJykpIHtcblx0XHQgICAgXHRcdCRkZWZhdWx0UGF5bWVudE1ldGhvZC5maW5kKCcuY2MtaW1hZ2UnKS5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAndXJsKCcgKyAkZGVmYXVsdFBheW1lbnRNZXRob2QuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJykgKyAnKScpO1xuXHRcdCAgICBcdH1cblx0XHQgICAgfVxuXHRcdCAgICBcblx0XHQgICAgaWYgKHdpbmRvdy5pbm5lcldpZHRoIDw9IDc2Nykge1xuXHRcdFx0XHQkKFtkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIGRvY3VtZW50LmJvZHldKS5hbmltYXRlKHtcblx0XHRcdFx0XHQvLyBzY3JvbGxUb3A6ICQoJy5wYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcudG9wLWJhbm5lcicpLmhlaWdodCgpICsgMjBcblx0XHRcdFx0XHRzY3JvbGxUb3A6ICQoJyNwYXltZW50U2VjdGlvbicpLm9mZnNldCgpLnRvcCAtICQoJy50b3AtYmFubmVyJykuaGVpZ2h0KCkgLSAxNVxuXHRcdFx0XHR9LCAyNTApO1xuXHRcdCAgICB9XG5cdFx0ICAgIFxuXHRcdCAgICAvLyBhZGRyZXNzZXMudXBkYXRlU3VtbWFyeSgpO1xuXHQgICAgfVxuXHR9KTtcblx0XG5cdCQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgKyAnXCJdIFtjcmVkaXQtY2FyZC1udW1iZXItaW5wdXRdJykub24oJ2tleWRvd24nLCBmdW5jdGlvbihlKSB7XG5cdFx0JGNyZWRpdENhcmRMaXN0LnZhbCgnJyk7XG5cdH0pO1xuXG5cdCQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgKyAnXCJdIFtjcmVkaXQtY2FyZC1udW1iZXItaW5wdXRdJykub24oJ2tleXVwJywgZnVuY3Rpb24oZSkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIGNyZWRpdENhcmROdW1iZXIgPSAkdGhpcy52YWwoKTtcblx0XHRcblx0XHR2YXIgc2VsZWN0ZWRDYXJkID0gdXRpbC5nZXRDcmVkaXRDYXJkVHlwZShjcmVkaXRDYXJkTnVtYmVyKTtcblx0XHRpZiAoc2VsZWN0ZWRDYXJkKSB7XG5cdFx0XHR2YXIgJHNlbGVjdGVkQ2FyZE51bWJlcklucHV0ID0gJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCArICdcIl0gW3BheW1lbnQtbWV0aG9kPVwiJyArIHNlbGVjdGVkQ2FyZC5QYXltZW50TWV0aG9kICsgJ1wiXSBbY3JlZGl0LWNhcmQtbnVtYmVyLWlucHV0XScpO1xuXHRcdFx0XG5cdFx0XHRpZiAoJHNlbGVjdGVkQ2FyZE51bWJlcklucHV0LmZpbHRlcignOnZpc2libGUnKS5sZW5ndGggPCAxKSB7XG5cdFx0XHRcdCRzZWxlY3RlZENhcmROdW1iZXJJbnB1dC52YWwoY3JlZGl0Q2FyZE51bWJlcik7XG5cdFx0XHR9XG5cblx0XHRcdCQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykudmFsKHNlbGVjdGVkQ2FyZC5QYXltZW50Q2FyZCk7XG5cdFx0XHQkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpLmZpbHRlcignaW5wdXRbdHlwZT1cInJhZGlvXCJdW3ZhbHVlPVwiJyArIHNlbGVjdGVkQ2FyZC5QYXltZW50Q2FyZERpc3BsYXlLZXkgKyAnXCJdJykuZmlyc3QoKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSkudHJpZ2dlcignY2hhbmdlJywgeyBkb1Jlc2V0OiBmYWxzZSB9KTtcblx0XHRcdFxuXHRcdFx0aWYgKCRzZWxlY3RlZENhcmROdW1iZXJJbnB1dC5maWx0ZXIoJzpmb2N1cycpLmxlbmd0aCA8IDEpIHtcblx0XHRcdFx0JHNlbGVjdGVkQ2FyZE51bWJlcklucHV0LmZvY3VzKCkudmFsKGNyZWRpdENhcmROdW1iZXIpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcuY2MtY2FyZGxpc3Qtc2VsZWN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpLnZhbCgnJyk7XG5cdFx0XHQkKCcucGF5bWVudC1jYXJkLWxpc3QuZ3JpZCcpLmZpbmQoJ1twYXltZW50LWNhcmRdJykuc2hvdygpO1xuXHRcdFx0JChjcmVkaXRDYXJkTGlzdFNlbGVjdG9yKS5maWx0ZXIoJ2lucHV0JykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHRcdCQoY3JlZGl0Q2FyZExpc3RTZWxlY3RvcikuZmluZCgnb3B0aW9uJykucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XG5cdFx0XHQkcGF5bWVudEZvcm0uZmluZCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCArICdcIl0gLmNjLWltYWdlJykuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJycpO1xuXHRcdH1cblxuXHRcdCRjcmVkaXRDYXJkU2F2ZUNoZWNrYm94Q29udGFpbmVyLnNob3coKTtcblx0fSk7XG5cdFxuXHQkKCcuYWRkLW5ldy1jYXJkJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHJlc2V0Q3JlZGl0Q2FyZEZpZWxkcygkKHRoaXMpLmNsb3Nlc3QoJ1twYXltZW50LW1ldGhvZF0nKSk7XG5cdFx0JCgnI29wYy1jYy1saXN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKTtcblx0XHQkKCcuY2MtY2FyZGxpc3Qtc2VsZWN0IDppbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpLnZhbCgnJyk7XG5cdFx0JCgnLmNjLWltYWdlJykuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ25vbmUnKTtcblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLnBheW1lbnQtbWV0aG9kLW9wdGlvbi5hY2NvcmRpb24gLmZvcm0tbGFiZWwnLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCh0aGlzKS5jbG9zZXN0KCcuYWNjb3JkaW9uJykudG9nZ2xlQ2xhc3MoJ29wZW4nKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlc2V0Q3JlZGl0Q2FyZEZpZWxkcygkcGF5bWVudE1ldGhvZCkge1xuXHQkcGF5bWVudE1ldGhvZC5maW5kKCdpbnB1dFtuYW1lKj1cIl9vd25lclwiXScpLnZhbCgnJyk7XG5cdCRwYXltZW50TWV0aG9kLmZpbmQoJ2lucHV0W25hbWUqPVwiX251bWJlclwiXScpLnZhbCgnJyk7XG5cdCRwYXltZW50TWV0aG9kLmZpbmQoJ2lucHV0W25hbWUqPVwiX2N2blwiXScpLnZhbCgnJyk7XG5cdCRwYXltZW50TWV0aG9kLmZpbmQoJ2lucHV0W25hbWUqPVwiX21vbnRoXCJdJykudmFsKCcnKTtcblx0JHBheW1lbnRNZXRob2QuZmluZCgnaW5wdXRbbmFtZSo9XCJfeWVhclwiXScpLnZhbCgnJyk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ha2UgdGhlIEFKQVggcmVxdWVzdCB0byBzZXQgY2FydCBkYXRhXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGZvcm0gVGhlIGZvcm0gZWxlbWVudCB0aGF0IHByZXNlbnQgYWRkcmVzcyBvYmplY3RcbiAqIEBwYXJhbSB7RWxlbWVudH0gQWN0aW9uIG5hbWUgdG8gYXBwbHkgdG8gZm9ybVxuICogQHJldHVybnMge1Byb21pc2V9XG4gKi9cbnZhciBzZXRPUENQYXltZW50RGF0YSA9IGZ1bmN0aW9uIChmb3JtU2VsZWN0b3IsIG5hbWUpIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm1TZWxlY3Rvcik7XG5cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuc2V0T3BjQWRkcmVzcyksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWVcbiAgICB9KSk7XG59O1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0XG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIChvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlciB8fCBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUmV3YXJkc0NyZWRpdCB8fCBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yR2lmdENhcmRzKSkge1xuICAgIFx0cmVjYXB0Y2hhLmluaXRpYWxpemUoKTtcblx0fVxuXHRcblx0aWYgKG9wdGlvbnMuQjJCICYmIG9wdGlvbnMuQjJCLkVuYWJsZWQpIHtcblx0XHRQYXltZW50Vm91Y2hlclBhbmVsID0gcmVxdWlyZSgnLi9jaGVja291dC9QYXltZW50Vm91Y2hlclBheW1lbnRQYW5lbCcpO1xuXHRcdFBheW1lbnRWb3VjaGVyUGFuZWwuaW5pdGlhbGl6ZSgpO1xuXHR9XG5cdEdpZnRDYXJkLmluaXRpYWxpemUob3B0aW9ucyk7XG5cdFJld2FyZHNDcmVkaXQuaW5pdGlhbGl6ZShvcHRpb25zKTtcblx0TG95YWx0eUNyZWRpdC5pbml0aWFsaXplKG9wdGlvbnMpO1xuICAgIGluaXRpYWxpemVFdmVudHMob3B0aW9ucyk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi90b29sdGlwJyk7XG5cbnZhciBvcHRpb25zID0ge307XG52YXIgYnVmZmVyID0ge307XG5cbmZ1bmN0aW9uIHRyaWdnZXJSZWFjdFdlYnZpZXdFdmVudCgpIHtcblx0aWYgKCdSZWFjdE5hdGl2ZVdlYlZpZXcnIGluIHdpbmRvdykge1xuXHRcdHdpbmRvdy5SZWFjdE5hdGl2ZVdlYlZpZXcucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkoeyBhY3Rpb246ICdvcmRlci1wYWdlJyB9KSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVByaWNlU3BpZGVyT3JkZXJUcmFja2luZygpIHtcblx0JChkb2N1bWVudCkub24oJ0RhdGFMYXllci5PcmRlckNvbXBsZXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhTGF5ZXIpIHtcblx0XHR2YXIgcHNyaWQgPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKCdwc3JpZCcpO1xuXHRcdGlmIChwc3JpZCAmJiBkYXRhTGF5ZXIgJiYgJ2V2ZW50JyBpbiBkYXRhTGF5ZXIgJiYgZGF0YUxheWVyLmV2ZW50ID09ICdwdXJjaGFzZScpIHtcdFxuXHRcdFx0dmFyIGl0ZW1zVGl0bGUgPSBbXTtcblx0XHRcdHZhciBpdGVtc1ByaWNlID0gW107XG5cdFx0XHR2YXIgaXRlbXNRdWFudGl0eSA9IFtdO1xuXHRcdFx0dmFyIGl0ZW1zU2t1ID0gW107XG5cdFx0XHR2YXIgaXRlbXNNYW51ZmFjdHVyZXIgPSBbXTtcblx0XHRcdHZhciBpdGVtRWxlbWVudHMgPSBkYXRhTGF5ZXIuaXRlbXM7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1FbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRpdGVtc1RpdGxlLnB1c2goaXRlbUVsZW1lbnRzW2ldLml0ZW1fbmFtZSk7XG5cdFx0XHRcdGl0ZW1zUXVhbnRpdHkucHVzaChpdGVtRWxlbWVudHNbaV0ucXVhbnRpdHkpO1xuXHRcdFx0XHRpdGVtc1ByaWNlLnB1c2goaXRlbUVsZW1lbnRzW2ldLnByaWNlKTtcblx0XHRcdFx0aXRlbXNTa3UucHVzaChpdGVtRWxlbWVudHNbaV0uaXRlbV9pZCk7XG5cdFx0XHRcdGl0ZW1zTWFudWZhY3R1cmVyLnB1c2goaXRlbUVsZW1lbnRzW2ldLml0ZW1fYnJhbmQpO1xuXHRcdFx0fVxuXHRcdFx0dmFyIG9yZGVyID0gcHN3dGIucHVyY2hhc2VUcmFja2luZy5jcmVhdGVPcmRlcigpO1xuXHRcdFx0b3JkZXIuY3VycmVuY3lDb2RlID0gZGF0YUxheWVyLmN1cnJlbmN5O1xuXHRcdFx0b3JkZXIucHVyY2hhc2VUb3RhbCA9IGRhdGFMYXllci52YWx1ZTtcblx0XHRcdHZhciBpdGVtc0RldGFpbHMgPSBbXTtcblx0XHRcdGZvciAodmFyIHkgPSAwOyB5IDwgaXRlbXNUaXRsZS5sZW5ndGg7IHkrKykge1xuXHRcdFx0XHRpdGVtc0RldGFpbHMucHVzaCh7XG5cdFx0XHRcdFx0XCJwcm9kdWN0TmFtZVwiOiBpdGVtc1RpdGxlW3ldLFxuXHRcdFx0XHRcdFwicXVhbnRpdHlcIjogaXRlbXNRdWFudGl0eVt5XSxcblx0XHRcdFx0XHRcInVuaXRQcmljZVwiOiBpdGVtc1ByaWNlW3ldIC8gaXRlbXNRdWFudGl0eVt5XSxcblx0XHRcdFx0XHRcIm1hbnVmYWN0dXJlclwiOiBpdGVtc01hbnVmYWN0dXJlclt5XSxcblx0XHRcdFx0XHRcInNrdVwiOiBpdGVtc1NrdVt5XVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdG9yZGVyLmRldGFpbHMgPSBpdGVtc0RldGFpbHM7XG5cdFx0XHRvcmRlci5yZWRpcmVjdFRva2VuID0gcHNyaWQ7XG5cdFx0XHRvcmRlci5zdWJtaXQoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplVldPT3JkZXJUcmFja2luZygpIHtcblx0YnVmZmVyWydpdGVtcyddID0gbnVsbDtcblx0aWYgKFNpdGVQcmVmZXJlbmNlcy5WV09fRU5BQkxFRCAmJiBTaXRlUHJlZmVyZW5jZXMuVldPX1BVUkNIQVNFX1RSQUNLSU5HX0VOQUJMRUQpIHtcblx0XHRidWZmZXJbJ3Z3b0xvYWRlZEludGVydmFsJ10gPSBzZXRJbnRlcnZhbCh0cmlnZ2VyVldPT3JkZXJUcmFja2luZywgMTAwKTtcblxuXHRcdCQoZG9jdW1lbnQpLm9uKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YUxheWVyKSB7XG5cdFx0XHR2YXIgaXRlbXMgPSBbXTtcblx0XHRcdHZhciBwYXltZW50TWV0aG9kcyA9ICcnO1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LlBheW1lbnRNZXRob2RzKSB7XG5cdFx0XHRcdHBheW1lbnRNZXRob2RzID0gcGFnZUNvbnRleHQuUGF5bWVudE1ldGhvZHMuam9pbignIHwgJyk7XG5cdFx0XHR9XG5cdFx0XHQkKCcucHJvZHVjdENhcmRNZXRhZGF0YScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciBpdGVtRGF0YUxheWVyO1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGl0ZW1EYXRhTGF5ZXIgPSBKU09OLnBhcnNlKCR0aGlzLmF0dHIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicpKTtcblx0XHRcdFx0fSBjYXRjaChleGNlcHRpb24pIHt9XG5cdFx0XHRcdGlmIChpdGVtRGF0YUxheWVyKSB7XG5cdFx0XHRcdFx0dmFyIHJldmVudWUgPSBpdGVtRGF0YUxheWVyLnByaWNlO1xuXHRcdFx0XHRcdHZhciBwcmljZSA9IHJldmVudWU7XG5cdFx0XHRcdFx0aWYgKGl0ZW1EYXRhTGF5ZXIuZGlzY291bnQpIHtcblx0XHRcdFx0XHRcdHByaWNlICs9IGl0ZW1EYXRhTGF5ZXIuZGlzY291bnQ7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGl0ZW1zLnB1c2goe1xuXHRcdFx0XHRcdFx0XCJwcmljZVwiOiBwcmljZS50b0ZpeGVkKDIpLFxuXHRcdFx0XHRcdFx0XCJpdGVtXCI6IGl0ZW1EYXRhTGF5ZXIuaXRlbV9pZCxcblx0XHRcdFx0XHRcdFwicGF5bWVudE1ldGhvZFwiOiBwYXltZW50TWV0aG9kcyxcblx0XHRcdFx0XHRcdFwicmVnaXN0ZXJlZFVzZXJcIjogQ3VzdG9tZXIucmVnaXN0ZXJlZCxcblx0XHRcdFx0XHRcdFwicmV2ZW51ZVwiOiByZXZlbnVlXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0XHRpZiAoaXRlbXMgJiYgaXRlbXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRidWZmZXJbJ2l0ZW1zJ10gPSBpdGVtcztcblx0XHRcdFx0dHJpZ2dlclZXT09yZGVyVHJhY2tpbmcoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiB0cmlnZ2VyVldPT3JkZXJUcmFja2luZygpIHtcblx0aWYgKGJ1ZmZlclsnaXRlbXMnXSAmJiB3aW5kb3cuVldPICYmIHdpbmRvdy5WV08uZXZlbnQgJiYgdHlwZW9mIHdpbmRvdy5WV08uZXZlbnQgPT0gJ2Z1bmN0aW9uJykge1xuXHRcdGNsZWFySW50ZXJ2YWwoYnVmZmVyWyd2d29Mb2FkZWRJbnRlcnZhbCddKTtcblx0XHRmb3IgKHZhciBpdGVtSW5kZXggPSAwOyBpdGVtSW5kZXggPCBidWZmZXJbJ2l0ZW1zJ10ubGVuZ3RoOyBpdGVtSW5kZXgrKykge1xuXHRcdFx0dmFyIGl0ZW0gPSBidWZmZXJbJ2l0ZW1zJ11baXRlbUluZGV4XTtcblx0XHRcdFZXTy5ldmVudChcInB1cmNoYXNlXCIsIGl0ZW0pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblxuXHR0b29sdGlwLmluaXQoe1xuXHRcdGl0ZW1zOiAnLnRvb2x0aXAnXG5cdH0pO1xuXHR0cmlnZ2VyUmVhY3RXZWJ2aWV3RXZlbnQoKTtcblx0aW5pdGlhbGl6ZVByaWNlU3BpZGVyT3JkZXJUcmFja2luZygpO1xuXHRpbml0aWFsaXplVldPT3JkZXJUcmFja2luZygpO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIG1pbmljYXJ0ID0gcmVxdWlyZSgnLi4vLi4vbWluaWNhcnQnKTtcbnZhciBwYWdlID0gcmVxdWlyZSgnLi4vLi4vcGFnZScpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG52YXIgZGF0YUJ1ZmZlciA9IHt9O1xuXG4vKipcbiAqIFdyYXBzIHRoZSBkaWFsb2cgY2xvc2UgZnVuY3Rpb25hbGl0eSBpbiBhIGZ1bmN0aW9uIHNvIHRoYXQgd2UgY2FuIGhvb2sgaW50byB0aGUgdHJhbnNpdGlvbkVuZCBldmVudFxuICogdG8gZmlyZSB0aGUgY2xvc2UgZXZlbnQgb24gdGhlIGRpYWxvZy5cbiAqIFRoaXMgYWxsb3dzIGZvciBhbiBhbmltYXRpb24gdG8gY29tcGxldGUgYmVmb3JlIHRoZSBkaWFsb2cgaXMgY2xvc2VkIGFuZCByZW1vdmVkIGZyb20gdGhlIGRvbVxuICovXG4gdmFyIGNsb3NlQWRkVG9DYXJ0TW9kYWwgPSBmdW5jdGlvbiAoKSB7XG5cdC8vIHNhdmUgb3ZlcmFseSBmb3IgY2xhc3MgYWRkaXRpb25zXG5cdHZhciAkb3ZlcmxheSA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykucGFyZW50KCkuZmluZCgnLnVpLXdpZGdldC1vdmVybGF5Jyk7XG5cdFxuXHQvLyBob29rIGludG8gdHJhbnNpdGlvbiBlbmRcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblJzcFVTKSB7XG5cdFx0dmFyIGN1cnJlbnRNb2RhbCA9ICQoJyNkaWFsb2ctY29udGFpbmVyJyk7XG5cdFx0aWYgKGN1cnJlbnRNb2RhbC5kaWFsb2coJ2lzT3BlbicpKSB7XG5cdFx0XHRjdXJyZW50TW9kYWwuZGlhbG9nKCdjbG9zZScpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwtd3JhcHBlcicpLm9uZSgndHJhbnNpdGlvbmVuZCB3ZWJraXRUcmFuc2l0aW9uRW5kIG9UcmFuc2l0aW9uRW5kJywgZnVuY3Rpb24gKGUpIHtcblx0XHRcdHZhciBjdXJyZW50TW9kYWwgPSAkKHRoaXMpLmZpbmQoJyNkaWFsb2ctY29udGFpbmVyJyk7XG5cdFx0XHRpZiAoY3VycmVudE1vZGFsLmRpYWxvZygnaXNPcGVuJykpIHtcblx0XHRcdFx0Y3VycmVudE1vZGFsLmRpYWxvZygnY2xvc2UnKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRcblx0JG92ZXJsYXkucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXInKS5yZW1vdmVDbGFzcygnc2hvdycpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gYWRkIGFuIGl0ZW0gdG8gY2FydFxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgaXRlbSBxdWFudGl0eSBhbmQgSUQgZGF0YVxuICogQHJldHVybnMge1Byb21pc2V9XG4gKi9cbnZhciBhZGRJdGVtVG9DYXJ0ID0gZnVuY3Rpb24gKGZvcm0pIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm0pLFxuICAgICAgICAkcXR5ID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIlF1YW50aXR5XCJdJyk7XG4gICAgaWYgKCRxdHkubGVuZ3RoID09PSAwIHx8IGlzTmFOKCRxdHkudmFsKCkpIHx8IHBhcnNlSW50KCRxdHkudmFsKCksIDEwKSA9PT0gMCkge1xuICAgICAgICAkcXR5LnZhbCgnMScpO1xuICAgIH1cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuYWRkUHJvZHVjdCksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpXG4gICAgfSkpO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciB0byBoYW5kbGUgdGhlIGFkZCB0byBjYXJ0IGV2ZW50XG4gKi9cbnZhciBhZGRUb0NhcnQgPSBmdW5jdGlvbihldmVudCwgZGF0YSkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdHZhciAkaHRtbCA9ICQoJ2h0bWwnKTtcblx0dmFyICRjb250YWluZXIgPSAkKCcjd3JhcHBlcicpO1xuICAgIHZhciAkZm9ybSA9ICQoJy5wZHBGb3JtJyk7XG4gICAgdmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHR2YXIgaXNTaXplU2VsZWN0ZWQgPSBzaXplU2VsZWN0ZWQubGVuZ3RoIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKTtcblxuICAgIGlmICghaXNTaXplU2VsZWN0ZWQpIHtcbiAgICBcdGRpYWxvZy5vcGVuKHtcblx0XHRcdGh0bWw6ICdQbGVhc2Ugc2VsZWN0IGEgc2l6ZScsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGRpYWxvZ0NsYXNzOiAnZGlhbG9nLWFsZXJ0Jyxcblx0XHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZVxuXHRcdFx0fVxuXHRcdH0pO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuY29sb3IuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aCkge1xuICAgIFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0aHRtbDogJ1BsZWFzZSBzZWxlY3QgYSBjb2xvcicsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGRpYWxvZ0NsYXNzOiAnZGlhbG9nLWFsZXJ0Jyxcblx0XHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZVxuXHRcdFx0fVxuXHRcdH0pO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBpc0JvcGlzID0gZmFsc2U7XG5cdHZhciAkYm9waXNBZGRUb0NhcnRPcHRpb25zID0gJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtY29udGFpbmVyJyk7XG5cdHZhciAkYm9waXNBZGRUb0NhcnRPcHRpb247XG5cdGlmICgkYm9waXNBZGRUb0NhcnRPcHRpb25zLmxlbmd0aCA+IDApIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMpIHtcblx0XHRcdCRib3Bpc0FkZFRvQ2FydE9wdGlvbnMuZmluZCgnaW5wdXRbbmFtZT1cIkFkZFRvQ2FydE9wdGlvblwiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0XHQkKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmNsb3Nlc3QoJ2xpJykuZmluZCgnaW5wdXRbbmFtZT1cIkFkZFRvQ2FydE9wdGlvblwiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHRcdCRib3Bpc0FkZFRvQ2FydE9wdGlvbnMgPSAkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXInKTtcblx0XHR9XG5cdFx0JGJvcGlzQWRkVG9DYXJ0T3B0aW9uID0gJGJvcGlzQWRkVG9DYXJ0T3B0aW9ucy5maW5kKCdpbnB1dFtuYW1lPVwiQWRkVG9DYXJ0T3B0aW9uXCJdOmNoZWNrZWQnKTtcblx0XHR2YXIgJGJvcGlzQWRkVG9DYXJ0TGFiZWwgPSAkYm9waXNBZGRUb0NhcnRPcHRpb24uY2xvc2VzdCgnbGknKTtcblx0XHR2YXIgJGJvcGlzT3B0aW9uYWxNZXNzYWdlID0gJGJvcGlzQWRkVG9DYXJ0TGFiZWwuZmluZCgnLmFkZC10by1jYXJ0LW9wdGlvbmFsLW1lc3NhZ2UnKTtcblx0XHRpZiAoJGJvcGlzT3B0aW9uYWxNZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHRcdGRhdGFCdWZmZXJbJ09wdGlvbmFsTWVzc2FnZSddID0gJGJvcGlzT3B0aW9uYWxNZXNzYWdlLmZpcnN0KCkuaHRtbCgpLnRyaW0oKTtcblx0XHR9XG5cdH1cblxuICAgIGlmICgkKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmhhc0NsYXNzKCdib3BpcycpIHx8IChkYXRhICYmIGRhdGEuYm9waXMpKSB7XG4gICAgXHRpc0JvcGlzID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKCRib3Bpc0FkZFRvQ2FydE9wdGlvbnMubGVuZ3RoID4gMCkge1xuXHRcdHZhciBib3Bpc1NoaXBwaW5nT3B0aW9uID0gJGJvcGlzQWRkVG9DYXJ0T3B0aW9uLnZhbCgpO1xuXHRcdGlmIChib3Bpc1NoaXBwaW5nT3B0aW9uID09ICdkZWxpdmVyeScpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0JvcGlzLkxvY2FsRGVsaXZlcnkuRGlzcGxheScsIHsgT3B0aW9uYWxNZXNzYWdlOiBkYXRhQnVmZmVyWydPcHRpb25hbE1lc3NhZ2UnXSB9KTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9IGVsc2UgaWYgKGJvcGlzU2hpcHBpbmdPcHRpb24gPT0gJ3NoaXB0b3N0b3JlcGlja3VwJykge1xuXHRcdFx0aXNCb3BpcyA9IHRydWU7XG5cdFx0XHRkYXRhID0gZGF0YSB8fCB7fTtcblx0XHRcdGRhdGEuYm9waXNTdG9yZSA9ICRib3Bpc0FkZFRvQ2FydE9wdGlvbnMuZmluZCgnLnNlbGVjdGVkLXN0b3JlW3N0b3JlLWlkXScpLmF0dHIoJ3N0b3JlLWlkJyk7XG5cdFx0XHRkYXRhLnNoaXBwaW5nT3B0aW9uID0gYm9waXNTaGlwcGluZ09wdGlvbjtcblx0XHR9IGVsc2UgaWYgKGJvcGlzU2hpcHBpbmdPcHRpb24gPT0gJ3BpY2t1cCcpIHtcblx0XHRcdGlzQm9waXMgPSB0cnVlO1xuXHRcdFx0dmFyIHN0b3JlRGF0YTtcblx0XHRcdHZhciAkc3RvcmVEYXRhID0gJGJvcGlzQWRkVG9DYXJ0T3B0aW9ucy5maW5kKCcuc2VsZWN0ZWQtc3RvcmVbc3RvcmUtZGF0YV0nKTtcblx0XHRcdGlmICgkc3RvcmVEYXRhLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0c3RvcmVEYXRhID0gSlNPTi5wYXJzZSgkc3RvcmVEYXRhLmF0dHIoJ3N0b3JlLWRhdGEnKSlcblx0XHRcdFx0ZGF0YSA9IGRhdGEgfHwge307XG5cdFx0XHRcdGRhdGEuYm9waXNTdG9yZSA9IHN0b3JlRGF0YS5sb2NhdGlvbi5jb2RlO1xuXHRcdFx0XHRkYXRhLnF1YW50aXR5QXZhaWxhYmxlID0gc3RvcmVEYXRhLmRldGFpbC5xdWFudGl0eTtcblx0XHRcdFx0ZGF0YS5zaGlwcGluZ09wdGlvbiA9IGJvcGlzU2hpcHBpbmdPcHRpb247XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cbiAgICB2YXIgJGJvcGlzU3RvcmU7XG4gICAgaWYgKGlzQm9waXMpIHtcbiAgICBcdCRib3Bpc1N0b3JlID0gJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpO1xuXHRcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19zdG9yZVwiXScpLnZhbChkYXRhLmJvcGlzU3RvcmUgPyBkYXRhLmJvcGlzU3RvcmUgOiAkYm9waXNTdG9yZS52YWwoKSk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfcXVhbnRpdHlfYXZhaWxhYmxlXCJdJykudmFsKGRhdGEucXVhbnRpdHlBdmFpbGFibGUgIT0gdW5kZWZpbmVkID8gZGF0YS5xdWFudGl0eUF2YWlsYWJsZSA6ICRib3Bpc1N0b3JlLmF0dHIoJ3F1YW50aXR5LWF2YWlsYWJsZScpKTtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19zaGlwcGluZ19vcHRpb25cIl0nKS52YWwoZGF0YS5zaGlwcGluZ09wdGlvbiA/IGRhdGEuc2hpcHBpbmdPcHRpb24gOiAnJyk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfZGVsaXZlcnlfYWRkcmVzc1wiXScpLnZhbChkYXRhLmRlbGl2ZXJ5QWRkcmVzcyA/IGRhdGEuZGVsaXZlcnlBZGRyZXNzIDogJycpO1xuICAgIFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImJvcGlzX2RlbGl2ZXJ5X25vdGVcIl0nKS52YWwoZGF0YS5kZWxpdmVyeU5vdGUgPyBkYXRhLmRlbGl2ZXJ5Tm90ZSA6ICcnKTtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19kZWxpdmVyeV9naWZ0X21lc3NhZ2VcIl0nKS52YWwoZGF0YS5naWZ0TWVzc2FnZSA/IGRhdGEuZ2lmdE1lc3NhZ2UgOiAnJyk7XG4gICAgXHQkKCcub3B0aW9uLWRyb3Bkb3duIHNlbGVjdFtuYW1lKj1cIl9Cb3Bpc1wiXScpLnZhbCgnWWVzJyk7XG4gICAgfSBlbHNlIHtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19zdG9yZVwiXScpLnZhbCgnJyk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfcXVhbnRpdHlfYXZhaWxhYmxlXCJdJykudmFsKCcnKTtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19zaGlwcGluZ19vcHRpb25cIl0nKS52YWwoJycpO1xuICAgIFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImJvcGlzX2RlbGl2ZXJ5X2FkZHJlc3NcIl0nKS52YWwoJycpO1xuICAgIFx0JCgnLm9wdGlvbi1kcm9wZG93biBzZWxlY3RbbmFtZSo9XCJfQm9waXNcIl0nKS52YWwoJ05vJyk7XG5cdH1cblxuXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiY2hhbm5lbFwiXScpLnZhbChkYXRhICYmIGRhdGEuY2hhbm5lbCA/IGRhdGEuY2hhbm5lbCA6ICcnKTtcblx0aWYgKGRhdGEgJiYgJ2NzcmZfdG9rZW4nIGluIGRhdGEgJiYgZGF0YS5jc3JmX3Rva2VuKSB7XG5cdFx0JCgnI2NzcmZ0b2tlbicpLnZhbChkYXRhLmNzcmZfdG9rZW4pO1xuXHR9XG4gICAgXG4gICAgaWYgKHNpemVTZWxlY3RlZC5oYXNDbGFzcyhcInRlbXBzZWxlY3Rpb25cIikpIHtcbiAgICBcdHNpemVTZWxlY3RlZC5hZGRDbGFzcygnZW50ZXJTZWxlY3RlZCcpO1xuICAgIFx0c2l6ZVNlbGVjdGVkLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgXHRzaXplU2VsZWN0ZWQuZmluZCgnLnN3YXRjaGFuY2hvcicpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgXHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpeyQoXCIjYWRkLXRvLWNhcnRcIikuY2xpY2soKX0sIDEwMCApO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZGF0YUxheWVyICE9PSAndW5kZWZpbmVkJykge1xuXHRcdHZhciBxdHkgPSAkKCcucHRfcHJvZHVjdC1kZXRhaWxzIC5wZHBGb3JtIC5wcm9kdWN0LWFkZC10by1jYXJ0IHNlbGVjdFtpZD1RdWFudGl0eV0nKS52YWwoKTtcblx0XHR2YXIgdmFyaWF0aW9uQXR0ciA9ICQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKS5kYXRhKCdhdHRyaWJ1dGVzJyk7XG5cdFx0dmFyIHNpemVBdHRyVmFsdWUgPSB2YXJpYXRpb25BdHRyLnNpemUuZGlzcGxheVZhbHVlO1xuXHRcdGlmIChzaXplQXR0clZhbHVlID09ICcnIHx8IHNpemVBdHRyVmFsdWUgPT0gbnVsbCApIHtcblx0XHRcdGlmIChzaXplU2VsZWN0ZWQuaGFzQ2xhc3MoXCJ0ZW1wc2VsZWN0aW9uXCIpICYmIHNpemVTZWxlY3RlZC5maW5kKCdhLnN3YXRjaGFuY2hvcicpLmRhdGEoKSAhPSBudWxsICkge1xuXHRcdFx0XHRzaXplU2VsZWN0ZWQuYWRkQ2xhc3MoJ2VudGVyU2VsZWN0ZWQnKTtcblx0XHRcdFx0dmFyIHNpemVPYmpSZWYgPSBzaXplU2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS5kYXRhKCk7XG5cdFx0XHRcdHNpemVBdHRyVmFsdWUgPSBzaXplT2JqUmVmLnNpemVOYW1lO1xuXHRcdFx0XHRzaXplU2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFRvQ2FydCcpO1xuXG5cdFx0Zm9yICh2YXIgaT0wOyBpIDwgZGF0YUxheWVyLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAoZGF0YUxheWVyW2ldLmV2ZW50ID09ICdwZHBEaXNwbGF5Jykge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRJdGVtID0gZGF0YUxheWVyW2ldLmVjb21tZXJjZS5kZXRhaWwucHJvZHVjdHNbMF07XG5cdFx0XHRcdHZhciBpdGVtUHJpY2UgPSAoc2VsZWN0ZWRJdGVtLnNpbGhvdWV0dGUgPT0gJ0dpZnQgQ2FyZCcpID8gIHBhcnNlSW50KCh2YXJpYXRpb25BdHRyLnNpemUudmFsdWUpLnJlcGxhY2UoJyQnLCcnKSkgOiBzZWxlY3RlZEl0ZW0ucHJpY2U7XG5cdFx0XHRcdHZhciBza3VJRCA9ICQoJyNwaWQnKS52YWwoKTtcblx0XHRcdFx0dmFyIGltYWdlID0gJCgnLnByb2R1Y3QtcHJpbWFyeS1pbWFnZSBbY2xhc3MqPVwiLXNsaWRlXCJdIC5wcmltYXJ5LWltYWdlLmZpcnN0JykuZmluZCgnYScpLmF0dHIoJ2hyZWYnKTtcblx0XHRcdFx0aWYgKCFpbWFnZSB8fCBpbWFnZSA9PSB1bmRlZmluZWQgfHwgaW1hZ2UgPT0gbnVsbCkge1xuXHRcdFx0XHRcdGltYWdlID0gJCgnLnByb2R1Y3QtcHJpbWFyeS1pbWFnZSBbY2xhc3MqPVwiLXNsaWRlXCJdIC5wcmltYXJ5LWltYWdlLmZpcnN0JykuZmluZCgnaW1nJykuYXR0cignc3JjJyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCkge1x0XHRcdFx0XG5cdFx0XHRcdFx0dmFyIGNhcnRfZGF0YSA9IFt7XG5cdFx0XHRcdFx0ICAgICdwcm9kdWN0SUQnOiBzZWxlY3RlZEl0ZW0uaWQsXG5cdFx0XHRcdFx0ICAgICdza3UnOiBza3VJRCxcblx0XHRcdFx0XHQgICAgJ2NhdGVnb3J5JzogKHNlbGVjdGVkSXRlbS5jYXRlZ29yeSkucmVwbGFjZSgvXFxcXC9nLCBcIlwiKSxcblx0XHRcdFx0XHQgICAgJ25hbWUnOiAoc2VsZWN0ZWRJdGVtLm5hbWUpLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XHRcdFx0ICAgICdxdHknOiBxdHksIFxuXHRcdFx0XHRcdCAgICAnaXRlbVByaWNlJzogaXRlbVByaWNlLFxuXHRcdFx0XHRcdCAgICAnaW1hZ2UnOiBpbWFnZSxcblx0XHRcdFx0XHQgICAgJ3VybCc6JChsb2NhdGlvbikuYXR0cihcImhyZWZcIikuc3BsaXQoXCI/dXRtXCIpWzBdLnNwbGl0KFwiI3V0bVwiKVswXS5zcGxpdChcIiZ1dG1cIilbMF0sXG5cdFx0XHRcdFx0ICAgICdhdHRyJzoge1xuXHRcdFx0XHRcdCAgICAgICAgJ21hbnVmYWN0dXJlcic6IHNlbGVjdGVkSXRlbS5icmFuZCxcblx0XHRcdFx0XHQgICAgXHQnY29sb3InOiB2YXJpYXRpb25BdHRyLmNvbG9yLmRpc3BsYXlWYWx1ZSxcblx0XHRcdFx0XHQgICAgICAgICdzaXplJzogdmFyaWF0aW9uQXR0ci5zaXplLmRpc3BsYXlWYWx1ZVxuXHRcdFx0XHRcdCAgICB9XG5cdFx0XHRcdFx0fV07XG5cdFxuXHRcdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRcdGNyZGwoW1xuXHRcdFx0XHRcdFx0XHRbJ2NhcnQnLCAndXBkYXRlJ10sXG5cdFx0XHRcdFx0XHRcdFsnY2FydGl0ZW0nLCAnYWRkJyAsIGNhcnRfZGF0YV0sIFxuXHRcdFx0XHRcdFx0XHRbJ2V2ZW50JywgJ2NhcnQnXVxuXHRcdFx0XHRcdFx0XSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgZGF0ZVRpbWUgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKTtcblx0XHRcdFx0dmFyIGV2ZW50SUQgPSAnYWRkdG9jYXJ0LScgKyBzZWxlY3RlZEl0ZW0uaWQgKyAnLScgKyBkYXRlVGltZTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyAmJiBTaXRlUHJlZmVyZW5jZXMuUElOVEVSRVNUX0VOQUJMRUQpIHtcblx0XHRcdFx0XHRwaW50cmsoJ3RyYWNrJywgJ2FkZHRvY2FydCcsIHtcblx0XHRcdFx0XHRcdGV2ZW50X2lkOiBldmVudElELFxuXHRcdFx0XHRcdFx0dmFsdWU6IGl0ZW1QcmljZSAqIHF0eSxcblx0XHRcdFx0XHRcdG9yZGVyX3F1YW50aXR5OiBxdHksXG5cdFx0XHRcdFx0XHRjdXJyZW5jeTogJCgnbWV0YVtpdGVtcHJvcD1cInByaWNlQ3VycmVuY3lcIl0nKS5hdHRyKCdjb250ZW50JyksXG5cdFx0XHRcdFx0XHRsaW5lX2l0ZW1zOiBbXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRwcm9kdWN0X25hbWU6IChzZWxlY3RlZEl0ZW0ubmFtZSkucmVwbGFjZSgvXFxcXC9nLCBcIlwiKSxcblx0XHRcdFx0XHRcdFx0XHRwcm9kdWN0X2lkOiBzZWxlY3RlZEl0ZW0uaWQsXG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF9jYXRlZ29yeTogKHNlbGVjdGVkSXRlbS5jYXRlZ29yeSkucmVwbGFjZSgvXFxcXC9nLCBcIlwiKSxcblx0XHRcdFx0XHRcdFx0XHRwcm9kdWN0X3ZhcmlhbnRfaWQ6IHNrdUlELFxuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RfcHJpY2U6IGl0ZW1QcmljZSxcblx0XHRcdFx0XHRcdFx0XHRwcm9kdWN0X3F1YW50aXR5OiBxdHksXG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF9icmFuZDogc2VsZWN0ZWRJdGVtLmJyYW5kXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdF1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cbiAgICB9XG5cbiAgICBhZGRJdGVtVG9DYXJ0KCRmb3JtKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgIFx0JC5hamF4KHt1cmwgOiBVcmxzLmNhcnRJdGVtQ291bnQsIG1ldGhvZDogJ1BPU1QnLCBkYXRhVHlwZTogJ2pzb24nLCBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5Qcm9kdWN0Q291bnQgIT0gdW5kZWZpbmVkKSB7XG4gICAgXHRcdFx0JCgnLmJ0bi1taW5pY2FydCBzcGFuJykuaHRtbChNYXRoLnJvdW5kKGRhdGEuUHJvZHVjdENvdW50KSk7XG5cdFx0XHR9XG4gICAgXHR9fSk7XG4gICAgICAgIHZhciAkdXVpZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJ1dWlkXCJdJyk7XG4gICAgICAgIGlmICgkdXVpZC5sZW5ndGggPiAwICYmICR1dWlkLnZhbCgpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHBhZ2UucmVmcmVzaCgpO1xuICAgICAgICB9IGVsc2UgaWYoU2l0ZVByZWZlcmVuY2VzLlJFRElSRUNUX1RPX0NBUlQgJiYgKCFwYWdlQ29udGV4dC5vcHRpb25zIHx8IHBhZ2VDb250ZXh0Lm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gIT0gJzIwMjRSZWRlc2lnbicpKXtcbiAgICBcdFx0dmFyIHJlZGlyZWN0VXJsID0gKFNpdGVQcmVmZXJlbmNlcy5ISURFX0JBU0tFVCkgPyBVcmxzLm9uZVBhZ2UgOiBVcmxzLmNhcnRTaG93O1xuICAgIFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IHJlZGlyZWN0VXJsO1xuICAgIFx0fSBlbHNlIHtcblx0XHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuQUREX1RPX0NBUlRfTU9EQUwgfHwgKHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykpIHtcblx0XHRcdFx0dmFyIHF0eUFkZGVkID0gJCgnLnB0X3Byb2R1Y3QtZGV0YWlscyAucGRwRm9ybSAucHJvZHVjdC1hZGQtdG8tY2FydCBzZWxlY3RbaWQ9UXVhbnRpdHldJykudmFsKCk7XG5cdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0dXJsOiBVcmxzLmFkZFRvQ2FydE1vZGFsRGlzcGxheSxcblx0XHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0XHRzdG9yZXVpdmVyc2lvbjogcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucyAmJiBwYWdlQ29udGV4dC5vcHRpb25zLlN0b3JlVUlWZXJzaW9uID8gcGFnZUNvbnRleHQub3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA6IG51bGwsXG5cdFx0XHRcdFx0XHRzaGlwcGluZ29wdGlvbjogYm9waXNTaGlwcGluZ09wdGlvblxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihtb2RhbENvbnRlbnQpIHtcblx0XHRcdFx0XHRcdGlmIChtb2RhbENvbnRlbnQubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHR2YXIgJG1vZGFsQ29udGVudCA9ICQobW9kYWxDb250ZW50KTtcblx0XHRcdFx0XHRcdFx0dmFyICRyZWNzQ29udGVudDtcblx0XHRcdFx0XHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY3NDb250ZW50ID0gJCgnI2Jlc3Rfc2VsbGluZ19wcm9kdWN0cy5hY2NvcmRpb24ucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMnKS5yZW1vdmVDbGFzcygnYWNjb3JkaW9uJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRcdFx0XHRcdFx0XHQkcmVjc0NvbnRlbnQgPSAkKCcucmVjb21tLXByb2QtcGRwLWEyYy1zbG90IC5hY2NvcmRpb24ucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMnKS5yZW1vdmVDbGFzcygnYWNjb3JkaW9uJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY3NDb250ZW50ID0gJCgnLm1haW4gLmFjY29yZGlvbi5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucycpLnJlbW92ZUNsYXNzKCdhY2NvcmRpb24nKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQkcmVjc0NvbnRlbnQuZmluZCgnLmFjY29yZGlvbi1oZWFkJykucmVtb3ZlQ2xhc3MoJ2FjY29yZGlvbi1oZWFkJyk7XG5cdFx0XHRcdFx0XHRcdCRyZWNzQ29udGVudC5maW5kKCcuYWNjb3JkaW9uLWJvZHknKS5yZW1vdmVDbGFzcygnYWNjb3JkaW9uLWJvZHknKTtcblxuXHRcdFx0XHRcdFx0XHRpZiAoJHJlY3NDb250ZW50LmZpbmQoJy5zbGljay1saXN0JykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciAkcmVjb21tZW5kYXRpb25zQ29udGVudEh0bWwgPSAkKCRyZWNzQ29udGVudFswXS5vdXRlckhUTUwpO1xuXHRcdFx0XHRcdFx0XHRcdHZhciAkcmVjb21tZW5kYXRpb25zU2xpZGVzID0gJHJlY29tbWVuZGF0aW9uc0NvbnRlbnRIdG1sLmZpbmQoJy5zbGlkZScpO1xuXHRcdFx0XHRcdFx0XHRcdHZhciByZWNvbW1lbmRhdGlvbnNTbGlkZXNIdG1sID0gJyc7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY29tbWVuZGF0aW9uc1NsaWRlcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZWNvbW1lbmRhdGlvbnNTbGlkZXNIdG1sICs9ICQodGhpcylbMF0ub3V0ZXJIVE1MO1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdCRyZWNvbW1lbmRhdGlvbnNDb250ZW50SHRtbC5maW5kKCcuc2xpZGVzJykuaHRtbChyZWNvbW1lbmRhdGlvbnNTbGlkZXNIdG1sKTtcblx0XHRcdFx0XHRcdFx0XHQkcmVjb21tZW5kYXRpb25zQ29udGVudEh0bWwuZmluZCgnLnNsaWRlcycpLnJlbW92ZUNsYXNzKCdzbGljay1pbml0aWFsaXplZCBzbGljay1zbGlkZXInKTtcblx0XHRcdFx0XHRcdFx0XHQkcmVjb21tZW5kYXRpb25zQ29udGVudEh0bWwuZmluZCgnLnNsaWRlJykucmVtb3ZlQ2xhc3MoJ3NsaWNrLXNsaWRlIHNsaWNrLWN1cnJlbnQgc2xpY2stYWN0aXZlIHNsaWNrLWNsb25lZCcpLmNzcygnd2lkdGgnLCAnJyk7XG5cdFx0XHRcdFx0XHRcdFx0JG1vZGFsQ29udGVudC5maW5kKCcucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMtY29udGFpbmVyJykuaHRtbCgkcmVjb21tZW5kYXRpb25zQ29udGVudEh0bWwpO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYgKGRhdGFCdWZmZXJbJ09wdGlvbmFsTWVzc2FnZSddKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIG9wdGlvbmFsTWVzc2FnZUh0bWwgPSAnPGRpdiBjbGFzcz1cImFkZC10by1jYXJ0LW1vZGFsLW9wdGlvbmFsLW1lc3NhZ2VcIj4nICsgZGF0YUJ1ZmZlclsnT3B0aW9uYWxNZXNzYWdlJ10gKyAnPC9kaXY+Jztcblx0XHRcdFx0XHRcdFx0XHQkbW9kYWxDb250ZW50LmZpbmQoJy5hZGRlZC1tZXNzYWdlJykuYXBwZW5kKG9wdGlvbmFsTWVzc2FnZUh0bWwpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdCRtb2RhbENvbnRlbnQuYXR0cignYm9waXMtc2hpcHBpbmctb3B0aW9uJywgYm9waXNTaGlwcGluZ09wdGlvbik7XG5cblx0XHRcdFx0XHRcdFx0dmFyIHNjcm9sbFRvcCA9IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3A7XG5cblx0XHRcdFx0XHRcdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0XHRcdFx0XHRcdGh0bWw6ICRtb2RhbENvbnRlbnQsXG5cdFx0XHRcdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGlhbG9nQ2xhc3M6ICdhZGQtdG8tY2FydC1tb2RhbCcsXG5cdFx0XHRcdFx0XHRcdFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0XHRcdFx0XHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdFx0XHRcdFx0XHRcdHdpZHRoOiAxMDkwLFxuXHRcdFx0XHRcdFx0XHRcdFx0b3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGRhdGFCdWZmZXJbJ3dyYXBwZXJTY3JvbGxUb3AnXSA9IHNjcm9sbFRvcDtcbiAgICBcdFx0XHRcdFx0XHRcdFx0XHRkYXRhQnVmZmVyWyd3cmFwcGVyTWFyZ2luVG9wJ10gPSAkY29udGFpbmVyLmNzcygnbWFyZ2luLXRvcCcpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkY29udGFpbmVyLmF0dHIoJ2J1ZmZlci1zY3JvbGxUb3AnLCBzY3JvbGxUb3ApO1xuXG4gICAgXHRcdFx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lci5jc3MoJ21hcmdpbi10b3AnLCBwYXJzZUZsb2F0KCRjb250YWluZXIuY3NzKCdtYXJnaW4tdG9wJykpIC0gc2Nyb2xsVG9wKTtcbiAgICBcdFx0XHRcdFx0XHRcdFx0XHRkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSAwO1xuICAgIFx0XHRcdFx0XHRcdFx0XHRcdCRodG1sLmFkZENsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwnKS53cmFwKCc8ZGl2IGNsYXNzPVwiYWRkLXRvLWNhcnQtbW9kYWwtd3JhcHBlclwiPjwvZGl2PicpO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGFkZCB3cmFwcGVyIHRvIGNsb3NlIGJ1dHRvbiBcblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXInKS5vZmYoJ2NsaWNrLkRpYWxvZy5DbG9zZUJ1dHRvbnMnKS5vbignY2xpY2suRGlhbG9nLkNsb3NlQnV0dG9ucycsICcudWktZGlhbG9nLXRpdGxlYmFyLWNsb3NlLCAuYnRuLmNvbnRpbnVlLXNob3BwaW5nJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjbG9zZUFkZFRvQ2FydE1vZGFsKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGFkZCAnc2hvdycgY2xhc3MgdG8gb3ZlcmxheSBmb3IgbmljZSBhbmltYXRlIGluXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciAkb3ZlcmxheSA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykucGFyZW50KCkuZmluZCgnLnVpLXdpZGdldC1vdmVybGF5Jyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCRvdmVybGF5LmFkZENsYXNzKCdhZGQtdG8tY2FydC1vdmVybGF5Jyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCRvdmVybGF5LmFkZENsYXNzKCdzaG93Jyk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXInKS5vZmYoJ2NsaWNrLkRpYWxvZy5DbG9zZScpLm9uKCdjbGljay5EaWFsb2cuQ2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIG9ubHkgY2FsbCB0aGlzIGJsb2NrIGlmIHRoZSB1aS13aWRnZXQgYmFja2dyb3VuZCBpcyBjbGlja2VkXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCcuYWRkLXRvLWNhcnQtbW9kYWwnKS5sZW5ndGggPD0gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y2xvc2VBZGRUb0NhcnRNb2RhbCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKHBhcnNlRmxvYXQoJCgnLmFkZC10by1jYXJ0LW1vZGFsJykuY3NzKCd0b3AnKSkgPCAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsJykuY3NzKCd0b3AnLCAnMCcpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gbW92ZSB0aXRsZSBmcm9tIG1haW4gY29udGVudCB0byB0b3Agb2YgdGhlIG1vZGFsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciAkYWRkTWVzc2FnZSA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbC1jb250ZW50IC5tYWluLWNvbnRlbnQgLmFkZGVkLW1lc3NhZ2UnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCRhZGRNZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwtY29udGVudCcpLnByZXBlbmQoJGFkZE1lc3NhZ2UpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIGZ1bGZpbGxtZW50VHlwZSA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLWNvbnRhaW5lcicpLmZpbmQoJ2lucHV0W25hbWU9XCJBZGRUb0NhcnRPcHRpb25cIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBpc0JvcGlzID0gZnVsZmlsbG1lbnRUeXBlICYmIChmdWxmaWxsbWVudFR5cGUgPT0gJ3NoaXB0b3N0b3JlcGlja3VwJyB8fCBmdWxmaWxsbWVudFR5cGUgPT0gJ3BpY2t1cCcpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBib3Bpc1N0b3JlTmFtZSA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBib3Bpc1N0b3JlQWRkcmVzcyA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChpc0JvcGlzKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRib3Bpc1N0b3JlTmFtZSA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLXN0b3JlLXNlbGVjdG9yIC5zZWxlY3RlZC1zdG9yZScpLmF0dHIoJ3N0b3JlLW5hbWUnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGJvcGlzU3RvcmVBZGRyZXNzID0gJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtc3RvcmUtc2VsZWN0b3IgLnNlbGVjdGVkLXN0b3JlJykuYXR0cignc3RvcmUtYWRkcmVzcycpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKGJvcGlzU3RvcmVBZGRyZXNzICYmIGJvcGlzU3RvcmVBZGRyZXNzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLm1vZGFsLW1pbmktY2FydC1zdG9yZS1tZXNzYWdlLWNvbnRhaW5lcicpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLm1vZGFsLW1pbmktY2FydC1zdG9yZS1tZXNzYWdlLWNvbnRhaW5lcicpLmZpbmQoJy5tb2RhbC1taW5pLWNhcnQtc3RvcmUtZGV0YWlscycpLmh0bWwoJzxzdHJvbmc+JyArYm9waXNTdG9yZU5hbWUrICc8L3N0cm9uZz48YnIgLz4nICtib3Bpc1N0b3JlQWRkcmVzcyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyICRjb250YWluZXJzID0gJCgnLmFkZC10by1jYXJ0LW1vZGFsJykuZmluZCgnLmFjY29yZGlvbiwgLnNlY3Rpb24tb2ZmZXJzJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkY29udGFpbmVycy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lcnMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciAkY29udGFpbmVyID0gJCh0aGlzKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkY29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRpbGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciAkY29udGFpbmVySGVhZGVyID0gJGNvbnRhaW5lci5maW5kKCcuYWNjb3JkaW9uLWhlYWQgaDUsIC5zZWN0aW9uLWhlYWQgaDInKS5maXJzdCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgJGNvbnRhaW5lckhlYWRlckNoZWNrID0gJGNvbnRhaW5lckhlYWRlci5maW5kKCdzcGFuJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkY29udGFpbmVySGVhZGVyQ2hlY2subGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCRjb250YWluZXJIZWFkZXIgPSAkY29udGFpbmVySGVhZGVyQ2hlY2s7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkY29udGFpbmVySGVhZGVyLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb21vdGlvbl9pZDogJ2FkZHRvY2FydG1vZGFsJyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb21vdGlvbl9uYW1lOiAnQWRkIHRvIENhcnQgTW9kYWwnXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1ZpZXdQcm9tb3Rpb24nLCBkYXRhT2JqZWN0LCB7IENvbnRhaW5lcjogJGNvbnRhaW5lciB9KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXInKS5hZGRDbGFzcygnc2hvdycpO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIFx0dmFyICRodG1sID0gJCgnaHRtbCcpO1xuXHRcdFx0XHRcdFx0XHRcdCAgICBcdHZhciAkY29udGFpbmVyID0gJCgnI3dyYXBwZXInKTtcblxuXHRcdFx0XHRcdFx0XHRcdCAgICBcdCRodG1sLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdGlmIChkYXRhQnVmZmVyWyd3cmFwcGVyU2Nyb2xsVG9wJ10gPiAwKSB7XG5cdFx0XHRcdFx0XHRcdCAgICBcdFx0XHRkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSBkYXRhQnVmZmVyWyd3cmFwcGVyU2Nyb2xsVG9wJ107XG5cdFx0XHRcdFx0XHRcdCAgICBcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQkY29udGFpbmVyLmNzcygnbWFyZ2luLXRvcCcsIHBhcnNlRmxvYXQoZGF0YUJ1ZmZlclsnd3JhcHBlck1hcmdpblRvcCddKSk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsJykudW53cmFwKCk7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICB9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwgLmFkZGVkLW1lc3NhZ2UgLmNvdW50JykudGV4dCgnSXRlbScpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoICQoJy5iYW5uZXItY2FydC1ob2xkZXIgLmJ0bi1taW5pY2FydCcpLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0dXJsIDogVXJscy5jYXJ0TWluaUNhcnQsXG5cdFx0XHRcdFx0ZGF0YSA6IHtkZXNrdG9wOiAnMSd9LFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdCQoJy5iYW5uZXItY2FydC1ob2xkZXIgLmJ0bi1taW5pY2FydCcpLnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0JCgnLmJhbm5lci1jYXJ0LWhvbGRlcicpLmFwcGVuZChkYXRhKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybCA6IFVybHMuY2FydE1pbmlDYXJ0LFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdHZhciBwYXJlbnRNaW5pQ2FydCA9ICQoJy50b3AtYmFubmVyLWlubmVyLWxpbmtzICNtaW5pLWNhcnQnKTtcblx0XHRcdFx0XHRcdGlmIChwYXJlbnRNaW5pQ2FydC5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdCQoJy50b3AtYmFubmVyLWlubmVyLWxpbmtzICNtaW5pLWNhcnQgYS5taW5pLWNhcnQtbGluaycpLnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0XHRwYXJlbnRNaW5pQ2FydC5hcHBlbmQoZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdC8vIGRvIG5vdCBjbG9zZSBxdWlja3ZpZXcgaWYgYWRkaW5nIGluZGl2aWR1YWwgaXRlbSB0aGF0IGlzIHBhcnQgb2YgcHJvZHVjdCBzZXRcblx0XHRcdC8vIEBUT0RPIHNob3VsZCBub3RpZnkgdGhlIHVzZXIgc29tZSBvdGhlciB3YXkgdGhhdCB0aGUgYWRkIGFjdGlvbiBoYXMgY29tcGxldGVkIHN1Y2Nlc3NmdWxseVxuXHRcdFx0aWYgKCEkKHRoaXMpLmhhc0NsYXNzKCdzdWItcHJvZHVjdC1pdGVtJykpIHtcblx0XHRcdFx0ZGlhbG9nLmNsb3NlKCk7XG5cdFx0XHR9XG5cdFx0XHRpZihTaXRlUHJlZmVyZW5jZXMuQUREX1RPX0NBUlRfTU9EQUwgIT0gdHJ1ZSl7XG5cdFx0XHRcdG1pbmljYXJ0LnNob3cocmVzcG9uc2UpO1xuXHRcdFx0fVxuICAgICAgICB9XG4gICAgfS5iaW5kKHRoaXMpKTtcblxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciB0byBoYW5kbGUgdGhlIGFkZCBhbGwgaXRlbXMgdG8gY2FydCBldmVudFxuICovXG52YXIgYWRkQWxsVG9DYXJ0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgdmFyICRwcm9kdWN0Rm9ybXMgPSAkKCcjcHJvZHVjdC1zZXQtbGlzdCcpLmZpbmQoJ2Zvcm0nKS50b0FycmF5KCk7XG4gICAgVFByb21pc2UuYWxsKF8ubWFwKCRwcm9kdWN0Rm9ybXMsIGFkZEl0ZW1Ub0NhcnQpKVxuICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzcG9uc2VzKSB7XG4gICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIC8vIHNob3cgdGhlIGZpbmFsIHJlc3BvbnNlIG9ubHksIHdoaWNoIHdvdWxkIGluY2x1ZGUgYWxsIHRoZSBvdGhlciBpdGVtc1xuICAgICAgICAgICAgbWluaWNhcnQuc2hvdyhyZXNwb25zZXNbcmVzcG9uc2VzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgfSk7XG59O1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBjbGljayBldmVudCB0byBhIGdpdmVuIHRhcmdldCBmb3IgdGhlIGFkZC10by1jYXJ0IGhhbmRsaW5nXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICQoJy5hZGQtdG8tY2FydFtkaXNhYmxlZF0nKS5hdHRyKCd0aXRsZScsICQoJy5hdmFpbGFiaWxpdHktbXNnJykudGV4dCgpKTtcbiAgICAkKCcucHJvZHVjdC1kZXRhaWwnKS5vbignY2xpY2snLCAnLmFkZC10by1jYXJ0Om5vdChbZGlzYWJsZWRdKTpub3QoW2xvYWRpbmddKScsIGFkZFRvQ2FydCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRJdGVtVG9DYXJ0JywgYWRkSXRlbVRvQ2FydCk7XG4gICAgJChkb2N1bWVudCkub24oJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIGFkZFRvQ2FydCk7XG5cdCQoJyNhZGQtYWxsLXRvLWNhcnQnKS5vbignY2xpY2snLCBhZGRBbGxUb0NhcnQpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSAgcmVxdWlyZSgnLi4vLi4vYWpheCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbnZhciB1cGRhdGVDb250YWluZXIgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIHZhciAkYXZhaWxhYmlsaXR5TXNnID0gJCgnI3BkcE1haW4gLmF2YWlsYWJpbGl0eSAuYXZhaWxhYmlsaXR5LW1zZycpO1xuICAgIHZhciBtZXNzYWdlOyAvLyB0aGlzIHNob3VsZCBiZSBsZXhpY2FsbHkgc2NvcGVkLCB3aGVuIGBsZXRgIGlzIHN1cHBvcnRlZCAoRVM2KVxuICAgIGlmICghZGF0YSkge1xuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmh0bWwoUmVzb3VyY2VzLklURU1fU1RBVFVTX05PVEFWQUlMQUJMRSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgJGF2YWlsYWJpbGl0eU1zZy5lbXB0eSgpO1xuICAgIC8vIExvb2sgdGhyb3VnaCBsZXZlbHMgLi4uIGlmIG1zZyBpcyBub3QgZW1wdHksIHRoZW4gY3JlYXRlIHNwYW4gZWxcbiAgICBpZiAoZGF0YS5sZXZlbHMuSU5fU1RPQ0sgPiAwKSB7XG4gICAgICAgIGlmIChkYXRhLmxldmVscy5QUkVPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5CQUNLT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuTk9UX0FWQUlMQUJMRSA9PT0gMCkge1xuICAgICAgICAgICAgLy8gSnVzdCBpbiBzdG9ja1xuICAgICAgICAgICAgbWVzc2FnZSA9IFJlc291cmNlcy5JTl9TVE9DSztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEluIHN0b2NrIHdpdGggY29uZGl0aW9ucyAuLi5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBkYXRhLmluU3RvY2tNc2c7XG4gICAgICAgIH1cbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5hcHBlbmQoJzxwIGNsYXNzPVwiaW4tc3RvY2stbXNnXCI+JyArIG1lc3NhZ2UgKyAnPC9wPicpO1xuICAgIH1cbiAgICBpZiAoZGF0YS5sZXZlbHMuUFJFT1JERVIgPiAwKSB7XG4gICAgICAgIGlmIChkYXRhLmxldmVscy5JTl9TVE9DSyA9PT0gMCAmJiBkYXRhLmxldmVscy5CQUNLT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuTk9UX0FWQUlMQUJMRSA9PT0gMCkge1xuICAgICAgICAgICAgbWVzc2FnZSA9IFJlc291cmNlcy5QUkVPUkRFUjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBkYXRhLnByZU9yZGVyTXNnO1xuICAgICAgICB9XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuYXBwZW5kKCc8cCBjbGFzcz1cInByZW9yZGVyLW1zZ1wiPicgKyBtZXNzYWdlICsgJzwvcD4nKTtcbiAgICB9XG4gICAgaWYgKGRhdGEubGV2ZWxzLkJBQ0tPUkRFUiA+IDApIHtcbiAgICAgICAgaWYgKGRhdGEubGV2ZWxzLklOX1NUT0NLID09PSAwICYmIGRhdGEubGV2ZWxzLlBSRU9SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLk5PVF9BVkFJTEFCTEUgPT09IDApIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBSZXNvdXJjZXMuQkFDS09SREVSO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWVzc2FnZSA9IGRhdGEuYmFja09yZGVyTXNnO1xuICAgICAgICB9XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuYXBwZW5kKCc8cCBjbGFzcz1cImJhY2tvcmRlci1tc2dcIj4nICsgbWVzc2FnZSArICc8L3A+Jyk7XG4gICAgfVxuICAgIGlmIChkYXRhLmluU3RvY2tEYXRlICE9PSAnJykge1xuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmFwcGVuZCgnPHAgY2xhc3M9XCJpbi1zdG9jay1kYXRlLW1zZ1wiPicgKyBTdHJpbmcuZm9ybWF0KFJlc291cmNlcy5JTl9TVE9DS19EQVRFLCBkYXRhLmluU3RvY2tEYXRlKSArICc8L3A+Jyk7XG4gICAgfVxuICAgIGlmIChkYXRhLmxldmVscy5OT1RfQVZBSUxBQkxFID4gMCkge1xuICAgICAgICBpZiAoZGF0YS5sZXZlbHMuUFJFT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuQkFDS09SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLklOX1NUT0NLID09PSAwKSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gUmVzb3VyY2VzLk5PVF9BVkFJTEFCTEU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gUmVzb3VyY2VzLlJFTUFJTl9OT1RfQVZBSUxBQkxFO1xuICAgICAgICB9XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuYXBwZW5kKCc8cCBjbGFzcz1cIm5vdC1hdmFpbGFibGUtbXNnXCI+JyArIG1lc3NhZ2UgKyAnPC9wPicpO1xuICAgIH1cbn07XG5cbnZhciBnZXRBdmFpbGFiaWxpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgdXJsOiB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKFVybHMuZ2V0QXZhaWxhYmlsaXR5LCB7XG4gICAgICAgICAgICBwaWQ6ICQoJyNwaWQnKS52YWwoKSxcbiAgICAgICAgICAgIFF1YW50aXR5OiAkKHRoaXMpLnZhbCgpXG4gICAgICAgIH0pLFxuICAgICAgICAvL2NhbGxiYWNrOiB1cGRhdGVDb250YWluZXJcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICQoJyNwZHBNYWluJykub24oJ2NoYW5nZScsICcucGRwRm9ybSBpbnB1dFtuYW1lPVwiUXVhbnRpdHlcIl0nLCBnZXRBdmFpbGFiaWxpdHkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxudmFyIHpvb21NZWRpYVF1ZXJ5ID0gbWF0Y2hNZWRpYSgnKG1pbi13aWR0aDogOTYwcHgpJyk7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVuYWJsZXMgdGhlIHpvb20gdmlld2VyIG9uIHRoZSBwcm9kdWN0IGRldGFpbCBwYWdlXG4gKiBAcGFyYW0gem1xIHtNZWRpYSBRdWVyeSBMaXN0fVxuICovXG52YXIgbG9hZFpvb20gPSBmdW5jdGlvbiAoem1xKSB7XG4gICAgdmFyICRpbWdab29tID0gJCgnI3BkcE1haW4gLm1haW4taW1hZ2UnKSxcbiAgICAgICAgaGlyZXNVcmw7XG4gICAgaWYgKCF6bXEpIHtcbiAgICAgICAgem1xID0gem9vbU1lZGlhUXVlcnk7XG4gICAgfVxuICAgIGlmICgkaW1nWm9vbS5sZW5ndGggPT09IDAgfHwgZGlhbG9nLmlzQWN0aXZlKCkgfHwgdXRpbC5pc01vYmlsZSgpIHx8ICF6b29tTWVkaWFRdWVyeS5tYXRjaGVzKSB7XG4gICAgICAgIC8vIHJlbW92ZSB6b29tXG4gICAgICAgICRpbWdab29tLnRyaWdnZXIoJ3pvb20uZGVzdHJveScpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGhpcmVzVXJsID0gJGltZ1pvb20uYXR0cignaHJlZicpO1xuXG4gICAgaWYgKGhpcmVzVXJsICYmIGhpcmVzVXJsICE9PSAnbnVsbCcgJiYgaGlyZXNVcmwuaW5kZXhPZignbm9pbWFnZWxhcmdlJykgPT09IC0xICYmIHpvb21NZWRpYVF1ZXJ5Lm1hdGNoZXMpIHtcbiAgICAgICAgJGltZ1pvb20uem9vbSh7XG4gICAgICAgICAgICB1cmw6IGhpcmVzVXJsXG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbnpvb21NZWRpYVF1ZXJ5LmFkZExpc3RlbmVyKGxvYWRab29tKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbWFpbiBpbWFnZSBhdHRyaWJ1dGVzIGFuZCB0aGUgaHJlZiBmb3IgdGhlIHN1cnJvdW5kaW5nIDxhPiB0YWdcbiAqIEBwYXJhbSB7T2JqZWN0fSBhdHRzIE9iamVjdCB3aXRoIHVybCwgYWx0LCB0aXRsZSBhbmQgaGlyZXMgcHJvcGVydGllc1xuICovXG52YXIgc2V0TWFpbkltYWdlID0gZnVuY3Rpb24gKGF0dHMpIHtcbiAgICAkKCcjcGRwTWFpbiAucHJpbWFyeS1pbWFnZScpLmF0dHIoe1xuICAgICAgICBzcmM6IGF0dHMudXJsLFxuICAgICAgICBhbHQ6IGF0dHMuYWx0LFxuICAgICAgICB0aXRsZTogYXR0cy50aXRsZVxuICAgIH0pO1xuICAgIGlmICghZGlhbG9nLmlzQWN0aXZlKCkgJiYgIXV0aWwuaXNNb2JpbGUoKSkge1xuICAgICAgICAkKCcjcGRwTWFpbiAubWFpbi1pbWFnZScpLmF0dHIoJ2hyZWYnLCBhdHRzLmhpcmVzKTtcbiAgICB9XG4gICAgbG9hZFpvb20oKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcGxhY2VzIHRoZSBpbWFnZXMgaW4gdGhlIGltYWdlIGNvbnRhaW5lciwgZm9yIGVnLiB3aGVuIGEgZGlmZmVyZW50IGNvbG9yIHdhcyBjbGlja2VkLlxuICovXG5cbnZhciByZXBsYWNlSW1hZ2VzID0gZnVuY3Rpb24gKCkge1xuXHRcbiAgICB2YXIgJG5ld0ltYWdlcyA9ICQoJyN1cGRhdGUtaW1hZ2VzJyksXG4gICAgICAgICR3aW4gPSAkKHdpbmRvdyksXG4gICAgICAgICRpbWFnZUNvbnRhaW5lcixcbiAgICAgICAgJGhlYWRlcixcbiAgICAgICAgJHByb21vc0Nsb25lLFxuICAgICAgICAkcHJvbW9zQ2xvbmVNb2JpbGUsXG4gICAgICAgIG5ld0ltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgXG4gICAgaWYgKCR3aW4ud2lkdGgoKSA8PSAxMDI0KSB7XG4gICAgXHQkaGVhZGVyID0gICQoJyNwZHBNYWluIC5wcm9kdWN0LWltYWdlLWNvbnRhaW5lcicpLmZpbmQoJ2hlYWRlcicpLmNsb25lKCk7XG4gICAgfVxuICAgIGlmICgkbmV3SW1hZ2VzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblxuICAgIC8vIHByb2R1Y3QgY29udGFpbmVyIGNsYXNzZXMgdG8gaGFuZGxlIHN0eWxlcyB3aGlsZSBpbWFnZSBpcyBsb2FkaW5nXG4gICAgJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyJykuYWRkQ2xhc3MoJ2xvYWRpbmctaW1hZ2UnKTtcbiAgICBuZXdJbWFnZS5zcmMgPSAkbmV3SW1hZ2VzLmZpbmQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2NsYXNzKj1cInNsaWRlXCJdJykuZmlyc3QoKS5maW5kKCdpbWcnKS5hdHRyKCdzcmMnKTtcbiAgICBuZXdJbWFnZS5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmctaW1hZ2UnKTtcbiAgICB9XG4gICAgXG4gICAgdmFyIGF0dGFjaFByb21vc01vYmlsZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcbiAgICAgICAgICAgIHZhciAkaW1hZ2VDb250YWluZXJNb2JpbGUgPSAkKCcjcGRwTWFpbiAucHJvZHVjdC1pbWFnZS1jb250YWluZXInKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciAkaW1hZ2VDb250YWluZXJNb2JpbGUgPSAkKCcjcGRwTWFpbiAucHJvZHVjdC1pbWFnZS1jb250YWluZXItbW9iaWxlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyICRwcm9tb01lc3NhZ2VzTW9iaWxlID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyLW1vYmlsZSAucHJvbW8tbWVzc2FnZXMnKSxcbiAgICAgICAgICAgICRwcm9tb3NDbG9uZU1vYmlsZSA9ICRwcm9tb01lc3NhZ2VzTW9iaWxlLmZpbmQoJy5wcm9tby1tZXNzYWdlcycpLmNsb25lKCk7XG4gICAgICAgIFxuICAgICAgICBpZiAoJHByb21vTWVzc2FnZXNNb2JpbGUuaXMoJzplbXB0eScpICYmICRwcm9tb3NDbG9uZU1vYmlsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkaW1hZ2VDb250YWluZXJNb2JpbGUuaHRtbCgkbmV3SW1hZ2VzLmh0bWwoKSk7XG4gICAgICAgICAgICAkKFwiPGRpdiBjbGFzcz0ncHJvbW8tbWVzc2FnZXMnPjwvZGl2PlwiKS5wcmVwZW5kVG8oJGltYWdlQ29udGFpbmVyTW9iaWxlKTtcbiAgICAgICAgICAgICRwcm9tb3NDbG9uZU1vYmlsZS5wcmVwZW5kVG8oJHByb21vTWVzc2FnZXNNb2JpbGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgJGltYWdlQ29udGFpbmVyTW9iaWxlLmh0bWwoJG5ld0ltYWdlcy5odG1sKCkpO1xuICAgICAgICAgICAgJHByb21vc0Nsb25lTW9iaWxlLnByZXBlbmRUbygkaW1hZ2VDb250YWluZXJNb2JpbGUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBhdHRhY2hQcm9tb3NEZXNrdG9wID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciAkaW1hZ2VDb250YWluZXIgPSAkKCcjcGRwTWFpbiAucHJvZHVjdC1pbWFnZS1jb250YWluZXInKSxcbiAgICAgICAgICAgICRwcm9tb01lc3NhZ2VzID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyIC5wcm9tby1tZXNzYWdlcycpLFxuICAgICAgICAgICAgJHByb21vc0Nsb25lID0gJHByb21vTWVzc2FnZXMuY2xvbmUoKTtcbiAgICAgICAgXG4gICAgICAgIC8vd2luZG93LmNvbnNvbGUubG9nKFwiJHByb21vTWVzc2FnZXM6IFwiLCRwcm9tb01lc3NhZ2VzLmxlbmd0aCwgXCIgJHByb21vc0Nsb25lLmxlbmd0aDogXCIsICRwcm9tb3NDbG9uZS5sZW5ndGgpO1xuICAgICAgICBcbiAgICAgICAgaWYgKCRwcm9tb01lc3NhZ2VzLmlzKCc6ZW1wdHknKSAmJiAkcHJvbW9zQ2xvbmUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGltYWdlQ29udGFpbmVyLmh0bWwoJG5ld0ltYWdlcy5odG1sKCkpO1xuICAgICAgICAgICAgJChcIjxkaXYgY2xhc3M9J3Byb21vLW1lc3NhZ2VzJz48L2Rpdj5cIikucHJlcGVuZFRvKCRpbWFnZUNvbnRhaW5lcik7XG4gICAgICAgICAgICAkcHJvbW9zQ2xvbmUucHJlcGVuZFRvKCRwcm9tb01lc3NhZ2VzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICRpbWFnZUNvbnRhaW5lci5odG1sKCRuZXdJbWFnZXMuaHRtbCgpKTtcbiAgICAgICAgICAgICRwcm9tb3NDbG9uZS5wcmVwZW5kVG8oJGltYWdlQ29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoJHdpbi53aWR0aCgpIDw9IDc2NyApIHtcbiAgICAgICAgYXR0YWNoUHJvbW9zTW9iaWxlKCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBhdHRhY2hQcm9tb3NEZXNrdG9wKCk7XG4gICAgfVxuICAgIFxuICAgICRuZXdJbWFnZXMucmVtb3ZlKCk7XG4gICAgbG9hZFpvb20oKTtcbn07XG5cbi8qIEBtb2R1bGUgaW1hZ2VcbiAqIEBkZXNjcmlwdGlvbiB0aGlzIG1vZHVsZSBoYW5kbGVzIHRoZSBwcmltYXJ5IGltYWdlIHZpZXdlciBvbiBQRFBcbiAqKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gYnkgZGVmYXVsdCwgdGhpcyBmdW5jdGlvbiBzZXRzIHVwIHpvb20gYW5kIGV2ZW50IGhhbmRsZXIgZm9yIHRodW1ibmFpbCBjbGlja1xuICoqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGRpYWxvZy5pc0FjdGl2ZSgpIHx8IHV0aWwuaXNNb2JpbGUoKSkge1xuICAgICAgICAkKCcjcGRwTWFpbiAubWFpbi1pbWFnZScpLnJlbW92ZUF0dHIoJ2hyZWYnKTtcbiAgICB9XG4gICAgbG9hZFpvb20oKTtcbiAgICAvLyBoYW5kbGUgcHJvZHVjdCB0aHVtYm5haWwgY2xpY2sgZXZlbnRcbiAgICAkKCcjcGRwTWFpbicpLm9uKCdjbGljaycsICcucHJvZHVjdHRodW1ibmFpbCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gc3dpdGNoIGluZGljYXRvclxuICAgICAgICAkKHRoaXMpLmNsb3Nlc3QoJy5wcm9kdWN0LXRodW1ibmFpbHMnKS5maW5kKCcudGh1bWIuc2VsZWN0ZWQnKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAgICAgJCh0aGlzKS5jbG9zZXN0KCcudGh1bWInKS5hZGRDbGFzcygnc2VsZWN0ZWQnKTtcblxuICAgICAgICBzZXRNYWluSW1hZ2UoJCh0aGlzKS5kYXRhKCdsZ2ltZycpKTtcbiAgICB9KTtcbn07XG5tb2R1bGUuZXhwb3J0cy5sb2FkWm9vbSA9IGxvYWRab29tO1xubW9kdWxlLmV4cG9ydHMuc2V0TWFpbkltYWdlID0gc2V0TWFpbkltYWdlO1xubW9kdWxlLmV4cG9ydHMucmVwbGFjZUltYWdlcyA9IHJlcGxhY2VJbWFnZXM7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBwcm9kdWN0U3RvcmVJbnZlbnRvcnkgPSByZXF1aXJlKCcuLi8uLi9zdG9yZWludmVudG9yeS9wcm9kdWN0Jyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xudmFyIGFkZFRvQ2FydCA9IHJlcXVpcmUoJy4vYWRkVG9DYXJ0Jyk7XG52YXIgYXZhaWxhYmlsaXR5ID0gcmVxdWlyZSgnLi9hdmFpbGFiaWxpdHknKTtcbnZhciBpbWFnZSA9IHJlcXVpcmUoJy4vaW1hZ2UnKTtcbnZhciB2aWRlbyA9IHJlcXVpcmUoJy4vdmlkZW8nKTtcbnZhciBwcm9kdWN0U2V0ID0gcmVxdWlyZSgnLi9wcm9kdWN0U2V0Jyk7XG52YXIgdmFyaWFudCA9IHJlcXVpcmUoJy4vdmFyaWFudCcpO1xudmFyIHJlcXVlc3RHaWZ0ID0gcmVxdWlyZSgnLi9yZXF1ZXN0R2lmdCcpO1xudmFyIHJlY2FwdGNoYSA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvUmVjYXB0Y2hhJyk7XG52YXIgcmVjZW50bHlWaWV3ZWRQcm9kdWN0cyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvUmVjZW50bHlWaWV3ZWRQcm9kdWN0cycpO1xudmFyIHJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zJyk7XG52YXIgc2FtZURheVNoaXBwaW5nQ291bnRkb3duID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9TYW1lRGF5U2hpcHBpbmdDb3VudGRvd24nKTtcbnZhciBTaG9wUGF5ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vaW50X3Nob3BwYXlfc2ZyYS9jYXJ0cmlkZ2UvY2xpZW50L2RlZmF1bHQvanMvY2FydC9pbml0U2hvcFBheUNhcnQnKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG52YXIgZGF0YUJ1ZmZlciA9IHt9O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplIHByb2R1Y3QgZGV0YWlsIHBhZ2Ugd2l0aCByZXZpZXdzLCByZWNvbW1lbmRhdGlvbiBhbmQgcHJvZHVjdCBuYXZpZ2F0aW9uLlxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRG9tKG9wdGlvbnMpIHtcblx0dG9vbHRpcC5pbml0KCk7XG5cblx0dmFyICRzYW1lRGF5U2hpcHBpbmdDb3VudGRvd25Db250YWluZXIgPSAkKCcuc2FtZS1kYXktc2hpcHBpbmctY291bnRkb3duJyk7XG5cdGlmICgkc2FtZURheVNoaXBwaW5nQ291bnRkb3duQ29udGFpbmVyLmxlbmd0aCA+IDAgJiYgKCFvcHRpb25zIHx8IG9wdGlvbnMuQ2hhbm5lbCAhPSAnQm9vdEJhcm5FeHByZXNzJykpIHtcblx0XHRzYW1lRGF5U2hpcHBpbmdDb3VudGRvd24uaW5pdGlhbGl6ZSgkc2FtZURheVNoaXBwaW5nQ291bnRkb3duQ29udGFpbmVyLCBvcHRpb25zLlNhbWVEYXlTaGlwcGluZyk7XG5cdH1cblxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyAmJiB3aW5kb3cuaW5uZXJXaWR0aCA+IDc2OCkge1xuXHRcdCQoZG9jdW1lbnQpLmZpbmQoJy5hY2NvcmRpb24taGVhZCcpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHQkKGRvY3VtZW50KS5maW5kKCcuYWNjb3JkaW9uLWJvZHknKS5jc3MoJ2Rpc3BsYXknLCAnYmxvY2snKTtcblx0fVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplIGV2ZW50IGhhbmRsZXJzIG9uIHByb2R1Y3QgZGV0YWlsIHBhZ2VcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cyhvcHRpb25zKSB7XG4gICAgdmFyICRwZHBNYWluID0gJCgnI3BkcE1haW4nKTtcblxuICAgIGFkZFRvQ2FydCgpO1xuICAgIGF2YWlsYWJpbGl0eSgpO1xuICAgIGltYWdlKCk7XG4gICAgdmlkZW8oKTtcbiAgICBwcm9kdWN0U2V0KCk7XG4gICAgcmVxdWVzdEdpZnQoeyBSZWNhcHRjaGE6IG9wdGlvbnMuUmVjYXB0Y2hhIH0pO1xuXG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgcHJvZHVjdFN0b3JlSW52ZW50b3J5LmluaXQoKTtcbiAgICB9XG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5wcm9kdWN0LXN3YXRjaGVzLWFjY29yZGlvbi1idXR0b24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkYWNjb3JkaW9uID0gJCh0aGlzKS5jbG9zZXN0KCcuYWNjb3JkaW9uJyk7XG5cbiAgICAgICAgaWYgKCRhY2NvcmRpb24ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGFjY29yZGlvbi50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEFkZCB0byBXaXNobGlzdCBhbmQgQWRkIHRvIEdpZnQgUmVnaXN0cnkgbGlua3MgYmVoYXZpb3JzXG4gICAgJHBkcE1haW4ub24oJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbj1cImdpZnQtcmVnaXN0cnlcIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkYXRhID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcygkKCcucGRwRm9ybScpLnNlcmlhbGl6ZSgpKTtcbiAgICAgICAgaWYgKGRhdGEuY2FydEFjdGlvbikge1xuICAgICAgICAgICAgZGVsZXRlIGRhdGEuY2FydEFjdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybCh0aGlzLmhyZWYsIGRhdGEpO1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnaHJlZicsIHVybCk7XG4gICAgfSk7XG5cbiAgICAvLyBwcm9kdWN0IG9wdGlvbnNcbiAgICAkcGRwTWFpbi5vbignY2hhbmdlJywgJy5wcm9kdWN0LW9wdGlvbnMgc2VsZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2FsZXNQcmljZSA9ICRwZHBNYWluLmZpbmQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IC5wcmljZS1zYWxlcycpO1xuICAgICAgICB2YXIgc2VsZWN0ZWRJdGVtID0gJCh0aGlzKS5jaGlsZHJlbigpLmZpbHRlcignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgc2FsZXNQcmljZS50ZXh0KHNlbGVjdGVkSXRlbS5kYXRhKCdjb21iaW5lZCcpKTtcbiAgICB9KTtcblxuICAgIC8vIHByZXZlbnQgZGVmYXVsdCBiZWhhdmlvciBvZiB0aHVtYm5haWwgbGluayBhbmQgYWRkIHRoaXMgQnV0dG9uXG4gICAgJHBkcE1haW4ub24oJ2NsaWNrJywgJy50aHVtYm5haWwtbGluaywgLnVuc2VsZWN0YWJsZSBhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0pO1xuXG4gICAgJHBkcE1haW4ub24oJ2NsaWNrJywgJ2Euc2l6ZS1jaGFydC1saW5rJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICB1cmw6ICQoZS50YXJnZXQpLmF0dHIoJ2hyZWYnKVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIFRlY2hub2xvZ3kgRmVhdHVyZXMgVG9vbHRpcFxuICAgIC8vICQoJy5saXN0LXByb2R1Y3QtaW5mbyBmaWd1cmUgaW1nJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAvLyBcdHZhciAkaW1nID0gJCh0aGlzKSxcbiAgICAvLyBcdFx0JHRhcmdldCA9ICRpbWcucGFyZW50cygnbGknKS5maXJzdCgpLmZpbmQoJy50b29sdGlwLWNvbnRlbnQgaW1nJyk7XG5cbiAgICAvLyBcdCR0YXJnZXQuYXR0cihcInNyY1wiLCAkaW1nLmRhdGEoJ2hvdmVyJykpLmF0dHIoXCJhbHRcIiwgJGltZy5hdHRyKFwiYWx0XCIpKS5hdHRyKFwid2lkdGhcIiwgXCIyMzZweFwiKTtcbiAgICAvLyB9KTtcblxuICAgIC8vICQoJy5saXN0LXByb2R1Y3QtaW5mbycpLnRvb2x0aXAoe1xuICAgIC8vICAgICBpdGVtczogJ2xpJyxcbiAgICAvLyAgICAgdG9vbHRpcENsYXNzOiAndGVjaGZlYXR1cmUtdG9vbHRpcCcsXG4gICAgLy8gICAgIHRyYWNrOiB0cnVlLFxuICAgIC8vICAgICBjb250ZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgLy8gICAgICAgICByZXR1cm4gJCh0aGlzKS5maW5kKCcudG9vbHRpcC1jb250ZW50JykuaHRtbCgpO1xuICAgIC8vICAgICB9XG4gICAgLy8gfSk7XG5cblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcuc2VhcmNoYWdhaW4tYnRuJyxmdW5jdGlvbigpIHtcblx0XHQkKCcjZGlhbG9nLWNvbnRhaW5lciAuZmluZFN0b3JlLXJlc3VsdCcpLmhpZGUoKTtcblx0XHQkKCcjZGlhbG9nLWNvbnRhaW5lciAudWktZGlhbG9nLWZvb3RlcicpLnNob3coKTtcblx0XHQkKCcudWktZGlhbG9nJykuY3NzKHsnaGVpZ2h0JyA6ICcyMzBweCAhaW1wb3J0YW50JywndG9wJzonMjYwcHggIWltcG9ydGFudCd9KTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywnLmZpbmQtc3RvcmUtYnRuJyxmdW5jdGlvbigpIHtcblx0XHRkaWFsb2cub3Blbih7XG5cdFx0XHRodG1sOigkKCcuZmluZFN0b3JlRGlhbG9nJykuaHRtbCgpKS5yZXBsYWNlKC9zZWxlY3QtaG9sZGVyL2csJycpLFxuXHRcdFx0Y2FsbGJhY2s6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkKGRvY3VtZW50KS5vbignY2xpY2snLCcuZmluZHN0b3JlLWZvcm1Db250YWluZXIgLmZpbmRTdG9yZS1idG4nLGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciB6aXBjb2RlICAgID0gJCgnI2RpYWxvZy1jb250YWluZXIgaW5wdXQuemlwY29kZScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0cmFkaXVzICAgICA9ICQoJyNkaWFsb2ctY29udGFpbmVyIHNlbGVjdC5yYWRpdXMnKS52YWwoKSxcblx0XHRcdFx0XHRcdHBvc3RhbGNvZGUgPSAkKCcjZGlhbG9nLWNvbnRhaW5lciAucG9zdGFsY29kZSBzZWxlY3QnKS52YWwoKSxcblx0XHRcdFx0XHRcdHN0YXRlY29kZSA9ICQoJyNkaWFsb2ctY29udGFpbmVyIC5zdGF0ZWNvZGUgc2VsZWN0JykudmFsKCksXG5cdFx0XHRcdFx0XHRwaWQgICAgICAgID0gJCgnI2RpYWxvZy1jb250YWluZXIgI3BpZCcpLnZhbCgpLFxuXHRcdFx0XHRcdFx0dmFsdWVzIFx0ICAgPSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHBpZCA6IHBpZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0emlwQ29kZSA6IHppcGNvZGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJhZGl1cyA6IHJhZGl1cyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0c3RhdGVjb2RlIDogc3RhdGVjb2RlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRwb3N0YWxjb2RlIDogcG9zdGFsY29kZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHRcdHVybDogVXJscy5zdG9yZWF2YWlsYWJpbGl0eSxcblx0XHRcdFx0XHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0XHRcdFx0XHRkYXRhOiB2YWx1ZXMgLFxuXHRcdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRcdFx0XHRcdCQoJyNkaWFsb2ctY29udGFpbmVyIC5maW5kU3RvcmUtcmVzdWx0Jykuc2hvdygpO1xuXHRcdFx0XHRcdFx0XHQkKCcjZGlhbG9nLWNvbnRhaW5lciAudWktZGlhbG9nLWZvb3RlcicpLmhpZGUoKTtcblx0XHRcdFx0XHRcdFx0JCgnI2RpYWxvZy1jb250YWluZXIgLmZpbmRTdG9yZS1yZXN1bHQnKS5odG1sKHJlc3BvbnNlKS50ZXh0KCk7XG5cblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKHRleHRTdGF0dXMsIGVycm9yVGhyb3duKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9LFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHR0aXRsZTogUmVzb3VyY2VzLkZJTkRTVE9SRV9USVRMRVxuXHRcdFx0fSxcblx0XHR9KTtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignUmVjZW50bHlWaWV3ZWRQcm9kdWN0cy5Eb25lJykub24oJ1JlY2VudGx5Vmlld2VkUHJvZHVjdHMuRG9uZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0bG9hZGVkLlJlY2VudGx5Vmlld2VkUHJvZHVjdHMgPSB0cnVlO1xuXHRcdGFkZFByb21vdGlvbkRhdGFMYXllcnMoKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdFaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuRG9uZScpLm9uKCdFaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuRG9uZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0bG9hZGVkLkVpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucyA9IHRydWU7XG5cdFx0YWRkUHJvbW90aW9uRGF0YUxheWVycygpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ1JlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Eb25lJykub24oJ1JlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Eb25lJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRsb2FkZWQuUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zICs9IDE7XG5cdFx0YWRkUHJvbW90aW9uRGF0YUxheWVycygpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gYWRkUHJvbW90aW9uRGF0YUxheWVycygpIHtcblx0aWYgKGxvYWRlZC5SZWNlbnRseVZpZXdlZFByb2R1Y3RzICYmIGxvYWRlZC5FaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMgJiYgbG9hZGVkLlJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucyA9PSBkYXRhQnVmZmVyWydSZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnNDb3VudCddKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignR29vZ2xlVGFnTWFuYWdlci5BZGRQcm9tb3Rpb25EYXRhTGF5ZXJzJyk7XG5cdH1cbn1cblxudmFyIHByb2R1Y3QgPSB7XG4gICAgaW5pdGlhbGl6ZUV2ZW50czogaW5pdGlhbGl6ZUV2ZW50cyxcbiAgICBpbml0OiBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuICAgIFx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdFx0bG9hZGVkID0ge1xuXHRcdFx0UmVjZW50bHlWaWV3ZWRQcm9kdWN0czogZmFsc2UsXG5cdFx0XHRFaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnM6IGZhbHNlLFxuXHRcdFx0UmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zOiAwXG5cdFx0fTtcblx0XHRkYXRhQnVmZmVyID0ge1xuXHRcdFx0UmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zQ291bnQ6IDBcblx0XHR9O1xuXG4gICAgXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yTWVycnlNYWlsKSB7XG4gICAgICAgIFx0cmVjYXB0Y2hhLmluaXRpYWxpemUoKTtcbiAgICBcdH1cblxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjZW50bHlWaWV3ZWRQcm9kdWN0cykge1xuICAgIFx0XHRyZWNlbnRseVZpZXdlZFByb2R1Y3RzLmluaXRpYWxpemUob3B0aW9ucy5SZWNlbnRseVZpZXdlZFByb2R1Y3RzKTtcbiAgICBcdH0gZWxzZSB7XG5cdFx0XHRsb2FkZWQuUmVjZW50bHlWaWV3ZWRQcm9kdWN0cyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLkVpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucykge1xuXHRcdFx0bG9hZGVkLkVpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5SZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMpIHtcblx0XHRcdGRhdGFCdWZmZXJbJ1JlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9uc0NvdW50J10gPSBvcHRpb25zLlJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Db250YWluZXJzLmxlbmd0aDtcblx0XHRcdHJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucy5pbml0aWFsaXplKG9wdGlvbnMuUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zKTtcblx0XHR9XG5cblx0XHR2YXJpYW50LmluaXRpYWxpemUob3B0aW9ucyk7XG5cblx0XHRpbml0aWFsaXplRG9tKG9wdGlvbnMpO1xuXHRcdGluaXRpYWxpemVFdmVudHMob3B0aW9ucyk7XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvZHVjdDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4JyksXG4gICAgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGFkZFRvQ2FydCA9ICQoJyNhZGQtdG8tY2FydCcpLFxuICAgICAgICAkYWRkQWxsVG9DYXJ0ID0gJCgnI2FkZC1hbGwtdG8tY2FydCcpLFxuICAgICAgICAkcHJvZHVjdFNldExpc3QgPSAkKCcjcHJvZHVjdC1zZXQtbGlzdCcpO1xuXG4gICAgdmFyIHVwZGF0ZUFkZFRvQ2FydEJ1dHRvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgkcHJvZHVjdFNldExpc3QuZmluZCgnLmFkZC10by1jYXJ0W2Rpc2FibGVkXScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRhZGRBbGxUb0NhcnQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIC8vIHByb2R1Y3Qgc2V0IGRvZXMgbm90IGhhdmUgYW4gYWRkLXRvLWNhcnQgYnV0dG9uLCBidXQgcHJvZHVjdCBidW5kbGUgZG9lc1xuICAgICAgICAgICAgJGFkZFRvQ2FydC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGFkZEFsbFRvQ2FydC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgJGFkZFRvQ2FydC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICgkcHJvZHVjdFNldExpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICB1cGRhdGVBZGRUb0NhcnRCdXR0b25zKCk7XG4gICAgfVxuICAgIC8vIGNsaWNrIG9uIHN3YXRjaCBmb3IgcHJvZHVjdCBzZXRcbiAgICAkcHJvZHVjdFNldExpc3Qub24oJ2NsaWNrJywgJy5wcm9kdWN0LXNldC1pdGVtIC5zd2F0Y2hhbmNob3InLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7IHJldHVybjsgfVxuICAgICAgICB2YXIgdXJsID0gVXJscy5nZXRTZXRJdGVtICsgdGhpcy5zZWFyY2g7XG4gICAgICAgIHZhciAkY29udGFpbmVyID0gJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC1zZXQtaXRlbScpO1xuICAgICAgICB2YXIgcXR5ID0gJGNvbnRhaW5lci5maW5kKCdmb3JtIGlucHV0W25hbWU9XCJRdWFudGl0eVwiXScpLmZpcnN0KCkudmFsKCk7XG5cbiAgICAgICAgYWpheC5sb2FkKHtcbiAgICAgICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ1F1YW50aXR5JywgaXNOYU4ocXR5KSA/ICcxJyA6IHF0eSksXG4gICAgICAgICAgICB0YXJnZXQ6ICRjb250YWluZXIsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZUFkZFRvQ2FydEJ1dHRvbnMoKTtcbiAgICAgICAgICAgICAgICB0b29sdGlwLmluaXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4Jyk7XG52YXIgcGFnZSA9IHJlcXVpcmUoJy4uLy4uL3BhZ2UnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xudmFyIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xudmFyIHZhbGlkYXRvciA9IHJlcXVpcmUoJy4uLy4uL3ZhbGlkYXRvcicpO1xuXG52YXIgb3B0aW9ucztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBwcm9kdWN0IGluZm9ybWF0aW9uXG4gKiBAcGFyYW0ge2V2ZW50fSBlIFRoZSBjbGljayBldmVudCBmcm9tIHRoZSByZXF1ZXN0IGdpZnQgYnV0dG9uXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBwcm9kdWN0SW5mb1xuICovXG52YXIgZ2V0UHJvZHVjdEluZm8gPSBmdW5jdGlvbihlKSB7XG5cdHZhciBwcm9kdWN0SW5mbztcblx0dmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHR2YXIgaXNTaXplU2VsZWN0ZWQgPSBzaXplU2VsZWN0ZWQubGVuZ3RoIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKTtcblxuXHRpZiAoIWlzU2l6ZVNlbGVjdGVkKSB7XG5cdFx0YWxlcnQoJ1BsZWFzZSBzZWxlY3QgYSBzaXplJyk7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cdGlmICghJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuY29sb3IuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aCkge1xuXHRcdGFsZXJ0KCdQbGVhc2Ugc2VsZWN0IGEgY29sb3InKTtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvLyBnZXQgcHJvZHVjdCBpbmZvXG5cdGlmICh0eXBlb2YgZGF0YUxheWVyICE9PSAndW5kZWZpbmVkJykge1xuXHRcdHZhciB2YXJpYXRpb25BdHRyaWJ1dGUgPSAkKCcucHJvZHVjdC12YXJpYXRpb25zJykuZGF0YSgnYXR0cmlidXRlcycpO1xuXHRcdHZhciBzaXplQXR0cmlidXRlVmFsdWUgPSB2YXJpYXRpb25BdHRyaWJ1dGUuc2l6ZS5kaXNwbGF5VmFsdWU7XG5cdFx0aWYgKCBzaXplQXR0cmlidXRlVmFsdWUgPT0gJycgfHwgc2l6ZUF0dHJpYnV0ZVZhbHVlID09IG51bGwgKSB7XG5cdFx0XHRpZiAoc2l6ZVNlbGVjdGVkLmhhc0NsYXNzKFwidGVtcHNlbGVjdGlvblwiKSAmJiBzaXplU2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS5kYXRhKCkgIT0gbnVsbCApIHtcblx0XHRcdFx0c2l6ZVNlbGVjdGVkLmFkZENsYXNzKCdlbnRlclNlbGVjdGVkJyk7XG5cdFx0XHRcdHZhciBzaXplT2JqZWN0UmVmZXJlbmNlID0gc2l6ZVNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykuZGF0YSgpO1xuXHRcdFx0XHRzaXplQXR0cmlidXRlVmFsdWUgPSBzaXplT2JqZWN0UmVmZXJlbmNlLnNpemVOYW1lO1xuXHRcdFx0XHRzaXplU2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvcih2YXIgaT0wO2k8ZGF0YUxheWVyLmxlbmd0aDtpKyspIHtcblx0XHRcdGlmKGRhdGFMYXllcltpXS5ldmVudCA9PSAncGRwRGlzcGxheScpIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkSXRlbSA9IGRhdGFMYXllcltpXS5lY29tbWVyY2UuZGV0YWlsLnByb2R1Y3RzWzBdO1xuXHRcdFx0XHR2YXIgaXNTd2lwZXIgPSAkKCcucHJvZHVjdC1wcmltYXJ5LWltYWdlIFtjbGFzcyo9XCItaW5pdGlhbGl6ZWRcIl0nKS5maXJzdCgpLmhhc0NsYXNzKCdzd2lwZXItaW5pdGlhbGl6ZWQnKTtcblx0XHRcdFx0dmFyIGFjdGl2ZUltYWdlID0gaXNTd2lwZXIgPyAkKGUudGFyZ2V0KS5jbG9zZXN0KCcjcGRwTWFpbicpLmZpbmQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgLnN3aXBlci1zbGlkZS1hY3RpdmUgaW1nJykuYXR0cignc3JjJykgOiAkKGUudGFyZ2V0KS5jbG9zZXN0KCcjcGRwTWFpbicpLmZpbmQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgLnNsaWNrLWFjdGl2ZSAuem9vbWVkSW1hZ2UnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdHByb2R1Y3RJbmZvID0ge1xuXHRcdFx0XHRcdFwiaWRcIjogc2VsZWN0ZWRJdGVtLmlkLFxuXHRcdFx0XHRcdFwibmFtZVwiOiBzZWxlY3RlZEl0ZW0ubmFtZSxcblx0XHRcdFx0XHRcImltYWdlVXJsXCI6IGFjdGl2ZUltYWdlLFxuXHRcdFx0XHRcdFwic2l6ZVwiOiBzaXplQXR0cmlidXRlVmFsdWUsXG5cdFx0XHRcdFx0XCJjb2xvclwiOiB2YXJpYXRpb25BdHRyaWJ1dGUuY29sb3IuZGlzcGxheVZhbHVlLFxuXHRcdFx0XHRcdFwiY29sb3JDb2RlXCI6IHZhcmlhdGlvbkF0dHJpYnV0ZS5jb2xvci52YWx1ZVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVx0XG5cdH1cblx0cmV0dXJuIHByb2R1Y3RJbmZvO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRm9ybWF0cyBhIFVSTCB3aXRoIHByZXNldCBwcm9kdWN0IGF0dHJpYnV0ZXNcbiAqIEBwYXJhbSB7b2JqZWN0fSBwcm9kdWN0SW5mbyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgcHJvZHVjdCdzIGF0dHJpYnV0ZXNcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHVybFxuICovXG52YXIgY3JlYXRlUHJvZHVjdFVybCA9IGZ1bmN0aW9uKHByb2R1Y3RJbmZvKSB7XG5cdHZhciB1cmwgPSB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWUgKyB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG5cdGlmIChwcm9kdWN0SW5mby5pZCAmJiBwcm9kdWN0SW5mby5pZC5sZW5ndGggPiAwKSB7XG5cdFx0dXJsID0gdXJsICsgJz9kd3Zhcl8nICsgcHJvZHVjdEluZm8uaWQ7XG5cdFx0aWYgKHByb2R1Y3RJbmZvLmNvbG9yQ29kZSAmJiBwcm9kdWN0SW5mby5jb2xvckNvZGUubGVuZ3RoID4gMCkge1xuXHRcdFx0dXJsID0gdXJsICsgJ19jb2xvcj0nICsgcHJvZHVjdEluZm8uY29sb3JDb2RlO1xuXHRcdH1cblx0XHRpZiAocHJvZHVjdEluZm8uc2l6ZSAmJiBwcm9kdWN0SW5mby5zaXplLmxlbmd0aCA+IDApIHtcblx0XHRcdHVybCA9IHVybCArICcjcHJlZm4xPXNpemUmcHJlZnYxPScgKyBwcm9kdWN0SW5mby5zaXplO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gdXJsO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gT3BlbiB0aGUgcmVxdWVzdCBnaWZ0IGRpYWxvZ1xuICogQHBhcmFtIHtldmVudH0gZSBUaGUgY2xpY2sgZXZlbnQgZnJvbSB0aGUgcmVxdWVzdCBnaWZ0IGJ1dHRvblxuICovXG52YXIgcmVxdWVzdEdpZnQgPSBmdW5jdGlvbihlKSB7XG5cdGUucHJldmVudERlZmF1bHQoKTtcblx0XG5cdHZhciB3aW5kb3dXaWR0aCA9ICQod2luZG93KS53aWR0aCgpO1xuXHRcblx0aWYgKHdpbmRvd1dpZHRoIDw9IDQ4MCkge1xuXHRcdHZhciBkaWFsb2dXaWR0aCA9IHdpbmRvd1dpZHRoIC0gMjA7XG5cdH0gZWxzZSBpZiAod2luZG93V2lkdGggPD0gODQwKSB7XG5cdFx0dmFyIGRpYWxvZ1dpZHRoID0gd2luZG93V2lkdGggLSA0MDtcblx0fSBlbHNlIHtcblx0XHR2YXIgZGlhbG9nV2lkdGggPSA4MDA7XG5cdH1cblxuXHR2YXIgcHJvZHVjdEluZm8gPSBnZXRQcm9kdWN0SW5mbyhlKTtcblx0dmFyIGRpYWxvZ0NsYXNzID0gJ2dpZnQtZGlhbG9nJztcblx0dmFyIHRlbXBsYXRlU2V0dGluZ3MgPSB7aW50ZXJwb2xhdGU6IC97eyhbXFxzXFxTXSs/KX19L2d9O1xuXHR2YXIgZm9ybVRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtcG9wdXAtZm9ybScpLmh0bWwoKSwgdGVtcGxhdGVTZXR0aW5ncyk7XG5cdHZhciBjb25maXJtYXRpb25UZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXBvcHVwLWNvbmZpcm1hdGlvbicpLmh0bWwoKSwgdGVtcGxhdGVTZXR0aW5ncyk7XG5cblx0aWYgKCFwcm9kdWN0SW5mbykge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGRpYWxvZy5vcGVuKHtcblx0XHRodG1sOiBmb3JtVGVtcGxhdGUocHJvZHVjdEluZm8pLFxuXHRcdG9wdGlvbnM6IHtcblx0XHRcdHRpdGxlOiAnU2VuZCBhIGhpbnQnLFxuXHRcdFx0d2lkdGg6IGRpYWxvZ1dpZHRoLFxuXHRcdFx0ZGlhbG9nQ2xhc3M6IGRpYWxvZ0NsYXNzLFxuXHRcdFx0YnV0dG9uczogW10sXG5cdFx0XHRtb2RhbDogdHJ1ZSxcblx0XHRcdG9wZW46IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgJGZvcm0gPSAkKHRoaXMpLmZpbmQoJyNnaWZ0LWZvcm0nKTtcblx0XHRcdFx0Ly8ganF1ZXJ5IHZhbGlkYXRlIGRvZXNuJ3QgcmVxdWlyZSBhbiBlbWFpbCBleHRlbnNpb24sIHNvIGFkZGluZyBpdCBtYW51YWxseVxuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ01lcnJ5TWFpbFZhbGlkYXRlRW1haWwnLFxuXHRcdFx0XHRcdGZ1bmN0aW9uKHZhbHVlLCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gL15cXHcrKFstKy4nXVxcdyspKkBcXHcrKFstLl1cXHcrKSpcXC5cXHcrKFstLl1cXHcrKSokLy50ZXN0KHZhbHVlKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdCdQbGVhc2UgZW50ZXIgYSB2YWxpZCBlbWFpbCBhZGRyZXNzLidcblx0XHRcdFx0KTtcblx0XHRcdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdNZXJyeU1haWxWYWxpZGF0ZU5hbWUnLFxuXHRcdFx0XHRcdGZ1bmN0aW9uKHZhbHVlLCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gISgvOlxcL1xcLy8udGVzdCh2YWx1ZSkpICYmICEoL1xcdysoWy0rLidcXHNdXFx3KSpAXFx3KyhbLS5dXFx3KykqXFwuXFx3KyhbLS5dXFx3KykqLy50ZXN0KHZhbHVlKSk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHQnUGxlYXNlIGVudGVyIGEgdmFsaWQgbmFtZS4nXG5cdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0JGZvcm0udmFsaWRhdGUoe1xuXHRcdFx0XHRcdHJ1bGVzOiB7XG5cdFx0XHRcdFx0XHRjdXN0b21NZXNzYWdlOiB7XG5cdFx0XHRcdFx0XHRcdHJlcXVpcmVkOiB7XG5cdFx0XHRcdFx0XHRcdFx0ZGVwZW5kczogZnVuY3Rpb24oZWxlbWVudCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJtZXNzYWdlXCJdW3ZhbHVlPVwiY3VzdG9tXCJdJykucHJvcCgnY2hlY2tlZCcpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdHNlbmRlck5hbWU6IHtcblx0XHRcdFx0XHRcdFx0TWVycnlNYWlsVmFsaWRhdGVOYW1lOiB0cnVlXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0c2VuZGVyRW1haWw6IHtcblx0XHRcdFx0XHRcdFx0TWVycnlNYWlsVmFsaWRhdGVFbWFpbDogdHJ1ZVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdHJlY2lwaWVudE5hbWU6IHtcblx0XHRcdFx0XHRcdFx0TWVycnlNYWlsVmFsaWRhdGVOYW1lOiB0cnVlXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0cmVjaXBpZW50RW1haWw6IHtcblx0XHRcdFx0XHRcdFx0TWVycnlNYWlsVmFsaWRhdGVFbWFpbDogdHJ1ZVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aWYgKCQoJyNtZXJyeU1haWxTdWJtaXRCdXR0b24nKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvck1lcnJ5TWFpbCAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZW5kZXIoJ21lcnJ5TWFpbFN1Ym1pdEJ1dHRvbicsIHtcblx0XHRcdCAgICAgICAgXHRzaXRla2V5OiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHRcdFx0ICAgICAgICBcdGNhbGxiYWNrOiBzdWJtaXRNZXJyeU1haWwsXG5cdFx0XHQgICAgICAgIFx0YmFkZ2U6ICdib3R0b21sZWZ0J1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQvLyB0cmlnZ2VyIHJhZGlvIGJ1dHRvbiBzZWxlY3Rpb24gaWYgdXNlciBjbGlja3MgaW50byBjdXN0b20gbWVzc2FnZSBpbnB1dFxuXHRcdFx0XHQkKHRoaXMpLmZpbmQoJ2lucHV0W25hbWU9XCJjdXN0b21NZXNzYWdlXCJdJykub2ZmKCdmb2N1cycpLm9uKCdmb2N1cycsIGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0XHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwibWVzc2FnZVwiXVt2YWx1ZT1cImN1c3RvbVwiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKS5jaGFuZ2UoKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0JChkb2N1bWVudCkub2ZmKCdNZXJyeU1haWwuU2VuZCcpLm9uKCdNZXJyeU1haWwuU2VuZCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICAgICAgICBpZiAoISRmb3JtLnZhbGlkKCkpIHtcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHQgICAgICAgIFxuXHRcdFx0XHRcdHZhciBmb3JtRGF0YSA9IHtcblx0XHRcdFx0XHRcdHJlY2lwaWVudE5hbWU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJyZWNpcGllbnROYW1lXCJdJykudmFsKCksXG5cdFx0XHRcdFx0XHRyZWNpcGllbnROYW1lQ2FwczogJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInJlY2lwaWVudE5hbWVcIl0nKS52YWwoKS50b1VwcGVyQ2FzZSgpLFxuXHRcdFx0XHRcdFx0cmVjaXBpZW50RW1haWw6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJyZWNpcGllbnRFbWFpbFwiXScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0c2VuZGVyTmFtZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInNlbmRlck5hbWVcIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdHNlbmRlckVtYWlsOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwic2VuZGVyRW1haWxcIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdGZyb21FbWFpbDogJCgnI21lcnJ5LW1haWwtZnJvbS1lbWFpbCcpLnRleHQoKS5sZW5ndGggPiAwID8gJCgnI21lcnJ5LW1haWwtZnJvbS1lbWFpbCcpLnRleHQoKSA6ICduby1yZXBseUBkZW1hbmR3YXJlLm5ldCcsXG5cdFx0XHRcdFx0XHRzdWJqZWN0OiAkKCcjbWVycnktbWFpbC1lbWFpbC1zdWJqZWN0JykudGV4dCgpLnJlcGxhY2UoJ1tzZW5kZXJfbmFtZV0nLCRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJzZW5kZXJOYW1lXCJdJykudmFsKCkpLFxuXHRcdFx0XHRcdFx0YmFzZVVybDogJCgnI21lcnJ5LW1haWwtYmFzZS11cmwnKS50ZXh0KCksXG5cdFx0XHRcdFx0XHR1bnN1YnNjcmliZVVybDogJCgnI21lcnJ5LW1haWwtdW5zdWJzY3JpYmUtdXJsJykudGV4dCgpLFxuXHRcdFx0XHRcdFx0bWVzc2FnZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIm1lc3NhZ2VcIl06Y2hlY2tlZCcpLnZhbCgpID09PSAnY3VzdG9tJyA/ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJjdXN0b21NZXNzYWdlXCJdJykudmFsKCkgOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwibWVzc2FnZVwiXTpjaGVja2VkJykudmFsKCksXG5cdFx0XHRcdFx0XHRwcm9kdWN0SWQ6IHByb2R1Y3RJbmZvLmlkLFxuXHRcdFx0XHRcdFx0cHJvZHVjdEltYWdlOiB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWUgKyBwcm9kdWN0SW5mby5pbWFnZVVybCxcblx0XHRcdFx0XHRcdHByb2R1Y3RVcmw6IGNyZWF0ZVByb2R1Y3RVcmwocHJvZHVjdEluZm8pLFxuXHRcdFx0XHRcdFx0cHJvZHVjdE5hbWU6IHByb2R1Y3RJbmZvLm5hbWUucmVwbGFjZSgvXFxcXCguKS9tZywgXCIkMVwiKSwgLy8gaGFuZGxlIGJhY2tzbGFzaCBlc2NhcGluZ1xuXHRcdFx0XHRcdFx0c2l6ZTogcHJvZHVjdEluZm8uc2l6ZSxcblx0XHRcdFx0XHRcdGNvbG9yOiBwcm9kdWN0SW5mby5jb2xvclxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcblx0XHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRcdFx0dXJsOiBVcmxzLnNlbmRHaWZ0UmVxdWVzdEVtYWlsLFxuXHRcdFx0XHRcdFx0ZGF0YTogZm9ybURhdGEsXG5cdFx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dmFyIGNvbmZpcm1NZXNzYWdlID0gJCgnI21lcnJ5LW1haWwtc3VjY2Vzcy1tZXNzYWdlJykuaHRtbCgpLnJlcGxhY2UoJ1tyZWNpcGllbnRfbmFtZV0nLGZvcm1EYXRhLnJlY2lwaWVudE5hbWUpO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0XHRcdFx0XHRcdGh0bWw6IGNvbmZpcm1hdGlvblRlbXBsYXRlKHtjb25maXJtTWVzc2FnZTogY29uZmlybU1lc3NhZ2V9KSxcblx0XHRcdFx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aXRsZTogJ1N1Y2Nlc3MhJyxcblx0XHRcdFx0XHRcdFx0XHRcdHdpZHRoOiBkaWFsb2dXaWR0aCxcblx0XHRcdFx0XHRcdFx0XHRcdGRpYWxvZ0NsYXNzOiBkaWFsb2dDbGFzcyxcblx0XHRcdFx0XHRcdFx0XHRcdGJ1dHRvbnM6IFt7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRleHQ6ICdPSycsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNsaWNrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkaWFsb2cuY2xvc2UoKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fV1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5HVE1fRU5BQkxFRCkge1xuXHRcdFx0XHRcdFx0XHRcdGRhdGFMYXllci5wdXNoKHtcblx0XHRcdFx0XHRcdFx0XHRcdCdldmVudCc6IFNpdGVQcmVmZXJlbmNlcy5NRVJSWU1BSUxfR1RNX0VWRU5UX05BTUUsXG5cdFx0XHRcdFx0XHRcdFx0XHQnbWVycnlNYWlsUHJvZHVjdCc6IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0J25hbWUnIDogZm9ybURhdGEucHJvZHVjdE5hbWUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCd1cmwnIDogZm9ybURhdGEucHJvZHVjdFVybFxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHQgICAgfSk7XG5cdFx0XHRcdFxuXHRcdFx0XHQvLyBoYW5kbGUgY2xpY2sgZXZlbnRzIG9uIHN1Ym1pdCBidXR0b25cblx0XHRcdFx0JGZvcm0uZmluZCgnaW5wdXRbdHlwZT1cInN1Ym1pdFwiXScpLm9mZignY2xpY2snKS5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JNZXJyeU1haWwgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcblx0XHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ01lcnJ5TWFpbC5TZW5kJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXHRcblx0cG9wdWxhdGVNb2RhbFByb2R1Y3RDb250ZW50KHByb2R1Y3RJbmZvKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBvcHVsYXRlcyB0aGUgbW9kYWwgd2l0aCBhcHBsaWNhYmxlIHZhcmlhbnQvcHJvZHVjdCBkYXRhXG4gKi9cbnZhciBwb3B1bGF0ZU1vZGFsUHJvZHVjdENvbnRlbnQgPSBmdW5jdGlvbihwcm9kdWN0SW5mbykge1xuXHR2YXIgcHJvZHVjdEltYWdlVXJsID0gcHJvZHVjdEluZm8uaW1hZ2VVcmw7XG5cdHZhciBjdXJyZW50UHJvZHVjdFVybCA9IGNyZWF0ZVByb2R1Y3RVcmwocHJvZHVjdEluZm8pO1xuXHRcblx0JCgnLmdpZnQtZGlhbG9nX19zYW1wbGUtbWVzc2FnZSAucHJvZHVjdC1pbWFnZScpLnJlcGxhY2VXaXRoKCc8aW1nIGNsYXNzPVwicHJvZHVjdC1pbWFnZVwiIHNyYz1cIicgKyBwcm9kdWN0SW1hZ2VVcmwgKyAnP3N3PTUwMFwiIGFsdD1cIlwiIC8+Jyk7XG5cdFxuXHR2YXIgaGludFRleHQgPSAkKCdzdHJvbmcuaGludC1pdGVtJykuaHRtbCgpO1xuXHQkKCdzdHJvbmcuaGludC1pdGVtJykucmVwbGFjZVdpdGgoJzxzdHJvbmcgY2xhc3M9XCJoaW50LWl0ZW1cIj48YSBocmVmPVwiJyArIGN1cnJlbnRQcm9kdWN0VXJsICsgJ1wiPicgKyBoaW50VGV4dCArICc8L2E+PC9zdHJvbmc+Jyk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGVzIHRoZSBzZW5kZXIgYW5kIHJlY2lwaWVudCBuYW1lcyBpbiB0aGUgc2FtcGxlIG1lc3NhZ2UgYXMgdGhlIHVzZXIgZW50ZXJzIHRoYXQgaW5mb3JtYXRpb24gaW50byB0aGUgZm9ybVxuICovXG52YXIgdXBkYXRlU2VuZGVyTmFtZSA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgY3VycmVudFNlbmRlck5hbWUgPSAkKCcuZ2lmdC1mb3JtX19pbnB1dFtuYW1lPVwic2VuZGVyTmFtZVwiXScpLnZhbCgpO1xuXHRcblx0JCgnLm1lcnJ5LW1haWwtbWVzc2FnZS1mcm9tJykucmVwbGFjZVdpdGgoJzxzcGFuIGNsYXNzPVwibWVycnktbWFpbC1tZXNzYWdlLWZyb20gcmVwbGFjZWRcIj4nICsgY3VycmVudFNlbmRlck5hbWUgKyAnPC9zcGFuPicpO1xufTtcblxudmFyIHVwZGF0ZVJlY2lwaWVudE5hbWUgPSBmdW5jdGlvbigpIHtcblx0dmFyIGN1cnJlbnRSZWNpcGllbnROYW1lID0gJCgnLmdpZnQtZm9ybV9faW5wdXRbbmFtZT1yZWNpcGllbnROYW1lXScpLnZhbCgpO1xuXHRcblx0JCgnLm1lcnJ5LW1haWwtbWVzc2FnZS10bycpLnJlcGxhY2VXaXRoKCc8c3BhbiBjbGFzcz1cIm1lcnJ5LW1haWwtbWVzc2FnZS10byByZXBsYWNlZFwiPicgKyBjdXJyZW50UmVjaXBpZW50TmFtZSArICc8L3NwYW4+Jyk7XG59O1xuXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGNsaWNrIGV2ZW50IHRvIHRoZSBidXR0b24gZm9yIHRoZSByZXF1ZXN0IGdpZnQgaGFuZGxpbmdcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0XG5cdCQoJy5wcm9kdWN0LWRldGFpbCcpLm9uKCdjbGljaycsICdbZGF0YS1hY3Rpb249XCJyZXF1ZXN0R2lmdFwiXScsIHJlcXVlc3RHaWZ0KTtcblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICdpbnB1dC5zZW5kZXItbmFtZScsIHVwZGF0ZVNlbmRlck5hbWUpO1xuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJ2lucHV0LnJlY2lwaWVudC1uYW1lJywgdXBkYXRlUmVjaXBpZW50TmFtZSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4Jyk7XG52YXIgaW1hZ2UgPSByZXF1aXJlKCcuL2ltYWdlJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgcHJvZHVjdFN0b3JlSW52ZW50b3J5ID0gcmVxdWlyZSgnLi4vLi4vc3RvcmVpbnZlbnRvcnkvcHJvZHVjdCcpO1xudmFyIHJhdGluZyA9IHJlcXVpcmUoJy4uLy4uL3JhdGluZycpO1xudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBib3Bpc0FkZFRvQ2FydE9wdGlvbnMgPSByZXF1aXJlKCcuLi8uLi9ib3Bpcy9jb21wb25lbnRzL0FkZFRvQ2FydE9wdGlvbnMnKTtcbnZhciBib3Bpc1N0b3JlU2VhcmNoID0gcmVxdWlyZSgnLi4vLi4vYm9waXMvY29tcG9uZW50cy9TdG9yZVNlYXJjaCcpO1xudmFyIHdpc2hsaXN0ID0gcmVxdWlyZSgnLi4vLi4vd2lzaGxpc3QnKTtcbnZhciBzbGlkZXJzID0gcmVxdWlyZSgnLi4vLi4vc2xpZGVycycpO1xudmFyIGltYWdlR2FsbGVyeTtcblxudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcblxudmFyIGh0bWwgPSB7fTtcbnZhciBkYXRhID0ge307XG52YXIgbG9hZGVkID0ge307XG52YXIgb3B0aW9ucztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZURvbSgpIHtcblx0bG9hZGVkWydjb250ZW50J10gPSB0cnVlO1xuXHRcblx0dXBkYXRlQ1NSRlRva2VuKCk7XG5cblx0dmFyIHNlbGVjdG9yUGF5bG9hZCA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMoJCgnLnBkcEZvcm0nKS5zZXJpYWxpemUoKSk7XG5cdFxuXHR2YXIgcXVlcnlTdHJpbmdQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh1dGlsLmdldFF1ZXJ5U3RyaW5nKHV0aWwuYXBwZW5kUGFyYW1zVG9Vcmwod2luZG93LmxvY2F0aW9uLnRvU3RyaW5nKCksIHNlbGVjdG9yUGF5bG9hZCkpKTtcblx0Zm9yICh2YXIgcGFyYW1ldGVyIGluIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycykge1xuXHRcdHNlbGVjdG9yUGF5bG9hZFtwYXJhbWV0ZXJdID0gcXVlcnlTdHJpbmdQYXJhbWV0ZXJzW3BhcmFtZXRlcl07XG5cdH1cblxuXHR2YXIgc2l6ZVZhbHVlID0gdXRpbC5nZXRQcmVmZXJlbmNlVmFsdWVGcm9tV2luZG93TG9jYXRpb24oJ3NpemUnKTtcblx0aWYgKHNpemVWYWx1ZSkge1xuXHRcdHNlbGVjdG9yUGF5bG9hZC5zZXRTaXplID0gc2l6ZVZhbHVlO1xuXHR9XG5cdFxuICAgIGJ1aWxkU2VsZWN0b3JzKHNlbGVjdG9yUGF5bG9hZCk7XG5cdCQoJy5idG4uYWRkLXRvLWNhcnQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnJlbW92ZUF0dHIoJ2xvYWRpbmcnKS5maW5kKCcubG9hZGluZy1pbmRpY2F0b3ItY29udGFpbmVyJykucmVtb3ZlKCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb2R1Y3RJbmZvKCkge1xuXHQkKCdsaS5zZWxlY3RlZC12YWx1ZScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0dmFyICRzZWxlY3RlZEl0ZW0gPSAkKHRoaXMpO1xuXHRcdCRzZWxlY3RlZEl0ZW0ucGFyZW50cygnLmF0dHJpYnV0ZScpLmZpcnN0KCkuZmluZCgnLmxhYmVsIC5jdXJyZW50LCAuc2VsZWN0LWRyb3Bkb3duIC5zZWxlY3QtdGV4dCcpLmh0bWwoJHNlbGVjdGVkSXRlbS5odG1sKCkpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlQ1NSRlRva2VuKCkge1xuICAgICQuYWpheCh7XG4gICAgXHRtZXRob2Q6ICdnZXQnLFxuICAgIFx0dXJsOiBVcmxzLkNTUkZUb2tlbi5HZXQsXG5cdFx0ZGF0YVR5cGU6ICdqc29uJyxcbiAgICBcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgXHRcdCQoJyNjc3JmdG9rZW4nKS52YWwocmVzcG9uc2UudG9rZW4pO1xuICAgIFx0fVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVQaWQoKSB7XG5cdGlmIChkYXRhWydwaWQnXSkge1xuXHRcdCQoJyNwaWQnKS52YWwoZGF0YVsncGlkJ10pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2VsZWN0b3JzKHBheWxvYWQpIHtcblx0bG9hZGVkWydzZWxlY3RvcnMnXSA9IGZhbHNlO1xuXHRcblx0aWYgKCFwYXlsb2FkKSB7XG5cdFx0cGF5bG9hZCA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMoJCgnLnBkcEZvcm0nKS5zZXJpYWxpemUoKSk7XG5cdH1cbiAgICBcbiAgICB2YXIgdGVtcGxhdGVzID0gW107XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25zJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3InXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3InKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JBdHRyaWJ1dGVHdWlkZSddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1hdHRyaWJ1dGUtZ3VpZGUnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLWRyb3Bkb3duJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvbiddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1kcm9wZG93bi1vcHRpb24nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duT3B0aW9uU2VsZWN0ZWQnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3ItZHJvcGRvd24tb3B0aW9uLXNlbGVjdGVkJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2gnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3Itc3dhdGNoJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3Itc3dhdGNoLW9wdGlvbicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoT3B0aW9uVW5zZWxlY3RhYmxlJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLXN3YXRjaC1vcHRpb24tdW5zZWxlY3RhYmxlJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIFxuXHRkYXRhWydhdHRyaWJ1dGVHdWlkZXMnXSA9IHt9O1xuXG4gICAgJC5hamF4KHtcbiAgICBcdG1ldGhvZDogJ3Bvc3QnLFxuICAgIFx0dXJsOiBVcmxzLmdldFZhcmlhdGlvbkF0dHJpYnV0ZXMsXG4gICAgXHRkYXRhOiBwYXlsb2FkLFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG4gICAgXHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0aHRtbFsndmFyaWF0aW9uU2VsZWN0b3JzJ10gPSAnJztcblx0XHRcdGRhdGFbJ0lzUmVzdHJpY3RlZEJ5R2xvYmFsZSddID0gcmVzcG9uc2UuSXNSZXN0cmljdGVkQnlHbG9iYWxlO1xuXG5cdFx0XHQvLyBDb2xvciBTd2F0Y2ggTGVuZ3RoIENoZWNrXG5cdFx0XHR2YXIgaXNNdWx0aVN3YXRjaDtcblx0XHRcdGlmIChyZXNwb25zZSAmJiAndmFyaWF0aW9ucycgaW4gcmVzcG9uc2UgJiYgcmVzcG9uc2UudmFyaWF0aW9ucy5sZW5ndGgpIHtcblx0XHRcdFx0aXNNdWx0aVN3YXRjaCA9IHJlc3BvbnNlLnZhcmlhdGlvbnMuZmlsdGVyKGZ1bmN0aW9uKHZhcmlhbnRHcm91cCkge1xuXHRcdFx0XHRcdGlmICh2YXJpYW50R3JvdXAgJiYgJ3R5cGUnIGluIHZhcmlhbnRHcm91cCAmJiAndmFsdWVzJyBpbiB2YXJpYW50R3JvdXApIHtcblx0XHRcdFx0XHRcdHJldHVybiB2YXJpYW50R3JvdXAudHlwZSA9PSAnc3dhdGNoJyAmJiB2YXJpYW50R3JvdXAudmFsdWVzLmxlbmd0aCA+IDE7IC8vIENoZWNrIGZvciBtdWx0aXBsZSBjb2xvciBzd2F0Y2hlc1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHR2YXIgaGFzU2l6ZUF0dHJpYnV0ZSA9IGZhbHNlO1xuXHRcdFx0aWYgKHJlc3BvbnNlICYmICd2YXJpYXRpb25zJyBpbiByZXNwb25zZSAmJiByZXNwb25zZS52YXJpYXRpb25zLmxlbmd0aCkge1xuXHRcdFx0XHRoYXNTaXplQXR0cmlidXRlID0gcmVzcG9uc2UudmFyaWF0aW9ucy5maWx0ZXIoZnVuY3Rpb24odmFyaWFudEdyb3VwKSB7XG5cdFx0XHRcdFx0aWYgKHZhcmlhbnRHcm91cCAmJiAncHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZScgaW4gdmFyaWFudEdyb3VwICYmICd2YWx1ZXMnIGluIHZhcmlhbnRHcm91cCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHZhcmlhbnRHcm91cC5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlID09ICdzaXplJyAmJiB2YXJpYW50R3JvdXAudmFsdWVzLmxlbmd0aCA+IDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIHZhcmlhdGlvbnM7XG5cdFx0XHRpZiAoaGFzU2l6ZUF0dHJpYnV0ZSkge1xuXHRcdFx0XHR2YXJpYXRpb25zID0gcmVzcG9uc2UudmFyaWF0aW9ucztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhcmlhdGlvbnMgPSByZXNwb25zZS52YXJpYXRpb25zO1xuXHRcdFx0fVxuXHRcdFx0Zm9yICh2YXIgdmFyaWF0aW9uIGluIHJlc3BvbnNlLnZhcmlhdGlvbnMpIHtcblx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGEgPSByZXNwb25zZS52YXJpYXRpb25zW3ZhcmlhdGlvbl07XG5cdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZCA9IG51bGw7XG5cdFx0XHRcdFxuXHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldE9wdGlvbnMnXSA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRmb3IgKHZhciB2YXJpYXRpb25WYWx1ZSBpbiB2YXJpYXRpb25EYXRhLnZhbHVlcykge1xuXHRcdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhVmFsdWUgPSB2YXJpYXRpb25EYXRhLnZhbHVlc1t2YXJpYXRpb25WYWx1ZV07XG5cdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlO1xuXHRcdFx0XHRcdHZhciB2YXJpYXRpb25UZXh0ID0gKHZhcmlhdGlvbkRhdGFWYWx1ZS5hdHRyaWJ1dGUgPT09ICdzaXplJykgPyB2YXJpYXRpb25EYXRhVmFsdWUudGV4dC5yZXBsYWNlKCcgMS8yJywgJ1xcdTAwQkQnKSA6IHZhcmlhdGlvbkRhdGFWYWx1ZS50ZXh0O1xuXHRcdFx0XHRcdHZhciB3aWR0aERlc2NyaXB0aW9uID0gdmFyaWF0aW9uRGF0YVZhbHVlLndpZHRoRGVzY3JpcHRpb24gPyAnPHNwYW4gY2xhc3M9XCJ3aWR0aC1kZXNjcmlwdGlvblwiPicgKyB2YXJpYXRpb25EYXRhVmFsdWUud2lkdGhEZXNjcmlwdGlvbiArICc8L3NwYW4+JyA6ICcnO1xuXHRcdFx0XHRcdHZhciBvcHRpb25BcmlhTGFiZWwgPSB2YXJpYXRpb25EYXRhVmFsdWUudmFsdWU7XG5cdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZS5zaGlwcGluZykge1xuXHRcdFx0XHRcdFx0b3B0aW9uQXJpYUxhYmVsICs9ICsgJyAtICcgKyB2YXJpYXRpb25EYXRhVmFsdWUuc2hpcHBpbmc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZVBheWxvYWQgPSB7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5hdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHR2YWx1ZUlkOiB2YXJpYXRpb25EYXRhVmFsdWUudmFsdWVJZCxcblx0XHRcdFx0XHRcdHZhbHVlOiB2YXJpYXRpb25EYXRhVmFsdWUudmFsdWUsXG5cdFx0XHRcdFx0XHR0aXRsZTogdmFyaWF0aW9uRGF0YVZhbHVlLnRpdGxlLFxuXHRcdFx0XHRcdFx0b3B0aW9uQXJpYUxhYmVsOiBvcHRpb25BcmlhTGFiZWwsXG5cdFx0XHRcdFx0XHR0ZXh0OiB2YXJpYXRpb25UZXh0LFxuXHRcdFx0XHRcdFx0d2lkdGhEZXNjcmlwdGlvbjogd2lkdGhEZXNjcmlwdGlvbixcblx0XHRcdFx0XHRcdHN0b2NrOiB2YXJpYXRpb25EYXRhVmFsdWUuc3RvY2ssXG5cdFx0XHRcdFx0XHRzaGlwcGluZzogdmFyaWF0aW9uRGF0YVZhbHVlLnNoaXBwaW5nLFxuXHRcdFx0XHRcdFx0aXNTYW1lRGF5U2hpcHBpbmdXaW5kb3c6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pc1NhbWVEYXlTaGlwcGluZ1dpbmRvdyxcblx0XHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZTogdmFyaWF0aW9uRGF0YVZhbHVlLnF1YW50aXR5U291cmNlVHlwZSxcblx0XHRcdFx0XHRcdGhyZWY6IHZhcmlhdGlvbkRhdGFWYWx1ZS5ocmVmLFxuXHRcdFx0XHRcdFx0c2VsZWN0YWJsZTogdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGFibGUgPyAnc2VsZWN0YWJsZScgOiAndW5zZWxlY3RhYmxlJyxcblx0XHRcdFx0XHRcdHNlbGVjdGVkOiB2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0ZWQgPyAnc2VsZWN0ZWQnIDogJycsXG5cdFx0XHRcdFx0XHRzd2F0Y2hJbWFnZVVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5zd2F0Y2gudXJsLFxuXHRcdFx0XHRcdFx0bGFyZ2VTd2F0Y2hJbWFnZVVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZVN3YXRjaC51cmwsXG5cdFx0XHRcdFx0XHRocmVmQXR0cmlidXRlOiB2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0YWJsZSA/ICdocmVmJyA6ICd4aHJlZidcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhLnR5cGUgPT0gJ3N3YXRjaCcpIHtcblx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0YWJsZSkge1xuXHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb24nXTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVQYXlsb2FkLmltYWdlTGFyZ2UgPSBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0XHRcdFx0dXJsOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmxhcmdlLnVybCxcblx0XHRcdFx0XHRcdFx0XHR0aXRsZTogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZS50aXRsZSxcblx0XHRcdFx0XHRcdFx0XHRhbHQ6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2UuYWx0LFxuXHRcdFx0XHRcdFx0XHRcdGhpcmVzOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmhpcmVzLnVybFxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaE9wdGlvblVuc2VsZWN0YWJsZSddO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvbiddO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHRcdHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkID0gdmFyaWF0aW9uRGF0YVZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdFx0aHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ10gKz0gdmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGUodmFyaWF0aW9uRGF0YVZhbHVlUGF5bG9hZCk7XHRcblx0XHRcdFx0fVx0XG5cdFx0XHRcdFxuXHRcdFx0XHQvLyBBZGQgY29sb3Igc3dhdGNoIGxlbmd0aCBib29sZWFuIHRvIHRlbXBsYXRlIGRhdGFcblx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGEudHlwZSA9PSAnc3dhdGNoJykge1xuXHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0J10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoJ10oe1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHRvcHRpb25zOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldE9wdGlvbnMnXSxcblx0XHRcdFx0XHRcdG11bHRpU3dhdGNoRGlzcGxheTogaXNNdWx0aVN3YXRjaC5sZW5ndGggPiAwID8gJ2QtYmxvY2snIDogJ2Qtbm9uZSdcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR2YXIgcGxhY2Vob2xkZXIgPSB2YXJpYXRpb25EYXRhLmxhYmVsLnBsYWNlaG9sZGVyLFxuXHRcdFx0XHRcdFx0YXJpYUxhYmVsID0gdmFyaWF0aW9uRGF0YS5sYWJlbC5wbGFjZWhvbGRlcjtcblxuXHRcdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUyAmJiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUgPT09ICdzaXplJyAmJiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZCA9PT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0cGxhY2Vob2xkZXIgKz0gJyAoJyArIHZhcmlhdGlvbkRhdGEubGFiZWwubWVzc2FnZSArICcpJztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRcdHZhciB2YXJpYXRpb25TZWxlY3RlZFRleHQgPSAodmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlID09PSAnc2l6ZScpID8gdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQudGV4dC5yZXBsYWNlKCcgMS8yJywgJ1xcdTAwQkQnKSA6IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnRleHQ7XG5cdFx0XHRcdFx0XHR2YXIgd2lkdGhEZXNjcmlwdGlvbiA9IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLndpZHRoRGVzY3JpcHRpb24gPyAnPHNwYW4gY2xhc3M9XCJ3aWR0aC1kZXNjcmlwdGlvblwiPicgKyB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC53aWR0aERlc2NyaXB0aW9uICsgJzwvc3Bhbj4nIDogJyc7XG5cblx0XHRcdFx0XHRcdHBsYWNlaG9sZGVyID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duT3B0aW9uU2VsZWN0ZWQnXSh7XG5cdFx0XHRcdFx0XHRcdHRleHQ6IHZhcmlhdGlvblNlbGVjdGVkVGV4dCxcblx0XHRcdFx0XHRcdFx0d2lkdGhEZXNjcmlwdGlvbjogd2lkdGhEZXNjcmlwdGlvbixcblx0XHRcdFx0XHRcdFx0c3RvY2s6IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnN0b2NrLFxuXHRcdFx0XHRcdFx0XHRzaGlwcGluZzogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQuc2hpcHBpbmcsXG5cdFx0XHRcdFx0XHRcdGlzU2FtZURheVNoaXBwaW5nV2luZG93OiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5pc1NhbWVEYXlTaGlwcGluZ1dpbmRvdyxcblx0XHRcdFx0XHRcdFx0cXVhbnRpdHlTb3VyY2VUeXBlOiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5xdWFudGl0eVNvdXJjZVR5cGVcblx0XHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0XHRhcmlhTGFiZWwgPSAnQ3VycmVudGx5IFNlbGVjdGVkOiAnICsgdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQudmFsdWU7IFxuXHRcdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnNoaXBwaW5nKSB7XG5cdFx0XHRcdFx0XHRcdGFyaWFMYWJlbCArPSAnIC0gJyArIHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnNoaXBwaW5nO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIEFkZCBjb2xvciBzd2F0Y2ggbGVuZ3RoIGJvb2xlYW4gdG8gdGVtcGxhdGUgZGF0YVxuXHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0J10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd24nXSh7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSxcblx0XHRcdFx0XHRcdHRleHQ6IHBsYWNlaG9sZGVyLFxuXHRcdFx0XHRcdFx0YXJpYUxhYmVsOiBhcmlhTGFiZWwsXG5cdFx0XHRcdFx0XHRvcHRpb25zOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldE9wdGlvbnMnXSxcblx0XHRcdFx0XHRcdG11bHRpU3dhdGNoRGlzcGxheTogaXNNdWx0aVN3YXRjaC5sZW5ndGggPiAwID8gJ2QtYmxvY2snIDogJ2Qtbm9uZSdcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGh0bWxbJ2F0dHJpYnV0ZUd1aWRlJ10gPSAnJztcblx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGEuYXR0cmlidXRlR3VpZGUpIHtcblx0XHRcdFx0XHRkYXRhWydhdHRyaWJ1dGVHdWlkZXMnXVt2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGVdID0gdmFyaWF0aW9uRGF0YS5hdHRyaWJ1dGVHdWlkZTtcblx0XHRcdFx0XHRodG1sWydhdHRyaWJ1dGVHdWlkZSddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckF0dHJpYnV0ZUd1aWRlJ10oXy5leHRlbmQodmFyaWF0aW9uRGF0YS5hdHRyaWJ1dGVHdWlkZSwgeyBBdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSB9KSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yJ10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yJ10oe1xuXHRcdFx0XHRcdGF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlLFxuXHRcdFx0XHRcdGxhYmVsOiB7XG5cdFx0XHRcdFx0XHR0ZXh0OiB2YXJpYXRpb25EYXRhLmxhYmVsLnRleHQsXG5cdFx0XHRcdFx0XHRtZXNzYWdlOiB2YXJpYXRpb25EYXRhLmxhYmVsLm1lc3NhZ2Vcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHNlbGVjdG9yOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldCddLFxuXHRcdFx0XHRcdGd1aWRlOiBodG1sWydhdHRyaWJ1dGVHdWlkZSddXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9ycyddICs9IGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yJ107XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGh0bWxbJ3NlbGVjdG9ycyddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25zJ10oe1xuXHRcdFx0XHRzZWxlY3RvcnM6IGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9ycyddXG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0ZGF0YVsnc2VsZWN0ZWQnXSA9IHJlc3BvbnNlLnNlbGVjdGVkO1xuXHRcdFx0ZGF0YVsncGlkJ10gPSByZXNwb25zZS5waWQ7XG5cdFx0XHRcblx0XHRcdGxvYWRlZFsnc2VsZWN0b3JzJ10gPSB0cnVlO1xuXHRcdFx0cmVuZGVyVmFyaWF0aW9uVXBkYXRlcygpO1xuICAgIFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2V0QWx0ZXJuYXRlcygpIHtcblx0JCgndWwuYWx0ZXJuYXRlLWl0ZW1zIGxpJykuc29ydChmdW5jdGlvbihhLGIpIHsgcmV0dXJuICQoYSkuZGF0YSgnaWQnKSAtICQoYikuZGF0YSgnaWQnKTsgfSkuYXBwZW5kVG8oJy5hbHRlcm5hdGUtaXRlbXMnKTtcblx0dmFyIGFsdFR5cGUgPSAkKCd1bC5hbHRlcm5hdGUtaXRlbXMnKS5kYXRhKCdhbHRlcm5hdGUnKTtcblx0dmFyIGFsdERlZmF1bHQgPSAkKCd1bC5hbHRlcm5hdGUtaXRlbXMnKS5kYXRhKCdkZWZhdWx0Jyk7XG5cdHZhciBhbHRlcm5hdGVzID0gW107XG5cblx0dmFyIGlzU3Vic2NyaXB0aW9uUHJvZHVjdCA9ICQoJy5wZHAtbWFpbicpLmhhc0NsYXNzKCdzdWJzY3JpcHRpb24tcHJvZHVjdC10ZW1wbGF0ZScpO1xuXHR2YXIgY29sb3JTZWxlY3RlZCA9ICQoJy5jb2xvci1vcHRpb25zIC5zZWxlY3RlZCBhJyk7XG5cdHZhciBzaXplU2VsZWN0ZWQgPSAkKCcuc2l6ZS1vcHRpb25zIC5zZWxlY3RlZCBhJykuZGF0YSgnc2l6ZS1pZCcpO1xuXG5cdGlmIChjb2xvclNlbGVjdGVkICYmIGlzU3Vic2NyaXB0aW9uUHJvZHVjdCkge1xuXHRcdGFsdGVybmF0ZXMucHVzaCh7J2FsdElEJzogJChjb2xvclNlbGVjdGVkKS5wYXJlbnQoJy5zZWxlY3RlZCcpLmRhdGEoJ2lkJyksICdhbHRWYWx1ZSc6ICQoY29sb3JTZWxlY3RlZCkuYXR0cignZGF0YS1jb2xvci1uYW1lJyl9KTtcblx0fVxuXHQkKCd1bC5hbHRlcm5hdGUtaXRlbXMgbGknKS5lYWNoKGZ1bmN0aW9uKGksIGVsZW0pIHtcblx0XHRhbHRlcm5hdGVzLnB1c2goeydhbHRJRCc6ICQoZWxlbSkuZGF0YSgnaWQnKSwgJ2FsdFZhbHVlJzogJChlbGVtKS50ZXh0KCkuc3BsaXQoJy0nKVsxXX0pO1xuXHR9KTtcblxuXHRpZiAoc2l6ZVNlbGVjdGVkICYmIHNpemVTZWxlY3RlZC5sZW5ndGggPiAwICYmICQoJy5hbHRlcm5hdGUnKS5sZW5ndGggPiAwKXtcblx0XHR1cGRhdGVBbHRlcm5hdGVzKHNpemVTZWxlY3RlZCk7XG5cdH0gZWxzZSBpZiAoYWx0ZXJuYXRlcyAmJiBhbHRlcm5hdGVzLmxlbmd0aCA+IDApe1xuXHRcdCQuYWpheCh7XG5cdFx0XHR1cmw6IFVybHMuZ2V0SXRlbUFsdGVybmF0ZXMsXG5cdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRkYXRhOiB7XG5cdFx0XHRcdCdhbHRlcm5hdGVzJzogSlNPTi5zdHJpbmdpZnkoYWx0ZXJuYXRlcylcblx0XHRcdH0sXG5cdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHR2YXIgYWx0U3dhdGNoZXMgPSAnJztcblx0XHRcdFx0dmFyIGFsdGVybmF0ZSA9IGRhdGEucmVzdWx0O1xuXHRcdFx0XHRcblx0XHRcdFx0JC5lYWNoKGFsdGVybmF0ZSwgZnVuY3Rpb24oaSwgZSl7XG5cdFx0XHRcdFx0dmFyIGlkID0gYWx0ZXJuYXRlW2ldLmlkO1xuXHRcdFx0XHRcdHZhciB0eXBlID0gYWx0VHlwZSA/IGFsdFR5cGUgOiAnQ29sb3InO1xuXHRcdFx0XHRcdHZhciB2YWx1ZSA9IGFsdGVybmF0ZVtpXS52YWx1ZTtcblx0XHRcdFx0XHR2YXIgaW1hZ2UgPSBhbHRlcm5hdGVbaV0uaW1hZ2U7XG5cdFx0XHRcdFx0dmFyIHVybCA9ICQoJy5hbHRlcm5hdGUtaXRlbXMgbGlbZGF0YS1pZD0nK2lkKyddJykuZGF0YSgndXJsJyk7XG5cdFx0XHRcdFx0dmFyIGFsdEhpZGRlbiA9ICdzaG93LWNvbnRlbnQnO1xuXHRcdFx0XHRcdGlmICggaSA+PSAxMSApe1xuXHRcdFx0XHRcdFx0YWx0SGlkZGVuID0gJ2hpZGRlbi1jb250ZW50Jztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCBpc1N1YnNjcmlwdGlvblByb2R1Y3QgJiYgaWQgPT0gJChjb2xvclNlbGVjdGVkKS5wYXJlbnQoJy5zZWxlY3RlZCcpLmRhdGEoJ2lkJykgKXtcblx0XHRcdFx0XHRcdCQoY29sb3JTZWxlY3RlZCkuY3NzKCdiYWNrZ3JvdW5kJywgJ3VybCgnK2ltYWdlKycpJyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGFsdFN3YXRjaGVzICs9ICc8bGkgY2xhc3M9XCJ1bnNlbGVjdGFibGUgYWx0ZXJuYXRlICcgKyBhbHRIaWRkZW4gKyAnXCIgZGF0YS1pZD1cIicraWQrJ1wiIGRhdGEtdHlwZT1cIicrYWx0VHlwZSsnXCIgZGF0YS12YWx1ZT1cIicrdmFsdWUrJ1wiPjxhIGNsYXNzPVwic3dhdGNoYW5jaG9yXCIgaHJlZj1cIicrdXJsKydcIiB0aXRsZT1cIlNlbGVjdCAnK2FsdFR5cGUrJzogJyt2YWx1ZSsnXCIgdmFsdWU9XCInK3ZhbHVlKydcIiBzdHlsZT1cImJhY2tncm91bmQ6IHVybCgnK2ltYWdlKyc/c3c9NzAmYW1wO3NoPTcwJmFtcDtzbT1maXQpOyBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0OyBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47IGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcIj48c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPlNlbGVjdCAnK2FsdFR5cGUrJzonK3ZhbHVlKyc8L3NwYW4+PC9hPjwvbGk+Jztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKGFsdFN3YXRjaGVzLmxlbmd0aCA+IDAgKXtcblx0XHRcdFx0XHQkKCcuY29sb3IuY29sb3Itb3B0aW9ucycpLnJlbW92ZUNsYXNzKCdjb2xvci1kLW5vbmUnKS5hcHBlbmQoYWx0U3dhdGNoZXMpLmZpbmQoJ2xpJykuc29ydChmdW5jdGlvbihhLGIpIHsgcmV0dXJuICQoYSkuZGF0YSgnaWQnKSAtICQoYikuZGF0YSgnaWQnKTsgfSkuYXBwZW5kVG8oJy5jb2xvci1vcHRpb25zJyk7XG5cdFx0XHRcdFx0aWYgKGFsdFR5cGUgJiYgYWx0RGVmYXVsdCl7XG5cdFx0XHRcdFx0XHQkKCcuY29sb3Itb3B0aW9ucyAuc2VsZWN0ZWQnKS5hdHRyKCdkYXRhLXR5cGUnLGFsdFR5cGUpLmF0dHIoJ2RhdGEtdmFsdWUnLGFsdERlZmF1bHQpLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykuYXR0cigndGl0bGUnLCdTZWxlY3QgJythbHRUeXBlKyc6ICcrYWx0RGVmYXVsdCk7XG5cdFx0XHRcdFx0XHR2YXIgbmV3VGV4dCA9ICc8c3BhbiBjbGFzcz1cInRleHRcIj4nK2FsdFR5cGUrJzxzcGFuIGNsYXNzPVwic2VwYXJhdG9yXCI+Ojwvc3Bhbj4gPHNwYW4gY2xhc3M9XCJjdXJyZW50IGNvbG9yLWN1cnJlbnRcIj4nK2FsdERlZmF1bHQrJzwvc3Bhbj48L3NwYW4+Jztcblx0XHRcdFx0XHRcdCQoJy5hdHRyaWJ1dGUtY29sb3IgLnRleHQnKS5odG1sKG5ld1RleHQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKHNpemVTZWxlY3RlZCAmJiBzaXplU2VsZWN0ZWQubGVuZ3RoID4gMCl7XG5cdFx0XHRcdFx0dXBkYXRlQWx0ZXJuYXRlcyhzaXplU2VsZWN0ZWQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgYWx0SGlkZGVuQ291bnQgPSAkKCcuaGlkZGVuLWNvbnRlbnQnKS5sZW5ndGg7XG5cdFx0XHRcdHZhciBhbHRIaWRkZW5Ub2dnbGUgPSAnKyAnICsgYWx0SGlkZGVuQ291bnQ7XG5cdFx0XHRcdGlmIChhbHRIaWRkZW5Db3VudCA+IDApe1xuXHRcdFx0XHRcdCQoJy5oaWRkZW4tY29udGVudCcpLmhpZGUoKTtcblx0XHRcdFx0XHQkKCcuY29sb3IuY29sb3Itb3B0aW9ucycpLmFwcGVuZCgnPGJ1dHRvbiBjbGFzcz1cImFsdEJ1dHRvblwiPicgKyBhbHRIaWRkZW5Ub2dnbGUgKyAnPC9idXR0b24+Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkKCdidXR0b24uYWx0QnV0dG9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdCQodGhpcykuY2xvc2VzdCgnLmNvbG9yLW9wdGlvbnMnKS5maW5kKCcuaGlkZGVuLWNvbnRlbnQnKS50b2dnbGUoKTtcblx0XHRcdFx0XHQkKCcuYWx0QnV0dG9uJykuaGlkZSgpO1xuXHRcdFx0XHR9KVxuXHRcdFx0XHRcblx0XHRcdFx0JChcIi5jb2xvci1vcHRpb25zIGxpXCIpLmhvdmVyKGZ1bmN0aW9uKCl7XG5cdFx0XHRcdFx0dmFyIGFsdFRpdGxlID0gJCh0aGlzKS5kYXRhKCd0eXBlJyk7XG5cdFx0XHRcdFx0dmFyIGFsdFZhbHVlID0gJCh0aGlzKS5kYXRhKCd2YWx1ZScpO1xuXHRcdFx0XHRcdHZhciBuZXdUZXh0ID0gJzxzcGFuIGNsYXNzPVwidGV4dFwiPicrYWx0VHlwZSsnPHNwYW4gY2xhc3M9XCJzZXBhcmF0b3JcIj46PC9zcGFuPiA8c3BhbiBjbGFzcz1cImN1cnJlbnQgY29sb3ItY3VycmVudFwiPicrYWx0VmFsdWUrJzwvc3Bhbj48L3NwYW4+Jztcblx0XHRcdFx0XHQkKCcuYXR0cmlidXRlLWNvbG9yIC50ZXh0JykuaHRtbChuZXdUZXh0KTtcblx0XHRcdFx0fSwgZnVuY3Rpb24oKXtcblx0XHRcdFx0XHR2YXIgYWx0VGl0bGUgPSAkKCcuY29sb3Itb3B0aW9ucyAuc2VsZWN0ZWQnKS5kYXRhKCd0eXBlJyk7XG5cdFx0XHRcdFx0dmFyIGFsdFZhbHVlID0gJCgnLmNvbG9yLW9wdGlvbnMgLnNlbGVjdGVkJykuZGF0YSgndmFsdWUnKTtcblx0XHRcdFx0XHR2YXIgbmV3VGV4dCA9ICc8c3BhbiBjbGFzcz1cInRleHRcIj4nK2FsdFR5cGUrJzxzcGFuIGNsYXNzPVwic2VwYXJhdG9yXCI+Ojwvc3Bhbj4gPHNwYW4gY2xhc3M9XCJjdXJyZW50IGNvbG9yLWN1cnJlbnRcIj4nK2FsdFZhbHVlKyc8L3NwYW4+PC9zcGFuPic7XG5cdFx0XHRcdFx0JCgnLmF0dHJpYnV0ZS1jb2xvciAudGV4dCcpLmh0bWwobmV3VGV4dCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUFsdGVybmF0ZXMoc2l6ZVNlbGVjdGVkKSB7XG5cdHZhciBhbHR1cGRhdGVzID0gW107XG5cdCQoJ3VsLmNvbG9yLW9wdGlvbnMgbGknKS5lYWNoKGZ1bmN0aW9uKGksIGVsZW0pIHtcblx0XHRhbHR1cGRhdGVzLnB1c2goU3RyaW5nKCQoZWxlbSkuZGF0YSgnaWQnKSkpO1xuXHR9KTtcblx0XG5cdGlmKGFsdHVwZGF0ZXMgJiYgYWx0dXBkYXRlcy5sZW5ndGggPiAwKXtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLnVwZGF0ZUl0ZW1BbHRlcm5hdGVzLFxuXHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0ZGF0YToge1xuXHRcdFx0XHQnYWx0dXBkYXRlcyc6IEpTT04uc3RyaW5naWZ5KGFsdHVwZGF0ZXMpLFxuXHRcdFx0XHQnc2l6ZSc6IHNpemVTZWxlY3RlZFxuXHRcdFx0fSxcblx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdHZhciBhbHRlcm5hdGUgPSBkYXRhLnJlc3VsdDtcblx0XHRcdFx0XG5cdFx0XHRcdCQuZWFjaChhbHRlcm5hdGUsIGZ1bmN0aW9uKGksIGUpe1xuXHRcdFx0XHRcdHZhciBpZCA9IGFsdGVybmF0ZVtpXS5pZDtcblx0XHRcdFx0XHR2YXIgYXBwZW5kVVJMID0gYWx0ZXJuYXRlW2ldLmFwcGVuZFVSTDtcblx0XHRcdFx0XHR2YXIgc2l6ZUF2YWlsYWJsZSA9ICFhbHRlcm5hdGVbaV0uc2l6ZUF2YWlsYWJsZTtcblx0XHRcdFx0XHR2YXIgb2xkVVJMID0gJCgndWwuY29sb3Itb3B0aW9ucyBsaVtkYXRhLWlkPScraWQrJ10gYScpLmF0dHIoJ2hyZWYnKTtcblx0XHRcdFx0XHR2YXIgbmV3VVJMID0gb2xkVVJMICsgYXBwZW5kVVJMO1xuXHRcdFx0XHRcdCQoJ3VsLmNvbG9yLW9wdGlvbnMgbGkuYWx0ZXJuYXRlW2RhdGEtaWQ9XCInK2lkKydcIl0gYScpLmF0dHIoJ2hyZWYnLG5ld1VSTCk7XG5cdFx0XHRcdFx0aWYoYXBwZW5kVVJMID09IG51bGwgfHwgKHR5cGVvZiBhcHBlbmRVUkwgPT09IFwic3RyaW5nXCIgJiYgYXBwZW5kVVJMLnRyaW0oKS5sZW5ndGggPT09IDApKXtcblx0XHRcdFx0XHRcdCQoJ3VsLmNvbG9yLW9wdGlvbnMgbGlbZGF0YS1pZD0nK2lkKyddIGEnKS5hZGRDbGFzcygnbm8tc2l6ZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyVmFyaWF0aW9uVXBkYXRlcygpIHtcblx0aWYgKGxvYWRlZFsnY29udGVudCddICYmIGxvYWRlZFsnc2VsZWN0b3JzJ10pIHtcblx0XHRyZW5kZXJTZWxlY3RvcnMoKTtcblx0XHR1cGRhdGVQaWQoKTtcblx0XHRzZXRBbHRlcm5hdGVzKCk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2FtZURheVNoaXBwaW5nQ291bnRkb3duLlVwZGF0ZScpO1xuXHRcdFxuXHRcdHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHRcdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHR2YXIgd2lkdGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLndpZHRoLndpZHRoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cdFx0dmFyIGlzQ29sb3JTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0XG5cdFx0dXBkYXRlV2lzaGxpc3RCdXR0b24oc2l6ZVNlbGVjdGVkKTtcblxuXHRcdGlmIChpc1NpemVTZWxlY3RlZCkge1xuXHRcdFx0JCgnLmF0dHJpYnV0ZS1zaXplJykuYWRkQ2xhc3MoJ3NpemUtc2VsZWN0ZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmF0dHJpYnV0ZS1zaXplJykucmVtb3ZlQ2xhc3MoJ3NpemUtc2VsZWN0ZWQnKTtcblx0XHR9XG5cdCAgICBpZiAoaXNTaXplU2VsZWN0ZWQgJiYgaXNDb2xvclNlbGVjdGVkKSB7XG5cdFx0XHQkKCcuYnRuLnN0b3JlLXNlYXJjaCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cblx0ICAgIFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5TZWxlY3RlZCcpO1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5BZGRUb0NhcnRPcHRpb25zJyk7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5WYXJpYW50LlN0b3JlU2VhcmNoJyk7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDdXJyZW5jeS5VcGRhdGUnLCAkKCcjcHJvZHVjdC1jb250ZW50JykpO1xuXHQgICAgfVxuXHQgICAgXG4gICAgXHR2YXIgJHNlbGVjdGFibGVDb3VudCA9IDA7XG4gICAgXHQkKCcucHJvZHVjdC1vcHRpb25zIC5hdHRyaWJ1dGUtc2l6ZSAuc2VsZWN0LWRyb3Bkb3duIHVsLnNpemUtb3B0aW9ucyBsaSwgLnByb2R1Y3Qtb3B0aW9ucyAuYXR0cmlidXRlLXNpemUgLnNlbGVjdC1kcm9wZG93biB1bC5sZW5ndGgtb3B0aW9ucyBsaScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIFx0dmFyICRzZWxlY3RDbGFzcyA9ICQodGhpcykuYXR0cignY2xhc3MnKS5yZXBsYWNlKCdzZWxlY3RlZCcsJycpLnRyaW0oKTtcbiAgICAgICAgXHRpZiggJHNlbGVjdENsYXNzID09ICdzZWxlY3RhYmxlJyl7XG4gICAgICAgIFx0XHQkc2VsZWN0YWJsZUNvdW50Kys7XG4gICAgICAgIFx0fSAgICAgICAgXG4gICAgICAgIH0pO1xuXG5cdFx0aWYgKGRhdGFbJ0lzUmVzdHJpY3RlZEJ5R2xvYmFsZSddIHx8ICRzZWxlY3RhYmxlQ291bnQgPT0gMCkge1xuXHRcdFx0JCgnLnNhbWUtZGF5LXNoaXBwaW5nLWNvdW50ZG93bicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdCQoJy5wcm9kdWN0LW9wdGlvbnMgLmF0dHJpYnV0ZS1zaXplIC5zZWxlY3QtZHJvcGRvd24nKS5jc3Moe1wicG9pbnRlci1ldmVudHNcIjogXCJub25lXCIsIFwiY3Vyc29yXCI6IFwiZGVmYXVsdFwifSk7XG5cdFx0XHQkKCcucHJvZHVjdC12YXJpYXRpb24nKS5hZGRDbGFzcygnbm90LWF2YWlsYWJsZScpO1xuXHRcdFx0aWYgKCQoJy5jb2xvci1vcHRpb25zIC5zZWxlY3RhYmxlJykubGVuZ3RoID4gMSB8fCAkKCcuYWx0ZXJuYXRlLWl0ZW1zIGxpJykubGVuZ3RoID4gMSkge1xuXHRcdFx0XHQkKCcucHJvZHVjdC12YXJpYXRpb24nKS5hZGRDbGFzcygnY29sb3JzLXNlbGVjdGFibGUnKTtcblx0XHRcdH1cblx0XHRcdGlmIChkYXRhWydJc1Jlc3RyaWN0ZWRCeUdsb2JhbGUnXSkge1xuXHRcdFx0XHQkKCcucHJvZHVjdC1nbG9iYWxlLXVuYXZhaWxhYmxlJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fSBlbHNlIGlmICgkc2VsZWN0YWJsZUNvdW50ID09IDApIHtcblx0XHRcdFx0JCgnLnByb2R1Y3Qtb3V0LW9mLXN0b2NrJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLlZhcmlhbnQuVXBkYXRlZCcpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclNlbGVjdG9ycygpIHtcblx0JCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLmh0bWwoaHRtbFsnc2VsZWN0b3JzJ10pO1xuXHQkKCcucHJvZHVjdC12YXJpYXRpb25zJykuYXR0cignZGF0YS1hdHRyaWJ1dGVzJywgSlNPTi5zdHJpbmdpZnkoZGF0YVsnc2VsZWN0ZWQnXSkpO1xuXHRjaGVja0ZvclNlbGVjdGVkU3dhdGNoKCQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKSk7XG5cblx0JCgnLmF0dHJpYnV0ZS1ndWlkZS1saW5rJykuZmFuY3lib3goKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tGb3JTZWxlY3RlZFN3YXRjaCgkY29udGFpbmVyKSB7XG5cdHZhciBzd2F0Y2hJc1NlbGVjdGVkID0gJGNvbnRhaW5lci5maW5kKCcuY29sb3Itb3B0aW9ucyAuc2VsZWN0YWJsZS5zZWxlY3RlZCcpLmxlbmd0aCA+IDA7XG5cdGlmICghc3dhdGNoSXNTZWxlY3RlZCkge1xuXHRcdCRjb250YWluZXIuZmluZCgnLmNvbG9yLW9wdGlvbnMgLnNlbGVjdGFibGU6Zmlyc3QtY2hpbGQ+LnN3YXRjaGFuY2hvcicpLm1vdXNlZW50ZXIoKTtcblx0fVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGUgcHJvZHVjdCBjb250ZW50IHdpdGggbmV3IHZhcmlhbnQgZnJvbSBocmVmLCBsb2FkIG5ldyBjb250ZW50IHRvICNwcm9kdWN0LWNvbnRlbnQgcGFuZWxcbiAqIEBwYXJhbSB7U3RyaW5nfSBocmVmIC0gdXJsIG9mIHRoZSBuZXcgcHJvZHVjdCB2YXJpYW50XG4gKiovXG52YXIgdXBkYXRlQ29udGVudCA9IGZ1bmN0aW9uIChocmVmKSB7XG5cdGxvYWRlZFsnY29udGVudCddID0gZmFsc2U7XG5cdCQoJy5idG4uYWRkLXRvLWNhcnQnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpLmxvYWRpbmcoKTtcblx0dmFyIGJvcGlzU3RvcmVTZWFyY2hQb3N0YWxDb2RlID0gJCgnLmJvcGlzLXN0b3JlLXNlYXJjaCBpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfcG9zdGFsQ29kZVwiXScpLnZhbCgpO1xuICAgIHZhciAkcGRwRm9ybSA9ICQoJy5wZHBGb3JtJyk7XG4gICAgdmFyIHF0eSA9ICRwZHBGb3JtLmZpbmQoJ3NlbGVjdFtuYW1lPVwiUXVhbnRpdHlcIl0nKS5maXJzdCgpLnZhbCgpO1xuICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgIFF1YW50aXR5OiBpc05hTihxdHkpID8gJzEnIDogcXR5LFxuICAgICAgICBmb3JtYXQ6ICdhamF4JyxcbiAgICAgICAgcHJvZHVjdGxpc3RpZDogJHBkcEZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInBpZFwiXScpLmZpcnN0KCkudmFsKCksXG4gICAgICAgIEJvcGlzRW5hYmxlZDogJCgnLmJvcGlzLXN0b3JlLXNlYXJjaCcpLmxlbmd0aCA+IDAgPyB0cnVlIDogZmFsc2UsXG5cdFx0VG9rZW46ICQoJy5ib3Bpcy1zdG9yZS1zZWFyY2ggaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKVxuICAgIH07XG5cbiAgICBidWlsZFNlbGVjdG9ycyh1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHV0aWwuZ2V0UXVlcnlTdHJpbmcodXRpbC5hcHBlbmRQYXJhbXNUb1VybChocmVmLCBwYXJhbXMpKSkpO1xuXHQkLmFqYXgoe1xuICAgIFx0bWV0aG9kOiAnR0VUJyxcbiAgICBcdHVybDogdXRpbC5hcHBlbmRQYXJhbXNUb1VybChocmVmLCBwYXJhbXMpLFxuICAgIFx0Y29tcGxldGU6IGZ1bmN0aW9uKGh0bWwpIHtcblx0XHRcdGxvYWRlZFsnY29udGVudCddID0gdHJ1ZTtcblx0XHRcdCQoJyNwcm9kdWN0LWNvbnRlbnQnKS5odG1sKGh0bWwucmVzcG9uc2VUZXh0KTtcblx0XHRcdHJlbmRlclZhcmlhdGlvblVwZGF0ZXMoKTtcblxuXHRcdFx0aWYgKGJvcGlzU3RvcmVTZWFyY2hQb3N0YWxDb2RlKSB7XG4gICAgICAgIFx0XHQkKCcuYm9waXMtc3RvcmUtc2VhcmNoIGlucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9wb3N0YWxDb2RlXCJdJykudmFsKGJvcGlzU3RvcmVTZWFyY2hQb3N0YWxDb2RlKTtcbiAgICAgICAgXHR9XG4gICAgICAgIFx0XG4gICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLlNUT1JFX1BJQ0tVUCkge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RTdG9yZUludmVudG9yeS5pbml0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbWFnZS5yZXBsYWNlSW1hZ2VzKCk7XG4gICAgICAgICAgICB0b29sdGlwLmluaXQoKTtcbiAgICAgICAgICAgIC8vIHJhdGluZy5pbml0KCk7XG4gICAgICAgICAgICB1cGRhdGVQcm9kdWN0SW5mbygpO1xuICAgICAgICAgICAgaW5pdGlhbGl6ZUltYWdlR2FsbGVyeSgpOyAgICAgICAgICAgIFxuXHRcdFx0dXBkYXRlQ1NSRlRva2VuKCk7XG5cdFx0XHQvLyBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdWaWV3SXRlbScpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7JChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXJldmlldy10ZXh0Jyk7fSwgNTAwKTtcblxuICAgICAgICAgICAgaWYgKCdhZmZpcm0nIGluIHdpbmRvdyAmJiAndWknIGluIGFmZmlybSAmJiAncmVmcmVzaCcgaW4gYWZmaXJtLnVpKSB7XG5cdFx0XHQgICAgYWZmaXJtLnVpLnJlZnJlc2goKTtcblx0XHRcdH1cbiAgICAgICAgICAgIFxuXHRcdFx0dmFyIHZhcmlhbnRTZWxlY3RlZCA9IGlzVmFyaWFudFNlbGVjdGVkKCk7XG4gICAgICAgICAgICBpZiAoJCgnLmJvcGlzLXN0b3JlLXNlYXJjaCcpLmxlbmd0aCA+IDAgfHwgJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtY29udGFpbmVyJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgXHRpZiAodmFyaWFudFNlbGVjdGVkKSB7XG4gICAgICAgICAgICBcdFx0b3B0aW9ucy5Cb3Bpcy5Jc1ZhcmlhbnRTZWxlY3RlZCA9IHRydWU7XG4gICAgICAgICAgICBcdH1cblx0XHRcdFx0aW5pdGlhbGl6ZUJvcGlzKCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0XHR1cGRhdGVBZGRUb0NhcnRSZWNvbW1lbmRhdGlvbnMoKTtcblx0XHRcdH1cblx0XHRcdCQoJy5idG4uYWRkLXRvLWNhcnQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnJlbW92ZUF0dHIoJ2xvYWRpbmcnKS5maW5kKCcubG9hZGluZy1pbmRpY2F0b3ItY29udGFpbmVyJykucmVtb3ZlKCk7ICAgIFx0XHRcbiAgICBcdH1cbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGlzVmFyaWFudFNlbGVjdGVkKCkge1xuXHR2YXIgc2l6ZVNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuc2l6ZS5zaXplLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHR2YXIgY29sb3JTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cblx0cmV0dXJuIChzaXplU2VsZWN0ZWQgfHwgKGxlbmd0aFNlbGVjdGVkICYmIHdpZHRoU2VsZWN0ZWQpKSAmJiBjb2xvclNlbGVjdGVkO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVBZGRUb0NhcnRSZWNvbW1lbmRhdGlvbnMoKSB7XG5cdHZhciBpbnRlcnZhbENvdW50ID0gMDtcblx0dmFyIGFkZFRvQ2FydFJlY29tbWVuZGF0aW9uc0NoZWNrID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCAkKCcucmVjb21tLXByb2QtcGRwLWEyYy1zbG90IC5hY2NvcmRpb24ucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMnKS5sZW5ndGggPiAwICkge1xuXHRcdFx0Y2xlYXJJbnRlcnZhbChhZGRUb0NhcnRSZWNvbW1lbmRhdGlvbnNDaGVjayk7XG5cdFx0XHRpbml0U2xpZGVyKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKGludGVydmFsQ291bnQgPT09IDUwKSB7XG5cdFx0XHRjbGVhckludGVydmFsKGFkZFRvQ2FydFJlY29tbWVuZGF0aW9uc0NoZWNrKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpbnRlcnZhbENvdW50Kys7XG5cdH0sIDIwMCk7XG5cblx0ZnVuY3Rpb24gaW5pdFNsaWRlcigpIHtcblx0XHRzbGlkZXJzLmluaXQoJy5yZWNvbW0tcHJvZC1wZHAtYTJjLXNsb3QgLmFjY29yZGlvbi5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucyAuc2xpZGVzJywge2JyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMSwgYXJyb3dzOiB0cnVlLCBkb3RzOiB0cnVlfSwgNzY4OiB7c2xpZGVzVG9TaG93OiAzLCBhcnJvd3M6IHRydWUsIGRvdHM6IGZhbHNlfSwgMTAyNDoge3NsaWRlc1RvU2hvdzogNCwgYXJyb3dzOiB0cnVlLCBkb3RzOiBmYWxzZX19fSwgdHJ1ZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc2l6ZU1lbnVPcGVuQ2xvc2UoZXZlbnQsIGVsLCBvcGVuKSB7XG5cdHZhciAkdGhpcyA9IGVsO1xuXHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJy5zZWxlY3QtZHJvcGRvd24nKTtcblx0dmFyICRtZW51ID0gJGNvbnRhaW5lci5maW5kKCcuc2VsZWN0LWRyb3Bkb3duLWlubmVyJyk7XG5cdFxuXHRpZiAob3Blbikge1xuXHRcdCR0aGlzLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHQkbWVudS5hZGRDbGFzcygnZXhwYW5kJyk7XG5cdFx0JG1lbnUuZmluZCgnbGkuc2VsZWN0YWJsZSBhJykucmVtb3ZlQXR0cigndGFiaW5kZXgnKTtcblx0fSBlbHNlIHtcblx0XHQkdGhpcy5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0JG1lbnUucmVtb3ZlQ2xhc3MoJ2V4cGFuZCcpO1xuXHRcdCRtZW51LmZpbmQoJ2xpLnNlbGVjdGFibGUgYScpLmF0dHIoJ3RhYmluZGV4JywgJy0xJyk7XG5cdFx0aWYgKCRtZW51LmZpbmQoJy50ZW1wc2VsZWN0aW9uJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JG1lbnUuZmluZCgnLnRlbXBzZWxlY3Rpb24nKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQgdGVtcHNlbGVjdGlvbicpO1xuXHRcdH1cblx0XHRpZiAoZXZlbnQua2V5Q29kZSkge1xuXHRcdFx0JGNvbnRhaW5lci5hZGRDbGFzcygnZm9jdXMtdmlzaWJsZS1pbmRpY2F0b3InKS5mb2N1cygpO1xuXHRcdH1cblx0fVxuXG5cdGlmICgkbWVudS5oYXNDbGFzcygnZXhwYW5kJykpIHtcblx0XHRzY3JvbGxUb0N1cnJlbnRTaXplKCk7XG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuXHRcdFx0JG1lbnUuYWRkQ2xhc3MoJ2V4cGFuZC1jbG9zZScpO1xuXHRcdH0sIDEwMCk7XG5cdH0gZWxzZSB7XG5cdFx0JG1lbnUucmVtb3ZlQ2xhc3MoJ2V4cGFuZC1jbG9zZScpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHNlbGVjdFNpemVPcHRpb24oZWwpIHtcblx0dmFyICRzZWxlY3RlZCA9ICQoZWwpO1xuXHRcblx0JHNlbGVjdGVkXG5cdFx0LmFkZENsYXNzKCdzZWxlY3RlZCcpXG5cdFx0LnNpYmxpbmdzKClcblx0XHQucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cblx0JHNlbGVjdGVkXG5cdFx0LmNsb3Nlc3QoJy5zZWxlY3QtZHJvcGRvd24taW5uZXInKVxuXHRcdC5yZW1vdmVDbGFzcygnZXhwYW5kJylcblx0XHQucmVtb3ZlQ2xhc3MoJ2V4cGFuZC1jbG9zZScpXG5cdFx0LnByZXYoJy5zZWxlY3QtdGV4dCcpXG5cdFx0LnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlV2lzaGxpc3RCdXR0b24oc2l6ZVNlbGVjdGVkKSB7XG5cdHZhciB2YXJpYW50SWQgPSAkKCcjcGlkJykudmFsKCk7XG5cdHZhciBpc1dpc2hsaXN0SXRlbSA9IHdpc2hsaXN0LmNoZWNrV2lzaGxpc3RGb3JJdGVtKHZhcmlhbnRJZCk7XG5cdHZhciBzaXplVGV4dCA9ICcnO1xuXG5cdGlmIChzaXplU2VsZWN0ZWQpIHtcblx0XHRzaXplVGV4dCA9IHNpemVTZWxlY3RlZC5maW5kKCcuc2l6ZScpLnRleHQoKTtcblx0fVxuXHRpZiAoaXNXaXNobGlzdEl0ZW0pIHsgXG5cdFx0d2lzaGxpc3QucHJlcGFyZVdpc2hsaXN0UmVtb3ZlVUkoJCgnLnBkcC1tYWluIC53aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24nKSwgc2l6ZVRleHQpO1xuXHR9IGVsc2Uge1xuXHRcdHdpc2hsaXN0LnByZXBhcmVXaXNobGlzdEFkZFVJKCQoJy5wZHAtbWFpbiAud2lzaGxpc3QtaXRlbS1zdGF0dXMtYnV0dG9uJyksIG51bGwsIHNpemVUZXh0KTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzICgpIHtcblx0dmFyICRwZHBNYWluID0gJCgnI3BkcE1haW4nKTtcblxuICAgIC8vIGhvdmVyIG9uIHN3YXRjaCAtIHNob3VsZCB1cGRhdGUgbWFpbiBpbWFnZSB3aXRoIHN3YXRjaCBpbWFnZS5cbi8vICAgICRwZHBNYWluLm9mZignbW91c2VlbnRlci5WYXJpYW50LlN3YXRjaEFuY2hvcicpLm9uKCdtb3VzZWVudGVyLlZhcmlhbnQuU3dhdGNoQW5jaG9yJywgJy5jb2xvcj5saT4uc3dhdGNoYW5jaG9yJywgZnVuY3Rpb24gKGUpIHtcbi8vICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4vLyAgICAgICAgaWYgKCQodGhpcykucGFyZW50cygnbGknKS5oYXNDbGFzcygndW5zZWxlY3RhYmxlJykpIHsgcmV0dXJuOyB9XG4vLyAgICAgICAgaWYgKCQodGhpcykucGFyZW50cygnbGknKS5oYXNDbGFzcygnc2VsZWN0ZWQnKSkgeyByZXR1cm47IH1cbi8vICAgICAgICB1cGRhdGVDb250ZW50KHRoaXMuaHJlZik7XG4vLyAgICB9KTtcblxuICAgIC8vIGNsaWNrIG9uIHN3YXRjaCAtIHNob3VsZCB1cGRhdGUgbWFpbiBpbWFnZSB3aXRoIHN3YXRjaCBpbWFnZS5cbiAgICAkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuU3dhdGNoQW5jaG9yJykub24oJ2NsaWNrLlZhcmlhbnQuU3dhdGNoQW5jaG9yJywgJy5wcm9kdWN0LWRldGFpbCAuc3dhdGNoYW5jaG9yJywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBkaWRSZWxvYWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKCQodGhpcykucGFyZW50cygnbGknKS5oYXNDbGFzcygndW5zZWxlY3RhYmxlJykpIHtcbiAgICAgICAgXHRpZiAoJCh0aGlzKS5wYXJlbnRzKCdsaScpLmhhc0NsYXNzKCdhbHRlcm5hdGUnKSkge1xuICAgICAgICBcdFx0dmFyIGFsdFVybExvYWQgPSAkKHRoaXMpLmF0dHIoJ2hyZWYnKTsgICAgXHRcdFxuICAgICAgICBcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBhbHRVcmxMb2FkO1xuICAgICAgICBcdH1cbiAgICAgICAgXHRcbiAgICAgICAgXHQkKCdsaS5kcm9wLWRvd24tc2VsZWN0LXZhbHVlJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICBcdFx0XHR2YXIgJHNlbGVjdGVkSXRlbSA9ICQodGhpcyk7XG4gICAgXHRcdFx0JHNlbGVjdGVkSXRlbS5zaWJsaW5ncygnbGkuc2VsZWN0ZWQtdmFsdWUnKS5odG1sKCRzZWxlY3RlZEl0ZW0uaHRtbCgpKTtcbiAgICAgICAgXHRcdCRzZWxlY3RlZEl0ZW0ucGFyZW50cygnLmF0dHJpYnV0ZScpLmZpcnN0KCkuZmluZCgnLmxhYmVsIC5jdXJyZW50LCAuc2VsZWN0LWRyb3Bkb3duIC5zZWxlY3QtdGV4dCcpLmh0bWwoJHNlbGVjdGVkSXRlbS5odG1sKCkpO1xuICAgICAgICBcdFx0aWYgKCAkc2VsZWN0ZWRJdGVtLnBhcmVudHMoJy5zZWxlY3QtZHJvcGRvd24taW5uZXInKSAhPSBudWxsICkge1xuICAgICAgICBcdFx0XHQkc2VsZWN0ZWRJdGVtLnBhcmVudHMoJy5zZWxlY3QtZHJvcGRvd24taW5uZXInKS5maW5kKCAnbGkuc2VsZWN0ZWQnICkucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgIFx0XHR9XG4gICAgICAgIFx0fSk7XG4gICAgXHRcdGlmICggJCh0aGlzKS5hdHRyKCd4aHJlZicpICE9IG51bGwgKSB7XG4gICAgXHRcdFx0dXBkYXRlQ29udGVudCgkKHRoaXMpLmF0dHIoJ3hocmVmJykpO1xuICAgIFx0XHRcdGRpZFJlbG9hZCA9IHRydWU7XG4gICAgXHRcdH0gZWxzZSB7IHJldHVybjsgfVxuICAgIFx0fVxuICAgICAgICBpZiAoICFkaWRSZWxvYWQgKSB7XG5cdCAgICAgICAgdmFyIGxpbmsgPSB0aGlzO1xuXHQgICAgICAgIGlmICghbGluay5ocmVmKSB7XG5cdCAgICAgICAgXHRsaW5rID0gJCh0aGlzKS5wYXJlbnQoKVswXTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgdXBkYXRlQ29udGVudChsaW5rLmhyZWYpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBjaGFuZ2UgZHJvcCBkb3duIHZhcmlhdGlvbiBhdHRyaWJ1dGUgLSBzaG91bGQgcmVwbGFjZSBwcm9kdWN0IGNvbnRlbnQgd2l0aCBuZXcgdmFyaWFudFxuICAgICRwZHBNYWluLm9mZignY2hhbmdlLlZhcmlhbnQuVmFyaWF0aW9uU2VsZWN0Jykub24oJ2NoYW5nZS5WYXJpYW50LlZhcmlhdGlvblNlbGVjdCcsICcudmFyaWF0aW9uLXNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCQodGhpcykudmFsKCkubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuICAgICAgICB1cGRhdGVDb250ZW50KCQodGhpcykudmFsKCkpO1xuICAgIH0pO1xuXG5cdC8vIEN1c3RvbSBTZWxlY3QgRHJvcGRvd25cbiAgICAkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuU2VsZWN0b3IuRXhwYW5kJykub24oJ2NsaWNrLlZhcmlhbnQuU2VsZWN0b3IuRXhwYW5kJywgJy5zZWxlY3QtZHJvcGRvd24gLnNlbGVjdC10ZXh0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciB0b2dnbGVPcGVuID0gISR0aGlzLmhhc0NsYXNzKCdhY3RpdmUnKTtcblx0XHRzaXplTWVudU9wZW5DbG9zZShldmVudCwgJHRoaXMsIHRvZ2dsZU9wZW4pO1xuXHR9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2suVmFyaWFudC5HZW5lcmFsLkNsb3NlJykub24oJ2NsaWNrLlZhcmlhbnQuR2VuZXJhbC5DbG9zZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHQkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIHVsLnNlbGVjdC1kcm9wZG93bi1pbm5lci5leHBhbmQtY2xvc2UnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBcdFx0JCh0aGlzKS5zaWJsaW5ncygnLnNlbGVjdC10ZXh0JykudHJpZ2dlcignY2xpY2snKTtcbiAgICBcdH0pO1xuXHR9KTtcblxuXHQkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuU2VsZWN0b3IuU2VsZWN0Jykub24oJ2NsaWNrLlZhcmlhbnQuU2VsZWN0b3IuU2VsZWN0JywgJy5zZWxlY3QtZHJvcGRvd24gLnNlbGVjdGFibGUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0c2VsZWN0U2l6ZU9wdGlvbih0aGlzKTtcblx0fSk7XG5cblx0Ly8gQ29sb3IgT3B0aW9uc1xuICAgICRwZHBNYWluLm9mZignY2xpY2suVmFyaWFudC5Db2xvci5TZWxlY3QnKS5vbignY2xpY2suVmFyaWFudC5Db2xvci5TZWxlY3QnLCAnLmNvbG9yLW9wdGlvbnMgYScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgbmFtZUNvbG9yID0gJCh0aGlzKS5kYXRhKCdjb2xvci1uYW1lJyk7XG5cblx0XHQkKHRoaXMpXG5cdFx0XHQucGFyZW50KClcblx0XHRcdC5hZGRDbGFzcygnc2VsZWN0ZWQnKVxuXHRcdFx0LnNpYmxpbmdzKClcblx0XHRcdC5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcblxuXHRcdCQodGhpcylcblx0XHRcdC5jbG9zZXN0KCcuYXR0cmlidXRlJylcblx0XHRcdC5maW5kKCcuY29sb3ItY3VycmVudCcpXG5cdFx0XHQudGV4dChuYW1lQ29sb3IpO1xuXHR9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbigna2V5dXAnLCAnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyBkaXYuc2VsZWN0LWRyb3Bkb3duJywgZnVuY3Rpb24oZSkge1xuXHRcdHZhciAkbGlzdENvbnRhaW5lciA9ICQodGhpcyksXG5cdFx0XHQkbGlzdFBhcmVudCA9ICRsaXN0Q29udGFpbmVyLmNoaWxkcmVuKCd1bC5zZWxlY3QtZHJvcGRvd24taW5uZXInKSxcblx0XHRcdCRkZWZhdWx0VGV4dEVsZW1lbnQgPSAkbGlzdENvbnRhaW5lci5jaGlsZHJlbignLnNlbGVjdC10ZXh0JyksXG5cdFx0XHQkc2l6ZUxpc3QgPSAkbGlzdFBhcmVudC5maW5kKCdsaS5zZWxlY3RhYmxlJyksXG5cdFx0XHQkc2VsZWN0ZWQgPSAkc2l6ZUxpc3QuZmlsdGVyKCcuc2VsZWN0ZWQnKSxcblx0XHRcdGlzTWVudU9wZW4gPSAkbGlzdFBhcmVudC5oYXNDbGFzcygnZXhwYW5kJyk7XG5cblx0XHRhbnRpSG92ZXIuaW5pdCgkbGlzdFBhcmVudC53aWR0aCgpLCAkbGlzdFBhcmVudC5oZWlnaHQoKSk7XG5cblx0XHRpZiAoZS5zaGlmdEtleSAmJiBlLmtleUNvZGUgPT0gOSAmJiBpc01lbnVPcGVuKSB7IC8vIFRhYiBiYWNrd2FyZHNcblx0XHRcdHNlbGVjdE9wdGlvbktleWRvd24oZSwgJ3VwJywgaXNNZW51T3Blbik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHN3aXRjaChlLmtleUNvZGUpIHtcblx0XHRcdFx0Y2FzZSAzODogLy8gVXAgQXJyb3dcblx0XHRcdFx0XHRzZWxlY3RPcHRpb25LZXlkb3duKGUsICd1cCcsIGlzTWVudU9wZW4pO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDQwOiAvLyBEb3duIEFycm93XG5cdFx0XHRcdFx0aWYgKCFpc01lbnVPcGVuKSB7XG5cdFx0XHRcdFx0XHRzaXplTWVudU9wZW5DbG9zZShlLCAkZGVmYXVsdFRleHRFbGVtZW50LCB0cnVlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0c2VsZWN0T3B0aW9uS2V5ZG93bihlLCAnZG93bicsIGlzTWVudU9wZW4pO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDk6IC8vIFRhYiBmb3J3YXJkc1xuXHRcdFx0XHRcdGlmIChpc01lbnVPcGVuKSB7XG5cdFx0XHRcdFx0XHRzZWxlY3RPcHRpb25LZXlkb3duKGUsICdkb3duJywgaXNNZW51T3Blbik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDI3OiAvLyBFc2NhcGUga2V5XG5cdFx0XHRcdFx0aWYgKGlzTWVudU9wZW4pIHtcblx0XHRcdFx0XHRcdHNpemVNZW51T3BlbkNsb3NlKGUsICRkZWZhdWx0VGV4dEVsZW1lbnQsIGZhbHNlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMTM6IC8vIEVudGVyIGtleVxuXHRcdFx0XHRcdCRsaXN0Q29udGFpbmVyLmZpbmQoJy5zZWxlY3QtdGV4dCcpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0XHQkbGlzdFBhcmVudC50b2dnbGVDbGFzcygnZXhwYW5kJykudG9nZ2xlQ2xhc3MoJ2V4cGFuZC1jbG9zZScpLnRvZ2dsZUNsYXNzKCdzaXplLWQtbm9uZScpO1xuXHRcdFx0XHRcdCRzaXplTGlzdC5maW5kKCdhW3RhYmluZGV4XScpLmxlbmd0aCA+IDAgPyAkc2l6ZUxpc3QuZmluZCgnYScpLnJlbW92ZUF0dHIoJ3RhYmluZGV4JykgOiAkc2l6ZUxpc3QuZmluZCgnYScpLmF0dHIoJ3RhYmluZGV4JywgJy0xJyk7XHRcblx0XHRcdFx0XHRpZiAoISRzZWxlY3RlZCkge1xuXHRcdFx0XHRcdFx0JGRlZmF1bHRUZXh0RWxlbWVudC50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkc2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0XHRcdH1cdFxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlbW92ZS5WYXJpYW50LkFudGlIb3ZlcicpLm9uKCdtb3VzZW1vdmUuVmFyaWFudC5BbnRpSG92ZXInLCAnI2FudGktaG92ZXInLCBmdW5jdGlvbihlKSB7XG4gICAgXHRhbnRpSG92ZXIubW92ZXJlbW92ZShwYXJzZUludChlLmNsaWVudFgpLCBwYXJzZUludChlLmNsaWVudFkpKTtcbiAgICB9KTtcblxuICAgIHZhciBzd2F0Y2hlcyA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbiB1bC5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGFibGUnKTtcblx0aWYgKHN3YXRjaGVzLmxlbmd0aCAmJiAhc3dhdGNoZXMuaXMoJy5zZWxlY3RlZCcpKSB7XG5cdFx0c2V0Q29sb3IoKTtcblx0fVxuXHRcblx0dXBkYXRlUHJvZHVjdEluZm8oKTtcbiAgICBpbml0aWFsaXplSW1hZ2VHYWxsZXJ5KCk7XG59O1xuXG5mdW5jdGlvbiBzZXRDb2xvcigpe1xuXHR2YXIgZCA9IG5ldyAkLkRlZmVycmVkKCk7XG5cblx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgIFx0dmFyIHN3YXRjaGVzID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9uIHVsLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0YWJsZScpO1xuICAgIFx0aWYgKHN3YXRjaGVzLmxlbmd0aCAmJiAhc3dhdGNoZXMuaXMoJy5zZWxlY3RlZCcpKSB7XG4gICAgXHRcdHN3YXRjaGVzLmZpcnN0KCkuZmluZCgnYScpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtkLnJlc29sdmUoKX0sIDE1MCk7XG4gICAgXHR9XG4gICAgXHRcbiAgICB9LCA1MCk7XG5cdFxuXHRyZXR1cm4gZC5wcm9taXNlKClcbn1cblxudmFyIGFudGlIb3ZlciA9IHtcblx0JGFudGlIb3ZlcjogbnVsbCxcblx0cG9zWDogMCxcblx0cG9zWTogMCxcblx0cmVtb3ZlOiBmdW5jdGlvbigpIHtcblx0XHRpZiAodGhpcy4kYW50aUhvdmVyKSB0aGlzLiRhbnRpSG92ZXIucmVtb3ZlKCk7XG5cdFx0dGhpcy5wb3NYID0gMDtcblx0XHR0aGlzLnBvc1kgPSAwO1xuXHR9LFxuXHRtb3ZlcmVtb3ZlOiBmdW5jdGlvbih4LCB5KSB7XG5cdFx0dGhpcy5wb3NYID0gKHRoaXMucG9zWCA9PSAwKSA/IHggOiB0aGlzLnBvc1g7XG5cdFx0dGhpcy5wb3NZID0gKHRoaXMucG9zWSA9PSAwKSA/IHkgOiB0aGlzLnBvc1k7XG5cdFx0aWYgKHRoaXMucG9zWCAhPSB4IHx8IHRoaXMucG9zWSAhPSB5KSB7XG5cdFx0XHQkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIHVsLnNlbGVjdC1kcm9wZG93bi1pbm5lciBsaS5zZWxlY3RhYmxlJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cdFx0XHR0aGlzLnJlbW92ZSgpO1xuXHRcdH1cblx0fSxcblx0Y2hlY2s6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiAodGhpcy4kYW50aUhvdmVyICYmIHRoaXMuJGFudGlIb3Zlci5sZW5ndGgpO1xuXHR9LFxuXHRpbml0OiBmdW5jdGlvbih3LCBoKSB7XG5cdFx0dGhpcy5yZW1vdmUoKTtcblx0XHQkKCcudmFsdWUuc2VsZWN0LWRyb3Bkb3duJykuYXBwZW5kKCc8ZGl2IHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlO1wiIGlkPVwiYW50aS1ob3ZlclwiPjwvZGl2PicpO1xuXHRcdHRoaXMuJGFudGlIb3ZlciA9ICQoJyNhbnRpLWhvdmVyJyk7XG5cdFx0dGhpcy4kYW50aUhvdmVyXG5cdFx0XHQuY3NzKCd6LWluZGV4JywgMTAwMClcblx0XHRcdC5jc3MoJ2hlaWdodCcsIGgpXG5cdFx0XHQuY3NzKCd3aWR0aCcsIHcpO1xuXHR9XG5cbn07XG5cbmZ1bmN0aW9uIHNlbGVjdE9wdGlvbktleWRvd24oZSwgYWN0aW9uLCBpc01lbnVPcGVuKSB7XG5cdGUucHJldmVudERlZmF1bHQoKTtcblxuXHR2YXIgJGxpc3RQYXJlbnQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIHVsLnNlbGVjdC1kcm9wZG93bi1pbm5lcicpLFxuXHRcdCRsaXN0Q29udGFpbmVyID0gJGxpc3RQYXJlbnQuY2xvc2VzdCgnLnNlbGVjdC1kcm9wZG93bicpLFxuXHRcdCRkZWZhdWx0VGV4dEVsZW1lbnQgPSAkbGlzdENvbnRhaW5lci5jaGlsZHJlbignLnNlbGVjdC10ZXh0JyksXG5cdFx0JHNpemVMaXN0ID0gJGxpc3RQYXJlbnQuZmluZCgnbGkuc2VsZWN0YWJsZScpLFxuXHRcdCRzZWxlY3RlZCA9ICRzaXplTGlzdC5maWx0ZXIoJy5zZWxlY3RlZCcpLFxuXHRcdGhlaWdodCA9IHBhcnNlSW50KCRzaXplTGlzdC5maXJzdCgpLmNzcygnaGVpZ2h0JykucmVwbGFjZSgvcHgvLCAnJykpLFxuXHRcdCRjdXJyZW50O1xuXG5cdFx0aWYgKCRzZWxlY3RlZC5sZW5ndGggPD0gMCkge1xuXHRcdFx0JHNlbGVjdGVkID0gJGxpc3RQYXJlbnQuZmluZCgnLmZvY3VzLXZpc2libGUtaW5kaWNhdG9yJykuY2xvc2VzdCgnbGkuc2VsZWN0YWJsZScpID8gJHNlbGVjdGVkIDogbnVsbDtcblx0XHR9XG5cdFx0aWYgKCEkc2VsZWN0ZWQgfHwgISRzZWxlY3RlZC5sZW5ndGgpIHtcblx0XHRcdCRjdXJyZW50ID0gJHNpemVMaXN0LmVxKDApO1xuXHRcdH0gZWxzZSBpZiAoYWN0aW9uID09ICd1cCcpIHtcblx0XHRcdGlmICgkc2VsZWN0ZWQuaXMoJzpmaXJzdC1jaGlsZCcpKSB7XG5cdFx0XHRcdCRjdXJyZW50ID0gJHNpemVMaXN0LmVxKDApO1xuXHRcdFx0XHQvLyBJZiB0aGlzIGlzIGZpcnN0IGxpc3QgaXRlbSwgYW5kIHVzZXIgcHJlc3NlZCBVcCBBcnJvdywgdGhlbiB3ZSBuZWVkIHRvIGNsb3NlIHRoZSBtZW51XG5cdFx0XHRcdHNpemVNZW51T3BlbkNsb3NlKGUsICRkZWZhdWx0VGV4dEVsZW1lbnQsIGZhbHNlKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRjdXJyZW50ID0gJHNlbGVjdGVkLnByZXYoKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCEkc2VsZWN0ZWQubmV4dCgpLmhhc0NsYXNzKCdzZWxlY3RhYmxlJykpIHtcblx0XHRcdFx0JGN1cnJlbnQgPSAkc2l6ZUxpc3QubGFzdCgpO1xuXHRcdFx0XHQvLyBJZiB0aGlzIGlzIGxhc3QgbGlzdCBpdGVtLCBhbmQgdXNlciBwcmVzc2VkIERvd24gQXJyb3csIHRoZW4gd2UgbmVlZCB0byBjbG9zZSB0aGUgbWVudVxuXHRcdFx0XHRzaXplTWVudU9wZW5DbG9zZShlLCAkZGVmYXVsdFRleHRFbGVtZW50LCBmYWxzZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkY3VycmVudCA9ICRzZWxlY3RlZC5uZXh0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIGxpc3RQYXJlbnRUb3AgPSAwO1xuXHRcdHZhciBsaXN0UGFyZW50Qm90dG9tID0gbGlzdFBhcmVudFRvcCArICRsaXN0UGFyZW50LmhlaWdodCgpO1xuXHRcdHZhciBjdXJyZW50VG9wID0gJGN1cnJlbnQucG9zaXRpb24oKS50b3A7XG5cdFx0dmFyIGN1cnJlbnRCb3R0b20gPSBjdXJyZW50VG9wICsgJGN1cnJlbnQuaGVpZ2h0KCk7XG5cdFx0dmFyIGZhdWx0UHggPSAxMDtcblx0XHRpZiAoY3VycmVudEJvdHRvbSArIGZhdWx0UHggPiBsaXN0UGFyZW50Qm90dG9tKSB7XG5cdFx0XHQkbGlzdFBhcmVudC5zY3JvbGxUb3AocGFyc2VJbnQoJGxpc3RQYXJlbnQuc2Nyb2xsVG9wKCkpICsgaGVpZ2h0KTtcblx0XHR9IGVsc2UgaWYgKGN1cnJlbnRUb3AgPCBsaXN0UGFyZW50VG9wKSB7XG5cdFx0XHQkbGlzdFBhcmVudC5zY3JvbGxUb3AocGFyc2VJbnQoJGxpc3RQYXJlbnQuc2Nyb2xsVG9wKCkpIC0gaGVpZ2h0KTtcblx0XHR9XHRcblxuXHRcdC8vJGN1cnJlbnQucGFyZW50cygnLmF0dHJpYnV0ZScpLmZpcnN0KCkuZmluZCgnLmxhYmVsIC5jdXJyZW50LCAuc2VsZWN0LWRyb3Bkb3duIC5zZWxlY3QtdGV4dCcpLmh0bWwoJGN1cnJlbnQuZmluZCgnYScpLmh0bWwoKSk7XG5cdFx0JHNpemVMaXN0LnJlbW92ZUNsYXNzKCdzZWxlY3RlZCB0ZW1wc2VsZWN0aW9uJyk7XG5cdFx0JGN1cnJlbnQuYWRkQ2xhc3MoJ3NlbGVjdGVkIHRlbXBzZWxlY3Rpb24nKS5maW5kKCdhJykuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJykuZm9jdXMoKTtcblx0XHQvLyBOZWVkZWQgdG8gY29tYmF0IGF1dG8tc2Nyb2xsIGJlaGF2aW9yIHRoYXQgaGFwcGVucyBpbiBwcmV2aW91cyBsaW5lIHdoZW4gZm9jdXMgYWRkZWQgdG8gPGE+XG5cdFx0aWYgKCRjdXJyZW50LmlzKCc6Zmlyc3QtY2hpbGQnKSkge1xuXHRcdFx0JGxpc3RQYXJlbnQuc2Nyb2xsVG9wKDApO1xuXHRcdH1cbn1cblxuZnVuY3Rpb24gc2Nyb2xsVG9DdXJyZW50U2l6ZSgpIHtcblx0dmFyICRsaXN0UGFyZW50ID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyB1bC5zZWxlY3QtZHJvcGRvd24taW5uZXInKSxcblx0XHQkc2l6ZUxpc3QgPSAkbGlzdFBhcmVudC5maW5kKCdsaS5zZWxlY3RhYmxlJyksXG5cdFx0JHNlbGVjdGVkID0gJHNpemVMaXN0LmZpbHRlcignLnNlbGVjdGVkJyksXG5cdFx0aGVpZ2h0ID0gJHNpemVMaXN0LmZpcnN0KCkuY3NzKCdoZWlnaHQnKS5yZXBsYWNlKC9weC8sICcnKTtcblxuXHRpZiAoJHNlbGVjdGVkKSB7XG5cdFx0JGxpc3RQYXJlbnQuc2Nyb2xsVG9wKGhlaWdodCAqICRzaXplTGlzdC5pbmRleCgkc2VsZWN0ZWQpKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplSW1hZ2VHYWxsZXJ5KCkge1xuXHR2YXIgcGFyYW1zO1xuXHRpZiAoU2l0ZVByZWZlcmVuY2VzLlBSSU1BUllfUFJPRFVDVF9TTElERVIgPT0gJ3N3aXBlckpTJykgeyBcblx0XHRpbWFnZUdhbGxlcnkgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0ltYWdlR2FsbGVyeS9Td2lwZXInKTtcblx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLlBSSU1BUllfUFJPRFVDVF9TTElERVJfQ09ORklHKSB7XG5cdFx0XHRwYXJhbXMgPSBKU09OLnBhcnNlKFNpdGVQcmVmZXJlbmNlcy5QUklNQVJZX1BST0RVQ1RfU0xJREVSX0NPTkZJRyk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdGltYWdlR2FsbGVyeSA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvSW1hZ2VHYWxsZXJ5L1NsaWNrQW5kSW1nVmlld2VyMicpO1xuXHR9XG5cdGltYWdlR2FsbGVyeS5pbml0aWFsaXplKHBhcmFtcyk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVCb3BpcygpIHtcblx0aWYgKCQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLWNvbnRhaW5lcicpLmxlbmd0aCA+IDApIHtcblx0XHRib3Bpc0FkZFRvQ2FydE9wdGlvbnMuaW5pdGlhbGl6ZSgkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXInKSwgJC5leHRlbmQob3B0aW9ucy5Cb3BpcywgeyBDaGFubmVsOiBvcHRpb25zLkNoYW5uZWwsIFByb2R1Y3RJZDogb3B0aW9ucy5Qcm9kdWN0SWQsIFN0b3JlVUlWZXJzaW9uOiBvcHRpb25zLlN0b3JlVUlWZXJzaW9uIH0pKTtcblx0fVxuXHRcblx0aWYgKCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5sZW5ndGggPiAwKSB7XG5cdFx0Ym9waXNTdG9yZVNlYXJjaC5pbml0aWFsaXplKCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKSwgJC5leHRlbmQob3B0aW9ucy5Cb3BpcywgeyBDaGFubmVsOiBvcHRpb25zLkNoYW5uZWwgfSkpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0aW5pdGlhbGl6ZURvbSgpO1xuXHRpbml0aWFsaXplRXZlbnRzKCk7XG5cdGluaXRpYWxpemVCb3BpcygpO1xufVxuXG52YXIgdmFyaWFudCA9IHtcblx0aW5pdGlhbGl6ZTogaW5pdGlhbGl6ZSxcblx0aW5pdGlhbGl6ZURvbTogaW5pdGlhbGl6ZURvbSxcblx0aW5pdGlhbGl6ZUV2ZW50czogaW5pdGlhbGl6ZUV2ZW50c1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB2YXJpYW50OyIsIid1c2Ugc3RyaWN0JztcbnZhciBkaXJlY3Rpb24sIHZpZGVvQ291bnQsIHdpZHRoLCBoZWlnaHQsIHZpZGVvQ291bnRlciA9IDAsIHBvc1ZhbHVlID0gMCwgbGFzdENvdW50ZXIgPSAwLCBhcnJvd1BvcztcblxudmFyIHNldENhcm91c2VsID0gZnVuY3Rpb24oKXtcblx0dmlkZW9Db3VudCA9ICQoJy52aWRlby1jb250YWluZXIgdWwgbGknKS5sZW5ndGg7XG5cdHdpZHRoID0gJCgnLnZpZGVvLWNvbnRhaW5lcicpLndpZHRoKCk7XG5cdGhlaWdodCA9IHdpZHRoICogMzE1IC8gNDIwO1xuXHQkKCcueW91dHViZS12aWRlbyBpZnJhbWUnKS5jc3Moeyd3aWR0aCc6IHdpZHRoICsgJ3B4JywnaGVpZ2h0JzogaGVpZ2h0ICsgJ3B4J30pO1xuXHR3aWR0aCArPSA0MDtcblx0YXJyb3dQb3MgPSBoZWlnaHQgLyAyIC0gMjA7XG5cdCQoJy52aWRlby1jb250YWluZXIgLmFycm93cyAuYXJyb3cnKS5jc3MoJ3RvcCcsIGFycm93UG9zICsgJ3B4Jyk7XG59O1xuXG52YXIgYXJyb3dDbGljayA9IGZ1bmN0aW9uKGFycm93KXtcblx0ZGlyZWN0aW9uID0gYXJyb3cuaGFzQ2xhc3MoJ2xlZnQnKSA/ICdsZWZ0JyA6ICdyaWdodCc7XG5cdGxhc3RDb3VudGVyID0gdmlkZW9Db3VudGVyO1xuXHRpZihkaXJlY3Rpb24gPT0gJ3JpZ2h0Jyl7XG5cdFx0aWYodmlkZW9Db3VudGVyID09ICh2aWRlb0NvdW50IC0gMSkpe1xuXHRcdFx0cG9zVmFsdWUgPSAwO1xuXHRcdFx0dmlkZW9Db3VudGVyID0gMDtcblx0XHR9XG5cdFx0ZWxzZXtcblx0XHRcdHZpZGVvQ291bnRlcisrO1xuXHRcdFx0cG9zVmFsdWUgPSB2aWRlb0NvdW50ZXIgKiB3aWR0aDtcblx0XHR9XG5cdH1cblx0ZWxzZXtcblx0XHRpZih2aWRlb0NvdW50ZXIgPT0gMCl7XG5cdFx0XHRwb3NWYWx1ZSA9ICh2aWRlb0NvdW50IC0gMSkgKiB3aWR0aDtcblx0XHRcdHZpZGVvQ291bnRlciA9IHZpZGVvQ291bnQgLSAxO1xuXHRcdH1cblx0XHRlbHNle1xuXHRcdFx0dmlkZW9Db3VudGVyLS07XG5cdFx0XHRwb3NWYWx1ZSA9IHZpZGVvQ291bnRlciAqIHdpZHRoO1xuXHRcdH1cblx0fVxuXHQkKCcudmlkZW8tY29udGFpbmVyIHVsJykuYW5pbWF0ZSh7J2xlZnQnOictJyArIHBvc1ZhbHVlICsgJ3B4J30sICdmYXN0Jyk7XG5cdHZhciBpZnJhbWUgPSAkKCcueW91dHViZS12aWRlbyBpZnJhbWU6ZXEoJysgbGFzdENvdW50ZXIgKycpJyk7XG5cdCQoaWZyYW1lKS5hdHRyKCdzcmMnLCAkKGlmcmFtZSkuYXR0cignc3JjJykpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHNldENhcm91c2VsKCk7XG4gICAgJCgnLnZpZGVvLWNvbnRhaW5lciAuYXJyb3dzIC5hcnJvdycpLm9uKCdjbGljaycsIGZ1bmN0aW9uKCl7XG4gICAgXHRhcnJvd0NsaWNrKCQodGhpcykpO1xuICAgIH0pO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBhZGRQcm9kdWN0VG9DYXJ0ID0gcmVxdWlyZSgnLi9wcm9kdWN0L2FkZFRvQ2FydCcpLFxuICAgIGFqYXggPSByZXF1aXJlKCcuLi9hamF4JyksXG4gICAgcXVpY2t2aWV3ID0gcmVxdWlyZSgnLi4vcXVpY2t2aWV3JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBMb2FkcyBhZGRyZXNzIGRldGFpbHMgdG8gYSBnaXZlbiBhZGRyZXNzIGFuZCBmaWxscyB0aGUgYWRkcmVzcyBmb3JtXG4gKiBAcGFyYW0ge1N0cmluZ30gYWRkcmVzc0lEIFRoZSBJRCBvZiB0aGUgYWRkcmVzcyB0byB3aGljaCBkYXRhIHdpbGwgYmUgbG9hZGVkXG4gKi9cbmZ1bmN0aW9uIHBvcHVsYXRlRm9ybShhZGRyZXNzSUQsICRmb3JtKSB7XG4gICAgLy8gbG9hZCBhZGRyZXNzIGRldGFpbHNcbiAgICB2YXIgdXJsID0gVXJscy5naWZ0UmVnQWRkICsgYWRkcmVzc0lEO1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSB8fCAhZGF0YS5hZGRyZXNzKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5SRUdfQUREUl9FUlJPUik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZmlsbCB0aGUgZm9ybVxuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2FkZHJlc3NpZFwiXScpLnZhbChkYXRhLmFkZHJlc3MuSUQpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2ZpcnN0bmFtZVwiXScpLnZhbChkYXRhLmFkZHJlc3MuZmlyc3ROYW1lKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9sYXN0bmFtZVwiXScpLnZhbChkYXRhLmFkZHJlc3MubGFzdE5hbWUpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKGRhdGEuYWRkcmVzcy5hZGRyZXNzMSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoZGF0YS5hZGRyZXNzLmFkZHJlc3MyKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9jaXR5XCJdJykudmFsKGRhdGEuYWRkcmVzcy5jaXR5KTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9jb3VudHJ5XCJdJykudmFsKGRhdGEuYWRkcmVzcy5jb3VudHJ5Q29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKGRhdGEuYWRkcmVzcy5wb3N0YWxDb2RlKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9zdGF0ZVwiXScpLnZhbChkYXRhLmFkZHJlc3Muc3RhdGVDb2RlKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9waG9uZVwiXScpLnZhbChkYXRhLmFkZHJlc3MucGhvbmUpO1xuICAgICAgICAgICAgLy8gJGZvcm0ucGFyZW50KCdmb3JtJykudmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZXZlbnRzIGZvciB0aGUgZ2lmdCByZWdpc3RyYXRpb25cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcbiAgICB2YXIgJGV2ZW50QWRkcmVzc0Zvcm0gPSAkKCdmb3JtW25hbWUkPVwiX2dpZnRyZWdpc3RyeVwiXScpLFxuICAgICAgICAkYmVmb3JlQWRkcmVzcyA9ICRldmVudEFkZHJlc3NGb3JtLmZpbmQoJ2ZpZWxkc2V0W25hbWU9XCJhZGRyZXNzLWJlZm9yZVwiXScpLFxuICAgICAgICAkYWZ0ZXJBZGRyZXNzID0gJGV2ZW50QWRkcmVzc0Zvcm0uZmluZCgnZmllbGRzZXRbbmFtZT1cImFkZHJlc3MtYWZ0ZXJcIl0nKTtcblxuICAgICQoJy51c2VwcmVldmVudCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZmlsdGVyIG91dCBzdG9yZWZyb250IHRvb2xraXRcbiAgICAgICAgJCgnOmlucHV0JywgJGJlZm9yZUFkZHJlc3MpLm5vdCgnW2lkXj1cImV4dFwiXScpLm5vdCgnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NCZWZvcmVMaXN0XCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZmllbGROYW1lID0gJCh0aGlzKS5hdHRyKCduYW1lJyksXG4gICAgICAgICAgICAgICAgJGFmdGVyRmllbGQgPSAkYWZ0ZXJBZGRyZXNzLmZpbmQoJ1tuYW1lPVwiJyArIGZpZWxkTmFtZS5yZXBsYWNlKCdCZWZvcmUnLCAnQWZ0ZXInKSArICdcIl0nKTtcbiAgICAgICAgICAgICRhZnRlckZpZWxkLnZhbCgkKHRoaXMpLnZhbCgpKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgJGV2ZW50QWRkcmVzc0Zvcm0ub24oJ2NoYW5nZScsICdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0JlZm9yZUxpc3RcIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhZGRyZXNzSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoYWRkcmVzc0lELmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAgICAgcG9wdWxhdGVGb3JtKGFkZHJlc3NJRCwgJGJlZm9yZUFkZHJlc3MpO1xuICAgIH0pXG4gICAgLm9uKCdjaGFuZ2UnLCAnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NBZnRlckxpc3RcIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhZGRyZXNzSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoYWRkcmVzc0lELmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAgICAgcG9wdWxhdGVGb3JtKGFkZHJlc3NJRCwgJGFmdGVyQWRkcmVzcyk7XG4gICAgfSk7XG5cbiAgICAkKCdmb3JtW25hbWUkPVwiX2dpZnRyZWdpc3RyeV9pdGVtc1wiXScpLm9uKCdjbGljaycsICcuaXRlbS1kZXRhaWxzIGEnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBwcm9kdWN0TGlzdElEID0gJCgnaW5wdXRbbmFtZT1wcm9kdWN0TGlzdElEXScpLnZhbCgpO1xuICAgICAgICBxdWlja3ZpZXcuc2hvdyh7XG4gICAgICAgICAgICB1cmw6IGUudGFyZ2V0LmhyZWYsXG4gICAgICAgICAgICBzb3VyY2U6ICdnaWZ0cmVnaXN0cnknLFxuICAgICAgICAgICAgcHJvZHVjdGxpc3RpZDogcHJvZHVjdExpc3RJRFxuICAgICAgICB9KTtcbiAgICB9KTtcblxufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xuICAgIGFkZFByb2R1Y3RUb0NhcnQoKTtcblxuICAgIHV0aWwuc2V0RGVsZXRlQ29uZmlybWF0aW9uKCcuaXRlbS1saXN0JywgU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ09ORklSTV9ERUxFVEUsIFJlc291cmNlcy5USVRMRV9HSUZUUkVHSVNUUlkpKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBib290QmFybkV4cHJlc3NSZWZpbmVtZW50V2l6YXJkID0gcmVxdWlyZSgnLi4vQm9vdEJhcm5FeHByZXNzL2NvbXBvbmVudHMvQm9vdEJhcm5FeHByZXNzUmVmaW5lbWVudFdpemFyZCcpO1xudmFyIGNvbXBhcmVXaWRnZXQgPSByZXF1aXJlKCcuLi9jb21wYXJlLXdpZGdldCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBwcm9kdWN0VGlsZSA9IHJlcXVpcmUoJy4uL3Byb2R1Y3QtdGlsZScpO1xudmFyIHBhZ2UgPSByZXF1aXJlKCcuLi9wYWdlJyk7XG52YXIgc2l6ZVJlZmluZW1lbnRzID0gcmVxdWlyZSgnLi4vc2l6ZS1yZWZpbmVtZW50cycpO1xudmFyIHN0eWxlQ291bnRzID0gcmVxdWlyZSgnLi4vc3R5bGUtY291bnRzJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcbnZhciB3aXNobGlzdCA9IHJlcXVpcmUoJy4uL3dpc2hsaXN0Jyk7XG52YXIgc2xpZGVycyA9IHJlcXVpcmUoJy4uL3NsaWRlcnMnKTtcblxudmFyIEltYWdlQ29uc3RhbnRzO1xuXG52YXIgUmVmaW5lbWVudFVJVmVyc2lvbkNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUmVmaW5lbWVudENvbnN0YW50cycpLlJlZmluZW1lbnRzVUlWZXJzaW9ucztcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG5cbnZhciBvcHRpb25zO1xudmFyIGRhdGFCdWZmZXIgPSBbXTtcbnZhciAkaHRtbCA9ICQoJ2h0bWwnKTtcbnZhciAkcmVmaW5lbWVudHNJbm5lciA9ICQoJy5yZWZpbmVtZW50cycpO1xudmFyIHJlZmluZW1lbnRzRXhwYW5kZWQ7XG52YXIgcmVmaW5lbWVudHNWaWV3QWxsO1xudmFyIGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncztcblxudmFyICRib290RmluZGVyRW1haWxGb3JtO1xudmFyIGJvb3RGaW5kZXJFbWFpbFZhbGlkYXRvcjtcblxudmFyIHByZXZpb3VzU29ydEFwcGxpZWQ7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHJlcGxhY2VzIGJyZWFkY3J1bWJzLCBsZWZ0aGFuZCBuYXYgYW5kIHByb2R1Y3QgbGlzdGluZyB3aXRoIGFqYXggYW5kIHB1dHMgYSBsb2FkaW5nIGluZGljYXRvciBvdmVyIHRoZSBwcm9kdWN0IGxpc3RpbmdcbiAqL1xuZnVuY3Rpb24gdXBkYXRlUHJvZHVjdExpc3RpbmcodXJsLCBjYWxsYmFjaywgaXNMb2FkTW9yZSkge1xuICAgIGlmICghdXJsIHx8IHVybCA9PT0gd2luZG93LmxvY2F0aW9uLmhyZWYpIHtcbiAgICBcdGlmICgkKCdib2R5JykuYXR0cignbG9hZGluZycpKSB7XG4gICAgXHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgXHR9XG5cdFx0aWYgKCQoJy5hcHBseS1yZWZpbmVtZW50cycpLmhhc0NsYXNzKCdsb2FkaW5nJykpIHtcbiAgICBcdFx0JCgnLmFwcGx5LXJlZmluZW1lbnRzJykubG9hZGluZygnZGVzdHJveScpO1xuICAgIFx0fVxuXHRcdGlmICh0eXBlb2YgY2FsbGJhY2sgPT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0Y2FsbGJhY2soKTtcblx0XHR9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cblx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicgfHwgKG9wdGlvbnMgJiYgb3B0aW9ucy5QYWdpbmF0aW9uICYmIG9wdGlvbnMuUGFnaW5hdGlvbi5Nb2RlID09ICdMb2FkTW9yZScpKSB7XG5cdFx0JCgnLmJ0bi5sb2FkLW1vcmUnKS5sb2FkaW5nKHsgSXNJbWFnZVNob3duOiBmYWxzZSB9KTtcblx0fVxuXG4gICAgdXBkYXRlSW52ZW50b3J5TWVzc2FnZXModXJsKTtcblx0c2F2ZUV4cGFuZGVkUmVmaW5lbWVudHMoKTtcblx0XG5cdCQuYWpheCh7XG5cdFx0dXJsOiB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnZm9ybWF0JywgJ2FqYXgnKSxcblx0XHR0eXBlOiAnR0VUJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3JlZmluZW1lbnRzLW1vYmlsZS1zY3JvbGwtbG9jaycpLmNzcygndG9wJywgJycpO1xuXHRcdFx0aWYgKCQoJ2JvZHknKS5hdHRyKCdsb2FkaW5nJykgPT0gJ2xvYWRpbmcnKSB7XG5cdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cblx0XHRcdGhpc3RvcnkucHVzaFN0YXRlKHt9LCAnJywgdXJsKTtcblx0XHRcdHZhciAkY29udGVudCA9ICQoZGF0YSk7XG5cdFx0XHRpZiAoaXNMb2FkTW9yZSkge1xuXHRcdFx0XHR2YXIgJHByb2R1Y3RHcmlkID0gJGNvbnRlbnQuZmluZCgnI3NlYXJjaC1yZXN1bHQtaXRlbXMnKTtcblx0XHRcdFx0dmFyIHByb2R1Y3RUaWxlQ291bnQgPSAkcHJvZHVjdEdyaWQuZmluZCgnLmdyaWQtdGlsZScpLmxlbmd0aCArICQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zJykuZmluZCgnLmdyaWQtdGlsZScpLmxlbmd0aDtcblx0XHRcdFx0dmFyIHByb2R1Y3RUb3RhbENvdW50ID0gcGFyc2VJbnQoJGNvbnRlbnQuZmluZCgnLnNlYXJjaC1yZXN1bHQtb3B0aW9ucy5ib3R0b20gLmNvdW50JykudGV4dCgpLnJlcGxhY2UoL1xcRC9nLCAnJyksIDEwKTtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkNvdW50J10gPSBwcm9kdWN0VG90YWxDb3VudDtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkluZGV4J10gKz0gb3B0aW9ucy5QYWdpbmF0aW9uLlNpemU7XG5cdFx0XHRcdCQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zJykuYXBwZW5kKCRwcm9kdWN0R3JpZC5odG1sKCkpO1xuXHRcdFx0XHQkKCcuc2VhcmNoLXJlc3VsdC1vcHRpb25zIC5kaXNwbGF5LWNvdW50JykudGV4dChwcm9kdWN0VGlsZUNvdW50KTtcblxuXHRcdFx0XHRpZiAocHJvZHVjdFRpbGVDb3VudCA+PSBkYXRhQnVmZmVyWydQYWdpbmF0aW9uQ291bnQnXSkge1xuXHRcdFx0XHRcdCQoJy5idG4ubG9hZC1tb3JlJykuaGlkZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5idG4ubG9hZC1tb3JlJykuc2hvdygpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicgfHwgKG9wdGlvbnMgJiYgb3B0aW9ucy5QYWdpbmF0aW9uICYmIG9wdGlvbnMuUGFnaW5hdGlvbi5Nb2RlID09ICdMb2FkTW9yZScpKSB7XG5cdFx0XHRcdFx0JCgnLmJ0bi5sb2FkLW1vcmUnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFCdWZmZXJbJ1BhZ2luYXRpb25JbmRleCddID0gMDtcblx0XHRcdFx0JCgnI21haW4nKS5odG1sKCRjb250ZW50KTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0XHRcdCQoJyNncmlkLXNvcnQtaGVhZGVyJykuc2VsZWN0bWVudSh7XG5cdFx0XHRcdFx0XHQnd2lkdGgnOiAyMDVcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICgndmFyaWFudEludmVudG9yeU1lc3NhZ2luZ1VybCcgaW4gcGFnZSAmJiBwYWdlLnZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmdVcmwpIHtcblx0XHRcdFx0XHRzaG93VmFyaWFudEludmVudG9yeU1lc3NhZ2luZygpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCFjaGVja0ZvclVwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKSAmJiAkKCcjcHJpbWFyeScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkKCdodG1sLGJvZHknKS5hbmltYXRlKHtcblx0XHRcdFx0XHRcdHNjcm9sbFRvcDogJCgnI3ByaW1hcnknKS5vZmZzZXQoKS50b3Bcblx0XHRcdFx0XHR9LCAxMDAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQkcmVmaW5lbWVudHNJbm5lciA9ICQoJy5yZWZpbmVtZW50cycpO1xuXHRcdFx0cmVkcmF3VXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygkY29udGVudCwgdXJsKTtcdFx0XHRcdFxuXHRcdFx0Y29tcGFyZVdpZGdldC5pbml0KCk7XG5cdFx0XHRwcm9kdWN0VGlsZS5pbml0KCk7XG5cdFx0XHRzaXplUmVmaW5lbWVudHMuaW5pdCgpO1xuXHRcdFx0aW5pdGlhbGl6ZVJlZmluZW1lbnRDb250cm9scygpO1x0XHRcdFxuXHRcdFx0cmVkcmF3U2hvcE15U3RvcmUoKTtcblx0XHRcdHNsaWRlcnMuaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycygnLm1haW4tY29udGVudCAuY2F0ZWdvcnktbGFuZGluZy1zbGlkZXI6bm90KC5zbGljay1pbml0aWFsaXplZCknKTtcblx0XHRcdHdpc2hsaXN0LnJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucygpO1xuXG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkpIHtcblx0XHRcdFx0YWZmaXJtLnVpLnJlZnJlc2goKTtcblx0XHRcdH1cblxuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2F0ZWdvcnlIZWFkZXJTbGlkZXJzLkluaXRpYWxpemUnKTtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0VpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Jbml0aWFsaXplJyk7XG5cdFx0XHRpZiAoJCgnI2NhdGVnb3J5VGl0bGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXt3aW5kb3cudG9wLmRvY3VtZW50LnRpdGxlID0gJCgnI2NhdGVnb3J5VGl0bGUnKS5kYXRhKCd0aXRsZScpO30sIDMwMDApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGluaXRpYWxpemVUaHVtYkRhdGFMYXllcih1cmwpO1xuXG5cdFx0XHRpZiAob3B0aW9ucy5TdHlsZUNvdW50Q2FjaGUpIHtcblx0XHRcdFx0c3R5bGVDb3VudHMucmVuZGVyKG9wdGlvbnMuU3R5bGVDb3VudENhY2hlKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdGlmICgoZGF0YS5zdGF0dXMgPT0gMzAxIHx8IGRhdGEuc3RhdHVzID09IDMwMikgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUludmVudG9yeU1lc3NhZ2VzKHVybCwgY2FsbGJhY2spIHtcblx0dmFyIHVybFBhcmFtcyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXModXJsKTtcblxuXHR2YXIgaW52ZW50b3J5TGlua1VybCA9IFVybHMuZ2V0SW52ZW50b3J5TGluaztcblx0Zm9yICh2YXIgdXJsUGFyYW1ldGVyIGluIHVybFBhcmFtcykge1xuXHRcdGlmICh1cmxQYXJhbXNbdXJsUGFyYW1ldGVyXSkge1xuXHRcdFx0aW52ZW50b3J5TGlua1VybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChpbnZlbnRvcnlMaW5rVXJsLCB1cmxQYXJhbWV0ZXIsIHVybFBhcmFtc1t1cmxQYXJhbWV0ZXJdKTtcblx0XHR9XG5cdH1cblxuXHQkLnBvc3QoaW52ZW50b3J5TGlua1VybCwgZnVuY3Rpb24oZGF0YSkge1xuXHRcdHZhciBkYXRhT2JqID0gSlNPTi5wYXJzZShkYXRhKTtcblx0XHRcblx0XHRpZiAoZGF0YU9iai5zdGF0dXMgJiYgZGF0YU9iai51cmwubGVuZ3RoKSB7XG5cdFx0XHR2YXIgbmV3VXJsID0gZGF0YU9iai51cmw7XG5cdFx0XHRcblx0XHRcdGlmICh1cmxQYXJhbXMuaGFzT3duUHJvcGVydHkoJ3N0YXJ0JykgJiYgdXJsUGFyYW1zLnN0YXJ0ID4gMCkge1xuXHRcdFx0XHRuZXdVcmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwobmV3VXJsLCAnc3RhcnQnLCB1cmxQYXJhbXMuc3RhcnQpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAodXJsUGFyYW1zLmhhc093blByb3BlcnR5KCdzeicpKSB7XG5cdFx0XHRcdG5ld1VybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChuZXdVcmwsICdzeicsIHVybFBhcmFtcy5zeik7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHBhZ2UudmFyaWFudEludmVudG9yeU1lc3NhZ2luZ1VybCA9IG5ld1VybDtcblx0XHR9XG5cdFx0IFxuXHRcdHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nICYmIGNhbGxiYWNrKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRVcmxQYXJhbXModXJsKSB7XG5cdHZhciB2YXJzID0ge307XG5cblx0dmFyIHBhcnRzID0gdXJsLnJlcGxhY2UoL1s/Jl0rKFtePSZdKyk9KFteJl0qKS9naSwgZnVuY3Rpb24obSwga2V5LCB2YWx1ZSkge1xuXHRcdHZhcnNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuXG5cdHJldHVybiB2YXJzO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplVGh1bWJEYXRhTGF5ZXIodXJsKSB7XG5cdHZhciBkYXRhID0ge307XG5cdFxuXHR2YXIgY3VycmVudENhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0aWYgKGN1cnJlbnRDYXRlZ29yeUlkICYmIGN1cnJlbnRDYXRlZ29yeUlkICE9ICdudWxsJykge1xuXHRcdGRhdGEuY2dpZCA9IGN1cnJlbnRDYXRlZ29yeUlkO1xuXHR9XG5cdFxuXHRpZiAoZ2V0VXJsUGFyYW1zKHVybClbJ3N6J10pIHtcblx0XHRkYXRhLnN6ID0gZ2V0VXJsUGFyYW1zKHVybClbJ3N6J107XG5cdH1cblx0XG5cdGlmIChnZXRVcmxQYXJhbXModXJsKVsnc3RhcnQnXSkge1xuXHRcdGRhdGEuc3RhcnQgPSBnZXRVcmxQYXJhbXModXJsKVsnc3RhcnQnXTtcblx0fVxuXHRcblx0aWYgKGdldFVybFBhcmFtcyh1cmwpWydxJ10pIHtcblx0XHRkYXRhLnEgPSBkZWNvZGVVUklDb21wb25lbnQoZ2V0VXJsUGFyYW1zKHVybClbJ3EnXSk7XG5cdH1cblx0XG5cdGlmIChnZXRVcmxQYXJhbXModXJsKVsnc3J1bGUnXSkge1xuXHRcdGRhdGEuc3J1bGUgPSBkZWNvZGVVUklDb21wb25lbnQoZ2V0VXJsUGFyYW1zKHVybClbJ3NydWxlJ10pO1xuXHR9XG5cdFxuXHRmb3IgKHZhciBwcmVmZXJlbmNlSW5kZXggPSAxOyBwcmVmZXJlbmNlSW5kZXggPCA5OyBwcmVmZXJlbmNlSW5kZXgrKykge1xuXHRcdGlmIChnZXRVcmxQYXJhbXModXJsKVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSkge1xuXHRcdFx0ZGF0YVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSA9IGRlY29kZVVSSUNvbXBvbmVudChnZXRVcmxQYXJhbXModXJsKVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChnZXRVcmxQYXJhbXModXJsKVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSkge1xuXHRcdFx0ZGF0YVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSA9IGRlY29kZVVSSUNvbXBvbmVudChnZXRVcmxQYXJhbXModXJsKVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSk7XG5cdFx0fVxuXHR9XG5cdFxuXHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JQYWdlKHBhZ2VDb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gZmlsdGVyUmVmaW5lbWVudHMoY29udGFpbmVyLCBmaWx0ZXJUZXh0KSB7XG5cdGNvbnRhaW5lci5maW5kKCcuY2hlY2tzIGxhYmVsJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJGZpbHRlciA9ICQodGhpcyk7XG5cdFx0aWYgKGZpbHRlclRleHQgPT09IFwiXCIpIHtcblx0XHRcdC8vIFJlc2V0IGZpbHRlclxuXHRcdFx0JGZpbHRlci5wYXJlbnQoKS5zaG93KCk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0dmFyIGxhYmVsVGV4dCA9ICRmaWx0ZXIuaHRtbCgpLnRyaW0oKS50b1VwcGVyQ2FzZSgpO1xuXHRcdFx0aWYgKGxhYmVsVGV4dC5pbmRleE9mKGZpbHRlclRleHQpID4gLTEpIHtcblx0XHRcdFx0JGZpbHRlci5wYXJlbnQoKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0JGZpbHRlci5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIGZvbGxvd2luZyBzZWFyY2ggcmVmaW5lbWVudCBjb250cm9sczo8YnIvPlxuICogPHA+c2Nyb2xsIGJhcjwvcD5cbiAqIDxwPnNlY3Rpb24gZHJvcGRvd25zPC9wPlxuICogPHA+cmFuZ2Ugc2xpZGVyPC9wPlxuICogPHA+dGV4dGJveCBmaWx0ZXI8L3A+XG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVSZWZpbmVtZW50Q29udHJvbHMoKSB7XG5cdGlmICgkKCcucmVmaW5lbWVudHMgLnJlZmluZW1lbnQ6dmlzaWJsZScpLmxlbmd0aCA+IDIpIHtcblx0XHQkKCcucmVmaW5lbWVudHMgLnNob3ctYWxsLXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHR9XG5cdFxuXHRpZiAoJCgnLnJlZmluZW1lbnQgaW5wdXQ6Y2hlY2tlZCwgLnJlZmluZW1lbnQgW3JlZmluZW1lbnQtdmFsdWVdLm1vZGlmaWVkOm5vdCg6Y2hlY2tlZCknKS5sZW5ndGggPiAwKSB7XG5cdFx0JCgnLnJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ3JlZmluZW1lbnRzLWFwcGxpZWQnKTtcblx0fVxuXHRcblx0Ly8gaGFuZGxlIHRvZ2dsZSByZWZpbmVtZW50IGJsb2Nrc1xuXHQkKCcucmVmaW5lbWVudDpub3QoLmRpc2FibGVkKSAudG9nZ2xlJykub2ZmKCdjbGljaycpO1xuXHQkKCcucmVmaW5lbWVudDpub3QoLmRpc2FibGVkKSAudG9nZ2xlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHJlZmluZW1lbnRCb2R5ID0gJHRoaXMucGFyZW50KCkuZmluZCgnLnJlZmluZW1lbnQtYm9keScpO1xuXG5cdFx0aWYgKCEkdGhpcy5oYXNDbGFzcygnZXhwYW5kZWQnKSkge1xuXHRcdFx0JHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKS5hZGRDbGFzcygnZXhwYW5kZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKS5yZW1vdmVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRcdFxuXHRcdH1cblx0XHQkdGhpcy50b2dnbGVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRpZiAoJHRoaXMuaGFzQ2xhc3MoJ2V4cGFuZGVkJykpIHtcblx0XHQgICAgJHJlZmluZW1lbnRCb2R5LnN0b3AoKS5zaG93KCk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHQkcmVmaW5lbWVudEJvZHkuc3RvcCgpLmhpZGUoKTtcbiAgICAgICAgfVxuXHRcdFxuXHRcdGlmICgkKCcucmVmaW5lbWVudC5leHBhbmRlZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJy5yZWZpbmVtZW50cycpLmFkZENsYXNzKCdyZWZpbmVtZW50LWV4cGFuZGVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5yZWZpbmVtZW50cycpLnJlbW92ZUNsYXNzKCdyZWZpbmVtZW50LWV4cGFuZGVkJyk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICgkdGhpcy5jbG9zZXN0KCcuc2hvdy1hbGwtcmVmaW5lbWVudHMnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkdGhpcy5wYXJlbnQoKS50b2dnbGVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRzYXZlRXhwYW5kZWRSZWZpbmVtZW50cygpO1xuXHRcdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHR1cGRhdGVTZWxlY3RlZFJlZmluZW1lbnRzKCk7XG5cdFx0fVxuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1N0aWNreVJlZmluZW1lbnRzLlJlZnJlc2gnKTtcblx0XHRcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgY3NzQ2xhc3MgPSAkdGhpcy5wYXJlbnQoKS5hdHRyKCdjbGFzcycpO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRHcm91cCA9ICQudHJpbShjc3NDbGFzcy5yZXBsYWNlKC9yZWZpbmVtZW50LywgJycpKTtcblx0XHRcdHJlZkdyb3Vwc1N0YXRlcy5zYXZlU3RhdGUocmVmaW5lbWVudEdyb3VwLCAkdGhpcy5oYXNDbGFzcygnZXhwYW5kZWQnKSk7XG5cdFx0fS5iaW5kKHRoaXMpLCAzMCk7XG5cdH0pO1xuXG5cdCQoJy5yZWZpbmVtZW50IC5mb3JtLXJvdyBpbnB1dFt0eXBlPXRleHRdJykub24oJ2lucHV0JywgZnVuY3Rpb24oKSB7XG5cdFx0dmFyICRpbnB1dCA9ICQodGhpcyk7XG5cblx0ICAgIHdpbmRvdy5jbGVhclRpbWVvdXQoJGlucHV0LmRhdGEoXCJ0aW1lb3V0XCIpKTtcblx0ICAgICRpbnB1dC5kYXRhKFwidGltZW91dFwiLCBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0ICAgIFx0ZmlsdGVyUmVmaW5lbWVudHMoJGlucHV0LnBhcmVudHMoJy5yZWZpbmVtZW50JykuZmlyc3QoKSwgJGlucHV0LnZhbCgpLnRyaW0oKS50b1VwcGVyQ2FzZSgpKTtcblx0ICAgIH0sIDEwMDApKTtcblx0fSk7XG5cblx0cHJpY2VTbGlkZXIoKTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZXZlbnRzIGZvciB0aGUgZm9sbG93aW5nIGVsZW1lbnRzOjxici8+XG4gKiA8cD5yZWZpbmVtZW50IGJsb2NrczwvcD5cbiAqIDxwPnVwZGF0aW5nIGdyaWQ6IHJlZmluZW1lbnRzLCBwYWdpbmF0aW9uLCBicmVhZGNydW1iPC9wPlxuICogPHA+aXRlbSBjbGljazwvcD5cbiAqIDxwPnNvcnRpbmcgY2hhbmdlczwvcD5cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcblx0Lypcblx0ICogQWRkZWQgYSBKUyBmb3Igc2VhcmNoIHJlc3VsdCBwYWdlIHRvIHByZXZlbnQgcmVmaW5lbWVudCBmcm9tIGhhdmluZyBhIG1hcmdpbi10b3AgZXZlbiB0aGUgaGVhZGVyIGlzIG5vdCBzaG93aW5nXG5cdCAqL1xuXHRpZiAoKG9wdGlvbnMuUmVmaW5lbWVudHNVSVZlcnNpb24gIT0gUmVmaW5lbWVudFVJVmVyc2lvbkNvbnN0YW50cy5VcGRhdGVkKSAmJiB3aW5kb3cuaW5uZXJXaWR0aCA8IDc2Nykge1xuXHRcdGlmKCQoXCIuc2VhcmNoLXBocmFzZS1jb250YWluZXJcIikubGVuZ3RoKSB7XG5cdFx0XHQkKCcucHRfcHJvZHVjdC1zZWFyY2gtcmVzdWx0ICNzZWNvbmRhcnkgLnJlZmluZW1lbnRzLWlubmVyJykuY3NzKHsnbWFyZ2luLXRvcCc6ICc2MHB4J30pO1xuXHRcdH1cblx0fVxuXG5cdCQod2luZG93KS5vbigncmVzaXplJywgZnVuY3Rpb24oKSB7XG5cdFx0aWYgKChvcHRpb25zLlJlZmluZW1lbnRzVUlWZXJzaW9uID09IFJlZmluZW1lbnRVSVZlcnNpb25Db25zdGFudHMuVXBkYXRlZCkgJiYgd2luZG93LmlubmVyV2lkdGggPiA3NjcpIHtcblx0XHRcdCQoJy5tb2RpZmllZCcpLnJlbW92ZUNsYXNzKCdtb2RpZmllZCcpLnByb3AoJ2NoZWNrZWQnLCAhJCgnLm1vZGlmaWVkJykucHJvcCgnY2hlY2tlZCcpKTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCQoXCJib2R5XCIpLmRlbGVnYXRlKFwiLnByb2R1Y3Qtc3dhdGNoZXMtYWxsXCIsIFwiY2xpY2tcIiwgZnVuY3Rpb24oKSB7XG5cdFx0XHQkKHRoaXMpLnBhcmVudCgpLmZpbmQoXCIuc3dhdGNoLWxpc3QgbGlcIikucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcblx0XHR9KTtcblxuXHRcdHByZXZpb3VzU29ydEFwcGxpZWQgPSAkKCcjZ3JpZC1zb3J0LWhlYWRlcicpLmZpbmQoJ29wdGlvbjpzZWxlY3RlZCcpLnRleHQoKTtcblx0fSk7XG5cblx0dmFyICRtYWluID0gJCgnI21haW4nKTtcbiAgICAvLyBjb21wYXJlIGNoZWNrZWRcbiAgICAkbWFpbi5vbignY2xpY2snLCAnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdLmNvbXBhcmUtY2hlY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYiA9ICQodGhpcyk7XG4gICAgICAgIHZhciB0aWxlID0gY2IuY2xvc2VzdCgnLnByb2R1Y3QtdGlsZScpO1xuXG4gICAgICAgIHZhciBmdW5jID0gdGhpcy5jaGVja2VkID8gY29tcGFyZVdpZGdldC5hZGRQcm9kdWN0IDogY29tcGFyZVdpZGdldC5yZW1vdmVQcm9kdWN0O1xuICAgICAgICB2YXIgaXRlbUltZyA9IHRpbGUuZmluZCgnLnByb2R1Y3QtaW1hZ2UgYSBpbWcnKS5maXJzdCgpO1xuICAgICAgICBmdW5jKHtcbiAgICAgICAgICAgIGl0ZW1pZDogdGlsZS5kYXRhKCdpdGVtaWQnKSxcbiAgICAgICAgICAgIHV1aWQ6IHRpbGVbMF0uaWQsXG4gICAgICAgICAgICBpbWc6IGl0ZW1JbWcsXG4gICAgICAgICAgICBjYjogY2JcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlRvZ2dsZS5SZWZpbmVtZW50cycpLm9uKCdjbGljay5Ub2dnbGUuUmVmaW5lbWVudHMnLCAnLnRvZ2dsZS1yZWZpbmVtZW50cycsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHRpZiAoISQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXInKS5oYXNDbGFzcygnb3BlbicpKSB7XG5cdCAgICAgXHQkKCcucmVmaW5lbWVudHMtaW5uZXItY29udGFpbmVyJykuZmluZCgnLnRvZ2dsZS5leHBhbmRlZCwgLnRvZ2dsZS5zZWxlY3RlZCwgLnJlZmluZW1lbnQuZXhwYW5kZWQnKS5yZW1vdmVDbGFzcygnZXhwYW5kZWQgc2VsZWN0ZWQnKTtcblx0ICAgICBcdCQoJy5yZWZpbmVtZW50cycpLnJlbW92ZUNsYXNzKCdyZWZpbmVtZW50LWV4cGFuZGVkJyk7XG5cdCAgICAgXHQkKCcucmVmaW5lbWVudC1ib2R5JykuaGlkZSgpO1xuICAgIFx0fVxuICAgIFx0XG4gICAgXHR0b2dnbGVCb2R5U2Nyb2xsTG9jaygpO1xuICAgIFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lcicpLnRvZ2dsZUNsYXNzKCdvcGVuJyk7XG4gICAgXHRyZWRyYXdVcGRhdGVkUmVmaW5lbWVudEhhbmRsaW5nKCk7XG4gICAgfSk7XG4gICAgXG4gICAgJG1haW4ub2ZmKCdjbGljay5Ub2dnbGUuU29ydGluZycpLm9uKCdjbGljay5Ub2dnbGUuU29ydGluZycsICcudG9nZ2xlLXNvcnQnLCBmdW5jdGlvbihldmVudCkge1xuICAgIFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFxuXHRcdCQoJy5zb3J0LWJ5Lm1vZGFsJykudG9nZ2xlKCk7XG5cdFx0JCgnLnNvcnQtYnkubW9kYWwnKS50b2dnbGVDbGFzcygnb3BlbicpO1xuXHRcdCQoJyNzZWFyY2gtcmVzdWx0JykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFxuICAgIH0pO1xuICAgIFxuICAgICRtYWluLm9mZignY2xpY2suU2VsZWN0LlNvcnRpbmcnKS5vbignY2xpY2suU2VsZWN0LlNvcnRpbmcnLCAnLnNvcnQtYnkubW9kYWwgaW5wdXQnLCBmdW5jdGlvbihldmVudCkge1xuICAgIFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgXHRcbiAgICBcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0JCgnLnNvcnQtYnkubW9kYWwnKS50b2dnbGUoKTtcblx0XHQkKCcuc29ydC1ieS5tb2RhbCcpLnRvZ2dsZUNsYXNzKCdvcGVuJyk7XG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZygkdGhpcy52YWwoKSk7XG4gICAgfSk7XG4gICAgXG4gICAgLy8gaGFuZGxlIGV2ZW50cyBmb3IgdXBkYXRpbmcgZ3JpZFxuICAgICRtYWluLm9uKCdjbGljaycsICcucmVmaW5lbWVudHMtaGVhZCBhLCAucmVmaW5lbWVudHMtaW5uZXIgYSwgLnBhZ2luYXRpb24tYmFyIGEsIC5icmVhZGNydW1iLXJlZmluZW1lbnQtdmFsdWUgYScsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblxuICAgIFx0aWYgKCEkdGhpcy5oYXNDbGFzcygncmVmLWZpbHRlcicpICYmIGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG4gICAgXHRcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9ICR0aGlzLmF0dHIoJ3ZhbHVlJyk7XG4gICAgXHRcdFxuICAgIFx0XHQkdGhpcy5jbG9zZXN0KCcucmVmaW5lbWVudC1ib2R5LWlubmVyJykuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZT1cIicgKyByZWZpbmVtZW50VmFsdWUgKyAnXCJdLCBhW3ZhbHVlPVwiJyArIHJlZmluZW1lbnRWYWx1ZSArICdcIl0nKS50b2dnbGVDbGFzcygnbW9kaWZpZWQnKTtcbiAgICBcdFx0cmVkcmF3VXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpO1xuICAgIFx0XHRyZXR1cm47XHRcbiAgICBcdH1cbiAgICBcdFxuICAgICAgICAvLyBkb24ndCBpbnRlcmNlcHQgZm9yIGNhdGVnb3J5IGFuZCBmb2xkZXIgcmVmaW5lbWVudHMsIGFzIHdlbGwgYXMgdW5zZWxlY3RhYmxlXG4gICAgICAgIGlmICgkdGhpcy5wYXJlbnRzKCcuY2F0ZWdvcnktcmVmaW5lbWVudCcpLmxlbmd0aCA+IDAgfHwgJHRoaXMucGFyZW50cygnLmZvbGRlci1yZWZpbmVtZW50JykubGVuZ3RoID4gMCB8fCAkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygndW5zZWxlY3RhYmxlJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgYWN0aXZlUmVmaW5lbWVudHNDb3VudCA9ICQoJ1tyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxlbmd0aCAtICQoJy5zd2F0Y2hlc1tjbGFzcyo9XCJwb3B1bGFyLVwiXSBbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0aWYgKCR0aGlzLnBhcmVudCgpLmhhc0NsYXNzKCdzZWxlY3RlZCcpICYmIGFjdGl2ZVJlZmluZW1lbnRzQ291bnQgPT0gMSAmJiBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50ICYmIG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQuVXJsKSB7XG5cdFx0XHRsb2NhdGlvbi5ocmVmID0gb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudC5Vcmw7XG4gICAgXHRcdHJldHVybjtcblx0XHR9XG5cbiAgICAgICAgaWYgKCR0aGlzLmhhc0NsYXNzKCdicmVhZGNydW1iLWVsZW1lbnQnKSAmJiAkdGhpcy5hdHRyKCdocmVmJykgIT0gbnVsbCkge1xuICAgIFx0XHRsb2NhdGlvbi5ocmVmID0gdGhpcy5ocmVmO1xuICAgIFx0XHRyZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBoaWRlIG9yIHNob3cvZXhwYW5kIGFsbCByZWZpbmVtZW50IGl0ZW1zXG4gICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygncmVmLWZpbHRlcicpKSB7XG4gICAgICAgIFx0dmFyIHJlZiA9ICcuJyArICQodGhpcykuZGF0YSgncmVmJyk7XG4gICAgICAgIFx0JChyZWYpLmZpbmQoJy50b2dnbGVhYmxlJykudG9nZ2xlQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICBcdGlmICgkdGhpcy5oYXNDbGFzcygnbW9yZS1saW5rJykpIHtcbiAgICAgICAgXHRcdCR0aGlzLnBhcmVudHMoJ2xpJykuaGlkZSgpLmNsb3Nlc3QoJy5yZWZpbmVtZW50JykuYWRkQ2xhc3MoJ21vcmUtZXhwYW5kZWQnKTtcbiAgICAgICAgXHR9IGVsc2Uge1xuICAgICAgICBcdFx0JChyZWYpLmZpbmQoJy5tb3JlLWxpbmsnKS5wYXJlbnRzKCdsaScpLnNob3coKS5jbG9zZXN0KCcucmVmaW5lbWVudCcpLnJlbW92ZUNsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG4gICAgICAgIFx0fVxuXHRcdFx0c2F2ZUV4cGFuZGVkUmVmaW5lbWVudHMoKTtcbiAgICAgICAgXHRyZXR1cm47XG4gICAgICAgIH1cblxuXHRcdGlmICgkdGhpcy5sZW5ndGggPiAwICYmICEkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cdFx0fVxuXG5cdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5HQV9ORVdfQUNUSU9OU19FTkFCTEVEKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudElkID0gJHRoaXMuY2xvc2VzdCgnW3JlZmluZW1lbnQtaWRdJykuYXR0cigncmVmaW5lbWVudC1pZCcpIHx8IG51bGw7XG5cdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gJHRoaXMuYXR0cigndmFsdWUnKSA/ICR0aGlzLmF0dHIoJ3ZhbHVlJykucmVwbGFjZSgnXCInLFwiIElOQ0hcIikgOiBudWxsO1xuXHRcdFx0aWYgKHJlZmluZW1lbnRJZCAmJiByZWZpbmVtZW50VmFsdWUpIHtcblx0XHRcdFx0dmFyIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSA9ICB7IFxuXHRcdFx0XHRcdCdhY3Rpb25fbmFtZSc6ICdmaWx0ZXInLFxuXHRcdFx0XHRcdCdhY3Rpb25fcGFnZV90eXBlJzogJ3BscCcsXG5cdFx0XHRcdFx0J2FjdGlvbl92YWx1ZSc6IHJlZmluZW1lbnRJZCwgXG5cdFx0XHRcdFx0J2FjdGlvbl9pdGVtcyc6IHJlZmluZW1lbnRWYWx1ZVxuXHRcdFx0XHR9O1xuXHRcdFx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdFdmVudCcsIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSk7XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHRoaXMuaHJlZik7XG5cblx0XHR2YXIgc2VsZWN0aW9uID0gJCgnZGl2LnByb2R1Y3Qtc2VsZWN0aW9ucyB1bCBsaScpO1xuXHRcdHZhciByZWZHcm91cCA9ICQoc2VsZWN0aW9uW3NlbGVjdGlvbi5sZW5ndGgtMl0pLmZpbmQoJ3NwYW46Zmlyc3QnKS5kYXRhKCdyZWZncm91cC1pZCcpO1xuXHRcdGlmIChyZWZHcm91cCAmJiByZWZHcm91cC5sZW5ndGggPiAwICYmIHJlZkdyb3Vwc1N0YXRlcy5jaGVja1N0YXRlKHJlZkdyb3VwKSkge1xuXHRcdFx0JCgnI3JlZmluZW1lbnRzLWlubmVyIC5yZWZpbmVtZW50LicrcmVmR3JvdXArJyAudG9nZ2xlJylbMF0uY2xpY2soKTtcblx0XHR9XG4gICAgfSk7XG5cbiAgICAvLyBoYW5kbGUgZXZlbnRzIGl0ZW0gY2xpY2suIGFwcGVuZCBwYXJhbXMuXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5wcm9kdWN0LXRpbGUgYTpub3QoXCIjcXVpY2t2aWV3YnV0dG9uXCIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYSA9ICQodGhpcyk7XG4gICAgICAgIC8vIGdldCBjdXJyZW50IHBhZ2UgcmVmaW5lbWVudCB2YWx1ZXNcbiAgICAgICAgdmFyIHdsID0gd2luZG93LmxvY2F0aW9uO1xuXG4gICAgICAgIHZhciBxc1BhcmFtcyA9ICh3bC5zZWFyY2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLnNlYXJjaC5zdWJzdHIoMSkpIDoge307XG4gICAgICAgIHZhciBoYXNoUGFyYW1zID0gKHdsLmhhc2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLmhhc2guc3Vic3RyKDEpKSA6IHt9O1xuXG4gICAgICAgIC8vIG1lcmdlIGhhc2ggcGFyYW1zIHdpdGggcXVlcnlzdHJpbmcgcGFyYW1zXG4gICAgICAgIHZhciBwYXJhbXMgPSAkLmV4dGVuZChoYXNoUGFyYW1zLCBxc1BhcmFtcyk7XG4gICAgICAgIGlmICghcGFyYW1zLnN0YXJ0KSB7XG4gICAgICAgICAgICBwYXJhbXMuc3RhcnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGdldCB0aGUgaW5kZXggb2YgdGhlIHNlbGVjdGVkIGl0ZW0gYW5kIHNhdmUgYXMgc3RhcnQgcGFyYW1ldGVyXG4gICAgICAgIHZhciB0aWxlID0gYS5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIHZhciBpZHggPSB0aWxlLmRhdGEoJ2lkeCcpID8gKyB0aWxlLmRhdGEoJ2lkeCcpIDogMDtcblxuICAgICAgICAvLyBjb252ZXJ0IHBhcmFtcy5zdGFydCB0byBpbnRlZ2VyIGFuZCBhZGQgaW5kZXhcbiAgICAgICAgcGFyYW1zLnN0YXJ0ID0gKCtwYXJhbXMuc3RhcnQpICsgKGlkeCArIDEpO1xuICAgICAgICAvLyBzZXQgdGhlIGhhc2ggYW5kIGFsbG93IG5vcm1hbCBhY3Rpb24gdG8gY29udGludWVcbiAgICAgICAgYVswXS5oYXNoID0gJC5wYXJhbShwYXJhbXMpO1xuICAgIH0pO1xuXG4gICAgLy8gaGFuZGxlIHNvcnRpbmcgY2hhbmdlXG4gICAgJG1haW4ub24oJ2NoYW5nZScsICcuc29ydC1ieSBzZWxlY3QnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIFxuXHRcdGlmICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdHZhciBpc1NvcnRpbmdDaGFuZ2VkID0gZmFsc2U7XG5cdFx0XHR2YXIgJHNvcnRpbmdSdWxlID0gJCgnLm1vZGFsLm9wZW4gLnNvcnQtYnkgb3B0aW9uOmNoZWNrZWQnKTtcblx0XHRcdGlmICgkc29ydGluZ1J1bGUgJiYgJHNvcnRpbmdSdWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0aXNTb3J0aW5nQ2hhbmdlZCA9ICEkc29ydGluZ1J1bGUuYXR0cignc2VsZWN0ZWQnKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGlzU29ydGluZ0NoYW5nZWQgfHwgJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdLm1vZGlmaWVkLCAubGlzdC1zZWxlY3Rpb25zIC52YWx1ZS5wZW5kaW5nLWNsZWFyJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkcmVmaW5lbWVudHNJbm5lci5hZGRDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkcmVmaW5lbWVudHNJbm5lci5yZW1vdmVDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XHRcdFxuXHRcdFx0dmFyIHNlbGVjdGVkU29ydCA9ICQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCk7XG5cblx0XHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuR0FfTkVXX0FDVElPTlNfRU5BQkxFRCkge1xuXHRcdFx0XHR2YXIgbmV3U29ydFZhbHVlID0gJCh0aGlzKS5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS50ZXh0KCk7XG5cdFx0XHRcdHZhciBvbGRTb3J0VmFsdWUgPSBwcmV2aW91c1NvcnRBcHBsaWVkID8gcHJldmlvdXNTb3J0QXBwbGllZCA6ICdUb3AgU2VsbGVycyc7XG5cdFx0XHRcdGlmIChuZXdTb3J0VmFsdWUgJiYgb2xkU29ydFZhbHVlKSB7XG5cdFx0XHRcdFx0dmFyIHNvcnRBbmFseXRpY3NUYWdnaW5nRGF0YSA9ICB7IFxuXHRcdFx0XHRcdFx0J2FjdGlvbl9uYW1lJzogJ3NvcnQnLFxuXHRcdFx0XHRcdFx0J2FjdGlvbl9wYWdlX3R5cGUnOiAncGxwJyxcblx0XHRcdFx0XHRcdCdhY3Rpb25fdmFsdWUnOiBuZXdTb3J0VmFsdWUsIFxuXHRcdFx0XHRcdFx0J2FjdGlvbl9pdGVtcyc6ICdmcm9tICcgKyBvbGRTb3J0VmFsdWVcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0V2ZW50Jywgc29ydEFuYWx5dGljc1RhZ2dpbmdEYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRwcmV2aW91c1NvcnRBcHBsaWVkID0gbmV3U29ydFZhbHVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoJCh0aGlzKS5hdHRyKCdpZCcpID09ICdtb2JpbGUtc29ydCcpe1xuXHRcdFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZyhzZWxlY3RlZFNvcnQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG5cdFx0XHRcdFx0dXBkYXRlUHJvZHVjdExpc3Rpbmcoc2VsZWN0ZWRTb3J0KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gc2VsZWN0ZWRTb3J0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuICAgIH0pO1xuXG5cdCQoJy5zZWFyY2gtcmVzdWx0LXBhZ2UnKS5vbignY2xpY2snLCAnI2dyaWQtc29ydC1oZWFkZXItbWVudSBsaScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcuc29ydC1ieSBzZWxlY3QnKS5wcm9wKCdzZWxlY3RlZEluZGV4JywgJCh0aGlzKS5pbmRleCgpKS5maXJzdCgpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9KTtcblxuICAgICRtYWluLm9uKCdjaGFuZ2UnLCAnLml0ZW1zLXBlci1wYWdlIHNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlZmluZVVybCA9ICQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCk7XG4gICAgICAgIGlmIChyZWZpbmVVcmwgPT09ICdJTkZJTklURV9TQ1JPTEwnKSB7XG4gICAgICAgICAgICAkKCdodG1sJykuYWRkQ2xhc3MoJ2luZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJCgnaHRtbCcpLmFkZENsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdpbmZpbml0ZS1zY3JvbGwnKTtcbiAgICAgICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHJlZmluZVVybCk7XG4gICAgICAgIH1cblx0fSk7XG5cblx0JG1haW4ub24oJ2NsaWNrJywgJy5tb2JpbGUtcmVmaW5lbWVudHMgLnRvZ2dsZS1idXR0b24nLCBmdW5jdGlvbigpIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgJiYgb3B0aW9ucy5SZWZpbmVtZW50c1VJVmVyc2lvbiAhPSBSZWZpbmVtZW50VUlWZXJzaW9uQ29uc3RhbnRzLlVwZGF0ZWQpIHtcblx0XHRcdGlmICgkKHRoaXMpLmhhc0NsYXNzKCdzb3J0LWJ5LXRvZ2dsZScpKSB7XG5cdFx0XHRcdFxuXHRcdFx0XHQvL0Vuc3VyZSBib3RoIHNvcnQtYnkgYW5kIHJlZmluZW1lbnRzIGFyZW4ndCBvcGVuIHNpbXVsdGFuZW91c2x5IFxuXHRcdFx0XHQkKCcjc2Vjb25kYXJ5LnJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCcubW9iaWxlLXJlZmluZW1lbnRzIC5yZWZpbmUtdG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXG5cdFx0XHRcdC8vY29udGFpbmVyIGZvciBuZXcgc29ydGluZyBvcHRpb25zXG5cdFx0XHRcdHZhciBzb3J0QnlPcHRpb25zQ29udGFpbmVyID0gJCgnLm1vYmlsZS1yZWZpbmVtZW50cyAuc29ydC1ieS1vcHRpb25zJyk7XG5cdFx0XHRcdGlmKHNvcnRCeU9wdGlvbnNDb250YWluZXIuaHRtbCgpLmxlbmd0aCA8IDEpIHtcblxuXHRcdFx0XHRcdC8vc29ydC1ieSBmb3JtIGZvciByZWZlcmVuY2UgYW5kIHB1bGxpbmcgb3B0aW9uc1xuXHRcdFx0XHRcdHZhciBjdXJyZW50U29ydEJ5T3B0aW9ucyA9ICQoJy5tb2JpbGUtcmVmaW5lbWVudHMgI3NvcnQtYnkgI2dyaWQtc29ydC1oZWFkZXIgb3B0aW9uJyk7XG5cblx0XHRcdFx0XHRzb3J0QnlPcHRpb25zQ29udGFpbmVyLmFwcGVuZChcIjx1bCBjbGFzcz0nc29ydC1ieS1saXN0Jz48L3VsPlwiKTtcblxuXHRcdFx0XHRcdC8vY3JlYXRlIG5ldyBsaXN0IHdpdGggZGF0YSBsaW5rZWQgdG8gZm9ybVxuXHRcdFx0XHRcdGN1cnJlbnRTb3J0QnlPcHRpb25zLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRWYWx1ZSA9ICQodGhpcykucHJvcCgnc2VsZWN0ZWQnKTtcblxuXHRcdFx0XHRcdFx0aWYgKHR5cGVvZiBzZWxlY3RlZFZhbHVlICE9PSB0eXBlb2YgdW5kZWZpbmVkICYmIHNlbGVjdGVkVmFsdWUgIT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBuZXdPcHRpb24gPSAnPGxpIGNsYXNzPVwic2VsZWN0YWJsZS1vcHRpb24gc2VsZWN0ZWRcIiBkYXRhLW9wdGlvbi1mb3I9XCInICArICQodGhpcykuYXR0cigndmFsdWUnKSArICdcIj4nICsgJCh0aGlzKS50ZXh0KCkgKyAnPC9saT4nO1xuXHRcdFx0XHRcdFx0XHRzb3J0QnlPcHRpb25zQ29udGFpbmVyLmZpbmQoJ3VsJykuYXBwZW5kKG5ld09wdGlvbik7XG5cdFx0XHRcdFx0XHR9IGVsc2UgIHtcblx0XHRcdFx0XHRcdFx0dmFyIG5ld09wdGlvbiA9ICc8bGkgY2xhc3M9XCJzZWxlY3RhYmxlLW9wdGlvblwiIGRhdGEtb3B0aW9uLWZvcj1cIicgICsgJCh0aGlzKS5hdHRyKCd2YWx1ZScpICsgJ1wiPicgKyAkKHRoaXMpLnRleHQoKSArICc8L2xpPic7XG5cdFx0XHRcdFx0XHRcdHNvcnRCeU9wdGlvbnNDb250YWluZXIuZmluZCgndWwnKS5hcHBlbmQobmV3T3B0aW9uKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcblx0XHRcdFx0fVxuXHRcdFx0XHQvL3RvZ2dsZSBzb3J0LWJ5IG9wdGlvbnMgdG8gYWN0aXZlIHN0YXRlXG5cdFx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnktb3B0aW9ucycpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCh0aGlzKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9IGVsc2UgaWYgKCQodGhpcykuaGFzQ2xhc3MoJ3JlZmluZS10b2dnbGUnKSkge1xuXHRcdFx0XHQvL0Vuc3VyZSBib3RoIHNvcnQtYnkgYW5kIHJlZmluZW1lbnRzIGFyZW4ndCBvcGVuIHNpbXVsdGFuZW91c2x5XG5cdFx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnktb3B0aW9ucycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnLm1vYmlsZS1yZWZpbmVtZW50cyAuc29ydC1ieS10b2dnbGUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdC8vdG9nZ2xlIHJlZmluZW1lbnRzIG9wdGlvbnMgdG8gYWN0aXZlIHN0YXRlXG5cdFx0XHRcdCQoJyNzZWNvbmRhcnkucmVmaW5lbWVudHMnKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCQodGhpcykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH1cdFxuXHR9KTtcblx0JG1haW4ub24oJ2NsaWNrJywgJy5zb3J0LWJ5LW9wdGlvbnMgLnNvcnQtYnktbGlzdCAuc2VsZWN0YWJsZS1vcHRpb24nLCBmdW5jdGlvbigpIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHRcdC8vc2V0IGNvcnJlY3Qgc29ydC1ieSBmb3JtIG9wdGlvbiBhcyBzZWxlY3RlZFxuXHRcdFx0dmFyIG9wdGlvblZhbHVlID0gJCh0aGlzKS5hdHRyKCdkYXRhLW9wdGlvbi1mb3InKTtcblx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnkjc29ydC1ieSBmb3JtICNncmlkLXNvcnQtaGVhZGVyIG9wdGlvblt2YWx1ZT1cIicrb3B0aW9uVmFsdWUrJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0XHQvL1RyaWdnZXIgZm9ybSBjaGFuZ2UgdG8gZmlyZSBzb3J0LWJ5IGNoYW5nZSB3YXRjaGVyXG5cdFx0XHQkKCcubW9iaWxlLXJlZmluZW1lbnRzIC5zb3J0LWJ5I3NvcnQtYnkgZm9ybSAjZ3JpZC1zb3J0LWhlYWRlciBvcHRpb24nKS5jaGFuZ2UoKTtcblx0XHR9XG5cdH0pO1xuXG4gICAgLy8gcmVmaW5lbWVudCBjaGVja2JveGVzXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5yZWZpbmVtZW50IC5jaGVja3MgaW5wdXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkcmVmaW5lbWVudCA9ICR0aGlzLmNsb3Nlc3QoJ1tyZWZpbmVtZW50LXZhbHVlXScpO1xuXHRcdGlmICgkcmVmaW5lbWVudC5sZW5ndGggPiAwICYmICEkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cdFx0fVxuXG5cdFx0aWYgKCR0aGlzLmNsb3Nlc3QoJy5yZWZpbmVtZW50LnNvcnQtYnknKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkdGhpcy5jbG9zZXN0KCcucmVmaW5lbWVudC1ib2R5JykuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdIGlucHV0Jykubm90KCR0aGlzKS5yZW1vdmVDbGFzcygnbW9kaWZpZWQnKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0JHRoaXMudG9nZ2xlQ2xhc3MoJ21vZGlmaWVkJyk7XG5cdFx0fVxuICAgIFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gJHRoaXMudmFsKCkucmVwbGFjZSgnXCInLFwiIElOQ0hcIik7XG4gICAgXHRcdGlmICgkdGhpcy5jbG9zZXN0KCdbaXMtcHJpY2UtcmVmaW5lbWVudD1cInRydWVcIl0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCQoJ1tpcy1wcmljZS1yZWZpbmVtZW50PVwidHJ1ZVwiXSBpbnB1dCcpLm5vdCgkdGhpcykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQ2xhc3MoJ21vZGlmaWVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnRvZ2dsZUNsYXNzKCdtb2RpZmllZCcpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyICRlcXVhbFZhbHVlSW5wdXRzID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQtYm9keScpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlPVwiJyArIHJlZmluZW1lbnRWYWx1ZSArICdcIl0nKTtcblx0ICAgIFx0XHQkZXF1YWxWYWx1ZUlucHV0cy50b2dnbGVDbGFzcygnbW9kaWZpZWQnKTtcblx0ICAgIFx0XHQkZXF1YWxWYWx1ZUlucHV0cy5ub3QoJHRoaXMpLnByb3AoJ2NoZWNrZWQnLCAkdGhpcy5wcm9wKCdjaGVja2VkJykpO1xuICAgIFx0XHR9XG4gICAgXHRcdHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKTtcbiAgICBcdFx0cmV0dXJuO1x0XG4gICAgXHR9XG5cblx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLkdBX05FV19BQ1RJT05TX0VOQUJMRUQgJiYgJHRoaXMuaXMoJzpjaGVja2VkJykpIHtcblx0XHRcdHZhciByZWZpbmVtZW50SWQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC1pZF0nKS5hdHRyKCdyZWZpbmVtZW50LWlkJykgfHwgbnVsbDtcblx0XHRcdHZhciByZWZpbmVtZW50VmFsdWUgPSAkdGhpcy52YWwoKSA/ICR0aGlzLnZhbCgpLnJlcGxhY2UoJ1wiJyxcIiBJTkNIXCIpIDogbnVsbDtcblx0XHRcdGlmIChyZWZpbmVtZW50SWQgJiYgcmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHRcdHZhciByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEgPSAgeyBcblx0XHRcdFx0XHQnYWN0aW9uX25hbWUnOiAnZmlsdGVyJyxcblx0XHRcdFx0XHQnYWN0aW9uX3BhZ2VfdHlwZSc6ICdwbHAnLFxuXHRcdFx0XHRcdCdhY3Rpb25fdmFsdWUnOiByZWZpbmVtZW50SWQsIFxuXHRcdFx0XHRcdCdhY3Rpb25faXRlbXMnOiByZWZpbmVtZW50VmFsdWVcblx0XHRcdFx0fTtcblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnRXZlbnQnLCByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciB1cmwgPSAkKHRoaXMpLnBhcmVudHMoJ2xpJykuZmlyc3QoKS5maW5kKCcudmlzdWFsbHktaGlkZGVuID4gYScpLmZpcnN0KCkuYXR0cignaHJlZicpO1xuXG5cdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcodXJsKTtcbiAgICB9KTtcblxuICAgICRtYWluLm9uKCdjbGljaycsICcucmVzdWx0LW9wdGlvbnMgLnN3aXRjaCBpbnB1dFtuYW1lPVwiZmllbGQtc3dpdGNoXCJdJywgZnVuY3Rpb24gKCkge1xuICAgIFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG4gICAgXHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKCQodGhpcykucGFyZW50cygnLnN3aXRjaCcpLmZpbmQoJy52aXN1YWxseS1oaWRkZW4gaW5wdXRbbmFtZT1cImZpZWxkLXRydWVcIl0gKyBhJykuZmlyc3QoKS5hdHRyKCdocmVmJykpO1xuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0ZG9jdW1lbnQubG9jYXRpb24gPSAkKHRoaXMpLnBhcmVudHMoJy5zd2l0Y2gnKS5maW5kKCcudmlzdWFsbHktaGlkZGVuIGlucHV0W25hbWU9XCJmaWVsZC10cnVlXCJdICsgYScpLmZpcnN0KCkuYXR0cignaHJlZicpO1xuICAgIFx0fVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5saXN0LXNlbGVjdGlvbnMgbGk6bm90KC5wZW5kaW5nLXNlbGVjdGlvbnMpIGEuY2xvc2UtYnRuLCAuY2xlYXItYWxsIC5jbG9zZS1idG4nLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgIFx0aWYgKCR0aGlzLmNsb3Nlc3QoJy52YWx1ZScpLmhhc0NsYXNzKCdhcHBsaWVkJykgJiYgJHRoaXMuY2xvc2VzdCgnLm1vZGFsJykubGVuZ3RoID4gMCkge1xuICAgIFx0XHQkdGhpcy5jbG9zZXN0KCcudmFsdWUnKS50b2dnbGVDbGFzcygncGVuZGluZy1jbGVhcicpO1xuICAgIFx0XHRyZWRyYXdVcGRhdGVkUmVmaW5lbWVudEhhbmRsaW5nKCk7XG4gICAgXHRcdHJldHVybjtcdFxuICAgIFx0fVxuXG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0XHR2YXIgYWN0aXZlUmVmaW5lbWVudHNDb3VudCA9ICQoJ1tyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxlbmd0aCAtICQoJy5zd2F0Y2hlc1tjbGFzcyo9XCJwb3B1bGFyLVwiXSBbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0aWYgKGFjdGl2ZVJlZmluZW1lbnRzQ291bnQgPT0gMSAmJiBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50ICYmIG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQuVXJsKSB7XG5cdFx0XHRsb2NhdGlvbi5ocmVmID0gb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudC5Vcmw7XG4gICAgXHRcdHJldHVybjtcblx0XHR9XG5cbiAgICBcdHZhciBocmVmID0gJHRoaXMuYXR0cignaHJlZicpO1xuICAgIFx0aWYgKGhyZWYgPT0gbnVsbCB8fCBocmVmID09ICdudWxsJykge1xuICAgIFx0XHR2YXIgc2VhcmNoID0gZG9jdW1lbnQubG9jYXRpb24uc2VhcmNoO1xuICAgIFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZyhkb2N1bWVudC5sb2NhdGlvbi5wYXRobmFtZSArIHNlYXJjaC5zdWJzdHIoMCwgc2VhcmNoLmluZGV4T2YoJyYnKSkpO1xuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcoaHJlZik7XG4gICAgXHR9XG5cdH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcubGlzdC1zZWxlY3Rpb25zIGxpLnBlbmRpbmctc2VsZWN0aW9ucyBhLmNsb3NlLWJ0bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBcdHZhciBwZW5kaW5nUmVmaW5lbWVudElkID0gJCh0aGlzKS5jbG9zZXN0KCdbZGF0YS1yZWZncm91cC1pZF0nKS5hdHRyKCdkYXRhLXJlZmdyb3VwLWlkJyk7XG4gICAgXHR2YXIgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSA9ICQodGhpcykuY2xvc2VzdCgnc3BhbicpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKTtcblx0XHR2YXIgc2VsZWN0b3IgPSAnW3JlZmluZW1lbnQtaWQ9XCInICsgcGVuZGluZ1JlZmluZW1lbnRJZCArICdcIl0gdWwgW3JlZmluZW1lbnQtdmFsdWU9XCInICsgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSArICdcIl0nO1xuXG4gICAgXHR2YXIgJHBlbmRpbmdSZWZpbmVtZW50SW5wdXQgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKHNlbGVjdG9yKTsgICAgXHRcbiAgICBcdGlmICgkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdpbnB1dCcpLmxlbmd0aCA+IDApIHtcbiAgICBcdFx0JHBlbmRpbmdSZWZpbmVtZW50SW5wdXQuZmluZCgnaW5wdXQnKS5jbGljaygpO1xuICAgIFx0fSBlbHNlIGlmICgkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdhJykubGVuZ3RoID4gMCkge1xuICAgIFx0XHQkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdhJykuY2xpY2soKTtcbiAgICBcdH1cblx0fSk7XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5wcm9kdWN0LXN3YXRjaGVzLWFjY29yZGlvbi1idXR0b24nLCBmdW5jdGlvbiAoKSB7XG4gICAgXHR2YXIgJGFjY29yZGlvbiA9ICQodGhpcykuY2xvc2VzdCgnLmFjY29yZGlvbicpO1xuICAgIFx0XG4gICAgXHRpZiAoJGFjY29yZGlvbi5sZW5ndGggPiAwKSB7XG4gICAgXHRcdCRhY2NvcmRpb24udG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0fVxuICAgIH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2hvcE15U3RvcmUnLCAnLnNob3AtbXktc3RvcmUgLmNoZWNrYm94LXRvZ2dsZSBpbnB1dCcpLm9uKCdjbGljay5TaG9wTXlTdG9yZScsICcuc2hvcC1teS1zdG9yZSAuY2hlY2tib3gtdG9nZ2xlIGlucHV0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG5cdFx0dmFyIHVybDtcblx0XHRpZiAoJHRoaXMucHJvcCgnY2hlY2tlZCcpKSAge1xuXHRcdFx0dXJsID0gJHRoaXMuYXR0cignaHJlZi1yZWZpbmUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dXJsID0gJHRoaXMuYXR0cignaHJlZi1yZWxheCcpO1xuXHRcdFx0JCgnYm9keScpLmF0dHIoJ2lzLXNob3AtbXktc3RvcmUtYWN0aXZlJywgZmFsc2UpO1xuXHRcdH1cblxuXHRcdGlmICh1cmwpIHtcblx0XHRcdCQoJy5zaG9wLW15LXN0b3JlIC5jaGVja2JveC10b2dnbGUnKS5sb2FkaW5nKHsgSXNMYWJlbFNob3duOiBmYWxzZSwgSXNJbWFnZVNob3duOiBmYWxzZSB9KTtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cblx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1Nob3BZb3VyU3RvcmUnLCB7IGVuYWJsZWQ6ICR0aGlzLnByb3AoJ2NoZWNrZWQnKSB9KTtcblxuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3Nob3BteXN0b3JlJywgJHRoaXMucHJvcCgnY2hlY2tlZCcpKTtcblx0XHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuICAgIH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignU2hvcE15U3RvcmUuVXBkYXRlJykub24oJ1Nob3BNeVN0b3JlLlVwZGF0ZScsIGZ1bmN0aW9uKGV2ZW50LCBzdG9yZUlkKSB7XG5cdFx0aWYgKCQoJy5zaG9wLW15LXN0b3JlIC5jaGVja2JveC10b2dnbGUgaW5wdXQnKS5wcm9wKCdjaGVja2VkJykpIHtcblx0XHRcdHZhciB1cmwgPSBsb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyBsb2NhdGlvbi5ob3N0bmFtZSArIGxvY2F0aW9uLnBhdGhuYW1lO1xuXHRcdFx0dmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMobG9jYXRpb24uc2VhcmNoKTtcblx0XHRcdGZvciAodmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyS2V5IGluIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycykge1xuXHRcdFx0XHR2YXIgcXVlcnlTdHJpbmdQYXJhbWV0ZXJWYWx1ZSA9IHF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1txdWVyeVN0cmluZ1BhcmFtZXRlcktleV07XG5cdFx0XHRcdGlmIChxdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlICYmIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUuaW5kZXhPZignYXZhaWxhYmxlU3RvcmVzJykgPiAtMSkge1xuXHRcdFx0XHRcdHZhciByZWZpbmVtZW50SW5kZXg7XG5cdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRJbmRleE1hdGNoID0gcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXkubWF0Y2goL3ByZWZuKFswLTldKSsvKTtcblx0XHRcdFx0XHRpZiAocmVmaW5lbWVudEluZGV4TWF0Y2ggJiYgcmVmaW5lbWVudEluZGV4TWF0Y2gubGVuZ3RoID4gMSkge1xuXHRcdFx0XHRcdFx0cmVmaW5lbWVudEluZGV4ID0gcmVmaW5lbWVudEluZGV4TWF0Y2hbMV07XG5cdFx0XHRcdFx0fVx0XHRcdFx0XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHRpZiAocmVmaW5lbWVudEluZGV4ICYmIHN0b3JlSWQpIHtcblx0XHRcdFx0cXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydwcmVmdicgKyByZWZpbmVtZW50SW5kZXhdID0gc3RvcmVJZDtcblx0XHRcdH1cblx0XG5cdFx0XHRmb3IgKHZhciBxdWVyeVN0cmluZ1BhcmFtZXRlcktleSBpbiBxdWVyeVN0cmluZ1BhcmFtZXRlcnMpIHtcblx0XHRcdFx0dmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUgPSBxdWVyeVN0cmluZ1BhcmFtZXRlcnNbcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXldO1xuXHRcdFx0XHRpZiAocXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXkgIT0gJ3N0YXJ0JyAmJiBxdWVyeVN0cmluZ1BhcmFtZXRlcktleSAhPSAnc3onKSB7XG5cdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXksIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKHtcblx0XHRcdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRcdFx0Q29udGVudDogJzxoNj5Ib2xkIFlvdXIgSG9yc2VzITwvaDY+PHA+WW91ciBzZWxlY3Rpb25zIGFyZSBsb2FkaW5nLi4uPC9wPicsXG5cdFx0XHRcdENzc0NsYXNzOiAnc2hvcHlvdXJzdG9yZScsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cblx0XHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlZHJhd1Nob3BNeVN0b3JlKCk7XG5cdFx0fVxuXHR9KTtcblxuICAgIHNlYXJjaFN0b3JlcygpO1xuICAgIGluaXRpYWxpemVSZWZpbmVtZW50Q29udHJvbHMoKTtcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0JCgnI2dyaWQtc29ydC1oZWFkZXInKS5zZWxlY3RtZW51KHtcblx0XHRcdCd3aWR0aCc6IDIwNVxuXHRcdH0pO1xuXHR9XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5hcHBseS1yZWZpbmVtZW50czpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdCQodGhpcykuYXR0cignZGF0YS1hcHBseS1yZWZpbmVtZW50cycsJ3RydWUnKTtcbiAgICBcdFxuXHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudHNEZWx0YSA9ICQoJyNzZWNvbmRhcnkgW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpOm5vdChbY2xhc3MqPVwicG9wdWxhclwiXSkubW9kaWZpZWQnKS5sZW5ndGggLSAkKCcjc2Vjb25kYXJ5IFtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZDpub3QoW2NsYXNzKj1cInBvcHVsYXJcIl0pLm1vZGlmaWVkJykubGVuZ3RoO1xuXHRcdHZhciBhY3RpdmVSZWZpbmVtZW50c0NvdW50ID0gJCgnI3NlY29uZGFyeSBbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGggLSAkKCcjc2Vjb25kYXJ5IC5zd2F0Y2hlc1tjbGFzcyo9XCJwb3B1bGFyLVwiXSBbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGggLSAkKCcjc2Vjb25kYXJ5IC5saXN0LXNlbGVjdGlvbnMgLnBlbmRpbmctY2xlYXInKS5sZW5ndGggKyBwZW5kaW5nUmVmaW5lbWVudHNEZWx0YTtcblx0XHRpZiAoYWN0aXZlUmVmaW5lbWVudHNDb3VudCA9PSAwICYmIG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQgJiYgb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudC5VcmwpIHtcblx0XHRcdGxvY2F0aW9uLmhyZWYgPSBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50LlVybDtcbiAgICBcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuR0FfTkVXX0FDVElPTlNfRU5BQkxFRCkge1xuXHRcdFx0dmFyICRyZWZpbmVtZW50ID0gICQoJy5yZWZpbmVtZW50cycpLmZpbmQoJ1tyZWZpbmVtZW50LWlkXTpub3QoLnNvcnQtYnkpJyk7XG5cdFx0XHR2YXIgJHNlbGVjdGVkUmVmaW5lbWVudHMgPSAkcmVmaW5lbWVudC5maW5kKCd1bDpub3QoW2NsYXNzKj1cInBvcHVsYXJcIl0pIGxpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpLm1vZGlmaWVkLCB1bDpub3QoW2NsYXNzKj1cInBvcHVsYXJcIl0pIGxpW3JlZmluZW1lbnQtdmFsdWVdLnNlbGVjdGVkOm5vdCgubW9kaWZpZWQpJyk7XG5cdFx0XHRpZiAoJHNlbGVjdGVkUmVmaW5lbWVudHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHR2YXIgcmVmaW5lbWVudElkLCByZWZpbmVtZW50VmFsdWU7XG5cdFx0XHRcdCRzZWxlY3RlZFJlZmluZW1lbnRzLmVhY2goZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHJlZmluZW1lbnRJZCA9ICQodGhpcykuY2xvc2VzdCgnW3JlZmluZW1lbnQtaWRdJykuYXR0cigncmVmaW5lbWVudC1pZCcpO1xuXHRcdFx0XHRcdHJlZmluZW1lbnRWYWx1ZSA9IHJlZmluZW1lbnRJZC50b1VwcGVyQ2FzZSgpID09ICdQUklDRScgPyAkKHRoaXMpLmZpbmQoJy5yZWZpbmVtZW50LWxhYmVsJykudGV4dCgpLnJlcGxhY2UoL1xccysvZywgJyAnKS50cmltKCkgOiAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKS5yZXBsYWNlKCcgSU5DSCcsJ1wiJyk7XG5cdFx0XHRcdFx0aWYgKHJlZmluZW1lbnRJZCAmJiByZWZpbmVtZW50VmFsdWUpIHtcblx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEgPSAgeyBcblx0XHRcdFx0XHRcdFx0J2FjdGlvbl9uYW1lJzogJ2ZpbHRlcicsXG5cdFx0XHRcdFx0XHRcdCdhY3Rpb25fcGFnZV90eXBlJzogJ3BscCcsXG5cdFx0XHRcdFx0XHRcdCdhY3Rpb25fdmFsdWUnOiByZWZpbmVtZW50SWQsIFxuXHRcdFx0XHRcdFx0XHQnYWN0aW9uX2l0ZW1zJzogcmVmaW5lbWVudFZhbHVlXG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnRXZlbnQnLCByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XHRcblx0XHRcdFxuXHRcdFx0Ly8gVGhlIG5ld1NvcnRWYWx1ZSB3aWxsIG9ubHkgYmUgcG9wdWxhdGVkIGlmIGEgY2hhbmdlIHRvIHNvcnQgaGFzIG9jY3VycmVkLCBhbmQgR0EgdGFnZ2luZyBvbmx5IGdldHMgZmlyZWQgaWYgbmV3U29ydFZhbHVlIGhhcyBkYXRhXG5cdFx0XHR2YXIgbmV3U29ydFZhbHVlID0gJCgnI21vYmlsZS1zb3J0IG9wdGlvbjpjaGVja2VkJykubGVuZ3RoID4gMCA/ICQoJyNtb2JpbGUtc29ydCBvcHRpb246Y2hlY2tlZCcpWzBdLmxhYmVsIDogbnVsbDtcblx0XHRcdHZhciBvbGRTb3J0VmFsdWUgPSBwcmV2aW91c1NvcnRBcHBsaWVkID8gcHJldmlvdXNTb3J0QXBwbGllZCA6ICdUb3AgU2VsbGVycyc7XG5cdFx0XHRpZiAobmV3U29ydFZhbHVlICYmIG9sZFNvcnRWYWx1ZSkge1xuXHRcdFx0XHR2YXIgc29ydEFuYWx5dGljc1RhZ2dpbmdEYXRhID0gIHsgXG5cdFx0XHRcdFx0J2FjdGlvbl9uYW1lJzogJ3NvcnQnLFxuXHRcdFx0XHRcdCdhY3Rpb25fcGFnZV90eXBlJzogJ3BscCcsXG5cdFx0XHRcdFx0J2FjdGlvbl92YWx1ZSc6IG5ld1NvcnRWYWx1ZSwgXG5cdFx0XHRcdFx0J2FjdGlvbl9pdGVtcyc6ICdmcm9tICcgKyBvbGRTb3J0VmFsdWVcblx0XHRcdFx0fTtcblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnRXZlbnQnLCBzb3J0QW5hbHl0aWNzVGFnZ2luZ0RhdGEpO1xuXHRcdFx0fVxuXHRcdFx0cHJldmlvdXNTb3J0QXBwbGllZCA9IG5ld1NvcnRWYWx1ZTtcblx0XHR9XG5cdFx0XG4gICAgXHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuICAgIFx0dXBkYXRlUHJvZHVjdExpc3RpbmcoYnVpbGRVcmxGb3JTZWxlY3RlZFJlZmluZW1lbnRzKG51bGwsIG51bGwsIGZhbHNlLCB0cnVlKSk7XG4gICAgfSk7XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5jbGVhci1yZWZpbmVtZW50czpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgIFx0dmFyIGhyZWYgPSAkdGhpcy5hdHRyKCdocmVmJyk7XG4gICAgXHR2YXIgJHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucyA9ICQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItaGVhZGVyIC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcbiAgICBcdFxuICAgIFx0aWYgKCRyZWZpbmVtZW50c01vZGFsUHJvZHVjdFNlbGVjdGlvbnMuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyAudmFsdWUuYXBwbGllZCcpLmxlbmd0aCA+IDApIHtcbiAgICBcdFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG4gICAgXHRcdFx0JCgnLmNsZWFyLXJlZmluZW1lbnRzJykubG9hZGluZyh7XG4gICAgXHRcdFx0XHRJc0ltYWdlU2hvd246IGZhbHNlXHRcbiAgICBcdFx0XHR9KTtcbiAgICBcdFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZygkKHRoaXMpLmF0dHIoJ2hyZWYnKSk7XG4gICAgXHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0ZG9jdW1lbnQubG9jYXRpb24gPSAkKHRoaXMpLmF0dHIoJ2hyZWYnKTtcbiAgICBcdFx0fVxuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0JCgnLnJlZmluZW1lbnRbdXVpZF0nKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXTpub3QoLnNlbGVjdGVkKS5tb2RpZmllZCcpLnJlbW92ZUNsYXNzKCdtb2RpZmllZCcpO1xuICAgIFx0XHQkKCcucmVmaW5lbWVudFt1dWlkXScpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpJykuZmluZCgnaW5wdXQ6Y2hlY2tlZCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG4gICAgXHRcdHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKTtcbiAgICBcdH1cbiAgICB9KTtcblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI21haW4gLmJ0bi5sb2FkLW1vcmU6bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyICRsb2FkTW9yZUJ1dHRvbiA9ICQodGhpcyk7XG5cblx0XHQvLyBMZXQncyBkaXNhYmxlIHRoZSBidXR0b24gYWZ0ZXIgZmlyc3QgY2xpY2ssIHNvIHRoYXQgZnVuY3Rpb25hbGl0eSBjYW4gY29tcGxldGUgYmVmb3JlIGJlaW5nIHJlLWVuYWJsZWRcblx0XHQkbG9hZE1vcmVCdXR0b24uYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cblx0XHRpZiAoIWRhdGFCdWZmZXJbJ1BhZ2luYXRpb25JbmRleCddKSB7XG5cdFx0XHRkYXRhQnVmZmVyWydQYWdpbmF0aW9uSW5kZXgnXSA9IG9wdGlvbnMuUGFnaW5hdGlvbi5TdGFydDtcblx0XHR9XG5cdFx0aWYgKCFkYXRhQnVmZmVyWydQYWdpbmF0aW9uQ291bnQnXSkge1xuXHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkNvdW50J10gPSBvcHRpb25zLlBhZ2luYXRpb24uQ291bnQ7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciB1cmwgPSBkb2N1bWVudC5sb2NhdGlvbi5ocmVmO1xuXHRcdHZhciBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh1dGlsLmdldFF1ZXJ5U3RyaW5nKHVybCkpO1xuXHRcdGlmIChjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydzdGFydCddKSB7XG5cdFx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdzdGFydCcpO1xuXHRcdH1cblx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnc3RhcnQnLCBkYXRhQnVmZmVyWydQYWdpbmF0aW9uSW5kZXgnXSArIG9wdGlvbnMuUGFnaW5hdGlvbi5TaXplKTtcblxuXHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCwgZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBVc2UgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIHJlLWVuYWJsZSB0aGUgTG9hZCBNb3JlIGJ1dHRvblxuXHRcdFx0JGxvYWRNb3JlQnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdH0sIHRydWUpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gdG9nZ2xlQm9keVNjcm9sbExvY2soKSB7XG5cdHZhciAkYm9keSA9ICQoJ2JvZHknKTtcblx0dmFyIGJvZHlTY3JvbGxMb2NrQ2xhc3MgPSAncmVmaW5lbWVudHMtbW9iaWxlLXNjcm9sbC1sb2NrJztcblxuXHRpZiAoJGJvZHkuaGFzQ2xhc3MoYm9keVNjcm9sbExvY2tDbGFzcykpIHtcblx0XHQkYm9keS5yZW1vdmVDbGFzcyhib2R5U2Nyb2xsTG9ja0NsYXNzKTtcblx0XHQkYm9keS5jc3MoJ3RvcCcsICcnKTtcblx0XHRkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSBkYXRhQnVmZmVyWydzY3JvbGxUb3AnXTtcblx0fSBlbHNlIHtcblx0XHR2YXIgc2Nyb2xsVG9wID0gZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcDtcbiAgICBcdGRhdGFCdWZmZXJbJ3Njcm9sbFRvcCddID0gc2Nyb2xsVG9wO1xuICAgIFx0JGJvZHkuY3NzKCd0b3AnLCAwIC0gc2Nyb2xsVG9wKTtcbiAgICBcdCRib2R5LmFkZENsYXNzKGJvZHlTY3JvbGxMb2NrQ2xhc3MpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVXJsRm9yU2VsZWN0ZWRSZWZpbmVtZW50cyhiYXNlVXJsLCB1cmxGb3JQYXJhbWV0ZXJzLCBpbmNsdWRlQ2F0ZWdvcnksIGluY2x1ZGVTb3J0KSB7XG5cdHZhciByZWZpbmVtZW50VmFsdWVzQnVmZmVyID0ge307XG5cdFxuXHQkcmVmaW5lbWVudHNJbm5lci5maW5kKCdbcmVmaW5lbWVudC1pZF06bm90KC5wcmljZS1yZWZpbmVtZW50KTpub3QoLnNvcnQtYnkpJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJHJlZmluZW1lbnQgPSAkKHRoaXMpO1xuXHRcdHZhciAkc2VsZWN0ZWRSZWZpbmVtZW50cyA9ICRyZWZpbmVtZW50LmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpLm1vZGlmaWVkLCBsaVtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZDpub3QoLm1vZGlmaWVkKScpO1xuXHRcdFxuXHRcdGlmICgkc2VsZWN0ZWRSZWZpbmVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgXHRcdHZhciByZWZpbmVtZW50SWQgPSAkcmVmaW5lbWVudC5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG4gICAgXHRcdHZhciBtYXBwZWRSZWZpbmVtZW50SWQ7XG5cdFx0XHRpZiAocmVmaW5lbWVudElkID09ICdhdmFpbGFibGVTdG9yZXMyJyB8fCByZWZpbmVtZW50SWQgPT0gJ2F2YWlsYWJsZVN0b3JlczMnKSB7XG5cdFx0XHRcdG1hcHBlZFJlZmluZW1lbnRJZCA9ICdhdmFpbGFibGVTdG9yZXMnO1x0XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXBwZWRSZWZpbmVtZW50SWQgPSByZWZpbmVtZW50SWQ7XG5cdFx0XHR9XG4gICAgXHRcdFxuICAgIFx0XHRpZiAoIXJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbbWFwcGVkUmVmaW5lbWVudElkXSkge1xuICAgIFx0XHRcdHJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbbWFwcGVkUmVmaW5lbWVudElkXSA9IFtdO1xuICAgIFx0XHR9XG4gICAgXHRcdFxuICAgIFx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50cy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBcdFx0XHR2YXIgdmFsdWUgPSAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKS5yZXBsYWNlKCcgSU5DSCcsJ1wiJyk7XG4gICAgXHRcdFx0dmFyIGlzTmV3VmFsdWUgPSB0cnVlO1xuICAgIFx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCByZWZpbmVtZW50VmFsdWVzQnVmZmVyW21hcHBlZFJlZmluZW1lbnRJZF0ubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgXHRcdFx0XHRpZiAocmVmaW5lbWVudFZhbHVlc0J1ZmZlclttYXBwZWRSZWZpbmVtZW50SWRdW2luZGV4XSA9PSB2YWx1ZSkge1xuICAgIFx0XHRcdFx0XHRpc05ld1ZhbHVlID0gZmFsc2U7XG4gICAgXHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0XG4gICAgXHRcdFx0aWYgKGlzTmV3VmFsdWUgJiYgJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyBbZGF0YS1yZWZncm91cC1pZD1cIicgKyByZWZpbmVtZW50SWQgKyAnXCJdIFt2YWx1ZT1cIicgKyAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKS5yZXBsYWNlKC9bXCInXS9nLCBcIlwiKSArICdcIl0ucGVuZGluZy1jbGVhcicpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlc0J1ZmZlclttYXBwZWRSZWZpbmVtZW50SWRdLnB1c2godmFsdWUpO1xuICAgIFx0XHRcdH1cbiAgICBcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdHZhciB1cmwgPSBiYXNlVXJsIHx8IG9wdGlvbnMuU2VhcmNoVXJsO1xuXHR2YXIgY3VycmVudENhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0aWYgKGluY2x1ZGVDYXRlZ29yeSAmJiBjdXJyZW50Q2F0ZWdvcnlJZCAmJiBjdXJyZW50Q2F0ZWdvcnlJZCAhPSAnbnVsbCcpIHtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdjZ2lkJyk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSk7XG5cdH1cblx0XG5cdHZhciBjdXJyZW50UXVlcnlTdHJpbmcgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nKHVybEZvclBhcmFtZXRlcnMgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZik7XG5cdHZhciBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyhjdXJyZW50UXVlcnlTdHJpbmcpO1xuXHRpZiAoY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1sncSddKSB7XG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncScpO1xuXHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdxJywgb3B0aW9ucy5TZWFyY2hQaHJhc2UpO1xuXHR9XG5cdFxuXHRpZiAoY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1snc3J1bGUnXSkge1xuXHRcdHVybCA9IHV0aWwucmVtb3ZlUGFyYW1Gcm9tVVJMKHVybCwgJ3NydWxlJyk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NydWxlJywgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1snc3J1bGUnXSk7XG5cdH1cblxuXHR2YXIgYXZhaWxhYmxlU3RvcmVzVmFsdWU7XG5cdHZhciBhY3RpdmVSZWZpbmVtZW50SW5kZXggPSAxO1xuXHR3aGlsZSAodXJsLmluZGV4T2YoJ3ByZWZuJyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleCkgPj0gMCkge1xuXHRcdGlmIChjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydwcmVmbicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXhdID09ICdhdmFpbGFibGVTdG9yZXMnKSB7XG5cdFx0XHRhdmFpbGFibGVTdG9yZXNWYWx1ZSA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnNbJ3ByZWZ2JyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleF07XG5cdFx0fVxuXG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncHJlZm4nICsgYWN0aXZlUmVmaW5lbWVudEluZGV4KTtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdwcmVmdicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXgpO1xuXHRcdGFjdGl2ZVJlZmluZW1lbnRJbmRleCsrO1xuXHR9XG5cblx0dmFyIGF2YWlsYWJsZVN0b3Jlc1JlZmluZW1lbnRJbmRleDtcblx0Zm9yICh2YXIgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyS2V5IGluIGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnMpIHtcblx0XHR2YXIgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUgPSBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzW2N1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcktleV07XG5cdFx0aWYgKGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlICYmIGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlLmluZGV4T2YoJ2F2YWlsYWJsZVN0b3JlcycpID4gLTEpIHtcblx0XHRcdHZhciByZWZpbmVtZW50SW5kZXhNYXRjaCA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcktleS5tYXRjaCgvcHJlZm4oWzAtOV0pKy8pO1xuXHRcdFx0aWYgKHJlZmluZW1lbnRJbmRleE1hdGNoICYmIHJlZmluZW1lbnRJbmRleE1hdGNoLmxlbmd0aCA+IDEpIHtcblx0XHRcdFx0YXZhaWxhYmxlU3RvcmVzUmVmaW5lbWVudEluZGV4ID0gcmVmaW5lbWVudEluZGV4TWF0Y2hbMV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aWYgKCFhdmFpbGFibGVTdG9yZXNWYWx1ZSAmJiBhdmFpbGFibGVTdG9yZXNSZWZpbmVtZW50SW5kZXgpIHtcblx0XHRhdmFpbGFibGVTdG9yZXNWYWx1ZSA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnNbJ3ByZWZ2JyArIGF2YWlsYWJsZVN0b3Jlc1JlZmluZW1lbnRJbmRleF07XG5cdH1cblxuXHRpZiAoYXZhaWxhYmxlU3RvcmVzVmFsdWUgJiYgIXJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbJ2F2YWlsYWJsZVN0b3JlcyddKSB7XG5cdFx0cmVmaW5lbWVudFZhbHVlc0J1ZmZlclsnYXZhaWxhYmxlU3RvcmVzJ10gPSBbXTtcblx0XHRyZWZpbmVtZW50VmFsdWVzQnVmZmVyWydhdmFpbGFibGVTdG9yZXMnXS5wdXNoKGF2YWlsYWJsZVN0b3Jlc1ZhbHVlKTtcblx0fVxuXHRcblx0dmFyIGFjdGl2ZVJlZmluZW1lbnRJbmRleCA9IDE7XG5cdGZvciAodmFyIHJlZmluZW1lbnRJZCBpbiByZWZpbmVtZW50VmFsdWVzQnVmZmVyKSB7XG5cdFx0aWYgKHJlZmluZW1lbnRJZCAmJiByZWZpbmVtZW50VmFsdWVzQnVmZmVyW3JlZmluZW1lbnRJZF0ubGVuZ3RoID4gMCkge1xuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuJyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleCwgcmVmaW5lbWVudElkKTtcblx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmdicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXgsIHJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbcmVmaW5lbWVudElkXS5qb2luKCd8JykpO1xuXHRcdFx0YWN0aXZlUmVmaW5lbWVudEluZGV4Kys7XG5cdFx0fVxuXHR9XG5cdFxuXHRpZiAoJCgnW2lzLXByaWNlLXJlZmluZW1lbnQ9XCJ0cnVlXCJdIGlucHV0OmNoZWNrZWQnKS5sZW5ndGggPiAwIHx8IFNpdGVQcmVmZXJlbmNlcy5QUklDRV9TTElERVJfRU5BQkxFRCkge1xuXHRcdHZhciBjdXJyZW50V2luZG93VXJsUVMgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nKHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcblx0XHR2YXIgdXJsUGFyYW1zID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyhjdXJyZW50V2luZG93VXJsUVMpOyAvLyBHZXQgdXJsIHBhcmFtZXRlcnMgaW4gb2JqZWN0IGZvcm1hdFxuXHRcdHZhciAkcmVmaW5lbWVudFByaWNlID0gJCgnW2lzLXByaWNlLXJlZmluZW1lbnQ9XCJ0cnVlXCJdIGlucHV0OmNoZWNrZWQnKS5jbG9zZXN0KCdbaXMtcHJpY2UtcmVmaW5lbWVudD1cInRydWVcIl0nKTtcblxuXHRcdHVybCA9IHV0aWwucmVtb3ZlUGFyYW1Gcm9tVVJMKHVybCwgJ3BtaW4nKTtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdwbWF4Jyk7XG5cblx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLlBSSUNFX1NMSURFUl9FTkFCTEVEKSB7IFxuXHRcdFx0aWYgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuXHRcdFx0XHR1cmwgPSBpbml0TW9iaWxlUHJpY2VTbGlkZXIodXJsKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICh1cmxQYXJhbXMucG1pbikge1xuXHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwbWluJywgdXJsUGFyYW1zLnBtaW4pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICh1cmxQYXJhbXMucG1heCkge1xuXHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwbWF4JywgdXJsUGFyYW1zLnBtYXgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICgkcmVmaW5lbWVudFByaWNlLmF0dHIoJ3BtaW4nKSkge1xuXHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncG1pbicsICRyZWZpbmVtZW50UHJpY2UuYXR0cigncG1pbicpKTtcblx0XHRcdH1cblx0XHRcdGlmICgkcmVmaW5lbWVudFByaWNlLmF0dHIoJ3BtYXgnKSkge1xuXHRcdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncG1heCcsICRyZWZpbmVtZW50UHJpY2UuYXR0cigncG1heCcpKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRpZiAoaW5jbHVkZVNvcnQgJiYgY2hlY2tGb3JVcGRhdGVkUmVmaW5lbWVudEhhbmRsaW5nKCkpIHtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdzcnVsZScpO1xuXHRcdFxuXHRcdHZhciAkc29ydGluZ1J1bGUgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCcuc29ydC1ieSBvcHRpb246Y2hlY2tlZCwgLnNvcnQtYnkgaW5wdXQ6Y2hlY2tlZCcpO1xuXHRcdGlmICgkc29ydGluZ1J1bGUgJiYgJHNvcnRpbmdSdWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBzb3J0aW5nUnVsZSA9ICRzb3J0aW5nUnVsZS5hdHRyKCdzb3J0aW5nLXJ1bGUnKTtcblxuXHRcdFx0aWYgKHNvcnRpbmdSdWxlICYmIHNvcnRpbmdSdWxlLmluZGV4T2YoJ0RlZmF1bHQnKSA8IDApIHtcblx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NydWxlJywgc29ydGluZ1J1bGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB1cmw7XG59XG5cbmZ1bmN0aW9uIGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpIHtcblx0aWYgKChvcHRpb25zLlJlZmluZW1lbnRzVUlWZXJzaW9uID09IFJlZmluZW1lbnRVSVZlcnNpb25Db25zdGFudHMuVXBkYXRlZCkgJiYgJGh0bWwuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykgJiYgKHBhZ2VDb250ZXh0LnNpdGUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMgfHwgb3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykpIHtcbiAgICBcdHJldHVybiB0cnVlO1xuXHR9XG5cdFxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoJGNvbnRlbnRQYXJhbWV0ZXIsIHVybEZvclBhcmFtZXRlcnMpIHtcblx0dmFyICRjb250ZW50O1xuXHRpZiAoJGNvbnRlbnRQYXJhbWV0ZXIgJiYgJGNvbnRlbnRQYXJhbWV0ZXIubGVuZ3RoID4gMCkge1xuXHRcdCRjb250ZW50ID0gJGNvbnRlbnRQYXJhbWV0ZXIuZmluZCgnLnJlZmluZW1lbnRzJyk7XG5cdH1cblx0aWYgKCEkY29udGVudCB8fCAkY29udGVudC5sZW5ndGggPT0gMCkge1xuXHRcdCRjb250ZW50ID0gJHJlZmluZW1lbnRzSW5uZXI7XG5cdH1cblxuXHQvL3VwZGF0ZU11bHRpUHJpY2VSZWZpbmVtZW50cygkY29udGVudCwgdXJsRm9yUGFyYW1ldGVycyk7XG5cdHVwZGF0ZVJlZmluZW1lbnRDb3VudHMoJGNvbnRlbnQsIHVybEZvclBhcmFtZXRlcnMpO1xuXHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdHVwZGF0ZVNlbGVjdGVkUmVmaW5lbWVudHMoKTtcblx0fVxuXHR1cGRhdGVQZW5kaW5nUmVmaW5lbWVudHMoKTtcblxuXHR2YXIgaXNTb3J0aW5nQ2hhbmdlZCA9IGZhbHNlO1xuXHR2YXIgJHNvcnRpbmdSdWxlID0gJCgnLm1vZGFsLm9wZW4gLnNvcnQtYnkgb3B0aW9uOmNoZWNrZWQsIC5tb2RhbC5vcGVuIC5zb3J0LWJ5IGlucHV0OmNoZWNrZWQnKTtcblx0aWYgKCRzb3J0aW5nUnVsZSAmJiAkc29ydGluZ1J1bGUubGVuZ3RoID4gMCkge1xuXHRcdGlzU29ydGluZ0NoYW5nZWQgPSAhJHNvcnRpbmdSdWxlLmF0dHIoJ3NlbGVjdGVkJyk7XG5cdH1cblxuXHRpZiAoaXNTb3J0aW5nQ2hhbmdlZCB8fCAkY29udGVudC5maW5kKCdbcmVmaW5lbWVudC12YWx1ZV0ubW9kaWZpZWQsIC5saXN0LXNlbGVjdGlvbnMgLnZhbHVlLnBlbmRpbmctY2xlYXInKS5sZW5ndGggPiAwKSB7XG5cdFx0JGNvbnRlbnQuYWRkQ2xhc3MoJ3JlZmluZW1lbnRzLW1vZGlmaWVkJyk7XG5cdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdH0gZWxzZSB7XG5cdFx0JGNvbnRlbnQucmVtb3ZlQ2xhc3MoJ3JlZmluZW1lbnRzLW1vZGlmaWVkJyk7XG5cdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdH1cblx0XG5cdGlmICgkKCdbaXMtcHJpY2UtcmVmaW5lbWVudD1cInRydWVcIl0gaW5wdXQ6Y2hlY2tlZCcpLmxlbmd0aCA+IDApIHtcblx0XHQkY29udGVudC5hZGRDbGFzcygncHJpY2Utc2VsZWN0ZWQnKTtcblx0fSBlbHNlIHtcblx0XHQkY29udGVudC5yZW1vdmVDbGFzcygncHJpY2Utc2VsZWN0ZWQnKTtcblx0fVxuXHRcblx0dmFyICRyZWZpbmVtZW50c01vZGFsUHJvZHVjdFNlbGVjdGlvbnMgPSAkKCcucmVmaW5lbWVudHMtaW5uZXItY29udGFpbmVyLWhlYWRlciAucHJvZHVjdC1zZWxlY3Rpb25zJyk7XHRcblx0aWYgKCgkcmVmaW5lbWVudHNNb2RhbFByb2R1Y3RTZWxlY3Rpb25zLmZpbmQoJy5saXN0LXNlbGVjdGlvbnMgLnZhbHVlLmFwcGxpZWQnKS5sZW5ndGggKyAkcmVmaW5lbWVudHNNb2RhbFByb2R1Y3RTZWxlY3Rpb25zLmZpbmQoJy5saXN0LXNlbGVjdGlvbnMgPiAucGVuZGluZy1zZWxlY3Rpb25zID4gc3BhbicpLmxlbmd0aCkgPiAwKSB7XG5cdFx0JHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucy5zaG93KCk7XG5cdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmNsZWFyLXJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdH0gZWxzZSB7XG5cdFx0JHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucy5oaWRlKCk7XG5cdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmNsZWFyLXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdH1cblx0dmFyICRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyO1xuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHQkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lciA9ICQoJy5wcmltYXJ5LWNvbnRlbnQgPiAuc29ydC1hbmQtcmVmaW5lID4gLnByb2R1Y3Qtc2VsZWN0aW9ucycpO1xuXHR9IGVsc2Uge1xuXHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyID0gJCgnLnByaW1hcnktY29udGVudCA+IC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0fVxuXG5cdGlmICgkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lci5maW5kKCcubGlzdC1zZWxlY3Rpb25zIC52YWx1ZS5hcHBsaWVkJykubGVuZ3RoID4gMCkge1xuXHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyLnNob3coKTtcblx0fSBlbHNlIHtcblx0XHQkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lci5oaWRlKCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlU2VsZWN0ZWRSZWZpbmVtZW50cygpIHtcblx0dmFyICRyZWZpbmVtZW50cyA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50W3V1aWRdLmV4cGFuZGVkJyk7XG5cdCRyZWZpbmVtZW50cy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkcmVmaW5lbWVudCA9ICQodGhpcyk7XG5cblx0XHR2YXIgJHNlbGVjdGVkUmVmaW5lbWVudHNDb250YWluZXIgPSAkcmVmaW5lbWVudC5maW5kKCcudG9nZ2xlJykuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucycpO1xuXHRcdGlmICghJHNlbGVjdGVkUmVmaW5lbWVudHNDb250YWluZXIgfHwgISRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyLmxlbmd0aCkge1xuXHRcdFx0JHJlZmluZW1lbnQuZmluZCgnLnRvZ2dsZScpLmFwcGVuZCgnPGRpdiBjbGFzcz1cInByb2R1Y3Qtc2VsZWN0aW9uc1wiPjx1bCBjbGFzcz1cImxpc3Qtc2VsZWN0aW9uc1wiLz48L2Rpdj4nKTtcblx0XHRcdCRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgnLnRvZ2dsZSAubGlzdC1zZWxlY3Rpb25zJyk7XG5cdFx0fVxuXG5cdFx0dmFyICRzZWxlY3RlZFJlZmluZW1lbnRzVmFsdWVzO1xuXHRcdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50c1ZhbHVlcyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsOm5vdCgucG9wdWxhciknKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50c1ZhbHVlcyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsOm5vdCgucG9wdWxhciknKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCwgaW5wdXQ6Y2hlY2tlZDpub3QoLm1vZGlmaWVkKScpO1xuXHRcdH1cblx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlciA9IFtdO1xuXHRcdCRzZWxlY3RlZFJlZmluZW1lbnRzVmFsdWVzLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50SWQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC1pZF0nKS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWUgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC12YWx1ZV0nKS5hdHRyKCdyZWZpbmVtZW50LXZhbHVlJyk7XG5cdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50VGV4dCA9ICR0aGlzLmNsb3Nlc3QoJ1tyZWZpbmVtZW50LXZhbHVlXScpLmF0dHIoJ2Rpc3BsYXktdmFsdWUnKSB8fCBzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZTtcblx0XHRcdFxuXHRcdFx0aWYgKCFzZWxlY3RlZFJlZmluZW1lbnRzQnVmZmVyW3NlbGVjdGVkUmVmaW5lbWVudElkXSkge1xuXHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRzQnVmZmVyW3NlbGVjdGVkUmVmaW5lbWVudElkXSA9IFtdO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHR2YXIgaXNOZXdWYWx1ZSA9IHRydWU7XG5cdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgc2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRJZF0ubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdGlmIChzZWxlY3RlZFJlZmluZW1lbnRzQnVmZmVyW3NlbGVjdGVkUmVmaW5lbWVudElkXVtpbmRleF0uVmFsdWUgPT0gc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWUpIHtcblx0XHRcdFx0XHRpc05ld1ZhbHVlID0gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKGlzTmV3VmFsdWUpIHtcblx0XHRcdFx0c2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRJZF0ucHVzaCh7XG5cdFx0XHRcdFx0VGV4dDogc2VsZWN0ZWRSZWZpbmVtZW50VGV4dCxcblx0XHRcdFx0XHRWYWx1ZTogc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWVcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50c0h0bWwgPSAnJztcblx0XHRmb3IgKHZhciBzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50IGluIHNlbGVjdGVkUmVmaW5lbWVudHNCdWZmZXIpIHtcblx0XHRcdHZhciBzZWxlY3RlZFJlZmluZW1lbnQgPSBzZWxlY3RlZFJlZmluZW1lbnRzQnVmZmVyW3NlbGVjdGVkUmVmaW5lbWVudEVsZW1lbnRdO1xuXHRcdFx0XG5cdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWVzSHRtbCA9ICcnO1xuXHRcdFx0Zm9yICh2YXIgc2VsZWN0ZWRSZWZpbmVtZW50RGF0YUVsZW1lbnQgaW4gc2VsZWN0ZWRSZWZpbmVtZW50KSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZFJlZmluZW1lbnREYXRhID0gc2VsZWN0ZWRSZWZpbmVtZW50W3NlbGVjdGVkUmVmaW5lbWVudERhdGFFbGVtZW50XTtcblx0XHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudFRleHQgPSBzZWxlY3RlZFJlZmluZW1lbnREYXRhLlRleHQ7XG5cdFx0XHRcdHZhciBzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZSA9IHNlbGVjdGVkUmVmaW5lbWVudERhdGEuVmFsdWU7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWVzSHRtbCkge1xuXHRcdFx0XHRcdHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlc0h0bWwgKz0gJzxzcGFuIGNsYXNzPVwiZGVsaW1pdGVyXCI+LDwvc3Bhbj4nO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50RGlzcGxheVZhbHVlID0gc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWU7XG5cdFx0XHRcdGlmIChzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50ID09ICdQcmljZScpIHtcblx0XHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnREaXNwbGF5VmFsdWUgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCdbcmVmaW5lbWVudC1pZD1cIicgKyBzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50ICsgJ1wiXScpLmF0dHIoJ2Rpc3BsYXktdmFsdWUnKTtcblx0XHRcdFx0fSBlbHNlIGlmIChzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50ID09ICdzaXplJykge1xuXHRcdFx0XHRcdHNlbGVjdGVkUmVmaW5lbWVudERpc3BsYXlWYWx1ZSA9ICdTaXplICcgKyBzZWxlY3RlZFJlZmluZW1lbnREaXNwbGF5VmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlc0h0bWwgKz0gJzxzcGFuIGNsYXNzPVwidmFsdWVcIiByZWZpbmVtZW50LXZhbHVlPVwiJyArIHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlICsgJ1wiPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRUZXh0ICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JzxhIGNsYXNzPVwiY2xvc2UtYnRuXCI+PGkgY2xhc3M9XCJmYSBmYS1jbG9zZVwiPjwvaT48L2E+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnPC9zcGFuPic7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHNlbGVjdGVkUmVmaW5lbWVudHNIdG1sICs9ICc8c3BhbiBkYXRhLXJlZmdyb3VwLWlkPVwiJyArIHNlbGVjdGVkUmVmaW5lbWVudEVsZW1lbnQgKyAnXCI+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JzxzcGFuIGNsYXNzPVwia2V5XCI+JyArIHNlbGVjdGVkUmVmaW5lbWVudEVsZW1lbnQgKyAnPC9zcGFuPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8c3BhbiBjbGFzcz1cImNvbG9uXCI+Ojwvc3Bhbj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZXNIdG1sICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Jzwvc3Bhbj4nO1xuXHRcdH1cblx0XHRcblx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lci5odG1sKHNlbGVjdGVkUmVmaW5lbWVudHNIdG1sKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVBlbmRpbmdSZWZpbmVtZW50cygpIHtcblx0dmFyICRwZW5kaW5nUmVmaW5lbWVudHNDb250YWluZXI7XG5cdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0dmFyICRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyID0gJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnLnJlZmluZW1lbnQuZXhwYW5kZWQgLnRvZ2dsZScpLmZpbmQoJy5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0XHRpZiAoISRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyIHx8ICEkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lci5sZW5ndGgpIHtcblx0XHRcdCRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50LmV4cGFuZGVkIC50b2dnbGUnKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJwcm9kdWN0LXNlbGVjdGlvbnNcIj48dWwgY2xhc3M9XCJsaXN0LXNlbGVjdGlvbnNcIi8+PC9kaXY+Jyk7XG5cdFx0fVxuXG5cdFx0JHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lciA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50LmV4cGFuZGVkIC50b2dnbGUnKS5maW5kKCcucGVuZGluZy1zZWxlY3Rpb25zJyk7XG5cdFx0aWYgKCEkcGVuZGluZ1JlZmluZW1lbnRzQ29udGFpbmVyIHx8ICEkcGVuZGluZ1JlZmluZW1lbnRzQ29udGFpbmVyLmxlbmd0aCkge1xuXHRcdFx0JHJlZmluZW1lbnRzSW5uZXIuZmluZCgnLnJlZmluZW1lbnQuZXhwYW5kZWQgLnRvZ2dsZSAubGlzdC1zZWxlY3Rpb25zJykuYXBwZW5kKCc8bGkgY2xhc3M9XCJwZW5kaW5nLXNlbGVjdGlvbnNcIi8+Jyk7XG5cdFx0XHQkcGVuZGluZ1JlZmluZW1lbnRzQ29udGFpbmVyID0gJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnLnJlZmluZW1lbnQuZXhwYW5kZWQgLnRvZ2dsZSAubGlzdC1zZWxlY3Rpb25zIC5wZW5kaW5nLXNlbGVjdGlvbnMnKTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0JHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lciA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5wZW5kaW5nLXNlbGVjdGlvbnMnKTtcblx0fVxuXHRcblx0dmFyICRwZW5kaW5nUmVmaW5lbWVudHNWYWx1ZXM7XG5cdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0JHBlbmRpbmdSZWZpbmVtZW50c1ZhbHVlcyA9ICQoJy5yZWZpbmVtZW50W3V1aWRdLmV4cGFuZGVkIHVsOm5vdCgucG9wdWxhciknKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXTpub3QoLnNlbGVjdGVkKS5tb2RpZmllZCwgaW5wdXQubW9kaWZpZWQ6bm90KFtjaGVja2VkPVwiY2hlY2tlZFwiXSknKTtcblx0fSBlbHNlIHtcblx0XHQkcGVuZGluZ1JlZmluZW1lbnRzVmFsdWVzID0gJCgnLnJlZmluZW1lbnRbdXVpZF0gdWw6bm90KC5wb3B1bGFyKScpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpLm1vZGlmaWVkJyk7XG5cdH1cblx0dmFyIHBlbmRpbmdSZWZpbmVtZW50c0J1ZmZlciA9IFtdO1xuXG5cdCRwZW5kaW5nUmVmaW5lbWVudHNWYWx1ZXMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50SWQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC1pZF0nKS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50VmFsdWUgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC12YWx1ZV0nKS5hdHRyKCdyZWZpbmVtZW50LXZhbHVlJyk7XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50VGV4dCA9ICR0aGlzLmNsb3Nlc3QoJ1tyZWZpbmVtZW50LXZhbHVlXScpLmF0dHIoJ2Rpc3BsYXktdmFsdWUnKSB8fCBwZW5kaW5nUmVmaW5lbWVudFZhbHVlO1xuXHRcdFxuXHRcdGlmICghcGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyW3BlbmRpbmdSZWZpbmVtZW50SWRdKSB7XG5cdFx0XHRwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXJbcGVuZGluZ1JlZmluZW1lbnRJZF0gPSBbXTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIGlzTmV3VmFsdWUgPSB0cnVlO1xuXHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXJbcGVuZGluZ1JlZmluZW1lbnRJZF0ubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRpZiAocGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyW3BlbmRpbmdSZWZpbmVtZW50SWRdW2luZGV4XS5WYWx1ZSA9PSBwZW5kaW5nUmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHRcdGlzTmV3VmFsdWUgPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0aWYgKGlzTmV3VmFsdWUpIHtcblx0XHRcdHBlbmRpbmdSZWZpbmVtZW50c0J1ZmZlcltwZW5kaW5nUmVmaW5lbWVudElkXS5wdXNoKHtcblx0XHRcdFx0VGV4dDogcGVuZGluZ1JlZmluZW1lbnRUZXh0LFxuXHRcdFx0XHRWYWx1ZTogcGVuZGluZ1JlZmluZW1lbnRWYWx1ZVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdHZhciBwZW5kaW5nUmVmaW5lbWVudHNIdG1sID0gJyc7XG5cdGZvciAodmFyIHBlbmRpbmdSZWZpbmVtZW50RWxlbWVudCBpbiBwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXIpIHtcblx0XHR2YXIgcGVuZGluZ1JlZmluZW1lbnQgPSBwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXJbcGVuZGluZ1JlZmluZW1lbnRFbGVtZW50XTtcblx0XHRcblx0XHR2YXIgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZXNIdG1sID0gJyc7XG5cdFx0Zm9yICh2YXIgcGVuZGluZ1JlZmluZW1lbnREYXRhRWxlbWVudCBpbiBwZW5kaW5nUmVmaW5lbWVudCkge1xuXHRcdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50RGF0YSA9IHBlbmRpbmdSZWZpbmVtZW50W3BlbmRpbmdSZWZpbmVtZW50RGF0YUVsZW1lbnRdO1xuXHRcdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50VGV4dCA9IHBlbmRpbmdSZWZpbmVtZW50RGF0YS5UZXh0O1xuXHRcdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50VmFsdWUgPSBwZW5kaW5nUmVmaW5lbWVudERhdGEuVmFsdWU7XG5cdFx0XHRcblx0XHRcdGlmIChwZW5kaW5nUmVmaW5lbWVudFZhbHVlc0h0bWwpIHtcblx0XHRcdFx0cGVuZGluZ1JlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8c3BhbiBjbGFzcz1cImRlbGltaXRlclwiPiw8L3NwYW4+Jztcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50RGlzcGxheVZhbHVlID0gcGVuZGluZ1JlZmluZW1lbnRWYWx1ZTtcblx0XHRcdGlmIChwZW5kaW5nUmVmaW5lbWVudEVsZW1lbnQgPT0gJ1ByaWNlJykge1xuXHRcdFx0XHRwZW5kaW5nUmVmaW5lbWVudERpc3BsYXlWYWx1ZSA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJ1tyZWZpbmVtZW50LWlkPVwiJyArIHBlbmRpbmdSZWZpbmVtZW50RWxlbWVudCArICdcIl0nKS5hdHRyKCdkaXNwbGF5LXZhbHVlJyk7XG5cdFx0XHR9IGVsc2UgaWYgKHBlbmRpbmdSZWZpbmVtZW50RWxlbWVudCA9PSAnc2l6ZScpIHtcblx0XHRcdFx0cGVuZGluZ1JlZmluZW1lbnREaXNwbGF5VmFsdWUgPSAnU2l6ZSAnICsgcGVuZGluZ1JlZmluZW1lbnREaXNwbGF5VmFsdWU7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHBlbmRpbmdSZWZpbmVtZW50VmFsdWVzSHRtbCArPSAnPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiIHJlZmluZW1lbnQtdmFsdWU9XCInICsgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSArICdcIj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHBlbmRpbmdSZWZpbmVtZW50VGV4dCArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnPGEgY2xhc3M9XCJjbG9zZS1idG5cIj48aSBjbGFzcz1cImZhIGZhLWNsb3NlXCI+PC9pPjwvYT4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnPC9zcGFuPic7XG5cdFx0fVxuXHRcdFxuXHRcdHBlbmRpbmdSZWZpbmVtZW50c0h0bWwgKz0gJzxzcGFuIGRhdGEtcmVmZ3JvdXAtaWQ9XCInICsgcGVuZGluZ1JlZmluZW1lbnRFbGVtZW50ICsgJ1wiPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQnPHNwYW4gY2xhc3M9XCJrZXlcIj4nICsgcGVuZGluZ1JlZmluZW1lbnRFbGVtZW50ICsgJzwvc3Bhbj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JzxzcGFuIGNsYXNzPVwiY29sb25cIj46PC9zcGFuPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRwZW5kaW5nUmVmaW5lbWVudFZhbHVlc0h0bWwgK1xuXHRcdFx0XHRcdFx0XHRcdFx0Jzwvc3Bhbj4nO1xuXHR9XG5cdFxuXHQkcGVuZGluZ1JlZmluZW1lbnRzQ29udGFpbmVyLmh0bWwocGVuZGluZ1JlZmluZW1lbnRzSHRtbCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVJlZmluZW1lbnRDb3VudHMoJGNvbnRlbnRQYXJhbWV0ZXIsIHVybEZvclBhcmFtZXRlcnMpIHtcblx0dmFyIHVybCA9IGJ1aWxkVXJsRm9yU2VsZWN0ZWRSZWZpbmVtZW50cyhVcmxzLmdldFJlZmluZW1lbnRDb3VudHMsIG51bGwsIHRydWUpO1xuXHR2YXIgJGNvbnRlbnQgPSAkY29udGVudFBhcmFtZXRlciB8fCAkKGRvY3VtZW50KTtcblx0dmFyICRyZWZpbmVtZW50cyA9ICRjb250ZW50LmZpbmQoJy5yZWZpbmVtZW50W3V1aWRdJyk7XG5cdHZhciAkcmVmaW5lbWVudFByb2R1Y3RDb3VudCA9ICRjb250ZW50LmZpbmQoJy5yZWZpbmVtZW50IC50b2dnbGUgLnByb2R1Y3QtY291bnQnKTtcblx0JHJlZmluZW1lbnRQcm9kdWN0Q291bnQubG9hZGluZygpO1xuXG5cdHZhciByZWZpbmVtZW50R3JvdXBzID0gW107XG5cdHZhciByZWZpbmVtZW50R3JvdXBJbmRleCA9IDA7XG5cdHZhciByZWZpbmVtZW50R3JvdXBTaXplTGltaXQgPSAyMDAwO1xuXHR2YXIgcmVmaW5lbWVudEdyb3VwU2l6ZUN1cnJlbnQgPSAwO1xuXHQkLmVhY2goJHJlZmluZW1lbnRzLCBmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkcmVmaW5lbWVudCA9ICQoZWxlbWVudCk7XG5cdFx0dmFyIHJlZmluZW1lbnRWYWx1ZUNvdW50ID0gJHJlZmluZW1lbnQuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdJykubGVuZ3RoO1xuXHRcdGlmICgocmVmaW5lbWVudFZhbHVlQ291bnQgKyByZWZpbmVtZW50R3JvdXBTaXplQ3VycmVudCkgPj0gcmVmaW5lbWVudEdyb3VwU2l6ZUxpbWl0KSB7XG5cdFx0XHRyZWZpbmVtZW50R3JvdXBJbmRleCsrO1xuXHRcdFx0cmVmaW5lbWVudEdyb3VwU2l6ZUN1cnJlbnQgPSAwO1xuXHRcdH1cblxuXHRcdGlmICghcmVmaW5lbWVudEdyb3Vwc1tyZWZpbmVtZW50R3JvdXBJbmRleF0pIHtcblx0XHRcdHJlZmluZW1lbnRHcm91cHNbcmVmaW5lbWVudEdyb3VwSW5kZXhdID0gJHJlZmluZW1lbnQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlZmluZW1lbnRHcm91cHNbcmVmaW5lbWVudEdyb3VwSW5kZXhdID0gcmVmaW5lbWVudEdyb3Vwc1tyZWZpbmVtZW50R3JvdXBJbmRleF0uYWRkKCRyZWZpbmVtZW50KTtcblx0XHR9XG5cblx0XHRyZWZpbmVtZW50R3JvdXBTaXplQ3VycmVudCArPSByZWZpbmVtZW50VmFsdWVDb3VudDtcblx0fSk7XG5cblx0ZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cEluZGV4J10gPSAwO1xuXHRkYXRhQnVmZmVyWyd1cGRhdGVSZWZpbmVtZW50Q291bnRzUmVmaW5lbWVudEdyb3VwQ291bnQnXSA9IHJlZmluZW1lbnRHcm91cHMubGVuZ3RoO1xuXG5cdCQuZWFjaChyZWZpbmVtZW50R3JvdXBzLCBmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkcmVmaW5lbWVudEdyb3VwID0gJChlbGVtZW50KTtcblx0XHR1cGRhdGVSZWZpbmVtZW50Q291bnRzRm9yUmVmaW5lbWVudHModXJsLCAkcmVmaW5lbWVudEdyb3VwKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVJlZmluZW1lbnRDb3VudHNGb3JSZWZpbmVtZW50cyh1cmwsICRyZWZpbmVtZW50cykge1xuXHR2YXIgcmVmaW5lbWVudElkcyA9ICRyZWZpbmVtZW50cy5tYXAoZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gJChlbGVtZW50KS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdH0pLmdldCgpO1xuXG5cdGlmIChyZWZpbmVtZW50SWRzKSB7XG5cdFx0dmFyICRyZWZpbmVtZW50UHJvZHVjdENvdW50ID0gJHJlZmluZW1lbnRzLmZpbmQoJy50b2dnbGUgLnByb2R1Y3QtY291bnQnKTtcblx0XHQkcmVmaW5lbWVudFByb2R1Y3RDb3VudC5sb2FkaW5nKCk7XG5cblx0XHRpZiAoZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cENvdW50J10gJiYgZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cENvdW50J10gPiAxKSB7XG5cdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncmVmaW5lbWVudHMnLCByZWZpbmVtZW50SWRzLmpvaW4oKSk7XG5cdFx0fVxuXG5cdFx0JC5hamF4KHtcblx0XHRcdHR5cGU6ICdnZXQnLFxuXHRcdFx0dXJsOiB1cmwsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50cy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0dmFyICRyZWZpbmVtZW50ID0gJChlbGVtZW50KTtcblx0XHRcdFx0XHRpZiAoZGF0YSkge1xuXHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRJZCA9ICRyZWZpbmVtZW50LmF0dHIoJ3JlZmluZW1lbnQtaWQnKTtcblx0XHRcdFx0XHRcdHZhciAkcmVmaW5lbWVudFZhbHVlcyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsIGxpW3JlZmluZW1lbnQtdmFsdWVdJyk7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YS5SZWZpbmVtZW50c1tyZWZpbmVtZW50SWRdKSB7XG5cdFx0XHRcdFx0XHRcdCQuZWFjaCgkcmVmaW5lbWVudFZhbHVlcywgZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZSA9ICQoZWxlbWVudCk7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9ICRyZWZpbmVtZW50VmFsdWUuYXR0cigncmVmaW5lbWVudC12YWx1ZScpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCRyZWZpbmVtZW50VmFsdWUuZmluZCgnaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdJykucHJvcCgnY2hlY2tlZCcpIHx8IGRhdGEuUmVmaW5lbWVudHNbcmVmaW5lbWVudElkXVtyZWZpbmVtZW50VmFsdWVdKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudFZhbHVlLmF0dHIoJ3JlZmluZW1lbnQtY291bnQnLCBkYXRhLlJlZmluZW1lbnRzW3JlZmluZW1lbnRJZF1bcmVmaW5lbWVudFZhbHVlXSkuZmluZCgnLnJlZmluZW1lbnQtY291bnQnKS5odG1sKGRhdGEuUmVmaW5lbWVudHNbcmVmaW5lbWVudElkXVtyZWZpbmVtZW50VmFsdWVdKTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0JHJlZmluZW1lbnRWYWx1ZS5hdHRyKCdyZWZpbmVtZW50LWNvdW50JywgMCkuZmluZCgnLnJlZmluZW1lbnQtY291bnQnKS5odG1sKCcwJyk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdFx0XHR2YXIgJHBvcHVsYXJSZWZpbmVtZW50VmFsdWVzID0gJHJlZmluZW1lbnQuZmluZCgndWwucG9wdWxhci1zaXplcywgdWwucG9wdWxhcicpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdJyk7XG5cdFx0XHRcdFx0XHRcdHZhciAkcG9wdWxhclJlZmluZW1lbnRWYWx1ZXNDaGVja3NDb250YWluZXIgPSAkcmVmaW5lbWVudC5maW5kKCcuY2hlY2tzLWNvbnRhaW5lci5wb3B1bGFyJyk7XG5cdFx0XHRcdFx0XHRcdHZhciBoYXNQb3B1bGFyUmVmaW5lbWVudFZhbHVlcyA9ICRwb3B1bGFyUmVmaW5lbWVudFZhbHVlcy5maWx0ZXIoJzpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpLmxlbmd0aCA+IDAgfHwgJHBvcHVsYXJSZWZpbmVtZW50VmFsdWVzLmZpbHRlcignOm5vdChbcmVmaW5lbWVudC1jb3VudD1cIjBcIl0pJykuZmluZCgnaW5wdXQ6Y2hlY2tlZCcpLmxlbmd0aCA+IDA7XG5cdFx0XHRcdFx0XHRcdGlmIChoYXNQb3B1bGFyUmVmaW5lbWVudFZhbHVlcykge1xuXHRcdFx0XHRcdFx0XHRcdCRwb3B1bGFyUmVmaW5lbWVudFZhbHVlc0NoZWNrc0NvbnRhaW5lci5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JHBvcHVsYXJSZWZpbmVtZW50VmFsdWVzQ2hlY2tzQ29udGFpbmVyLmhpZGUoKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0dmFyICRub3JtYWxSZWZpbmVtZW50VmFsdWVzID0gJHJlZmluZW1lbnQuZmluZCgndWw6bm90KC5wb3B1bGFyLXNpemVzKTpub3QoLnBvcHVsYXIpJykuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV0nKTtcblx0XHRcdFx0XHRcdFx0dmFyICRub3JtYWxSZWZpbmVtZW50VmFsdWVzQ2hlY2tzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgnLmNoZWNrcy1jb250YWluZXI6bm90KC5wb3B1bGFyKScpO1xuXHRcdFx0XHRcdFx0XHR2YXIgaGFzTm9ybWFsUmVmaW5lbWVudFZhbHVlcyA9ICRub3JtYWxSZWZpbmVtZW50VmFsdWVzLmZpbHRlcignOm5vdChbcmVmaW5lbWVudC1jb3VudD1cIjBcIl0pJykubGVuZ3RoID4gMCB8fCAkbm9ybWFsUmVmaW5lbWVudFZhbHVlcy5maWx0ZXIoJzpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpLmZpbmQoJ2lucHV0OmNoZWNrZWQnKS5sZW5ndGggPiAwO1xuXHRcdFx0XHRcdFx0XHRpZiAoaGFzTm9ybWFsUmVmaW5lbWVudFZhbHVlcykge1xuXHRcdFx0XHRcdFx0XHRcdCRub3JtYWxSZWZpbmVtZW50VmFsdWVzQ2hlY2tzQ29udGFpbmVyLnNob3coKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHQkbm9ybWFsUmVmaW5lbWVudFZhbHVlc0NoZWNrc0NvbnRhaW5lci5oaWRlKCk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvKiAtLS0gUHJpY2Ugc2xpZGVyIG1vZGlmaWNhdGlvbnMgLS0tICovXG5cdFx0XHRcdFx0XHRcdHZhciBoYXNQcmljZVNsaWRlciA9IFNpdGVQcmVmZXJlbmNlcy5QUklDRV9TTElERVJfRU5BQkxFRCAmJiAocmVmaW5lbWVudElkID09ICdQcmljZScgfHwgcmVmaW5lbWVudElkID09ICdyZWYtcG9zdERpc2NvdW50UHJpY2UnKTsgXG5cdFx0XHRcdFx0XHRcdGlmIChoYXNQcmljZVNsaWRlcikge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBwYWdlVXJsID0gdXRpbC5nZXRRdWVyeVN0cmluZyh3aW5kb3cubG9jYXRpb24uaHJlZik7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHBhZ2VVcmwpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhciBoYXNQcmljZUF0dHJpYnV0ZXMgPSBwYWdlVXJsLmluZGV4T2YoJ3BtaW4nKSA+IC0xIHx8IHBhZ2VVcmwuaW5kZXhPZigncG1heCcpID4gLTE7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgaXNNb2JpbGUgPSAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoaGFzUHJpY2VBdHRyaWJ1dGVzICYmICFpc01vYmlsZSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkKCcucHJpY2UtcmVmaW5lbWVudCcpLmZpbmQoJy5yZWZpbmVtZW50LWJvZHknKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkKCcucHJpY2UtcmVmaW5lbWVudCcpLmZpbmQoJy5yZWZpbmVtZW50LWJvZHknKS5oaWRlKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYgKGhhc05vcm1hbFJlZmluZW1lbnRWYWx1ZXMgfHwgaGFzUG9wdWxhclJlZmluZW1lbnRWYWx1ZXMgfHwgaGFzUHJpY2VTbGlkZXIpIHtcblx0XHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JHJlZmluZW1lbnQuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGlmICgkcmVmaW5lbWVudC5maW5kKCd1bC5jaGVja3MsIHVsLnN3YXRjaGVzJykuZmluZCgnbGknKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUF0dHIoJ2xvYWRpbmcnKTtcblx0XHRcdFx0XHR1cGRhdGVNb3JlTGVzcygkcmVmaW5lbWVudCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cEluZGV4J10rKztcblx0XHRcdFx0aWYgKCRyZWZpbmVtZW50UHJvZHVjdENvdW50LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50UHJvZHVjdENvdW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR1cGRhdGVSZWZpbmVtZW50Q291bnRzQ29tcGxldGUoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50Q291bnRzQ29tcGxldGUoKSB7XG5cdGlmIChkYXRhQnVmZmVyWyd1cGRhdGVSZWZpbmVtZW50Q291bnRzUmVmaW5lbWVudEdyb3VwSW5kZXgnXSA9PSBkYXRhQnVmZmVyWyd1cGRhdGVSZWZpbmVtZW50Q291bnRzUmVmaW5lbWVudEdyb3VwQ291bnQnXSkge1xuXHRcdHVwZGF0ZVByb2R1Y3RDb3VudEluSGVhZGVyKCk7XG5cdFx0dXBkYXRlUmVmaW5lbWVudHNJbkhlYWRlcigpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb2R1Y3RDb3VudEluSGVhZGVyKCkge1xuXHR2YXIgJHJlZmluZW1lbnRzUHJvZHVjdENvdW50ID0gJCgnLnJlZmluZW1lbnRzIC5zbG90LWdyaWQtc3ViaGVhZGVyIC5wcm9kdWN0LWNvdW50IHNwYW4nKTtcblx0dmFyICRoZWFkZXJQcm9kdWN0Q291bnQgPSAkKCcudG9wLWJhbm5lciAuc2xvdC1ncmlkLXN1YmhlYWRlciAucHJvZHVjdC1jb3VudCBzcGFuJyk7XG5cblx0aWYgKCRyZWZpbmVtZW50c1Byb2R1Y3RDb3VudC5sZW5ndGggPiAwICYmICRoZWFkZXJQcm9kdWN0Q291bnQubGVuZ3RoID4gMCkge1xuXHRcdCRoZWFkZXJQcm9kdWN0Q291bnQudGV4dCgkcmVmaW5lbWVudHNQcm9kdWN0Q291bnQudGV4dCgpKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50c0luSGVhZGVyKCkge1xuXHR2YXIgJHJlZmluZW1lbnRzUmVmaW5lbWVudHMgPSAkKCcucHJpbWFyeS1jb250ZW50IC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0dmFyICRoZWFkZXJSZWZpbmVtZW50cyA9ICQoJy50b3AtYmFubmVyIC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblxuXHRpZiAoJHJlZmluZW1lbnRzUmVmaW5lbWVudHMubGVuZ3RoID4gMCAmJiAkaGVhZGVyUmVmaW5lbWVudHMubGVuZ3RoID4gMCkge1xuXHRcdCRoZWFkZXJSZWZpbmVtZW50cy5odG1sKCRyZWZpbmVtZW50c1JlZmluZW1lbnRzLmh0bWwoKSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlTW9yZUxlc3MoJHJlZmluZW1lbnQpIHtcblx0dmFyIHJlZmluZW1lbnRJZCA9ICRyZWZpbmVtZW50LmF0dHIoJ3JlZmluZW1lbnQtaWQnKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgndWw6bm90KC5wb3B1bGFyLXNpemVzKTpub3QoLnBvcHVsYXIpJyk7XG5cdHZhciAkcmVmaW5lbWVudENvbnRhaW5lciA9ICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmNsb3Nlc3QoJy5yZWZpbmVtZW50LWJvZHktaW5uZXInKTtcblx0dmFyICRtb3JlTGluayA9ICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmZpbmQoJy5yZWYtZmlsdGVyLm1vcmUtbGluaycpLmNsb3Nlc3QoJ2xpJykuZGV0YWNoKCkuZmlyc3QoKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzID0gJHJlZmluZW1lbnRWYWx1ZXNDb250YWluZXIuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV0nKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZSA9ICRyZWZpbmVtZW50VmFsdWVzLmZpbHRlcignOm5vdChbcmVmaW5lbWVudC1jb3VudD1cIjBcIl0pJyk7XG5cblx0aWYgKCRtb3JlTGluay5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIG1vcmVMZXNzQ291bnQ7XG5cdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgJHJlZmluZW1lbnQuYXR0cigncmVmaW5lbWVudC1pZCcpID09ICdzaXplJykge1xuXHRcdFx0bW9yZUxlc3NDb3VudCA9IDEyO1xuXHRcdH0gZWxzZSBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5Sc3BVUyAmJiBvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRtb3JlTGVzc0NvdW50ID0gMTAwMDAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtb3JlTGVzc0NvdW50ID0gOTtcblx0XHR9XG5cblx0XHRpZiAoJHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmxlbmd0aCA+IG1vcmVMZXNzQ291bnQpIHtcblx0XHRcdHZhciBtb3JlTGVzc0luZGV4ID0gJHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmluZGV4KCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5lcShtb3JlTGVzc0NvdW50KSk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlc1Zpc2libGUuc2xpY2UoMCwgbW9yZUxlc3NJbmRleCkucmVtb3ZlQ2xhc3MoJ3RvZ2dsZWFibGUgaGlkZGVuJyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlc1Zpc2libGUuc2xpY2UobW9yZUxlc3NJbmRleCwgJHJlZmluZW1lbnRWYWx1ZXMubGVuZ3RoKS5hZGRDbGFzcygndG9nZ2xlYWJsZSBoaWRkZW4nKTtcblx0XHRcdCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5lcShtb3JlTGVzc0luZGV4IC0gMSkuYWZ0ZXIoJG1vcmVMaW5rKTtcblx0XHRcdCRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmZpbmQoJy5tb3JlLWxpbmstY29udGFpbmVyJykuc2hvdygpO1xuXHRcdFx0JHJlZmluZW1lbnRDb250YWluZXIuZmluZCgnLmxlc3MtcmVmaW5lbWVudCcpLnNob3coKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLnJlbW92ZUNsYXNzKCd0b2dnbGVhYmxlIGhpZGRlbicpO1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmVxKCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5sZW5ndGggLSAxKS5hZnRlcigkbW9yZUxpbmspO1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNDb250YWluZXIuZmluZCgnLm1vcmUtbGluay1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHQkcmVmaW5lbWVudENvbnRhaW5lci5maW5kKCcubGVzcy1yZWZpbmVtZW50JykuaGlkZSgpO1xuXHRcdH1cblx0fVxuXG5cdGlmICghJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpIHx8IHdpbmRvdy5pbm5lcldpZHRoID4gNzY3KSB7XG5cdFx0aWYgKHJlZmluZW1lbnRzRXhwYW5kZWQpIHtcblx0XHRcdGlmIChyZWZpbmVtZW50c0V4cGFuZGVkLmluZGV4T2YocmVmaW5lbWVudElkKSA+IC0xKSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmFkZENsYXNzKCdleHBhbmRlZCcpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcudG9nZ2xlJykuYWRkQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUtY29udGVudCcpLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUNsYXNzKCdleHBhbmRlZCcpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcudG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUtY29udGVudCcpLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCQoJy5yZWZpbmVtZW50LmV4cGFuZGVkJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnLnJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ3JlZmluZW1lbnQtZXhwYW5kZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ3JlZmluZW1lbnQtZXhwYW5kZWQnKTtcblx0XHR9XG5cblx0XHRpZiAocmVmaW5lbWVudHNWaWV3QWxsICYmICRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5sZW5ndGggPiBtb3JlTGVzc0NvdW50KSB7XG5cdFx0XHRpZiAocmVmaW5lbWVudHNWaWV3QWxsLmluZGV4T2YocmVmaW5lbWVudElkKSA+IC0xKSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmFkZENsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGVhYmxlJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcubW9yZS1saW5rLWNvbnRhaW5lcicpLmNzcygnZGlzcGxheScsICdub25lJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy5sZXNzLXJlZmluZW1lbnQudG9nZ2xlYWJsZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUNsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy5tb3JlLWxpbmstY29udGFpbmVyJykuY3NzKCdkaXNwbGF5JywgJ2xpc3QtaXRlbScpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcubGVzcy1yZWZpbmVtZW50LnRvZ2dsZWFibGUnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbnZhciByZWZHcm91cHNTdGF0ZXMgPSB7XG5cdFx0Y29va2llUmVmR3JvdXBzS2V5OiAncmVmZ3JvdXAnLFxuXHRcdHNhdmVTdGF0ZTogZnVuY3Rpb24ocmVmZ3JvdXAsIHZpc2libGUpIHtcblx0XHRcdGlmICh0aGlzLmdldENvb2tpZSgnZHdfY29va2llc19hY2NlcHRlZCcpKSB7XG5cdFx0XHRcdHZhciBnZXRSZWZHcm91cENvb2tpZSA9IHRoaXMuZ2V0Q29va2llKHRoaXMuY29va2llUmVmR3JvdXBzS2V5KSB8fCAne30nO1xuXHRcdFx0XHR2YXIgZ2V0UmVmR3JvdXBPYmogPSBKU09OLnBhcnNlKGdldFJlZkdyb3VwQ29va2llKTtcblx0XHRcdFx0Z2V0UmVmR3JvdXBPYmpbcmVmZ3JvdXBdID0gdmlzaWJsZTtcblx0XHRcdFx0Z2V0UmVmR3JvdXBDb29raWUgPSBKU09OLnN0cmluZ2lmeShnZXRSZWZHcm91cE9iaik7XG5cdFx0XHRcdHRoaXMuc2V0Q29va2llKCdyZWZncm91cCcsIGdldFJlZkdyb3VwQ29va2llKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGNoZWNrU3RhdGU6IGZ1bmN0aW9uKHJlZmdyb3VwKSB7XG5cdFx0XHRpZiAodGhpcy5nZXRDb29raWUoJ2R3X2Nvb2tpZXNfYWNjZXB0ZWQnKSkge1xuXHRcdFx0XHR2YXIgZ2V0UmVmR3JvdXBDb29raWUgPSB0aGlzLmdldENvb2tpZSh0aGlzLmNvb2tpZVJlZkdyb3Vwc0tleSk7XG5cdFx0XHRcdGlmIChnZXRSZWZHcm91cENvb2tpZSkge1xuXHRcdFx0XHRcdHZhciBnZXRSZWZHcm91cE9iaiA9IEpTT04ucGFyc2UoZ2V0UmVmR3JvdXBDb29raWUpO1xuXHRcdFx0XHRcdGlmIChnZXRSZWZHcm91cE9ialtyZWZncm91cF0gIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZ2V0UmVmR3JvdXBPYmpbcmVmZ3JvdXBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblx0XHRnZXRDb29raWU6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHQgICAgdmFyIGNvb2tpZXMgPSBkb2N1bWVudC5jb29raWUuc3BsaXQoJzsnKTtcblx0XHQgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb29raWVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0ICAgICAgICB2YXIgdG9rZW5zID0gY29va2llc1tpXS5zcGxpdCgnPScpO1xuXHRcdCAgICAgICAgdmFyIGNvb2tpZUtleSA9IHRva2Vuc1swXS50cmltKCk7XG5cdFx0ICAgICAgICBpZiAoY29va2llS2V5ID09PSBrZXkpIHtcblx0XHQgICAgICAgICAgICByZXR1cm4gdG9rZW5zWzFdO1xuXHRcdCAgICAgICAgfVxuXHRcdCAgICB9XG5cdFx0ICAgIHJldHVybiAnJztcblx0XHR9LFxuXHRcdHNldENvb2tpZTogZnVuY3Rpb24oa2V5LCB2YWx1ZSwgbWludXRlcykge1xuXHRcdCAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0ICAgIGRhdGUuc2V0VGltZShkYXRlICsgKG1pbnV0ZXMgKiA2MCAqIDEwMDApKTtcblx0XHQgICAgZG9jdW1lbnQuY29va2llID0ga2V5ICsgJz0nICsgdmFsdWUgKyAnOyBleHBpcmVzPScgKyBkYXRlLnRvR01UU3RyaW5nKCkgKyAnOyBwYXRoPS8nO1xuXHRcdH1cbn1cblxuZnVuY3Rpb24gc2VhcmNoU3RvcmVzKCkge1xuXHR2YXIgc2VhcmNoU3RvcmVzUXVlcnkgPSAkKCcuc2VhcmNoLXN0b3Jlcy1xdWVyeScpO1xuXG5cdCQoJy5nby1maW5kLXN0b3JlcycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGVsID0gJChlLnRhcmdldCksXG5cdFx0XHRkYXRhID0ge1xuXHRcdFx0XHR0eXBlS2V5OiBlbC5hdHRyKCd0eXBlJylcblx0XHRcdH07XG5cblx0XHRpZiAoZWwuYXR0cigndHlwZScpID09PSAnZ2VvJykge1xuXHRcdFx0aWYgKG5hdmlnYXRvci5nZW9sb2NhdGlvbikge1xuXHRcdFx0XHRuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0XHRcdFx0ZGF0YS5sb25naXR1ZGUgPSBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlO1xuXHRcdFx0XHRcdGRhdGEubGF0aXR1ZGUgPSBwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGU7XG5cblx0XHRcdFx0XHRzZWFyY2hTdG9yZXNBSkFYKGRhdGEpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFsZXJ0KCdZb3VyIGJyb3dzZXIgbm90IHN1cHBvcnRlZCBnZW9sb2NhdGlvbicpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRhLnNlYXJjaEtleSA9IHNlYXJjaFN0b3Jlc1F1ZXJ5LnZhbCgpLnRyaW0oKTtcblxuXHRcdFx0dmFyIGdlb2NvZGVyID0gbmV3IGdvb2dsZS5tYXBzLkdlb2NvZGVyKCk7XG5cdFx0XHRnZW9jb2Rlci5nZW9jb2RlKCB7ICdhZGRyZXNzJzogc2VhcmNoU3RvcmVzUXVlcnkudmFsKCkudHJpbSgpfSwgZnVuY3Rpb24ocmVzdWx0cywgc3RhdHVzKSB7XG5cdFx0XHRcdGlmIChzdGF0dXMgPT0gZ29vZ2xlLm1hcHMuR2VvY29kZXJTdGF0dXMuT0spIHtcblx0XHRcdFx0ICBcdGRhdGEubG9uZ2l0dWRlID0gcmVzdWx0c1swXS5nZW9tZXRyeS5sb2NhdGlvbi5sbmcoKTtcblx0XHRcdFx0ICBcdGRhdGEubGF0aXR1ZGUgPSByZXN1bHRzWzBdLmdlb21ldHJ5LmxvY2F0aW9uLmxhdCgpO1xuXG5cdFx0XHRcdCAgXHRzZWFyY2hTdG9yZXNBSkFYKGRhdGEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGFsZXJ0KFwiR2VvY29kZSB3YXMgbm90IHN1Y2Nlc3NmdWwgZm9yIHRoZSBmb2xsb3dpbmcgcmVhc29uOiBcIiArIHN0YXR1cyk7XG5cdFx0XHRcdH1cblx0XHQgICAgfSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2VhcmNoU3RvcmVzQUpBWChwYXJhbXMpIHtcblx0JC5hamF4KHtcblx0XHR0eXBlOiAnZ2V0Jyxcblx0XHR1cmw6IFVybHMuc2VhcmNoU3RvcmVzLFxuXHRcdGRhdGE6IHBhcmFtcyxcblxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR2YXIgcG9wdXBMaXN0ID0gJCgnLmNhdGVnb3J5LXBvcHVwLWxpc3Qtc3RvcmVzJyk7XG5cblx0XHRcdCQoJy5ncmlkLXBhZ2Utc3RvcmVzZWxlY3Rvci1wb3B1cCcpLmRpYWxvZygnY2xvc2UnKTtcblx0XHRcdHBvcHVwTGlzdFxuXHRcdFx0XHQuaHRtbChkYXRhKVxuXHRcdFx0XHQuZGlhbG9nKHtcblx0XHRcdFx0XHR3aWR0aDogNDUwLFxuXHRcdFx0XHRcdGF1dG9PcGVuOiBmYWxzZSxcblx0XHRcdFx0XHRtb2RhbDogdHJ1ZSxcblx0XHRcdFx0XHRyZXNpemFibGU6IGZhbHNlXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRwb3B1cExpc3QucGFyZW50KCkuZmluZCgnLnVpLWRpYWxvZy10aXRsZScpLmh0bWwoZGF0YS5tYXRjaCgvU3RvcmVzIG5lYXIuezAsfS9taSlbMF0ucmVwbGFjZSgnPC9zcGFuPicsICcnKSk7XG5cdFx0XHRwb3B1cExpc3QuZGlhbG9nKCdvcGVuJyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2hvd1ZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmcoKSB7XG4gIFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Cb3BpcyAmJiBvcHRpb25zLkJvcGlzLklzTG9jYXRpb25TZWFyY2hGaWx0ZXJlZCkge1xuXHRcdHJldHVybjtcblx0fVxuXG4gICQuYWpheCh7XG4gICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgdXJsOiBwYWdlLnZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmdVcmwsXG4gICAgICBhc3luYzogdHJ1ZVxuICB9KVxuICAvLyBzdWNjZXNzXG4gIC5kb25lKGZ1bmN0aW9uICh2YWx1ZXMpIHtcblx0ICBpZiAodmFsdWVzKSB7XG5cdFx0ICB2YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuXHRcdFx0ICB2YXIgJHRpbGUgPSAkKCdbZGF0YS1pdGVtaWQ9XCInICsgdmFsLm1hc3RlclByb2R1Y3RJRCArICdcIl0nKTtcblx0XHRcdCAgaWYgKCR0aWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0ICBpZiAoIHR5cGVvZiB2YWwudXJsSGFzaCAhPSAndW5kZWZpbmVkJyApIHtcblx0XHRcdFx0XHQgIHZhciBmaWx0ZXJQID0gdmFsLnVybEhhc2gucmVwbGFjZSgnIycsJycpLnNwbGl0KCc9JylbMF07XG5cdFx0XHRcdFx0ICB2YXIgcnIgPSBuZXcgUmVnRXhwKFwicHJlZm5bMC05XT1cIitmaWx0ZXJQKTtcblx0XHRcdFx0XHQgIGlmICggbG9jYXRpb24uaHJlZi5tYXRjaChycikgKSB7XG5cdFx0XHRcdFx0XHQgIGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuXHRcdFx0XHRcdFx0XHQvL1B1dCB0aGUgaW52ZW50b3J5IG1lc3NhZ2UgaW4gdGhlIHByb2R1Y3QgYmFkZ2UgaWYgdmFyaWFudFdoc0luU3RvY2sgaXMgZmFsc2Vcblx0XHRcdFx0XHRcdFx0dmFyIHByb2R1Y3RCYWRnZSA9ICR0aWxlLmZpbmQoJy5wcm9kdWN0LWJhZGdlLndocy1pbi1zdG9jaycpO1xuXHRcdFx0XHRcdFx0XHRpZiAodmFsLnZhcmlhbnRXaHNJblN0b2NrID09ICd0cnVlJykge1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAodmFsLmRyb3BzaGlwTGVhZCA8PSAxMCkge1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS50ZXh0KHZhbC5pbnZlbnRvcnlNc2cpO1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS5yZW1vdmVDbGFzcygnd2hzLWluLXN0b2NrJykuYWRkQ2xhc3MoJ2F2YWlsYWJpbGl0eS1tc2cnKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0ICB9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR2YXIgJG1zZyA9ICQoJzxkaXYgLz4nKS5hdHRyKCdjbGFzcycsICdhdmFpbGFiaWxpdHktbXNnJykudGV4dCh2YWwuaW52ZW50b3J5TXNnKTsgXG5cdFx0XHRcdFx0XHRcdCR0aWxlLmZpbmQoJy5wcm9kdWN0LXByaWNpbmcnKS5hcHBlbmQoJG1zZyk7XG5cdFx0XHRcdFx0XHRcdGlmICh2YWwudmFyaWFudFdoc0luU3RvY2sgPT0gJ3RydWUnKSB7XG5cdFx0XHRcdFx0XHRcdFx0JHRpbGUuZmluZCgnLndocy1pbi1zdG9jaycpLnNob3coKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ICB9XG5cdFx0XHRcdFx0ICB9XG5cdFx0XHRcdCAgfVxuXHRcdFx0ICB9XG5cdFx0ICB9KTtcblx0ICB9XG4gIH0pXG4gIC5mYWlsKGZ1bmN0aW9uICh4aHIsIHRleHRTdGF0dXMpIHtcbiAgICAgIGlmICh0ZXh0U3RhdHVzID09PSAncGFyc2VyZXJyb3InKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ0ludmVudG9yeSBNZXNzYWdpbmcgRXJyb3IgJyArIFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gc2F2ZVNjcm9sbFBvc2l0aW9uKCkge1xuXHRpZiAoc2Vzc2lvblN0b3JhZ2UpIHtcblx0XHQkKGRvY3VtZW50KS5vZmYoJ3Njcm9sbC5TY3JvbGxQb3NpdGlvblNhdmUnKS5vbignc2Nyb2xsLlNjcm9sbFBvc2l0aW9uU2F2ZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHR2YXIgY2F0ZWdvcnlJZCA9ICQoJy5jdXJyQ0dJRCcpLnZhbCgpO1xuXHRcdFx0dmFyIHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb247XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID0gSlNPTi5wYXJzZShzZXNzaW9uU3RvcmFnZS5TY3JvbGxQb3NpdGlvbik7XG5cdFx0XHR9IGNhdGNoKGV4Y2VwdGlvbikge31cblx0XHRcdGlmICghc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiB8fCB0eXBlb2Ygc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiAhPSAnb2JqZWN0JyB8fCAhc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbltjYXRlZ29yeUlkXSkge1xuXHRcdFx0XHRzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID0ge307XHRcblx0XHRcdH1cblx0XHRcdHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb25bY2F0ZWdvcnlJZF0gPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCk7XG5cdFx0XHRzZXNzaW9uU3RvcmFnZS5TY3JvbGxQb3NpdGlvbiA9IEpTT04uc3RyaW5naWZ5KHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb24pO1xuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGxvYWRTY3JvbGxQb3NpdGlvbigpIHtcblx0aWYgKHNlc3Npb25TdG9yYWdlKSB7XG5cdFx0dmFyIGNhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0XHR2YXIgc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbjtcblx0XHR0cnkge1xuXHRcdFx0c2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiA9IEpTT04ucGFyc2Uoc2Vzc2lvblN0b3JhZ2UuU2Nyb2xsUG9zaXRpb24pO1xuXHRcdH0gY2F0Y2goZXhjZXB0aW9uKSB7fVxuXHRcdGlmIChzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uICYmIHR5cGVvZiBzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID09ICdvYmplY3QnICYmIHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb25bY2F0ZWdvcnlJZF0pIHtcblx0XHRcdCQod2luZG93KS5zY3JvbGxUb3Aoc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbltjYXRlZ29yeUlkXSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVTdGlja3lSZWZpbmVtZW50cygpIHtcblx0JChkb2N1bWVudCkub2ZmKCdzY3JvbGwuU3RpY2t5UmVmaW5lbWVudHMgU3RpY2t5UmVmaW5lbWVudHMuUmVmcmVzaCcpLm9uKCdzY3JvbGwuU3RpY2t5UmVmaW5lbWVudHMgU3RpY2t5UmVmaW5lbWVudHMuUmVmcmVzaCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyICRyZWZpbmVtZW50cyA9ICQoJyNzZWNvbmRhcnknKTtcblx0XHR2YXIgJHByaW1hcnkgPSAkKCcjcHJpbWFyeScpO1xuXG5cdFx0aWYgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSB8fCB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRcdCRyZWZpbmVtZW50cy5jc3MoJ3RyYW5zZm9ybScsICcnKTtcblx0XHRcdCRyZWZpbmVtZW50cy5zY3JvbGxUb3AoMCk7XG5cdFx0XHQkcmVmaW5lbWVudHMuaGVpZ2h0KCdhdXRvJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBkb2N1bWVudFNjcm9sbFRvcCA9IHBhcnNlSW50KCQoZG9jdW1lbnQpLnNjcm9sbFRvcCgpLCAxMCk7XG5cdFx0XHR2YXIgZG9jdW1lbnRTY3JvbGxEZWx0YSA9IDA7XG5cdFx0XHRpZiAoZGF0YUJ1ZmZlclsnZG9jdW1lbnRTY3JvbGxUb3AnXSkge1xuXHRcdFx0XHRkb2N1bWVudFNjcm9sbERlbHRhID0gZG9jdW1lbnRTY3JvbGxUb3AgLSBkYXRhQnVmZmVyWydkb2N1bWVudFNjcm9sbFRvcCddO1xuXHRcdFx0fVxuXHRcdFx0dmFyIHdpbmRvd0hlaWdodCA9IHBhcnNlSW50KCQod2luZG93KS5oZWlnaHQoKSwgMTApO1xuXHRcdFx0dmFyIHdpbmRvd0JvdHRvbSA9IGRvY3VtZW50U2Nyb2xsVG9wICsgd2luZG93SGVpZ2h0O1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0ID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzWzBdLnNjcm9sbEhlaWdodCwgMTApO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzT2Zmc2V0VG9wID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzLm9mZnNldCgpLnRvcCwgMTApO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzLm9mZnNldCgpLnRvcCArIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0LCAxMCk7XG5cdFx0XHR2YXIgcHJpbWFyeVRvcCA9IHBhcnNlSW50KCRwcmltYXJ5Lm9mZnNldCgpLnRvcCwgMTApO1xuXHRcdFx0dmFyIHByaW1hcnlCb3R0b20gPSBwcmltYXJ5VG9wICsgcGFyc2VJbnQoJHByaW1hcnkub3V0ZXJIZWlnaHQoKSwgMTApO1xuXHRcdFx0dmFyIGRvY3VtZW50U2Nyb2xsVG9wRnJvbVByaW1hcnlUb3AgPSBkb2N1bWVudFNjcm9sbFRvcCAtIHByaW1hcnlUb3A7XG4gICAgICAgICAgICBpZiAoZG9jdW1lbnRTY3JvbGxUb3BGcm9tUHJpbWFyeVRvcCA8IDApIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudFNjcm9sbFRvcEZyb21QcmltYXJ5VG9wID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB3aW5kb3dCb3R0b21Gcm9tUHJpbWFyeUJvdHRvbSA9IHdpbmRvd0JvdHRvbSAtIHByaW1hcnlCb3R0b207XG4gICAgICAgICAgICBpZiAod2luZG93Qm90dG9tRnJvbVByaW1hcnlCb3R0b20gPCAwKSB7XG4gICAgICAgICAgICAgICAgd2luZG93Qm90dG9tRnJvbVByaW1hcnlCb3R0b20gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlZmluZW1lbnRzT2Zmc2V0VG9wTmV3O1xuICAgICAgICAgICAgdmFyIHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tTmV3O1xuICAgICAgICAgICAgaWYgKGRvY3VtZW50U2Nyb2xsRGVsdGEpIHtcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50c09mZnNldFRvcE5ldyA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wICsgZG9jdW1lbnRTY3JvbGxEZWx0YTtcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50c09mZnNldEJvdHRvbU5ldyA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wTmV3ICsgcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG4gICAgICAgICAgICB9XG5cblx0XHRcdHZhciByZWZpbmVtZW50c1RyYW5zbGF0ZVk7XG5cdFx0XHRpZiAoJHJlZmluZW1lbnRzLm91dGVySGVpZ2h0KCkgPj0gJHByaW1hcnkub3V0ZXJIZWlnaHQoKSkge1xuXHRcdFx0XHRyZWZpbmVtZW50c1RyYW5zbGF0ZVkgPSAwO1xuXHRcdFx0fSBlbHNlIGlmIChkb2N1bWVudFNjcm9sbERlbHRhID49IDApIHtcblx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcmVmaW5lbWVudHNPZmZzZXRUb3AgLSBwcmltYXJ5VG9wO1xuXG5cdFx0XHRcdGlmICgkcmVmaW5lbWVudHMuaGFzQ2xhc3MoJ3RvcCcpKSB7XG5cdFx0XHRcdFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdzdGlja3ktcmVmaW5lbWVudHMnKTtcblx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRyZWZpbmVtZW50c1RyYW5zbGF0ZVkgPSByZWZpbmVtZW50c1RyYW5zbGF0ZVkgLSBkb2N1bWVudFNjcm9sbERlbHRhO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tID49IHByaW1hcnlCb3R0b20pIHtcblx0XHRcdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHByaW1hcnlCb3R0b20gLSBwcmltYXJ5VG9wIC0gcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVmaW5lbWVudHNPZmZzZXRCb3R0b20gPCB3aW5kb3dCb3R0b20gJiYgcHJpbWFyeUJvdHRvbSA+PSB3aW5kb3dCb3R0b20pIHtcblx0XHRcdFx0XHRpZiAocmVmaW5lbWVudHNTY3JvbGxIZWlnaHQgPiB3aW5kb3dIZWlnaHQpIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygnYm90dG9tJyk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChkb2N1bWVudFNjcm9sbFRvcCA+PSBwcmltYXJ5VG9wKSB7XG5cdFx0XHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMuYWRkQ2xhc3MoJ3RvcCcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmIChyZWZpbmVtZW50c09mZnNldEJvdHRvbSA8IHdpbmRvd0JvdHRvbSAmJiBwcmltYXJ5Qm90dG9tIDwgd2luZG93Qm90dG9tKSB7XG5cdFx0XHRcdFx0aWYgKChkb2N1bWVudFNjcm9sbFRvcCArIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0KSA+IHByaW1hcnlCb3R0b20pIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHByaW1hcnlCb3R0b20gLSBwcmltYXJ5VG9wIC0gcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygndG9wJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKGRvY3VtZW50U2Nyb2xsRGVsdGEgPCAwKSB7XG5cdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wIC0gcHJpbWFyeVRvcDtcblxuXHRcdFx0XHRpZiAoJHJlZmluZW1lbnRzLmhhc0NsYXNzKCdib3R0b20nKSkge1xuXHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcmVmaW5lbWVudHNUcmFuc2xhdGVZIC0gZG9jdW1lbnRTY3JvbGxEZWx0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChyZWZpbmVtZW50c09mZnNldFRvcCA8PSBwcmltYXJ5VG9wICYmIGRvY3VtZW50U2Nyb2xsVG9wIDw9IHByaW1hcnlUb3ApIHtcblx0XHRcdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IDA7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVmaW5lbWVudHNPZmZzZXRCb3R0b20gPj0gcHJpbWFyeUJvdHRvbSAmJiByZWZpbmVtZW50c09mZnNldFRvcCA8PSBkb2N1bWVudFNjcm9sbFRvcCkge1xuXHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcHJpbWFyeUJvdHRvbSAtIHByaW1hcnlUb3AgLSByZWZpbmVtZW50c1Njcm9sbEhlaWdodDtcblx0XHRcdFx0fSBlbHNlIGlmIChyZWZpbmVtZW50c09mZnNldFRvcCA+PSBkb2N1bWVudFNjcm9sbFRvcCAmJiByZWZpbmVtZW50c09mZnNldFRvcCA+IHByaW1hcnlUb3ApIHtcblx0XHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygndG9wJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKHJlZmluZW1lbnRzVHJhbnNsYXRlWSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0JHJlZmluZW1lbnRzLmNzcygndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZVkoJyArIHJlZmluZW1lbnRzVHJhbnNsYXRlWSArICdweCknKTtcblx0XHRcdH1cblxuXHRcdFx0ZGF0YUJ1ZmZlclsnZG9jdW1lbnRTY3JvbGxUb3AnXSA9IGRvY3VtZW50U2Nyb2xsVG9wO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVTdGlja3lTdWJoZWFkZXIoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignc2Nyb2xsLlN0aWNreVN1YmhlYWRlcicpLm9uKCdzY3JvbGwuU3RpY2t5U3ViaGVhZGVyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHNsb3RHcmlkU3ViaGVhZGVyID0gJCgnLnNsb3QtZ3JpZC1zdWJoZWFkZXInKTtcblx0XHR2YXIgJHNsb3RHcmlkU3ViaGVhZGVyRml4ZWQgPSAkKCcuc2xvdC1ncmlkLXN1YmhlYWRlci1maXhlZCcpO1xuXHRcdGlmICgkc2xvdEdyaWRTdWJoZWFkZXIubGVuZ3RoID4gMCAmJiAkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5sZW5ndGggPiAwKSB7XG5cdFx0XHR2YXIgJHByaW1hcnkgPSAkKCcjcHJpbWFyeScpO1xuXHRcdFx0dmFyIGRvY3VtZW50U2Nyb2xsVG9wID0gJChkb2N1bWVudCkuc2Nyb2xsVG9wKCk7XG5cdFx0XHR2YXIgd2luZG93SGVpZ2h0ID0gJCh3aW5kb3cpLmhlaWdodCgpO1xuXHRcdFx0dmFyIHdpbmRvd0JvdHRvbSA9IGRvY3VtZW50U2Nyb2xsVG9wICsgd2luZG93SGVpZ2h0O1xuXHRcdFx0dmFyIHByaW1hcnlUb3AgPSAkcHJpbWFyeS5vZmZzZXQoKS50b3A7XG5cdFx0XHR2YXIgcHJpbWFyeUJvdHRvbSA9IHByaW1hcnlUb3AgKyAkcHJpbWFyeS5vdXRlckhlaWdodCgpO1xuXG5cdFx0XHRpZiAocHJpbWFyeUJvdHRvbSA8IHdpbmRvd0JvdHRvbSkge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9IGVsc2UgaWYgKCRzbG90R3JpZFN1YmhlYWRlci5vZmZzZXQoKS50b3AgPCBkb2N1bWVudFNjcm9sbFRvcCkge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVJlZmluZW1lbnRGaWx0ZXJCeVRleHQoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZigna2V5dXAuUmVmaW5lbWVudEZpbHRlclRleHQnKS5vbigna2V5dXAuUmVmaW5lbWVudEZpbHRlclRleHQnLCAnLnJlZmluZW1lbnQgLnJlZmluZW1lbnQtZmlsdGVyLXRleHQgaW5wdXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIGZpbHRlclRleHQgPSAkdGhpcy52YWwoKTtcblx0XHR2YXIgZmlsdGVyVGV4dFJlZ0V4O1xuXHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQtZmlsdGVyLXRleHQnKTtcblx0XHR2YXIgJHJlc2V0ID0gJGNvbnRhaW5lci5maW5kKCdhLnJlc2V0Jyk7XG5cdFx0dmFyICRub1Jlc3VsdHMgPSAkY29udGFpbmVyLmZpbmQoJy5uby1yZXN1bHRzJyk7XG5cdFx0dmFyICRyZWZpbmVtZW50ID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKTtcblx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZXMgPSAkdGhpcy5jbG9zZXN0KCcuY2hlY2tzLWNvbnRhaW5lcicpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlXTpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpO1xuXG5cdFx0aWYgKGZpbHRlclRleHQpIHtcblx0XHRcdGZpbHRlclRleHRSZWdFeCA9IG5ldyBSZWdFeHAoJ14nICsgZmlsdGVyVGV4dCArICd8ICcgKyBmaWx0ZXJUZXh0LCAnZ2knKTtcblx0XHRcdCRyZXNldC5hZGRDbGFzcygnc2hvdycpO1xuXHRcdFx0JHJlZmluZW1lbnQuYWRkQ2xhc3MoJ2ZpbHRlci10ZXh0Jyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdHZhciAkcmVmaW5lbWVudFZhbHVlID0gJCh0aGlzKTtcblx0XHRcdFx0aWYgKCRyZWZpbmVtZW50VmFsdWUuYXR0cigncmVmaW5lbWVudC12YWx1ZScpLm1hdGNoKGZpbHRlclRleHRSZWdFeCkpIHtcblx0XHRcdFx0XHQkcmVmaW5lbWVudFZhbHVlLmFkZENsYXNzKCdmaWx0ZXItdGV4dC1zaG93Jyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRWYWx1ZS5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQtc2hvdycpLmhpZGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAoJHJlZmluZW1lbnRWYWx1ZXMuZmlsdGVyKCc6dmlzaWJsZScpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdCRub1Jlc3VsdHMuZmluZCgnc3BhbicpLnRleHQoZmlsdGVyVGV4dCk7XG5cdFx0XHRcdCRub1Jlc3VsdHMuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JG5vUmVzdWx0cy5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXNldC5yZW1vdmVDbGFzcygnc2hvdycpO1xuXHRcdFx0JHJlZmluZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZpbHRlci10ZXh0Jyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlcy5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQtc2hvdycpLmNzcygnZGlzcGxheScsICcnKTtcblx0XHRcdCRub1Jlc3VsdHMuaGlkZSgpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5SZWZpbmVtZW50RmlsdGVyVGV4dFJlc2V0Jykub24oJ2NsaWNrLlJlZmluZW1lbnRGaWx0ZXJUZXh0UmVzZXQnLCAnLnJlZmluZW1lbnQgLnJlZmluZW1lbnQtZmlsdGVyLXRleHQgYS5yZXNldCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJy5yZWZpbmVtZW50LWZpbHRlci10ZXh0Jyk7XG5cdFx0dmFyICRub1Jlc3VsdHMgPSAkY29udGFpbmVyLmZpbmQoJy5uby1yZXN1bHRzJyk7XG5cdFx0dmFyICRyZWZpbmVtZW50ID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKTtcblx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZXMgPSAkdGhpcy5jbG9zZXN0KCcuY2hlY2tzLWNvbnRhaW5lcicpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlXScpO1xuXG5cdFx0JHRoaXMucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQnKTtcblx0XHQkcmVmaW5lbWVudC5maW5kKCcucmVmaW5lbWVudC1maWx0ZXItdGV4dCBpbnB1dCcpLnZhbCgnJyk7XG5cdFx0JHJlZmluZW1lbnRWYWx1ZXMucmVtb3ZlQ2xhc3MoJ2ZpbHRlci10ZXh0LXNob3cnKS5jc3MoJ2Rpc3BsYXknLCAnJyk7XG5cdFx0JG5vUmVzdWx0cy5oaWRlKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzYXZlRXhwYW5kZWRSZWZpbmVtZW50cygpIHtcblx0cmVmaW5lbWVudHNFeHBhbmRlZCA9ICQoJy5yZWZpbmVtZW50cyBbcmVmaW5lbWVudC1pZF0uZXhwYW5kZWQnKS5tYXAoZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gJCh0aGlzKS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdH0pLmdldCgpO1xuXG5cdHJlZmluZW1lbnRzVmlld0FsbCA9ICQoJy5yZWZpbmVtZW50cyBbcmVmaW5lbWVudC1pZF0ubW9yZS1leHBhbmRlZCcpLm1hcChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHJldHVybiAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtaWQnKTtcblx0fSkuZ2V0KCk7XG59XG5cbmZ1bmN0aW9uIHJlZHJhd1Nob3BNeVN0b3JlKCkge1xuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0dXJsOiB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoVXJscy5TdG9yZXMuR2V0U2hvcE15U3RvcmVQYW5lbCArIGxvY2F0aW9uLnNlYXJjaCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSksXG5cdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHQkKCcuc2hvcC1teS1zdG9yZScpLnJlcGxhY2VXaXRoKGRhdGEpO1xuXHRcdFx0dXBkYXRlU2hvcE15U3RvcmUoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaG9wTXlTdG9yZSgpIHtcblx0aWYgKCQoJy5zaG9wLW15LXN0b3JlLXRvZ2dsZSBpbnB1dDpjaGVja2VkJykubGVuZ3RoID4gMCkge1xuXHRcdCQoJ2JvZHknKS5hdHRyKCdpcy1zaG9wLW15LXN0b3JlLWFjdGl2ZScsIHRydWUpO1xuXHR9IGVsc2Uge1xuXHRcdCQoJ2JvZHknKS5hdHRyKCdpcy1zaG9wLW15LXN0b3JlLWFjdGl2ZScsIGZhbHNlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplUmFuZ2VmaW5kZXJFdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suUmVmaW5lbWVudEZpbHRlclRleHRSZXNldCcpLm9uKCdjbGljay5SZWZpbmVtZW50RmlsdGVyVGV4dFJlc2V0JywgJy5wcm9kdWN0LXRpbGUgYScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRwcm9kdWN0ID0gJHRoaXMuY2xvc2VzdCgnW2RhdGEtaXRlbWlkXScpO1xuXHRcdGlmICgkcHJvZHVjdC5sZW5ndGggPiAwKSB7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdFx0ZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMucHJvZHVjdERldGFpbCwgJ3BpZCcsICRwcm9kdWN0LmF0dHIoJ2RhdGEtaXRlbWlkJykpLFxuXHRcdFx0XHRjYWxsYmFjazogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuICAgICAgICAgICAgfSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUJvb3RGaW5kZXJFdmVudHMoKSB7XG5cdHZhciAkYm9vdEZpbmRlclJlc3VsdHNCYW5uZXIgPSAkKCcuYm9vdGZpbmRlci1yZXN1bHRzYmFubmVyJyk7XG5cdGlmICgkYm9vdEZpbmRlclJlc3VsdHNCYW5uZXIgJiYgJGJvb3RGaW5kZXJSZXN1bHRzQmFubmVyLmxlbmd0aCkge1xuXHRcdCRib290RmluZGVyRW1haWxGb3JtID0gJGJvb3RGaW5kZXJSZXN1bHRzQmFubmVyLmZpbmQoJ2Zvcm0uZW1haWwnKTtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3IgPSAkYm9vdEZpbmRlckVtYWlsRm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3Iuc2V0dGluZ3Mub25mb2N1c291dCA9IFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwub25mb2N1c291dDtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3Iuc2V0dGluZ3MuZXJyb3JQbGFjZW1lbnQgPSBWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsLmVycm9yUGxhY2VtZW50O1xuXHRcdCRib290RmluZGVyRW1haWxGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJlbWFpbFwiXScpLnJ1bGVzKCdhZGQnLCAkLmV4dGVuZChWYWxpZGF0aW9uUnVsZXMuRW1haWwsIHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0bWVzc2FnZXM6IHtcblx0XHRcdFx0cmVxdWlyZWQ6ICQudmFsaWRhdG9yLmZvcm1hdCgnUGxlYXNlIGVudGVyIGFuIGVtYWlsIGFkZHJlc3MuJylcblx0XHRcdH1cblx0XHR9KSk7XG5cdFx0JGJvb3RGaW5kZXJFbWFpbEZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInVzZXJhZ3JlZW1lbnRcIl0nKS5ydWxlcygnYWRkJywge1xuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRtZXNzYWdlczoge1xuXHRcdFx0XHRyZXF1aXJlZDogJC52YWxpZGF0b3IuZm9ybWF0KCdQbGVhc2UgYWdyZWUgdG8gdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zLicpXG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJSZXN1bHRzRW1haWwnKS5vbignY2xpY2suQm9vdEZpbmRlclJlc3VsdHNFbWFpbCcsICcuYm9vdGZpbmRlci1yZXN1bHRzYmFubmVyIC5idG4uc2VuZC1yZXN1bHRzLWVtYWlsJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGlmICgkYm9vdEZpbmRlckVtYWlsRm9ybSAmJiAkYm9vdEZpbmRlckVtYWlsRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnZm9ybScpO1xuXHRcdFx0XHQkY29udGFpbmVyLmxvYWRpbmcoJC5leHRlbmQobG9hZGluZ0luZGljYXRvclNldHRpbmdzLCB7XG5cdFx0XHRcdFx0SXNMYWJlbFNob3duOiB0cnVlLFxuXHRcdFx0XHRcdENvbnRlbnQ6ICdTZW5kaW5nIEVtYWlsLi4uJ1xuXHRcdFx0XHR9KSk7XG5cdFx0XHRcdHZhciB1cmxQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh3aW5kb3cubG9jYXRpb24uaHJlZik7XG5cdFx0XHRcdHZhciBib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCA9IFVybHMuQm9vdEZpbmRlci5TZW5kUmVzdWx0c0VtYWlsO1xuXHRcdFx0XHRib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSk7XG5cdFx0XHRcdGZvciAodmFyIHVybFBhcmFtZXRlciBpbiB1cmxQYXJhbWV0ZXJzKSB7XG5cdFx0XHRcdFx0aWYgKHVybFBhcmFtZXRlcnNbdXJsUGFyYW1ldGVyXSkge1xuXHRcdFx0XHRcdFx0Ym9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWxVcmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoYm9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWxVcmwsIHVybFBhcmFtZXRlciwgdXJsUGFyYW1ldGVyc1t1cmxQYXJhbWV0ZXJdKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdFx0ZW1haWw6ICRjb250YWluZXIuZmluZCgnaW5wdXRbdHlwZT1cImVtYWlsXCJdJykudmFsKCksXG5cdFx0XHRcdFx0dXJsOiB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh3aW5kb3cubG9jYXRpb24uaHJlZiwgJ2Jvb3RmaW5kZXJ2aWV3cmVzdWx0cycpXG5cdFx0XHRcdH1cblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR0eXBlOiAncG9zdCcsXG5cdFx0XHRcdFx0dXJsOiBib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCxcblx0XHRcdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdCRjb250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5zdWNjZXNzKSB7XG5cdFx0XHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykuaHRtbCgnPHNwYW4gY2xhc3M9XCJlcnJvclwiPkVtYWlsIHNlbnQhPC9zcGFuPicpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCcudmFsaWRhdGlvbi1lcnJvci1jb250YWluZXInKS5odG1sKCc8c3BhbiBjbGFzcz1cImVycm9yXCI+QW4gZXJyb3Igb2NjdXJyZWQgc2VuZGluZyB0aGUgZW1haWwuIFBsZWFzZSB0cnkgYWdhaW4uPC9zcGFuPicpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gZ2V0RGVjb2RlZE51bWJlcihzdHJpbmdOdW1iZXIpIHtcblx0dmFyIGRlY29kZWROdW1iZXIgPSBkZWNvZGVVUklDb21wb25lbnQoc3RyaW5nTnVtYmVyKTtcblx0dmFyIGNsZWFuZWROdW1iZXIgPSBwYXJzZUludChkZWNvZGVkTnVtYmVyLnJlcGxhY2UoLywvZywgJycpKTtcblx0cmV0dXJuIGNsZWFuZWROdW1iZXI7XG59XG5cbmZ1bmN0aW9uIHByaWNlU2xpZGVyKCkge1xuXHRpZiAoIVNpdGVQcmVmZXJlbmNlcy5QUklDRV9TTElERVJfRU5BQkxFRCkge1xuXHRcdHJldHVybjtcblx0fSBlbHNlIHtcblx0XHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcdFxuXHRcdFx0dmFyIG1heFByb2R1Y3RQcmljZSA9IDEyMDA7XHQvLyBTZXQgZGVmYXVsdCB2YWx1ZSBvZiBzbGlkZXIgbWF4IHRvICQxMjAwLiBUaGlzIGdldHMgb3ZlcndyaXR0ZW4gbGF0ZXIgaW4gY29kZSBkZXBlbmRpbmcgb24gcmV0dXJuZWQgcmVzdWx0cy5cblx0XHRcdHZhciB1cmxRdWVyeVN0cmluZyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmcod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuXHRcdFx0dmFyIHVybFBhcmFtcyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXModXJsUXVlcnlTdHJpbmcpOyAvLyBHZXQgdXJsIHBhcmFtZXRlcnMgaW4gb2JqZWN0IGZvcm1hdFxuXHRcdFx0dmFyIGhhc0NhdGVnb3J5ID0gWydjZ2lkJ10gaW4gdXJsUGFyYW1zO1xuXHRcdFx0dmFyIGhhc1F1ZXJ5ID0gWydxJ10gaW4gdXJsUGFyYW1zO1xuXHRcdFx0dmFyIGhpZGRlbkZpZWxkQ2F0ZWdvcnlJZCA9ICQoJy5jdXJyQ0dJRCcpLnZhbCgpO1xuXHRcdFx0dmFyIHNsaWRlck1pblZhbHVlID0gMDtcblx0XHRcdHZhclx0c2xpZGVyTWF4VmFsdWUgPSBtYXhQcm9kdWN0UHJpY2U7XG5cdFx0XHR2YXIgcHNtaSA9IHVybFBhcmFtcy5wc21pO1xuXHRcdFx0dmFyIGNvbnZlcnRlZFByaWNlcztcblxuXHRcdFx0aWYgKHVybFBhcmFtcy5wbWluKSB7XG5cdFx0XHRcdHVybFBhcmFtcy5wbWluID0gZ2V0RGVjb2RlZE51bWJlcih1cmxQYXJhbXMucG1pbik7IC8vIFJlbW92ZSBjb21tYXMgZnJvbSBwcmljZSBtaW5pbXVtIGFuZCB0cmFuc2Zvcm0gc3RyaW5nIGludG8gaW50ZWdlclxuXHRcdFx0XHRpZiAodXJsUGFyYW1zLnBtaW4gPCAwKSB7XG5cdFx0XHRcdFx0dXJsUGFyYW1zLnBtaW4gPSAwO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAodXJsUGFyYW1zLnBtYXgpIHtcblx0XHRcdFx0dXJsUGFyYW1zLnBtYXggPSBnZXREZWNvZGVkTnVtYmVyKHVybFBhcmFtcy5wbWF4KTsgLy8gUmVtb3ZlIGNvbW1hcyBmcm9tIHByaWNlIG1heGltdW0gYW5kIHRyYW5zZm9ybSBzdHJpbmcgaW50byBpbnRlZ2VyXG5cdFx0XHRcdGlmICh1cmxQYXJhbXMucG1heCA8IHVybFBhcmFtcy5wbWluKSB7XG5cdFx0XHRcdFx0dXJsUGFyYW1zLnBtYXggPSB1cmxQYXJhbXMucG1pbjtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyBOZWVkZWQgYmVjYXVzZSBzZXJ2ZXItc2lkZSB3aWxsIG9ubHkgcmV0dXJuIHByb2R1Y3RzIGxlc3MgdGhhbiBwcmljZU1heCwgbm90IGVxdWFsIHRvLiBBZGQgMSB0byBnZXQgcHJvZHVjdHMgZXF1YWwgdG8uXG5cdFx0XHRcdGlmICghcHNtaSB8fCBwc21pICE9ICd0cnVlJykge1xuXHRcdFx0XHRcdHVybFBhcmFtcy5wbWF4ID0gdXJsUGFyYW1zLnBtYXggKyAxOyBcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCFoYXNRdWVyeSAmJiAhaGFzQ2F0ZWdvcnkgJiYgaGlkZGVuRmllbGRDYXRlZ29yeUlkKSB7XG5cdFx0XHRcdC8vIElmIHVybCBwYXJhbXMgZG9uJ3QgaGF2ZSBhIGNnaWQgb3IgYSBxdWVyeSwgdHJ5IGdyYWJiaW5nIGNnaWQgZnJvbSBoaWRkZW4gZmllbGQgb24gcGFnZSB0byB1c2UgZm9yIHByb2R1Y3RTZWFyY2hNb2RlbCBcblx0XHRcdFx0dXJsUGFyYW1zLmNnaWQgPSBoaWRkZW5GaWVsZENhdGVnb3J5SWQ7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFVzZSBzZXJ2ZXItc2lkZSBzY3JpcHQgdG8gZ2V0IGhpZ2hlc3QgcHJpY2VkIHByb2R1Y3QsIGFuZCB0byBnZXQgR0xPQkFMRSBwcmljZXMgaWYgYXBwbGljYWJsZVxuXHRcdFx0dmFyIG1vZGlmaWVkVXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLlNlYXJjaC5HZXRQcmljZVNsaWRlclByaWNlcywgdXJsUGFyYW1zKTtcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiBtb2RpZmllZFVybCxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdHNsaWRlck1pbjogc2xpZGVyTWluVmFsdWUsXG5cdFx0XHRcdFx0c2xpZGVyTWF4OiBzbGlkZXJNYXhWYWx1ZSxcblx0XHRcdFx0XHRwcmljZVNsaWRlclNvcnRpbmdSdWxlOiAncHJpY2UtaGlnaC10by1sb3cnXG5cdFx0XHRcdH0pLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0XHRcdGlmICghcmVzcG9uc2UgfHwgcmVzcG9uc2Uuc3RhdHVzID09ICdFUlJPUicpIHtcblx0XHRcdFx0XHRcdC8vIEVycm9yIGhhbmRsaW5nXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdG1heFByb2R1Y3RQcmljZSA9IHJlc3BvbnNlLmNvbnZlcnRlZFNsaWRlclBtYXguY29udmVydGVkVmFsdWU7XG5cdFx0XHRcdFx0XHRcdGNvbnZlcnRlZFByaWNlcyA9IHJlc3BvbnNlO1xuXHRcdFx0XHRcdFx0fSBjYXRjaChlKSB7XG5cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aW5pdGlhbGl6ZVByaWNlU2xpZGVyKG1heFByb2R1Y3RQcmljZSwgY29udmVydGVkUHJpY2VzLCBwc21pKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XHRcdFxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQcmljZVNsaWRlcihtYXhQcm9kdWN0UHJpY2UsIGNvbnZlcnRlZFByaWNlcywgcHNtaSkge1xuXHR2YXIgJHByaWNlU2xpZGVyID0gJCgnI3ByaWNlLXNsaWRlcicpO1xuXHR2YXIgJHByaWNlU2xpZGVyQ29udGFpbmVyID0gJHByaWNlU2xpZGVyLmNsb3Nlc3QoJy5wcmljZS1zbGlkZXItcGFyZW50Jyk7XG5cdHZhciBpc01vYmlsZSA9ICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKTtcblx0dmFyIHNsaWRlckJvdHRvbVZhbHVlID0gMDtcblx0dmFyIHNsaWRlclRvcFZhbHVlID0gbWF4UHJvZHVjdFByaWNlID8gKE1hdGguY2VpbChtYXhQcm9kdWN0UHJpY2UgLyA1KSAqIDUpIDogMTIwMDtcblx0dmFyIHVzZXJQbWluID0gMDtcblx0dmFyIHVzZXJQbWF4ID0gc2xpZGVyVG9wVmFsdWU7XG5cdHZhciBjb252ZXJ0ZWRTeW1ib2wsIGNvbnZlcnRlZFNsaWRlck1pbiwgY29udmVydGVkU2xpZGVyTWF4LCBjb252ZXJ0ZWRVc2VyTWluLCBjb252ZXJ0ZWRVc2VyTWF4LCBjb252ZXJ0ZWRTbGlkZXJSYW5nZSwgY29udmVydGVkUHJpY2VSYW5nZTtcblxuXHQvLyBOdWxsIGNoZWNrc1xuXHRpZiAoIWNvbnZlcnRlZFByaWNlcykge1xuXHRcdGNvbnZlcnRlZFN5bWJvbCA9ICckJztcblx0XHRjb252ZXJ0ZWRTbGlkZXJNaW4gPSBzbGlkZXJCb3R0b21WYWx1ZTtcblx0XHRjb252ZXJ0ZWRTbGlkZXJNYXggPSBzbGlkZXJUb3BWYWx1ZTtcblx0XHRjb252ZXJ0ZWRVc2VyTWluID0gdXNlclBtaW47XG5cdFx0Y29udmVydGVkVXNlck1heCA9IHVzZXJQbWF4O1xuXHR9IGVsc2Uge1xuXHRcdGNvbnZlcnRlZFN5bWJvbCA9IGNvbnZlcnRlZFByaWNlcy5jb252ZXJ0ZWRTbGlkZXJQbWF4LmNvbnZlcnRlZFN5bWJvbDtcblx0XHRjb252ZXJ0ZWRTbGlkZXJNaW4gPSBjb252ZXJ0ZWRQcmljZXMuY29udmVydGVkU2xpZGVyUG1pbi5jb252ZXJ0ZWRWYWx1ZTtcblx0XHRjb252ZXJ0ZWRTbGlkZXJNYXggPSBjb252ZXJ0ZWRQcmljZXMuY29udmVydGVkU2xpZGVyUG1heC5jb252ZXJ0ZWRWYWx1ZTtcblx0XHRjb252ZXJ0ZWRVc2VyTWluID0gY29udmVydGVkUHJpY2VzLmNvbnZlcnRlZFVzZXJQbWluLmNvbnZlcnRlZFZhbHVlO1xuXHRcdGNvbnZlcnRlZFVzZXJNYXggPSBjb252ZXJ0ZWRQcmljZXMuY29udmVydGVkVXNlclBtYXguY29udmVydGVkVmFsdWU7XG5cdH1cblxuXHQvLyBJZiBzbGlkZXIgaW5zdGFuY2UgaXMgYWxyZWFkeSBpbml0aWFsaXplZCwgZ28gYWhlYWQgYW5kIGRlc3Ryb3kgYmVmb3JlIGNyZWF0aW5nIGEgbmV3IGluaXRpYWxpemF0aW9uXG5cdGlmICgkcHJpY2VTbGlkZXIuc2xpZGVyKCdpbnN0YW5jZScpKSB7XG5cdFx0JCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcignZGVzdHJveScpO1xuXHR9XG5cdFxuXHQvLyBDaGVja3Mgcm91bmRlZCBwcmljaW5nIGFnYWluc3QgY29udmVydGVkIHByaWNpbmdcblx0aWYgKHNsaWRlclRvcFZhbHVlICE9IGNvbnZlcnRlZFNsaWRlck1heCkge1xuXHRcdC8vIERvIHRoaXMgY2hlY2sgYmVmb3JlIHRoZSByb3VuZGVkIHVwIHZhbHVlIGlzIGFwcGxpZWQgdG8gY29udmVydGVkU2xpZGVyTWF4XG5cdFx0aWYgKGNvbnZlcnRlZFVzZXJNYXggPT0gY29udmVydGVkU2xpZGVyTWF4KSB7XG5cdFx0XHRjb252ZXJ0ZWRVc2VyTWF4ID0gc2xpZGVyVG9wVmFsdWU7XG5cdFx0fVxuXHRcdC8vIE5vdyB1cGRhdGUgY29udmVydGVkU2xpZGVyTWF4IHRvIHJvdW5kZWQgdmFsdWVcblx0XHRjb252ZXJ0ZWRTbGlkZXJNYXggPSBzbGlkZXJUb3BWYWx1ZTtcblx0fVxuXHQvLyBJZiB3ZSBoYXZlIGEgcG1pbiBvciBwbWF4IGFwcGxpZWQsIHRoZW4gZW5zdXJlIHRoYXQgdGhlIHByaWNlIHJlZmlubWVudCBidWNrZXQgaXMgZXhwYW5kZWRcblx0aWYgKChjb252ZXJ0ZWRVc2VyTWluICE9IGNvbnZlcnRlZFNsaWRlck1pbikgfHwgKGNvbnZlcnRlZFVzZXJNYXggIT0gY29udmVydGVkU2xpZGVyTWF4KSkge1xuXHRcdGlmICghaXNNb2JpbGUgJiYgISQoJy5wcmljZS1yZWZpbmVtZW50JykuaGFzQ2xhc3MoJ2V4cGFuZGVkJykpIHtcblx0XHRcdCQoJy5wcmljZS1yZWZpbmVtZW50JykuYWRkQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0fVxuXHRcdC8vIElmIHdlIHNvbWVob3cgaGF2ZSBhIGdyZWF0ZXIgdXNlclBtYXggdGhhbiBoaWdoZXN0UHJpY2VkUHJvZHVjdCBpbiBjYXRlZ29yeSwgZ28gYWhlYWQgYW5kIHJldmVydCB1c2VyUG1heCB0byBoaWdoZXN0UHJpY2VkUHJvZHVjdCB2YWx1ZVxuXHRcdGlmIChjb252ZXJ0ZWRVc2VyTWF4ID4gY29udmVydGVkU2xpZGVyTWF4KSB7XG5cdFx0XHRjb252ZXJ0ZWRVc2VyTWF4ID0gY29udmVydGVkU2xpZGVyTWF4O1xuXHRcdH1cblx0fVxuXHQvLyBVcGRhdGUgdGhlIERPTSBhdHRyaWJ1dGVzIHdpdGggY29udmVyc2lvbiBmYWN0b3IgdG8gdXNlIHdoZW4gcHJpY2Ugc2xpZGVyIGlzIG1vZGlmaWVkXG5cdHZhciBjb252ZXJzaW9uRmFjdG9yID0gMTtcblx0aWYgKGNvbnZlcnRlZFByaWNlcykge1xuXHRcdGNvbnZlcnNpb25GYWN0b3IgPSBjb252ZXJ0ZWRQcmljZXMuY29udmVydGVkU2xpZGVyUG1heC5kZWZhdWx0VmFsdWUgLyBjb252ZXJ0ZWRQcmljZXMuY29udmVydGVkU2xpZGVyUG1heC5jb252ZXJ0ZWRWYWx1ZTtcblx0fVxuXHQkcHJpY2VTbGlkZXJDb250YWluZXIuYXR0cignZGF0YS1jdXJyZW5jeS1jb252ZXJzaW9uLWZhY3RvcicsIGNvbnZlcnNpb25GYWN0b3IudG9TdHJpbmcoKSk7XG5cblx0XG5cdC8vIEluaXRpYWxpemUgcHJpY2Ugc2xpZGVyXG5cdCQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoe1xuXHRcdHJhbmdlOiB0cnVlLFxuXHRcdG1pbjogY29udmVydGVkU2xpZGVyTWluLFxuXHRcdG1heDogY29udmVydGVkU2xpZGVyTWF4LFxuXHRcdHZhbHVlczogWyBjb252ZXJ0ZWRVc2VyTWluLCBjb252ZXJ0ZWRVc2VyTWF4IF0sXG5cdFx0c2xpZGU6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0Ly8gT24gc2xpZGUgZXZlbnQsIGdyYWIgdXNlciBpbnB1dCBmb3IgcG1pbi9wbWF4IGFuZCBhcHBseSB0byBzbGlkZXIgdGV4dCwgcGx1cyBpbnB1dCBmaWVsZHNcblx0XHRcdGNvbnZlcnRlZFVzZXJNaW4gPSB1aS52YWx1ZXNbMF07XG5cdFx0XHRjb252ZXJ0ZWRVc2VyTWF4ID0gdWkudmFsdWVzWzFdO1xuXHRcdFx0Y29udmVydGVkUHJpY2VSYW5nZSA9IGNvbnZlcnRlZFN5bWJvbCArIGNvbnZlcnRlZFVzZXJNaW4gKyAnIC0gJyArIGNvbnZlcnRlZFN5bWJvbCArIGNvbnZlcnRlZFVzZXJNYXg7XG5cdFx0XHRjb252ZXJ0ZWRTbGlkZXJSYW5nZSA9IGNvbnZlcnRlZFN5bWJvbCArIGNvbnZlcnRlZFNsaWRlck1pbiArICcgLSAnICsgY29udmVydGVkU3ltYm9sICsgY29udmVydGVkU2xpZGVyTWF4O1xuXHRcdFx0JCgnLnByaWNlLXJhbmdlLWFtb3VudCcpLnRleHQoY29udmVydGVkUHJpY2VSYW5nZSk7XG5cdFx0XHQkKCcjcHJpY2Utc2xpZGVyID4gLnVpLXNsaWRlci1yYW5nZScpLmF0dHIoJ3RpdGxlJywgJ0FwcGxpZWQgUHJpY2UgUmFuZ2U6ICcgKyBjb252ZXJ0ZWRQcmljZVJhbmdlKTtcblx0XHRcdCQoJyNwcmljZS1zbGlkZXInKS5hdHRyKCd0aXRsZScsICdNYXggUmFuZ2U6ICcgKyBjb252ZXJ0ZWRTbGlkZXJSYW5nZSk7XG5cdFx0XHQkKCdbZGF0YS1uYW1lPVwicHJpY2UtaW5wdXQtbWluXCJdIC5wcmljZS1pbnB1dC1jdXJyZW5jeS1zeW1ib2wnKS5odG1sKGNvbnZlcnRlZFN5bWJvbCk7XG5cdFx0XHQkKCdbZGF0YS1uYW1lPVwicHJpY2UtaW5wdXQtbWF4XCJdIC5wcmljZS1pbnB1dC1jdXJyZW5jeS1zeW1ib2wnKS5odG1sKGNvbnZlcnRlZFN5bWJvbCk7XG5cdFx0XHQkKCdpbnB1dC5wcmljZS1pbnB1dC1taW4nKS52YWwoY29udmVydGVkVXNlck1pbik7XG5cdFx0XHQkKCdpbnB1dC5wcmljZS1pbnB1dC1tYXgnKS52YWwoY29udmVydGVkVXNlck1heCk7XG5cdFx0fSxcblx0XHRzdG9wOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRjb252ZXJ0ZWRVc2VyTWluID0gdWkudmFsdWVzWzBdO1xuXHRcdFx0XHRjb252ZXJ0ZWRVc2VyTWF4ID0gdWkudmFsdWVzWzFdO1xuXHRcdFx0XHRpZiAoIWlzTW9iaWxlKSB7IC8vIERlc2t0b3Bcblx0XHRcdFx0XHR0cmlnZ2VyUHJpY2VTbGlkZXIoY29udmVydGVkVXNlck1pbiwgY29udmVydGVkVXNlck1heCk7XG5cdFx0XHRcdH0gZWxzZSB7IC8vTW9iaWxlXG5cdFx0XHRcdFx0cHJpY2VTbGlkZXJJbnB1dHMoY29udmVydGVkVXNlck1pbiwgY29udmVydGVkVXNlck1heCwgaXNNb2JpbGUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCA3NTApOyAvLyAwLjc1IHNlY29uZHNcblx0XHR9XG5cdH0pO1x0XG5cblx0Ly8gRm9yIHNsaWRlciBpbml0aWFsaXphdGlvbiwgZ3JhYiBzbGlkZXIgbWluIGFuZCBtYXggYW5kIGFwcGx5IHZhbHVlcyB0byBzbGlkZXIgdGV4dCBhbmQgaW5wdXRzLCBzbyBldmVyeXRoaW5nIG1hdGNoZXMgYXQgdGltZSBvZiBmaXJzdCBsb2FkXG5cdGNvbnZlcnRlZFVzZXJNaW4gPSAkKCcjcHJpY2Utc2xpZGVyJykuc2xpZGVyKCd2YWx1ZXMnLCAwKTtcblx0Y29udmVydGVkVXNlck1heCA9ICQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoJ3ZhbHVlcycsIDEpO1xuXHRjb252ZXJ0ZWRQcmljZVJhbmdlID0gY29udmVydGVkU3ltYm9sICsgY29udmVydGVkVXNlck1pbiArICcgLSAnICsgY29udmVydGVkU3ltYm9sICsgY29udmVydGVkVXNlck1heDtcblx0Y29udmVydGVkU2xpZGVyUmFuZ2UgPSBjb252ZXJ0ZWRTeW1ib2wgKyBjb252ZXJ0ZWRTbGlkZXJNaW4gKyAnIC0gJyArIGNvbnZlcnRlZFN5bWJvbCArIGNvbnZlcnRlZFNsaWRlck1heDtcblx0JCgnLnByaWNlLXJhbmdlLWFtb3VudCcpLnRleHQoY29udmVydGVkUHJpY2VSYW5nZSk7XG5cdCQoJyNwcmljZS1zbGlkZXIgPiAudWktc2xpZGVyLXJhbmdlJykuYXR0cigndGl0bGUnLCAnQXBwbGllZCBQcmljZSBSYW5nZTogJyArIGNvbnZlcnRlZFByaWNlUmFuZ2UpO1xuXHQkKCcjcHJpY2Utc2xpZGVyJykuYXR0cigndGl0bGUnLCAnTWF4IFJhbmdlOiAnICsgY29udmVydGVkU2xpZGVyUmFuZ2UpO1xuXHQkKCdbZGF0YS1uYW1lPVwicHJpY2UtaW5wdXQtbWluXCJdIC5wcmljZS1pbnB1dC1jdXJyZW5jeS1zeW1ib2wnKS5odG1sKGNvbnZlcnRlZFN5bWJvbCk7XG5cdCQoJ1tkYXRhLW5hbWU9XCJwcmljZS1pbnB1dC1tYXhcIl0gLnByaWNlLWlucHV0LWN1cnJlbmN5LXN5bWJvbCcpLmh0bWwoY29udmVydGVkU3ltYm9sKTtcblx0JCgnaW5wdXQucHJpY2UtaW5wdXQtbWluJykudmFsKGNvbnZlcnRlZFVzZXJNaW4pO1xuXHQkKCdpbnB1dC5wcmljZS1pbnB1dC1tYXgnKS52YWwoY29udmVydGVkVXNlck1heCk7XG5cblx0Ly8gUHJpY2UgaW5wdXRzXG5cdCQoZG9jdW1lbnQpLm9mZigna2V5cHJlc3MnLCAnLnByaWNlLWlucHV0LWNvbnRhaW5lciBpbnB1dCcpLm9uKCdrZXlwcmVzcycsICcucHJpY2UtaW5wdXQtY29udGFpbmVyIGlucHV0JywgZnVuY3Rpb24oZSkge1xuXHRcdCQoJy5wcmljZS1pbnB1dHMtYXBwbHktYnV0dG9uIGJ1dHRvbicpLmNzcygnZGlzcGxheScsJ2Jsb2NrJyk7XG5cdH0pLm9mZignY2xpY2snLCAnLnByaWNlLWlucHV0cy1hcHBseS1idXR0b24gYnV0dG9uJykub24oJ2NsaWNrJywgJy5wcmljZS1pbnB1dHMtYXBwbHktYnV0dG9uIGJ1dHRvbicsIGZ1bmN0aW9uKGUpIHtcblx0XHRwcmljZVNsaWRlcklucHV0cyhjb252ZXJ0ZWRTbGlkZXJNaW4sIGNvbnZlcnRlZFNsaWRlck1heCwgaXNNb2JpbGUpO1xuXHR9KVxufVxuXG5mdW5jdGlvbiBwcmljZVNsaWRlckdvb2dsZUFuYWx5dGljc1RhZ2dpbmcoKSB7XG5cdGlmIChTaXRlUHJlZmVyZW5jZXMuR0FfTkVXX0FDVElPTlNfRU5BQkxFRCkge1xuXHRcdHZhciByZWZpbmVtZW50SWQgPSAkKCcjcHJpY2Utc2xpZGVyJykuY2xvc2VzdCgnW3JlZmluZW1lbnQtaWRdJykuYXR0cigncmVmaW5lbWVudC1pZCcpIHx8IG51bGw7XG5cdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9ICQoJyNwcmljZS1zbGlkZXInKS5jbG9zZXN0KCcucHJpY2Utc2xpZGVyLXBhcmVudCcpLmZpbmQoJy5wcmljZS1yYW5nZS1oZWFkZXIgLnByaWNlLXJhbmdlLWFtb3VudCcpLnRleHQoKSB8fCBudWxsO1xuXHRcdGlmIChyZWZpbmVtZW50SWQgJiYgcmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudEFuYWx5dGljc1RhZ2dpbmdEYXRhID0gIHsgXG5cdFx0XHRcdCdhY3Rpb25fdmFsdWUnOiB7ICdyZWZpbmVtZW50X2NhdGVnb3J5JzogcmVmaW5lbWVudElkIH0sIFxuXHRcdFx0XHQnYWN0aW9uX2l0ZW1zJzogeyAncmVmaW5lbWVudF92YWx1ZSc6IHJlZmluZW1lbnRWYWx1ZSB9XG5cdFx0XHR9O1xuXHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQXBwbHlSZWZpbmVtZW50JywgcmVmaW5lbWVudEFuYWx5dGljc1RhZ2dpbmdEYXRhKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdE1vYmlsZVByaWNlU2xpZGVyKHVybCkge1xuXHR2YXIgaXNQcmljZVNsaWRlciA9IFNpdGVQcmVmZXJlbmNlcy5QUklDRV9TTElERVJfRU5BQkxFRCAmJiAkKCcjcHJpY2Utc2xpZGVyJykuc2xpZGVyKCdpbnN0YW5jZScpO1xuXHR2YXIgaXNNb2JpbGUgPSAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJyk7XG5cdHZhciAkYXBwbHlSZWZpbmVtZW50c0J0biA9ICQoJy5hcHBseS1yZWZpbmVtZW50czpub3QoLmRpc2FibGVkKScpO1xuXHR2YXIgaXNCdXR0b25DbGljayA9ICRhcHBseVJlZmluZW1lbnRzQnRuLmxlbmd0aCA+IDAgJiYgJGFwcGx5UmVmaW5lbWVudHNCdG5bMF0uaGFzQXR0cmlidXRlKCdkYXRhLWFwcGx5LXJlZmluZW1lbnRzJykgJiYgJGFwcGx5UmVmaW5lbWVudHNCdG4uYXR0cignZGF0YS1hcHBseS1yZWZpbmVtZW50cycpID09ICd0cnVlJztcblx0XG5cdGlmIChpc1ByaWNlU2xpZGVyICYmIGlzTW9iaWxlICYmIGlzQnV0dG9uQ2xpY2spIHtcblx0XHR2YXIgaXNQcmljZVNsaWRlckNoYW5nZWQgPSAoJCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcignb3B0aW9uJywgJ21pbicpICE9ICQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoJ3ZhbHVlcycsIDApIHx8ICQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoJ29wdGlvbicsICdtYXgnKSAhPSAkKCcjcHJpY2Utc2xpZGVyJykuc2xpZGVyKCd2YWx1ZXMnLCAxKSkgfHwgZmFsc2U7XG5cdFx0aWYgKGlzUHJpY2VTbGlkZXJDaGFuZ2VkKSB7XG5cdFx0XHR2YXIgdXNlclByaWNlTWluID0gJCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcigndmFsdWVzJywgMCk7XG5cdFx0XHR2YXIgdXNlclByaWNlTWF4ID0gJCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcigndmFsdWVzJywgMSk7XG5cdFx0XHQkYXBwbHlSZWZpbmVtZW50c0J0bi5hdHRyKCdkYXRhLWFwcGx5LXJlZmluZW1lbnRzJywnZmFsc2UnKTtcblx0XHRcdHJldHVybiB0cmlnZ2VyUHJpY2VTbGlkZXIodXNlclByaWNlTWluLCB1c2VyUHJpY2VNYXgsIHVybCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB1cmw7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHJldHVybiB1cmw7XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJpY2VTbGlkZXJJbnB1dHMoc2xpZGVyQm90dG9tVmFsdWUsIHNsaWRlclRvcFZhbHVlLCBpc01vYmlsZSkge1xuXHQvLyBJbnB1dCBmaWVsZHNcblx0dmFyIGlucHV0UG1pbiA9ICQoJy5wcmljZS1pbnB1dC1taW4nKS52YWwoKSA/IHBhcnNlSW50KCQoJy5wcmljZS1pbnB1dC1taW4nKS52YWwoKSkgOiBzbGlkZXJCb3R0b21WYWx1ZTtcblx0dmFyIGlucHV0UG1heCA9ICQoJy5wcmljZS1pbnB1dC1tYXgnKS52YWwoKSA/IHBhcnNlSW50KCQoJy5wcmljZS1pbnB1dC1tYXgnKS52YWwoKSkgOiBzbGlkZXJUb3BWYWx1ZTtcblx0aWYgKGlucHV0UG1pbiA8IDApIHtcblx0XHRpbnB1dFBtaW4gPSAwO1xuXHRcdCQoJy5wcmljZS1pbnB1dC1taW4nKS52YWwoaW5wdXRQbWluKTtcblx0fVxuXHRpZiAoaW5wdXRQbWF4ID4gc2xpZGVyVG9wVmFsdWUpIHtcblx0XHRpbnB1dFBtYXggPSBzbGlkZXJUb3BWYWx1ZTtcblx0XHQkKCcucHJpY2UtaW5wdXQtbWF4JykudmFsKGlucHV0UG1heCk7XG5cdH1cblx0Ly8gVXBkYXRlIHRoZSBwcmljZSBzbGlkZXIgdmFsdWVzIGJhc2VkIG9uIHRoZSBpbnB1dCBmaWVsZHNcblx0dmFyICRwcmljZVNsaWRlciA9ICQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoJ2luc3RhbmNlJyk7XG5cdGlmICgkcHJpY2VTbGlkZXIpIHtcblx0XHQkKCcjcHJpY2Utc2xpZGVyJykuc2xpZGVyKHtcblx0XHRcdHZhbHVlczogWyBpbnB1dFBtaW4sIGlucHV0UG1heCBdXG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoIWlzTW9iaWxlIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMpIHtcblx0XHQvLyBEZXNrdG9wXHRcblx0XHR0cmlnZ2VyUHJpY2VTbGlkZXIoaW5wdXRQbWluLCBpbnB1dFBtYXgpO1xuXHR9IGVsc2Uge1xuXHRcdC8vIE1vYmlsZVxuXHRcdGlmICgkcHJpY2VTbGlkZXIpIHtcblx0XHRcdHZhciBpc1ByaWNlU2xpZGVyQ2hhbmdlZCA9ICgkKCcjcHJpY2Utc2xpZGVyJykuc2xpZGVyKCdvcHRpb24nLCAnbWluJykgIT0gJCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcigndmFsdWVzJywgMCkgfHwgJCgnI3ByaWNlLXNsaWRlcicpLnNsaWRlcignb3B0aW9uJywgJ21heCcpICE9ICQoJyNwcmljZS1zbGlkZXInKS5zbGlkZXIoJ3ZhbHVlcycsIDEpKSB8fCBmYWxzZTtcblx0XHRcdGlmIChpc1ByaWNlU2xpZGVyQ2hhbmdlZCkge1xuXHRcdFx0XHQkKCcucmVmaW5lbWVudHMnKS5hZGRDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcucmVmaW5lbWVudHMnKS5yZW1vdmVDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbi8vIEV4cGVjdHMgbnVtYmVycyBhcyBwYXJhbWV0ZXJzLCBub3Qgc3RyaW5nc1xuZnVuY3Rpb24gdHJpZ2dlclByaWNlU2xpZGVyKHByaWNlTWluLCBwcmljZU1heCwgcGFzc2VkVXJsKSB7XG5cdHRyeSB7XG5cdFx0dmFyIHVybCA9IHBhc3NlZFVybDtcblx0XHRpZiAoIXBhc3NlZFVybCB8fCBwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblJzcFVTKSB7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdFx0dXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWY7XG5cdFx0fVxuXG5cdFx0Ly8gVGFrZSB1c2VyIGxvY2FsIGN1cnJlbmN5IGFuZCByZXZlcnQgaXQgYmFjayB0byBVLlMuIChtZXJjaGFudCBzaXRlIGN1cnJlbmN5KSBiZWZvcmUgcnVubmluZyB0aGUgc2VhcmNoIHF1ZXJ5XG5cdFx0dmFyIGN1cnJlbmN5Q29udmVyc2lvbkZhY3RvciA9IHBhcnNlRmxvYXQoJCgnI3ByaWNlLXNsaWRlcicpLmNsb3Nlc3QoJy5wcmljZS1zbGlkZXItcGFyZW50JykuYXR0cignZGF0YS1jdXJyZW5jeS1jb252ZXJzaW9uLWZhY3RvcicpKTtcblx0XHR2YXIgcmV2ZXJ0ZWRQbWluID0gcHJpY2VNaW4gKiBjdXJyZW5jeUNvbnZlcnNpb25GYWN0b3I7XG5cdFx0dmFyIHJldmVydGVkUG1heCA9IHByaWNlTWF4ICogY3VycmVuY3lDb252ZXJzaW9uRmFjdG9yOyBcblx0XHRyZXZlcnRlZFBtYXggPSByZXZlcnRlZFBtYXggKyAxOyAvLyBOZWVkZWQgYmVjYXVzZSBzZXJ2ZXItc2lkZSB3aWxsIG9ubHkgcmV0dXJuIHByb2R1Y3RzIGxlc3MgdGhhbiBwcmljZU1heCwgbm90IGVxdWFsIHRvLiBBZGQgMSB0byBnZXQgcHJvZHVjdHMgZXF1YWwgdG8uXG5cblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdwbWluJyk7XG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncG1heCcpO1xuXHRcdHVybCA9IHV0aWwucmVtb3ZlUGFyYW1Gcm9tVVJMKHVybCwgJ3BzbWknKTtcblx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncG1pbicsIHJldmVydGVkUG1pbi50b0ZpeGVkKCkpO1xuXHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwbWF4JywgcmV2ZXJ0ZWRQbWF4LnRvRml4ZWQoKSk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3BzbWknLCAndHJ1ZScpO1xuXG5cdFx0cHJpY2VTbGlkZXJHb29nbGVBbmFseXRpY3NUYWdnaW5nKCk7XG5cdFx0XG5cdFx0aWYgKCFwYXNzZWRVcmwgfHwgcGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5Sc3BVUykge1xuXHRcdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcodXJsKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHVybDtcblx0XHR9XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHR9XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXG5cdEltYWdlQ29uc3RhbnRzID0gcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMgPyByZXF1aXJlKCcuLi8uLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3VudHJ5b3V0Zml0dGVycy9jYXJ0cmlkZ2UvanMvSW1hZ2VDb25zdGFudHMnKSA6IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvSW1hZ2VDb25zdGFudHMnKTtcblx0XG4gICAgY29tcGFyZVdpZGdldC5pbml0KCk7XG4gICAgaWYgKCd2YXJpYW50SW52ZW50b3J5TWVzc2FnaW5nVXJsJyBpbiBwYWdlICYmIHBhZ2UudmFyaWFudEludmVudG9yeU1lc3NhZ2luZ1VybCkge1xuICAgIFx0dmFyIHVybFBhcmFtcyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaC5zdWJzdHIoMSkpO1xuICAgIFx0aWYodXJsUGFyYW1zLmhhc093blByb3BlcnR5KCdzdGFydCcpICYmIHVybFBhcmFtcy5zdGFydCA+IDApe1xuICAgIFx0XHR1cGRhdGVJbnZlbnRvcnlNZXNzYWdlcyh3aW5kb3cubG9jYXRpb24uaHJlZiwgc2hvd1ZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmcpO1xuICAgIFx0fSBlbHNlIHtcbiAgICAgICAgICAgIHNob3dWYXJpYW50SW52ZW50b3J5TWVzc2FnaW5nKCk7XG4gICAgXHR9XG4gICAgfVxuXG4gICAgcHJvZHVjdFRpbGUuaW5pdCgpO1xuICAgIHNpemVSZWZpbmVtZW50cy5pbml0KCk7XG4gICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xuXHR1cGRhdGVTaG9wTXlTdG9yZSgpO1xuXHRzbGlkZXJzLmluaXRpYWxpemVDYXRlZ29yeVNsaWRlcnMoJy5tYWluLWNvbnRlbnQgLmNhdGVnb3J5LWxhbmRpbmctc2xpZGVyOm5vdCguc2xpY2staW5pdGlhbGl6ZWQpJyk7XG5cdGluaXRpYWxpemVSZWZpbmVtZW50RmlsdGVyQnlUZXh0KCk7XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0aW5pdGlhbGl6ZUJvb3RGaW5kZXJFdmVudHMoKTtcblx0fVxuXHRsb2FkU2Nyb2xsUG9zaXRpb24oKTtcblx0c2F2ZVNjcm9sbFBvc2l0aW9uKCk7XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0aW5pdGlhbGl6ZVN0aWNreVJlZmluZW1lbnRzKCk7XG5cdFx0Ly8gaW5pdGlhbGl6ZVN0aWNreVN1YmhlYWRlcigpO1xuXHR9XG5cblx0bG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0Q3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fTtcblxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuUmFuZ2VmaW5kZXIpIHtcblx0XHRpbml0aWFsaXplUmFuZ2VmaW5kZXJFdmVudHMoKTtcblx0fVxuXG5cdGlmIChvcHRpb25zKSB7XG5cdFx0aWYgKG9wdGlvbnMuU3R5bGVDb3VudENhY2hlKSB7XG5cdFx0XHRzdHlsZUNvdW50cy5yZW5kZXIob3B0aW9ucy5TdHlsZUNvdW50Q2FjaGUpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLkJvcGlzICYmIG9wdGlvbnMuQm9waXMuRW5hYmxlZCAmJiBvcHRpb25zLkJvcGlzLlNlbGVjdGVkTG9jYXRpb25zKSB7XG5cdFx0XHRib290QmFybkV4cHJlc3NSZWZpbmVtZW50V2l6YXJkLmluaXRpYWxpemUoJCgnI2RpYWxvZy1ib290YmFybmV4cHJlc3MtcmVmaW5lbWVudC13aXphcmQnKSwgb3B0aW9ucyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuUmVmaW5lbWVudHNVSVZlcnNpb24gPT0gUmVmaW5lbWVudFVJVmVyc2lvbkNvbnN0YW50cy5VcGRhdGVkKSB7XG5cdFx0XHR1cGRhdGVSZWZpbmVtZW50Q291bnRzKCk7XG5cdFx0XHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdFx0XHR1cGRhdGVTZWxlY3RlZFJlZmluZW1lbnRzKCk7XG5cdFx0XHRcdHVwZGF0ZVBlbmRpbmdSZWZpbmVtZW50cygpO1xuXHRcdFx0fVxuXHRcdFxuXHRcdFx0dmFyICRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyO1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyID0gJCgnLnByaW1hcnktY29udGVudCA+IC5zb3J0LWFuZC1yZWZpbmUgPiAucHJvZHVjdC1zZWxlY3Rpb25zJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lciA9ICQoJy5wcmltYXJ5LWNvbnRlbnQgPiAucHJvZHVjdC1zZWxlY3Rpb25zJylcblx0XHRcdH1cblxuXHRcdFx0aWYgKCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyLmZpbmQoJy5saXN0LXNlbGVjdGlvbnMgLnZhbHVlLmFwcGxpZWQnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBMb2NhdGlvblNlYXJjaCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2JvcGlzL2NvbXBvbmVudHMvTG9jYXRpb25TZWFyY2gnKTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0dmFyIGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyA9IHtcblx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdENzc0NsYXNzOiAnZnVsbHNjcmVlbicsXG5cdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdH07XG5cblx0aWYgKCQoJy5wdF9zdG9yZWZyb250IC5zZWFyY2gtc3RvcmVzJykubGVuZ3RoID4gMCkge1xuXHRcdHZhciBsb2NhdGlvblNlYXJjaCA9IG5ldyBMb2NhdGlvblNlYXJjaCgpO1xuXHRcdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU3RvcmVmcm9udC5TdG9yZVNlYXJjaCcpLm9uKCdjbGljay5TdG9yZWZyb250LlN0b3JlU2VhcmNoJywgJy5wdF9zdG9yZWZyb250IC5zZWFyY2gtc3RvcmVzOm5vdCguZGlzYWJsZWQpJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGxvY2F0aW9uU2VhcmNoLmluaXRpYWxpemUoJCgnLmxvY2F0aW9uLXNlYXJjaC1kaWFsb2cnKSwgb3B0aW9ucyk7XG5cdFx0XHQkKCcubG9jYXRpb24tc2VhcmNoLWRpYWxvZycpLnRyaWdnZXIoJ0xvY2F0aW9uU2VhcmNoLkZvcm1TdWJtaXQnKTtcblx0XHR9KTtcblx0fVxuXG5cdCQoJy5wdF9zdG9yZWZyb250IC5zZWN0aW9uIC5idG46bm90KC5zZWFyY2gtc3RvcmVzKScpLm9mZignY2xpY2suTG9hZGluZ0luZGljYXRvcicpLm9uKCdjbGljay5Mb2FkaW5nSW5kaWNhdG9yJywgZnVuY3Rpb24oKSB7XG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0fSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgR2VvbG9jYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0dlb2xvY2F0aW9uL0dlb2xvY2F0aW9uSGVscGVyJyk7XG52YXIgc2hvcFlvdXJTdG9yZURpYWxvZyA9IHJlcXVpcmUoJy4uL2JvcGlzL2NvbXBvbmVudHMvU2hvcFlvdXJTdG9yZURpYWxvZycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xudmFyIGlucHV0U2VhcmNoVGltZXI7XG5cbnZhciAkY29udGFpbmVyO1xudmFyICRjb250ZW50O1xudmFyICR1c2VNeUxvY2F0aW9uQnV0dG9uO1xudmFyICRzZWFyY2hCdXR0b247XG52YXIgJGxvY2F0aW9uU2VhcmNoUmVzdWx0cztcbnZhciBsb2NhdGlvblNlYXJjaFJlc3VsdENvbnRhaW5lclRlbXBsYXRlO1xudmFyIGxvY2F0aW9uU2VhcmNoUmVzdWx0SXRlbVRlbXBsYXRlO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNob3BZb3VyU3RvcmVEaWFsb2cnKS5vbignY2xpY2suU2hvcFlvdXJTdG9yZURpYWxvZycsICcuc2hvcC1zdG9yZS1pbnZlbnRvcnknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkc3RvcmUgPSAkdGhpcy5jbG9zZXN0KCdbc3RvcmUtaWRdJyk7XG5cdFx0c2hvcFlvdXJTdG9yZURpYWxvZy5pbml0aWFsaXplKHtcblx0XHRcdFN0b3JlSWQ6ICRzdG9yZS5hdHRyKCdzdG9yZS1pZCcpLFxuXHRcdFx0U3RvcmVOYW1lOiAkc3RvcmUuYXR0cignc3RvcmUtbmFtZScpXG5cdFx0fSk7XG5cdH0pO1xuXG5cdCQoJy5wdF9zdG9yZS1sb2NhdG9yJykub2ZmKCdjbGljay5Vc2VNeUxvY2F0aW9uJykub24oJ2NsaWNrLlVzZU15TG9jYXRpb24nLCAnLnVzZS1teS1sb2NhdGlvbicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRkYXRhQnVmZmVyLmxpbWl0ID0gd2luZG93Lm91dGVyV2lkdGggPj0gMTAyNCA/IDEwIDogNTtcblx0XHRkYXRhQnVmZmVyLm9mZnNldCA9IDA7XG5cdFx0ZGF0YUJ1ZmZlci5xdWVyeSA9ICcnO1xuXHRcdCQoJy5zdG9yZS1maWx0ZXItY29udGFpbmVyIFt0eXBlPVwidGV4dFwiXScpLnZhbCgnJyk7XG5cblx0XHQkdXNlTXlMb2NhdGlvbkJ1dHRvbi5sb2FkaW5nKCk7XG5cdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5odG1sKCcnKTtcblx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmxvYWRpbmcoKTtcblx0XHRHZW9sb2NhdGlvbkhlbHBlci5HZXRQb3NpdGlvbigpLnRoZW4oZnVuY3Rpb24ocG9zaXRpb24pIHtcblx0XHRcdGRhdGFCdWZmZXIucG9zaXRpb24gPSBwb3NpdGlvbjtcblx0XHRcdGdldFN0b3JlTGlzdCgpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHQkKCcucHRfc3RvcmUtbG9jYXRvcicpLm9mZignc3VibWl0LlNlYXJjaCcpLm9uKCdzdWJtaXQuU2VhcmNoJywgJy5zdG9yZS1maWx0ZXItY29udGFpbmVyIGZvcm0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNlYXJjaCgpO1xuXHR9KTtcblxuXHQkKCcucHRfc3RvcmUtbG9jYXRvcicpLm9mZignY2xpY2suU2VhcmNoJykub24oJ2NsaWNrLlNlYXJjaCcsICcuc3RvcmUtZmlsdGVyLWNvbnRhaW5lciAuYnRuLmJ0bi1wcmltYXJ5JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRzZWFyY2goKTtcblx0fSk7XG5cblx0JCgnLnB0X3N0b3JlLWxvY2F0b3InKS5vZmYoJ2NsaWNrLkxvYWRNb3JlJykub24oJ2NsaWNrLkxvYWRNb3JlJywgJy5sb2NhdGlvbi1zZWFyY2gtcmVzdWx0cyAubG9hZC1tb3JlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0ZGF0YUJ1ZmZlci5saW1pdCA9IHdpbmRvdy5vdXRlcldpZHRoID49IDEwMjQgPyAxMCA6IDU7XG5cdFx0ZGF0YUJ1ZmZlci5vZmZzZXQgKz0gZGF0YUJ1ZmZlci5saW1pdDtcblx0XHQkdGhpcy5wYXJlbnQoKS5sb2FkaW5nKCk7XG5cdFx0R2VvbG9jYXRpb25IZWxwZXIuR2V0UG9zaXRpb24oKS50aGVuKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0XHRkYXRhQnVmZmVyLnBvc2l0aW9uID0gcG9zaXRpb247XG5cdFx0XHRnZXRTdG9yZUxpc3QoKTtcblx0XHR9KS5jYXRjaChmdW5jdGlvbigpIHtcblx0XHRcdGlmICgkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHNlYXJjaCgpIHtcblx0ZGF0YUJ1ZmZlci5saW1pdCA9IHdpbmRvdy5vdXRlcldpZHRoID49IDEwMjQgPyAxMCA6IDU7XG5cdGRhdGFCdWZmZXIub2Zmc2V0ID0gMDtcblx0ZGF0YUJ1ZmZlci5xdWVyeSA9ICQoJy5zdG9yZS1maWx0ZXItY29udGFpbmVyIFt0eXBlPVwidGV4dFwiXScpLnZhbCgpO1xuXG5cdCRzZWFyY2hCdXR0b24ubG9hZGluZygpO1xuXHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmh0bWwoJycpO1xuXHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmxvYWRpbmcoKTtcblx0R2VvbG9jYXRpb25IZWxwZXIuR2V0UG9zaXRpb24oKS50aGVuKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0ZGF0YUJ1ZmZlci5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuXHRcdGdldFN0b3JlTGlzdCgpO1xuXHR9KS5jYXRjaChmdW5jdGlvbigpIHtcblx0XHRpZiAoJGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygnZGVzdHJveScpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldFN0b3JlTGlzdCgpIHtcblx0dmFyIGdlb2xvY2F0aW9uUG9zaXRpb247XG5cdGlmIChkYXRhQnVmZmVyLnBvc2l0aW9uICYmIGRhdGFCdWZmZXIucG9zaXRpb24uY29vcmRzKSB7XG5cdFx0Z2VvbG9jYXRpb25Qb3NpdGlvbiA9IHtcblx0XHRcdGNvb3Jkczoge1xuXHRcdFx0XHRhY2N1cmFjeTogZGF0YUJ1ZmZlci5wb3NpdGlvbi5jb29yZHMuYWNjdXJhY3ksXG5cdFx0XHRcdGxhdGl0dWRlOiBkYXRhQnVmZmVyLnBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSxcblx0XHRcdFx0bG9uZ2l0dWRlOiBkYXRhQnVmZmVyLnBvc2l0aW9uLmNvb3Jkcy5sb25naXR1ZGVcblx0XHRcdH0sXG5cdFx0XHR0aW1lc3RhbXA6IGRhdGFCdWZmZXIucG9zaXRpb24udGltZXN0YW1wXG5cdFx0fTtcblx0fVxuXG5cdHZhciBwYXlsb2FkID0ge1xuXHRcdFNvdXJjZTogJ1N0b3JlTG9jYXRvclBhZ2UnLFxuXHRcdEdlb2xvY2F0aW9uUG9zaXRpb246IGdlb2xvY2F0aW9uUG9zaXRpb25cblx0fTtcblx0aWYgKGRhdGFCdWZmZXIucXVlcnkgIT0gdW5kZWZpbmVkKSB7XG5cdFx0cGF5bG9hZC5RdWVyeSA9IGRhdGFCdWZmZXIucXVlcnk7XG5cdH1cblx0aWYgKGRhdGFCdWZmZXIubGltaXQgIT0gdW5kZWZpbmVkKSB7XG5cdFx0cGF5bG9hZC5MaW1pdCA9IGRhdGFCdWZmZXIubGltaXQ7XG5cdH1cblx0aWYgKGRhdGFCdWZmZXIub2Zmc2V0ICE9IHVuZGVmaW5lZCkge1xuXHRcdHBheWxvYWQuT2Zmc2V0ID0gZGF0YUJ1ZmZlci5vZmZzZXQ7XG5cdH1cblxuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdHVybDogVXJscy5Cb3Bpcy5HZXRTdG9yZXNGb3JHZW9sb2NhdGlvblBvc2l0aW9uLFxuXHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksXG5cdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRyZW5kZXJTdG9yZUxpc3QoZGF0YSk7XG5cdFx0fSxcblx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcblx0XHR9XG5cdH0pO1x0XHRcbn1cblxuZnVuY3Rpb24gcmVuZGVyU3RvcmVMaXN0KGRhdGEpIHtcblx0dmFyIGxvY2F0aW9uRGF0YTtcblx0aWYgKGRhdGEgJiYgZGF0YS5TZXJ2aWNlU3VjY2Vzc2Z1bGx5Q2FsbGVkICYmIGRhdGEuSW5xdWlyeVJlc3VsdCAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YSAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0bG9jYXRpb25EYXRhID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGE7XG5cdH1cblxuXHQkY29udGFpbmVyLmF0dHIoJ3N0YXRlJywgJ3Jlc3VsdCcpO1xuXHRpZiAobG9jYXRpb25EYXRhICYmIGxvY2F0aW9uRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0bG9jYXRpb25EYXRhID0gbG9jYXRpb25EYXRhLnNvcnQoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcblx0XHRcdHJldHVybiBsZWZ0LmRpc3RhbmNlIC0gcmlnaHQuZGlzdGFuY2U7XG5cdFx0fSk7XG5cdFx0XG5cdFx0ZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ10gPSBbXTtcblx0XHQkY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsIGxvY2F0aW9uRGF0YS5sZW5ndGgpO1xuXHRcdFxuXHRcdHZhciBzdG9yZUxpc3RIdG1sID0gJyc7XG5cdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5maW5kKCcubm8tcmVzdWx0cycpLnJlbW92ZSgpO1xuXHRcdGZvciAodmFyIGxvY2F0aW9uRWxlbWVudCBpbiBsb2NhdGlvbkRhdGEpIHtcblx0XHRcdHZhciBsb2NhdGlvbiA9IGxvY2F0aW9uRGF0YVtsb2NhdGlvbkVsZW1lbnRdO1xuXHRcdFx0XG5cdFx0XHRpZiAobG9jYXRpb24gJiYgIWRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2xvY2F0aW9uLmNvZGVdICYmIGxvY2F0aW9uLlN0b3JlSW5mby5TdGF0ZUNvZGVQYXJzZWQgJiYgbG9jYXRpb24uU3RvcmVJbmZvLlBvc3RhbENvZGUpIHtcblx0XHRcdFx0dmFyIHN0b3JlUGhvbmUgPSAnJztcblx0XHRcdFx0dmFyIHN0b3JlT3BlblVudGlsID0gJyc7XG5cdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8pIHtcblx0XHRcdFx0XHRpZiAobG9jYXRpb24uU3RvcmVJbmZvLlBob25lKSB7XG5cdFx0XHRcdFx0XHRzdG9yZVBob25lID0gbG9jYXRpb24uU3RvcmVJbmZvLlBob25lO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAobG9jYXRpb24uU3RvcmVJbmZvLk9wZW5VbnRpbCkge1xuXHRcdFx0XHRcdFx0c3RvcmVPcGVuVW50aWwgPSBsb2NhdGlvbi5TdG9yZUluZm8uT3BlblVudGlsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0dmFyIHN0b3JlSW52ZW50b3J5TGluayA9ICcnO1xuXHRcdFx0XHRpZiAobG9jYXRpb24uU3RvcmVJbmZvLlN0b3JlSW52ZW50b3J5TGluaykge1xuXHRcdFx0XHRcdHN0b3JlSW52ZW50b3J5TGluayA9ICc8YSBjbGFzcz1cInNob3Atc3RvcmUtaW52ZW50b3J5XCI+JyArIFJlc291cmNlcy5TdG9yZXMuU2hvcFN0b3JlSW52ZW50b3J5ICsgJzwvYT4nO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGRpcmVjdGlvbnNMaW5rID0gJyc7XG5cdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uRGlyZWN0aW9uc1VybCkge1xuXHRcdFx0XHRcdGRpcmVjdGlvbnNMaW5rID0gJzxhIGNsYXNzPVwiZGlyZWN0aW9uc1wiIGhyZWY9XCInICsgbG9jYXRpb24uU3RvcmVJbmZvLkRpcmVjdGlvbnNVcmwgKyAnXCIgdGFyZ2V0PVwiX2JsYW5rXCI+RGlyZWN0aW9uczwvYT4nO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0c3RvcmVMaXN0SHRtbCArPSBsb2NhdGlvblNlYXJjaFJlc3VsdEl0ZW1UZW1wbGF0ZSh7XG5cdFx0XHRcdFx0U3RvcmVJZDogbG9jYXRpb24uY29kZSxcblx0XHRcdFx0XHRTdG9yZU5hbWU6IGxvY2F0aW9uLlN0b3JlSW5mby5OYW1lLFxuXHRcdFx0XHRcdERpc3RhbmNlOiBsb2NhdGlvbi5TdG9yZUluZm8uRGlzdGFuY2UudG9GaXhlZCgxKSArICcgbWknLFxuXHRcdFx0XHRcdEh0bWw6ICc8YSBocmVmPVwiJyArIFVybHMuc3RvcmVEZXRhaWxzICsgJz9TdG9yZUlEPScgKyBsb2NhdGlvbi5jb2RlICsgJ1wiPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uTmFtZSArICc8L2E+PGJyLz4nICtcblx0XHRcdFx0XHRcdFx0bG9jYXRpb24uU3RvcmVJbmZvLkFkZHJlc3MxICsgJzxici8+JyArIFxuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5TdG9yZUluZm8uQ2l0eSArICcsICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uU3RhdGVDb2RlUGFyc2VkICsgJyAnICsgbG9jYXRpb24uU3RvcmVJbmZvLlBvc3RhbENvZGUuc3Vic3RyKDAsIDUpICsgJzxici8+JyArXG5cdFx0XHRcdFx0XHRcdHN0b3JlUGhvbmUgKyAnPGJyLz4nICtcblx0XHRcdFx0XHRcdFx0c3RvcmVPcGVuVW50aWwsXG5cdFx0XHRcdFx0RGlyZWN0aW9uc0xpbms6IGRpcmVjdGlvbnNMaW5rLFxuXHRcdFx0XHRcdFN0b3JlSW52ZW50b3J5TGluazogc3RvcmVJbnZlbnRvcnlMaW5rXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRkYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtsb2NhdGlvbi5jb2RlXSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChkYXRhLklucXVpcnlSZXN1bHQubWV0YSAmJiBkYXRhLklucXVpcnlSZXN1bHQubWV0YS5wYWdlIDwgZGF0YS5JbnF1aXJ5UmVzdWx0Lm1ldGEucGFnZXMpIHtcblx0XHRcdHN0b3JlTGlzdEh0bWwgKz0gJzxsaSBjbGFzcz1cImxvYWQtbW9yZS1jb250YWluZXJcIj48YSBjbGFzcz1cImxvYWQtbW9yZVwiPkxvYWQgTW9yZTwvYT48L2xpPic7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciByZXN1bHRIdG1sID0gbG9jYXRpb25TZWFyY2hSZXN1bHRDb250YWluZXJUZW1wbGF0ZSh7XG5cdFx0XHRIdG1sOiBzdG9yZUxpc3RIdG1sXG5cdFx0fSk7XG5cdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5maW5kKCcubG9hZC1tb3JlLWNvbnRhaW5lcicpLnJlbW92ZSgpO1xuXHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuYXBwZW5kKHJlc3VsdEh0bWwpO1xuXHR9IGVsc2Uge1xuXHRcdCRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgJzAnKTtcblx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmh0bWwoJzxsaSBjbGFzcz1cIm5vLXJlc3VsdHNcIj5ObyBzdG9yZXMgZm91bmQhIFBsZWFzZSB0cnkgYSBkaWZmZXJlbnQgc2VhcmNoLjwvbGk+Jyk7XG5cdH1cblxuXHRpZiAoJHVzZU15TG9jYXRpb25CdXR0b24uYXR0cignbG9hZGluZycpKSB7XG5cdFx0JHVzZU15TG9jYXRpb25CdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHR9XG5cdGlmICgkc2VhcmNoQnV0dG9uLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdCRzZWFyY2hCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHR9XG5cdGlmICgkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygnZGVzdHJveScpO1xuXHR9XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXHRkYXRhQnVmZmVyID0ge1xuXHRcdG9mZnNldDogMFxuXHR9O1xuXG5cdCRjb250YWluZXIgPSAkKCcjc3RvcmVzX21haW4nKTtcblx0JGNvbnRlbnQgPSAkY29udGFpbmVyLmZpbmQoJy5jb250ZW50Jyk7XG5cdCR1c2VNeUxvY2F0aW9uQnV0dG9uID0gJCgnLnN0b3JlLWZpbHRlci1jb250YWluZXIgLnVzZS1teS1sb2NhdGlvbicpO1xuXHQkc2VhcmNoQnV0dG9uID0gJCgnLnN0b3JlLWZpbHRlci1jb250YWluZXIgLmJ0bi5idG4tcHJpbWFyeScpO1xuXHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzID0gJCgnLmxvY2F0aW9uLXNlYXJjaC1yZXN1bHRzJyk7XG5cdGxvY2F0aW9uU2VhcmNoUmVzdWx0Q29udGFpbmVyVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRsb2NhdGlvblNlYXJjaFJlc3VsdEl0ZW1UZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1pdGVtLXN0b3JlLWxvY2F0b3InKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XHRcblxuXHRpbml0aWFsaXplRXZlbnRzKCk7XG59OyIsIid1c2Ugc3RyaWN0JztcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG5cdFxyXG5cdGVsZW1lbnRQcmVmaXg6ICdzaGlwcGluZy1yZXN0cmljdGlvbnMtcG9wdXAnLFxyXG5cdGVsZW1lbnQ6IG51bGwsXHJcblx0ZGVmYXVsdFRpdGxlOiAnJyxcclxuXHRkZWZhdWx0Q29udGVudDogJycsXHJcblx0XHJcblx0aW5pdDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRcdGlmICghJCggJy4nICsgdGhpcy5lbGVtZW50UHJlZml4ICkubGVuZ3RoKSB7XHJcblx0XHRcdCQoJ2JvZHknKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCInICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ1wiPjxkaXYgY2xhc3M9XCInICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ19fcG9wdXBcIj48aDIgY2xhc3M9XCInICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ19faDJcIj48L2gyPjxhIGNsYXNzPVwiJyArIHRoaXMuZWxlbWVudFByZWZpeCArICdfX2Nsb3NlXCIgaHJlZj1cIiNcIj4mdGltZXM7PC9hPjxkaXYgY2xhc3M9XCInICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ19fY29udGVudFwiPjwvZGl2PjwvZGl2PjwvZGl2PicpO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnQgPSAkKCAnLicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKTtcclxuXHRcdFx0dmFyIGVsID0gdGhpcztcclxuXHRcdFx0dGhpcy5lbGVtZW50LmZpbmQoJy4nICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ19fY2xvc2UnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdGVsLmhpZGVQb3B1cChlKTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblx0XHR0aGlzLmVsZW1lbnQuZmluZCgnLicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19oMicpLmh0bWwob3B0aW9ucy50aXRsZSB8fCB0aGlzLmRlZmF1bHRUaXRsZSk7XHJcblx0XHR0aGlzLmVsZW1lbnQuZmluZCgnLicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19jb250ZW50JykuaHRtbChvcHRpb25zLmNvbnRlbnQgfHwgdGhpcy5kZWZhdWx0Q29udGVudCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cdFxyXG5cdHNob3dQb3B1cDogZnVuY3Rpb24gKCkge1xyXG4gICAgXHR0aGlzLmVsZW1lbnQuYWRkQ2xhc3ModGhpcy5lbGVtZW50UHJlZml4ICsgJ19fdmlzaWJsZScpO1xyXG4gICAgXHRyZXR1cm4gdGhpcztcclxuICAgIH0sXHJcbiAgICBcclxuICAgIGhpZGVQb3B1cDogZnVuY3Rpb24gKGUpIHtcclxuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgXHR0aGlzLmVsZW1lbnQucmVtb3ZlQ2xhc3ModGhpcy5lbGVtZW50UHJlZml4ICsgJ19fdmlzaWJsZScpO1xyXG4gICAgfSxcclxufTtcclxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW1hZ2VzTG9hZGVkID0gcmVxdWlyZSgnaW1hZ2VzbG9hZGVkJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG5leHBvcnRzLnN5bmNIZWlnaHRPZlRpbGVzID0gc3luY0hlaWdodE9mVGlsZXM7XG5cbnZhciB3aW5kb3dXaWR0aDtcblxuZnVuY3Rpb24gZ3JpZFZpZXdUb2dnbGUoKSB7XG4gICAgJCgnLnRvZ2dsZS1ncmlkJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKCcuc2VhcmNoLXJlc3VsdC1jb250ZW50JykudG9nZ2xlQ2xhc3MoJ3dpZGUtdGlsZXMnKTtcbiAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnd2lkZScpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBsaW5lIGNsYW1waW5nIGZvciBwcm9kdWN0IHRpbGUgcHJvZHVjdCB0aXRsZXMuXG4gKi9cblxuIGZ1bmN0aW9uIGNsYW1wUHJvZHVjdFRpbGVUaXRsZXMoKSB7XG4gICAgJCgnaDYucHJvZHVjdC1uYW1lIC5uYW1lLWxpbmsnKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBjbGFtcFRpdGxlKSB7XG4gICAgICAgICRjbGFtcChjbGFtcFRpdGxlLCB7XG4gICAgICAgICAgICBjbGFtcDogMixcbiAgICAgICAgICAgIHVzZU5hdGl2ZUNMYW1wOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9KTtcbiB9XG4gXG4gZnVuY3Rpb24gaW5pdGlhbGl6ZVN3YXRjaGVzKCkge1xuXHQgJCgnLmdyaWQtdGlsZScpLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHQkKGVsZW1lbnQpLmZpbmQoJy55ZXMtYWx0cyB1bC5zd2F0Y2gtbGlzdCBsaScpLmVhY2goZnVuY3Rpb24oaSwgZWxlbSkge1xuXHRcdFx0dmFyIGFsdERpc3BsYXkgPSAnc2hvdy1jb250ZW50Jztcblx0XHRcdGlmICggaSA+PSA0ICl7XG5cdFx0XHRcdGFsdERpc3BsYXkgPSAnaGlkZGVuLWNvbnRlbnQnO1xuXHRcdFx0fVxuXHRcdFx0JChlbGVtKS5hZGRDbGFzcyhhbHREaXNwbGF5KTtcblx0XHR9KTtcblx0XHR2YXIgYWx0SGlkZGVuQ291bnQgPSAkKGVsZW1lbnQpLmZpbmQoJy5oaWRkZW4tY29udGVudCcpLmxlbmd0aDtcblx0XHR2YXIgYWx0SGlkZGVuVG9nZ2xlID0gJysgJyArIGFsdEhpZGRlbkNvdW50O1xuXHRcdHZhciBhbHRCdXR0b25FeGlzdHMgPSAkKGVsZW1lbnQpLmZpbmQoJy5hbHRCdXR0b24nKS5sZW5ndGg7XG5cdFx0aWYgKGFsdEhpZGRlbkNvdW50ID4gMCl7XG5cdFx0XHQkKGVsZW1lbnQpLmZpbmQoJy5oaWRkZW4tY29udGVudCcpLmhpZGUoKTtcblx0XHRcdGlmIChhbHRCdXR0b25FeGlzdHMgPT0gMCl7XG5cdFx0XHRcdCQoZWxlbWVudCkuZmluZCgnLnllcy1hbHRzIHVsLnN3YXRjaC1saXN0JykuYXBwZW5kKCc8YnV0dG9uIGNsYXNzPVwiYWx0QnV0dG9uXCI+JyArIGFsdEhpZGRlblRvZ2dsZSArICc8L2J1dHRvbj4nKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoZWxlbWVudCkuZmluZCgnLmFsdEJ1dHRvbicpLnRleHQoYWx0SGlkZGVuVG9nZ2xlKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuIH1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZXZlbnRzIG9uIHRoZSBwcm9kdWN0LXRpbGUgZm9yIHRoZSBmb2xsb3dpbmcgZWxlbWVudHM6XG4gKiAtIHN3YXRjaGVzXG4gKiAtIHRodW1ibmFpbHNcbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcbiAgICBncmlkVmlld1RvZ2dsZSgpO1xuICAgIGluaXRpYWxpemVTd2F0Y2hlcygpO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgIFx0JCgnI3NlYXJjaC1yZXN1bHQtaXRlbXMgLmdyaWQtdGlsZScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgXHRcdHZhciAkZ3JpZEl0ZW0gPSAkKHRoaXMpLFxuICAgIFx0XHRcdCRwcmltYXJ5Q29sb3IgPSAkZ3JpZEl0ZW0uZGF0YSgncHJpbWFyeS1jb2xvcicpLFxuICAgIFx0XHRcdCR0aHVtYiA9ICRncmlkSXRlbS5maW5kKCcucHJvZHVjdC1pbWFnZSAudGh1bWItbGluayBpbWcnKS5lcSgwKSxcbiAgICBcdFx0XHQkdGh1bWJsaW5rID0gJGdyaWRJdGVtLmZpbmQoJy5wcm9kdWN0LWltYWdlIGEudGh1bWItbGluaycpLmVxKDApLFxuICAgIFx0XHRcdCRuYW1lbGluayA9ICRncmlkSXRlbS5maW5kKCcucHJvZHVjdC1jb250ZW50IC5wcm9kdWN0LW5hbWUgYS5uYW1lLWxpbmsnKS5lcSgwKTtcbiAgICBcdFx0JGdyaWRJdGVtLmZpbmQoJy5wcm9kdWN0LWNvbnRlbnQgLnByb2R1Y3Qtc3dhdGNoZXMgLnN3YXRjaC1saXN0IGxpJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICBcdFx0XHR2YXIgJGN1cnJzd2F0Y2ggPSAkKHRoaXMpLFxuICAgIFx0XHRcdFx0JGN1cnJocmVmID0gJGN1cnJzd2F0Y2guZmluZCgnYS5zd2F0Y2gnKS5hdHRyKCdocmVmJyksXG4gICAgXHRcdFx0XHQkY3VycmNvbG9yID0gJGN1cnJzd2F0Y2guZGF0YSgnY29sb3InKTtcbiAgICBcdFx0XHRpZiAoJHByaW1hcnlDb2xvciA9PSAkY3VycmNvbG9yKSB7XG4gICAgXHRcdFx0XHR2YXIgJGRhdGEgPSAkY3VycnN3YXRjaC5maW5kKCcuc3dhdGNoLWltYWdlJykuZGF0YSgndGh1bWInKTtcbiAgICBcdFx0XHRcdFxuICAgIFx0XHRcdFx0aWYgKCR0aHVtYmxpbmsuYXR0cignc2VsZWN0ZWQtbG9jYXRpb25zJykpIHtcbiAgICBcdFx0XHRcdFx0JGN1cnJocmVmID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKCRjdXJyaHJlZiwgJ3NlbGVjdGVkTG9jYXRpb25zJywgJHRodW1ibGluay5hdHRyKCdzZWxlY3RlZC1sb2NhdGlvbnMnKSk7XG4gICAgXHRcdFx0XHR9XG4gICAgXHRcdFx0XHRcbiAgICBcdFx0XHRcdCRuYW1lbGluay5hdHRyKCdocmVmJywgJGN1cnJocmVmKTtcbiAgICBcdFx0XHRcdCR0aHVtYmxpbmsuYXR0cignaHJlZicsICRjdXJyaHJlZik7XG4gICAgXHRcdFx0XHRcblx0XHRcdFx0XHRpZiAoJGRhdGEpIHtcblx0XHRcdFx0XHRcdCR0aHVtYi5hdHRyKHtcblx0XHRcdFx0XHRcdFx0c3JjOiAkZGF0YS5zcmMsXG5cdFx0XHRcdFx0XHRcdGFsdDogJGRhdGEuYWx0LFxuXHRcdFx0XHRcdFx0XHR0aXRsZTogJGRhdGEudGl0bGVcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cbiAgICBcdFx0XHR9XG4gICAgXHRcdH0pXG4gICAgXHR9KTtcblxuXHRcdCQod2luZG93KS5vZmYoJ2xvYWQuUHJvZHVjdFRpbGUgcmVzaXplLlByb2R1Y3RUaWxlJykub24oJ2xvYWQuUHJvZHVjdFRpbGUgcmVzaXplLlByb2R1Y3RUaWxlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHdpbmRvd1dpZHRoICE9ICQod2luZG93KS53aWR0aCgpKSB7XG5cdFx0XHQgICAgc3luY0hlaWdodE9mVGlsZXMoKTtcbiAgICAgICAgICAgIH1cblx0XHR9KTtcblxuXHRcdGltYWdlc0xvYWRlZCgkKCcjc2VhcmNoLXJlc3VsdC1pdGVtcyAuZ3JpZC10aWxlJykpLm9uKCdkb25lJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0c3luY0hlaWdodE9mVGlsZXMoKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgXG5cdCQoJy5zd2F0Y2gtbGlzdCAuc3dhdGNoJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAvLyBnZXQgY3VycmVudCB0aHVtYiBkZXRhaWxzXG4gICAgICAgIHZhciAkdGlsZSA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3QtdGlsZScpLFxuICAgICAgICAgICAgJHRodW1iID0gJHRpbGUuZmluZCgnLnByb2R1Y3QtaW1hZ2UgLnRodW1iLWxpbmsgaW1nJykuZXEoMCksXG4gICAgICAgICAgICBkYXRhID0gJCh0aGlzKS5jaGlsZHJlbignLnN3YXRjaC1pbWFnZScpLmZpbHRlcignOmZpcnN0JykuZGF0YSgndGh1bWInKSxcbiAgICAgICAgICAgIGN1cnJlbnQgPSAkdGh1bWIuZGF0YSgnY3VycmVudCcpO1xuXG4gICAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IHRpbWUsIHRoZW4gcmVjb3JkIHRoZSBjdXJyZW50IGltZ1xuICAgICAgICBpZiAoIWN1cnJlbnQpIHtcbiAgICAgICAgICAgICR0aHVtYi5kYXRhKCdjdXJyZW50Jywge1xuICAgICAgICAgICAgICAgIHNyYzogJHRodW1iWzBdLnNyYyxcbiAgICAgICAgICAgICAgICBhbHQ6ICR0aHVtYlswXS5hbHQsXG4gICAgICAgICAgICAgICAgdGl0bGU6ICR0aHVtYlswXS50aXRsZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgdGhlIHRpbGUgaW1hZ2UgdG8gdGhlIHZhbHVlcyBwcm92aWRlZCBvbiB0aGUgc3dhdGNoIGRhdGEgYXR0cmlidXRlc1xuXHRcdGlmIChkYXRhKSB7XG5cdFx0XHQkdGh1bWIuYXR0cih7XG5cdFx0XHRcdHNyYzogZGF0YS5zcmMsXG5cdFx0XHRcdGFsdDogZGF0YS5hbHQsXG5cdFx0XHRcdHRpdGxlOiBkYXRhLnRpdGxlXG5cdFx0XHR9KTtcblx0XHR9XG4gICAgfSk7XG5cdFxuICAgIC8vIGNoZWNrIGV2ZXJ5IDIgc2VjcyBpZiBCViBzdGFycyBoYXMgYWxyZWFkeSBsb2FkZWRcbiAgICAvLyBpbiBjYXNlIEJWIGlzIGp1c3QgZGVsYXllZCBpbiBzaG93aW5nIHVwLCB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBpbnRlcnZhbCBmb3IgYXQgbGVhc3QgNXggdG8gcHJldmVudCBpbmZpbml0ZSBsb29wXG4gICAgdmFyIGhpZGVTdGFycyA9IHNldEludGVydmFsKGZ1bmN0aW9uKCl7XG4gICAgXHR2YXIgY3RyID0gMDtcbiAgICBcdCQoXCJkaXZbaWRePUJWUlJJbmxpbmVSYXRpbmddXCIpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgIFx0XHRpZiAoJCh0aGlzKS5maW5kKFwiLmJ2LXJhdGluZy1zdGFycy1vblwiKS53aWR0aCgpID4gMCkgeyB9IGVsc2UgeyAkKHRoaXMpLmZpbmQoXCIuYnYtc3RhcnMtY29udGFpbmVyXCIpLmF0dHIoXCJzdHlsZVwiLCBcImRpc3BsYXk6bm9uZSAhaW1wb3J0YW50XCIpOyB9XG4gICAgXHRcdGlmICgkKHRoaXMpLmZpbmQoXCIuYnYtcmF0aW5nLXN0YXJzLW9uXCIpLmxlbmd0aCkge1xuICAgIFx0XHRcdGNsZWFySW50ZXJ2YWwoaGlkZVN0YXJzKTtcbiAgICBcdFx0fSBlbHNlIHsgY3RyKys7XHR9XG4gICAgXHR9KTtcbiAgICBcdGlmIChjdHI+MTApIHsgY2xlYXJJbnRlcnZhbChoaWRlU3RhcnMpOyB9IC8vd2UgbmVlZCB0byBzdG9wIHRoZSBmdW5jdGlvbiBpZiBCViBpcyBub3QgY29uZmlndXJlZC5cbiAgICB9LCAyMDAwKTtcblxuICAgIHZhciBhdHRlbXB0c1RvQ2hhbmdlVGV4dCA9IDA7XG4gICAgdmFyIGFkZFRleHRSZXZpZXdzVG9Db3VudFJldmlld3MgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpe1xuICAgIFx0YXR0ZW1wdHNUb0NoYW5nZVRleHQrKztcbiAgICBcdCQoJ2RpdltpZF49QlZSUklubGluZVJhdGluZ10nKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgXHRcdHZhciAkcmF0aW5nID0gJCh0aGlzKS5maW5kKCdzcGFuLmJ2LXJhdGluZy1sYWJlbCcpO1xuICAgIFx0XHRpZiAoJHJhdGluZy5sZW5ndGgpIHtcbiAgICBcdFx0XHR2YXIgdGV4dCA9ICRyYXRpbmcuaHRtbCgpO1xuICAgICAgICBcdFx0aWYgKHRleHQuaW5kZXhPZihSZXNvdXJjZXMuUkVWSUVXUykgPCAwKSB7XG4gICAgICAgIFx0XHRcdCRyYXRpbmcuaHRtbCh0ZXh0LnJlcGxhY2UoJyknLCAnICcgKyBSZXNvdXJjZXMuUkVWSUVXUyArICcpJykpO1xuICAgICAgICBcdFx0XHRjbGVhckludGVydmFsKGFkZFRleHRSZXZpZXdzVG9Db3VudFJldmlld3MpO1xuICAgICAgICBcdFx0fVxuICAgIFx0XHR9XG4gICAgXHR9KTtcbiAgICBcdGlmIChhdHRlbXB0c1RvQ2hhbmdlVGV4dCA+IDE1KSB7XG4gICAgXHRcdGNsZWFySW50ZXJ2YWwoYWRkVGV4dFJldmlld3NUb0NvdW50UmV2aWV3cyk7XG4gICAgXHR9XG4gICAgfSwgNTAwKTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnZGl2LmJ2LWNvbXBhdCcsIGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhciAkdGlsZUJsb2NrID0gJCh0aGlzKS5jbG9zZXN0KCdkaXYucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIGlmICgkdGlsZUJsb2NrKSB7XG4gICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gJHRpbGVCbG9jay5maW5kKCdhLnRodW1iLWxpbmsnKS5hdHRyKCdocmVmJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGNsYW1wUHJvZHVjdFRpbGVUaXRsZXMoKTtcbn1cblxuZnVuY3Rpb24gc3luY0hlaWdodE9mVGlsZXMoKSB7XG5cdHZhciAkdGlsZXMgPSAkKCcudGlsZXMtY29udGFpbmVyIC5wcm9kdWN0LXRpbGUnKTtcbiAgICBpZiAoJHRpbGVzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblxuXHQkdGlsZXMuZmluZCgnLnByb2R1Y3QtaW1hZ2UgLnRodW1iLWxpbmsnKS5zeW5jSGVpZ2h0VG9BdmVyYWdlKCk7XG5cdCR0aWxlcy5lYWNoKGZ1bmN0aW9uIChpZHgpIHtcblx0XHQkKHRoaXMpLmRhdGEoJ2lkeCcsIGlkeCk7XG5cdH0pO1xufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgd2luZG93V2lkdGggPSAkKHdpbmRvdykud2lkdGgoKTtcblxuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuXHRcclxuXHRpbml0OiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0aWYgKCQoJy5yb3RhdGUtM2RfX2ltZycpLmxlbmd0aCkge1xyXG5cdFx0XHQkKCcucm90YXRlLTNkX19jb250YWluZXInKS5wcmVwZW5kKCc8YSBocmVmPVwiI1wiIGNsYXNzPVwicm90YXRlLTNkX19yb3RhdGUgcm90YXRlLTNkX19yb3RhdGVMZWZ0XCI+Jm5ic3A7PC9hPjxhIGhyZWY9XCIjXCIgY2xhc3M9XCJyb3RhdGUtM2RfX3JvdGF0ZSByb3RhdGUtM2RfX3JvdGF0ZVJpZ2h0XCI+Jm5ic3A7PC9hPicpO1xyXG5cdFx0XHQkKCcucm90YXRlLTNkX19yb3RhdGVMZWZ0Jykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0JCgnLnJvdGF0ZS0zZF9faW1nJykudHJpZ2dlcihcInN0ZXBMZWZ0XCIpO1xyXG5cdFx0XHR9KTtcclxuXHRcdFx0JCgnLnJvdGF0ZS0zZF9fcm90YXRlUmlnaHQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHQkKCcucm90YXRlLTNkX19pbWcnKS50cmlnZ2VyKFwic3RlcFJpZ2h0XCIpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG59O1xyXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciAkbG9hZGVyO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFNob3dzIGFuIEFKQVgtbG9hZGVyIG9uIHRvcCBvZiBhIGdpdmVuIGNvbnRhaW5lclxuICogQHBhcmFtIHtFbGVtZW50fSBjb250YWluZXIgVGhlIEVsZW1lbnQgb24gdG9wIG9mIHdoaWNoIHRoZSBBSkFYLUxvYWRlciB3aWxsIGJlIHNob3duXG4gKi9cbnZhciBzaG93ID0gZnVuY3Rpb24gKGNvbnRhaW5lciwgZGlzcGxheUluTGluZSkge1xuICAgIHZhciB0YXJnZXQgPSAoIWNvbnRhaW5lciB8fCAkKGNvbnRhaW5lcikubGVuZ3RoID09PSAwKSA/ICQoJ2JvZHknKSA6ICQoY29udGFpbmVyKTtcbiAgICAkbG9hZGVyID0gJGxvYWRlciB8fCAkKCcubG9hZGVyJyk7XG5cbiAgICBpZiAoJGxvYWRlci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgJGxvYWRlciA9ICQoJzxkaXYvPicpLmFkZENsYXNzKCdsb2FkZXInKVxuICAgICAgICAgICAgLmFwcGVuZCgkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnbG9hZGVyLWluZGljYXRvcicpLCAkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnbG9hZGVyLWJnJykpO1xuICAgIH1cblxuICAgIGlmIChkaXNwbGF5SW5MaW5lKSB7XG4gICAgICAgICRsb2FkZXIuY3NzKCdkaXNwbGF5JywgJ2lubGluZS1ibG9jaycpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICRsb2FkZXIuY3NzKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgfVxuICAgIHJldHVybiAkbG9hZGVyLmFwcGVuZFRvKHRhcmdldCk7XG59O1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBIaWRlcyBhbiBBSkFYLWxvYWRlclxuICovXG52YXIgaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoJGxvYWRlcikge1xuICAgICAgICAkbG9hZGVyLmhpZGUoKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLnNob3cgPSBzaG93O1xuZXhwb3J0cy5oaWRlID0gaGlkZTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhZ2UgPSByZXF1aXJlKCcuL3BhZ2UnKTtcbnZhciBEYXRhTGF5ZXJDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0RhdGFMYXllckNvbnN0YW50cycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxudmFyIGlzQ2hlY2tvdXQsIGlzRWNob0NhcnQsIGZuVXBkYXRlQ2FydCwgZm5SZW5kZXJDYXJ0LCAkZm9jdXNlZEVsZW1lbnQ7XG52YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuICAgIElzTGFiZWxTaG93bjogZmFsc2UsXG4gICAgQ3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcbiAgICBCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcbn07XG5cbmZ1bmN0aW9uIHVwZGF0ZVN0ZXBwZXJRdHlVSSgkdGhpcywgaW5jcmVtZW50KSB7XG5cdHZhciAkcXVhbnRpdHlTdGVwcGVyID0gaW5jcmVtZW50ICE9IHVuZGVmaW5lZCA/ICR0aGlzLnBhcmVudCgnLnF1YW50aXR5LXN0ZXBwZXInKSA6ICR0aGlzO1xuXHR2YXIgJGlucHV0ID0gJHF1YW50aXR5U3RlcHBlci5maW5kKCdpbnB1dC5pbnB1dC10ZXh0Jyk7XG5cdHZhciBxdWFudGl0eSA9IHBhcnNlSW50KCRpbnB1dC52YWwoKSk7XG5cdC8vIE9ubHkgaW5jcmVtZW50IG9yIGRlY3JlbWVudCBxdWFudGl0eSBpZiBhIGJvb2xlYW4gd2FzIHBhc3NlZCBpbnRvIHRoZSBmdW5jdGlvblxuXHRpZiAoaW5jcmVtZW50ICE9IHVuZGVmaW5lZCkge1xuXHRcdGluY3JlbWVudCA/IHF1YW50aXR5KysgOiBxdWFudGl0eS0tO1xuXHR9XG5cdFxuXHQvLyBFbmFibGUgb3IgRGlzYWJsZSB0aGUgcGx1cy9taW51cyBzaWducyBvbiB0aGUgcXVhbnRpdHkgc3RlcHBlclxuXHR2YXIgJGluY0J1dHRvbiA9ICRxdWFudGl0eVN0ZXBwZXIuZmluZCgnYnV0dG9uLmluY3JlYXNlLnBsdXMnKTtcblx0dmFyICRkZWNCdXR0b24gPSAkcXVhbnRpdHlTdGVwcGVyLmZpbmQoJ2J1dHRvbi5kZWNyZWFzZS5taW51cycpO1xuXG5cdGlmIChxdWFudGl0eSA8PSAxKSB7XG5cdFx0JGRlY0J1dHRvbi5hZGRDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdCRpbmNCdXR0b24ucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0fSBlbHNlIGlmIChxdWFudGl0eSA+IDEpIHtcblx0XHQkZGVjQnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0JGluY0J1dHRvbi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHR9XG5cblx0Ly8gVXBkYXRlIHRoZSB2YWx1ZSBvZiB0aGUgcXVhbnRpdHkgc3RlcHBlclxuXHQkaW5wdXQuYXR0cigncXVhbnRpdHktYnVmZmVyJywgcXVhbnRpdHkpO1xuXHQkaW5wdXQudmFsKHF1YW50aXR5KTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlTWluaUNhcnRVSShpbmNyZW1lbnQsICRsaW5lSXRlbSkge1xuXHR2YXIgJG1pbmlDYXJ0RWxtID0gJCgnLm1pbmktY2FydCAubWluaWNhcnQtcXVhbnRpdHknKS5sZW5ndGggPiAwID8gJCgnLm1pbmktY2FydCAubWluaWNhcnQtcXVhbnRpdHknKSA6ICQoJy5taW5pLWNhcnQgLmJ0bi1taW5pY2FydCAuYnRuLW1pbmljYXJ0LXF0eScpO1xuXHR2YXIgbWluaUNhcnRUb3RhbDtcblx0aWYgKCRtaW5pQ2FydEVsbS5sZW5ndGggPiAwKSB7XG5cdFx0bWluaUNhcnRUb3RhbCA9IHBhcnNlSW50KCRtaW5pQ2FydEVsbS5odG1sKCkudHJpbSgpKTtcblx0fVxuXG5cdGlmICgoaW5jcmVtZW50ICE9IG51bGwgJiYgdHlwZW9mIGluY3JlbWVudCA9PT0gXCJib29sZWFuXCIpICYmICEkbGluZUl0ZW0pIHtcblx0XHRpbmNyZW1lbnQgPyBtaW5pQ2FydFRvdGFsKysgOiBtaW5pQ2FydFRvdGFsLS07XG5cdH0gZWxzZSBpZiAoKGluY3JlbWVudCA9PSBudWxsIHx8IHR5cGVvZiBpbmNyZW1lbnQgIT0gXCJib29sZWFuXCIpICYmICRsaW5lSXRlbSkge1xuXHRcdHZhciBpdGVtUXR5ID0gcGFyc2VJbnQoJGxpbmVJdGVtLmZpbmQoJy5vcGMtcXR5JykudmFsKCkpO1xuXHRcdG1pbmlDYXJ0VG90YWwgPSBpdGVtUXR5ICYmIHR5cGVvZiBpdGVtUXR5ID09ICdudW1iZXInICYmIGl0ZW1RdHkgPiAwID8gbWluaUNhcnRUb3RhbCAtIGl0ZW1RdHkgOiBtaW5pQ2FydFRvdGFsO1xuXHRcdCRsaW5lSXRlbS5yZW1vdmUoKTtcblx0fVxuXHRcblx0Ly8gVXBkYXRlIHRoZSBiYXNrZXQgcXVhbnRpdHkgb24gdGhlIG1haW4gbmF2aWdhdGlvbiBiYXIgPiBtaW5pY2FydCBpY29uXG5cdG1pbmlDYXJ0VG90YWwgPj0gMSA/ICRtaW5pQ2FydEVsbS5odG1sKG1pbmlDYXJ0VG90YWwpIDogJG1pbmlDYXJ0RWxtLmh0bWwoMCk7XG5cblx0Ly8gVXBkYXRlIHRoZSBtaW5pY2FydCBtb2RhbCwgaWYgaXQncyBjdXJyZW50bHkgb3BlblxuXHRpZiAoJCgnLmFkZC10by1jYXJ0LW1vZGFsJykubGVuZ3RoID4gMCkge1xuXHRcdHZhciBwcm9kdWN0UmVjb21tZW5kYXRpb25zSHRtbCA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbCAgLm1haW4tY29udGVudCAucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMtY29udGFpbmVyJykuaHRtbCgpO1xuXHRcdCQuYWpheCh7dXJsIDogVXJscy5hZGRUb0NhcnRNb2RhbERpc3BsYXksIGRhdGFUeXBlOiAnaHRtbCcsIHN1Y2Nlc3MgOiBmdW5jdGlvbihtb2RhbENvbnRlbnQpIHtcblx0XHRcdGlmIChtb2RhbENvbnRlbnQubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwgLnVpLWRpYWxvZy1jb250ZW50JykuaHRtbChtb2RhbENvbnRlbnQpO1xuXHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwtY29udGVudCAubWFpbi1jb250ZW50IC5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucy1jb250YWluZXInKS5hcHBlbmQocHJvZHVjdFJlY29tbWVuZGF0aW9uc0h0bWwpO1xuXHRcdFx0XHQvLyBSZWZlcmVuY2UgYWRkVG9DYXJ0LmpzID4gYWRkSXRlbVRvQ2FydCgpID4gbGluZSAzMTQgKE1vdmUgdGl0bGUgZnJvbSBtYWluIGNvbnRlbnQgdG8gdG9wIG9mIHRoZSBtb2RhbClcblx0XHRcdFx0aWYgKCQoJy5hZGQtdG8tY2FydC1tb2RhbC1jb250ZW50JykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHZhciAkYWRkTWVzc2FnZSA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbC1jb250ZW50IC5tYWluLWNvbnRlbnQgLmFkZGVkLW1lc3NhZ2UnKTtcblx0XHRcdFx0XHQvLyBSZWZlcmVuY2UgYWRkVG9DYXJ0LmpzID4gYWRkSXRlbVRvQ2FydCgpID4gbGluZSAzNzcgKEluc2VydHMgdGhlIHdvcmQgJ0l0ZW0nIGludG8gdGhlIG1pbmljYXJ0IHRpdGxlKVxuXHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbC1jb250ZW50IC5hZGRlZC1tZXNzYWdlIC5jb3VudCcpLnRleHQoJ0l0ZW0nKTtcblx0XHRcdFx0XHRpZiAoJGFkZE1lc3NhZ2UubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLWNvbnRlbnQnKS5wcmVwZW5kKCRhZGRNZXNzYWdlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlQ2FydFRvdGFscygpIHtcblx0aWYgKGlzQ2hlY2tvdXQgJiYgZm5VcGRhdGVDYXJ0KSB7XG5cdFx0Zm5VcGRhdGVDYXJ0KCQoJy51cGRhdGUtY2FydC1idXR0b24nKS5hdHRyKCduYW1lJykpO1xuXHR9XG5cdGlmIChpc0VjaG9DYXJ0ICYmIGZuUmVuZGVyQ2FydCkge1xuXHRcdGZuUmVuZGVyQ2FydCgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUZyb21DYXJ0RGF0YUxheWVyKCR0aGlzKSB7XG5cdHZhciAkaXRlbSA9ICR0aGlzLmNsb3Nlc3QoJ1tkYXRhLXV1aWRdJyk7XG5cdGlmICgkaXRlbSkge1xuXHRcdHZhciBwcm9kdWN0RGF0YUZvclVuaXZlcnNhbEFuYWx5dGljcyA9IEpTT04ucGFyc2UoJGl0ZW0uZmluZCgnW2RhdGEtcHJvZHVjdC1ndG0tanNvbl0nKS5hdHRyKCdkYXRhLXByb2R1Y3QtZ3RtLWpzb24nKSk7XG5cdFx0dmFyIHByb2R1Y3REYXRhRm9yR29vZ2xlQW5hbHl0aWNzNCA9IEpTT04ucGFyc2UoJGl0ZW0uZmluZCgnW2RhdGEtcHJvZHVjdC1nYTQtanNvbl0nKS5hdHRyKCdkYXRhLXByb2R1Y3QtZ2E0LWpzb24nKSk7XG5cblx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFVuaXZlcnNhbEFuYWx5dGljczoge1xuXHRcdFx0XHRlY29tbWVyY2U6IHtcblx0XHRcdFx0XHRyZW1vdmU6IHtcblx0XHRcdFx0XHRcdHByb2R1Y3RzOiBbcHJvZHVjdERhdGFGb3JVbml2ZXJzYWxBbmFseXRpY3NdXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRHb29nbGVBbmFseXRpY3M0OiB7XG5cdFx0XHRcdHZhbHVlOiBwcm9kdWN0RGF0YUZvckdvb2dsZUFuYWx5dGljczQucHJpY2UsXG5cdFx0XHRcdGl0ZW1zOiBbcHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0XVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1JlbW92ZUZyb21DYXJ0JywgZGF0YU9iamVjdCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcXVhbnRpdHlEYXRhbGF5ZXJFdmVudHMoJHRoaXMsIGV2ZW50VHlwZSwgcXVhbnRpdHkpIHtcblx0dmFyICRpdGVtID0gJHRoaXMuY2xvc2VzdCgnW2RhdGEtdXVpZF0nKTtcblxuXHR2YXIgZXZlbnROYW1lO1xuXHR2YXIgZWNvbW1lcmNlS2V5O1xuXHRpZiAoZXZlbnRUeXBlID09IERhdGFMYXllckNvbnN0YW50cy5FdmVudFR5cGVzLk1pbnVzKSB7XG5cdFx0ZXZlbnROYW1lID0gRGF0YUxheWVyQ29uc3RhbnRzLkV2ZW50cy5DYXJ0LlJlbW92ZUZyb21DYXJ0Lk5hbWU7XG5cdFx0ZWNvbW1lcmNlS2V5ID0gJ3JlbW92ZSc7XG5cdH0gZWxzZSB7XG5cdFx0ZXZlbnROYW1lID0gRGF0YUxheWVyQ29uc3RhbnRzLkV2ZW50cy5DYXJ0LkFkZFRvQ2FydC5OYW1lO1xuXHRcdGVjb21tZXJjZUtleSA9ICdhZGQnO1xuXHR9IFxuXHRcblx0dmFyIHByb2R1Y3REYXRhRm9yVW5pdmVyc2FsQW5hbHl0aWNzID0gSlNPTi5wYXJzZSgkaXRlbS5maW5kKCdbZGF0YS1wcm9kdWN0LWd0bS1qc29uXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0dmFyIHByb2R1Y3REYXRhRm9yR29vZ2xlQW5hbHl0aWNzNCA9IEpTT04ucGFyc2UoJGl0ZW0uZmluZCgnW2RhdGEtcHJvZHVjdC1nYTQtanNvbl0nKS5hdHRyKCdkYXRhLXByb2R1Y3QtZ2E0LWpzb24nKSk7XG5cdGlmIChxdWFudGl0eSkge1xuXHRcdHByb2R1Y3REYXRhRm9yVW5pdmVyc2FsQW5hbHl0aWNzLnF1YW50aXR5ID0gcXVhbnRpdHk7XG5cdFx0cHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0LnF1YW50aXR5ID0gcXVhbnRpdHk7XG5cdH1cblxuXHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRVbml2ZXJzYWxBbmFseXRpY3M6IHtcblx0XHRcdGVjb21tZXJjZToge31cblx0XHR9LFx0XHRcdFx0XHRcdFx0XG5cdFx0R29vZ2xlQW5hbHl0aWNzNDoge1xuXHRcdFx0dmFsdWU6IHByb2R1Y3REYXRhRm9yR29vZ2xlQW5hbHl0aWNzNC5wcmljZSxcblx0XHRcdGl0ZW1zOiBbcHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0XVxuXHRcdH1cblx0fVxuXG5cdGRhdGFPYmplY3QuVW5pdmVyc2FsQW5hbHl0aWNzLmVjb21tZXJjZVtlY29tbWVyY2VLZXldID0ge1xuXHRcdHByb2R1Y3RzOiBbcHJvZHVjdERhdGFGb3JVbml2ZXJzYWxBbmFseXRpY3NdXG5cdH1cblxuXHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKGV2ZW50TmFtZSwgZGF0YU9iamVjdCk7XG59XG5cbmZ1bmN0aW9uIHF1YW50aXR5Q2hhbmdlRXZlbnRzKCR0aGlzLCBxdWFudGl0eSwgaW5jcmVtZW50KSB7XG5cdHZhciBldmVudFR5cGUgPSBpbmNyZW1lbnQgPyBEYXRhTGF5ZXJDb25zdGFudHMuRXZlbnRUeXBlcy5QbHVzIDogRGF0YUxheWVyQ29uc3RhbnRzLkV2ZW50VHlwZXMuTWludXM7XG5cdHF1YW50aXR5RGF0YWxheWVyRXZlbnRzKCR0aGlzLCBldmVudFR5cGUsIHF1YW50aXR5KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSh1cGRhdGVDYXJ0LCByZW5kZXJDYXJ0KSB7XG5cdGlzQ2hlY2tvdXQgPSAocGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQudHlwZSA9PSAnY2FydCcgfHwgcGFnZUNvbnRleHQudHlwZSA9PSAnb25lcGNoZWNrb3V0JyB8fCBwYWdlQ29udGV4dC50eXBlID09ICdvbmVwY2hlY2tvdXRfZ3JvdXBzJykgfHwgKHBhZ2UubnMgJiYgcGFnZS5ucyA9PSAnY2FydCcgfHwgcGFnZS5ucyA9PSAnb25lcGNoZWNrb3V0JyB8fCBwYWdlLm5zID09ICdvbmVwY2hlY2tvdXRfZ3JvdXBzJyk7XG5cdGlzRWNob0NhcnQgPSAocGFnZUNvbnRleHQgJiYgJ3R5cGUnIGluIHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0LnR5cGUgPT0gJ2NhcnRfZWNobycpIHx8IChwYWdlLm5zICYmIHBhZ2UubnMgPT0gJ2NhcnRfZWNobycpO1xuXHRmblVwZGF0ZUNhcnQgPSB1cGRhdGVDYXJ0ICYmIHR5cGVvZiB1cGRhdGVDYXJ0ID09PSAnZnVuY3Rpb24nID8gdXBkYXRlQ2FydCA6IG51bGw7XG5cdGZuUmVuZGVyQ2FydCA9IHJlbmRlckNhcnQgJiYgdHlwZW9mIHJlbmRlckNhcnQgPT09ICdmdW5jdGlvbicgPyByZW5kZXJDYXJ0IDogbnVsbDtcblxuXHQvLyBSZW1vdmUgQnV0dG9uXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suUXVhbnRpdHlTdGVwcGVyLlByb2R1Y3RSZW1vdmUnKS5vbignY2xpY2suUXVhbnRpdHlTdGVwcGVyLlByb2R1Y3RSZW1vdmUnLCAnLnF1YW50aXR5LXN0ZXBwZXItcmVtb3ZlIC5yZW1vdmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGl0ZW1Sb3cgPSAkdGhpcy5jbG9zZXN0KCdbZGF0YS11dWlkXScpO1xuXHRcdHZhciBpc01pbmlDYXJ0ID0gJGl0ZW1Sb3cuYXR0cignY2xhc3MnKS5pbmRleE9mKCdtaW5pLWNhcnQnKSA+IC0xO1xuXHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLkNhcnQuUmVtb3ZlUHJvZHVjdCxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFByb2R1Y3RMaW5lSXRlbVVVSUQ6ICRpdGVtUm93LmRhdGEoJ3V1aWQnKSxcblx0XHRcdH0pLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbih4aHIpIHtcblx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0dXBkYXRlQ2FydFRvdGFscygpO1xuXHRcdFx0XHRpZiAoaXNNaW5pQ2FydCkge1xuXHRcdFx0XHRcdHVwZGF0ZU1pbmlDYXJ0VUkobnVsbCwgJGl0ZW1Sb3cpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlbW92ZUZyb21DYXJ0RGF0YUxheWVyKCR0aGlzKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cblx0Ly8gUGx1cy9NaW51cyBRdHkgQnV0dG9uc1xuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScsICcucXVhbnRpdHktc3RlcHBlciBidXR0b246bm90KFwiLmRpc2FibGVkXCIpJykub24oJ2NsaWNrLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScsICcucXVhbnRpdHktc3RlcHBlciBidXR0b246bm90KFwiLmRpc2FibGVkXCIpJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkc3RlcHBlckJ1dHRvbiA9ICQodGhpcyk7XG5cdFx0dmFyIGlzSW5jcmVtZW50ID0gJHN0ZXBwZXJCdXR0b24uaGFzQ2xhc3MoJ2luY3JlYXNlJyk7XG5cdFx0dmFyIGNhcnRRdHlVcmwgPSBpc0luY3JlbWVudCA/IFVybHMuQ2FydC5BZGRQcm9kdWN0UXVhbnRpdHkgOiBVcmxzLkNhcnQuUmVtb3ZlUHJvZHVjdFF1YW50aXR5O1xuXG5cdFx0JGZvY3VzZWRFbGVtZW50ID0gJHN0ZXBwZXJCdXR0b247XG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0dXJsOiBjYXJ0UXR5VXJsLFxuXHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0UHJvZHVjdExpbmVJdGVtVVVJRDogJCh0aGlzKS5jbG9zZXN0KCdbZGF0YS11dWlkXScpLmRhdGEoJ3V1aWQnKSxcblx0XHRcdFx0UXVhbnRpdHk6IDFcblx0XHRcdH0pLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbih4aHIpIHtcblx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0dXBkYXRlU3RlcHBlclF0eVVJKCRzdGVwcGVyQnV0dG9uLCBpc0luY3JlbWVudCk7XG5cdFx0XHRcdHVwZGF0ZU1pbmlDYXJ0VUkoaXNJbmNyZW1lbnQpO1xuXHRcdFx0XHR1cGRhdGVDYXJ0VG90YWxzKCk7XG5cdFx0XHRcdHF1YW50aXR5Q2hhbmdlRXZlbnRzKCRzdGVwcGVyQnV0dG9uLCAxLCBpc0luY3JlbWVudCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdC8vIE9uIGNoYW5nZSBvZiBwcm9kdWN0IHF0eSBpbiBDYXJ0LCBjaGVjayB0aGUgVUkgdmFsdWUgb2YgUXVhbnRpdHkgU3RlcHBlciwgYW5kIG1ha2UgcXR5ID0gMSBpZiB2YWx1ZSBpc24ndCB2YWxpZFxuXHQkKGRvY3VtZW50KS5vZmYoJ2NoYW5nZS5RdWFudGl0eVN0ZXBwZXIuUXVhbnRpdHlDaGFuZ2UnKS5vbignY2hhbmdlLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScsICcucXVhbnRpdHktc3RlcHBlciBpbnB1dFtuYW1lJD1fcXVhbnRpdHldJywgZnVuY3Rpb24gKCkge1xuXHRcdGlmIChpc05hTigkKHRoaXMpLnZhbCgpKSB8fCBwYXJzZUludCgkKHRoaXMpLnZhbCgpLCAxMCkgPT09IDApIHtcblx0XHRcdCQodGhpcykudmFsKCcxJyk7XG5cdFx0XHQkZm9jdXNlZEVsZW1lbnQgPSAkKHRoaXMpO1xuXHRcdH1cblx0fSk7XG5cblx0Ly8gS2V5Ym9hcmQgZXZlbnRzIGZvciBRdWFudGl0eSBTdGVwcGVyXG5cdCQoZG9jdW1lbnQpLm9mZigna2V5ZG93bi5RdWFudGl0eVN0ZXBwZXIuUXVhbnRpdHlDaGFuZ2UnKS5vbigna2V5ZG93bi5RdWFudGl0eVN0ZXBwZXIuUXVhbnRpdHlDaGFuZ2UnLCAnLnF1YW50aXR5LXN0ZXBwZXIgaW5wdXRbbmFtZSQ9X3F1YW50aXR5XScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cblx0XHRpZiAoZXZlbnQud2hpY2ggPT09IFNpdGVDb25zdGFudHMuS2V5Q29kZXMuRW50ZXIpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHQkZm9jdXNlZEVsZW1lbnQgPSAkdGhpcztcblx0XHRcdGlmICgkKGV2ZW50LnRhcmdldCkudmFsKCkgPiAwKSB7XG5cdFx0XHRcdHZhciBxdWFudGl0eURlbHRhID0gcGFyc2VJbnQoJHRoaXMudmFsKCksIDEwKSAtIHBhcnNlSW50KCR0aGlzLmF0dHIoJ3F1YW50aXR5LWJ1ZmZlcicpLCAxMCk7XG5cdFx0XHRcdHVwZGF0ZVN0ZXBwZXJRdHlVSSgkdGhpcywgdHJ1ZSk7XG5cdFx0XHRcdHVwZGF0ZU1pbmlDYXJ0VUkodHJ1ZSk7XG5cdFx0XHRcdHVwZGF0ZUNhcnRUb3RhbHMoKTtcblx0XHRcdFx0cXVhbnRpdHlDaGFuZ2VFdmVudHMoJHRoaXMsIE1hdGguYWJzKHF1YW50aXR5RGVsdGEpLCBxdWFudGl0eURlbHRhID4gMCk7XG5cdFx0XHRcdCR0aGlzLmF0dHIoJ3F1YW50aXR5LWJ1ZmZlcicsICR0aGlzLnZhbCgpKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignUXVhbnRpdHlTdGVwcGVyLlRhcmdldEZvY3VzJykub24oJ1F1YW50aXR5U3RlcHBlci5UYXJnZXRGb2N1cycsIGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoJGZvY3VzZWRFbGVtZW50KSB7XG5cdFx0XHQkZm9jdXNlZEVsZW1lbnQuZm9jdXMoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5leHBvcnRzLmluaXQgPSBpbml0aWFsaXplOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyksXG4gICAgcHJvZHVjdCA9IHJlcXVpcmUoJy4vcGFnZXMvcHJvZHVjdCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKSxcbiAgICBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG5cblxudmFyIG1ha2VVcmwgPSBmdW5jdGlvbiAodXJsLCBzb3VyY2UsIHByb2R1Y3RMaXN0SUQpIHtcbiAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdzb3VyY2UnLCBzb3VyY2UpO1xuICAgIH1cbiAgICBpZiAocHJvZHVjdExpc3RJRCkge1xuICAgICAgICB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAncHJvZHVjdGxpc3RpZCcsIHByb2R1Y3RMaXN0SUQpO1xuICAgIH1cbiAgICByZXR1cm4gdXJsO1xufTtcblxudmFyIHJlbW92ZVBhcmFtID0gZnVuY3Rpb24gKHVybCkge1xuICAgIGlmICh1cmwuaW5kZXhPZignPycpICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gdXJsLnN1YnN0cmluZygwLCB1cmwuaW5kZXhPZignPycpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdXJsO1xuICAgIH1cbn07XG5cbnZhciBxdWlja3ZpZXcgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHRoaXMuJGNvbnRhaW5lciA9ICQoJzxkaXYvPicpLmF0dHIoJ2lkJywgJ1F1aWNrVmlld0RpYWxvZycpLmFwcGVuZFRvKGRvY3VtZW50LmJvZHkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvZHVjdExpbmtzID0gJCgnI3NlYXJjaC1yZXN1bHQtaXRlbXMgLnRodW1iLWxpbmsnKS5tYXAoZnVuY3Rpb24gKGluZGV4LCB0aHVtYkxpbmspIHtcbiAgICAgICAgICAgIHJldHVybiAkKHRodW1iTGluaykuYXR0cignaHJlZicpO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgc2V0dXA6IGZ1bmN0aW9uIChxdlVybCkge1xuXG4gICAgICAgIHByb2R1Y3QuaW5pdGlhbGl6ZUV2ZW50cygpO1xuXG4gICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gc3RlcCAtIEhvdyBtYW55IHByb2R1Y3RzIGF3YXkgZnJvbSBjdXJyZW50IHByb2R1Y3QgdG8gbmF2aWdhdGUgdG8uIE5lZ2F0aXZlIG51bWJlciBtZWFucyBuYXZpZ2F0ZSBiYWNrd2FyZFxuICAgICAqL1xuICAgIG5hdmlnYXRlUXVpY2t2aWV3OiBmdW5jdGlvbiAoc3RlcCkge1xuICAgICAgICAvLyBkZWZhdWx0IHN0ZXAgdG8gMFxuICAgICAgICB0aGlzLnByb2R1Y3RMaW5rSW5kZXggKz0gKHN0ZXAgPyBzdGVwIDogMCk7XG4gICAgICAgIHZhciB1cmwgPSBtYWtlVXJsKHRoaXMucHJvZHVjdExpbmtzW3RoaXMucHJvZHVjdExpbmtJbmRleF0sICdxdWlja3ZpZXcnKTtcbiAgICAgICAgZGlhbG9nLnJlcGxhY2Uoe1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBjYWxsYmFjazogdGhpcy5zZXR1cC5iaW5kKHRoaXMsIHVybClcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBzaG93IHF1aWNrIHZpZXcgZGlhbG9nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy51cmwgLSB1cmwgb2YgdGhlIHByb2R1Y3QgZGV0YWlsc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnNvdXJjZSAtIHNvdXJjZSBvZiB0aGUgZGlhbG9nIHRvIGJlIGFwcGVuZGVkIHRvIFVSTFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnByb2R1Y3RsaXN0aWQgLSB0byBiZSBhcHBlbmRlZCB0byBVUkxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmNhbGxiYWNrIC0gY2FsbGJhY2sgb25jZSB0aGUgZGlhbG9nIGlzIG9wZW5lZFxuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciB1cmw7XG4gICAgICAgIGlmICghdGhpcy5leGlzdHMoKSkge1xuICAgICAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgIH1cbiAgICAgICAgdXJsID0gbWFrZVVybChvcHRpb25zLnVybCwgb3B0aW9ucy5zb3VyY2UsIG9wdGlvbnMucHJvZHVjdGxpc3RpZCk7XG5cbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLiRjb250YWluZXIsXG4gICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogMTA2OCxcbiAgICAgICAgICAgICAgICB0aXRsZTogUmVzb3VyY2VzLlFVSUNLX1ZJRVdfUE9QVVAsXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHVwKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgeyBvcHRpb25zLmNhbGxiYWNrKCk7IH1cbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBleGlzdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuJGNvbnRhaW5lciAmJiAodGhpcy4kY29udGFpbmVyLmxlbmd0aCA+IDApO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcXVpY2t2aWV3O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIGNvcGllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9kYXJrc2t5YXBwL3N0cmluZy1oYXNoXG4gKi9cbmZ1bmN0aW9uIGhhc2hGbihzdHIpIHtcbiAgICB2YXIgaGFzaCA9IDUzODEsXG4gICAgICAgIGkgPSBzdHIubGVuZ3RoO1xuXG4gICAgd2hpbGUgKGkpIHtcbiAgICAgICAgaGFzaCA9IChoYXNoICogMzMpIF4gc3RyLmNoYXJDb2RlQXQoLS1pKTtcbiAgICB9XG4gICAgLyogSmF2YVNjcmlwdCBkb2VzIGJpdHdpc2Ugb3BlcmF0aW9ucyAobGlrZSBYT1IsIGFib3ZlKSBvbiAzMi1iaXQgc2lnbmVkXG4gICAgKiBpbnRlZ2Vycy4gU2luY2Ugd2Ugd2FudCB0aGUgcmVzdWx0cyB0byBiZSBhbHdheXMgcG9zaXRpdmUsIGNvbnZlcnQgdGhlXG4gICAgKiBzaWduZWQgaW50IHRvIGFuIHVuc2lnbmVkIGJ5IGRvaW5nIGFuIHVuc2lnbmVkIGJpdHNoaWZ0LiAqL1xuICAgIHJldHVybiBoYXNoID4+PiAwO1xufVxuXG4vKipcbiAqIENyZWF0ZSByYXRpbmcgYmFzZWQgb24gaGFzaCByYW5naW5nIGZyb20gMi01XG4gKiBAcGFyYW0gcGlkXG4gKi9cbmZ1bmN0aW9uIGdldFJhdGluZyhwaWQpIHtcbiAgICByZXR1cm4gaGFzaEZuKHBpZC50b1N0cmluZygpKSAlIDMwIC8gMTAgKyAyO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJy52YXJpYW50LWluZm8gLnByb2R1Y3QtcmV2aWV3JykuZWFjaChmdW5jdGlvbiAoaW5kZXgsIHJldmlldykge1xuICAgICAgICAgICAgdmFyIHBpZCA9ICQocmV2aWV3KS5kYXRhKCdwaWQnKTtcbiAgICAgICAgICAgIGlmICghcGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmF0aW5nIHJhbmdlIGZyb20gMiAtIDVcbiAgICAgICAgICAgIHZhciByYXRpbmcgPSBnZXRSYXRpbmcocGlkKTtcbiAgICAgICAgICAgIHZhciBiYXNlUmF0aW5nID0gTWF0aC5mbG9vcihyYXRpbmcpO1xuICAgICAgICAgICAgdmFyIHN0YXJzQ291bnQgPSAwO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiYXNlUmF0aW5nOyBpKyspIHtcbiAgICAgICAgICAgICAgICAkKCcucmF0aW5nJywgcmV2aWV3KS5hcHBlbmQoJzxpIGNsYXNzPVwiZmEgZmEtc3RhclwiPjwvaT4nKTtcbiAgICAgICAgICAgICAgICBzdGFyc0NvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBnaXZlIGhhbGYgc3RhciBmb3IgYW55dGhpbmcgaW4gYmV0d2VlblxuICAgICAgICAgICAgaWYgKHJhdGluZyA+IGJhc2VSYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAkKCcucmF0aW5nJywgcmV2aWV3KS5hcHBlbmQoJzxpIGNsYXNzPVwiZmEgZmEtc3Rhci1oYWxmLW9cIj48L2k+Jyk7XG4gICAgICAgICAgICAgICAgc3RhcnNDb3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXJzQ291bnQgPCA1KSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCA1IC0gc3RhcnNDb3VudDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJy5yYXRpbmcnLCByZXZpZXcpLmFwcGVuZCgnPGkgY2xhc3M9XCJmYSBmYS1zdGFyLW9cIj48L2k+Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBSRUdJU1RFUlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBhbGVydCA9IHJlcXVpcmUoJy4vYWxlcnQnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIHdpc2hsaXN0ID0gcmVxdWlyZSgnLi93aXNobGlzdCcpO1xuXG52YXIgUmVxdWVzdEhlbHBlciA9IHJlcXVpcmUoJy4vaGVscGVycy9SZXF1ZXN0SGVscGVyJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyA9IHtcbiAgICBJc0xhYmVsU2hvd246IGZhbHNlLFxuICAgIENzc0NsYXNzOiAnZnVsbHNjcmVlbicsXG4gICAgQmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG59O1xuXG5mdW5jdGlvbiBlcnJvckhhbmRsaW5nKGRhdGEsIGRpYWxvZ1RpdGxlLCBkaWFsb2dIdG1sKSB7XG4gICAgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdtZXNzYWdlJyBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGRhdGEubWVzc2FnZSk7XG4gICAgfVxuICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgaHRtbDogZGlhbG9nSHRtbCxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgdGl0bGU6IGRpYWxvZ1RpdGxlLFxuICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlUmVnaXN0cmF0aW9uRm9ybSgkZm9ybSkge1x0XG4gICAgdmFyIHJld2FyZHNGb3JtRmllbGRzID0ge1xuICAgICAgICBlbWFpbDogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2VtYWlsJyksXG4gICAgICAgIGZpcnN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2ZpcnN0bmFtZScpLFxuICAgICAgICBsYXN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2xhc3RuYW1lJyksXG4gICAgICAgIHBob25lOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfcGhvbmUnKSxcbiAgICAgICAgemlwOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJhZGRyZXNzX3ppcGNvZGUnKS5sZW5ndGggPiAwID8gJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyYWRkcmVzc196aXBjb2RlJykgOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfemlwY29kZScpXG4gICAgfVxuXHRpZiAoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9wYXNzd29yZFwiXScpLmxlbmd0aCA+IDApIHtcblx0XHRyZXdhcmRzRm9ybUZpZWxkcy5wYXNzd29yZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfcGFzc3dvcmRcIl0nKTtcblx0fVxuICAgIHZhciByZWdpc3RyYXRpb25Gb3JtRmllbGRzID0ge1xuICAgICAgICBlbWFpbDogJGZvcm0uZmluZCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfZW1haWwnKSxcbiAgICAgICAgY29uZmlybUVtYWlsOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9lbWFpbGNvbmZpcm0nKSxcbiAgICAgICAgZmlyc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9maXJzdG5hbWUnKSxcbiAgICAgICAgbGFzdE5hbWU6ICRmb3JtLmZpbmQoJyNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2xhc3RuYW1lJylcbiAgICB9XG5cdGlmICgkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cImR3ZnJtX3Byb2ZpbGVfbG9naW5fcGFzc3dvcmRfXCJdJykubGVuZ3RoID4gMCkge1xuXHRcdHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHMucGFzc3dvcmQgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cImR3ZnJtX3Byb2ZpbGVfbG9naW5fcGFzc3dvcmRfXCJdJyk7XG5cdH1cblx0aWYgKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZGNvbmZpcm1cIl0nKS5sZW5ndGggPiAwKSB7XG5cdFx0cmVnaXN0cmF0aW9uRm9ybUZpZWxkcy5jb25maXJtUGFzc3dvcmQgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cImR3ZnJtX3Byb2ZpbGVfbG9naW5fcGFzc3dvcmRjb25maXJtXCJdJyk7XG5cdH1cbiAgICB2YXIgY2hlY2tGb3JtRmllbGRzID0gJGZvcm0uYXR0cignaWQnKSA9PSAnZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbicgPyByZXdhcmRzRm9ybUZpZWxkcyA6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHM7XG5cdHZhciBmb3JtVmFsaWRhdGlvbiA9IG5ldyBBcnJheSgpO1xuICAgIHZhciByZWdleEVtYWlsID0gL15bYS16QS1aMC05LiEjJCUmJyorLz0/Xl9ge3x9fi1dK0BbYS16QS1aMC05LV0rKD86XFwuW2EtekEtWjAtOS1dKykqJC9nO1xuXHR2YXIgcmVnZXhQaG9uZSA9IC9eXFwrP1xcKD8oWzAtOV1bMC04XVswLTldKVxcKT9bXFwtXFwuIF0/KFsyLTldWzAtOV17Mn0pW1xcLVxcLiBdPyhbMC05XXs0fSkoXFxzKnhbMC05XSspPyQvZztcbiAgICB2YXIgcmVnZXhaaXAgPSAvXihcXGR7NX0pKC1cXGR7NH0pPyQvZztcbiAgICB2YXIgcmVnZXhQYXNzd29yZCA9IC9eKD89Lio/W0Etel0pKD89Lio/WzAtOV0pKD89Lio/WyM/IVxcPVxcL1xcLFxcLlxcflxcYFxcKFxcKVxce1xcfVxcW1xcXVxcXFxAXyQlXiYqLV0pLns4LDIwfSQvZztcblxuICAgIGZvciAodmFyIGZpZWxkTmFtZSBpbiBjaGVja0Zvcm1GaWVsZHMpIHtcbiAgICAgICAgdmFyIGZpZWxkVmFsdWUgPSBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5sZW5ndGggPyBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS52YWwoKS50cmltKCkgOiBudWxsO1xuXG4gICAgICAgIGlmIChmaWVsZFZhbHVlICE9IG51bGwgJiYgZmllbGRWYWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZiAoZmllbGROYW1lID09ICdlbWFpbCcgfHwgZmllbGROYW1lID09ICdjb25maXJtRW1haWwnKSB7XG4gICAgICAgICAgICAgICAgaWYgKFN0cmluZyhmaWVsZFZhbHVlKS5tYXRjaChyZWdleEVtYWlsKSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5hZGRDbGFzcygnZXJyb3InKTtcblx0XHRcdFx0XHR2YXIgZW1haWxGb3JtYXRFcnJvckNsYXNzID0gZmllbGROYW1lID09ICdlbWFpbCcgPyAnc3Bhbi5pbnZhbGlkLWVtYWlsLWZvcm1hdCcgOiAnc3Bhbi5pbnZhbGlkLWVtYWlsLWNvbmZpcm0tZm9ybWF0Jztcblx0XHRcdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoZW1haWxGb3JtYXRFcnJvckNsYXNzKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgfVxuXHRcdFx0XHRpZiAoZmllbGROYW1lID09ICdjb25maXJtRW1haWwnICYmIChmaWVsZFZhbHVlICE9IGNoZWNrRm9ybUZpZWxkc1snZW1haWwnXS52YWwoKS50cmltKCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5hZGRDbGFzcygnZXJyb3InKTtcblx0XHRcdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoJ3NwYW4uaW52YWxpZC1lbWFpbC1jb25maXJtLW1pc21hdGNoJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUgPT0gJ3Bob25lJykge1xuICAgICAgICAgICAgICAgIGlmIChTdHJpbmcoZmllbGRWYWx1ZSkubWF0Y2gocmVnZXhQaG9uZSkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBmb3JtVmFsaWRhdGlvbi5wdXNoKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tGb3JtRmllbGRzW2ZpZWxkTmFtZV0uYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XHRcdFx0JCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3JbZGF0YS1yZWxhdGlvbj1cIicrZmllbGROYW1lKydcIl0nKS5maW5kKCdzcGFuLmludmFsaWQtcGhvbmUtZm9ybWF0JykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUgPT0gJ3ppcCcpIHtcbiAgICAgICAgICAgICAgICBpZiAoU3RyaW5nKGZpZWxkVmFsdWUpLm1hdGNoKHJlZ2V4WmlwKSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5hZGRDbGFzcygnZXJyb3InKTtcblx0XHRcdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoJ3NwYW4uaW52YWxpZC16aXAtZm9ybWF0JykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUgPT0gJ3Bhc3N3b3JkJyB8fCBmaWVsZE5hbWUgPT0gJ2NvbmZpcm1QYXNzd29yZCcpIHtcbiAgICAgICAgICAgICAgICBpZiAoU3RyaW5nKGZpZWxkVmFsdWUpLm1hdGNoKHJlZ2V4UGFzc3dvcmQpID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24ucHVzaChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHRcdHZhciBwYXNzd29yZEZvcm1hdEVycm9yQ2xhc3MgPSBmaWVsZE5hbWUgPT0gJ3Bhc3N3b3JkJyA/ICdzcGFuLmludmFsaWQtcGFzc3dvcmQtZm9ybWF0JyA6ICdzcGFuLmludmFsaWQtcGFzc3dvcmQtY29uZmlybS1mb3JtYXQnO1xuXHRcdFx0XHRcdCQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yW2RhdGEtcmVsYXRpb249XCInK2ZpZWxkTmFtZSsnXCJdJykuZmluZChwYXNzd29yZEZvcm1hdEVycm9yQ2xhc3MpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkTmFtZSA9PSAnY29uZmlybVBhc3N3b3JkJyAmJiAoZmllbGRWYWx1ZSAhPSBjaGVja0Zvcm1GaWVsZHNbJ3Bhc3N3b3JkJ10udmFsKCkudHJpbSgpKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3JtVmFsaWRhdGlvbi5wdXNoKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tGb3JtRmllbGRzW2ZpZWxkTmFtZV0uYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XHRcdFx0JCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3JbZGF0YS1yZWxhdGlvbj1cIicrZmllbGROYW1lKydcIl0nKS5maW5kKCdzcGFuLmludmFsaWQtcGFzc3dvcmQtY29uZmlybS1taXNtYXRjaCcpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3JtVmFsaWRhdGlvbi5wdXNoKGZhbHNlKTtcbiAgICAgICAgICAgIGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0JCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3JbZGF0YS1yZWxhdGlvbj1cIicrZmllbGROYW1lKydcIl0nKS5maW5kKCdzcGFuLmludmFsaWQtbWlzc2luZy1maWVsZHMnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgIH1cbiAgICB9XG5cdFx0XHRcblx0aWYgKGZvcm1WYWxpZGF0aW9uLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICRmb3JtLmZpbmQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yIHNwYW4nKS5hZGRDbGFzcygnZC1ub25lJyk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblxuLy8gQ29yZGlhbCByZXdhcmRzIHJlZ2lzdHJhdGlvbiB0cmFja2luZyAoQkIpXG5mdW5jdGlvbiByZXdhcmRzUmVnaXN0ZXJDb3JkaWFsRXZlbnQoJGZvcm0sIGlzUmVnaXN0ZXJEaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgdmFyIHJld2FyZHNGb3JtRmllbGRzID0ge1xuICAgICAgICBlbWFpbDogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2VtYWlsJykudmFsKCkudHJpbSgpLFxuICAgICAgICBmaXJzdE5hbWU6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9maXJzdG5hbWUnKS52YWwoKS50cmltKCksXG4gICAgICAgIGxhc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfbGFzdG5hbWUnKS52YWwoKS50cmltKCksXG4gICAgICAgIHBob25lOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfcGhvbmUnKS52YWwoKS50cmltKCksXG4gICAgICAgIHppcDogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyYWRkcmVzc196aXBjb2RlJykubGVuZ3RoID4gMCA/ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcmFkZHJlc3NfemlwY29kZScpLnZhbCgpLnRyaW0oKSA6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl96aXBjb2RlJykudmFsKCkudHJpbSgpXG4gICAgfVxuICAgIHZhciBzaWdudXBFdmVudCA9IFwiXCI7XG5cblx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRlbWFpbDogcmV3YXJkc0Zvcm1GaWVsZHNbJ2VtYWlsJ11cblx0fVx0XHRcblx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHQnY2hhbm5lbHMnOiB7XG5cdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdCdhZGRyZXNzJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ2VtYWlsJ10gICAgICBcblx0XHRcdH1cblx0XHR9LFx0XHQgICAgXG5cdFx0J2ZpcnN0X25hbWUnOiByZXdhcmRzRm9ybUZpZWxkc1snZmlyc3ROYW1lJ10sXG5cdFx0J2xhc3RfbmFtZSc6IHJld2FyZHNGb3JtRmllbGRzWydsYXN0TmFtZSddLFxuXHRcdCdwaG9uZSc6IHJld2FyZHNGb3JtRmllbGRzWydwaG9uZSddLFxuXHRcdCdwb3N0YWxfY29kZSc6IHJld2FyZHNGb3JtRmllbGRzWyd6aXAnXSxcblx0XHQnc291cmNlX2NyZWF0ZSc6ICdteWFjY291bnQnLFxuXHRcdCdnZW9fbG9jYXRpb24nOiB7XG5cdFx0XHQncG9zdGFsX2NvZGUnOiByZXdhcmRzRm9ybUZpZWxkc1snemlwJ11cblx0XHR9XG5cdH07XHRcdFx0XG5cdHZhciBsb2dpblByb3BlcnRpZXMgPSB7XG5cdFx0XCJlbWFpbFwiOiByZXdhcmRzRm9ybUZpZWxkc1snZW1haWwnXSxcblx0XHRcImxvZ2luVHlwZVwiOiBpc1JlZ2lzdGVyRGlhbG9nID8gXCJyZWdpc3RyYXRpb24tZGlhbG9nXCIgOiBcInJlZ3VsYXItcmVnaXN0cmF0aW9uXCJcblx0fTtcdFxuXHR2YXIgcmVnaXN0ZXJQcm9wZXJ0aWVzID0ge1xuXHRcdFwiZW1haWxcIjogcmV3YXJkc0Zvcm1GaWVsZHNbJ2VtYWlsJ10sXG5cdFx0XCJyZWdpc3RlclR5cGVcIjogaXNSZWdpc3RlckRpYWxvZyA/IFwicmVnaXN0cmF0aW9uLWRpYWxvZ1wiIDogXCJyZWd1bGFyLXJlZ2lzdHJhdGlvblwiXG5cdH07XHRcdFx0XG5cdGlmICgkKCdpbnB1dCNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3JlY2VpdmVSZXdhcmRzRW1haWwnKS5pcygnOmNoZWNrZWQnKSkge1xuXHRcdHZhciBjb250YWN0X2RhdGEgPSB7XG5cdFx0XHQnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdCdlbWFpbCc6IHtcblx0XHRcdFx0XHQnYWRkcmVzcyc6IHJld2FyZHNGb3JtRmllbGRzWydlbWFpbCddLFxuXHRcdFx0XHRcdCdzdWJzY3JpYmVTdGF0dXMnOiAnc3Vic2NyaWJlZCdcdFx0XHRcdCAgICAgICAgICAgIFxuXHRcdFx0XHR9XG5cdFx0XHR9LFx0XHQgICAgXG5cdFx0XHQnZmlyc3RfbmFtZSc6IHJld2FyZHNGb3JtRmllbGRzWydmaXJzdE5hbWUnXSxcblx0XHRcdCdsYXN0X25hbWUnOiByZXdhcmRzRm9ybUZpZWxkc1snbGFzdE5hbWUnXSxcblx0XHRcdCdwaG9uZSc6IHJld2FyZHNGb3JtRmllbGRzWydwaG9uZSddLFxuXHRcdFx0J3Bvc3RhbF9jb2RlJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ3ppcCddLFxuXHRcdFx0J3NpZ251cF9zb3VyY2UnOiAncmV3YXJkcycsXG5cdFx0XHQnc291cmNlX2NyZWF0ZSc6ICdteWFjY291bnQnLFxuXHRcdFx0J3dlbGNvbWVfc2lnbnVwX3Jld2FyZHNfb25saW5lJzogdHJ1ZSxcblx0XHRcdCdnZW9fbG9jYXRpb24nOiB7XG5cdFx0XHRcdCdwb3N0YWxfY29kZSc6IHJld2FyZHNGb3JtRmllbGRzWyd6aXAnXVxuXHRcdFx0fVxuXHRcdH07XHRcdFxuXHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XCJzaWdudXBfc291cmNlXCI6ICdyZXdhcmRzJyxcblx0XHRcdFwid2VsY29tZV9zaWdudXBfcmV3YXJkc19vbmxpbmVcIjogdHJ1ZVxuXHRcdH07XHRcdFxuXHRcdHNpZ251cEV2ZW50ID0gWydldmVudCcsICdlbWFpbF9zaWdudXAnLCBwcm9wZXJ0aWVzXTtcblx0fVx0XG5cdFJlcXVlc3RIZWxwZXIuVmFsaWRhdGUoJ0NvcmRpYWwtRW1haWxTaWdudXAnKS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdGNyZGwoW1x0XHRcdFx0XG5cdFx0XHRcdFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxcblx0XHRcdFx0WydldmVudCcsICdhY2NvdW50X2NyZWF0ZScsIHJlZ2lzdGVyUHJvcGVydGllc10sXG5cdFx0XHRcdFsnZXZlbnQnLCAnbG9naW4nLCBsb2dpblByb3BlcnRpZXNdLFxuXHRcdFx0XHRzaWdudXBFdmVudFxuXHRcdFx0XSk7XG5cdFx0fVxuXHRcdGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcblx0fSkuY2F0Y2goKTtcdFxufVxuXG4vLyBDb3JkaWFsIHJlZ2lzdHJhdGlvbiB0cmFja2luZyAoU0hQIGFuZCBDTylcbmZ1bmN0aW9uIHJlZ2lzdGVyQ29yZGlhbEV2ZW50KCRmb3JtLCBpc1JlZ2lzdGVyRGlhbG9nLCBjYWxsYmFjaykge1xuICAgIHZhciByZWdpc3RyYXRpb25Gb3JtRmllbGRzID0ge1xuICAgICAgICBlbWFpbDogJGZvcm0uZmluZCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfZW1haWwnKS52YWwoKS50cmltKCksXG4gICAgICAgIGZpcnN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfZmlyc3RuYW1lJykudmFsKCkudHJpbSgpLFxuICAgICAgICBsYXN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbGFzdG5hbWUnKS52YWwoKS50cmltKClcbiAgICB9XG5cdHZhciBzaWdudXBFdmVudCA9IFwiXCI7XHRcblxuXHR2YXIgYXV0aF9kYXRhID0ge1xuXHRcdGVtYWlsOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydlbWFpbCddXG5cdH1cdFx0XHRcblx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHQnY2hhbm5lbHMnOiB7XG5cdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdCdhZGRyZXNzJzogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZW1haWwnXVx0XHRcdCAgICAgICAgICAgIFxuXHRcdFx0fVxuXHRcdH0sXHRcdCAgICBcblx0XHQnZmlyc3RfbmFtZSc6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHNbJ2ZpcnN0TmFtZSddLFxuXHRcdCdsYXN0X25hbWUnOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydsYXN0TmFtZSddLFxuXHRcdCdzb3VyY2VfY3JlYXRlJzogJ215YWNjb3VudCdcblx0fTtcblx0dmFyIGxvZ2luUHJvcGVydGllcyA9IHtcblx0XHRcImVtYWlsXCI6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHNbJ2VtYWlsJ10sXG5cdFx0XCJsb2dpblR5cGVcIjogaXNSZWdpc3RlckRpYWxvZyA/IFwicmVnaXN0cmF0aW9uLWRpYWxvZ1wiIDogXCJyZWdpc3RyYXRpb25cIlxuXHR9O1x0XHRcblx0dmFyIHJlZ2lzdGVyUHJvcGVydGllcyA9IHtcblx0XHRcImVtYWlsXCI6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHNbJ2VtYWlsJ10sXG5cdFx0XCJyZWdpc3RlclR5cGVcIjogaXNSZWdpc3RlckRpYWxvZyA/IFwicmVnaXN0cmF0aW9uLWRpYWxvZ1wiIDogXCJyZWdpc3RyYXRpb25cIlxuXHR9O1x0XHRcdFx0XHRcdFxuXHRpZiAoJCgnaW5wdXQjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9hZGR0b2VtYWlsbGlzdCcpLmlzKCc6Y2hlY2tlZCcpKSB7XG5cdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdFx0J2VtYWlsJzoge1xuXHRcdFx0XHRcdCdhZGRyZXNzJzogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZW1haWwnXSxcblx0XHRcdFx0XHQnc3Vic2NyaWJlU3RhdHVzJzogJ3N1YnNjcmliZWQnXG5cdFx0XHRcdH1cblx0XHRcdH0sXHRcdCAgICBcblx0XHRcdCdmaXJzdF9uYW1lJzogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZmlyc3ROYW1lJ10sXG5cdFx0XHQnbGFzdF9uYW1lJzogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snbGFzdE5hbWUnXSxcblx0XHRcdCdzaWdudXBfc291cmNlJzogJ215YWNjb3VudCcsXG5cdFx0XHQnc291cmNlX2NyZWF0ZSc6ICdteWFjY291bnQnLFxuXHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZVxuXHRcdH07XHRcdFxuXHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XCJzaWdudXBfc291cmNlXCI6IFwibXlhY2NvdW50XCIsXG5cdFx0XHRcInBhZ2VcIjogXCJteWFjY291bnRcIixcblx0XHRcdFwid2VsY29tZV9zaWdudXBcIjogdHJ1ZVxuXHRcdH07XG5cdFx0c2lnbnVwRXZlbnQgPSBbJ2V2ZW50JywgJ2VtYWlsX3NpZ251cCcsIHByb3BlcnRpZXNdO1xuXHR9XG5cdFJlcXVlc3RIZWxwZXIuVmFsaWRhdGUoJ0NvcmRpYWwtRW1haWxTaWdudXAnKS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdGNyZGwoW1x0XHRcdFx0XG5cdFx0XHRcdFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxcblx0XHRcdFx0WydldmVudCcsICdhY2NvdW50X2NyZWF0ZScsIHJlZ2lzdGVyUHJvcGVydGllc10sXG5cdFx0XHRcdFsnZXZlbnQnLCAnbG9naW4nLCBsb2dpblByb3BlcnRpZXNdLFxuXHRcdFx0XHRzaWdudXBFdmVudFxuXHRcdFx0XSk7XG5cdFx0fVxuXHRcdGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcblx0fSkuY2F0Y2goKTtcdFxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBhZGQgcnVsZXMgdG8gY29kZSBpbnB1dCBmaWVsZFxuICovXG5mdW5jdGlvbiBpbml0QWRkUnVsZXNGb3JDb2RlSW5wdXQoKSB7XG4gICAgJCgnZm9ybSN2ZXJpZnktY29kZScpLnZhbGlkYXRlKCk7XG4gICAgJCgnI3ZlcmlmeS1jb2RlICNlbnRlci1jb2RlJykucnVsZXMoJ2FkZCcsIHtcbiAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgIGRpZ2l0czogdHJ1ZSxcbiAgICAgICAgbWlubGVuZ3RoOiA2LFxuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgICAgcmVxdWlyZWQ6IFJlc291cmNlcy5WQUxJREFURV9DT0RFLFxuICAgICAgICAgICAgbWlubGVuZ3RoOiBSZXNvdXJjZXMuVkFMSURBVEVfQ09ERVxuICAgICAgICB9LFxuICAgICAgICBub3JtYWxpemVyOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuICQudHJpbSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gaW5pdCByZWdpc3RyYXRpb24gYnV0dG9uIGV2ZW50IGZvciByZWdpc3RyYXRpb24gcGFnZSBhbmQgZGlhbG9nXG4gKi9cbmZ1bmN0aW9uIGluaXRSZWdpc3RyYXRpb25CdXR0b24oKSB7XG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljay5SZWdpc3RyYXRpb24nKS5vbignY2xpY2suUmVnaXN0cmF0aW9uJywgJy5hY2NvdW50UmVnaXN0ZXJCdXR0b24sIC5zYXZlUmV3YXJkc1JlZ2lzdHJhdGlvbi5idG4sIC5jb25maXJtYXRpb25SZWdpc3RlckJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblx0XHR2YXIgZGlhbG9nSHRtbCA9ICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+T29wcywgc29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCByZWdpc3RyYXRpb24uIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG4gICAgICAgIHZhciAkcmVnaXN0cmF0aW9uQnV0dG9uID0gJCh0aGlzKTtcblx0XHR2YXIgJHJlZ2lzdHJhdGlvbkZvcm0gPSAkcmVnaXN0cmF0aW9uQnV0dG9uLmNsb3Nlc3QoJ2Zvcm1bZGF0YS1mb3JtLXR5cGU9XCJyZWdpc3RlclwiXScpO1xuICAgICAgICB2YXIgZm9ybVVybCA9ICRyZWdpc3RyYXRpb25Gb3JtLmF0dHIoJ2FjdGlvbicpO1xuXHRcdHZhciBpc0NvbmZpcm1hdGlvblBhZ2UgPSAkcmVnaXN0cmF0aW9uQnV0dG9uLmhhc0NsYXNzKCdjb25maXJtYXRpb25SZWdpc3RlckJ1dHRvbicpO1xuXG5cdFx0Ly8gQ2xlYXIgcHJldmlvdXMgZm9ybSBlcnJvcnNcblx0XHQkcmVnaXN0cmF0aW9uRm9ybS5maW5kKCdpbnB1dCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuXHRcdCRyZWdpc3RyYXRpb25Gb3JtLmZpbmQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yIHNwYW4nKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cblx0XHR2YXIgaXNWYWxpZEZvcm0gPSB2YWxpZGF0ZVJlZ2lzdHJhdGlvbkZvcm0oJHJlZ2lzdHJhdGlvbkZvcm0pO1xuXHRcdHZhciBpc1JlZ2lzdGVyRGlhbG9nID0gZm9ybVVybC5pbmRleE9mKCdsb2dpbkRpYWxvZycpID49IDA7XG5cdFx0dmFyIGZvcm1EYXRhID0gJHJlZ2lzdHJhdGlvbkZvcm0uc2VyaWFsaXplKCk7IFxuXHRcdGZvcm1EYXRhICs9ICcmJyArICRyZWdpc3RyYXRpb25CdXR0b24uYXR0cignbmFtZScpICsgJz0nICsgJHJlZ2lzdHJhdGlvbkJ1dHRvbi5hdHRyKCd2YWx1ZScpO1xuXHRcdGlmIChwYWdlQ29udGV4dC5vcHRpb25zLlRva2VuKSB7XG5cdFx0XHRmb3JtRGF0YSArPSAnJmNzcmZfdG9rZW49JyArIHBhZ2VDb250ZXh0Lm9wdGlvbnMuVG9rZW47XG5cdFx0fVxuXHRcdFxuICAgICAgICAvLyBVc2luZyBBSkFYIGluc3RlYWQgb2YgZGVmYXVsdCBIVE1MIGJ1dHRvbiBzdWJtaXQgZm9yIHJlZ2lzdHJhdGlvbiBkaWFsb2cgYW5kIFwiQ3JlYXRlIGFuIEFjY291bnRcIiBwYWdlXG4gICAgICAgIGlmIChpc1ZhbGlkRm9ybSkge1xuICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcbiAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuUkVURU5USU9OX0NPTV9FTkFCTEVEKSB7XG4gICAgICAgICAgICBcdGdlcS5zdXBwcmVzcygpO1xuICAgICAgICAgICAgfSAgICAgICAgICAgXG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICB1cmw6IGZvcm1VcmwsXG4gICAgICAgICAgICAgICAgZGF0YTogZm9ybURhdGEsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyAmJiAncmVzdWx0JyBpbiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5yZXN1bHQgPT0gJ2Vycm9yJykge1xuXHRcdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0XHRpZiAoaXNSZWdpc3RlckRpYWxvZyB8fCBpc0NvbmZpcm1hdGlvblBhZ2UpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgZXJyb3JzRm91bmQ7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRhdGEudmFsaWRhdGlvbkVycm9ycykge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JzRm91bmQgPSBKU09OLnBhcnNlKGRhdGEudmFsaWRhdGlvbkVycm9ycyk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGlmIChlcnJvcnNGb3VuZCAmJiBPYmplY3Qua2V5cyhlcnJvcnNGb3VuZCkubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Zm9yICh2YXIgZmllbGROYW1lIGluIGVycm9yc0ZvdW5kKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoJ1tuYW1lKj1cIicgK2ZpZWxkTmFtZSsgJ1wiXScpLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkKGVycm9yc0ZvdW5kW2ZpZWxkTmFtZV0pLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVnaXN0ZXIgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IGRhdGEucmVnaXN0ZXJEaWFsb2dDb250aW51ZVVybDtcblx0XHRcdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLnJlc3VsdCA9PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdFx0Ly8gSWYgYSByZXdhcmRzIGFjY291bnQgd2FzIGZvdW5kIGluIHJld2FyZHMgREIsIHRoZW4gdmVyaWZ5IGN1c3RvbWVyIGFuZCB0aWUgbmV3bHkgcmVnaXN0ZXJlZCBlbWFpbCBhZGRyZXNzIHRvIGV4aXNpdG5nIHJld2FyZHMgYWNjb3VudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgndmFsaWRhdGVDdXN0b21lcicgaW4gZGF0YSAmJiBkYXRhLnZhbGlkYXRlQ3VzdG9tZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkcmVnaXN0cmF0aW9uRm9ybS5hdHRyKCdpZCcpID09ICdkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uJykge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXdhcmRzUmVnaXN0ZXJDb3JkaWFsRXZlbnQoJHJlZ2lzdHJhdGlvbkZvcm0sIGlzUmVnaXN0ZXJEaWFsb2cpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmVnaXN0ZXJDb3JkaWFsRXZlbnQoJHJlZ2lzdHJhdGlvbkZvcm0sIGlzUmVnaXN0ZXJEaWFsb2cpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cdFx0XHRcdFx0XHRcdFx0dmFyIG5ld0F0dHJpYnV0ZXMgPSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcImRhdGEtbW9kYWwtdHlwZVwiOiBcInJlZ2lzdGVyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY29udGludWUtdXJsXCI6ICdyZWdpc3RlckRpYWxvZ0NvbnRpbnVlVXJsJyBpbiBkYXRhID8gZGF0YS5yZWdpc3RlckRpYWxvZ0NvbnRpbnVlVXJsIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtZmlyc3QtbmFtZVwiOiAnY3VzdG9tZXJGaXJzdE5hbWUnIGluIGRhdGEgPyBkYXRhLmN1c3RvbWVyRmlyc3ROYW1lIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtc3RvcmUtbnVtYmVyXCI6ICdzdG9yZUZyb21Qcm9maWxlJyBpbiBkYXRhID8gZGF0YS5zdG9yZUZyb21Qcm9maWxlIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY2FydC1xdWFudGl0eVwiOiAnY2FydFF1YW50aXR5JyBpbiBkYXRhID8gZGF0YS5jYXJ0UXVhbnRpdHkgOiAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5odG1sKGRhdGEudmFsaWRhdGVDdXN0b21lcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5hZGRDbGFzcygndmFsaWRhdGUtY3VzdG9tZXItc2hvdyBmb2xsb3ctYWNjb3VudC1kaWFsb2ctcGF0aCcpLmF0dHIobmV3QXR0cmlidXRlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZvciByZWdpc3Rlci1kaWFsb2cgYmVjYXVzZSB0aGUgdmFsaWRhdGlvbiBmb3JtIGlzIG9ubHkgbG9hZGVkIGludG8gcGFnZSB2aWEgQUpBWCwgc28gcnVsZXMgY2FuJ3QgYmUgYWRkZWQgdW50aWwgZm9ybSBpcyBsb2FkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdEFkZFJ1bGVzRm9yQ29kZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoaXNDb25maXJtYXRpb25QYWdlKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBSZWRpcmVjdCB0byBNeSBBY2NvdW50IGlmIHRoaXMgaXMgYSByZWdpc3RyYXRpb24gZnJvbSBvcmRlciBjb25maXJtYXRpb24gcGFnZVxuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YS5yZWdpc3RlckRpYWxvZ0NvbnRpbnVlVXJsID0gVXJscy5hY2NvdW50O1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCRyZWdpc3RyYXRpb25Gb3JtLmF0dHIoJ2lkJykgPT0gJ2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb24nKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJld2FyZHNSZWdpc3RlckNvcmRpYWxFdmVudCgkcmVnaXN0cmF0aW9uRm9ybSwgaXNSZWdpc3RlckRpYWxvZywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScsIHsgcmVzdWx0czogZGF0YSwgaXNBY2NvdW50RGlhbG9nOiBpc1JlZ2lzdGVyRGlhbG9nLCBkaXNwbGF5TWVzc2FnZTogJ3JlZ2lzdGVyJyB9KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZWdpc3RlckNvcmRpYWxFdmVudCgkcmVnaXN0cmF0aW9uRm9ybSwgaXNSZWdpc3RlckRpYWxvZywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScsIHsgcmVzdWx0czogZGF0YSwgaXNBY2NvdW50RGlhbG9nOiBpc1JlZ2lzdGVyRGlhbG9nLCBkaXNwbGF5TWVzc2FnZTogJ3JlZ2lzdGVyJyB9KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Bvc3RBamF4QXV0aGVudGljYXRpb25BY3Rpb25zLkluaXRpYWxpemUnLCB7IHJlc3VsdHM6IGRhdGEsIGlzQWNjb3VudERpYWxvZzogaXNSZWdpc3RlckRpYWxvZywgZGlzcGxheU1lc3NhZ2U6ICdyZWdpc3RlcicgfSk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXHRlcnJvckhhbmRsaW5nKGRhdGEsICdSZWdpc3RlciAtIEVycm9yJywgZGlhbG9nSHRtbCk7XG5cdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0aWYgKGlzUmVnaXN0ZXJEaWFsb2cpIHtcblx0XHRcdFx0XHRcdFx0ZXJyb3JIYW5kbGluZyhkYXRhLCAnUmVnaXN0ZXIgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRpZiAoIWlzUmVnaXN0ZXJEaWFsb2cpIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gbG9jYXRpb24uaHJlZjtcblx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gIFxuXHR9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gZGlzcGxheXMgdGhlIHJlZ2lzdHJhdGlvbiBmb3JtIGluIHRoZSBkaWFsb2cgb24gYnV0dG9uIGNsaWNrXG4gKi9cbmZ1bmN0aW9uIGluaXRSZWdpc3RyYXRpb25Gb3JtKCkge1xuXHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyN0b2dnbGUtcmVnaXN0cmF0aW9uJywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJGRpYWxvZyA9ICQodGhpcykucGFyZW50cygnLmxvZ2luLWRpYWxvZycpO1xuXHRcdHZhciAkZGlhbG9nVGl0bGViYXIgPSAkZGlhbG9nLmZpbmQoJy51aS1kaWFsb2ctdGl0bGViYXInKTtcblx0XHR2YXIgJGRpYWxvZ0NvbnRlbnQgPSAkZGlhbG9nLmZpbmQoJy51aS1kaWFsb2ctY29udGVudCcpO1xuXHRcdHZhciAkZGlhbG9nRm9ybXNDb250YWluZXIgPSAkZGlhbG9nLmZpbmQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyJyk7XG5cdFx0dmFyIGNhbGN1bGF0ZWRTcGFjaW5nID0gJCh3aW5kb3cpLmhlaWdodCgpICogMC4yMTtcblx0XHR2YXIgbmV3RGlhbG9nSGVpZ2h0ID0gJCh3aW5kb3cpLmhlaWdodCgpIC0gY2FsY3VsYXRlZFNwYWNpbmc7XG5cdFx0dmFyIG5ld1RvcFZhbHVlID0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpICsgKGNhbGN1bGF0ZWRTcGFjaW5nICogMC4yMzMpO1xuXG5cdFx0aWYgKCRkaWFsb2dUaXRsZWJhciAmJiAkZGlhbG9nVGl0bGViYXIuaXMoXCI6dmlzaWJsZVwiKSkge1xuXHRcdFx0bmV3RGlhbG9nSGVpZ2h0ID0gbmV3RGlhbG9nSGVpZ2h0ICsgJGRpYWxvZ1RpdGxlYmFyLm91dGVySGVpZ2h0KCk7XG5cdFx0fVxuXG5cdFx0dmFyIHBhZGRpbmdUb3AgPSAnMzJweCc7XG5cdFx0dmFyIGN1cnJlbnRTaXRlID0gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQuc2l0ZSA/IHBhZ2VDb250ZXh0LnNpdGUgOiBudWxsO1xuXHRcdGlmICgoY3VycmVudFNpdGUgJiYgY3VycmVudFNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHx8IChwYWdlQ29udGV4dCAmJiBwYWdlQ29udGV4dC5pc3N0b3Jlc2l0ZSkpIHtcblx0XHRcdHBhZGRpbmdUb3AgPSAnMjhweCc7XG5cdFx0fVxuXG5cdFx0JCgnLmxvZ2luLWRpYWxvZy1zaWduaW4tY29udGFpbmVyLCAjdG9nZ2xlLXJlZ2lzdHJhdGlvbicpLmhpZGUoKTtcblx0XHQkKCcubG9naW4tZGlhbG9nLXJlZ2lzdGVyLWZvcm0nKS5hZGRDbGFzcygncmVnaXN0ZXItZm9ybS1zaG93Jyk7XG5cdFx0JGRpYWxvZy5jc3Moe1xuXHRcdFx0J2hlaWdodCc6IG5ld0RpYWxvZ0hlaWdodCsncHgnLFxuXHRcdFx0J3RvcCc6IG5ld1RvcFZhbHVlKydweCcsXG5cdFx0XHQnb3ZlcmZsb3cnOiAndmlzaWJsZSdcblx0XHQgIH0pO1xuXHRcdCRkaWFsb2dDb250ZW50LmNzcyh7XG5cdFx0XHQnaGVpZ2h0JzogJzEwMCUnLFxuXHRcdFx0J3BhZGRpbmcnOiAnMCAxMXB4IDIwcHgnLFxuXHRcdFx0J3BhZGRpbmctdG9wJzogcGFkZGluZ1RvcFxuXHRcdH0pO1xuXHRcdCRkaWFsb2dGb3Jtc0NvbnRhaW5lci5jc3MoJ2hlaWdodCcsJzEwMCUnKTtcblx0fSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXG5cdFx0aW5pdFJlZ2lzdHJhdGlvbkZvcm0oKTtcbiAgICAgICAgaW5pdFJlZ2lzdHJhdGlvbkJ1dHRvbigpO1xuICAgIH1cbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgc2l0ZU5hbWU7XG52YXIgJHdpbiA9ICQod2luZG93KTtcblxuXG4vKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQ29uZmlndXJlcyBwYXJhbWV0ZXJzIGFuZCByZXF1aXJlZCBvYmplY3QgaW5zdGFuY2VzXG4gICAgICovXG5mdW5jdGlvbiBpbml0ICgpIHtcbiAgICBzaXRlTmFtZSA9IHdpbmRvdy5wYWdlQ29udGV4dC5zaXRlIHx8ICcnO1xuXG4gICAgJCgnLnRvcC1iYW5uZXIgLmhlYWRlci1zZWFyY2ggYnV0dG9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICB2YXIgJHNlYXJjaEZvcm0gPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG4gICAgICAgIHZhciAkc2VhcmNoSW5wdXQgPSAkc2VhcmNoRm9ybS5maW5kKCdbbmFtZT1cInFcIl0nKTtcbiAgICAgICAgdmFyIGFjdGlvbiA9ICRzZWFyY2hGb3JtLmF0dHIoJ2FjdGlvbicpO1xuICAgICAgICB2YXIga2V5d29yZCA9ICRzZWFyY2hJbnB1dC52YWwoKTtcbiAgICAgICAgdmFyIHVybCA9IGFjdGlvbiArIFwiP3E9XCIgKyBrZXl3b3JkO1xuXG4gICAgICAgIGlmIChrZXl3b3JkICYmIGtleXdvcmQgIT0gJHNlYXJjaElucHV0LmF0dHIoJ3BsYWNlaG9sZGVyJykpIHtcbiAgICAgICAgICAgICRzZWFyY2hGb3JtLmF0dHIoJ2FjdGlvbicsIHVybCk7XG4gICAgICAgICAgICAkc2VhcmNoRm9ybS5zdWJtaXQoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG4gICAgICAgICQoJy5oZWFkZXItc2VhcmNoJykub24oJ2NsaWNrJyxmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICQoJy5oZWFkZXItc2VhcmNoJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkKCcuaGVhZGVyLXNlYXJjaCBpbnB1dCNxJykuZm9jdXNvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAkKCcuaGVhZGVyLXNlYXJjaCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuUFJPTU9URURfU0VBUkNIRVMpIHtcbiAgICAgICAgJChkb2N1bWVudCkub24oJ2ZvY3VzIGNsaWNrIGtleWRvd24nLCAnLmhlYWRlci1zZWFyY2ggaW5wdXQjcSwgLmhlYWRlci1zZWFyY2ggaW5wdXQjbW9iaWxlLXEnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHByb21vdGVkU3VnZ2VzdGlvbnMoKTtcbiAgICAgICAgICAgIC8vIFRPLURPOiBXaGVuIHRpY2tldCBwb3BzIHVwIGZvciBzdWdnZXN0ZWQgc2VhcmNoZXMsIGNyZWF0ZSBhbm90aGVyIHByZWZlcmVuY2UgYW5kIGFkZCB0aGUgSUYgc3RhdGVtZW50IGhlcmVcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJChkb2N1bWVudCkub24oJ21vdXNlbGVhdmUnLCAnLnNlYXJjaC1zdWdnZXN0aW9ucy1jb250YWluZXIsIC5oZWFkZXItc2VhcmNoIFtuYW1lPVwicVwiXScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWFyY2hIZWFkZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaGVhZGVyLXNlYXJjaCcpO1xuICAgICAgICAgICAgaWYgKCFzZWFyY2hIZWFkZXIuY29udGFpbnMoZS5yZWxhdGVkVGFyZ2V0KSAmJiAkKCcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lcicpLmZpbmQoZS5yZWxhdGVkVGFyZ2V0KS5sZW5ndGggPCAxKSB7XG4gICAgICAgICAgICAgICAgJCgnLnNlYXJjaC1zdWdnZXN0aW9ucy1jb250YWluZXInKS5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuY2xvc2Utc2VhcmNoLXN1Z2dlc3Rpb25zJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAkKCcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lcicpLmhpZGUoKTtcbiAgICAgICAgfSk7ICBcbiAgICAgICAgXG4gICAgICAgICQoZG9jdW1lbnQpLm9mZignU2VhcmNoQmFyLkV4cGFuZCcpLm9uKCdTZWFyY2hCYXIuRXhwYW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBleHBhbmQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJChkb2N1bWVudCkub2ZmKCdTZWFyY2hCYXIuU2Nyb2xsVG9wJykub24oJ1NlYXJjaEJhci5TY3JvbGxUb3AnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHNjcm9sbFRvcCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkKGRvY3VtZW50KS5vZmYoJ1NlYXJjaEJhci5IaWRlJykub24oJ1NlYXJjaEJhci5IaWRlJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBoaWRlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvblxuICovXG5mdW5jdGlvbiBleHBhbmQgKCkge1xuICAgICQoJy50b3AtYmFubmVyJykudG9nZ2xlQ2xhc3MoJ3NlYXJjaC1lbmFibGVkJyk7XG4gICAgdmFyICR0YXJnZXQgPSAkKCcuaGVhZGVyLXNlYXJjaCcpO1xuICAgIGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuICAgICAgICAkdGFyZ2V0ID0gJCgnLnNlYXJjaC1ob2xkZXInKTtcbiAgICB9XG4gICAgICAgICAgICBcbiAgICBpZiAoKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTIHx8IHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSAmJiAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcbiAgICAgICAgJHRhcmdldC5jc3MoJ3RvcCcsICQoJy50b3AtYmFubmVyLWJhcicpLm91dGVySGVpZ2h0KCkgKyAkKCcudG9wLWJhbm5lci1pbm5lcicpLm91dGVySGVpZ2h0KCkgLSAkd2luLnNjcm9sbFRvcCgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAkdGFyZ2V0LmNzcygndG9wJywgJycpO1xuICAgIH1cbiAgICAgICAgICAgIFxuICAgIGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuICAgICAgICAkdGFyZ2V0LmZpbmQoJ2lucHV0W3R5cGU9XCJ0ZXh0XCJdJykuZm9jdXMoKTtcbiAgICB9XG4gICAgICAgICAgICBcbiAgICBpZiAoJCgnLnRvcC1iYW5uZXInKS5oYXNDbGFzcygnc2VhcmNoLWVuYWJsZWQnKSAmJiAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykgJiYgJCgnLnRvcC1iYW5uZXItYmFyJykuYXR0cignZGF0YS1oZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuICAgICAgICAkKCcjc2VhcmNoICNxJykuZm9jdXMoKTtcbiAgICB9XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb25cbiAqL1xuZnVuY3Rpb24gc2Nyb2xsVG9wICgpIHtcbiAgICBpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSAkKCcuaGVhZGVyLXNlYXJjaCcpO1xuICAgICAgICBpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcbiAgICAgICAgICAgICR0YXJnZXQgPSAkKCcuc2VhcmNoLWhvbGRlcicpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpKSB7XG4gICAgICAgICAgICAkdGFyZ2V0LmNzcygndG9wJywgJCgnLnRvcC1iYW5uZXItYmFyJykub3V0ZXJIZWlnaHQoKSArICQoJy50b3AtYmFubmVyLWlubmVyJykub3V0ZXJIZWlnaHQoKSAtICR3aW4uc2Nyb2xsVG9wKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHRhcmdldC5jc3MoJ3RvcCcsICcnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvblxuICovXG5mdW5jdGlvbiBoaWRlICgpIHtcbiAgICBpZigkKCcuaGVhZGVyLXNlYXJjaCcpLmhhc0NsYXNzKCdzaG93JykpIHtcbiAgICAgICAgJCgnLmhlYWRlci1zZWFyY2gnKS5yZW1vdmVDbGFzcygnc2hvdycpO1xuICAgICAgICBpZiAoc2l0ZU5hbWUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMpIHtcbiAgICAgICAgICAgICQoJy50b3AtYmFubmVyJykucmVtb3ZlQ2xhc3MoJ3NlYXJjaC1lbmFibGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gdHJpZ2dlciBwcm9tb3RlZCBzdWdnZXN0aW9ucyBmb3Igc2l0ZSBzZWFyY2hcbiAqL1xuZnVuY3Rpb24gcHJvbW90ZWRTdWdnZXN0aW9ucyAoKSB7XG4gICAgdmFyIGlzQ29udGVudFBvcHVsYXRlZCA9ICQoJy5zZWFyY2gtc3VnZ2VzdGlvbnMtY29udGFpbmVyID4gZGl2JykubGVuZ3RoID4gMDtcbiAgICBpZiAoJCgnLnNlYXJjaC1zdWdnZXN0aW9ucy1jb250YWluZXInKS5pcygnOmhpZGRlbicpICYmIGlzQ29udGVudFBvcHVsYXRlZCkge1xuICAgICAgICAkKCcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lcicpLnNob3coKTtcbiAgICB9XG59XG5cbmV4cG9ydHMuaW5pdCA9IGluaXQ7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIGV2ZW50IHRvIHRoZSBwbGFjZSBob2xkZXIgKC5ibHVyKVxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgICQoJyNxJykuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICBpZiAoaW5wdXQudmFsKCkgPT09IGlucHV0LmF0dHIoJ3BsYWNlaG9sZGVyJykpIHtcbiAgICAgICAgICAgIGlucHV0LnZhbCgnJyk7XG4gICAgICAgIH1cbiAgICB9KVxuICAgIC5ibHVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gJCh0aGlzKTtcbiAgICAgICAgaWYgKGlucHV0LnZhbCgpID09PSAnJyB8fCBpbnB1dC52YWwoKSA9PT0gaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSkge1xuICAgICAgICAgICAgaW5wdXQudmFsKGlucHV0LmF0dHIoJ3BsYWNlaG9sZGVyJykpO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAuYmx1cigpO1xufVxuXG5leHBvcnRzLmluaXQgPSBpbml0aWFsaXplRXZlbnRzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpO1xuXG52YXIgaXNUb3VjaE1vdmVkID0gZmFsc2U7XG52YXIgaXNDdXJyZW50VGFyZ2V0U3dhdGNoID0gZmFsc2U7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU3dhdGNoLk1lbnUuQ2xvc2UnKS5vbignY2xpY2suU3dhdGNoLk1lbnUuQ2xvc2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHR2YXIgJGN1cnJlbnRUYXJnZXQgPSAkKGV2ZW50LmN1cnJlbnRUYXJnZXQpO1xuXHRcdFxuXHRcdGlmICgkY3VycmVudFRhcmdldC5jbG9zZXN0KCcuc2xpZGUtZG93bi1zd2F0Y2gnKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0JCgnLnNsaWRlLWRvd24tc3dhdGNoIHVsJykuc2xpZGVVcCgpO1xuXHRcdH1cblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vZmYoJ3RvdWNoc3RhcnQuU3dhdGNoLk1lbnUuQ2xvc2UnKS5vbigndG91Y2hzdGFydC5Td2F0Y2guTWVudS5DbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHZhciAkY3VycmVudFRhcmdldCA9ICQoZXZlbnQuY3VycmVudFRhcmdldCk7XG5cdFx0XG5cdFx0aXNUb3VjaE1vdmVkID0gZmFsc2U7XG5cdFx0aXNDdXJyZW50VGFyZ2V0U3dhdGNoID0gJGN1cnJlbnRUYXJnZXQuY2xvc2VzdCgnLnNsaWRlLWRvd24tc3dhdGNoJykubGVuZ3RoID4gMDtcblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vZmYoJ3RvdWNobW92ZS5Td2F0Y2guTWVudS5DbG9zZScpLm9uKCd0b3VjaG1vdmUuU3dhdGNoLk1lbnUuQ2xvc2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRpc1RvdWNoTW92ZWQgPSB0cnVlO1xuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9mZigndG91Y2hlbmQuU3dhdGNoLk1lbnUuQ2xvc2UnKS5vbigndG91Y2hlbmQuU3dhdGNoLk1lbnUuQ2xvc2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRpZiAoIWlzQ3VycmVudFRhcmdldFN3YXRjaCAmJiAhaXNUb3VjaE1vdmVkKSB7XG5cdFx0XHQkKCcuc2xpZGUtZG93bi1zd2F0Y2ggdWwnKS5zbGlkZVVwKCk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdCQoJy5zd2F0Y2hlcy5zaXplID4gbGkgPiBhLnNsaWRlLWRvd24nKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFxuXHRcdCQodGhpcylcblx0XHQubmV4dCgndWwnKVxuXHRcdC5zdG9wKClcblx0XHQuc2xpZGVUb2dnbGUoKVxuXHRcdC5wYXJlbnQoKVxuXHRcdC5zaWJsaW5ncygpXG5cdFx0LmNoaWxkcmVuKCd1bCcpXG5cdFx0LnNsaWRlVXAoKVxuXHRcdC5wcmV2KCcuc2xpZGUtZG93bicpO1xuXHR9KTtcblxuXHQvLyBEZWZhdWx0IHNlbGVjdGVkIHZhbHVlIGFzIHNsaWRlIGRvd25cblx0JCgnLnN3YXRjaGVzLnNpemUgPiBsaSA+IGEuc2xpZGUtZG93bicpXG5cdC5uZXh0KCd1bCcpXG5cdC5maW5kKCcuY3VycmVudCcpXG5cdC5jbG9zZXN0KCd1bCcpXG5cdC5wcmV2KCcuc2xpZGUtZG93bicpXG5cdC5hZGRDbGFzcygnY3VycmVudCcpXG5cdC5jbG9zZXN0KCdsaScpLmFkZENsYXNzKCdhY3RpdmUnKTtcblxuXHQkKCcucmVmaW5lbWVudHMgLnN3YXRjaGVzLnNpemUgPiBsaS5hY3RpdmUgPiB1bCcpLnNsaWRlRG93bigpO1xuXG5cdCQoJy5zd2F0Y2hlcyA+IGxpLnNsaWRlLWRvd24tc3dhdGNoID4gdWwnKS5vZmYoJ2NsaWNrJyk7XG5cblx0Ly8gUmVtb3ZlIGVtcHR5IHRpbGVzIFxuXHQkKCcuc3dhdGNoZXMuc2l6ZSA+IGxpID4gYS5zbGlkZS1kb3duJykubmV4dCgndWwnKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdGlmICgkKHRoaXMpLmZpbmQoJ2xpJykubGVuZ3RoID09PSAwKSB7XG5cdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJ2xpJykucmVtb3ZlKCk7XG5cdFx0fVxuXHR9KTtcbn1cblxudmFyIHNpemVSZWZpbmVtZW50cyA9IHtcblx0aW5pdDogZnVuY3Rpb24oKSB7XG5cdFx0aW5pdGlhbGl6ZUV2ZW50cygpO1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHNpemVSZWZpbmVtZW50czsiLCIndXNlIHN0cmljdCc7XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEFEQSBTbGljayBNb2RzXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gaW5pdCAoKSB7XG4gICAgJChkb2N1bWVudCkub2ZmKCdTbGlja1NsaWRlckFjY2Vzc2liaWxpdHlNb2RzJykub24oJ1NsaWNrU2xpZGVyQWNjZXNzaWJpbGl0eU1vZHMnLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAkKCcuc2xpY2stc2xpZGVyIC5zbGljay1zbGlkZSwgLnNsaWNrLXNsaWRlciAuc2xpY2stYWN0aXZlJykucmVtb3ZlQXR0cignYXJpYS1kZXNjcmliZWRieSByb2xlIHRhYmluZGV4Jyk7XHRcdFx0XG4gICAgICAgICQoJy5zbGljay1zbGlkZXIgLnNsaWNrLWRvdHMgYnV0dG9uJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBidXR0b25WYWwgPSAkKHRoaXMpLmh0bWwoKTtcbiAgICAgICAgICAgIHZhciBhZGRTcGFuID0gJzxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+JyArIGJ1dHRvblZhbCArICc8L3NwYW4+JztcbiAgICAgICAgICAgICQodGhpcykuaHRtbChhZGRTcGFuKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogLS0gU2xpZGVycyAtLVxuICogXG4gKiBDb25maWd1cmF0aW9uIE9wdGlvbnM6XG4gKiAgICAgICAgICAgICAgICBsb29wOiAgQk9PTEVBTiAgQm90aDsgSWYgbm8gb3B0aW9uIGdpdmVuLCBwcm9ncmFtbWF0aWNhbGx5IHNldCB0byB0cnVlLlxuICogICAgICAgICAgICAgICAgZG90czogIEJPT0xFQU4gIEJvdGg7IElmIG5vIG9wdGlvbiBnaXZlbiwgcHJvZ3JhbW1hdGljYWxseSBzZXQgdG8gdHJ1ZS5cbiAqICAgICAgICAgIHBhZ2luYXRpb246ICBPQkpFQ1QgICBTd2lwZXIgb25seTsgSWYgbm8gb3B0aW9uIGdpdmVuLCBwYWdpbmF0aW9uIGlzIG9taXR0ZWQgZnJvbSBzbGlkZXIgc2V0dGluZ3MuXG4gKiAgICAgICAgICAgICAgYXJyb3dzOiAgQk9PTEVBTiAgQm90aDsgSWYgbm8gb3B0aW9uIGdpdmVuLCBhdXRvbWF0aWNhbGx5IHNldCB0byB0cnVlIGluIHdpZGdldCBiYWNrZ3JvdW5kLlxuICogICAgICBhcnJvd3NQb3NpdGlvbjogIFNUUklORyAgIFsnaW5zaWRlJyBvciAnb3V0c2lkZSddIFN3aXBlciBvbmx5OyBJZiBubyBvcHRpb24gZ2l2ZW4sIGF1dG9tYXRpY2FsbHkgc2V0IHRvIHRoZSBvdXRzaWRlLlxuICogICAgICAgICAgbmF2aWdhdGlvbjogIE9CSkVDVCAgIFN3aXBlciBvbmx5OyBJZiBubyBvcHRpb24gZ2l2ZW4sIG5hdmlnYXRpb24gaXMgb21pdHRlZCBmcm9tIHNsaWRlciBzZXR0aW5ncy5cbiAqICAgICAgICBzbGlkZXNUb1Nob3c6ICBOVU1CRVIgICBCb3RoOyBJZiBubyBvcHRpb24gZ2l2ZW4sIHByb2dyYW1tYXRpY2FsbHkgc2V0IHRvIDEuXG4gKiAgICAgIHNsaWRlc1RvU2Nyb2xsOiAgTlVNQkVSICAgQm90aDsgSWYgbm8gb3B0aW9uIGdpdmVuLCBwcm9ncmFtbWF0aWNhbGx5IHNldCB0byAxLlxuICogICAgICAgICAgICBhdXRvcGxheTogIE5VTUJFUiAgIEJvdGg7IFdoZW4gZ2l2ZW4sIG51bWJlciBpcyBwcm9ncmFtbWF0aWNhbGx5IHNldCB0byBBdXRvcGxheSBTcGVlZCBhbmQgQXV0b3BsYXkgaXMgc2V0IHRvIHRydWUuIElmIG5vIG9wdGlvbiBnaXZlbiwgYXV0b3BsYXkgaXMgc2V0IHRvIGZhbHNlLlxuICogICAgICAgICBicmVha3BvaW50czogIE9CSkVDVCAgIEJvdGg7IFByb3BlcnRpZXMgYXJlIGxvb3BlZCBvdmVyIHRvIGFwcGx5IHZhcmlvdXMgYnJlYWtwb2ludCBzZXR0aW5ncy4gSWYgbm8gb3B0aW9uIGdpdmVuLCBicmVha3BvaW50cyBpcyBvbWl0dGVkIGZyb20gc2xpZGVyIHNldHRpbmdzLlxuICogICAgIFxuICogRXhhbXBsZSBDb2RlOlxuICogICAgICAgIHNsaWRlcnMuaW5pdCgnLnNvbWUtY2xhc3MtbmFtZScsIFxuICogICAgICAgIHtcbiAqICAgICAgICAgICAgIGxvb3A6IHRydWUsIFxuICogICAgICAgICAgICAgZG90czogdHJ1ZSwgXG4gKiAgICAgICAgICAgICBwYWdpbmF0aW9uOiB7ZWw6ICcuc3dpcGVyLXBhZ2luYXRpb24nLCBjbGlja2FibGU6IHRydWV9LCBcbiAqICAgICAgICAgICAgIGFycm93czogdHJ1ZSxcbiAqICAgICAgICAgICAgIGFycm93c1Bvc2l0aW9uOiAnaW5zaWRlJyxcbiAqICAgICAgICAgICAgIG5hdmlnYXRpb246IHtuZXh0RWw6ICcuc3dpcGVyLWJ1dHRvbi1uZXh0JywgcHJldkVsOiAnLnN3aXBlci1idXR0b24tcHJldid9LFxuICogICAgICAgICAgICAgc2xpZGVzVG9TaG93OiA2LFxuICogICAgICAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG4gKiAgICAgICAgICAgICBhdXRvcGxheTogMzAwMCxcbiAqICAgICAgICAgICAgIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogMX0sIDc2ODoge3NsaWRlc1RvU2hvdzogM319XG4gKiAgICAgICAgfSk7XG4gKiBcbiAqIFxuICogQWRkaXRpb25hbCBjb25maWd1cmF0aW9uIG9wdGlvbnMgZXhpc3QgZm9yIGJvdGggc2xpZGVycywgYnV0IGFkZGl0aW9uYWwgY29kZSBjaGFuZ2VzIHdvdWxkIGJlIG5lZWRlZCB0byBpbmNsdWRlIHRoZW0uIFxuICogXG4gKiBSZWZlcmVuY2Ugc2xpZGVyIGRvY3VtZW50YXRpb246XG4gKiBcbiAqIFN3aXBlciBkb2N1bWVudGF0aW9uIC0gaHR0cHM6Ly9zd2lwZXJqcy5jb20vc3dpcGVyLWFwaVxuICogU2xpY2sgZG9jdW1lbnRhdGlvbiAtIGh0dHBzOi8va2Vud2hlZWxlci5naXRodWIuaW8vc2xpY2svXG4gKiAgXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxuZXhwb3J0cy5pbml0ID0gaW5pdDtcbmV4cG9ydHMuaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycyA9IGluaXRpYWxpemVDYXRlZ29yeVNsaWRlcnM7XG5leHBvcnRzLmluaXRpYWxpemVSZWNvbW1lbmRhdGlvblNsaWRlciA9IGluaXRpYWxpemVSZWNvbW1lbmRhdGlvblNsaWRlcjtcblxuZnVuY3Rpb24gZ2V0VW5pcXVlTnVtYmVyKCkge1xuXHR2YXIgZGF0ZU9iamVjdCA9IG5ldyBEYXRlKCk7XG5cdHZhciB1bmlxdWVOdW1iZXIgPSBkYXRlT2JqZWN0LnZhbHVlT2YoKTtcbiAgICB2YXIgc3VmZml4TnVtYmVyID0gMSArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMCk7XG4gICAgdW5pcXVlTnVtYmVyID0gdW5pcXVlTnVtYmVyICsgc3VmZml4TnVtYmVyO1xuXHRyZXR1cm4gdW5pcXVlTnVtYmVyO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0ZWRTbGlja0JyZWFrcG9pbnRTaXplKGJyZWFrcG9pbnRTaXplLCBicmVha3BvaW50U2l6ZUFycmF5KSB7XG4gICAgdmFyIHNvcnRlZEJyZWFrcG9pbnRTaXplcyA9IGJyZWFrcG9pbnRTaXplQXJyYXkuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYSAtIGI7IH0pO1xuICAgIHZhciBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZTtcbiAgICBcbiAgICBpZiAoYnJlYWtwb2ludFNpemUgPT0gMCkge1xuICAgICAgICB2YXIgbW9iaWxlTWF4U2l6ZSA9IHNvcnRlZEJyZWFrcG9pbnRTaXplc1tzb3J0ZWRCcmVha3BvaW50U2l6ZXMuaW5kZXhPZigwKSArIDFdO1xuICAgICAgICBpZiAobW9iaWxlTWF4U2l6ZSkge1xuICAgICAgICAgICAgY29udmVydGVkQnJlYWtwb2ludFNpemUgPSBtb2JpbGVNYXhTaXplIC0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID0gNzY3O1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChicmVha3BvaW50U2l6ZSA9PSA3NjgpIHtcbiAgICAgICAgdmFyIGRlc2t0b3BNYXhTaXplID0gc29ydGVkQnJlYWtwb2ludFNpemVzW3NvcnRlZEJyZWFrcG9pbnRTaXplcy5pbmRleE9mKDc2OCkgKyAxXTtcbiAgICAgICAgaWYgKGRlc2t0b3BNYXhTaXplKSB7XG4gICAgICAgICAgICBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9IGRlc2t0b3BNYXhTaXplIC0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID0gOTk5OTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBicmVha3BvaW50TWF4U2l6ZSA9IHNvcnRlZEJyZWFrcG9pbnRTaXplc1tzb3J0ZWRCcmVha3BvaW50U2l6ZXMuaW5kZXhPZihicmVha3BvaW50U2l6ZSkgKyAxXTtcbiAgICAgICAgaWYgKGJyZWFrcG9pbnRNYXhTaXplKSB7XG4gICAgICAgICAgICBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9IGJyZWFrcG9pbnRNYXhTaXplIC0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID0gOTk5OTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZTtcbn1cblxuZnVuY3Rpb24gaW5pdFNsaWNrKGVsZW1lbnRTZWxlY3Rvciwgc2V0dGluZ3MpIHtcbiAgICBpZiAoIWVsZW1lbnRTZWxlY3Rvcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHNsaWRlclNldHRpbmdzID0ge1xuICAgICAgICBpbmZpbml0ZTogdHJ1ZSxcbiAgICAgICAgc2xpZGVzVG9TaG93OiAxLFxuICAgICAgICBzbGlkZXNUb1Njcm9sbDogMVxuICAgIH07XG4gICAgaWYgKHNldHRpbmdzKSB7XG4gICAgICAgIGlmICgnbG9vcCcgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmluZmluaXRlID0gc2V0dGluZ3MubG9vcDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2RvdHMnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5kb3RzID0gc2V0dGluZ3MuZG90cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2Fycm93cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmFycm93cyA9IHNldHRpbmdzLmFycm93cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ3NsaWRlc1RvU2hvdycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLnNsaWRlc1RvU2hvdyA9IHNldHRpbmdzLnNsaWRlc1RvU2hvdztcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ3NsaWRlc1RvU2Nyb2xsJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3Muc2xpZGVzVG9TY3JvbGwgPSBzZXR0aW5ncy5zbGlkZXNUb1Njcm9sbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2F1dG9wbGF5JyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXlTcGVlZCA9IHNldHRpbmdzLmF1dG9wbGF5O1xuICAgICAgICB9XG4gICAgICAgIGlmICgnYnJlYWtwb2ludHMnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5yZXNwb25zaXZlID0gW107XG4gICAgICAgICAgICB2YXIgYnJlYWtwb2ludFNpemVBcnJheSA9IE9iamVjdC5rZXlzKHNldHRpbmdzLmJyZWFrcG9pbnRzKS5tYXAoZnVuY3Rpb24gKHgpIHsgXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlSW50KHgpOyAvLyBFeHRyYSBwcmVjYXV0aW9uIG9mIHNhbml0aXppbmcgZGF0YSBmb3IgdXNlIGluIG1hdGhlbWF0aWNhbCBlcXVhdGlvbnNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZm9yICh2YXIgYnJlYWtwb2ludFNpemUgaW4gc2V0dGluZ3MuYnJlYWtwb2ludHMpIHtcbiAgICAgICAgICAgICAgICBicmVha3BvaW50U2l6ZSA9IHBhcnNlSW50KGJyZWFrcG9pbnRTaXplKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udmVydGVkQnJlYWtwb2ludFNpemUgPSBjb252ZXJ0ZWRTbGlja0JyZWFrcG9pbnRTaXplKGJyZWFrcG9pbnRTaXplLCBicmVha3BvaW50U2l6ZUFycmF5KTtcbiAgICAgICAgICAgICAgICB2YXIgYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0ID0ge1xuICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50OiBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3M6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgYnJlYWtwb2ludFNpemVTZXR0aW5ncyA9IHNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBzaXplU2V0dGluZyBpbiBicmVha3BvaW50U2l6ZVNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgnbG9vcCcgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdC5zZXR0aW5ncy5pbmZpbml0ZSA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgnZG90cycgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdC5zZXR0aW5ncy5kb3RzID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdhcnJvd3MnID09IHNpemVTZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50U2V0dGluZ3NPYmplY3Quc2V0dGluZ3MuYXJyb3dzID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdzbGlkZXNUb1Nob3cnID09IHNpemVTZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udmVydGVkQnJlYWtwb2ludFNpemUgPT0gOTk5OSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLnNsaWRlc1RvU2hvdyA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50U2V0dGluZ3NPYmplY3Quc2V0dGluZ3Muc2xpZGVzVG9TaG93ID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdzbGlkZXNUb1Njcm9sbCcgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9PSA5OTk5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3Muc2xpZGVzVG9TY3JvbGwgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0LnNldHRpbmdzLnNsaWRlc1RvU2Nyb2xsID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdhdXRvcGxheScgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9PSA5OTk5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmF1dG9wbGF5U3BlZWQgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXS5hdXRvcGxheTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0LnNldHRpbmdzLmF1dG9wbGF5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50U2V0dGluZ3NPYmplY3Quc2V0dGluZ3MuYXV0b3BsYXlTcGVlZCA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vaWYgKGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplICE9IDk5OTkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MucmVzcG9uc2l2ZS5wdXNoKGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdCk7XG4gICAgICAgICAgICAgICAgLy99XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAkKGVsZW1lbnRTZWxlY3Rvcikuc2xpY2soc2xpZGVyU2V0dGluZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICQoZWxlbWVudFNlbGVjdG9yKS5zbGljaygpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW5pdFN3aXBlcihlbGVtZW50U2VsZWN0b3IsIHNldHRpbmdzLCBjbGFzc2VzRm9yU2V0dGluZ3MpIHtcbiAgICBpZiAoIWVsZW1lbnRTZWxlY3Rvcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHNsaWRlclNldHRpbmdzID0ge1xuICAgICAgICBsb29wOiB0cnVlLFxuICAgICAgICBzcGFjZUJldHdlZW46IDIwLFxuICAgICAgICBwcmV2ZW50SW50ZXJhY3Rpb25PblRyYW5zaXRpb246IHRydWUsXG4gICAgICAgIGExMXk6IHtcbiAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICBmaXJzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGZpcnN0IHNsaWRlJyxcbiAgICAgICAgICAgIGxhc3RTbGlkZU1lc3NhZ2U6ICdUaGlzIGlzIHRoZSBsYXN0IHNsaWRlJ1xuICAgICAgICB9LFxuICAgICAgICBrZXlib2FyZDoge1xuXHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdHBhZ2VVcERvd246IHRydWVcblx0XHR9XG4gICAgfTtcbiAgICBpZiAoc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKCdsb29wJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MubG9vcCA9IHNldHRpbmdzLmxvb3A7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdwYWdpbmF0aW9uJyBpbiBzZXR0aW5ncyB8fCAnZG90cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5wYWdpbmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKCdlbCcgaW4gc2V0dGluZ3MucGFnaW5hdGlvbiAmJiBzZXR0aW5ncy5wYWdpbmF0aW9uLmVsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MucGFnaW5hdGlvbiA9IHNldHRpbmdzLnBhZ2luYXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoc2V0dGluZ3MuZG90cykge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5wYWdpbmF0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWw6ICcuc3dpcGVyLXBhZ2luYXRpb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2xpY2thYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gXG4gICAgICAgIGlmICgnbmF2aWdhdGlvbicgaW4gc2V0dGluZ3MgfHwgJ2Fycm93cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5uYXZpZ2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKCduZXh0RWwnIGluIHNldHRpbmdzLm5hdmlnYXRpb24gJiYgc2V0dGluZ3MubmF2aWdhdGlvbi5uZXh0RWwubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5uYXZpZ2F0aW9uID0gc2V0dGluZ3MubmF2aWdhdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzZXR0aW5ncy5hcnJvd3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MubmF2aWdhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRFbDogJy5zd2lwZXItYnV0dG9uLW5leHQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldkVsOiAnLnN3aXBlci1idXR0b24tcHJldidcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoJ3NsaWRlc1RvU2hvdycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLnNsaWRlc1BlclZpZXcgPSBzZXR0aW5ncy5zbGlkZXNUb1Nob3c7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdhdXRvcGxheScgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmF1dG9wbGF5ID0ge1xuICAgICAgICAgICAgICAgIGRlbGF5OiBzZXR0aW5ncy5hdXRvcGxheSxcbiAgICAgICAgICAgICAgICBkaXNhYmxlT25JbnRlcmFjdGlvbjogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2JyZWFrcG9pbnRzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHMgPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIGJyZWFrcG9pbnRTaXplIGluIHNldHRpbmdzLmJyZWFrcG9pbnRzKSB7XG4gICAgICAgICAgICAgICAgYnJlYWtwb2ludFNpemUgPSBwYXJzZUludChicmVha3BvaW50U2l6ZSk7XG4gICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGJyZWFrcG9pbnRTaXplU2V0dGluZ3MgPSBzZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV07XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgc2l6ZVNldHRpbmcgaW4gYnJlYWtwb2ludFNpemVTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoJ2xvb3AnID09IHNpemVTZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5sb29wID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdkb3RzJyA9PSBzaXplU2V0dGluZyAmJiBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXSA9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0ucGFnaW5hdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkOiBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbDogJy5zd2lwZXItcGFnaW5hdGlvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpY2thYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsYXNzZXNGb3JTZXR0aW5ncyAmJiBjbGFzc2VzRm9yU2V0dGluZ3MucGFnaW5hdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXS5wYWdpbmF0aW9uLmVsID0gY2xhc3Nlc0ZvclNldHRpbmdzLnBhZ2luYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICB9ICBcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ2Fycm93cycgPT0gc2l6ZVNldHRpbmcgJiYgYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ10gPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdLm5hdmlnYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5hYmxlZDogYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEVsOiAnLnN3aXBlci1idXR0b24tbmV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkVsOiAnLnN3aXBlci1idXR0b24tcHJldidcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlc0ZvclNldHRpbmdzICYmIGNsYXNzZXNGb3JTZXR0aW5ncy5uZXh0ICYmIGNsYXNzZXNGb3JTZXR0aW5ncy5wcmV2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdLm5hdmlnYXRpb24ubmV4dEVsID0gY2xhc3Nlc0ZvclNldHRpbmdzLm5leHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdLm5hdmlnYXRpb24ucHJldkVsID0gY2xhc3Nlc0ZvclNldHRpbmdzLnByZXY7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdzbGlkZXNUb1Nob3cnID09IHNpemVTZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0uc2xpZGVzUGVyVmlldyA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Muc2xpZGVzVG9TaG93O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgnc2xpZGVzVG9TY3JvbGwnID09IHNpemVTZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0uc2xpZGVzUGVyR3JvdXAgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzLnNsaWRlc1RvU2Nyb2xsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgnYXV0b3BsYXknIGluIGJyZWFrcG9pbnRTaXplU2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmF1dG9wbGF5ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5OiBicmVha3BvaW50U2l6ZVNldHRpbmdzLmF1dG9wbGF5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVPbkludGVyYWN0aW9uOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdLmF1dG9wbGF5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG5ldyBTd2lwZXIgKGVsZW1lbnRTZWxlY3Rvciwgc2xpZGVyU2V0dGluZ3MpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRTbGlja0hUTUwoJGVsZW1lbnQsIHNldHRpbmdzLCBpc0VpbnN0ZWluKSB7XG4gICAgdmFyIG9yaWdpbmFsU2xpZGVFbGVtZW50cyA9ICRlbGVtZW50LmNoaWxkcmVuKCkudG9BcnJheSgpO1xuICAgIHZhciB1bmlxdWVTbGlkZXI7XG5cbiAgICBpZiAoJGVsZW1lbnQuYXR0cignaWQnKSAmJiAkZWxlbWVudC5hdHRyKCdpZCcpLmluZGV4T2YoJ3NsaWRlci1pbmRleCcpID4gLTEpIHtcbiAgICAgICAgdW5pcXVlU2xpZGVyID0gJGVsZW1lbnQuYXR0cignaWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB1bmlxdWVTbGlkZXIgPSAnc2xpZGVyLWluZGV4LScgKyBnZXRVbmlxdWVOdW1iZXIoKS50b1N0cmluZygpO1xuICAgIH1cblxuICAgICRlbGVtZW50LmF0dHIoJ2lkJywgdW5pcXVlU2xpZGVyKTtcblxuICAgIC8vIEVpbnN0ZWluIENRdW90aWVudCBzY3JpcHRzIGFyZSBtaXhlZCBpbiB3aXRoIHNsaWRlcyBhdCB0aW1lIG9mIHNsaWRlciBpbml0aWFsaXphdGlvbi4gUmV3b3JrIHRoZSBIVE1MIHN0cnVjdHVyZS5cbiAgICBpZiAob3JpZ2luYWxTbGlkZUVsZW1lbnRzLmxlbmd0aCA+IDAgJiYgaXNFaW5zdGVpbikge1xuICAgICAgICB2YXIgbW9kaWZpZWRTbGlkZUVsZW1lbnRzID0gW107XG4gICAgICAgIHZhciBjcVNjcmlwdHMgPSBbXTtcblxuICAgICAgICAkLmVhY2gob3JpZ2luYWxTbGlkZUVsZW1lbnRzLCBmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b1VwcGVyQ2FzZSgpID09PSAnU0NSSVBUJykge1xuICAgICAgICAgICAgICAgIGNxU2NyaXB0cy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdMSScpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWRTbGlkZUVsZW1lbnRzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfSAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChjcVNjcmlwdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGVsZW1lbnQuY2xvc2VzdCgnZGl2LnNsaWRlci1jbGlwJykuYXBwZW5kKGNxU2NyaXB0cyk7XG4gICAgICAgIH1cblxuICAgICAgICAkZWxlbWVudC5odG1sKCcnKTtcbiAgICAgICAgJGVsZW1lbnQuYXBwZW5kKG1vZGlmaWVkU2xpZGVFbGVtZW50cyk7XG4gICAgfVxuICAgIHJldHVybjtcbn1cblxuZnVuY3Rpb24gZm9ybWF0U3dpcGVySFRNTCgkZWxlbWVudCwgc2V0dGluZ3MsIGlzRWluc3RlaW4pIHtcbiAgICB2YXIgb3JpZ2luYWxTbGlkZUVsZW1lbnRzID0gJGVsZW1lbnQuY2hpbGRyZW4oKS50b0FycmF5KCk7XG4gICAgdmFyIHVuaXF1ZVNsaWRlciwgc29ydGVkU2xpZGVzUGVyVmlld0FycmF5LCBhZGRTbGlkZXMsIGZpbmFsU2xpZGVzO1xuICAgIHZhciBpc0xvb3AgPSB0cnVlO1xuICAgIHZhciBzbGlkZXNQZXJWaWV3QXJyYXkgPSBbXTtcbiAgICB2YXIgY3FTY3JpcHRzID0gW107XG4gICAgdmFyIG1vZGlmaWVkU2xpZGVFbGVtZW50cyA9IFtdO1xuICAgIHZhciBkdXBsaWNhdGVkU2xpZGVFbGVtZW50cyA9IFtdO1xuICAgIHZhciBoYXNTd2lwZXJIVE1MID0gJGVsZW1lbnQuaGFzQ2xhc3MoJ3N3aXBlci1mdWxsLXdyYXBwZXInKSAmJiAkZWxlbWVudC5maW5kKCcuc3dpcGVyJykubGVuZ3RoID4gMDtcbiAgICB2YXIgc3dpcGVyQ2xhc3Nlc0ZvclNldHRpbmdzID0ge307XG5cbiAgICBpZiAoJGVsZW1lbnQuYXR0cignaWQnKSAmJiAkZWxlbWVudC5hdHRyKCdpZCcpLmluZGV4T2YoJ3NsaWRlci1pbmRleCcpID4gLTEpIHtcbiAgICAgICAgdW5pcXVlU2xpZGVyID0gJGVsZW1lbnQuYXR0cignaWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB1bmlxdWVTbGlkZXIgPSAnc2xpZGVyLWluZGV4LScgKyBnZXRVbmlxdWVOdW1iZXIoKS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHZhciAkc3dpcGVyUGFyZW50ID0gJCgnPGRpdiAvPicsIHsgJ2NsYXNzJzogJ3N3aXBlcicsICdpZCc6IHVuaXF1ZVNsaWRlciB9KSxcbiAgICAgICAgJHN3aXBlclBhZ2luYXRpb24gPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLXBhZ2luYXRpb24gc3dpcGVyLXBhZ2luYXRpb24tJyArIHVuaXF1ZVNsaWRlciB9KSxcbiAgICAgICAgJHN3aXBlck5hdmlnYXRpb24gPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLW5hdmlnYXRpb24tYnV0dG9ucy1jb250YWluZXInIH0pLFxuICAgICAgICAkc3dpcGVyUHJldkFycm93ID0gJCgnPGRpdiAvPicsIHsgJ2NsYXNzJzogJ3N3aXBlci1idXR0b24tcHJldiBzd2lwZXItYnV0dG9uLXByZXYtJyArIHVuaXF1ZVNsaWRlciB9KSxcbiAgICAgICAgJHN3aXBlck5leHRBcnJvdyA9ICQoJzxkaXYgLz4nLCB7ICdjbGFzcyc6ICdzd2lwZXItYnV0dG9uLW5leHQgc3dpcGVyLWJ1dHRvbi1uZXh0LScgKyB1bmlxdWVTbGlkZXIgfSksXG4gICAgICAgICRzd2lwZXJXcmFwcGVyID0gJCgnPGRpdiAvPicsIHsgJ2NsYXNzJzogJ3N3aXBlci13cmFwcGVyJyB9KTtcblxuICAgIGlmIChzZXR0aW5ncykge1xuICAgICAgICBpZiAoJ2JyZWFrcG9pbnRzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgZm9yICh2YXIgYnJlYWtwb2ludFNpemUgaW4gc2V0dGluZ3MuYnJlYWtwb2ludHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgYnJlYWtwb2ludFNpemVTZXR0aW5ncyA9IHNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXTtcblxuICAgICAgICAgICAgICAgIC8qIC0tLSBTd2lwZXIgQXJyb3dzIE5hdmlnYXRpb24gLS0tICovXG4gICAgICAgICAgICAgICAgLy8gU3dpcGVyIGRvZXMgbm90IGRpc3BsYXkgYXJyb3dzIGJ5IGRlZmF1bHQgdGhlIHdheSBTbGljayBkb2VzLiBXZSBtdXN0IGFjdGl2ZWx5IGluY2x1ZGUgdGhlbSB0byBtYXRjaCB0aGUgZGVmYXVsdHMgb2YgU2xpY2suXG4gICAgICAgICAgICAgICAgdmFyIG5hdkRpc3BsYXlDbGFzcyA9IGJyZWFrcG9pbnRTaXplID09ICcwJyA/ICdzaG93LW1vYmlsZS1uYXYtYnV0dG9ucycgOiAnc2hvdy1kZXNrdG9wLW5hdi1idXR0b25zJztcbiAgICAgICAgICAgICAgICAkc3dpcGVyTmF2aWdhdGlvbi5hZGRDbGFzcyhuYXZEaXNwbGF5Q2xhc3MpO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgYXJyb3dzIHdlcmUgZGVsaWJlcmF0ZWx5IHNldCB0byBmYWxzZSBpbiBzZXR0aW5ncywgdGhhdCBtZWFucyBoaWRlIHRoZW0gZm9yIGFsbCBicmVha3BvaW50IHNpemVzLlxuICAgICAgICAgICAgICAgIGlmICgnYXJyb3dzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2V0dGluZ3MuYXJyb3dzID09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkc3dpcGVyTmF2aWdhdGlvbi5yZW1vdmVDbGFzcygnc2hvdy1tb2JpbGUtbmF2LWJ1dHRvbnMgc2hvdy1kZXNrdG9wLW5hdi1idXR0b25zJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBFbHNlIGlmIGFycm93cyB3ZXJlIGRlbGliZXJhdGVseSBzZXQgdG8gZmFsc2UgZm9yIHNwZWNpZmljIGJyZWFrcG9pbnQsIHRoZW4gaGlkZSBmb3IgdGhhdCBicmVha3BvaW50LlxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2Fycm93cycgaW4gYnJlYWtwb2ludFNpemVTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYnJlYWtwb2ludFNpemVTZXR0aW5ncy5hcnJvd3MgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLnJlbW92ZUNsYXNzKG5hdkRpc3BsYXlDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvKiAtLS0gU3dpcGVyIERvdHMgUGFnaW5hdGlvbiAtLS0gKi9cbiAgICAgICAgICAgICAgICAvLyBTd2lwZXIgZG9lcyBub3QgZGlzcGxheSBwYWdpbmF0aW9uIGRvdHMgYnkgZGVmYXVsdCB0aGUgd2F5IFNsaWNrIGRvZXMuIFdlIG11c3QgYWN0aXZlbHkgaW5jbHVkZSB0aGVtIHRvIG1hdGNoIHRoZSBkZWZhdWx0cyBvZiBTbGljay5cbiAgICAgICAgICAgICAgICB2YXIgcGFnaW5hdGlvbkRpc3BsYXlDbGFzcyA9IGJyZWFrcG9pbnRTaXplID09ICcwJyA/ICdzaG93LW1vYmlsZS1wYWdpbmF0aW9uJyA6ICdzaG93LWRlc2t0b3AtcGFnbmlhdGlvbic7XG4gICAgICAgICAgICAgICAgJHN3aXBlclBhZ2luYXRpb24uYWRkQ2xhc3MocGFnaW5hdGlvbkRpc3BsYXlDbGFzcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBkb3RzIHdlcmUgZGVsaWJlcmF0ZWx5IHNldCB0byBmYWxzZSBpbiBzZXR0aW5ncywgdGhhdCBtZWFucyBoaWRlIHRoZW0gZm9yIGFsbCBicmVha3BvaW50IHNpemVzLlxuICAgICAgICAgICAgICAgIGlmICgnZG90cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNldHRpbmdzLmRvdHMgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzd2lwZXJQYWdpbmF0aW9uLnJlbW92ZUNsYXNzKCdzaG93LW1vYmlsZS1wYWdpbmF0aW9uIHNob3ctZGVza3RvcC1wYWduaWF0aW9uJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBFbHNlIGlmIGRvdHMgd2VyZSBkZWxpYmVyYXRlbHkgc2V0IHRvIGZhbHNlIGZvciBzcGVjaWZpYyBicmVha3BvaW50LCB0aGVuIGhpZGUgZm9yIHRoYXQgYnJlYWtwb2ludC5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdkb3RzJyBpbiBicmVha3BvaW50U2l6ZVNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChicmVha3BvaW50U2l6ZVNldHRpbmdzLmRvdHMgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzd2lwZXJQYWdpbmF0aW9uLnJlbW92ZUNsYXNzKHBhZ2luYXRpb25EaXNwbGF5Q2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCdzbGlkZXNUb1Nob3cnIGluIGJyZWFrcG9pbnRTaXplU2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc2xpZGVzUGVyVmlld0FycmF5LnB1c2gocGFyc2VJbnQoYnJlYWtwb2ludFNpemVTZXR0aW5ncy5zbGlkZXNUb1Nob3cpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBTd2lwZXIgZG9lcyBub3QgZGlzcGxheSBhcnJvd3MgYnkgZGVmYXVsdCB0aGUgd2F5IFNsaWNrIGRvZXMuIFdlIG11c3QgYWN0aXZlbHkgaW5jbHVkZSB0aGVtIHRvIG1hdGNoIHRoZSBkZWZhdWx0cyBvZiBTbGljay5cbiAgICAgICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLmFkZENsYXNzKCdzaG93LW1vYmlsZS1uYXYtYnV0dG9ucyBzaG93LWRlc2t0b3AtbmF2LWJ1dHRvbnMnKTtcblxuICAgICAgICAgICAgLy8gSWYgYXJyb3dzIHdlcmUgZGVsaWJlcmF0ZWx5IHNldCB0byBmYWxzZSBpbiBzZXR0aW5ncywgdGhhdCBtZWFucyBoaWRlIHRoZW0gZm9yIGFsbCBicmVha3BvaW50IHNpemVzLlxuICAgICAgICAgICAgaWYgKCdhcnJvd3MnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNldHRpbmdzLmFycm93cyA9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAkc3dpcGVyTmF2aWdhdGlvbi5yZW1vdmVDbGFzcygnc2hvdy1tb2JpbGUtbmF2LWJ1dHRvbnMgc2hvdy1kZXNrdG9wLW5hdi1idXR0b25zJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTd2lwZXIgZG9lcyBub3QgZGlzcGxheSBwYWdpbmF0aW9uIGRvdHMgYnkgZGVmYXVsdCB0aGUgd2F5IFNsaWNrIGRvZXMuIFdlIG11c3QgYWN0aXZlbHkgaW5jbHVkZSB0aGVtIHRvIG1hdGNoIHRoZSBkZWZhdWx0cyBvZiBTbGljay5cbiAgICAgICAgICAgICRzd2lwZXJQYWdpbmF0aW9uLmFkZENsYXNzKCdzaG93LWRlc2t0b3AtcGFnbmlhdGlvbiBzaG93LW1vYmlsZS1wYWdpbmF0aW9uJyk7XG5cbiAgICAgICAgICAgIC8vIElmIGRvdHMgd2VyZSBkZWxpYmVyYXRlbHkgc2V0IHRvIGZhbHNlIGluIHNldHRpbmdzLCB0aGF0IG1lYW5zIGhpZGUgdGhlbSBmb3IgYWxsIGJyZWFrcG9pbnQgc2l6ZXMuXG4gICAgICAgICAgICBpZiAoJ2RvdHMnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNldHRpbmdzLmRvdHMgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgJHN3aXBlclBhZ2luYXRpb24ucmVtb3ZlQ2xhc3MoJ3Nob3ctZGVza3RvcC1wYWduaWF0aW9uIHNob3ctbW9iaWxlLXBhZ2luYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdsb29wJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgaXNMb29wID0gc2V0dGluZ3MubG9vcDtcbiAgICAgICAgfVxuICAgIH0gICAgXG5cbiAgICBpZiAoc2xpZGVzUGVyVmlld0FycmF5KSB7XG4gICAgICAgIHNvcnRlZFNsaWRlc1BlclZpZXdBcnJheSA9IHNsaWRlc1BlclZpZXdBcnJheS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhIC0gYjsgfSk7XG4gICAgfVxuXG4gICAgaWYgKCFoYXNTd2lwZXJIVE1MICYmIG9yaWdpbmFsU2xpZGVFbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICRlbGVtZW50LmFkZENsYXNzKCdzd2lwZXItZnVsbC13cmFwcGVyJyk7XG5cbiAgICAgICAgLy8gRWluc3RlaW4gQ1F1b3RpZW50IHNjcmlwdHMgYXJlIG1peGVkIGluIHdpdGggc2xpZGVzIGF0IHRpbWUgb2Ygc2xpZGVyIGluaXRpYWxpemF0aW9uLiBSZXdvcmsgdGhlIEhUTUwgc3RydWN0dXJlLlxuICAgICAgICBpZiAoaXNFaW5zdGVpbikge1xuICAgICAgICAgICAgJC5lYWNoKG9yaWdpbmFsU2xpZGVFbGVtZW50cywgZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdTQ1JJUFQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNxU2NyaXB0cy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmb3JtYXR0ZWRTbGlkZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b1VwcGVyQ2FzZSgpID09PSAnRElWJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkU2xpZGUgPSAkKGVsZW1lbnQpLmFkZENsYXNzKCdzd2lwZXItc2xpZGUnKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlZFNsaWRlID0gJCgnPGRpdiAvPicsIHsgJ2NsYXNzJzogJ3N3aXBlci1zbGlkZScgfSkuaHRtbCgkKGVsZW1lbnQpLmh0bWwoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWRTbGlkZUVsZW1lbnRzLnB1c2goZm9ybWF0dGVkU2xpZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gUHJvY2VlZCB0byBtb2RpZnkgcmVndWxhciBzbGlkZSBlbGVtZW50cyAobm9uLUVpbnN0ZWluKVxuICAgICAgICAgICAgbW9kaWZpZWRTbGlkZUVsZW1lbnRzID0gb3JpZ2luYWxTbGlkZUVsZW1lbnRzLm1hcChmdW5jdGlvbihlbGVtZW50LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKSA9PT0gJ0RJVicpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQoZWxlbWVudCkuYWRkQ2xhc3MoJ3N3aXBlci1zbGlkZScpWzBdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLXNsaWRlJyB9KS5odG1sKCQoZWxlbWVudCkuaHRtbCgpKVswXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhZGRpdGlvbmFsIHNsaWRlcyAoYWNjb3JkaW5nIHRvIGxvd2VzdCBjb21tb24gbXVsdGlwbGUpIHRvIGZpeCBsb29wIGJ1ZyBpbiBTd2lwZXJcbiAgICAgICAgaWYgKG1vZGlmaWVkU2xpZGVFbGVtZW50cyAmJiBzb3J0ZWRTbGlkZXNQZXJWaWV3QXJyYXkgJiYgaXNMb29wKSB7XG4gICAgICAgICAgICB2YXIgTENNID0gbGVhc3RDb21tb25NdWx0aXBsZShzb3J0ZWRTbGlkZXNQZXJWaWV3QXJyYXkpO1xuICAgICAgICAgICAgaWYgKHNvcnRlZFNsaWRlc1BlclZpZXdBcnJheS5pbmRleE9mKExDTSkgPiAtMSkge1xuICAgICAgICAgICAgICAgIGFkZFNsaWRlcyA9IChMQ00gKiAyKSAtIG1vZGlmaWVkU2xpZGVFbGVtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFkZFNsaWRlcyA9IExDTSAtIG1vZGlmaWVkU2xpZGVFbGVtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWRkU2xpZGVzIDwgMCkge1xuICAgICAgICAgICAgICAgIHZhciBIQ00gPSBzb3J0ZWRTbGlkZXNQZXJWaWV3QXJyYXkucmVkdWNlKGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhICogYjsgfSk7XG4gICAgICAgICAgICAgICAgYWRkU2xpZGVzID0gSENNIC0gbW9kaWZpZWRTbGlkZUVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZWFjaChtb2RpZmllZFNsaWRlRWxlbWVudHMsIGZ1bmN0aW9uKGlkeCwgaXRlbSkge1xuICAgICAgICAgICAgICAgIGlmIChpZHggPCBhZGRTbGlkZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZHVwbGljYXRlZFNsaWRlRWxlbWVudHMucHVzaCgkKGl0ZW0pLmNsb25lKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGZpbmFsIGFycmF5IG9mIHNsaWRlIGVsZW1lbnRzXG4gICAgICAgIGZpbmFsU2xpZGVzID0gJC5tZXJnZShtb2RpZmllZFNsaWRlRWxlbWVudHMsIGR1cGxpY2F0ZWRTbGlkZUVsZW1lbnRzKTtcblxuICAgICAgICAvLyBBcHBlbmQgbmV3IHN3aXBlciBIVE1MIGVsZW1lbnRzIHRvIHN3aXBlciB3cmFwcGVyXG4gICAgICAgICRzd2lwZXJXcmFwcGVyLmFwcGVuZChmaW5hbFNsaWRlcyk7XG4gICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLmFwcGVuZCgkc3dpcGVyUHJldkFycm93KS5hcHBlbmQoJHN3aXBlck5leHRBcnJvdyk7XG4gICAgICAgICRzd2lwZXJQYXJlbnQuYXBwZW5kKCRzd2lwZXJXcmFwcGVyKS5hcHBlbmQoJHN3aXBlclBhZ2luYXRpb24pO1xuXG4gICAgICAgIC8vIFNldCBzbGlkZSBhcnJvd3MgZWl0aGVyIGluc2lkZSBvciBvdXRzaWRlIHNsaWRlciBjb250YWluZXJcbiAgICAgICAgdmFyIGFycm93c1Bvc2l0aW9uID0gc2V0dGluZ3MgJiYgJ2Fycm93c1Bvc2l0aW9uJyBpbiBzZXR0aW5ncyA/IHNldHRpbmdzLmFycm93c1Bvc2l0aW9uIDogbnVsbDtcbiAgICAgICAgaWYgKGFycm93c1Bvc2l0aW9uICYmIGFycm93c1Bvc2l0aW9uID09ICdpbnNpZGUnKSB7XG4gICAgICAgICAgICAkc3dpcGVyUGFyZW50LmFwcGVuZCgkc3dpcGVyTmF2aWdhdGlvbikuYWRkQ2xhc3MoJ3N3aXBlci1pbnNpZGUtbmF2aWdhdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVwbGFjZSBzd2lwZXIgd3JhcHBlciBjb250ZW50cyB3aXRoIG5ldyBIVE1MXG4gICAgICAgICRlbGVtZW50Lmh0bWwoJHN3aXBlclBhcmVudCk7XG5cbiAgICAgICAgaWYgKCFhcnJvd3NQb3NpdGlvbiB8fCBhcnJvd3NQb3NpdGlvbiA9PSAnb3V0c2lkZScpIHsgLy8gSWYgYXJyb3dzIGFyZSBvdXRzaWRlLCB3ZSBoYXZlIHRvIHdhaXQgdW50aWwgc3dpcGVyIHdyYXBwZXIgaGFzIGNvbnRlbnQgaW4gbGluZSBhYm92ZSBiZWZvcmUgd2UgcHJlcGVuZFxuICAgICAgICAgICAgJGVsZW1lbnQucHJlcGVuZCgkc3dpcGVyTmF2aWdhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzRWluc3RlaW4gJiYgY3FTY3JpcHRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRlbGVtZW50LmFwcGVuZChjcVNjcmlwdHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR3JhYiB0aGUgdW5pcXVlIGNsYXNzZXMgZnJvbSBhbGwgdGhlIG5ldyBlbGVtZW50cyBhYm92ZSBhbmQgcmV0dXJuIGZvciBmdXJ0aGVyIHVzZVxuICAgICAgICBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3MucGFyZW50ID0gJyMnICsgdW5pcXVlU2xpZGVyO1xuICAgICAgICBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3MucGFnaW5hdGlvbiA9ICcuc3dpcGVyLXBhZ2luYXRpb24tJyArIHVuaXF1ZVNsaWRlcjtcbiAgICAgICAgc3dpcGVyQ2xhc3Nlc0ZvclNldHRpbmdzLnByZXYgPSAnLnN3aXBlci1idXR0b24tcHJldi0nICsgdW5pcXVlU2xpZGVyO1xuICAgICAgICBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3MubmV4dCA9ICcuc3dpcGVyLWJ1dHRvbi1uZXh0LScgKyB1bmlxdWVTbGlkZXI7XG4gICAgfVxuICAgIHJldHVybiBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3M7XG59XG5cbmZ1bmN0aW9uIGluaXQgKGVsZW1lbnRDbGFzcywgc2V0dGluZ3MsIGlzRWluc3RlaW4pIHtcbiAgICB2YXIgc2VsZWN0b3IgPSBlbGVtZW50Q2xhc3M7XG4gICAgaWYgKCFlbGVtZW50Q2xhc3MgfHwgKCQoZWxlbWVudENsYXNzKS5sZW5ndGggPT0gMCAmJiBlbGVtZW50Q2xhc3MuaW5kZXhPZignOmhhcycpIDwgMCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPTlRFTlRfU0xPVF9TTElERVIgPT0gJ3N3aXBlckpTJykgeyBcbiAgICAgICAgJChlbGVtZW50Q2xhc3MpLmVhY2goZnVuY3Rpb24obiwgZWxtKSB7XG4gICAgICAgICAgICB2YXIgJGVsZW1lbnQgPSAkKGVsbSk7XG4gICAgICAgICAgICB2YXIgaGFzU3dpcGVySFRNTCA9ICRlbGVtZW50LmZpbmQoJy5zd2lwZXItaW5pdGlhbGl6ZWQnKS5sZW5ndGggPiAwO1xuXG4gICAgICAgICAgICBpZiAoIWhhc1N3aXBlckhUTUwpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2xhc3Nlc0ZvclNldHRpbmdzID0gZm9ybWF0U3dpcGVySFRNTCgkZWxlbWVudCwgc2V0dGluZ3MsIGlzRWluc3RlaW4pO1xuICAgICAgICAgICAgICAgIGlmICghc2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXNGb3JTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICAvLyBPdmVycmlkZSBzZWxlY3RvciBjbGFzcyBmb3IgSUQgaWYgd2UgaGF2ZSBpdFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RvciA9IGNsYXNzZXNGb3JTZXR0aW5ncy5wYXJlbnQgPyBjbGFzc2VzRm9yU2V0dGluZ3MucGFyZW50IDogc2VsZWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdzLnBhZ2luYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbDogY2xhc3Nlc0ZvclNldHRpbmdzLnBhZ2luYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGlja2FibGU6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MubmF2aWdhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRFbDogY2xhc3Nlc0ZvclNldHRpbmdzLm5leHQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2RWw6IGNsYXNzZXNGb3JTZXR0aW5ncy5wcmV2XG4gICAgICAgICAgICAgICAgICAgIH07ICAgIFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5pdFN3aXBlcihzZWxlY3Rvciwgc2V0dGluZ3MsIGNsYXNzZXNGb3JTZXR0aW5ncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICQoZWxlbWVudENsYXNzKS5lYWNoKGZ1bmN0aW9uKG4sIGVsbSkge1xuICAgICAgICAgICAgdmFyICRlbGVtZW50ID0gJChlbG0pO1xuICAgICAgICAgICAgdmFyIGVsZW1lbnRJZFNlbGVjdG9yO1xuICAgICAgICAgICAgZm9ybWF0U2xpY2tIVE1MKCRlbGVtZW50LCBzZXR0aW5ncywgaXNFaW5zdGVpbik7XG4gICAgICAgICAgICBlbGVtZW50SWRTZWxlY3RvciA9ICcjJyArICRlbGVtZW50LmF0dHIoJ2lkJyk7XG4gICAgICAgICAgICBpbml0U2xpY2soZWxlbWVudElkU2VsZWN0b3IsIHNldHRpbmdzKTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBsZWFzdENvbW1vbk11bHRpcGxlKHZhbHVlcykge1xuICAgIGZ1bmN0aW9uIGdjZChhLCBiKSB7XG4gICAgICAgIC8vIEdyZWF0ZXN0IGNvbW1vbiBkaXZpc29yIG9mIDIgaW50ZWdlcnNcbiAgICAgICAgcmV0dXJuICFiID8gYSA6IGdjZChiLCBhICUgYik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGNtKGEsIGIpIHtcbiAgICAgICAgLy8gTGVhc3QgY29tbW9uIG11bHRpcGxlIG9mIDIgaW50ZWdlcnNcbiAgICAgICAgcmV0dXJuIChhICogYikgLyBnY2QoYSwgYik7ICAgXG4gICAgfVxuXG4gICAgdmFyIG11bHRpcGxlID0gdmFsdWVzWzBdO1xuICAgIC8vIExlYXN0IGNvbW1vbiBtdWx0aXBsZSBvZiBhIGxpc3Qgb2YgaW50ZWdlcnNcbiAgICB2YWx1ZXMuZm9yRWFjaChmdW5jdGlvbihuKSB7XG4gICAgICAgIG11bHRpcGxlID0gbGNtKG11bHRpcGxlLCBuKTtcbiAgICB9KTtcblxuICAgIC8vIFJldHVybiBsZWFzdCBjb21tb24gbXVsdGlwbGUgZm9yIGFycmF5IG9mIHZhbHVlc1xuICAgIHJldHVybiBtdWx0aXBsZTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycyhlbGVtZW50Q2xhc3MpIHtcblx0dmFyICRjYXRlZ29yeVNsaWRlcnMgPSAkKGVsZW1lbnRDbGFzcyk7XG5cdGlmICgkY2F0ZWdvcnlTbGlkZXJzLmxlbmd0aCA+IDApIHtcblx0XHQkY2F0ZWdvcnlTbGlkZXJzLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRcdHZhciAkZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgICAgICAgICB2YXIgY2F0ZWdvcnlTbGlkZXJPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRzOiB7fVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciB1bmlxdWVTbGlkZXIgPSAnY2F0ZWdvcnktc2xpZGVyLWluZGV4LScgKyBnZXRVbmlxdWVOdW1iZXIoKS50b1N0cmluZygpO1xuICAgICAgICAgICAgJGVsZW1lbnQuYWRkQ2xhc3ModW5pcXVlU2xpZGVyKTtcblxuXHRcdFx0Ly8gRGVza3RvcCBzbG90IGNvbmZpZyBvcHRpb25zXG5cdFx0XHR2YXIgY2F0ZWdvcnlTbGlkZXJEZXNrdG9wT3B0aW9ucyA9ICRlbGVtZW50LmF0dHIoJ3NsaWRlci1kZXNrdG9wLW9wdGlvbnMnKTtcblx0XHRcdGlmIChjYXRlZ29yeVNsaWRlckRlc2t0b3BPcHRpb25zKSB7XG5cdFx0XHRcdGNhdGVnb3J5U2xpZGVyRGVza3RvcE9wdGlvbnMgPSBKU09OLnBhcnNlKGNhdGVnb3J5U2xpZGVyRGVza3RvcE9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGNhdGVnb3J5U2xpZGVyT3B0aW9ucy5icmVha3BvaW50c1tjYXRlZ29yeVNsaWRlckRlc2t0b3BPcHRpb25zLmJyZWFrcG9pbnRTaXplXSA9IGNhdGVnb3J5U2xpZGVyRGVza3RvcE9wdGlvbnM7XG5cdFx0XHR9XG5cdFx0XHQvLyBNb2JpbGUgc2xvdCBjb25maWcgb3B0aW9uc1xuXHRcdFx0dmFyIGNhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucyA9ICRlbGVtZW50LmF0dHIoJ3NsaWRlci1tb2JpbGUtb3B0aW9ucycpO1xuXHRcdFx0aWYgKGNhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucykge1xuXHRcdFx0XHRjYXRlZ29yeVNsaWRlck1vYmlsZU9wdGlvbnMgPSBKU09OLnBhcnNlKGNhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgY2F0ZWdvcnlTbGlkZXJPcHRpb25zLmJyZWFrcG9pbnRzW2NhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucy5icmVha3BvaW50U2l6ZV0gPSBjYXRlZ29yeVNsaWRlck1vYmlsZU9wdGlvbnM7XG5cdFx0XHR9XG5cbiAgICAgICAgICAgIGluaXQoJy4nICsgdW5pcXVlU2xpZGVyLCBjYXRlZ29yeVNsaWRlck9wdGlvbnMpO1xuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVSZWNvbW1lbmRhdGlvblNsaWRlcigpIHtcblx0dmFyIGF0dGVtcHROdW1iZXIgPSAwO1xuXHR2YXIgdGltZXIgPSBzZXRJbnRlcnZhbChyZWNvbW1lbmRhdGlvblNsaWRlckludGVydmFsSGFuZGxlciwgNTAwKTtcblx0ZnVuY3Rpb24gcmVjb21tZW5kYXRpb25TbGlkZXJJbnRlcnZhbEhhbmRsZXIoKSB7XG4gICAgICAgIHZhciBzbGlkZXJJbml0aWFsaXplZENsYXNzID0gU2l0ZVByZWZlcmVuY2VzLkNPTlRFTlRfU0xPVF9TTElERVIgPT0gJ3N3aXBlckpTJyA/ICdzd2lwZXItaW5pdGlhbGl6ZWQnIDogJ3NsaWNrLWluaXRpYWxpemVkJztcbiAgICAgICAgdmFyIHNsaWRlclNlbGVjdG9yID0gJy5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucyAuc2xpZGVyLXByb2R1Y3RzLXByaW1hcnkgLnNsaWRlcyc7XG4gICAgICAgIHZhciByZWNvbW1lbmRhdGlvblNsaWRlckluaXRpYWxpemVkO1xuXG4gICAgICAgIGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG4gICAgICAgICAgICBzbGlkZXJTZWxlY3RvciA9ICcucmVjb21tLXByb2QtYW5jaG9yLXNsb3QgJyArIHNsaWRlclNlbGVjdG9yO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT05URU5UX1NMT1RfU0xJREVSID09ICdzd2lwZXJKUycpIHtcbiAgICAgICAgICAgIHJlY29tbWVuZGF0aW9uU2xpZGVySW5pdGlhbGl6ZWQgPSAkKHNsaWRlclNlbGVjdG9yKS5maW5kKCcuJyArIHNsaWRlckluaXRpYWxpemVkQ2xhc3MpLmxlbmd0aCA+IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWNvbW1lbmRhdGlvblNsaWRlckluaXRpYWxpemVkID0gJChzbGlkZXJTZWxlY3RvcikuZmlsdGVyKGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQodGhpcykuaGFzQ2xhc3Moc2xpZGVySW5pdGlhbGl6ZWRDbGFzcyk7XG4gICAgICAgICAgICB9KS5sZW5ndGggPiAwO1xuICAgICAgICB9XG5cblx0XHRhdHRlbXB0TnVtYmVyKys7XG5cdFx0aWYocmVjb21tZW5kYXRpb25TbGlkZXJJbml0aWFsaXplZCB8fCBhdHRlbXB0TnVtYmVyID4gMjApIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0VpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Eb25lJywgJCgnI3Byb2R1Y3QtcmVjb21tZW5kYXRpb25zJykpO1xuICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT05URU5UX1NMT1RfU0xJREVSID09ICdpbWdWaWV3ZXIyU2xpY2snKSB7IFxuXHRcdFx0ICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NsaWNrU2xpZGVyQWNjZXNzaWJpbGl0eU1vZHMnKTtcbiAgICAgICAgICAgIH1cblx0XHRcdGNsZWFySW50ZXJ2YWwodGltZXIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cbiAgICAgICAgJCgnLnNsaWRlci1wcm9kdWN0cy1wcmltYXJ5JykudHJpZ2dlcignaW5pdC1zbGlkZXInKTtcblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGludmVudG9yeSA9IHJlcXVpcmUoJy4vJyk7XG5cbnZhciBjYXJ0SW52ZW50b3J5ID0ge1xuICAgIHNldFNlbGVjdGVkU3RvcmU6IGZ1bmN0aW9uIChzdG9yZUlkKSB7XG4gICAgICAgIHZhciAkc2VsZWN0ZWRTdG9yZSA9ICQoJy5zdG9yZS10aWxlLicgKyBzdG9yZUlkKSxcbiAgICAgICAgICAgICRsaW5lSXRlbSA9ICQoJy5jYXJ0LXJvd1tkYXRhLXV1aWQ9XCInICsgdGhpcy51dWlkICsgJ1wiXScpLFxuICAgICAgICAgICAgc3RvcmVBZGRyZXNzID0gJHNlbGVjdGVkU3RvcmUuZmluZCgnLnN0b3JlLWFkZHJlc3MnKS5odG1sKCksXG4gICAgICAgICAgICBzdG9yZVN0YXR1cyA9ICRzZWxlY3RlZFN0b3JlLmZpbmQoJy5zdG9yZS1zdGF0dXMnKS5kYXRhKCdzdGF0dXMnKSxcbiAgICAgICAgICAgIHN0b3JlU3RhdHVzVGV4dCA9ICRzZWxlY3RlZFN0b3JlLmZpbmQoJy5zdG9yZS1zdGF0dXMnKS50ZXh0KCk7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZSA9IHN0b3JlSWQ7XG5cbiAgICAgICAgJGxpbmVJdGVtLmZpbmQoJy5pbnN0b3JlLWRlbGl2ZXJ5IC5zZWxlY3RlZC1zdG9yZS1hZGRyZXNzJylcbiAgICAgICAgICAgIC5kYXRhKCdzdG9yZUlkJywgc3RvcmVJZClcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLXN0b3JlLWlkJywgc3RvcmVJZClcbiAgICAgICAgICAgIC5odG1sKHN0b3JlQWRkcmVzcyk7XG4gICAgICAgICRsaW5lSXRlbS5maW5kKCcuaW5zdG9yZS1kZWxpdmVyeSAuc2VsZWN0ZWQtc3RvcmUtYXZhaWxhYmlsaXR5JylcbiAgICAgICAgICAgIC5kYXRhKCdzdGF0dXMnLCBzdG9yZVN0YXR1cylcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLXN0YXR1cycsIHN0b3JlU3RhdHVzKVxuICAgICAgICAgICAgLnRleHQoc3RvcmVTdGF0dXNUZXh0KTtcbiAgICAgICAgJGxpbmVJdGVtLmZpbmQoJy5pbnN0b3JlLWRlbGl2ZXJ5IC5kZWxpdmVyeS1vcHRpb24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgfSxcbiAgICBjYXJ0U2VsZWN0U3RvcmU6IGZ1bmN0aW9uIChzZWxlY3RlZFN0b3JlKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgaW52ZW50b3J5LmdldFN0b3Jlc0ludmVudG9yeSh0aGlzLnV1aWQpLnRoZW4oZnVuY3Rpb24gKHN0b3Jlcykge1xuICAgICAgICAgICAgaW52ZW50b3J5LnNlbGVjdFN0b3JlRGlhbG9nKHtcbiAgICAgICAgICAgICAgICBzdG9yZXM6IHN0b3JlcyxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZFN0b3JlSWQ6IHNlbGVjdGVkU3RvcmUsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZVRleHQ6IFJlc291cmNlcy5TRUxFQ1RFRF9TVE9SRSxcbiAgICAgICAgICAgICAgICBjb250aW51ZUNhbGxiYWNrOiBmdW5jdGlvbiAoKSB7fSxcbiAgICAgICAgICAgICAgICBzZWxlY3RTdG9yZUNhbGxiYWNrOiBzZWxmLnNldFNlbGVjdGVkU3RvcmUuYmluZChzZWxmKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLmRvbmUoKTtcbiAgICB9LFxuICAgIHNldERlbGl2ZXJ5T3B0aW9uOiBmdW5jdGlvbiAodmFsdWUsIHN0b3JlSWQpIHtcbiAgICAgICAgLy8gc2V0IGxvYWRpbmcgc3RhdGVcbiAgICAgICAgJCgnLml0ZW0tZGVsaXZlcnktb3B0aW9ucycpXG4gICAgICAgICAgICAuYWRkQ2xhc3MoJ2xvYWRpbmcnKVxuICAgICAgICAgICAgLmNoaWxkcmVuKCkuaGlkZSgpO1xuXG4gICAgICAgIHZhciBkYXRhID0ge1xuICAgICAgICAgICAgcGxpZDogdGhpcy51dWlkLFxuICAgICAgICAgICAgc3RvcmVwaWNrdXA6ICh2YWx1ZSA9PT0gJ3N0b3JlJyA/IHRydWUgOiBmYWxzZSlcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHZhbHVlID09PSAnc3RvcmUnKSB7XG4gICAgICAgICAgICBkYXRhLnN0b3JlcGlja3VwID0gdHJ1ZTtcbiAgICAgICAgICAgIGRhdGEuc3RvcmVpZCA9IHN0b3JlSWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkYXRhLnN0b3JlcGlja3VwID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogVXJscy5zZXRTdG9yZVBpY2t1cCxcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGxvYWRpbmcgc3RhdGVcbiAgICAgICAgICAgICAgICAkKCcuaXRlbS1kZWxpdmVyeS1vcHRpb25zJylcbiAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKCdsb2FkaW5nJylcbiAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCkuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAkKCcuaXRlbS1kZWxpdmVyeS1vcHRpb25zIC5zZXQtcHJlZmVycmVkLXN0b3JlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHNlbGYudXVpZCA9ICQodGhpcykuZGF0YSgndXVpZCcpO1xuICAgICAgICAgICAgdmFyIHNlbGVjdGVkU3RvcmUgPSAkKHRoaXMpLmNsb3Nlc3QoJy5pbnN0b3JlLWRlbGl2ZXJ5JykuZmluZCgnLnNlbGVjdGVkLXN0b3JlLWFkZHJlc3MnKS5kYXRhKCdzdG9yZUlkJyk7XG4gICAgICAgICAgICBpZiAoIVVzZXIuemlwKSB7XG4gICAgICAgICAgICAgICAgaW52ZW50b3J5LnppcFByb21wdChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY2FydFNlbGVjdFN0b3JlKHNlbGVjdGVkU3RvcmUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLmNhcnRTZWxlY3RTdG9yZShzZWxlY3RlZFN0b3JlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgICQoJy5pdGVtLWRlbGl2ZXJ5LW9wdGlvbnMgLmRlbGl2ZXJ5LW9wdGlvbicpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIHJlc2V0IHRoZSB1dWlkXG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRTdG9yZSA9ICQodGhpcykuY2xvc2VzdCgnLmluc3RvcmUtZGVsaXZlcnknKS5maW5kKCcuc2VsZWN0ZWQtc3RvcmUtYWRkcmVzcycpLmRhdGEoJ3N0b3JlSWQnKTtcbiAgICAgICAgICAgIHNlbGYudXVpZCA9ICQodGhpcykuY2xvc2VzdCgnLmNhcnQtcm93JykuZGF0YSgndXVpZCcpO1xuICAgICAgICAgICAgc2VsZi5zZXREZWxpdmVyeU9wdGlvbigkKHRoaXMpLnZhbCgpLCBzZWxlY3RlZFN0b3JlKTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjYXJ0SW52ZW50b3J5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpLFxuICAgIGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpLFxuICAgIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbnZhciBuZXdMaW5lID0gJ1xcbic7XG52YXIgc3RvcmVUZW1wbGF0ZSA9IGZ1bmN0aW9uIChzdG9yZSwgc2VsZWN0ZWRTdG9yZUlkLCBzZWxlY3RlZFN0b3JlVGV4dCkge1xuICAgIHJldHVybiBbXG4gICAgICAgICc8bGkgY2xhc3M9XCJzdG9yZS10aWxlICcgKyBzdG9yZS5zdG9yZUlkICsgKHN0b3JlLnN0b3JlSWQgPT09IHNlbGVjdGVkU3RvcmVJZCA/ICcgc2VsZWN0ZWQnIDogJycpICsgJ1wiPicsXG4gICAgICAgICcgICAgPHAgY2xhc3M9XCJzdG9yZS1hZGRyZXNzXCI+JyxcbiAgICAgICAgJyAgICAgICAgJyArIHN0b3JlLmFkZHJlc3MxICsgJzxici8+JyxcbiAgICAgICAgJyAgICAgICAgJyArIHN0b3JlLmNpdHkgKyAnLCAnICsgc3RvcmUuc3RhdGVDb2RlICsgJyAnICsgc3RvcmUucG9zdGFsQ29kZSxcbiAgICAgICAgJyAgICA8L3A+JyxcbiAgICAgICAgJyAgICA8cCBjbGFzcz1cInN0b3JlLXN0YXR1c1wiIGRhdGEtc3RhdHVzPVwiJyArIHN0b3JlLnN0YXR1c2NsYXNzICsgJ1wiPicgKyBzdG9yZS5zdGF0dXMgKyAnPC9wPicsXG4gICAgICAgICcgICAgPGJ1dHRvbiBjbGFzcz1cInNlbGVjdC1zdG9yZS1idXR0b25cIiBkYXRhLXN0b3JlLWlkPVwiJyArIHN0b3JlLnN0b3JlSWQgKyAnXCInICtcbiAgICAgICAgKHN0b3JlLnN0YXR1c2NsYXNzICE9PSAnc3RvcmUtaW4tc3RvY2snID8gJ2Rpc2FibGVkPVwiZGlzYWJsZWRcIicgOiAnJykgKyAnPicsXG4gICAgICAgICcgICAgICAgICcgKyAoc3RvcmUuc3RvcmVJZCA9PT0gc2VsZWN0ZWRTdG9yZUlkID8gc2VsZWN0ZWRTdG9yZVRleHQgOiBSZXNvdXJjZXMuU0VMRUNUX1NUT1JFKSxcbiAgICAgICAgJyAgICA8L2J1dHRvbj4nLFxuICAgICAgICAnPC9saT4nXG4gICAgXS5qb2luKG5ld0xpbmUpO1xufTtcblxudmFyIHN0b3JlTGlzdFRlbXBsYXRlID0gZnVuY3Rpb24gKHN0b3Jlcywgc2VsZWN0ZWRTdG9yZUlkLCBzZWxlY3RlZFN0b3JlVGV4dCkge1xuICAgIGlmIChzdG9yZXMgJiYgc3RvcmVzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJzdG9yZS1saXN0LWNvbnRhaW5lclwiPicsXG4gICAgICAgICAgICAnPHVsIGNsYXNzPVwic3RvcmUtbGlzdFwiPicsXG4gICAgICAgICAgICBfLm1hcChzdG9yZXMsIGZ1bmN0aW9uIChzdG9yZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9yZVRlbXBsYXRlKHN0b3JlLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KTtcbiAgICAgICAgICAgIH0pLmpvaW4obmV3TGluZSksXG4gICAgICAgICAgICAnPC91bD4nLFxuICAgICAgICAgICAgJzwvZGl2PicsXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cInN0b3JlLWxpc3QtcGFnaW5hdGlvblwiPicsXG4gICAgICAgICAgICAnPC9kaXY+J1xuICAgICAgICBdLmpvaW4obmV3TGluZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuICc8ZGl2IGNsYXNzPVwibm8tcmVzdWx0c1wiPicgKyBSZXNvdXJjZXMuSU5WQUxJRF9aSVAgKyAnPC9kaXY+JztcbiAgICB9XG59O1xuXG52YXIgemlwUHJvbXB0VGVtcGxhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJzxkaXYgaWQ9XCJwcmVmZXJyZWQtc3RvcmUtcGFuZWxcIj4nLFxuICAgICAgICAnICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGlkPVwidXNlci16aXBcIiBwbGFjZWhvbGRlcj1cIicgKyBSZXNvdXJjZXMuRU5URVJfWklQICsgJ1wiIG5hbWU9XCJ6aXBDb2RlXCIvPicsXG4gICAgICAgICc8L2Rpdj4nXG4gICAgXS5qb2luKG5ld0xpbmUpO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gdGVzdCB3aGV0aGVyIHppcGNvZGUgaXMgdmFsaWQgZm9yIGVpdGhlciBVUyBvciBDYW5hZGFcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgdGhlIHppcGNvZGUgaXMgdmFsaWQgZm9yIGVpdGhlciBjb3VudHJ5LCBmYWxzZSBpZiBpdCdzIGludmFsaWQgZm9yIGJvdGhcbiAqKi9cbnZhciB2YWxpZGF0ZVppcENvZGUgPSBmdW5jdGlvbiAoemlwQ29kZSkge1xuICAgIHZhciByZWdleGVzID0ge1xuICAgICAgICAgICAgY2FuYWRhOiAvXltBQkNFR0hKS0xNTlBSU1RWWFldXFxkW0FCQ0VHSEpLTE1OUFJTVFZXWFlaXSggKT9cXGRbQUJDRUdISktMTU5QUlNUVldYWVpdXFxkJC9pLFxuICAgICAgICAgICAgdXNhOiAvXlxcZHs1fSgtXFxkezR9KT8kL1xuICAgICAgICB9LFxuICAgICAgICB2YWxpZCA9IGZhbHNlO1xuICAgIGlmICghemlwQ29kZSkgeyByZXR1cm47IH1cbiAgICBfLmVhY2gocmVnZXhlcywgZnVuY3Rpb24gKHJlKSB7XG4gICAgICAgIHZhciByZWdleHAgPSBuZXcgUmVnRXhwKHJlKTtcbiAgICAgICAgdmFsaWQgPSByZWdleHAudGVzdCh6aXBDb2RlKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdmFsaWQ7XG59O1xuXG52YXIgc3RvcmVpbnZlbnRvcnkgPSB7XG4gICAgemlwUHJvbXB0OiBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICBodG1sOiB6aXBQcm9tcHRUZW1wbGF0ZSgpLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBSZXNvdXJjZXMuU1RPUkVfTkVBUl9ZT1UsXG4gICAgICAgICAgICAgICAgd2lkdGg6IDUwMCxcbiAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuU0VBUkNILFxuICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHppcENvZGUgPSAkKCcjdXNlci16aXAnKS52YWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZGF0ZVppcENvZGUoemlwQ29kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnNldFVzZXJaaXAoemlwQ29kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHppcENvZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1dLFxuICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnI3VzZXItemlwJykub24oJ2tleXByZXNzJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09PSAxMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyaWdnZXIgdGhlIHNlYXJjaCBidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcudWktZGlhbG9nLWJ1dHRvbnNldCAudWktYnV0dG9uJykudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGdldFN0b3Jlc0ludmVudG9yeTogZnVuY3Rpb24gKHBpZCkge1xuICAgICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5zdG9yZXNJbnZlbnRvcnksIHtcbiAgICAgICAgICAgICAgcGlkOiBwaWQsXG4gICAgICAgICAgICAgIHppcENvZGU6IFVzZXIuemlwXG4gICAgICAgICAgfSksXG4gICAgICAgICAgZGF0YVR5cGU6ICdqc29uJ1xuICAgICAgfSkpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIG9wZW4gdGhlIGRpYWxvZyB0byBzZWxlY3Qgc3RvcmVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLnN0b3Jlc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnNlbGVjdGVkU3RvcmVJZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnNlbGVjdGVkU3RvcmVUZXh0XG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0aW9ucy5jb250aW51ZUNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0aW9ucy5zZWxlY3RTdG9yZUNhbGxiYWNrXG4gICAgICoqL1xuICAgIHNlbGVjdFN0b3JlRGlhbG9nOiBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXG4gICAgICAgICAgICBzdG9yZXMgPSBvcHRpb25zLnN0b3JlcyxcbiAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVJZCA9IG9wdGlvbnMuc2VsZWN0ZWRTdG9yZUlkLFxuICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZVRleHQgPSBvcHRpb25zLnNlbGVjdGVkU3RvcmVUZXh0LFxuICAgICAgICAgICAgc3RvcmVMaXN0ID0gc3RvcmVMaXN0VGVtcGxhdGUoc3RvcmVzLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KTtcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgaHRtbDogc3RvcmVMaXN0LFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBSZXNvdXJjZXMuU0VMRUNUX1NUT1JFICsgJyAtICcgKyBVc2VyLnppcCxcbiAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuQ0hBTkdFX0xPQ0FUSU9OLFxuICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zZXRVc2VyWmlwKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciB0aGUgZXZlbnQgdG8gc3RhcnQgdGhlIHByb2Nlc3MgYWxsIG92ZXIgYWdhaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICQoJy5zZXQtcHJlZmVycmVkLXN0b3JlJykudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuQ09OVElOVUUsXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5jb250aW51ZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5jb250aW51ZUNhbGxiYWNrKHN0b3Jlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1dLFxuICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnLnNlbGVjdC1zdG9yZS1idXR0b24nKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0b3JlSWQgPSAkKHRoaXMpLmRhdGEoJ3N0b3JlSWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBzdG9yZSBpcyBhbHJlYWR5IHNlbGVjdGVkLCBkb24ndCBzZWxlY3QgYWdhaW5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdG9yZUlkID09PSBzZWxlY3RlZFN0b3JlSWQpIHsgcmV0dXJuOyB9XG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcuc3RvcmUtbGlzdCAuc3RvcmUtdGlsZS5zZWxlY3RlZCcpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy5zZWxlY3Qtc3RvcmUtYnV0dG9uJykudGV4dChSZXNvdXJjZXMuU0VMRUNUX1NUT1JFKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykudGV4dChzZWxlY3RlZFN0b3JlVGV4dClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2xvc2VzdCgnLnN0b3JlLXRpbGUnKS5hZGRDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNlbGVjdFN0b3JlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLnNlbGVjdFN0b3JlQ2FsbGJhY2soc3RvcmVJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBzZXRVc2VyWmlwOiBmdW5jdGlvbiAoemlwKSB7XG4gICAgICAgIFVzZXIuemlwID0gemlwO1xuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6IFVybHMuc2V0WmlwQ29kZSxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICB6aXBDb2RlOiB6aXBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBzaGlwcGluZ0xvYWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRjaGVja291dEZvcm0gPSAkKCcuYWRkcmVzcycpO1xuICAgICAgICAkY2hlY2tvdXRGb3JtLm9mZignY2xpY2snKTtcbiAgICAgICAgJGNoZWNrb3V0Rm9ybS5vbignY2xpY2snLCAnaW5wdXRbbmFtZSQ9XCJfc2hpcHBpbmdBZGRyZXNzX2lzR2lmdFwiXScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykucGFyZW50KCkuc2libGluZ3MoJy5naWZ0LW1lc3NhZ2UtdGV4dCcpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nLCAkKCdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdOmNoZWNrZWQnKS52YWwoKSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc3RvcmVpbnZlbnRvcnk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gICAgaW52ZW50b3J5ID0gcmVxdWlyZSgnLi8nKTtcblxudmFyIG5ld0xpbmUgPSAnXFxuJztcbnZhciBwZHBTdG9yZVRlbXBsYXRlID0gZnVuY3Rpb24gKHN0b3JlKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJzxsaSBjbGFzcz1cInN0b3JlLWxpc3QtaXRlbSAnICsgKHN0b3JlLnN0b3JlSWQgPT09IFVzZXIuc3RvcmVJZCA/ICcgc2VsZWN0ZWQnIDogJycpICsgJ1wiPicsXG4gICAgICAgICcgICAgPGRpdiBjbGFzcz1cInN0b3JlLWFkZHJlc3NcIj4nICsgc3RvcmUuYWRkcmVzczEgKyAnLCAnICsgc3RvcmUuY2l0eSArICcgJyArIHN0b3JlLnN0YXRlQ29kZSArXG4gICAgICAgICcgJyArIHN0b3JlLnBvc3RhbENvZGUgKyAnPC9kaXY+JyxcbiAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwic3RvcmUtc3RhdHVzXCIgZGF0YS1zdGF0dXM9XCInICsgc3RvcmUuc3RhdHVzY2xhc3MgKyAnXCI+JyArIHN0b3JlLnN0YXR1cyArICc8L2Rpdj4nLFxuICAgICAgICAnPC9saT4nXG4gICAgXS5qb2luKG5ld0xpbmUpO1xufTtcbnZhciBwZHBTdG9yZXNMaXN0aW5nVGVtcGxhdGUgPSBmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgaWYgKHN0b3JlcyAmJiBzdG9yZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cInN0b3JlLWxpc3QtcGRwLWNvbnRhaW5lclwiPicsXG4gICAgICAgICAgICAoc3RvcmVzLmxlbmd0aCA+IDEgPyAnICAgIDxhIGNsYXNzPVwic3RvcmVzLXRvZ2dsZSBjb2xsYXBzZWRcIiBocmVmPVwiI1wiPicgKyBSZXNvdXJjZXMuU0VFX01PUkUgKyAnPC9hPicgOiAnJyksXG4gICAgICAgICAgICAnICAgIDx1bCBjbGFzcz1cInN0b3JlLWxpc3QtcGRwXCI+JyxcbiAgICAgICAgICAgIF8ubWFwKHN0b3JlcywgcGRwU3RvcmVUZW1wbGF0ZSkuam9pbihuZXdMaW5lKSxcbiAgICAgICAgICAgICcgICAgPC91bD4nLFxuICAgICAgICAgICAgJzwvZGl2PidcbiAgICAgICAgXS5qb2luKG5ld0xpbmUpO1xuICAgIH1cbn07XG5cbnZhciBzdG9yZXNMaXN0aW5nID0gZnVuY3Rpb24gKHN0b3Jlcykge1xuICAgIC8vIGxpc3QgYWxsIHN0b3JlcyBvbiBQRFAgcGFnZVxuICAgIGlmICgkKCcuc3RvcmUtbGlzdC1wZHAtY29udGFpbmVyJykubGVuZ3RoKSB7XG4gICAgICAgICQoJy5zdG9yZS1saXN0LXBkcC1jb250YWluZXInKS5yZW1vdmUoKTtcbiAgICB9XG4gICAgJCgnLmF2YWlsYWJpbGl0eS1yZXN1bHRzJykuYXBwZW5kKHBkcFN0b3Jlc0xpc3RpbmdUZW1wbGF0ZShzdG9yZXMpKTtcbn07XG5cbnZhciBwcm9kdWN0SW52ZW50b3J5ID0ge1xuICAgIHNldFByZWZlcnJlZFN0b3JlOiBmdW5jdGlvbiAoc3RvcmVJZCkge1xuICAgICAgICBVc2VyLnN0b3JlSWQgPSBzdG9yZUlkO1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLnNldFByZWZlcnJlZFN0b3JlLFxuICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgZGF0YToge3N0b3JlSWQ6IHN0b3JlSWR9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcHJvZHVjdFNlbGVjdFN0b3JlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgaW52ZW50b3J5LmdldFN0b3Jlc0ludmVudG9yeSh0aGlzLnBpZCkudGhlbihmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgICAgICAgICBpbnZlbnRvcnkuc2VsZWN0U3RvcmVEaWFsb2coe1xuICAgICAgICAgICAgICAgIHN0b3Jlczogc3RvcmVzLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVJZDogVXNlci5zdG9yZUlkLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVUZXh0OiBSZXNvdXJjZXMuUFJFRkVSUkVEX1NUT1JFLFxuICAgICAgICAgICAgICAgIGNvbnRpbnVlQ2FsbGJhY2s6IHN0b3Jlc0xpc3RpbmcsXG4gICAgICAgICAgICAgICAgc2VsZWN0U3RvcmVDYWxsYmFjazogc2VsZi5zZXRQcmVmZXJyZWRTdG9yZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLmRvbmUoKTtcbiAgICB9LFxuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRhdmFpbGFiaWxpdHlDb250YWluZXIgPSAkKCcuYXZhaWxhYmlsaXR5LXJlc3VsdHMnKSxcbiAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuICAgICAgICB0aGlzLnBpZCA9ICQoJ2lucHV0W25hbWU9XCJwaWRcIl0nKS52YWwoKTtcblxuICAgICAgICAkKCcjcHJvZHVjdC1jb250ZW50IC5zZXQtcHJlZmVycmVkLXN0b3JlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGlmICghVXNlci56aXApIHtcbiAgICAgICAgICAgICAgICBpbnZlbnRvcnkuemlwUHJvbXB0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcm9kdWN0U2VsZWN0U3RvcmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5wcm9kdWN0U2VsZWN0U3RvcmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCRhdmFpbGFiaWxpdHlDb250YWluZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoVXNlci5zdG9yZUlkKSB7XG4gICAgICAgICAgICAgICAgaW52ZW50b3J5LmdldFN0b3Jlc0ludmVudG9yeSh0aGlzLnBpZCkudGhlbihzdG9yZXNMaXN0aW5nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2VlIG1vcmUgb3IgbGVzcyBzdG9yZXMgaW4gdGhlIGxpc3RpbmdcbiAgICAgICAgICAgICRhdmFpbGFiaWxpdHlDb250YWluZXIub24oJ2NsaWNrJywgJy5zdG9yZXMtdG9nZ2xlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgJCgnLnN0b3JlLWxpc3QtcGRwIC5zdG9yZS1saXN0LWl0ZW0nKS50b2dnbGVDbGFzcygndmlzaWJsZScpO1xuICAgICAgICAgICAgICAgIGlmICgkKHRoaXMpLmhhc0NsYXNzKCdjb2xsYXBzZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRleHQoUmVzb3VyY2VzLlNFRV9MRVNTKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRleHQoUmVzb3VyY2VzLlNFRV9NT1JFKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnY29sbGFwc2VkJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvZHVjdEludmVudG9yeTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHJlbmRlciA9IGZ1bmN0aW9uKHN0eWxlQ291bnRDYWNoZSkge1xuXHRpZiAoc3R5bGVDb3VudENhY2hlKSB7XG5cdFx0JCgnW2RhdGEtbGluay1jYXRlZ29yeV0nKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGNhdGVnb3J5SWQgPSAkKHRoaXMpLmRhdGEoJ2xpbmstY2F0ZWdvcnknKTtcblx0XHRcdFxuXHRcdFx0aWYgKGNhdGVnb3J5SWQpIHtcblx0XHRcdFx0dmFyIGNhdGVnb3J5UmVmaW5lbWVudHMgPSBzdHlsZUNvdW50Q2FjaGUuQ2F0ZWdvcnlMaW5rc1tjYXRlZ29yeUlkXTtcblx0XHRcdFx0aWYgKGNhdGVnb3J5UmVmaW5lbWVudHMgJiYgY2F0ZWdvcnlSZWZpbmVtZW50cy5jb3VudCA+IDApIHtcblx0XHRcdFx0XHR2YXIgJHN0eWxlQ291bnQgPSAkKHRoaXMpLmZpbmQoJy5zdHlsZS1udW1iZXInKTsgXG5cdFx0XHRcdFx0dmFyIG1lc3NhZ2VUZW1wbGF0ZSA9IGNhdGVnb3J5UmVmaW5lbWVudHMuY291bnQgPiAxID8gUmVzb3VyY2VzLlNUWUxFX1BMVVJBTCA6IFJlc291cmNlcy5TVFlMRV9TSU5HVUxBUjtcblx0XHRcdFx0XHR2YXIgbWVzc2FnZSA9IG1lc3NhZ2VUZW1wbGF0ZS5yZXBsYWNlKCd7MH0nLCBjYXRlZ29yeVJlZmluZW1lbnRzLmNvdW50KTtcblx0XHRcdFx0XHQkc3R5bGVDb3VudC5hZGRDbGFzcygndmlzaWJsZScpLnRleHQobWVzc2FnZSk7XG5cblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cdFxuXHRcdFx0fVxuXG5cdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJ2xpJykucmVtb3ZlKCk7XG5cdFx0fSk7XG5cblx0XHQkKCdbZGF0YS1saW5rLWF0dHJpYnV0ZS1pZF0nKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGNhdGVnb3J5SWQgPSAkKHRoaXMpLmRhdGEoJ2xpbmstY2dpZCcpLFxuXHRcdFx0cmVmaW5lbWVudElkID0gJCh0aGlzKS5kYXRhKCdsaW5rLWF0dHJpYnV0ZS1pZCcpLFxuXHRcdFx0cmVmaW5lbWVudFZhbHVlID0gJCh0aGlzKS5kYXRhKCdsaW5rLWF0dHJpYnV0ZS12YWx1ZScpO1xuXG5cdFx0XHR2YXIgY2F0ZWdvcnlSZWZpbmVtZW50cyA9IHN0eWxlQ291bnRDYWNoZS5SZWZpbmVtZW50TGlua3NbY2F0ZWdvcnlJZF07XG5cdFx0XHRpZiAoY2F0ZWdvcnlSZWZpbmVtZW50cykge1xuXHRcdFx0XHR2YXIgYXR0cmlidXRlUmVmaW5lbWVudHMgPSBjYXRlZ29yeVJlZmluZW1lbnRzW3JlZmluZW1lbnRJZF07XG5cdFx0XHRcdGlmIChhdHRyaWJ1dGVSZWZpbmVtZW50cykge1xuXHRcdFx0XHRcdHZhciBhdHRyaWJ1dGVSZWZpbmVtZW50ID0gYXR0cmlidXRlUmVmaW5lbWVudHNbcmVmaW5lbWVudFZhbHVlXTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiAoYXR0cmlidXRlUmVmaW5lbWVudCAmJiBhdHRyaWJ1dGVSZWZpbmVtZW50LmNvdW50ID4gMCkge1xuXHRcdFx0XHRcdFx0dmFyICRzdHlsZUNvdW50ID0gJCh0aGlzKS5maW5kKCcuc3R5bGUtbnVtYmVyJyk7XG5cdFx0XHRcdFx0XHR2YXIgbWVzc2FnZVRlbXBsYXRlID0gYXR0cmlidXRlUmVmaW5lbWVudC5jb3VudCA+IDEgPyBSZXNvdXJjZXMuU1RZTEVfUExVUkFMIDogUmVzb3VyY2VzLlNUWUxFX1NJTkdVTEFSO1xuXHRcdFx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBtZXNzYWdlVGVtcGxhdGUucmVwbGFjZSgnezB9JywgYXR0cmlidXRlUmVmaW5lbWVudC5jb3VudCk7XG5cdFx0XHRcdFx0XHQkc3R5bGVDb3VudC5hZGRDbGFzcygndmlzaWJsZScpLnRleHQobWVzc2FnZSk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSAgICAgICAgIFx0XHRcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JCh0aGlzKS5jbG9zZXN0KCdsaScpLnJlbW92ZSgpO1xuXHRcdH0pO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzLnJlbmRlciA9IHJlbmRlcjsiLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBUTFMgYW5kIGRpc3BsYXlzIGEgd2FybmluZyBpZiBhcHByb3ByaWF0ZVxuICogQGZ1bmN0aW9uIGdldFVzZXJBZ2VudCBDaGVja3MgdGhlIFRMUyBhbmQgZGlzcGxheXMgYSB3YXJuaW5nIGlmIGFwcHJvcHJpYXRlXG4gKiovXG5mdW5jdGlvbiBnZXRVc2VyQWdlbnQoKSB7XG4gICAgLy8gVXNlIGFuIGV4dGVybmFsIHNlcnZpY2UgdG8gY2hlY2sgdGhlIFRMUyBvZiB0aGUgYnJvd3NlclxuICAgIC8vIE5PVEU6IHRoaXMgaW1wbGVtZW50YXRpb24gdXNlcyBodHRwczovL3d3dy5ob3dzbXlzc2wuY29tXG4gICAgLy8gICAgIHlvdSBtYXkgYWxzbyB3aXNoIHRvIGNvbnNpZGVyIHRoZSBBUEkgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3LnNzbGxhYnMuY29tL3Byb2plY3RzL3NzbGxhYnMtYXBpcy9pbmRleC5odG1sXG4gICAgdmFyIHVybCA9ICdodHRwczovL3d3dy5ob3dzbXlzc2wuY29tL2EvY2hlY2snO1xuICAgIHZhciBjb29raWVOYW1lID0gJ2R3X1RMU1dhcm5pbmcnO1xuICAgIHZhciBjb29raWVWYWx1ZSA9IGdldENvb2tpZShjb29raWVOYW1lKTtcblxuICAgIC8vIFRlc3QgdG8gc2VlIGlmIHRoaXMgYnJvd3NlciBoYXMgYWxyZWFkeSBiZWVuIGZsYWdnZWQgYnkgbG9va2luZyBhdCBpdHMgY29va2llc1xuICAgIGlmICghY29va2llVmFsdWUpIHtcbiAgICAgICAgZ2V0VExTKHVybCwgZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzaG93V2FybmluZyhtZXNzYWdlWzBdKTtcblxuICAgICAgICAgICAgICAgIC8vIHRoZSBicm93c2VyIGlzIGJhZCAtIHNldCB0aGUgY29va2llIHRvIHRydWUgKGZvciAxNSBtaW51dGVzKVxuICAgICAgICAgICAgICAgIHNldENvb2tpZShjb29raWVOYW1lLCAndHJ1ZScsIDE1KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZWxzZSB0aGUgYnJvd3NlciBpcyBnb29kLCBzZXQgdGhlIGNvb2tpZSB0byBmYWxzZSAoZm9yIDMwIGRheXMpIHNvIHdlIGRvbid0IGNoZWNrIGFnYWluXG4gICAgICAgICAgICAgICAgc2V0Q29va2llKGNvb2tpZU5hbWUsICdmYWxzZScsIDYwICogMjQgKiAzMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoY29va2llVmFsdWUgPT09ICd0cnVlJykge1xuICAgICAgICAvLyBpZiB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGlzIGlzIGFuIGludmFsaWQgYnJvd3Nlciwgc2hvdyB0aGUgd2FybmluZ1xuICAgICAgICBzaG93V2FybmluZyhSZXNvdXJjZXMuVExTX1dBUk5JTkcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxscyBvdXQgdG8gdGhlIFRMUyBzZXJ2aWNlIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgd2l0aCBhIG1lc3NhZ2UgKGlmIG5lY2Vzc2FyeSlcbiAqIEBmdW5jdGlvbiBnZXRUTFNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gVVJMIG9mIGV4dGVybmFsIFRMUy1jaGVja2luZyBBUElcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gZnVuY3Rpb24gdG8gY2FsbCB3aXRoIHJlc3BvbnNlXG4gKiovXG5mdW5jdGlvbiBnZXRUTFModXJsLCBjYWxsYmFjaykge1xuICAgIHZhciBtZXNzYWdlID0gW107XG5cbiAgICAvLyBGaXJzdCwgc2VlIGlmIHRoZSBicm93c2VyIGlzIGFtb25nIHRoZSBzdXNwZWN0IGJyb3dzZXJzIHRvIHNlZSBpZiBhIFRMUyBjaGVjayBpcyBuZWNlc3NhcnlcbiAgICB2YXIgdXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGlzIGxpc3QgZGVyaXZlZCBmcm9tIGh0dHBzOi8vd3d3LnNzbGxhYnMuY29tL3NzbHRlc3QvY2xpZW50cy5odG1sICoqL1xuICAgIHZhciBiYWRCcm93c2VycyA9IFsnTVNJRSA2LjAnLCdNU0lFIDcuMCcsJ01TSUUgOC4wJywnTVNJRSA5LjAnLCdNU0lFIDEwLjAnLFxuICAgICAgICAgICAgICAgICAgICAgICAnQW5kcm9pZCAyLjMuNycsICdBbmRyb2lkIDQuMC40JywgJ0FuZHJvaWQgNC4xLjEnLCAnQW5kcm9pZCA0LjIuMicsICdBbmRyb2lkIDQuMycsXG4gICAgICAgICAgICAgICAgICAgICAgICdTYWZhcmkgNS4xLjkgLyBPUyBYIDEwLjYuOCcsICdTYWZhcmkgNi4wLjQgLyBPUyBYIDEwLjguNCAnXTtcbiAgICBmdW5jdGlvbiBjaGVja1RMU0xldmVsKGRhdGEpIHtcbiAgICAgICAgLy8gSWYgd2UgY2FuIGRldGVybWluZSB0aGUgVExTIGxldmVsLCBjaGVjayB0byBzZWUgaWYgaXQncyBsZXNzIHRoYW4gMS4yXG4gICAgICAgIGlmIChwYXJzZUZsb2F0KGRhdGEudGxzX3ZlcnNpb24uc3BsaXQoJyAnKVsxXSkgPCAxLjEpIHtcbiAgICAgICAgICAgIG1lc3NhZ2UucHVzaChSZXNvdXJjZXMuVExTX1dBUk5JTkcpO1xuICAgICAgICAgICAgY2FsbGJhY2sobWVzc2FnZSk7XG5cbiAgICAgICAgICAgIC8vSWYgeW91IHdhbnQgdG8gdHJhY2sgc3RhdGlzdGljcyBvbiBiYWQgVExTIGhpdHMsIGluY2x1ZGUgdGhpcyBjYWxsXG4gICAgICAgICAgICAkLmFqYXgoe3VybDogVXJscy5UTFNCYWRUTFN9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlcG9ydEJhZEJyb3dzZXIgKCkge1xuICAgICAgICAvLyBJZiB0aGUgVExTIGxldmVsIGNhbm5vdCBiZSBkZXRlcm1pbmVkIGp1c3QgcmVwb3J0IHRoYXQgdGhpcyBicm93c2VyIGlzIHN1c3BlY3RcbiAgICAgICAgbWVzc2FnZS5wdXNoKFJlc291cmNlcy5UTFNfV0FSTklORyk7XG4gICAgICAgIGNhbGxiYWNrKG1lc3NhZ2UpO1xuXG4gICAgICAgIC8vSWYgeW91IHdhbnQgdG8gdHJhY2sgc3RhdGlzdGljcyBvbiBkZXByZWNhdGVkIGJyb3dzZXJzLCBpbmNsdWRlIHRoaXMgY2FsbFxuICAgICAgICAkLmFqYXgoe3VybDogVXJscy5UTFNCYWRCcm93c2VyfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiYWRCcm93c2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodXNlckFnZW50Lm1hdGNoKGJhZEJyb3dzZXJzW2ldKSkge1xuICAgICAgICAgICAgLy8gSXQncyBhIHN1c3BlY3QgYnJvd3NlciwgbGV0J3Mgc2VlIHdoYXQgaXQncyBUTFMgbGV2ZWwgaXNcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiB1cmxcbiAgICAgICAgICAgIH0pLmRvbmUoY2hlY2tUTFNMZXZlbCkuZmFpbChyZXBvcnRCYWRCcm93c2VyKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEZvciB0ZXN0aW5nIHB1cnBvc2VzLCB1bmNvbW1lbnQgdGhpcyBibG9ja1xuICAgICAgICBtZXNzYWdlLnB1c2goUmVzb3VyY2VzLlRMU19XQVJOSU5HKTtcbiAgICAqKi9cbiAgICBjYWxsYmFjayhtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb24gc2hvd1dhcm5pbmcgdHVybnMgb24gdGhlIGJyb3dzZXItY29tcGF0aWJpbGl0eS1hbGVydCBhbmQgc2V0cyB0aGUgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gdGhlIG1lc3NhZ2UgdGhhdCB3aWxsIGJlIHNob3duIHVwb24gZGV0ZWN0aW9uIG9mIGEgYmFkIGJyb3dzZXJcbiAqKi9cbmZ1bmN0aW9uIHNob3dXYXJuaW5nKG1lc3NhZ2UpIHtcbiAgICAkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnYnJvd3Nlci1jb21wYXRpYmlsaXR5LWFsZXJ0JykuYXBwZW5kKCQoJzxwLz4nKS5hZGRDbGFzcygnYnJvd3Nlci1lcnJvcicpLmh0bWwobWVzc2FnZSkpLmFwcGVuZFRvKCcjYnJvd3Nlci1jaGVjaycpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBnZXRDb29raWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGNvb2tpZSBuYW1lXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB2YWx1ZSAtIHRoZSB2YWx1ZSBvZiB0aGUgY29va2llIGlmIGZvdW5kLCBudWxsIG90aGVyd2lzZVxuICoqL1xuZnVuY3Rpb24gZ2V0Q29va2llKGtleSkge1xuICAgIHZhciBjb29raWVzID0gZG9jdW1lbnQuY29va2llLnNwbGl0KCc7Jyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb29raWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0b2tlbnMgPSBjb29raWVzW2ldLnNwbGl0KCc9Jyk7XG4gICAgICAgIHZhciBjb29raWVLZXkgPSB0b2tlbnNbMF0udHJpbSgpO1xuICAgICAgICBpZiAoY29va2llS2V5ID09PSBrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiB0b2tlbnNbMV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBzZXRDb29raWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGNvb2tpZSBuYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgY29va2llIHZhbHVlXG4gKiBAcGFyYW0ge2ludGVnZXJ9IG1pbnV0ZXMgLSBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgdG8gZXhwaXJlIHRoZSBjb29raWVcbiAqKi9cbmZ1bmN0aW9uIHNldENvb2tpZSAoa2V5LCB2YWx1ZSwgbWludXRlcykge1xuICAgIHZhciBkYXRlID0gbmV3IERhdGUoKTtcbiAgICBkYXRlLnNldFRpbWUoZGF0ZSArIChtaW51dGVzICogNjAgKiAxMDAwKSk7XG5cbiAgICBkb2N1bWVudC5jb29raWUgPSBrZXkgKyAnPScgKyB2YWx1ZSArICc7IGV4cGlyZXM9JyArIGRhdGUudG9HTVRTdHJpbmcoKSArICc7IHBhdGg9Lyc7XG59XG5cbi8qKlxuICogRXhwb3J0IHRoZSBnZXRVc2VyQWdlbnQgZnVuY3Rpb25cbiAqL1xuXG5leHBvcnRzLmdldFVzZXJBZ2VudCA9IGdldFVzZXJBZ2VudDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgdG9vbHRpcC1jb250ZW50IGFuZCBsYXlvdXRcbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24ob3B0aW9uc1BhcmFtZXRlciwgJGNvbnRhaW5lclBhcmFtZXRlcikge1xuXHR2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgICAgIGl0ZW1zOiAnLnRvb2x0aXAnLFxuICAgICAgICB0cmFjazogdHJ1ZSxcbiAgICAgICAgY29udGVudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICQodGhpcykuZmluZCgnLnRvb2x0aXAtY29udGVudCcpLmh0bWwoKTtcbiAgICAgICAgfVxuICAgIH07XG5cdFxuXHR2YXIgb3B0aW9ucztcblx0aWYgKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0XHRvcHRpb25zID0gJC5leHRlbmQoZGVmYXVsdE9wdGlvbnMsIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXHR9IGVsc2Uge1xuXHRcdG9wdGlvbnMgPSBkZWZhdWx0T3B0aW9ucztcblx0fVxuXHRcblx0dmFyICRjb250YWluZXI7XG5cdGlmICgkY29udGFpbmVyUGFyYW1ldGVyKSB7XG5cdFx0JGNvbnRhaW5lciA9ICRjb250YWluZXJQYXJhbWV0ZXI7XG5cdH0gZWxzZSB7XG5cdFx0JGNvbnRhaW5lciA9ICQoZG9jdW1lbnQpO1xuXHR9XG5cdFxuICAgICRjb250YWluZXIudG9vbHRpcChvcHRpb25zKTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJy50b29sdGlwJykub24oJ2NsaWNrJywgJy50b29sdGlwJywgZnVuY3Rpb24oZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnLnNoYXJlLWxpbmsnKS5vbignY2xpY2snLCAnLnNoYXJlLWxpbmsnLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHRhcmdldCA9ICQodGhpcykuZGF0YSgndGFyZ2V0Jyk7XG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICAgICQodGFyZ2V0KS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcbnZhciBDcmVkaXRDYXJkQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9QYXltZW50SW5zdHJ1bWVudENvbnN0YW50cycpLkNyZWRpdENhcmRzO1xuXG52YXIgdXRpbCA9IHtcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gYXBwZW5kcyB0aGUgcGFyYW1ldGVyIHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIHZhbHVlIHRvIHRoZSBnaXZlbiB1cmwgYW5kIHJldHVybnMgdGhlIGNoYW5nZWQgdXJsXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybCB0aGUgdXJsIHRvIHdoaWNoIHRoZSBwYXJhbWV0ZXIgd2lsbCBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgdGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBhcHBlbmRQYXJhbVRvVVJMOiBmdW5jdGlvbiAodXJsLCBuYW1lLCB2YWx1ZSkge1xuICAgICAgICAvLyBxdWl0IGlmIHRoZSBwYXJhbSBhbHJlYWR5IGV4aXN0c1xuICAgICAgICBpZiAodXJsLmluZGV4T2YobmFtZSArICc9JykgIT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzZXBhcmF0b3IgPSB1cmwuaW5kZXhPZignPycpICE9PSAtMSA/ICcmJyA6ICc/Jztcblx0XHR2YXIgYW5jaG9yID0gJyc7XG5cdFx0aWYgKHVybC5pbmRleE9mKCcjJykgPiAtMSkge1xuICAgICAgICAgICAgdmFyIHVybEFuZEFuY2hvciA9IHVybC5zcGxpdCgnIycpO1xuXHRcdFx0dXJsID0gdXJsQW5kQW5jaG9yWzBdO1xuXHRcdFx0YW5jaG9yID0gJyMnICsgdXJsQW5kQW5jaG9yWzFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cmwgKyBzZXBhcmF0b3IgKyBuYW1lICsgKHZhbHVlID8gJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSA6ICcnKSArIGFuY2hvcjtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIHJlbW92ZSB0aGUgcGFyYW1ldGVyIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgZ2l2ZW4gdXJsIGFuZCByZXR1cm5zIHRoZSBjaGFuZ2VkIHVybFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgdGhlIHVybCBmcm9tIHdoaWNoIHRoZSBwYXJhbWV0ZXIgd2lsbCBiZSByZW1vdmVkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgcGFyYW1ldGVyIHRoYXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdXJsXG4gICAgICovXG4gICAgcmVtb3ZlUGFyYW1Gcm9tVVJMOiBmdW5jdGlvbiAodXJsLCBuYW1lKSB7XG4gICAgICAgIGlmICh1cmwuaW5kZXhPZignPycpID09PSAtMSB8fCB1cmwuaW5kZXhPZihuYW1lICsgJz0nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhhc2g7XG4gICAgICAgIHZhciBwYXJhbXM7XG4gICAgICAgIHZhciBkb21haW4gPSB1cmwuc3BsaXQoJz8nKVswXTtcbiAgICAgICAgdmFyIHBhcmFtVXJsID0gdXJsLnNwbGl0KCc/JylbMV07XG4gICAgICAgIHZhciBuZXdQYXJhbXMgPSBbXTtcbiAgICAgICAgLy8gaWYgdGhlcmUgaXMgYSBoYXNoIGF0IHRoZSBlbmQsIHN0b3JlIHRoZSBoYXNoXG4gICAgICAgIGlmIChwYXJhbVVybC5pbmRleE9mKCcjJykgPiAtMSkge1xuICAgICAgICAgICAgaGFzaCA9IHBhcmFtVXJsLnNwbGl0KCcjJylbMV0gfHwgJyc7XG4gICAgICAgICAgICBwYXJhbVVybCA9IHBhcmFtVXJsLnNwbGl0KCcjJylbMF07XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1zID0gcGFyYW1Vcmwuc3BsaXQoJyYnKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIC8vIHB1dCBiYWNrIHBhcmFtIHRvIG5ld1BhcmFtcyBhcnJheSBpZiBpdCBpcyBub3QgdGhlIG9uZSB0byBiZSByZW1vdmVkXG4gICAgICAgICAgICBpZiAocGFyYW1zW2ldLnNwbGl0KCc9JylbMF0gIT09IG5hbWUpIHtcbiAgICAgICAgICAgICAgICBuZXdQYXJhbXMucHVzaChwYXJhbXNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkb21haW4gKyAnPycgKyBuZXdQYXJhbXMuam9pbignJicpICsgKGhhc2ggPyAnIycgKyBoYXNoIDogJycpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gYXBwZW5kcyB0aGUgcGFyYW1ldGVycyB0byB0aGUgZ2l2ZW4gdXJsIGFuZCByZXR1cm5zIHRoZSBjaGFuZ2VkIHVybFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgdGhlIHVybCB0byB3aGljaCB0aGUgcGFyYW1ldGVycyB3aWxsIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICAgICAqL1xuICAgIGFwcGVuZFBhcmFtc1RvVXJsOiBmdW5jdGlvbiAodXJsLCBwYXJhbXMpIHtcbiAgICAgICAgdmFyIF91cmwgPSB1cmw7XG4gICAgICAgIF8uZWFjaChwYXJhbXMsIGZ1bmN0aW9uICh2YWx1ZSwgbmFtZSkge1xuICAgICAgICAgICAgX3VybCA9IHRoaXMuYXBwZW5kUGFyYW1Ub1VSTChfdXJsLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIHJldHVybiBfdXJsO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIGV4dHJhY3QgdGhlIHF1ZXJ5IHN0cmluZyBmcm9tIFVSTFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgdGhlIHVybCB0byBleHRyYSBxdWVyeSBzdHJpbmcgZnJvbVxuICAgICAqKi9cbiAgICBnZXRRdWVyeVN0cmluZzogZnVuY3Rpb24gKHVybCkge1xuICAgICAgICB2YXIgcXM7XG4gICAgICAgIGlmICghXy5pc1N0cmluZyh1cmwpKSB7IHJldHVybjsgfVxuICAgICAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgYS5ocmVmID0gdXJsO1xuICAgICAgICBpZiAoYS5zZWFyY2gpIHtcbiAgICAgICAgICAgIHFzID0gYS5zZWFyY2guc3Vic3RyKDEpOyAvLyByZW1vdmUgdGhlIGxlYWRpbmcgP1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBxcztcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGVsZW1lbnRJblZpZXdwb3J0OiBmdW5jdGlvbiAoZWwsIG9mZnNldFRvVG9wKSB7XG4gICAgICAgIHZhciB0b3AgPSBlbC5vZmZzZXRUb3AsXG4gICAgICAgICAgICBsZWZ0ID0gZWwub2Zmc2V0TGVmdCxcbiAgICAgICAgICAgIHdpZHRoID0gZWwub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQgPSBlbC5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgd2hpbGUgKGVsLm9mZnNldFBhcmVudCkge1xuICAgICAgICAgICAgZWwgPSBlbC5vZmZzZXRQYXJlbnQ7XG4gICAgICAgICAgICB0b3AgKz0gZWwub2Zmc2V0VG9wO1xuICAgICAgICAgICAgbGVmdCArPSBlbC5vZmZzZXRMZWZ0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZihvZmZzZXRUb1RvcCkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0b3AgLT0gb2Zmc2V0VG9Ub3A7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAod2luZG93LnBhZ2VYT2Zmc2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHRvcCA8ICh3aW5kb3cucGFnZVlPZmZzZXQgKyB3aW5kb3cuaW5uZXJIZWlnaHQpICYmXG4gICAgICAgICAgICAgICAgbGVmdCA8ICh3aW5kb3cucGFnZVhPZmZzZXQgKyB3aW5kb3cuaW5uZXJXaWR0aCkgJiZcbiAgICAgICAgICAgICAgICAodG9wICsgaGVpZ2h0KSA+IHdpbmRvdy5wYWdlWU9mZnNldCAmJlxuICAgICAgICAgICAgICAgIChsZWZ0ICsgd2lkdGgpID4gd2luZG93LnBhZ2VYT2Zmc2V0XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRvY3VtZW50LmNvbXBhdE1vZGUgPT09ICdDU1MxQ29tcGF0Jykge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB0b3AgPCAod2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgKyB3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCkgJiZcbiAgICAgICAgICAgICAgICBsZWZ0IDwgKHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCArIHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgpICYmXG4gICAgICAgICAgICAgICAgKHRvcCArIGhlaWdodCkgPiB3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCAmJlxuICAgICAgICAgICAgICAgIChsZWZ0ICsgd2lkdGgpID4gd2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBBcHBlbmRzIHRoZSBwYXJhbWV0ZXIgJ2Zvcm1hdD1hamF4JyB0byBhIGdpdmVuIHBhdGhcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcGF0aCB0aGUgcmVsYXRpdmUgcGF0aFxuICAgICAqL1xuICAgIGFqYXhVcmw6IGZ1bmN0aW9uIChwYXRoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFwcGVuZFBhcmFtVG9VUkwocGF0aCwgJ2Zvcm1hdCcsICdhamF4Jyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAgICAgKi9cbiAgICB0b0Fic29sdXRlVXJsOiBmdW5jdGlvbiAodXJsKSB7XG4gICAgICAgIGlmICh1cmwuaW5kZXhPZignaHR0cCcpICE9PSAwICYmIHVybC5jaGFyQXQoMCkgIT09ICcvJykge1xuICAgICAgICAgICAgdXJsID0gJy8nICsgdXJsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gTG9hZHMgY3NzIGR5bmFtaWNhbGx5IGZyb20gZ2l2ZW4gdXJsc1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IHVybHMgQXJyYXkgb2YgdXJscyBmcm9tIHdoaWNoIGNzcyB3aWxsIGJlIGR5bmFtaWNhbGx5IGxvYWRlZC5cbiAgICAgKi9cbiAgICBsb2FkRHluYW1pY0NzczogZnVuY3Rpb24gKHVybHMpIHtcbiAgICAgICAgdmFyIGksIGxlbiA9IHVybHMubGVuZ3RoO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkQ3NzRmlsZXMucHVzaCh0aGlzLmxvYWRDc3NGaWxlKHVybHNbaV0pKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gTG9hZHMgY3NzIGZpbGUgZHluYW1pY2FsbHkgZnJvbSBnaXZlbiB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIFRoZSB1cmwgZnJvbSB3aGljaCBjc3MgZmlsZSB3aWxsIGJlIGR5bmFtaWNhbGx5IGxvYWRlZC5cbiAgICAgKi9cbiAgICBsb2FkQ3NzRmlsZTogZnVuY3Rpb24gKHVybCkge1xuICAgICAgICByZXR1cm4gJCgnPGxpbmsvPicpLmFwcGVuZFRvKCQoJ2hlYWQnKSkuYXR0cih7XG4gICAgICAgICAgICB0eXBlOiAndGV4dC9jc3MnLFxuICAgICAgICAgICAgcmVsOiAnc3R5bGVzaGVldCdcbiAgICAgICAgfSkuYXR0cignaHJlZicsIHVybCk7IC8vIGZvciBpLmUuIDw5LCBocmVmIG11c3QgYmUgYWRkZWQgYWZ0ZXIgbGluayBoYXMgYmVlbiBhcHBlbmRlZCB0byBoZWFkXG4gICAgfSxcbiAgICAvLyBhcnJheSB0byBrZWVwIHRyYWNrIG9mIHRoZSBkeW5hbWljYWxseSBsb2FkZWQgQ1NTIGZpbGVzXG4gICAgbG9hZGVkQ3NzRmlsZXM6IFtdLFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFJlbW92ZXMgYWxsIGNzcyBmaWxlcyB3aGljaCB3ZXJlIGR5bmFtaWNhbGx5IGxvYWRlZFxuICAgICAqL1xuICAgIGNsZWFyRHluYW1pY0NzczogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaSA9IHRoaXMubG9hZGVkQ3NzRmlsZXMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoMCA+IGktLSkge1xuICAgICAgICAgICAgJCh0aGlzLmxvYWRlZENzc0ZpbGVzW2ldKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxvYWRlZENzc0ZpbGVzID0gW107XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gRXh0cmFjdHMgYWxsIHBhcmFtZXRlcnMgZnJvbSBhIGdpdmVuIHF1ZXJ5IHN0cmluZyBpbnRvIGFuIG9iamVjdFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBxcyBUaGUgcXVlcnkgc3RyaW5nIGZyb20gd2hpY2ggdGhlIHBhcmFtZXRlcnMgd2lsbCBiZSBleHRyYWN0ZWRcbiAgICAgKi9cbiAgICBnZXRRdWVyeVN0cmluZ1BhcmFtczogZnVuY3Rpb24gKHFzKSB7XG4gICAgICAgIGlmICghcXMgfHwgcXMubGVuZ3RoID09PSAwKSB7IHJldHVybiB7fTsgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge30sXG4gICAgICAgICAgICB1bmVzY2FwZWRRUyA9IHVuZXNjYXBlKHFzKTtcbiAgICAgICAgLy8gVXNlIHRoZSBTdHJpbmc6OnJlcGxhY2UgbWV0aG9kIHRvIGl0ZXJhdGUgb3ZlciBlYWNoXG4gICAgICAgIC8vIG5hbWUtdmFsdWUgcGFpciBpbiB0aGUgc3RyaW5nLlxuICAgICAgICB1bmVzY2FwZWRRUy5yZXBsYWNlKG5ldyBSZWdFeHAoJyhbXj89Jl0rKSg9KFteJl0qKSk/JywgJ2cnKSxcbiAgICAgICAgICAgIGZ1bmN0aW9uICgkMCwgJDEsICQyLCAkMykge1xuICAgICAgICAgICAgICAgIHBhcmFtc1skMV0gPSAkMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICB9LFxuXG4gICAgZmlsbEFkZHJlc3NGaWVsZHM6IGZ1bmN0aW9uIChhZGRyZXNzLCAkZm9ybSkge1xuICAgICAgICBmb3IgKHZhciBmaWVsZCBpbiBhZGRyZXNzKSB7XG4gICAgICAgICAgICBpZiAoZmllbGQgPT09ICdVVUlEJyB8fCBmaWVsZCA9PT0gJ2tleScpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHRoZSBrZXkgaW4gYWRkcmVzcyBvYmplY3QgZW5kcyB3aXRoICdDb2RlJywgcmVtb3ZlIHRoYXQgc3VmZml4XG4gICAgICAgICAgICAvLyBrZXlzIHRoYXQgZW5kcyB3aXRoICdDb2RlJyBhcmUgcG9zdGFsQ29kZSwgc3RhdGVDb2RlIGFuZCBjb3VudHJ5Q29kZVxuICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSBzdGF0ZSBmaWVsZHNcbiAgICAgICAgICAgIGlmIChmaWVsZCA9PT0gJ2NvdW50cnlDb2RlJykge1xuICAgICAgICAgICAgXHQkZm9ybS5maW5kKCdbbmFtZSQ9XCJjb3VudHJ5XCJdJykudmFsKGFkZHJlc3NbJ2NvdW50cnlDb2RlJ10udG9VcHBlckNhc2UoKSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAgICAgLy8gcmV0cmlnZ2VyIHN0YXRlIHNlbGVjdGlvbiBhZnRlciBjb3VudHJ5IGhhcyBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgLy8gdGhpcyByZXN1bHRzIGluIGR1cGxpY2F0aW9uIG9mIHRoZSBzdGF0ZSBjb2RlLCBidXQgaXMgYSBuZWNlc3NhcnkgZXZpbFxuICAgICAgICAgICAgICAgIC8vIGZvciBub3cgYmVjYXVzZSBzb21ldGltZXMgY291bnRyeUNvZGUgY29tZXMgYWZ0ZXIgc3RhdGVDb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgIFx0dmFyIHNlbGVjdGVkU3RhdGVWYWx1ZSA9IGFkZHJlc3NbJ3N0YXRlQ29kZSddO1xuICAgICAgICAgICAgXHRpZiAoJGZvcm0uZmluZCgnW25hbWUkPVwic3RhdGVcIl0gb3B0aW9uW2xhYmVsPVwiJyArIGFkZHJlc3NbJ3N0YXRlQ29kZSddICsgJ1wiXScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIFx0XHRzZWxlY3RlZFN0YXRlVmFsdWUgPSAkZm9ybS5maW5kKCdbbmFtZSQ9XCJzdGF0ZVwiXSBvcHRpb25bbGFiZWw9XCInICsgYWRkcmVzc1snc3RhdGVDb2RlJ10gKyAnXCJdJykudmFsKCk7XG4gICAgICAgICAgICBcdH1cbiAgICAgICAgICAgIFx0XG4gICAgICAgICAgICBcdCRmb3JtLmZpbmQoJ1tuYW1lJD1cInN0YXRlXCJdJykudmFsKHNlbGVjdGVkU3RhdGVWYWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGZpZWxkID09PSAnc3RhdGVDb2RlJykge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRTdGF0ZVZhbHVlID0gYWRkcmVzc1snc3RhdGVDb2RlJ107XG4gICAgICAgICAgICBcdGlmICgkZm9ybS5maW5kKCdbbmFtZSQ9XCJzdGF0ZVwiXSBvcHRpb25bbGFiZWw9XCInICsgYWRkcmVzc1snc3RhdGVDb2RlJ10gKyAnXCJdJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgXHRcdHNlbGVjdGVkU3RhdGVWYWx1ZSA9ICRmb3JtLmZpbmQoJ1tuYW1lJD1cInN0YXRlXCJdIG9wdGlvbltsYWJlbD1cIicgKyBhZGRyZXNzWydzdGF0ZUNvZGUnXSArICdcIl0nKS52YWwoKTtcbiAgICAgICAgICAgIFx0fVxuICAgICAgICAgICAgXHRcbiAgICAgICAgICAgIFx0JGZvcm0uZmluZCgnW25hbWUkPVwic3RhdGVcIl0nKS52YWwoc2VsZWN0ZWRTdGF0ZVZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBcdGlmIChhZGRyZXNzW2ZpZWxkXSAhPSBudWxsKSB7XG4gICAgICAgICAgICBcdFx0JGZvcm0uZmluZCgnW25hbWUkPVwiXycgKyBmaWVsZC5yZXBsYWNlKCdDb2RlJywgJycpICsgJ1wiXScpLnZhbCgoJycrYWRkcmVzc1tmaWVsZF0pLnJlcGxhY2UoL1xcXi9naSxcIidcIikpO1xuICAgICAgICAgICAgXHR9IGVsc2Uge1xuICAgICAgICAgICAgXHRcdCRmb3JtLmZpbmQoJ1tuYW1lJD1cIl8nICsgZmllbGQucmVwbGFjZSgnQ29kZScsICcnKSArICdcIl0nKS52YWwoYWRkcmVzc1tmaWVsZF0pO1xuICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIHRoZSBudW1iZXIgb2YgdGhlIHJlbWFpbmluZyBjaGFyYWN0ZXJcbiAgICAgKiBiYXNlZCBvbiB0aGUgY2hhcmFjdGVyIGxpbWl0IGluIGEgdGV4dCBhcmVhXG4gICAgICovXG4gICAgbGltaXRDaGFyYWN0ZXJzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJ2Zvcm0nKS5maW5kKCd0ZXh0YXJlYVtkYXRhLWNoYXJhY3Rlci1saW1pdF0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjaGFyYWN0ZXJMaW1pdCA9ICQodGhpcykuZGF0YSgnY2hhcmFjdGVyLWxpbWl0Jyk7XG4gICAgICAgICAgICB2YXIgY2hhckNvdW50SHRtbCA9IFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNIQVJfTElNSVRfTVNHLFxuICAgICAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cImNoYXItcmVtYWluLWNvdW50XCI+JyArIGNoYXJhY3RlckxpbWl0ICsgJzwvc3Bhbj4nLFxuICAgICAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cImNoYXItYWxsb3dlZC1jb3VudFwiPicgKyBjaGFyYWN0ZXJMaW1pdCArICc8L3NwYW4+Jyk7XG4gICAgICAgICAgICB2YXIgY2hhckNvdW50Q29udGFpbmVyID0gJCh0aGlzKS5uZXh0KCdkaXYuY2hhci1jb3VudCcpO1xuICAgICAgICAgICAgaWYgKGNoYXJDb3VudENvbnRhaW5lci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBjaGFyQ291bnRDb250YWluZXIgPSAkKCc8ZGl2IGNsYXNzPVwiY2hhci1jb3VudFwiLz4nKS5pbnNlcnRBZnRlcigkKHRoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoYXJDb3VudENvbnRhaW5lci5odG1sKGNoYXJDb3VudEh0bWwpO1xuICAgICAgICAgICAgLy8gdHJpZ2dlciB0aGUga2V5ZG93biBldmVudCBzbyB0aGF0IGFueSBleGlzdGluZyBjaGFyYWN0ZXIgZGF0YSBpcyBjYWxjdWxhdGVkXG4gICAgICAgICAgICAkKHRoaXMpLmNoYW5nZSgpO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBCaW5kcyB0aGUgb25jbGljay1ldmVudCB0byBhIGRlbGV0ZSBidXR0b24gb24gYSBnaXZlbiBjb250YWluZXIsXG4gICAgICogd2hpY2ggb3BlbnMgYSBjb25maXJtYXRpb24gYm94IHdpdGggYSBnaXZlbiBtZXNzYWdlXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGNvbnRhaW5lciBUaGUgbmFtZSBvZiBlbGVtZW50IHRvIHdoaWNoIHRoZSBmdW5jdGlvbiB3aWxsIGJlIGJpbmRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBUaGUgbWVzc2FnZSB0aGUgd2lsbCBiZSBzaG93biB1cG9uIGEgY2xpY2tcbiAgICAgKi9cbiAgICBzZXREZWxldGVDb25maXJtYXRpb246IGZ1bmN0aW9uIChjb250YWluZXIsIG1lc3NhZ2UpIHtcbiAgICAgICAgJChjb250YWluZXIpLm9uKCdjbGljaycsICcuZGVsZXRlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5jb25maXJtKG1lc3NhZ2UpO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBTY3JvbGxzIGEgYnJvd3NlciB3aW5kb3cgdG8gYSBnaXZlbiB4IHBvaW50XG4gICAgICogQHBhcmFtIHtTdHJpbmd9IFRoZSB4IGNvb3JkaW5hdGVcbiAgICAgKi9cbiAgICBzY3JvbGxCcm93c2VyOiBmdW5jdGlvbiAoeExvY2F0aW9uKSB7XG4gICAgICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHtzY3JvbGxUb3A6IHhMb2NhdGlvbn0sIDUwMCk7XG4gICAgfSxcbiAgICBcbiAgICBpc1RvdWNoRGV2aWNlOiBmdW5jdGlvbigpIHtcbiAgICBcdC8vZGV0ZWN0IHRvdWNoLWFiaWxpdHkgKG1heFRvdWNoUG9pbnRzIGZvciB3aW5kb3dzIHN1cmZhY2UpXG4gICAgXHRyZXR1cm4gKCdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdyB8fCBuYXZpZ2F0b3IubXNNYXhUb3VjaFBvaW50cyB8fCBuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHMgPiAwKTtcbiAgICB9LFxuXG4gICAgaXNNb2JpbGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1vYmlsZUFnZW50SGFzaCA9IFsnbW9iaWxlJywgJ3RhYmxldCcsICdwaG9uZScsICdpcGFkJywgJ2lwb2QnLCAnYW5kcm9pZCcsICdibGFja2JlcnJ5JywgJ3dpbmRvd3MgY2UnLCAnb3BlcmEgbWluaScsICdwYWxtJ107XG4gICAgICAgIHZhciAgICBpZHggPSAwO1xuICAgICAgICB2YXIgaXNNb2JpbGUgPSBmYWxzZTtcbiAgICAgICAgdmFyIHVzZXJBZ2VudCA9IChuYXZpZ2F0b3IudXNlckFnZW50KS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIHdoaWxlIChtb2JpbGVBZ2VudEhhc2hbaWR4XSAmJiAhaXNNb2JpbGUpIHtcbiAgICAgICAgICAgIGlzTW9iaWxlID0gKHVzZXJBZ2VudC5pbmRleE9mKG1vYmlsZUFnZW50SGFzaFtpZHhdKSA+PSAwKTtcbiAgICAgICAgICAgIGlkeCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc01vYmlsZTtcbiAgICB9LFxuICAgIFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgZS1tYWlsIGFkZHJlc3NcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gRS1tYWlsIGFkZHJlc3NcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn1cbiAgICAgKi9cbiAgICB2YWxpZGF0ZUVtYWlsOiBmdW5jdGlvbiAoZW1haWwpIHtcbiAgICAgICAgdmFyIHJlID0gL14oKFtePD4oKVxcW1xcXVxcXFwuLDs6XFxzQFwiXSsoXFwuW148PigpXFxbXFxdXFxcXC4sOzpcXHNAXCJdKykqKXwoXCIuK1wiKSlAKChcXFtbMC05XXsxLDN9XFwuWzAtOV17MSwzfVxcLlswLTldezEsM31cXC5bMC05XXsxLDN9XSl8KChbYS16QS1aXFwtMC05XStcXC4pK1thLXpBLVpdezIsfSkpJC87XG4gICAgICAgIHJldHVybiByZS50ZXN0KGVtYWlsKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEhlbHBlciBtZXRob2QgdG8gZW5jb2RlIGlucHV0cyBhbmQgcHJldmVudCB4c3NcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7U3RyaW5nfVxuICAgICAqL1xuICAgIGh0bWxFbmNvZGU6IGZ1bmN0aW9uICh2YWx1ZSkgeyBcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4galF1ZXJ5KCc8ZGl2Lz4nKS50ZXh0KHZhbHVlKS5odG1sKCk7IFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBcbiAgICAvKipcbiAgICAgKiBMaW1pdHMgYSB0ZXh0IGlucHV0IHRvIGEgZGVmaW5lZCBsZW5ndGguIFxuICAgICAqIEBwYXJhbSAoU3RyaW5nKSBpbnB1dFNlbGVjdG9yIC0gQSBqUXVlcnkgc2VsZWN0b3IgZm9yIHRoZSBpbnB1dCB0byBsaW1pdC5cbiAgICAgKiBAcGFyYW0gKE51bWJlcikgbGVuZ3RoTGltaXQgLSBUaGUgbGVuZ3RoIHRvIGxpbWl0IHRoZSBpbnB1dCB0by5cbiAgICAgKiBAcmV0dXJuIHZvaWRcbiAgICAgKi9cbiAgICBsaW1pdElucHV0VG9MZW5ndGg6IGZ1bmN0aW9uIChpbnB1dFNlbGVjdG9yLCBsZW5ndGhMaW1pdCkge1xuICAgICAgICAkKGlucHV0U2VsZWN0b3IpLm9uKFwia2V5dXAgY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudmFsdWUubGVuZ3RoID4gbGVuZ3RoTGltaXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS5zdWJzdHJpbmcoMCwgbGVuZ3RoTGltaXQpO1xuICAgIFx0XHR9XG4gICAgXHR9KTtcbiAgICB9LFxuICAgIFxuICAgIC8qKlxuICAgICAqIERldGVjdHMgdGhlIGNyZWRpdCBjYXJkIHR5cGUgYmFzZWQgb2ZmIG9mIHRoZSBwcm92aWRlZCBjcmVkaXQgY2FyZCBudW1iZXIuXG4gICAgICogQHBhcmFtIChTdHJpbmcpIGNyZWRpdENhcmROdW1iZXIgLSBUaGUgY3JlZGl0IGNhcmQgbnVtYmVyIHRvIGRldGVjdCB0aGUgdHlwZSBmb3IuXG4gICAgICogQHJldHVybiAoU3RyaW5nKSAtIFRoZSB0eXBlIG9mIGNyZWRpdCBjYXJkLlxuICAgICAqL1xuICAgIGdldENyZWRpdENhcmRUeXBlOiBmdW5jdGlvbiAoY3JlZGl0Q2FyZE51bWJlcikge1xuICAgICAgICBjcmVkaXRDYXJkTnVtYmVyID0gY3JlZGl0Q2FyZE51bWJlci5yZXBsYWNlKC9cXEQvZywgJycpO1xuICAgICAgICBcbiAgICAgICAgaWYgKGNyZWRpdENhcmROdW1iZXIubGVuZ3RoID49IDQpIHtcblx0ICAgICAgICB2YXIgY3JlZGl0Q2FyZFR5cGVzID0gW1xuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5WaXNhLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuVmlzYSxcblx0ICAgICAgICBcdFx0UGF5bWVudE1ldGhvZDogUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkLFxuXHQgICAgICAgIFx0XHRQYXR0ZXJuOiBuZXcgUmVnRXhwKCdeNFswLTldezAsfSQnKVxuXHQgICAgICAgIFx0fSxcblx0ICAgICAgICBcdHtcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmQ6IENyZWRpdENhcmRDb25zdGFudHMuQW1lcmljYW5FeHByZXNzLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuQW1lcmljYW5FeHByZXNzLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14zWzQ3XVswLTldezAsfSQnKVxuXHQgICAgICAgIFx0fSxcblx0ICAgICAgICBcdHtcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmQ6IENyZWRpdENhcmRDb25zdGFudHMuRGluZXJzLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuRGlzY292ZXIsXG5cdCAgICAgICAgXHRcdFBheW1lbnRNZXRob2Q6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXjMoPzowWzAtNTldezF9fFs2ODldKVswLTldezAsfSQnKVxuXHQgICAgICAgIFx0fSxcblx0ICAgICAgICBcdHtcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmQ6IENyZWRpdENhcmRDb25zdGFudHMuSkNCLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuSkNCLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14oPzoyMTMxfDE4MDB8MzUpWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYXN0ZXJjYXJkLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuTWFzdGVyY2FyZCxcblx0ICAgICAgICBcdFx0UGF5bWVudE1ldGhvZDogUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkLFxuXHQgICAgICAgIFx0XHRQYXR0ZXJuOiBuZXcgUmVnRXhwKCdeKDVbMS01XSlbMC05XXswLH0kJylcblx0ICAgICAgICBcdH0sXG5cdFx0XHRcdHtcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmQ6IENyZWRpdENhcmRDb25zdGFudHMuTWFzdGVyY2FyZFNlcmllczIsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYXN0ZXJjYXJkLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14oMjIyWzEtOV18MjJbMy05XXwyWzMtNl18MjdbMDFdfDI3MjApWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5EaXNjb3Zlcixcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmREaXNwbGF5S2V5OiBDcmVkaXRDYXJkQ29uc3RhbnRzLkRpc2NvdmVyLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14oNjAxMXw2NXw2NFs0LTldfDYyMjEyWzYtOV18NjIyMVszLTldfDYyMlsyLThdfDYyMjlbMDFdfDYyMjkyWzAtNV0pWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYWVzdHJvLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuTWFzdGVyY2FyZCxcblx0ICAgICAgICBcdFx0UGF5bWVudE1ldGhvZDogUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkLFxuXHQgICAgICAgIFx0XHRQYXR0ZXJuOiBuZXcgUmVnRXhwKCdeKDVbMDY3ODldfDYpWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5Cb290QmFybkNyZWRpdCxcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmREaXNwbGF5S2V5OiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkFsbGlhbmNlRGF0YSxcblx0ICAgICAgICBcdFx0UGF5bWVudE1ldGhvZDogUGF5bWVudE1ldGhvZENvbnN0YW50cy5BbGxpYW5jZURhdGEsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ143Nzg4WzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9XG5cdCAgICAgICAgXVxuXHQgICAgICAgIFxuXHQgICAgICAgIGZvciAodmFyIGNyZWRpdENhcmRUeXBlS2V5IGluIGNyZWRpdENhcmRUeXBlcykge1xuXHQgICAgICAgIFx0dmFyIGNyZWRpdENhcmRUeXBlID0gY3JlZGl0Q2FyZFR5cGVzW2NyZWRpdENhcmRUeXBlS2V5XTtcblx0ICAgICAgICBcdFxuXHQgICAgICAgIFx0aWYgKGNyZWRpdENhcmRUeXBlLlBhdHRlcm4gJiYgY3JlZGl0Q2FyZE51bWJlci5tYXRjaChjcmVkaXRDYXJkVHlwZS5QYXR0ZXJuKSkge1xuXHQgICAgICAgIFx0XHRyZXR1cm4gY3JlZGl0Q2FyZFR5cGU7XG5cdCAgICAgICAgXHR9XG5cdCAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgXG4gICAgLyoqXG4gICAgICogTWFza3MgYSBwcm92aWRlZCBudW1iZXIuXG4gICAgICogQHBhcmFtIChOdW1iZXIgb3IgU3RyaW5nKSBudW1iZXIgLSBUaGUgbnVtYmVyIHRvIG1hc2suXG4gICAgICogQHBhcmFtIChOdW1iZXIpIGxlbmd0aFRvU2hvdyAtIFRoZSBsZW5ndGggb2YgdGhlIG51bWJlciB0byBsZWF2ZSB1bm1hc2tlZCBhdCBlbmQuXG4gICAgICogQHBhcmFtIChTdHJpbmcpIG1hc2tDaGFyYWN0ZXIgLSBUaGUgY2hhcmFjdGVyIHRvIHVzZSBmb3IgbWFza2luZy4gRGVmYXVsdHMgdG8gKi5cbiAgICAgKiBAcmV0dXJuIChTdHJpbmcpIC0gVGhlIHR5cGUgb2YgY3JlZGl0IGNhcmQuXG4gICAgICovXG4gICAgZ2V0TWFza2VkTnVtYmVyOiBmdW5jdGlvbiAobnVtYmVyLCBsZW5ndGhUb1Nob3csIG1hc2tQYXR0ZXJuKSB7XG4gICAgXHRpZiAoIW51bWJlcikge1xuICAgIFx0XHRyZXR1cm4gJyc7XHRcbiAgICBcdH1cbiAgICBcdFxuICAgIFx0bGVuZ3RoVG9TaG93ID0gbGVuZ3RoVG9TaG93IHx8IDQ7XG4gICAgXHRtYXNrUGF0dGVybiA9IG1hc2tQYXR0ZXJuIHx8ICcqJztcbiAgICAgICBcdFxuICAgICAgIFx0dmFyIG51bWJlck1hc2tlZDtcbiAgICBcdGlmIChtYXNrUGF0dGVybi5sZW5ndGggPiAxKSB7XG4gICAgXHRcdG51bWJlck1hc2tlZCA9IG1hc2tQYXR0ZXJuO1xuICAgIFx0fSBlbHNlIGlmIChtYXNrUGF0dGVybi5sZW5ndGggPj0gMSkge1xuICAgIFx0XHRudW1iZXJNYXNrZWQgPSBuZXcgQXJyYXkobnVtYmVyLmxlbmd0aCArIDEpLmpvaW4obWFza1BhdHRlcm4pO1xuICAgIFx0fVxuICAgICAgICAgICAgXG4gICAgXHRudW1iZXIgKz0gJyc7XG4gICAgXHRpZiAobnVtYmVyICE9IG51bGwgJiYgbnVtYmVyICE9ICcnKSB7IFxuICAgIFx0XHRudW1iZXJNYXNrZWQgPSBudW1iZXJNYXNrZWQuc3Vic3RyKDAsIG51bWJlci5sZW5ndGggLSBsZW5ndGhUb1Nob3cpOyBcbiAgICBcdFx0bnVtYmVyTWFza2VkICs9IG51bWJlci5zdWJzdHIobnVtYmVyLmxlbmd0aCAtIGxlbmd0aFRvU2hvdyk7XG4gICAgXHR9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gbnVtYmVyTWFza2VkO1xuICAgIH0sXG5cblx0Z2V0UHJlZmVyZW5jZVZhbHVlRnJvbVdpbmRvd0xvY2F0aW9uOiBmdW5jdGlvbiAocHJlZmVyZW5jZU5hbWUpIHtcblx0XHR2YXIgaGFzaCA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoLnN1YnN0cigxKSxcblx0XHRcdHByZWZlcmVuY2VWYWx1ZSA9ICcnLFxuXHRcdFx0aGFzaFRhYmxlID0gaGFzaC5zcGxpdCgnJicpLnJlZHVjZShmdW5jdGlvbiAoaGFzaFRhYmxlLCBpdGVtKSB7XG5cdFx0XHRcdHZhciBwYXJ0cyA9IGl0ZW0uc3BsaXQoJz0nKTtcblx0XHRcdFx0aGFzaFRhYmxlW3BhcnRzWzBdXSA9IGRlY29kZVVSSUNvbXBvbmVudChwYXJ0c1sxXSkucmVwbGFjZSgvW1xcK1xcc10rL2csICcgJyk7XG5cdFx0XHRcdHJldHVybiBoYXNoVGFibGU7XG5cdFx0XHR9LCB7fSk7XG5cdFx0XG5cdFx0Zm9yICh2YXIgaSA9IDE7IGkgPD0gNTsgaSsrKXtcblx0XHRcdGlmKCFoYXNoVGFibGUuaGFzT3duUHJvcGVydHkoJ3ByZWZuJyArIGkpKXsgICBcdFxuXHRcdFx0XHRicmVhaztcblx0XHRcdH0gZWxzZSBpZihoYXNoVGFibGVbJ3ByZWZuJyArIGldID09IHByZWZlcmVuY2VOYW1lKXtcblx0XHRcdFx0cHJlZmVyZW5jZVZhbHVlID0gaGFzaFRhYmxlWydwcmVmdicgKyBpXTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBwcmVmZXJlbmNlVmFsdWU7XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdXRpbDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIG5hUGhvbmUgPSAvXlxcKz9cXCg/KFswLTldWzAtOF1bMC05XSlcXCk/W1xcLVxcLiBdPyhbMi05XVswLTldezJ9KVtcXC1cXC4gXT8oWzAtOV17NH0pKFxccyp4WzAtOV0rKT8kLztcbnZhciBpbnRlcm5hdGlvbmFsTnVtYmVyID0gL14oPzpcXHMqXFwrKT9bXFxkXFxzXFwuXFwtXFwoXFwpXSskLztcbnZhciBkZWZhdWx0UG9zdGFsID0gL15cXGR7Myw3fSQvO1xudmFyIHJlZ2V4ID0ge1xuICAgIHBob25lOiB7XG4gICAgICAgIHVzOiBuYVBob25lLFxuICAgICAgICBjYTogaW50ZXJuYXRpb25hbE51bWJlcixcbiAgICAgICAgZnI6IGludGVybmF0aW9uYWxOdW1iZXIsXG4gICAgICAgIGl0OiBpbnRlcm5hdGlvbmFsTnVtYmVyLFxuICAgICAgICBqcDogaW50ZXJuYXRpb25hbE51bWJlcixcbiAgICAgICAgY246IC8uKi8sXG4gICAgICAgIGdiOiBpbnRlcm5hdGlvbmFsTnVtYmVyXG4gICAgfSxcbiAgICBwb3N0YWw6IHtcbiAgICAgICAgdXM6IC9eXFxkezV9KC1cXGR7NH0pPyQvLFxuICAgICAgICBjYTogL15bQUJDRUdISktMTU5QUlNUVlhZXXsxfVxcZHsxfVtBLVpdezF9ICpcXGR7MX1bQS1aXXsxfVxcZHsxfSQvaSxcbiAgICAgICAgZnI6IC9eKEYtKT8oKDJbQXxCXSl8WzAtOV17Mn0pWzAtOV17M30kLyxcbiAgICAgICAgaXQ6IC9eKFswLTldKXs1fSQvLFxuICAgICAgICBqcDogL14oWzAtOV0pezN9Wy1dKFswLTldKXs0fSQvLFxuICAgICAgICBjbjogL14oWzAtOV0pezZ9JC8sXG4gICAgICAgIGdiOiAvXihbQS1QUi1VV1laMC05XVtBLUhLLVkwLTldW0FFSE1OUFJUVlhZMC05XT9bQUJFSE1OUFJWV1hZMC05XT8gezEsMn1bMC05XVtBQkQtSEpMTi1VVy1aXXsyfXxHSVIgMEFBKSQvaVxuICAgIH0sXG4gICAgbm90Q0M6IC9eKD8hKChbMC05IC1dKXsxMywxOX0pKS4qJC9cbn07XG4vLyBnbG9iYWwgZm9ybSB2YWxpZGF0b3Igc2V0dGluZ3NcbnZhciBzZXR0aW5ncyA9IHtcbiAgICBlcnJvckNsYXNzOiAnZXJyb3InLFxuICAgIGVycm9yRWxlbWVudDogJ3NwYW4nLFxuICAgIG9ua2V5dXA6IGZhbHNlLFxuICAgIG9uZm9jdXNvdXQ6IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5jaGVja2FibGUoZWxlbWVudCkpIHtcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZXJyb3JQbGFjZW1lbnQ6IGZ1bmN0aW9uIChlcnJvciwgZWxlbWVudCkge1xuICAgIFx0ZXJyb3IuYXBwZW5kVG8oZWxlbWVudC5wYXJlbnQoKSk7XG4gICAgfVxufTtcbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdGVzIGEgZ2l2ZW4gcGhvbmUgbnVtYmVyIGFnYWluc3QgdGhlIGNvdW50cmllcyBwaG9uZSByZWdleFxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIFRoZSBwaG9uZSBudW1iZXIgd2hpY2ggd2lsbCBiZSB2YWxpZGF0ZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBlbCBUaGUgaW5wdXQgZmllbGRcbiAqL1xudmFyIHZhbGlkYXRlUGhvbmUgPSBmdW5jdGlvbiAodmFsdWUsIGVsKSB7XG4gICAgdmFyIGNvdW50cnkgPSAkKGVsKS5jbG9zZXN0KCdmb3JtJykuZmluZCgnLmNvdW50cnknKTtcbiAgICB2YXIgY291bnRyeVZhbHVlO1xuICAgIGlmIChjb3VudHJ5Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgY291bnRyeVZhbHVlID0gY291bnRyeS52YWwoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvdW50cnlWYWx1ZSB8fCAhcmVnZXgucGhvbmVbY291bnRyeS52YWwoKS50b0xvd2VyQ2FzZSgpXSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgcmd4ID0gcmVnZXgucGhvbmVbY291bnRyeS52YWwoKS50b0xvd2VyQ2FzZSgpXTtcbiAgICB2YXIgaXNPcHRpb25hbCA9IHRoaXMub3B0aW9uYWwoZWwpO1xuICAgIHZhciBpc1ZhbGlkID0gcmd4LnRlc3QoJC50cmltKHZhbHVlKSk7XG5cbiAgICByZXR1cm4gaXNPcHRpb25hbCB8fCBpc1ZhbGlkO1xufTtcblxudmFyIHZhbGlkYXRlUG9zdGFsID0gZnVuY3Rpb24gKHZhbHVlLCBlbCkge1xuICAgIHZhciBjb3VudHJ5ID0gJChlbCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJy5jb3VudHJ5Jyk7XG4gICAgdmFyIGNvdW50cnlWYWx1ZTtcbiAgICBpZiAoY291bnRyeS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvdW50cnlWYWx1ZSA9IGNvdW50cnkudmFsKCk7XG4gICAgfVxuXG4gICAgaWYgKCFjb3VudHJ5VmFsdWUgfHwgIXJlZ2V4LnBvc3RhbFtjb3VudHJ5LnZhbCgpLnRvTG93ZXJDYXNlKCldKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciByZ3ggPSByZWdleC5wb3N0YWxbY291bnRyeVZhbHVlLnRvTG93ZXJDYXNlKCldO1xuICAgIHZhciBpc09wdGlvbmFsID0gdGhpcy5vcHRpb25hbChlbCk7XG4gICAgdmFyIGlzVmFsaWQgPSByZ3gudGVzdCgkLnRyaW0odmFsdWUpKTtcblxuICAgIHJldHVybiBpc09wdGlvbmFsIHx8IGlzVmFsaWQ7XG59O1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgdGhhdCBhIGNyZWRpdCBjYXJkIG93bmVyIGlzIG5vdCBhIENyZWRpdCBjYXJkIG51bWJlclxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIFRoZSBvd25lciBmaWVsZCB3aGljaCB3aWxsIGJlIHZhbGlkYXRlZFxuICogQHBhcmFtIHtTdHJpbmd9IGVsIFRoZSBpbnB1dCBmaWVsZFxuICovXG52YXIgdmFsaWRhdGVPd25lciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHZhciBpc1ZhbGlkID0gcmVnZXgubm90Q0MudGVzdCgkLnRyaW0odmFsdWUpKTtcbiAgICByZXR1cm4gaXNWYWxpZDtcbn07XG5cbi8qKlxuICogQWRkIHBob25lIHZhbGlkYXRpb24gbWV0aG9kIHRvIGpRdWVyeSB2YWxpZGF0aW9uIHBsdWdpbi5cbiAqIFRleHQgZmllbGRzIG11c3QgaGF2ZSAncGhvbmUnIGNzcyBjbGFzcyB0byBiZSB2YWxpZGF0ZWQgYXMgcGhvbmVcbiAqL1xuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCdwaG9uZScsIHZhbGlkYXRlUGhvbmUsIFJlc291cmNlcy5JTlZBTElEX1BIT05FKTtcbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgncG9zdGFsJywgdmFsaWRhdGVQb3N0YWwsIFJlc291cmNlcy5JTlZBTElEX1pJUCk7XG5cbi8qKlxuICogQWRkIENDT3duZXIgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdvd25lcicgY3NzIGNsYXNzIHRvIGJlIHZhbGlkYXRlZCBhcyBub3QgYSBjcmVkaXQgY2FyZFxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ293bmVyJywgdmFsaWRhdGVPd25lciwgUmVzb3VyY2VzLklOVkFMSURfT1dORVIpO1xuXG4vKipcbiAqIEFkZCBnaWZ0IGNlcnQgYW1vdW50IHZhbGlkYXRpb24gbWV0aG9kIHRvIGpRdWVyeSB2YWxpZGF0aW9uIHBsdWdpbi5cbiAqIFRleHQgZmllbGRzIG11c3QgaGF2ZSAnZ2lmdC1jZXJ0LWFtb250JyBjc3MgY2xhc3MgdG8gYmUgdmFsaWRhdGVkXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgnZ2lmdC1jZXJ0LWFtb3VudCcsIGZ1bmN0aW9uICh2YWx1ZSwgZWwpIHtcbiAgICB2YXIgaXNPcHRpb25hbCA9IHRoaXMub3B0aW9uYWwoZWwpO1xuICAgIHZhciBpc1ZhbGlkID0gKCFpc05hTih2YWx1ZSkpICYmIChwYXJzZUZsb2F0KHZhbHVlKSA+PSA1KSAmJiAocGFyc2VGbG9hdCh2YWx1ZSkgPD0gNTAwMCk7XG4gICAgcmV0dXJuIGlzT3B0aW9uYWwgfHwgaXNWYWxpZDtcbn0sIFJlc291cmNlcy5HSUZUX0NFUlRfQU1PVU5UX0lOVkFMSUQpO1xuXG4vKipcbiAqIEFkZCBwb3NpdGl2ZSBudW1iZXIgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdwb3NpdGl2ZW51bWJlcicgY3NzIGNsYXNzIHRvIGJlIHZhbGlkYXRlZCBhcyBwb3NpdGl2ZW51bWJlclxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc2l0aXZlbnVtYmVyJywgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgaWYgKCQudHJpbSh2YWx1ZSkubGVuZ3RoID09PSAwKSB7IHJldHVybiB0cnVlOyB9XG4gICAgcmV0dXJuICghaXNOYU4odmFsdWUpICYmIE51bWJlcih2YWx1ZSkgPj0gMCk7XG59LCBSZXNvdXJjZXMuVkFMSURBVEVfTlVNQkVSKTtcblxuLyoqXG4gKiBBZGQgbWV0aG9kIHRvIGNoZWNrIGZvciBlbWFpbCBleHRlbnNpb24gd2hlbiB2YWxpZGF0aW5nIGVtYWlscyxcbiAqIHNpbmNlIGRlZmF1bHQgc2V0dGluZ3MgZG9uJ3QgcmVxdWlyZSBhbiBleHRlbnNpb25cbiAqL1xuJC52YWxpZGF0b3IuYWRkTWV0aG9kKFwicmVxdWlyZUVtYWlsRXh0ZW5zaW9uXCIsIGZ1bmN0aW9uKHZhbHVlLCBlbGVtZW50KSB7XG4gICAgaWYgKCQudHJpbSh2YWx1ZSkubGVuZ3RoID09PSAwKSB7IHJldHVybiB0cnVlOyB9XG4gICAgcmV0dXJuIC9eXFx3KyhbLSsuJ11cXHcrKSpAXFx3KyhbLS5dXFx3KykqXFwuXFx3KyhbLS5dXFx3KykqJC8udGVzdCh2YWx1ZSk7XG59LCBSZXNvdXJjZXMuVkFMSURBVEVfRU1BSUwpO1xuXG4vKlxuICogTGV0cyB5b3Ugc2F5IFwiYXQgbGVhc3QgWCBpbnB1dHMgdGhhdCBtYXRjaCBzZWxlY3RvciBZIG11c3QgYmUgZmlsbGVkLlwiXG4gKlxuICogVGhlIGVuZCByZXN1bHQgaXMgdGhhdCBuZWl0aGVyIG9mIHRoZXNlIGlucHV0czpcbiAqXG4gKiAgPGlucHV0IGNsYXNzPVwicHJvZHVjdGluZm9cIiBuYW1lPVwicGFydG51bWJlclwiPlxuICogIDxpbnB1dCBjbGFzcz1cInByb2R1Y3RpbmZvXCIgbmFtZT1cImRlc2NyaXB0aW9uXCI+XG4gKlxuICogIC4uLndpbGwgdmFsaWRhdGUgdW5sZXNzIGF0IGxlYXN0IG9uZSBvZiB0aGVtIGlzIGZpbGxlZC5cbiAqXG4gKiBwYXJ0bnVtYmVyOiAge3JlcXVpcmVfZnJvbV9ncm91cDogWzEsXCIucHJvZHVjdGluZm9cIl19LFxuICogZGVzY3JpcHRpb246IHtyZXF1aXJlX2Zyb21fZ3JvdXA6IFsxLFwiLnByb2R1Y3RpbmZvXCJdfVxuICpcbiAqIG9wdGlvbnNbMF06IG51bWJlciBvZiBmaWVsZHMgdGhhdCBtdXN0IGJlIGZpbGxlZCBpbiB0aGUgZ3JvdXBcbiAqIG9wdGlvbnNbMV06IENTUyBzZWxlY3RvciB0aGF0IGRlZmluZXMgdGhlIGdyb3VwIG9mIGNvbmRpdGlvbmFsbHkgcmVxdWlyZWQgZmllbGRzXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCggXCJyZXF1aXJlX2Zyb21fZ3JvdXBcIiwgZnVuY3Rpb24oIHZhbHVlLCBlbGVtZW50LCBvcHRpb25zICkge1xuICAgIHZhciAkZmllbGRzID0gJChvcHRpb25zWzFdLCBlbGVtZW50LmZvcm0pO1xuICAgIHZhciAkZmllbGRzRmlyc3QgPSAkZmllbGRzLmVxKDApO1xuICAgIHZhciB2YWxpZGF0b3IgPSAkZmllbGRzRmlyc3QuZGF0YShcInZhbGlkX3JlcV9ncnBcIikgPyAkZmllbGRzRmlyc3QuZGF0YShcInZhbGlkX3JlcV9ncnBcIikgOiAkLmV4dGVuZCh7fSwgdGhpcyk7XG4gICAgdmFyIGlzVmFsaWQgPSAkZmllbGRzLmZpbHRlcihmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbGlkYXRvci5lbGVtZW50VmFsdWUodGhpcyk7XG4gICAgfSkubGVuZ3RoID49IG9wdGlvbnNbMF07XG5cbiAgICAvLyBTdG9yZSB0aGUgY2xvbmVkIHZhbGlkYXRvciBmb3IgZnV0dXJlIHZhbGlkYXRpb25cbiAgICAkZmllbGRzRmlyc3QuZGF0YShcInZhbGlkX3JlcV9ncnBcIiwgdmFsaWRhdG9yKTtcblxuICAgIC8vIElmIGVsZW1lbnQgaXNuJ3QgYmVpbmcgdmFsaWRhdGVkLCBydW4gZWFjaCByZXF1aXJlX2Zyb21fZ3JvdXAgZmllbGQncyB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgaWYgKCEkKGVsZW1lbnQpLmRhdGEoXCJiZWluZ192YWxpZGF0ZWRcIikpIHtcbiAgICAgICAgJGZpZWxkcy5kYXRhKFwiYmVpbmdfdmFsaWRhdGVkXCIsIHRydWUpO1xuICAgICAgICAkZmllbGRzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YWxpZGF0b3IuZWxlbWVudCh0aGlzKTtcbiAgICAgICAgfSk7XG4gICAgICAgICRmaWVsZHMuZGF0YShcImJlaW5nX3ZhbGlkYXRlZFwiLCBmYWxzZSk7XG4gICAgfVxuICAgIHJldHVybiBpc1ZhbGlkO1xufSwgJC52YWxpZGF0b3IuZm9ybWF0KFwiUGxlYXNlIGZpbGwgYXQgbGVhc3QgezB9IG9mIHRoZXNlIGZpZWxkcy5cIikpO1xuXG4kLmV4dGVuZCgkLnZhbGlkYXRvci5tZXNzYWdlcywge1xuICAgIHJlcXVpcmVkOiBSZXNvdXJjZXMuVkFMSURBVEVfUkVRVUlSRUQsXG4gICAgcmVtb3RlOiBSZXNvdXJjZXMuVkFMSURBVEVfUkVNT1RFLFxuICAgIGVtYWlsOiBSZXNvdXJjZXMuVkFMSURBVEVfRU1BSUwsXG4gICAgdXJsOiBSZXNvdXJjZXMuVkFMSURBVEVfVVJMLFxuICAgIGRhdGU6IFJlc291cmNlcy5WQUxJREFURV9EQVRFLFxuICAgIGRhdGVJU086IFJlc291cmNlcy5WQUxJREFURV9EQVRFSVNPLFxuICAgIG51bWJlcjogUmVzb3VyY2VzLlZBTElEQVRFX05VTUJFUixcbiAgICBkaWdpdHM6IFJlc291cmNlcy5WQUxJREFURV9ESUdJVFMsXG4gICAgY3JlZGl0Y2FyZDogUmVzb3VyY2VzLlZBTElEQVRFX0NSRURJVENBUkQsXG4gICAgZXF1YWxUbzogUmVzb3VyY2VzLlZBTElEQVRFX0VRVUFMVE8sXG4gICAgbWF4bGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX01BWExFTkdUSCksXG4gICAgbWlubGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX01JTkxFTkdUSCksXG4gICAgcmFuZ2VsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfUkFOR0VMRU5HVEgpLFxuICAgIHJhbmdlOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX1JBTkdFKSxcbiAgICBtYXg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUFYKSxcbiAgICBtaW46ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUlOKVxufSk7XG5cbnZhciB2YWxpZGF0b3IgPSB7XG4gICAgcmVnZXg6IHJlZ2V4LFxuICAgIHNldHRpbmdzOiBzZXR0aW5ncyxcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgJCgnZm9ybTpub3QoLnN1cHByZXNzKScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS52YWxpZGF0ZShzZWxmLnNldHRpbmdzKTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBpbml0Rm9ybTogZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgJChmKS52YWxpZGF0ZSh0aGlzLnNldHRpbmdzKTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHZhbGlkYXRvcjtcbiIsIi8qIFxuICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiBcbiAqIHdhdGVybWFyay5qcyAtIENyZWF0ZSB3YXRlcm1hcmtlZCBpbWFnZXMgd2l0aCBDYW52YXMgYW5kIEpTXG4gKlxuICogVmVyc2lvbjogMSAoMjAxMS0wNC0wNClcbiAqIENvcHlyaWdodCAoYykgMjAxMVx0UGF0cmljayBXaWVkICggaHR0cDovL3d3dy5wYXRyaWNrLXdpZWQuYXQgKVxuICogVGhpcyBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTUlUIExJQ0VOU0VcbiAqXG4gKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqIFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odyl7XG5cdHZhciB3ID0gd2luZG93O1xuXHR2YXIgd20gPSAoZnVuY3Rpb24odyl7XG5cdFx0dmFyIGRvYyA9IHcuZG9jdW1lbnQsXG5cdFx0Z2NhbnZhcyA9IHt9LFxuXHRcdGdjdHggPSB7fSxcblx0XHRpbWdRdWV1ZSA9IFtdLFxuXHRcdGNsYXNzTmFtZXMgPSBbXCJ3YXRlcm1hcmtcIl0sXG5cdFx0d2F0ZXJtYXJrID0gZmFsc2UsXG5cdFx0d2F0ZXJtYXJrUG9zaXRpb24gPSBcImJvdHRvbS1yaWdodFwiLFxuXHRcdHdhdGVybWFya1BhdGggPSBcIndhdGVybWFyay5wbmc/XCIrKCsobmV3IERhdGUoKSkpLFxuXHRcdG9wYWNpdHkgPSAoMjU1LygxMDAvNTApKSwgLy8gNTAlXG5cdFx0aW5pdENhbnZhcyA9IGZ1bmN0aW9uKCl7XG5cdFx0XHRnY2FudmFzID0gZG9jLmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG5cdFx0XHRnY2FudmFzLnN0eWxlLmNzc1RleHQgPSBcImRpc3BsYXk6bm9uZTtcIjtcblx0XHRcdGdjdHggPSBnY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcblx0XHRcdGRvYy5ib2R5LmFwcGVuZENoaWxkKGdjYW52YXMpO1xuXHRcdH0sXG5cdFx0aW5pdFdhdGVybWFyayA9IGZ1bmN0aW9uKCl7XG5cdFx0XHR3YXRlcm1hcmsgPSBuZXcgSW1hZ2UoKTtcblx0XHRcdHdhdGVybWFyay5zcmMgPSBcIlwiO1xuXHRcdFx0d2F0ZXJtYXJrLnNyYyA9IHdhdGVybWFya1BhdGg7XG5cdFx0XHRcblx0XHRcdGlmKG9wYWNpdHkgIT0gMjU1KXtcblx0XHRcdFx0aWYoIXdhdGVybWFyay5jb21wbGV0ZSlcblx0XHRcdFx0XHR3YXRlcm1hcmsub25sb2FkID0gZnVuY3Rpb24oKXtcdFxuXHRcdFx0XHRcdFx0YXBwbHlUcmFuc3BhcmVuY3koKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRhcHBseVRyYW5zcGFyZW5jeSgpO1xuXHRcdFx0XHRcblxuXHRcdFx0fWVsc2V7XG5cdFx0XHRcdGFwcGx5V2F0ZXJtYXJrcygpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0fSxcblx0XHQvLyBmdW5jdGlvbiBmb3IgYXBwbHlpbmcgdHJhbnNwYXJlbmN5IHRvIHRoZSB3YXRlcm1hcmtcblx0XHRhcHBseVRyYW5zcGFyZW5jeSA9IGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgdyA9IHdhdGVybWFyay53aWR0aCB8fCB3YXRlcm1hcmsub2Zmc2V0V2lkdGgsXG5cdFx0XHRoID0gd2F0ZXJtYXJrLmhlaWdodCB8fCB3YXRlcm1hcmsub2Zmc2V0SGVpZ2h0O1xuXHRcdFx0c2V0Q2FudmFzU2l6ZSh3LCBoKTtcblx0XHRcdGdjdHguZHJhd0ltYWdlKHdhdGVybWFyaywgMCwgMCk7XG5cdFx0XHRcdFx0XG5cdFx0XHR2YXIgaW1hZ2UgPSBnY3R4LmdldEltYWdlRGF0YSgwLCAwLCB3LCBoKTtcblx0XHRcdHZhciBpbWFnZURhdGEgPSBpbWFnZS5kYXRhLFxuXHRcdFx0bGVuZ3RoID0gaW1hZ2VEYXRhLmxlbmd0aDtcblx0XHRcdGZvcih2YXIgaT0zOyBpIDwgbGVuZ3RoOyBpKz00KXsgIFxuXHRcdFx0XHRpbWFnZURhdGFbaV0gPSAoaW1hZ2VEYXRhW2ldPG9wYWNpdHkpP2ltYWdlRGF0YVtpXTpvcGFjaXR5O1xuXHRcdFx0fVxuXHRcdFx0aW1hZ2UuZGF0YSA9IGltYWdlRGF0YTtcblx0XHRcdGdjdHgucHV0SW1hZ2VEYXRhKGltYWdlLCAwLCAwKTtcblx0XHRcdHdhdGVybWFyay5vbmxvYWQgPSBudWxsO1xuXHRcdFx0d2F0ZXJtYXJrLnNyYyA9IFwiXCI7XG5cdFx0XHR3YXRlcm1hcmsuc3JjID0gZ2NhbnZhcy50b0RhdGFVUkwoKTtcblx0XHRcdC8vIGFzc2lnbiBpbWcgYXR0cmlidXRlcyB0byB0aGUgdHJhbnNwYXJlbnQgd2F0ZXJtYXJrXG5cdFx0XHQvLyBiZWNhdXNlIGJyb3dzZXJzIHJlY2FsY3VsYXRpb24gZG9lc24ndCB3b3JrIGFzIGZhc3QgYXMgbmVlZGVkXG5cdFx0XHR3YXRlcm1hcmsud2lkdGggPSB3O1xuXHRcdFx0d2F0ZXJtYXJrLmhlaWdodCA9IGg7XG5cblx0XHRcdGFwcGx5V2F0ZXJtYXJrcygpO1xuXHRcdH0sXG5cdFx0Y29uZmlndXJlID0gZnVuY3Rpb24oY29uZmlnKXtcblx0XHRcdGlmKGNvbmZpZ1tcIndhdGVybWFya1wiXSlcblx0XHRcdFx0d2F0ZXJtYXJrID0gY29uZmlnW1wid2F0ZXJtYXJrXCJdO1xuXHRcdFx0aWYoY29uZmlnW1wicGF0aFwiXSlcblx0XHRcdFx0d2F0ZXJtYXJrUGF0aCA9IGNvbmZpZ1tcInBhdGhcIl07XG5cdFx0XHRpZihjb25maWdbXCJwb3NpdGlvblwiXSlcblx0XHRcdFx0d2F0ZXJtYXJrUG9zaXRpb24gPSBjb25maWdbXCJwb3NpdGlvblwiXTtcblx0XHRcdGlmKGNvbmZpZ1tcIm9wYWNpdHlcIl0pXG5cdFx0XHRcdG9wYWNpdHkgPSAoMjU1LygxMDAvY29uZmlnW1wib3BhY2l0eVwiXSkpO1xuXHRcdFx0aWYoY29uZmlnW1wiY2xhc3NOYW1lc1wiXSlcblx0XHRcdFx0Y2xhc3NOYW1lcyA9IGNvbmZpZ1tcImNsYXNzTmFtZXNcIl07XG5cdFx0XHRcblx0XHRcdGluaXRDYW52YXMoKTtcblx0XHRcdGluaXRXYXRlcm1hcmsoKTtcblx0XHR9XG5cdFx0c2V0Q2FudmFzU2l6ZSA9IGZ1bmN0aW9uKHcsIGgpe1xuXHRcdFx0Z2NhbnZhcy53aWR0aCA9IHc7XG5cdFx0XHRnY2FudmFzLmhlaWdodCA9IGg7XG5cdFx0fSxcblx0XHRhcHBseVdhdGVybWFyayA9IGZ1bmN0aW9uKGltZyl7XG5cdFx0XHRnY2FudmFzLndpZHRoID0gaW1nLm5hdHVyYWxXaWR0aCB8fCBpbWcud2lkdGggfHwgaW1nLm9mZnNldFdpZHRoO1xuXHRcdFx0Z2NhbnZhcy5oZWlnaHQgPSBpbWcubmF0dXJhbEhlaWdodCB8fCBpbWcuaGVpZ2h0IHx8IGltZy5vZmZzZXRIZWlnaHQ7XG5cdFx0XHRnY3R4LmRyYXdJbWFnZShpbWcsIDAsIDApO1xuXHRcdFx0dmFyIHBvc2l0aW9uID0gd2F0ZXJtYXJrUG9zaXRpb24sXG5cdFx0XHR4ID0gMCxcblx0XHRcdHkgPSAwO1xuXHRcdFx0aWYocG9zaXRpb24uaW5kZXhPZihcInRvcFwiKSE9LTEpXG5cdFx0XHRcdHkgPSAxMDtcblx0XHRcdGVsc2UgaWYocG9zaXRpb24uaW5kZXhPZihcIm1pZGRsZVwiKSE9LTEpXG5cdFx0XHRcdHkgPSAoZ2NhbnZhcy5oZWlnaHQtd2F0ZXJtYXJrLmhlaWdodCkgLyAyO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR5ID0gZ2NhbnZhcy5oZWlnaHQtd2F0ZXJtYXJrLmhlaWdodC0xMDtcblx0XHRcdFxuXHRcdFx0aWYocG9zaXRpb24uaW5kZXhPZihcImxlZnRcIikhPS0xKVxuXHRcdFx0XHR4ID0gMTA7XG5cdFx0XHRlbHNlIGlmKHBvc2l0aW9uLmluZGV4T2YoXCJjZW50ZXJcIikhPS0xKVxuXHRcdFx0XHR4ID0gKGdjYW52YXMud2lkdGgtd2F0ZXJtYXJrLndpZHRoKSAvIDI7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHggPSBnY2FudmFzLndpZHRoLXdhdGVybWFyay53aWR0aC0xMDtcblxuXG5cdFx0XHRnY3R4LmRyYXdJbWFnZSh3YXRlcm1hcmssIHgsIHkpO1xuXHRcdFx0aW1nLm9ubG9hZCA9IG51bGw7XG5cdFxuXHRcdFx0aW1nLnNyYyA9IGdjYW52YXMudG9EYXRhVVJMKCk7XG5cblx0XHR9LFxuXHRcdGFwcGx5V2F0ZXJtYXJrcyA9IGZ1bmN0aW9uKCl7XG5cdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHRcdGZvcih2YXIgaSA9IDA7IGkgPCBjbGFzc05hbWVzLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0XHR2YXIgZWxzID0gZG9jLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoY2xhc3NOYW1lc1tpXSksXG5cdFx0XHRcdFx0bGVuID0gZWxzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZShsZW4tLSl7XG5cdFx0XHRcdFx0XHR2YXIgaW1nID0gZWxzW2xlbl07XG5cdFx0XHRcdFx0XHRpZihpbWcudGFnTmFtZS50b1VwcGVyQ2FzZSgpICE9IFwiSU1HXCIgfHwgKGltZy50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT0gXCJJTUdcIiAmJiBpbWcuZ2V0QXR0cmlidXRlKCdzcmMnKS5pbmRleE9mKCdkYXRhOmltYWdlL3BuZycpID4gLTEpIHx8IGltZy5uYXR1cmFsV2lkdGggPT0gMClcblx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmKCFpbWcuY29tcGxldGUpe1xuXHRcdFx0XHRcdFx0XHRpbWcub25sb2FkID0gZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdFx0XHRhcHBseVdhdGVybWFyayh0aGlzKTtcblx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdH1lbHNle1xuXHRcdFx0XHRcdFx0XHRhcHBseVdhdGVybWFyayhpbWcpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSwxMCk7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHRyZXR1cm4ge1xuXHRcdFx0aW5pdDogZnVuY3Rpb24oY29uZmlnKXtcblx0XHRcdFx0Y29uZmlndXJlKGNvbmZpZyk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fSkodyk7XG5cdHcud21hcmsgPSB3bTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi9kaWFsb2cnKTtcbnZhciBwcm9ncmVzcyA9IHJlcXVpcmUoJy4vcHJvZ3Jlc3MnKTtcbnZhciBsb2dpbkRpYWxvZyA9IHJlcXVpcmUoJy4vbG9naW5EaWFsb2cnKTtcblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogV0lTSExJU1RcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG5mdW5jdGlvbiBlcnJvckhhbmRsaW5nKGRhdGEsIGRpYWxvZ1RpdGxlLCBkaWFsb2dIdG1sKSB7XG4gICAgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdtZXNzYWdlJyBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGRhdGEubWVzc2FnZSk7XG4gICAgfVxuICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgaHRtbDogZGlhbG9nSHRtbCxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgdGl0bGU6IGRpYWxvZ1RpdGxlLFxuICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNTUkZUb2tlbigpIHtcblx0aWYgKHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnZ2V0Jyxcblx0XHRcdHVybDogVXJscy5DU1JGVG9rZW4uR2V0LFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRcdHBhZ2VDb250ZXh0Lm9wdGlvbnMuVG9rZW4gPSByZXNwb25zZS50b2tlbjtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiBjaGVja1dpc2hsaXN0Rm9ySXRlbSh3aXNobGlzdEl0ZW1JZCkge1xuICAgIGlmICgnbG9jYWxTdG9yYWdlJyBpbiB3aW5kb3cgJiYgd2luZG93Wydsb2NhbFN0b3JhZ2UnXSAhPT0gbnVsbCAmJiAnV2lzaGxpc3RQcm9kdWN0SURzJyBpbiB3aW5kb3cubG9jYWxTdG9yYWdlICYmIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdmFyIHdpc2hsaXN0SXRlbXMgPSBKU09OLnBhcnNlKHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzKTtcbiAgICAgICAgdmFyIHBhZ2VUeXBlID0gcGFnZUNvbnRleHQgJiYgJ3R5cGUnIGluIHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0LnR5cGUgPyBwYWdlQ29udGV4dC50eXBlIDogJCgnI3dyYXBwZXInKS5hdHRyKCdjbGFzcycpO1xuICAgICAgICB2YXIgaXNXaXNobGlzdEl0ZW0gPSB3aXNobGlzdEl0ZW1zLmZpbHRlcihmdW5jdGlvbihwcm9kdWN0T2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAocHJvZHVjdE9iamVjdC5wcm9kdWN0SUQgPT0gd2lzaGxpc3RJdGVtSWQpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBOT1QgYSBQRFAsIHRoZW4gd2UgbmVlZCB0byBydW4gYWRkaXRpb25hbCBjaGVja3MgdG8gc2VlIGlmIE1hc3RlciBQcm9kdWN0IG9yIGFueSBvZiB0aGUgVmFyaWF0aW9ucyBhcmUgaW4gdGhlIHdpc2hsaXN0XG4gICAgICAgICAgICBpZiAocGFnZVR5cGUgIT0gJ3Byb2R1Y3QnKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb2R1Y3RPYmplY3QubWFzdGVySUQgPT0gd2lzaGxpc3RJdGVtSWQpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICAgICAgICAgIGlmIChwcm9kdWN0T2JqZWN0LnZhcmlhbnRzLmluZGV4T2Yod2lzaGxpc3RJdGVtSWQpID4gLTEpIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGlzV2lzaGxpc3RJdGVtLmxlbmd0aCA+IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gbW9kaWZ5V2lzaGxpc3RJblN0b3JhZ2UoZGF0YSkge1xuICAgIGlmICgnbG9jYWxTdG9yYWdlJyBpbiB3aW5kb3cgJiYgd2luZG93Wydsb2NhbFN0b3JhZ2UnXSAhPT0gbnVsbCkge1xuICAgICAgICBpZiAoIXdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzKSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9ICdbXSc7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGl0ZW0gPSAncHJvZHVjdERhdGEnIGluIGRhdGEgJiYgZGF0YS5wcm9kdWN0RGF0YS5wcm9kdWN0SUQgPyBkYXRhLnByb2R1Y3REYXRhLnByb2R1Y3RJRCA6IG51bGw7XG4gICAgICAgIHZhciBpc0RhdGFBY3Rpb24gPSBkYXRhLmFjdGlvbjtcbiAgICAgICAgdmFyIHdpc2hsaXN0SXRlbXMgPSBKU09OLnBhcnNlKHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzKTtcblxuICAgICAgICBpZiAoaXRlbSAmJiBpc0RhdGFBY3Rpb24pIHtcbiAgICAgICAgICAgIGlmIChpc0RhdGFBY3Rpb24gPT0gJ3dpc2hsaXN0SXRlbUFkZGVkJykge1xuICAgICAgICAgICAgICAgIHdpc2hsaXN0SXRlbXMucHVzaChkYXRhLnByb2R1Y3REYXRhKTtcbiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9IEpTT04uc3RyaW5naWZ5KHdpc2hsaXN0SXRlbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzRGF0YUFjdGlvbiA9PSAnd2lzaGxpc3RJdGVtUmVtb3ZlZCcgJiYgd2lzaGxpc3RJdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1vZGlmaWVkV2lzaGxpc3QgPSB3aXNobGlzdEl0ZW1zLmZpbHRlcihmdW5jdGlvbihwcm9kdWN0T2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9kdWN0T2JqZWN0LnByb2R1Y3RJRCAhPSBpdGVtKSB7IHJldHVybiB0cnVlIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9IEpTT04uc3RyaW5naWZ5KG1vZGlmaWVkV2lzaGxpc3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBhZGRXaXNobGlzdEV2ZW50KGV2ZW50LCBwcm9kdWN0SUQpIHtcblx0dmFyIGV2ZW50VHlwZSA9IFwid2lzaGxpc3RfXCIgKyBldmVudDtcblx0dmFyIHVybCwgaW1hZ2U7XG5cdHZhciBpbWFnZXMgPSBbXTtcblx0XG5cdHZhciB0aGlzVGlsZSA9ICQoJy5wcm9kdWN0LXRpbGVbZGF0YS1pdGVtaWQ9XCInK3Byb2R1Y3RJRCsnXCJdJyk7XG5cdHZhciB0aGlzSXRlbSA9IEpTT04ucGFyc2UoJCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEuZXZlbnQtYnJvd3NlW2RhdGEtcGlkPVwiJytwcm9kdWN0SUQrJ1wiXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0aWYgKHRoaXNUaWxlLmxlbmd0aCA+IDApIHtcblx0XHR1cmwgPSB0aGlzVGlsZS5maW5kKCcudGh1bWItbGluaycpLmF0dHIoJ2hyZWYnKTtcblx0XHRpbWFnZSA9IHRoaXNUaWxlLmZpbmQoJy50aHVtYi1saW5rIGltZycpLmF0dHIoJ3NyYycpO1xuXHRcdGltYWdlcy5wdXNoKGltYWdlKTtcblx0fSBlbHNlIHtcblx0XHR2YXIgc2VsZWN0ZWRTaXplT3B0aW9uID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuc2l6ZS5zaXplLW9wdGlvbnMgbGkuc2VsZWN0ZWQgLnN3YXRjaGFuY2hvcicpO1xuXHRcdHZhciBzZWxlY3RlZFNpemVVcmwgPSBzZWxlY3RlZFNpemVPcHRpb24uYXR0cignaHJlZicpLnJlcGxhY2UoJ1Byb2R1Y3QtVmFyaWF0aW9uJywgJ1Byb2R1Y3QtU2hvdycpO1xuXHRcdHZhciBzZWxlY3RlZFNpemVWYWx1ZSA9IHNlbGVjdGVkU2l6ZU9wdGlvbi5hdHRyKCdkYXRhLXNpemUtaWQnKS5yZXBsYWNlKC8gL2csICclMjAnKTtcblx0XHR1cmwgPSBzZWxlY3RlZFNpemVVcmwucmVwbGFjZShcIl9zaXplPVwiLCBcIl9zaXplPVwiK3NlbGVjdGVkU2l6ZVZhbHVlKTtcblx0XHQkKCcucHJvZHVjdC1wcmltYXJ5LWltYWdlIFtjbGFzcyo9XCItc2xpZGVcIl0nKS5ub3QoJy5zbGljay1jbG9uZWQnKS5lYWNoKGZ1bmN0aW9uIChpbmRleCkge1xuXHRcdFx0aWYoaW5kZXggPiAtMSkge1xuXHRcdFx0XHR2YXIgaW1hZ2UgPSAkKHRoaXMpLmZpbmQoJ2EnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdGlmICghaW1hZ2UgfHwgaW1hZ2UgPT0gdW5kZWZpbmVkIHx8IGltYWdlID09IG51bGwpIHtcblx0XHRcdFx0XHRpbWFnZSA9ICQodGhpcykuZmluZCgnaW1nJykuYXR0cignc3JjJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGltYWdlcy5pbmRleE9mKGltYWdlKSA9PT0gLTEpIHtcblx0XHRcdFx0XHRpbWFnZXMucHVzaChpbWFnZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRcblx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XCJwcm9kdWN0SURcIjogdGhpc0l0ZW1bXCJpZFwiXSxcblx0XHRcInByb2R1Y3ROYW1lXCI6IHRoaXNJdGVtW1wibmFtZVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFwiY2F0ZWdvcnlcIjogdGhpc0l0ZW1bXCJjYXRlZ29yeVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFwicHJpY2VcIjogdGhpc0l0ZW1bXCJwcmljZVwiXSxcblx0XHRcImltYWdlc1wiOiBpbWFnZXMsXG5cdFx0XCJ1cmxcIjogdXJsLFxuXHRcdFwiYXR0clwiOiB7XG5cdFx0XHRcIm1hbnVmYWN0dXJlclwiOiB0aGlzSXRlbVtcImJyYW5kXCJdXG5cdFx0fSxcblx0fTtcblxuXHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0Y3JkbCgnZXZlbnQnLCBldmVudFR5cGUsIHByb3BlcnRpZXMpOyBcblx0fVx0XG59XG5cbmZ1bmN0aW9uIHByZXBhcmVXaXNobGlzdEFkZFVJKGJ1dHRvbnMsIHdpc2hsaXN0SXRlbUlkLCBzaXplVGV4dCkge1xuICAgIGlmICghYnV0dG9ucykge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKGlkeCwgZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKGVsZW1lbnQpO1xuICAgICAgICAgICAgdmFyIGFkZFVybCA9IFVybHMud2lzaGxpc3RBZGQgKyAnP3BpZD0nICsgJGJ1dHRvbi5hdHRyKCdkYXRhLXBpZCcpO1xuICAgICAgICAgICAgJGJ1dHRvbi5yZW1vdmVDbGFzcygnd2lzaGxpc3QtaXRlbS1hZGRlZCcpLmFkZENsYXNzKCd3aXNobGlzdC1pdGVtLXJlYWR5Jyk7XG4gICAgICAgICAgICAkYnV0dG9uLmNzcygnZGlzcGxheScsICdpbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICRidXR0b24uYXR0cignZGF0YS11cmwnLCBhZGRVcmwpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCdkYXRhLWFjdGlvbicsICdBZGRJbnRlcm5hbCcpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCd0aXRsZScsICgkYnV0dG9uLmF0dHIoJ2RhdGEtdGl0bGUtYWRkJykgKyAnIC0gJyArIHNpemVUZXh0KSk7XG4gICAgICAgICAgICBpZiAoJGJ1dHRvbi5hdHRyKCdpZCcpID09ICd3aXNobGlzdC1idXR0b24nKSB7XG4gICAgICAgICAgICAgICAgJGJ1dHRvbi5maW5kKCdzcGFuJykuaHRtbCgkYnV0dG9uLmF0dHIoJ2RhdGEtYWRkLW1lc3NhZ2UnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBcbiAgICBpZiAoJCgnLnB0X3dpc2gtbGlzdCcpLmxlbmd0aCA+IDAgJiYgKHdpc2hsaXN0SXRlbUlkKSkge1xuICAgICAgICBpZiAoJ2xvY2FsU3RvcmFnZScgaW4gd2luZG93ICYmIHdpbmRvd1snbG9jYWxTdG9yYWdlJ10gIT09IG51bGwgJiYgJ1dpc2hsaXN0UHJvZHVjdElEcycgaW4gd2luZG93LmxvY2FsU3RvcmFnZSAmJiB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB2YXIgd2lzaGxpc3RJdGVtcyA9IEpTT04ucGFyc2Uod2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMpO1xuICAgICAgICAgICAgdmFyIHZhcmlhdGlvbk1vZGVsID0gd2lzaGxpc3RJdGVtcy5maWx0ZXIoZnVuY3Rpb24ocHJvZHVjdE9iamVjdCkge1xuICAgICAgICAgICAgICAgIGlmIChwcm9kdWN0T2JqZWN0LnByb2R1Y3RJRCA9PSB3aXNobGlzdEl0ZW1JZCB8fCBwcm9kdWN0T2JqZWN0Lm1hc3RlcklEID09IHdpc2hsaXN0SXRlbUlkIHx8IHByb2R1Y3RPYmplY3QudmFyaWFudHMuaW5kZXhPZih3aXNobGlzdEl0ZW1JZCkgPiAtMSkgeyBcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2R1Y3RPYmplY3Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodmFyaWF0aW9uTW9kZWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHdpc2hsaXN0SXRlbXNUb1JlbW92ZSA9IHZhcmlhdGlvbk1vZGVsWzBdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiB3aXNobGlzdEl0ZW1zVG9SZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gd2lzaGxpc3RJdGVtc1RvUmVtb3ZlW2tleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIG1hdGNoaW5nIHZhcmlhbnQgb3IgbWFzdGVyXG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgPT0gJ3Byb2R1Y3RJRCcgfHwga2V5ID09ICdtYXN0ZXJJRCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoJy5wcm9kdWN0LXRpbGVbZGF0YS1pdGVtaWQ9XCInK3ZhbHVlKydcIl0nKS5wYXJlbnRzKCdsaS53aXNobGlzdC1pdGVtJykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVsc2UsIGNoZWNrIHRoZSBvdGhlciB2YXJpYW50c1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhcmlhbnRzID0gdmFsdWUuc3BsaXQoJywnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChpIDwgdmFyaWFudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhcmlhbnRJRCA9IHZhcmlhbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5wcm9kdWN0LXRpbGVbZGF0YS1pdGVtaWQ9XCInK3ZhcmlhbnRJRCsnXCJdJykucGFyZW50cygnbGkud2lzaGxpc3QtaXRlbScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBJZiB1c2VyIHJlbW92ZXMgYWxsIHNoYXJlYWJsZSBwcm9kdWN0cyBmcm9tIHdpc2hsaXN0LCB0aGVuIGhpZGUgdGhlIHNoYXJlIHRvZ2dsZSBhbmQgc2V0IHRoZSB3aXNobGlzdCB0byBwcml2YXRlXG4gICAgICAgICAgICAgICAgaWYgKCQoJ2xpLndpc2hsaXN0LWl0ZW1bZGF0YS1zaGFyZWFibGUtaXRlbT1cInRydWVcIl0nKS5sZW5ndGggPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJy53aXNobGlzdC1zaGFyZS1jb250YWluZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICQoJy5zaGFyZS13aXNobGlzdC10b2dnbGUgaW5wdXRbbmFtZT1cInNoYXJlLXdpc2hsaXN0LWNoZWNrYm94XCJdJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCQoJ2xpLndpc2hsaXN0LWl0ZW0nKS5sZW5ndGggPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJy53aXNobGlzdC1tZXNzYWdlLmVtcHR5LXdpc2hsaXN0JykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcHJlcGFyZVdpc2hsaXN0UmVtb3ZlVUkoYnV0dG9ucywgc2l6ZVRleHQpIHtcbiAgICBpZiAoIWJ1dHRvbnMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGJ1dHRvbnMuZWFjaChmdW5jdGlvbihpZHgsIGVsZW1lbnQpIHtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJChlbGVtZW50KTtcbiAgICAgICAgICAgIHZhciByZW1vdmVVcmwgPSBVcmxzLndpc2hsaXN0UmVtb3ZlICsgJz9waWQ9JyArICRidXR0b24uYXR0cignZGF0YS1waWQnKTtcbiAgICAgICAgICAgICRidXR0b24ucmVtb3ZlQ2xhc3MoJ3dpc2hsaXN0LWl0ZW0tcmVhZHknKS5hZGRDbGFzcygnd2lzaGxpc3QtaXRlbS1hZGRlZCcpO1xuICAgICAgICAgICAgJGJ1dHRvbi5jc3MoJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyk7XG4gICAgICAgICAgICAkYnV0dG9uLmF0dHIoJ2RhdGEtdXJsJywgcmVtb3ZlVXJsKTtcbiAgICAgICAgICAgICRidXR0b24uYXR0cignZGF0YS1hY3Rpb24nLCAnUmVtb3ZlSW50ZXJuYWwnKTtcbiAgICAgICAgICAgICRidXR0b24uYXR0cigndGl0bGUnLCAoJGJ1dHRvbi5hdHRyKCdkYXRhLXRpdGxlLXJlbW92ZScpICsgJyAtICcgKyBzaXplVGV4dCkpO1xuICAgICAgICAgICAgaWYgKCRidXR0b24uYXR0cignaWQnKSA9PSAnd2lzaGxpc3QtYnV0dG9uJykge1xuICAgICAgICAgICAgICAgICRidXR0b24uZmluZCgnc3BhbicpLmh0bWwoJGJ1dHRvbi5hdHRyKCdkYXRhLXJlbW92ZS1tZXNzYWdlJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucygpIHtcbiAgICAkKCcud2lzaGxpc3QtaXRlbS1zdGF0dXMtYnV0dG9uJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpO1xuICAgICAgICB2YXIgd2lzaGxpc3RJdGVtSWQgPSAkYnV0dG9uLmF0dHIoJ2RhdGEtcGlkJyk7XG4gICAgICAgIGlmICh3aXNobGlzdEl0ZW1JZCAmJiB3aXNobGlzdEl0ZW1JZCAhPSAnJykge1xuICAgICAgICAgICAgdmFyIGlzV2lzaGxpc3RJdGVtID0gY2hlY2tXaXNobGlzdEZvckl0ZW0od2lzaGxpc3RJdGVtSWQpO1xuICAgICAgICAgICAgaWYgKGlzV2lzaGxpc3RJdGVtKSB7IFxuICAgICAgICAgICAgICAgIHByZXBhcmVXaXNobGlzdFJlbW92ZVVJKCRidXR0b24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVwYXJlV2lzaGxpc3RBZGRVSSgkYnV0dG9uLCB3aXNobGlzdEl0ZW1JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVFbWFpbEZvcm0oJGVtYWlsLCAkbWVzc2FnZSkge1x0XG4gICAgJCgnLnNoYXJlLXdpc2hsaXN0LW1lbnUtcG9wdXAgLmVycm9yLWNvbnRhaW5lcicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblxuICAgIHZhciByZWdleEVtYWlsID0gL15bYS16QS1aMC05LiEjJCUmJyorLz0/Xl9ge3x9fi1dK0BbYS16QS1aMC05LV0rKD86XFwuW2EtekEtWjAtOS1dKykqJC9nO1x0XG4gICAgdmFyIHJlZ2V4TWVzc2FnZSA9IC9eW0EtWmEtejAtOSBfLiwhXCInXFwvKCkkXSovZztcbiAgICB2YXIgZW1haWwgPSAkZW1haWwudmFsKCkudHJpbSgpO1xuICAgIHZhciBtZXNzYWdlID0gJG1lc3NhZ2UudmFsKCkudHJpbSgpO1xuXHR2YXIgZm9ybVZhbGlkYXRpb24gPSB0cnVlO1xuXHRcdFx0XG5cdGlmICgoIWVtYWlsIHx8IGVtYWlsLmxlbmd0aCA9PSAwKSB8fCBTdHJpbmcoZW1haWwpLm1hdGNoKHJlZ2V4RW1haWwpID09IG51bGwpIHtcblx0XHRmb3JtVmFsaWRhdGlvbiA9IGZhbHNlO1xuICAgICAgICAkZW1haWwuYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdCAgICAkKCcjc2hhcmUtd2lzaGxpc3QtZW1haWwtcG9wdXAgLmludmFsaWQtZW1haWwtZm9ybWF0JykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHR9XG4gICAgaWYgKCghbWVzc2FnZSB8fCBtZXNzYWdlLmxlbmd0aCA9PSAwKSB8fCBTdHJpbmcobWVzc2FnZSkubWF0Y2gocmVnZXhNZXNzYWdlKSA9PSBudWxsKSB7XG4gICAgICAgIGZvcm1WYWxpZGF0aW9uID0gZmFsc2U7XG4gICAgICAgICRtZXNzYWdlLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICAkKCcjc2hhcmUtd2lzaGxpc3QtZW1haWwtcG9wdXAgLmludmFsaWQtZW1haWwtbWVzc2FnZS1mb3JtYXQnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgfVxuXHRcdFx0XG5cdGlmICghZm9ybVZhbGlkYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW5pdCAoKSB7XG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgdXBkYXRlQ1NSRlRva2VuKCk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9uIHBhZ2UgbG9hZCwgbWFrZSBBSkFYIGNhbGwgdG8gZ2V0IHdpc2hsaXN0IGl0ZW1zIGFuZCBzdG9yZSBpbiBsb2NhbFN0b3JhZ2UuIEZyb20gbG9jYWxTdG9yYWdlLCBjb21wYXJlIHRoZSBpdGVtcyBiZWluZyBsb2FkZWQgb24gXG4gICAgICAgICAqIHBhZ2UgdG8gc2VlIGlmIGFueSBhcmUgaW4gd2lzaGxpc3QsIGFuZCBtYXJrIHRoZSBoZWFydCBpY29ucyBhY2NvcmRpbmdseS4gXG4gICAgICAgICAqL1xuICAgICAgICBpZiAoJ2xvY2FsU3RvcmFnZScgaW4gd2luZG93ICYmIHdpbmRvd1snbG9jYWxTdG9yYWdlJ10gIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIE9ubHkgbWFrZSBBSkFYIGNhbGwgdG8gZ2V0IHdpc2hsaXN0IHByb2R1Y3QgSURzIGlmIGN1c3RvbWVyIGlzIGxvZ2dlZCBpblxuICAgICAgICAgICAgaWYgKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiBVcmxzLndpc2hsaXN0R2V0SXRlbXMsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoJy53aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24nKS5jc3MoJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiYgJ3dpc2hsaXN0JyBpbiByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLndpc2hsaXN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyQWxsV2lzaGxpc3RCdXR0b25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLndpc2hsaXN0LWl0ZW0tc3RhdHVzLWJ1dHRvbicpLmNzcygnZGlzcGxheScsICdpbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTsgICBcbiAgICAgICAgICAgIC8vIElmIGd1ZXN0IHVzZXIsIGp1c3QgcmVuZGVyIHRoZSB3aXNobGlzdCBidXR0b25zIGFzIGVtcHR5XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gJyc7XG4gICAgICAgICAgICAgICAgcmVuZGVyQWxsV2lzaGxpc3RCdXR0b25zKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogT24gY2xpY2sgb2YgYSB3aXNobGlzdCBoZWFydCBidXR0b24sIG9wZW4gYSBsb2dpbiBkaWFsb2cgKGlmIGd1ZXN0IHVzZXIpIG9yIGFkZC9yZW1vdmUgaXRlbSBmcm9tIHdpc2hsaXN0IChpZiBsb2dnZWQtaW4gY3VzdG9tZXIpXG4gICAgICAgICAqL1xuICAgICAgICAkKCdib2R5Jykub24oJ2NsaWNrJywgJy53aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24sIC53aXNobGlzdC1idXR0b24nLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgICAgIHZhciB3aXNobGlzdFVybCA9ICRidXR0b24uYXR0cignZGF0YS11cmwnKTtcbiAgICAgICAgICAgIHZhciB3aXNobGlzdENvbnRyb2xsZXIgPSAkYnV0dG9uLmF0dHIoJ2RhdGEtY29udHJvbGxlcicpO1xuICAgICAgICAgICAgdmFyIHdpc2hsaXN0QWN0aW9uID0gJGJ1dHRvbi5hdHRyKCdkYXRhLWFjdGlvbicpO1xuICAgICAgICAgICAgdmFyIHByb2R1Y3RJRCA9ICRidXR0b24uYXR0cignZGF0YS1waWQnKTtcblxuICAgICAgICAgICAgdmFyIGlzUHJvZHVjdFBhZ2UgPSAkKCcucHRfcHJvZHVjdC1kZXRhaWxzJykubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGNvbnRpbnVlV2lzaGxpc3QgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoaXNQcm9kdWN0UGFnZSkge1xuICAgICAgICAgICAgICAgIHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHRcdFx0XHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0XHRcdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHRcdFx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cdFx0XHRcdHZhciBpc0NvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmICghaXNTaXplU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxlcnQoJ1BsZWFzZSBzZWxlY3QgYSBzaXplJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlV2lzaGxpc3QgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChjb250aW51ZVdpc2hsaXN0KSB7XG4gICAgICAgICAgICBcdC8vQ29yZGlhbCB3aXNobGlzdCBhZGQvcmVtb3ZlIGV2ZW50c1xuICAgICAgICAgICAgXHRpZiAoJGJ1dHRvbi5oYXNDbGFzcygnd2lzaGxpc3QtaXRlbS1hZGRlZCcpKSB7XG4gICAgXHRcdFx0XHRhZGRXaXNobGlzdEV2ZW50KCdyZW1vdmUnLCBwcm9kdWN0SUQpO1xuICAgIFx0XHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0XHRhZGRXaXNobGlzdEV2ZW50KCdhZGQnLCBwcm9kdWN0SUQpO1xuICAgIFx0XHRcdH1cbiAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgLy8gV0lTSExJU1QgUkVQT1JUSU5HOiBUcmFjayB3aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24gY2xpY2tzIChib3RoIGd1ZXN0IGFuZCBsb2dnZWQtaW4gdXNlcnMpXG4gICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMud2lzaGxpc3RUcmFja0FjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogd2lzaGxpc3RBY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBwaWQ6IHByb2R1Y3RJRFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dpc2hsaXN0LVRyYWNrQWN0aW9uczogRXJyb3IgaW4gaW5jcmVtZW50aW5nIHdpc2hsaXN0IGFjdGlvbiBjb3VudGVycy4gRVJST1IgVEVYVDogJyt0ZXh0U3RhdHVzKycsIEVSUk9SIFRIUk9XTjogJytlcnJvclRocm93bisnLicpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlKSB7fVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBndWVzdCB1c2VyLCBvcGVuIGEgbG9naW4gZGlhbG9nXG4gICAgICAgICAgICAgICAgaWYgKCFDdXN0b21lci5hdXRoZW50aWNhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJhbXMgPSB3aXNobGlzdFVybC5zdWJzdHJpbmcod2lzaGxpc3RVcmwuaW5kZXhPZignPycpLCB3aXNobGlzdFVybC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBsb2dpbkRpYWxvZy5zaG93KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9yIHJlcG9ydGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgW2RhdGEtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtbG9naW4tc291cmNlJywgJ3dpc2hsaXN0LW1vZGFsJyk7IFxuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgW2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLXBhc3N3b3JkbGVzcy1sb2dpbi1zb3VyY2UnLCAnd2lzaGxpc3QtbW9kYWwnKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgd2lzaGxpc3RDb250cm9sbGVyLCB3aXNobGlzdEFjdGlvbiwgcHJvZHVjdElELCBwYXJhbXMsIHdpc2hsaXN0VXJsKTtcbiAgICAgICAgICAgICAgICAvLyBFbHNlLCBpZiBsb2dnZWQtaW4gdXNlciwgYWxsb3cgY3VzdG9tZXIgdG8gYWRkL3JlbW92ZSB3aXNobGlzdCBpdGVtXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiB3aXNobGlzdFVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhlcnJvclRocm93biwgJ1dpc2hsaXN0IC0gRXJyb3InLCAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPlRoZXJlIHdhcyBhIHByb2JsZW0gaGFuZGxpbmcgeW91ciByZXF1ZXN0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5yZXN1bHQgJiYgcmVzcG9uc2UucmVzdWx0ID09ICdzdWNjZXNzJyAmJiByZXNwb25zZS5hY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5V2lzaGxpc3RJblN0b3JhZ2UocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuYWN0aW9uID09ICd3aXNobGlzdEl0ZW1SZW1vdmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb2R1Y3RJZFJlbW92ZWQgPSByZXNwb25zZSAmJiByZXNwb25zZS5mb3JtYXR0ZWREYXRhICYmIHJlc3BvbnNlLmZvcm1hdHRlZERhdGEucHJvZHVjdElEID8gcmVzcG9uc2UuZm9ybWF0dGVkRGF0YS5wcm9kdWN0SUQgOiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlcGFyZVdpc2hsaXN0QWRkVUkoJGJ1dHRvbiwgcHJvZHVjdElkUmVtb3ZlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVwYXJlV2lzaGxpc3RSZW1vdmVVSSgkYnV0dG9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5VbmFibGUgdG8gbW9kaWZ5IHdpc2hsaXN0IGF0IHRoaXMgdGltZS4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmFjdGlvbiA9PSAnd2lzaGxpc3RJdGVtUmVtb3ZlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5VbmFibGUgdG8gcmVtb3ZlIGl0ZW0gZnJvbSB3aXNobGlzdC4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nSHRtbCA9ICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+VW5hYmxlIHRvIGFkZCBpdGVtIHRvIHdpc2hsaXN0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcobnVsbCwgJ1dpc2hsaXN0IC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFkZCBwcm9kdWN0IHRvIGN1c3RvbWVyJ3MgY2FydCB3aGVuIFwiQWRkIHRvIENhcnRcIiBidXR0b24gaXMgY2xpY2tlZCBvbiBXaXNobGlzdCBwYWdlXG4gICAgICAgICAqL1xuICAgICAgICAkKCdib2R5Jykub24oJ2NsaWNrJywgJy53aXNobGlzdC1hZGQtdG8tY2FydC1idXR0b24nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBwcm9kdWN0SWQgPSAkYnV0dG9uLmF0dHIoJ2RhdGEtcGlkJyk7XG4gICAgICAgICAgICAkYnV0dG9uLmZpbmQoJ3NwYW4nKS5odG1sKCcnKTtcbiAgICAgICAgICAgIHByb2dyZXNzLnNob3coJGJ1dHRvbi5maW5kKCdzcGFuJyksIHRydWUpO1xuXG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICB1cmw6IFVybHMuYWRkUHJvZHVjdCxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICBwaWQ6IHByb2R1Y3RJZCxcbiAgICAgICAgICAgICAgICAgICAgIGNzcmZfdG9rZW46IHBhZ2VDb250ZXh0Lm9wdGlvbnMuVG9rZW5cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAkYnV0dG9uLmZpbmQoJ3NwYW4nKS5odG1sKCdBZGQgdG8gQ2FydCcpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGVycm9yVGhyb3duLCAnV2lzaGxpc3QgLSBFcnJvcicsICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+VW5hYmxlIHRvIGFkZCBpdGVtIHRvIGNhcnQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPicpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRtaW5pQ2FydEVsbSA9ICQoJy5taW5pLWNhcnQgLm1pbmljYXJ0LXF1YW50aXR5JykubGVuZ3RoID4gMCA/ICQoJy5taW5pLWNhcnQgLm1pbmljYXJ0LXF1YW50aXR5JykgOiAkKCcubWluaS1jYXJ0IC5idG4tbWluaWNhcnQgLmJ0bi1taW5pY2FydC1xdHknKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbmlDYXJ0VG90YWw7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkbWluaUNhcnRFbG0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluaUNhcnRUb3RhbCA9IHBhcnNlSW50KCRtaW5pQ2FydEVsbS5odG1sKCkudHJpbSgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSAgXG4gICAgICAgICAgICAgICAgICAgIG1pbmlDYXJ0VG90YWwrKzsgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgJG1pbmlDYXJ0RWxtLmh0bWwobWluaUNhcnRUb3RhbCk7XG4gICAgICAgICAgICAgICAgICAgICRidXR0b24uYXR0cignZGlzYWJsZWQnLCB0cnVlKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgJGJ1dHRvbi5maW5kKCdzcGFuJykuaHRtbCgnPGkgY2xhc3M9XCJmYSBmYS1jaGVja1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT4gSXRlbSBBZGRlZCcpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgZmlyZSB0aGlzIEFKQVggY2FsbCBpZiB0aGUgY3VzdG9tZXIgc3VjY2Vzc2Z1bGx5IGFkZGVkIHRoZSBwcm9kdWN0IHRvIHRoZWlyIGNhcnQuIE9uIGVycm9yIG9mIGFkZFByb2R1Y3QsIGRvIG5vdGhpbmcuXG4gICAgICAgICAgICAgICAgICAgIGlmIChDdXN0b21lci5hdXRoZW50aWNhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXSVNITElTVCBSRVBPUlRJTkc6IFRyYWNrICdBZGQgdG8gQ2FydCcgY2xpY2tzIGZyb20gd2lzaGxpc3QgcGFnZVxuICAgICAgICAgICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMud2lzaGxpc3RUcmFja0FkZFRvQ2FydCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dpc2hsaXN0LVRyYWNrQWRkVG9DYXJ0OiBFcnJvciBpbiBpbmNyZW1lbnRpbmcgd2lzaGxpc3QgQWRkLXRvLUNhcnQgY291bnRlci4gRVJST1IgVEVYVDogJyt0ZXh0U3RhdHVzKycsIEVSUk9SIFRIUk9XTjogJytlcnJvclRocm93bisnLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlKSB7fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICBcdHZhciB0aGlzSXRlbSA9ICQoJy5wcm9kdWN0LXRpbGVbZGF0YS1pdGVtaWQ9XCInK3Byb2R1Y3RJZCsnXCJdJyk7XG4gICAgICAgICAgICBcdHZhciBpdGVtTWV0YSA9IEpTT04ucGFyc2UoJCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEuZXZlbnQtYnJvd3NlW2RhdGEtcGlkPVwiJytwcm9kdWN0SWQrJ1wiXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0XHRcdFx0dmFyIGNhcnRfZGF0YSA9IFt7XG5cdFx0XHRcdCAgICAncHJvZHVjdElEJzogaXRlbU1ldGFbXCJpZFwiXSxcblx0XHRcdFx0ICAgICdza3UnOiBpdGVtTWV0YVtcInNrdWlkXCJdLFxuXHRcdFx0XHQgICAgJ2NhdGVnb3J5JzogaXRlbU1ldGFbXCJjYXRlZ29yeVwiXS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFx0XHQgICAgJ25hbWUnOiBpdGVtTWV0YVtcIm5hbWVcIl0ucmVwbGFjZSgvXFxcXC9nLCBcIlwiKSxcblx0XHRcdFx0ICAgICdxdHknOiAnMScsIFxuXHRcdFx0XHQgICAgJ2l0ZW1QcmljZSc6IGl0ZW1NZXRhW1wicHJpY2VcIl0sXG5cdFx0XHRcdCAgICAnaW1hZ2UnOiB0aGlzSXRlbS5maW5kKCcudGlsZS1pbWFnZScpLmF0dHIoJ3NyYycpLFxuXHRcdFx0XHQgICAgJ3VybCc6IHRoaXNJdGVtLmZpbmQoJy50aHVtYi1saW5rJykuYXR0cignaHJlZicpLFxuXHRcdFx0XHQgICAgJ2F0dHInOiB7XG5cdFx0XHRcdCAgICAgICAgJ21hbnVmYWN0dXJlcic6IGl0ZW1NZXRhW1wiYnJhbmRcIl0sXG5cdFx0XHRcdCAgICBcdCdjb2xvcic6IHRoaXNJdGVtLmZpbmQoJy5wcm9kdWN0LWNvbG9yJykudGV4dCgpLnJlcGxhY2UoJ0NvbG9yOiAnLFwiXCIpLFxuXHRcdFx0XHQgICAgICAgICdzaXplJzogdGhpc0l0ZW0uZmluZCgnLnByb2R1Y3Qtc2l6ZScpLnRleHQoKS5yZXBsYWNlKCdTaXplOiAnLFwiXCIpXG5cdFx0XHRcdCAgICB9XG5cdFx0XHRcdH1dO1xuXG5cdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFsnY2FydCcsICd1cGRhdGUnXSxcblx0XHRcdFx0XHRcdFsnY2FydGl0ZW0nLCAnYWRkJyAsIGNhcnRfZGF0YV0sIFxuXHRcdFx0XHRcdFx0WydldmVudCcsICdjYXJ0J11cblx0XHRcdFx0XHRdKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuICAgICAgICB9KTtcblxuICAgICAgICAkKCdib2R5Jykub24oJ2NsaWNrJywgJyNtb2JpbGUtc2hhcmUtd2lzaGxpc3QtYnV0dG9uJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAkKCcud2lzaGxpc3Qtc2hhcmUtbW9iaWxlLWNvbnRhaW5lcicpLnNsaWRlVG9nZ2xlKCdzbG93Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICAkKCdib2R5Jykub24oJ2NoYW5nZScsICcuc2hhcmUtd2lzaGxpc3QtdG9nZ2xlIGlucHV0W25hbWU9XCJzaGFyZS13aXNobGlzdC1jaGVja2JveFwiXScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHN0YXR1cyA9ICQodGhpcykuaXMoJzpjaGVja2VkJyk7XG4gICAgICAgICAgICBpZiAoc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgJCgnI3NoYXJlLXdpc2hsaXN0LW1lbnUnKS5zbGlkZURvd24oJ3Nsb3cnKS5jc3MoJ2Rpc3BsYXknLCdmbGV4Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICQoJyNzaGFyZS13aXNobGlzdC1tZW51Jykuc2xpZGVVcCgnc2xvdycpLnJlbW92ZUNsYXNzKCdzaG93LXNoYXJlLXdpc2hsaXN0LW1lbnUnKS5jc3MoJ2Rpc3BsYXknLCdub25lJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoQ3VzdG9tZXIuYXV0aGVudGljYXRlZCkge1xuICAgICAgICAgICAgICAgIHZhciB3aXNobGlzdElEID0gJCgnaW5wdXRbbmFtZT1cImN1cnJlbnRfd2lzaGxpc3RfaWRcIl0nKS52YWwoKS50cmltKCk7XG4gICAgICAgICAgICAgICAgaWYgKHdpc2hsaXN0SUQpIHtcbiAgICAgICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMud2lzaGxpc3RTZXRQdWJsaWMsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgV2lzaGxpc3RJRDogd2lzaGxpc3RJRCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZXRQdWJsaWM6IHN0YXR1c1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KS5kb25lKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UucmVzdWx0ID09ICdlcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKG51bGwsICcnLCAnV2lzaGxpc3QgU2hhcmUgLSBFcnJvcicsICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+T29wcywgc29tZXRoaW5nIHdlbnQgd3JvbmcgYW5kIGNhbm5vdCB1cGRhdGUgeW91ciBXaXNobGlzdCBhdCB0aGlzIHRpbWUuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5yZXN1bHQgPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm8gb24tc2NyZWVuIHZpc3VhbHMgbmVlZCB0byBvY2N1clxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKG51bGwsICcnLCAnV2lzaGxpc3QgU2hhcmUgLSBFcnJvcicsICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+T29wcywgc29tZXRoaW5nIHdlbnQgd3JvbmcgYW5kIHdlIGNvdWxkIG5vdCByZXRyaWV2ZSB5b3VyIFdpc2hsaXN0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5hY2NvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCgnYm9keScpLm9uKCdjbGljaycsICcuc2hhcmUtd2lzaGxpc3QtbWVudS1wb3B1cCAuY2xvc2UtYnV0dG9uJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICAgICAgJHRoaXMucGFyZW50cygnLnNoYXJlLXdpc2hsaXN0LW1lbnUtcG9wdXAnKS5hZGRDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICB2YXIgc2hhcmVMaW5rID0gJHRoaXMucGFyZW50cygnLnNoYXJlLXdpc2hsaXN0LW1lbnUtcG9wdXAnKS5hdHRyKCdpZCcpLmluZGV4T2YoJ2xpbmstcG9wdXAnKSA+IC0xO1xuICAgICAgICAgICAgaWYgKHNoYXJlTGluaykge1xuICAgICAgICAgICAgICAgICR0aGlzLnNpYmxpbmdzKCcuZm9ybS1yb3ctYnV0dG9uJykuZmluZCgnYnV0dG9uW25hbWU9XCJzaGFyZS13aXNobGlzdC1saW5rLWNvcHlcIl0nKS5yZW1vdmVDbGFzcygnYnRuLWNvbXBsZXRlIGRpc2FibGVkJykuaHRtbCgnQ29weScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCgnYm9keScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZT1cInNoYXJlLXdpc2hsaXN0LWxpbmstY29weVwiXTpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpO1xuICAgICAgICAgICAgdmFyIHdpc2hsaXN0VXJsID0gJCgnI3NoYXJlLXdpc2hsaXN0LWxpbmstcG9wdXAgLnNoYXJlLXdpc2hsaXN0LXVybCBhJykuaHRtbCgpO1xuICAgICAgICAgICAgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQod2lzaGxpc3RVcmwpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hZGRDbGFzcygnYnRuLWNvbXBsZXRlIGRpc2FibGVkJykuaHRtbCgnPGkgY2xhc3M9XCJmYSBmYS1jaGVja1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT4gQ29waWVkIScpO1xuICAgICAgICB9KTtcbiAgICAgICAgJCgnYm9keScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZT1cInNoYXJlLXdpc2hsaXN0LWVtYWlsLXNlbmRcIl06bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgICAgICB2YXIgJGVtYWlsID0gJCgnI3dpc2hsaXN0LXNoYXJlLWVtYWlsLWlucHV0Jyk7XG4gICAgICAgICAgICB2YXIgJG1lc3NhZ2UgPSAkKCcjd2lzaGxpc3Qtc2hhcmUtZW1haWwtbWVzc2FnZScpO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWRFbWFpbEZvcm0gPSB2YWxpZGF0ZUVtYWlsRm9ybSgkZW1haWwsICRtZXNzYWdlKTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkRW1haWxGb3JtKSB7XG4gICAgICAgICAgICAgICAgaWYgKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdpc2hsaXN0SUQgPSAkKCdpbnB1dFtuYW1lPVwiY3VycmVudF93aXNobGlzdF9pZFwiXScpLnZhbCgpLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpc2hsaXN0SUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiBVcmxzLndpc2hsaXN0U2hhcmVCeUVtYWlsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2lzaGxpc3RJRDogd2lzaGxpc3RJRCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG9FbWFpbDogJGVtYWlsLnZhbCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbWFpbE1lc3NhZ2U6ICRtZXNzYWdlLnZhbCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSkuZG9uZShmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5yZXN1bHQgPT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKG51bGwsICcnLCAnV2lzaGxpc3QgU2hhcmUgLSBFcnJvcicsICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+T29wcywgc29tZXRoaW5nIHdlbnQgd3JvbmcgYW5kIGNvdWxkIG5vdCBzZW5kIHlvdXIgV2lzaGxpc3QgZW1haWwuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UucmVzdWx0ID09ICdzdWNjZXNzJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy5wYXJlbnRzKCcjc2hhcmUtd2lzaGxpc3QtZW1haWwtcG9wdXAnKS5hZGRDbGFzcygnc2hhcmUtd2lzaGxpc3QtZW1haWwtc3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhudWxsLCAnJywgJ1dpc2hsaXN0IFNoYXJlIC0gRXJyb3InLCAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIGFuZCB3ZSBjb3VsZCBub3QgcmV0cmlldmUgeW91ciBXaXNobGlzdCBmb3Igc2hhcmluZy4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuYWNjb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAkKCdib2R5Jykub24oJ2NsaWNrJywgJyNzaGFyZS13aXNobGlzdC1tZW51IC5idG4tb3BlbicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpO1xuICAgICAgICAgICAgdmFyICRzaGFyZVBvcHVwID0gJGJ1dHRvbi5zaWJsaW5ncygnLnNoYXJlLXdpc2hsaXN0LW1lbnUtcG9wdXAnKTtcbiAgICAgICAgICAgIGlmICgkc2hhcmVQb3B1cC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkc2hhcmVQb3B1cC5yZW1vdmVDbGFzcygnZC1ub25lIHNoYXJlLXdpc2hsaXN0LWVtYWlsLXN1Y2Nlc3MnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydHMuY2hlY2tXaXNobGlzdEZvckl0ZW0gPSBjaGVja1dpc2hsaXN0Rm9ySXRlbTtcbmV4cG9ydHMucHJlcGFyZVdpc2hsaXN0QWRkVUkgPSBwcmVwYXJlV2lzaGxpc3RBZGRVSTtcbmV4cG9ydHMucHJlcGFyZVdpc2hsaXN0UmVtb3ZlVUkgPSBwcmVwYXJlV2lzaGxpc3RSZW1vdmVVSTtcbmV4cG9ydHMucmVuZGVyQWxsV2lzaGxpc3RCdXR0b25zID0gcmVuZGVyQWxsV2lzaGxpc3RCdXR0b25zO1xuZXhwb3J0cy5pbml0ID0gaW5pdDsiLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuU2xpY2tTbGlkZXIgPSB7XG5cdE9wdGlvbnM6IHtcblx0XHRTaW5nbGU6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0aW5maW5pdGU6IFx0XHR0cnVlLFxuXHRcdFx0ZG90czogXHRcdFx0ZmFsc2UsXG5cdFx0XHRhcnJvd3M6IFx0XHRmYWxzZSxcblx0XHRcdHNsaWRlc1RvU2hvdzogXHQxLFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDEsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2Nyxcblx0XHRcdFx0XHRzZXR0aW5nczogXHR7XG5cdFx0XHRcdFx0XHRkb3RzOiB0cnVlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSxcblx0XHRUaHVtYm5haWw6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0ZHJhZ2dhYmxlOiB0cnVlLFxuXHRcdFx0aW5maW5pdGU6IGZhbHNlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBmYWxzZSxcblx0XHRcdHNsaWRlc1RvU2hvdzogNyxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiA3XG5cdFx0fSxcblx0XHRDYXRlZ29yeUxhbmRpbmc6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0ZHJhZ2dhYmxlOiB0cnVlLFxuXHRcdFx0aW5maW5pdGU6IHRydWUsXG5cdFx0XHRmb2N1c09uU2VsZWN0OiBcdGZhbHNlLFxuXHRcdFx0ZG90czogZmFsc2UsXG5cdFx0XHRhcnJvd3M6IHRydWUsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDQsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogNCxcblx0XHRcdHJlc3BvbnNpdmU6IFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogNzY3XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwLFxuXHRcdFx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Nob3c6IDMsXG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Njcm9sbDogM1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH1cblx0fVxufSIsIm1vZHVsZS5leHBvcnRzPXtcIk5ZXCI6e1wiMDA1XCI6dHJ1ZSxcIjA2M1wiOnRydWUsXCIxMDBcIjp0cnVlLFwiMTAxXCI6dHJ1ZSxcIjEwMlwiOnRydWUsXCIxMDNcIjp0cnVlLFwiMTA0XCI6dHJ1ZSxcIjEwNVwiOnRydWUsXCIxMDZcIjp0cnVlLFwiMTA3XCI6dHJ1ZSxcIjEwOFwiOnRydWUsXCIxMDlcIjp0cnVlLFwiMTEwXCI6dHJ1ZSxcIjExMVwiOnRydWUsXCIxMTJcIjp0cnVlLFwiMTEzXCI6dHJ1ZSxcIjExNFwiOnRydWUsXCIxMTVcIjp0cnVlLFwiMTE2XCI6dHJ1ZSxcIjExN1wiOnRydWUsXCIxMThcIjp0cnVlLFwiMTE5XCI6dHJ1ZSxcIjEyMFwiOnRydWUsXCIxMjFcIjp0cnVlLFwiMTIyXCI6dHJ1ZSxcIjEyM1wiOnRydWUsXCIxMjRcIjp0cnVlLFwiMTI1XCI6dHJ1ZSxcIjEyNlwiOnRydWUsXCIxMjdcIjp0cnVlLFwiMTI4XCI6dHJ1ZSxcIjEyOVwiOnRydWUsXCIxMzBcIjp0cnVlLFwiMTMxXCI6dHJ1ZSxcIjEzMlwiOnRydWUsXCIxMzNcIjp0cnVlLFwiMTM0XCI6dHJ1ZSxcIjEzNVwiOnRydWUsXCIxMzZcIjp0cnVlLFwiMTM3XCI6dHJ1ZSxcIjEzOFwiOnRydWUsXCIxMzlcIjp0cnVlLFwiMTQwXCI6dHJ1ZSxcIjE0MVwiOnRydWUsXCIxNDJcIjp0cnVlLFwiMTQzXCI6dHJ1ZSxcIjE0NFwiOnRydWUsXCIxNDVcIjp0cnVlLFwiMTQ2XCI6dHJ1ZSxcIjE0N1wiOnRydWUsXCIxNDhcIjp0cnVlLFwiMTQ5XCI6dHJ1ZX0sXCJQUlwiOntcIjAwNlwiOnRydWUsXCIwMDdcIjp0cnVlLFwiMDA4XCI6dHJ1ZSxcIjAwOVwiOnRydWV9LFwiVklcIjp7XCIwMDZcIjp0cnVlLFwiMDA3XCI6dHJ1ZSxcIjAwOFwiOnRydWUsXCIwMDlcIjp0cnVlfSxcIk1BXCI6e1wiMDEwXCI6dHJ1ZSxcIjAxMVwiOnRydWUsXCIwMTJcIjp0cnVlLFwiMDEzXCI6dHJ1ZSxcIjAxNFwiOnRydWUsXCIwMTVcIjp0cnVlLFwiMDE2XCI6dHJ1ZSxcIjAxN1wiOnRydWUsXCIwMThcIjp0cnVlLFwiMDE5XCI6dHJ1ZSxcIjAyMFwiOnRydWUsXCIwMjFcIjp0cnVlLFwiMDIyXCI6dHJ1ZSxcIjAyM1wiOnRydWUsXCIwMjRcIjp0cnVlLFwiMDI1XCI6dHJ1ZSxcIjAyNlwiOnRydWUsXCIwMjdcIjp0cnVlLFwiMDU1XCI6dHJ1ZX0sXCJSSVwiOntcIjAyOFwiOnRydWUsXCIwMjlcIjp0cnVlfSxcIk5IXCI6e1wiMDMwXCI6dHJ1ZSxcIjAzMVwiOnRydWUsXCIwMzJcIjp0cnVlLFwiMDMzXCI6dHJ1ZSxcIjAzNFwiOnRydWUsXCIwMzVcIjp0cnVlLFwiMDM2XCI6dHJ1ZSxcIjAzN1wiOnRydWUsXCIwMzhcIjp0cnVlLFwiMDM5XCI6dHJ1ZX0sXCJWVFwiOntcIjAzNVwiOnRydWUsXCIwMzZcIjp0cnVlLFwiMDM3XCI6dHJ1ZSxcIjA1MFwiOnRydWUsXCIwNTFcIjp0cnVlLFwiMDUyXCI6dHJ1ZSxcIjA1M1wiOnRydWUsXCIwNTRcIjp0cnVlLFwiMDU2XCI6dHJ1ZSxcIjA1N1wiOnRydWUsXCIwNThcIjp0cnVlLFwiMDU5XCI6dHJ1ZX0sXCJNRVwiOntcIjAzOVwiOnRydWUsXCIwNDBcIjp0cnVlLFwiMDQxXCI6dHJ1ZSxcIjA0MlwiOnRydWUsXCIwNDNcIjp0cnVlLFwiMDQ0XCI6dHJ1ZSxcIjA0NVwiOnRydWUsXCIwNDZcIjp0cnVlLFwiMDQ3XCI6dHJ1ZSxcIjA0OFwiOnRydWUsXCIwNDlcIjp0cnVlfSxcIkNUXCI6e1wiMDYwXCI6dHJ1ZSxcIjA2MVwiOnRydWUsXCIwNjJcIjp0cnVlLFwiMDYzXCI6dHJ1ZSxcIjA2NFwiOnRydWUsXCIwNjVcIjp0cnVlLFwiMDY2XCI6dHJ1ZSxcIjA2N1wiOnRydWUsXCIwNjhcIjp0cnVlLFwiMDY5XCI6dHJ1ZX0sXCJOSlwiOntcIjA3MFwiOnRydWUsXCIwNzFcIjp0cnVlLFwiMDcyXCI6dHJ1ZSxcIjA3M1wiOnRydWUsXCIwNzRcIjp0cnVlLFwiMDc1XCI6dHJ1ZSxcIjA3NlwiOnRydWUsXCIwNzdcIjp0cnVlLFwiMDc4XCI6dHJ1ZSxcIjA3OVwiOnRydWUsXCIwODBcIjp0cnVlLFwiMDgxXCI6dHJ1ZSxcIjA4MlwiOnRydWUsXCIwODNcIjp0cnVlLFwiMDg0XCI6dHJ1ZSxcIjA4NVwiOnRydWUsXCIwODZcIjp0cnVlLFwiMDg3XCI6dHJ1ZSxcIjA4OFwiOnRydWUsXCIwODlcIjp0cnVlfSxcIkFFXCI6e1wiMDkwXCI6dHJ1ZSxcIjA5MVwiOnRydWUsXCIwOTJcIjp0cnVlLFwiMDkzXCI6dHJ1ZSxcIjA5NFwiOnRydWUsXCIwOTVcIjp0cnVlLFwiMDk2XCI6dHJ1ZSxcIjA5N1wiOnRydWUsXCIwOThcIjp0cnVlLFwiMDk5XCI6dHJ1ZX0sXCJQQVwiOntcIjE1MFwiOnRydWUsXCIxNTFcIjp0cnVlLFwiMTUyXCI6dHJ1ZSxcIjE1M1wiOnRydWUsXCIxNTRcIjp0cnVlLFwiMTU1XCI6dHJ1ZSxcIjE1NlwiOnRydWUsXCIxNTdcIjp0cnVlLFwiMTU4XCI6dHJ1ZSxcIjE1OVwiOnRydWUsXCIxNjBcIjp0cnVlLFwiMTYxXCI6dHJ1ZSxcIjE2MlwiOnRydWUsXCIxNjNcIjp0cnVlLFwiMTY0XCI6dHJ1ZSxcIjE2NVwiOnRydWUsXCIxNjZcIjp0cnVlLFwiMTY3XCI6dHJ1ZSxcIjE2OFwiOnRydWUsXCIxNjlcIjp0cnVlLFwiMTcwXCI6dHJ1ZSxcIjE3MVwiOnRydWUsXCIxNzJcIjp0cnVlLFwiMTczXCI6dHJ1ZSxcIjE3NFwiOnRydWUsXCIxNzVcIjp0cnVlLFwiMTc2XCI6dHJ1ZSxcIjE3N1wiOnRydWUsXCIxNzhcIjp0cnVlLFwiMTc5XCI6dHJ1ZSxcIjE4MFwiOnRydWUsXCIxODFcIjp0cnVlLFwiMTgyXCI6dHJ1ZSxcIjE4M1wiOnRydWUsXCIxODRcIjp0cnVlLFwiMTg1XCI6dHJ1ZSxcIjE4NlwiOnRydWUsXCIxODdcIjp0cnVlLFwiMTg4XCI6dHJ1ZSxcIjE4OVwiOnRydWUsXCIxOTBcIjp0cnVlLFwiMTkxXCI6dHJ1ZSxcIjE5MlwiOnRydWUsXCIxOTNcIjp0cnVlLFwiMTk0XCI6dHJ1ZSxcIjE5NVwiOnRydWUsXCIxOTZcIjp0cnVlLFwiMTk3XCI6dHJ1ZX0sXCJERVwiOntcIjE5N1wiOnRydWUsXCIxOThcIjp0cnVlLFwiMTk5XCI6dHJ1ZX0sXCJEQ1wiOntcIjIwMFwiOnRydWUsXCIyMDJcIjp0cnVlLFwiMjAzXCI6dHJ1ZSxcIjIwNFwiOnRydWUsXCIyMDVcIjp0cnVlfSxcIlZBXCI6e1wiMjAxXCI6dHJ1ZSxcIjIyMFwiOnRydWUsXCIyMjFcIjp0cnVlLFwiMjIyXCI6dHJ1ZSxcIjIyM1wiOnRydWUsXCIyMjRcIjp0cnVlLFwiMjI1XCI6dHJ1ZSxcIjIyNlwiOnRydWUsXCIyMjdcIjp0cnVlLFwiMjI4XCI6dHJ1ZSxcIjIyOVwiOnRydWUsXCIyMzBcIjp0cnVlLFwiMjMxXCI6dHJ1ZSxcIjIzMlwiOnRydWUsXCIyMzNcIjp0cnVlLFwiMjM0XCI6dHJ1ZSxcIjIzNVwiOnRydWUsXCIyMzZcIjp0cnVlLFwiMjM3XCI6dHJ1ZSxcIjIzOFwiOnRydWUsXCIyMzlcIjp0cnVlLFwiMjQwXCI6dHJ1ZSxcIjI0MVwiOnRydWUsXCIyNDJcIjp0cnVlLFwiMjQzXCI6dHJ1ZSxcIjI0NFwiOnRydWUsXCIyNDVcIjp0cnVlLFwiMjQ2XCI6dHJ1ZX0sXCJNRFwiOntcIjIwNlwiOnRydWUsXCIyMDdcIjp0cnVlLFwiMjA4XCI6dHJ1ZSxcIjIwOVwiOnRydWUsXCIyMTBcIjp0cnVlLFwiMjExXCI6dHJ1ZSxcIjIxMlwiOnRydWUsXCIyMTRcIjp0cnVlLFwiMjE1XCI6dHJ1ZSxcIjIxNlwiOnRydWUsXCIyMTdcIjp0cnVlLFwiMjE4XCI6dHJ1ZSxcIjIxOVwiOnRydWUsXCIyNjdcIjp0cnVlfSxcIldWXCI6e1wiMjQ2XCI6dHJ1ZSxcIjI0N1wiOnRydWUsXCIyNDhcIjp0cnVlLFwiMjQ5XCI6dHJ1ZSxcIjI1MFwiOnRydWUsXCIyNTFcIjp0cnVlLFwiMjUyXCI6dHJ1ZSxcIjI1M1wiOnRydWUsXCIyNTRcIjp0cnVlLFwiMjU1XCI6dHJ1ZSxcIjI1NlwiOnRydWUsXCIyNTdcIjp0cnVlLFwiMjU4XCI6dHJ1ZSxcIjI1OVwiOnRydWUsXCIyNjBcIjp0cnVlLFwiMjYxXCI6dHJ1ZSxcIjI2MlwiOnRydWUsXCIyNjNcIjp0cnVlLFwiMjY0XCI6dHJ1ZSxcIjI2NVwiOnRydWUsXCIyNjZcIjp0cnVlLFwiMjY3XCI6dHJ1ZSxcIjI2OFwiOnRydWV9LFwiTkNcIjp7XCIyNzBcIjp0cnVlLFwiMjcxXCI6dHJ1ZSxcIjI3MlwiOnRydWUsXCIyNzNcIjp0cnVlLFwiMjc0XCI6dHJ1ZSxcIjI3NVwiOnRydWUsXCIyNzZcIjp0cnVlLFwiMjc3XCI6dHJ1ZSxcIjI3OFwiOnRydWUsXCIyNzlcIjp0cnVlLFwiMjgwXCI6dHJ1ZSxcIjI4MVwiOnRydWUsXCIyODJcIjp0cnVlLFwiMjgzXCI6dHJ1ZSxcIjI4NFwiOnRydWUsXCIyODVcIjp0cnVlLFwiMjg2XCI6dHJ1ZSxcIjI4N1wiOnRydWUsXCIyODhcIjp0cnVlLFwiMjg5XCI6dHJ1ZSxcIjI5N1wiOnRydWV9LFwiU0NcIjp7XCIyOTBcIjp0cnVlLFwiMjkxXCI6dHJ1ZSxcIjI5MlwiOnRydWUsXCIyOTNcIjp0cnVlLFwiMjk0XCI6dHJ1ZSxcIjI5NVwiOnRydWUsXCIyOTZcIjp0cnVlLFwiMjk3XCI6dHJ1ZSxcIjI5OFwiOnRydWUsXCIyOTlcIjp0cnVlfSxcIkdBXCI6e1wiMjk4XCI6dHJ1ZSxcIjI5OVwiOnRydWUsXCIzMDBcIjp0cnVlLFwiMzAxXCI6dHJ1ZSxcIjMwMlwiOnRydWUsXCIzMDNcIjp0cnVlLFwiMzA0XCI6dHJ1ZSxcIjMwNVwiOnRydWUsXCIzMDZcIjp0cnVlLFwiMzA3XCI6dHJ1ZSxcIjMwOFwiOnRydWUsXCIzMDlcIjp0cnVlLFwiMzEwXCI6dHJ1ZSxcIjMxMVwiOnRydWUsXCIzMTJcIjp0cnVlLFwiMzEzXCI6dHJ1ZSxcIjMxNFwiOnRydWUsXCIzMTVcIjp0cnVlLFwiMzE2XCI6dHJ1ZSxcIjMxN1wiOnRydWUsXCIzMThcIjp0cnVlLFwiMzE5XCI6dHJ1ZSxcIjM5OFwiOnRydWUsXCIzOTlcIjp0cnVlfSxcIkZMXCI6e1wiMzIwXCI6dHJ1ZSxcIjMyMVwiOnRydWUsXCIzMjJcIjp0cnVlLFwiMzIzXCI6dHJ1ZSxcIjMyNFwiOnRydWUsXCIzMjVcIjp0cnVlLFwiMzI2XCI6dHJ1ZSxcIjMyN1wiOnRydWUsXCIzMjhcIjp0cnVlLFwiMzI5XCI6dHJ1ZSxcIjMzMFwiOnRydWUsXCIzMzFcIjp0cnVlLFwiMzMyXCI6dHJ1ZSxcIjMzM1wiOnRydWUsXCIzMzRcIjp0cnVlLFwiMzM1XCI6dHJ1ZSxcIjMzNlwiOnRydWUsXCIzMzdcIjp0cnVlLFwiMzM4XCI6dHJ1ZSxcIjMzOVwiOnRydWUsXCIzNDFcIjp0cnVlLFwiMzQyXCI6dHJ1ZSxcIjM0NFwiOnRydWUsXCIzNDZcIjp0cnVlLFwiMzQ3XCI6dHJ1ZSxcIjM0OVwiOnRydWV9LFwiQUFcIjp7XCIzMzFcIjp0cnVlLFwiMzQwXCI6dHJ1ZX0sXCJBUFwiOntcIjM0MFwiOnRydWUsXCI5NjJcIjp0cnVlLFwiOTYzXCI6dHJ1ZSxcIjk2NFwiOnRydWUsXCI5NjVcIjp0cnVlLFwiOTY2XCI6dHJ1ZX0sXCJBTFwiOntcIjM1MFwiOnRydWUsXCIzNTFcIjp0cnVlLFwiMzUyXCI6dHJ1ZSxcIjM1NFwiOnRydWUsXCIzNTVcIjp0cnVlLFwiMzU2XCI6dHJ1ZSxcIjM1N1wiOnRydWUsXCIzNThcIjp0cnVlLFwiMzU5XCI6dHJ1ZSxcIjM2MFwiOnRydWUsXCIzNjFcIjp0cnVlLFwiMzYyXCI6dHJ1ZSxcIjM2M1wiOnRydWUsXCIzNjRcIjp0cnVlLFwiMzY1XCI6dHJ1ZSxcIjM2NlwiOnRydWUsXCIzNjdcIjp0cnVlLFwiMzY4XCI6dHJ1ZSxcIjM2OVwiOnRydWV9LFwiTVNcIjp7XCIzNjlcIjp0cnVlLFwiMzcwXCI6dHJ1ZSxcIjM4NlwiOnRydWUsXCIzODdcIjp0cnVlLFwiMzg4XCI6dHJ1ZSxcIjM4OVwiOnRydWUsXCIzOTBcIjp0cnVlLFwiMzkxXCI6dHJ1ZSxcIjM5MlwiOnRydWUsXCIzOTNcIjp0cnVlLFwiMzk0XCI6dHJ1ZSxcIjM5NVwiOnRydWUsXCIzOTZcIjp0cnVlLFwiMzk3XCI6dHJ1ZX0sXCJUTlwiOntcIjM3MFwiOnRydWUsXCIzNzFcIjp0cnVlLFwiMzcyXCI6dHJ1ZSxcIjM3M1wiOnRydWUsXCIzNzRcIjp0cnVlLFwiMzc1XCI6dHJ1ZSxcIjM3NlwiOnRydWUsXCIzNzdcIjp0cnVlLFwiMzc4XCI6dHJ1ZSxcIjM3OVwiOnRydWUsXCIzODBcIjp0cnVlLFwiMzgxXCI6dHJ1ZSxcIjM4MlwiOnRydWUsXCIzODNcIjp0cnVlLFwiMzg0XCI6dHJ1ZSxcIjM4NVwiOnRydWUsXCIzODZcIjp0cnVlLFwiNzIzXCI6dHJ1ZX0sXCJLWVwiOntcIjQwMFwiOnRydWUsXCI0MDFcIjp0cnVlLFwiNDAyXCI6dHJ1ZSxcIjQwM1wiOnRydWUsXCI0MDRcIjp0cnVlLFwiNDA1XCI6dHJ1ZSxcIjQwNlwiOnRydWUsXCI0MDdcIjp0cnVlLFwiNDA4XCI6dHJ1ZSxcIjQwOVwiOnRydWUsXCI0MTBcIjp0cnVlLFwiNDExXCI6dHJ1ZSxcIjQxMlwiOnRydWUsXCI0MTNcIjp0cnVlLFwiNDE0XCI6dHJ1ZSxcIjQxNVwiOnRydWUsXCI0MTZcIjp0cnVlLFwiNDE3XCI6dHJ1ZSxcIjQxOFwiOnRydWUsXCI0MjBcIjp0cnVlLFwiNDIxXCI6dHJ1ZSxcIjQyMlwiOnRydWUsXCI0MjNcIjp0cnVlLFwiNDI0XCI6dHJ1ZSxcIjQyNVwiOnRydWUsXCI0MjZcIjp0cnVlLFwiNDI3XCI6dHJ1ZSxcIjQ3MVwiOnRydWV9LFwiT0hcIjp7XCI0MTBcIjp0cnVlLFwiNDMwXCI6dHJ1ZSxcIjQzMVwiOnRydWUsXCI0MzJcIjp0cnVlLFwiNDMzXCI6dHJ1ZSxcIjQzNFwiOnRydWUsXCI0MzVcIjp0cnVlLFwiNDM2XCI6dHJ1ZSxcIjQzN1wiOnRydWUsXCI0MzhcIjp0cnVlLFwiNDM5XCI6dHJ1ZSxcIjQ0MFwiOnRydWUsXCI0NDFcIjp0cnVlLFwiNDQyXCI6dHJ1ZSxcIjQ0M1wiOnRydWUsXCI0NDRcIjp0cnVlLFwiNDQ1XCI6dHJ1ZSxcIjQ0NlwiOnRydWUsXCI0NDdcIjp0cnVlLFwiNDQ4XCI6dHJ1ZSxcIjQ0OVwiOnRydWUsXCI0NTBcIjp0cnVlLFwiNDUxXCI6dHJ1ZSxcIjQ1MlwiOnRydWUsXCI0NTNcIjp0cnVlLFwiNDU0XCI6dHJ1ZSxcIjQ1NVwiOnRydWUsXCI0NTZcIjp0cnVlLFwiNDU3XCI6dHJ1ZSxcIjQ1OFwiOnRydWUsXCI0NTlcIjp0cnVlLFwiNDcwXCI6dHJ1ZSxcIjQ3MlwiOnRydWV9LFwiSU5cIjp7XCI0MjRcIjp0cnVlLFwiNDYwXCI6dHJ1ZSxcIjQ2MVwiOnRydWUsXCI0NjJcIjp0cnVlLFwiNDYzXCI6dHJ1ZSxcIjQ2NFwiOnRydWUsXCI0NjVcIjp0cnVlLFwiNDY2XCI6dHJ1ZSxcIjQ2N1wiOnRydWUsXCI0NjhcIjp0cnVlLFwiNDY5XCI6dHJ1ZSxcIjQ3MFwiOnRydWUsXCI0NzFcIjp0cnVlLFwiNDcyXCI6dHJ1ZSxcIjQ3M1wiOnRydWUsXCI0NzRcIjp0cnVlLFwiNDc1XCI6dHJ1ZSxcIjQ3NlwiOnRydWUsXCI0NzdcIjp0cnVlLFwiNDc4XCI6dHJ1ZSxcIjQ3OVwiOnRydWV9LFwiTUlcIjp7XCI0ODBcIjp0cnVlLFwiNDgxXCI6dHJ1ZSxcIjQ4MlwiOnRydWUsXCI0ODNcIjp0cnVlLFwiNDg0XCI6dHJ1ZSxcIjQ4NVwiOnRydWUsXCI0ODZcIjp0cnVlLFwiNDg3XCI6dHJ1ZSxcIjQ4OFwiOnRydWUsXCI0ODlcIjp0cnVlLFwiNDkwXCI6dHJ1ZSxcIjQ5MVwiOnRydWUsXCI0OTJcIjp0cnVlLFwiNDkzXCI6dHJ1ZSxcIjQ5NFwiOnRydWUsXCI0OTVcIjp0cnVlLFwiNDk2XCI6dHJ1ZSxcIjQ5N1wiOnRydWUsXCI0OThcIjp0cnVlLFwiNDk5XCI6dHJ1ZX0sXCJJQVwiOntcIjUwMFwiOnRydWUsXCI1MDFcIjp0cnVlLFwiNTAyXCI6dHJ1ZSxcIjUwM1wiOnRydWUsXCI1MDRcIjp0cnVlLFwiNTA1XCI6dHJ1ZSxcIjUwNlwiOnRydWUsXCI1MDdcIjp0cnVlLFwiNTA4XCI6dHJ1ZSxcIjUwOVwiOnRydWUsXCI1MTBcIjp0cnVlLFwiNTExXCI6dHJ1ZSxcIjUxMlwiOnRydWUsXCI1MTNcIjp0cnVlLFwiNTE0XCI6dHJ1ZSxcIjUxNVwiOnRydWUsXCI1MTZcIjp0cnVlLFwiNTIwXCI6dHJ1ZSxcIjUyMVwiOnRydWUsXCI1MjJcIjp0cnVlLFwiNTIzXCI6dHJ1ZSxcIjUyNFwiOnRydWUsXCI1MjVcIjp0cnVlLFwiNTI2XCI6dHJ1ZSxcIjUyN1wiOnRydWUsXCI1MjhcIjp0cnVlfSxcIk5FXCI6e1wiNTE1XCI6dHJ1ZSxcIjUxNlwiOnRydWUsXCI2ODBcIjp0cnVlLFwiNjgxXCI6dHJ1ZSxcIjY4M1wiOnRydWUsXCI2ODRcIjp0cnVlLFwiNjg1XCI6dHJ1ZSxcIjY4NlwiOnRydWUsXCI2ODdcIjp0cnVlLFwiNjg4XCI6dHJ1ZSxcIjY4OVwiOnRydWUsXCI2OTBcIjp0cnVlLFwiNjkxXCI6dHJ1ZSxcIjY5MlwiOnRydWUsXCI2OTNcIjp0cnVlfSxcIklMXCI6e1wiNTI3XCI6dHJ1ZSxcIjYwMFwiOnRydWUsXCI2MDFcIjp0cnVlLFwiNjAyXCI6dHJ1ZSxcIjYwM1wiOnRydWUsXCI2MDRcIjp0cnVlLFwiNjA1XCI6dHJ1ZSxcIjYwNlwiOnRydWUsXCI2MDdcIjp0cnVlLFwiNjA4XCI6dHJ1ZSxcIjYwOVwiOnRydWUsXCI2MTBcIjp0cnVlLFwiNjExXCI6dHJ1ZSxcIjYxMlwiOnRydWUsXCI2MTNcIjp0cnVlLFwiNjE0XCI6dHJ1ZSxcIjYxNVwiOnRydWUsXCI2MTZcIjp0cnVlLFwiNjE3XCI6dHJ1ZSxcIjYxOFwiOnRydWUsXCI2MTlcIjp0cnVlLFwiNjIwXCI6dHJ1ZSxcIjYyMlwiOnRydWUsXCI2MjNcIjp0cnVlLFwiNjI0XCI6dHJ1ZSxcIjYyNVwiOnRydWUsXCI2MjZcIjp0cnVlLFwiNjI3XCI6dHJ1ZSxcIjYyOFwiOnRydWUsXCI2MjlcIjp0cnVlLFwiNjM0XCI6dHJ1ZSxcIjYzNVwiOnRydWV9LFwiV0lcIjp7XCI1MzBcIjp0cnVlLFwiNTMxXCI6dHJ1ZSxcIjUzMlwiOnRydWUsXCI1MzRcIjp0cnVlLFwiNTM1XCI6dHJ1ZSxcIjUzN1wiOnRydWUsXCI1MzhcIjp0cnVlLFwiNTM5XCI6dHJ1ZSxcIjU0MFwiOnRydWUsXCI1NDFcIjp0cnVlLFwiNTQyXCI6dHJ1ZSxcIjU0M1wiOnRydWUsXCI1NDRcIjp0cnVlLFwiNTQ1XCI6dHJ1ZSxcIjU0NlwiOnRydWUsXCI1NDdcIjp0cnVlLFwiNTQ4XCI6dHJ1ZSxcIjU0OVwiOnRydWV9LFwiTU5cIjp7XCI1NDBcIjp0cnVlLFwiNTUwXCI6dHJ1ZSxcIjU1MVwiOnRydWUsXCI1NTNcIjp0cnVlLFwiNTU0XCI6dHJ1ZSxcIjU1NlwiOnRydWUsXCI1NTdcIjp0cnVlLFwiNTU4XCI6dHJ1ZSxcIjU1OVwiOnRydWUsXCI1NjBcIjp0cnVlLFwiNTYxXCI6dHJ1ZSxcIjU2MlwiOnRydWUsXCI1NjNcIjp0cnVlLFwiNTY0XCI6dHJ1ZSxcIjU2NVwiOnRydWUsXCI1NjZcIjp0cnVlLFwiNTY3XCI6dHJ1ZX0sXCJORFwiOntcIjU2N1wiOnRydWUsXCI1ODBcIjp0cnVlLFwiNTgxXCI6dHJ1ZSxcIjU4MlwiOnRydWUsXCI1ODNcIjp0cnVlLFwiNTg0XCI6dHJ1ZSxcIjU4NVwiOnRydWUsXCI1ODZcIjp0cnVlLFwiNTg3XCI6dHJ1ZSxcIjU4OFwiOnRydWV9LFwiU0RcIjp7XCI1NzBcIjp0cnVlLFwiNTcxXCI6dHJ1ZSxcIjU3MlwiOnRydWUsXCI1NzNcIjp0cnVlLFwiNTc0XCI6dHJ1ZSxcIjU3NVwiOnRydWUsXCI1NzZcIjp0cnVlLFwiNTc3XCI6dHJ1ZX0sXCJNVFwiOntcIjU5MFwiOnRydWUsXCI1OTFcIjp0cnVlLFwiNTkyXCI6dHJ1ZSxcIjU5M1wiOnRydWUsXCI1OTRcIjp0cnVlLFwiNTk1XCI6dHJ1ZSxcIjU5NlwiOnRydWUsXCI1OTdcIjp0cnVlLFwiNTk4XCI6dHJ1ZSxcIjU5OVwiOnRydWV9LFwiTU9cIjp7XCI2MjBcIjp0cnVlLFwiNjIyXCI6dHJ1ZSxcIjYzMFwiOnRydWUsXCI2MzFcIjp0cnVlLFwiNjMzXCI6dHJ1ZSxcIjYzNFwiOnRydWUsXCI2MzVcIjp0cnVlLFwiNjM2XCI6dHJ1ZSxcIjYzN1wiOnRydWUsXCI2MzhcIjp0cnVlLFwiNjM5XCI6dHJ1ZSxcIjY0MFwiOnRydWUsXCI2NDFcIjp0cnVlLFwiNjQ0XCI6dHJ1ZSxcIjY0NVwiOnRydWUsXCI2NDZcIjp0cnVlLFwiNjQ3XCI6dHJ1ZSxcIjY0OFwiOnRydWUsXCI2NDlcIjp0cnVlLFwiNjUwXCI6dHJ1ZSxcIjY1MVwiOnRydWUsXCI2NTJcIjp0cnVlLFwiNjUzXCI6dHJ1ZSxcIjY1NFwiOnRydWUsXCI2NTVcIjp0cnVlLFwiNjU2XCI6dHJ1ZSxcIjY1N1wiOnRydWUsXCI2NThcIjp0cnVlfSxcIktTXCI6e1wiNjYwXCI6dHJ1ZSxcIjY2MVwiOnRydWUsXCI2NjJcIjp0cnVlLFwiNjY0XCI6dHJ1ZSxcIjY2NVwiOnRydWUsXCI2NjZcIjp0cnVlLFwiNjY3XCI6dHJ1ZSxcIjY2OFwiOnRydWUsXCI2NjlcIjp0cnVlLFwiNjcwXCI6dHJ1ZSxcIjY3MVwiOnRydWUsXCI2NzJcIjp0cnVlLFwiNjczXCI6dHJ1ZSxcIjY3NFwiOnRydWUsXCI2NzVcIjp0cnVlLFwiNjc2XCI6dHJ1ZSxcIjY3N1wiOnRydWUsXCI2NzhcIjp0cnVlLFwiNjc5XCI6dHJ1ZX0sXCJMQVwiOntcIjcwMFwiOnRydWUsXCI3MDFcIjp0cnVlLFwiNzAzXCI6dHJ1ZSxcIjcwNFwiOnRydWUsXCI3MDVcIjp0cnVlLFwiNzA2XCI6dHJ1ZSxcIjcwN1wiOnRydWUsXCI3MDhcIjp0cnVlLFwiNzEwXCI6dHJ1ZSxcIjcxMVwiOnRydWUsXCI3MTJcIjp0cnVlLFwiNzEzXCI6dHJ1ZSxcIjcxNFwiOnRydWV9LFwiQVJcIjp7XCI3MTZcIjp0cnVlLFwiNzE3XCI6dHJ1ZSxcIjcxOFwiOnRydWUsXCI3MTlcIjp0cnVlLFwiNzIwXCI6dHJ1ZSxcIjcyMVwiOnRydWUsXCI3MjJcIjp0cnVlLFwiNzIzXCI6dHJ1ZSxcIjcyNFwiOnRydWUsXCI3MjVcIjp0cnVlLFwiNzI2XCI6dHJ1ZSxcIjcyN1wiOnRydWUsXCI3MjhcIjp0cnVlLFwiNzI5XCI6dHJ1ZX0sXCJPS1wiOntcIjczMFwiOnRydWUsXCI3MzFcIjp0cnVlLFwiNzM0XCI6dHJ1ZSxcIjczNVwiOnRydWUsXCI3MzZcIjp0cnVlLFwiNzM3XCI6dHJ1ZSxcIjczOFwiOnRydWUsXCI3MzlcIjp0cnVlLFwiNzQwXCI6dHJ1ZSxcIjc0MVwiOnRydWUsXCI3NDNcIjp0cnVlLFwiNzQ0XCI6dHJ1ZSxcIjc0NVwiOnRydWUsXCI3NDZcIjp0cnVlLFwiNzQ3XCI6dHJ1ZSxcIjc0OFwiOnRydWUsXCI3NDlcIjp0cnVlfSxcIlRYXCI6e1wiNzMzXCI6dHJ1ZSxcIjczOVwiOnRydWUsXCI3NTBcIjp0cnVlLFwiNzUxXCI6dHJ1ZSxcIjc1MlwiOnRydWUsXCI3NTNcIjp0cnVlLFwiNzU0XCI6dHJ1ZSxcIjc1NVwiOnRydWUsXCI3NTZcIjp0cnVlLFwiNzU3XCI6dHJ1ZSxcIjc1OFwiOnRydWUsXCI3NTlcIjp0cnVlLFwiNzYwXCI6dHJ1ZSxcIjc2MVwiOnRydWUsXCI3NjJcIjp0cnVlLFwiNzYzXCI6dHJ1ZSxcIjc2NFwiOnRydWUsXCI3NjVcIjp0cnVlLFwiNzY2XCI6dHJ1ZSxcIjc2N1wiOnRydWUsXCI3NjhcIjp0cnVlLFwiNzY5XCI6dHJ1ZSxcIjc3MFwiOnRydWUsXCI3NzFcIjp0cnVlLFwiNzcyXCI6dHJ1ZSxcIjc3M1wiOnRydWUsXCI3NzRcIjp0cnVlLFwiNzc1XCI6dHJ1ZSxcIjc3NlwiOnRydWUsXCI3NzdcIjp0cnVlLFwiNzc4XCI6dHJ1ZSxcIjc3OVwiOnRydWUsXCI3ODBcIjp0cnVlLFwiNzgxXCI6dHJ1ZSxcIjc4MlwiOnRydWUsXCI3ODNcIjp0cnVlLFwiNzg0XCI6dHJ1ZSxcIjc4NVwiOnRydWUsXCI3ODZcIjp0cnVlLFwiNzg3XCI6dHJ1ZSxcIjc4OFwiOnRydWUsXCI3ODlcIjp0cnVlLFwiNzkwXCI6dHJ1ZSxcIjc5MVwiOnRydWUsXCI3OTJcIjp0cnVlLFwiNzkzXCI6dHJ1ZSxcIjc5NFwiOnRydWUsXCI3OTVcIjp0cnVlLFwiNzk2XCI6dHJ1ZSxcIjc5N1wiOnRydWUsXCI3OThcIjp0cnVlLFwiNzk5XCI6dHJ1ZSxcIjg4NVwiOnRydWV9LFwiQ09cIjp7XCI4MDBcIjp0cnVlLFwiODAxXCI6dHJ1ZSxcIjgwMlwiOnRydWUsXCI4MDNcIjp0cnVlLFwiODA0XCI6dHJ1ZSxcIjgwNVwiOnRydWUsXCI4MDZcIjp0cnVlLFwiODA3XCI6dHJ1ZSxcIjgwOFwiOnRydWUsXCI4MDlcIjp0cnVlLFwiODEwXCI6dHJ1ZSxcIjgxMVwiOnRydWUsXCI4MTJcIjp0cnVlLFwiODEzXCI6dHJ1ZSxcIjgxNFwiOnRydWUsXCI4MTVcIjp0cnVlLFwiODE2XCI6dHJ1ZX0sXCJXWVwiOntcIjgyMFwiOnRydWUsXCI4MjFcIjp0cnVlLFwiODIyXCI6dHJ1ZSxcIjgyM1wiOnRydWUsXCI4MjRcIjp0cnVlLFwiODI1XCI6dHJ1ZSxcIjgyNlwiOnRydWUsXCI4MjdcIjp0cnVlLFwiODI4XCI6dHJ1ZSxcIjgyOVwiOnRydWUsXCI4MzBcIjp0cnVlLFwiODMxXCI6dHJ1ZSxcIjgzNFwiOnRydWV9LFwiSURcIjp7XCI4MzJcIjp0cnVlLFwiODMzXCI6dHJ1ZSxcIjgzNFwiOnRydWUsXCI4MzVcIjp0cnVlLFwiODM2XCI6dHJ1ZSxcIjgzN1wiOnRydWUsXCI4MzhcIjp0cnVlLFwiOTc5XCI6dHJ1ZSxcIjk5NFwiOnRydWV9LFwiV0FcIjp7XCI4MzhcIjp0cnVlLFwiOTgwXCI6dHJ1ZSxcIjk4MVwiOnRydWUsXCI5ODJcIjp0cnVlLFwiOTgzXCI6dHJ1ZSxcIjk4NFwiOnRydWUsXCI5ODVcIjp0cnVlLFwiOTg2XCI6dHJ1ZSxcIjk4OFwiOnRydWUsXCI5ODlcIjp0cnVlLFwiOTkwXCI6dHJ1ZSxcIjk5MVwiOnRydWUsXCI5OTJcIjp0cnVlLFwiOTkzXCI6dHJ1ZSxcIjk5NFwiOnRydWV9LFwiVVRcIjp7XCI4NDBcIjp0cnVlLFwiODQxXCI6dHJ1ZSxcIjg0MlwiOnRydWUsXCI4NDNcIjp0cnVlLFwiODQ0XCI6dHJ1ZSxcIjg0NVwiOnRydWUsXCI4NDZcIjp0cnVlLFwiODQ3XCI6dHJ1ZX0sXCJBWlwiOntcIjg1MFwiOnRydWUsXCI4NTFcIjp0cnVlLFwiODUyXCI6dHJ1ZSxcIjg1M1wiOnRydWUsXCI4NTVcIjp0cnVlLFwiODU2XCI6dHJ1ZSxcIjg1N1wiOnRydWUsXCI4NTlcIjp0cnVlLFwiODYwXCI6dHJ1ZSxcIjg2M1wiOnRydWUsXCI4NjRcIjp0cnVlLFwiODY1XCI6dHJ1ZX0sXCJOTVwiOntcIjg3MFwiOnRydWUsXCI4NzFcIjp0cnVlLFwiODcyXCI6dHJ1ZSxcIjg3M1wiOnRydWUsXCI4NzRcIjp0cnVlLFwiODc1XCI6dHJ1ZSxcIjg3N1wiOnRydWUsXCI4NzhcIjp0cnVlLFwiODc5XCI6dHJ1ZSxcIjg4MFwiOnRydWUsXCI4ODFcIjp0cnVlLFwiODgyXCI6dHJ1ZSxcIjg4M1wiOnRydWUsXCI4ODRcIjp0cnVlfSxcIk5WXCI6e1wiODc3XCI6dHJ1ZSxcIjg4OVwiOnRydWUsXCI4OTBcIjp0cnVlLFwiODkxXCI6dHJ1ZSxcIjg5M1wiOnRydWUsXCI4OTRcIjp0cnVlLFwiODk1XCI6dHJ1ZSxcIjg5N1wiOnRydWUsXCI4OThcIjp0cnVlLFwiOTYxXCI6dHJ1ZX0sXCJDQVwiOntcIjkwMFwiOnRydWUsXCI5MDFcIjp0cnVlLFwiOTAyXCI6dHJ1ZSxcIjkwM1wiOnRydWUsXCI5MDRcIjp0cnVlLFwiOTA1XCI6dHJ1ZSxcIjkwNlwiOnRydWUsXCI5MDdcIjp0cnVlLFwiOTA4XCI6dHJ1ZSxcIjkxMFwiOnRydWUsXCI5MTFcIjp0cnVlLFwiOTEyXCI6dHJ1ZSxcIjkxM1wiOnRydWUsXCI5MTRcIjp0cnVlLFwiOTE1XCI6dHJ1ZSxcIjkxNlwiOnRydWUsXCI5MTdcIjp0cnVlLFwiOTE4XCI6dHJ1ZSxcIjkxOVwiOnRydWUsXCI5MjBcIjp0cnVlLFwiOTIxXCI6dHJ1ZSxcIjkyMlwiOnRydWUsXCI5MjNcIjp0cnVlLFwiOTI0XCI6dHJ1ZSxcIjkyNVwiOnRydWUsXCI5MjZcIjp0cnVlLFwiOTI3XCI6dHJ1ZSxcIjkyOFwiOnRydWUsXCI5MzBcIjp0cnVlLFwiOTMxXCI6dHJ1ZSxcIjkzMlwiOnRydWUsXCI5MzNcIjp0cnVlLFwiOTM0XCI6dHJ1ZSxcIjkzNVwiOnRydWUsXCI5MzZcIjp0cnVlLFwiOTM3XCI6dHJ1ZSxcIjkzOFwiOnRydWUsXCI5MzlcIjp0cnVlLFwiOTQwXCI6dHJ1ZSxcIjk0MVwiOnRydWUsXCI5NDJcIjp0cnVlLFwiOTQzXCI6dHJ1ZSxcIjk0NFwiOnRydWUsXCI5NDVcIjp0cnVlLFwiOTQ2XCI6dHJ1ZSxcIjk0N1wiOnRydWUsXCI5NDhcIjp0cnVlLFwiOTQ5XCI6dHJ1ZSxcIjk1MFwiOnRydWUsXCI5NTFcIjp0cnVlLFwiOTUyXCI6dHJ1ZSxcIjk1M1wiOnRydWUsXCI5NTRcIjp0cnVlLFwiOTU1XCI6dHJ1ZSxcIjk1NlwiOnRydWUsXCI5NTdcIjp0cnVlLFwiOTU4XCI6dHJ1ZSxcIjk1OVwiOnRydWUsXCI5NjBcIjp0cnVlLFwiOTYxXCI6dHJ1ZX0sXCJISVwiOntcIjk2N1wiOnRydWUsXCI5NjhcIjp0cnVlfSxcIkFTXCI6e1wiOTY3XCI6dHJ1ZX0sXCJHVVwiOntcIjk2OVwiOnRydWV9LFwiTUhcIjp7XCI5NjlcIjp0cnVlfSxcIk9SXCI6e1wiOTcwXCI6dHJ1ZSxcIjk3MVwiOnRydWUsXCI5NzJcIjp0cnVlLFwiOTczXCI6dHJ1ZSxcIjk3NFwiOnRydWUsXCI5NzVcIjp0cnVlLFwiOTc2XCI6dHJ1ZSxcIjk3N1wiOnRydWUsXCI5NzhcIjp0cnVlLFwiOTc5XCI6dHJ1ZSxcIjk4NlwiOnRydWV9LFwiQUtcIjp7XCI5OTVcIjp0cnVlLFwiOTk2XCI6dHJ1ZSxcIjk5N1wiOnRydWUsXCI5OThcIjp0cnVlLFwiOTk5XCI6dHJ1ZX19IiwibW9kdWxlLmV4cG9ydHM9e1wiMTAwXCI6XCJOWVwiLFwiMTAxXCI6XCJOWVwiLFwiMTAyXCI6XCJOWVwiLFwiMTAzXCI6XCJOWVwiLFwiMTA0XCI6XCJOWVwiLFwiMTA1XCI6XCJOWVwiLFwiMTA2XCI6XCJOWVwiLFwiMTA3XCI6XCJOWVwiLFwiMTA4XCI6XCJOWVwiLFwiMTA5XCI6XCJOWVwiLFwiMTEwXCI6XCJOWVwiLFwiMTExXCI6XCJOWVwiLFwiMTEyXCI6XCJOWVwiLFwiMTEzXCI6XCJOWVwiLFwiMTE0XCI6XCJOWVwiLFwiMTE1XCI6XCJOWVwiLFwiMTE2XCI6XCJOWVwiLFwiMTE3XCI6XCJOWVwiLFwiMTE4XCI6XCJOWVwiLFwiMTE5XCI6XCJOWVwiLFwiMTIwXCI6XCJOWVwiLFwiMTIxXCI6XCJOWVwiLFwiMTIyXCI6XCJOWVwiLFwiMTIzXCI6XCJOWVwiLFwiMTI0XCI6XCJOWVwiLFwiMTI1XCI6XCJOWVwiLFwiMTI2XCI6XCJOWVwiLFwiMTI3XCI6XCJOWVwiLFwiMTI4XCI6XCJOWVwiLFwiMTI5XCI6XCJOWVwiLFwiMTMwXCI6XCJOWVwiLFwiMTMxXCI6XCJOWVwiLFwiMTMyXCI6XCJOWVwiLFwiMTMzXCI6XCJOWVwiLFwiMTM0XCI6XCJOWVwiLFwiMTM1XCI6XCJOWVwiLFwiMTM2XCI6XCJOWVwiLFwiMTM3XCI6XCJOWVwiLFwiMTM4XCI6XCJOWVwiLFwiMTM5XCI6XCJOWVwiLFwiMTQwXCI6XCJOWVwiLFwiMTQxXCI6XCJOWVwiLFwiMTQyXCI6XCJOWVwiLFwiMTQzXCI6XCJOWVwiLFwiMTQ0XCI6XCJOWVwiLFwiMTQ1XCI6XCJOWVwiLFwiMTQ2XCI6XCJOWVwiLFwiMTQ3XCI6XCJOWVwiLFwiMTQ4XCI6XCJOWVwiLFwiMTQ5XCI6XCJOWVwiLFwiMTUwXCI6XCJQQVwiLFwiMTUxXCI6XCJQQVwiLFwiMTUyXCI6XCJQQVwiLFwiMTUzXCI6XCJQQVwiLFwiMTU0XCI6XCJQQVwiLFwiMTU1XCI6XCJQQVwiLFwiMTU2XCI6XCJQQVwiLFwiMTU3XCI6XCJQQVwiLFwiMTU4XCI6XCJQQVwiLFwiMTU5XCI6XCJQQVwiLFwiMTYwXCI6XCJQQVwiLFwiMTYxXCI6XCJQQVwiLFwiMTYyXCI6XCJQQVwiLFwiMTYzXCI6XCJQQVwiLFwiMTY0XCI6XCJQQVwiLFwiMTY1XCI6XCJQQVwiLFwiMTY2XCI6XCJQQVwiLFwiMTY3XCI6XCJQQVwiLFwiMTY4XCI6XCJQQVwiLFwiMTY5XCI6XCJQQVwiLFwiMTcwXCI6XCJQQVwiLFwiMTcxXCI6XCJQQVwiLFwiMTcyXCI6XCJQQVwiLFwiMTczXCI6XCJQQVwiLFwiMTc0XCI6XCJQQVwiLFwiMTc1XCI6XCJQQVwiLFwiMTc2XCI6XCJQQVwiLFwiMTc3XCI6XCJQQVwiLFwiMTc4XCI6XCJQQVwiLFwiMTc5XCI6XCJQQVwiLFwiMTgwXCI6XCJQQVwiLFwiMTgxXCI6XCJQQVwiLFwiMTgyXCI6XCJQQVwiLFwiMTgzXCI6XCJQQVwiLFwiMTg0XCI6XCJQQVwiLFwiMTg1XCI6XCJQQVwiLFwiMTg2XCI6XCJQQVwiLFwiMTg3XCI6XCJQQVwiLFwiMTg4XCI6XCJQQVwiLFwiMTg5XCI6XCJQQVwiLFwiMTkwXCI6XCJQQVwiLFwiMTkxXCI6XCJQQVwiLFwiMTkyXCI6XCJQQVwiLFwiMTkzXCI6XCJQQVwiLFwiMTk0XCI6XCJQQVwiLFwiMTk1XCI6XCJQQVwiLFwiMTk2XCI6XCJQQVwiLFwiMTk3XCI6XCJERVwiLFwiMTk4XCI6XCJERVwiLFwiMTk5XCI6XCJERVwiLFwiMjAwXCI6XCJEQ1wiLFwiMjAxXCI6XCJWQVwiLFwiMjAyXCI6XCJEQ1wiLFwiMjAzXCI6XCJEQ1wiLFwiMjA0XCI6XCJEQ1wiLFwiMjA1XCI6XCJEQ1wiLFwiMjA2XCI6XCJNRFwiLFwiMjA3XCI6XCJNRFwiLFwiMjA4XCI6XCJNRFwiLFwiMjA5XCI6XCJNRFwiLFwiMjEwXCI6XCJNRFwiLFwiMjExXCI6XCJNRFwiLFwiMjEyXCI6XCJNRFwiLFwiMjE0XCI6XCJNRFwiLFwiMjE1XCI6XCJNRFwiLFwiMjE2XCI6XCJNRFwiLFwiMjE3XCI6XCJNRFwiLFwiMjE4XCI6XCJNRFwiLFwiMjE5XCI6XCJNRFwiLFwiMjIwXCI6XCJWQVwiLFwiMjIxXCI6XCJWQVwiLFwiMjIyXCI6XCJWQVwiLFwiMjIzXCI6XCJWQVwiLFwiMjI0XCI6XCJWQVwiLFwiMjI1XCI6XCJWQVwiLFwiMjI2XCI6XCJWQVwiLFwiMjI3XCI6XCJWQVwiLFwiMjI4XCI6XCJWQVwiLFwiMjI5XCI6XCJWQVwiLFwiMjMwXCI6XCJWQVwiLFwiMjMxXCI6XCJWQVwiLFwiMjMyXCI6XCJWQVwiLFwiMjMzXCI6XCJWQVwiLFwiMjM0XCI6XCJWQVwiLFwiMjM1XCI6XCJWQVwiLFwiMjM2XCI6XCJWQVwiLFwiMjM3XCI6XCJWQVwiLFwiMjM4XCI6XCJWQVwiLFwiMjM5XCI6XCJWQVwiLFwiMjQwXCI6XCJWQVwiLFwiMjQxXCI6XCJWQVwiLFwiMjQyXCI6XCJWQVwiLFwiMjQzXCI6XCJWQVwiLFwiMjQ0XCI6XCJWQVwiLFwiMjQ1XCI6XCJWQVwiLFwiMjQ2XCI6XCJXVlwiLFwiMjQ3XCI6XCJXVlwiLFwiMjQ4XCI6XCJXVlwiLFwiMjQ5XCI6XCJXVlwiLFwiMjUwXCI6XCJXVlwiLFwiMjUxXCI6XCJXVlwiLFwiMjUyXCI6XCJXVlwiLFwiMjUzXCI6XCJXVlwiLFwiMjU0XCI6XCJXVlwiLFwiMjU1XCI6XCJXVlwiLFwiMjU2XCI6XCJXVlwiLFwiMjU3XCI6XCJXVlwiLFwiMjU4XCI6XCJXVlwiLFwiMjU5XCI6XCJXVlwiLFwiMjYwXCI6XCJXVlwiLFwiMjYxXCI6XCJXVlwiLFwiMjYyXCI6XCJXVlwiLFwiMjYzXCI6XCJXVlwiLFwiMjY0XCI6XCJXVlwiLFwiMjY1XCI6XCJXVlwiLFwiMjY2XCI6XCJXVlwiLFwiMjY3XCI6XCJXVlwiLFwiMjY4XCI6XCJXVlwiLFwiMjcwXCI6XCJOQ1wiLFwiMjcxXCI6XCJOQ1wiLFwiMjcyXCI6XCJOQ1wiLFwiMjczXCI6XCJOQ1wiLFwiMjc0XCI6XCJOQ1wiLFwiMjc1XCI6XCJOQ1wiLFwiMjc2XCI6XCJOQ1wiLFwiMjc3XCI6XCJOQ1wiLFwiMjc4XCI6XCJOQ1wiLFwiMjc5XCI6XCJOQ1wiLFwiMjgwXCI6XCJOQ1wiLFwiMjgxXCI6XCJOQ1wiLFwiMjgyXCI6XCJOQ1wiLFwiMjgzXCI6XCJOQ1wiLFwiMjg0XCI6XCJOQ1wiLFwiMjg1XCI6XCJOQ1wiLFwiMjg2XCI6XCJOQ1wiLFwiMjg3XCI6XCJOQ1wiLFwiMjg4XCI6XCJOQ1wiLFwiMjg5XCI6XCJOQ1wiLFwiMjkwXCI6XCJTQ1wiLFwiMjkxXCI6XCJTQ1wiLFwiMjkyXCI6XCJTQ1wiLFwiMjkzXCI6XCJTQ1wiLFwiMjk0XCI6XCJTQ1wiLFwiMjk1XCI6XCJTQ1wiLFwiMjk2XCI6XCJTQ1wiLFwiMjk3XCI6XCJTQ1wiLFwiMjk4XCI6XCJHQVwiLFwiMjk5XCI6XCJHQVwiLFwiMzAwXCI6XCJHQVwiLFwiMzAxXCI6XCJHQVwiLFwiMzAyXCI6XCJHQVwiLFwiMzAzXCI6XCJHQVwiLFwiMzA0XCI6XCJHQVwiLFwiMzA1XCI6XCJHQVwiLFwiMzA2XCI6XCJHQVwiLFwiMzA3XCI6XCJHQVwiLFwiMzA4XCI6XCJHQVwiLFwiMzA5XCI6XCJHQVwiLFwiMzEwXCI6XCJHQVwiLFwiMzExXCI6XCJHQVwiLFwiMzEyXCI6XCJHQVwiLFwiMzEzXCI6XCJHQVwiLFwiMzE0XCI6XCJHQVwiLFwiMzE1XCI6XCJHQVwiLFwiMzE2XCI6XCJHQVwiLFwiMzE3XCI6XCJHQVwiLFwiMzE4XCI6XCJHQVwiLFwiMzE5XCI6XCJHQVwiLFwiMzIwXCI6XCJGTFwiLFwiMzIxXCI6XCJGTFwiLFwiMzIyXCI6XCJGTFwiLFwiMzIzXCI6XCJGTFwiLFwiMzI0XCI6XCJGTFwiLFwiMzI1XCI6XCJGTFwiLFwiMzI2XCI6XCJGTFwiLFwiMzI3XCI6XCJGTFwiLFwiMzI4XCI6XCJGTFwiLFwiMzI5XCI6XCJGTFwiLFwiMzMwXCI6XCJGTFwiLFwiMzMxXCI6XCJBQVwiLFwiMzMyXCI6XCJGTFwiLFwiMzMzXCI6XCJGTFwiLFwiMzM0XCI6XCJGTFwiLFwiMzM1XCI6XCJGTFwiLFwiMzM2XCI6XCJGTFwiLFwiMzM3XCI6XCJGTFwiLFwiMzM4XCI6XCJGTFwiLFwiMzM5XCI6XCJGTFwiLFwiMzQwXCI6XCJBUFwiLFwiMzQxXCI6XCJGTFwiLFwiMzQyXCI6XCJGTFwiLFwiMzQ0XCI6XCJGTFwiLFwiMzQ2XCI6XCJGTFwiLFwiMzQ3XCI6XCJGTFwiLFwiMzQ5XCI6XCJGTFwiLFwiMzUwXCI6XCJBTFwiLFwiMzUxXCI6XCJBTFwiLFwiMzUyXCI6XCJBTFwiLFwiMzU0XCI6XCJBTFwiLFwiMzU1XCI6XCJBTFwiLFwiMzU2XCI6XCJBTFwiLFwiMzU3XCI6XCJBTFwiLFwiMzU4XCI6XCJBTFwiLFwiMzU5XCI6XCJBTFwiLFwiMzYwXCI6XCJBTFwiLFwiMzYxXCI6XCJBTFwiLFwiMzYyXCI6XCJBTFwiLFwiMzYzXCI6XCJBTFwiLFwiMzY0XCI6XCJBTFwiLFwiMzY1XCI6XCJBTFwiLFwiMzY2XCI6XCJBTFwiLFwiMzY3XCI6XCJBTFwiLFwiMzY4XCI6XCJBTFwiLFwiMzY5XCI6XCJNU1wiLFwiMzcwXCI6XCJUTlwiLFwiMzcxXCI6XCJUTlwiLFwiMzcyXCI6XCJUTlwiLFwiMzczXCI6XCJUTlwiLFwiMzc0XCI6XCJUTlwiLFwiMzc1XCI6XCJUTlwiLFwiMzc2XCI6XCJUTlwiLFwiMzc3XCI6XCJUTlwiLFwiMzc4XCI6XCJUTlwiLFwiMzc5XCI6XCJUTlwiLFwiMzgwXCI6XCJUTlwiLFwiMzgxXCI6XCJUTlwiLFwiMzgyXCI6XCJUTlwiLFwiMzgzXCI6XCJUTlwiLFwiMzg0XCI6XCJUTlwiLFwiMzg1XCI6XCJUTlwiLFwiMzg2XCI6XCJUTlwiLFwiMzg3XCI6XCJNU1wiLFwiMzg4XCI6XCJNU1wiLFwiMzg5XCI6XCJNU1wiLFwiMzkwXCI6XCJNU1wiLFwiMzkxXCI6XCJNU1wiLFwiMzkyXCI6XCJNU1wiLFwiMzkzXCI6XCJNU1wiLFwiMzk0XCI6XCJNU1wiLFwiMzk1XCI6XCJNU1wiLFwiMzk2XCI6XCJNU1wiLFwiMzk3XCI6XCJNU1wiLFwiMzk4XCI6XCJHQVwiLFwiMzk5XCI6XCJHQVwiLFwiNDAwXCI6XCJLWVwiLFwiNDAxXCI6XCJLWVwiLFwiNDAyXCI6XCJLWVwiLFwiNDAzXCI6XCJLWVwiLFwiNDA0XCI6XCJLWVwiLFwiNDA1XCI6XCJLWVwiLFwiNDA2XCI6XCJLWVwiLFwiNDA3XCI6XCJLWVwiLFwiNDA4XCI6XCJLWVwiLFwiNDA5XCI6XCJLWVwiLFwiNDEwXCI6XCJPSFwiLFwiNDExXCI6XCJLWVwiLFwiNDEyXCI6XCJLWVwiLFwiNDEzXCI6XCJLWVwiLFwiNDE0XCI6XCJLWVwiLFwiNDE1XCI6XCJLWVwiLFwiNDE2XCI6XCJLWVwiLFwiNDE3XCI6XCJLWVwiLFwiNDE4XCI6XCJLWVwiLFwiNDIwXCI6XCJLWVwiLFwiNDIxXCI6XCJLWVwiLFwiNDIyXCI6XCJLWVwiLFwiNDIzXCI6XCJLWVwiLFwiNDI0XCI6XCJJTlwiLFwiNDI1XCI6XCJLWVwiLFwiNDI2XCI6XCJLWVwiLFwiNDI3XCI6XCJLWVwiLFwiNDMwXCI6XCJPSFwiLFwiNDMxXCI6XCJPSFwiLFwiNDMyXCI6XCJPSFwiLFwiNDMzXCI6XCJPSFwiLFwiNDM0XCI6XCJPSFwiLFwiNDM1XCI6XCJPSFwiLFwiNDM2XCI6XCJPSFwiLFwiNDM3XCI6XCJPSFwiLFwiNDM4XCI6XCJPSFwiLFwiNDM5XCI6XCJPSFwiLFwiNDQwXCI6XCJPSFwiLFwiNDQxXCI6XCJPSFwiLFwiNDQyXCI6XCJPSFwiLFwiNDQzXCI6XCJPSFwiLFwiNDQ0XCI6XCJPSFwiLFwiNDQ1XCI6XCJPSFwiLFwiNDQ2XCI6XCJPSFwiLFwiNDQ3XCI6XCJPSFwiLFwiNDQ4XCI6XCJPSFwiLFwiNDQ5XCI6XCJPSFwiLFwiNDUwXCI6XCJPSFwiLFwiNDUxXCI6XCJPSFwiLFwiNDUyXCI6XCJPSFwiLFwiNDUzXCI6XCJPSFwiLFwiNDU0XCI6XCJPSFwiLFwiNDU1XCI6XCJPSFwiLFwiNDU2XCI6XCJPSFwiLFwiNDU3XCI6XCJPSFwiLFwiNDU4XCI6XCJPSFwiLFwiNDU5XCI6XCJPSFwiLFwiNDYwXCI6XCJJTlwiLFwiNDYxXCI6XCJJTlwiLFwiNDYyXCI6XCJJTlwiLFwiNDYzXCI6XCJJTlwiLFwiNDY0XCI6XCJJTlwiLFwiNDY1XCI6XCJJTlwiLFwiNDY2XCI6XCJJTlwiLFwiNDY3XCI6XCJJTlwiLFwiNDY4XCI6XCJJTlwiLFwiNDY5XCI6XCJJTlwiLFwiNDcwXCI6XCJJTlwiLFwiNDcxXCI6XCJJTlwiLFwiNDcyXCI6XCJJTlwiLFwiNDczXCI6XCJJTlwiLFwiNDc0XCI6XCJJTlwiLFwiNDc1XCI6XCJJTlwiLFwiNDc2XCI6XCJJTlwiLFwiNDc3XCI6XCJJTlwiLFwiNDc4XCI6XCJJTlwiLFwiNDc5XCI6XCJJTlwiLFwiNDgwXCI6XCJNSVwiLFwiNDgxXCI6XCJNSVwiLFwiNDgyXCI6XCJNSVwiLFwiNDgzXCI6XCJNSVwiLFwiNDg0XCI6XCJNSVwiLFwiNDg1XCI6XCJNSVwiLFwiNDg2XCI6XCJNSVwiLFwiNDg3XCI6XCJNSVwiLFwiNDg4XCI6XCJNSVwiLFwiNDg5XCI6XCJNSVwiLFwiNDkwXCI6XCJNSVwiLFwiNDkxXCI6XCJNSVwiLFwiNDkyXCI6XCJNSVwiLFwiNDkzXCI6XCJNSVwiLFwiNDk0XCI6XCJNSVwiLFwiNDk1XCI6XCJNSVwiLFwiNDk2XCI6XCJNSVwiLFwiNDk3XCI6XCJNSVwiLFwiNDk4XCI6XCJNSVwiLFwiNDk5XCI6XCJNSVwiLFwiNTAwXCI6XCJJQVwiLFwiNTAxXCI6XCJJQVwiLFwiNTAyXCI6XCJJQVwiLFwiNTAzXCI6XCJJQVwiLFwiNTA0XCI6XCJJQVwiLFwiNTA1XCI6XCJJQVwiLFwiNTA2XCI6XCJJQVwiLFwiNTA3XCI6XCJJQVwiLFwiNTA4XCI6XCJJQVwiLFwiNTA5XCI6XCJJQVwiLFwiNTEwXCI6XCJJQVwiLFwiNTExXCI6XCJJQVwiLFwiNTEyXCI6XCJJQVwiLFwiNTEzXCI6XCJJQVwiLFwiNTE0XCI6XCJJQVwiLFwiNTE1XCI6XCJORVwiLFwiNTE2XCI6XCJORVwiLFwiNTIwXCI6XCJJQVwiLFwiNTIxXCI6XCJJQVwiLFwiNTIyXCI6XCJJQVwiLFwiNTIzXCI6XCJJQVwiLFwiNTI0XCI6XCJJQVwiLFwiNTI1XCI6XCJJQVwiLFwiNTI2XCI6XCJJQVwiLFwiNTI3XCI6XCJJTFwiLFwiNTI4XCI6XCJJQVwiLFwiNTMwXCI6XCJXSVwiLFwiNTMxXCI6XCJXSVwiLFwiNTMyXCI6XCJXSVwiLFwiNTM0XCI6XCJXSVwiLFwiNTM1XCI6XCJXSVwiLFwiNTM3XCI6XCJXSVwiLFwiNTM4XCI6XCJXSVwiLFwiNTM5XCI6XCJXSVwiLFwiNTQwXCI6XCJNTlwiLFwiNTQxXCI6XCJXSVwiLFwiNTQyXCI6XCJXSVwiLFwiNTQzXCI6XCJXSVwiLFwiNTQ0XCI6XCJXSVwiLFwiNTQ1XCI6XCJXSVwiLFwiNTQ2XCI6XCJXSVwiLFwiNTQ3XCI6XCJXSVwiLFwiNTQ4XCI6XCJXSVwiLFwiNTQ5XCI6XCJXSVwiLFwiNTUwXCI6XCJNTlwiLFwiNTUxXCI6XCJNTlwiLFwiNTUzXCI6XCJNTlwiLFwiNTU0XCI6XCJNTlwiLFwiNTU2XCI6XCJNTlwiLFwiNTU3XCI6XCJNTlwiLFwiNTU4XCI6XCJNTlwiLFwiNTU5XCI6XCJNTlwiLFwiNTYwXCI6XCJNTlwiLFwiNTYxXCI6XCJNTlwiLFwiNTYyXCI6XCJNTlwiLFwiNTYzXCI6XCJNTlwiLFwiNTY0XCI6XCJNTlwiLFwiNTY1XCI6XCJNTlwiLFwiNTY2XCI6XCJNTlwiLFwiNTY3XCI6XCJORFwiLFwiNTcwXCI6XCJTRFwiLFwiNTcxXCI6XCJTRFwiLFwiNTcyXCI6XCJTRFwiLFwiNTczXCI6XCJTRFwiLFwiNTc0XCI6XCJTRFwiLFwiNTc1XCI6XCJTRFwiLFwiNTc2XCI6XCJTRFwiLFwiNTc3XCI6XCJTRFwiLFwiNTgwXCI6XCJORFwiLFwiNTgxXCI6XCJORFwiLFwiNTgyXCI6XCJORFwiLFwiNTgzXCI6XCJORFwiLFwiNTg0XCI6XCJORFwiLFwiNTg1XCI6XCJORFwiLFwiNTg2XCI6XCJORFwiLFwiNTg3XCI6XCJORFwiLFwiNTg4XCI6XCJORFwiLFwiNTkwXCI6XCJNVFwiLFwiNTkxXCI6XCJNVFwiLFwiNTkyXCI6XCJNVFwiLFwiNTkzXCI6XCJNVFwiLFwiNTk0XCI6XCJNVFwiLFwiNTk1XCI6XCJNVFwiLFwiNTk2XCI6XCJNVFwiLFwiNTk3XCI6XCJNVFwiLFwiNTk4XCI6XCJNVFwiLFwiNTk5XCI6XCJNVFwiLFwiNjAwXCI6XCJJTFwiLFwiNjAxXCI6XCJJTFwiLFwiNjAyXCI6XCJJTFwiLFwiNjAzXCI6XCJJTFwiLFwiNjA0XCI6XCJJTFwiLFwiNjA1XCI6XCJJTFwiLFwiNjA2XCI6XCJJTFwiLFwiNjA3XCI6XCJJTFwiLFwiNjA4XCI6XCJJTFwiLFwiNjA5XCI6XCJJTFwiLFwiNjEwXCI6XCJJTFwiLFwiNjExXCI6XCJJTFwiLFwiNjEyXCI6XCJJTFwiLFwiNjEzXCI6XCJJTFwiLFwiNjE0XCI6XCJJTFwiLFwiNjE1XCI6XCJJTFwiLFwiNjE2XCI6XCJJTFwiLFwiNjE3XCI6XCJJTFwiLFwiNjE4XCI6XCJJTFwiLFwiNjE5XCI6XCJJTFwiLFwiNjIwXCI6XCJNT1wiLFwiNjIyXCI6XCJNT1wiLFwiNjIzXCI6XCJJTFwiLFwiNjI0XCI6XCJJTFwiLFwiNjI1XCI6XCJJTFwiLFwiNjI2XCI6XCJJTFwiLFwiNjI3XCI6XCJJTFwiLFwiNjI4XCI6XCJJTFwiLFwiNjI5XCI6XCJJTFwiLFwiNjMwXCI6XCJNT1wiLFwiNjMxXCI6XCJNT1wiLFwiNjMzXCI6XCJNT1wiLFwiNjM0XCI6XCJNT1wiLFwiNjM1XCI6XCJNT1wiLFwiNjM2XCI6XCJNT1wiLFwiNjM3XCI6XCJNT1wiLFwiNjM4XCI6XCJNT1wiLFwiNjM5XCI6XCJNT1wiLFwiNjQwXCI6XCJNT1wiLFwiNjQxXCI6XCJNT1wiLFwiNjQ0XCI6XCJNT1wiLFwiNjQ1XCI6XCJNT1wiLFwiNjQ2XCI6XCJNT1wiLFwiNjQ3XCI6XCJNT1wiLFwiNjQ4XCI6XCJNT1wiLFwiNjQ5XCI6XCJNT1wiLFwiNjUwXCI6XCJNT1wiLFwiNjUxXCI6XCJNT1wiLFwiNjUyXCI6XCJNT1wiLFwiNjUzXCI6XCJNT1wiLFwiNjU0XCI6XCJNT1wiLFwiNjU1XCI6XCJNT1wiLFwiNjU2XCI6XCJNT1wiLFwiNjU3XCI6XCJNT1wiLFwiNjU4XCI6XCJNT1wiLFwiNjYwXCI6XCJLU1wiLFwiNjYxXCI6XCJLU1wiLFwiNjYyXCI6XCJLU1wiLFwiNjY0XCI6XCJLU1wiLFwiNjY1XCI6XCJLU1wiLFwiNjY2XCI6XCJLU1wiLFwiNjY3XCI6XCJLU1wiLFwiNjY4XCI6XCJLU1wiLFwiNjY5XCI6XCJLU1wiLFwiNjcwXCI6XCJLU1wiLFwiNjcxXCI6XCJLU1wiLFwiNjcyXCI6XCJLU1wiLFwiNjczXCI6XCJLU1wiLFwiNjc0XCI6XCJLU1wiLFwiNjc1XCI6XCJLU1wiLFwiNjc2XCI6XCJLU1wiLFwiNjc3XCI6XCJLU1wiLFwiNjc4XCI6XCJLU1wiLFwiNjc5XCI6XCJLU1wiLFwiNjgwXCI6XCJORVwiLFwiNjgxXCI6XCJORVwiLFwiNjgzXCI6XCJORVwiLFwiNjg0XCI6XCJORVwiLFwiNjg1XCI6XCJORVwiLFwiNjg2XCI6XCJORVwiLFwiNjg3XCI6XCJORVwiLFwiNjg4XCI6XCJORVwiLFwiNjg5XCI6XCJORVwiLFwiNjkwXCI6XCJORVwiLFwiNjkxXCI6XCJORVwiLFwiNjkyXCI6XCJORVwiLFwiNjkzXCI6XCJORVwiLFwiNzAwXCI6XCJMQVwiLFwiNzAxXCI6XCJMQVwiLFwiNzAzXCI6XCJMQVwiLFwiNzA0XCI6XCJMQVwiLFwiNzA1XCI6XCJMQVwiLFwiNzA2XCI6XCJMQVwiLFwiNzA3XCI6XCJMQVwiLFwiNzA4XCI6XCJMQVwiLFwiNzEwXCI6XCJMQVwiLFwiNzExXCI6XCJMQVwiLFwiNzEyXCI6XCJMQVwiLFwiNzEzXCI6XCJMQVwiLFwiNzE0XCI6XCJMQVwiLFwiNzE2XCI6XCJBUlwiLFwiNzE3XCI6XCJBUlwiLFwiNzE4XCI6XCJBUlwiLFwiNzE5XCI6XCJBUlwiLFwiNzIwXCI6XCJBUlwiLFwiNzIxXCI6XCJBUlwiLFwiNzIyXCI6XCJBUlwiLFwiNzIzXCI6XCJBUlwiLFwiNzI0XCI6XCJBUlwiLFwiNzI1XCI6XCJBUlwiLFwiNzI2XCI6XCJBUlwiLFwiNzI3XCI6XCJBUlwiLFwiNzI4XCI6XCJBUlwiLFwiNzI5XCI6XCJBUlwiLFwiNzMwXCI6XCJPS1wiLFwiNzMxXCI6XCJPS1wiLFwiNzMzXCI6XCJUWFwiLFwiNzM0XCI6XCJPS1wiLFwiNzM1XCI6XCJPS1wiLFwiNzM2XCI6XCJPS1wiLFwiNzM3XCI6XCJPS1wiLFwiNzM4XCI6XCJPS1wiLFwiNzM5XCI6XCJUWFwiLFwiNzQwXCI6XCJPS1wiLFwiNzQxXCI6XCJPS1wiLFwiNzQzXCI6XCJPS1wiLFwiNzQ0XCI6XCJPS1wiLFwiNzQ1XCI6XCJPS1wiLFwiNzQ2XCI6XCJPS1wiLFwiNzQ3XCI6XCJPS1wiLFwiNzQ4XCI6XCJPS1wiLFwiNzQ5XCI6XCJPS1wiLFwiNzUwXCI6XCJUWFwiLFwiNzUxXCI6XCJUWFwiLFwiNzUyXCI6XCJUWFwiLFwiNzUzXCI6XCJUWFwiLFwiNzU0XCI6XCJUWFwiLFwiNzU1XCI6XCJUWFwiLFwiNzU2XCI6XCJUWFwiLFwiNzU3XCI6XCJUWFwiLFwiNzU4XCI6XCJUWFwiLFwiNzU5XCI6XCJUWFwiLFwiNzYwXCI6XCJUWFwiLFwiNzYxXCI6XCJUWFwiLFwiNzYyXCI6XCJUWFwiLFwiNzYzXCI6XCJUWFwiLFwiNzY0XCI6XCJUWFwiLFwiNzY1XCI6XCJUWFwiLFwiNzY2XCI6XCJUWFwiLFwiNzY3XCI6XCJUWFwiLFwiNzY4XCI6XCJUWFwiLFwiNzY5XCI6XCJUWFwiLFwiNzcwXCI6XCJUWFwiLFwiNzcxXCI6XCJUWFwiLFwiNzcyXCI6XCJUWFwiLFwiNzczXCI6XCJUWFwiLFwiNzc0XCI6XCJUWFwiLFwiNzc1XCI6XCJUWFwiLFwiNzc2XCI6XCJUWFwiLFwiNzc3XCI6XCJUWFwiLFwiNzc4XCI6XCJUWFwiLFwiNzc5XCI6XCJUWFwiLFwiNzgwXCI6XCJUWFwiLFwiNzgxXCI6XCJUWFwiLFwiNzgyXCI6XCJUWFwiLFwiNzgzXCI6XCJUWFwiLFwiNzg0XCI6XCJUWFwiLFwiNzg1XCI6XCJUWFwiLFwiNzg2XCI6XCJUWFwiLFwiNzg3XCI6XCJUWFwiLFwiNzg4XCI6XCJUWFwiLFwiNzg5XCI6XCJUWFwiLFwiNzkwXCI6XCJUWFwiLFwiNzkxXCI6XCJUWFwiLFwiNzkyXCI6XCJUWFwiLFwiNzkzXCI6XCJUWFwiLFwiNzk0XCI6XCJUWFwiLFwiNzk1XCI6XCJUWFwiLFwiNzk2XCI6XCJUWFwiLFwiNzk3XCI6XCJUWFwiLFwiNzk4XCI6XCJUWFwiLFwiNzk5XCI6XCJUWFwiLFwiODAwXCI6XCJDT1wiLFwiODAxXCI6XCJDT1wiLFwiODAyXCI6XCJDT1wiLFwiODAzXCI6XCJDT1wiLFwiODA0XCI6XCJDT1wiLFwiODA1XCI6XCJDT1wiLFwiODA2XCI6XCJDT1wiLFwiODA3XCI6XCJDT1wiLFwiODA4XCI6XCJDT1wiLFwiODA5XCI6XCJDT1wiLFwiODEwXCI6XCJDT1wiLFwiODExXCI6XCJDT1wiLFwiODEyXCI6XCJDT1wiLFwiODEzXCI6XCJDT1wiLFwiODE0XCI6XCJDT1wiLFwiODE1XCI6XCJDT1wiLFwiODE2XCI6XCJDT1wiLFwiODIwXCI6XCJXWVwiLFwiODIxXCI6XCJXWVwiLFwiODIyXCI6XCJXWVwiLFwiODIzXCI6XCJXWVwiLFwiODI0XCI6XCJXWVwiLFwiODI1XCI6XCJXWVwiLFwiODI2XCI6XCJXWVwiLFwiODI3XCI6XCJXWVwiLFwiODI4XCI6XCJXWVwiLFwiODI5XCI6XCJXWVwiLFwiODMwXCI6XCJXWVwiLFwiODMxXCI6XCJXWVwiLFwiODMyXCI6XCJJRFwiLFwiODMzXCI6XCJJRFwiLFwiODM0XCI6XCJJRFwiLFwiODM1XCI6XCJJRFwiLFwiODM2XCI6XCJJRFwiLFwiODM3XCI6XCJJRFwiLFwiODM4XCI6XCJXQVwiLFwiODQwXCI6XCJVVFwiLFwiODQxXCI6XCJVVFwiLFwiODQyXCI6XCJVVFwiLFwiODQzXCI6XCJVVFwiLFwiODQ0XCI6XCJVVFwiLFwiODQ1XCI6XCJVVFwiLFwiODQ2XCI6XCJVVFwiLFwiODQ3XCI6XCJVVFwiLFwiODUwXCI6XCJBWlwiLFwiODUxXCI6XCJBWlwiLFwiODUyXCI6XCJBWlwiLFwiODUzXCI6XCJBWlwiLFwiODU1XCI6XCJBWlwiLFwiODU2XCI6XCJBWlwiLFwiODU3XCI6XCJBWlwiLFwiODU5XCI6XCJBWlwiLFwiODYwXCI6XCJBWlwiLFwiODYzXCI6XCJBWlwiLFwiODY0XCI6XCJBWlwiLFwiODY1XCI6XCJBWlwiLFwiODcwXCI6XCJOTVwiLFwiODcxXCI6XCJOTVwiLFwiODcyXCI6XCJOTVwiLFwiODczXCI6XCJOTVwiLFwiODc0XCI6XCJOTVwiLFwiODc1XCI6XCJOTVwiLFwiODc3XCI6XCJOVlwiLFwiODc4XCI6XCJOTVwiLFwiODc5XCI6XCJOTVwiLFwiODgwXCI6XCJOTVwiLFwiODgxXCI6XCJOTVwiLFwiODgyXCI6XCJOTVwiLFwiODgzXCI6XCJOTVwiLFwiODg0XCI6XCJOTVwiLFwiODg1XCI6XCJUWFwiLFwiODg5XCI6XCJOVlwiLFwiODkwXCI6XCJOVlwiLFwiODkxXCI6XCJOVlwiLFwiODkzXCI6XCJOVlwiLFwiODk0XCI6XCJOVlwiLFwiODk1XCI6XCJOVlwiLFwiODk3XCI6XCJOVlwiLFwiODk4XCI6XCJOVlwiLFwiOTAwXCI6XCJDQVwiLFwiOTAxXCI6XCJDQVwiLFwiOTAyXCI6XCJDQVwiLFwiOTAzXCI6XCJDQVwiLFwiOTA0XCI6XCJDQVwiLFwiOTA1XCI6XCJDQVwiLFwiOTA2XCI6XCJDQVwiLFwiOTA3XCI6XCJDQVwiLFwiOTA4XCI6XCJDQVwiLFwiOTEwXCI6XCJDQVwiLFwiOTExXCI6XCJDQVwiLFwiOTEyXCI6XCJDQVwiLFwiOTEzXCI6XCJDQVwiLFwiOTE0XCI6XCJDQVwiLFwiOTE1XCI6XCJDQVwiLFwiOTE2XCI6XCJDQVwiLFwiOTE3XCI6XCJDQVwiLFwiOTE4XCI6XCJDQVwiLFwiOTE5XCI6XCJDQVwiLFwiOTIwXCI6XCJDQVwiLFwiOTIxXCI6XCJDQVwiLFwiOTIyXCI6XCJDQVwiLFwiOTIzXCI6XCJDQVwiLFwiOTI0XCI6XCJDQVwiLFwiOTI1XCI6XCJDQVwiLFwiOTI2XCI6XCJDQVwiLFwiOTI3XCI6XCJDQVwiLFwiOTI4XCI6XCJDQVwiLFwiOTMwXCI6XCJDQVwiLFwiOTMxXCI6XCJDQVwiLFwiOTMyXCI6XCJDQVwiLFwiOTMzXCI6XCJDQVwiLFwiOTM0XCI6XCJDQVwiLFwiOTM1XCI6XCJDQVwiLFwiOTM2XCI6XCJDQVwiLFwiOTM3XCI6XCJDQVwiLFwiOTM4XCI6XCJDQVwiLFwiOTM5XCI6XCJDQVwiLFwiOTQwXCI6XCJDQVwiLFwiOTQxXCI6XCJDQVwiLFwiOTQyXCI6XCJDQVwiLFwiOTQzXCI6XCJDQVwiLFwiOTQ0XCI6XCJDQVwiLFwiOTQ1XCI6XCJDQVwiLFwiOTQ2XCI6XCJDQVwiLFwiOTQ3XCI6XCJDQVwiLFwiOTQ4XCI6XCJDQVwiLFwiOTQ5XCI6XCJDQVwiLFwiOTUwXCI6XCJDQVwiLFwiOTUxXCI6XCJDQVwiLFwiOTUyXCI6XCJDQVwiLFwiOTUzXCI6XCJDQVwiLFwiOTU0XCI6XCJDQVwiLFwiOTU1XCI6XCJDQVwiLFwiOTU2XCI6XCJDQVwiLFwiOTU3XCI6XCJDQVwiLFwiOTU4XCI6XCJDQVwiLFwiOTU5XCI6XCJDQVwiLFwiOTYwXCI6XCJDQVwiLFwiOTYxXCI6XCJDQVwiLFwiOTYyXCI6XCJBUFwiLFwiOTYzXCI6XCJBUFwiLFwiOTY0XCI6XCJBUFwiLFwiOTY1XCI6XCJBUFwiLFwiOTY2XCI6XCJBUFwiLFwiOTY3XCI6XCJBU1wiLFwiOTY4XCI6XCJISVwiLFwiOTY5XCI6XCJNSFwiLFwiOTcwXCI6XCJPUlwiLFwiOTcxXCI6XCJPUlwiLFwiOTcyXCI6XCJPUlwiLFwiOTczXCI6XCJPUlwiLFwiOTc0XCI6XCJPUlwiLFwiOTc1XCI6XCJPUlwiLFwiOTc2XCI6XCJPUlwiLFwiOTc3XCI6XCJPUlwiLFwiOTc4XCI6XCJPUlwiLFwiOTc5XCI6XCJPUlwiLFwiOTgwXCI6XCJXQVwiLFwiOTgxXCI6XCJXQVwiLFwiOTgyXCI6XCJXQVwiLFwiOTgzXCI6XCJXQVwiLFwiOTg0XCI6XCJXQVwiLFwiOTg1XCI6XCJXQVwiLFwiOTg2XCI6XCJPUlwiLFwiOTg4XCI6XCJXQVwiLFwiOTg5XCI6XCJXQVwiLFwiOTkwXCI6XCJXQVwiLFwiOTkxXCI6XCJXQVwiLFwiOTkyXCI6XCJXQVwiLFwiOTkzXCI6XCJXQVwiLFwiOTk0XCI6XCJXQVwiLFwiOTk1XCI6XCJBS1wiLFwiOTk2XCI6XCJBS1wiLFwiOTk3XCI6XCJBS1wiLFwiOTk4XCI6XCJBS1wiLFwiOTk5XCI6XCJBS1wiLFwiMDA1XCI6XCJOWVwiLFwiMDYzXCI6XCJDVFwiLFwiMDA2XCI6XCJWSVwiLFwiMDA3XCI6XCJWSVwiLFwiMDA4XCI6XCJWSVwiLFwiMDA5XCI6XCJWSVwiLFwiMDEwXCI6XCJNQVwiLFwiMDExXCI6XCJNQVwiLFwiMDEyXCI6XCJNQVwiLFwiMDEzXCI6XCJNQVwiLFwiMDE0XCI6XCJNQVwiLFwiMDE1XCI6XCJNQVwiLFwiMDE2XCI6XCJNQVwiLFwiMDE3XCI6XCJNQVwiLFwiMDE4XCI6XCJNQVwiLFwiMDE5XCI6XCJNQVwiLFwiMDIwXCI6XCJNQVwiLFwiMDIxXCI6XCJNQVwiLFwiMDIyXCI6XCJNQVwiLFwiMDIzXCI6XCJNQVwiLFwiMDI0XCI6XCJNQVwiLFwiMDI1XCI6XCJNQVwiLFwiMDI2XCI6XCJNQVwiLFwiMDI3XCI6XCJNQVwiLFwiMDU1XCI6XCJNQVwiLFwiMDI4XCI6XCJSSVwiLFwiMDI5XCI6XCJSSVwiLFwiMDMwXCI6XCJOSFwiLFwiMDMxXCI6XCJOSFwiLFwiMDMyXCI6XCJOSFwiLFwiMDMzXCI6XCJOSFwiLFwiMDM0XCI6XCJOSFwiLFwiMDM1XCI6XCJWVFwiLFwiMDM2XCI6XCJWVFwiLFwiMDM3XCI6XCJWVFwiLFwiMDM4XCI6XCJOSFwiLFwiMDM5XCI6XCJNRVwiLFwiMDUwXCI6XCJWVFwiLFwiMDUxXCI6XCJWVFwiLFwiMDUyXCI6XCJWVFwiLFwiMDUzXCI6XCJWVFwiLFwiMDU0XCI6XCJWVFwiLFwiMDU2XCI6XCJWVFwiLFwiMDU3XCI6XCJWVFwiLFwiMDU4XCI6XCJWVFwiLFwiMDU5XCI6XCJWVFwiLFwiMDQwXCI6XCJNRVwiLFwiMDQxXCI6XCJNRVwiLFwiMDQyXCI6XCJNRVwiLFwiMDQzXCI6XCJNRVwiLFwiMDQ0XCI6XCJNRVwiLFwiMDQ1XCI6XCJNRVwiLFwiMDQ2XCI6XCJNRVwiLFwiMDQ3XCI6XCJNRVwiLFwiMDQ4XCI6XCJNRVwiLFwiMDQ5XCI6XCJNRVwiLFwiMDYwXCI6XCJDVFwiLFwiMDYxXCI6XCJDVFwiLFwiMDYyXCI6XCJDVFwiLFwiMDY0XCI6XCJDVFwiLFwiMDY1XCI6XCJDVFwiLFwiMDY2XCI6XCJDVFwiLFwiMDY3XCI6XCJDVFwiLFwiMDY4XCI6XCJDVFwiLFwiMDY5XCI6XCJDVFwiLFwiMDcwXCI6XCJOSlwiLFwiMDcxXCI6XCJOSlwiLFwiMDcyXCI6XCJOSlwiLFwiMDczXCI6XCJOSlwiLFwiMDc0XCI6XCJOSlwiLFwiMDc1XCI6XCJOSlwiLFwiMDc2XCI6XCJOSlwiLFwiMDc3XCI6XCJOSlwiLFwiMDc4XCI6XCJOSlwiLFwiMDc5XCI6XCJOSlwiLFwiMDgwXCI6XCJOSlwiLFwiMDgxXCI6XCJOSlwiLFwiMDgyXCI6XCJOSlwiLFwiMDgzXCI6XCJOSlwiLFwiMDg0XCI6XCJOSlwiLFwiMDg1XCI6XCJOSlwiLFwiMDg2XCI6XCJOSlwiLFwiMDg3XCI6XCJOSlwiLFwiMDg4XCI6XCJOSlwiLFwiMDg5XCI6XCJOSlwiLFwiMDkwXCI6XCJBRVwiLFwiMDkxXCI6XCJBRVwiLFwiMDkyXCI6XCJBRVwiLFwiMDkzXCI6XCJBRVwiLFwiMDk0XCI6XCJBRVwiLFwiMDk1XCI6XCJBRVwiLFwiMDk2XCI6XCJBRVwiLFwiMDk3XCI6XCJBRVwiLFwiMDk4XCI6XCJBRVwiLFwiMDk5XCI6XCJBRVwifSIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5WZXJpZnlBZGRyZXNzID0gdmVyaWZ5QWRkcmVzcztcbmV4cG9ydHMuQXV0b2NvbXBsZXRlQWRkcmVzcyA9IGF1dG9jb21wbGV0ZUFkZHJlc3M7XG5leHBvcnRzLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZyA9IHNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZztcbmV4cG9ydHMuQnVpbGRBZGRyZXNzT2JqZWN0RnJvbUNoZWNrb3V0Rm9ybSA9IGJ1aWxkQWRkcmVzc09iamVjdEZyb21DaGVja291dEZvcm07XG5leHBvcnRzLkJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbiA9IGJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbjtcbmV4cG9ydHMuQnVpbGRBZGRyZXNzT2JqZWN0RnJvbUFkZHJlc3NWZXJpZnlSZXNwb25zZSA9IGJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzVmVyaWZ5UmVzcG9uc2U7XG5leHBvcnRzLkNvbXBhcmVBZGRyZXNzT2JqZWN0cyA9IGNvbXBhcmVBZGRyZXNzT2JqZWN0cztcblxudmFyIGRhdGFCdWZmZXIgPSB7fTtcblxuZnVuY3Rpb24gdmVyaWZ5QWRkcmVzcygkZm9ybSwgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0dmFyIGFkZHJlc3NWZXJpZmljYXRpb25QYXlsb2FkID0ge1xuXHRcdFx0cHJpbWFyeV9saW5lOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0c2Vjb25kYXJ5X2xpbmU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHRjaXR5OiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHRzdGF0ZTogJGZvcm0uZmluZCgnc2VsZWN0W25hbWUkPVwiX3N0YXRlXCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHR6aXBfY29kZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJwb3N0YWxcIl0nKS52YWwoKSB8fCAnJ1xuXHRcdH07XG5cdFx0YWRkcmVzc1ZlcmlmaWNhdGlvblBheWxvYWRbb3B0aW9ucy5DU1JGVG9rZW4uTmFtZV0gPSBvcHRpb25zLkNTUkZUb2tlbi5Ub2tlbjtcblxuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdHVybDogVXJscy5Mb2IuQWRkcmVzc1ZlcmlmeSxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShhZGRyZXNzVmVyaWZpY2F0aW9uUGF5bG9hZCksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoIWRhdGEgfHwgIWRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCkge1xuXHRcdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGF0YS5TdGF0dXMgPSAnZGVsaXZlcmFibGUnO1xuXHRcdFx0XHRcdGRhdGEuTWF0Y2ggPSB0cnVlO1xuXHRcdFx0XHRcdGlmIChkYXRhLklucXVpcnlSZXN1bHQpIHtcblx0XHRcdFx0XHRcdGRhdGEuQWRkcmVzc09yaWdpbmFsID0gYnVpbGRBZGRyZXNzT2JqZWN0RnJvbUNoZWNrb3V0Rm9ybSgkZm9ybSk7XG5cdFx0XHRcdFx0XHRkYXRhLkFkZHJlc3NWZXJpZmllZCA9IGJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzVmVyaWZ5UmVzcG9uc2UoZGF0YSk7XG5cdFx0XHRcdFx0XHRkYXRhLkFkZHJlc3NDb21wYXJpc29uID0gY29tcGFyZUFkZHJlc3NPYmplY3RzKGRhdGEuQWRkcmVzc09yaWdpbmFsLCBkYXRhLkFkZHJlc3NWZXJpZmllZCk7XG5cdFx0XHRcdFx0XHRkYXRhLk1hdGNoID0gZGF0YS5BZGRyZXNzQ29tcGFyaXNvbi5NYXRjaDtcblx0XHRcdFx0XHRcdGRhdGEuU3RhdHVzID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRlbGl2ZXJhYmlsaXR5O1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChkYXRhLlN0YXR1cyA9PSAnZGVsaXZlcmFibGUnICYmIGRhdGEuTWF0Y2gpIHtcblx0XHRcdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJlamVjdChkYXRhKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0fSxcblx0XHR9KTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGF1dG9jb21wbGV0ZUFkZHJlc3MoJGZvcm0sICRmaWVsZCwgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0dmFyIGFkZHJlc3NBdXRvY29tcGxldGVQYXlsb2FkID0ge1xuXHRcdFx0YWRkcmVzc19wcmVmaXg6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHRjaXR5OiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHRzdGF0ZTogJGZvcm0uZmluZCgnc2VsZWN0W25hbWUkPVwiX3N0YXRlXCJdJykudmFsKCkgfHwgJycsXG5cdFx0XHR6aXBfY29kZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJwb3N0YWxcIl0nKS52YWwoKSB8fCAnJ1xuXHRcdH07XG5cdFx0YWRkcmVzc0F1dG9jb21wbGV0ZVBheWxvYWRbb3B0aW9ucy5DU1JGVG9rZW4uTmFtZV0gPSBvcHRpb25zLkNTUkZUb2tlbi5Ub2tlbjtcblxuXHRcdGlmIChkYXRhQnVmZmVyICYmIGRhdGFCdWZmZXJbJ0F1dG9jb21wbGV0ZUFkZHJlc3NBamF4J10gJiYgZGF0YUJ1ZmZlclsnQXV0b2NvbXBsZXRlQWRkcmVzc0FqYXgnXS5yZWFkeVN0YXRlICE9PSA0KSB7XG5cdFx0XHRkYXRhQnVmZmVyWydBdXRvY29tcGxldGVBZGRyZXNzQWpheCddLmFib3J0KCk7XG5cdFx0fVxuXG5cdFx0ZGF0YUJ1ZmZlclsnQXV0b2NvbXBsZXRlQWRkcmVzc0FqYXgnXSA9ICQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdHVybDogVXJscy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZSxcblx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShhZGRyZXNzQXV0b2NvbXBsZXRlUGF5bG9hZCksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoIWRhdGEgfHwgIWRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCkge1xuXHRcdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGF0YS4kZm9ybSA9ICRmb3JtO1xuXHRcdFx0XHRcdGRhdGEuJGZpZWxkID0gJGZpZWxkO1xuXG5cdFx0XHRcdFx0cmVzb2x2ZShkYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pXG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coJGZvcm0sIGFkZHJlc3NEYXRhKSB7XG5cdGlmIChhZGRyZXNzRGF0YS5GaXJzdE5hbWUpIHtcblx0XHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9maXJzdE5hbWVcIl0nKS52YWwoYWRkcmVzc0RhdGEuRmlyc3ROYW1lKTtcblx0fVxuXHRpZiAoYWRkcmVzc0RhdGEuTGFzdE5hbWUpIHtcblx0XHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9sYXN0TmFtZVwiXScpLnZhbChhZGRyZXNzRGF0YS5MYXN0TmFtZSk7XG5cdH1cblx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoYWRkcmVzc0RhdGEuUHJpbWFyeUxpbmUpO1xuXHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbChhZGRyZXNzRGF0YS5TZWNvbmRhcnlMaW5lKTtcblx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbChhZGRyZXNzRGF0YS5DaXR5KTtcblx0JGZvcm0uZmluZCgnc2VsZWN0W25hbWUkPVwiX3N0YXRlXCJdJykudmFsKGFkZHJlc3NEYXRhLlN0YXRlQ29kZSk7XG5cdCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbChhZGRyZXNzRGF0YS5Qb3N0YWxDb2RlKTtcblx0aWYgKGFkZHJlc3NEYXRhLkNvdW50cnlDb2RlKSB7XG5cdFx0JGZvcm0uZmluZCgnc2VsZWN0W25hbWUkPVwiX2NvdW50cnlDb2RlXCJdJykudmFsKGFkZHJlc3NEYXRhLkNvdW50cnlDb2RlKTtcblx0fVxuXHRpZiAoYWRkcmVzc0RhdGEuUGhvbmUpIHtcblx0XHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cInBob25lXCJdJykudmFsKGFkZHJlc3NEYXRhLlBob25lKTtcblx0fVxufVxuXG5mdW5jdGlvbiBidWlsZEFkZHJlc3NPYmplY3RGcm9tQ2hlY2tvdXRGb3JtKCRmb3JtKSB7XG5cdHZhciBhZGRyZXNzT2JqZWN0ID0ge307XG5cdFxuXHRhZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKTtcblx0YWRkcmVzc09iamVjdC5TZWNvbmRhcnlMaW5lID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoKTtcblx0YWRkcmVzc09iamVjdC5DaXR5ID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpO1xuXHRhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKTtcblx0YWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCk7XG5cblx0cmV0dXJuIGFkZHJlc3NPYmplY3Q7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbihkYXRhKSB7XG5cdHZhciBhZGRyZXNzT2JqZWN0ID0ge307XG5cblx0aWYgKGRhdGEpIHtcblx0XHRhZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lID0gZGF0YS5wcmltYXJ5X2xpbmUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5TZWNvbmRhcnlMaW5lID0gZGF0YS5zZWNvbmRhcnlfbGluZSB8fCAnJztcblx0XHRhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9IGRhdGEuc3RhdGUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlID0gZGF0YS56aXBfY29kZSB8fCAnJztcblx0XHRhZGRyZXNzT2JqZWN0LkNpdHkgPSBkYXRhLmNpdHkgfHwgJyc7XG5cdH1cblxuXHRyZXR1cm4gYWRkcmVzc09iamVjdDtcbn1cblxuZnVuY3Rpb24gYnVpbGRBZGRyZXNzT2JqZWN0RnJvbUFkZHJlc3NWZXJpZnlSZXNwb25zZShkYXRhKSB7XG5cdHZhciBhZGRyZXNzT2JqZWN0ID0ge307XG5cblx0aWYgKGRhdGEgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0KSB7XG5cdFx0YWRkcmVzc09iamVjdC5QcmltYXJ5TGluZSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5wcmltYXJ5X2xpbmUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5TZWNvbmRhcnlMaW5lID0gZGF0YS5JbnF1aXJ5UmVzdWx0LnNlY29uZGFyeV9saW5lIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuU3RhdGVDb2RlID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmNvbXBvbmVudHMuc3RhdGUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmNvbXBvbmVudHMuemlwX2NvZGUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5DaXR5ID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmNvbXBvbmVudHMuY2l0eSB8fCAnJztcblx0fVxuXG5cdHJldHVybiBhZGRyZXNzT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBjb21wYXJlQWRkcmVzc09iamVjdHMoYWRkcmVzc09yaWdpbmFsLCBhZGRyZXNzVmVyaWZpZWQpIHtcblx0dmFyIGFkZHJlc3NPYmplY3QgPSB7fTtcblxuXHRpZiAoYWRkcmVzc09yaWdpbmFsICYmIGFkZHJlc3NWZXJpZmllZCkge1xuXHRcdGFkZHJlc3NPYmplY3QuUHJpbWFyeUxpbmUgPSBjb21wYXJlQWRkcmVzc0VsZW1lbnQoYWRkcmVzc09yaWdpbmFsLlByaW1hcnlMaW5lLCBhZGRyZXNzVmVyaWZpZWQuUHJpbWFyeUxpbmUpO1xuXHRcdGFkZHJlc3NPYmplY3QuU2Vjb25kYXJ5TGluZSA9IGNvbXBhcmVBZGRyZXNzRWxlbWVudChhZGRyZXNzT3JpZ2luYWwuU2Vjb25kYXJ5TGluZSwgYWRkcmVzc1ZlcmlmaWVkLlNlY29uZGFyeUxpbmUpO1xuXHRcdGFkZHJlc3NPYmplY3QuU3RhdGVDb2RlID0gY29tcGFyZUFkZHJlc3NFbGVtZW50KGFkZHJlc3NPcmlnaW5hbC5TdGF0ZUNvZGUsIGFkZHJlc3NWZXJpZmllZC5TdGF0ZUNvZGUpO1xuXHRcdGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSA9IGNvbXBhcmVBZGRyZXNzRWxlbWVudChhZGRyZXNzT3JpZ2luYWwuUG9zdGFsQ29kZSwgYWRkcmVzc1ZlcmlmaWVkLlBvc3RhbENvZGUpO1xuXHRcdGFkZHJlc3NPYmplY3QuQ2l0eSA9IGNvbXBhcmVBZGRyZXNzRWxlbWVudChhZGRyZXNzT3JpZ2luYWwuQ2l0eSwgYWRkcmVzc1ZlcmlmaWVkLkNpdHkpO1xuXHR9XG5cblx0dmFyIGZpZWxkc0RpZmZlcmVudCA9IFtdO1xuXHRmb3IgKHZhciBhZGRyZXNzRWxlbWVudCBpbiBhZGRyZXNzT2JqZWN0KSB7XG5cdFx0aWYgKCFhZGRyZXNzT2JqZWN0W2FkZHJlc3NFbGVtZW50XSkge1xuXHRcdFx0ZmllbGRzRGlmZmVyZW50W2ZpZWxkc0RpZmZlcmVudC5sZW5ndGhdID0gYWRkcmVzc0VsZW1lbnQ7XG5cdFx0fVxuXHR9XG5cdGFkZHJlc3NPYmplY3QuRmllbGRzRGlmZmVyZW50ID0gZmllbGRzRGlmZmVyZW50O1xuXHRhZGRyZXNzT2JqZWN0Lk1hdGNoID0gZmllbGRzRGlmZmVyZW50Lmxlbmd0aCA9PSAwO1xuXG5cdHJldHVybiBhZGRyZXNzT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBjb21wYXJlQWRkcmVzc0VsZW1lbnQoYWRkcmVzc0VsZW1lbnRPcmlnaW5hbCwgYWRkcmVzc0VsZW1lbnRWZXJpZmllZCkge1xuXHRhZGRyZXNzRWxlbWVudE9yaWdpbmFsID0gYWRkcmVzc0VsZW1lbnRPcmlnaW5hbCB8fCAnJztcblx0YWRkcmVzc0VsZW1lbnRWZXJpZmllZCA9IGFkZHJlc3NFbGVtZW50VmVyaWZpZWQgfHwgJyc7XG5cblx0cmV0dXJuIGFkZHJlc3NFbGVtZW50T3JpZ2luYWwudHJpbSgpLnRvTG93ZXJDYXNlKCkgPT0gYWRkcmVzc0VsZW1lbnRWZXJpZmllZC50cmltKCkudG9Mb3dlckNhc2UoKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuUmVzcG9uc2VDb2RlcyA9IHtcblx0QWxyZWFkeUluQmFza2V0OiAnQUxSRUFEWV9JTl9CQVNLRVQnXG59XG5cbmV4cG9ydHMuVXNlciA9IHtcblx0U2VsZWN0ZWRDdXN0b21lclNoaXBwaW5nTWV0aG9kOiAnc2VsZWN0ZWRDdXN0b21lclNoaXBwaW5nTWV0aG9kJyxcblx0U2VsZWN0ZWRTdG9yZVNoaXBwaW5nTWV0aG9kOiAnc2VsZWN0ZWRTdG9yZVNoaXBwaW5nTWV0aG9kJ1xufVxuXG5leHBvcnRzLlNoaXBwaW5nTWV0aG9kcyA9IHtcblx0Qm9waXM6ICdCb3BpcycsXG5cdExvY2FsRGVsaXZlcnk6ICdMb2NhbERlbGl2ZXJ5Jyxcblx0U2hpcFRvU3RvcmU6ICdTaGlwLXRvLVN0b3JlJyxcblx0U2hpcFRvU3RvcmVQaWNrdXA6ICdNeV9TdG9yZV9GcmVlX1NoaXBwaW5nJyxcblx0U2hpcFRvU3RvcmVQaWNrdXBGb3JXaGlwOiAnV0hJUCBGUkVFIFNoaXAtdG8tc3RvcmUnLFxuXHRWaXJ0dWFsOiAnVmlydHVhbCdcbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuRXZlbnRzID0ge1xuXHRDYXJ0OiB7XG5cdFx0QWRkVG9DYXJ0OiB7XG5cdFx0XHROYW1lOiAnQWRkVG9DYXJ0J1xuXHRcdH0sXG5cdFx0UmVtb3ZlRnJvbUNhcnQ6IHtcblx0XHRcdE5hbWU6ICdSZW1vdmVGcm9tQ2FydCdcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0cy5FdmVudFR5cGVzID0ge1xuXHRNaW51czogJ21pbnVzJyxcblx0UGx1czogJ3BsdXMnXG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLkdldFBvc2l0aW9uID0gZ2V0UG9zaXRpb247XG5cbmZ1bmN0aW9uIGdldFBvc2l0aW9uKCkge1xuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuXHRcdGlmIChuYXZpZ2F0b3IuZ2VvbG9jYXRpb24pIHtcblx0XHRcdHZhciBnZW9sb2NhdGlvblN1Y2Nlc3MgPSBmdW5jdGlvbihwb3NpdGlvbikge1x0XG5cdFx0XHRcdHJlc29sdmUocG9zaXRpb24pO1xuXHRcdFx0fTtcblxuXHRcdFx0dmFyIGdlb2xvY2F0aW9uRXJyb3IgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmVzb2x2ZSgpO1xuXHRcdFx0fTtcblxuXHRcdFx0bmF2aWdhdG9yLmdlb2xvY2F0aW9uLmdldEN1cnJlbnRQb3NpdGlvbihnZW9sb2NhdGlvblN1Y2Nlc3MsIGdlb2xvY2F0aW9uRXJyb3IpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXNvbHZlKCk7XG5cdFx0fVxuXHR9KTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuU2xpY2tTbGlkZXIgPSB7XG5cdE9wdGlvbnM6IHtcblx0XHRTaW5nbGU6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0aW5maW5pdGU6IFx0XHR0cnVlLFxuXHRcdFx0ZG90czogXHRcdFx0ZmFsc2UsXG5cdFx0XHRhcnJvd3M6IFx0XHRmYWxzZSxcblx0XHRcdHNsaWRlc1RvU2hvdzogXHQxLFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDEsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2Nyxcblx0XHRcdFx0XHRzZXR0aW5nczogXHR7XG5cdFx0XHRcdFx0XHRkb3RzOiBcdHRydWUsXG5cdFx0XHRcdFx0XHRhcnJvd3M6IHRydWVcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwXG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9LFxuXHRcdFRodW1ibmFpbDoge1xuXHRcdFx0YWNjZXNzaWJpbGl0eTogIHRydWUsXG5cdFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0aW5maW5pdGU6IGZhbHNlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBmYWxzZSxcblx0XHRcdHNsaWRlc1RvU2hvdzogNyxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiA3LFxuXHRcdFx0cmVzcG9uc2l2ZTogXHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiA3Njdcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDEyMDAsXG5cdFx0XHRcdFx0c2V0dGluZ3M6IHtcblx0XHRcdFx0XHRcdHNsaWRlc1RvU2hvdzogNCxcblx0XHRcdFx0XHRcdHNsaWRlc1RvU2Nyb2xsOiA0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSxcblx0XHRDYXRlZ29yeUxhbmRpbmc6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0ZHJhZ2dhYmxlOiB0cnVlLFxuXHRcdFx0aW5maW5pdGU6IHRydWUsXG5cdFx0XHRmb2N1c09uU2VsZWN0OiBcdGZhbHNlLFxuXHRcdFx0ZG90czogZmFsc2UsXG5cdFx0XHRhcnJvd3M6IHRydWUsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDQsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogNCxcblx0XHRcdHJlc3BvbnNpdmU6IFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogNzY3XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwLFxuXHRcdFx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Nob3c6IDMsXG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Njcm9sbDogM1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH1cblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5QYXltZW50TWV0aG9kcyA9IHtcblx0QWxsaWFuY2VEYXRhOiAnQWxsaWFuY2VfRGF0YScsXG5cdEFwcGxlUGF5OiAnRFdfQVBQTEVfUEFZJyxcblx0QmlsbE1lTGF0ZXI6ICdCTUwnLFxuXHRDcmVkaXRDYXJkOiAnQ1JFRElUX0NBUkQnLFxuXHRHaWZ0Q2VydGlmaWNhdGU6ICdHSUZUX0NFUlRJRklDQVRFJyxcblx0UGF5UGFsOiAnUGF5UGFsJyxcblx0R2xvYmFsZTogJ0dMT0JBTEUnLFxuXHRSZXdhcmRzQ3JlZGl0OiAnUkVXQVJEU19DUkVESVQnLFxuXHRMb3lhbHR5Q3JlZGl0OiAnTE9ZQUxUWV9DUkVESVQnLFxuXHRTdG9yZWRWYWx1ZVNvbHV0aW9uczogJ1NWU19HaWZ0X0NhcmQnLFxuXHRBZmZpcm06ICdBZmZpcm0nLFxuXHRQYXltZW50Vm91Y2hlcjogJ0IyQl9QYXltZW50X1ZvdWNoZXInLFxuXHRTaG9wUGF5OiAnU2hvcFBheSdcbn07XG5cbmV4cG9ydHMuQ3JlZGl0Q2FyZHMgPSB7XG5cdEFtZXJpY2FuRXhwcmVzczogJ0FtZXgnLFxuXHRCb290QmFybkNyZWRpdDogJ0Jvb3QgQmFybiBDcmVkaXQgQ2FyZCcsXG5cdERpc2NvdmVyOiAnRGlzY292ZXInLFxuXHRKQ0I6ICdKQ0InLFxuXHRNYWVzdHJvOiAnTWFlc3RybycsXG5cdE1hc3RlcmNhcmQ6ICdNYXN0ZXInLFxuXHRNYXN0ZXJjYXJkU2VyaWVzMjogJ01hc3RlciBTZXJpZXMgMicsXG5cdFZpc2E6ICdWaXNhJ1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuUmVmaW5lbWVudHNVSVZlcnNpb25zID0ge1xuXHRVcGRhdGVkOiAnVXBkYXRlZCcsXG5cdExlZ2FjeTogJ0xlZ2FjeSdcbn0iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRWYWxpZGF0aW9uOiB7XG5cdFx0RW1haWw6IC9eW2EtekEtWjAtOS4hIyQlJicqK1xcLz0/Xl9ge3x9fi1dK0BbYS16QS1aMC05XSg/OlthLXpBLVowLTktXXswLDYxfVthLXpBLVowLTldKT8oPzpcXC5bYS16QS1aMC05XSg/OlthLXpBLVowLTktXXswLDYxfVthLXpBLVowLTldKT8pKiQvLFxuXHRcdE9yZGVyTnVtYmVyOiAvXlthLXpBLVpdezAsNn1bLS5fXXswLDF9WzAtOV17NiwxMn0kLyxcblx0XHRQb3N0YWxDb2RlOiAvXlthLXpBLVowLTldW2EtekEtWjAtOVxcLSBdezAsMTB9W2EtekEtWjAtOV0kLyxcblx0XHRQb3N0T2ZmaWNlQm94OiAvKCgoKHBbXFxzXFwuXT8pXFxzP1tvXFxzXVtcXC5dPylcXHM/KXwocG9zdFxccz9vZmZpY2VcXHM/KXwocG9zdGFsXFxzPyl8KHBvc3RcXHM/KSkoKGJveHxiaW58YlxcLj8pP1xccz8oKG51bXxudW1iZXJ8bm98IylcXC4/KT9cXHM/XFxkKykvaSxcblx0XHRaaXBDb2RlOiAvXlswLTldezV9KC1bMC05XXs0fSkqJC8sXG5cdFx0UmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbjogL15bI10qW15fXFxXXSsvLFxuXHRcdEdpZnRDYXJkTnVtYmVyTGVuZ3RoOiAvKFxcZCkvZyxcblx0XHRHaWZ0Q2FyZE51bWJlclZhbHVlczogL15bLVxcczAtOV0qJC8sXG5cdH1cbn1cblxuLy8gRW1haWwgcGF0dGVybiBpcyBmcm9tIFczQyBzcGVjLCBzYW1lIHRoYXQgalF1ZXJ5IFZhbGlkYXRlIHVzZXM6IGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL2lucHV0Lmh0bWwjdmFsaWQtZS1tYWlsLWFkZHJlc3Ncbi8vIFBvc3RhbCBDb2RlIHBhdHRlcm4gaXMgZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81Nzg0MDYvd2hhdC1pcy10aGUtdWx0aW1hdGUtcG9zdGFsLWNvZGUtYW5kLXppcC1yZWdleFxuLy8gUE8gQm94IHBhdHRlcm4gaXMgbW9kaWZpZWQgZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81NjgwMDUwL3BvLWJveC1yZWd1bGFyLWV4cHJlc3Npb24tdmFsaWRhdGlvbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5BZGRyZXNzVHlwZXMgPSB7XG5cdEN1c3RvbWVyOiAnQ3VzdG9tZXJBZGRyZXNzJyxcblx0U3RvcmU6ICdTdG9yZUFkZHJlc3MnXG59XG5cbmV4cG9ydHMuQ291bnRyeUNvZGVzID0ge1xuXHRVbml0ZWRTdGF0ZXM6ICdVUycsXG5cdENhbmFkYTogJ0NBJ1xufVxuXG5leHBvcnRzLlN0YXRlQ29kZXMgPSB7XG5cdE5ld1lvcms6ICdOWSdcbn1cblxuZXhwb3J0cy5LZXlDb2RlcyA9IHtcblx0RW50ZXI6IDEzLFxuXHRUYWI6IDksXG5cdEFycm93TGVmdDogMzcsXG5cdEFycm93VXA6IDM4LFxuXHRBcnJvd1JpZ2h0OiAzOSxcblx0QXJyb3dEb3duOiA0MFxufVxuXG5leHBvcnRzLlJlc3BvbnNpdmUgPSB7XG5cdFdpZHRoczoge1xuXHRcdE1vYmlsZTogNzY3LFxuXHRcdFRhYmxldDogMTAyNFxuXHR9XG59XG5cbmV4cG9ydHMuU2l0ZUlkcyA9IHtcblx0Qm9vdEJhcm5VUzogJ2Jvb3RiYXJuX3VzJyxcblx0U2hlcGxlcnNVUzogJ3NoZXBsZXJzX3VzJyxcblx0Q291bnRyeU91dGZpdHRlcnNVUzogJ2NvdW50cnlfb3V0Zml0dGVyc191cycsXG5cdEJvb3RCYXJuUnNwVVM6ICdib290YmFybl9yc3BfdXMnLFxuXHRCb290QmFyblBheW1lbnRzOiAnYm9vdGJhcm5fcGF5bWVudHMnLFxuXHRCb290QmFybkIyQlVTOiAnYm9vdGJhcm5fYjJiX3VzJyxcblx0UmFuZ2VmaW5kZXI6ICdyYW5nZWZpbmRlcidcbn1cblxuZXhwb3J0cy5Qcm9kdWN0UmVjb21tZW5kYXRpb25TeXN0ZW1zID0ge1xuXHRFaW5zdGVpbjogJ0VpbnN0ZWluJyxcblx0UmVsZXZhbnQ6ICdSZWxldmFudCdcbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuTG9kYXNoID0ge1xuXHRTZXR0aW5nczoge1xuXHRcdGludGVycG9sYXRlOiAve3soW1xcc1xcU10rPyl9fS9nXG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuU2V0dGluZ3MgPSB7XG5cdEdsb2JhbDoge1xuXHQgICAgZXJyb3JDbGFzczogJ2Vycm9yJyxcblx0ICAgIGVycm9yRWxlbWVudDogJ3NwYW4nLFxuXHQgICAgb25rZXl1cDogZmFsc2UsXG5cdCAgICBlcnJvclBsYWNlbWVudDogZnVuY3Rpb24gKGVycm9yLCBlbGVtZW50KSB7XG5cdFx0XHR2YXIgJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lciA9IGVsZW1lbnQuY2xvc2VzdCgnZm9ybScpLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpO1xuXHRcdFx0aWYgKCR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRlcnJvci5hcHBlbmRUbygkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyKTtcblx0ICAgIFx0fSBlbHNlIGlmIChlbGVtZW50LmF0dHIoJ2Vycm9yLWNvbnRhaW5lcicpKSB7XG5cdCAgICBcdFx0ZXJyb3IuYXBwZW5kVG8oJChlbGVtZW50LmF0dHIoJ2Vycm9yLWNvbnRhaW5lcicpKSk7XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0ZXJyb3IuYXBwZW5kVG8oZWxlbWVudC5wYXJlbnQoKSk7XG5cdCAgICBcdH1cblx0ICAgIH1cblx0fSxcblx0Q2hlY2tvdXQ6IHtcblx0ICAgIGVycm9yUGxhY2VtZW50OiBmdW5jdGlvbihlcnJvciwgZWxlbWVudCkge1xuXHQgICAgXHRpZiAoZWxlbWVudC5hdHRyKCdlcnJvci1jb250YWluZXInKSkge1xuXHQgICAgXHRcdGVycm9yLmFwcGVuZFRvKCQoZWxlbWVudC5hdHRyKCdlcnJvci1jb250YWluZXInKSkpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdGVycm9yLmFwcGVuZFRvKGVsZW1lbnQucGFyZW50KCkpO1xuXHQgICAgXHR9XG5cblx0XHRcdHZhciAkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyID0gZWxlbWVudC5jbG9zZXN0KCdmb3JtJykuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJyk7XG5cdFx0XHRpZiAoJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lci5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHZhciAkZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cdFx0XHRcdHZhciAkZWxlbWVudFZhbGlkYXRpb25FcnJvciA9ICR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3JbZmllbGQ9XCInICsgJGVsZW1lbnQuYXR0cignaWQnKSArICdcIl0nKTtcblx0XHRcdFx0aWYgKCRlbGVtZW50VmFsaWRhdGlvbkVycm9yLmxlbmd0aCA8PSAwKSB7XG5cdFx0XHRcdFx0dmFyIHZhbGlkYXRpb25FcnJvclRleHQgPSAkKCc8c3BhbiBjbGFzcz1cInZhbGlkYXRpb24tZXJyb3JcIiBmaWVsZD1cIicgKyAkZWxlbWVudC5hdHRyKCdpZCcpICsgJ1wiIC8+JykudGV4dCgkZWxlbWVudC5jbG9zZXN0KCcuZm9ybWZpZWxkJykuZmluZCgnbGFiZWwgc3BhbicpLnRleHQoKSArICcgaXMgcmVxdWlyZWQuJyk7XG5cdFx0XHRcdFx0JHZhbGlkYXRpb25FcnJvckNvbnRhaW5lci5hcHBlbmQodmFsaWRhdGlvbkVycm9yVGV4dCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0ICAgIH0sXG5cdFx0b25mb2N1c291dDogZnVuY3Rpb24oZWxlbWVudCkge1xuXHRcdFx0aWYgKCF0aGlzLmNoZWNrYWJsZShlbGVtZW50KSkge1xuXHRcdFx0XHR2YXIgaXNFbGVtZW50VmFsaWQgPSB0aGlzLmVsZW1lbnQoZWxlbWVudCk7XG5cdFx0XHRcdHZhciAkZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cdFx0XHRcdHZhciAkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyID0gJGVsZW1lbnQuY2xvc2VzdCgnZm9ybScpLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpO1xuXHRcdFx0XHR2YXIgJGVsZW1lbnRWYWxpZGF0aW9uRXJyb3IgPSAkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yW2ZpZWxkPVwiJyArICRlbGVtZW50LmF0dHIoJ2lkJykgKyAnXCJdJyk7XG5cdFx0XHRcdGlmIChpc0VsZW1lbnRWYWxpZCAmJiAkZWxlbWVudFZhbGlkYXRpb25FcnJvci5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JGVsZW1lbnRWYWxpZGF0aW9uRXJyb3IucmVtb3ZlKCk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIWlzRWxlbWVudFZhbGlkICYmICRlbGVtZW50VmFsaWRhdGlvbkVycm9yLmxlbmd0aCA8PSAwKSB7XG5cdFx0XHRcdFx0dmFyIHZhbGlkYXRpb25FcnJvclRleHQgPSAkKCc8c3BhbiBjbGFzcz1cInZhbGlkYXRpb24tZXJyb3JcIiBmaWVsZD1cIicgKyAkZWxlbWVudC5hdHRyKCdpZCcpICsgJ1wiIC8+JykudGV4dCgkZWxlbWVudC5jbG9zZXN0KCcuZm9ybWZpZWxkJykuZmluZCgnbGFiZWwgc3BhbicpLnRleHQoKSArICcgaXMgcmVxdWlyZWQuJyk7XG5cdFx0XHRcdFx0JHZhbGlkYXRpb25FcnJvckNvbnRhaW5lci5hcHBlbmQodmFsaWRhdGlvbkVycm9yVGV4dCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0cy5SdWxlcyA9IHtcblx0UmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbjoge1xuXHRcdHJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb246IHRydWVcblx0fSxcblx0VmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveDoge1xuXHRcdHBvc3RPZmZpY2VCb3g6IHRydWVcblx0fSxcblx0VmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHk6IHtcblx0XHRwb3N0T2ZmaWNlQm94T25seTogdHJ1ZVxuXHR9LFxuXHRFbWFpbDoge1xuXHRcdGVtYWlsOiB0cnVlLFxuXHRcdG1pbmxlbmd0aDogMVxuXHR9LFxuXHRPcmRlck51bWJlcjoge1xuXHRcdG9yZGVyTnVtYmVyOiB0cnVlXG5cdH0sXG5cdFBvc3RhbENvZGU6IHtcblx0XHRwb3N0YWxDb2RlOiB0cnVlXG5cdH0sXG5cdFBvc3RhbENvZGVBbmRTdGF0ZUNvZGU6IHtcblx0XHRwb3N0YWxDb2RlOiB0cnVlLFxuXHRcdHppcENvZGVGb3JTdGF0ZUNvZGU6IHRydWVcblx0fSxcblx0WmlwQ29kZToge1xuXHRcdHppcENvZGU6IHRydWVcblx0fSxcblx0WmlwQ29kZUFuZFN0YXRlQ29kZToge1xuXHRcdHppcENvZGU6IHRydWUsXG5cdFx0emlwQ29kZUZvclN0YXRlQ29kZTogdHJ1ZVxuXHR9LFxuXHRTdGF0ZUNvZGVGb3JDYWxpZm9ybmlhU3RhdGVMaW5lOiB7XG5cdFx0c3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZTogdHJ1ZVxuXHR9LFxuXHRHaWZ0Q2FyZDoge1xuXHRcdE51bWJlcjoge1xuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRnaWZ0Q2FyZE51bWJlckxlbmd0aDogdHJ1ZSxcblx0XHRcdGdpZnRDYXJkTnVtYmVyVmFsdWVzOiB0cnVlXG5cdFx0fSxcblx0XHRQaW46IHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGlnaXRzOiB0cnVlLFxuXHRcdFx0bWlubGVuZ3RoOiA0LFxuXHRcdFx0bWF4bGVuZ3RoOiA4LFxuXHRcdFx0bWVzc2FnZXM6IHtcblx0XHRcdFx0bWlubGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuTnVtYmVycy5NaW5pbXVtTGVuZ3RoKSxcblx0XHRcdFx0bWF4bGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuTnVtYmVycy5NYXhpbXVtTGVuZ3RoKVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0UmV3YXJkc0NyZWRpdDoge1xuXHRcdE51bWJlcjoge1xuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRkaWdpdHM6IHRydWUsXG5cdFx0XHRtaW5sZW5ndGg6IDE2LFxuXHRcdFx0bWF4bGVuZ3RoOiAxNixcblx0XHRcdG1lc3NhZ2VzOiB7XG5cdFx0XHRcdG1pbmxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWluaW11bUxlbmd0aCksXG5cdFx0XHRcdG1heGxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWF4aW11bUxlbmd0aClcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdExveWFsdHlDcmVkaXQ6IHtcblx0XHROdW1iZXI6IHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGlnaXRzOiB0cnVlLFxuXHRcdFx0bWlubGVuZ3RoOiAxLFxuXHRcdFx0bWF4bGVuZ3RoOiAxMCxcblx0XHRcdG1lc3NhZ2VzOiB7XG5cdFx0XHRcdG1pbmxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWluaW11bUxlbmd0aCksXG5cdFx0XHRcdG1heGxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWF4aW11bUxlbmd0aClcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdFBheW1lbnRWb3VjaGVyOiB7XG5cdFx0TnVtYmVyOiB7XG5cdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdGRpZ2l0czogZmFsc2UsXG5cdFx0XHRtaW5sZW5ndGg6IDEsXG5cdFx0XHRtYXhsZW5ndGg6IDI4LFxuXHRcdFx0bWVzc2FnZXM6IHtcblx0XHRcdFx0bWlubGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuTnVtYmVycy5NaW5pbXVtTGVuZ3RoKSxcblx0XHRcdFx0bWF4bGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuTnVtYmVycy5NYXhpbXVtTGVuZ3RoKVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5QdXNoRGF0YUxheWVyRm9yUGFnZSA9IHB1c2hEYXRhTGF5ZXJGb3JQYWdlO1xuZXhwb3J0cy5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSA9IHB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlO1xuZXhwb3J0cy5QdXNoRGF0YUxheWVyRm9yRXZlbnQgPSBwdXNoRGF0YUxheWVyRm9yRXZlbnQ7XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXJGb3JQYWdlKHBhZ2UpIHtcblx0d2luZG93LmRhdGFMYXllciA9IHdpbmRvdy5kYXRhTGF5ZXIgfHwgW107XG5cblx0aWYgKHBhZ2UpIHtcblx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkVuYWJsZUdvb2dsZUFuYWx5dGljczQpIHtcblx0XHRcdHB1c2hEYXRhTGF5ZXJGb3JQYWdlRm9yR29vZ2xlQW5hbHl0aWNzNChwYWdlKTtcblx0XHR9XG5cdFx0cHVzaERhdGFMYXllckZvclBhZ2VGb3JVbml2ZXJzYWxBbmFseXRpY3MocGFnZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcHVzaERhdGFMYXllckZvclBhZ2VGb3JHb29nbGVBbmFseXRpY3M0KHBhZ2UpIHtcblx0d2luZG93LmRhdGFMYXllciA9IHdpbmRvdy5kYXRhTGF5ZXIgfHwgW107XG5cblx0aWYgKHBhZ2UpIHtcblx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlRm9yR29vZ2xlQW5hbHl0aWNzNCkge1xuXHRcdFx0dmFyIGRhdGFMYXllcjtcblx0XHRcdGlmIChwYWdlLm5zID09ICdvcmRlcmNvbmZpcm1hdGlvbicpIHtcblx0XHRcdFx0ZGF0YUxheWVyID0gcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuRGF0YUxheWVyQ2FjaGVGb3JHb29nbGVBbmFseXRpY3M0O1xuXHRcdFx0XHRkYXRhTGF5ZXIuaXRlbXMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKCdkYXRhLXByb2R1Y3QtZ2E0LWpzb24nKTtcblx0XHRcdFx0cHVzaERhdGFMYXllcihkYXRhTGF5ZXIpO1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGRhdGFMYXllcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBUaGlzIHNob3VsZCBiZSBhY3RpdmF0ZWQgd2hlbiBVQSBpcyByZW1vdmVkLlxuXHRcdFx0XHQvLyAkLmFqYXgoe1xuXHRcdFx0XHQvLyBcdHVybDogVXJscy5Hb29nbGVUYWdNYW5hZ2VyLkdldERhdGFMYXllcixcblx0XHRcdFx0Ly8gXHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdC8vIFx0ZGF0YToge1xuXHRcdFx0XHQvLyBcdFx0RGF0YUxheWVyVHlwZTogJ0dlbmVyYWwnLFxuXHRcdFx0XHQvLyBcdFx0RGF0YUxheWVyVmVyc2lvbjogJ0dvb2dsZUFuYWx5dGljczQnXG5cdFx0XHRcdC8vIFx0fSxcblx0XHRcdFx0Ly8gXHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHQvLyBcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0Ly8gXHRcdGRhdGFMYXllciA9ICQuZXh0ZW5kKHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlRm9yR29vZ2xlQW5hbHl0aWNzNCwgZGF0YSk7XG5cdFx0XHRcdC8vIFx0XHR3aW5kb3cuZGF0YUxheWVyLnB1c2goZGF0YUxheWVyKTtcblx0XHRcdFx0Ly8gXHR9LFxuXHRcdFx0XHQvLyBcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHQvLyBcdH1cblx0XHRcdFx0Ly8gfSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoaXMgc2hvdWxkIGJlIGFjdGl2YXRlZCB3aGVuIFVBIGlzIHJlbW92ZWQuXG5cdFx0XHQvLyAkKGRvY3VtZW50KS50cmlnZ2VyKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGRhdGFMYXllcik7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChwYWdlLm5zICE9ICdvcmRlcmNvbmZpcm1hdGlvbicpIHtcblx0XHRcdHZhciBwYXlsb2FkID0ge307XG5cblx0XHRcdHZhciBkYXRhTGF5ZXJQYWdlVHlwZTtcblx0XHRcdGlmIChwYWdlLm9wdGlvbnMgJiYgcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIgJiYgcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuUGFnZVR5cGUpIHtcblx0XHRcdFx0ZGF0YUxheWVyUGFnZVR5cGUgPSBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5QYWdlVHlwZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFMYXllclBhZ2VUeXBlID0gcGFnZS5ucztcblx0XHRcdH1cdFx0XG5cdFx0XHRwYXlsb2FkLlBhZ2UgPSBkYXRhTGF5ZXJQYWdlVHlwZTtcdFxuXG5cdFx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyKSB7XG5cdFx0XHRcdHBheWxvYWQuT3B0aW9ucyA9IEpTT04uc3RyaW5naWZ5KHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyKTtcblx0XHRcdFx0cGF5bG9hZC5EYXRhTGF5ZXJWZXJzaW9uID0gJ0dvb2dsZUFuYWx5dGljczQnO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMuR29vZ2xlVGFnTWFuYWdlci5HZXREYXRhTGF5ZXIsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChwYWdlLm9wdGlvbnMgJiYgcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIgJiYgcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuRGF0YUxheWVyQ2FjaGVGb3JHb29nbGVBbmFseXRpY3M0KSB7XG5cdFx0XHRcdFx0XHRkYXRhID0gJC5leHRlbmQocGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuRGF0YUxheWVyQ2FjaGVGb3JHb29nbGVBbmFseXRpY3M0LCBkYXRhKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKHBhZ2UubnMgPT0gJ3Byb2R1Y3QnKSB7XG5cdFx0XHRcdFx0XHRpZiAoIWRhdGEudmFsdWUgJiYgZGF0YS5pdGVtcyAmJiBkYXRhLml0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0ZGF0YS5jdXJyZW5jeSA9IGRhdGEuaXRlbXNbMF0uY3VycmVuY3k7XG5cdFx0XHRcdFx0XHRcdGRhdGEudmFsdWUgPSBkYXRhLml0ZW1zWzBdLnByaWNlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAocGFnZS5ucyA9PSAnc2VhcmNoJykge1xuXHRcdFx0XHRcdFx0ZGF0YS5pdGVtcyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicsIHsgQ29udGFpbmVyOiAkKCcuc2VhcmNoLXJlc3VsdC1jb250ZW50JykgfSk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwYWdlLm5zID09ICdjYXJ0JyB8fCBwYWdlLm5zID09ICdvbmVwY2hlY2tvdXQnIHx8IHBhZ2UubnMgPT0gJ29uZXBjaGVja291dF9ncm91cHMnKSB7XG5cdFx0XHRcdFx0XHRkYXRhLml0ZW1zID0gZ2V0UHJvZHVjdERhdGFMYXllcignZGF0YS1wcm9kdWN0LWdhNC1qc29uJyk7XG5cdFx0XHRcdFx0XHRpZiAoIWRhdGEudmFsdWUgJiYgZGF0YS5pdGVtcyAmJiBkYXRhLml0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0dmFyIHZhbHVlID0gMDtcblx0XHRcdFx0XHRcdFx0Zm9yICh2YXIgaXRlbUtleSBpbiBkYXRhLml0ZW1zKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIGl0ZW0gPSBkYXRhLml0ZW1zW2l0ZW1LZXldO1xuXHRcdFx0XHRcdFx0XHRcdHZhbHVlICs9IGl0ZW0ucHJpY2U7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0ZGF0YS52YWx1ZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwdXNoRGF0YUxheWVyKGRhdGEpO1xuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0RhdGFMYXllci5PcmRlckNvbXBsZXRlJywgZGF0YSk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXJGb3JQYWdlRm9yVW5pdmVyc2FsQW5hbHl0aWNzKHBhZ2UpIHtcblx0d2luZG93LmRhdGFMYXllciA9IHdpbmRvdy5kYXRhTGF5ZXIgfHwgW107XG5cblx0aWYgKHBhZ2UpIHtcblx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlKSB7XG5cdFx0XHR2YXIgZGF0YUxheWVyO1xuXHRcdFx0aWYgKHBhZ2UubnMgPT0gJ29yZGVyY29uZmlybWF0aW9uJykge1xuXHRcdFx0XHRkYXRhTGF5ZXIgPSBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5EYXRhTGF5ZXJDYWNoZTtcblx0XHRcdFx0ZGF0YUxheWVyLmVjb21tZXJjZSA9IGRhdGFMYXllci5lY29tbWVyY2UgfHwge307XG5cdFx0XHRcdGRhdGFMYXllci5lY29tbWVyY2UucHVyY2hhc2UgPSBkYXRhTGF5ZXIuZWNvbW1lcmNlLnB1cmNoYXNlIHx8IHt9O1xuXHRcdFx0XHRkYXRhTGF5ZXIuZWNvbW1lcmNlLnB1cmNoYXNlLnByb2R1Y3RzID0gZ2V0UHJvZHVjdERhdGFMYXllcigpO1xuXHRcdFx0XHRwdXNoRGF0YUxheWVyKGRhdGFMYXllcik7XG5cdFx0XHRcdC8vICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0RhdGFMYXllci5PcmRlckNvbXBsZXRlJywgZGF0YUxheWVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0dXJsOiBVcmxzLkdvb2dsZVRhZ01hbmFnZXIuR2V0RGF0YUxheWVyLFxuXHRcdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0XHREYXRhTGF5ZXJUeXBlOiAnR2VuZXJhbCcsXG5cdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiAnVW5pdmVyc2FsQW5hbHl0aWNzJ1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHRkYXRhTGF5ZXIgPSAkLmV4dGVuZChwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5EYXRhTGF5ZXJDYWNoZSwgZGF0YSk7XG5cdFx0XHRcdFx0XHRwdXNoRGF0YUxheWVyKGRhdGFMYXllcik7XG5cdFx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGRhdGFMYXllcik7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHRpZiAocGFnZS5ucyAhPSAnb3JkZXJjb25maXJtYXRpb24nKSB7XG5cdFx0XHR2YXIgcGF5bG9hZCA9IHtcblx0XHRcdFx0UGFnZTogcGFnZS5uc1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyKSB7XG5cdFx0XHRcdHBheWxvYWQuT3B0aW9ucyA9IEpTT04uc3RyaW5naWZ5KHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyKTtcblx0XHRcdFx0cGF5bG9hZC5EYXRhTGF5ZXJWZXJzaW9uID0gJ1VuaXZlcnNhbEFuYWx5dGljcyc7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHVybDogVXJscy5Hb29nbGVUYWdNYW5hZ2VyLkdldERhdGFMYXllcixcblx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKHBhZ2UubnMgPT0gJ3NlYXJjaCcpIHtcblx0XHRcdFx0XHRcdGRhdGEuZWNvbW1lcmNlID0gZGF0YS5lY29tbWVyY2UgfHwge307XG5cdFx0XHRcdFx0XHRkYXRhLmVjb21tZXJjZS5pbXByZXNzaW9ucyA9IGdldFByb2R1Y3REYXRhTGF5ZXIobnVsbCwgeyBDb250YWluZXI6ICQoJy5zZWFyY2gtcmVzdWx0LWNvbnRlbnQnKSB9KTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHBhZ2UubnMgPT0gJ3Byb2R1Y3QnKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmVjb21tZXJjZSA9IGRhdGEuZWNvbW1lcmNlIHx8IHt9O1xuXHRcdFx0XHRcdFx0ZGF0YS5lY29tbWVyY2UuZGV0YWlsID0gZGF0YS5lY29tbWVyY2UuZGV0YWlsIHx8IHt9O1xuXHRcdFx0XHRcdFx0ZGF0YS5lY29tbWVyY2UuZGV0YWlsLnByb2R1Y3RzID0gZ2V0UHJvZHVjdERhdGFMYXllcigpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAocGFnZS5ucyA9PSAnY2FydCcgfHwgcGFnZS5ucyA9PSAnb25lcGNoZWNrb3V0JyB8fCBwYWdlLm5zID09ICdvbmVwY2hlY2tvdXRfZ3JvdXBzJykge1xuXHRcdFx0XHRcdFx0ZGF0YS5lY29tbWVyY2UgPSBkYXRhLmVjb21tZXJjZSB8fCB7fTtcblx0XHRcdFx0XHRcdGRhdGEuZWNvbW1lcmNlLmNhcnRDb250ZW50cyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cHVzaERhdGFMYXllcihkYXRhKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoZGF0YUxheWVyVHlwZSwgZGF0YU9iamVjdCwgb3B0aW9ucykge1xuXHR2YXIgZGF0YU9iamVjdCA9IGRhdGFPYmplY3QgfHwge307XG5cblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdHZhciBhamF4Q29tcGxldGVTdGF0dXMgPSB7XG5cdFx0XHRHb29nbGVBbmFseXRpY3M0OiAnJyxcblx0XHRcdFVuaXZlcnNhbEFuYWx5dGljczogJydcblx0XHR9XG5cblx0XHR2YXIgYWpheENvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoYWpheENvbXBsZXRlU3RhdHVzLlVuaXZlcnNhbEFuYWx5dGljcyA9PSAnc3VjY2VzcycgJiYgYWpheENvbXBsZXRlU3RhdHVzLkdvb2dsZUFuYWx5dGljczQgPT0gJ3N1Y2Nlc3MnKSB7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdH0gZWxzZSBpZiAoYWpheENvbXBsZXRlU3RhdHVzLlVuaXZlcnNhbEFuYWx5dGljcyAmJiBhamF4Q29tcGxldGVTdGF0dXMuR29vZ2xlQW5hbHl0aWNzNCAmJiAoYWpheENvbXBsZXRlU3RhdHVzLlVuaXZlcnNhbEFuYWx5dGljcyA9PSAnZXJyb3InIHx8IGFqYXhDb21wbGV0ZVN0YXR1cy5Hb29nbGVBbmFseXRpY3M0ID09ICdlcnJvcicpKSB7XG5cdFx0XHRcdHJlamVjdCgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChkYXRhTGF5ZXJUeXBlICE9ICdFdmVudCcpIHtcblx0XHRcdHB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlRm9yRGF0YUxheWVyVmVyc2lvbihkYXRhTGF5ZXJUeXBlLCBkYXRhT2JqZWN0LlVuaXZlcnNhbEFuYWx5dGljcyB8fCBPYmplY3QuYXNzaWduKHt9LCBkYXRhT2JqZWN0KSwgJ1VuaXZlcnNhbEFuYWx5dGljcycsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGFqYXhDb21wbGV0ZVN0YXR1cy5Vbml2ZXJzYWxBbmFseXRpY3MgPSAnc3VjY2Vzcyc7XG5cdFx0XHRcdGFqYXhDb21wbGV0ZSgpO1xuXHRcdFx0fSkuY2F0Y2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGFqYXhDb21wbGV0ZVN0YXR1cy5Vbml2ZXJzYWxBbmFseXRpY3MgPSAnZXJyb3InO1xuXHRcdFx0XHRhamF4Q29tcGxldGUoKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0XHRwdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZUZvckRhdGFMYXllclZlcnNpb24oZGF0YUxheWVyVHlwZSwgZGF0YU9iamVjdC5Hb29nbGVBbmFseXRpY3M0IHx8IE9iamVjdC5hc3NpZ24oe30sIGRhdGFPYmplY3QpLCAnR29vZ2xlQW5hbHl0aWNzNCcsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRhamF4Q29tcGxldGVTdGF0dXMuR29vZ2xlQW5hbHl0aWNzNCA9ICdzdWNjZXNzJztcblx0XHRcdGFqYXhDb21wbGV0ZSgpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0YWpheENvbXBsZXRlU3RhdHVzLkdvb2dsZUFuYWx5dGljczQgPSAnZXJyb3InO1xuXHRcdFx0YWpheENvbXBsZXRlKCk7XG5cdFx0fSk7O1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGVGb3JEYXRhTGF5ZXJWZXJzaW9uKGRhdGFMYXllclR5cGUsIGRhdGFPYmplY3QsIGRhdGFMYXllclZlcnNpb24sIG9wdGlvbnMpIHtcblx0dmFyIGRhdGFMYXllclR5cGUgPSBkYXRhTGF5ZXJUeXBlIHx8ICdHZW5lcmFsJztcblx0dmFyIGRhdGFMYXllclZlcnNpb24gPSBkYXRhTGF5ZXJWZXJzaW9uIHx8ICdVbml2ZXJzYWxBbmFseXRpY3MnO1xuXHR2YXIgZGF0YU9iamVjdCA9IGRhdGFPYmplY3QgfHwge307XG5cblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdGlmIChkYXRhTGF5ZXJUeXBlKSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMuR29vZ2xlVGFnTWFuYWdlci5HZXREYXRhTGF5ZXIsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdERhdGFMYXllclR5cGU6IGRhdGFMYXllclR5cGUsXG5cdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvblxuXHRcdFx0XHR9LFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGFMYXllcjtcblx0XHRcdFx0XHRpZiAoZGF0YSAmJiAhJC5pc0VtcHR5T2JqZWN0KGRhdGEpKSB7XG5cdFx0XHRcdFx0XHRkYXRhTGF5ZXIgPSAkLmV4dGVuZChkYXRhLCBkYXRhT2JqZWN0KTtcblxuXHRcdFx0XHRcdFx0aWYgKGRhdGFMYXllclR5cGUgPT0gJ0FkZFBheW1lbnRJbmZvJykge1xuXHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdENvbnRhaW5lclNlbGVjdG9yOiBvcHRpb25zICYmIG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgPyBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yIDogJydcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGRhdGFMYXllclR5cGUgPT0gJ0FkZFNoaXBwaW5nSW5mbycpIHtcblx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvbixcblx0XHRcdFx0XHRcdFx0XHRDb250YWluZXJTZWxlY3Rvcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yID8gb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA6ICcnXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdBZGRUb0NhcnQnKSB7XG5cdFx0XHRcdFx0XHRcdGlmICgoZGF0YUxheWVyLmV2ZW50ID09ICdhZGRfdG9fY2FydCcgJiYgKCFkYXRhTGF5ZXIuaXRlbXMgfHwgZGF0YUxheWVyLml0ZW1zLmxlbmd0aCA9PSAwKSkgfHwgKGRhdGFMYXllci5ldmVudCA9PSAnYWRkVG9DYXJ0JyAmJiAoIWRhdGFMYXllci5lY29tbWVyY2UgfHwgIWRhdGFMYXllci5lY29tbWVyY2UgfHwgIWRhdGFMYXllci5lY29tbWVyY2UuYWRkIHx8ICFkYXRhTGF5ZXIuZWNvbW1lcmNlLmFkZC5wcm9kdWN0cyB8fCBkYXRhTGF5ZXIuZWNvbW1lcmNlLmFkZC5wcm9kdWN0cy5sZW5ndGggPT0gMCkpKSB7XG5cdFx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdFx0Q29udGFpbmVyU2VsZWN0b3I6IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA/IG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgOiAnJyxcblx0XHRcdFx0XHRcdFx0XHRcdEZpbHRlclNlbGVjdG9yOiAnLnBkcC1icm93c2UnLFxuXHRcdFx0XHRcdFx0XHRcdFx0VW5pdmVyc2FsQW5hbHl0aWNzS2V5OiAnYWRkJ1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmIChkYXRhTGF5ZXIuaXRlbXMgJiYgZGF0YUxheWVyLml0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIWRhdGFMYXllci5pdGVtc1swXS5xdWFudGl0eSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLml0ZW1zWzBdLnF1YW50aXR5ID0gMTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLmN1cnJlbmN5ID0gZGF0YUxheWVyLml0ZW1zWzBdLmN1cnJlbmN5O1xuXHRcdFx0XHRcdFx0XHRcdGRhdGFMYXllci52YWx1ZSA9IGRhdGFMYXllci5pdGVtc1swXS5wcmljZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdSZW1vdmVGcm9tQ2FydCcpIHtcblx0XHRcdFx0XHRcdFx0aWYgKGRhdGFMYXllci5pdGVtcyAmJiBkYXRhTGF5ZXIuaXRlbXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICghZGF0YUxheWVyLml0ZW1zWzBdLnF1YW50aXR5KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRkYXRhTGF5ZXIuaXRlbXNbMF0ucXVhbnRpdHkgPSAxO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRkYXRhTGF5ZXIuY3VycmVuY3kgPSBkYXRhTGF5ZXIuaXRlbXNbMF0uY3VycmVuY3k7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLnZhbHVlID0gZGF0YUxheWVyLml0ZW1zWzBdLnByaWNlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGRhdGFMYXllclR5cGUgPT0gJ1NlbGVjdFByb21vdGlvbicpIHtcblx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvbixcblx0XHRcdFx0XHRcdFx0XHRDb250YWluZXI6IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXIgPyBvcHRpb25zLkNvbnRhaW5lciA6ICcnXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdWaWV3SXRlbScpIHtcblx0XHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHRcdERhdGFMYXllclZlcnNpb246IGRhdGFMYXllclZlcnNpb24sXG5cdFx0XHRcdFx0XHRcdFx0XHRDb250YWluZXJTZWxlY3Rvcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yID8gb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA6ICcnLFxuXHRcdFx0XHRcdFx0XHRcdFx0RmlsdGVyU2VsZWN0b3I6ICcucGRwLWJyb3dzZScsXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0VW5pdmVyc2FsQW5hbHl0aWNzS2V5OiAnZGV0YWlsJ1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdWaWV3UHJvbW90aW9uJykge1xuXHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdENvbnRhaW5lcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lciA/IG9wdGlvbnMuQ29udGFpbmVyIDogJydcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmVzb2x2ZShkYXRhTGF5ZXIpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmVqZWN0KCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZWplY3QoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBwdXNoRGF0YUxheWVyRm9yRXZlbnQoZXZlbnROYW1lLCBkYXRhT2JqZWN0LCBkYXRhTGF5ZXJUeXBlLCBkYXRhTGF5ZXJWZXJzaW9uKSB7XG5cdHZhciBkYXRhT2JqZWN0ID0gZGF0YU9iamVjdCB8fCB7fTtcblxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0aWYgKGV2ZW50TmFtZSkge1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLkdvb2dsZVRhZ01hbmFnZXIuR2V0RGF0YUxheWVyLFxuXHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHREYXRhTGF5ZXJUeXBlOiBkYXRhTGF5ZXJUeXBlIHx8ICdHZW5lcmFsJyxcblx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uIHx8ICdVbml2ZXJzYWxBbmFseXRpY3MnXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHR2YXIgZGF0YUxheWVyID0gJC5leHRlbmQoZGF0YU9iamVjdCwgZGF0YSk7XG5cdFx0XHRcdFx0ZGF0YUxheWVyLmV2ZW50ID0gZXZlbnROYW1lO1xuXHRcdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKTtcblx0XHRcdFx0XHRyZXNvbHZlKGRhdGFMYXllcik7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZWplY3QoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlamVjdCgpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGRlY29yYXRlRGF0YUxheWVyV2l0aFByb2R1Y3REYXRhKGRhdGFMYXllciwgb3B0aW9ucykge1xuXHR2YXIgdW5pdmVyc2FsQW5hbHl0aWNzS2V5ID0gb3B0aW9ucyAmJiBvcHRpb25zLlVuaXZlcnNhbEFuYWx5dGljc0tleSA/IG9wdGlvbnMuVW5pdmVyc2FsQW5hbHl0aWNzS2V5IDogJyc7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5EYXRhTGF5ZXJWZXJzaW9uID09ICdHb29nbGVBbmFseXRpY3M0Jykge1xuXHRcdGRhdGFMYXllci5pdGVtcyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicsIG9wdGlvbnMpO1xuXHR9IGVsc2Uge1xuXHRcdGRhdGFMYXllci5lY29tbWVyY2UgPSBkYXRhTGF5ZXIuZWNvbW1lcmNlIHx8IHt9O1xuXHRcdGRhdGFMYXllci5lY29tbWVyY2VbdW5pdmVyc2FsQW5hbHl0aWNzS2V5XSA9IGRhdGFMYXllci5lY29tbWVyY2VbdW5pdmVyc2FsQW5hbHl0aWNzS2V5XSB8fCB7fTtcblx0XHRkYXRhTGF5ZXIuZWNvbW1lcmNlW3VuaXZlcnNhbEFuYWx5dGljc0tleV0ucHJvZHVjdHMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKG51bGwsIG9wdGlvbnMpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGdldFByb2R1Y3REYXRhTGF5ZXIoYXR0cmlidXRlSWRQYXJhbWV0ZXIsIG9wdGlvbnMpIHtcblx0dmFyIGRhdGFMYXllclByb2R1Y3RzID0gd2luZG93LmRhdGFMYXllclByb2R1Y3RzIHx8IFtdO1xuXHR2YXIgYXR0cmlidXRlSWQgPSBhdHRyaWJ1dGVJZFBhcmFtZXRlciB8fCAnZGF0YS1wcm9kdWN0LWd0bS1qc29uJztcblx0dmFyIGNvbnRhaW5lciA9IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXIgPyBvcHRpb25zLkNvbnRhaW5lciA6ICcnO1xuXHR2YXIgY29udGFpbmVyU2VsZWN0b3IgPSBvcHRpb25zICYmIG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgPyBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yIDogJyc7XG5cdHZhciBmaWx0ZXJTZWxlY3RvciA9IG9wdGlvbnMgJiYgb3B0aW9ucy5GaWx0ZXJTZWxlY3RvciA/IG9wdGlvbnMuRmlsdGVyU2VsZWN0b3IgOiAnJztcblxuXHR2YXIgJHByb2R1Y3RDYXJkcztcblx0aWYgKGNvbnRhaW5lcikge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSBjb250YWluZXIuZmluZCgnWycgKyBhdHRyaWJ1dGVJZCArICddJyArIGZpbHRlclNlbGVjdG9yKTtcblx0fSBlbHNlIGlmIChjb250YWluZXJTZWxlY3Rvcikge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSAkKGNvbnRhaW5lclNlbGVjdG9yKS5maW5kKCdbJyArIGF0dHJpYnV0ZUlkICsgJ10nICsgZmlsdGVyU2VsZWN0b3IpO1xuXHR9IGVsc2Uge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSAkKCdbJyArIGF0dHJpYnV0ZUlkICsgJ10nICsgZmlsdGVyU2VsZWN0b3IpO1xuXHR9XG5cdCRwcm9kdWN0Q2FyZHMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cblx0XHR2YXIgc2xpY2tJbmRleCA9IG51bGw7XG5cdFx0dmFyIGlzVmFsaWQgPSB0cnVlO1xuXHRcdGlmICgkZWxlbWVudC5jbG9zZXN0KCdbZGF0YS1zbGljay1pbmRleF0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRzbGlja0luZGV4ID0gcGFyc2VJbnQoJGVsZW1lbnQuY2xvc2VzdCgnW2RhdGEtc2xpY2staW5kZXhdJykuZGF0YSgnc2xpY2staW5kZXgnKSwgMTApICsgMTtcblx0XHRcdGlmIChzbGlja0luZGV4IDwgMSkge1xuXHRcdFx0XHRpc1ZhbGlkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGlzVmFsaWQpIHtcblx0XHRcdHZhciBqc29uT2JqZWN0ID0gSlNPTi5wYXJzZSgkZWxlbWVudC5hdHRyKGF0dHJpYnV0ZUlkKSk7XG5cdFx0XHRpZiAoYXR0cmlidXRlSWQgPT0gJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpIHtcblx0XHRcdFx0anNvbk9iamVjdC5wb3NpdGlvbiA9IGluZGV4O1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0anNvbk9iamVjdC5pbmRleCA9IGluZGV4O1xuXHRcdFx0fVxuXHRcdFx0ZGF0YUxheWVyUHJvZHVjdHMucHVzaChqc29uT2JqZWN0KTtcblx0XHR9XG5cdH0pO1xuXHRcdFxuXHRyZXR1cm4gZGF0YUxheWVyUHJvZHVjdHM7XG59XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKSB7XG5cdHZhciBpc0NhcnRQYWdlID0gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucyAmJiBwYWdlQ29udGV4dC5vcHRpb25zLmlzQ2FydFBhZ2U7XG5cdHZhciBpc0NoZWNrb3V0UGFnZSA9IHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5pc0NoZWNrb3V0UGFnZTtcblx0dmFyIGlzQ29uZmlybWF0aW9uUGFnZSA9IHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5pc0NvbmZpcm1hdGlvblBhZ2U7XG5cdHZhciByZWFjdERhdGFMYXllclBhZ2VzID0gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucyAmJiBwYWdlQ29udGV4dC5vcHRpb25zLk1vYmlsZUFwcCAmJiBwYWdlQ29udGV4dC5vcHRpb25zLk1vYmlsZUFwcC5SZWFjdERhdGFMYXllclBhZ2VzID8gcGFnZUNvbnRleHQub3B0aW9ucy5Nb2JpbGVBcHAuUmVhY3REYXRhTGF5ZXJQYWdlcyA6IFtdO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDYXJ0ID0gaXNDYXJ0UGFnZSAmJiByZWFjdERhdGFMYXllclBhZ2VzLmluZGV4T2YoJ0NhcnQnKSA+IC0xO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDaGVja291dCA9IGlzQ2hlY2tvdXRQYWdlICYmIHJlYWN0RGF0YUxheWVyUGFnZXMuaW5kZXhPZignQ2hlY2tvdXQnKSA+IC0xO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDb25maXJtYXRpb24gPSBpc0NvbmZpcm1hdGlvblBhZ2UgJiYgcmVhY3REYXRhTGF5ZXJQYWdlcy5pbmRleE9mKCdDb25maXJtYXRpb24nKSA+IC0xO1xuXG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cgJiYgKHNlbmRSZWFjdEV2ZW50Rm9yQ2FydCB8fCBzZW5kUmVhY3RFdmVudEZvckNoZWNrb3V0IHx8IHNlbmRSZWFjdEV2ZW50Rm9yQ29uZmlybWF0aW9uKSkge1xuXHRcdHRyaWdnZXJSZWFjdFdlYnZpZXdFdmVudChkYXRhTGF5ZXIuZXZlbnQsIGRhdGFMYXllcik7XG5cdH0gZWxzZSB7XG5cdFx0d2luZG93LmRhdGFMYXllci5wdXNoKGRhdGFMYXllcik7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJpZ2dlclJlYWN0V2Vidmlld0V2ZW50KGFjdGlvbiwgZGF0YUxheWVyKSB7XG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cpIHtcblx0XHR2YXIgbWVzc2FnZSA9ICB7XG5cdFx0XHRhY3Rpb246IGFjdGlvblxuXHRcdH1cblx0XHRpZiAoZGF0YUxheWVyKSB7XG5cdFx0XHRtZXNzYWdlLmRhdGFMYXllciA9IGRhdGFMYXllcjtcblx0XHR9XG5cblx0XHR3aW5kb3cuUmVhY3ROYXRpdmVXZWJWaWV3LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpKTtcblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zID0gcmVxdWlyZSgnLi4vLi4vanMvUmVnZXhQYXR0ZXJucycpLlZhbGlkYXRpb247XG52YXIgU3RhdGVUb1ppcENvZGVNYXAgPSByZXF1aXJlKCcuLi8uLi9kYXRhL1N0YXRlVG9aaXBDb2RlTWFwLmpzb24nKTtcblxuZXhwb3J0cy5WYWxpZGF0ZVJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24gPSB2YWxpZGF0ZVJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb247XG5leHBvcnRzLlZhbGlkYXRlT3JkZXJOdW1iZXIgPSB2YWxpZGF0ZU9yZGVyTnVtYmVyO1xuZXhwb3J0cy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94ID0gdmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveDtcbmV4cG9ydHMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHkgPSB2YWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seTtcbmV4cG9ydHMuVmFsaWRhdGVQb3N0YWxDb2RlID0gdmFsaWRhdGVQb3N0YWxDb2RlO1xuZXhwb3J0cy5WYWxpZGF0ZVppcENvZGUgPSB2YWxpZGF0ZVppcENvZGU7XG5leHBvcnRzLlZhbGlkYXRlWmlwQ29kZVByZWZpeEZvclN0YXRlQ29kZSA9IHZhbGlkYXRlWmlwQ29kZVByZWZpeEZvclN0YXRlQ29kZTtcbmV4cG9ydHMuVmFsaWRhdGVaaXBDb2RlUHJlZml4Rm9yU3RhdGVDb2RlVmFsdWVzID0gdmFsaWRhdGVaaXBDb2RlUHJlZml4Rm9yU3RhdGVDb2RlVmFsdWVzO1xuZXhwb3J0cy5WYWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUgPSB2YWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmU7XG5leHBvcnRzLlZhbGlkYXRlR2lmdENhcmROdW1iZXJMZW5ndGggPSB2YWxpZGF0ZUdpZnRDYXJkTnVtYmVyTGVuZ3RoO1xuZXhwb3J0cy5WYWxpZGF0ZUdpZnRDYXJkTnVtYmVyVmFsdWVzID0gdmFsaWRhdGVHaWZ0Q2FyZE51bWJlclZhbHVlcztcblxuZnVuY3Rpb24gdmFsaWRhdGVSZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKHZhbHVlLCBlbGVtZW50KSB7XG4gICAgcmV0dXJuIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24udGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3JkZXJOdW1iZXIodmFsdWUsIGVsZW1lbnQpIHtcbiAgICByZXR1cm4gUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuT3JkZXJOdW1iZXIudGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3godmFsdWUsIGVsZW1lbnQpIHtcblx0cmV0dXJuICFSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5Qb3N0T2ZmaWNlQm94LnRlc3QoKHZhbHVlICsgJycpLnRyaW0oKSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5KHZhbHVlLCBlbGVtZW50KSB7XG5cdHZhciBhZGRyZXNzMSA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCk7XG5cdHZhciBhZGRyZXNzMiA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCk7XG5cblx0cmV0dXJuICghUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuUG9zdE9mZmljZUJveC50ZXN0KChhZGRyZXNzMSArICcnKS50cmltKCkpICYmICFSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5Qb3N0T2ZmaWNlQm94LnRlc3QoKGFkZHJlc3MyICsgJycpLnRyaW0oKSkpIHx8ICghYWRkcmVzczEgfHwgIWFkZHJlc3MyKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVQb3N0YWxDb2RlKHZhbHVlLCBlbGVtZW50KSB7XG4gICAgcmV0dXJuIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zLlBvc3RhbENvZGUudGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlWmlwQ29kZSh2YWx1ZSwgZWxlbWVudCkge1xuICAgIHJldHVybiBSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5aaXBDb2RlLnRlc3QoKHZhbHVlICsgJycpLnRyaW0oKSk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVppcENvZGVQcmVmaXhGb3JTdGF0ZUNvZGUodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIHppcENvZGVQcmVmaXggPSB2YWx1ZS5zdWJzdHIoMCwzKTtcblx0dmFyIHN0YXRlQ29kZSA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZXNfc3RhdGVcIl0nKS52YWwoKS50b1VwcGVyQ2FzZSgpO1xuXHRpZiAoc3RhdGVDb2RlICYmIFN0YXRlVG9aaXBDb2RlTWFwICYmIFN0YXRlVG9aaXBDb2RlTWFwW3N0YXRlQ29kZV0pIHtcblx0XHRyZXR1cm4gU3RhdGVUb1ppcENvZGVNYXBbc3RhdGVDb2RlXVt6aXBDb2RlUHJlZml4XTtcblx0fVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVppcENvZGVQcmVmaXhGb3JTdGF0ZUNvZGVWYWx1ZXMoemlwQ29kZSwgc3RhdGVDb2RlKSB7XG5cdHZhciB6aXBDb2RlUHJlZml4ID0gemlwQ29kZS5zdWJzdHIoMCwzKTtcblx0aWYgKFN0YXRlVG9aaXBDb2RlTWFwICYmIFN0YXRlVG9aaXBDb2RlTWFwW3N0YXRlQ29kZV0pIHtcblx0XHRyZXR1cm4gU3RhdGVUb1ppcENvZGVNYXBbc3RhdGVDb2RlXVt6aXBDb2RlUHJlZml4XTtcblx0fVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIHN0YXRlQ29kZUZvclN0b3JlID0gJChlbGVtZW50KS5jbG9zZXN0KCdbc3RvcmUtc3RhdGVdJykuYXR0cignc3RvcmUtc3RhdGUnKTtcblxuXHRpZiAoKHZhbHVlICE9ICdDQScgJiYgc3RhdGVDb2RlRm9yU3RvcmUgIT0gJ0NBJykgfHwgdmFsdWUgPT0gc3RhdGVDb2RlRm9yU3RvcmUpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlR2lmdENhcmROdW1iZXJMZW5ndGgodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIGRpZ2l0cyA9ICh2YWx1ZSArICcnKS50cmltKCkubWF0Y2goUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuR2lmdENhcmROdW1iZXJMZW5ndGgpO1xuXHRyZXR1cm4gZGlnaXRzICYmIGRpZ2l0cy5sZW5ndGggPT0gMTk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUdpZnRDYXJkTnVtYmVyVmFsdWVzKHZhbHVlLCBlbGVtZW50KSB7XG5cdHJldHVybiBSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5HaWZ0Q2FyZE51bWJlclZhbHVlcy50ZXN0KCh2YWx1ZSArICcnKS50cmltKCkpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuU2xpY2tTbGlkZXIgPSB7XG5cdE9wdGlvbnM6IHtcblx0XHRTaW5nbGU6IHtcblx0XHRcdGluZmluaXRlOiBcdFx0dHJ1ZSxcblx0XHRcdGRvdHM6IFx0XHRcdGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBcdFx0ZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IFx0MSxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiAxLFxuXHRcdFx0cmVzcG9uc2l2ZTogXHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiA3NjcsXG5cdFx0XHRcdFx0c2V0dGluZ3M6IFx0e1xuXHRcdFx0XHRcdFx0ZG90czogXHR0cnVlLFxuXHRcdFx0XHRcdFx0YXJyb3dzOiB0cnVlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMFxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSxcblx0XHRUaHVtYm5haWw6IHtcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiBmYWxzZSxcblx0XHRcdGZvY3VzT25TZWxlY3Q6IFx0ZmFsc2UsXG5cdFx0XHRkb3RzOiBmYWxzZSxcblx0XHRcdGFycm93czogZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDcsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogNyxcblx0XHRcdHJlc3BvbnNpdmU6IFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogNzY3XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwLFxuXHRcdFx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Nob3c6IDQsXG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Njcm9sbDogNFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0vKixcblx0XHRDYXRlZ29yeUxhbmRpbmc6IHtcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiB0cnVlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiB0cnVlLFxuXHRcdFx0c2xpZGVzVG9TaG93OiA0LFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDQsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2N1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMCxcblx0XHRcdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRcdFx0c2xpZGVzVG9TaG93OiAzLFxuXHRcdFx0XHRcdFx0c2xpZGVzVG9TY3JvbGw6IDNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9Ki9cblx0fVxufSIsIi8qIEdsb2JhbCBWYXJpYWJsZXMgKi9cbnZhciBoZWxwZXIgPSByZXF1aXJlKCcuLi9oZWxwZXJzL3Nob3BwYXlIZWxwZXInKTtcbnZhciBpc0J1eU5vdyA9IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcyA/IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cgOiBudWxsO1xudmFyIGlzQUFUZXN0ID0gd2luZG93LnNob3BwYXlDbGllbnRSZWZzICYmIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5QUFUZXN0ID8gd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlBQVRlc3QgOiBmYWxzZTtcbnZhciBzZXNzaW9uO1xuXG4kKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHdpbmRvdy5TaG9wUGF5KSB7XG4gICAgICAgIGluaXRTaG9wUGF5Q29uZmlnKCk7XG5cdFx0aWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5RW1haWxMaXN0ZW5lckVuYWJsZWQgJiYgJCgnLnNob3BpZnktZW1haWwtbGlzdGVuZXInKS5sZW5ndGgpIHtcblx0XHRcdGluaXRTaG9wUGF5RW1haWxSZWNvZ25pdGlvbigpO1xuXHRcdH1cblx0XHRpbml0U2hvcFBheUJ1dHRvbigpO1xuICAgICAgICB2YXIgcmVhZHlPblBhZ2VMb2FkID0gaGVscGVyLmlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCgpO1xuICAgICAgICBpZiAocmVhZHlPblBhZ2VMb2FkKSB7XG4gICAgICAgICAgICB2YXIgcGFnZUxvYWREYXRhID0gaGVscGVyLmdldEluaXRQcm9kdWN0RGF0YSgpO1xuICAgICAgICAgICAgaGVscGVyLnNldEluaXRQcm9kdWN0RGF0YShwYWdlTG9hZERhdGEpOyAvLyB1cGRhdGVzIGdsb2JhbCBwcm9kIGRhdGEuXG4gICAgICAgIH1cblxuICAgICAgICAvKiAgVGhlIGJlbG93IGNvZGUgdHJpZ2dlcnMgaWYgYSBwcm9kdWN0IGlzIGEgQnV5IE5vdyBpdGVtLCBidXQgaXMgbm90IHJlYWR5IHRvIG9yZGVyIG9uIHBhZ2UgbG9hZFxuICAgICAgICAgICAgKGV4OiByZXF1aXJlZCBwcm9kdWN0IGF0dHJpYnV0ZXMgbGlrZSBjb2xvciBvciBzaXplIGFyZSBub3QgeWV0IGNob3NlbikuIEhlcmUsIGEgd2F0Y2hlciBpcyBzZXRcbiAgICAgICAgICAgIHRvIGNhcHR1cmUgdXNlciBpbnRlcmFjdGlvbnMgd2hlbiBwcm9kdWN0IGF0dHJpYnV0ZXMgYXJlIHNlbGVjdGVkLiBIZWxwZXIgc2NyaXB0cyB3aWxsIGJlIHRyaWdnZXJlZFxuICAgICAgICAgICAgYnkgdGhlc2UgaW50ZXJhY3Rpb25zIHRvIGRldGVybWluZSBpZiB0aGUgaXRlbSBpcyByZWFkeSB0byBvcmRlciB3aGVuIGFsbCByZXF1aXJlZCBhdHRyaWJ1dGVzIGFyZVxuICAgICAgICAgICAgc2VsZWN0ZWQuXG4gICAgICAgICovXG4gICAgICAgIGlmIChpc0J1eU5vdyAmJiAhcmVhZHlPblBhZ2VMb2FkKSB7XG4gICAgICAgICAgICAkKCdib2R5Jykub24oJ3Byb2R1Y3Q6YWZ0ZXJBdHRyaWJ1dGVTZWxlY3QnLCBpbml0QnV5Tm93KTsgLy8gcmVjZWl2ZXMgdGhlIEV2ZW50ICYgUmVzcG9uc2VcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXHQkKGRvY3VtZW50KS5vbignQ2FydC5VcGRhdGVTdWNjZXNzJywgZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHdpbmRvdy5TaG9wUGF5ICYmICFpc0J1eU5vdykge1xuXHRcdFx0aWYgKCFzZXNzaW9uKSB7XG5cdFx0XHRcdHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlID0gaGVscGVyLmJ1aWxkUGF5bWVudFJlcXVlc3Qoc2Vzc2lvbik7XG5cdFx0XHRcdHZhciByZXNwb25zZUpTT04gPSAgcGF5bWVudFJlcXVlc3RSZXNwb25zZSA/IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UucmVzcG9uc2VKU09OIDogbnVsbDtcblx0XG5cdFx0XHRcdGlmIChyZXNwb25zZUpTT04pIHtcblx0XHRcdFx0XHRoZWxwZXIuc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzaG9wLXBheS1idXR0b24tY29udGFpbmVyXCIpKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0aWYgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCAhPT0gbnVsbCkge1xuXHRcdFx0XHRcdHNlc3Npb24uY2xvc2UoKTtcblx0XHRcdFx0XHRzZXNzaW9uID0gaW5pdFNob3BQYXlTZXNzaW9uKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufSk7XG5cbmZ1bmN0aW9uIGluaXRTaG9wUGF5Q29uZmlnKCkge1xuICAgIHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNvbmZpZ3VyZSh7XG4gICAgICAgIHNob3BJZDogd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlTdG9yZUlkLFxuICAgICAgICBjbGllbnRJZDogd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlDbGllbnRJZCxcbiAgICAgICAgZGVidWc6IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5TW9kYWxEZWJ1Z0VuYWJsZWRcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdFNob3BQYXlCdXR0b24oKSB7XG5cdHZhciBwYXltZW50U2VsZWN0b3JzID0gWycjc2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lcicsICcjc2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lci1tb2JpbGUnLCAnI3Nob3AtcGF5LWJ1dHRvbi1jb250YWluZXItZGVza3RvcCddXG5cdGZvciAodmFyIHBheW1lbnRTZWxlY3RvckluZGV4IGluIHBheW1lbnRTZWxlY3RvcnMpIHtcblx0XHR2YXIgcGF5bWVudFNlbGVjdG9yID0gcGF5bWVudFNlbGVjdG9yc1twYXltZW50U2VsZWN0b3JJbmRleF07XG5cdFx0aWYgKCQocGF5bWVudFNlbGVjdG9yKS5sZW5ndGggPiAwKSB7XG5cdFx0XHR3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5jcmVhdGVCdXR0b24oe2J1eVdpdGg6IGlzQnV5Tm93fSkucmVuZGVyKHBheW1lbnRTZWxlY3Rvcik7XG5cdFx0XHRoZWxwZXIuc2hvcHBheU11dGF0aW9uT2JzZXJ2ZXIocGF5bWVudFNlbGVjdG9yKTtcblx0XHR9XG5cdH1cbn1cblxuXG5mdW5jdGlvbiBpbml0QnV5Tm93KGUsIHJlc3BvbnNlKSB7XG4gICAgdmFyIHJlc3BvbnNlUHJvZHVjdCA9IHJlc3BvbnNlLmRhdGEucHJvZHVjdDtcbiAgICB2YXIgeyBidXlOb3csIHJlYWR5VG9PcmRlciwgaWQsIHNlbGVjdGVkUXVhbnRpdHksIG9wdGlvbnMsIGNoaWxkUHJvZHVjdHMgfSA9IHJlc3BvbnNlUHJvZHVjdDtcblxuICAgIGlmIChyZXNwb25zZVByb2R1Y3QgJiYgYnV5Tm93KSB7XG4gICAgICAgIGlmIChyZWFkeVRvT3JkZXIpIHtcbiAgICAgICAgICAgIGluaXRTaG9wUGF5U2Vzc2lvbihidXlOb3csIHJlYWR5VG9PcmRlcik7XG4gICAgICAgICAgICBoZWxwZXIuc2V0SW5pdFByb2R1Y3REYXRhKHtcbiAgICAgICAgICAgICAgICBwaWQ6IGlkLFxuICAgICAgICAgICAgICAgIHF1YW50aXR5OiBzZWxlY3RlZFF1YW50aXR5LFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGNoaWxkUHJvZHVjdHMpIHtcbiAgICAgICAgICAgICAgICBoZWxwZXIucHJvZHVjdERhdGEuY2hpbGRQcm9kdWN0cyA9IGNoaWxkUHJvZHVjdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGluaXRTaG9wUGF5RW1haWxSZWNvZ25pdGlvbigpIHtcbiAgICAvKiAgSWYgeW91ciBjaGVja291dCBpcyBub3QgYnVpbHQgd2l0aCBTRlJBIG9yIHlvdSBoYXZlIGN1c3RvbWl6ZWQgYW5kIHJlbW92ZWQgdGhlICdlbWFpbC1ndWVzdCdcbiAgICAgICAgaWQgb24gdGhlIGVtYWlsIGlucHV0IHlvdSB3aWxsIG5lZWQgdG8gdXBkYXRlIHRoZSBpZCB2YWx1ZSBmb3IgZW1haWxJbnB1dElkXG5cbiAgICAgICAgTm90ZTogQSAxLjUgc2Vjb25kIGRlbGF5IGhhcyBiZWVuIGFkZGVkIGJlZm9yZSBhdHRhY2hpbmcgdG8gdGhlIGVtYWlsIHRyaWdnZXIgdG8gdGhlIGVtYWlsIGZpZWxkIHRvXG4gICAgICAgIGFjY29tbW9kYXRlIHVzZXJzIHdobyBtYXkgaGF2ZSBpbmNvcnBvcmF0ZWQgYnJvd3NlciBhdXRvZmlsbHMuIFRoZSBwb3AtdXAgd2lsbCBhcHBlYXIgaWYgdGhlIGZpZWxkXG4gICAgICAgIGlzIGF1dG9maWxsZWQgd2l0aCBhIHJlY29nbml6ZWQgZW1haWwgYWRkcmVzc1xuICAgICovXG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHQkKCcuc2hvcGlmeS1lbWFpbC1saXN0ZW5lcjp2aXNpYmxlJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNyZWF0ZUxvZ2luKHtlbWFpbElucHV0SWQ6ICQodGhpcykuYXR0cignaWQnKX0pLnJlbmRlcignI3Nob3AtcGF5LWxvZ2luLWNvbnRhaW5lcicpO1xuXHRcdH0pO1xuICAgIH0sIDE1MDApO1xufVxuXG4kKCdib2R5Jykub24oJ2NhcnQ6dXBkYXRlIHByb2R1Y3Q6YWZ0ZXJBZGRUb0NhcnQgcHJvbW90aW9uOnN1Y2Nlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgLyogIE9ubHkgaW50ZXJlc3RlZCBpbiBjYXJ0IHVwZGF0ZXMgb24gQ2FydCBwYWdlIChjYXJ0IHVwZGF0ZXMgYXJlIG5vdCB0cmlnZ2VyZWQgaW4gY2hlY2tvdXQpLiBCdXkgTm93IGFscmVhZHlcbiAgICAgICAgaGFzIGEgc2VwYXJhdGUgZXZlbnQgaGFuZGxlciBmb3IgY2hhbmdlcyB0byBhdHRyaWJ1dGUgc2VsZWN0aW9uc1xuICAgICovXG4gICAgaWYgKHdpbmRvdy5TaG9wUGF5ICYmICFpc0J1eU5vdykge1xuICAgICAgICBpZiAoIXNlc3Npb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlID0gaGVscGVyLmJ1aWxkUGF5bWVudFJlcXVlc3Qoc2Vzc2lvbik7XG4gICAgICAgICAgICB2YXIgcmVzcG9uc2VKU09OID0gIHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPyBwYXltZW50UmVxdWVzdFJlc3BvbnNlLnJlc3BvbnNlSlNPTiA6IG51bGw7XG5cbiAgICAgICAgICAgIGlmIChyZXNwb25zZUpTT04pIHtcbiAgICAgICAgICAgICAgICBoZWxwZXIuc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzaG9wLXBheS1idXR0b24tY29udGFpbmVyXCIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uID0gaW5pdFNob3BQYXlTZXNzaW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuXG5mdW5jdGlvbiBpbml0U2hvcFBheVNlc3Npb24ocGF5bWVudFJlcXVlc3RJbnB1dCwgcmVhZHlUb09yZGVyKSB7XG4gICAgdmFyIHBheW1lbnRSZXF1ZXN0O1xuICAgIHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlO1xuICAgIHZhciByZXNwb25zZUpTT047XG5cbiAgICBpZiAoaXNCdXlOb3cgJiYgcGF5bWVudFJlcXVlc3RJbnB1dCkge1xuICAgICAgICBwYXltZW50UmVxdWVzdCA9IHBheW1lbnRSZXF1ZXN0SW5wdXQ7XG4gICAgfSBlbHNlIGlmIChpc0J1eU5vdyAmJiAhcGF5bWVudFJlcXVlc3RJbnB1dCkge1xuICAgICAgICB2YXIgcHJvZHVjdERhdGEgPSBoZWxwZXIuZ2V0SW5pdFByb2R1Y3REYXRhKCk7XG4gICAgICAgIGlmIChwcm9kdWN0RGF0YSkge1xuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3RSZXNwb25zZSA9IGhlbHBlci5jcmVhdGVSZXNwb25zZShwcm9kdWN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuQnV5Tm93RGF0YSk7XG4gICAgICAgICAgICBpZiAocGF5bWVudFJlcXVlc3RSZXNwb25zZS5leGNlcHRpb24gfHwgcGF5bWVudFJlcXVlc3RSZXNwb25zZS5lcnJvcil7XG4gICAgICAgICAgICAgICAgLyogIE5vIG5lZWQgdG8gY2xvc2UgYW55IHNlc3Npb24gYmVjYXVzZSBhIHNlc3Npb24gZG9lcyBub3QgZXhpc3QgYXQgdGhpcyBwb2ludCAoaGFzIG5vdCB5ZXQgYmVlblxuICAgICAgICAgICAgICAgICAgICBpbml0aWF0ZWQpLiBSZXR1cm4gdG8gZXhpdCBmdW5jdGlvbiAtIGRvbid0IHJlbG9hZCB0aGUgcGFnZSBpbiBjYXNlIHRoZXJlIGlzIGEgcGFnZSByZW5kZXJpbmdcbiAgICAgICAgICAgICAgICAgICAgaXNzdWUgKHdpbGwgcmVzdWx0IGluIGluZmluaXRlIHJlbG9hZCBsb29wKS5cbiAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0ID0gcGF5bWVudFJlcXVlc3RSZXNwb25zZS5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgICAgIHJlc3BvbnNlSlNPTiA9IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPyBwYXltZW50UmVxdWVzdFJlc3BvbnNlIDogbnVsbDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPSBoZWxwZXIuYnVpbGRQYXltZW50UmVxdWVzdChzZXNzaW9uKTtcbiAgICAgICAgcmVzcG9uc2VKU09OID0gcGF5bWVudFJlcXVlc3RSZXNwb25zZSA/IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UucmVzcG9uc2VKU09OIDogbnVsbDtcbiAgICB9XG5cbiAgICBpZiAocGF5bWVudFJlcXVlc3QgfHwgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yKSkge1xuICAgICAgICB2YXIgaW5pdGlhbFBheW1lbnRSZXF1ZXN0ID0gcmVzcG9uc2VKU09OICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCA/IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCkgOiB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZChwYXltZW50UmVxdWVzdCk7XG4gICAgICAgIC8vIEVuYWJsZSBCdXlOb3cgQnV0dG9uIENsaWNrIG9uIFBEUCBpZiBQcm9kdWN0IGlzIFJlYWR5IFRvIE9yZGVyXG4gICAgICAgIGhlbHBlci5zaG9wcGF5QnRuRGlzYWJsZWRTdHlsZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNob3AtcGF5LWJ1dHRvbi1jb250YWluZXJcIiksIHJlYWR5VG9PcmRlcik7XG5cbiAgICAgICAgdmFyIHNob3BwYXlTZXNzaW9uID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuY3JlYXRlU2Vzc2lvbih7XG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogaW5pdGlhbFBheW1lbnRSZXF1ZXN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzaG9wcGF5U2Vzc2lvbikge1xuICAgICAgICAgICAgaGVscGVyLnNldFNlc3Npb25MaXN0ZW5lcnMoc2hvcHBheVNlc3Npb24pO1xuICAgICAgICAgICAgJCgnYm9keScpLm9mZigncHJvZHVjdDphZnRlckF0dHJpYnV0ZVNlbGVjdCcsIGluaXRCdXlOb3cpO1xuXG4gICAgICAgICAgICAkKCdib2R5Jykub24oJ3Byb2R1Y3Q6YWZ0ZXJBdHRyaWJ1dGVTZWxlY3QnLCBmdW5jdGlvbihlLCByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIHZhciByZXNwb25zZVByb2R1Y3QgPSByZXNwb25zZS5kYXRhLnByb2R1Y3Q7XG4gICAgICAgICAgICAgICAgaWYgKGlzQnV5Tm93ICYmIHJlc3BvbnNlUHJvZHVjdC5idXlOb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVscGVyLnNldEluaXRQcm9kdWN0RGF0YSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwaWQ6IHJlc3BvbnNlUHJvZHVjdC5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1YW50aXR5OiByZXNwb25zZVByb2R1Y3Quc2VsZWN0ZWRRdWFudGl0eSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHJlc3BvbnNlUHJvZHVjdC5vcHRpb25zXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvcHBheVNlc3Npb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3BwYXlTZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQocmVzcG9uc2VQcm9kdWN0LmJ1eU5vdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG9wcGF5U2Vzc2lvbiA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNyZWF0ZVNlc3Npb24oe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiB1cGRhdGVkUGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWxwZXIuc2V0U2Vzc2lvbkxpc3RlbmVycyhzaG9wcGF5U2Vzc2lvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IGhlbHBlci5nZXRVcmxXaXRoQ3NyZlRva2VuKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLkdldENhcnRTdW1tYXJ5KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzeW5jOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaG9wcGF5U2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvcHBheVNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF5bWVudFJlcXVlc3QgPSB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZChyZXNwb25zZS5wcm9kdWN0LmJ1eU5vdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3BwYXlTZXNzaW9uID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuY3JlYXRlU2Vzc2lvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50UmVxdWVzdDogcGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlbHBlci5zZXRTZXNzaW9uTGlzdGVuZXJzKHNob3BwYXlTZXNzaW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLnJlc3BvbnNlSlNPTiB8fCBlcnIuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2RhbCBoYXNuJ3Qgb3BlbmVkIHlldCBzbyBcIndpbmRvd2Nsb3NlZFwiIGxpc3RlbmVyIHdvbid0IGZpcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaG9wcGF5U2Vzc2lvbjtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXRTaG9wUGF5U2Vzc2lvbjogaW5pdFNob3BQYXlTZXNzaW9uXG59OyIsIi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4vKiBHbG9iYWwgVmFyaWFibGVzICovXG5sZXQgY2hlY2tvdXRVcmwgPSBudWxsO1xubGV0IG9ic2VydmVyO1xubGV0IG9yZGVyQ29uZmlybWF0aW9uRGF0YTtcbmxldCBwcm9kdWN0RGF0YSA9IHt9O1xubGV0IHJlbG9hZE9uQ2xvc2UgPSB0cnVlO1xubGV0IHNvdXJjZUlkZW50aWZpZXIgPSBudWxsO1xuY29uc3QgdGVjaG5pY2FsRXJyb3JNc2cgPSB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMgPyB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLnRlY2huaWNhbEVycm9yIDogbnVsbDtcbmxldCB0b2tlbiA9IG51bGw7XG5cbi8qKlxuICogQWRkIGNzcmYgdG9rZW4gcGFyYW0gdG8gdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gc291cmNlIHVybFxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2tldElkIC0gVVVJRCBvZiB0aGUgdGVtcG9yYXJ5IGJhc2tldCBpbiB0aGUgc2Vzc2lvbiwgaWYgYXBwbGljYWJsZVxuICogQHJldHVybnMge3N0cmluZ30gLSB1cmwgd2l0aCBjc3JmX3Rva2VuIHBhcmFtXG4gKi9cbmZ1bmN0aW9uIGdldFVybFdpdGhDc3JmVG9rZW4odXJsLCBiYXNrZXRJZCkge1xuICAgIGNvbnN0IHVybEluc3RhbmNlID0gbmV3IFVSTCh1cmwsIGxvY2F0aW9uLm9yaWdpbik7XG5cbiAgICB1cmxJbnN0YW5jZS5zZWFyY2hQYXJhbXMuYXBwZW5kKCdjc3JmX3Rva2VuJywgZ2V0Q3NyZlRva2VuKCkpO1xuXG4gICAgaWYgKGJhc2tldElkKSB7XG4gICAgICAgIHVybEluc3RhbmNlLnNlYXJjaFBhcmFtcy5hcHBlbmQoJ2Jhc2tldElkJywgYmFza2V0SWQpO1xuICAgIH1cblxuICAgIHJldHVybiB1cmxJbnN0YW5jZS50b1N0cmluZygpO1xufVxuXG4vKipcbiAqIEdldCBDU1JGIFRva2VuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGNzcmYgdG9rZW4gdmFsdWVcbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKCkge1xuICAgIGxldCAkZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWNzcmYtdG9rZW5dJyk7XG5cbiAgICBpZiAoJGVsZW1lbnQgJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1jc3JmLXRva2VuJ10gJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1jc3JmLXRva2VuJ10udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtY3NyZi10b2tlbiddLnZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiAnJztcbn1cblxuLyoqXG4gKiBHZXQgSW5pdCBQcm9kdWN0IERhdGEgKHBhZ2UgbG9hZCBhbmQgY2FwdHVyZXMgZGF0YSBhdmFpbGFibGUgb24gcGFnZSBsb2FkKVxuICogQHJldHVybnMge09iamVjdH0gLSBwcm9kdWN0RGF0YSB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlOiB7IHBpZDogcHJvZElkLCBxdWFudGl0eTogc2VsZWN0ZWRRdWFudGl0eSwgb3B0aW9uczogc2VsZWN0ZWRPcHRpb25zIH1cbiAqL1xuZnVuY3Rpb24gZ2V0SW5pdFByb2R1Y3REYXRhKCkge1xuICAgIGxldCBwcm9kdWN0RGF0YSA9IG51bGw7XG4gICAgbGV0ICRlbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtYnV5LW5vdy1pbml0XScpO1xuICAgIGlmICgkZWxlbWVudCAmJiAkZWxlbWVudC5hdHRyaWJ1dGVzWydkYXRhLWJ1eS1ub3ctaW5pdCddICYmICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtYnV5LW5vdy1pbml0J10udmFsdWUpIHtcbiAgICAgICAgcHJvZHVjdERhdGEgPSBKU09OLnBhcnNlKCRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtYnV5LW5vdy1pbml0J10udmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvZHVjdERhdGE7XG59XG5cbi8qKlxuICogU2V0IEluaXQgUHJvZHVjdCBEYXRhXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSAtIGFjY2VwdHMgcHJvZHVjdCBkYXRhIG9iaiAmIHVwZGF0ZXMgZ2xvYmFsIHByb2R1Y3REYXRhIHZhcmlhYmxlOiB7IHBpZDogcHJvZElkLCBxdWFudGl0eTogc2VsZWN0ZWRRdWFudGl0eSwgb3B0aW9uczogc2VsZWN0ZWRPcHRpb25zIH1cbiAqL1xuZnVuY3Rpb24gc2V0SW5pdFByb2R1Y3REYXRhKGRhdGEpIHtcbiAgICBwcm9kdWN0RGF0YSA9IGRhdGE7XG59XG5cbi8qKlxuICogU2V0cyBVcCBTaG9wUGF5IGxpc3RlbmVyIEV2ZW50c1xuICogQHBhcmFtIHtPYmplY3R9IHNlc3Npb24gLSBBY2NlcHRzIHRoZSBTaG9wIFBheSBzZXNzaW9uIG9iamVjdCBhbmQgZXN0YWJsaXNoZXMgbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycyBvbiB0aGUgc2Vzc2lvbi5cbiAqL1xuZnVuY3Rpb24gc2V0U2Vzc2lvbkxpc3RlbmVycyhzZXNzaW9uKSB7XG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwic2Vzc2lvbnJlcXVlc3RlZFwiLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgbGV0IHNlc3Npb25QYXltZW50UmVxdWVzdDtcbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiBnZXRVcmxXaXRoQ3NyZlRva2VuKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlByZXBhcmVCYXNrZXQpLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGFzeW5jOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeShwcm9kdWN0RGF0YSksXG4gICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb25QYXltZW50UmVxdWVzdCA9IGRhdGEucGF5bWVudFJlcXVlc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VJZGVudGlmaWVyID0gZGF0YS5iYXNrZXRJZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0IHJldHVyblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZCB1c2UgZGVmYXVsdCBtb2RhbCBlcnJvciBoYW5kbGluZy5cbiAgICAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95IHRoZSBzZXNzaW9uIGFuZCByZXR1cm4uXG4gICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2Vzc2lvblBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uUGF5bWVudFJlcXVlc3RcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4od2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuQmVnaW5TZXNzaW9uKSxcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgYXN5bmM6IGZhbHNlLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdERhdGEpLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRva2VuID0gZGF0YS50b2tlbjtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tvdXRVcmwgPSBkYXRhLmNoZWNrb3V0VXJsO1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2VJZGVudGlmaWVyID0gZGF0YS5zb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3Qoe3Rva2VuLCBjaGVja291dFVybCwgc291cmNlSWRlbnRpZmllcn0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNc2cgPSBkYXRhLmVycm9yTXNnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0IHJldHVyblxuICAgICAgICAgICAgICAgICAgICAgICAgYW5kIHVzZSBkZWZhdWx0IG1vZGFsIGVycm9yIGhhbmRsaW5nLlxuICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgLyogIHNlc3Npb24uY29tcGxldGVTZXNzaW9uUmVxdWVzdCgpIGRvZXMgbm90IHRha2UgYW4gZXJyb3JzIGFycmF5IGFzIGlucHV0IHNvIGp1c3RcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveSB0aGUgc2Vzc2lvbiBhbmQgcmV0dXJuLlxuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcImRpc2NvdW50Y29kZWNoYW5nZWRcIiwgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgbGV0IHJlcXVlc3REYXRhID0ge1xuICAgICAgICAgICAgZGlzY291bnRDb2RlczogZXYuZGlzY291bnRDb2Rlc1xuICAgICAgICB9O1xuICAgICAgICBpZiAod2luZG93LnNob3BwYXlDbGllbnRSZWZzLmNvbnN0YW50cy5pc0J1eU5vdykge1xuICAgICAgICAgICAgcmVxdWVzdERhdGEuYmFza2V0SWQgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3BvbnNlSlNPTiA9IGNyZWF0ZVJlc3BvbnNlKHJlcXVlc3REYXRhLCB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMudXJscy5EaXNjb3VudENvZGVDaGFuZ2VkKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5leGNlcHRpb24pe1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiZGlzY291bnRDb2RlRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiZGlzY291bnRDb2RlRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGRlbGl2ZXJ5TWV0aG9kcywgZGlzY291bnRDb2RlcywgbGluZUl0ZW1zLCBzaGlwcGluZ0xpbmVzLCBzdWJ0b3RhbCwgZGlzY291bnRzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuXG5cdFx0dmFyIHBheW1lbnRSZXF1ZXN0T2JqZWN0ID0ge307XG5cdFx0Zm9yICh2YXIgcHJvcGVydHlLZXkgaW4gY3VycmVudFBheW1lbnRSZXF1ZXN0KSB7XG5cdFx0XHRwYXltZW50UmVxdWVzdE9iamVjdFtwcm9wZXJ0eUtleV0gPSBjdXJyZW50UGF5bWVudFJlcXVlc3RbcHJvcGVydHlLZXldO1xuXHRcdH1cblxuICAgICAgICBsZXQgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAvLyAuLi5jdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgICAgICBkaXNjb3VudENvZGVzOiBkaXNjb3VudENvZGVzLFxuICAgICAgICAgICAgbGluZUl0ZW1zOiBsaW5lSXRlbXMsXG4gICAgICAgICAgICBzaGlwcGluZ0xpbmVzOiBzaGlwcGluZ0xpbmVzLFxuICAgICAgICAgICAgZGVsaXZlcnlNZXRob2RzOiBkZWxpdmVyeU1ldGhvZHMsXG4gICAgICAgICAgICBzdWJ0b3RhbDogc3VidG90YWwsXG4gICAgICAgICAgICBkaXNjb3VudHM6IGRpc2NvdW50cyxcbiAgICAgICAgICAgIHRvdGFsVGF4OiB0b3RhbFRheCxcbiAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICB9KSk7XG4gICAgICAgIGlmICh0b3RhbFNoaXBwaW5nUHJpY2UpIHtcbiAgICAgICAgICAgIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKHVwZGF0ZWRQYXltZW50UmVxdWVzdCwge1xuICAgICAgICAgICAgICAgIC8vIC4uLnVwZGF0ZWRQYXltZW50UmVxdWVzdCxcbiAgICAgICAgICAgICAgICB0b3RhbFNoaXBwaW5nUHJpY2U6IHRvdGFsU2hpcHBpbmdQcmljZVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZGVsaXZlcnltZXRob2RjaGFuZ2VkXCIsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRQYXltZW50UmVxdWVzdCA9IHNlc3Npb24ucGF5bWVudFJlcXVlc3Q7XG4gICAgICAgIGxldCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIGRlbGl2ZXJ5TWV0aG9kOiBldi5kZWxpdmVyeU1ldGhvZCxcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuRGVsaXZlcnlNZXRob2RDaGFuZ2VkKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5leGNlcHRpb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24uY29tcGxldGVEZWxpdmVyeU1ldGhvZENoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeyBzaGlwcGluZ0xpbmVzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAgICAgLy8gLi4uY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICAgICAgICAgIHNoaXBwaW5nTGluZXM6IHNoaXBwaW5nTGluZXMsXG4gICAgICAgICAgICAgICAgdG90YWxTaGlwcGluZ1ByaWNlOiB0b3RhbFNoaXBwaW5nUHJpY2UsXG4gICAgICAgICAgICAgICAgdG90YWxUYXg6IHRvdGFsVGF4LFxuICAgICAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RDaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBzaGlwcGluZ0xpbmVzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcGF5bWVudCByZXF1ZXN0IGJhc2VkIG9uIHRoZSBkZWxpdmVyeSBtZXRob2QgY2hhbmdlIGFuZCB1cGRhdGUgdGhlIHRvdGFsIGFjY29yZGluZ2x5XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwge1xuICAgICAgICAgICAgLy8gLi4uY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICAgICAgc2hpcHBpbmdMaW5lczogc2hpcHBpbmdMaW5lcyxcbiAgICAgICAgICAgIHRvdGFsU2hpcHBpbmdQcmljZTogdG90YWxTaGlwcGluZ1ByaWNlLFxuICAgICAgICAgICAgdG90YWxUYXg6IHRvdGFsVGF4LFxuICAgICAgICAgICAgdG90YWw6IHRvdGFsXG4gICAgICAgIH0pKTtcblxuICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RDaGFuZ2UoeyB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdCB9KTtcbiAgICB9KTtcblxuICAgIHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInNoaXBwaW5nYWRkcmVzc2NoYW5nZWRcIiwgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgaWYgKCFldi5zaGlwcGluZ0FkZHJlc3MpIHtcbiAgICAgICAgICAgIC8qIFRoaXMgZXZlbnQgaXMgdHJpZ2dlcmVkIHdpdGggbm8gc2hpcHBpbmcgYWRkcmVzcyB3aGVuIGEgY3VzdG9tZXIgY2xpY2tzIFwiY2hhbmdlXCJcbiAgICAgICAgICAgICAgIHRvIGNob29zZSBhbiBhbHRlcm5hdGUgZW1haWwgYWRkcmVzcyBpbiB0aGUgbW9kYWxcbiAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlU2hpcHBpbmdBZGRyZXNzQ2hhbmdlKHsgdXBkYXRlZFBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJlcXVlc3REYXRhID0ge1xuICAgICAgICAgICAgc2hpcHBpbmdBZGRyZXNzOiBldi5zaGlwcGluZ0FkZHJlc3MsXG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlNoaXBwaW5nQWRkcmVzc0NoYW5nZWQpO1xuICAgICAgICBpZiAocmVzcG9uc2VKU09OLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGRlbGl2ZXJ5TWV0aG9kcywgc2hpcHBpbmdMaW5lcywgdG90YWxTaGlwcGluZ1ByaWNlLCB0b3RhbFRheCwgdG90YWwgfSA9IHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdDtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHBheW1lbnQgcmVxdWVzdCBiYXNlZCBvbiB0aGUgc2hpcHBpbmcgYWRkcmVzcyBjaGFuZ2VcbiAgICAgICAgY29uc3QgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAvLyAuLi5jdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgICAgICBkZWxpdmVyeU1ldGhvZHM6IGRlbGl2ZXJ5TWV0aG9kcyxcbiAgICAgICAgICAgIHNoaXBwaW5nTGluZXM6IHNoaXBwaW5nTGluZXMsXG4gICAgICAgICAgICB0b3RhbFNoaXBwaW5nUHJpY2U6IHRvdGFsU2hpcHBpbmdQcmljZSxcbiAgICAgICAgICAgIHRvdGFsVGF4OiB0b3RhbFRheCxcbiAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICB9KSk7XG5cbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwicGF5bWVudGNvbmZpcm1hdGlvbnJlcXVlc3RlZFwiLCBmdW5jdGlvbihldikge1xuICAgICAgICBjb25zdCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIHRva2VuOiBzZXNzaW9uLnRva2VuLFxuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3Q6IHNlc3Npb24ucGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuU3VibWl0UGF5bWVudCk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGF5bWVudENvbmZpcm1hdGlvblJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImdlbmVyYWxFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgbGV0IGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGF5bWVudENvbmZpcm1hdGlvblJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImdlbmVyYWxFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgb3JkZXJDb25maXJtYXRpb25EYXRhID0ge1xuICAgICAgICAgICAgb3JkZXJJRDogcmVzcG9uc2VKU09OLm9yZGVySUQsXG4gICAgICAgICAgICBvcmRlclRva2VuOiByZXNwb25zZUpTT04ub3JkZXJUb2tlbixcbiAgICAgICAgICAgIGNvbnRpbnVlVXJsOiByZXNwb25zZUpTT04uY29udGludWVVcmxcbiAgICAgICAgfTtcbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVBheW1lbnRDb25maXJtYXRpb25SZXF1ZXN0KCk7XG4gICAgfSk7XG5cbiAgICBzZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJwYXltZW50Y29tcGxldGVcIiwgZnVuY3Rpb24oZXYpIHtcblx0XHR2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICB0b2tlbjogc2Vzc2lvbi50b2tlbixcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0LFxuXHRcdFx0ZXZlbnQ6IGV2XG4gICAgICAgIH07XG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblx0XHR2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlBheW1lbnRDb21wbGV0ZSk7XG5cdFx0aWYgKGV2LnByb2Nlc3NpbmdTdGF0dXMuc3RhdHVzID09PSBcImNvbXBsZXRlZFwiKSB7XG5cdFx0XHRyZWxvYWRPbkNsb3NlID0gZmFsc2U7XG5cdFx0XHRzZXNzaW9uLmNsb3NlKCk7XG5cdFx0XHR2YXIgZGF0YSA9IG9yZGVyQ29uZmlybWF0aW9uRGF0YTtcblx0XHRcdHZhciByZWRpcmVjdCA9ICQoJzxmb3JtPicpLmFwcGVuZFRvKGRvY3VtZW50LmJvZHkpLmF0dHIoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0YWN0aW9uOiBkYXRhLmNvbnRpbnVlVXJsXG5cdFx0XHR9KTtcblx0XHRcdCQoJzxpbnB1dD4nKS5hcHBlbmRUbyhyZWRpcmVjdCkuYXR0cih7XG5cdFx0XHRcdG5hbWU6ICdvcmRlcklEJyxcblx0XHRcdFx0dmFsdWU6IGRhdGEub3JkZXJJRFxuXHRcdFx0fSk7XG5cdFx0XHQkKCc8aW5wdXQ+JykuYXBwZW5kVG8ocmVkaXJlY3QpLmF0dHIoe1xuXHRcdFx0XHRuYW1lOiAnb3JkZXJUb2tlbicsXG5cdFx0XHRcdHZhbHVlOiBkYXRhLm9yZGVyVG9rZW5cblx0XHRcdH0pO1xuXHRcdFx0cmVkaXJlY3Quc3VibWl0KCk7XG5cdFx0fVxuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwid2luZG93Y2xvc2VkXCIsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIC8vIFJlc2V0IGdsb2JhbCB2YWx1ZSB0byBkZWZhdWx0XG4gICAgICAgIC8vIGlmICghcmVsb2FkT25DbG9zZSkge1xuICAgICAgICAvLyAgICAgcmVsb2FkT25DbG9zZSA9IHRydWU7XG4gICAgICAgIC8vIH0gZWxzZSB7XG4gICAgICAgIC8vICAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG4gICAgICAgIC8vIH1cblx0XHR2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICB0b2tlbjogc2Vzc2lvbi50b2tlbixcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0LFxuXHRcdFx0ZXZlbnQ6IGV2XG4gICAgICAgIH07XG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblx0XHR2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLldpbmRvd0Nsb3NlZCk7XG4gICAgfSk7XG5cblx0c2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZGVsaXZlcnltZXRob2R0eXBlY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBkZWxpdmVyeU1ldGhvZFR5cGU6IGV2LmRlbGl2ZXJ5TWV0aG9kVHlwZSxcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlZCk7XG5cdFx0dmFyIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwgcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0KSk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgdXBkYXRlZFBheW1lbnRSZXF1ZXN0OiB1cGRhdGVkUGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cdFx0c2Vzc2lvbi5jb21wbGV0ZURlbGl2ZXJ5TWV0aG9kVHlwZUNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG5cdHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInBpY2t1cGxvY2F0aW9uY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBwaWNrdXBMb2NhdGlvbjogZXYucGlja3VwTG9jYXRpb24sXG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlBpY2t1cExvY2F0aW9uQ2hhbmdlZCk7XG5cdFx0dmFyIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwgcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0KSk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25DaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiB0ZWNobmljYWxFcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgfSwgMjAwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2VKU09OLmVycm9yKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3JNc2cgPSB0ZWNobmljYWxFcnJvck1zZztcbiAgICAgICAgICAgIGlmIChyZXNwb25zZUpTT04uZXJyb3JNc2cpIHtcbiAgICAgICAgICAgICAgICBlcnJvck1zZyA9IHJlc3BvbnNlSlNPTi5lcnJvck1zZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlc3Npb24uY29tcGxldGVQaWNrdXBMb2NhdGlvbkNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXHRcdHNlc3Npb24uY29tcGxldGVQaWNrdXBMb2NhdGlvbkNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG5cdHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInBpY2t1cGxvY2F0aW9uZmlsdGVyY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBidXllckxvY2F0aW9uOiBldi5idXllckxvY2F0aW9uLFxuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3Q6IGN1cnJlbnRQYXltZW50UmVxdWVzdCxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAod2luZG93LnNob3BwYXlDbGllbnRSZWZzLmNvbnN0YW50cy5pc0J1eU5vdykge1xuICAgICAgICAgICAgcmVxdWVzdERhdGEuYmFza2V0SWQgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlc3BvbnNlSlNPTiA9IGNyZWF0ZVJlc3BvbnNlKHJlcXVlc3REYXRhLCB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMudXJscy5QaWNrdXBMb2NhdGlvbkZpbHRlckNoYW5nZWQpO1xuXHRcdHZhciB1cGRhdGVkUGF5bWVudFJlcXVlc3QgPSB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZCgkLmV4dGVuZChjdXJyZW50UGF5bWVudFJlcXVlc3QsIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCkpO1xuICAgICAgICBpZiAocmVzcG9uc2VKU09OLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVBpY2t1cExvY2F0aW9uRmlsdGVyQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25GaWx0ZXJDaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblx0XHRzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25GaWx0ZXJDaGFuZ2UoeyB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdCB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBFbmFibGVzICYgRGlzYWJsZXMgU2hvcCBQYXkncyBCdXkgTm93IGJ1dHRvbiBjbGljayBiYXNlZCBvbiB3aGV0aGVyIHRoZSBwcm9kdWN0IGlzIHJlYWR5IHRvIG9yZGVyIG9uIHRoZSBQRFBcbiAqL1xuZnVuY3Rpb24gc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZWxlbSwgaXNSZWFkeVRvT3JkZXIsIGZvcmNlRGlzYWJsZSkge1xuICAgIGxldCByZWFkeVRvT3JkZXJQYWdlTG9hZCA9IGlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCgpO1xuICAgIGxldCBpc0J1eU5vdyA9IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3c7XG5cbiAgICBpZiAoZWxlbSkge1xuICAgICAgICAvLyBBbiBlcnJvciBvY2N1cnJlZCwgZGlzYWJsZSB0aGUgYnV0dG9uXG4gICAgICAgIGlmICghaXNCdXlOb3cgJiYgZm9yY2VEaXNhYmxlKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgICAgICBpZiAob2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0J1eU5vdyB8fCAoaXNCdXlOb3cgJiYgKGlzUmVhZHlUb09yZGVyIHx8IHJlYWR5VG9PcmRlclBhZ2VMb2FkKSkpIHtcbiAgICAgICAgICAgIGVsZW0uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhdXRvJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVsZW0uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBXYXRjaGVzIGZvciB3aGVuIFNob3BQYXkgYnV0dG9uIGlzIGZpcnN0IHJlbmRlcmVkIHRvIHRoZSBwYWdlIHRvIHRoZW4gYXBwbHkgY29ycmVjdCBidXR0b24gc3R5bGluZyBkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgYmFza2V0IGlzIGVtcHR5IG9yIG5vdFxuICovXG5mdW5jdGlvbiBzaG9wcGF5TXV0YXRpb25PYnNlcnZlcihlbGVtU2VsZWN0b3IpIHtcbiAgICBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKChtdXRhdGlvbnNMaXN0LCBvYnNlcnZlcikgPT4ge1xuICAgICAgICBjb25zdCByZW5kZXJlZFNob3BQYXlFbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlbGVtU2VsZWN0b3IpO1xuICAgICAgICBpZiAocmVuZGVyZWRTaG9wUGF5RWxlbSkge1xuICAgICAgICAgICAgc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUocmVuZGVyZWRTaG9wUGF5RWxlbSk7XG4gICAgICAgICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIG9ic2VydmVyLm9ic2VydmUoZG9jdW1lbnQuYm9keSwgeyBjaGlsZExpc3Q6IHRydWUsIHN1YnRyZWU6IHRydWUgfSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBCdXkgTm93IHByb2R1Y3QgaXMgcmVhZHkgb24gcGFnZSBsb2FkIG9yIG5vdCAoZXg6IHNpbXBsZSBwcm9kdWN0cyB2cy4gdmFyaWFudHMgd2l0aCBtdWx0aXBsZSBvcHRpb25zIHRvIGNob29zZSBmcm9tLCBldGMuKVxuICovXG5mdW5jdGlvbiBpc1JlYWR5VG9PcmRlck9uUGFnZUxvYWQoKSB7XG4gICAgbGV0IHJlYWR5VG9PcmRlciA9IGZhbHNlO1xuICAgIGxldCAkZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLXJlYWR5LXRvLW9yZGVyXScpO1xuICAgIGlmICgkZWxlbWVudCAmJiAkZWxlbWVudC5hdHRyaWJ1dGVzWydkYXRhLXJlYWR5LXRvLW9yZGVyJ10gJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1yZWFkeS10by1vcmRlciddLnZhbHVlKSB7XG4gICAgICAgIHJlYWR5VG9PcmRlciA9ICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtcmVhZHktdG8tb3JkZXInXS52YWx1ZSA9PT0gXCJ0cnVlXCI7XG4gICAgfVxuICAgIHJldHVybiByZWFkeVRvT3JkZXI7XG59XG5cbi8qKlxuICogSGFuZGxlcyBBSkFYIGNhbGwgdG8gY3JlYXRlIC8gdXBkYXRlIHRoZSBwYXltZW50IHJlc3BvbnNlIG5lZWRlZCBmb3IgdGhlIFNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoKSBtZXRob2QuXG4gKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdE9iaiAtIGEgcmVxdWVzdCBvYmplY3QgdGhhdCBjb250YWlucyByZWxldmFudCBldmVudCBkYXRhICYgc2Vzc2lvbiBkYXRhLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRyb2xsZXJVUkwgLSBTdHJpbmcgdXJsIG9mIHRoZSB0YXJnZXRlZCBjb250cm9sbGVyIChiYXNlZCBvbiB0aGUgdXJscyBPYmogc2V0IGluIHNob3BwYXlHbG9iYWxSZWZzLmpzKVxuICogQHJldHVybnMge09iamVjdH0gcmVzcG9uc2VKU09OIC0gYW4gdXBkYXRlZCByZXNwb25zZSBvYmplY3QgdG8gYmUgdXNlZCBpbiB0aGUgYnVpbGQgJiBvbiB0aGUgU2hvcFBheS5QYXltZW50UmVxdWVzdCBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVJlc3BvbnNlIChyZXF1ZXN0T2JqLCBjb250cm9sbGVyVVJMKSB7XG4gICAgbGV0IHJlc3BvbnNlSlNPTjtcbiAgICAkLmFqYXgoe1xuICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4oY29udHJvbGxlclVSTCksXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBhc3luYzogZmFsc2UsXG4gICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHJlcXVlc3RPYmopLFxuICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICByZXNwb25zZUpTT04gPSBkYXRhO1xuICAgICAgICAgICAgcmVzcG9uc2VKU09OLmV4Y2VwdGlvbiA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgcmVzcG9uc2VKU09OID0gZXJyLnJlc3BvbnNlSlNPTiA/IGVyci5yZXNwb25zZUpTT04gOiB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlSlNPTi5leGNlcHRpb24gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzcG9uc2VKU09OO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgQUpBWCBjYWxsIHRvIGdldCB0aGUgcGF5bWVudCByZXNwb25zZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IHBheW1lbnRSZXNwb25zZSAtIGFuIHJlc3BvbnNlIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRQYXltZW50UmVxdWVzdChzZXNzaW9uKSB7XG4gICAgbGV0IHRva2VuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtY3NyZi10b2tlbl0nKTtcbiAgICBsZXQgcmVzcG9uc2U7XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICAgIGNvbnN0IHBheW1lbnRSZXNwb25zZSA9ICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4od2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuR2V0Q2FydFN1bW1hcnkpLFxuICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgYXN5bmM6IGZhbHNlLFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghZGF0YS5lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlSlNPTjogZGF0YVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNob3BwYXlCdG5EaXNhYmxlZFN0eWxlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lclwiKSwgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAvKiAgUmV0dXJuIHRvIGV4aXQgZnVuY3Rpb24gLSBkb24ndCByZWxvYWQgdGhlIHBhZ2UgaW4gY2FzZSB0aGVyZSBpcyBhIHBhZ2UgcmVuZGVyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICBpc3N1ZSAod2lsbCByZXN1bHQgaW4gaW5maW5pdGUgcmVsb2FkIGxvb3ApLlxuICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNob3BwYXlCdG5EaXNhYmxlZFN0eWxlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lclwiKSwgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLyogIFJldHVybiB0byBleGl0IGZ1bmN0aW9uIC0gZG9uJ3QgcmVsb2FkIHRoZSBwYWdlIGluIGNhc2UgdGhlcmUgaXMgYSBwYWdlIHJlbmRlcmluZ1xuICAgICAgICAgICAgaXNzdWUgKHdpbGwgcmVzdWx0IGluIGluZmluaXRlIHJlbG9hZCBsb29wKS5cbiAgICAgICAgKi9cbiAgICAgICAgaWYgKHNlc3Npb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBzaG9wcGF5QnRuRGlzYWJsZWRTdHlsZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNob3AtcGF5LWJ1dHRvbi1jb250YWluZXJcIiksIG51bGwsIHRydWUpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYnVpbGRQYXltZW50UmVxdWVzdDogYnVpbGRQYXltZW50UmVxdWVzdCxcbiAgICBjcmVhdGVSZXNwb25zZTogY3JlYXRlUmVzcG9uc2UsXG4gICAgZ2V0Q3NyZlRva2VuOiBnZXRDc3JmVG9rZW4sXG4gICAgZ2V0SW5pdFByb2R1Y3REYXRhOiBnZXRJbml0UHJvZHVjdERhdGEsXG4gICAgZ2V0VXJsV2l0aENzcmZUb2tlbjogZ2V0VXJsV2l0aENzcmZUb2tlbixcbiAgICBpc1JlYWR5VG9PcmRlck9uUGFnZUxvYWQ6IGlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCxcbiAgICBwcm9kdWN0RGF0YTogcHJvZHVjdERhdGEsXG4gICAgc2V0SW5pdFByb2R1Y3REYXRhOiBzZXRJbml0UHJvZHVjdERhdGEsXG4gICAgc2V0U2Vzc2lvbkxpc3RlbmVyczogc2V0U2Vzc2lvbkxpc3RlbmVycyxcbiAgICBzaG9wcGF5QnRuRGlzYWJsZWRTdHlsZTogc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUsXG4gICAgc2hvcHBheU11dGF0aW9uT2JzZXJ2ZXI6IHNob3BwYXlNdXRhdGlvbk9ic2VydmVyLFxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5TZXJ2aWNlU3VmZml4ZXMgPSB7XG5cdFNlcnZpY2VTdWl0ZTogJy9lY29tbS8wLjEnLFxuXHRBdXRoZW50aWNhdGU6ICcvYXV0aGVudGljYXRlL3Jvb3QnLFxuXHRQdXJjaGFzZUdpZnRDYXJkOiAnL2Z1bGZpbGxtZW50LzAuMS9wdXJjaGFzZWVnaWZ0Lydcbn07XG5cbmV4cG9ydHMuTWVzc2FnZVByZWZpeGVzID0ge1xuXHROb25TdWNjZXNzOiAnU3RvcmVkIFZhbHVlIFNvbHV0aW9ucyByZXR1cm5lZCBhIHJlc3VsdCBvdGhlciB0aGFuIE9LIGFuZC9vciB3aXRob3V0IGRhdGEgJyxcblx0RXJyb3I6ICdTdG9yZWQgVmFsdWUgU29sdXRpb25zIGVuY291bnRlcmVkIGFuZCB1bmV4cGVjdGVkIGV4Y2VwdGlvbiAnXG59O1xuXG5leHBvcnRzLlRyYW5zYWN0aW9uSW5mb3JtYXRpb24gPSB7XG5cdFN1Y2Nlc3M6ICdTdWNjZXNzZnVsIFRyYW5zYWN0aW9uIC0gTm8gQWRkaXRpb25hbCBJbmZvcm1hdGlvbicsXG5cdEZhaWx1cmU6IHtcblx0XHRCYWxhbmNlRXhjZWVkZWQ6ICdPcmRlciBGYWlsdXJlIC0gUmVxdWVzdGVkIEFtb3VudCBFeGNlZWRlZCBHaWZ0IENhcmQgQmFsYW5jZScsXG5cdFx0SGVsZEFtb3VudFJlbGVhc2VkOiAnT3JkZXIgRmFpbHVyZSAtIFJlbGVhc2luZyBBbW91bnQgSGVsZCBieSBQcmUtQXV0aG9yaXphdGlvbidcblx0fVxufVxuXG5leHBvcnRzLlRyYW5zYWN0aW9uVHlwZXMgPSB7XG5cdEJhbGFuY2VJbnF1aXJ5OiAnQmFsYW5jZSBJbnF1aXJ5Jyxcblx0UHJlQXV0aG9yaXphdGlvbjogJ1ByZS1BdXRob3JpemF0aW9uJyxcblx0UHJlQXV0aG9yaXphdGlvbkNvbXBsZXRlOiAnUHJlLUF1dGhvcml6YXRpb24gQ29tcGxldGUnXG59XG5cbmV4cG9ydHMuUmVzcG9uc2VQYXJzZXJzID0ge1xuXHRiYWxhbmNlSW5xdWlyeVJlc3BvbnNlOiB7XG5cdFx0UGF0aDogJy9pbnRfc3ZzL2NhcnRyaWRnZS9zY3JpcHRzL0JhbGFuY2VJbnF1aXJ5UmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAnYmFsYW5jZUlucXVpcnlSZXR1cm4nXG5cdH0sXG5cdHByZUF1dGhSZXNwb25zZToge1xuXHRcdFBhdGg6ICcvaW50X3N2cy9jYXJ0cmlkZ2Uvc2NyaXB0cy9QcmVBdXRob3JpemF0aW9uUmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAncHJlQXV0aFJldHVybidcblx0fSxcblx0cHJlQXV0aENvbXBsZXRlUmVzcG9uc2U6IHtcblx0XHRQYXRoOiAnL2ludF9zdnMvY2FydHJpZGdlL3NjcmlwdHMvUHJlQXV0aG9yaXphdGlvbkNvbXBsZXRlUmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAncHJlQXV0aENvbXBsZXRlUmV0dXJuJ1xuXHR9XG59O1xuXG5leHBvcnRzLlJldHVybkNvZGVzID0ge1xuXHRBcHByb3ZhbDogJzAxJyxcblx0SW5hY3RpdmVDYXJkOiAnMDInLFxuXHRJbnZhbGlkQ2FyZE51bWJlcjogJzAzJyxcblx0SW52YWxpZFRyYW5zYWN0aW9uQ29kZTogJzA0Jyxcblx0SW5zdWZmaWNpZW50RnVuZHM6ICcwNScsXG5cdE5vUHJldmlvdXNBdXRob3JpemF0aW9uczogJzA2Jyxcblx0SW52YWxpZE1lc3NhZ2U6ICcwNycsXG5cdE5vQ2FyZEZvdW5kOiAnMDgnLFxuXHRJbnN1ZmZpY2VudEZ1bmRzRHVlVG9PdXRzdGFuZGluZ1ByZUF1dGhvcml6YXRpb246ICcwOScsXG5cdERlbmlhbE5vUHJldmlvdXNBdXRob3JpemF0aW9uOiAnMTAnLFxuXHROb0F1dGhvcml6YXRpb25OdW1iZXI6ICcxMScsXG5cdEludmFsaWRBdXRob3JpemF0aW9uTnVtYmVyOiAnMTInLFxuXHRNYXhpbXVtU2luZ2xlUmVjaGFyZ2VFeGNlZWRlZDogJzEzJyxcblx0TWF4aW11bVdPcmtpbmdCYWxhbmNlRXhjZWVkZWQ6ICcxNCcsXG5cdEhvc3RVbmF2YWlsYWJsZTogJzE1Jyxcblx0SW52YWxpZENhcmRTdGF0dXM6ICcxNicsXG5cdFVua25vd25EZWFsZXJTdG9yZUNvZGVTcGVjaWFsRWRpdDogJzE3Jyxcblx0TWF4aW11bU51bWJlck9mUmVjaGFyZ2VzRXhjZWVkZWQ6ICcxOCcsXG5cdEludmFsaWRDYXJkVmVyaWZpY2F0aW9uVmFsdWVPclNlY29uZGFyeVNlY3VyaXR5Q29kZTogJzE5Jyxcblx0SW52YWxpZFBpbk51bWJlck9yUGluTG9ja2VkOiAnMjAnLFxuXHRDYXJkQWxyZWFkeUlzc3VlZDogJzIxJyxcblx0Q2FyZE5vdElzc3VlZDogJzIyJyxcblx0Q2FyZEFscmVhZHlVc2VkOiAnMjMnLFxuXHRNYW51YWxUcmFuc2FjdGlvbk5vdEFsbG93ZWQ6ICcyNCcsXG5cdE1hZ1N0cmlwZVJlYWROb3RWYWxpZDogJzI1Jyxcblx0VHJhbnNhY3Rpb25UeXBlVW5rbm93bjogJzI2Jyxcblx0SW52YWxpZFRlbmRlclR5cGU6ICcyNycsXG5cdEludmFsaWRDdXN0b21lclR5cGU6ICcyOCcsXG5cdE1heE51bWJoZXJPZlJlZGVtcHRpb25FeGNlZWRlZDogJzMwJyxcblx0SW52YWxpZEN1cnJlbmN5Q29kZTogJzMxJyxcblx0SW52YWxpZFNlcnZlcklkOiAnMzInLFxuXHRGcm96ZW5DYXJkT3JVbmtub3duOiAnMzMnLFxuXHRJbnZhbGlkQW1vdW50OiAnMzQnLFxuXHRUcmFuc2FjdGlvblJlamVjdGVkSW52YWxpZFRyYW5zYWN0aW9uUHJvbW90aW9uV2lkZU9ySW52YWxpZEZvck9yaWdpbmF0aW5nTWVyY2hhbnRBbmRTdG9yZTogJzM2Jyxcblx0VHJhbnNhY3Rpb25SZWplY3RlZEludmFsaWRNZXJjaGFudEFuZFN0b3JlQ29tYmluYXRpb25Gb3JQcm9tb3Rpb246ICczNycsXG5cdFRyYW5zYWN0aW9uUmVqZWN0ZWRFeGNlZWRlZE1heGltdW1OdW1iZXJPZlByb21vdGlvbkNhcmRzOiAnMzgnLFxuXHRUcmFuc2FjdGlvbkRlY2xpbmVkQW1vdW50TGVzc1RoYW5NaW5pbXVtOiAnNDInLFxuXHRGYWlsdXJlSW5SZXRyaWV2aW5nRGF0YTogJzk5Jyxcblx0UmF0ZUxpbWl0RXhjZWVkZWQ6ICc5OTknXG59O1xuXG5leHBvcnRzLlJldHVybkRlc2NyaXB0aW9uTWVzc2FnZXNGb3JSZXR1cm5Db2RlcyA9IHtcblx0JzAzJzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJyxcblx0JzA4JzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJyxcblx0JzIwJzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJ1xufVxuXG5leHBvcnRzLkdpZnRDYXJkVHlwZXMgPSB7XG5cdGVHaWZ0OiAnZUdpZnQnLFxuXHRQaHlzaWNhbDogJ1BoeXNpY2FsJyxcblx0Tm90QXBwbGljYWJsZTogJ05vdEFwcGxpY2FibGUnXG59O1xuXG5leHBvcnRzLk9yZGVyVHlwZXMgPSB7XG5cdEludGVyYWN0aXZlOiAnSScsXG5cdFdlYjogJ1cnXG59OyJdfQ=="}