{"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;;AC1gBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACr+DA;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;;AC/gBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACvZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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.$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.$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\tself.loaded['LocationData'] = false;\n\t\t\tself.loaded['InventoryData'] = false;\n\t\t\tself.dataBuffer['LocationData'] = null;\n\t\t\tself.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}\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};\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}\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\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-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.$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.$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: 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\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\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\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// Range Slider\n\t$('.range-slider').each(function () {\n\t\tvar minValue = +$(this).data('min'),\n\t\t\tmaxValue = +$(this).data('max');\n\t\t$(this).slider({\n\t\t\trange: \ttrue,\n\t\t\tmin: \tminValue,\n\t\t\tmax: \tmaxValue,\n\t\t\tvalues: [getUrlVars()['pmin'] || minValue, getUrlVars()['pmax'] || maxValue],\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$(this).children('.price-min').html('$' + ui.values[0]);\n\t\t\t\t$(this).children('.price-max').html('$' + ui.values[1]);\n\t\t\t}\n\t\t});\n\t});\n\n\tvar timeout;\n\t$('.range-slider').on('slidechange', function( event, ui ) {\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(function () {\n\t\t\tvar cgid = getUrlVars()['cgid'],\n\t\t\t\tsiteLocation = window.location;\n\t\t\tsiteLocation.assign( siteLocation.protocol + '//' + siteLocation.hostname + siteLocation.pathname + '?cgid=' + cgid + '&pmin=' + ui.values[0] + '&pmax=' + ui.values[1]);\n\t\t}, 2000);\n\t});\n\n\t$(document).ready(function() {\n\t\tif ($('.range-slider').length > 0 && getUrlVars()['pmin']) {\n\t\t\tvar slider = $('.range-slider');\n\t\t\tslider.children('.price-min').html('$' + getUrlVars()['pmin']);\n\t\t\tslider.children('.price-max').html('$' + getUrlVars()['pmax']);\n\t\t\t$('.slider-toggle').toggleClass('expanded')\n\t\t\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t\t.find('.refinement-body')\n\t\t\t\t\t\t\t\t.stop()\n\t\t\t\t\t\t\t\t.toggle();\n\t\t}\n\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}\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\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_value': { 'refinement_category': refinementId }, \n\t\t\t\t\t'action_items': { 'refinement_value': refinementValue }\n\t\t\t\t};\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ApplyRefinement', 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\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_value': { 'refinement_category': refinementId }, \n\t\t\t\t\t'action_items': { 'refinement_value': refinementValue }\n\t\t\t\t};\n\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ApplyRefinement', 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\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\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_value': { 'refinement_category': refinementId }, \n\t\t\t\t\t\t\t'action_items': { 'refinement_value': refinementValue }\n\t\t\t\t\t\t};\n\t\t\t\t\t\tGoogleTagManagerClient.PushDataLayerForDataLayerType('ApplyRefinement', refinementAnalyticsTaggingData);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\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) {\n\t\turl = util.removeParamFromURL(url, 'pmin');\n\t\turl = util.removeParamFromURL(url, 'pmax');\n\t\t\n\t\tvar $refinementPrice = $('[is-price-refinement=\"true\"] input:checked').closest('[is-price-refinement=\"true\"]');\n\t\turl = util.appendParamToURL(url, 'pmin', $refinementPrice.attr('pmin'));\n\t\turl = util.appendParamToURL(url, 'pmax', $refinementPrice.attr('pmax'));\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\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) {\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\tif (hasNormalRefinementValues || hasPopularRefinementValues) {\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\nfunction getUrlVars() {\n    var vars = [], hash;\n    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');\n    for(var i = 0; i < hashes.length; i++)\n\t    {\n\t        hash = hashes[i].split('=');\n\t        vars.push(hash[0]);\n\t        vars[hash[0]] = hash[1];\n\t    }\n    return vars;\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\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\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\tpushDataLayerForDataLayerTypeForDataLayerVersion(dataLayerType, dataObject.UniversalAnalytics || Object.assign({}, dataObject), 'UniversalAnalytics', options).then(function() {\n\t\t\tajaxCompleteStatus.UniversalAnalytics = 'success';\n\t\t\tajaxComplete();\n\t\t}).catch(function() {\n\t\t\tajaxCompleteStatus.UniversalAnalytics = 'error';\n\t\t\tajaxComplete();\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvaW1hZ2VzbG9hZGVkL2ltYWdlc2xvYWRlZC5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvbm9kZV9tb2R1bGVzL2V2ZW50aWUvZXZlbnRpZS5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvbm9kZV9tb2R1bGVzL3dvbGZ5ODctZXZlbnRlbWl0dGVyL0V2ZW50RW1pdHRlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL3Byb21pc2UvbGliL2RvbmUuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZXM2LWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZmluYWxseS5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9ub2RlLWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvc3luY2hyb25vdXMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9ub2RlX21vZHVsZXMvYXNhcC9icm93c2VyLWFzYXAuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9ub2RlX21vZHVsZXMvYXNhcC9icm93c2VyLXJhdy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9Cb290QmFybkV4cHJlc3MvY29tcG9uZW50cy9Cb290QmFybkV4cHJlc3NSZWZpbmVtZW50V2l6YXJkLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL0xvYi9BZGRyZXNzQXV0b2NvbXBsZXRlL0FkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvTG9iL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9hamF4LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2FsZXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2FwcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib251cy1wcm9kdWN0cy12aWV3LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2JvcGlzL2NvbXBvbmVudHMvQWRkVG9DYXJ0T3B0aW9ucy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL0FkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL0xvY2FsRGVsaXZlcnlEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvYm9waXMvY29tcG9uZW50cy9Mb2NhdGlvblNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL1Byb2R1Y3RMaW5lSXRlbUhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9ib3Bpcy9jb21wb25lbnRzL1Nob3BZb3VyU3RvcmVEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvYm9waXMvY29tcG9uZW50cy9TdG9yZVNlYXJjaC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jYXB0Y2hhLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBhcmUtd2lkZ2V0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvQ2Fyb3VzZWxWaWRlby5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0Nvb2tpZU5vdGlmaWNhdGlvbi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0VtYWlsRm9ybS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0VtYWlsU2lnbnVwLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvR2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0dpZnRDYXJkQmFsYW5jZUlucXVpcnlEaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9HbG9iYWxlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvSW1hZ2VHYWxsZXJ5L1NsaWNrQW5kSW1nVmlld2VyMi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL0ltYWdlR2FsbGVyeS9Td2lwZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvTmF2aWdhdGlvbkNvbnRyb2xsZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9PcmRlclN0YXR1c0Zvcm0uanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9SZWNhcHRjaGEuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY29tcG9uZW50cy9SZWNlbnRseVZpZXdlZFByb2R1Y3RzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvU2FtZURheVNoaXBwaW5nQ291bnRkb3duLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2Nvb2tpZXByaXZhY3kuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvY291bnRkb3duLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2NvdW50cmllcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9kaWFsb2cuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZmluZE1vcmVTdG9yZXMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZ2lmdGNhcmQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvZ2lmdGNlcnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvaGVscGVycy9HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5SGVscGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2hlbHBlcnMvUmVxdWVzdEhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9qcXVlcnktZXh0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xhenlsb2FkUGFnZUVsZW1lbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xvZ2luLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL2xvZ2luRGlhbG9nLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL21pbmljYXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2UuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvQXV0aGVudGljYXRpb24vRW1haWxBZGRyZXNzQ2FwdHVyZS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9hY2NvdW50LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2Jvb3RiYXJuZXhwcmVzcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9ib290ZmluZGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NhcnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2FydF9lY2hvLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NhdGVnb3J5bGFuZGluZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9BcHBsZVBheS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9HaWZ0Q2FyZFBheW1lbnRQYW5lbC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9Mb3lhbHR5Q3JlZGl0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L1BheW1lbnRWb3VjaGVyUGF5bWVudFBhbmVsLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L1Jld2FyZHNDcmVkaXQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvYWRkcmVzcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9iaWxsaW5nLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L2Zvcm1QcmVwYXJlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L2luZGV4LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L211bHRpc2hpcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9vcGNhZGRyZXNzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L29wY2FkZHJlc3NfZW5oYW5jZWQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvb3BjcGF5bWVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9zaGlwcGluZy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dF9lY2hvLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL2NvbXBhcmUuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvY29udGVudC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9vbmVwY2hlY2tvdXQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvb25lcGNoZWNrb3V0X2dyb3Vwcy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9vcmRlcmNvbmZpcm1hdGlvbi5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2FkZFRvQ2FydC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2F2YWlsYWJpbGl0eS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2ltYWdlLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvaW5kZXguanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC9wcm9kdWN0U2V0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvcmVxdWVzdEdpZnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC92YXJpYW50LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvdmlkZW8uanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvcmVnaXN0cnkuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvc2VhcmNoLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BhZ2VzL3N0b3JlZnJvbnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcGFnZXMvc3RvcmVsb2NhdG9yLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3BvcHVwLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3Byb2R1Y3QtdGlsZS5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9wcm9kdWN0Um90YXRlM2QuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcHJvZ3Jlc3MuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcXVhbnRpdHlTdGVwcGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3F1aWNrdmlldy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9yYXRpbmcuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvcmVnaXN0ZXIuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc2VhcmNoYmFyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NlYXJjaHBsYWNlaG9sZGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NpemUtcmVmaW5lbWVudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc2xpY2tTbGlkZXJIZWxwZXJzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3NsaWRlcnMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvc3RvcmVpbnZlbnRvcnkvY2FydC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9pbmRleC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9wcm9kdWN0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3N0eWxlLWNvdW50cy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy90bHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvdG9vbHRpcC5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy91dGlsLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL3ZhbGlkYXRvci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy93YXRlcm1hcmsuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvd2lzaGxpc3QuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYXBwX3N0b3JlZnJvbnRfY291bnRyeW91dGZpdHRlcnMvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvZGF0YS9TdGF0ZVRvWmlwQ29kZU1hcC5qc29uIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvZGF0YS9aaXBDb2RlVG9TdGF0ZU1hcC5qc29uIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQ2hlY2tvdXRDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9EYXRhTGF5ZXJDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9HZW9sb2NhdGlvbi9HZW9sb2NhdGlvbkhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9SZWZpbmVtZW50Q29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUmVnZXhQYXR0ZXJucy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cy5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQuanMiLCIuLi8uLi9UZW1wL0NhcnRyaWRnZXMvYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9ib290YmFybl9yc3AvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzLmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2ludF9zaG9wcGF5X3NmcmEvY2FydHJpZGdlL2NsaWVudC9kZWZhdWx0L2pzL2NhcnQvaW5pdFNob3BQYXlDYXJ0LmpzIiwiLi4vLi4vVGVtcC9DYXJ0cmlkZ2VzL2ludF9zaG9wcGF5X3NmcmEvY2FydHJpZGdlL2NsaWVudC9kZWZhdWx0L2pzL2hlbHBlcnMvc2hvcHBheUhlbHBlci5qcyIsIi4uLy4uL1RlbXAvQ2FydHJpZGdlcy9pbnRfc3ZzL2NhcnRyaWRnZS9zY3JpcHRzL0dpZnRDYXJkQ29uc3RhbnRzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMxZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMvallBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDL05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3prQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOWJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMWtDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25uQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDek1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbldBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL3FCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbGdEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdDRCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNod0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM21CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5UkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4NEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyK0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL09BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN2NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9nQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTs7QUNBQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMXNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvKiFcbiAqIGltYWdlc0xvYWRlZCB2My4yLjBcbiAqIEphdmFTY3JpcHQgaXMgYWxsIGxpa2UgXCJZb3UgaW1hZ2VzIGFyZSBkb25lIHlldCBvciB3aGF0P1wiXG4gKiBNSVQgTGljZW5zZVxuICovXG5cbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHsgJ3VzZSBzdHJpY3QnO1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cblxuICAvKmdsb2JhbCBkZWZpbmU6IGZhbHNlLCBtb2R1bGU6IGZhbHNlLCByZXF1aXJlOiBmYWxzZSAqL1xuXG4gIGlmICggdHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG4gICAgLy8gQU1EXG4gICAgZGVmaW5lKCBbXG4gICAgICAnZXZlbnRFbWl0dGVyL0V2ZW50RW1pdHRlcicsXG4gICAgICAnZXZlbnRpZS9ldmVudGllJ1xuICAgIF0sIGZ1bmN0aW9uKCBFdmVudEVtaXR0ZXIsIGV2ZW50aWUgKSB7XG4gICAgICByZXR1cm4gZmFjdG9yeSggd2luZG93LCBFdmVudEVtaXR0ZXIsIGV2ZW50aWUgKTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShcbiAgICAgIHdpbmRvdyxcbiAgICAgIHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyksXG4gICAgICByZXF1aXJlKCdldmVudGllJylcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmltYWdlc0xvYWRlZCA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICB3aW5kb3cuRXZlbnRFbWl0dGVyLFxuICAgICAgd2luZG93LmV2ZW50aWVcbiAgICApO1xuICB9XG5cbn0pKCB3aW5kb3csXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICBmYWN0b3J5IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIGZhY3RvcnkoIHdpbmRvdywgRXZlbnRFbWl0dGVyLCBldmVudGllICkge1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciAkID0gd2luZG93LmpRdWVyeTtcbnZhciBjb25zb2xlID0gd2luZG93LmNvbnNvbGU7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLy8gZXh0ZW5kIG9iamVjdHNcbmZ1bmN0aW9uIGV4dGVuZCggYSwgYiApIHtcbiAgZm9yICggdmFyIHByb3AgaW4gYiApIHtcbiAgICBhWyBwcm9wIF0gPSBiWyBwcm9wIF07XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbnZhciBvYmpUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5mdW5jdGlvbiBpc0FycmF5KCBvYmogKSB7XG4gIHJldHVybiBvYmpUb1N0cmluZy5jYWxsKCBvYmogKSA9PSAnW29iamVjdCBBcnJheV0nO1xufVxuXG4vLyB0dXJuIGVsZW1lbnQgb3Igbm9kZUxpc3QgaW50byBhbiBhcnJheVxuZnVuY3Rpb24gbWFrZUFycmF5KCBvYmogKSB7XG4gIHZhciBhcnkgPSBbXTtcbiAgaWYgKCBpc0FycmF5KCBvYmogKSApIHtcbiAgICAvLyB1c2Ugb2JqZWN0IGlmIGFscmVhZHkgYW4gYXJyYXlcbiAgICBhcnkgPSBvYmo7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBvYmoubGVuZ3RoID09ICdudW1iZXInICkge1xuICAgIC8vIGNvbnZlcnQgbm9kZUxpc3QgdG8gYXJyYXlcbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgb2JqLmxlbmd0aDsgaSsrICkge1xuICAgICAgYXJ5LnB1c2goIG9ialtpXSApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBhcnJheSBvZiBzaW5nbGUgaW5kZXhcbiAgICBhcnkucHVzaCggb2JqICk7XG4gIH1cbiAgcmV0dXJuIGFyeTtcbn1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBpbWFnZXNMb2FkZWQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvKipcbiAgICogQHBhcmFtIHtBcnJheSwgRWxlbWVudCwgTm9kZUxpc3QsIFN0cmluZ30gZWxlbVxuICAgKiBAcGFyYW0ge09iamVjdCBvciBGdW5jdGlvbn0gb3B0aW9ucyAtIGlmIGZ1bmN0aW9uLCB1c2UgYXMgY2FsbGJhY2tcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gb25BbHdheXMgLSBjYWxsYmFjayBmdW5jdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gSW1hZ2VzTG9hZGVkKCBlbGVtLCBvcHRpb25zLCBvbkFsd2F5cyApIHtcbiAgICAvLyBjb2VyY2UgSW1hZ2VzTG9hZGVkKCkgd2l0aG91dCBuZXcsIHRvIGJlIG5ldyBJbWFnZXNMb2FkZWQoKVxuICAgIGlmICggISggdGhpcyBpbnN0YW5jZW9mIEltYWdlc0xvYWRlZCApICkge1xuICAgICAgcmV0dXJuIG5ldyBJbWFnZXNMb2FkZWQoIGVsZW0sIG9wdGlvbnMsIG9uQWx3YXlzICk7XG4gICAgfVxuICAgIC8vIHVzZSBlbGVtIGFzIHNlbGVjdG9yIHN0cmluZ1xuICAgIGlmICggdHlwZW9mIGVsZW0gPT0gJ3N0cmluZycgKSB7XG4gICAgICBlbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCggZWxlbSApO1xuICAgIH1cblxuICAgIHRoaXMuZWxlbWVudHMgPSBtYWtlQXJyYXkoIGVsZW0gKTtcbiAgICB0aGlzLm9wdGlvbnMgPSBleHRlbmQoIHt9LCB0aGlzLm9wdGlvbnMgKTtcblxuICAgIGlmICggdHlwZW9mIG9wdGlvbnMgPT0gJ2Z1bmN0aW9uJyApIHtcbiAgICAgIG9uQWx3YXlzID0gb3B0aW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgZXh0ZW5kKCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMgKTtcbiAgICB9XG5cbiAgICBpZiAoIG9uQWx3YXlzICkge1xuICAgICAgdGhpcy5vbiggJ2Fsd2F5cycsIG9uQWx3YXlzICk7XG4gICAgfVxuXG4gICAgdGhpcy5nZXRJbWFnZXMoKTtcblxuICAgIGlmICggJCApIHtcbiAgICAgIC8vIGFkZCBqUXVlcnkgRGVmZXJyZWQgb2JqZWN0XG4gICAgICB0aGlzLmpxRGVmZXJyZWQgPSBuZXcgJC5EZWZlcnJlZCgpO1xuICAgIH1cblxuICAgIC8vIEhBQ0sgY2hlY2sgYXN5bmMgdG8gYWxsb3cgdGltZSB0byBiaW5kIGxpc3RlbmVyc1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG4gICAgICBfdGhpcy5jaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgSW1hZ2VzTG9hZGVkLnByb3RvdHlwZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLm9wdGlvbnMgPSB7fTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmdldEltYWdlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaW1hZ2VzID0gW107XG5cbiAgICAvLyBmaWx0ZXIgJiBmaW5kIGl0ZW1zIGlmIHdlIGhhdmUgYW4gaXRlbSBzZWxlY3RvclxuICAgIGZvciAoIHZhciBpPTA7IGkgPCB0aGlzLmVsZW1lbnRzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGVsZW0gPSB0aGlzLmVsZW1lbnRzW2ldO1xuICAgICAgdGhpcy5hZGRFbGVtZW50SW1hZ2VzKCBlbGVtICk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge05vZGV9IGVsZW1lbnRcbiAgICovXG4gIEltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkRWxlbWVudEltYWdlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuICAgIC8vIGZpbHRlciBzaWJsaW5nc1xuICAgIGlmICggZWxlbS5ub2RlTmFtZSA9PSAnSU1HJyApIHtcbiAgICAgIHRoaXMuYWRkSW1hZ2UoIGVsZW0gKTtcbiAgICB9XG4gICAgLy8gZ2V0IGJhY2tncm91bmQgaW1hZ2Ugb24gZWxlbWVudFxuICAgIGlmICggdGhpcy5vcHRpb25zLmJhY2tncm91bmQgPT09IHRydWUgKSB7XG4gICAgICB0aGlzLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzKCBlbGVtICk7XG4gICAgfVxuXG4gICAgLy8gZmluZCBjaGlsZHJlblxuICAgIC8vIG5vIG5vbi1lbGVtZW50IG5vZGVzLCAjMTQzXG4gICAgdmFyIG5vZGVUeXBlID0gZWxlbS5ub2RlVHlwZTtcbiAgICBpZiAoICFub2RlVHlwZSB8fCAhZWxlbWVudE5vZGVUeXBlc1sgbm9kZVR5cGUgXSApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGNoaWxkSW1ncyA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCgnaW1nJyk7XG4gICAgLy8gY29uY2F0IGNoaWxkRWxlbXMgdG8gZmlsdGVyRm91bmQgYXJyYXlcbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgY2hpbGRJbWdzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGltZyA9IGNoaWxkSW1nc1tpXTtcbiAgICAgIHRoaXMuYWRkSW1hZ2UoIGltZyApO1xuICAgIH1cblxuICAgIC8vIGdldCBjaGlsZCBiYWNrZ3JvdW5kIGltYWdlc1xuICAgIGlmICggdHlwZW9mIHRoaXMub3B0aW9ucy5iYWNrZ3JvdW5kID09ICdzdHJpbmcnICkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gZWxlbS5xdWVyeVNlbGVjdG9yQWxsKCB0aGlzLm9wdGlvbnMuYmFja2dyb3VuZCApO1xuICAgICAgZm9yICggaT0wOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKysgKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICB0aGlzLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzKCBjaGlsZCApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgZWxlbWVudE5vZGVUeXBlcyA9IHtcbiAgICAxOiB0cnVlLFxuICAgIDk6IHRydWUsXG4gICAgMTE6IHRydWVcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gICAgdmFyIHN0eWxlID0gZ2V0U3R5bGUoIGVsZW0gKTtcbiAgICAvLyBnZXQgdXJsIGluc2lkZSB1cmwoXCIuLi5cIilcbiAgICB2YXIgcmVVUkwgPSAvdXJsXFwoWydcIl0qKFteJ1wiXFwpXSspWydcIl0qXFwpL2dpO1xuICAgIHZhciBtYXRjaGVzID0gcmVVUkwuZXhlYyggc3R5bGUuYmFja2dyb3VuZEltYWdlICk7XG4gICAgd2hpbGUgKCBtYXRjaGVzICE9PSBudWxsICkge1xuICAgICAgdmFyIHVybCA9IG1hdGNoZXMgJiYgbWF0Y2hlc1sxXTtcbiAgICAgIGlmICggdXJsICkge1xuICAgICAgICB0aGlzLmFkZEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICAgICAgfVxuICAgICAgbWF0Y2hlcyA9IHJlVVJMLmV4ZWMoIHN0eWxlLmJhY2tncm91bmRJbWFnZSApO1xuICAgIH1cbiAgfTtcblxuICAvLyBJRThcbiAgdmFyIGdldFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUgfHwgZnVuY3Rpb24oIGVsZW0gKSB7XG4gICAgcmV0dXJuIGVsZW0uY3VycmVudFN0eWxlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0ltYWdlfSBpbWdcbiAgICovXG4gIEltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkSW1hZ2UgPSBmdW5jdGlvbiggaW1nICkge1xuICAgIHZhciBsb2FkaW5nSW1hZ2UgPSBuZXcgTG9hZGluZ0ltYWdlKCBpbWcgKTtcbiAgICB0aGlzLmltYWdlcy5wdXNoKCBsb2FkaW5nSW1hZ2UgKTtcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmFkZEJhY2tncm91bmQgPSBmdW5jdGlvbiggdXJsLCBlbGVtICkge1xuICAgIHZhciBiYWNrZ3JvdW5kID0gbmV3IEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICAgIHRoaXMuaW1hZ2VzLnB1c2goIGJhY2tncm91bmQgKTtcbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB0aGlzLnByb2dyZXNzZWRDb3VudCA9IDA7XG4gICAgdGhpcy5oYXNBbnlCcm9rZW4gPSBmYWxzZTtcbiAgICAvLyBjb21wbGV0ZSBpZiBubyBpbWFnZXNcbiAgICBpZiAoICF0aGlzLmltYWdlcy5sZW5ndGggKSB7XG4gICAgICB0aGlzLmNvbXBsZXRlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Qcm9ncmVzcyggaW1hZ2UsIGVsZW0sIG1lc3NhZ2UgKSB7XG4gICAgICAvLyBIQUNLIC0gQ2hyb21lIHRyaWdnZXJzIGV2ZW50IGJlZm9yZSBvYmplY3QgcHJvcGVydGllcyBoYXZlIGNoYW5nZWQuICM4M1xuICAgICAgc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG4gICAgICAgIF90aGlzLnByb2dyZXNzKCBpbWFnZSwgZWxlbSwgbWVzc2FnZSApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yICggdmFyIGk9MDsgaSA8IHRoaXMuaW1hZ2VzLmxlbmd0aDsgaSsrICkge1xuICAgICAgdmFyIGxvYWRpbmdJbWFnZSA9IHRoaXMuaW1hZ2VzW2ldO1xuICAgICAgbG9hZGluZ0ltYWdlLm9uY2UoICdwcm9ncmVzcycsIG9uUHJvZ3Jlc3MgKTtcbiAgICAgIGxvYWRpbmdJbWFnZS5jaGVjaygpO1xuICAgIH1cbiAgfTtcblxuICBJbWFnZXNMb2FkZWQucHJvdG90eXBlLnByb2dyZXNzID0gZnVuY3Rpb24oIGltYWdlLCBlbGVtLCBtZXNzYWdlICkge1xuICAgIHRoaXMucHJvZ3Jlc3NlZENvdW50Kys7XG4gICAgdGhpcy5oYXNBbnlCcm9rZW4gPSB0aGlzLmhhc0FueUJyb2tlbiB8fCAhaW1hZ2UuaXNMb2FkZWQ7XG4gICAgLy8gcHJvZ3Jlc3MgZXZlbnRcbiAgICB0aGlzLmVtaXQoICdwcm9ncmVzcycsIHRoaXMsIGltYWdlLCBlbGVtICk7XG4gICAgaWYgKCB0aGlzLmpxRGVmZXJyZWQgJiYgdGhpcy5qcURlZmVycmVkLm5vdGlmeSApIHtcbiAgICAgIHRoaXMuanFEZWZlcnJlZC5ub3RpZnkoIHRoaXMsIGltYWdlICk7XG4gICAgfVxuICAgIC8vIGNoZWNrIGlmIGNvbXBsZXRlZFxuICAgIGlmICggdGhpcy5wcm9ncmVzc2VkQ291bnQgPT0gdGhpcy5pbWFnZXMubGVuZ3RoICkge1xuICAgICAgdGhpcy5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIGlmICggdGhpcy5vcHRpb25zLmRlYnVnICYmIGNvbnNvbGUgKSB7XG4gICAgICBjb25zb2xlLmxvZyggJ3Byb2dyZXNzOiAnICsgbWVzc2FnZSwgaW1hZ2UsIGVsZW0gKTtcbiAgICB9XG4gIH07XG5cbiAgSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBldmVudE5hbWUgPSB0aGlzLmhhc0FueUJyb2tlbiA/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+IDApIHtcblx0XHR2YXIgc3RvcmVEYXRhID0gSlNPTi5wYXJzZSgkc3RvcmVEYXRhLmZpcnN0KCkuYXR0cignc3RvcmUtZGF0YScpKTtcblx0XHRpZiAoc3RvcmVEYXRhICYmIHN0b3JlRGF0YS5sb2NhdGlvbiAmJiBzdG9yZURhdGEubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yICYmIHN0b3JlRGF0YS5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV9yYWRpdXMpIHtcblx0XHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSBzdG9yZURhdGEubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfcmFkaXVzO1xuXHRcdH1cblx0fVxuXG5cdCQoJy5hZGQtdG8tY2FydC1vcHRpb25zLXRvb2x0aXAnKS5maW5kKCcuZGVsaXZlcnktcmFkaXVzJykuaHRtbChsb2NhbERlbGl2ZXJ5UmFkaXVzKTtcblx0dG9vbHRpcC5pbml0KHtcblx0XHRpdGVtczogJy5hZGQtdG8tY2FydC1vcHRpb25zLXRvb2x0aXAnLFxuXHRcdHRvb2x0aXBDbGFzczogJ2FkZC10by1jYXJ0LW9wdGlvbnMtdG9vbHRpcCdcblx0fSwgJCgnLmFkZC10by1jYXJ0LW9wdGlvbnMtdG9vbHRpcCcpKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIEdlb2xvY2F0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9HZW9sb2NhdGlvbi9HZW9sb2NhdGlvbkhlbHBlcicpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG52YXIgWmlwQ29kZVRvU3RhdGVNYXAgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2RhdGEvWmlwQ29kZVRvU3RhdGVNYXAuanNvbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaDtcblxuZnVuY3Rpb24gQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoKCkge1xuXHR0aGlzLm9wdGlvbnM7XG5cdHRoaXMudmFsaWRhdG9yO1xuXHR0aGlzLmxvYWRlZDtcblx0dGhpcy5kYXRhQnVmZmVyO1xuXG5cdHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGU7XG5cdHRoaXMucmVzdWx0SXRlbVRlbXBsYXRlO1xuXHR0aGlzLmxvY2FsRGVsaXZlcnlEZWNvcmF0b3I7XG5cblx0dGhpcy4kY29udGFpbmVyO1xuXHR0aGlzLiRmb3JtO1xuXHR0aGlzLiRyZXN1bHQ7XG5cdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGU7XG5cdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uO1xuXHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lcjtcblx0dGhpcy4kYm9waXNCdXR0b247XG5cdHRoaXMuJGVycm9yTWVzc2FnZTtcblx0dGhpcy4kaW5wdXRUb29sdGlwO1xuXG5cdHRoaXMuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKCRjb250YWluZXJQYXJhbWV0ZXIsIG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0aWYgKCF0aGlzLmRhdGFCdWZmZXIpIHtcblx0XHRcdHRoaXMuZGF0YUJ1ZmZlciA9IHt9O1xuXHRcdH1cblx0XHRpZiAoIXRoaXMubG9hZGVkKSB7XG5cdFx0XHR0aGlzLmxvYWRlZCA9IHt9O1xuXHRcdH1cblx0XHR0aGlzLm9wdGlvbnMgPSAkLmV4dGVuZCh7XG5cdFx0XHRzdWNjZXNzQ2FsbGJhY2s6IG51bGwsXG5cdFx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdFx0fSwgb3B0aW9uc1BhcmFtZXRlcik7XG5cblx0XHR0aGlzLnJlc3VsdENvbnRhaW5lclRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWNvbnRhaW5lci1hZGR0b2NhcnRvcHRpb25zJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRcdHRoaXMucmVzdWx0SXRlbVRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWl0ZW0tYWRkdG9jYXJ0b3B0aW9ucycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0XHR0aGlzLmxvY2FsRGVsaXZlcnlEZWNvcmF0b3IgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1sb2NhbGRlbGl2ZXJ5LWRlY29yYXRvcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lciA9ICRjb250YWluZXJQYXJhbWV0ZXI7XG5cdFx0dGhpcy4kZm9ybSA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCdmb3JtJyk7XG5cdFx0dGhpcy4kcmVzdWx0ID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQnKTtcblx0XHR0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlID0gdGhpcy4kZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxDb2RlXCJdJyk7XG5cdFx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b24gPSB0aGlzLiRjb250YWluZXIuZmluZCgnLmJ0bi5zdG9yZS1zZWFyY2gnKTtcblx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lciA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLXN0b3JlLXNlYXJjaC1jb250YWluZXInKTtcblx0XHR0aGlzLiRib3Bpc0J1dHRvbiA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLmJvcGlzJyk7XG5cdFx0dGhpcy4kZXJyb3JNZXNzYWdlID0gdGhpcy4kZm9ybS5maW5kKCdzcGFuLmVycm9yJyk7XG5cdFx0dGhpcy4kaW5wdXRUb29sdGlwID0gdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5wYXJlbnQoKTtcblx0XHR0aGlzLiRjb250YWluZXIuZmluZCgnLmJ0bi5zdG9yZS1zZWxlY3QnKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0XHQkKCdodG1sJykuYWRkQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cblx0XHRpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5ICYmIHRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5LlJhZGl1cykge1xuXHRcdFx0dGhpcy4kY29udGFpbmVyLmZpbmQoJy5kZWxpdmVyeS1yYWRpdXMnKS5odG1sKHRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5LlJhZGl1cyk7XG5cdFx0fVxuXHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdFx0dGhpcy52YWxpZGF0b3IgPSB0aGlzLiRmb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnemlwQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVaaXBDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdFx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlppcENvZGUpO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLmFkZENsYXNzKCdzaG93Jyk7XG5cdFx0aWYgKHRoaXMuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScpID09PSAnZm9ybScgJiYgdGhpcy52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgIXRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcblx0XHR9XG5cblx0XHR0aGlzLiRmb3JtLm9mZignY2xpY2suYXBwbHknKS5vbignY2xpY2suYXBwbHknLCAnLmJ0bi5zdG9yZS1zZWFyY2g6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lci5sb2FkaW5nKCk7XG5cdFx0XHRzZWxmLnNlYXJjaCgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suYXBwbHknKS5vbignY2xpY2suYXBwbHknLCAnLmJ0bi5ib3Bpczpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0dmFyIHNlbGVjdGVkTG9jYXRpb24gPSBzZWxmLmRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddWyQoJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdOmNoZWNrZWQnKS52YWwoKV07XG5cdFx0XHRpZiAoc2VsZWN0ZWRMb2NhdGlvbikge1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCB7IGJvcGlzOiB0cnVlLCBzaGlwcGluZ09wdGlvbjogJ3BpY2t1cCcsIGNoYW5uZWw6IHNlbGYub3B0aW9ucy5DaGFubmVsIH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuQm9waXMuQWRkVG9DYXJ0JywgeyBjaGFubmVsOiBzZWxmLm9wdGlvbnMuQ2hhbm5lbCB9KTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXlkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJykub24oJ2tleWRvd24uQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGlmIChzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLmxlbmd0aCA9PSA1ICYmIHBhcnNlSW50KGV2ZW50LmtleSwgMTApID09IGV2ZW50LmtleSAmJiAhd2luZG93LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCkpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbignY2hhbmdlLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRpZiAoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKS5sZW5ndGggPiA1KSB7XG5cdFx0XHRcdHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkuc3Vic3RyKDAsIDUpKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXl1cC5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaywgY2hhbmdlLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJykub24oJ2tleXVwLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrLCBjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHRpZiAoc2VsZi4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJykge1xuXHRcdFx0XHRpZiAoc2VsZi52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgIXNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHRcdFx0c2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uYWRkQ2xhc3MoJ3JlYWR5Jyk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIXNlbGYudmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmIHNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHRcdFx0c2VsZi4kc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQ2xhc3MoJ3JlYWR5Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKHNlbGYuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScpID09PSAncmVzdWx0Jykge1xuXHRcdFx0XHRzZWxmLiRjb250YWluZXIuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuXHRcdFx0XHRzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgnJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ21vdXNlZG93bi5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DbGVhcicpLm9uKCdtb3VzZWRvd24uQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2xlYXInLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGlmIChzZWxmLnZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdChzZWxmLiRjb250YWluZXIpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdHNlbGYudmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuXHRcdFx0XHRzZWxmLiRlcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0JChkb2N1bWVudCkub2ZmKCdCb3Bpcy5TdG9yZVNlYXJjaC5SZXNldCcpLm9uKCdCb3Bpcy5TdG9yZVNlYXJjaC5SZXNldCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0c2VsZi5yZXNldCgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suQm9waXNTdG9yZVNlYXJjaC5TZWxlY3Rpb24nKS5vbignY2xpY2suQm9waXNTdG9yZVNlYXJjaC5TZWxlY3Rpb24nLCAnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciBib3Bpc1N0b3JlID0gJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXG5cdFx0XHRpZiAoIXNlbGYuJGJvcGlzQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHRcdHNlbGYuJGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHRcdFx0fVxuXG5cdFx0XHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblxuXHRcdFx0aWYgKGJvcGlzU3RvcmUpIHtcblx0XHRcdFx0c2VsZi4kYm9waXNCdXR0b24uYXR0cignc3RhdGUnLCAncGlja3VwJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWxmLiRib3Bpc0J1dHRvbi5hdHRyKCdzdGF0ZScsICdzaGlwJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR0aGlzLiRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLk5vUmVzdWx0c1NoaXAnKS5vbignY2xpY2suQm9waXNTdG9yZVNlYXJjaC5Ob1Jlc3VsdHNTaGlwJywgJy5idG4ubm8tcmVzdWx0cy1zaGlwJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHRzZWxmLmNsb3NlKCk7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCB7IGNoYW5uZWw6IHNlbGYub3B0aW9ucy5DaGFubmVsIH0pO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suQm9waXNBZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2guU2VsZWN0Jykub24oJ2NsaWNrLkJvcGlzQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoLlNlbGVjdCcsICdsaVtzdG9yZV0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHQkdGhpcy5maW5kKCdpbnB1dCcpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHRcdHNlbGYuJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlbGVjdCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suQm9waXNBZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2guQ29uZmlybScpLm9uKCdjbGljay5Cb3Bpc0FkZFRvQ2FydE9wdGlvbnNTdG9yZVNlYXJjaC5Db25maXJtJywgJy5idG4uc3RvcmUtc2VsZWN0Om5vdCguZGlzYWJsZWQpJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHR2YXIgc3RvcmUgPSAkKHRoaXMpLmNsb3Nlc3QoJ2lucHV0W3N0b3JlXScpLmF0dHIoJ3N0b3JlJyk7XG5cdFx0XHR2YXIgc3RvcmUgPSBzZWxmLiRjb250YWluZXIuZmluZCgnaW5wdXRbbmFtZT1cImJvcGlzLXN0b3JlXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0XHRcdHZhciBldmVudE5hbWUgPSAnQm9waXMuU3RvcmVTZWFyY2guU2VsZWN0JztcblxuXHRcdFx0aWYgKHNlbGYub3B0aW9ucy5FdmVudHMgJiYgc2VsZi5vcHRpb25zLkV2ZW50cy5TZWxlY3RTdG9yZSkge1xuXHRcdFx0XHRldmVudE5hbWUgPSBzZWxmLm9wdGlvbnMuRXZlbnRzLlNlbGVjdFN0b3JlO1xuXHRcdFx0XHRzdG9yZSA9IHNlbGYuZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ11bc3RvcmVdO1xuXHRcdFx0fVxuXHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcihldmVudE5hbWUsIHN0b3JlKTtcblx0XHRcdHNlbGYuY2xvc2UoKTtcblx0XHR9KTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvcGlzQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoLkNsb3NlJykub24oJ2NsaWNrLkJvcGlzQWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoLkNsb3NlJywgJy5jbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdzY3JvbGwtbG9jaycpO1xuXHRcdFx0c2VsZi5jbG9zZSgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suVXNlTXlMb2NhdGlvbicpLm9uKCdjbGljay5Vc2VNeUxvY2F0aW9uJywgJy51c2UtbXktbG9jYXRpb24nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcblx0XHRcdEdlb2xvY2F0aW9uSGVscGVyLkdldFBvc2l0aW9uKCkudGhlbihmdW5jdGlvbihwb3NpdGlvbikge1xuXHRcdFx0XHRzZWxmLnNlYXJjaCh0cnVlLCBwb3NpdGlvbik7XG5cdFx0XHR9KS5jYXRjaCgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5yZXNldCgpO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicgJiYgdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKSkge1xuXHRcdFx0dGhpcy5zZWFyY2goKTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG5cdFx0dGhpcy4kY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsICcwJyk7XG5cdFx0dGhpcy4kcmVzdWx0Lmh0bWwoJycpO1xuXHR9XG5cblx0dGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuXHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnc2Nyb2xsLWxvY2snKTtcblx0XHRpZiAodGhpcy5vcHRpb25zLkZ1bmN0aW9ucyAmJiB0aGlzLm9wdGlvbnMuRnVuY3Rpb25zLkNsb3NlKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuRnVuY3Rpb25zLkNsb3NlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5ib3Bpcy1hZGQtdG8tY2FydC1zdG9yZS1zZWFyY2gtY29udGFpbmVyJykucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLnNlYXJjaCA9IGZ1bmN0aW9uKGlzQnlHZW9sb2NhdGlvbiwgcG9zaXRpb24pIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dmFyIGNvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHRcdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHR2YXIgd2lkdGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLndpZHRoLndpZHRoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLlN0b3JlVUlWZXJzaW9uICE9ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRpZiAoIWlzU2l6ZVNlbGVjdGVkICYmICFjb2xvclNlbGVjdGVkKSB7XG5cdFx0XHRcdHRoaXMuJGVycm9yTWVzc2FnZS5odG1sKCdQbGVhc2Ugc2VsZWN0IGEgc2l6ZSBhbmQgY29sb3IuJykuc2hvdygpO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCFpc1NpemVTZWxlY3RlZCkge1xuXHRcdFx0XHR0aGlzLiRlcnJvck1lc3NhZ2UuaHRtbCgnUGxlYXNlIHNlbGVjdCBhIHNpemUuJykuc2hvdygpO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCFjb2xvclNlbGVjdGVkKSB7XG5cdFx0XHRcdHRoaXMuJGVycm9yTWVzc2FnZS5odG1sKCdQbGVhc2Ugc2VsZWN0IGEgY29sb3IuJykuc2hvdygpO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuJGVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cdFx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblxuXHRcdHZhciBnZW9sb2NhdGlvblBvc2l0aW9uO1xuXHRcdGlmIChpc0J5R2VvbG9jYXRpb24gJiYgcG9zaXRpb24gJiYgcG9zaXRpb24uY29vcmRzKSB7XG5cdFx0XHRnZW9sb2NhdGlvblBvc2l0aW9uID0ge1xuXHRcdFx0XHRjb29yZHM6IHtcblx0XHRcdFx0XHRhY2N1cmFjeTogcG9zaXRpb24uY29vcmRzLmFjY3VyYWN5LFxuXHRcdFx0XHRcdGxhdGl0dWRlOiBwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGUsXG5cdFx0XHRcdFx0bG9uZ2l0dWRlOiBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRpbWVzdGFtcDogcG9zaXRpb24udGltZXN0YW1wXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIGlzVmFsaWQgPSBpc0J5R2VvbG9jYXRpb24gfHwgdGhpcy52YWxpZGF0b3IudmFsaWQoKTtcblx0XHRpZiAoVXJscyAmJiBVcmxzLkJvcGlzLkdldFN0b3JlSW52ZW50b3J5Rm9yUHJvZHVjdEZvclBvc3RhbENvZGUgJiYgaXNWYWxpZCkge1xuXHRcdFx0dGhpcy4kcmVzdWx0Lmh0bWwoJycpO1xuXHRcdFx0dGhpcy4kcmVzdWx0LmxvYWRpbmcoKTtcblxuXHRcdFx0c2VsZi5sb2FkZWRbJ0xvY2F0aW9uRGF0YSddID0gZmFsc2U7XG5cdFx0XHRzZWxmLmxvYWRlZFsnSW52ZW50b3J5RGF0YSddID0gZmFsc2U7XG5cdFx0XHRzZWxmLmRhdGFCdWZmZXJbJ0xvY2F0aW9uRGF0YSddID0gbnVsbDtcblx0XHRcdHNlbGYuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddID0gbnVsbDtcblxuXHRcdFx0dmFyIGdldExvY2F0aW9uVXJsO1xuXHRcdFx0dmFyIGdldExvY2F0aW9uRGF0YTtcblx0XHRcdGlmIChpc0J5R2VvbG9jYXRpb24pIHtcblx0XHRcdFx0Z2V0TG9jYXRpb25VcmwgPSBVcmxzLkJvcGlzLkdldExvY2F0aW9uc0Zvckdlb2xvY2F0aW9uUG9zaXRpb247XG5cdFx0XHRcdGdldExvY2F0aW9uRGF0YSA9IHtcblx0XHRcdFx0XHRDaGFubmVsOiB0aGlzLm9wdGlvbnMuQ2hhbm5lbCxcblx0XHRcdFx0XHRTb3VyY2U6IHRoaXMub3B0aW9ucy5Tb3VyY2UsXG5cdFx0XHRcdFx0R2VvbG9jYXRpb25Qb3NpdGlvbjogZ2VvbG9jYXRpb25Qb3NpdGlvblxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRnZXRMb2NhdGlvblVybCA9IFVybHMuQm9waXMuR2V0TG9jYXRpb25zRm9yUG9zdGFsQ29kZTtcblx0XHRcdFx0Z2V0TG9jYXRpb25EYXRhID0ge1xuXHRcdFx0XHRcdENoYW5uZWw6IHRoaXMub3B0aW9ucy5DaGFubmVsLFxuXHRcdFx0XHRcdFNvdXJjZTogdGhpcy5vcHRpb25zLlNvdXJjZSxcblx0XHRcdFx0XHRQb3N0YWxDb2RlOiB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0XHR1cmw6IGdldExvY2F0aW9uVXJsLFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShnZXRMb2NhdGlvbkRhdGEpLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0dmFyIGxvY2F0aW9uRGF0YTtcblx0XHRcdFx0XHRpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uRGF0YSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhO1xuXG5cdFx0XHRcdFx0XHRpZiAobG9jYXRpb25EYXRhICYmIGxvY2F0aW9uRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdGxvY2F0aW9uRGF0YSA9IGxvY2F0aW9uRGF0YS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGxlZnQuZGlzdGFuY2UgLSByaWdodC5kaXN0YW5jZTtcblx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyWydMb2NhdGlvbkRhdGEnXSA9IGxvY2F0aW9uRGF0YTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzZWxmLmxvYWRlZFsnTG9jYXRpb25EYXRhJ10gPSB0cnVlO1xuXHRcdFx0XHRcdHNlbGYucmVuZGVyKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoc2VsZi5vcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcblx0XHRcdFx0XHRcdHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0dmFyIHByb2R1Y3RJZCA9ICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJwaWRcIl0nKS52YWwoKTtcblx0XHRcdHZhciBnZXRTdG9yZUludmVudG9yeVVybDtcblx0XHRcdHZhciBnZXRTdG9yZUludmVudG9yeURhdGE7XG5cdFx0XHRpZiAoaXNCeUdlb2xvY2F0aW9uKSB7XG5cdFx0XHRcdGdldFN0b3JlSW52ZW50b3J5VXJsID0gVXJscy5Cb3Bpcy5HZXRTdG9yZUludmVudG9yeUZvclByb2R1Y3RGb3JHZW9sb2NhdGlvblBvc2l0aW9uO1xuXHRcdFx0XHRnZXRTdG9yZUludmVudG9yeURhdGEgPSB7XG5cdFx0XHRcdFx0Q2hhbm5lbDogdGhpcy5vcHRpb25zLkNoYW5uZWwsXG5cdFx0XHRcdFx0U291cmNlOiB0aGlzLm9wdGlvbnMuU291cmNlLFxuXHRcdFx0XHRcdFByb2R1Y3RJZDogcHJvZHVjdElkLFxuXHRcdFx0XHRcdEdlb2xvY2F0aW9uUG9zaXRpb246IGdlb2xvY2F0aW9uUG9zaXRpb25cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Z2V0U3RvcmVJbnZlbnRvcnlVcmwgPSBVcmxzLkJvcGlzLkdldFN0b3JlSW52ZW50b3J5Rm9yUHJvZHVjdEZvclBvc3RhbENvZGU7XG5cdFx0XHRcdGdldFN0b3JlSW52ZW50b3J5RGF0YSA9IHtcblx0XHRcdFx0XHRDaGFubmVsOiB0aGlzLm9wdGlvbnMuQ2hhbm5lbCxcblx0XHRcdFx0XHRTb3VyY2U6IHRoaXMub3B0aW9ucy5Tb3VyY2UsXG5cdFx0XHRcdFx0UHJvZHVjdElkOiBwcm9kdWN0SWQsXG5cdFx0XHRcdFx0UG9zdGFsQ29kZTogdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKSxcblx0XHRcdFx0XHRTYXZlUG9zdGFsQ29kZTogdHJ1ZVxuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiBnZXRTdG9yZUludmVudG9yeVVybCxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoZ2V0U3RvcmVJbnZlbnRvcnlEYXRhKSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEuU2VydmljZVN1Y2Nlc3NmdWxseUNhbGxlZCAmJiBkYXRhLklucXVpcnlSZXN1bHQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGEgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGEubGVuZ3RoID4gMCAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YVswXS5pbnZlbnRvcnlfc3VwcGxpZXMpIHtcblx0XHRcdFx0XHRcdHZhciBpbnF1aXJ5UmVzdWx0ID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAoaW5xdWlyeVJlc3VsdCAmJiBpbnF1aXJ5UmVzdWx0Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyWydJbnZlbnRvcnlEYXRhJ10gPSBbXTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGZvciAodmFyIGludmVudG9yeVJlY29yZEVsZW1lbnQgaW4gaW5xdWlyeVJlc3VsdCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBpbnZlbnRvcnlSZWNvcmQgPSBpbnF1aXJ5UmVzdWx0W2ludmVudG9yeVJlY29yZEVsZW1lbnRdO1xuXHRcdFx0XHRcdFx0XHRcdHNlbGYuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSA9IGludmVudG9yeVJlY29yZDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHNlbGYubG9hZGVkWydJbnZlbnRvcnlEYXRhJ10gPSB0cnVlO1xuXHRcdFx0XHRcdHNlbGYucmVuZGVyKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoc2VsZi4kcmVzdWx0LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRcdFx0c2VsZi4kcmVzdWx0LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoc2VsZi5vcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcblx0XHRcdFx0XHRcdHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLnJlbmRlciA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICh0aGlzLmxvYWRlZFsnTG9jYXRpb25EYXRhJ10gJiYgdGhpcy5sb2FkZWRbJ0ludmVudG9yeURhdGEnXSkge1xuXHRcdFx0aWYgKHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbkNvbnRhaW5lci5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy4kcmVzdWx0LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHR0aGlzLiRyZXN1bHQubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLiRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG5cdFx0XHRpZiAodGhpcy5kYXRhQnVmZmVyWydMb2NhdGlvbkRhdGEnXSAmJiB0aGlzLmRhdGFCdWZmZXJbJ0xvY2F0aW9uRGF0YSddLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXSA9IFtdO1xuXG5cdFx0XHRcdHZhciAkYWRkVG9DYXJ0T3B0aW9ucyA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zJyk7XG5cdFx0XHRcdHZhciBxdWFudGl0eVNvdXJjZVR5cGU7XG5cdFx0XHRcdHZhciBkcm9wc2hpcExlYWREYXlzO1xuXHRcdFx0XHRpZiAoJGFkZFRvQ2FydE9wdGlvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZSA9ICRhZGRUb0NhcnRPcHRpb25zLmF0dHIoJ3F1YW50aXR5LXNvdXJjZS10eXBlJyk7XG5cdFx0XHRcdFx0ZHJvcHNoaXBMZWFkRGF5cyA9IHBhcnNlSW50KCRhZGRUb0NhcnRPcHRpb25zLmF0dHIoJ2Ryb3BzaGlwLWxlYWQtZGF5cycpLCAxMCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIHF1YW50aXR5U291cmNlVHlwZU9mZnNldCA9IDA7XG5cdFx0XHRcdGlmIChxdWFudGl0eVNvdXJjZVR5cGUgPT0gJ1dIUycpIHtcblx0XHRcdFx0XHRxdWFudGl0eVNvdXJjZVR5cGVPZmZzZXQgPSAtMTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBzdG9yZUxpc3RIdG1sID0gJyc7XG5cdFx0XHRcdHZhciBpc1N0b3JlU2VsZWN0ZWQgPSBmYWxzZTtcblx0XHRcdFx0dmFyIHN0YXR1cyA9ICcnO1xuXHRcdFx0XHR2YXIgc3RhdHVzRGlzcGxheSA9ICcnO1xuXHRcdFx0XHR2YXIgaXNMb2NhbERlbGl2ZXJ5U3VwcG9ydGVkID0gZmFsc2U7XG5cdFx0XHRcdHZhciBsb2NhbERlbGl2ZXJ5SHRtbCA9ICcnO1xuXHRcdFx0XHR2YXIgc3RvcmVzRGlzcGxheWVkQ291bnQgPSAwO1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZTtcblx0XHRcdFx0dmFyIHF1YW50aXR5QXZhaWxhYmxlID0gZmFsc2U7XG5cdFx0XHRcdGZvciAodmFyIGxvY2F0aW9uS2V5IGluIHRoaXMuZGF0YUJ1ZmZlclsnTG9jYXRpb25EYXRhJ10pIHtcblx0XHRcdFx0XHR2YXIgbG9jYXRpb24gPSB0aGlzLmRhdGFCdWZmZXJbJ0xvY2F0aW9uRGF0YSddW2xvY2F0aW9uS2V5XTtcblxuXHRcdFx0XHRcdHZhciBpbnZlbnRvcnlSZWNvcmQ7XG5cdFx0XHRcdFx0aWYgKHRoaXMuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddICYmIHRoaXMuZGF0YUJ1ZmZlclsnSW52ZW50b3J5RGF0YSddW2xvY2F0aW9uLmNvZGVdKSB7XG5cdFx0XHRcdFx0XHRpbnZlbnRvcnlSZWNvcmQgPSB0aGlzLmRhdGFCdWZmZXJbJ0ludmVudG9yeURhdGEnXVtsb2NhdGlvbi5jb2RlXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzdGF0dXMgPSAndW5hdmFpbGFibGUnO1xuXHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnVW5hdmFpbGFibGUnO1xuXHRcdFx0XHRcdGlzTG9jYWxEZWxpdmVyeVN1cHBvcnRlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdGxvY2FsRGVsaXZlcnlIdG1sID0gJyc7XG5cdFx0XHRcdFx0aWYgKGludmVudG9yeVJlY29yZCAmJiBpbnZlbnRvcnlSZWNvcmQuZGV0YWlsICYmIGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHkgPiAwICYmICF0aGlzLmRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2ludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlXSAmJiAoIXRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSB8fCAoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X2VuYWJsZWQgJiYgdGhpcy5pc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKGludmVudG9yeVJlY29yZC5sb2NhdGlvbikpKSkge1xuXHRcdFx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuU2VsZWN0ZWRMb2NhdGlvbnMgPT0gaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmNvZGUpIHtcblx0XHRcdFx0XHRcdFx0aXNTdG9yZVNlbGVjdGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9J2NoZWNrZWQnO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9ICcnO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuRW5hYmxlZCAmJiB0aGlzLmlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uKSAmJiBpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfZW5hYmxlZCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhbERlbGl2ZXJ5SHRtbCA9IHRoaXMubG9jYWxEZWxpdmVyeURlY29yYXRvcigpO1xuXHRcdFx0XHRcdFx0XHRpc0xvY2FsRGVsaXZlcnlTdXBwb3J0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoaXNMb2NhbERlbGl2ZXJ5U3VwcG9ydGVkICYmIGludmVudG9yeVJlY29yZC5kZXRhaWwgJiYgaW52ZW50b3J5UmVjb3JkLmRldGFpbC5xdWFudGl0eSA+IDApIHtcblx0XHRcdFx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnU2FtZS1EYXkgRGVsaXZlcnk8YnIvPkF2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gJ2F2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIXRoaXMub3B0aW9ucy5Mb2NhbERlbGl2ZXJ5T25seSkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIHN0YXR1c0Rpc3BsYXkgPSAnUGlja3VwICYgU2FtZS1EYXk8YnIvPkRlbGl2ZXJ5IEF2YWlsYWJsZSc7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzRGlzcGxheSA9ICdBdmFpbGFibGUgVG9kYXknO1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1cyA9ICdhdmFpbGFibGUnO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCF0aGlzLm9wdGlvbnMuTG9jYWxEZWxpdmVyeU9ubHkgJiYgaW52ZW50b3J5UmVjb3JkLmRldGFpbCAmJiBpbnZlbnRvcnlSZWNvcmQuZGV0YWlsLnF1YW50aXR5ID4gMCkge1xuXHRcdFx0XHRcdFx0XHRzdGF0dXNEaXNwbGF5ID0gJ0F2YWlsYWJsZSBUb2RheSc7XG5cdFx0XHRcdFx0XHRcdHN0YXR1cyA9ICdhdmFpbGFibGUnO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRxdWFudGl0eUF2YWlsYWJsZSA9IGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICghdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnlPbmx5ICYmIHBhZ2VDb250ZXh0LnNpdGUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMpIHtcblx0XHRcdFx0XHRcdHN0YXR1c0Rpc3BsYXkgPSAnQXJyaXZlcyBpbiAnICsgKHRoaXMub3B0aW9ucy5TaGlwcGluZ01ldGhvZHMuU2hpcFRvU3RvcmUuRGF5UmFuZ2VTdGFydCArIGRyb3BzaGlwTGVhZERheXMgKyBxdWFudGl0eVNvdXJjZVR5cGVPZmZzZXQpICsgJy0nICsgKHRoaXMub3B0aW9ucy5TaGlwcGluZ01ldGhvZHMuU2hpcFRvU3RvcmUuRGF5UmFuZ2VFbmQgKyBkcm9wc2hpcExlYWREYXlzICsgcXVhbnRpdHlTb3VyY2VUeXBlT2Zmc2V0KSArICc8YnIvPkJ1c2luZXNzIERheXMnO1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gJ2F2YWlsYWJsZSc7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHF1YW50aXR5QXZhaWxhYmxlID0gZmFsc2Vcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgbG9jYXRpb25OYW1lO1xuXHRcdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbk5hbWUgPSAnPHN0cm9uZz4nICsgbG9jYXRpb24uU3RvcmVJbmZvLk5hbWUgKyAnIC0gJyArIGxvY2F0aW9uLlN0b3JlSW5mby5TdG9yZUlkICsgJzwvc3Ryb25nPic7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uTmFtZSA9ICc8c3Ryb25nPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uTmFtZSArICc8L3N0cm9uZz4nO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5BZ2VudFN0b3JlSUQgPT0gbG9jYXRpb24uY29kZSkge1xuXHRcdFx0XHRcdFx0bG9jYXRpb25OYW1lICs9ICc8YnIvPihZb3VyIFN0b3JlKSc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0c3RvcmVMaXN0SHRtbCArPSB0aGlzLnJlc3VsdEl0ZW1UZW1wbGF0ZSh7XG5cdFx0XHRcdFx0XHRTdG9yZUlkOiBsb2NhdGlvbi5jb2RlLFxuXHRcdFx0XHRcdFx0UXVhbnRpdHlBdmFpbGFibGU6IHF1YW50aXR5QXZhaWxhYmxlLFxuXHRcdFx0XHRcdFx0SHRtbDogJzxzcGFuIGNsYXNzPVwic3RvcmUtbmFtZVwiPicgKyBsb2NhdGlvbk5hbWUgKyAnPC9zcGFuPjxici8+JyArIGxvY2F0aW9uLlN0b3JlSW5mby5BZGRyZXNzMSArICc8YnIvPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uQ2l0eSArICcsICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uU3RhdGVDb2RlUGFyc2VkICsgJywgJyArIGxvY2F0aW9uLlN0b3JlSW5mby5Qb3N0YWxDb2RlLnN1YnN0cigwLCA1KSxcblx0XHRcdFx0XHRcdFNlbGVjdGVkOiBzZWxlY3RlZFN0b3JlQXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0TG9jYWxEZWxpdmVyeTogbG9jYWxEZWxpdmVyeUh0bWwsXG5cdFx0XHRcdFx0XHRTdGF0dXM6IHN0YXR1cyxcblx0XHRcdFx0XHRcdFN0YXR1c0Rpc3BsYXk6IHN0YXR1c0Rpc3BsYXlcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdHN0b3Jlc0Rpc3BsYXllZENvdW50ICs9IDE7XG5cdFx0XHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtsb2NhdGlvbi5jb2RlXSA9IGludmVudG9yeVJlY29yZCA/IGludmVudG9yeVJlY29yZCA6IHsgbG9jYXRpb246IGxvY2F0aW9uIH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgcmVzdWx0SHRtbCA9IHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGUoe1xuXHRcdFx0XHRcdEh0bWw6IHN0b3JlTGlzdEh0bWxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0aWYgKGlzU3RvcmVTZWxlY3RlZCkge1xuXHRcdFx0XHRcdHRoaXMuJGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHN0b3Jlc0Rpc3BsYXllZENvdW50ID4gMCkge1xuXHRcdFx0XHRcdHRoaXMuJHJlc3VsdC5odG1sKHJlc3VsdEh0bWwpO1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCBzdG9yZXNEaXNwbGF5ZWRDb3VudCk7XG5cdFx0XHRcdFx0dGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQtY29udGFpbmVyJykuc2hvdygpO1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5maW5kKCcucmVzdWx0LWVtcHR5JykuaGlkZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCAwKTtcblx0XHRcdFx0XHR0aGlzLiRjb250YWluZXIuZmluZCgnLnJlc3VsdC1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHRcdFx0dGhpcy4kY29udGFpbmVyLmZpbmQoJy5yZXN1bHQtZW1wdHknKS5zaG93KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0XHRcdGl0ZW1zOiAnLnRvb2x0aXAnXG5cdFx0XHRcdH0sIHRoaXMuJHJlc3VsdCk7XG5cblx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2spIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuc3VjY2Vzc0NhbGxiYWNrKGlucXVpcnlSZXN1bHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBidXR0b24nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0dGhpcy5yZXNldCgpO1x0XHRcdFx0XHRcdFxuXHRcdFx0XHR0aGlzLiRyZXN1bHQuY2xvc2VzdCgnLnJlc3VsdC1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHRcdHRoaXMuJGNvbnRhaW5lci5maW5kKCcucmVzdWx0LWVtcHR5Jykuc2hvdygpO1xuXG5cdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR0aGlzLmlzTG9jYXRpb25JbkxvY2FsRGVsaXZlcnlSYWRpdXMgPSBmdW5jdGlvbihsb2NhdGlvbikge1xuXHRcdHZhciBsb2NhbERlbGl2ZXJ5UmFkaXVzO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkpIHtcblx0XHRcdGlmIChsb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgJiYgbG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yID09ICdHb0xvY2FsJykge1xuXHRcdFx0XHRsb2NhbERlbGl2ZXJ5UmFkaXVzID0gdGhpcy5vcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzRm9yR29Mb2NhbDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSB0aGlzLm9wdGlvbnMuTG9jYWxEZWxpdmVyeS5SYWRpdXNGb3JSb2FkaWU7XG5cdFx0XHR9XG5cdFx0fVx0XG5cblx0XHRpZiAobG9jYWxEZWxpdmVyeVJhZGl1cyAmJiBsb2NhdGlvbiAmJiBsb2NhdGlvbi5kaXN0YW5jZSAmJiBsb2NhbERlbGl2ZXJ5UmFkaXVzID49IGxvY2F0aW9uLmRpc3RhbmNlKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoID0gcmVxdWlyZSgnLi9BZGRUb0NhcnRPcHRpb25zU3RvcmVTZWFyY2gnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKTtcbnZhciBWYWxpZGF0aW9uU2V0dGluZ3MgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5TZXR0aW5ncztcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFppcENvZGVUb1N0YXRlTWFwID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9kYXRhL1ppcENvZGVUb1N0YXRlTWFwLmpzb24nKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcbmV4cG9ydHMucmVtb3ZlID0gcmVtb3ZlO1xuXG52YXIgb3B0aW9ucztcbnZhciBvcHRpb25zTG9jYWxEZWxpdmVyeTtcbnZhciB2YWxpZGF0b3I7XG52YXIgZGF0YUJ1ZmZlcjtcbnZhciBsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2g7XG52YXIgbG9jYWxEZWxpdmVyeVJhZGl1cztcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyLCBzZWxlY3RlZExvY2F0aW9uLCBsb2NhbERlbGl2ZXJ5Rm9ybURhdGEpIHtcblx0ZGF0YUJ1ZmZlciA9IHt9O1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXG5cdGlmIChzZWxlY3RlZExvY2F0aW9uICYmIHNlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24gJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5sb2NhbF9kZWxpdmVyeV92ZW5kb3IgPT0gJ0dvTG9jYWwnKSB7XG5cdFx0bG9jYWxEZWxpdmVyeVJhZGl1cyA9IG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5SYWRpdXNGb3JHb0xvY2FsO1xuXHR9IGVsc2UgaWYgKHNlbGVjdGVkTG9jYXRpb24gJiYgc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbiAmJiBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X3ZlbmRvciAmJiBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X3ZlbmRvciA9PSAnUm9hZGllJykge1xuXHRcdGxvY2FsRGVsaXZlcnlSYWRpdXMgPSBvcHRpb25zLkxvY2FsRGVsaXZlcnkuUmFkaXVzRm9yUm9hZGllO1xuXHR9XG5cblx0YnVpbGRBZGRyZXNzSHRtbEZvckxvY2F0aW9uKHNlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24pO1xuXHQkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5maW5kKCcuZGVsaXZlcnktcmFkaXVzJykuaHRtbChsb2NhbERlbGl2ZXJ5UmFkaXVzKTtcblx0dmFyICRvcHRpb25hbE1lc3NhZ2UgPSAkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMgaGVhZGVyIC5vcHRpb25hbC1tZXNzYWdlJyk7XG5cdFxuXHRpZiAob3B0aW9ucy5PcHRpb25hbE1lc3NhZ2UpIHtcblx0XHRpZiAoJG9wdGlvbmFsTWVzc2FnZS5sZW5ndGggPT0gMCkge1xuXHRcdFx0JCgnI2RpYWxvZy1ib3Bpcy1vcHRpb25zIGhlYWRlcicpLmFwcGVuZCgnPHAgY2xhc3M9XCJvcHRpb25hbC1tZXNzYWdlXCI+JyArIG9wdGlvbnMuT3B0aW9uYWxNZXNzYWdlICsgJzwvcD4nKVxuXHRcdH1cblx0fSBlbHNlIGlmICgkb3B0aW9uYWxNZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHQkb3B0aW9uYWxNZXNzYWdlLnJlbW92ZSgpO1xuXHR9XG5cdFxuXHRsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2ggPSBuZXcgYWRkVG9DYXJ0T3B0aW9uc1N0b3JlU2VhcmNoKCk7XG5cdG9wdGlvbnNMb2NhbERlbGl2ZXJ5ID0gT2JqZWN0LmFzc2lnbihvcHRpb25zLCB7XG5cdFx0TG9jYWxEZWxpdmVyeU9ubHk6IHRydWUsXG5cdFx0RXZlbnRzOiB7XG5cdFx0XHRTZWxlY3RTdG9yZTogJ0JvcGlzLlN0b3JlU2VhcmNoU2VsZWN0TG9jYWxEZWxpdmVyeSdcblx0XHR9LFxuXHRcdEZ1bmN0aW9uczoge1xuXHRcdFx0Q2xvc2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJy51aS13aWRnZXQtb3ZlcmxheScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnLmJvcGlzLWxvY2FsLWRlbGl2ZXJ5LXN0b3JlLXNlYXJjaC1jb250YWluZXInKS5yZW1vdmVDbGFzcygnc2hvdycpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRXZlbnQoJ3JvYWRpZUZvcm1EaXNwbGF5Jyk7XG5cdGRpYWxvZy5vcGVuKHtcblx0XHRodG1sOiAkKCcjZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5odG1sKCksXG5cdFx0b3B0aW9uczoge1xuXHRcdFx0ZGlhbG9nQ2xhc3M6ICdkaWFsb2ctYm9waXMtb3B0aW9ucycsXG5cdFx0XHR3aWR0aDogMzIwLFxuXHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdHJlc2l6YWJsZTogZmFsc2UsXG5cdFx0XHRvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0dmFyICRhZGRyZXNzRm9ybSA9ICR0aGlzLmZpbmQoJ2Zvcm0uYm9waXMtZGVsaXZlcnktYWRkcmVzcycpO1xuXHRcdFx0XHRhcHBlbmRDU1JGVG9rZW4oJGFkZHJlc3NGb3JtKTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEpIHtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5FbWFpbCB8fCAnJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwaG9uZVwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuUGhvbmUgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiZmlyc3ROYW1lXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5GaXJzdE5hbWUgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwibGFzdE5hbWVcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkxhc3ROYW1lIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFkZHJlc3MxXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5BZGRyZXNzMSB8fCAnJyk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhZGRyZXNzMlwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuQWRkcmVzczIgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWRkcmVzczNcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkFkZHJlc3MzIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImNpdHlcIl0nKS52YWwobG9jYWxEZWxpdmVyeUZvcm1EYXRhLkNpdHkgfHwgJycpO1xuXHRcdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbbmFtZT1cInN0YXRlQ29kZVwiXSBvcHRpb25bdmFsdWU9XCInICsgbG9jYWxEZWxpdmVyeUZvcm1EYXRhLlN0YXRlICsgJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwb3N0YWxDb2RlXCJdJykudmFsKGxvY2FsRGVsaXZlcnlGb3JtRGF0YS5Qb3N0YWxDb2RlIHx8ICcnKTtcblx0XHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgndGV4dGFyZWFbbmFtZT1cImRlbGl2ZXJ5Tm90ZVwiXScpLnZhbChsb2NhbERlbGl2ZXJ5Rm9ybURhdGEuRGVsaXZlcnlOb3RlIHx8ICcnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBhZGRyZXNzVmFsaWRhdG9yID0gJGFkZHJlc3NGb3JtLnZhbGlkYXRlKFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3JlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24nLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbiwgUmVzb3VyY2VzLklOVkFMSURfVkFMVUUpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc3RPZmZpY2VCb3gnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3gsIFJlc291cmNlcy5JTlZBTElEX0FERFJFU1NfUE9CT1gpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ppcENvZGUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlWmlwQ29kZSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVEFMX0NPREUpO1xuXHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3N0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlU3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZSwgUmVzb3VyY2VzLklOVkFMSURfQ0FMSUZPUk5JQV9TVEFURV9MSU5FX0xPQ0FMX0RFTElWRVJZKTtcblx0XHRcdFx0XG5cdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWRkcmVzczFcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3gpO1xuXHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFkZHJlc3MyXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94KTtcblx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhZGRyZXNzM1wiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveCk7XG5cdFx0XHRcdCRhZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbbmFtZT1cInN0YXRlQ29kZVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuU3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZSk7XG5cdFx0XHQgICAgJGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwb3N0YWxDb2RlXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5aaXBDb2RlKTtcblx0XHRcdFx0JGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLCBzZWxlY3QucmVxdWlyZWQnKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHRcdFx0XHQkYWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5FbWFpbCk7XG5cdFx0XHRcdCR0aGlzLmF0dHIoJ2xvY2FsLWRlbGl2ZXJ5LXJhZGl1cycsIGlzTG9jYWxEZWxpdmVyeVZhbGlkKHNlbGVjdGVkTG9jYXRpb24pKTtcblx0XHRcdFx0JHRoaXMuYXR0cignc3RvcmUtc3RhdGUnLCBzZWxlY3RlZExvY2F0aW9uLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLnByb3ZpbmNlX29yX3N0YXRlKTtcblx0XHRcdFx0XG5cdFx0XHRcdCR0aGlzLm9mZignY2xpY2suU2VsZWN0RGVsaXZlcnlPcHRpb24nKS5vbignY2xpY2suU2VsZWN0RGVsaXZlcnlPcHRpb24nLCAnLmRlbGl2ZXJ5LW9wdGlvbiBsYWJlbCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0XHRcdHZhciBkZWxpdmVyeU9wdGlvbiA9ICQodGhpcykuZmluZCgnaW5wdXQnKS52YWwoKTtcblxuXHRcdFx0XHRcdGlmIChkZWxpdmVyeU9wdGlvbiA9PSAncGlja3VwJykge1xuXHRcdFx0XHRcdFx0JHRoaXMuZmluZCgnLmFkZHJlc3MtZm9ybScpLmhpZGUoKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGRlbGl2ZXJ5T3B0aW9uID09ICdkZWxpdmVyeScpIHtcblx0XHRcdFx0XHRcdCR0aGlzLmZpbmQoJy5hZGRyZXNzLWZvcm0nKS5zaG93KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQkdGhpcy5vZmYoJ2NsaWNrLkFwcGx5Jykub24oJ2NsaWNrLkFwcGx5JywgJy5idG4uYm9waXMtb3B0aW9uOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0XHRcdCR0aGlzLmZpbmQoJy51aS1kaWFsb2ctZm9vdGVyIC5lcnJvcicpLnJlbW92ZSgpO1xuXG5cdFx0XHRcdFx0dmFyIHNlbGVjdGVkQm9waXNPcHRpb247XG5cdFx0XHRcdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Nb2RlID09ICdBZGRUb0NhcnRPcHRpb25zJykge1xuXHRcdFx0XHRcdFx0c2VsZWN0ZWRCb3Bpc09wdGlvbiA9ICdkZWxpdmVyeSc7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGVjdGVkQm9waXNPcHRpb24gPSAkdGhpcy5maW5kKCdpbnB1dFtuYW1lPVwiYm9waXMtb3B0aW9uXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIGV2ZW50RGF0YSA9IHtib3BpczogdHJ1ZSwgYm9waXNTdG9yZTogc2VsZWN0ZWRMb2NhdGlvbi5sb2NhdGlvbi5jb2RlLCBzaGlwcGluZ09wdGlvbjogc2VsZWN0ZWRCb3Bpc09wdGlvbiwgY2hhbm5lbDogb3B0aW9ucy5DaGFubmVsLCBxdWFudGl0eUF2YWlsYWJsZTogc2VsZWN0ZWRMb2NhdGlvbi5kZXRhaWwucXVhbnRpdHl9O1xuXHRcdFx0XHRcdGlmIChzZWxlY3RlZEJvcGlzT3B0aW9uID09ICdkZWxpdmVyeScpIHtcblx0XHRcdFx0XHRcdHZhciBkZWxpdmVyeUFkZHJlc3NPYmplY3QgPSB7fTtcblx0XHRcdFx0XHRcdHZhciAkZGVsaXZlcnlBZGRyZXNzRm9ybSA9ICR0aGlzLmZpbmQoJy5ib3Bpcy1kZWxpdmVyeS1hZGRyZXNzJyk7XG5cdFx0XHRcdFx0XHR2YXIgZGVsaXZlcnlBZGRyZXNzQXJyYXkgPSAkZGVsaXZlcnlBZGRyZXNzRm9ybS5zZXJpYWxpemVBcnJheSgpO1xuXHRcdFx0XHRcdFx0JChkZWxpdmVyeUFkZHJlc3NBcnJheSkuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdFx0XHRcdFx0XHRpZiAoZWxlbWVudC52YWx1ZSAhPSAnZGlzYWJsZWQnICYmICRkZWxpdmVyeUFkZHJlc3NGb3JtLmZpbmQoJ1tuYW1lPVwiJyArIGVsZW1lbnQubmFtZSArICdcIl0nKS5hdHRyKCd0eXBlJykgIT0gJ2hpZGRlbicpIHtcblx0XHRcdFx0XHRcdFx0XHRkZWxpdmVyeUFkZHJlc3NPYmplY3RbZWxlbWVudC5uYW1lXSA9IGVsZW1lbnQudmFsdWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0ZXZlbnREYXRhLmRlbGl2ZXJ5QWRkcmVzcyA9IEpTT04uc3RyaW5naWZ5KGRlbGl2ZXJ5QWRkcmVzc09iamVjdCk7XG5cdFx0XHRcdFx0XHQkZGVsaXZlcnlBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFt0eXBlPVwiaGlkZGVuXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdFx0XHRcdGV2ZW50RGF0YVskdGhpcy5hdHRyKCduYW1lJyldID0gJHRoaXMudmFsKCk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoc2VsZWN0ZWRCb3Bpc09wdGlvbiAhPSAnZGVsaXZlcnknIHx8ICRhZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdFx0XHRpZiAoc2VsZWN0ZWRCb3Bpc09wdGlvbiA9PSAnZGVsaXZlcnknKSB7XG5cdFx0XHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdFx0ICAgICAgICAgICAgdXJsOiBVcmxzLkJvcGlzLlZhbGlkYXRlUG9zdGFsQ29kZUZvckxvY2F0aW9ucyxcblx0XHRcdFx0XHQgICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRcdCAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgUG9zdGFsQ29kZTogJGFkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwb3N0YWxDb2RlXCJdJykudmFsKCksXG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIExvY2F0aW9uczogW3NlbGVjdGVkTG9jYXRpb24ubG9jYXRpb24uY29kZV1cblx0XHRcdFx0XHQgICAgICAgICAgICB9KSxcblx0XHRcdFx0XHQgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRcdCAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdGlmIChkYXRhKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckV2ZW50KCdyb2FkaWVGb3JtU3VibWl0Jyk7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIGV2ZW50RGF0YSk7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgXHR9IGVsc2Uge1xuXHRcdFx0XHRcdCAgICAgICAgICAgIFx0XHR2YXIgZXJyb3JNZXNzYWdlID0gJzxkaXYgY2xhc3M9XCJlcnJvclwiPlRoZSB6aXAgY29kZSB5b3UgZW50ZXJlZCBpcyBkaWZmZXJlbnQgdGhhbiB0aGUgb25lIHlvdSBzZWFyY2hlZCB3aXRoLCBhbmQgdGhlIHNlbGVjdGVkIGxvY2F0aW9uIGlzIG5vdCBpbiByYW5nZS4gUGxlYXNlIHVwZGF0ZSB5b3VyIGFkZHJlc3MgYW5kIHRyeSBhZ2Fpbi48L2Rpdj4nXG5cblx0XHRcdFx0XHQgICAgICAgICAgICBcdFx0JHRoaXMuZmluZCgnLnVpLWRpYWxvZy1mb290ZXInKS5wcmVwZW5kKGVycm9yTWVzc2FnZSk7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgXHR9XG5cdFx0XHRcdFx0ICAgICAgICAgICAgfVxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLkJvcGlzLkFkZFRvQ2FydCcsIGV2ZW50RGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQkdGhpcy5vZmYoJ2NsaWNrLkNoYW5nZVppcCcpLm9uKCdjbGljay5DaGFuZ2VaaXAnLCAnLmJ0bi5jaGFuZ2UtemlwJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQm9waXMuU3RvcmVTZWFyY2guUmVzZXQnKTtcblx0XHRcdFx0XHRkaWFsb2cuY2xvc2UoKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0JHRoaXMub2ZmKCdjbGljay5DaGFuZ2VTdG9yZScpLm9uKCdjbGljay5DaGFuZ2VTdG9yZScsICcuYnRuLmNoYW5nZS1zdG9yZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0XHRcdGRpYWxvZy5jbG9zZSgpO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQkdGhpcy5vZmYoJ2NsaWNrLlNlYXJjaFN0b3JlJykub24oJ2NsaWNrLlNlYXJjaFN0b3JlJywgJy5zZWFyY2gtc3RvcmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHRcdFx0JCgnLmRpYWxvZy1ib3Bpcy1vcHRpb25zJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdCQoJy51aS13aWRnZXQtb3ZlcmxheScpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRsb2NhbERlbGl2ZXJ5U3RvcmVTZWFyY2guaW5pdGlhbGl6ZSgkKCcuYm9waXMtbG9jYWwtZGVsaXZlcnktc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpLCBvcHRpb25zTG9jYWxEZWxpdmVyeSk7XG5cdFx0XHRcdH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblxuICAgICAgICAgICAgfVxuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdCb3Bpcy5TdG9yZVNlYXJjaFNlbGVjdExvY2FsRGVsaXZlcnknKS5vbignQm9waXMuU3RvcmVTZWFyY2hTZWxlY3RMb2NhbERlbGl2ZXJ5JywgZnVuY3Rpb24gKGV2ZW50LCBzdG9yZSkge1xuXHRcdGJ1aWxkQWRkcmVzc0h0bWxGb3JMb2NhdGlvbihzdG9yZS5sb2NhdGlvbik7XG5cdFx0JCgnLmRpYWxvZy1ib3Bpcy1vcHRpb25zJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdCQoJy51aS13aWRnZXQtb3ZlcmxheScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHQkKCcuYm9waXMtbG9jYWwtZGVsaXZlcnktc3RvcmUtc2VhcmNoLWNvbnRhaW5lcicpLnJlbW92ZUNsYXNzKCdzaG93Jyk7XG5cdFx0JCgnLmRpYWxvZy1ib3Bpcy1vcHRpb25zJykuZmluZCgnLmRpYWxvZy1jb250ZW50JykuYXR0cignbG9jYWwtZGVsaXZlcnktcmFkaXVzJywgaXNMb2NhbERlbGl2ZXJ5VmFsaWQoc3RvcmUpKTtcblx0XHQkKCcuZGlhbG9nLWJvcGlzLW9wdGlvbnMnKS5maW5kKCcuZGlhbG9nLWNvbnRlbnQnKS5hdHRyKCdzdG9yZS1zdGF0ZScsIHN0b3JlLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLnByb3ZpbmNlX29yX3N0YXRlKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSgpIHtcblx0dmFsaWRhdG9yLmRlc3Ryb3koKTtcblx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWRkcmVzc0h0bWxGb3JMb2NhdGlvbihsb2NhdGlvbikge1xuXHR2YXIgbG9jYXRpb25IdG1sO1xuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLk1vZGUgPT0gJ0FkZFRvQ2FydE9wdGlvbnMnKSB7XG5cdFx0bG9jYXRpb25IdG1sID0gJzxwIGNsYXNzPVwic2VsZWN0ZWQtbG9jYXRpb24tbmFtZVwiPicgKyBsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5uYW1lICsgJzwvcD4nICsgXG5cdFx0XHRcdFx0XHRcdFx0JzxwIGNsYXNzPVwic2VsZWN0ZWQtbG9jYXRpb24tYWRkcmVzc1wiPicgKyBsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5hZGRyZXNzX2xpbmUxICsgJzxici8+JyArXG5cdFx0XHRcdFx0XHRcdFx0bG9jYXRpb24ucG9zdGFsX2FkZHJlc3MuY2l0eSArICcsICcgKyBsb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5wcm92aW5jZV9vcl9zdGF0ZSArICc8L3A+JyArXG5cdFx0XHRcdFx0XHRcdFx0JzxhIGNsYXNzPVwic2VhcmNoLXN0b3JlXCI+Q2hhbmdlIFN0b3JlPC9hPic7XG5cdH0gZWxzZSB7XG5cdFx0bG9jYXRpb25IdG1sID0gbG9jYXRpb24ucG9zdGFsX2FkZHJlc3MuYWRkcmVzc19saW5lMSArICc8YnIvPicgK1xuXHRcdGxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLmNpdHkgKyAnLCAnICsgbG9jYXRpb24ucG9zdGFsX2FkZHJlc3MucHJvdmluY2Vfb3Jfc3RhdGU7XG5cdH1cblxuXHQkKCcudWktZGlhbG9nLmRpYWxvZy1ib3Bpcy1vcHRpb25zJykuZmluZCgnLnNlbGVjdGVkLWxvY2F0aW9uLWRldGFpbHMnKS5odG1sKGxvY2F0aW9uSHRtbCk7XG5cdCQoJyNkaWFsb2ctYm9waXMtb3B0aW9ucycpLmZpbmQoJy5zZWxlY3RlZC1sb2NhdGlvbi1kZXRhaWxzJykuaHRtbChsb2NhdGlvbkh0bWwpO1xufVxuXG5mdW5jdGlvbiBpc0xvY2FsRGVsaXZlcnlWYWxpZChyZWNvcmQpIHtcblx0aWYgKG9wdGlvbnMuTG9jYWxEZWxpdmVyeSAmJiBvcHRpb25zLkxvY2FsRGVsaXZlcnkuRW5hYmxlZCAmJiBpc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKHJlY29yZC5sb2NhdGlvbikgJiYgcmVjb3JkLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X2VuYWJsZWQgJiYgcmVjb3JkLmRldGFpbCAmJiByZWNvcmQuZGV0YWlsLnF1YW50aXR5ID4gMCkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0cmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKGxvY2F0aW9uKSB7XG5cdGlmIChsb2NhbERlbGl2ZXJ5UmFkaXVzICYmIGxvY2F0aW9uLmRpc3RhbmNlICYmIGxvY2FsRGVsaXZlcnlSYWRpdXMgPj0gbG9jYXRpb24uZGlzdGFuY2UpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gYXBwZW5kQ1NSRlRva2VuKCRmb3JtKSB7XG5cdCQuYWpheCh7XG5cdFx0bWV0aG9kOiAnZ2V0Jyxcblx0XHR1cmw6IFVybHMuQ1NSRlRva2VuLkdldCxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHQkZm9ybS5hcHBlbmQoJzxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cIicgKyByZXNwb25zZS5uYW1lICsgJ1wiIHZhbHVlPVwiJyArIHJlc3BvbnNlLnRva2VuICsgJ1wiLz4nKTtcblx0XHR9XG5cdH0pO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgR2VvbG9jYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0dlb2xvY2F0aW9uL0dlb2xvY2F0aW9uSGVscGVyJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTG9jYXRpb25TZWFyY2g7XG5cbmZ1bmN0aW9uIExvY2F0aW9uU2VhcmNoKCkge1xuXHR0aGlzLiRjb250YWluZXI7XG5cdHRoaXMuJGZvcm07XG5cdHRoaXMuZGF0YUJ1ZmZlcjtcblx0dGhpcy5vcHRpb25zO1xuXHR0aGlzLnZhbGlkYXRvcjtcblx0XG5cdHRoaXMucmVzdWx0Q29udGFpbmVyVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib3Bpcy1yZXN1bHQtY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHR0aGlzLnJlc3VsdEl0ZW1UZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1pdGVtJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXG5cdHRoaXMuJHJlc3VsdDtcblx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZTtcblx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b247XG5cdHRoaXMuJHN0b3JlU2VsZWN0QnV0dG9uO1xuXHR0aGlzLiRib3Bpc0J1dHRvbjtcblx0dGhpcy4kZXJyb3JNZXNzYWdlO1xuXHRcblx0dGhpcy5pbml0aWFsaXplID0gZnVuY3Rpb24gKCRjb250YWluZXIsIG9wdGlvbnMpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dGhpcy4kY29udGFpbmVyID0gJGNvbnRhaW5lcjtcblx0XHR0aGlzLiRmb3JtID0gJGNvbnRhaW5lci5maW5kKCdmb3JtJyk7XG5cdFx0dGhpcy5vcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdFx0c3VjY2Vzc0NhbGxiYWNrOiBudWxsLFxuXHRcdFx0ZXJyb3JDYWxsYmFjazogbnVsbFxuXHRcdH0sIG9wdGlvbnMpO1xuXHRcdHRoaXMuZGF0YUJ1ZmZlciA9IHtcblx0XHRcdGxpbWl0OiB0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLkJvcGlzICYmIHRoaXMub3B0aW9ucy5Cb3Bpcy5TdG9yZVNlYXJjaExpbWl0ID8gdGhpcy5vcHRpb25zLkJvcGlzLlN0b3JlU2VhcmNoTGltaXQgOiA1XG5cdFx0fTtcblx0XHR0aGlzLiRyZXN1bHQgPSB0aGlzLiRjb250YWluZXIuZmluZCgnLnJlc3VsdCcpO1xuXHRcdHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUgPSB0aGlzLiRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbENvZGVcIl0nKTtcblx0XHR0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbiA9IHRoaXMuJGNvbnRhaW5lci5maW5kKCcuYnRuLnN0b3JlLXNlYXJjaCcpO1xuXHRcdHRoaXMuJHN0b3JlU2VsZWN0QnV0dG9uID0gdGhpcy4kY29udGFpbmVyLmZpbmQoJy5idG4uc3RvcmUtc2VsZWN0Jyk7XG5cdFx0dGhpcy4kYm9waXNCdXR0b24gPSB0aGlzLiRjb250YWluZXIuZmluZCgnLmJ0bi5ib3BpcycpO1xuXHQgICAgdGhpcy4kZXJyb3JNZXNzYWdlID0gdGhpcy4kZm9ybS5maW5kKCdzcGFuLmVycm9yJyk7XG5cdFx0JCgnaHRtbCcpLmFkZENsYXNzKCdzY3JvbGwtbG9jaycpO1xuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5EZWZhdWx0WmlwQ29kZSkge1xuXHRcdFx0dGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwodGhpcy5vcHRpb25zLkRlZmF1bHRaaXBDb2RlKTtcblx0XHR9XG5cblx0ICAgIHRoaXMuJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdCAgICB0aGlzLnZhbGlkYXRvciA9IHRoaXMuJGZvcm0udmFsaWRhdGUoVmFsaWRhdGlvblNldHRpbmdzLkdsb2JhbCk7XG5cdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCd6aXBDb2RlJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVppcENvZGUsIFJlc291cmNlcy5JTlZBTElEX1BPU1RBTF9DT0RFKTtcblx0ICAgIHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5aaXBDb2RlKTtcblx0XG5cdCAgICBpZiAodGhpcy52YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgdGhpcy4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJyAmJiAhdGhpcy4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdHRoaXMuJHN0b3JlU2VhcmNoQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdCAgICB9XG5cdFx0dGhpcy4kY29udGFpbmVyLnNob3coKTtcblx0ICAgIFxuXHQgICAgdGhpcy4kZm9ybS5vZmYoJ2NsaWNrLkFwcGx5Jykub24oJ2NsaWNrLkFwcGx5JywgJy5idG4uc3RvcmUtc2VhcmNoOm5vdChbbG9hZGluZ10pJywgJy5idG4uc3RvcmUtc2VhcmNoOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdCAgICBcdCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdCAgICBcdHNlbGYuJGNvbnRhaW5lci50cmlnZ2VyKCdMb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0Jyk7XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgdGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suRGlhbG9nQ2xvc2UnKS5vbignY2xpY2suRGlhbG9nQ2xvc2UnLCAnLmNsb3NlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdCAgICBcdCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdFx0XHQkKCcubG9jYXRpb24tc2VhcmNoLWRpYWxvZycpLmhpZGUoKTtcblx0ICAgIH0pO1xuXHQgICAgXG5cdCAgICB0aGlzLiRjb250YWluZXIub2ZmKCdMb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0Jykub24oJ0xvY2F0aW9uU2VhcmNoLkZvcm1TdWJtaXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0ICAgICAgICBzZWxmLiRlcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHQgICAgICAgIGlmIChVcmxzICYmIFVybHMuQm9waXMuR2V0TG9jYXRpb25zRm9yUG9zdGFsQ29kZSAmJiBzZWxmLnZhbGlkYXRvci52YWxpZCgpICYmIHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkpIHtcblx0XHRcdFx0c2VsZi5kYXRhQnVmZmVyLmxvYWRNb3JlID0gJ3Bvc3RhbENvZGUnO1xuXHRcdFx0XHRzZWxmLmRhdGFCdWZmZXIub2Zmc2V0ID0gMDtcblx0XHRcdFx0c2VsZi4kc3RvcmVTZWFyY2hCdXR0b24ubG9hZGluZygpO1xuXHRcdFx0XHRzZWxmLiRyZXN1bHQuaHRtbCgnJyk7XG5cdFx0XHRcdHNlbGYuJHJlc3VsdC5sb2FkaW5nKCk7XG5cdFx0XHRcdHNlbGYuZ2V0U3RvcmVMaXN0Rm9yUG9zdGFsQ29kZShzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpKTtcblx0XHRcdH1cblx0XHR9KTtcblx0ICAgIFxuXHQgICAgdGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suU2VsZWN0U3RvcmUnKS5vbignY2xpY2suU2VsZWN0U3RvcmUnLCAnLmJ0bi5zZWxlY3Qtc3RvcmU6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnc2Nyb2xsLWxvY2snKTtcblx0XHRcdCQodGhpcykubG9hZGluZyh7XG5cdFx0XHRcdENvbnRlbnQ6ICc8aDY+SG9sZCBZb3VyIEhvcnNlcyE8L2g2PjxwPllvdXIgc2VsZWN0aW9ucyBhcmUgbG9hZGluZy4uLjwvcD4nLFxuXHRcdFx0XHRDc3NDbGFzczogJ2Jvb3RiYXJuZXhwcmVzcycsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cdCAgICB9KTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLlNlbGVjdFN0b3JlJykub24oJ2NsaWNrLlNlbGVjdFN0b3JlJywgJy5idG4uc2V0LW15LXN0b3JlOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyICRzdG9yZUlucHV0ID0gJHRoaXMuY2xvc2VzdCgnbGknKS5maW5kKCdpbnB1dCcpO1xuXHRcdFx0dmFyIHN0b3JlSWQ7XG5cdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ3Njcm9sbC1sb2NrJyk7XG5cdFx0XHRpZiAoJHN0b3JlSW5wdXQgJiYgJHN0b3JlSW5wdXQubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRzdG9yZUlkID0gJHN0b3JlSW5wdXQudmFsKCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzdG9yZUlkKSB7XG5cdFx0XHRcdHNlbGYudXBkYXRlU3RvcmVEZXRhaWxzKHN0b3JlSWQpO1xuXHRcdFx0fVxuXHQgICAgfSk7XG5cdCAgICBcblx0ICAgIHRoaXMuJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdrZXlwcmVzcy5Mb2NhdGlvblNlYXJjaC5Gb3JtU3VibWl0Jykub24oJ2tleXByZXNzLkxvY2F0aW9uU2VhcmNoLkZvcm1TdWJtaXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgIFx0aWYgKGV2ZW50LmtleSA9PSAnRW50ZXInKSB7XG5cdCAgICBcdFx0c2VsZi4kY29udGFpbmVyLnRyaWdnZXIoJ0xvY2F0aW9uU2VhcmNoLkZvcm1TdWJtaXQnKTtcblx0ICAgIFx0XHRyZXR1cm4gZmFsc2U7XG5cdCAgICBcdH1cblx0ICAgIH0pO1xuXHQgICAgXG5cdCAgICB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLm9mZigna2V5ZG93bi5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbigna2V5ZG93bi5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgIFx0aWYgKHNlbGYuJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkubGVuZ3RoID09IDUgJiYgcGFyc2VJbnQoZXZlbnQua2V5LCAxMCkgPT0gZXZlbnQua2V5ICYmICF3aW5kb3cuZ2V0U2VsZWN0aW9uKCkudG9TdHJpbmcoKSkge1xuXHQgICAgXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdCQoZG9jdW1lbnQpLmZpbmQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgXG5cdCAgICB0aGlzLiRmb3JtSW5wdXRQb3N0YWxDb2RlLm9mZignY2hhbmdlLkxvY2F0aW9uU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdjaGFuZ2UuTG9jYXRpb25TZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdCAgICBcdGlmIChzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLmxlbmd0aCA+IDUpIHtcblx0ICAgIFx0XHRzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbChzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgpLnN1YnN0cigwLCA1KSk7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdCQoZG9jdW1lbnQpLmZpbmQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG5cdCAgICB9KTtcblx0ICAgIFxuXHQgICAgdGhpcy4kZm9ybUlucHV0UG9zdGFsQ29kZS5vZmYoJ2tleXVwLkxvY2F0aW9uU2VhcmNoLlZhbGlkYXRpb25DaGVjaywgY2hhbmdlLkxvY2F0aW9uU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdrZXl1cC5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2ssIGNoYW5nZS5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0ICAgIFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdCAgICBcdFxuXHRcdFx0aWYgKCRjb250YWluZXIuYXR0cignc3RhdGUnKSA9PT0gJ2Zvcm0nKSB7XG5cdFx0XHRcdGlmIChzZWxmLnZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAhc2VsZi4kc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0XHRzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCFzZWxmLnZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiBzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5oYXNDbGFzcygncmVhZHknKSkge1xuXHRcdFx0XHRcdHNlbGYuJHN0b3JlU2VhcmNoQnV0dG9uLnJlbW92ZUNsYXNzKCdyZWFkeScpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0ICAgIH0pO1xuXHQgICAgXG5cdCAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlZG93bi5Mb2NhdGlvblNlYXJjaC5WYWxpZGF0aW9uQ2xlYXInKS5vbignbW91c2Vkb3duLkxvY2F0aW9uU2VhcmNoLlZhbGlkYXRpb25DbGVhcicsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgICAgIGlmIChzZWxmLnZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdChzZWxmLiRjb250YWluZXIpLmxlbmd0aCA9PSAwKSB7XG5cdCAgICAgICAgICAgIHNlbGYuJGVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cdCBcblx0ICAgIHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkxvY2F0aW9uU2VhcmNoLlJlc2V0Jykub24oJ2NsaWNrLkxvY2F0aW9uU2VhcmNoLlJlc2V0JywgJy5yZXNldCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgXHRzZWxmLiRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgnJyk7XG5cdCAgICAgICAgc2VsZi4kY29udGFpbmVyLmF0dHIoJ3N0YXRlJywgJ2Zvcm0nKTtcblx0ICAgICAgICBzZWxmLiRzdG9yZVNlYXJjaEJ1dHRvbi5yZW1vdmVDbGFzcygncmVhZHknKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHQgICAgICAgICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdCAgICAgICAgc2VsZi4kYm9waXNCdXR0b24ucmVtb3ZlQ2xhc3MoJ3JlYWR5Jyk7XG5cdCAgICB9KTtcbiAgIFxuXHQgICAgdGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suTG9jYXRpb25TZWFyY2guU2VsZWN0aW9uJykub24oJ2NsaWNrLkxvY2F0aW9uU2VhcmNoLlNlbGVjdGlvbicsICdpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfU3RvcmVJZFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHQgICAgICAgIHZhciBib3Bpc1N0b3JlID0gJCgnaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX1N0b3JlSWRcIl06Y2hlY2tlZCcpLnZhbCgpO1xuXHQgICAgICAgIFxuXHQgICAgICAgIGlmICghc2VsZi4kYm9waXNCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0ICAgICAgICBcdHNlbGYuJGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuXHQgICAgICAgIH1cblxuXHRcdFx0aWYgKHNlbGYuJHN0b3JlU2VsZWN0QnV0dG9uLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0c2VsZi4kc3RvcmVTZWxlY3RCdXR0b24uYXR0cignaHJlZicsIFVybHMuc3RvcmVMYW5kaW5nUGFnZSArICc/U3RvcmU9JyArIGJvcGlzU3RvcmUpLmFkZENsYXNzKCdyZWFkeScpOzsgXG5cdFx0XHR9XG5cdCAgICAgICAgXG5cdCAgICAgICAgJCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0ICAgICAgICBcblx0ICAgICAgICBpZiAoYm9waXNTdG9yZSkge1xuXHQgICAgICAgIFx0c2VsZi4kYm9waXNCdXR0b24uYXR0cignc3RhdGUnLCAncGlja3VwJyk7XG5cdCAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICBcdHNlbGYuJGJvcGlzQnV0dG9uLmF0dHIoJ3N0YXRlJywgJ3NoaXAnKTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHRcdHRoaXMuJGNvbnRhaW5lci5vZmYoJ2NsaWNrLlVzZU15TG9jYXRpb24nKS5vbignY2xpY2suVXNlTXlMb2NhdGlvbicsICcudXNlLW15LWxvY2F0aW9uJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0c2VsZi5nZW9sb2NhdGlvblNlYXJjaCgpO1xuXHRcdH0pO1xuXG5cdFx0JChkb2N1bWVudCkub2ZmKCdMb2NhdGlvblNlYXJjaC5HZW9sb2NhdGlvblNlYXJjaCcpLm9uKCdMb2NhdGlvblNlYXJjaC5HZW9sb2NhdGlvblNlYXJjaCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0c2VsZi5nZW9sb2NhdGlvblNlYXJjaCgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy4kY29udGFpbmVyLm9mZignY2xpY2suTG9hZE1vcmUnKS5vbignY2xpY2suTG9hZE1vcmUnLCAnLmxvYWQtbW9yZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0JCh0aGlzKS5sb2FkaW5nKHsgSXNMYWJlbFNob3duOiBmYWxzZSB9KTtcblx0XHRcdHNlbGYuZGF0YUJ1ZmZlci5vZmZzZXQgKz0gc2VsZi5kYXRhQnVmZmVyLmxpbWl0O1xuXHRcdFx0aWYgKHNlbGYuZGF0YUJ1ZmZlci5sb2FkTW9yZSA9PSAnZ2VvbG9jYXRpb25Qb3NpdGlvbicpIHtcblx0XHRcdFx0c2VsZi5nZXRTdG9yZUxpc3RGb3JHZW9sb2NhdGlvblBvc2l0aW9uKHNlbGYuZGF0YUJ1ZmZlci5nZW9sb2NhdGlvblBvc2l0aW9uLCB0cnVlKTtcblx0XHRcdH0gZWxzZSBpZiAoc2VsZi5kYXRhQnVmZmVyLmxvYWRNb3JlID09ICdwb3N0YWxDb2RlJykge1xuXHRcdFx0XHRzZWxmLmdldFN0b3JlTGlzdEZvclBvc3RhbENvZGUoc2VsZi4kZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKSwgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHR0aGlzLmdlb2xvY2F0aW9uU2VhcmNoID0gZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHNlbGYuZGF0YUJ1ZmZlci5sb2FkTW9yZSA9ICdnZW9sb2NhdGlvblBvc2l0aW9uJztcblx0XHRzZWxmLmRhdGFCdWZmZXIub2Zmc2V0ID0gMDtcblx0XHR0aGlzLiRyZXN1bHQuaHRtbCgnJyk7XG5cdFx0dGhpcy4kcmVzdWx0LmxvYWRpbmcoKTtcblx0XHRHZW9sb2NhdGlvbkhlbHBlci5HZXRQb3NpdGlvbigpLnRoZW4oZnVuY3Rpb24ocG9zaXRpb24pIHtcblx0XHRcdHNlbGYuZGF0YUJ1ZmZlci5nZW9sb2NhdGlvblBvc2l0aW9uID0gcG9zaXRpb247XG5cdFx0XHRzZWxmLmdldFN0b3JlTGlzdEZvckdlb2xvY2F0aW9uUG9zaXRpb24oc2VsZi5kYXRhQnVmZmVyLmdlb2xvY2F0aW9uUG9zaXRpb24pO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKHNlbGYuJHJlc3VsdC5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0c2VsZi4kcmVzdWx0LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oKSB7XG5cdFx0dGhpcy52YWxpZGF0b3IuZGVzdHJveSgpO1xuXHRcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdH1cblx0XG5cdHRoaXMuZ2V0U3RvcmVMaXN0Rm9yR2VvbG9jYXRpb25Qb3NpdGlvbiA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBpc0xvYWRNb3JlKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHZhciBnZW9sb2NhdGlvblBvc2l0aW9uO1xuXHRcdGlmIChwb3NpdGlvbiAmJiBwb3NpdGlvbi5jb29yZHMpIHtcblx0XHRcdGdlb2xvY2F0aW9uUG9zaXRpb24gPSB7XG5cdFx0XHRcdGNvb3Jkczoge1xuXHRcdFx0XHRcdGFjY3VyYWN5OiBwb3NpdGlvbi5jb29yZHMuYWNjdXJhY3ksXG5cdFx0XHRcdFx0bGF0aXR1ZGU6IHBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSxcblx0XHRcdFx0XHRsb25naXR1ZGU6IHBvc2l0aW9uLmNvb3Jkcy5sb25naXR1ZGVcblx0XHRcdFx0fSxcblx0XHRcdFx0dGltZXN0YW1wOiBwb3NpdGlvbi50aW1lc3RhbXBcblx0XHRcdH07XG5cdFx0fVxuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdHVybDogVXJscy5Cb3Bpcy5HZXRMb2NhdGlvbnNGb3JHZW9sb2NhdGlvblBvc2l0aW9uLFxuXHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0Q2hhbm5lbDogdGhpcy5vcHRpb25zLkNoYW5uZWwsXG5cdFx0XHRcdFNvdXJjZTogdGhpcy5vcHRpb25zLlNvdXJjZSxcblx0XHRcdFx0R2VvbG9jYXRpb25Qb3NpdGlvbjogZ2VvbG9jYXRpb25Qb3NpdGlvbixcblx0XHRcdFx0UmFkaXVzOiAzMDAwLFxuXHRcdFx0XHRMaW1pdDogc2VsZi5kYXRhQnVmZmVyLmxpbWl0LFxuXHRcdFx0XHRPZmZzZXQ6IHNlbGYuZGF0YUJ1ZmZlci5vZmZzZXRcblx0XHRcdH0pLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0c2VsZi5yZW5kZXJTdG9yZUxpc3QoZGF0YSwgaXNMb2FkTW9yZSk7XG5cdFx0XHR9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcblx0XHRcdH1cblx0XHR9KTtcdFx0XG5cdH1cblxuXHR0aGlzLmdldFN0b3JlTGlzdEZvclBvc3RhbENvZGUgPSBmdW5jdGlvbihwb3N0YWxDb2RlLCBpc0xvYWRNb3JlKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdHVybDogVXJscy5Cb3Bpcy5HZXRTdG9yZXNCeUNpdHlTdGF0ZVBvc3RhbFNlYXJjaEtleUFqYXgsXG5cdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRDaGFubmVsOiBzZWxmLm9wdGlvbnMuQ2hhbm5lbCxcblx0XHRcdFx0U291cmNlOiBzZWxmLm9wdGlvbnMuU291cmNlLFxuXHRcdFx0XHRTZWFyY2hLZXk6IHBvc3RhbENvZGUsXG5cdFx0XHRcdExpbWl0OiBzZWxmLmRhdGFCdWZmZXIubGltaXQsXG5cdFx0XHRcdE9mZnNldDogc2VsZi5kYXRhQnVmZmVyLm9mZnNldFxuXHRcdFx0fSksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRzZWxmLnJlbmRlclN0b3JlTGlzdChkYXRhLCBpc0xvYWRNb3JlKTtcblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmIChzZWxmLm9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuXHRcdFx0XHRcdHNlbGYub3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHRoaXMucmVuZGVyU3RvcmVMaXN0ID0gZnVuY3Rpb24oZGF0YSwgaXNMb2FkTW9yZSkge1xuXHRcdHZhciBsb2NhdGlvbkRhdGE7XG5cdFx0aWYgKGRhdGEgJiYgZGF0YS5TZXJ2aWNlU3VjY2Vzc2Z1bGx5Q2FsbGVkICYmIGRhdGEuSW5xdWlyeVJlc3VsdCAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YSAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHRsb2NhdGlvbkRhdGEgPSBkYXRhLklucXVpcnlSZXN1bHQuZGF0YTtcblx0XHR9XG5cblx0XHR0aGlzLiRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG5cdFx0aWYgKGxvY2F0aW9uRGF0YSAmJiBsb2NhdGlvbkRhdGEubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFyIGxvY2F0aW9uc0Rpc3BsYXllZCA9IDA7XG5cdFx0XHRsb2NhdGlvbkRhdGEgPSBsb2NhdGlvbkRhdGEuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuXHRcdFx0XHRyZXR1cm4gbGVmdC5kaXN0YW5jZSAtIHJpZ2h0LmRpc3RhbmNlO1xuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdHRoaXMuZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ10gPSBbXTtcblx0XHRcdHRoaXMuJGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCBsb2NhdGlvbkRhdGEubGVuZ3RoKTtcblx0XHRcdFxuXHRcdFx0dmFyIHN0b3JlTGlzdEh0bWwgPSAnJztcblx0XHRcdGZvciAodmFyIGxvY2F0aW9uRWxlbWVudCBpbiBsb2NhdGlvbkRhdGEpIHtcblx0XHRcdFx0dmFyIGxvY2F0aW9uID0gbG9jYXRpb25EYXRhW2xvY2F0aW9uRWxlbWVudF07XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAobG9jYXRpb24gJiYgIXRoaXMuZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ11bbG9jYXRpb24uY29kZV0pIHtcblx0XHRcdFx0XHR2YXIgc3RvcmVQaG9uZSA9ICcnO1xuXHRcdFx0XHRcdHZhciBzdG9yZU9wZW5VbnRpbCA9ICcnO1xuXHRcdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8pIHtcblx0XHRcdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uUGhvbmUpIHtcblx0XHRcdFx0XHRcdFx0c3RvcmVQaG9uZSA9IGxvY2F0aW9uLlN0b3JlSW5mby5QaG9uZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uT3BlblVudGlsKSB7XG5cdFx0XHRcdFx0XHRcdHN0b3JlT3BlblVudGlsID0gbG9jYXRpb24uU3RvcmVJbmZvLk9wZW5VbnRpbDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgbG9jYXRpb25OYW1lO1xuXHRcdFx0XHRcdGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRcdFx0XHRsb2NhdGlvbk5hbWUgPSAnPHN0cm9uZz4nICsgbG9jYXRpb24uU3RvcmVJbmZvLk5hbWUgKyAnIC0gJyArIGxvY2F0aW9uLlN0b3JlSW5mby5TdG9yZUlkICsgJzwvc3Ryb25nPic7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uTmFtZSA9ICc8c3Ryb25nPicgKyBsb2NhdGlvbi5TdG9yZUluZm8uTmFtZSArICc8L3N0cm9uZz4nO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5BZ2VudFN0b3JlSUQgPT0gbG9jYXRpb24uY29kZSkge1xuXHRcdFx0XHRcdFx0bG9jYXRpb25OYW1lICs9ICc8YnIvPihZb3VyIFN0b3JlKSc7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHZhciBodG1sID0gbG9jYXRpb25OYW1lICsgJzxici8+JyArXG5cdFx0XHRcdFx0XHRcdFx0bG9jYXRpb24uU3RvcmVJbmZvLkFkZHJlc3MxICsgJzxiciAvPicgKyBcblx0XHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5TdG9yZUluZm8uQ2l0eSArICcsICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uU3RhdGVDb2RlUGFyc2VkICsgJyAnICsgbG9jYXRpb24uU3RvcmVJbmZvLlBvc3RhbENvZGUuc3Vic3RyKDAsIDUpICsgJzxiciAvPicgK1xuXHRcdFx0XHRcdFx0XHRcdHN0b3JlUGhvbmU7XG5cdFx0XHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGVJZCA9PSBTaXRlQ29uc3RhbnRzLkJvb3RCYXJuUnNwVVMgJiYgc3RvcmVPcGVuVW50aWwpIHtcblx0XHRcdFx0XHRcdGh0bWwgKz0gJzxiciAvPicgKyBzdG9yZU9wZW5VbnRpbDtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzdG9yZUxpc3RIdG1sICs9IHRoaXMucmVzdWx0SXRlbVRlbXBsYXRlKHtcblx0XHRcdFx0XHRcdFN0b3JlSWQ6IGxvY2F0aW9uLmNvZGUsXG5cdFx0XHRcdFx0XHREaXN0YW5jZTogbG9jYXRpb24uU3RvcmVJbmZvLkRpc3RhbmNlLnRvRml4ZWQoMSkgKyAnPGJyLz5taScsXG5cdFx0XHRcdFx0XHRTZWxlY3RlZDogJycsXG5cdFx0XHRcdFx0XHRMYW5kaW5nQ2F0ZWdvcnk6IHRoaXMub3B0aW9ucy5MYW5kaW5nQ2F0ZWdvcnksXG5cdFx0XHRcdFx0XHRTdGF0dXNEaXNwbGF5OiBzdG9yZU9wZW5VbnRpbCxcblx0XHRcdFx0XHRcdEh0bWw6IGh0bWxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0bG9jYXRpb25zRGlzcGxheWVkKys7XG5cdFx0XHRcdGlmIChsb2NhdGlvbnNEaXNwbGF5ZWQgPj0gdGhpcy5kYXRhQnVmZmVyLmxpbWl0KSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5kYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtsb2NhdGlvbi5jb2RlXSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHZhciByZXN1bHRIdG1sID0gdGhpcy5yZXN1bHRDb250YWluZXJUZW1wbGF0ZSh7XG5cdFx0XHRcdEh0bWw6IHN0b3JlTGlzdEh0bWxcblx0XHRcdH0pO1xuXHRcdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGVJZCA9PSBTaXRlQ29uc3RhbnRzLkJvb3RCYXJuUnNwVVMgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0Lm1ldGEucGFnZSA8IGRhdGEuSW5xdWlyeVJlc3VsdC5tZXRhLnBhZ2VzKSB7XG5cdFx0XHRcdHJlc3VsdEh0bWwgKz0gJzxhIGhyZWY9XCIjXCIgY2xhc3M9XCJsb2FkLW1vcmVcIj5Mb2FkIE1vcmU8L2E+Jztcblx0XHRcdH1cblx0XHRcdGlmICh0aGlzLiRzdG9yZVNlYXJjaEJ1dHRvbi5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0dGhpcy4kc3RvcmVTZWFyY2hCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuJHJlc3VsdC5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0dGhpcy4kcmVzdWx0LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdH1cblx0XHRcdGlmIChpc0xvYWRNb3JlKSB7XG5cdFx0XHRcdHRoaXMuJHJlc3VsdC5maW5kKCcubG9hZC1tb3JlJykucmVtb3ZlKCk7XG5cdFx0XHRcdHRoaXMuJHJlc3VsdC5hcHBlbmQocmVzdWx0SHRtbCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLiRyZXN1bHQuaHRtbChyZXN1bHRIdG1sKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKCFpc0xvYWRNb3JlKSB7XG5cdFx0XHR0aGlzLiRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgJzAnKTtcblx0XHRcdHRoaXMuJHJlc3VsdC5odG1sKCcnKTtcblx0XHR9XG5cdH1cblxuXHR0aGlzLnVwZGF0ZVN0b3JlRGV0YWlscyA9IGZ1bmN0aW9uKHN0b3JlSWQpIHtcblx0XHRpZiAoc3RvcmVJZCkge1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdHVybDogVXJscy5TdG9yZXMuU2V0TXlTdG9yZSxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFN0b3JlSWQ6IHN0b3JlSWRcblx0XHRcdFx0fSksXG5cdFx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHQkKCcubXktc3RvcmUtcGFuZWwnKS5yZXBsYWNlV2l0aChkYXRhKTtcblx0XHRcdFx0XHQkKCcubXktc3RvcmUtbW9kYWwnKS5oaWRlKCk7XG5cdFx0XHRcdFx0JCgnLmxvY2F0aW9uLXNlYXJjaC1kaWFsb2cnKS5oaWRlKCk7XG5cblx0XHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdFx0XHRcdHVybDogVXJscy5TdG9yZXMuR2V0TXlTdG9yZVBhbmVsLFxuXHRcdFx0XHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdFx0JCgnLm15LXN0b3JlLXBhbmVsJykucmVwbGFjZVdpdGgoZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdFx0XHRcdHVybDogVXJscy5TdG9yZXMuR2V0TXlTdG9yZU1vZGFsLFxuXHRcdFx0XHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdFx0JCgnLm15LXN0b3JlLW1vZGFsJykucmVwbGFjZVdpdGgoZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdFx0bWV0aG9kOiAnR0VUJyxcblx0XHRcdFx0XHRcdHVybDogVXJscy5nZXRTdG9yZXNQYW5lbCxcblx0XHRcdFx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHRcdCQoJyNsb2NhdGlvbicpLmh0bWwoZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdTaG9wTXlTdG9yZS5VcGRhdGUnLCBzdG9yZUlkKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCQoJy5teS1zdG9yZS1tb2RhbCcpLmhpZGUoKTtcblx0XHRcdFx0XHQkKCcubG9jYXRpb24tc2VhcmNoLWRpYWxvZycpLmhpZGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0dGhpcy5hc3NpZ25TdG9yZUlkID0gZnVuY3Rpb24oc3RvcmVJZCkge1xuXHRcdGlmIChzdG9yZUlkKSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmwgOiBVcmxzLmFzc2lnblN0b3JlSWQsXG5cdFx0XHRcdGRhdGEgOiB7IHN0b3JlX2lkIDogc3RvcmVJZCB9LFxuXHRcdFx0XHRtZXRob2QgOiBcIlBPU1RcIixcblx0XHRcdFx0ZGF0YVR5cGUgOiBcIkpTT05cIixcblx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRpZiAoJ3N1Y2Nlc3MnIGluIGRhdGEgJiYgZGF0YVsnc3VjY2VzcyddID09IHRydWUpIHtcblx0XHRcdFx0XHRcdC8vIFRPRE86IGFueSBmb2xsb3ctdXAgbmVlZGVkIGNsaWVudC1zaWRlP1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cdFxuXHRyZXR1cm4gdGhpcztcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5WYWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXMgPSB2YWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXM7XG5cbnZhciBvcHRpb25zO1xudmFyIGJ1ZmZlciA9IHt9O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXMoJGJvcGlzUHJvZHVjdExpbmVJdGVtcywgb3B0aW9uc1BhcmFtZXRlcikge1xuXHRpZiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRcdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXHR9XG5cdFxuXHRidWZmZXJbJ1RvdGFsQ291bnQnXSA9ICRib3Bpc1Byb2R1Y3RMaW5lSXRlbXMubGVuZ3RoO1xuXHRidWZmZXJbJ0xvYWRlZENvdW50J10gPSAwO1xuXHRidWZmZXJbJ1Byb2R1Y3RMaW5lSXRlbXMnXSA9IHt9O1xuXHRcblx0JGJvcGlzUHJvZHVjdExpbmVJdGVtcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgdXVpZCA9ICR0aGlzLmF0dHIoJ3V1aWQnKTtcblx0XHR2YXIgcHJvZHVjdElkID0gJHRoaXMuYXR0cignc2t1Jyk7XG5cdFx0dmFyIHN0b3JlSWQgPSAkdGhpcy5hdHRyKCdzdG9yZScpO1xuXHRcdHZhciBxdWFudGl0eVJlcXVlc3RlZCA9ICR0aGlzLmNsb3Nlc3QoJy5vcmRlci1pdGVtJykuZmluZCgnLnF0eS1lZGl0IGlucHV0W3R5cGU9XCJ0ZXh0XCJdJykudmFsKCk7XG5cdFx0XG5cdFx0JC5hamF4KHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgdXJsOiBVcmxzLkJvcGlzLkdldFN0b3JlSW52ZW50b3J5Rm9yUHJvZHVjdEZvclN0b3JlLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIGFzeW5jOiB0cnVlLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIFByb2R1Y3RJZDogcHJvZHVjdElkLFxuICAgICAgICAgICAgICAgIFN0b3JlSWQ6IHN0b3JlSWRcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5xdWlyeVJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhWzBdLmludmVudG9yeV9zdXBwbGllcykge1xuICAgICAgICAgICAgICAgICAgICBpbnF1aXJ5UmVzdWx0ID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZiAoaW5xdWlyeVJlc3VsdCAmJiBpbnF1aXJ5UmVzdWx0ICYmIGlucXVpcnlSZXN1bHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIFx0YnVmZmVyWydQcm9kdWN0TGluZUl0ZW1zJ11bdXVpZF0gPSB7XG4gICAgICAgICAgICAgICAgXHRcdFF1YW50aXR5UmVxdWVzdGVkOiBwYXJzZUludChxdWFudGl0eVJlcXVlc3RlZCwgMTApLFxuICAgICAgICAgICAgICAgIFx0XHRJbnF1aXJ5UmVzdWx0OiBpbnF1aXJ5UmVzdWx0XG4gICAgICAgICAgICAgICAgXHR9O1xuICAgICAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlclsnTG9hZGVkQ291bnQnXSArPSAxO1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXNTdWNjZXNzKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBcdCRyZXN1bHQuaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLkVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5FcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXHR9KTtcblx0XG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVQcm9kdWN0TGluZUl0ZW1zU3VjY2VzcygpIHtcblx0aWYgKGJ1ZmZlclsnTG9hZGVkQ291bnQnXSA9PSBidWZmZXJbJ1RvdGFsQ291bnQnXSkge1xuXHRcdHZhciBpc0JvcGlzSW52ZW50b3J5VmFsaWQgPSB0cnVlO1xuXHRcdGZvciAodmFyIHByb2R1Y3RMaW5lSXRlbVVVSUQgaW4gYnVmZmVyWydQcm9kdWN0TGluZUl0ZW1zJ10pIHtcblx0XHRcdHZhciBwcm9kdWN0TGluZUl0ZW1cdD0gYnVmZmVyWydQcm9kdWN0TGluZUl0ZW1zJ11bcHJvZHVjdExpbmVJdGVtVVVJRF07XG5cdFx0XHRcblx0XHRcdGlmIChwcm9kdWN0TGluZUl0ZW0uUXVhbnRpdHlSZXF1ZXN0ZWQgPiBwcm9kdWN0TGluZUl0ZW0uSW5xdWlyeVJlc3VsdFswXS5kZXRhaWwucXVhbnRpdHkpIHtcblx0XHRcdFx0aXNCb3Bpc0ludmVudG9yeVZhbGlkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuU3VjY2Vzc0V2ZW50KSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKG9wdGlvbnMuU3VjY2Vzc0V2ZW50LCB7XG5cdFx0XHRcdFN1Ym1pdFBheW1lbnRGb3JCb3BpczogdHJ1ZSxcblx0XHRcdFx0SXNCb3Bpc0ludmVudG9yeVZhbGlkOiBpc0JvcGlzSW52ZW50b3J5VmFsaWRcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyIG9wdGlvbnM7XG52YXIgZGF0YUJ1ZmZlcjtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdGRhdGFCdWZmZXIgPSB7fTtcblx0b3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRzdWNjZXNzQ2FsbGJhY2s6IG51bGwsXG5cdFx0ZXJyb3JDYWxsYmFjazogbnVsbFxuXHR9LCBvcHRpb25zUGFyYW1ldGVyKTtcblxuXHQkKCcjc2hvcC15b3VyLXN0b3JlLWRpYWxvZycpLmZpbmQoJy5zdG9yZS1uYW1lJykudGV4dChvcHRpb25zLlN0b3JlTmFtZSk7XG5cdCQoJyNzaG9wLXlvdXItc3RvcmUtZGlhbG9nJykuZmluZCgnLmNhdGVnb3J5LWxpbmtzIGEnKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgaHJlZiA9ICR0aGlzLmF0dHIoJ2hyZWYnKTtcblx0XHRpZiAoaHJlZi5pbmRleE9mKCc/JykgPiAtMSkge1xuXHRcdFx0aHJlZiA9IGhyZWYuc3Vic3RyKDAsIGhyZWYuaW5kZXhPZignPycpKTtcblx0XHR9XG5cdFx0JHRoaXMuYXR0cignaHJlZicsIGhyZWYgKyAnP3ByZWZuMT1hdmFpbGFibGVTdG9yZXMmcHJlZnYxPScgKyBvcHRpb25zLlN0b3JlSWQgKyAnJnNob3BteXN0b3JlPXRydWUnKTtcblx0fSlcblx0XG5cdC8vIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckV2ZW50KCdyb2FkaWVGb3JtRGlzcGxheScpO1xuXHRkaWFsb2cub3Blbih7XG5cdFx0aHRtbDogJCgnI3Nob3AteW91ci1zdG9yZS1kaWFsb2cnKS5odG1sKCksXG5cdFx0b3B0aW9uczoge1xuXHRcdFx0ZGlhbG9nQ2xhc3M6ICdzaG9wLXlvdXItc3RvcmUtZGlhbG9nJyxcblx0XHRcdHdpZHRoOiAzODAsXG5cdFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHR2YXIgJHNob3BZb3VyU3RvcmVUb2dnbGUgPSAkdGhpcy5maW5kKCcuc2hvcC1teS1zdG9yZS10b2dnbGUgLmNoZWNrYm94LXRvZ2dsZScpO1xuXHRcdFx0XHRkYXRhQnVmZmVyWyd0b2dnbGVUaW1lciddID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JHNob3BZb3VyU3RvcmVUb2dnbGUuY2xpY2soKTtcblx0XHRcdFx0fSwgMjAwMCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHRjbGVhckludGVydmFsKGRhdGFCdWZmZXJbJ3RvZ2dsZVRpbWVyJ10pO1xuXHRcdFx0XHQkKHRoaXMpLmZpbmQoJy5zaG9wLW15LXN0b3JlLXRvZ2dsZSAuY2hlY2tib3gtdG9nZ2xlIGlucHV0JykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblx0XHR9XG5cdH0pO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgTG9jYWxEZWxpdmVyeURpYWxvZyA9IHJlcXVpcmUoJy4vTG9jYWxEZWxpdmVyeURpYWxvZycpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyk7XG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcbnZhciBaaXBDb2RlVG9TdGF0ZU1hcCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvZGF0YS9aaXBDb2RlVG9TdGF0ZU1hcC5qc29uJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5leHBvcnRzLnNlYXJjaCA9IHNlYXJjaDtcbmV4cG9ydHMucmVtb3ZlID0gcmVtb3ZlO1xuXG52YXIgb3B0aW9ucztcbnZhciB2YWxpZGF0b3I7XG52YXIgZGF0YUJ1ZmZlcjtcblxudmFyIHJlc3VsdENvbnRhaW5lclRlbXBsYXRlO1xudmFyIHJlc3VsdEl0ZW1UZW1wbGF0ZTtcbnZhciBsb2NhbERlbGl2ZXJ5RGVjb3JhdG9yO1xuXG52YXIgJGNvbnRhaW5lcjtcbnZhciAkZm9ybTtcbnZhciAkcmVzdWx0O1xudmFyICRmb3JtSW5wdXRQb3N0YWxDb2RlO1xudmFyICRzdG9yZVNlYXJjaEJ1dHRvbjtcbnZhciAkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXI7XG52YXIgJGJvcGlzQnV0dG9uO1xudmFyICRlcnJvck1lc3NhZ2U7XG52YXIgJGlucHV0VG9vbHRpcDtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgkY29udGFpbmVyUGFyYW1ldGVyLCBvcHRpb25zUGFyYW1ldGVyKSB7XG5cdGRhdGFCdWZmZXIgPSB7fTtcblx0b3B0aW9ucyA9ICQuZXh0ZW5kKHtcblx0XHRzdWNjZXNzQ2FsbGJhY2s6IG51bGwsXG5cdFx0ZXJyb3JDYWxsYmFjazogbnVsbFxuXHR9LCBvcHRpb25zUGFyYW1ldGVyKTtcblxuXHRyZXN1bHRDb250YWluZXJUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1jb250YWluZXInKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdHJlc3VsdEl0ZW1UZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1pdGVtJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHRsb2NhbERlbGl2ZXJ5RGVjb3JhdG9yID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtbG9jYWxkZWxpdmVyeS1kZWNvcmF0b3InKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cblx0JGNvbnRhaW5lciA9ICRjb250YWluZXJQYXJhbWV0ZXI7XG5cdCRmb3JtID0gJGNvbnRhaW5lci5maW5kKCdmb3JtJyk7XG5cdCRyZXN1bHQgPSAkY29udGFpbmVyLmZpbmQoJy5yZXN1bHQnKTtcblx0JGZvcm1JbnB1dFBvc3RhbENvZGUgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxDb2RlXCJdJyk7XG5cdCRzdG9yZVNlYXJjaEJ1dHRvbiA9ICRjb250YWluZXIuZmluZCgnLmJ0bi5zdG9yZS1zZWFyY2gnKTtcblx0JHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyID0gJGNvbnRhaW5lci5maW5kKCcuYnRuLXN0b3JlLXNlYXJjaC1jb250YWluZXInKTtcblx0JGJvcGlzQnV0dG9uID0gJGNvbnRhaW5lci5maW5kKCcuYnRuLmJvcGlzJyk7XG4gICAgJGVycm9yTWVzc2FnZSA9ICRmb3JtLmZpbmQoJ3NwYW4uZXJyb3InKTtcblx0JGlucHV0VG9vbHRpcCA9ICRmb3JtSW5wdXRQb3N0YWxDb2RlLnBhcmVudCgpO1xuXG4gICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Jc1ZhcmlhbnRTZWxlY3RlZCkge1xuXHRcdCQoJy5idG4uc3RvcmUtc2VhcmNoJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHQkaW5wdXRUb29sdGlwLnJlbW92ZUNsYXNzKCd0b29sdGlwJyk7XG4gICAgfVxuXG5cdHRvb2x0aXAuaW5pdCh7XG5cdFx0aXRlbXM6ICcuc3RvcmUtc2VhcmNoLXRvb2x0aXAnLFxuXHRcdHRvb2x0aXBDbGFzczogJ3N0b3JlLXNlYXJjaC10b29sdGlwJ1xuXHR9LCAkKCcuc3RvcmUtc2VhcmNoLXRvb2x0aXAnKSk7XG5cbiAgICAkY29udGFpbmVyLmF0dHIoJ3N0YXRlJywgJ2Zvcm0nKTtcbiAgICB2YWxpZGF0b3IgPSAkZm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCd6aXBDb2RlJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVppcENvZGUsIFJlc291cmNlcy5JTlZBTElEX1BPU1RBTF9DT0RFKTtcbiAgICAkZm9ybUlucHV0UG9zdGFsQ29kZS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlppcENvZGUpO1xuXG5cdGlmICgkY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJyAmJiB2YWxpZGF0b3IuY2hlY2tGb3JtKCkgJiYgISRzdG9yZVNlYXJjaEJ1dHRvbi5oYXNDbGFzcygncmVhZHknKSkge1xuXHRcdCRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcbiAgICB9XG5cbiAgICAkZm9ybS5vZmYoJ2NsaWNrLmFwcGx5Jykub24oJ2NsaWNrLmFwcGx5JywgJy5idG4uc3RvcmUtc2VhcmNoOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRzZWFyY2goKTtcblx0fSk7XG5cbiAgICAkY29udGFpbmVyLm9mZignY2xpY2suYXBwbHknKS5vbignY2xpY2suYXBwbHknLCAnLmJ0bi5ib3Bpczpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgc2VsZWN0ZWRMb2NhdGlvbiA9IGRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddWyQoJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdOmNoZWNrZWQnKS52YWwoKV07XG5cdFx0aWYgKHNlbGVjdGVkTG9jYXRpb24pIHtcblx0XHRcdGlmIChvcHRpb25zLkxvY2FsRGVsaXZlcnkuRW5hYmxlZCkge1xuXHRcdFx0XHRMb2NhbERlbGl2ZXJ5RGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgc2VsZWN0ZWRMb2NhdGlvbik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCB7IGJvcGlzOiB0cnVlLCBzaGlwcGluZ09wdGlvbjogJ3BpY2t1cCcsIGNoYW5uZWw6IG9wdGlvbnMuQ2hhbm5lbCB9KTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuQm9waXMuQWRkVG9DYXJ0JywgeyBjaGFubmVsOiBvcHRpb25zLkNoYW5uZWwgfSk7XG5cdFx0fVxuXHR9KTtcblxuICAgICRmb3JtSW5wdXRQb3N0YWxDb2RlLm9mZigna2V5ZG93bi5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdrZXlkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgXHRpZiAoJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkubGVuZ3RoID09IDUgJiYgcGFyc2VJbnQoZXZlbnQua2V5LCAxMCkgPT0gZXZlbnQua2V5ICYmICF3aW5kb3cuZ2V0U2VsZWN0aW9uKCkudG9TdHJpbmcoKSkge1xuICAgIFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0fVxuICAgIH0pO1xuXG4gICAgJGZvcm1JbnB1dFBvc3RhbENvZGUub2ZmKCdjaGFuZ2UuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2snKS5vbignY2hhbmdlLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgXHRpZiAoJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkubGVuZ3RoID4gNSkge1xuICAgIFx0XHQkZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoJGZvcm1JbnB1dFBvc3RhbENvZGUudmFsKCkuc3Vic3RyKDAsIDUpKTtcbiAgICBcdH1cbiAgICB9KTtcblxuICAgICRmb3JtSW5wdXRQb3N0YWxDb2RlLm9mZigna2V5dXAuQm9waXNTdG9yZVNlYXJjaC5WYWxpZGF0aW9uQ2hlY2ssIGNoYW5nZS5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaycpLm9uKCdrZXl1cC5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DaGVjaywgY2hhbmdlLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNoZWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgXHRldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblxuXHRcdGlmICgkY29udGFpbmVyLmF0dHIoJ3N0YXRlJykgPT09ICdmb3JtJykge1xuXHRcdFx0aWYgKHZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAhJHN0b3JlU2VhcmNoQnV0dG9uLmhhc0NsYXNzKCdyZWFkeScpKSB7XG5cdFx0XHRcdCRzdG9yZVNlYXJjaEJ1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcblx0XHRcdH0gZWxzZSBpZiAoIXZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAkc3RvcmVTZWFyY2hCdXR0b24uaGFzQ2xhc3MoJ3JlYWR5JykpIHtcblx0XHRcdFx0JHN0b3JlU2VhcmNoQnV0dG9uLnJlbW92ZUNsYXNzKCdyZWFkeScpO1xuXHRcdFx0fVxuXHRcdH1cblxuICAgIFx0aWYgKCRjb250YWluZXIuYXR0cignc3RhdGUnKSA9PT0gJ3Jlc3VsdCcpIHtcblx0XHRcdCRjb250YWluZXIuYXR0cignc3RhdGUnLCAnZm9ybScpO1xuICAgICAgICBcdCRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgnJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkJvcGlzU3RvcmVTZWFyY2guVmFsaWRhdGlvbkNsZWFyJykub24oJ21vdXNlZG93bi5Cb3Bpc1N0b3JlU2VhcmNoLlZhbGlkYXRpb25DbGVhcicsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAodmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCRjb250YWluZXIpLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICB2YWxpZGF0b3IucmVzZXRGb3JtKCk7XG4gICAgICAgICAgICAkZXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdCb3Bpcy5TdG9yZVNlYXJjaC5SZXNldCcpLm9uKCdCb3Bpcy5TdG9yZVNlYXJjaC5SZXNldCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHJlc2V0KCk7XG4gICAgfSk7XG5cbiAgICAkY29udGFpbmVyLm9mZignY2xpY2suQm9waXNTdG9yZVNlYXJjaC5SZXNldCcpLm9uKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlJlc2V0JywgJy5yZXNldCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHJlc2V0KCk7XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ1Byb2R1Y3REZXRhaWxQYWdlLlZhcmlhbnQuU3RvcmVTZWFyY2gnKS5vbignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5TdG9yZVNlYXJjaCcsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAob3B0aW9ucy5TZWxlY3RlZExvY2F0aW9ucykge1xuXHRcdFx0dmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdFx0XHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0XHR2YXIgd2lkdGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLndpZHRoLndpZHRoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0XHR2YXIgaXNTaXplU2VsZWN0ZWQgPSBzaXplU2VsZWN0ZWQubGVuZ3RoIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKTtcblx0XHRcdHZhciBpc0NvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXG5cdFx0XHRpZiAoaXNTaXplU2VsZWN0ZWQgJiYgaXNDb2xvclNlbGVjdGVkKSB7XG5cdFx0XHRcdHNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdH1cbiAgICB9KTtcblxuICAgICRjb250YWluZXIub2ZmKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlNlbGVjdGlvbicpLm9uKCdjbGljay5Cb3Bpc1N0b3JlU2VhcmNoLlNlbGVjdGlvbicsICdpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfU3RvcmVJZFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgYm9waXNTdG9yZSA9ICQoJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdOmNoZWNrZWQnKS52YWwoKTtcblxuICAgICAgICBpZiAoISRib3Bpc0J1dHRvbi5oYXNDbGFzcygncmVhZHknKSkge1xuICAgICAgICBcdCRib3Bpc0J1dHRvbi5hZGRDbGFzcygncmVhZHknKTtcbiAgICAgICAgfVxuXG4gICAgICAgICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXG4gICAgICAgIGlmIChib3Bpc1N0b3JlKSB7XG4gICAgICAgIFx0JGJvcGlzQnV0dG9uLmF0dHIoJ3N0YXRlJywgJ3BpY2t1cCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICBcdCRib3Bpc0J1dHRvbi5hdHRyKCdzdGF0ZScsICdzaGlwJyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcmVzZXQoKSB7XG5cdCRmb3JtSW5wdXRQb3N0YWxDb2RlLnZhbCgnJyk7XG4gICAgJGNvbnRhaW5lci5hdHRyKCdzdGF0ZScsICdmb3JtJyk7XG4gICAgJHN0b3JlU2VhcmNoQnV0dG9uLnJlbW92ZUNsYXNzKCdyZWFkeScpO1xuICAgICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgICRib3Bpc0J1dHRvbi5yZW1vdmVDbGFzcygncmVhZHknKTtcbn1cblxuZnVuY3Rpb24gc2VhcmNoKCkge1xuXHR2YXIgc2l6ZVNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuc2l6ZS5zaXplLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKTtcblx0dmFyIGxlbmd0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAubGVuZ3RoLmxlbmd0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHR2YXIgd2lkdGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLndpZHRoLndpZHRoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciBpc1NpemVTZWxlY3RlZCA9IHNpemVTZWxlY3RlZC5sZW5ndGggfHwgKGxlbmd0aFNlbGVjdGVkICYmIHdpZHRoU2VsZWN0ZWQpO1xuXHR2YXIgaXNDb2xvclNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuY29sb3IuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblxuICAgIGlmICghaXNTaXplU2VsZWN0ZWQgJiYgIWlzQ29sb3JTZWxlY3RlZCkge1xuICAgIFx0JGVycm9yTWVzc2FnZS5odG1sKCdQbGVhc2Ugc2VsZWN0IGEgc2l6ZSBhbmQgY29sb3IgZmlyc3QuJykuc2hvdygpO1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSBpZiAoIWlzU2l6ZVNlbGVjdGVkKSB7XG4gICAgXHQkZXJyb3JNZXNzYWdlLmh0bWwoJ1BsZWFzZSBzZWxlY3QgYSBzaXplIGZpcnN0LicpLnNob3coKTtcbiAgICBcdHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2UgaWYgKCFpc0NvbG9yU2VsZWN0ZWQpIHtcbiAgICBcdCRlcnJvck1lc3NhZ2UuaHRtbCgnUGxlYXNlIHNlbGVjdCBhIGNvbG9yIGZpcnN0LicpLnNob3coKTtcbiAgICBcdHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgIFx0JGVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG4gICAgXHQkc3RvcmVTZWFyY2hCdXR0b24ucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICB9XG5cbiAgICBpZiAoVXJscyAmJiBVcmxzLkJvcGlzLkdldFN0b3JlSW52ZW50b3J5Rm9yUHJvZHVjdEZvclBvc3RhbENvZGUgJiYgdmFsaWRhdG9yLnZhbGlkKCkpIHtcbiAgICAgICAgJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmxvYWRpbmcoe1xuICAgICAgICAgICAgSXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRcdExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5Mb2FkaW5nLFxuXHRcdFx0QmFja2dyb3VuZENvbG9yOiAkc3RvcmVTZWFyY2hCdXR0b24uY3NzKCdiYWNrZ3JvdW5kLWNvbG9yJylcbiAgICAgICAgfSk7XG5cblx0XHQkLmFqYXgoe1xuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6IFVybHMuQm9waXMuR2V0U3RvcmVJbnZlbnRvcnlGb3JQcm9kdWN0Rm9yUG9zdGFsQ29kZSxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdENoYW5uZWw6IG9wdGlvbnMuQ2hhbm5lbCxcblx0XHRcdFx0U291cmNlOiBvcHRpb25zLlNvdXJjZSxcbiAgICAgICAgICAgICAgICBQcm9kdWN0SWQ6ICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJwaWRcIl0nKS52YWwoKSxcbiAgICAgICAgICAgICAgICBQb3N0YWxDb2RlOiAkZm9ybUlucHV0UG9zdGFsQ29kZS52YWwoKVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoJHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmF0dHIoJ2xvYWRpbmcnKSkge1xuICAgICAgICAgICAgICAgIFx0JHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGlucXVpcnlSZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5TZXJ2aWNlU3VjY2Vzc2Z1bGx5Q2FsbGVkICYmIGRhdGEuSW5xdWlyeVJlc3VsdCAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YSAmJiBkYXRhLklucXVpcnlSZXN1bHQuZGF0YS5sZW5ndGggPiAwICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhWzBdLmludmVudG9yeV9zdXBwbGllcykge1xuICAgICAgICAgICAgICAgICAgICBpbnF1aXJ5UmVzdWx0ID0gZGF0YS5JbnF1aXJ5UmVzdWx0LmRhdGFbMF0uaW52ZW50b3J5X3N1cHBsaWVzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG4gICAgICAgICAgICAgICAgaWYgKGlucXVpcnlSZXN1bHQgJiYgaW5xdWlyeVJlc3VsdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgXHRkYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsIGlucXVpcnlSZXN1bHQubGVuZ3RoKTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgc3RvcmVMaXN0SHRtbCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXNTdG9yZVNlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZFN0b3JlQXR0cmlidXRlO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpbnZlbnRvcnlSZWNvcmRFbGVtZW50IGluIGlucXVpcnlSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgXHR2YXIgaW52ZW50b3J5UmVjb3JkID0gaW5xdWlyeVJlc3VsdFtpbnZlbnRvcnlSZWNvcmRFbGVtZW50XTtcblxuICAgICAgICAgICAgICAgICAgICBcdGlmIChpbnZlbnRvcnlSZWNvcmQuZGV0YWlsICYmIGludmVudG9yeVJlY29yZC5kZXRhaWwucXVhbnRpdHkgPiAwICYmICFkYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24uY29kZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuU2VsZWN0ZWRMb2NhdGlvbnMgPT0gaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgXHRcdFx0aXNTdG9yZVNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgXHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9J2NoZWNrZWQnO1xuICAgICAgICAgICAgICAgICAgICBcdFx0fSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgXHRcdFx0c2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBcdFx0fVxuXG4gICAgICAgICAgICAgICAgICAgIFx0XHR2YXIgbG9jYWxEZWxpdmVyeUh0bWwgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgXHRcdGlmIChvcHRpb25zLkxvY2FsRGVsaXZlcnkuRW5hYmxlZCAmJiBpc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKGludmVudG9yeVJlY29yZC5sb2NhdGlvbikgJiYgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X2VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgXHRcdFx0bG9jYWxEZWxpdmVyeUh0bWwgPSBsb2NhbERlbGl2ZXJ5RGVjb3JhdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0dmFyIGxhYmVsUHJlZml4O1xuXHRcdFx0XHRcdFx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLklzU3RvcmVIb2xpZGF5KSB7XG5cdFx0XHRcdFx0XHRcdFx0bGFiZWxQcmVmaXggPSAnQXZhaWxhYmxlIEF0ICc7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0bGFiZWxQcmVmaXggPSAnQXZhaWxhYmxlIFRPREFZIEF0ICc7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRpZiAoaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLm5hbWVQcmVmaXgpIHtcblx0XHRcdFx0XHRcdFx0XHRsYWJlbFByZWZpeCArPSAnPHNwYW4gY2xhc3M9XCJub3dyYXBcIj4nICsgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLm5hbWVQcmVmaXggKyAnPC9zcGFuPiAnO1xuXHRcdFx0XHRcdFx0XHR9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIFx0c3RvcmVMaXN0SHRtbCArPSByZXN1bHRJdGVtVGVtcGxhdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgXHRcdFN0b3JlSWQ6IGludmVudG9yeVJlY29yZC5sb2NhdGlvbi5jb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgXHRcdFF1YW50aXR5QXZhaWxhYmxlOiBpbnZlbnRvcnlSZWNvcmQuZGV0YWlsLnF1YW50aXR5LFxuXHQgICAgICAgICAgICAgICAgICAgICAgICBcdEh0bWw6IGxhYmVsUHJlZml4ICsgaW52ZW50b3J5UmVjb3JkLmxvY2F0aW9uLnBvc3RhbF9hZGRyZXNzLm5hbWUgKyAnLDxici8+JyArIGludmVudG9yeVJlY29yZC5sb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5hZGRyZXNzX2xpbmUxICsgJywgJyArIGludmVudG9yeVJlY29yZC5sb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5jaXR5ICsgJywgJyArIGludmVudG9yeVJlY29yZC5sb2NhdGlvbi5wb3N0YWxfYWRkcmVzcy5wcm92aW5jZV9vcl9zdGF0ZSxcblx0ICAgICAgICAgICAgICAgICAgICAgICAgXHRTZWxlY3RlZDogc2VsZWN0ZWRTdG9yZUF0dHJpYnV0ZSxcblx0ICAgICAgICAgICAgICAgICAgICAgICAgXHRMb2NhbERlbGl2ZXJ5OiBsb2NhbERlbGl2ZXJ5SHRtbFxuXHQgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgXHR9XG5cbiAgICAgICAgICAgICAgICAgICAgXHRkYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXVtpbnZlbnRvcnlSZWNvcmQubG9jYXRpb24uY29kZV0gPSBpbnZlbnRvcnlSZWNvcmQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3RvcmVMaXN0SHRtbCArPSByZXN1bHRJdGVtVGVtcGxhdGUoe1xuICAgICAgICAgICAgICAgICAgICBcdFN0b3JlSWQ6ICcnLFxuICAgICAgICAgICAgICAgICAgICBcdFF1YW50aXR5QXZhaWxhYmxlOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgXHRIdG1sOiAnU2hpcCBJbnN0ZWFkJyxcbiAgICAgICAgICAgICAgICAgICAgXHRTZWxlY3RlZDogJycsXG4gICAgICAgICAgICAgICAgICAgIFx0TG9jYWxEZWxpdmVyeTogJydcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdEh0bWwgPSByZXN1bHRDb250YWluZXJUZW1wbGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIFx0SHRtbDogc3RvcmVMaXN0SHRtbFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdG9yZVNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIFx0JGJvcGlzQnV0dG9uLmFkZENsYXNzKCdyZWFkeScpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgJHJlc3VsdC5odG1sKHJlc3VsdEh0bWwpO1xuXG5cdFx0XHRcdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdCAgICAgICAgXHRpdGVtczogJy50b29sdGlwJ1xuICAgICAgICAgICAgICAgIFx0fSwgJHJlc3VsdCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3VjY2Vzc0NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIFx0b3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2soaW5xdWlyeVJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLmF0dHIoJ3Jlc3VsdC1jb3VudCcsICcwJyk7XG4gICAgICAgICAgICAgICAgXHQkcmVzdWx0Lmh0bWwoJycpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgXHRvcHRpb25zLmVycm9yQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICgkc3RvcmVTZWFyY2hCdXR0b25Db250YWluZXIuYXR0cignbG9hZGluZycpKSB7XG4gICAgICAgICAgICBcdFx0JHN0b3JlU2VhcmNoQnV0dG9uQ29udGFpbmVyLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIFx0b3B0aW9ucy5lcnJvckNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW1vdmUoKSB7XG5cdHZhbGlkYXRvci5kZXN0cm95KCk7XG5cdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xufVxuXG5mdW5jdGlvbiBpc0xvY2F0aW9uSW5Mb2NhbERlbGl2ZXJ5UmFkaXVzKGxvY2F0aW9uKSB7XG5cdHZhciBsb2NhbERlbGl2ZXJ5UmFkaXVzO1xuXHRpZiAobG9jYXRpb24ubG9jYWxfZGVsaXZlcnlfdmVuZG9yICYmIGxvY2F0aW9uLmxvY2FsX2RlbGl2ZXJ5X3ZlbmRvciA9PSAnR29Mb2NhbCcpIHtcblx0XHRsb2NhbERlbGl2ZXJ5UmFkaXVzID0gb3B0aW9ucy5Mb2NhbERlbGl2ZXJ5LlJhZGl1c0ZvckdvTG9jYWw7XG5cdH0gZWxzZSB7XG5cdFx0bG9jYWxEZWxpdmVyeVJhZGl1cyA9IG9wdGlvbnMuTG9jYWxEZWxpdmVyeS5SYWRpdXNGb3JSb2FkaWU7XG5cdH1cdFxuXG5cdGlmIChsb2NhbERlbGl2ZXJ5UmFkaXVzICYmIGxvY2F0aW9uICYmIGxvY2F0aW9uLmRpc3RhbmNlICYmIGxvY2FsRGVsaXZlcnlSYWRpdXMgPj0gbG9jYXRpb24uZGlzdGFuY2UpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbnZhciBTZXNzaW9uQXR0cmlidXRlcyA9IHdpbmRvdy5TZXNzaW9uQXR0cmlidXRlcztcblxuLyoqXG4gKiBAZnVuY3Rpb24gY2FwdGNoYSAgICBVc2VkIHRvIGRpc3BsYXkvY29udHJvbCB0aGUgc2NyaW0gY29udGFpbmluZyB0aGUgc2ltdWxhdGVkIGNhcHRjaGEgY29kZVxuICoqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdC8qKlxuXHQgKiBpZiB0aGUgc2Vzc2lvbi5wcml2YWN5LnJhdGVsaW1pdGVkIGVsZW1lbnQgaXMgcHJlc2VudCB0aGVuIHNob3cgdGhlIG5vdGlmaWNhdGlvblxuXHQgKiBOT1RFOiBZb3Ugd2lsbCBwcm9iYWJseSB3YW50IHRvIHJlcGxhY2UgdGhpcyB3aXRoIGEgY2FsbCB0byBhbiBhY3R1YWwgQ0FQVENIQSBzeXN0ZW0gdG8gcmVwbGFjZSB0aGUgc2ltcGxlIG9uZSBoZXJlXG5cdCAqL1xuXHRpZiAoU2Vzc2lvbkF0dHJpYnV0ZXMuU0hPV19DQVBUQ0hBKSB7XG5cdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0aHRtbDogJzxwPicgKyBSZXNvdXJjZXMuUEFTU1dPUkRfVElQXzEgKyAnPC9wPjxwPicgKyBSZXNvdXJjZXMuUEFTU1dPUkRfVElQXzIgKyAnPC9wPicsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdHRpdGxlOiBSZXNvdXJjZXMuQVJFX1lPVV9IVU1BTixcblx0XHRcdFx0Y2xvc2VPbkVzY2FwZTogZmFsc2UsXG5cdFx0XHRcdGRpYWxvZ0NsYXNzOiAnbm8tY2xvc2UgcGFzc3dvcmQtZXJyb3InLFxuXHRcdFx0XHR3aWR0aDogNDAwLFxuXHRcdFx0XHRidXR0b25zOiBbe1xuXHRcdFx0XHRcdHRleHQ6IFJlc291cmNlcy5PSyxcblx0XHRcdFx0XHRjbGljazogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0dmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5yYXRlTGltaXRlclJlc2V0LCB7Zm9ybWF0OiAnYWpheCd9KTtcblx0XHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHRcdHVybDogdXJsXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdCQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fV1cblx0XHRcdH1cblx0XHR9KTtcblx0fVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHBhZ2UgPSByZXF1aXJlKCcuL3BhZ2UnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyksXG4gICAgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG5cbnZhciBfY3VycmVudENhdGVnb3J5ID0gJycsXG4gICAgTUFYX0FDVElWRSA9IDY7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFZlcmlmaWVzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIGNvbXBhcmUgY29udGFpbmVyIGFuZCB1cGRhdGVzIGl0IHdpdGggc2VxdWVudGlhbCBjbGFzc2VzIGZvciB1aSB0YXJnZXRpbmdcbiAqL1xuZnVuY3Rpb24gcmVmcmVzaENvbnRhaW5lcigpIHtcbiAgICB2YXIgJGNvbXBhcmVDb250YWluZXIgPSAkKCcuY29tcGFyZS1pdGVtcycpO1xuICAgIHZhciAkY29tcGFyZUl0ZW1zID0gJGNvbXBhcmVDb250YWluZXIuZmluZCgnLmNvbXBhcmUtaXRlbScpO1xuICAgIHZhciBudW1BY3RpdmUgPSAkY29tcGFyZUl0ZW1zLmZpbHRlcignLmFjdGl2ZScpLmxlbmd0aDtcblxuICAgIGlmIChudW1BY3RpdmUgPCAyKSB7XG4gICAgICAgICQoJyNjb21wYXJlLWl0ZW1zLWJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJCgnI2NvbXBhcmUtaXRlbXMtYnV0dG9uJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICB9XG5cbiAgICAkY29tcGFyZUNvbnRhaW5lci50b2dnbGUobnVtQWN0aXZlID4gMCk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBBZGRzIGFuIGl0ZW0gdG8gdGhlIGNvbXBhcmUgY29udGFpbmVyIGFuZCByZWZyZXNoZXMgaXRcbiAqL1xuZnVuY3Rpb24gYWRkVG9MaXN0KGRhdGEpIHtcbiAgICAvLyBnZXQgdGhlIGZpcnN0IGNvbXBhcmUtaXRlbSBub3QgY3VycmVudGx5IGFjdGl2ZVxuICAgIHZhciAkaXRlbSA9ICQoJy5jb21wYXJlLWl0ZW1zIC5jb21wYXJlLWl0ZW0nKS5ub3QoJy5hY3RpdmUnKS5maXJzdCgpLFxuICAgICAgICAkcHJvZHVjdFRpbGUgPSAkKCcjJyArIGRhdGEudXVpZCk7XG5cbiAgICBpZiAoJGl0ZW0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlmICgkcHJvZHVjdFRpbGUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJHByb2R1Y3RUaWxlLmZpbmQoJy5jb21wYXJlLWNoZWNrJylbMF0uY2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQ09NUEFSRV9BRERfRkFJTCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBpZiBhbHJlYWR5IGFkZGVkIHNvbWVob3csIHJldHVyblxuICAgIGlmICgkKCdbZGF0YS11dWlkPVwiJyArIGRhdGEudXVpZCArICdcIl0nKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gc2V0IGFzIGFjdGl2ZSBpdGVtXG4gICAgJGl0ZW0uYWRkQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAgIC5hdHRyKCdkYXRhLXV1aWQnLCBkYXRhLnV1aWQpXG4gICAgICAgIC5hdHRyKCdkYXRhLWl0ZW1pZCcsIGRhdGEuaXRlbWlkKVxuICAgICAgICAuZGF0YSgndXVpZCcsIGRhdGEudXVpZClcbiAgICAgICAgLmRhdGEoJ2l0ZW1pZCcsIGRhdGEuaXRlbWlkKVxuICAgICAgICAuYXBwZW5kKCQoZGF0YS5pbWcpLmNsb25lKCkuYWRkQ2xhc3MoJ2NvbXBhcmUtaXRlbS1pbWFnZScpKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogZGVzY3JpcHRpb24gUmVtb3ZlcyBhbiBpdGVtIGZyb20gdGhlIGNvbXBhcmUgY29udGFpbmVyIGFuZCByZWZyZXNoZXMgaXRcbiAqL1xuZnVuY3Rpb24gcmVtb3ZlRnJvbUxpc3QoJGl0ZW0pIHtcbiAgICBpZiAoJGl0ZW0ubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuICAgIC8vIHJlbW92ZSBjbGFzcywgZGF0YSBhbmQgaWQgZnJvbSBpdGVtXG4gICAgJGl0ZW0ucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAgIC5yZW1vdmVBdHRyKCdkYXRhLXV1aWQnKVxuICAgICAgICAucmVtb3ZlQXR0cignZGF0YS1pdGVtaWQnKVxuICAgICAgICAuZGF0YSgndXVpZCcsICcnKVxuICAgICAgICAuZGF0YSgnaXRlbWlkJywgJycpXG4gICAgICAgIC8vIHJlbW92ZSB0aGUgaW1hZ2VcbiAgICAgICAgLmZpbmQoJy5jb21wYXJlLWl0ZW0taW1hZ2UnKS5yZW1vdmUoKTtcbn1cblxuZnVuY3Rpb24gYWRkUHJvZHVjdEFqYXgoYXJncykge1xuICAgIHZhciBwcm9taXNlID0gbmV3IFRQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogVXJscy5jb21wYXJlQWRkLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHBpZDogYXJncy5pdGVtaWQsXG4gICAgICAgICAgICAgICAgY2F0ZWdvcnk6IF9jdXJyZW50Q2F0ZWdvcnlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nXG4gICAgICAgIH0pLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlIHx8ICFyZXNwb25zZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihSZXNvdXJjZXMuQ09NUEFSRV9BRERfRkFJTCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuZmFpbChmdW5jdGlvbiAoanF4aHIsIHN0YXR1cywgZXJyKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGVycikpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcHJvbWlzZTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlUHJvZHVjdEFqYXgoYXJncykge1xuICAgIHZhciBwcm9taXNlID0gbmV3IFRQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogVXJscy5jb21wYXJlUmVtb3ZlLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHBpZDogYXJncy5pdGVtaWQsXG4gICAgICAgICAgICAgICAgY2F0ZWdvcnk6IF9jdXJyZW50Q2F0ZWdvcnlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nXG4gICAgICAgIH0pLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlIHx8ICFyZXNwb25zZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihSZXNvdXJjZXMuQ09NUEFSRV9SRU1PVkVfRkFJTCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuZmFpbChmdW5jdGlvbiAoanF4aHIsIHN0YXR1cywgZXJyKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGVycikpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcHJvbWlzZTtcbn1cblxuZnVuY3Rpb24gc2hpZnRJbWFnZXMoKSB7XG4gICAgcmV0dXJuIG5ldyBUUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICB2YXIgJGl0ZW1zID0gJCgnLmNvbXBhcmUtaXRlbXMgLmNvbXBhcmUtaXRlbScpO1xuICAgICAgICAkaXRlbXMuZWFjaChmdW5jdGlvbiAoaSwgaXRlbSkge1xuICAgICAgICAgICAgdmFyICRpdGVtID0gJChpdGVtKTtcbiAgICAgICAgICAgIC8vIGxhc3QgaXRlbVxuICAgICAgICAgICAgaWYgKGkgPT09ICRpdGVtcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZUZyb21MaXN0KCRpdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciAkbmV4dCA9ICRpdGVtcy5lcShpICsgMSk7XG4gICAgICAgICAgICBpZiAoJG5leHQuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0cyBvd24gaW1hZ2VcbiAgICAgICAgICAgICAgICAkbmV4dC5maW5kKCcuY29tcGFyZS1pdGVtLWltYWdlJykuZGV0YWNoKCkuYXBwZW5kVG8oJGl0ZW0pO1xuICAgICAgICAgICAgICAgICRpdGVtLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cignZGF0YS11dWlkJywgJG5leHQuZGF0YSgndXVpZCcpKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cignZGF0YS1pdGVtaWQnLCAkbmV4dC5kYXRhKCdpdGVtaWQnKSlcbiAgICAgICAgICAgICAgICAgICAgLmRhdGEoJ3V1aWQnLCAkbmV4dC5kYXRhKCd1dWlkJykpXG4gICAgICAgICAgICAgICAgICAgIC5kYXRhKCdpdGVtaWQnLCAkbmV4dC5kYXRhKCdpdGVtaWQnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQWRkcyBwcm9kdWN0IHRvIHRoZSBjb21wYXJlIHRhYmxlXG4gKi9cbmZ1bmN0aW9uIGFkZFByb2R1Y3QoYXJncykge1xuICAgIHZhciBwcm9taXNlO1xuICAgIHZhciAkaXRlbXMgPSAkKCcuY29tcGFyZS1pdGVtcyAuY29tcGFyZS1pdGVtJyk7XG4gICAgdmFyICRjYiA9ICQoYXJncy5jYik7XG4gICAgdmFyIG51bUFjdGl2ZSA9ICRpdGVtcy5maWx0ZXIoJy5hY3RpdmUnKS5sZW5ndGg7XG4gICAgaWYgKG51bUFjdGl2ZSA9PT0gTUFYX0FDVElWRSkge1xuICAgICAgICBpZiAoIXdpbmRvdy5jb25maXJtKFJlc291cmNlcy5DT01QQVJFX0NPTkZJUk1BVElPTikpIHtcbiAgICAgICAgICAgICRjYlswXS5jaGVja2VkID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZW1vdmUgcHJvZHVjdCB1c2luZyBpZFxuICAgICAgICB2YXIgJGZpcnN0SXRlbSA9ICRpdGVtcy5maXJzdCgpO1xuICAgICAgICBwcm9taXNlID0gcmVtb3ZlSXRlbSgkZmlyc3RJdGVtKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzaGlmdEltYWdlcygpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcm9taXNlID0gVFByb21pc2UucmVzb2x2ZSgwKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBhZGRQcm9kdWN0QWpheChhcmdzKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGFkZFRvTGlzdChhcmdzKTtcbiAgICAgICAgICAgIGlmICgkY2IgJiYgJGNiLmxlbmd0aCA+IDApIHsgJGNiWzBdLmNoZWNrZWQgPSB0cnVlOyB9XG4gICAgICAgICAgICByZWZyZXNoQ29udGFpbmVyKCk7XG4gICAgICAgIH0pO1xuICAgIH0pLnRoZW4obnVsbCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoJGNiICYmICRjYi5sZW5ndGggPiAwKSB7ICRjYlswXS5jaGVja2VkID0gZmFsc2U7IH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBSZW1vdmVzIHByb2R1Y3QgZnJvbSB0aGUgY29tcGFyZSB0YWJsZVxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSB0aGUgYXJndW1lbnRzIG9iamVjdCBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6IGl0ZW1pZCwgdXVpZCBhbmQgY2IgKGNoZWNrYm94KVxuICovXG5mdW5jdGlvbiByZW1vdmVQcm9kdWN0KGFyZ3MpIHtcbiAgICB2YXIgJGNiID0gYXJncy5jYiA/ICQoYXJncy5jYikgOiBudWxsO1xuICAgIHJldHVybiByZW1vdmVQcm9kdWN0QWpheChhcmdzKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRpdGVtID0gJCgnW2RhdGEtdXVpZD1cIicgKyBhcmdzLnV1aWQgKyAnXCJdJyk7XG4gICAgICAgIHJlbW92ZUZyb21MaXN0KCRpdGVtKTtcbiAgICAgICAgaWYgKCRjYiAmJiAkY2IubGVuZ3RoID4gMCkgeyAkY2JbMF0uY2hlY2tlZCA9IGZhbHNlOyB9XG4gICAgICAgIHJlZnJlc2hDb250YWluZXIoKTtcbiAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgkY2IgJiYgJGNiLmxlbmd0aCA+IDApIHsgJGNiWzBdLmNoZWNrZWQgPSB0cnVlOyB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUl0ZW0oJGl0ZW0pIHtcbiAgICB2YXIgdXVpZCA9ICRpdGVtLmRhdGEoJ3V1aWQnKSxcbiAgICAgICAgJHByb2R1Y3RUaWxlID0gJCgnIycgKyB1dWlkKTtcbiAgICByZXR1cm4gcmVtb3ZlUHJvZHVjdCh7XG4gICAgICAgIGl0ZW1pZDogJGl0ZW0uZGF0YSgnaXRlbWlkJyksXG4gICAgICAgIHV1aWQ6IHV1aWQsXG4gICAgICAgIGNiOiAoJHByb2R1Y3RUaWxlLmxlbmd0aCA9PT0gMCkgPyBudWxsIDogJHByb2R1Y3RUaWxlLmZpbmQoJy5jb21wYXJlLWNoZWNrJylcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIERPTS1PYmplY3Qgb2YgdGhlIGNvbXBhcmUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVEb20oKSB7XG4gICAgdmFyICRjb21wYXJlQ29udGFpbmVyID0gJCgnLmNvbXBhcmUtaXRlbXMnKTtcbiAgICBfY3VycmVudENhdGVnb3J5ID0gJGNvbXBhcmVDb250YWluZXIuZGF0YSgnY2F0ZWdvcnknKSB8fCAnJztcbiAgICB2YXIgJGFjdGl2ZSA9ICRjb21wYXJlQ29udGFpbmVyLmZpbmQoJy5jb21wYXJlLWl0ZW0nKS5maWx0ZXIoJy5hY3RpdmUnKTtcbiAgICAkYWN0aXZlLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHByb2R1Y3RUaWxlID0gJCgnIycgKyAgJCh0aGlzKS5kYXRhKCd1dWlkJykpO1xuICAgICAgICBpZiAoJHByb2R1Y3RUaWxlLmxlbmd0aCA9PT0gMCkge3JldHVybjt9XG4gICAgICAgICRwcm9kdWN0VGlsZS5maW5kKCcuY29tcGFyZS1jaGVjaycpWzBdLmNoZWNrZWQgPSB0cnVlO1xuICAgIH0pO1xuICAgIC8vIHNldCBjb250YWluZXIgc3RhdGVcbiAgICByZWZyZXNoQ29udGFpbmVyKCk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBldmVudHMgb24gdGhlIGNvbXBhcmUgY29udGFpbmVyXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgLy8gYWRkIGV2ZW50IHRvIGJ1dHRvbnMgdG8gcmVtb3ZlIHByb2R1Y3RzXG4gICAgJCgnLmNvbXBhcmUtaXRlbScpLm9uKCdjbGljaycsICcuY29tcGFyZS1pdGVtLXJlbW92ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVtb3ZlSXRlbSgkKHRoaXMpLmNsb3Nlc3QoJy5jb21wYXJlLWl0ZW0nKSk7XG4gICAgfSk7XG5cbiAgICAvLyBCdXR0b24gdG8gZ28gdG8gY29tcGFyZSBwYWdlXG4gICAgJCgnI2NvbXBhcmUtaXRlbXMtYnV0dG9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBwYWdlLnJlZGlyZWN0KHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChVcmxzLmNvbXBhcmVTaG93LCAnY2F0ZWdvcnknLCBfY3VycmVudENhdGVnb3J5KSk7XG4gICAgfSk7XG5cbiAgICAvLyBCdXR0b24gdG8gY2xlYXIgYWxsIGNvbXBhcmVkIGl0ZW1zXG4gICAgLy8gcmVseSBvbiByZWZyZXNoQ29udGFpbmVyIHRvIHRha2UgY2FyZSBvZiBoaWRpbmcgdGhlIGNvbnRhaW5lclxuICAgICQoJyNjbGVhci1jb21wYXJlZC1pdGVtcycpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnLmNvbXBhcmUtaXRlbXMgLmFjdGl2ZScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmVtb3ZlSXRlbSgkKHRoaXMpKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpbml0aWFsaXplRG9tKCk7XG4gICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xufTtcblxuZXhwb3J0cy5hZGRQcm9kdWN0ID0gYWRkUHJvZHVjdDtcbmV4cG9ydHMucmVtb3ZlUHJvZHVjdCA9IHJlbW92ZVByb2R1Y3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9qcy9kaWFsb2cnKTtcblxudmFyIG9wZW5DYXJvdXNlbFZpZGVvTW9kYWwgPSBmdW5jdGlvbihldmVudCkge1xuICAgIHZhciAkdmlkZW9FbGVtZW50ID0gJCgnW2RhdGEtY2Fyb3VzZWwtdmlkZW8tZWxlbWVudF0nKS53cmFwKCc8ZGl2IGNsYXNzPVwidmlkZW8tY29udGFpbmVyXCI+PC9kaXY+JykucGFyZW50KCk7XG4gICAgXG4gICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICBodG1sOiAkdmlkZW9FbGVtZW50WzBdLm91dGVySFRNTCxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgZGlhbG9nQ2xhc3M6ICdmaXhlZCBjYXJvdXNlbC12aWRlby1tb2RhbCcsXG4gICAgICAgICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnMTAwJScsXG5cdFx0XHRkcmFnZ2FibGU6IGZhbHNlLFxuXHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuICAgICAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnLmNhcm91c2VsLXZpZGVvLWVsZW1lbnQnKVswXS5wbGF5KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuICAgICAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnLmNhcm91c2VsLXZpZGVvLWVsZW1lbnQnKVswXS5wYXVzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQ2Fyb3VzZWxWaWRlby5QbGF5Jykub24oJ2NsaWNrLkNhcm91c2VsVmlkZW8uUGxheScsICcucHJvZHVjdC1wcmltYXJ5LWltYWdlIFtkYXRhLWNhcm91c2VsLXZpZGVvXScsIG9wZW5DYXJvdXNlbFZpZGVvTW9kYWwpO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQ2Fyb3VzZWxWaWRlby5DYXRjaCcpLm9uKCdjbGljay5DYXJvdXNlbFZpZGVvLkNhdGNoJywgJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgLmNhcm91c2VsLXZpZGVvLWxpbmsnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cy5pbml0ID0gaW5pdGlhbGl6ZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5IZWFkZXJCYW5uZXIuQ2xvc2UnKS5vbignY2xpY2suSGVhZGVyQmFubmVyLkNsb3NlJywgJy5oZWFkZXItYmFubmVyIC5jbG9zZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFxuXHRcdHZhciBjb250ZW50QXNzZXRJZCA9ICR0aGlzLmNsb3Nlc3QoJ1tjb250ZW50LWFzc2V0LWlkXScpLmF0dHIoJ2NvbnRlbnQtYXNzZXQtaWQnKTtcblx0XHRpZiAoY29udGVudEFzc2V0SWQpIHtcblx0XHRcdGFja25vd2xlZGdlKGNvbnRlbnRBc3NldElkLCAnWWVzJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCQoJy5oZWFkZXItYmFubmVyJykuaGlkZSgpO1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdhcHAucmVzaXplJyk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQ29va2llTm90aWZpY2F0aW9uLlllcycpLm9uKCdjbGljay5Db29raWVOb3RpZmljYXRpb24uWWVzJywgJy5ub3RpZmljYXRpb24uY3ByYS1jb29raWUtbm90aWZpY2F0aW9uIC5hY3Rpb25zIC55ZXMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcblx0XHQkdGhpcy5jbG9zZXN0KCcubm90aWZpY2F0aW9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdGFja25vd2xlZGdlKCdDb29raWVzJywgJ1llcycpO1xuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQ29va2llTm90aWZpY2F0aW9uLk5vJykub24oJ2NsaWNrLkNvb2tpZU5vdGlmaWNhdGlvbi5ObycsICcubm90aWZpY2F0aW9uLmNwcmEtY29va2llLW5vdGlmaWNhdGlvbiAuYWN0aW9ucyAubm8nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcblx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9ICR0aGlzLmF0dHIoJ2hyZWYnKTtcblx0XHRhY2tub3dsZWRnZSgnQ29va2llcycsICdObycpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gYWNrbm93bGVkZ2Uobm90aWZpY2F0aW9uLCBhY2tub3dsZWRnZW1lbnQsIGNhbGxiYWNrU3VjY2Vzc1BhcmFtZXRlciwgY2FsbGJhY2tFcnJvclBhcmFtZXRlcikge1xuXHR2YXIgY2FsbGJhY2tTdWNjZXNzID0gY2FsbGJhY2tTdWNjZXNzUGFyYW1ldGVyIHx8IGZ1bmN0aW9uKCkgeyB9O1xuXHR2YXIgY2FsbGJhY2tFcnJvciA9IGNhbGxiYWNrRXJyb3JQYXJhbWV0ZXIgfHwgZnVuY3Rpb24oKSB7IH07XG5cblx0aWYgKG5vdGlmaWNhdGlvbiAmJiBhY2tub3dsZWRnZW1lbnQpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLkNvb2tpZU5vdGlmaWNhdGlvbi5BY2tub3dsZWRnZSxcblx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0Tm90aWZpY2F0aW9uOiBub3RpZmljYXRpb24sXG5cdFx0XHRcdEFja25vd2xlZGdlbWVudDogYWNrbm93bGVkZ2VtZW50XG5cdFx0XHR9LFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGNhbGxiYWNrU3VjY2Vzcyxcblx0XHRcdGVycm9yOiBjYWxsYmFja0Vycm9yXG5cdFx0fSk7XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi9kaWFsb2cnKTtcblxudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoJGNvbnRhaW5lcikge1xuXHQkY29udGFpbmVyLmZpbmQoJ1tlbWFpbC1mb3JtXScpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyICRmb3JtID0gJChlbGVtZW50KTtcblx0XHR2YXIgZm9ybVR5cGUgPSAkZm9ybS5hdHRyKCdlbWFpbC1mb3JtJyk7XG5cdFx0YXBwZW5kQ1NSRlRva2VuKCRmb3JtKTtcblxuXHRcdGlmIChmb3JtVHlwZSAmJiB0eXBlb2YgaGFuZGxlcnNbZm9ybVR5cGVdID09ICdmdW5jdGlvbicpIHtcblx0XHRcdGhhbmRsZXJzW2Zvcm1UeXBlXSgkZm9ybSk7XG5cdFx0fVxuXHR9KTtcbn1cblxudmFyIGhhbmRsZXJzID0ge1xuXHQnY3ByYSc6IGZ1bmN0aW9uKCRmb3JtKSB7XG5cdFx0dmFyICRyZXF1aXJlZEZpZWxkcyA9ICRmb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkJyk7XG5cdFx0dmFyICRmb3JtTmFtZUZpcnN0ID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJuYW1lX2ZpcnN0XCJdJyk7XG5cdFx0dmFyICRmb3JtTmFtZUxhc3QgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIm5hbWVfbGFzdFwiXScpO1xuXHRcdHZhciAkZm9ybUVtYWlsID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJlbWFpbFwiXScpO1xuXHRcdHZhciAkZm9ybVBob25lID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJwaG9uZVwiXScpO1xuXHRcdHZhciAkZm9ybVJlcXVlc3RUeXBlID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJyZXF1ZXN0VHlwZVwiXScpO1xuXHRcdFxuXHRcdHZhciBmb3JtVmFsaWRhdG9yID0gJGZvcm0udmFsaWRhdGUoVmFsaWRhdGlvblNldHRpbmdzLkdsb2JhbCk7XG5cdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdyZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZVJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24sIFJlc291cmNlcy5JTlZBTElEX1ZBTFVFKTtcblx0XHQkcmVxdWlyZWRGaWVsZHMucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0XHQkZm9ybUVtYWlsLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuRW1haWwpO1xuXHRcdCRmb3JtLmZpbmQoJ3NwYW4uZXJyb3InKS5yZW1vdmUoKTtcblx0XHRcblx0XHQkZm9ybS5maW5kKCdpbnB1dFt0eXBlPVwic3VibWl0XCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGlmIChmb3JtVmFsaWRhdG9yLmZvcm0oKSkge1xuXHRcdFx0XHR2YXIgZGF0YSA9IHtcblx0XHRcdFx0XHQnZm9ybV90eXBlJzogJGZvcm0uYXR0cignZW1haWwtZm9ybScpLFxuXHRcdFx0XHRcdCduYW1lX2ZpcnN0JzogJGZvcm1OYW1lRmlyc3QudmFsKCksXG5cdFx0XHRcdFx0J25hbWVfbGFzdCc6ICRmb3JtTmFtZUxhc3QudmFsKCksXG5cdFx0XHRcdFx0J2VtYWlsJzogJGZvcm1FbWFpbC52YWwoKSxcblx0XHRcdFx0XHQncGhvbmUnOiAkZm9ybVBob25lLnZhbCgpLFxuLy9cdFx0XHRcdFx0J3JlcXVlc3RfdHlwZSc6ICRmb3JtUmVxdWVzdFR5cGUuZmlsdGVyKCc6Y2hlY2tlZCcpLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMudmFsdWU7IH0pLmdldCgpLmpvaW4oJyBhbmQgJylcblx0XHRcdFx0XHQncmVxdWVzdF90eXBlJzogJGZvcm1SZXF1ZXN0VHlwZS52YWwoKVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0JGZvcm0uZmluZCgnaW5wdXRbdHlwZT1cImhpZGRlblwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdFx0ZGF0YVskdGhpcy5hdHRyKCduYW1lJyldID0gJHRoaXMudmFsKCk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0dXJsOiBVcmxzLkVtYWlsRm9ybS5TZW5kLFxuXHRcdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0XHRkYXRhOiBkYXRhLFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEuRW1haWxTZW50KSB7XG5cdFx0XHRcdFx0XHRcdHZhciAkc3VjY2Vzc0NvbnRlbnQgPSAkKCcuY29udGVudC5jcHJhLWZvcm0tc3VjY2VzcycpO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0XHRcdCAgICAgICAgICAgIGh0bWw6ICRzdWNjZXNzQ29udGVudC5odG1sKCksXG5cdFx0XHRcdFx0ICAgICAgICAgICAgb3B0aW9uczoge1xuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICB0aXRsZTogJHN1Y2Nlc3NDb250ZW50LmF0dHIoJ3RpdGxlJyksXG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnZml4ZWQgY2hlY2tvdXQtdGVybXMnICsgKCRzdWNjZXNzQ29udGVudC5hdHRyKCdkaWFsb2ctY2xhc3MnKSA/ICcgJyArICRzdWNjZXNzQ29udGVudC5hdHRyKCdkaWFsb2ctY2xhc3MnKSA6ICcnKSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0XHQgICAgICAgIFxuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgXHQkKCdib2R5JykuYWRkQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCR0aGlzLnNjcm9sbFRvcCgwKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0XHQgICAgICAgICAgICB9XG5cdFx0XHRcdFx0ICAgICAgICB9KTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHZhciAkZXJyb3JDb250ZW50ID0gJCgnLmNvbnRlbnQuY3ByYS1mb3JtLWVycm9yJyk7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRkaWFsb2cub3Blbih7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgaHRtbDogJGVycm9yQ29udGVudC5odG1sKCksXG5cdFx0XHRcdFx0ICAgICAgICAgICAgb3B0aW9uczoge1xuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICB0aXRsZTogJGVycm9yQ29udGVudC5hdHRyKCd0aXRsZScpLFxuXHRcdFx0XHRcdCAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ2ZpeGVkIGNoZWNrb3V0LXRlcm1zJyArICgkZXJyb3JDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpID8gJyAnICsgJGVycm9yQ29udGVudC5hdHRyKCdkaWFsb2ctY2xhc3MnKSA6ICcnKSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdFx0XHQgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0ICAgICAgICAgICAgICAgIFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0XHQgICAgICAgIFxuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgXHQkKCdib2R5JykuYWRkQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCR0aGlzLnNjcm9sbFRvcCgwKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0XHQgICAgICAgICAgICB9XG5cdFx0XHRcdFx0ICAgICAgICB9KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHZhciAkZXJyb3JDb250ZW50ID0gJCgnLmNvbnRlbnQuY3ByYS1mb3JtLWVycm9yJyk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0ICAgICAgICAgICAgaHRtbDogJGVycm9yQ29udGVudC5odG1sKCksXG5cdFx0XHRcdCAgICAgICAgICAgIG9wdGlvbnM6IHtcblx0XHRcdFx0ICAgICAgICAgICAgICAgIHRpdGxlOiAkZXJyb3JDb250ZW50LmF0dHIoJ3RpdGxlJyksXG5cdFx0XHRcdCAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ2ZpeGVkIGNoZWNrb3V0LXRlcm1zJyArICgkZXJyb3JDb250ZW50LmF0dHIoJ2RpYWxvZy1jbGFzcycpID8gJyAnICsgJGVycm9yQ29udGVudC5hdHRyKCdkaWFsb2ctY2xhc3MnKSA6ICcnKSxcblx0XHRcdFx0ICAgICAgICAgICAgICAgIGRyYWdnYWJsZTogZmFsc2UsXG5cdFx0XHRcdCAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0ICAgICAgICAgICAgICAgIFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0ICAgICAgICBcblx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdCR0aGlzLnNjcm9sbFRvcCgwKTtcblx0XHRcdFx0XHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRcdCAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFx0XHQgICAgICAgICAgICBcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnZGlhbG9nLW9wZW4nKTtcblx0XHRcdFx0XHQgICAgICAgICAgICB9XG5cdFx0XHRcdCAgICAgICAgICAgIH1cblx0XHRcdFx0ICAgICAgICB9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGFwcGVuZENTUkZUb2tlbigkZm9ybSkge1xuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ2dldCcsXG5cdFx0dXJsOiBVcmxzLkNTUkZUb2tlbi5HZXQsXG5cdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0JGZvcm0uYXBwZW5kKCc8aW5wdXQgdHlwZT1cImhpZGRlblwiIG5hbWU9XCInICsgcmVzcG9uc2UubmFtZSArICdcIiB2YWx1ZT1cIicgKyByZXNwb25zZS50b2tlbiArICdcIi8+Jyk7XG5cdFx0fVxuXHR9KTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBSZWNhcHRjaGEgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL1JlY2FwdGNoYScpO1xudmFyIFJlcXVlc3RIZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9oZWxwZXJzL1JlcXVlc3RIZWxwZXInKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG5cbmV4cG9ydHMuSW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciAkZm9vdGVyRW1haWxGb3JtO1xudmFyIHZhbGlkYXRvcjtcbnZhciBkYXRhQnVmZmVyID0ge307XG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xuXG5cbmZ1bmN0aW9uIGluaXRpYWxpemUocGFnZSkge1xuXHRpZiAocGFnZSAmJiBwYWdlLm9wdGlvbnMpIHtcblx0XHRvcHRpb25zID0gcGFnZS5vcHRpb25zO1xuXHR9XG5cblx0dmFyIGZvb3RlckVtYWlsRm9ybVNlbGVjdG9yO1xuXHRpZiAocGFnZS5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0Zm9vdGVyRW1haWxGb3JtU2VsZWN0b3IgPSAnZm9ybSNlbWFpbC1hbGVydC1zaWdudXAnO1xuXHR9IGVsc2UgaWYgKHBhZ2Uuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdGZvb3RlckVtYWlsRm9ybVNlbGVjdG9yID0gJ2Zvcm0jYm9vdGJhcm4tZm9vdGVyLWVtYWlsLWFsZXJ0LXNpZ251cCc7XG5cdH0gZWxzZSB7XG5cdFx0Zm9vdGVyRW1haWxGb3JtU2VsZWN0b3IgPSAnZm9ybSNmb290ZXItZW1haWwtc2lnbnVwJztcblx0fVxuXHRcblx0JGZvb3RlckVtYWlsRm9ybSA9ICQoZm9vdGVyRW1haWxGb3JtU2VsZWN0b3IpO1xuXHRpZiAoJGZvb3RlckVtYWlsRm9ybS5sZW5ndGggPiAwKSB7XHRcdFxuXHRcdHZhciAkdmFsaWRhdG9yRXJyb3JNZXNzYWdlID0gJGZvb3RlckVtYWlsRm9ybS5maW5kKCdzcGFuLmVycm9yJyk7XG5cdFx0XG5cdFx0JGZvb3RlckVtYWlsRm9ybS5vbignc3VibWl0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JGb290ZXJFbWFpbFNpZ251cCkge1xuXHRcdFx0XHRzdWJtaXRFbWFpbFNpZ251cCgpO1xuXHRcdFx0fVx0XHRcdFxuXHRcdH0pO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkVtYWlsU2lnblVwLlZhbGlkYXRpb25DbGVhcicpLm9uKCdtb3VzZWRvd24uRW1haWxTaWduVXAuVmFsaWRhdGlvbkNsZWFyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGlmICh2YWxpZGF0b3IgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3QoZm9vdGVyRW1haWxGb3JtU2VsZWN0b3IpLnBhcmVudCgpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdHZhbGlkYXRvci5yZXNldEZvcm0oKTtcblx0XHRcdFx0JHZhbGlkYXRvckVycm9yTWVzc2FnZS5yZW1vdmVDbGFzcygnc2lnbnVwLXN1Y2Nlc3MnKS5odG1sKCcnKS5oaWRlKCk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0XHQkKGRvY3VtZW50KS5vbignR2xvYmFsLkVtYWlsU2lnbnVwJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG5cdFx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yRm9vdGVyRW1haWxTaWdudXApIHtcblx0XHRcdFx0c3VibWl0RW1haWxTaWdudXAoKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JGb290ZXJFbWFpbFNpZ251cCAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0XHRSZWNhcHRjaGEuaW5pdGlhbGl6ZSgpO1xuXHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yRW1haWxTaWdudXAoKTtcblx0XHRcdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRcdFx0bG9hZGVkLlJlY2FwdGNoYSA9IHRydWU7XG5cdFx0XHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yRW1haWxTaWdudXAoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdEVtYWlsU2lnbnVwKCkge1xuXHR2YXIgJGVtYWlsQWRkcmVzcyA9ICRmb290ZXJFbWFpbEZvcm0uZmluZCgnaW5wdXQjZW1haWwtYWxlcnQtYWRkcmVzcycpO1x0XHRcblx0dmFsaWRhdG9yID0gJGZvb3RlckVtYWlsRm9ybS52YWxpZGF0ZSgpO1xuXHQkZW1haWxBZGRyZXNzLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuRW1haWwpO1xuXHR2YWxpZGF0b3IuZm9ybSgpO1xuXG5cdGlmICh2YWxpZGF0b3IudmFsaWQoKSkge1xuXHRcdGlmKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpe1xuXHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0ZW1haWw6ICRlbWFpbEFkZHJlc3MudmFsKClcblx0XHRcdH1cblx0XHRcdHZhciBjb250YWN0X2RhdGEgPSB7XG5cdFx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdFx0XHQnYWRkcmVzcyc6ICRlbWFpbEFkZHJlc3MudmFsKCksXG5cdFx0XHRcdFx0XHQnc3Vic2NyaWJlU3RhdHVzJzogJ3N1YnNjcmliZWQnXHRcdFx0XHQgICAgICAgICAgICBcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXHRcdFx0XHQgICAgXG5cdFx0XHRcdCdzaWdudXBfc291cmNlJzogJ2Zvb3RlcicsXG5cdFx0XHRcdCd3ZWxjb21lX3NpZ251cCc6IHRydWVcblx0XHRcdH07XG5cdFx0XHRcblx0XHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XHRcInNpZ251cF9zb3VyY2VcIjogJ2Zvb3RlcicsXG5cdFx0XHRcdFwid2VsY29tZV9zaWdudXBcIjogdHJ1ZVxuXHRcdFx0fTtcblxuXHRcdFx0UmVxdWVzdEhlbHBlci5WYWxpZGF0ZSgnQ29yZGlhbC1FbWFpbFNpZ251cCcpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxcblx0XHRcdFx0XHRcdFsnZXZlbnQnLCAnZW1haWxfc2lnbnVwJywgcHJvcGVydGllc11cblx0XHRcdFx0XHRdKTtcblx0XHRcdFx0fVxuXHRcdFx0fSkuY2F0Y2goKTtcblx0XHR9XG5cdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5SRVRFTlRJT05fQ09NX0VOQUJMRUQpIHtcblx0XHRcdGdlcS5zdXBwcmVzcygpO1xuXHRcdH1cblxuXHRcdGlmICgkKCcjZW1haWwtYWxlcnQtYWRkcmVzcy52YWxpZCcpLmxlbmd0aCA+IDAgJiYgJCgnI2VtYWlsLWFsZXJ0LWFkZHJlc3MnKS52YWwoKSAhPSAnJykge1xuXHRcdFx0JCgnaW5wdXQjZW1haWwtYWxlcnQtYWRkcmVzcycpLnZhbCgnJyk7XG5cdFx0XHQkKCcuc2lnbnVwLXN1Y2Nlc3MnKS5zaG93KCk7XG5cdFx0fVxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHQkKCcuc2lnbnVwLXN1Y2Nlc3MnKS5oaWRlKCk7XG5cdFx0fSwgNTAwMCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhRm9yRW1haWxTaWdudXAoKSB7XG4gICAgaWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJGZvb3RlckVtYWlsRm9ybS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckZvb3RlckVtYWlsU2lnbnVwICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcbiAgICAgICAgaWYgKGRhdGFCdWZmZXIuRW1haWxTaWdudXBSZWNhcHRjaGEpIHtcbiAgICAgICAgICAgIGdyZWNhcHRjaGEucmVzZXQoZGF0YUJ1ZmZlci5FbWFpbFNpZ251cFJlY2FwdGNoYSk7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YUJ1ZmZlci5FbWFpbFNpZ251cFJlY2FwdGNoYSA9IGdyZWNhcHRjaGEucmVuZGVyKCdmb290ZXItZW1haWwtYWxlcnQtc2lnbnVwLXN1Ym1pdCcsIHtcbiAgICAgICAgICAgICdzaXRla2V5Jzogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcbiAgICAgICAgICAgICdjYWxsYmFjayc6IGVtYWlsU2lnbnVwLFxuICAgICAgICAgICAgJ2JhZGdlJzogJ2lubGluZSdcbiAgICAgICAgfSk7XG4gICAgfVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBSZXR1cm5Db2RlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2ludF9zdnMvY2FydHJpZGdlL3NjcmlwdHMvR2lmdENhcmRDb25zdGFudHMnKS5SZXR1cm5Db2RlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuZXhwb3J0cy5yZW1vdmUgPSByZW1vdmU7XG5cbnZhciBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5VmFsaWRhdG9yO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCRjb250YWluZXIsIG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0dmFyIG9wdGlvbnMgPSAkLmV4dGVuZCh7XG5cdFx0c3VjY2Vzc0NhbGxiYWNrOiBudWxsLFxuXHRcdGVycm9yQ2FsbGJhY2s6IG51bGxcblx0fSwgb3B0aW9uc1BhcmFtZXRlcik7XG5cdFxuXHR2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDb21wb25lbnQgPSAkY29udGFpbmVyLmZpbmQoJy5naWZ0LWNhcmQtYmFsYW5jZS1pbnF1aXJ5LWNvbXBvbmVudCcpO1xuXHRcblx0dmFyICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Rm9ybSA9ICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50LmZpbmQoJ2Zvcm0nKTtcblx0dmFyICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UmVzdWx0ID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDb21wb25lbnQuZmluZCgnLmJhbGFuY2UtaW5xdWlyeS1yZXN1bHQnKTtcblx0dmFyICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UmVzdWx0QW1vdW50ID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDb21wb25lbnQuZmluZCgnLmFtb3VudCcpO1xuXHR2YXIgJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiZ2lmdENhcmRfbnVtYmVyXCJdJyk7XG4gICAgdmFyICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5UGluTnVtYmVyID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiZ2lmdENhcmRfcGluXCJdJyk7XG4gICAgdmFyICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RXJyb3JNZXNzYWdlID0gJGdpZnRDYXJkQmFsYW5jZUlucXVpcnlGb3JtLmZpbmQoJ3NwYW4uZXJyb3InKTtcblx0XG4gICAgJGNvbnRhaW5lci5hdHRyKCdiYWxhbmNlLWlucXVpcnktc3RhdGUnLCAnZm9ybScpO1xuXHRcbiAgICAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5vZmYoJ2NsaWNrLmFwcGx5Jykub24oJ2NsaWNrLmFwcGx5JywgJy5idG4uYmFsYW5jZS1pbnF1aXJ5Om5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdCRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVZhbGlkYXRvciA9ICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Rm9ybS52YWxpZGF0ZSgpO1xuXHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnZ2lmdENhcmROdW1iZXJMZW5ndGgnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlR2lmdENhcmROdW1iZXJMZW5ndGgsIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkdpZnRDYXJkLk51bWJlci5MZW5ndGgpO1xuXHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnZ2lmdENhcmROdW1iZXJWYWx1ZXMnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlR2lmdENhcmROdW1iZXJWYWx1ZXMsIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkdpZnRDYXJkLk51bWJlci5WYWx1ZXMpO1xuXHRcdCRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlci5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLkdpZnRDYXJkLk51bWJlcik7XG5cdFx0JGdpZnRDYXJkQmFsYW5jZUlucXVpcnlQaW5OdW1iZXIucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5HaWZ0Q2FyZC5QaW4pO1xuICAgICAgICBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5VmFsaWRhdG9yLmZvcm0oKTtcblxuICAgICAgICBpZiAoVXJscyAmJiBVcmxzLkdpZnRDYXJkLkJhbGFuY2VJbnF1aXJ5ICYmIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlWYWxpZGF0b3IudmFsaWQoKSkge1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcblxuICAgICAgICAgICAgJHRoaXMubG9hZGluZyh7XG4gICAgICAgICAgICAgICAgSXNJbWFnZVNob3duOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuTG9hZGluZ1xuICAgICAgICAgICAgfSk7XG5cblx0XHRcdHZhciBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlciA9ICRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlci52YWwoKS5tYXRjaCgvKFxcZCkvZyk7XG5cdFx0XHRpZiAoZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIgJiYgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIubGVuZ3RoKSB7XG5cdFx0XHRcdGdpZnRDYXJkQmFsYW5jZUlucXVpcnlDYXJkTnVtYmVyID0gZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIuam9pbignJyk7XG5cdFx0XHR9XG5cbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgdXJsOiBVcmxzLkdpZnRDYXJkLkJhbGFuY2VJbnF1aXJ5LFxuICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBjYXJkTnVtYmVyOiBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5Q2FyZE51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgcGluOiAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVBpbk51bWJlci52YWwoKVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMubG9hZGluZygnZGVzdHJveScpO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnF1aXJ5UmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnF1aXJ5UmVzdWx0ID0gZGF0YS5JbnF1aXJ5UmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucXVpcnlSZXN1bHQgJiYgaW5xdWlyeVJlc3VsdC5SZXR1cm5Db2RlLlJldHVybkNvZGUgPT0gUmV0dXJuQ29kZXMuQXBwcm92YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRjb250YWluZXIuYXR0cignYmFsYW5jZS1pbnF1aXJ5LXN0YXRlJywgJ3Jlc3VsdCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVJlc3VsdEFtb3VudC50ZXh0KGlucXVpcnlSZXN1bHQuQmFsYW5jZUFtb3VudC5BbW91bnRGb3JtYXR0ZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0b3B0aW9ucy5zdWNjZXNzQ2FsbGJhY2soaW5xdWlyeVJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIFx0aWYgKGlucXVpcnlSZXN1bHQuUmV0dXJuQ29kZS5SZXR1cm5EZXNjcmlwdGlvbiA9PSAnSW52YWxpZCBNZXNzYWdlJykge1xuICAgICAgICAgICAgICAgICAgICBcdFx0aW5xdWlyeVJlc3VsdC5SZXR1cm5Db2RlLlJldHVybkRlc2NyaXB0aW9uID0gUmVzb3VyY2VzLkVycm9yLkdlbmVyaWM7XHRcbiAgICAgICAgICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUVycm9yTWVzc2FnZS5odG1sKGlucXVpcnlSZXN1bHQuUmV0dXJuQ29kZS5SZXR1cm5EZXNjcmlwdGlvbiB8fCBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5lcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdG9wdGlvbnMuZXJyb3JDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cdFx0fVxuXHR9KTtcbiAgICBcbiAgICAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNhcmROdW1iZXIub2ZmKCdrZXlkb3duLkdpZnRDYXJkQmFsYW5jZUlucXVpcnkuVmFsaWRhdGlvbkNsZWFyLCBjaGFuZ2UuR2lmdENhcmRCYWxhbmNlSW5xdWlyeS5WYWxpZGF0aW9uQ2xlYXInKS5vbigna2V5ZG93bi5HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5LlZhbGlkYXRpb25DbGVhciwgY2hhbmdlLkdpZnRDYXJkQmFsYW5jZUlucXVpcnkuVmFsaWRhdGlvbkNsZWFyJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0aWYgKCRjb250YWluZXIuYXR0cignYmFsYW5jZS1pbnF1aXJ5LXN0YXRlJykgPT09ICdyZXN1bHQnKSB7XG5cdFx0XHQkY29udGFpbmVyLmF0dHIoJ2JhbGFuY2UtaW5xdWlyeS1zdGF0ZScsICdmb3JtJyk7XG4gICAgICAgIFx0JGdpZnRDYXJkQmFsYW5jZUlucXVpcnlQaW5OdW1iZXIudmFsKCcnKTtcbiAgICAgICAgXHQkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVJlc3VsdEFtb3VudC50ZXh0KCcnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkdpZnRDYXJkQmFsYW5jZUlucXVpcnkuVmFsaWRhdGlvbkNsZWFyJykub24oJ21vdXNlZG93bi5HaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5LlZhbGlkYXRpb25DbGVhcicsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoZ2lmdENhcmRCYWxhbmNlSW5xdWlyeVZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgnLmdpZnQtY2FyZC1iYWxhbmNlLWlucXVpcnktY29tcG9uZW50JykucGFyZW50KCkubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIGdpZnRDYXJkQmFsYW5jZUlucXVpcnlWYWxpZGF0b3IucmVzZXRGb3JtKCk7XG4gICAgICAgICAgICAkZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKCkge1xuXHRnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5VmFsaWRhdG9yLmRlc3Ryb3koKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi9kaWFsb2cnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBkaWFsb2cub3Blbih7XG4gICAgICAgIGh0bWw6ICQoJyNkaWFsb2ctY29udGVudC1naWZ0LWNhcmQtYmFsYW5jZS1pbnF1aXJ5JykuaHRtbCgpLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICB0aXRsZTogJ0dpZnQgQ2FyZCBCYWxhbmNlIENoZWNrJyxcbiAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnZ2lmdC1jYXJkLWJhbGFuY2UtaW5xdWlyeScsXG4gICAgICAgICAgICByZXNpemFibGU6IGZhbHNlLFxuICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi9Mb2FkaW5nSW5kaWNhdG9yJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciBvcHRpb25zO1xudmFyIGRhdGFCdWZmZXI7XG52YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuICAgIElzTGFiZWxTaG93bjogZmFsc2UsXG4gICAgQ3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcbiAgICBCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcbn07XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gJC5leHRlbmQoe1xuXHRcdHN1Y2Nlc3NDYWxsYmFjazogbnVsbCxcblx0XHRlcnJvckNhbGxiYWNrOiBudWxsXG5cdH0sIG9wdGlvbnNQYXJhbWV0ZXIpO1xuXHRkYXRhQnVmZmVyID0ge1xuXHRcdGluaXRpYWxpemVkOiBmYWxzZVxuXHR9O1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suR2xvYmFsZUluaXRpYWxpemUnKS5vbignY2xpY2suR2xvYmFsZUluaXRpYWxpemUnLCAnLmNvdW50cnktc2VsZWN0b3InLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICgkKCdkaXYjZ2xvYmFsZS1zY3JpcHQtbG9hZGVyLWRhdGEnKS5sZW5ndGggPiAwICYmICFkYXRhQnVmZmVyLmluaXRpYWxpemVkKSB7XG5cdFx0XHRkYXRhQnVmZmVyLmluaXRpYWxpemVkID0gdHJ1ZTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdFx0JCgnYm9keScpLmFwcGVuZCgnPHNjcmlwdCB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCIgaWQ9XCJnbG9iYWxlLXNjcmlwdC1sb2FkZXJcIiBzcmM9XCInICsgVXJscy5HbG9iYWxlLlNjcmlwdExvYWRlciArICdcIj48L3NjcmlwdD4nKTtcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignR2xvYmFsZS5Jbml0aWFsaXplZCcpLm9uKCdHbG9iYWxlLkluaXRpYWxpemVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoZGF0YUJ1ZmZlci5pbml0aWFsaXplZCAmJiAkKCcucHRfY2hlY2tvdXRfZ2xvYmFsZScpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRkYXRhQnVmZmVyLnNob3dTaGlwcGluZ1N3aXRjaGVySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzaG93U2hpcHBpbmdTd2l0Y2hlciwgMjUwKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzaG93U2hpcHBpbmdTd2l0Y2hlcigpIHtcblx0aWYgKEdsb2JhbEUgJiYgR2xvYmFsRS5TaGlwcGluZ1N3aXRjaGVyICYmIEdsb2JhbEUuU2hpcHBpbmdTd2l0Y2hlci5TaG93ICYmIHR5cGVvZiBHbG9iYWxFLlNoaXBwaW5nU3dpdGNoZXIuU2hvdyA9PSAnZnVuY3Rpb24nKSB7XG5cdFx0aWYgKCQoJ2JvZHknKS5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0fVxuXHRcdGNsZWFySW50ZXJ2YWwoZGF0YUJ1ZmZlci5zaG93U2hpcHBpbmdTd2l0Y2hlckludGVydmFsKTtcblx0XHRHbG9iYWxFLlNoaXBwaW5nU3dpdGNoZXIuU2hvdygpO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgSW1hZ2VDb25zdGFudHM7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgY2Fyb3VzZWxWaWRlbyA9IHJlcXVpcmUoJy4vLi4vQ2Fyb3VzZWxWaWRlbycpO1xuXG52YXIgc2luZ2xlSW1hZ2VTbGlja09wdGlvbnM7XG52YXIgcHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucztcblxudmFyIGh0bWwgPSBbXTtcbnZhciBkYXRhID0gW107XG52YXIgbG9hZGVkID0gW107XG52YXIgb3B0aW9ucztcblxudmFyICRzaW5nbGVJbWFnZVNsaWRlcztcbnZhciAkdGh1bWJuYWlsSW1hZ2VDb250YWluZXI7XG52YXIgJHRodW1ibmFpbEltYWdlU2xpZGVzO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKHBhcmFtcykge1xuXHRpZiAocGFyYW1zKSB7XG4gICAgXHRvcHRpb25zID0gcGFyYW1zO1xuXHR9XG4gICAgdmFyICRwZHBNYWluID0gJCgnI3BkcE1haW4nKTtcblxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRJbWFnZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvdW50cnlvdXRmaXR0ZXJzL2NhcnRyaWRnZS9qcy9JbWFnZUNvbnN0YW50cycpO1xuXHR9IGVsc2UgaWYgKHBhZ2VDb250ZXh0Lmlzc3RvcmVzaXRlKSB7XG5cdFx0SW1hZ2VDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9ib290YmFybl9yc3AvY2FydHJpZGdlL2pzL0ltYWdlQ29uc3RhbnRzJyk7XG5cdH0gZWxzZSB7IFxuXHRcdEltYWdlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9JbWFnZUNvbnN0YW50cycpO1xuXHR9XG5cdHNpbmdsZUltYWdlU2xpY2tPcHRpb25zID0gSW1hZ2VDb25zdGFudHMuU2xpY2tTbGlkZXIuT3B0aW9ucy5TaW5nbGU7XG5cdHByb2R1Y3RUaHVtYm5haWxTbGlja09wdGlvbnMgPSBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlRodW1ibmFpbDtcblxuICAgICRzaW5nbGVJbWFnZVNsaWRlcyA9ICQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKTtcbiAgICAkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIgPSAkKCcucHJvZHVjdC10aHVtYm5haWxzLWNvbnRhaW5lcicpO1xuXHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMgPSAkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnNsaWRlcycpO1xuXG4gICAgJHBkcE1haW4ub2ZmKCdjbGljay5WYXJpYW50LkxlYWZsZXQuWm9vbS5JbicpLm9uKCdjbGljay5WYXJpYW50LkxlYWZsZXQuWm9vbS5JbicsICcuY3VzdG9tLmxlYWZsZXQtY29udHJvbC16b29tLWluJywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgJHNsaWRlcyA9ICQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKTtcblx0XHR2YXIgc2xpY2sgPSAkc2xpZGVzLnNsaWNrKCdnZXRTbGljaycpO1xuXHRcdCRzbGlkZXMuZmluZCgnW2RhdGEtc2xpY2staW5kZXg9XCInICsgc2xpY2suY3VycmVudFNsaWRlICsgJ1wiXSBpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignZ2V0TWFwJykuem9vbUluKCk7XG4gICAgfSk7XG4gICAgXG4gICAgJHBkcE1haW4ub2ZmKCdjbGljay5WYXJpYW50LkxlYWZsZXQuWm9vbS5PdXQnKS5vbignY2xpY2suVmFyaWFudC5MZWFmbGV0Llpvb20uT3V0JywgJy5jdXN0b20ubGVhZmxldC1jb250cm9sLXpvb20tb3V0JywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgJHNsaWRlcyA9ICQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKTtcblx0XHR2YXIgc2xpY2sgPSAkc2xpZGVzLnNsaWNrKCdnZXRTbGljaycpO1xuXHRcdCRzbGlkZXMuZmluZCgnW2RhdGEtc2xpY2staW5kZXg9XCInICsgc2xpY2suY3VycmVudFNsaWRlICsgJ1wiXSBpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignZ2V0TWFwJykuem9vbU91dCgpO1xuICAgIH0pO1xuXHRcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTIHx8IHBhZ2VDb250ZXh0Lm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHQkKHdpbmRvdykub2ZmKCdyZXNpemUuUERQLlNsaWRlci5QcmltYXJ5Jykub24oJ3Jlc2l6ZS5QRFAuU2xpZGVyLlByaW1hcnknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdGlmIChkYXRhWydtYXBSZXNpemVUaW1lciddKSB7XG5cdFx0XHRcdGNsZWFyVGltZW91dChkYXRhWydtYXBSZXNpemVUaW1lciddKTtcblx0XHRcdH1cblx0XHRcdGRhdGFbJ21hcFJlc2l6ZVRpbWVyJ10gPSBzZXRUaW1lb3V0KG1hcFJlc2l6ZVRpbWVySGFuZGxlciwgMjUwKTtcblx0XHR9KTtcblx0fVxuXHRcblx0JHNpbmdsZUltYWdlU2xpZGVzLm9uKCdpbml0JywgZnVuY3Rpb24oZXZlbnQsIHNsaWNrKSB7XG5cdFx0Ly8gaWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHR2YXIgJGluaXRpYWxTbGlkZSA9ICRzaW5nbGVJbWFnZVNsaWRlcy5maW5kKCcuc2xpY2stc2xpZGUuc2xpY2stYWN0aXZlJyk7XG5cdFx0XHRkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0luaXRpYWxTbGlkZSddID0gJGluaXRpYWxTbGlkZS5hdHRyKCdkYXRhLXNsaWNrLWluZGV4Jyk7XG5cdFx0XHRkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0N1cnJlbnRTbGlkZSddID0gZGF0YVsnc2luZ2xlSW1hZ2VTbGlkZXNJbml0aWFsU2xpZGUnXTtcblxuXHRcdFx0aW5pdGlhbGl6ZUltYWdlVmlld2VyT25TbGlkZSgkaW5pdGlhbFNsaWRlKTtcblx0XHRcdC8vIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtyZXNpemVTbGlkZXJUb01hdGNoU2xpZGUoJGluaXRpYWxTbGlkZSk7fSwgMjUwKTtcblx0XHQvLyB9XG5cdH0pO1xuXHRcblx0JHNpbmdsZUltYWdlU2xpZGVzLm9uKCdiZWZvcmVDaGFuZ2UnLCBmdW5jdGlvbihldmVudCwgc2xpY2ssIGN1cnJlbnRTbGlkZSwgbmV4dFNsaWRlKSB7XG5cdFx0aWYgKG5leHRTbGlkZSAhPSBkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0N1cnJlbnRTbGlkZSddKSB7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLWN1cnJlbnQnKS5yZW1vdmVDbGFzcygnc2xpY2stY3VycmVudCcpO1xuXHRcdFx0JHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGlkZVtkYXRhLXNsaWNrLWluZGV4PVwiJyArIG5leHRTbGlkZSArICdcIl0nKS5hZGRDbGFzcygnc2xpY2stY3VycmVudCcpO1xuXHRcdFx0c2V0VGh1bWJuYWlsUGFnZUJ5U2xpZGUobmV4dFNsaWRlICsgMSk7XG5cblx0XHRcdC8vIHZhciAkY3VycmVudFNsaWRlID0gJHNpbmdsZUltYWdlU2xpZGVzLmZpbmQoJ1tkYXRhLXNsaWNrLWluZGV4PVwiJyArIGN1cnJlbnRTbGlkZSArICdcIl0nKTtcblx0XHRcdC8vIHJlbW92ZUltYWdlVmlld2VyT25TbGlkZSgkY3VycmVudFNsaWRlKTtcblxuXHRcdFx0dmFyICRuZXh0U2xpZGUgPSAkc2luZ2xlSW1hZ2VTbGlkZXMuZmluZCgnW2RhdGEtc2xpY2staW5kZXg9XCInICsgbmV4dFNsaWRlICsgJ1wiXScpO1xuXHRcdFx0Ly8gdHVybiBvZmYgem9vbSBvbiB2aWRlbyBzbGlkZVxuXHRcdFx0aWYgKCEkbmV4dFNsaWRlLmhhc0NsYXNzKCdjYXJvdXNlbC12aWRlby1zbGlkZScpKSB7XG5cdFx0XHRcdGluaXRpYWxpemVJbWFnZVZpZXdlck9uU2xpZGUoJG5leHRTbGlkZSk7XG5cdFx0XHR9XG5cdFx0XHQvLyBpbml0aWFsaXplU2xpZGVzVG9TaWRlKCRuZXh0U2xpZGUpO1xuXG5cdFx0XHRkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0N1cnJlbnRTbGlkZSddID0gbmV4dFNsaWRlO1xuXHRcdH1cblx0fSk7XG5cbiAgICB2YXIgc2luZ2xlSW1hZ2VTbGlja09wdGlvbnMgPSBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlNpbmdsZTtcbiAgICBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcbiAgICBcdHNpbmdsZUltYWdlU2xpY2tPcHRpb25zLmRvdHMgPSB0cnVlO1xuXHRcdHNpbmdsZUltYWdlU2xpY2tPcHRpb25zLnJlc3BvbnNpdmVbMF0uc2V0dGluZ3MuYXJyb3dzID0gZmFsc2U7XG5cdH1cblxuXHQkc2luZ2xlSW1hZ2VTbGlkZXMubm90KCcuc2xpY2staW5pdGlhbGl6ZWQnKS5zbGljayhzaW5nbGVJbWFnZVNsaWNrT3B0aW9ucyk7XG5cbiAgICB2YXIgcHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucyA9IEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuVGh1bWJuYWlsO1xuICAgIGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUyB8fCBwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdHByb2R1Y3RUaHVtYm5haWxTbGlja09wdGlvbnMudmVydGljYWwgPSB0cnVlO1xuXHR9XG5cdCR0aHVtYm5haWxJbWFnZVNsaWRlcy5ub3QoJy5zbGljay1pbml0aWFsaXplZCcpLnNsaWNrKHByb2R1Y3RUaHVtYm5haWxTbGlja09wdGlvbnMpO1xuXG5cdGRhdGFbJ3RodW1ibmFpbHNDdXJyZW50UGFnZSddID0gMTtcblx0ZGF0YVsndGh1bWJuYWlsc01heGltdW1TbGlkZSddID0gJHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGlkZScpLmxlbmd0aDtcblx0ZGF0YVsndGh1bWJuYWlsc01heGltdW1QYWdlJ10gPSBNYXRoLmNlaWwoZGF0YVsndGh1bWJuYWlsc01heGltdW1TbGlkZSddIC8gcHJvZHVjdFRodW1ibmFpbFNsaWNrT3B0aW9ucy5zbGlkZXNUb1Nob3cpO1xuXG5cdGlmIChkYXRhWyd0aHVtYm5haWxzTWF4aW11bVBhZ2UnXSA8PSAxKSB7XG5cdFx0JHRodW1ibmFpbEltYWdlQ29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRodW1ibmFpbHMtYXJyb3cubmV4dCcpLmFkZENsYXNzKCdkaXNhYmxlJyk7XG5cdH0gZWxzZSB7XG5cdFx0JHRodW1ibmFpbEltYWdlQ29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRodW1ibmFpbHMtYXJyb3cubmV4dCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlJyk7XG5cdH1cblxuXHQkKCcucHJvZHVjdC10aHVtYm5haWxzLWNvbnRhaW5lciAucHJvZHVjdC10aHVtYm5haWxzLWFycm93Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgcGFnZURlbHRhID0gMDtcblx0XHRpZiAoJHRoaXMuaGFzQ2xhc3MoJ25leHQnKSkge1xuXHRcdFx0cGFnZURlbHRhID0gMTtcblx0XHR9IGVsc2UgaWYgKCR0aGlzLmhhc0NsYXNzKCdwcmV2aW91cycpKSB7XG5cdFx0XHRwYWdlRGVsdGEgPSAtMTtcblx0XHR9XG5cblx0XHRzZXRUaHVtYm5haWxQYWdlKGRhdGFbJ3RodW1ibmFpbHNDdXJyZW50UGFnZSddICsgcGFnZURlbHRhKTtcblx0fSk7XG5cblx0JCgnLnByb2R1Y3QtdGh1bWJuYWlscyAuc2xpZGUgYScpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRjdXJyZW50U2xpZGUgPSAkdGhpcy5jbG9zZXN0KCcuc2xpY2stdHJhY2snKS5maW5kKCcuc2xpY2stY3VycmVudCcpO1xuXHRcdHZhciBjdXJyZW50U2xpZGUgPSAkY3VycmVudFNsaWRlLmRhdGEoJ3NsaWNrLWluZGV4Jyk7XG5cdFx0dmFyICRuZXh0U2xpZGUgPSAkdGhpcy5jbG9zZXN0KCcuc2xpZGUnKTtcblx0XHR2YXIgbmV4dFNsaWRlID0gJG5leHRTbGlkZS5kYXRhKCdzbGljay1pbmRleCcpO1xuXG5cdFx0JHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGljay1jdXJyZW50JykucmVtb3ZlQ2xhc3MoJ3NsaWNrLWN1cnJlbnQnKTtcblx0XHQkbmV4dFNsaWRlLmFkZENsYXNzKCdzbGljay1jdXJyZW50Jyk7XG5cdFx0JHNpbmdsZUltYWdlU2xpZGVzLnNsaWNrKCdzbGlja0dvVG8nLCBuZXh0U2xpZGUpO1xuXHR9KTtcblxuXHRjYXJvdXNlbFZpZGVvLmluaXQoKTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVNsaWRlc1RvU2lkZSgkc2xpZGUpIHtcblx0dmFyICRsZWZ0U2xpZGUgPSAkc2xpZGUucHJldigpO1xuXHRpZiAoJGxlZnRTbGlkZS5sZW5ndGggPiAwKSB7XG5cdFx0aW5pdGlhbGl6ZUltYWdlVmlld2VyT25TbGlkZSgkbGVmdFNsaWRlKTtcblx0fVxuXG5cdHZhciAkcmlnaHRTbGlkZSA9ICRzbGlkZS5uZXh0KCk7XG5cdGlmICgkcmlnaHRTbGlkZS5sZW5ndGggPiAwKSB7XG5cdFx0aW5pdGlhbGl6ZUltYWdlVmlld2VyT25TbGlkZSgkcmlnaHRTbGlkZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc2V0VGh1bWJuYWlsUGFnZUJ5U2xpZGUoc2VsZWN0ZWRTbGlkZSkge1xuXHRpZiAoc2VsZWN0ZWRTbGlkZSA+PSAxICYmIHNlbGVjdGVkU2xpZGUgPD0gZGF0YVsndGh1bWJuYWlsc01heGltdW1TbGlkZSddKSB7XG5cdFx0c2V0VGh1bWJuYWlsUGFnZShNYXRoLmNlaWwoc2VsZWN0ZWRTbGlkZSAvIEltYWdlQ29uc3RhbnRzLlNsaWNrU2xpZGVyLk9wdGlvbnMuVGh1bWJuYWlsLnNsaWRlc1RvU2hvdykpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHNldFRodW1ibmFpbFBhZ2Uoc2VsZWN0ZWRQYWdlKSB7XG5cdGlmIChzZWxlY3RlZFBhZ2UgPj0gMSAmJiBzZWxlY3RlZFBhZ2UgPD0gZGF0YVsndGh1bWJuYWlsc01heGltdW1QYWdlJ10pIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRcdHZhciBvZmZzZXRYID0gJHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGljay10cmFjaycpLm9mZnNldCgpLmxlZnQgLSAkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrIC5zbGlkZVtkYXRhLXNsaWNrLWluZGV4PVwiJyArIChzZWxlY3RlZFBhZ2UgKiBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlRodW1ibmFpbC5zbGlkZXNUb1Nob3cgLSBJbWFnZUNvbnN0YW50cy5TbGlja1NsaWRlci5PcHRpb25zLlRodW1ibmFpbC5zbGlkZXNUb1Nob3cpICsgJ1wiXScpLm9mZnNldCgpLmxlZnQgKyAncHgnO1xuXHRcdFx0JHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGljay10cmFjaycpLmNzcygndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZTNkKCcgKyBvZmZzZXRYICsgJywgMCwgMCknKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIG9mZnNldFkgPSAkdGh1bWJuYWlsSW1hZ2VTbGlkZXMuZmluZCgnLnNsaWNrLXRyYWNrJykub2Zmc2V0KCkudG9wIC0gJHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGljay10cmFjayAuc2xpZGVbZGF0YS1zbGljay1pbmRleD1cIicgKyAoc2VsZWN0ZWRQYWdlICogSW1hZ2VDb25zdGFudHMuU2xpY2tTbGlkZXIuT3B0aW9ucy5UaHVtYm5haWwuc2xpZGVzVG9TaG93IC0gSW1hZ2VDb25zdGFudHMuU2xpY2tTbGlkZXIuT3B0aW9ucy5UaHVtYm5haWwuc2xpZGVzVG9TaG93KSArICdcIl0nKS5vZmZzZXQoKS50b3AgKyAncHgnO1xuXHRcdFx0JHRodW1ibmFpbEltYWdlU2xpZGVzLmZpbmQoJy5zbGljay10cmFjaycpLmNzcygndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZTNkKDAsICcgKyBvZmZzZXRZICsgJywgMCknKTtcblx0XHR9XG5cblx0XHRpZiAoc2VsZWN0ZWRQYWdlID4gMSkge1xuXHRcdFx0JHRodW1ibmFpbEltYWdlQ29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRodW1ibmFpbHMtYXJyb3cucHJldmlvdXMnKS5yZW1vdmVDbGFzcygnZGlzYWJsZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5wcmV2aW91cycpLmFkZENsYXNzKCdkaXNhYmxlJyk7XG5cdFx0fVxuXG5cdFx0aWYgKHNlbGVjdGVkUGFnZSA8IGRhdGFbJ3RodW1ibmFpbHNNYXhpbXVtUGFnZSddKSB7XG5cdFx0XHQkdGh1bWJuYWlsSW1hZ2VDb250YWluZXIuZmluZCgnLnByb2R1Y3QtdGh1bWJuYWlscy1hcnJvdy5uZXh0JykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRodW1ibmFpbEltYWdlQ29udGFpbmVyLmZpbmQoJy5wcm9kdWN0LXRodW1ibmFpbHMtYXJyb3cubmV4dCcpLmFkZENsYXNzKCdkaXNhYmxlJyk7XG5cdFx0fVxuXG5cdFx0ZGF0YVsndGh1bWJuYWlsc0N1cnJlbnRQYWdlJ10gPSBzZWxlY3RlZFBhZ2U7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlSW1hZ2VWaWV3ZXJPblNsaWRlKCRzbGlkZSkge1xuXHRpZiAoJHNsaWRlLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5sZW5ndGggPiAwKSB7XG5cdFx0JHNsaWRlLmZpbmQoJ2ltZycpLnJlbW92ZUNsYXNzKCdoaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdkZXN0cm95Jyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUltYWdlVmlld2VyT25TbGlkZSgkc2xpZGVUb0luaXRpYWxpemUpIHtcblx0aWYgKCRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcuaGlnaC1yZXNvbHV0aW9uJykubGVuZ3RoID09IDApIHtcblx0XHQkc2xpZGVUb0luaXRpYWxpemUuZmluZCgnaW1nJykuYXR0cignc3JjJywgJHNsaWRlVG9Jbml0aWFsaXplLmZpbmQoJ2Euem9vbWVkSW1hZ2UnKS5hdHRyKCdocmVmJykpLmFkZENsYXNzKCdoaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKHtcblx0XHRcdHpvb21NYXg6IDQsXG5cdFx0XHRkcmFnYWJsZTogZmFsc2UsXG5cdFx0XHRvblJlYWR5OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGltZ1ZpZXdlcjIgPSB0aGlzO1xuXHRcdFx0XHR2YXIgbWFwID0gdGhpcy5tYXA7XG5cblx0XHRcdFx0aW1nVmlld2VyMi5zZXRab29tKDEpO1xuXHRcdFx0XHRpZiAobWFwICYmIG1hcC50YXApIHtcblx0XHRcdFx0XHRtYXAudGFwLmRpc2FibGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobWFwICYmIG1hcC5kcmFnZ2luZykge1xuXHRcdFx0XHRcdG1hcC5kcmFnZ2luZy5kaXNhYmxlKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkKG1hcC5nZXRDb250YWluZXIoKSkub2ZmKCd3aGVlbCcpLm9uKCd3aGVlbCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0dmFyIHdoZWVsU2Nyb2xsQW5pbWF0aW9uVGFyZ2V0RGVsdGEgPSAwO1xuXG5cdFx0XHRcdFx0aWYgKGRhdGFbJ3doZWVsU2Nyb2xsQW5pbWF0aW9uJ10pIHtcblx0XHRcdFx0XHRcdHdoZWVsU2Nyb2xsQW5pbWF0aW9uVGFyZ2V0RGVsdGEgPSBkYXRhWyd3aGVlbFNjcm9sbEFuaW1hdGlvblRhcmdldCddIC0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpO1xuXHRcdFx0XHRcdFx0ZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb24nXS5zdG9wKCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIHpvb21MZXZlbCA9IGltZ1ZpZXdlcjIuZ2V0Wm9vbSgpO1xuXHRcdFx0XHRcdHZhciB6b29tTWF4aW11bSA9ICRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignb3B0aW9uJywgJ3pvb21NYXgnKTtcblx0XHRcdFx0XHRpZiAoKHpvb21MZXZlbCA9PSAxICYmIGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGVsdGFZID4gMCkgfHwgKHpvb21MZXZlbCA+ICh6b29tTWF4aW11bSAtIDAuNSkpICYmIGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGVsdGFZIDwgMCkge1xuXHRcdFx0XHRcdFx0ZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb25UYXJnZXQnXSA9ICQod2luZG93KS5zY3JvbGxUb3AoKSArIGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGVsdGFZICsgd2hlZWxTY3JvbGxBbmltYXRpb25UYXJnZXREZWx0YTtcblx0XHRcdFx0XHRcdGRhdGFbJ3doZWVsU2Nyb2xsQW5pbWF0aW9uJ10gPSAkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7XG5cdFx0XHRcdFx0XHRcdHNjcm9sbFRvcDogZGF0YVsnd2hlZWxTY3JvbGxBbmltYXRpb25UYXJnZXQnXVxuXHRcdFx0XHRcdFx0fSwge1xuXHRcdFx0XHRcdFx0XHRkdXJhdGlvbjogJ2Zhc3QnLFxuXHRcdFx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oKSB7IFxuXHRcdFx0XHRcdFx0XHRcdGRhdGFbJ3doZWVsU2Nyb2xsQW5pbWF0aW9uJ10gPSBudWxsO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdG1hcC5vbignem9vbScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0dmFyIHpvb21MZXZlbCA9IGltZ1ZpZXdlcjIuZ2V0Wm9vbSgpO1xuXG5cdFx0XHRcdFx0aWYgKHpvb21MZXZlbCA+IDEuMDUpIHtcblx0XHRcdFx0XHRcdCRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignb3B0aW9uJywgJ2RyYWdhYmxlJywgdHJ1ZSk7XG5cblx0XHRcdFx0XHRcdGlmIChtYXAgJiYgbWFwLnRhcCkge1xuXHRcdFx0XHRcdFx0XHRtYXAudGFwLmVuYWJsZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKG1hcCAmJiBtYXAuZHJhZ2dpbmcpIHtcblx0XHRcdFx0XHRcdFx0bWFwLmRyYWdnaW5nLmVuYWJsZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0JCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLnNsaWNrKCdzbGlja1NldE9wdGlvbicsICdkcmFnZ2FibGUnLCBmYWxzZSwgdHJ1ZSk7XG5cdFx0XHRcdFx0XHQkKCcuc2xpZGVyLXNpbmdsZS1pbWFnZSAuc2xpZGVzJykuc2xpY2soJ3NsaWNrU2V0T3B0aW9uJywgJ3N3aXBlJywgZmFsc2UsIHRydWUpO1xuXHRcdFx0XHRcdFx0JCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLnNsaWNrKCdzbGlja1NldE9wdGlvbicsICd0b3VjaE1vdmUnLCBmYWxzZSwgdHJ1ZSk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignb3B0aW9uJywgJ2RyYWdhYmxlJywgZmFsc2UpO1xuXG5cdFx0XHRcdFx0XHRpZiAobWFwICYmIG1hcC50YXApIHtcblx0XHRcdFx0XHRcdFx0bWFwLnRhcC5kaXNhYmxlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAobWFwICYmIG1hcC5kcmFnZ2luZykge1xuXHRcdFx0XHRcdFx0XHRtYXAuZHJhZ2dpbmcuZGlzYWJsZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0JCgnLnNsaWRlci1zaW5nbGUtaW1hZ2UgLnNsaWRlcycpLnNsaWNrKCdzbGlja1NldE9wdGlvbicsICdkcmFnZ2FibGUnLCB0cnVlLCB0cnVlKTtcblx0XHRcdFx0XHRcdCQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKS5zbGljaygnc2xpY2tTZXRPcHRpb24nLCAnc3dpcGUnLCB0cnVlLCB0cnVlKTtcblx0XHRcdFx0XHRcdCQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKS5zbGljaygnc2xpY2tTZXRPcHRpb24nLCAndG91Y2hNb3ZlJywgdHJ1ZSwgdHJ1ZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHR2YXIgc2xpZGVJbWFnZU1hcCA9ICRzbGlkZVRvSW5pdGlhbGl6ZS5maW5kKCdpbWcuaGlnaC1yZXNvbHV0aW9uJykuaW1nVmlld2VyMignZ2V0TWFwJyk7XG5cdFx0aWYgKHNsaWRlSW1hZ2VNYXApIHtcblx0XHRcdHNsaWRlSW1hZ2VNYXAuaW52YWxpZGF0ZVNpemUoKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gbWFwUmVzaXplVGltZXJIYW5kbGVyKCkge1xuXHRpZiAoZGF0YVsnc2luZ2xlSW1hZ2VTbGlkZXNJbml0aWFsU2xpZGUnXSAhPSB1bmRlZmluZWQpIHtcblx0XHR2YXIgJGluaXRpYWxTbGlkZSA9ICQoJy5zbGlkZXItc2luZ2xlLWltYWdlIC5zbGlkZXMnKS5maW5kKCdbZGF0YS1zbGljay1pbmRleD1cIicgKyBkYXRhWydzaW5nbGVJbWFnZVNsaWRlc0luaXRpYWxTbGlkZSddICsgJ1wiXScpO1xuXHRcdHJlc2l6ZVNsaWRlclRvTWF0Y2hTbGlkZSgkaW5pdGlhbFNsaWRlKTtcblxuICAgICAgICB2YXIgc2xpY2sgPSAkc2luZ2xlSW1hZ2VTbGlkZXMuc2xpY2soJ2dldFNsaWNrJyk7XG4gICAgICAgIHZhciAkY3VycmVudFNsaWRlID0gJHNpbmdsZUltYWdlU2xpZGVzLmZpbmQoJ1tkYXRhLXNsaWNrLWluZGV4PVwiJyArIHNsaWNrLmN1cnJlbnRTbGlkZSArICdcIl0nKTtcblx0XHR2YXIgY3VycmVudFNsaWRlSW1hZ2VNYXAgPSAkY3VycmVudFNsaWRlLmZpbmQoJ2ltZy5oaWdoLXJlc29sdXRpb24nKS5pbWdWaWV3ZXIyKCdnZXRNYXAnKTtcblx0XHRpZiAoY3VycmVudFNsaWRlSW1hZ2VNYXApIHtcblx0XHRcdGN1cnJlbnRTbGlkZUltYWdlTWFwLmludmFsaWRhdGVTaXplKCk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHJlc2l6ZVNsaWRlclRvTWF0Y2hTbGlkZSgkc2xpZGUpIHtcblx0dmFyICRzbGlkZVRyYWNrID0gJHNsaWRlLmNsb3Nlc3QoJy5zbGljay10cmFjaycpO1xuXHQkc2xpZGVUcmFjay5jc3MoJ2hlaWdodCcsICdhdXRvJyk7XG5cblx0dmFyICRzbGlkZUltYWdlID0gJHNsaWRlLmZpbmQoJy5zbGlkZS1pbWFnZSA+IGltZycpO1xuXHR2YXIgc2xpZGVJbWFnZUhlaWdodCA9ICRzbGlkZS5oZWlnaHQoKTtcblx0dmFyIHNsaWRlSW1hZ2VXaWR0aCA9ICRzbGlkZS53aWR0aCgpO1xuXHR2YXIgc2xpZGVBc3BlY3RSYXRpbyA9IHNsaWRlSW1hZ2VXaWR0aCAvIHNsaWRlSW1hZ2VIZWlnaHQ7XG5cblx0JHNsaWRlVHJhY2suY3NzKCdoZWlnaHQnLCBzbGlkZUltYWdlSGVpZ2h0KTtcblx0JHNsaWRlVHJhY2suZmluZCgnLnNsaWNrLXNsaWRlJykubm90KCRzbGlkZSkuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkdGhpc0ltYWdlID0gJHRoaXMuZmluZCgnLnNsaWRlLWltYWdlID4gaW1nJyk7XG5cdFx0dmFyIHRoaXNJbWFnZUFzcGVjdFJhdGlvID0gJHRoaXNJbWFnZS53aWR0aCgpIC8gJHRoaXNJbWFnZS5oZWlnaHQoKTtcblxuXHRcdGlmICgkdGhpc0ltYWdlLmhlaWdodCgpID4gc2xpZGVJbWFnZUhlaWdodCAmJiB0aGlzSW1hZ2VBc3BlY3RSYXRpbyA8PSBzbGlkZUFzcGVjdFJhdGlvKSB7XG5cdFx0XHQkdGhpcy5hZGRDbGFzcygnY29uc3RyYWluLWhlaWdodCcpO1xuXHRcdH1cblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2Fyb3VzZWxWaWRlbyA9IHJlcXVpcmUoJy4uL0Nhcm91c2VsVmlkZW8nKTtcblxuLy8gR2xvYmFsIHZhcnNcbnZhciBvcHRpb25zO1xudmFyIGlzTW9iaWxlID0gd2luZG93LmlubmVyV2lkdGggPD0gNzY3O1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKHBhcmFtcykge1xuXHRpZiAocGFyYW1zKSB7XG5cdFx0b3B0aW9ucyA9IHBhcmFtcztcblx0fVxuXHR2YXIgdGh1bWJHYWxsZXJ5U3dpcGVyLCBsYXJnZVN3aXBlcixcblx0XHR0aHVtYkdhbGxlcnlCcmVha3BvaW50cyA9IG9wdGlvbnMgJiYgb3B0aW9ucy50aHVtYkdhbGxlcnlCcmVha3BvaW50cyA/IG9wdGlvbnMudGh1bWJHYWxsZXJ5QnJlYWtwb2ludHMgOiBudWxsLFxuXHRcdHRodW1iR2FsbGVyeUJyZWFrcG9pbnRTZXR0aW5ncyA9IHRodW1iR2FsbGVyeUJyZWFrcG9pbnRzID8gKGlzTW9iaWxlID8gdGh1bWJHYWxsZXJ5QnJlYWtwb2ludHNbJzAnXSA6IHRodW1iR2FsbGVyeUJyZWFrcG9pbnRzWyc3NjgnXSkgOiBudWxsLFxuXHRcdGVuYWJsZVRodW1iR2FsbGVyeUZvckN1cnJlbnRCcmVha3BvaW50ID0gdGh1bWJHYWxsZXJ5QnJlYWtwb2ludFNldHRpbmdzICYmIHRodW1iR2FsbGVyeUJyZWFrcG9pbnRTZXR0aW5ncy5lbmFibGVkLFxuXHRcdGlzVGh1bWJuYWlsc0VsbSA9ICQoJy50aHVtYnMtcHJvZHVjdC1zd2lwZXInKS5sZW5ndGggPiAwO1xuXG5cdC8vIENoZWNrIHRvIHNlZSBpZiB3ZSBoYXZlIGFueSB0aHVtYm5haWxzIGF0IGFsbFxuXHRpZiAoaXNUaHVtYm5haWxzRWxtKSB7XG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aHVtYm5haWxzIGdhbGxlcnkgYW5kIGFzc2lnbiBpbnN0YW5jZSB0byAndGh1bWJHYWxsZXJ5U3dpcGVyJ1xuXHRcdGlmIChlbmFibGVUaHVtYkdhbGxlcnlGb3JDdXJyZW50QnJlYWtwb2ludCkge1xuXHRcdFx0dGh1bWJHYWxsZXJ5U3dpcGVyID0gdGh1bWJHYWxsZXJ5U3dpcGVySW5pdChvcHRpb25zKTtcblx0XHRcdC8vIFRodW1ibmFpbCBzbGlkZXIgbW9kaWZpY2F0aW9ucyAtIGNhbiBvbmx5IG1ha2UgbW9kcyBhZnRlciB0aHVtYnMgZ2FsbGVyeSBzbGlkZXIgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuXG5cdFx0XHQvLyBObyBkZWZhdWx0IGFycm93IG5hdmlnYXRpb24gZXhpc3RzIGZvciB0aHVtYm5haWxzIGdhbGxlcnkgaW4gc3dpcGVyLCBzbyB3ZSBhZGQgb3VyIG93bi5cblx0XHRcdHRodW1iR2FsbGVyeU5hdmlnYXRpb24ob3B0aW9ucywgdGh1bWJHYWxsZXJ5U3dpcGVyLCB0aHVtYkdhbGxlcnlCcmVha3BvaW50U2V0dGluZ3MpO1xuXHRcdFx0aWYgKGlzTW9iaWxlKSB7XG5cdFx0XHRcdCQoJy5wcm9kdWN0LWltYWdlLWNvbnRhaW5lci1tb2JpbGUnKS5hZGRDbGFzcygnc3dpcGVyLXRodW1icy1tb2JpbGUtZWRpdHMnKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnRodW1icy1wcm9kdWN0LXN3aXBlcicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblx0XHR9XG5cdFx0Ly8gSW5pdGlhbGl6ZSBQRFAgbWFpbiBpbWFnZSBzd2lwZXIgYW5kIHBhc3MgaW4gdGh1bWJuYWlscyBnYWxsZXJ5IGlmIGl0IGV4aXN0c1xuXHRcdGxhcmdlU3dpcGVyID0gbGFyZ2VTd2lwZXJJbml0KG9wdGlvbnMsIHRodW1iR2FsbGVyeVN3aXBlcik7XG5cdH0gZWxzZSB7XG5cdFx0bGFyZ2VTd2lwZXIgPSBsYXJnZVN3aXBlckluaXQob3B0aW9ucywgbnVsbCk7XG5cdH1cblxuXHRpZiAob3B0aW9ucy56b29tKSB7XG5cdFx0JCgnI3BkcE1haW4nKS5vZmYoJ2NsaWNrLlZhcmlhbnQuU3dpcGVyLlpvb20uSW4nKS5vbignY2xpY2suVmFyaWFudC5Td2lwZXIuWm9vbS5JbicsICcuY3VzdG9tLmxlYWZsZXQtY29udHJvbC16b29tLWluJywgZnVuY3Rpb24gKGUpIHtcblx0XHRcdGxhcmdlU3dpcGVyLnpvb20uaW4oKTtcblx0XHR9KTtcblx0XHRcblx0XHQkKCcjcGRwTWFpbicpLm9mZignY2xpY2suVmFyaWFudC5Td2lwZXIuWm9vbS5PdXQnKS5vbignY2xpY2suVmFyaWFudC5Td2lwZXIuWm9vbS5PdXQnLCAnLmN1c3RvbS5sZWFmbGV0LWNvbnRyb2wtem9vbS1vdXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0bGFyZ2VTd2lwZXIuem9vbS5vdXQoKTtcblx0XHR9KTtcblx0fVxuXG5cdGNhcm91c2VsVmlkZW8uaW5pdCgpO1xufVxuXG5mdW5jdGlvbiB0aHVtYkdhbGxlcnlTd2lwZXJJbml0KG9wdGlvbnMpIHtcblx0Ly8gVGh1bWJuYWlscyBzd2lwZXIgb3B0aW9uc1xuXHR2YXIgdGh1bWJuYWlsc1N3aXBlck9wdGlvbnMgPSB7XG5cdFx0ZGlyZWN0aW9uOiBpc01vYmlsZSA/ICdob3Jpem9udGFsJyA6J3ZlcnRpY2FsJyxcblx0XHRzbGlkZXNQZXJWaWV3OiA3LFxuXHRcdHNsaWRlc1Blckdyb3VwOiA3LFxuXHRcdGxvb3A6IGZhbHNlLFxuXHRcdHNsaWRlVG9DbGlja2VkU2xpZGU6IHRydWUsXG5cdFx0YWxsb3dUb3VjaE1vdmU6IHRydWUsXG5cdFx0YTExeToge1xuICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgIGZpcnN0U2xpZGVNZXNzYWdlOiAnVGhpcyBpcyB0aGUgZmlyc3Qgc2xpZGUnLFxuICAgICAgICAgICAgbGFzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGxhc3Qgc2xpZGUnXG4gICAgICAgIH0sXG5cdFx0a2V5Ym9hcmQ6IHtcblx0XHRcdGVuYWJsZWQ6IHRydWUsXG5cdFx0XHRwYWdlVXBEb3duOiB0cnVlXG5cdFx0fVxuXHR9O1xuXG5cdGlmIChvcHRpb25zLnRodW1iR2FsbGVyeVNjcm9sbERpcmVjdGlvbikge1xuXHRcdHRodW1ibmFpbHNTd2lwZXJPcHRpb25zLmRpcmVjdGlvbiA9IGlzTW9iaWxlID8gJ2hvcml6b250YWwnIDogb3B0aW9ucy50aHVtYkdhbGxlcnlTY3JvbGxEaXJlY3Rpb247XG5cdH1cblxuXHQvLyBJbml0aWF0ZSB0aHVtYm5haWxzIHN3aXBlclxuXHRyZXR1cm4gbmV3IFN3aXBlciAoJy50aHVtYnMtcHJvZHVjdC1zd2lwZXInLCB0aHVtYm5haWxzU3dpcGVyT3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIGxhcmdlU3dpcGVySW5pdChvcHRpb25zLCB0aHVtYm5haWxzU3dpcGVyKSB7XG5cdHZhciBsYXJnZVN3aXBlck9wdGlvbnM7XG5cdHZhciBtb2JpbGVEb3RzID0gb3B0aW9ucy5icmVha3BvaW50cyAmJiBvcHRpb25zLmJyZWFrcG9pbnRzWycwJ10gJiYgb3B0aW9ucy5icmVha3BvaW50c1snMCddLmRvdHMgPyBvcHRpb25zLmJyZWFrcG9pbnRzWycwJ10uZG90cyA6IHRydWU7XG5cdHZhciBkZXNrdG9wRG90cyA9IG9wdGlvbnMuYnJlYWtwb2ludHMgJiYgb3B0aW9ucy5icmVha3BvaW50c1snNzY4J10gJiYgb3B0aW9ucy5icmVha3BvaW50c1snNzY4J10uZG90cyA/IG9wdGlvbnMuYnJlYWtwb2ludHNbJzc2OCddLmRvdHMgOiBmYWxzZTtcblxuXHQvLyBMYXJnZSBwcm9kdWN0IHN3aXBlciBvcHRpb25zXG5cdGxhcmdlU3dpcGVyT3B0aW9ucyA9IHtcblx0XHRzbGlkZXNQZXJWaWV3OiAxLFxuXHRcdGNlbnRlcmVkU2xpZGVzOiB0cnVlLFxuXHRcdGxvb3A6IGZhbHNlLFxuXHRcdGExMXk6IHtcbiAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICBmaXJzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGZpcnN0IHNsaWRlJyxcbiAgICAgICAgICAgIGxhc3RTbGlkZU1lc3NhZ2U6ICdUaGlzIGlzIHRoZSBsYXN0IHNsaWRlJ1xuICAgICAgICB9LFxuXHRcdGtleWJvYXJkOiB7XG5cdFx0XHRlbmFibGVkOiB0cnVlLFxuXHRcdFx0cGFnZVVwRG93bjogdHJ1ZVxuXHRcdH0sXG5cdFx0YnJlYWtwb2ludHM6IHtcblx0XHRcdDA6IHtcblx0XHRcdFx0cGFnaW5hdGlvbjoge1xuXHRcdFx0XHRcdGVuYWJsZWQ6IG1vYmlsZURvdHMsXG5cdFx0XHRcdFx0ZWw6ICcuc3dpcGVyLXBhZ2luYXRpb24nLFxuXHRcdFx0XHRcdGNsaWNrYWJsZTogdHJ1ZVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0NzY4OiB7XG5cdFx0XHRcdHBhZ2luYXRpb246IHtcblx0XHRcdFx0XHRlbmFibGVkOiBkZXNrdG9wRG90cyxcblx0XHRcdFx0XHRlbDogJy5zd2lwZXItcGFnaW5hdGlvbicsXG5cdFx0XHRcdFx0Y2xpY2thYmxlOiB0cnVlXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0aWYgKGRlc2t0b3BEb3RzIHx8IG1vYmlsZURvdHMpIHtcblx0XHR2YXIgbW9kaWZpZXJDbGFzcztcblx0XHRpZiAoIWRlc2t0b3BEb3RzICYmIG1vYmlsZURvdHMpIHtcblx0XHRcdG1vZGlmaWVyQ2xhc3MgPSAnc3dpcGVyLXBhZ2luYXRlZC1tb2JpbGUtJztcblx0XHR9XG5cdFx0aWYgKGRlc2t0b3BEb3RzICYmICFtb2JpbGVEb3RzKSB7XG5cdFx0XHRtb2RpZmllckNsYXNzID0gJ3N3aXBlci1wYWdpbmF0ZWQtZGVza3RvcC0nO1xuXHRcdH1cblx0XHRpZiAoZGVza3RvcERvdHMgJiYgbW9iaWxlRG90cykge1xuXHRcdFx0bW9kaWZpZXJDbGFzcyA9ICdzd2lwZXItcGFnaW5hdGVkLWJvdGgtJztcblx0XHR9XG5cdFx0aWYgKG1vZGlmaWVyQ2xhc3MpIHtcblx0XHRcdGxhcmdlU3dpcGVyT3B0aW9ucy5jb250YWluZXJNb2RpZmllckNsYXNzID0gbW9kaWZpZXJDbGFzcztcblx0XHR9XG5cdH1cblxuXHRpZiAob3B0aW9ucy56b29tKSB7XG5cdFx0bGFyZ2VTd2lwZXJPcHRpb25zLnpvb20gPSB7XG5cdFx0XHRtYXhSYXRpbzogMyxcblx0XHRcdG1pblJhdGlvOiAxXG5cdFx0fVxuXHR9XG5cblx0aWYgKHRodW1ibmFpbHNTd2lwZXIpIHtcblx0XHRsYXJnZVN3aXBlck9wdGlvbnMudGh1bWJzID0ge1xuXHRcdFx0c3dpcGVyOiB0aHVtYm5haWxzU3dpcGVyXG5cdFx0fVxuXHR9XG5cblx0Ly8gSW5pdGlhdGUgbGFyZ2UgcHJvZHVjdCBzd2lwZXJcblx0cmV0dXJuIG5ldyBTd2lwZXIgKCcubGFyZ2UtcHJvZHVjdC1zd2lwZXInLCBsYXJnZVN3aXBlck9wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiB0aHVtYkdhbGxlcnlOYXZpZ2F0aW9uKG9wdGlvbnMsIHN3aXBlckluc3RhbmNlLCBicmVha3BvaW50U2V0dGluZ3MpIHtcblx0dmFyICRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudCA9ICQoJy50aHVtYnMtcHJvZHVjdC1zd2lwZXInKTtcblx0aWYgKCEkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQgfHwgIXN3aXBlckluc3RhbmNlIHx8ICFicmVha3BvaW50U2V0dGluZ3MgfHwgJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50LmZpbmQoJy5zd2lwZXItc2xpZGUnKS5sZW5ndGggPCA4KSB7XG5cdFx0cmV0dXJuO1xuXHR9IGVsc2Uge1xuXHRcdHZhciBhZGROYXZpZ2F0aW9uID0gYnJlYWtwb2ludFNldHRpbmdzID8gKGJyZWFrcG9pbnRTZXR0aW5ncy5hcnJvd3MgPyBicmVha3BvaW50U2V0dGluZ3MuYXJyb3dzIDogZmFsc2UpIDogbnVsbCxcblx0XHRcdGlzVmVydGljYWwgPSAkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuaGFzQ2xhc3MoJ3N3aXBlci12ZXJ0aWNhbCcpLFxuXHRcdFx0aXNIb3Jpem9udGFsID0gJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50Lmhhc0NsYXNzKCdzd2lwZXItaG9yaXpvbnRhbCcpLFxuXHRcdFx0dGh1bWJHYWxsZXJ5U2xpZGVzID0gJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50LmZpbmQoJy5zd2lwZXItc2xpZGUnKSxcblx0XHRcdHRodW1ic0RpcmVjdGlvbkNsYXNzID0gaXNWZXJ0aWNhbCA/ICd0aHVtYnMtdmVydGljYWwnIDogJ3RodW1icy1ob3Jpem9udGFsJywgXG5cdFx0XHQkdGh1bWJuYWlsc05hdmlnYXRpb24gPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAndGh1bWJzLXByb2R1Y3QtbmF2aWdhdGlvbicgfSksXG5cdFx0XHRjYXJldHM7XG5cblx0XHRcdGlmIChhZGROYXZpZ2F0aW9uKSB7XG5cdFx0XHRcdGlmIChpc1ZlcnRpY2FsKSB7XG5cdFx0XHRcdFx0Y2FyZXRzID0gJzxpIGNsYXNzPVwiZmEtc29saWQgZmEtYW5nbGUtdXAgZC1ub25lXCI+PC9pPjxpIGNsYXNzPVwiZmEtc29saWQgZmEtYW5nbGUtZG93blwiPjwvaT4nO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChpc0hvcml6b250YWwpIHtcblx0XHRcdFx0XHRjYXJldHMgPSAnPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1hbmdsZS1sZWZ0IGQtbm9uZVwiPjwvaT48aSBjbGFzcz1cImZhLXNvbGlkIGZhLWFuZ2xlLXJpZ2h0XCI+PC9pPic7XG5cdFx0XHRcdH1cblx0XHRcdFx0JHRodW1ibmFpbHNOYXZpZ2F0aW9uLmh0bWwoY2FyZXRzKS5hZGRDbGFzcyh0aHVtYnNEaXJlY3Rpb25DbGFzcykuaW5zZXJ0QmVmb3JlKCRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudCk7XG5cdFx0XHRcdHZhciBwcmV2SWNvbnMgPSAnLnRodW1icy1wcm9kdWN0LW5hdmlnYXRpb24gLmZhLWFuZ2xlLXVwLCAudGh1bWJzLXByb2R1Y3QtbmF2aWdhdGlvbiAuZmEtYW5nbGUtbGVmdCc7XG5cdFx0XHRcdHZhciBuZXh0SWNvbnMgPSAnLnRodW1icy1wcm9kdWN0LW5hdmlnYXRpb24gLmZhLWFuZ2xlLWRvd24sIC50aHVtYnMtcHJvZHVjdC1uYXZpZ2F0aW9uIC5mYS1hbmdsZS1yaWdodCc7XG5cdFx0XHRcdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsIHByZXZJY29ucywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0c3dpcGVySW5zdGFuY2Uuc2xpZGVQcmV2KDUwMCk7XG5cdFx0XHRcdFx0dmFyIHByZXZJY29uc0ZpcnN0VmlzaWJsZUluZGV4ID0gdGh1bWJHYWxsZXJ5U2xpZGVzLmluZGV4KCRzd2lwZXJUaHVtYm5haWxzRG9tRWxlbWVudC5maW5kKCcuc3dpcGVyLXNsaWRlLXZpc2libGU6Zmlyc3QnKSk7XG5cdFx0XHRcdFx0dmFyIHByZXZJY29uc0xhc3RWaXNpYmxlSW5kZXggPSB0aHVtYkdhbGxlcnlTbGlkZXMuaW5kZXgoJHN3aXBlclRodW1ibmFpbHNEb21FbGVtZW50LmZpbmQoJy5zd2lwZXItc2xpZGUtdmlzaWJsZTpsYXN0JykpO1xuXHRcdFx0XHRcdGlmIChwcmV2SWNvbnNGaXJzdFZpc2libGVJbmRleCA9PSAwKSB7XG5cdFx0XHRcdFx0XHQkKHByZXZJY29ucykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkKHByZXZJY29ucykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAocHJldkljb25zTGFzdFZpc2libGVJbmRleCA8IDcpIHtcblx0XHRcdFx0XHRcdCQobmV4dEljb25zKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQobmV4dEljb25zKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgbmV4dEljb25zLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRzd2lwZXJJbnN0YW5jZS5zbGlkZU5leHQoNTAwKTtcblx0XHRcdFx0XHR2YXIgbmV4dEljb25zTGFzdFZpc2libGVJbmRleCA9IHRodW1iR2FsbGVyeVNsaWRlcy5pbmRleCgkc3dpcGVyVGh1bWJuYWlsc0RvbUVsZW1lbnQuZmluZCgnLnN3aXBlci1zbGlkZS12aXNpYmxlOmxhc3QnKSk7XG5cdFx0XHRcdFx0aWYgKG5leHRJY29uc0xhc3RWaXNpYmxlSW5kZXggPT0gKHRodW1iR2FsbGVyeVNsaWRlcy5sZW5ndGggLSAxKSkge1xuXHRcdFx0XHRcdFx0JChuZXh0SWNvbnMpLmFkZENsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JChuZXh0SWNvbnMpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKG5leHRJY29uc0xhc3RWaXNpYmxlSW5kZXggPiA2KSB7XG5cdFx0XHRcdFx0XHQkKHByZXZJY29ucykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkKHByZXZJY29ucykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XHRcblx0XHRcdH1cblx0fVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xuXG4kLndpZGdldCgnYm9vdGJhcm4ubG9hZGluZycsIHtcbiAgICBvcHRpb25zOiB7XG4gICAgICAgIElzSW1hZ2VTaG93bjogdHJ1ZSxcbiAgICAgICAgSXNMYWJlbFNob3duOiB0cnVlLFxuICAgICAgICBMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuTG9hZGluZyxcbiAgICAgICAgQ29udGVudDogJycsXG4gICAgICAgIENzc0NsYXNzOiAnJyxcbiAgICAgICAgQmFja2dyb3VuZENvbG9yOiBudWxsXG4gICAgfSxcblxuICAgIF9jcmVhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aGlzLmVsZW1lbnQuYXR0cignbG9hZGluZycsICdsb2FkaW5nJyk7XG5cbiAgICAgICAgdmFyIGxvYWRpbmdJbmRpY2F0b3JUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWxvYWRpbmctaW5kaWNhdG9yJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgICAgICB2YXIgJGxvYWRpbmdJbmRpY2F0b3JDb250YWluZXIgPSAkKGxvYWRpbmdJbmRpY2F0b3JUZW1wbGF0ZSh7XG4gICAgICAgIFx0Q29udGVudDogdGhpcy5vcHRpb25zLkNvbnRlbnRcbiAgICAgICAgfSkpO1xuICAgICAgICB2YXIgJGxvYWRpbmdJbmRpY2F0b3IgPSAkbG9hZGluZ0luZGljYXRvckNvbnRhaW5lci5maW5kKCcubG9hZGluZy1pbmRpY2F0b3InKTtcbiAgICAgICAgJGxvYWRpbmdJbmRpY2F0b3JDb250YWluZXIuY3NzKCdiYWNrZ3JvdW5kLWNvbG9yJywgdGhpcy5vcHRpb25zLkJhY2tncm91bmRDb2xvciA/IHRoaXMub3B0aW9ucy5CYWNrZ3JvdW5kQ29sb3IgOiB0aGlzLmVsZW1lbnQuY3NzKCdiYWNrZ3JvdW5kLWNvbG9yJykpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuQ3NzQ2xhc3MpIHtcbiAgICAgICAgICAgICRsb2FkaW5nSW5kaWNhdG9yQ29udGFpbmVyLmFkZENsYXNzKHRoaXMub3B0aW9ucy5Dc3NDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuSXNMYWJlbFNob3duICYmICF0aGlzLm9wdGlvbnMuQ29udGVudCkge1xuICAgICAgICAgICAgJGxvYWRpbmdJbmRpY2F0b3IuYWRkQ2xhc3MoJ2xhYmVsJyk7XG4gICAgICAgICAgICAkbG9hZGluZ0luZGljYXRvci5hdHRyKCdsYWJlbCcsIHRoaXMub3B0aW9ucy5MYWJlbCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLklzSW1hZ2VTaG93bikge1xuICAgICAgICAgICAgJGxvYWRpbmdJbmRpY2F0b3IuYWRkQ2xhc3MoJ2ltYWdlJyk7XG4gICAgICAgIH1cblxuXHRcdCRsb2FkaW5nSW5kaWNhdG9yQ29udGFpbmVyLmFwcGVuZFRvKHRoaXMuZWxlbWVudCk7XG5cdH0sXG4gICAgXG4gICAgX2Rlc3Ryb3k6IGZ1bmN0aW9uKCkge1xuXHRcdHRoaXMuZWxlbWVudC5yZW1vdmVBdHRyKCdsb2FkaW5nJykuZmluZCgnLmxvYWRpbmctaW5kaWNhdG9yLWNvbnRhaW5lcicpLnJlbW92ZSgpO1xuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG5leHBvcnRzLkluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuZXhwb3J0cy5DbG9zZU5hdmlnYXRpb24gPSBjbG9zZU5hdmlnYXRpb247XG5cbnZhciBuYXZEYXRhQnVmZmVyID0ge307XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG5cdHZhciBzaXRlTmFtZSA9ICQoJy50b3AtYmFubmVyLWJhcicpLmRhdGEoJ2hlYWRlci1mb3InKSB8fCBcIlwiO1xuXHR2YXIgJG5hdlNlY29uZGFyeSA9ICQoJy5uYXYtc2Vjb25kYXJ5Jyk7XG5cdFxuXHQkKCcubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnBhcmVudCgpLmFkZENsYXNzKCdoYXMtZHJvcGRvd24nKTtcblx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0aWYgKHdpbmRvdy5pbm5lcldpZHRoIDwgMTAyNCkge1xuXHRcdFx0JG5hdlNlY29uZGFyeS5maW5kKCdsaSNsb2NhdGlvbicpLnJlbW92ZUNsYXNzKCdoYXMtZHJvcGRvd24nKTtcblx0XHR9XG5cdH1cblxuXHQvLyBCb290QmFybiAyMDIwIEZ1bGwgd2lkdGggbmF2IGRyb3AgZG93biBoZWxwZXJcblx0aWYgKCQoJy50b3AtYmFubmVyLWJhcicpLmRhdGEoJ2hlYWRlci1mb3InKSA9PSAnYm9vdGJhcm5fdXMnKSB7XG5cdFx0Ly8gbWFpbiBuYXYgaG92ZXIgZWZmZWN0c1x0XHRcblx0XHQkKCdodG1sICNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKS5ob3ZlcihmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuXHRcdFx0XHQkKHRoaXMpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCh0aGlzKS5jbG9zZXN0KCcudG9wLWJhbm5lcicpLmFkZENsYXNzKCduYXYtYWN0aXZlJyk7XG5cdFx0XHRcdCQoJ2h0bWwnKS5hZGRDbGFzcygnZGVza3RvcC1uYXYtYWN0aXZlJyk7XG5cdFx0XHRcdCQoJy5uYXYtY292ZXInKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0fSwgZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKCEkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdFx0JCgnLm5hdi1jb3ZlcicpLmhpZGUoKTtcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXInKS5yZW1vdmVDbGFzcygnbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ2Rlc2t0b3AtbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHQkKHRoaXMpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRcblx0aWYgKCRuYXZTZWNvbmRhcnkuZmluZCgnI2xvY2F0aW9uLWRpc3BsYXktY2FwdGlvbicpLmxlbmd0aCA+IDAgJiYgJG5hdlNlY29uZGFyeS5maW5kKCcjbG9jYXRpb24tZGlzcGxheS1jYXB0aW9uJykuaGFzQ2xhc3MoJ25vLXN0b3JlLXRvLWRpc3BsYXknKSkge1xuXHRcdGlmICgkbmF2U2Vjb25kYXJ5LmZpbmQoJyNsb2NhdGlvbi1kaXNwbGF5LWNhcHRpb24nKS5wYXJlbnRzKCcjbG9jYXRpb24nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkbmF2U2Vjb25kYXJ5LmZpbmQoJyNsb2NhdGlvbi1kaXNwbGF5LWNhcHRpb24nKS5wYXJlbnRzKCcjbG9jYXRpb24nKS5yZW1vdmVDbGFzcygnaGFzLWRyb3Bkb3duJyk7XG5cdFx0fVxuXHR9XHRcblx0XG5cdC8vIGNvbGxpc2lvbiBkZXRlY3Rpb24gYW5kIGFkanVzdG1lbnQgZm9yIGlmIG1lbnUgb2ZmLXNjcmVlblxuXHQvLyB0aGlzIGlzIGJvdW5kIHRvIGRvY3VtZW50IGFuZCAuc2l6ZS1kZXNrdG9wIHRvIGF2b2lkIGlPUyBpc3N1ZSB3aXRoIGZpcnN0IHRhcCB0cmlnZ2VyaW5nIG1vdXNlb3ZlciBpbnN0ZWFkIG9mIGNsaWNrIC0gZGFuQHJlZHZhblxuXHQkKGRvY3VtZW50KS5vbignbW91c2VvdmVyJywgJ2h0bWwuc2l6ZS1kZXNrdG9wICNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24gPiBhJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRuYXZpZ2F0aW9uQ29sbGlzaW9uRGV0ZWN0aW9uKCQoZXZlbnQuY3VycmVudFRhcmdldCkpO1xuXHR9KTtcblx0XG5cdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93biA+IGEsIC5uYXYtc2Vjb25kYXJ5IC5oYXMtZHJvcGRvd24gPiBhJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRwYXJlbnQgPSAkdGhpcy5jbG9zZXN0KCcuaGFzLWRyb3Bkb3duJyk7XG5cdFx0dmFyICRjb250YWluZXIgPSAkcGFyZW50LmNsb3Nlc3QoJyNuYXZpZ2F0aW9uLCAubmF2LXNlY29uZGFyeScpO1xuXHRcdFxuXHRcdGlmICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdHZhciAkc2Nyb2xsaW5nQ29udGFpbmVyID0gJCgnI25hdmlnYXRpb24nKTtcblx0XHRcdHZhciBvZmZzZXRPcGVuTWVudSA9IDA7XG5cdFx0XHR2YXIgc2Nyb2xsVG9wTmV3ID0gMDtcblx0XHRcdFxuXHRcdFx0aWYgKCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykuZmlyc3QoKS5sZW5ndGggPiAwICYmICgkKCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duLmFjdGl2ZScpLmZpcnN0KCkub2Zmc2V0KCkudG9wIDwgJHRoaXMub2Zmc2V0KCkudG9wKSkge1xuXHRcdFx0XHRvZmZzZXRPcGVuTWVudSA9ICQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykuZmlyc3QoKS5maW5kKCcubGV2ZWwtMiwgLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5vdXRlckhlaWdodCgpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRzY3JvbGxUb3BOZXcgPSAkdGhpcy5vZmZzZXQoKS50b3AgLSAkc2Nyb2xsaW5nQ29udGFpbmVyLm9mZnNldCgpLnRvcCArICRzY3JvbGxpbmdDb250YWluZXIuc2Nyb2xsVG9wKCkgLSBvZmZzZXRPcGVuTWVudTtcblxuXHRcdFx0JHNjcm9sbGluZ0NvbnRhaW5lci5hbmltYXRlKHtcblx0XHRcdFx0c2Nyb2xsVG9wOiBzY3JvbGxUb3BOZXdcblx0XHRcdH0sIDE1MCk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUyAmJiAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtdGFibGV0JykpIHtcblx0XHRcdGlmICgkcGFyZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0XHQkcGFyZW50LnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH0gZWxzZSBpZiAoISRwYXJlbnQuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHRcdCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCRwYXJlbnQuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICgoISQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1kZXNrdG9wJykgJiYgcGFnZUNvbnRleHQuc2l0ZSAhPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHx8ICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykgJiYgcGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpKSB7XG5cdFx0XHQvL2Nsb3NlIG90aGVyIGhlYWRlciBtZW51c1xuXHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0XHRcdCQoJy50b3AtYmFubmVyLWJhciAubmF2LXNlY29uZGFyeSAuaGFzLWRyb3Bkb3duIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuaGlkZSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItYmFyIC5uYXYtc2Vjb25kYXJ5IC5oYXMtZHJvcGRvd24gLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5zdG9wKCkuc2xpZGVVcCgxNTApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoJHBhcmVudC5oYXNDbGFzcygnYWN0aXZlJykpIHtcblx0XHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0XHRcdFx0JHBhcmVudC5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLmxldmVsLTIsIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuaGlkZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCRwYXJlbnQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnN0b3AoKS5zbGlkZVVwKDE1MCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdFx0XHRcdCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLmhpZGUoKTtcblx0XHRcdFx0XHQkcGFyZW50LmFkZENsYXNzKCdhY3RpdmUnKS5maW5kKCcubGV2ZWwtMiwgLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5zaG93KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bi5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLmxldmVsLTIsIC5uYXYtc2Vjb25kYXJ5LWRyb3Bkb3duJykuc3RvcCgpLnNsaWRlVXAoMTUwKTtcblx0XHRcdFx0XHQkcGFyZW50LmFkZENsYXNzKCdhY3RpdmUnKS5maW5kKCcubGV2ZWwtMiwgLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5zdG9wKCkuc2xpZGVEb3duKDE1MCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlOm5vdCguYWNjb3JkaW9uKScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JGNvbnRhaW5lci5hdHRyKCdhY3RpdmUtbWVudS1sZXZlbCcsICcxJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkY29udGFpbmVyLnJlbW92ZUF0dHIoJ2FjdGl2ZS1tZW51LWxldmVsJyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmICgkKCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duLmFjdGl2ZScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JCgnLm1lbnUtdG9nZ2xlJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykuYWRkQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cblx0XHRcdFx0aWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSAmJiB3aW5kb3cuaW5uZXJXaWR0aCA9PSAxMDI0KSB7XG5cdFx0XHRcdFx0JCh0aGlzKS5jbG9zZXN0KCcudG9wLWJhbm5lcicpLmFkZENsYXNzKCduYXYtYWN0aXZlJyk7XG5cdFx0XHRcdFx0JCgnaHRtbCcpLmFkZENsYXNzKCdkZXNrdG9wLW5hdi1hY3RpdmUnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICh3aW5kb3cuaW5uZXJXaWR0aCA+PSAxMDI0KSB7XG5cdFx0XHRcdCQoJy5tZW51LXRvZ2dsZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdtZW51LWFjdGl2ZScpO1xuXG5cdFx0XHRcdGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUyAmJiAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtdGFibGV0JykgJiYgd2luZG93LmlubmVyV2lkdGggPT0gMTAyNCkge1xuXHRcdFx0XHRcdCQodGhpcykuY2xvc2VzdCgnLnRvcC1iYW5uZXInKS5yZW1vdmVDbGFzcygnbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHRcdCQoJ2h0bWwnKS5yZW1vdmVDbGFzcygnZGVza3RvcC1uYXYtYWN0aXZlJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoISQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuXHRcdFx0bmF2aWdhdGlvbkNvbGxpc2lvbkRldGVjdGlvbigkdGhpcyk7XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBmYWxzZTtcblx0fSlcblx0Lm9uKCdjbGljaycsICcubWVudS10b2dnbGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRpZiAoJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpIHx8ICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSkge1xuXHRcdFx0dmFyICRodG1sID0gJCgnaHRtbCcpO1xuXHRcdFx0dmFyICRib2R5ID0gJCgnYm9keScpO1xuXHRcdFx0dmFyICRjb250YWluZXIgPSAkKCcjd3JhcHBlcicpO1xuXHRcdFx0dmFyIGhlYWRlcldyYXBwZXIgPSAkKCcuaGVhZGVyLXdyYXBwZXInKTtcblx0XHRcdHZhciBqdW1ib3Ryb25Db250YWluZXIgPSBoZWFkZXJXcmFwcGVyLmZpbmQoJy5qdW1ib3Ryb24tYWpheCcpO1xuXHRcdFx0dmFyIGxvZ29BbmRMaW5rcyA9IGhlYWRlcldyYXBwZXIuZmluZCgnLmxvZ28tYW5kLWxpbmtzLWNvbnRhaW5lcicpO1xuXHRcdFx0dmFyIG5hdkZpeGVkSGVhZGVyTGltaXQgPSA4MDA7XG5cdFx0XHR2YXIgdG9wQmFubmVyQmFyID0gaGVhZGVyV3JhcHBlci5maW5kKCcudG9wLWJhbm5lci1iYXInKTtcblx0XG5cdFx0XHR2YXIgdG9iQmFubmVySW5uZXJIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSAocGFyc2VGbG9hdCh0b3BCYW5uZXJCYXIub3V0ZXJIZWlnaHQoKSkgKyBwYXJzZUZsb2F0KGp1bWJvdHJvbkNvbnRhaW5lci5vdXRlckhlaWdodCgpKSk7XG5cdFx0XHR2YXIgbmF2Q29udGFpbmVySGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0IC0gKHBhcnNlRmxvYXQodG9wQmFubmVyQmFyLm91dGVySGVpZ2h0KCkpICsgcGFyc2VGbG9hdChsb2dvQW5kTGlua3Mub3V0ZXJIZWlnaHQoKSkgKyBwYXJzZUZsb2F0KGp1bWJvdHJvbkNvbnRhaW5lci5vdXRlckhlaWdodCgpKSk7IFxuXHRcblx0XHRcdGlmICghJGh0bWwuaGFzQ2xhc3MoJ21lbnUtYWN0aXZlJykpIHtcblx0XHRcdFx0dmFyIHNjcm9sbFRvcCA9IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3A7XG5cdFx0XHRcdG5hdkRhdGFCdWZmZXJbJ3dyYXBwZXJTY3JvbGxUb3AnXSA9IHNjcm9sbFRvcDtcblx0XHRcdFx0bmF2RGF0YUJ1ZmZlclsnd3JhcHBlck1hcmdpblRvcCddID0gJGNvbnRhaW5lci5jc3MoJ21hcmdpbi10b3AnKTtcblx0XHRcdFx0JGNvbnRhaW5lci5hdHRyKCdidWZmZXItc2Nyb2xsVG9wJywgc2Nyb2xsVG9wKTtcblx0XHRcdFx0XG5cdFx0XHRcdCQoJy50b3AtYmFubmVyLWlubmVyJykuY3NzKCdoZWlnaHQnLCB0b2JCYW5uZXJJbm5lckhlaWdodCk7XG5cdFx0XHRcdCQoJy50b3AtYmFubmVyLWlubmVyIC5uYXZpZ2F0aW9uLWFuZC1qdW1ib3Ryb24tY29udGFpbmVyJykuY3NzKCdoZWlnaHQnLCBuYXZDb250YWluZXJIZWlnaHQpO1xuXHRcdFx0XHRcblx0XHRcdFx0JGh0bWwuYWRkQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XG5cdFx0XHRcdCR0aGlzLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JHRoaXMuYXR0cignYXJpYS1sYWJlbCcsICR0aGlzLmF0dHIoJ2RhdGEtY2xvc2UnKSk7IC8vIENoYW5nZSB0aGUgYXJpYS1sYWJlbCBvbiB0aGUgbWVudS10b2dnbGUgZm9yIHNjcmVlbiByZWFkZXJzXG5cblx0XHRcdFx0aWYgKHdpbmRvdy5pbm5lcldpZHRoIDw9IDEwMjMgJiYgc2Nyb2xsVG9wID4gbmF2Rml4ZWRIZWFkZXJMaW1pdCkge1xuXHRcdFx0XHRcdCQoJy5oZWFkZXItd3JhcHBlcicpLmNzcygnbWF4LWhlaWdodCcsIHdpbmRvdy5pbm5lckhlaWdodCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0JCgnLm15LXN0b3JlLXBhbmVsLm1vYmlsZS1vbmx5IC5zaG93LXN0b3JlLXNlYXJjaCcpLmZvY3VzKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkaHRtbC5yZW1vdmVDbGFzcygnbWVudS1hY3RpdmUnKTtcblx0XHRcdFx0JHRoaXMucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkdGhpcy5hdHRyKCdhcmlhLWxhYmVsJywgJHRoaXMuYXR0cignZGF0YS1vcGVuJykpOyAvLyBDaGFuZ2UgdGhlIGFyaWEtbGFiZWwgb24gdGhlIG1lbnUtdG9nZ2xlIGZvciBzY3JlZW4gcmVhZGVyc1xuXHRcblx0XHRcdFx0aWYgKG5hdkRhdGFCdWZmZXJbJ3dyYXBwZXJTY3JvbGxUb3AnXSA+IDApIHtcblx0XHRcdFx0XHRkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSBuYXZEYXRhQnVmZmVyWyd3cmFwcGVyU2Nyb2xsVG9wJ107XG5cdFx0XHRcdH1cblx0XHRcdFx0JCgnI25hdmlnYXRpb24nKS5yZW1vdmVBdHRyKCdhY3RpdmUtbWVudS1sZXZlbCcpO1xuXHRcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItaW5uZXInKS5jc3MoJ2hlaWdodCcsICcnKTtcblx0XHRcdFx0JCgnLnRvcC1iYW5uZXItaW5uZXIgLm5hdmlnYXRpb24tYW5kLWp1bWJvdHJvbi1jb250YWluZXInKS5jc3MoJ2hlaWdodCcsICdhdXRvJyk7XG5cdFxuXHRcdFx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gMTAyMykge1xuXHRcdFx0XHRcdCQoJy5oZWFkZXItd3JhcHBlcicpLmNzcygndHJhbnNmb3JtJywgJ25vbmUnKTtcblx0XHRcdFx0XHQkKCcuaGVhZGVyLXdyYXBwZXInKS5jc3MoJ21heC1oZWlnaHQnLCAnYXV0bycpO1xuXHRcdFx0XHRcdCQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHsgc2Nyb2xsVG9wOiAwIH0sIDMwMCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQkKCcjbmF2aWdhdGlvbiAubGV2ZWwtMicpLmhpZGUoKTtcblx0XHQkKCcjbmF2aWdhdGlvbiAubGV2ZWwtMScpLnNsaWRlRG93bigpO1xuXHRcdCQoJyNuYXZpZ2F0aW9uIC5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XHRcdFx0XG5cdFx0JCgnLm5hdi1zZWNvbmRhcnktZHJvcGRvd24nKS5zbGlkZVVwKDE1MCk7XG5cblx0XHRpZiAoJCgnI21pbmktY2FydCcpLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuXHRcdFx0JCgnI21pbmktY2FydCAubWluaS1jYXJ0LWxpbmsnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkKCcjbWluaS1jYXJ0JykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH1cblxuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NlYXJjaEJhci5IaWRlJyk7XG5cdFx0XG5cdFx0aWYgKCQoJy5zZWNvbmQtbW9ibmF2JykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XHRcdFx0XHRcblx0XHRcdCQoJy5zZWNvbmQtbW9ibmF2JykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG5cdFx0XHQkKCcjc2Vjb25kLW1vYm5hdicpLnN0b3AoKS5zbGlkZVVwKDE1MCk7XG5cdFx0fVxuXHR9KVxuXHQub24oJ2NsaWNrLk1lbnVJdGVtVG9nZ2xlJywgJy5tZW51LWNhdGVnb3J5IGxpIC5tZW51LWl0ZW0tdG9nZ2xlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR2YXIgJHBhcmVudExpID0gJChlLnRhcmdldCkuY2xvc2VzdCgnbGknKTtcblx0XHQkcGFyZW50TGkuc2libGluZ3MoJ2xpJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5tZW51LWl0ZW0tdG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2ZhLWNoZXZyb24tdXAgYWN0aXZlJykuYWRkQ2xhc3MoJ2ZhLWNoZXZyb24tcmlnaHQnKTtcblx0XHQkcGFyZW50TGkudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdCQoZS50YXJnZXQpLnRvZ2dsZUNsYXNzKCdmYS1jaGV2cm9uLXJpZ2h0IGZhLWNoZXZyb24tdXAgYWN0aXZlJyk7XG5cdH0pO1xuXG5cdC8qIC0tLSBBREEgQ29tcGxpYW5jZTogS2V5Ym9hcmQgbWFpbiBtZW51IG5hdmlnYXRpb24gLS0tXG5cdCAqIEFSUk9XIERPV046IFdpbGwgb3BlbiBmbHlvdXRzOyBmb2N1cyBnb2VzIHRvIGZpcnN0IGNsaWNrYWJsZSBsaW5rIGluIGZseW91dFxuXHQgKiBBUlJPVyBVUDogV2lsbCBjbG9zZSBmbHlvdXRzOyBmb2N1cyByZXR1cm5zIHRvIHRoZSBwYXJlbnQgb2YgdGhlIGZseW91dFxuXHQgKiBUQUI6IEEgZm9jdXMgaW5kaWNhdG9yIHdpbGwgc2hvdyB1cCBhdCB0aW1lIG9mIGVhY2ggdGFiXG5cdCAqIEVOVEVSOiBCeSBkZWZhdWx0LCBoaXR0aW5nIGVudGVyIHdpbGwgZW5nYWdlIGFueSBsaW5rIHRoYXQgaGFzIGN1cnJlbnQgZm9jdXNcblx0ICovXG5cdCQoZG9jdW1lbnQpLm9uKCdrZXl1cCcsICd1bC5tZW51LWNhdGVnb3J5IGxpLmhhcy1kcm9wZG93bicsIGZ1bmN0aW9uIChldmVudCkgeyBcblx0XHQvLyBEb3duIEFycm93OiBJZiBzdWItbWVudSBoYXMgYmVlbiBvcGVuZWQuLi5cblx0XHRpZiAoZXZlbnQud2hpY2ggPT09IFNpdGVDb25zdGFudHMuS2V5Q29kZXMuQXJyb3dEb3duKSB7XG5cdFx0XHQvLyBCb290QmFybi1zcGVjaWZpYyBuYXYgZmVhdHVyZXNcblx0XHRcdGlmICgkKCcudG9wLWJhbm5lci1iYXInKS5kYXRhKCdoZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuXHRcdFx0XHQkKHRoaXMpLnRyaWdnZXIoJ21vdXNlZW50ZXInKTtcblx0XHRcdH1cblx0XHRcdCQodGhpcykuZmluZCgndWwnKS5maW5kKCdhW2hyZWYhPVwiXCJdW2hyZWZdJykucmVtb3ZlQXR0cigndGFiaW5kZXgnKTsgLy8gUmVtb3ZlIHRhYmluZGV4IHRvIGFsbG93IG5hdHVyYWwgdGFiIGZsb3cgb2YgbmF2IGxpc3Rcblx0XHRcdHZhciBuYXZMaW5rc1BvcHVsYXRlZCA9ICQodGhpcykuZmluZCgnLmxldmVsLTIgdWw6Zmlyc3Qtb2YtdHlwZSBsaTpmaXJzdC1vZi10eXBlJykuZmluZCgnYScpLmZpbHRlcihmdW5jdGlvbih4LCBuYXZMaW5rKSB7XG5cdFx0XHRcdGlmICgkKG5hdkxpbmspLmF0dHIoJ2hyZWYnKSAmJiAkKG5hdkxpbmspLmF0dHIoJ2hyZWYnKS50cmltKCkubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHJldHVybiBuYXZMaW5rO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdCQobmF2TGlua3NQb3B1bGF0ZWRbMF0pLmZvY3VzKCkuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJyk7IC8vIEZvY3VzIG9uIGZpcnN0IHBvcHVsYXRlZCA8YT4gd2l0aGluIG9wZW5lZCBzdWItbWVudSBhbmQgYWRkIHZpc3VhbCBpbmRpY2F0b3Jcblx0XHRcdCQodGhpcykuYXR0cignYXJpYS1leHBhbmRlZCcsJ3RydWUnKS5hZGRDbGFzcygnYWN0aXZlIGtleWJvYXJkLWFjdGl2YXRlZCcpOyAvLyBVcGRhdGUgZXhwYW5kZWQgYXR0cmlidXRlIGFuZCBhZGQga2V5Ym9hcmQgY2xhc3Ncblx0XHR9XG5cdFx0Ly8gVXAgQXJyb3c6IElmIHN1Yi1tZW51IGhhcyBiZWVuIGNsb3NlZC4uLlxuXHRcdGlmIChldmVudC53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5BcnJvd1VwKSB7XG5cdFx0XHQvLyBCb290QmFybi1zcGVjaWZpYyBuYXYgZmVhdHVyZXNcblx0XHRcdGlmICgkKCcudG9wLWJhbm5lci1iYXInKS5kYXRhKCdoZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuXHRcdFx0XHQkKHRoaXMpLnRyaWdnZXIoJ21vdXNlbGVhdmUnKTtcblx0XHRcdH1cblx0XHRcdCQodGhpcykuZmluZCgndWwnKS5maW5kKCdhW2hyZWYhPVwiXCJdW2hyZWZdJykuYXR0cigndGFiaW5kZXgnLCctMScpOyAvLyBBZGQgbmVnYXRpdmUgdGFiaW5kZXggdG8gc2tpcCBuZXN0ZWQgYW5jaG9yc1xuXHRcdFx0JCh0aGlzKS5hdHRyKCdhcmlhLWV4cGFuZGVkJywnZmFsc2UnKS5yZW1vdmVDbGFzcygnYWN0aXZlIGtleWJvYXJkLWFjdGl2YXRlZCcpLmZvY3VzKCkuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJyk7IC8vIFVwZGF0ZSBleHBhbmRlZCBhdHRyaWJ1dGUsIHJlbW92ZSBrZXlib2FyZCBjbGFzcyBhbmQgcmVwb3NpdGlvbiBmb2N1cyBpbmRpY2F0b3Jcblx0XHR9XG5cdFx0Ly8gVGFiOiBLZXlib2FyZCBsb2dpYyBmb3IgbmF2IHRhYmJpbmcuLi5cblx0XHRpZiAoZXZlbnQud2hpY2ggPT09IFNpdGVDb25zdGFudHMuS2V5Q29kZXMuVGFiKSB7XG5cdFx0XHRpZiAoISQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuaGFzQ2xhc3MoJ2tleWJvYXJkLWFjdGl2YXRlZCcpICYmICgkKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpLmNsb3Nlc3QoJ2xpLmhhcy1kcm9wZG93bicpICYmICEkKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpLmNsb3Nlc3QoJ2xpLmhhcy1kcm9wZG93bicpLmhhc0NsYXNzKCdrZXlib2FyZC1hY3RpdmF0ZWQnKSkpIHsgLy8gSWYgdXNlciB0YWJiZWQgYXdheSBmcm9tIGFjdGl2YXRlZCBzdWItbWVudSwgY2xvc2UgdGhlIHN1Yi1tZW51XG5cdFx0XHRcdC8vIEJvb3RCYXJuLXNwZWNpZmljIG5hdiBmZWF0dXJlc1xuXHRcdFx0XHRpZiAoJCgnLnRvcC1iYW5uZXItYmFyJykuZGF0YSgnaGVhZGVyLWZvcicpID09ICdib290YmFybl91cycpIHtcblx0XHRcdFx0XHQkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykudHJpZ2dlcignbW91c2VsZWF2ZScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCQoJ2xpLmhhcy1kcm9wZG93bi5rZXlib2FyZC1hY3RpdmF0ZWQnKS5maW5kKCd1bCcpLmZpbmQoJ2FbaHJlZiE9XCJcIl1baHJlZl0nKS5hdHRyKCd0YWJpbmRleCcsJy0xJyk7IC8vIEFkZCBuZWdhdGl2ZSB0YWJpbmRleCB0byBza2lwIG5lc3RlZCBhbmNob3JzIHdoZW4gc3VibWVudSBpcyBjbG9zZWRcblx0XHRcdFx0JCgnbGkuaGFzLWRyb3Bkb3duLmtleWJvYXJkLWFjdGl2YXRlZCcpLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCdmYWxzZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUga2V5Ym9hcmQtYWN0aXZhdGVkJyk7IC8vIFVwZGF0ZSBleHBhbmRlZCBhdHRyaWJ1dGUgYW5kIHJlbW92ZSBrZXlib2FyZCBjbGFzc1xuXHRcdFx0fVxuXHRcdH1cblx0fSlcblx0Lm9uKCdrZXlkb3duJywgJy5tZW51LXRvZ2dsZScsIGZ1bmN0aW9uIChldmVudCkgeyBcblx0XHRpZiAoKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSB8fCAkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtdGFibGV0JykpICYmIGV2ZW50LndoaWNoID09PSBTaXRlQ29uc3RhbnRzLktleUNvZGVzLkVudGVyKSB7XG5cdFx0XHQkKCcubXktc3RvcmUtcGFuZWwubW9iaWxlLW9ubHkgYScpLmZvY3VzKCkuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJyk7XG5cdFx0fVxuXHR9KVxuXHQub24oJ21vdXNlb3ZlcicsICd1bC5tZW51LWNhdGVnb3J5IGxpLmhhcy1kcm9wZG93bicsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdCQodGhpcykuYXR0cignYXJpYS1leHBhbmRlZCcsJ3RydWUnKTsgLy8gQ1NTLWV4cGFuZWQgc3ViLW1lbnUgb2NjdXJzIG9uIGhvdmVyLiBVc2UgSlMgdG8gdXBkYXRlIHRoZSBleHBhbmRlZCBhdHRyaWJ1dGUgZm9yIG1vdXNlIHVzZXJzLlxuXHR9KVxuXHQub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdCQoJy5mb2N1cy12aXNpYmxlLWluZGljYXRvcicpLnJlbW92ZUNsYXNzKCdmb2N1cy12aXNpYmxlLWluZGljYXRvcicpO1xuXHRcdGlmICgkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykpIHtcblx0XHRcdGlmICgkKCcudG9wLWJhbm5lci1iYXInKS5kYXRhKCdoZWFkZXItZm9yJykgPT0gJ2Jvb3RiYXJuX3VzJykge1xuXHRcdFx0XHQkKCdsaS5oYXMtZHJvcGRvd24ua2V5Ym9hcmQtYWN0aXZhdGVkJykudHJpZ2dlcignbW91c2VsZWF2ZScpO1xuXHRcdFx0fVxuXHRcdFx0JCgnbGkuaGFzLWRyb3Bkb3duLmtleWJvYXJkLWFjdGl2YXRlZCcpLmZpbmQoJ3VsJykuZmluZCgnYVtocmVmIT1cIlwiXVtocmVmXScpLmF0dHIoJ3RhYmluZGV4JywnLTEnKTsgLy8gQWRkIG5lZ2F0aXZlIHRhYmluZGV4IHRvIHNraXAgbmVzdGVkIGFuY2hvcnMgd2hlbiBzdWJtZW51IGlzIGNsb3NlZFxuXHRcdFx0JCgnbGkuaGFzLWRyb3Bkb3duLmtleWJvYXJkLWFjdGl2YXRlZCcpLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCdmYWxzZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUga2V5Ym9hcmQtYWN0aXZhdGVkJyk7IC8vIFVwZGF0ZSBleHBhbmRlZCBhdHRyaWJ1dGUgYW5kIHJlbW92ZSBrZXlib2FyZCBjbGFzc1xuXHRcdH1cblx0fSk7XG5cblx0LyogLS0tIERvY3VtZW50IFJlYWR5IC0tLSAqL1xuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHR2YXIgYWRhU3ViTWVudUF0dHJpYnV0ZXMgPSB7XG5cdFx0XHQncm9sZSc6ICdtZW51aXRlbScsXG5cdFx0XHQnYXJpYS1oYXNwb3B1cCc6ICd0cnVlJyxcblx0XHRcdCdhcmlhLWV4cGFuZGVkJzogJ2ZhbHNlJ1xuXHRcdH1cblx0XHQkKCd1bC5tZW51LWNhdGVnb3J5LmxldmVsLTEgdWwnKS5hdHRyKCdyb2xlJywnbWVudScpLmF0dHIoJ2FyaWEtbGFiZWwnLCBmdW5jdGlvbihuLCB4KSB7XG5cdFx0XHRyZXR1cm4gJCh0aGlzKS5jbG9zZXN0KCdsaScpLmZpbmQoJy5oYXMtc3ViLW1lbnUnKS5maXJzdCgpLmh0bWwoKTtcblx0XHR9KTtcblx0XHQkKCd1bC5tZW51LWNhdGVnb3J5LmxldmVsLTEnKS5maW5kKCdhJykuZmlsdGVyKGZ1bmN0aW9uKG4sIG5hdkxpbmspIHtcblx0XHRcdC8vIEFkZCByb2xlPVwibm9uZVwiIHRvIGFsbCBsaXN0IGl0ZW1zLCBhbmQgdGhlbiB1c2Ugc3BlY2lmaWNpdHkgZnVydGhlciBkb3duIHRvIG92ZXJyaWRlIGlmIG5lZWRlZFxuXHRcdFx0JChuYXZMaW5rKS5wYXJlbnRzKCd1bDpub3QoLmxldmVsLTEpJykuZmluZCgnbGknKS5hdHRyKCdyb2xlJywnbm9uZScpO1xuXHRcdFx0Ly8gQWRkIHRhYmluZGV4PVwiLTFcIiB0byBhbGwgbmVzdGVkIGFuY2hvciB0YWdzIHRvIGZvcmNlIHRhYiBvcmRlciB1c2luZyBhcnJvdyB1cCBhbmQgZG93biBldmVudHNcblx0XHRcdCQobmF2TGluaykuYXR0cigndGFiaW5kZXgnLCctMScpO1xuXHRcdFx0Ly8gSUYgdGhlIGhyZWYgYXR0cmlidXRlIGlzIG5vdCBlbXB0eSwgYXBwbHkgQURBIGF0dHJpYnV0ZXMgY29ycmVjdGx5IGZvciBhIG1lbnVpdGVtXG5cdFx0XHRpZiAoJChuYXZMaW5rKS5hdHRyKCdocmVmJykgJiYgJChuYXZMaW5rKS5hdHRyKCdocmVmJykudHJpbSgpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JChuYXZMaW5rKS5hdHRyKCdyb2xlJywnbWVudWl0ZW0nKTtcblx0XHRcdC8vIEVMU0UsIGlmIGhyZWYgYXR0cmlidXRlIGlzIGVtcHR5LCB0aGVuIGVuc3VyZSA8YT4gZ2V0cyBza2lwcGVkIGluIGtleWJvYXJkIG5hdmlnYXRpb24gYW5kIHNjcmVlbiByZWFkZXJzXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKG5hdkxpbmspLnBhcmVudCgpLmF0dHIoYWRhU3ViTWVudUF0dHJpYnV0ZXMpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgd2luZG93LmlubmVyV2lkdGggPT0gMTAyNCkge1x0XHRcblx0XHQkKCdib2R5Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0aWYgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS10YWJsZXQnKSAmJiAkKCcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHRcdGlmKGUudGFyZ2V0LmlkID09ICcjbmF2aWdhdGlvbiAuaGFzLWRyb3Bkb3duJykge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiggJChlLnRhcmdldCkuY2xvc2VzdCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bicpLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JCgnI25hdmlnYXRpb24gLmhhcy1kcm9wZG93bicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdtZW51LWFjdGl2ZScpO1xuXHRcdFx0XHQkKCcuaGVhZGVyLXdyYXBwZXIgLnRvcC1iYW5uZXInKS5yZW1vdmVDbGFzcygnbmF2LWFjdGl2ZScpO1xuXHRcdFx0XHQkKCdodG1sJykucmVtb3ZlQ2xhc3MoJ2Rlc2t0b3AtbmF2LWFjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdFxuXHRcblx0JCgnYm9keScpLm9uKCdjbGljaycsICcjbmF2aWdhdGlvbiAubGV2ZWwtMyA+IGxpID4gYS5vZmZlci1wcmltYXJ5JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMgJiYgJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyICRwYXJlbnQgPSAkdGhpcy5jbG9zZXN0KCdsaScpO1xuXHRcdFx0dmFyICRjb250YWluZXIgPSAkcGFyZW50LmNsb3Nlc3QoJy5sZXZlbC0yJyk7XG5cdFx0XHRcblx0XHRcdCRjb250YWluZXIuZmluZCgnLmxldmVsLTMgbGknKS5ub3QoJHBhcmVudCkucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JHBhcmVudC50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gbmF2aWdhdGlvbkNvbGxpc2lvbkRldGVjdGlvbigkbmF2aWdhdGlvbkV2ZW50VGFyZ2V0KSB7XG5cdHZhciAkY29udGFpbmVyID0gJG5hdmlnYXRpb25FdmVudFRhcmdldC5jbG9zZXN0KCcuaGFzLWRyb3Bkb3duJyk7XG5cdFxuXHQkY29udGFpbmVyLnJlbW92ZUNsYXNzKCdjb2xsaXNpb24tcmlnaHQgY29sbGlzaW9uLWJvdGgnKTtcblx0XHRcblx0dmFyICRtZW51ID0gJGNvbnRhaW5lci5maW5kKCc+IC5sZXZlbC0yJyk7XG5cdFxuXHRpZiAoJG1lbnUubGVuZ3RoID4gMCkge1xuXHRcdHZhciBtZW51TGVmdCA9ICRtZW51Lm9mZnNldCgpLmxlZnQ7XG5cdFx0dmFyIG1lbnVSaWdodCA9IG1lbnVMZWZ0ICsgJG1lbnUub3V0ZXJXaWR0aCgpO1xuXHRcdFxuXHRcdHZhciAkYm91bmRhcnlDb250YWluZXIgPSAkKCcudG9wLWJhbm5lci1pbm5lcicpO1xuXHRcdFxuXHRcdGlmICgkYm91bmRhcnlDb250YWluZXIuZmluZCgnPiAuc2hlbGwnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkYm91bmRhcnlDb250YWluZXIgPSAkYm91bmRhcnlDb250YWluZXIuZmluZCgnPiAuc2hlbGwnKTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIGJvdW5kYXJ5TGVmdCA9ICRib3VuZGFyeUNvbnRhaW5lci5vZmZzZXQoKS5sZWZ0O1xuXHRcdHZhciBib3VuZGFyeVJpZ2h0ID0gYm91bmRhcnlMZWZ0ICsgJGJvdW5kYXJ5Q29udGFpbmVyLm91dGVyV2lkdGgoKTtcblx0XHRcblx0XHR2YXIgYm91bmRhcnlCdWZmZXIgPSAzMDtcblxuXHRcdGlmIChtZW51UmlnaHQgPj0gKGJvdW5kYXJ5UmlnaHQgKyBib3VuZGFyeUJ1ZmZlcikpIHtcblx0XHRcdHZhciBidXR0b25SaWdodCA9ICRuYXZpZ2F0aW9uRXZlbnRUYXJnZXQub2Zmc2V0KCkubGVmdCArICRuYXZpZ2F0aW9uRXZlbnRUYXJnZXQub3V0ZXJXaWR0aCgpO1xuXHRcdFx0XG5cdFx0XHRpZiAoYnV0dG9uUmlnaHQgLSAkbWVudS5vdXRlcldpZHRoKCkgPD0gKGJvdW5kYXJ5TGVmdCAtIGJvdW5kYXJ5QnVmZmVyKSkge1xuXHRcdFx0XHQkY29udGFpbmVyLmFkZENsYXNzKCdjb2xsaXNpb24tYm90aCcpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGNvbnRhaW5lci5hZGRDbGFzcygnY29sbGlzaW9uLXJpZ2h0Jyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGNsb3NlTmF2aWdhdGlvbigpIHtcblx0JCgnaHRtbCcpLnJlbW92ZUNsYXNzKCdtZW51LWFjdGl2ZScpO1xuXHQkKCcubWVudS10b2dnbGUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdCQoJyNuYXZpZ2F0aW9uIC5oYXMtZHJvcGRvd24uYWN0aXZlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5sZXZlbC0yLCAubmF2LXNlY29uZGFyeS1kcm9wZG93bicpLnN0b3AoKS5zbGlkZVVwKDE1MCk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVmFsaWRhdGlvblNldHRpbmdzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuU2V0dGluZ3M7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgkb3JkZXJTdGF0dXNGb3JtKSB7XG5cdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnb3JkZXJOdW1iZXInLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlT3JkZXJOdW1iZXIsIFJlc291cmNlcy5JTlZBTElEX09SREVSX05VTUJFUik7XG5cdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgncG9zdGFsQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVQb3N0YWxDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdFxuXHR2YXIgJG9yZGVyU3RhdHVzRm9ybU9yZGVyTnVtYmVyID0gJG9yZGVyU3RhdHVzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9vcmRlck51bWJlclwiXScpO1xuXHR2YXIgJG9yZGVyU3RhdHVzRm9ybU9yZGVyRW1haWwgPSAkb3JkZXJTdGF0dXNGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX29yZGVyRW1haWxcIl0nKTtcblx0dmFyICRvcmRlclN0YXR1c0Zvcm1PcmRlclBvc3RhbENvZGUgPSAkb3JkZXJTdGF0dXNGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbENvZGVcIl0nKTtcblx0XG5cdHZhciBmb3JtVmFsaWRhdG9yID0gJG9yZGVyU3RhdHVzRm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0JG9yZGVyU3RhdHVzRm9ybU9yZGVyTnVtYmVyLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuT3JkZXJOdW1iZXIpO1xuXHQkb3JkZXJTdGF0dXNGb3JtT3JkZXJFbWFpbC5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLkVtYWlsKTtcblx0JG9yZGVyU3RhdHVzRm9ybU9yZGVyUG9zdGFsQ29kZS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlBvc3RhbENvZGUpO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5leHBvcnRzLnZlcmlmeSA9IHZlcmlmeTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcblx0d2luZG93LnJlY2FwdGNoYUxvYWRlZCA9IGZ1bmN0aW9uICgpIHtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdSZWNhcHRjaGEuTG9hZGVkJyk7XG5cdH07XG5cblx0d2luZG93LmVtYWlsU2lnbnVwID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ0dsb2JhbC5FbWFpbFNpZ251cCcpO1xuXHR9O1xuXG5cdHdpbmRvdy5hY2NvdW50TG9naW4gPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnQWNjb3VudC5TdWJtaXRMb2dpbicpO1xuXHR9O1xuXG5cdHdpbmRvdy5yZXNldFBhc3N3b3JkID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ0FjY291bnQuUmVzZXRQYXNzd29yZCcpO1xuXHR9O1xuXG5cdHdpbmRvdy5zdWJtaXRPUENQYXltZW50ID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ0NoZWNrb3V0LlN1Ym1pdFBheW1lbnQnKTtcblx0fTtcblx0XG5cdHdpbmRvdy5zdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ0NoZWNrb3V0LlN1Ym1pdFBheW1lbnRQcml2YXRlTGFiZWwnKTtcblx0fTtcblxuXHR3aW5kb3cuc3VibWl0TWVycnlNYWlsID0gZnVuY3Rpb24gKHRva2VuKSB7XG5cdFx0cmV0dXJuIHZlcmlmeUFuZFRyaWdnZXJFdmVudCh0b2tlbiwgJ01lcnJ5TWFpbC5TZW5kJyk7XG5cdH07XG5cdFxuXHR3aW5kb3cuc3VibWl0UmV3YXJkc0NyZWRpdCA9IGZ1bmN0aW9uICh0b2tlbikge1xuXHRcdHJldHVybiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sICdSZXdhcmRzQ3JlZGl0LkFkZCcpO1xuXHR9O1xuXHRcblx0d2luZG93LnN1Ym1pdExveWFsdHlDcmVkaXQgPSBmdW5jdGlvbiAodG9rZW4pIHtcblx0XHRyZXR1cm4gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCAnTG95YWx0eUNyZWRpdC5BZGQnKTtcblx0fTtcblx0XG5cdHdpbmRvdy5zdWJtaXRHaWZ0Q2FyZCA9IGZ1bmN0aW9uICh0b2tlbikge1xuXHRcdHJldHVybiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sICdHaWZ0Q2FyZC5BcHBseScpO1xuXHR9O1xuXG5cdHdpbmRvdy5zdWJtaXRQYXltZW50Vm91Y2hlciA9IGZ1bmN0aW9uICh0b2tlbikge1xuXHRcdHJldHVybiB2ZXJpZnlBbmRUcmlnZ2VyRXZlbnQodG9rZW4sICdQYXltZW50Vm91Y2hlci5BcHBseScpO1xuXHR9O1xufTtcblxuZnVuY3Rpb24gdmVyaWZ5QW5kVHJpZ2dlckV2ZW50KHRva2VuLCBldmVudE5hbWUpIHtcblx0cmV0dXJuICQud2hlbih2ZXJpZnkodG9rZW4pKS50aGVuKGZ1bmN0aW9uKGRhdGEsIHRleHRTdGF0dXMsIHhtbEh0dHBSZXF1ZXN0KSB7XG5cdFx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdFx0aWYgKGRhdGEuc3VjY2Vzcykge1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKGV2ZW50TmFtZSk7XG5cdFx0XHRcdHJlc29sdmUoKTtcdFxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVqZWN0KCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1x0XG59XG5cbmZ1bmN0aW9uIHZlcmlmeSh0b2tlbikge1xuXHRyZXR1cm4gJC5hamF4KHtcblx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHR1cmw6IFVybHMudmVyaWZ5UmVjYXB0Y2hhLFxuXHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0dG9rZW46IHRva2VuXG5cdFx0fSlcblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4vTG9hZGluZ0luZGljYXRvcicpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyIHByb2R1Y3RUaWxlQ29udGFpbmVycyA9IFtdO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnMpIHtcblx0aWYgKG9wdGlvbnMuVXJsICYmIG9wdGlvbnMuQ29udGFpbmVycyAmJiBvcHRpb25zLkNvbnRhaW5lcnMubGVuZ3RoID4gMCkge1xuXHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBvcHRpb25zLkNvbnRhaW5lcnMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHR2YXIgY29udGFpbmVyID0gb3B0aW9ucy5Db250YWluZXJzW2luZGV4XTtcblx0XHRcdFxuXHRcdFx0cHJvZHVjdFRpbGVDb250YWluZXJzW3Byb2R1Y3RUaWxlQ29udGFpbmVycy5sZW5ndGhdID0gbmV3IFByb2R1Y3RUaWxlQ29udGFpbmVyKG9wdGlvbnMuVXJsLCBjb250YWluZXIpLmxvYWQoKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gUHJvZHVjdFRpbGVDb250YWluZXIodXJsLCBjb250YWluZXIsIHJlcXVlc3REYXRhKSB7XG5cdHZhciAkY29udGFpbmVyO1xuXHR2YXIgJGNvbnRhaW5lckJvZHk7XG5cdHZhciBkYXRhQnVmZmVyID0ge307XG5cdHZhciBodG1sQnVmZmVyID0ge307XG5cdHZhciBjdXJyZW50SHRtbEJ1ZmZlckNvdW50ID0gMDtcblx0dmFyIGV4cGVjdGVkSHRtbEJ1ZmZlckNvdW50ID0gMDtcblxuXHR0aGlzLmxvYWQgPSBmdW5jdGlvbigpIHtcblx0XHQkY29udGFpbmVyID0gJChjb250YWluZXIuU2VsZWN0b3IpO1xuXHRcdCRjb250YWluZXJCb2R5ID0gJGNvbnRhaW5lci5maW5kKCcuYWNjb3JkaW9uLWJvZHknKTtcblx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcblx0XHRpZiAoJGNvbnRhaW5lci5sZW5ndGggPiAwKSB7XG5cdFx0XHQkY29udGFpbmVyQm9keS5sb2FkaW5nKCk7XG5cdFx0XHQkY29udGFpbmVyLnNob3coKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdHVybDogdXJsLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0YWRkUHJvZHVjdElkOiBjb250YWluZXIuYWRkUHJvZHVjdElkLFxuXHRcdFx0XHRcdGV4Y2x1ZGVQcm9kdWN0SWQ6IGNvbnRhaW5lci5leGNsdWRlUHJvZHVjdElkXG5cdFx0XHRcdH0pLFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5Qcm9kdWN0SWRzICYmIGRhdGEuUHJvZHVjdElkcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRkYXRhQnVmZmVyID0gZGF0YTtcblx0XHRcdFx0XHRcdGV4cGVjdGVkSHRtbEJ1ZmZlckNvdW50ID0gZGF0YS5Qcm9kdWN0SWRzLmxlbmd0aDtcblxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGRhdGEuUHJvZHVjdElkcy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0XHRcdFx0Z2V0UHJvZHVjdEhpdFRpbGUoZGF0YS5Qcm9kdWN0SWRzW2luZGV4XSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1JlY2VudGx5Vmlld2VkUHJvZHVjdHMuRG9uZScsICRjb250YWluZXIpO1xuXHRcdFx0XHRcdFx0JGNvbnRhaW5lci5oaWRlKCk7XG5cdFx0XHRcdFx0XHRmaW5pc2goKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcdFx0XHRmaW5pc2goKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1JlY2VudGx5Vmlld2VkUHJvZHVjdHMuRG9uZScsICRjb250YWluZXIpO1xuXHRcdH1cblx0fVxuXG5cdHZhciBnZXRQcm9kdWN0SGl0VGlsZSA9IGZ1bmN0aW9uKHByb2R1Y3RJZCkge1xuXHRcdHZhciByZXF1ZXN0RGF0YSA9IHtcblx0XHRcdHBpZDogcHJvZHVjdElkLFxuXHRcdFx0c2hvd3N3YXRjaGVzOiAndHJ1ZScsXG5cdFx0XHRzaG93cHJpY2luZzogJ3RydWUnLFxuXHRcdFx0c2hvd3Byb21vdGlvbjogJ3RydWUnLFxuXHRcdFx0c2hvd3JhdGluZzogJ3RydWUnLFxuXHRcdFx0c2hvd2JhZGdlczogJ2ZhbHNlJyxcblx0XHRcdHNob3dhZmZpcm06ICdmYWxzZScsXG5cdFx0fVxuXG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0XHR1cmw6IFVybHMuaGl0VGlsZSxcblx0XHRcdGRhdGE6IHJlcXVlc3REYXRhLFxuXHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRcdGlmIChkYXRhKSB7XG5cdFx0XHRcdFx0aHRtbEJ1ZmZlcltwcm9kdWN0SWRdID0gJzxsaSBjbGFzcz1cInNsaWRlXCI+JyArIGRhdGEgKyAnPC9saT4nO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0Y3VycmVudEh0bWxCdWZmZXJDb3VudCsrO1xuXHRcdFx0XHRyZW5kZXIoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHZhciByZW5kZXIgPSBmdW5jdGlvbigpIHtcblx0XHRpZiAoY3VycmVudEh0bWxCdWZmZXJDb3VudCA9PSBleHBlY3RlZEh0bWxCdWZmZXJDb3VudCkge1xuXHRcdFx0dmFyIGh0bWwgPSAnJztcblxuXHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGRhdGFCdWZmZXIuUHJvZHVjdElkcy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0aWYgKGh0bWxCdWZmZXJbZGF0YUJ1ZmZlci5Qcm9kdWN0SWRzW2luZGV4XV0pIHtcblx0XHRcdFx0XHRodG1sICs9IGh0bWxCdWZmZXJbZGF0YUJ1ZmZlci5Qcm9kdWN0SWRzW2luZGV4XV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dmFyICRodG1sID0gJChodG1sKTtcblx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlICE9IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG5cdFx0XHRcdCRodG1sLmZpbmQoJy5wcm9kdWN0LXRpbGUnKS5hZGRDbGFzcygncHJvZHVjdCcpO1xuXHRcdFx0fVxuXHRcdFx0JGNvbnRhaW5lci5maW5kKCcuc2xpZGVzJykuaHRtbCgkaHRtbCk7XG5cdFx0XHQkY29udGFpbmVyLmZpbmQoJy5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeScpLnRyaWdnZXIoJ2luaXQtc2xpZGVyJyk7XG5cdFx0XHRmaW5pc2goKTtcblxuXHRcdFx0aWYgKCdhZmZpcm0nIGluIHdpbmRvdyAmJiAndWknIGluIGFmZmlybSAmJiAncmVmcmVzaCcgaW4gYWZmaXJtLnVpKSB7XG5cdFx0XHQgICAgYWZmaXJtLnVpLnJlZnJlc2goKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR2YXIgZmluaXNoID0gZnVuY3Rpb24oKSB7XG5cdFx0JGNvbnRhaW5lckJvZHkubG9hZGluZygnZGVzdHJveScpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1JlY2VudGx5Vmlld2VkUHJvZHVjdHMuRG9uZScsICRjb250YWluZXIpO1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0N1cnJlbmN5LlVwZGF0ZScsICRjb250YWluZXIpO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4vTG9hZGluZ0luZGljYXRvcicpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgcmVjb21tZW5kYXRpb25zQ29udGFpbmVycyA9IFtdO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnMpIHtcblx0aWYgKG9wdGlvbnMuVXJsICYmIG9wdGlvbnMuQ29udGFpbmVycyAmJiBvcHRpb25zLkNvbnRhaW5lcnMubGVuZ3RoID4gMCkge1xuXHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBvcHRpb25zLkNvbnRhaW5lcnMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRyZWNvbW1lbmRhdGlvbnNDb250YWluZXJzW3JlY29tbWVuZGF0aW9uc0NvbnRhaW5lcnMubGVuZ3RoXSA9IG5ldyBSZWNvbW1lbmRhdGlvbnNDb250YWluZXIob3B0aW9ucy5VcmwsIG9wdGlvbnMuQ29udGFpbmVyc1tpbmRleF0pLmxvYWQoKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gUmVjb21tZW5kYXRpb25zQ29udGFpbmVyKHVybCwgY29udGFpbmVyKSB7XG5cdHZhciAkY29udGFpbmVyO1xuXHR2YXIgJGNvbnRhaW5lckJvZHk7XG5cdHZhciBkYXRhQnVmZmVyID0ge307XG5cdHZhciBodG1sQnVmZmVyID0ge307XG5cdHZhciBjdXJyZW50SHRtbEJ1ZmZlckNvdW50ID0gMDtcblx0dmFyIGV4cGVjdGVkSHRtbEJ1ZmZlckNvdW50ID0gMDtcblxuXHR0aGlzLmxvYWQgPSBmdW5jdGlvbigpIHtcblx0XHQkY29udGFpbmVyID0gJChjb250YWluZXIuU2VsZWN0b3IpO1xuXHRcdCRjb250YWluZXJCb2R5ID0gJGNvbnRhaW5lci5maW5kKCcuYWNjb3JkaW9uLWJvZHknKTtcblx0XHRcblx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcblx0XHRpZiAoJGNvbnRhaW5lci5sZW5ndGggPiAwICYmIGNvbnRhaW5lci5Qcm9kdWN0SWQgJiYgY29udGFpbmVyLlJlbGF0aW9uVHlwZSkge1xuXHRcdFx0JGNvbnRhaW5lckJvZHkubG9hZGluZygpO1xuXHRcdFx0JGNvbnRhaW5lci5zaG93KCk7XG5cdFx0XHRcblx0XHRcdHZhciByZXF1ZXN0RGF0YSA9IHtcblx0XHRcdFx0J3N0eWxlcyc6IGNvbnRhaW5lci5Qcm9kdWN0SWQsXG5cdFx0XHRcdCdyZWxhdGlvbnR5cGUnOiBjb250YWluZXIuUmVsYXRpb25UeXBlXG5cdFx0XHR9XG5cblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0XHRcdHVybDogdXJsLFxuXHRcdFx0XHRkYXRhOiByZXF1ZXN0RGF0YSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEucHJvZHVjdHMgJiYgZGF0YS5wcm9kdWN0cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRkYXRhQnVmZmVyID0gZGF0YTtcblx0XHRcdFx0XHRcdGV4cGVjdGVkSHRtbEJ1ZmZlckNvdW50ID0gZGF0YS5wcm9kdWN0cy5sZW5ndGg7XG5cblx0XHRcdFx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBkYXRhLnByb2R1Y3RzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRcdFx0XHRnZXRQcm9kdWN0SGl0VGlsZSgoaW5kZXggKyAxKSwgZGF0YS5wcm9kdWN0c1tpbmRleF0ucHJvZHVjdGlkKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JGNvbnRhaW5lci5oaWRlKCk7XG5cdFx0XHRcdFx0XHRmaW5pc2goKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHRcdFx0XHRmaW5pc2goKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0dmFyIGdldFByb2R1Y3RIaXRUaWxlID0gZnVuY3Rpb24ocG9zaXRpb24sIHByb2R1Y3RJZCkge1xuXHRcdHZhciByZXF1ZXN0RGF0YSA9IHtcblx0XHRcdCdwb3NpdGlvbic6IHBvc2l0aW9uLFxuXHRcdFx0J3BpZCc6IHByb2R1Y3RJZCxcblx0XHRcdCdzaG93c3dhdGNoZXMnOiAndHJ1ZScsXG5cdFx0XHQnc2hvd3ByaWNpbmcnOiAndHJ1ZScsXG5cdFx0XHQnc2hvd3Byb21vdGlvbic6ICd0cnVlJyxcblx0XHRcdCdzaG93cmF0aW5nJzogJ3RydWUnLFxuXHRcdFx0J3Nob3diYWRnZXMnOiAnZmFsc2UnLFxuXHRcdFx0J3Nob3dhZmZpcm0nOiAnZmFsc2UnLFxuXHRcdH1cblxuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdFx0dXJsOiBVcmxzLmhpdFRpbGUsXG5cdFx0XHRkYXRhOiByZXF1ZXN0RGF0YSxcblx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRpZiAoZGF0YSkge1xuXHRcdFx0XHRcdGh0bWxCdWZmZXJbcHJvZHVjdElkXSA9ICc8bGkgY2xhc3M9XCJzbGlkZVwiPicgKyBkYXRhICsgJzwvbGk+Jztcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdGN1cnJlbnRIdG1sQnVmZmVyQ291bnQrKztcblx0XHRcdFx0cmVuZGVyKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHR2YXIgcmVuZGVyID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYgKGN1cnJlbnRIdG1sQnVmZmVyQ291bnQgPT0gZXhwZWN0ZWRIdG1sQnVmZmVyQ291bnQpIHtcblx0XHRcdHZhciBodG1sID0gJyc7XG5cblx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBkYXRhQnVmZmVyLnByb2R1Y3RzLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRpZiAoaHRtbEJ1ZmZlcltkYXRhQnVmZmVyLnByb2R1Y3RzW2luZGV4XS5wcm9kdWN0aWRdKSB7XG5cdFx0XHRcdFx0aHRtbCArPSBodG1sQnVmZmVyW2RhdGFCdWZmZXIucHJvZHVjdHNbaW5kZXhdLnByb2R1Y3RpZF07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dmFyICRodG1sID0gJChodG1sKTtcblx0XHRcdCRodG1sLmZpbmQoJy5wcm9kdWN0LXRpbGUnKS5hZGRDbGFzcygncHJvZHVjdCcpO1xuXG5cdFx0XHQkY29udGFpbmVyLmZpbmQoJy5zbGlkZXMnKS5odG1sKCRodG1sKTtcblx0XHRcdCRjb250YWluZXIuZmluZCgnLnNsaWRlci1wcm9kdWN0cy1wcmltYXJ5JykudHJpZ2dlcignaW5pdC1zbGlkZXInKTtcblx0XHRcdGZpbmlzaCgpO1xuXG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkpIHtcblx0XHRcdCAgICBhZmZpcm0udWkucmVmcmVzaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHZhciBmaW5pc2ggPSBmdW5jdGlvbigpIHtcblx0XHQkY29udGFpbmVyQm9keS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zLkRvbmUnLCAkY29udGFpbmVyKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDdXJyZW5jeS5VcGRhdGUnLCAkY29udGFpbmVyKTtcblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcbmV4cG9ydHMucmVuZGVyID0gcmVuZGVyO1xuXG52YXIgZGF0YTtcbnZhciBsb2FkZWQ7XG52YXIgb3B0aW9ucztcbnZhciAkY29udGFpbmVyO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplKCRjb250YWluZXJPYmplY3QsIG9wdGlvbnNPYmplY3QpIHtcblx0aWYgKFVybHMgJiYgVXJscy5nZXRTYW1lRGF5U2hpcHBpbmdDb3VudGRvd25EYXRhICYmIFVybHMuZ2V0U2FtZURheVNoaXBwaW5nQ291bnRkb3duQ29udGVudFNsb3QpIHtcblx0XHQkY29udGFpbmVyID0gJGNvbnRhaW5lck9iamVjdDtcblx0XHRvcHRpb25zID0gb3B0aW9uc09iamVjdDtcblx0XHRkYXRhID0ge307XG5cdFx0bG9hZGVkID0ge1xuXHRcdFx0Q29udGVudFNsb3Q6IGZhbHNlLFxuXHRcdFx0RGF0YTogZmFsc2Vcblx0XHR9XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub2ZmKCdTYW1lRGF5U2hpcHBpbmdDb3VudGRvd24uVXBkYXRlJykub24oJ1NhbWVEYXlTaGlwcGluZ0NvdW50ZG93bi5VcGRhdGUnLCB1cGRhdGUpO1xuXHRcdFxuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdHVybDogVXJscy5nZXRTYW1lRGF5U2hpcHBpbmdDb3VudGRvd25EYXRhLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0XHRsb2FkZWQuRGF0YSA9IHRydWU7XG5cdFx0XHRcdGRhdGEuUmVzcG9uc2UgPSByZXNwb25zZTtcblx0XHRcdFx0cmVuZGVyKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0XG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLmdldFNhbWVEYXlTaGlwcGluZ0NvdW50ZG93bkNvbnRlbnRTbG90LFxuXHRcdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChodG1sKSB7XG5cdFx0XHRcdGxvYWRlZC5Db250ZW50U2xvdCA9IHRydWU7XG5cdFx0XHRcdGRhdGEuSHRtbCA9IGh0bWw7XG5cdFx0XHRcdHJlbmRlcigpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlcigpIHtcblx0aWYgKGxvYWRlZCAmJiBsb2FkZWQuQ29udGVudFNsb3QgJiYgbG9hZGVkLkRhdGEgJiYgZGF0YSkge1xuXHRcdHZhciBjb3VudGRvd25UZXh0ID0gJyc7XG5cdFx0XG5cdFx0aWYgKGRhdGEuUmVzcG9uc2UgJiYgZGF0YS5SZXNwb25zZS5UaW1lTGVmdCkge1xuXHRcdFx0aWYgKGRhdGEuUmVzcG9uc2UuVGltZUxlZnQuSG91cnMgPiAwKSB7XG5cdFx0XHRcdGNvdW50ZG93blRleHQgKz0gZGF0YS5SZXNwb25zZS5UaW1lTGVmdC5Ib3VycyArICcgJyArIChkYXRhLlJlc3BvbnNlLlRpbWVMZWZ0LkhvdXJzID4gMSA/IFJlc291cmNlcy5IT1VSU19BQkJSRVZJQVRFRCA6IFJlc291cmNlcy5IT1VSX0FCQlJFVklBVEVEKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKGRhdGEuUmVzcG9uc2UuVGltZUxlZnQuTWludXRlcyA+IDApIHtcblx0XHRcdFx0aWYgKGNvdW50ZG93blRleHQgIT0gJycpIHtcblx0XHRcdFx0XHRjb3VudGRvd25UZXh0ICs9ICcgJztcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0Y291bnRkb3duVGV4dCArPSBkYXRhLlJlc3BvbnNlLlRpbWVMZWZ0Lk1pbnV0ZXMgKyAnICcgKyAoZGF0YS5SZXNwb25zZS5UaW1lTGVmdC5NaW51dGVzID4gMSA/IFJlc291cmNlcy5NSU5VVEVTX0FCQlJFVklBVEVEIDogUmVzb3VyY2VzLk1JTlVURV9BQkJSRVZJQVRFRCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGRhdGEuSHRtbCkge1xuXHRcdFx0JGNvbnRhaW5lci5odG1sKGRhdGEuSHRtbCkuZmluZCgnaW5wdXRbbmFtZT1cImluaXRUaW1lXCJdJykucmVtb3ZlKCk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChjb3VudGRvd25UZXh0KSB7XG5cdFx0XHQkY29udGFpbmVyLmh0bWwoXy50ZW1wbGF0ZSgkY29udGFpbmVyLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSh7XG5cdFx0XHRcdGNvdW50ZG93bjogY291bnRkb3duVGV4dFxuXHRcdFx0fSkpO1xuXHRcdFx0XG5cdFx0XHR1cGRhdGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JChkb2N1bWVudCkub2ZmKCdTYW1lRGF5U2hpcHBpbmdDb3VudGRvd24uVXBkYXRlJyk7XG5cdFx0fVxuXHR9XG59O1xuXG5mdW5jdGlvbiB1cGRhdGUoKSB7XG5cdGlmICgkY29udGFpbmVyLmh0bWwoKS5yZXBsYWNlKC88IS0tKFteXFxkXSopLS0+L2csICcnKS50cmltKCkubGVuZ3RoID4gMCkge1xuXHRcdHZhciAkc2VsZWN0ZWRWYXJpYXRpb24gPSAkKCcucHJvZHVjdC12YXJpYXRpb25zIC5hdHRyaWJ1dGUtc2l6ZSAuc2VsZWN0LXRleHQgW3NhbWUtZGF5LXNoaXBwaW5nXScpO1xuXHRcdFxuXHRcdGlmICgkc2VsZWN0ZWRWYXJpYXRpb24ubGVuZ3RoID4gMCkge1xuXHRcdFx0aWYgKCRzZWxlY3RlZFZhcmlhdGlvbi5hdHRyKCdzYW1lLWRheS1zaGlwcGluZycpLnRvTG93ZXJDYXNlKCkgPT0gJ3RydWUnKSB7XG5cdFx0XHRcdCRjb250YWluZXIuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGNvbnRhaW5lci5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChwYXJzZUZsb2F0KG9wdGlvbnMucGVyY2VudGFnZU9mVmFyaWFudHNGcm9tV2FyZWhvdXNlKSA+PSBwYXJzZUZsb2F0KG9wdGlvbnMuc2FtZURheVNoaXBwaW5nV2luZG93V2FyZWhvdXNlUGVyY2VudGFnZSkpIHtcblx0XHRcdCRjb250YWluZXIuc2hvdygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkY29udGFpbmVyLmhpZGUoKTtcblx0XHR9XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xuXG4vKipcbiAqIEBmdW5jdGlvbiBjb29raWVwcml2YWN5ICAgIFVzZWQgdG8gZGlzcGxheS9jb250cm9sIHRoZSBzY3JpbSBjb250YWluaW5nIHRoZSBjb29raWUgcHJpdmFjeSBjb2RlXG4gKiovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAvKipcbiAgICAgKiBJZiB3ZSBoYXZlIG5vdCBhY2NlcHRlZCBjb29raWVzIEFORCB3ZSdyZSBub3Qgb24gdGhlIFByaXZhY3kgUG9saWN5IHBhZ2UsIHRoZW4gc2hvdyB0aGUgbm90aWZpY2F0aW9uXG4gICAgICogTk9URTogWW91IHdpbGwgcHJvYmFibHkgd2FudCB0byBhZGp1c3QgdGhlIFByaXZhY3kgUGFnZSB0ZXN0IHRvIG1hdGNoIHlvdXIgc2l0ZSdzIHNwZWNpZmljIHByaXZhY3kgLyBjb29raWUgcGFnZVxuICAgICAqL1xuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09PS0lFX0hJTlQgPT09IHRydWUgJiYgZG9jdW1lbnQuY29va2llLmluZGV4T2YoJ2R3X2Nvb2tpZXNfYWNjZXB0ZWQnKSA8IDApIHtcbiAgICAgICAgLy8gY2hlY2sgZm9yIHByaXZhY3kgcG9saWN5IHBhZ2VcbiAgICAgICAgaWYgKCQoJy5wcml2YWN5LXBvbGljeScpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgIHVybDogVXJscy5jb29raWVIaW50LFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgY2xvc2VPbkVzY2FwZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnbm8tY2xvc2UnLFxuICAgICAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogUmVzb3VyY2VzLklfQUdSRUUsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZUNvb2tpZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE90aGVyd2lzZSwgd2UgZG9uJ3QgbmVlZCB0byBzaG93IHRoZSBhc3NldCwganVzdCBlbmFibGUgdGhlIGNvb2tpZXNcbiAgICAgICAgZW5hYmxlQ29va2llcygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVuYWJsZUNvb2tpZXMoKSB7XG4gICAgICAgIGlmIChkb2N1bWVudC5jb29raWUuaW5kZXhPZignZHc9MScpIDwgMCkge1xuICAgICAgICAgICAgZG9jdW1lbnQuY29va2llID0gJ2R3PTE7IHBhdGg9Lyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRvY3VtZW50LmNvb2tpZS5pbmRleE9mKCdkd19jb29raWVzX2FjY2VwdGVkJykgPCAwKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSAnZHdfY29va2llc19hY2NlcHRlZD0xOyBwYXRoPS8nO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gaW5pdCAoKSB7XG5cbiAgICAkKCcuY291bnRkb3duLXdyYXBwZXInKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpLFxuICAgICAgICAgIGNvdW50ZG93blN0ciA9ICR0aGlzLmRhdGEoJ2NvdW50ZG93bi1kYXRlJyksXG4gICAgICAgICAgY291bnRkb3duRGF0ZSA9IG5ldyBEYXRlKGNvdW50ZG93blN0cik7XG5cbiAgICAgICAgdmFyIHRzID0gY291bnRkb3duKG5ldyBEYXRlKCksIGNvdW50ZG93bkRhdGUsIGNvdW50ZG93bi5EQVlTIHwgY291bnRkb3duLkhPVVJTIHwgY291bnRkb3duLk1JTlVURVMpO1xuICAgICAgICB2YXIgc2hvd0NvdW50ZG93biA9IHRzLnZhbHVlID4gMDtcblxuICAgICAgICBpZiAoc2hvd0NvdW50ZG93bikge1xuICAgICAgICAgICR0aGlzLmZpbmQoJy5jb3VudGRvd24tdGV4dCcpLnRleHQodHMudG9TdHJpbmcoKSk7XG4gICAgICAgIH1cblxuXG4gICAgfSk7XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uIGluaXQgKCkge1xuICAgICQoJy5jb3VudHJ5LXNlbGVjdG9yIC5jdXJyZW50LWNvdW50cnknKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJy5jb3VudHJ5LXNlbGVjdG9yIC5zZWxlY3RvcicpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnc2VsZWN0b3ItYWN0aXZlJyk7XG4gICAgfSk7XG4gICAgLy8gc2V0IGN1cnJlbmN5IGZpcnN0IGJlZm9yZSByZWxvYWRcbiAgICAkKCcuY291bnRyeS1zZWxlY3RvciAuc2VsZWN0b3IgLmxvY2FsZScpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHVybCA9IHRoaXMuaHJlZjtcbiAgICAgICAgdmFyIGN1cnJlbmN5ID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2RhdGEtY3VycmVuY3knKTtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICB1cmw6IFVybHMuc2V0U2Vzc2lvbkN1cnJlbmN5LFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGZvcm1hdDogJ2FqYXgnLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5TW5lbW9uaWM6IGN1cnJlbmN5XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5kb25lKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gc2V0IGN1cnJlbmN5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybDtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4vYWpheCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKSxcbiAgICBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gICAgaW1hZ2VzTG9hZGVkID0gcmVxdWlyZSgnaW1hZ2VzbG9hZGVkJyk7XG5cbnZhciBkaWFsb2cgPSB7XG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEFwcGVuZHMgYSBkaWFsb2cgdG8gYSBnaXZlbiBjb250YWluZXIgKHRhcmdldClcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zICBwYXJhbXMudGFyZ2V0IGNhbiBiZSBhbiBpZCBzZWxlY3RvciBvciBhbiBqcXVlcnkgb2JqZWN0XG4gICAgICovXG4gICAgY3JlYXRlOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciAkdGFyZ2V0LCBpZDtcblxuICAgICAgICBpZiAoXy5pc1N0cmluZyhwYXJhbXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgaWYgKHBhcmFtcy50YXJnZXQuY2hhckF0KDApID09PSAnIycpIHtcbiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJChwYXJhbXMudGFyZ2V0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJHRhcmdldCA9ICQoJyMnICsgcGFyYW1zLnRhcmdldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zLnRhcmdldCBpbnN0YW5jZW9mIGpRdWVyeSkge1xuICAgICAgICAgICAgJHRhcmdldCA9IHBhcmFtcy50YXJnZXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoJCgnI2RpYWxvZy1jb250YWluZXInKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkdGFyZ2V0ID0gJCgnI2RpYWxvZy1jb250YWluZXInKTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdCR0YXJnZXQgPSAkKCc8ZGl2IGlkPVwiZGlhbG9nLWNvbnRhaW5lclwiLz4nKS5hcHBlbmRUbygnYm9keScpO1xuXHRcdH1cblxuICAgICAgICAvLyBpZiBubyBlbGVtZW50IGZvdW5kLCBjcmVhdGUgb25lXG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgaWYgKCR0YXJnZXQuc2VsZWN0b3IgJiYgJHRhcmdldC5zZWxlY3Rvci5jaGFyQXQoMCkgPT09ICcjJykge1xuICAgICAgICAgICAgICAgIGlkID0gJHRhcmdldC5zZWxlY3Rvci5zdWJzdHIoMSk7XG4gICAgICAgICAgICAgICAgJHRhcmdldCA9ICQoJzxkaXY+JykuYXR0cignaWQnLCBpZCkuYWRkQ2xhc3MoJ2RpYWxvZy1jb250ZW50JykuYXBwZW5kVG8oJ2JvZHknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgocGFyYW1zLm9wdGlvbnMgIT0gdW5kZWZpbmVkICYmIHBhcmFtcy5vcHRpb25zICE9IG51bGwpICYmIChwYXJhbXMub3B0aW9ucy50aXRsZSA9PSB1bmRlZmluZWQgfHwgKCd0aXRsZScgaW4gcGFyYW1zLm9wdGlvbnMgJiYgcGFyYW1zLm9wdGlvbnMudGl0bGUubGVuZ3RoID09IDApKSkge1xuICAgICAgICAgICAgcGFyYW1zLm9wdGlvbnMuZGlhbG9nQ2xhc3MgKz0gJyB1aS1kaWFsb2ctdGl0bGUtY29sbGFwc2UnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY3JlYXRlIHRoZSBkaWFsb2dcbiAgICAgICAgdGhpcy4kY29udGFpbmVyID0gJHRhcmdldDtcbiAgICAgICAgdGhpcy4kY29udGFpbmVyLmRpYWxvZyhfLm1lcmdlKHt9LCB0aGlzLnNldHRpbmdzLCBwYXJhbXMub3B0aW9ucyB8fCB7fSkpO1xuXG4gICAgICAgIC8qIC0tLSBCT09ULTUzODYgLS0tXG4gICAgICAgICAqIFRoaXMgaXMgYSB3b3JrYXJvdW5kIGZvciBhIGtub3duIGpxdWVyeSBEaWFsb2cgVUkgYnVnIHdpdGggdGhlIG1heFdpZHRoIG9wdGlvbi4gQnkgc2V0dGluZyB0aGUgRGlhbG9nIHdpZHRoIG9wdGlvbiB0byAxMDAlIGFuZCBzZXR0aW5nIHRoZSBDU1MgbWF4LXdpZHRoXG4gICAgICAgICAqIHRvIDgwMHB4LCB0aGlzIGFsbG93cyB0aGUgZGlhbG9ncyB0byBiZSByZXNwb25zaXZlIHdpZHRoLiBUaGlzIGZpeCBpcyBuZWNlc3NhcnkgdG8gY3JlYXRlIHJlc3BvbnNpdmUgRGlhbG9ncyBmb3Igc21hbGxlciBzY3JlZW5zLCBidXQgYWxzbyBiZSBiYWNrd2FyZHMgXG4gICAgICAgICAqIGNvbXBhdGlibGUgd2l0aCBleGlzdGluZyBkaWFsb2dzIG9uIHRoZSBzaXRlIHRoYXQgaGF2ZSBiZWVuIHByZXZpb3VzbHkgc2V0IHRvIHRoZSBkZWZhdWx0IHNpemUgb2YgODAwcHguXG4gICAgICAgICAqIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE2NDcxODkwL3Jlc3BvbnNpdmUtanF1ZXJ5LXVpLWRpYWxvZy1hbmQtYS1maXgtZm9yLW1heHdpZHRoLWJ1Z1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy4kY29udGFpbmVyLnBhcmVudCgpLmNzcyhcIm1heC13aWR0aFwiLCBcIjgwMHB4XCIpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIE9wZW5zIGEgZGlhbG9nIHVzaW5nIHRoZSBnaXZlbiB1cmwgKHBhcmFtcy51cmwpIG9yIGh0bWwgKHBhcmFtcy5odG1sKVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zLnVybCBzaG91bGQgY29udGFpbiB0aGUgdXJsXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy5odG1sIGNvbnRhaW5zIHRoZSBodG1sIG9mIHRoZSBkaWFsb2cgY29udGVudFxuICAgICAqL1xuICAgIG9wZW46IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgLy8gY2xvc2UgYW55IG9wZW4gZGlhbG9nXG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgdGhpcy5jcmVhdGUocGFyYW1zKTtcbiAgICAgICAgdGhpcy5yZXBsYWNlKHBhcmFtcyk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gcG9wdWxhdGUgdGhlIGRpYWxvZyB3aXRoIGh0bWwgY29udGVudCwgdGhlbiBvcGVuIGl0XG4gICAgICoqL1xuICAgIG9wZW5XaXRoQ29udGVudDogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgY29udGVudCwgcG9zaXRpb24sIGNhbGxiYWNrO1xuXG4gICAgICAgIGlmICghdGhpcy4kY29udGFpbmVyKSB7IHJldHVybjsgfVxuICAgICAgICBjb250ZW50ID0gcGFyYW1zLmNvbnRlbnQgfHwgcGFyYW1zLmh0bWw7XG4gICAgICAgIGlmICghY29udGVudCkgeyByZXR1cm47IH1cbiAgICAgICAgdGhpcy4kY29udGFpbmVyLmVtcHR5KCkuaHRtbChjb250ZW50KTtcbiAgICAgICAgaWYgKCF0aGlzLiRjb250YWluZXIuZGlhbG9nKCdpc09wZW4nKSkge1xuICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyLmRpYWxvZygnb3BlbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcy5vcHRpb25zKSB7XG4gICAgICAgICAgICBwb3NpdGlvbiA9IHBhcmFtcy5vcHRpb25zLnBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcG9zaXRpb24pIHtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gdGhpcy5zZXR0aW5ncy5wb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBpbWFnZXNMb2FkZWQodGhpcy4kY29udGFpbmVyKS5vbignZG9uZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJGNvbnRhaW5lci5kaWFsb2coJ29wdGlvbicsICdwb3NpdGlvbicsIHBvc2l0aW9uKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBjYWxsYmFjayA9ICh0eXBlb2YgcGFyYW1zLmNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSA/IHBhcmFtcy5jYWxsYmFjayA6IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgY3VycmVudCBkaWFsb2dcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcGFyYW1zXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmFtcy51cmwgLSBJZiB0aGUgdXJsIHByb3BlcnR5IGlzIHByb3ZpZGVkLCBhbiBhamF4IGNhbGwgaXMgcGVyZm9ybWVkIHRvIGdldCB0aGUgY29udGVudCB0byByZXBsYWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmFtcy5odG1sIC0gSWYgbm8gdXJsIHByb3BlcnR5IGlzIHByb3ZpZGVkLCB1c2UgaHRtbCBwcm92aWRlZCB0byByZXBsYWNlXG4gICAgICovXG4gICAgcmVwbGFjZTogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoIXRoaXMuJGNvbnRhaW5lcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbXMudXJsKSB7XG4gICAgICAgICAgICBwYXJhbXMudXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHBhcmFtcy51cmwsICdmb3JtYXQnLCAnYWpheCcpO1xuICAgICAgICAgICAgYWpheC5sb2FkKHtcbiAgICAgICAgICAgICAgICB1cmw6IHBhcmFtcy51cmwsXG4gICAgICAgICAgICAgICAgZGF0YTogcGFyYW1zLmRhdGEsXG4gICAgICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMuY29udGVudCA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW5XaXRoQ29udGVudChwYXJhbXMpO1xuICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zLmh0bWwpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbldpdGhDb250ZW50KHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBDbG9zZXMgdGhlIGRpYWxvZ1xuICAgICAqL1xuICAgIGNsb3NlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy4kY29udGFpbmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy4kY29udGFpbmVyLmRpYWxvZygnY2xvc2UnKTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBTdWJtaXRzIHRoZSBkaWFsb2cgZm9ybSB3aXRoIHRoZSBnaXZlbiBhY3Rpb25cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gVGhlIGFjdGlvbiB3aGljaCB3aWxsIGJlIHRyaWdnZXJlZCB1cG9uIGZvcm0gc3VibWl0XG4gICAgICovXG4gICAgc3VibWl0OiBmdW5jdGlvbiAoYWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgJGZvcm0gPSB0aGlzLiRjb250YWluZXIuZmluZCgnZm9ybTpmaXJzdCcpO1xuICAgICAgICAvLyBzZXQgdGhlIGFjdGlvblxuICAgICAgICAkKCc8aW5wdXQvPicpLmF0dHIoe1xuICAgICAgICAgICAgbmFtZTogYWN0aW9uLFxuICAgICAgICAgICAgdHlwZTogJ2hpZGRlbidcbiAgICAgICAgfSkuYXBwZW5kVG8oJGZvcm0pO1xuICAgICAgICAvLyBzZXJpYWxpemUgdGhlIGZvcm0gYW5kIGdldCB0aGUgcG9zdCB1cmxcbiAgICAgICAgdmFyIGRhdGEgPSAkZm9ybS5zZXJpYWxpemUoKTtcbiAgICAgICAgdmFyIHVybCA9ICRmb3JtLmF0dHIoJ2FjdGlvbicpO1xuICAgICAgICAvLyBtYWtlIHN1cmUgdGhlIHNlcnZlciBrbm93cyB0aGlzIGlzIGFuIGFqYXggcmVxdWVzdFxuICAgICAgICBpZiAoZGF0YS5pbmRleE9mKCdhamF4JykgPT09IC0xKSB7XG4gICAgICAgICAgICBkYXRhICs9ICcmZm9ybWF0PWFqYXgnO1xuICAgICAgICB9XG4gICAgICAgIC8vIHBvc3QgdGhlIGRhdGEgYW5kIHJlcGxhY2UgY3VycmVudCBjb250ZW50IHdpdGggcmVzcG9uc2UgY29udGVudFxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBkYXRhOiBkYXRhLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdodG1sJyxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChodG1sKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyLmh0bWwoaHRtbCk7XG4gICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgZmFpbHVyZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuU0VSVkVSX0VSUk9SKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBleGlzdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuJGNvbnRhaW5lciAmJiAodGhpcy4kY29udGFpbmVyLmxlbmd0aCA+IDApO1xuICAgIH0sXG4gICAgaXNBY3RpdmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhpc3RzKCkgJiYgKHRoaXMuJGNvbnRhaW5lci5jaGlsZHJlbi5sZW5ndGggPiAwKTtcbiAgICB9LFxuICAgIHNldHRpbmdzOiB7XG4gICAgICAgIGF1dG9PcGVuOiBmYWxzZSxcbiAgICAgICAgaGVpZ2h0OiAnYXV0bycsXG4gICAgICAgIG1vZGFsOiB0cnVlLFxuICAgICAgICBvdmVybGF5OiB7XG4gICAgICAgICAgICBvcGFjaXR5OiAwLjUsXG4gICAgICAgICAgICBiYWNrZ3JvdW5kOiAnYmxhY2snXG4gICAgICAgIH0sXG4gICAgICAgIHJlc2l6YWJsZTogZmFsc2UsXG4gICAgICAgIHRpdGxlOiAnJyxcbiAgICAgICAgd2lkdGg6ICcxMDAlJyxcblx0XHRvcGVuOiBmdW5jdGlvbihldmVudCwgdWkpIHtcblx0XHRcdFxuXHRcdH0sXG4gICAgICAgIGNsb3NlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkKHRoaXMpLmRpYWxvZygnY2xvc2UnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgIG15OiAnY2VudGVyJyxcbiAgICAgICAgICAgIGF0OiAnY2VudGVyJyxcbiAgICAgICAgICAgIG9mOiB3aW5kb3csXG4gICAgICAgICAgICBjb2xsaXNpb246ICdmbGlwZml0J1xuICAgICAgICB9XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBkaWFsb2c7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG5cdGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG5cbnZhciAkZGlhbG9nQ29udGVudCxcblx0c3RhdGUgPSB7fSxcblx0cmVhZHkgPSB7fSxcblx0dGVtcGxhdGVzID0ge30sXG5cdGh0bWwgPSB7fTtcblxudmFyIHRlbXBsYXRlU2V0dGluZ3MgPSB7IGludGVycG9sYXRlOiAve3soW1xcc1xcU10rPyl9fS9nIH07XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9ucykge1xuXHRzdGF0ZVsnb3B0aW9ucyddID0gb3B0aW9ucyB8fCB7fTtcblx0XG5cdGxvYWRUZW1wbGF0ZXMoKTtcblx0bG9hZFN0b3JlcygpO1xuXHRsb2FkU3RhdGVzKCk7XG5cdFxuXHRvcGVuRGlhbG9nKCk7XHRcbn1cblxuZnVuY3Rpb24gb3BlbkRpYWxvZygpIHtcblx0cmVhZHlbJ2RpYWxvZyddID0gZmFsc2U7XG5cdFxuXHRkaWFsb2cub3Blbih7XG5cdFx0aHRtbDogJzxkaXYgY2xhc3M9XCJkaWFsb2ctbG9hZGluZ1wiPjwvZGl2PicsXG5cdFx0b3B0aW9uczoge1xuXHRcdFx0dGl0bGU6IFJlc291cmNlcy5GSU5EX01PUkVfU1RPUkVTLFxuXHRcdFx0ZGlhbG9nQ2xhc3M6ICdkaWFsb2ctZmluZC1tb3JlLXN0b3JlcycsXG5cdFx0XHRyZXNpemFibGU6IGZhbHNlLFxuXHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdG9wZW46IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkZGlhbG9nQ29udGVudCA9ICQodGhpcyk7XG5cdFx0XHRcdHJlYWR5WydkaWFsb2cnXSA9IHRydWU7XG5cdFx0XHRcdFxuXHRcdFx0XHRldmVudHMoKTtcblx0XHRcdFx0cmVuZGVyKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZXZlbnRzKCkge1xuXHQkZGlhbG9nQ29udGVudC5vZmYoJ2NsaWNrLmZpbmRNb3JlU3RvcmVzLmdvJykub24oJ2NsaWNrLmZpbmRNb3JlU3RvcmVzLmdvJywgJy5zZWFyY2ggYnV0dG9uJywgZnVuY3Rpb24gKCkge1xuXHRcdGxvYWRTdG9yZXModHJ1ZSk7XG5cdH0pO1xuXHRcblx0JGRpYWxvZ0NvbnRlbnQub2ZmKCdjbGljay5maW5kTW9yZVN0b3Jlcy5zdWJtaXQnKS5vbignY2xpY2suZmluZE1vcmVTdG9yZXMuc3VibWl0JywgJy5zdWJtaXQnLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHNlbGVjdGVkU3RvcmUgPSAkZGlhbG9nQ29udGVudC5maW5kKCcuc3RvcmVzLWxpc3QgaW5wdXQ6Y2hlY2tlZCcpLnZhbCgpO1xuXHRcdFxuXHRcdGlmIChzZWxlY3RlZFN0b3JlKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdvcGMuU2V0U2hpcHBpbmdBZGRyZXNzJywgc3RhdGVbJ3N0b3JlcyddLmFkZHJlc3Nlc1tzZWxlY3RlZFN0b3JlXSk7XG5cdFx0XHRkaWFsb2cuY2xvc2UoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBsb2FkU3RhdGVzKCkge1xuXHRyZWFkeVsnc3RhdGVzJ10gPSBmYWxzZTtcblx0XG5cdCQuYWpheCh7IG1ldGhvZDogJ1BPU1QnLCB1cmw6IFVybHMuZ2V0Q291bnRyeVN0YXRlcywgZGF0YTogJ2NvdW50cnlDb2RlPVVTJywgZGF0YVR5cGU6ICdqc29uJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcdFx0XG5cdFx0c3RhdGVbJ3N0YXRlcyddID0gSlNPTi5wYXJzZShkYXRhLnN0YXRlc0xpc3QpO1xuXHRcdHJlYWR5WydzdGF0ZXMnXSA9IHRydWU7XG5cdFx0XHRcdFxuXHRcdHJlbmRlcigpO1xuXHR9fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclN0YXRlcygpIHtcblx0aHRtbFsnc3RhdGVzJ10gPSAnPG9wdGlvbiBjbGFzcz1cInBsYWNlaG9sZGVyXCI+PC9vcHRpb24+Jztcblx0XG5cdGZvciAodmFyIHN0YXRlRWxlbWVudCBpbiBzdGF0ZVsnc3RhdGVzJ10pIHtcblx0XHR2YXIgc3RhdGVPcHRpb24gPSBzdGF0ZS5zdGF0ZXNbc3RhdGVFbGVtZW50XTtcblx0XHRcblx0XHRodG1sWydzdGF0ZXMnXSArPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBzdGF0ZU9wdGlvbi5sYWJlbCArICdcIj4nICsgc3RhdGVPcHRpb24ubGFiZWwgKyAnPC9vcHRpb24+Jztcblx0fVxuXHRcblx0JGRpYWxvZ0NvbnRlbnQuZmluZCgnc2VsZWN0W25hbWU9XCJTdGF0ZUNvZGVcIl0nKS5odG1sKGh0bWxbJ3N0YXRlcyddKTtcbn1cblxuZnVuY3Rpb24gbG9hZFN0b3Jlcyh1cGRhdGUpIHtcblx0cmVhZHlbJ3N0b3JlcyddID0gZmFsc2U7XG5cdFxuXHR2YXIgcGF5bG9hZCA9IHt9O1xuXHRcblx0aWYgKCRkaWFsb2dDb250ZW50KSB7XG5cdFx0cGF5bG9hZC5Qb3N0YWxDb2RlID0gJGRpYWxvZ0NvbnRlbnQuZmluZCgnLnNlYXJjaCBbbmFtZT1cIlBvc3RhbENvZGVcIl0nKS52YWwoKTtcblx0XHRwYXlsb2FkLlN0YXRlQ29kZSA9ICRkaWFsb2dDb250ZW50LmZpbmQoJy5zZWFyY2ggW25hbWU9XCJTdGF0ZUNvZGVcIl0nKS52YWwoKTtcblx0fVxuXHRcblx0cGF5bG9hZC5zdG9yZVF1ZXJ5ID0gc3RhdGUub3B0aW9uc1snc3RvcmVRdWVyeSddID8gc3RhdGUub3B0aW9uc1snc3RvcmVRdWVyeSddIDoge307XG5cdFxuXHQkLmFqYXgoeyBtZXRob2Q6ICdQT1NUJywgdXJsOiBVcmxzLmdldE1vcmVTdG9yZXNBZGRyZXNzTGlzdCwgZGF0YTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsIGRhdGFUeXBlOiAnanNvbicsIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XHRcdFxuXHRcdHN0YXRlWydzdG9yZXMnXSA9IGRhdGE7XG5cdFx0cmVhZHlbJ3N0b3JlcyddID0gdHJ1ZTtcblx0XHRcblx0XHRpZiAodXBkYXRlKSB7XG5cdFx0XHRyZW5kZXJTdG9yZXMoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVuZGVyKCk7XG5cdFx0fVxuXHR9fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclN0b3JlcygpIHtcblx0aHRtbFsnc3RvcmVzJ10gPSAnJztcblx0XG5cdGlmIChzdGF0ZVsnc3RvcmVzJ10uYWRkcmVzc2VzLmxlbmd0aCA+IDApIHtcblx0XHR2YXIgaW5kZXggPSAwO1xuXHRcdGZvciAodmFyIHN0b3JlQWRkcmVzc2VzRWxlbWVudCBpbiBzdGF0ZVsnc3RvcmVzJ10uYWRkcmVzc2VzKSB7XG5cdFx0XHR2YXIgc3RvcmVBZGRyZXNzID0gc3RhdGVbJ3N0b3JlcyddLmFkZHJlc3Nlc1tzdG9yZUFkZHJlc3Nlc0VsZW1lbnRdO1xuXHRcdFx0XG5cdFx0XHR2YXIgc3RyZWV0QWRkcmVzcyA9IHN0b3JlQWRkcmVzcy5hZGRyZXNzMTtcblx0XHRcdGlmIChzdG9yZUFkZHJlc3MuYWRkcmVzczIpIHtcblx0XHRcdFx0c3RyZWV0QWRkcmVzcyArPSBzdG9yZUFkZHJlc3MuYWRkcmVzczI7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGh0bWxbJ3N0b3JlcyddICs9IHRlbXBsYXRlc1snbG9jYXRpb24nXSh7XG5cdFx0XHRcdGlkOiBpbmRleCxcblx0XHRcdFx0bmFtZTogc3RvcmVBZGRyZXNzLmZ1bGxOYW1lICsgJyAnICsgc3RvcmVBZGRyZXNzLmxhc3ROYW1lLFxuXHRcdFx0XHRhZGRyZXNzOiBzdHJlZXRBZGRyZXNzLFxuXHRcdFx0XHRjaXR5OiBzdG9yZUFkZHJlc3MuY2l0eSxcblx0XHRcdFx0c3RhdGU6IHN0b3JlQWRkcmVzcy5zdGF0ZUNvZGUsXG5cdFx0XHRcdHBvc3RhbDogc3RvcmVBZGRyZXNzLnBvc3RhbENvZGUsXG5cdFx0XHRcdHBob25lOiBzdG9yZUFkZHJlc3MucGhvbmVcblx0XHRcdH0pO1xuXHRcdFx0XG5cdFx0XHRpbmRleCsrO1xuXHRcdH1cblx0XHRcblx0XHQkZGlhbG9nQ29udGVudC5maW5kKCcubm8tcmVzdWx0cycpLmhpZGUoKTtcblx0XHQkZGlhbG9nQ29udGVudC5maW5kKCcuc3RvcmVzLWxpc3QnKS5odG1sKGh0bWxbJ3N0b3JlcyddKS5zaG93KCk7XG5cdH0gZWxzZSB7XG5cdFx0JGRpYWxvZ0NvbnRlbnQuZmluZCgnLm5vLXJlc3VsdHMnKS5zaG93KCk7XG5cdFx0JGRpYWxvZ0NvbnRlbnQuZmluZCgnLnN0b3Jlcy1saXN0JykuaGlkZSgpO1xuXHR9XG5cdFxuXHRcbn1cblxuZnVuY3Rpb24gbG9hZFRlbXBsYXRlcygpIHtcblx0dGVtcGxhdGVzID0ge307XG5cdFxuXHQkLmFqYXgoeyBtZXRob2Q6ICdQT1NUJywgdXJsOiBVcmxzLmdldE1vcmVTdG9yZXNEaWFsb2dUZW1wbGF0ZSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHR0ZW1wbGF0ZXNbJ2RpYWxvZyddID0gXy50ZW1wbGF0ZShkYXRhLCB0ZW1wbGF0ZVNldHRpbmdzKTtcblx0XHRyZW5kZXIoKTtcblx0fX0pO1xuXHRcblx0JC5hamF4KHsgbWV0aG9kOiAnUE9TVCcsIHVybDogVXJscy5nZXRNb3JlU3RvcmVzTG9jYXRpb25UZW1wbGF0ZSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHR0ZW1wbGF0ZXNbJ2xvY2F0aW9uJ10gPSBfLnRlbXBsYXRlKGRhdGEsIHRlbXBsYXRlU2V0dGluZ3MpO1xuXHRcdHJlbmRlcigpO1xuXHR9fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlcih1cGRhdGUpIHtcblx0aWYgKHJlYWR5WydkaWFsb2cnXSAmJiByZWFkeVsnc3RvcmVzJ10gJiYgcmVhZHlbJ3N0YXRlcyddICYmIHRlbXBsYXRlc1snZGlhbG9nJ10gJiYgdGVtcGxhdGVzWydsb2NhdGlvbiddKSB7XG5cdFx0JGRpYWxvZ0NvbnRlbnQuaHRtbCh0ZW1wbGF0ZXNbJ2RpYWxvZyddKCkpO1xuXHRcdFxuXHRcdGlmIChzdGF0ZS5vcHRpb25zICYmIHN0YXRlLm9wdGlvbnMudmlldykge1xuXHRcdFx0JGRpYWxvZ0NvbnRlbnQuYXR0cigndmlldycsIHN0YXRlLm9wdGlvbnMudmlldyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRkaWFsb2dDb250ZW50LnJlbW92ZUF0dHIoJ3ZpZXcnKTtcblx0XHR9XG5cdFx0XG5cdFx0cmVuZGVyU3RvcmVzKCk7XG5cdFx0cmVuZGVyU3RhdGVzKCk7XG5cdH1cdFxufVxuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSByZXF1aXJlKCcuL2FqYXgnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIExvYWQgZGV0YWlscyB0byBhIGdpdmVuIGdpZnQgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSB7U3RyaW5nfSBpZCBUaGUgSUQgb2YgdGhlIGdpZnQgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIEEgZnVuY3Rpb24gdG8gY2FsbGVkXG4gKi9cbmV4cG9ydHMuY2hlY2tCYWxhbmNlID0gZnVuY3Rpb24gKGlkLCBjYWxsYmFjaykge1xuICAgIC8vIGxvYWQgZ2lmdCBjZXJ0aWZpY2F0ZSBkZXRhaWxzXG4gICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChVcmxzLmdpZnRDYXJkQ2hlY2tCYWxhbmNlLCAnZ2lmdENlcnRpZmljYXRlSUQnLCBpZCk7XG5cbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4vYWpheCcpLFxuICAgIG1pbmljYXJ0ID0gcmVxdWlyZSgnLi9taW5pY2FydCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxudmFyIHNldEFkZFRvQ2FydEhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB2YXIgZm9ybSA9ICQodGhpcykuY2xvc2VzdCgnZm9ybScpO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKGZvcm0uYXR0cignYWN0aW9uJykpLFxuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgY2FjaGU6IGZhbHNlLFxuICAgICAgICBkYXRhOiBmb3JtLnNlcmlhbGl6ZSgpXG4gICAgfTtcbiAgICAkLmFqYXgob3B0aW9ucykuZG9uZShmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIGFqYXgubG9hZCh7XG4gICAgICAgICAgICAgICAgdXJsOiBVcmxzLm1pbmljYXJ0R0MsXG4gICAgICAgICAgICAgICAgZGF0YToge2xpbmVJdGVtSWQ6IHJlc3BvbnNlLnJlc3VsdC5saW5lSXRlbUlkfSxcbiAgICAgICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbmljYXJ0LnNob3cocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgICAgICBmb3JtLmZpbmQoJ2lucHV0LHRleHRhcmVhJykudmFsKCcnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm0uZmluZCgnc3Bhbi5lcnJvcicpLmhpZGUoKTtcbiAgICAgICAgICAgIGZvciAodmFyIGlkIGluIHJlc3BvbnNlLmVycm9ycy5Gb3JtRXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlcnJvckVsID0gJCgnIycgKyBpZCkuYWRkQ2xhc3MoJ2Vycm9yJykucmVtb3ZlQ2xhc3MoJ3ZhbGlkJykubmV4dCgnLmVycm9yJyk7XG4gICAgICAgICAgICAgICAgaWYgKCEkZXJyb3JFbCB8fCAkZXJyb3JFbC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJGVycm9yRWwgPSAkKCc8c3BhbiBmb3I9XCInICsgaWQgKyAnXCIgZ2VuZXJhdGVkPVwidHJ1ZVwiIGNsYXNzPVwiZXJyb3JcIiBzdHlsZT1cIlwiPjwvc3Bhbj4nKTtcbiAgICAgICAgICAgICAgICAgICAgJCgnIycgKyBpZCkuYWZ0ZXIoJGVycm9yRWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkZXJyb3JFbC50ZXh0KHJlc3BvbnNlLmVycm9ycy5Gb3JtRXJyb3JzW2lkXS5yZXBsYWNlKC9cXFxcJy9nLCAnXFwnJykpLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pLmZhaWwoZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cykge1xuICAgICAgICAvLyBmYWlsZWRcbiAgICAgICAgaWYgKHRleHRTdGF0dXMgPT09ICdwYXJzZXJlcnJvcicpIHtcbiAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQkFEX1JFU1BPTlNFKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuU0VSVkVSX0NPTk5FQ1RJT05fRVJST1IpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCgnI0FkZFRvQmFza2V0QnV0dG9uJykub24oJ2NsaWNrJywgc2V0QWRkVG9DYXJ0SGFuZGxlcik7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudCA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvR2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudCcpO1xuXG5leHBvcnRzLmluaXRpYWxpemVBbGxGb3VuZENvbXBvbmVudHMgPSBpbml0aWFsaXplQWxsRm91bmRDb21wb25lbnRzO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplQWxsRm91bmRDb21wb25lbnRzKCRjb250YWluZXJQYXJhbWV0ZXIpIHtcblx0dmFyICRjb250YWluZXIgPSAkY29udGFpbmVyUGFyYW1ldGVyIHx8ICQoZG9jdW1lbnQpO1xuXHRcblx0dmFyICRiYWxhbmNlSW5xdWlyeUNvbXBvbmVudHMgPSAkY29udGFpbmVyLmZpbmQoJy5naWZ0LWNhcmQtYmFsYW5jZS1pbnF1aXJ5LWNvbXBvbmVudCcpO1xuXHRpZiAoJGJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0JGJhbGFuY2VJbnF1aXJ5Q29tcG9uZW50cy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0Z2lmdENhcmRCYWxhbmNlSW5xdWlyeUNvbXBvbmVudC5pbml0aWFsaXplKCQodGhpcykucGFyZW50KCkpO1xuXHRcdH0pO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlZhbGlkYXRlID0gdmFsaWRhdGU7XG5cbmZ1bmN0aW9uIHZhbGlkYXRlKGFjdGlvbikge1xuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0JC5hamF4KHtcblx0XHRcdG1ldGhvZDogJ3Bvc3QnLFxuXHRcdFx0dXJsOiBVcmxzLlJlcXVlc3QuVmFsaWRhdGUsXG5cdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRBY3Rpb246IGFjdGlvblxuXHRcdFx0fSksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRpZiAoZGF0YSkge1xuXHRcdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmVqZWN0KGRhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZWplY3QoZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuLy8galF1ZXJ5IGV4dGVuc2lvbnNcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gcGFyYW1zXG4gICAgLy8gdG9nZ2xlQ2xhc3MgLSByZXF1aXJlZFxuICAgIC8vIHRyaWdnZXJTZWxlY3RvciAtIG9wdGlvbmFsLiB0aGUgc2VsZWN0b3IgZm9yIHRoZSBlbGVtZW50IHRoYXQgdHJpZ2dlcnMgdGhlIGV2ZW50IGhhbmRsZXIuIGRlZmF1bHRzIHRvIHRoZSBjaGlsZCBlbGVtZW50cyBvZiB0aGUgbGlzdC5cbiAgICAvLyBldmVudE5hbWUgLSBvcHRpb25hbC4gZGVmYXVsdHMgdG8gJ2NsaWNrJ1xuICAgICQuZm4udG9nZ2xlZExpc3QgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICBpZiAoIW9wdGlvbnMudG9nZ2xlQ2xhc3MpIHsgcmV0dXJuIHRoaXM7IH1cbiAgICAgICAgdmFyIGxpc3QgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbGlzdC5vbihvcHRpb25zLmV2ZW50TmFtZSB8fCAnY2xpY2snLCBvcHRpb25zLnRyaWdnZXJTZWxlY3RvciB8fCBsaXN0LmNoaWxkcmVuKCksIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB2YXIgY2xhc3NUYXJnZXQgPSBvcHRpb25zLnRyaWdnZXJTZWxlY3RvciA/ICQodGhpcykucGFyZW50KCkgOiAkKHRoaXMpO1xuICAgICAgICAgICAgY2xhc3NUYXJnZXQudG9nZ2xlQ2xhc3Mob3B0aW9ucy50b2dnbGVDbGFzcyk7XG4gICAgICAgICAgICAvLyBleGVjdXRlIGNhbGxiYWNrIGlmIGV4aXN0c1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2spIHtvcHRpb25zLmNhbGxiYWNrKCk7fVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgJC5mbi5zeW5jSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuaGVpZ2h0KCdhdXRvJyk7XG4gICAgICAgIHZhciBhcnIgPSAkLm1ha2VBcnJheSh0aGlzKTtcbiAgICAgICAgYXJyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAkKGEpLmhlaWdodCgpIC0gJChiKS5oZWlnaHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmhlaWdodCgkKGFyclthcnIubGVuZ3RoIC0gMV0pLmhlaWdodCgpKTtcbiAgICB9O1xuXG5cdCQuZm4uc3luY0hlaWdodFRvTWluaW11bSA9IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLmhlaWdodCgnYXV0bycpO1xuICAgICAgICB2YXIgYXJyID0gJC5tYWtlQXJyYXkodGhpcyk7XG4gICAgICAgIGFyci5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gJChhKS5oZWlnaHQoKSAtICQoYikuaGVpZ2h0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5oZWlnaHQoJChhcnJbMF0pLmhlaWdodCgpKTtcbiAgICB9O1xuXG5cdCQuZm4uc3luY0hlaWdodFRvQXZlcmFnZSA9IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLmhlaWdodCgnYXV0bycpO1xuICAgICAgICB2YXIgYXJyID0gJC5tYWtlQXJyYXkodGhpcyk7XG4gICAgICAgIGFyci5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gJChhKS5oZWlnaHQoKSAtICQoYikuaGVpZ2h0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5oZWlnaHQoJChhcnJbcGFyc2VJbnQoYXJyLmxlbmd0aC8yLCAxMCldKS5oZWlnaHQoKSk7XG4gICAgfTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgc2xpZGVycyA9IHJlcXVpcmUoJy4vc2xpZGVycycpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gaW5pdCAoKSB7XG5cdHNsaWNrU2xpZGVKdW1ib3Ryb24oKTtcblxuXHQvLyAkKCcuanVtYm90cm9uLWFqYXgnKS5yZWFkeShmdW5jdGlvbigpe1xuXHQvLyBcdHJlbmRlckp1bWJvdHJvblNsb3QoKTtcblx0Ly8gfSk7XG5cdFxuXHR2YXIgcmVuZGVySnVtYm90cm9uU2xvdCA9IGZ1bmN0aW9uKCl7XG5cdFx0aWYgKFVybHMgJiYgVXJscy5nZXRKdW1ib3Ryb25TbG90KSB7XG5cdFx0XHQkLmFqYXgoeyBtZXRob2Q6ICdQT1NUJywgdXJsOiBVcmxzLmdldEp1bWJvdHJvblNsb3QsIGRhdGFUeXBlOiAnaHRtbCcsIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRcdHZhciBodG1sID0gJyc7XG5cdFx0XHRcdHZhciBjb250ZW50U2xvdDtcblx0XHRcdFx0dmFyIGlzSnNvbiA9IGZhbHNlO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIHRlbXBsYXRlU2V0dGluZ3MgPSB7XG5cdFx0XHQgICAgXHRpbnRlcnBvbGF0ZTogL3t7KFtcXHNcXFNdKz8pfX0vZ1xuXHRcdFx0ICAgIH07XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgdGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1qdW1ib3Ryb24nKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIGRhdGFQYXlsb2FkID0gZGF0YS5zdWJzdHIoZGF0YS5pbmRleE9mKCd7JyksIGRhdGEubGVuZ3RoKTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciBlbmRQYXlsb2FkSW5kZXggPSBkYXRhUGF5bG9hZC5sZW5ndGg7XG5cdFx0XHRcdGlmIChkYXRhUGF5bG9hZC5pbmRleE9mKCc8IS0tIGR3TWFya2VyJykgPiAwKSB7XG5cdFx0XHRcdFx0ZW5kUGF5bG9hZEluZGV4ID0gZGF0YVBheWxvYWQuaW5kZXhPZignPCEtLSBkd01hcmtlcicpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQYXlsb2FkID0gZGF0YVBheWxvYWQuc3Vic3RyKDAsIGVuZFBheWxvYWRJbmRleCk7XG5cdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29udGVudFNsb3QgPSBKU09OLnBhcnNlKGRhdGFQYXlsb2FkKTtcblx0XHRcdFx0XHRpc0pzb24gPSB0cnVlO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0Y29uc29sZS53YXJuKCdDb250ZW50U2xvdCB0ZW1wbGF0ZSBub3Qgc2V0IHRvIEpTT04nKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKGNvbnRlbnRTbG90KSB7XG5cdFx0XHRcdFx0aWYgKGNvbnRlbnRTbG90LmNvbnRlbnQpIHtcblx0XHRcdFx0XHRcdGh0bWwgPSB0ZW1wbGF0ZSh7IGp1bWJvdHJvbjogYnVpbGRDb250ZW50U2xvdEZyb21KU09OKGNvbnRlbnRTbG90KSB9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSBpZiAoIWlzSnNvbikge1xuXHRcdFx0XHRcdGh0bWwgPSB0ZW1wbGF0ZSh7IGp1bWJvdHJvbjogZGF0YSB9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0JCgnLmp1bWJvdHJvbi1hamF4JykuYWRkQ2xhc3MoJ2FjdGl2ZScpLmh0bWwoaHRtbCk7XG5cdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuXHRcdFx0XHRcdHNsaWNrU2xpZGVKdW1ib3Ryb24oKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdhcHAucmVzaXplJyk7XG5cdFx0XHR9fSk7XG5cdFx0fVxuXHR9XG5cblx0Ly9maXNodGFnIHJpZ2dpbmcgY29udGVudCBhc3NldCAnY2F0LWdsb2JhbC1oZWFkZXInXG5cdC8vJCgnLmNhdC1nbG9iYWwtaGVhZGVyJykucmVhZHkoZnVuY3Rpb24oKXtcblx0Ly9cdHJlbmRlckZpc2h0YWcoKTtcblx0Ly99KTtcblx0XG5cdGZ1bmN0aW9uIHJlbmRlckZpc2h0YWcoKXtcblx0XHRpZiAoVXJscyAmJiBVcmxzLmdldEZpc2h0YWcpIHtcblx0XHRcdCQuYWpheCh7IG1ldGhvZDogJ1BPU1QnLCB1cmw6IFVybHMuZ2V0RmlzaHRhZywgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24oZGF0YSl7XG5cdFx0XHRcdHZhciBodG1sID0gJyc7XG5cdFx0XHRcdHZhciBjb250ZW50U2xvdDtcblx0XHRcdFx0dmFyIGlzSnNvbiA9IGZhbHNlO1xuXHRcdFx0XHRcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb250ZW50U2xvdCA9IEpTT04ucGFyc2UoZGF0YS5zdWJzdHIoZGF0YS5pbmRleE9mKCd7JyksIGRhdGEubGVuZ3RoKSk7XG5cdFx0XHRcdFx0aXNKc29uID0gdHJ1ZTtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdGNvbnNvbGUud2FybignQ29udGVudFNsb3QgdGVtcGxhdGUgbm90IHNldCB0byBKU09OJyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmIChjb250ZW50U2xvdCAmJiBjb250ZW50U2xvdC5jb250ZW50KSB7XG5cdFx0XHRcdFx0aHRtbCA9IGJ1aWxkQ29udGVudFNsb3RGcm9tSlNPTihjb250ZW50U2xvdCk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIWlzSnNvbikge1xuXHRcdFx0XHRcdGh0bWwgPSBkYXRhO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHQkKCcuZmlzaHRhZy1zbG90JykuaHRtbChodG1sKTtcbiAgICAgICAgICAgICAgICByb3RhdGVUZXh0KCQoJy50b3AtYmFubmVyLW1lc3NhZ2UnKSwgJCgnLnRvcC1iYW5uZXItbWVzc2FnZScpLmRhdGEoJ2R1cmF0aW9uJykpO1xuXHRcdFx0fX0pO1xuXHRcdH1cblx0fVxuXHRcblx0ZnVuY3Rpb24gYnVpbGRDb250ZW50U2xvdEZyb21KU09OKGNvbnRlbnRTbG90SlNPTikge1xuXHRcdHZhciBib2R5ID0gJyc7XG5cdFx0XG5cdFx0aWYgKGNvbnRlbnRTbG90SlNPTiAmJiBjb250ZW50U2xvdEpTT04uY29udGVudCkge1xuXHRcdFx0Zm9yICh2YXIgY29udGVudFNsb3RJdGVtIGluIGNvbnRlbnRTbG90SlNPTi5jb250ZW50KSB7XG5cdFx0XHRcdGJvZHkgKz0gY29udGVudFNsb3RKU09OLmNvbnRlbnRbY29udGVudFNsb3RJdGVtXS5ib2R5O1xuXHRcdFx0fVxuXHRcdFxuXHRcdFx0aWYgKGNvbnRlbnRTbG90SlNPTi5jb3VudGRvd25Ubykge1xuXHRcdFx0XHRib2R5ID0gJzxkaXYgY2xhc3M9XCJjb3VudGRvd24td3JhcHBlclwiIGRhdGEtY291bnRkb3duLWRhdGU9XCInICsgY29udGVudFNsb3RKU09OLmNvdW50ZG93blRvICsgJ1wiPicgKyBib2R5ICsgJzwvZGl2Pic7IFxuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHRyZXR1cm4gYm9keTtcblx0fVxuXHRcblx0Ly8gUm90YXRlIFRleHQgZm9yIGZpc2h0YWdcblx0ZnVuY3Rpb24gcm90YXRlVGV4dCgkZWxlbWVudCwgZHVyYXRpb24pIHtcblx0XHR2YXIgbGVuZ3RoU2xpZGVyIFx0XHRcdD0gJGVsZW1lbnQuZmluZCgnLnJvdGF0ZS1lbGVtZW50JykubGVuZ3RoO1xuXHRcdHZhciAkcm90YXRlRWxlbWVudCBcdFx0XHQ9ICRlbGVtZW50LmZpbmQoJy5yb3RhdGUtZWxlbWVudCcpO1xuXG5cdFx0c2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgJHJvdGF0ZUVsZW1lbnRBY3RpdmUgXHQ9ICRlbGVtZW50LmZpbmQoJy5hY3RpdmUnKTtcblx0XHRcdHZhciAkbmV4dEVsZW1lbnQgPSAkcm90YXRlRWxlbWVudEFjdGl2ZS5uZXh0KCk7XG5cblx0XHRcdGlmKCRuZXh0RWxlbWVudC5pbmRleCgpID09PSAtMSkge1xuXHRcdFx0XHQkbmV4dEVsZW1lbnQgPSAkZWxlbWVudC5maW5kKCcucm90YXRlLWVsZW1lbnQ6Zmlyc3QtY2hpbGQnKTtcblxuXHRcdFx0XHQkbmV4dEVsZW1lbnRcblx0XHRcdFx0XHQuYWRkQ2xhc3MoJ2FjdGl2ZScpXG5cdFx0XHRcdFx0LnNpYmxpbmdzKClcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JG5leHRFbGVtZW50XG5cdFx0XHRcdFx0LmFkZENsYXNzKCdhY3RpdmUnKVxuXHRcdFx0XHRcdC5zaWJsaW5ncygpXG5cdFx0XHRcdFx0LnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH1cblx0XHR9LCBkdXJhdGlvbik7XG5cdH1cblxuXHRmdW5jdGlvbiBzbGlja1NsaWRlSnVtYm90cm9uKCkge1xuXHRcdHZhciBzbGlkZXNNb2JpbGUgPSAkKCcuZ2Jjb2x1bW5zJykuY2xvc2VzdCgnW2RhdGEtc2xpZGVzLW1vYmlsZV0nKS5sZW5ndGggPiAwID8gcGFyc2VJbnQoJCgnLmdiY29sdW1ucycpLmNsb3Nlc3QoJ1tkYXRhLXNsaWRlcy1tb2JpbGVdJykuYXR0cignZGF0YS1zbGlkZXMtbW9iaWxlJykpIDogMTtcblx0XHR2YXIgc2xpZGVzRGVza3RvcCA9ICQoJy5nYmNvbHVtbnMnKS5jbG9zZXN0KCdbZGF0YS1zbGlkZXMtZGVza3RvcF0nKS5sZW5ndGggPiAwID8gcGFyc2VJbnQoJCgnLmdiY29sdW1ucycpLmNsb3Nlc3QoJ1tkYXRhLXNsaWRlcy1kZXNrdG9wXScpLmF0dHIoJ2RhdGEtc2xpZGVzLWRlc2t0b3AnKSkgOiA0O1xuXHRcblx0XHRzbGlkZXJzLmluaXQoJy5nYmNvbHVtbnMnLCB7ZG90czogZmFsc2UsIGJyZWFrcG9pbnRzOiB7MDoge3NsaWRlc1RvU2hvdzogc2xpZGVzTW9iaWxlLCBhcnJvd3M6IHRydWV9LCA3Njg6IHtzbGlkZXNUb1Nob3c6IHNsaWRlc0Rlc2t0b3B9fX0pO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBMT0dJTlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xudmFyIGxvZ2luRGlhbG9nID0gcmVxdWlyZSgnLi9sb2dpbkRpYWxvZycpO1xudmFyIHJlY2FwdGNoYSA9IHJlcXVpcmUoJy4vY29tcG9uZW50cy9SZWNhcHRjaGEnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7IC8vdXRpbCByZWZlcmVuY2VcbnZhclx0dmFsaWRhdG9yID0gcmVxdWlyZSgnLi92YWxpZGF0b3InKTtcblxudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcblxudmFyIGRhdGFCdWZmZXIgPSB7fTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG52YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuICAgIElzTGFiZWxTaG93bjogZmFsc2UsXG4gICAgQ3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcbiAgICBCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcbn07XG52YXIgb3BjTG9nZ2VkSW5DdXN0b21lckFkZHJlc3NlcyA9IFtdO1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBpbml0IGV2ZW50cyBmb3IgdGhlIGxvZ2luUGFnZVxuICovXG5mdW5jdGlvbiBpbml0TG9naW5FdmVudHMoKSB7XG4gICAgLy90b2dnbGUgdGhlIHZhbHVlIG9mIHRoZSByZW1lbWJlcm1lIGNoZWNrYm94XG4gICAgJChkb2N1bWVudCkub24oJ2NoYW5nZScsICcubG9naW4tcmVtZW1iZXJtZSBpbnB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCQodGhpcykucHJvcCgnY2hlY2tlZCcpKSB7XG4gICAgICAgICAgICAkKCcjcmVtZW1iZXJtZScpLnZhbCgndHJ1ZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJCgnI3JlbWVtYmVybWUnKS52YWwoJ2ZhbHNlJyk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI29wdGluLXByaXZhY3ktcG9saWN5JywgZnVuY3Rpb24oZSkgeyBcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyBcbiAgICAgICAgbG9jYXRpb24uaHJlZiA9IFVybHMucHJpdmFjeVBhZ2U7IFxuICAgIH0pO1xuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjcmV3YXJkLWxlYXJuLW1vcmUnLCBmdW5jdGlvbihlKSB7IFxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IFxuICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5sZWFybkZBUTsgXG4gICAgfSk7XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5tb3ZldG9hZGRyJywgZnVuY3Rpb24oZSl7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoeyBcbiAgICAgICAgICAgIHNjcm9sbFRvcDogJCgnLmJpbGxpbmctYWRkcmVzcy1mb3JtJykuZXEoMCkub2Zmc2V0KCkudG9wXG4gICAgICAgIH0sIDEwMDApO1xuICAgIH0pO1xuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjYXR0YWNoLXJld2FyZHMtZm9ybSBsYWJlbCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAkKCcjYXR0YWNoLXJld2FyZHMtZm9ybSBpbnB1dCcpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKTtcbiAgICAgICAgJCh0aGlzKS5zaWJsaW5ncygnW25hbWU9XCJhdHRhY2gtcmV3YXJkcy1vcHRpb25zXCJdJykuYXR0cignY2hlY2tlZCcsICdjaGVja2VkJyk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlTG9naW5Gb3JtKCRmb3JtLCBjaGVja0ZpZWxkcykge1x0XG4gICAgaWYgKCEkZm9ybSB8fCAhY2hlY2tGaWVsZHMpIHsgcmV0dXJuIGZhbHNlIH1cblxuICAgIHZhciAkZW1haWxGaWVsZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3VzZXJuYW1lXCJdJyk7XHRcbiAgICB2YXIgJHBhc3N3b3JkRmllbGQgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cIl9wYXNzd29yZFwiXScpO1xuICAgIHZhciAkcGFzc2NvZGVGaWVsZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3Bhc3Njb2RlXCJdJyk7XG4gICAgdmFyIGVtYWlsVmFsdWUgPSAkZW1haWxGaWVsZC5sZW5ndGggPiAwID8gJGVtYWlsRmllbGQudmFsKCkudHJpbSgpIDogbnVsbDtcblx0dmFyIHBhc3N3b3JkVmFsdWUgPSAkcGFzc3dvcmRGaWVsZC5sZW5ndGggPiAwID8gJHBhc3N3b3JkRmllbGQudmFsKCkudHJpbSgpIDogbnVsbDtcbiAgICB2YXIgcGFzc2NvZGVWYWx1ZSA9ICRwYXNzY29kZUZpZWxkLmxlbmd0aCA+IDAgPyAkcGFzc2NvZGVGaWVsZC52YWwoKS50cmltKCkgOiBudWxsO1xuXHR2YXIgZm9ybVZhbGlkYXRpb24gPSB0cnVlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGVja0ZpZWxkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY3VycmVudEZpZWxkID0gY2hlY2tGaWVsZHNbaV07XG4gICAgICAgICAgICAgICAgXG4gICAgICAgIGlmIChjdXJyZW50RmllbGQudG9VcHBlckNhc2UoKSA9PSAnRU1BSUwnICYmICghZW1haWxWYWx1ZSB8fCBlbWFpbFZhbHVlLmxlbmd0aCA9PSAwKSkge1xuICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3VzZXJuYW1lXCJdJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN1cnJlbnRGaWVsZC50b1VwcGVyQ2FzZSgpID09ICdQQVNTV09SRCcgJiYgKCFwYXNzd29yZFZhbHVlIHx8IHBhc3N3b3JkVmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBmb3JtVmFsaWRhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJfcGFzc3dvcmRcIl0nKS5hZGRDbGFzcygnZXJyb3InKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudEZpZWxkLnRvVXBwZXJDYXNlKCkgPT0gJ1BBU1NDT0RFJyAmJiAoIXBhc3Njb2RlVmFsdWUgfHwgcGFzc2NvZGVWYWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cIl9wYXNzY29kZVwiXScpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICB9XG4gICAgfVxuXHRcdFx0XG5cdGlmICghZm9ybVZhbGlkYXRpb24pIHtcbiAgICAgICAgJGZvcm0uZmluZCgnLmxvZ2luLWRpYWxvZy1lcnJvciAuaW52YWxpZC1taXNzaW5nLWZpZWxkcycpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICRmb3JtLmZpbmQoJy5sb2dpbi1kaWFsb2ctZXJyb3Igc3BhbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlcnJvckhhbmRsaW5nKGRhdGEsIGRpYWxvZ1RpdGxlLCBkaWFsb2dIdG1sKSB7XG4gICAgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdtZXNzYWdlJyBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGRhdGEubWVzc2FnZSk7XG4gICAgfVxuICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgaHRtbDogZGlhbG9nSHRtbCxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgdGl0bGU6IGRpYWxvZ1RpdGxlLFxuICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG4gICAgICAgICAgICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8vIENvcmRpYWwgdHJhY2tpbmcgZm9yIGxvZ2luUGFnZSBhbmQgbG9naW5EaWFsb2dcbmZ1bmN0aW9uIGxvZ2luQ29yZGlhbEFjY291bnRFdmVudCgkZm9ybSwgaXNMb2dpbkRpYWxvZykge1xuICAgIHZhciB1c2VybmFtZSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiX3VzZXJuYW1lXCJdJykudmFsKCkudHJpbSgpO1xuICAgICAgICBcbiAgICB2YXIgYXV0aF9kYXRhID0ge1xuICAgICAgICBlbWFpbDogdXNlcm5hbWVcbiAgICB9XG4gICAgICAgIFxuICAgIHZhciBjb250YWN0X2RhdGEgPSB7XG4gICAgICAgICdjaGFubmVscyc6IHtcbiAgICAgICAgICAgICdlbWFpbCc6IHtcbiAgICAgICAgICAgICAgICAnYWRkcmVzcyc6IHVzZXJuYW1lICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFxuICAgIHZhciBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBcImVtYWlsXCI6IHVzZXJuYW1lLFxuICAgICAgICBcImxvZ2luVHlwZVwiOiBpc0xvZ2luRGlhbG9nID8gXCJsb2dpbi1kaWFsb2dcIiA6IFwibG9naW5cIlxuICAgIH07XG4gICAgICAgIFxuICAgIGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY3JkbChbXHRcdFx0XHRcbiAgICAgICAgICAgIFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxcbiAgICAgICAgICAgIFsnZXZlbnQnLCAnbG9naW4nLCBwcm9wZXJ0aWVzXVxuICAgICAgICBdKTtcbiAgICB9XG59XG5cbi8vIENvcmRpYWwgcGFzc3dvcmQgcmVzZXQgLSBubyBhY2NvdW50IGV2ZW50XG5mdW5jdGlvbiBwYXNzd29yZFJlc2V0Tm9BY2NvdW50Q29yZGlhbEV2ZW50KGNvbnRhaW5lcikge1xuICAgIGlmIChjb250YWluZXIgJiYgJChjb250YWluZXIpLmZpbmQoJy5yZXNldC1wYXNzd29yZCAubm8tYWNjb3VudCcpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdmFyIGVtYWlsID0gJCgnLm5vLWFjY291bnQnKS50ZXh0KCk7XG5cdFxuXHRcdHZhciBhdXRoX2RhdGEgPSB7XG5cdFx0XHRlbWFpbDogZW1haWxcblx0XHR9XG5cdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdCAgICAnZW1haWwnOiB7XG5cdFx0XHQgICAgICAgICdhZGRyZXNzJzogZW1haWxcblx0XHRcdCAgICB9XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRcdFxuXHRcdHZhciBwcm9wZXJ0aWVzID0ge1xuXHRcdFx0XCJlbWFpbFwiOiBlbWFpbFxuXHRcdH07XG5cblx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRjcmRsKFtcblx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRbJ2V2ZW50JywgJ3Jlc2V0LXBhc3N3b3JkLW5vLWFjY291bnQnLCBwcm9wZXJ0aWVzXVxuXHRcdFx0XSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVSZWNhcHRjaGFGb3JMb2dpbigpIHtcblx0cmVuZGVyUmVjYXB0Y2hhRm9yTG9naW4oKTtcblx0JChkb2N1bWVudCkub24oJ0FjY291bnQuU3VibWl0TG9naW4nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdCQoJyNhY2NvdW50TG9naW5CdXR0b24nKS5jbGljaygpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhRm9yTG9naW4oKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmICQoJyNhY2NvdW50TG9naW5CdXR0b24nKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckFjY291bnRMb2dpbiAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0ZGF0YUJ1ZmZlci5Mb2dpblJlY2FwdGNoYSA9IGdyZWNhcHRjaGEucmVuZGVyKCdhY2NvdW50TG9naW5CdXR0b24nLCB7XG5cdCAgICAgICAgJ3NpdGVrZXknOiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgICdjYWxsYmFjayc6IGFjY291bnRMb2dpbixcblx0ICAgICAgICAnYmFkZ2UnOiAnYm90dG9tbGVmdCdcblx0ICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYUZvclBhc3N3b3JkUmVzZXQoKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmICQoJyNyZXF1ZXN0LXBhc3N3b3JkLXNlbmQtYnRuJykubGVuZ3RoID4gMCAmJiBvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQYXNzd29yZFJlc2V0ICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkpIHtcblx0XHRpZiAoZGF0YUJ1ZmZlci5SZXNldFBhc3N3b3JkUmVjYXB0Y2hhKSB7XG5cdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGRhdGFCdWZmZXIuUmVzZXRQYXNzd29yZFJlY2FwdGNoYSk7XG5cdFx0fVxuXG5cdFx0ZGF0YUJ1ZmZlci5SZXNldFBhc3N3b3JkUmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ3JlcXVlc3QtcGFzc3dvcmQtc2VuZC1idG4nLCB7XG5cdCAgICAgICAgJ3NpdGVrZXknOiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgICdjYWxsYmFjayc6IHdpbmRvdy5yZXNldFBhc3N3b3JkLFxuXHQgICAgICAgICdiYWRnZSc6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxudmFyIHVwZGF0ZUN1c3RvbWVyRGV0YWlscyA9IGZ1bmN0aW9uIChmb3JtLCBuYW1lKSB7XG4gICAgdmFyICRmb3JtID0gJChmb3JtKTtcbiBcbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMub25lUGFnZUxvZ2luKSxcbiAgICAgICAgZGF0YTogJGZvcm0uc2VyaWFsaXplKCkgKyAnJicgKyBuYW1lICsgJz0nICsgbmFtZVxuICAgIH0pKTtcbiB9XG5cbmZ1bmN0aW9uIHNob3dOb3RpZmljYXRpb24odGV4dCwgc2VsZWN0b3IsIG1zZ1R5cGUpIHtcbiAgICB2YXIgJHNlbGVjdG9yID0gJChzZWxlY3Rvcik7XG5cdGlmICgkc2VsZWN0b3IubGVuZ3RoID09IDApIHtcbiAgICAgICAgdmFyICRmb3JtID0gJCgnZm9ybS5vcGMtbG9naW4nKSxcbiAgICAgICAgICAgICRzZWxlY3RvciA9ICQoJzxzcGFuLz4nLCB7J2NsYXNzJzogJ2xvZ2luLW5vdGlmaWNhdGlvbicsICd0YWJpbmRleCc6ICcwJ30pLndyYXAoJzxkaXYgY2xhc3M9XCJmb3JtZmllbGQgY2xlYXJmaXggZXJyb3ItYm94XCI+PGRpdiBjbGFzcz1cImZvcm0tcm93IHJlcXVpcmVkXCI+PGRpdiBjbGFzcz1cImZpZWxkLXdyYXBwZXJcIj48L2Rpdj48L2Rpdj48L2Rpdj4nKTtcblxuICAgICAgICAkc2VsZWN0b3IucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuaW5zZXJ0QmVmb3JlKCdmb3JtLm9wYy1sb2dpbiAuZm9ybS1yb3ctYnV0dG9uJyk7XG4gICAgICAgICRzZWxlY3RvciA9ICQoc2VsZWN0b3IpO1xuICAgIH1cblxuICAgICRzZWxlY3Rvci5yZW1vdmVDbGFzcygnc3VjY2VzcyBlcnJvcicpLmFkZENsYXNzKG1zZ1R5cGUpLnRleHQodGV4dCkuZm9jdXMoKTtcbn1cbiBcbmZ1bmN0aW9uIGNsZWFyTm90aWZpY2F0aW9uKHNlbGVjdG9yKSB7XG4gICAgIGlmKHNlbGVjdG9yLmxlbmd0aCl7XG4gICAgICAgICQoJy5mb3JtZmllbGQuZXJyb3ItYm94JykucmVtb3ZlKCk7XG5cdFx0c2VsZWN0b3IucmVtb3ZlQ2xhc3MoJ3N1Y2Nlc3MgZXJyb3InKTtcbiAgICAgfVxufVxuIFxuLy8gR1RNIGFuZCBDb3JkaWFsIHRhZ2dpbmcgZm9yIGNhcnQgb3BjLWxvZ2luXG5mdW5jdGlvbiBvcGNMb2dpblRhZ2dpbmcoJGZvcm0sIGNhbGxiYWNrKSB7XG4gICAgdmFyIGVtYWlsID0gICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwidXNlcm5hbWVcIl0nKS52YWwoKTtcbiAgICB2YXIgYXV0aF9kYXRhID0ge1xuICAgICAgICBlbWFpbDogZW1haWxcbiAgICB9XG4gICAgdmFyIGNvbnRhY3RfZGF0YSA9IHtcbiAgICAgICAgJ2NoYW5uZWxzJzoge1xuICAgICAgICAgICAgJ2VtYWlsJzoge1xuICAgICAgICAgICAgICAgICdhZGRyZXNzJzogZW1haWwgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgdmFyIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIFwiZW1haWxcIjogZW1haWxcbiAgICB9O1xuICAgIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0N1c3RvbWVyTG9naW4nLCB7IG1ldGhvZDogJ2NhcnQnIH0pLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY3JkbChbXG4gICAgICAgICAgICAgICAgICAgIFsnY29udGFjdCcsIGF1dGhfZGF0YSwgY29udGFjdF9kYXRhXSxbJ2V2ZW50JywgJ2xvZ2luJywgcHJvcGVydGllc11cbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKCk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHBhc3N3b3JkbGVzc0xvZ2luU2VxdWVuY2UoaXNDaGVja291dExvZ2luKSB7XG4gICAgaWYgKCFpc0NoZWNrb3V0TG9naW4pIHtcbiAgICAgICAgJCgnI290cC10b2dnbGUtYnV0dG9uJykuaGlkZSgpO1xuICAgIH1cbiAgICAkKCcubG9naW4tZGlhbG9nLXNpZ25pbi1jb250YWluZXIsIC5sb2dpbi1kaWFsb2ctcmVnaXN0ZXItbWVzc2FnZSwgI3RvZ2dsZS1yZWdpc3RyYXRpb24nKS5oaWRlKCk7XG4gICAgJCgnLmxvZ2luLWRpYWxvZy1wYXNzY29kZS1jb250YWluZXInKS5hZGRDbGFzcygncGFzc2NvZGUtZm9ybS1zaG93Jyk7XG4gICAgJCgnLm90cC1wYXNzY29kZS1maWVsZC1jb250YWluZXIsIC5vdHAtcmVzZW5kLWNvZGUtY29udGFpbmVyJykuaGlkZSgpO1xuICAgICQoJy5vdHAtZW1haWwtZmllbGQtY29udGFpbmVyJykuc2hvdygpO1xuICAgICQoJy5sb2dpbi1kaWFsb2ctcGFzc2NvZGUtY29udGFpbmVyIGlucHV0W25hbWUqPVwiZHdmcm1fb3RwbG9naW5cIl0nKS52YWwoJycpOyAvLyBjbGVhciBwcmV2aW91cyBmb3JtIGlucHV0IHZhbHVlc1xufVxuXG4vKipcbiAqIExvZ2luIHJlcG9ydGluZyAtIGluY3JlbWVudHMgY291bnRlcnMgaW4gY3VzdG9tIG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IHR5cGUgLSBFaXRoZXIgJ25vcm1hbCcgZm9yIHRyYWRpdGlvbmFsIGxvZ2luIHR5cGUsIG9yICdwYXNzd29yZGxlc3MnIGZvciBuZXcgbG9naW4gdHlwZVxuICogQHBhcmFtIHtTdHJpbmd9IHNvdXJjZSAtIFNvdXJjZSBvZiBsb2dpbiwgd2hpY2ggY2FuIGJlIG9yaWdpbmFsLCBjYXJ0LCBjYXJ0LW1vZGFsLCBvciB3aXNobGlzdC1tb2RhbFxuICovXG5mdW5jdGlvbiB0cmFja0xvZ2luQWN0aW9ucyh0eXBlLCBzb3VyY2UpIHtcbiAgICBpZiAoIXR5cGUgfHwgIXNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IFVybHMubG9naW5UcmFja2luZyxcbiAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlXG4gICAgICAgIH0pLFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnTG9naW4tVHJhY2tBY3Rpb25zOiBFcnJvciBpbiBpbmNyZW1lbnRpbmcgbG9naW4gYWN0aW9uIGNvdW50ZXJzLiBFUlJPUiBURVhUOiAnK3RleHRTdGF0dXMrJywgRVJST1IgVEhST1dOOiAnK2Vycm9yVGhyb3duKycuJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UpIHt9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gaW5pdCBsb2dpbiBidXR0b24gZXZlbnQgZm9yIHRoZSBsb2dpblBhZ2UsIGxvZ2luRGlhbG9nIGFuZCBjaGVja291dCBsb2dpblxuICovXG5mdW5jdGlvbiBpbml0TG9naW5CdXR0b25zKCkge1xuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI2FjY291bnRMb2dpbkJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGRpYWxvZ0h0bWwgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggbG9naW4uIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG4gICAgICAgIHZhciAkYWNjb3VudExvZ2luQnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRhY2NvdW50TG9naW5Gb3JtID0gJGFjY291bnRMb2dpbkJ1dHRvbi5jbG9zZXN0KCdmb3JtI2R3ZnJtX2xvZ2luJyk7XG4gICAgICAgIHZhciBmb3JtUmVtZW1iZXJNZSA9ICRhY2NvdW50TG9naW5Gb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fbG9naW5fcmVtZW1iZXJtZVwiXScpLmlzKCc6Y2hlY2tlZCcpO1xuICAgICAgICB2YXIgZm9ybVVzZXJuYW1lID0gZm9ybVJlbWVtYmVyTWUgPyAnPScgKyAkYWNjb3VudExvZ2luRm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cImR3ZnJtX2xvZ2luX3VzZXJuYW1lXCJdJykudmFsKCkgOiAnJztcbiAgICAgICAgdmFyIGZvcm1VcmwgPSAkYWNjb3VudExvZ2luRm9ybS5hdHRyKCdhY3Rpb24nKTtcblxuICAgICAgICAvLyBDbGVhciBwcmV2aW91cyBmb3JtIGVycm9yc1xuICAgICAgICAkYWNjb3VudExvZ2luRm9ybS5maW5kKCdpbnB1dCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgICAgICAkYWNjb3VudExvZ2luRm9ybS5maW5kKCcubG9naW4tZGlhbG9nLWVycm9yIHNwYW4nKS5hZGRDbGFzcygnZC1ub25lJyk7XG5cbiAgICAgICAgdmFyIGlzVmFsaWRGb3JtID0gdmFsaWRhdGVMb2dpbkZvcm0oJGFjY291bnRMb2dpbkZvcm0sIFsnZW1haWwnLCdwYXNzd29yZCddKTtcbiAgICAgICAgdmFyIGlzTG9naW5EaWFsb2cgPSBmb3JtVXJsLmluZGV4T2YoJ2xvZ2luRGlhbG9nJykgPj0gMDtcbiAgICAgICAgdmFyIGZvcm1EYXRhID0gJGFjY291bnRMb2dpbkZvcm0uc2VyaWFsaXplKCk7XG5cbiAgICAgICAgaWYgKCFpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAkKCdbZGF0YS1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1sb2dpbi1zb3VyY2UnLCAnb3JpZ2luYWwnKTsgLy8gRm9yIHJlcG9ydGluZyBcbiAgICAgICAgfVxuXHRcdFxuICAgICAgICAvLyBVc2luZyBBSkFYIGluc3RlYWQgb2YgZGVmYXVsdCBIVE1MIGJ1dHRvbiBzdWJtaXQgZm9yIGxvZ2luIHBhZ2UgYW5kIGRpYWxvZ1xuICAgICAgICBpZiAoaXNWYWxpZEZvcm0pIHsgICAgICAgIFxuICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIHVybDogZm9ybVVybCxcbiAgICAgICAgICAgICAgICBkYXRhOiBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdyZXN1bHQnIGluIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJlc3VsdCA9PSAnZXJyb3InKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNMb2dpbkRpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYWNjb3VudExvZ2luRm9ybS5maW5kKCcubG9naW4tZGlhbG9nLWVycm9yIC5pbnZhbGlkLWxvZ2luJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gZGF0YS5sb2dpbkRpYWxvZ0NvbnRpbnVlVXJsICsgJz9yZXRyeSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLnJlc3VsdCA9PSAnc3VjY2VzcycgfHwgZGF0YS5yZXN1bHQgPT0gJ2NvbXBsZXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3ZhbGlkYXRlQ3VzdG9tZXInIHByb3BlcnR5IG9ubHkgcmV0dXJucyBpbiB0aGUgZGF0YSBpZiB0aGlzIGlzIGEgZGlhbG9nLiBPdGhlcndpc2UsIHJld2FyZHMgdmFsaWRhdGlvbiBoYXBwZW5zIHRocm91Z2ggdGhlIFVSTCB1c2luZyBsb2dpbkRpYWxvZ0NvbnRpbnVlVXJsLiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGlzIGEgcmV3YXJkcyBjdXN0b21lciwgYW5kIHRoZSBjdXNvbXRlciBhY2NvdW50IHJlcXVpcmVzIHZhbGlkYXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ3ZhbGlkYXRlQ3VzdG9tZXInIGluIGRhdGEgJiYgZGF0YS52YWxpZGF0ZUN1c3RvbWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpbkNvcmRpYWxBY2NvdW50RXZlbnQoJGFjY291bnRMb2dpbkZvcm0sIGlzTG9naW5EaWFsb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdBdHRyaWJ1dGVzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLW1vZGFsLXR5cGVcIjogXCJsb2dpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWNvbnRpbnVlLXVybFwiOiAnbG9naW5EaWFsb2dDb250aW51ZVVybCcgaW4gZGF0YSA/IGRhdGEubG9naW5EaWFsb2dDb250aW51ZVVybCA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWZpcnN0LW5hbWVcIjogJ2N1c3RvbWVyRmlyc3ROYW1lJyBpbiBkYXRhID8gZGF0YS5jdXN0b21lckZpcnN0TmFtZSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLXN0b3JlLW51bWJlclwiOiAnc3RvcmVGcm9tUHJvZmlsZScgaW4gZGF0YSA/IGRhdGEuc3RvcmVGcm9tUHJvZmlsZSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWNhcnQtcXVhbnRpdHlcIjogJ2NhcnRRdWFudGl0eScgaW4gZGF0YSA/IGRhdGEuY2FydFF1YW50aXR5IDogJydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuaHRtbChkYXRhLnZhbGlkYXRlQ3VzdG9tZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuYWRkQ2xhc3MoJ3ZhbGlkYXRlLWN1c3RvbWVyLXNob3cgZm9sbG93LWFjY291bnQtZGlhbG9nLXBhdGgnKS5hdHRyKG5ld0F0dHJpYnV0ZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBEbyB0aGlzIGluIHR3byBwbGFjZXM6IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoMSkgZm9yIGxvZ2luLWRpYWxvZyBoZXJlIGJlY2F1c2UgdGhlIGVsZW1lbnQgaXMgb25seSBsb2FkZWQgaW50byBwYWdlIHZpYSBBSkFYLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKDIpIGluaXQgb2YgcGFnZSBsb2FkIGZvciByZWd1bGFyIHJld2FyZHMgdmVyaWZpY2F0aW9uIHBhZ2VzIHRocm91Z2ggbm9ybWFsIGxvZ2luIGZsb3dcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdEFkZFJ1bGVzRm9yQ29kZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZSB0aGUgY29yZGlhbCBsb2dpbiBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9naW5Db3JkaWFsQWNjb3VudEV2ZW50KCRhY2NvdW50TG9naW5Gb3JtLCBpc0xvZ2luRGlhbG9nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFja0xvZ2luQWN0aW9ucygncGFzc3dvcmQnLCAkKCdbZGF0YS1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1sb2dpbi1zb3VyY2UnKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIGZvbGxvdy11cCBhY3Rpb25zIGFjY29yZGluZ2x5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Bvc3RBamF4QXV0aGVudGljYXRpb25BY3Rpb25zLkluaXRpYWxpemUnLCB7IHJlc3VsdHM6IGRhdGEsIGlzQWNjb3VudERpYWxvZzogaXNMb2dpbkRpYWxvZywgZGlzcGxheU1lc3NhZ2U6ICdsb2dpbicgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ0xvZ2luIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNMb2dpbkRpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ0xvZ2luIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmLnNwbGl0KCc/JylbMF0rJz9yZXRyeSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0xvZ2luRGlhbG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWYuc3BsaXQoJz8nKVswXSsnP3JldHJ5JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9ICBcblx0fSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLm9wYy1sb2dpbi1zdWJtaXQtYnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyICRvcGNMb2dpbkJ1dHRvbiA9ICQodGhpcyk7XG4gICAgICAgIHZhciAkb3BjTG9naW5Gb3JtID0gJG9wY0xvZ2luQnV0dG9uLmNsb3Nlc3QoJ2Zvcm0ub3BjLWxvZ2luJyk7XG4gICAgICAgIHZhciBub3RpZmljYXRpb25TZWxlY3RvciA9ICQoJy5sb2dpbi1ub3RpZmljYXRpb24nKTtcblxuICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXG4gICAgICAgICQoJ1tkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScsICdjYXJ0Jyk7IC8vIEZvciByZXBvcnRpbmdcbiAgICAgICAgJG9wY0xvZ2luRm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcbiAgICAgICAgY2xlYXJOb3RpZmljYXRpb24obm90aWZpY2F0aW9uU2VsZWN0b3IpO1xuICAgICAgICB1cGRhdGVDdXN0b21lckRldGFpbHMoJG9wY0xvZ2luRm9ybSwgJCh0aGlzKS5hdHRyKCduYW1lJykpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlICE9ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCd2aWV3TW9kZWwnIGluIHJlc3BvbnNlICYmICdDdXN0b21lcicgaW4gcmVzcG9uc2Uudmlld01vZGVsICYmIHJlc3BvbnNlLnZpZXdNb2RlbC5DdXN0b21lci5hdXRoZW50aWNhdGVkID09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBDdXN0b21lci5hdXRoZW50aWNhdGVkID0gcmVzcG9uc2Uudmlld01vZGVsLkN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQ7XG4gICAgICAgICAgICAgICAgb3BjTG9nZ2VkSW5DdXN0b21lckFkZHJlc3NlcyA9IHJlc3BvbnNlLnZpZXdNb2RlbC5BZGRyZXNzZXM7XG4gICAgICAgICAgICAgICAgaWYgKCd2YWxpZGF0ZUN1c3RvbWVyJyBpbiByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMucmVuZGVyRGlhbG9nVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhlcnJvclRocm93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wY0xvZ2luVGFnZ2luZygkb3BjTG9naW5Gb3JtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9wY0xvZ2luQ29udGludWVVcmwgPSAkKCcjY2FydC1pdGVtcy1mb3JtJykubGVuZ3RoID8gVXJscy5vbmVQYWdlIDogVXJscy5hY2NvdW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWw6IGRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nQ2xhc3M6ICdsb2dpbi1kaWFsb2cnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiA2MDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5hZGRDbGFzcygnZGlhbG9nLW9wZW4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5zY3JvbGxUb3AoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dpbkNvcmRpYWxBY2NvdW50RXZlbnQoJG9wY0xvZ2luRm9ybSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnVpLWRpYWxvZy5sb2dpbi1kaWFsb2cnKS5jc3MoJ2hlaWdodCcsICc0MzBweCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcudWktZGlhbG9nLmxvZ2luLWRpYWxvZyAubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lcicpLmNzcygnbWFyZ2luJywgJzAgLThweCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXBhc3Njb2RlLWNvbnRhaW5lciwgLmxvZ2luLWRpYWxvZy1yZWdpc3Rlci1jb250YWluZXInKS5oaWRlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0F0dHJpYnV0ZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtbW9kYWwtdHlwZVwiOiBcImxvZ2luXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtY29udGludWUtdXJsXCI6IG9wY0xvZ2luQ29udGludWVVcmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtZmlyc3QtbmFtZVwiOiAnY3VzdG9tZXJGaXJzdE5hbWUnIGluIHJlc3BvbnNlID8gcmVzcG9uc2UuY3VzdG9tZXJGaXJzdE5hbWUgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1zdG9yZS1udW1iZXJcIjogJ3N0b3JlRnJvbVByb2ZpbGUnIGluIHJlc3BvbnNlID8gcmVzcG9uc2Uuc3RvcmVGcm9tUHJvZmlsZSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWNhcnQtcXVhbnRpdHlcIjogJ2NhcnRRdWFudGl0eScgaW4gcmVzcG9uc2UgPyByZXNwb25zZS5jYXJ0UXVhbnRpdHkgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1vcGMtbG9naW5cIjogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctdmFsaWRhdGUtY3VzdG9tZXInKS5odG1sKHJlc3BvbnNlLnZhbGlkYXRlQ3VzdG9tZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuYWRkQ2xhc3MoJ3ZhbGlkYXRlLWN1c3RvbWVyLXNob3cgZm9sbG93LWFjY291bnQtZGlhbG9nLXBhdGgnKS5hdHRyKG5ld0F0dHJpYnV0ZXMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRBZGRSdWxlc0ZvckNvZGVJbnB1dCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkcGFzc3dvcmRSZXNldCA9ICQodGhpcykuZmluZCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXIgI3Bhc3N3b3JkLXJlc2V0LWJ1dHRvbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFzc3dvcmRSZXNldC5hdHRyKCdkYXRhLXRhcmdldCcsICRwYXNzd29yZFJlc2V0LmF0dHIoJ2RhdGEtdGFyZ2V0JykgKyAnP2xvZ2luRGlhbG9nPXRydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICBvcGNMb2dpblRhZ2dpbmcoJG9wY0xvZ2luRm9ybSk7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNrTG9naW5BY3Rpb25zKCdwYXNzd29yZCcsICQoJ1tkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScpKTtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IFVybHMub25lUGFnZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgJCgnLm9wYy1sb2dpbiAuZmllbGQtd3JhcHBlciBpbnB1dCcpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICAgICAgICAgIHNob3dOb3RpZmljYXRpb24oUmVzb3VyY2VzLlBXRF9FTUFJTF9FUlJPUiwgJy5sb2dpbi1ub3RpZmljYXRpb24nLCAnZXJyb3InKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTsgICAgXG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI290cC10b2dnbGUtYnV0dG9uJywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGlzQWNjb3VudERpYWxvZyA9ICQodGhpcykuY2xvc2VzdCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXInKS5sZW5ndGg7XG4gICAgICAgIHZhciBpc0NoZWNrb3V0TG9naW4gPSAkKHRoaXMpLmhhc0NsYXNzKCdvcGMtcGFzc3dvcmRsZXNzLWxvZ2luJyk7XG4gICAgICAgIGlmIChpc0FjY291bnREaWFsb2cpIHtcbiAgICAgICAgICAgIHBhc3N3b3JkbGVzc0xvZ2luU2VxdWVuY2UoZmFsc2UpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQ2hlY2tvdXRMb2dpbikge1xuICAgICAgICAgICAgbG9naW5EaWFsb2cuc2hvdyhmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBwYXNzd29yZGxlc3NMb2dpblNlcXVlbmNlKHRydWUpO1xuICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyIFtkYXRhLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLWxvZ2luLXNvdXJjZScsICdjYXJ0LW1vZGFsJyk7IFxuICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyIFtkYXRhLXBhc3N3b3JkbGVzcy1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1wYXNzd29yZGxlc3MtbG9naW4tc291cmNlJywgJ2NhcnQtbW9kYWwnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLnBhc3N3b3JkbGVzc0xvZ2luO1xuICAgICAgICB9XG5cdH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNvdHBDYW5jZWxCdXR0b24nLCBmdW5jdGlvbihlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgaXNBY2NvdW50RGlhbG9nID0gJCh0aGlzKS5jbG9zZXN0KCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lcicpLmxlbmd0aDtcbiAgICAgICAgdmFyIGlzQ2hlY2tvdXQgPSAkKCdbZGF0YS1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1sb2dpbi1zb3VyY2UnKSAhPSB1bmRlZmluZWQgJiYgJCgnW2RhdGEtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtbG9naW4tc291cmNlJykuaW5kZXhPZignY2FydCcpID4gLTE7XG4gICAgICAgIGlmIChpc0FjY291bnREaWFsb2cpIHtcbiAgICAgICAgICAgIGlmIChpc0NoZWNrb3V0KSB7XG4gICAgICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciAkb3RwSGVhZGVyID0gJCgnZm9ybSNkd2ZybV9vdHBsb2dpbiAucHJvZmlsZS1oZWFkZXInKTtcbiAgICAgICAgICAgICAgICB2YXIgJG90cEluc3RydWN0aW9ucyA9ICQoJ2Zvcm0jZHdmcm1fb3RwbG9naW4gLm90cC1pbnN0cnVjdGlvbnMnKTtcbiAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXNpZ25pbi1jb250YWluZXIsIC5sb2dpbi1kaWFsb2ctcmVnaXN0ZXItbWVzc2FnZSwgI290cC10b2dnbGUtYnV0dG9uLCAjdG9nZ2xlLXJlZ2lzdHJhdGlvbicpLnNob3coKTtcbiAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXBhc3Njb2RlLWNvbnRhaW5lcicpLnJlbW92ZUNsYXNzKCdwYXNzY29kZS1mb3JtLXNob3cnKTtcbiAgICAgICAgICAgICAgICAkb3RwSGVhZGVyLmh0bWwoJG90cEhlYWRlci5hdHRyKCdkYXRhLWVtYWlsJykpO1xuICAgICAgICAgICAgICAgICRvdHBJbnN0cnVjdGlvbnMuaHRtbCgkb3RwSW5zdHJ1Y3Rpb25zLmF0dHIoJ2RhdGEtZW1haWwnKSk7XG4gICAgICAgICAgICAgICAgJCgnI2R3ZnJtX290cGxvZ2luX3VzZXJuYW1lJykuc2hvdygpOyAvLyBkb24ndCBjbGVhciBwcmV2aW91cyBlbWFpbCB2YWx1ZSBmb3IgZm9ybSB2YWxpZGF0aW9uXG4gICAgICAgICAgICAgICAgJCgnI290cENvbnRpbnVlQnV0dG9uJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICQoJyNkd2ZybV9vdHBsb2dpbl9wYXNzY29kZScpLmhpZGUoKS52YWwoJycpOyAvLyBjbGVhciBwcmV2aW91cyBwYXNzY29kZSB2YWx1ZSBmb3IgZm9ybVxuICAgICAgICAgICAgICAgICQoJyNvdHBWZXJpZnlCdXR0b24nKS5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuYWNjb3VudDtcbiAgICAgICAgfVxuXHR9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjb3RwQ29udGludWVCdXR0b24sIC5vdHAtcmVzZW5kLWNvZGUnLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgZXJyb3JNZXNzYWdlID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Tb3JyeSwgd2Ugd2VyZSB1bmFibGUgdG8gc2VuZCBhIG9uZS10aW1lIHBhc3Njb2RlIGF0IHRoaXMgdGltZS4gUGxlYXNlIGxvZ2luIHVzaW5nIHlvdXIgY3JlZGVudGlhbHMgaW5zdGVhZC48L3A+JztcbiAgICAgICAgdmFyICRvdHBDb250aW51ZUJ1dHRvbiA9ICQodGhpcyk7XG4gICAgICAgIHZhciAkb3RwTG9naW5Gb3JtID0gJG90cENvbnRpbnVlQnV0dG9uLmNsb3Nlc3QoJ2Zvcm0jZHdmcm1fb3RwbG9naW4nKTtcbiAgICAgICAgdmFyIGlzUmVzZW5kID0gJCh0aGlzKS5oYXNDbGFzcygnb3RwLXJlc2VuZC1jb2RlJyk7XG5cbiAgICAgICAgLy8gQ2xlYXIgcHJldmlvdXMgZm9ybSBlcnJvcnNcbiAgICAgICAgJG90cExvZ2luRm9ybS5maW5kKCdpbnB1dCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgICAgICAkb3RwTG9naW5Gb3JtLmZpbmQoJy5sb2dpbi1kaWFsb2ctZXJyb3Igc3BhbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblxuICAgICAgICB2YXIgaXNWYWxpZEZvcm0gPSB2YWxpZGF0ZUxvZ2luRm9ybSgkb3RwTG9naW5Gb3JtLCBbJ2VtYWlsJ10pO1xuICAgICAgICB2YXIgZW1haWxBZGRyZXNzID0gJG90cExvZ2luRm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cIl91c2VybmFtZVwiXScpLnZhbCgpO1xuXG4gICAgICAgICQoJy5sb2dpbi1kaWFsb2ctcGFzc2NvZGUtY29udGFpbmVyLCAub3RwLWxvZ2luLWZvcm0tY29udGFpbmVyJykuYXR0cignZGF0YS1lbWFpbCcsIGVtYWlsQWRkcmVzcyk7XG5cbiAgICAgICAgLy8gVXNpbmcgQUpBWCBpbnN0ZWFkIG9mIGRlZmF1bHQgSFRNTCBidXR0b24gc3VibWl0IGZvciBsb2dpbiBwYWdlIGFuZCBkaWFsb2dcbiAgICAgICAgaWYgKGlzVmFsaWRGb3JtKSB7XG4gICAgICAgICAgICBpZiAoaXNSZXNlbmQpIHtcbiAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpOyBcbiAgICAgICAgICAgIH0gICAgIFxuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgdXJsOiBVcmxzLmdldFBhc3Njb2RlLFxuICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgZW1haWxBZGRyZXNzOiBlbWFpbEFkZHJlc3NcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycgJiYgZGF0YS5sZW5ndGggPT0gMCkgeyBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1Jlc2VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7IFxuICAgICAgICAgICAgICAgICAgICAgICAgfSBcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Bhc3N3b3JkbGVzcyBMb2dpbiAtIEVycm9yJywgZXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1Jlc2VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7IFxuICAgICAgICAgICAgICAgICAgICAgICAgfSAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHRleHRTdGF0dXMgJiYgdGV4dFN0YXR1cyAhPSAnc3VjY2VzcycpIHx8IChkYXRhICYmICdzdGF0dXMnIGluIGRhdGEgJiYgZGF0YS5zdGF0dXMgPT0gJ0VSUk9SJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdQYXNzd29yZGxlc3MgTG9naW4gLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiAnc3RhdHVzJyBpbiBkYXRhICYmIChkYXRhLnN0YXR1cyA9PSAnT0snIHx8ICBkYXRhLnN0YXR1cyA9PSAnTk9UX0ZPVU5EJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkb3RwTG9naW5Gb3JtLmF0dHIoJ2RhdGEtdXNpZCcsIGRhdGEudXNpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRvdHBIZWFkZXIgPSAkb3RwTG9naW5Gb3JtLmZpbmQoJy5wcm9maWxlLWhlYWRlcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkb3RwSW5zdHJ1Y3Rpb25zID0gJG90cExvZ2luRm9ybS5maW5kKCcub3RwLWluc3RydWN0aW9ucycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvdHBIZWFkZXIuaHRtbCgkb3RwSGVhZGVyLmF0dHIoJ2RhdGEtdmVyaWZ5JykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvdHBJbnN0cnVjdGlvbnMuaHRtbCgkb3RwSW5zdHJ1Y3Rpb25zLmF0dHIoJ2RhdGEtdmVyaWZ5JykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRvdHBJbnN0cnVjdGlvbnMuYXBwZW5kKCc8c3Bhbj4nK2VtYWlsQWRkcmVzcysnPC9zcGFuPicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5vdHAtZW1haWwtZmllbGQtY29udGFpbmVyLCAjb3RwQ29udGludWVCdXR0b24nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLm90cC1wYXNzY29kZS1maWVsZC1jb250YWluZXInKS5jc3MoJ2Rpc3BsYXknLCAnZmxleCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJyNkd2ZybV9vdHBsb2dpbl9wYXNzY29kZScpLnNob3coKS52YWwoJycpLnJlbW92ZUF0dHIoJ3BsYWNlaG9sZGVyJykuYXR0cignaW5wdXRtb2RlJywnbnVtZXJpYycpOyAvLyBjbGVhciBwcmV2aW91cyBwYXNzY29kZSB2YWx1ZSBmcm9tIGZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcjb3RwVmVyaWZ5QnV0dG9uLCAub3RwLXJlc2VuZC1jb2RlLWNvbnRhaW5lcicpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gICAgXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUGFzc3dvcmRsZXNzIExvZ2luIC0gRXJyb3InLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI290cFZlcmlmeUJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPlNvcnJ5LCB3ZSB3ZXJlIHVuYWJsZSB0byBzZW5kIGEgcGFzc2NvZGUgYXQgdGhpcyB0aW1lLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuICAgICAgICB2YXIgJG90cFZlcmlmeUJ1dHRvbiA9ICQodGhpcyk7XG4gICAgICAgIHZhciAkb3RwTG9naW5Gb3JtID0gJG90cFZlcmlmeUJ1dHRvbi5jbG9zZXN0KCdmb3JtI2R3ZnJtX290cGxvZ2luJyk7XG4gICAgICAgIHZhciBmb3JtVXJsID0gJG90cExvZ2luRm9ybS5hdHRyKCdhY3Rpb24nKTtcblxuICAgICAgICAvLyBDbGVhciBwcmV2aW91cyBmb3JtIGVycm9yc1xuICAgICAgICAkb3RwTG9naW5Gb3JtLmZpbmQoJ2lucHV0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICRvdHBMb2dpbkZvcm0uZmluZCgnLmxvZ2luLWRpYWxvZy1lcnJvciBzcGFuJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXG4gICAgICAgIHZhciBpc0xvZ2luRGlhbG9nID0gZm9ybVVybC5pbmRleE9mKCdsb2dpbkRpYWxvZycpID49IDA7XG4gICAgICAgIHZhciBpc1ZhbGlkRm9ybSA9IHZhbGlkYXRlTG9naW5Gb3JtKCRvdHBMb2dpbkZvcm0sIFsnZW1haWwnLCdwYXNzY29kZSddKTtcbiAgICAgICAgdmFyIGZvcm1EYXRhID0gJG90cExvZ2luRm9ybS5zZXJpYWxpemUoKTtcbiAgICAgICAgZm9ybURhdGEgKz0gJyZ1c2lkPScgKyAkb3RwTG9naW5Gb3JtLmF0dHIoJ2RhdGEtdXNpZCcpO1xuICAgICAgICBmb3JtRGF0YSArPSAnJicgKyAkb3RwVmVyaWZ5QnV0dG9uLmF0dHIoJ25hbWUnKSArICc9JyArICRvdHBWZXJpZnlCdXR0b24uYXR0cignbmFtZScpO1xuXG4gICAgICAgIC8vIFVzaW5nIEFKQVggaW5zdGVhZCBvZiBkZWZhdWx0IEhUTUwgYnV0dG9uIHN1Ym1pdCBmb3IgbG9naW4gcGFnZSBhbmQgZGlhbG9nXG4gICAgICAgIGlmIChpc1ZhbGlkRm9ybSkgeyAgIFxuICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTsgIFxuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgdXJsOiBmb3JtVXJsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGZvcm1EYXRhLFxuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgZGF0YS5zdGF0dXMgIT0gJ0VSUk9SJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3ZhbGlkYXRlQ3VzdG9tZXInIHByb3BlcnR5IG9ubHkgcmV0dXJucyBpbiB0aGUgZGF0YSBpZiB0aGlzIGlzIGEgZGlhbG9nLiBPdGhlcndpc2UsIHJld2FyZHMgdmFsaWRhdGlvbiBoYXBwZW5zIHRocm91Z2ggdGhlIFVSTCB1c2luZyBsb2dpbkRpYWxvZ0NvbnRpbnVlVXJsLiBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYSByZXdhcmRzIGN1c3RvbWVyLCBhbmQgdGhlIGN1c29tdGVyIGFjY291bnQgcmVxdWlyZXMgdmFsaWRhdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCd2YWxpZGF0ZUN1c3RvbWVyJyBpbiBkYXRhICYmIGRhdGEudmFsaWRhdGVDdXN0b21lcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2luQ29yZGlhbEFjY291bnRFdmVudCgkb3RwTG9naW5Gb3JtLCBpc0xvZ2luRGlhbG9nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0F0dHJpYnV0ZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1tb2RhbC10eXBlXCI6IFwibG9naW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWNvbnRpbnVlLXVybFwiOiAnbG9naW5EaWFsb2dDb250aW51ZVVybCcgaW4gZGF0YSA/IGRhdGEubG9naW5EaWFsb2dDb250aW51ZVVybCA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRhdGEtZmlyc3QtbmFtZVwiOiAnY3VzdG9tZXJGaXJzdE5hbWUnIGluIGRhdGEgPyBkYXRhLmN1c3RvbWVyRmlyc3ROYW1lIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1zdG9yZS1udW1iZXJcIjogJ3N0b3JlRnJvbVByb2ZpbGUnIGluIGRhdGEgPyBkYXRhLnN0b3JlRnJvbVByb2ZpbGUgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkYXRhLWNhcnQtcXVhbnRpdHlcIjogJ2NhcnRRdWFudGl0eScgaW4gZGF0YSA/IGRhdGEuY2FydFF1YW50aXR5IDogJydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lciwgLm90cC1sb2dpbi1mb3JtLWNvbnRhaW5lcicpLmh0bWwoZGF0YS52YWxpZGF0ZUN1c3RvbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyLCAub3RwLWxvZ2luLWZvcm0tY29udGFpbmVyJykuYWRkQ2xhc3MoJ3ZhbGlkYXRlLWN1c3RvbWVyLXNob3cgZm9sbG93LWFjY291bnQtZGlhbG9nLXBhdGgnKS5hdHRyKG5ld0F0dHJpYnV0ZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIHRoZSBjb3JkaWFsIGxvZ2luIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9naW5Db3JkaWFsQWNjb3VudEV2ZW50KCRvdHBMb2dpbkZvcm0sIGlzTG9naW5EaWFsb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFja0xvZ2luQWN0aW9ucygncGFzc3dvcmRsZXNzJywgJCgnW2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLXBhc3N3b3JkbGVzcy1sb2dpbi1zb3VyY2UnKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoaXMgdmFsdWUgdG8gUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZSBmb3IgdGhlIGlzQWNjb3VudERpYWxvZyBkdWUgdG8gc2NvcGUgb2YgQk9PVC02MTAwLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBub3QgdXNpbmcgdGhpcyB0aWNrZXQgdG8gcHJldmVudCBjYXJ0IHJlZnJlc2ggZm9yIG1vZGFsLiBXaWxsIG5lZWQgYWRkaXRpb25hbCB0aWNrZXQgd2l0aCBzY29wZSB0byBjaGFuZ2UgY2FydCBiZWhhdmlvci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXNDYXJ0UGFzc3dvcmRsZXNzID0gJCgnW2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZV0nKS5hdHRyKCdkYXRhLXBhc3N3b3JkbGVzcy1sb2dpbi1zb3VyY2UnKSA9PSAnY2FydC1tb2RhbCcgPyBmYWxzZSA6IGlzTG9naW5EaWFsb2c7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgZm9sbG93LXVwIGFjdGlvbnMgYWNjb3JkaW5nbHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplJywgeyByZXN1bHRzOiBkYXRhLCBpc0FjY291bnREaWFsb2c6IGlzQ2FydFBhc3N3b3JkbGVzcywgZGlzcGxheU1lc3NhZ2U6ICdsb2dpbicgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9ICAgIFxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yc0ZvdW5kO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEudmFsaWRhdGlvbkVycm9ycykge1xuXHRcdFx0XHRcdFx0XHRlcnJvcnNGb3VuZCA9IEpTT04ucGFyc2UoZGF0YS52YWxpZGF0aW9uRXJyb3JzKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChlcnJvcnNGb3VuZCAmJiBPYmplY3Qua2V5cyhlcnJvcnNGb3VuZCkubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRmb3IgKHZhciBmaWVsZE5hbWUgaW4gZXJyb3JzRm91bmQpIHtcblx0XHRcdFx0XHRcdFx0XHQkKGVycm9yc0ZvdW5kW2ZpZWxkTmFtZV0pLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5yZXNwb25zZURhdGEgJiYgZGF0YS5yZXNwb25zZURhdGEuRXJyb3JDb2RlID09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcuaW52YWxpZC13cm9uZy1wYXNzY29kZScpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUGFzc3dvcmRsZXNzIExvZ2luIC0gRXJyb3InLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdQYXNzd29yZGxlc3MgTG9naW4gLSBFcnJvcicsIGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gY2FsbE5leHRDb250cm9sbGVyKHVybCwgY2FsbGJhY2spIHtcbiAgICAkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgfSxcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XHRcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gcmVnaXN0ZXIgb24tY2xpY2sgZXZlbnQgZm9yIHJld2FyZHMgdmFsaWRhdGlvbiA+IHNlbmQgY29kZSBidXR0b25cbiAqIEBub3RlcyBjaGFuZ2VkIHRoZSBidXR0b24ub24oJ2NsaWNrJykgdG8gYSBkb2N1bWVudC5vbignY2xpY2snKSBmb3IgSFRNTCB0aGF0IGlzIGR5bmFtaWNhbGx5IGxvYWRlZCBpbiBwYWdlIHdpdGggQUpBWCB3ZWxsIGFmdGVyIGluaXRpYWwgcGFnZSBsb2FkXG4gKi9cbmZ1bmN0aW9uIGluaXRWYWxpZGF0ZVJld2FyZHNBY2NvdW50KCkge1x0XG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjdmFsaWRhdGUtYWNjb3VudCBidXR0b24jc2VuZC1jb2RlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHZhciAkdmFsaWRhdGVBY2NvdW50Rm9ybSA9ICQoJyN2YWxpZGF0ZS1hY2NvdW50Jyk7XG4gICAgICAgIHZhciBpc0FjY291bnREaWFsb2cgPSAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuaGFzQ2xhc3MoJ2ZvbGxvdy1hY2NvdW50LWRpYWxvZy1wYXRoJyk7XG4gICAgICAgIHZhciBzZW5kVHlwZSA9ICR2YWxpZGF0ZUFjY291bnRGb3JtLmZpbmQoJ2lucHV0W25hbWU9dmFsaWRhdGUtYWNjb3VudF06Y2hlY2tlZCcpLmF0dHIoJ2lkJykuaW5kZXhPZignbm9uZScpID4gLTEgPyAnbm9uZScgOiAnb3RoZXInO1xuXG5cdFx0aWYgKHNlbmRUeXBlID09IFwibm9uZVwiKSB7XHRcdFx0XHRcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHR5cGU6ICdwb3N0Jyxcblx0XHRcdFx0dXJsOiBVcmxzLmNyZWF0ZVJld2FyZHNBY2NvdW50LFxuXHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0Zmlyc3ROYW1lOiAkKCcuY3VzdG9tZXItYWNjb3VudCAuZmlyc3QtbmFtZScpLnRleHQoKSxcblx0XHRcdFx0XHRsYXN0TmFtZTogJCgnLmN1c3RvbWVyLWFjY291bnQgLmxhc3QtbmFtZScpLnRleHQoKSxcblx0XHRcdFx0XHRlbWFpbEFkZHJlc3M6ICQoJy5jdXN0b21lci1hY2NvdW50IC5lbWFpbC1hZGRyZXNzJykudGV4dCgpLFxuXHRcdFx0XHRcdHBob25lTnVtYmVyOiAkKCcuY3VzdG9tZXItYWNjb3VudCAucGhvbmUtbnVtYmVyJykudGV4dCgpLFxuXHRcdFx0XHRcdHppcENvZGU6ICQoJy5jdXN0b21lci1hY2NvdW50IC56aXAtY29kZScpLnRleHQoKVxuXHRcdFx0XHR9KSxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0XHRjb25zb2xlLmxvZygnUmV3YXJkcyBhY2NvdW50IGNyZWF0ZWQuJyk7XG5cdFx0XHRcdFx0aW5pdFZlcmlmaWNhdGlvbkRpcmVjdGlvbigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcdFx0XHRcblx0XHR9IGVsc2Uge1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLnNlbmRWYWxpZGF0aW9uQ29kZSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHQnc2VuZE1ldGhvZCc6ICR2YWxpZGF0ZUFjY291bnRGb3JtLmZpbmQoJ2lucHV0W25hbWU9dmFsaWRhdGUtYWNjb3VudF06Y2hlY2tlZCcpLnZhbCgpLFxuXHRcdFx0XHRcdCdzZW5kVG8nOiAkdmFsaWRhdGVBY2NvdW50Rm9ybS5maW5kKCdpbnB1dFtuYW1lPXZhbGlkYXRlLWFjY291bnRdOmNoZWNrZWQnKS5hdHRyKCdkYXRhLXZhbHVlJylcblx0XHRcdFx0fSxcblx0XHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHR2YXIgcmVzdWx0U3RhdHVzID0gJ3N0YXR1cycgaW4gZGF0YSAmJiBkYXRhLnN0YXR1cyAhPSAncGVuZGluZycgPyB0cnVlIDogJ3Jlc3VsdCcgaW4gZGF0YSAmJiAnc3RhdHVzJyBpbiBkYXRhLnJlc3VsdCAmJiBkYXRhLnJlc3VsdC5zdGF0dXMgIT0gJ3BlbmRpbmcnID8gdHJ1ZSA6IGZhbHNlO1xuXHRcdFx0XHRcdGlmICgoJ2Vycm9yJyBpbiBkYXRhICYmIGRhdGEuZXJyb3IpIHx8IHJlc3VsdFN0YXR1cykge1xuXHRcdFx0XHRcdFx0JCgnLmZ1cnRoZXItaW5mbycpLmhpZGUoKTtcblx0XHRcdFx0XHRcdCQoJy52ZXJpZnktZm9ybScpLmhpZGUoKTtcblx0XHRcdFx0XHRcdCQoJy52ZXJpZnktZmFpbCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0XHR9XHRcblx0XHRcdFx0XHQkKCcuYWNjb3VudC1yZWNvZ25pemVkJykuaGlkZSgpO1xuXHRcdFx0XHRcdGlmIChpc0FjY291bnREaWFsb2cpIHtcblx0XHRcdFx0XHRcdCQoJy52ZXJpZnktYWNjb3VudCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKS5hZGRDbGFzcygndmFsaWRhdGUtY3VzdG9tZXItc2hvdycpO1x0XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoJy52ZXJpZnktYWNjb3VudCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcdFxuXHRcdFx0XHRcdH1cdFx0XHRcblx0XHRcdFx0XHQkKCcuJyArIHNlbmRUeXBlICsgJy1tZXRob2QnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cdFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcjYXR0YWNoLXJld2FyZHMtYnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9ICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+U29ycnksIHdlIHdlcmUgdW5hYmxlIHRvIGZpbmFsaXplIHlvdXIgcmV3YXJkcyBhY2NvdW50IHVwZGF0ZXMuPC9wPic7XG4gICAgICAgIHZhciAkYXR0YWNoUmV3YXJkc0Zvcm0gPSAkKCcjYXR0YWNoLXJld2FyZHMtZm9ybScpO1xuICAgICAgICB2YXIgJHNlbGVjdGVkT3B0aW9uID0gJGF0dGFjaFJld2FyZHNGb3JtLmZpbmQoJ2lucHV0W25hbWU9YXR0YWNoLXJld2FyZHMtb3B0aW9uc106Y2hlY2tlZCcpO1xuICAgICAgICB2YXIgc3VibWl0dGVkRW1haWwgPSAkKCcubG9naW4tZGlhbG9nLXBhc3Njb2RlLWNvbnRhaW5lciwgLm90cC1sb2dpbi1mb3JtLWNvbnRhaW5lcicpLmF0dHIoJ2RhdGEtZW1haWwnKTtcblxuICAgICAgICBpZiAoISRzZWxlY3RlZE9wdGlvbikge1xuICAgICAgICAgICAgJCgnLmF0dGFjaC1yZXdhcmRzLWZvcm0tZXJyb3JzJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogVXJscy5hdHRhY2hSZXdhcmRzLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdKU09OJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICdvcHRpb24nOiAkc2VsZWN0ZWRPcHRpb24udmFsKCksXG4gICAgICAgICAgICAgICAgJ2VtYWlsJzogc3VibWl0dGVkRW1haWxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhICYmIGRhdGEucmVzdWx0ICYmIGRhdGEucmVzdWx0ID09ICdzdWNjZXNzJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnUmV3YXJkcyBhdHRhY2htZW50IGNvbXBsZXRlLicpO1xuICAgICAgICAgICAgICAgICAgICBpbml0VmVyaWZpY2F0aW9uRGlyZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUmV3YXJkcyBBY2NvdW50IC0gRXJyb3InLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhkYXRhLCAnUmV3YXJkcyBBY2NvdW50IC0gRXJyb3InLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gcmVnaXN0ZXIgb24tY2xpY2sgZXZlbnQgZm9yIHJld2FyZHMgdmFsaWRhdGlvbiA+IHZlcmlmeSBjb2RlIGJ1dHRvblxuICovXG5mdW5jdGlvbiBpbml0VmVyaWZ5Q29kZVNlbnQoKSB7ICAgXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJyN2ZXJpZnktY29kZSBidXR0b24jdmVyaWZ5LXVzZXInLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHZhciAkdmVyaWZ5Q29kZUZvcm0gPSAkKCcjdmVyaWZ5LWNvZGUnKTtcbiAgICAgICAgaWYgKCEkdmVyaWZ5Q29kZUZvcm0udmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogVXJscy52ZXJpZnlTdWJtaXR0ZWRDb2RlLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdKU09OJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICdjb2RlJzogICR2ZXJpZnlDb2RlRm9ybS5maW5kKCdpbnB1dFtuYW1lPWVudGVyLWNvZGVdJywgJyN2ZXJpZnktY29kZScpLnZhbCgpLFxuICAgICAgICAgICAgICAgICdzZW5kVG8nOiAkKCcjdmFsaWRhdGUtYWNjb3VudCcpLmZpbmQoJ2lucHV0W25hbWU9dmFsaWRhdGUtYWNjb3VudF06Y2hlY2tlZCcpLmF0dHIoJ2RhdGEtdmFsdWUnKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCgnZXJyb3InIGluIGRhdGEgJiYgZGF0YS5lcnJvcikgfHwgKCdzdGF0dXMnIGluIGRhdGEgJiYgZGF0YS5zdGF0dXMgIT0gJ2FwcHJvdmVkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnLmZ1cnRoZXItaW5mbycpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgJCgnLnZlcmlmeS1mb3JtJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAkKCcudmVyaWZ5LWZhaWwnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHRcdFx0XHRcdFx0XHRcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnUmV3YXJkcyB2ZXJpZmljYXRpb24gY29tcGxldGUuJyk7XG4gICAgICAgICAgICAgICAgICAgIGluaXRWZXJpZmljYXRpb25EaXJlY3Rpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tcGxldGU6IGZ1bmN0aW9uKGRhdGEsIHN0YXR1cywgeGhyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gZGlyZWN0cyB0aGUgcGFnZSBsb2FkIG9yIHRoZSBwYWdlIHJlZHJhdyBhZnRlciByZXdhcmRzIHZlcmlmaWNhdGlvbiBzY3JlZW5cbiAqL1xuZnVuY3Rpb24gaW5pdFZlcmlmaWNhdGlvbkRpcmVjdGlvbigpIHtcbiAgICB2YXIgJHZhbGlkYXRlRGlhbG9nID0gJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpO1xuICAgIHZhciBpc0FjY291bnREaWFsb2cgPSAkKCcubG9naW4tZGlhbG9nLXZhbGlkYXRlLWN1c3RvbWVyJykuaGFzQ2xhc3MoJ2ZvbGxvdy1hY2NvdW50LWRpYWxvZy1wYXRoJyk7XG4gICAgdmFyIGRhdGFNb2RhbFR5cGUsIGRhdGFOZXh0Q29udHJvbGxlclVybCwgZGF0YUNvbnRpbnVlVXJsLCBkYXRhRmlyc3ROYW1lLCBkYXRhU3RvcmUsIGRhdGFDYXJ0UXVhbnRpdHksIGlzT3BjTG9naW47XG5cbiAgICBpZiAoJHZhbGlkYXRlRGlhbG9nLmxlbmd0aCkge1xuICAgICAgICBkYXRhTW9kYWxUeXBlID0gJHZhbGlkYXRlRGlhbG9nLmF0dHIoJ2RhdGEtbW9kYWwtdHlwZScpO1xuICAgICAgICBkYXRhTmV4dENvbnRyb2xsZXJVcmwgPSAkdmFsaWRhdGVEaWFsb2cuYXR0cignZGF0YS1uZXh0LWNvbnRyb2xsZXItdXJsJyk7XG4gICAgICAgIGRhdGFDb250aW51ZVVybCA9ICR2YWxpZGF0ZURpYWxvZy5hdHRyKCdkYXRhLWNvbnRpbnVlLXVybCcpO1xuICAgICAgICBkYXRhRmlyc3ROYW1lID0gJHZhbGlkYXRlRGlhbG9nLmF0dHIoJ2RhdGEtZmlyc3QtbmFtZScpO1xuICAgICAgICBkYXRhU3RvcmUgPSAkdmFsaWRhdGVEaWFsb2cuYXR0cignZGF0YS1zdG9yZS1udW1iZXInKTtcbiAgICAgICAgZGF0YUNhcnRRdWFudGl0eSA9ICR2YWxpZGF0ZURpYWxvZy5hdHRyKCdkYXRhLWNhcnQtcXVhbnRpdHknKTtcbiAgICAgICAgaXNPcGNMb2dpbiA9ICR2YWxpZGF0ZURpYWxvZy5hdHRyKCdkYXRhLW9wYy1sb2dpbicpID09ICd0cnVlJztcblxuICAgICAgICBpZiAoaXNPcGNMb2dpbikge1xuICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5vbmVQYWdlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0FjY291bnREaWFsb2cpIHtcbiAgICAgICAgICAgIGlmIChkYXRhTmV4dENvbnRyb2xsZXJVcmwpIHtcbiAgICAgICAgICAgICAgICBjYWxsTmV4dENvbnRyb2xsZXIoZGF0YU5leHRDb250cm9sbGVyVXJsLCBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgJiYgJ3Jlc3VsdCcgaW4gcmVzcG9uc2UgJiYgKHJlc3BvbnNlLnJlc3VsdCA9PSAnc3VjY2VzcycgfHwgcmVzcG9uc2UucmVzdWx0ID09ICdjb21wbGV0ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5jdXN0b21lckZpcnN0TmFtZSA9IGRhdGFGaXJzdE5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5zdG9yZUZyb21Qcm9maWxlID0gZGF0YVN0b3JlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuY2FydFF1YW50aXR5ID0gZGF0YUNhcnRRdWFudGl0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBmb2xsb3ctdXAgYWN0aW9ucyBhY2NvcmRpbmdseVxuICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScsIHsgcmVzdWx0czogcmVzcG9uc2UsIGlzQWNjb3VudERpYWxvZzogaXNBY2NvdW50RGlhbG9nLCBkaXNwbGF5TWVzc2FnZTogZGF0YU1vZGFsVHlwZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUNvbnRpbnVlVXJsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvY2F0aW9uLmhyZWYgPSBkYXRhQ29udGludWVVcmw7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IFVybHMuYWNjb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBsb2NhdGlvbi5ocmVmID0gVXJscy5hY2NvdW50O1xuICAgIH1cbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gYWRkIHJ1bGVzIHRvIGNvZGUgaW5wdXQgZmllbGRcbiAqL1xuZnVuY3Rpb24gaW5pdEFkZFJ1bGVzRm9yQ29kZUlucHV0KCkge1xuICAgICQoJ2Zvcm0jdmVyaWZ5LWNvZGUnKS52YWxpZGF0ZSgpO1xuICAgICQoJyN2ZXJpZnktY29kZSAjZW50ZXItY29kZScpLnJ1bGVzKCdhZGQnLCB7XG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICBkaWdpdHM6IHRydWUsXG4gICAgICAgIG1pbmxlbmd0aDogNixcbiAgICAgICAgbWVzc2FnZXM6IHtcbiAgICAgICAgICAgIHJlcXVpcmVkOiBSZXNvdXJjZXMuVkFMSURBVEVfQ09ERSxcbiAgICAgICAgICAgIG1pbmxlbmd0aDogUmVzb3VyY2VzLlZBTElEQVRFX0NPREVcbiAgICAgICAgfSxcbiAgICAgICAgbm9ybWFsaXplcjogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAkLnRyaW0odmFsdWUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHJlZ2lzdGVyIG9uLWNsaWNrIGV2ZW50IGZvciByZXdhcmRzIHZhbGlkYXRpb24gPiB2ZXJpZnkgY29kZSA+IHJlc2VuZCBjb2RlIGxpbmtcbiAqL1xuZnVuY3Rpb24gaW5pdFJlc2VuZFZhbGlkYXRpb25Db2RlKCkge1xuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcudmVyaWZ5LWFjY291bnQgYS5yZXNlbmQtY29kZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHRcdFxuICAgICAgICBpZiAoJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpLmhhc0NsYXNzKCdmb2xsb3ctYWNjb3VudC1kaWFsb2ctcGF0aCcpKSB7XG4gICAgICAgICAgICAkKCcudmVyaWZ5LWFjY291bnQsIC5mdXJ0aGVyLWluZm8gc3BhbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcdFxuICAgICAgICAgICAgJCgnLmFjY291bnQtcmVjb2duaXplZCcpLmNzcygnbGVmdCcsJy05OTk5cHgnKS5yZW1vdmVDbGFzcygnaGlkZGVuJykuc2hvdygpLmFkZENsYXNzKCd2YWxpZGF0ZS1jdXN0b21lci1zaG93Jyk7XHRcdFx0XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiByZWdpc3RlciBvbi1jbGljayBldmVudHMgZm9yIHJlc2V0LXBhc3N3b3JkIGZsb3dcbiAqL1xuZnVuY3Rpb24gaW5pdFJlc2V0UGFzc3dvcmRFdmVudHMoKSB7XHRcbiAgICAvLyBTaG93IHJlc2V0IHBhc3N3b3JkIGZvcm1cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJyNwYXNzd29yZC1yZXNldC1idXR0b24nLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgJHJlc2V0UGFzc3dvcmRCdXR0b24gPSAkKHRoaXMpO1xuICAgICAgICB2YXIgcmVzZXREaWFsb2dVcmwgPSAkcmVzZXRQYXNzd29yZEJ1dHRvbi5hdHRyKCdkYXRhLXRhcmdldCcpO1xuICAgICAgICB2YXIgaXNMb2dpbkRpYWxvZyA9IHJlc2V0RGlhbG9nVXJsLmluZGV4T2YoJ2xvZ2luRGlhbG9nJykgPj0gMDtcblxuICAgICAgICBpZiAoaXNMb2dpbkRpYWxvZykge1xuICAgICAgICAgICAgJCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcbiAgICAgICAgICAgIHZhciBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Pb3BzLCBzb21ldGhpbmcgd2VudCB3cm9uZyB3aXRoIFBhc3N3b3JkIFJlc2V0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuXG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgIHVybDogcmVzZXREaWFsb2dVcmwsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyAmJiAncmVzdWx0JyBpbiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5yZXN1bHQgPT0gJ2NvbXBsZXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgcmVjZWl2ZWQgSFRNTCBpbiB0aGUgZGF0YSBmb3IgZGlzcGxheWluZyB0aGUgcmVzZXQgcGFzc3dvcmQgZm9ybSwgdGhlbiBkaXNwbGF5IGl0Li4uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCdyZXNldFBhc3N3b3JkRm9ybScgaW4gZGF0YSAmJiBkYXRhLnJlc2V0UGFzc3dvcmRGb3JtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy5sb2dpbi1kaWFsb2ctcmVzZXQtcGFzc3dvcmQnKS5odG1sKGRhdGEucmVzZXRQYXNzd29yZEZvcm0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLXJlc2V0LXBhc3N3b3JkJykuYWRkQ2xhc3MoJ3Jlc2V0LXBhc3N3b3JkLXNob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy1yZXNldC1wYXNzd29yZCcpLmZpbmQoJyNQYXNzd29yZFJlc2V0Rm9ybScpLmF0dHIoJ2FjdGlvbicsICQoJy5sb2dpbi1kaWFsb2ctcmVzZXQtcGFzc3dvcmQnKS5maW5kKCcjUGFzc3dvcmRSZXNldEZvcm0nKS5hdHRyKCdhY3Rpb24nKSArICc/bG9naW5EaWFsb2c9dHJ1ZScpO1xuXHRcdFx0XHRcdFx0XHRcdHJlbmRlclJlY2FwdGNoYUZvclBhc3N3b3JkUmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGRhdGEsICdSZXNldCBQYXNzd29yZCAtIEVycm9yJywgZGlhbG9nSHRtbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNMb2dpbkRpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNMb2dpbkRpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoU2l0ZVByZWZlcmVuY2VzLlJFU0VUX1BPUFVQX0VOQUJMRUQpIHtcblx0XHRcdGRpYWxvZy5vcGVuKHtcblx0ICAgICAgICAgICAgdXJsOiByZXNldERpYWxvZ1VybCxcblx0ICAgICAgICAgICAgb3B0aW9uczoge1xuXHQgICAgICAgICAgICBcdGRpYWxvZ0NsYXNzOiAncmVzZXRwd2Rwb3B1cCcsXG5cdCAgICAgICAgICAgIFx0d2lkdGg6IDM4NSxcblx0ICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHJlbmRlclJlY2FwdGNoYUZvclBhc3N3b3JkUmVzZXQoKTtcblx0ICAgICAgICAgICAgICAgICAgICAkKFwiLnJlc2V0LXBhc3N3b3JkLWhlYWRpbmctY2xvc2UtYnRuLCAudWktd2lkZ2V0LW92ZXJsYXlcIikub24oJ2NsaWNrJyxmdW5jdGlvbigpe1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAkKFwiYnV0dG9uLnVpLWRpYWxvZy10aXRsZWJhci1jbG9zZVwiKS5jbGljaygpO1xuXHQgICAgICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdFx0XHR9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gcmVzZXREaWFsb2dVcmw7XG4gICAgICAgIH1cblx0fSk7XG5cdFxuICAgIC8vIFN1Ym1pdCByZXNldCBwYXNzd29yZCBmb3JtXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrLlJlc2V0UGFzc3dvcmQnLCAnI3JlcXVlc3QtcGFzc3dvcmQtc2VuZC1idG4sIFtuYW1lJD1cIl9yZXF1ZXN0cGFzc3dvcmRfc2VuZFwiXScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGFzc3dvcmRSZXNldCkge1xuXHRcdFx0cmVzZXRQYXNzd29yZChldmVudCwgJCh0aGlzKSk7XG5cdFx0fVxuXHR9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignQWNjb3VudC5SZXNldFBhc3N3b3JkJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG5cdFx0cmVzZXRQYXNzd29yZChldmVudCwgbnVsbCwgdHJ1ZSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZXNldFBhc3N3b3JkKGV2ZW50LCAkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24sIGlzUmVjYXB0Y2hhRXZlbnQpIHtcblx0aWYgKCEkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24pIHtcblx0XHQkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24gPSAkKCcjcmVxdWVzdC1wYXNzd29yZC1zZW5kLWJ0bicpO1xuXHR9XG5cblx0dmFyICRyZXNldFBhc3N3b3JkU2VuZEZvcm0gPSAkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24uY2xvc2VzdCgnZm9ybSNQYXNzd29yZFJlc2V0Rm9ybScpO1xuXHR2YXIgaXNMb2dpbkRpYWxvZyA9ICRyZXNldFBhc3N3b3JkU2VuZEZvcm0uYXR0cignYWN0aW9uJykuaW5kZXhPZignbG9naW5EaWFsb2cnKSA+PSAwO1xuXG5cdC8vIFRyeSB0byBwcmV2ZW50IHRoZSBmb3JtIHN1Ym1pc3Npb24gYXMgcXVpY2tseSBhcyBwb3NzaWJsZSBiZWZvcmUgZG9pbmcgYWxsIG9mIHRoZSBvdGhlciBsb2dpY1xuXHRpZiAoaXNMb2dpbkRpYWxvZyB8fCAoU2l0ZVByZWZlcmVuY2VzLlJFU0VUX1BPUFVQX0VOQUJMRUQgJiYgZGlhbG9nLmlzQWN0aXZlKCkpKSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0fVxuXG5cdHZhbGlkYXRvci5pbml0KCk7XG5cdHZhciBpc1ZhbGlkRm9ybSA9ICRyZXNldFBhc3N3b3JkU2VuZEZvcm0udmFsaWQoKTtcblxuXHRpZiAoaXNWYWxpZEZvcm0pIHsgICBcblx0XHRpZiAoaXNMb2dpbkRpYWxvZykge1xuXHRcdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0XHRcdHZhciBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Pb3BzLCBzb21ldGhpbmcgd2VudCB3cm9uZyB3aXRoIFBhc3N3b3JkIFJlc2V0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuXHRcdFx0dmFyIGZvcm1EYXRhID0gJHJlc2V0UGFzc3dvcmRTZW5kRm9ybS5zZXJpYWxpemUoKTtcblx0XHRcdGZvcm1EYXRhICs9ICcmJyArICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi5hdHRyKCduYW1lJykgKyAnPScgKyAkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24uYXR0cignbmFtZScpOyAgXG5cblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiAkcmVzZXRQYXNzd29yZFNlbmRGb3JtLmF0dHIoJ2FjdGlvbicpLFxuXHRcdFx0XHRkYXRhOiBmb3JtRGF0YSxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcblx0XHRcdFx0XHRpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdyZXN1bHQnIGluIGRhdGEpIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhLnJlc3VsdCA9PSAnY29tcGxldGUnKSB7XG5cdFx0XHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHRcdC8vIElmIHJlc2V0IHBhc3N3b3JkIGVtYWlsIHdhcyBzZW50LCBzaG93IGNvbmZpcm1hdGlvbiB3aXRoaW4gdGhlIGRpYWxvZ1xuXHRcdFx0XHRcdFx0XHRpZiAoJ3Jlc2V0UGFzc3dvcmRDb25maXJtYXRpb24nIGluIGRhdGEgJiYgZGF0YS5yZXNldFBhc3N3b3JkQ29uZmlybWF0aW9uKSB7XG5cdFx0XHRcdFx0XHRcdFx0JCgnLmxvZ2luLWRpYWxvZy1yZXNldC1wYXNzd29yZCcpLmh0bWwoZGF0YS5yZXNldFBhc3N3b3JkQ29uZmlybWF0aW9uKTtcblx0XHRcdFx0XHRcdFx0XHQkKCcubG9naW4tZGlhbG9nLXJlc2V0LXBhc3N3b3JkJykuYWRkQ2xhc3MoJ3Jlc2V0LXBhc3N3b3JkLXNob3cnKTtcblx0XHRcdFx0XHRcdFx0XHRwYXNzd29yZFJlc2V0Tm9BY2NvdW50Q29yZGlhbEV2ZW50KCcubG9naW4tZGlhbG9nLXJlc2V0LXBhc3N3b3JkJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdFx0XHRlcnJvckhhbmRsaW5nKGRhdGEsICdSZXNldCBQYXNzd29yZCAtIEVycm9yJywgZGlhbG9nSHRtbCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHRcdGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdGlmIChpc0xvZ2luRGlhbG9nKSB7XG5cdFx0XHRcdFx0XHRcdGVycm9ySGFuZGxpbmcoZGF0YSwgJ1Jlc2V0IFBhc3N3b3JkIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gbG9jYXRpb24uaHJlZjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcblx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdGlmICghaXNMb2dpbkRpYWxvZykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIGlmIChTaXRlUHJlZmVyZW5jZXMuUkVTRVRfUE9QVVBfRU5BQkxFRCAmJiBkaWFsb2cuaXNBY3RpdmUoKSkge1xuXHRcdFx0ZGlhbG9nLnN1Ym1pdCgkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24uYXR0cignbmFtZScpLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0cGFzc3dvcmRSZXNldE5vQWNjb3VudENvcmRpYWxFdmVudCgnLnJlc2V0cHdkcG9wdXAnKTtcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSBpZiAoaXNSZWNhcHRjaGFFdmVudCkge1xuXHRcdFx0JHJlc2V0UGFzc3dvcmRTZW5kRm9ybS5hcHBlbmQoJzxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cIicgKyAkcmVzZXRQYXNzd29yZFNlbmRCdXR0b24uYXR0cignbmFtZScpICsgJ1wiIHZhbHVlPVwiJyArICRyZXNldFBhc3N3b3JkU2VuZEJ1dHRvbi52YWwoKSArICdcIi8+Jylcblx0XHRcdCRyZXNldFBhc3N3b3JkU2VuZEZvcm0uc3VibWl0KCk7XG5cdFx0fVxuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdFx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cbiAgICAgICAgaW5pdExvZ2luRXZlbnRzKCk7XG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgKG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JBY2NvdW50TG9naW4gfHwgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBhc3N3b3JkUmVzZXQpKSB7XG5cdFx0XHQkKGRvY3VtZW50KS5vbignUmVjYXB0Y2hhLkxvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdGlmICghbG9hZGVkLlJlY2FwdGNoYSkge1xuXHRcdFx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHRcdFx0XHRcdHJlbmRlclJlY2FwdGNoYUZvckxvZ2luKCk7XG5cdFx0XHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yUGFzc3dvcmRSZXNldCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0cmVjYXB0Y2hhLmluaXRpYWxpemUoKTtcblx0XHRcdGluaXRpYWxpemVSZWNhcHRjaGFGb3JMb2dpbigpO1xuXHRcdFx0cmVuZGVyUmVjYXB0Y2hhRm9yUGFzc3dvcmRSZXNldCgpO1xuXHRcdH1cblx0XHRpbml0TG9naW5CdXR0b25zKCk7XG4gICAgICAgIGluaXRWYWxpZGF0ZVJld2FyZHNBY2NvdW50KCk7XG4gICAgICAgIGluaXRWZXJpZnlDb2RlU2VudCgpO1xuICAgICAgICBpbml0UmVzZW5kVmFsaWRhdGlvbkNvZGUoKTtcbiAgICAgICAgaW5pdEFkZFJ1bGVzRm9yQ29kZUlucHV0KCk7XG4gICAgICAgIGluaXRSZXNldFBhc3N3b3JkRXZlbnRzKCk7XG4gICAgfVxufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBMT0dJTiBNT0RBTFxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBsb2dpbkRpYWxvZyA9IHtcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gU2hvd3MgdGhlIGFjY291bnQtbG9naW4gZm9ybSBpbiBhIGRpYWxvZ1xuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uKGNhbGxiYWNrLCBjb250cm9sbGVyLCBhY3Rpb24sIHByb2R1Y3RJRCwgcGFyYW1zLCBjb21wbGV0ZVVybCkge1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgdXJsOiBVcmxzLmxvZ2luRGlhbG9nLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IGNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgYWN0aW9uOiBhY3Rpb24sXG4gICAgICAgICAgICAgICAgcGFzc2VkUXVlcnlTdHJpbmc6IHBhcmFtc1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGVycm9yVGhyb3duKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0XHRpZiAocmVzcG9uc2UpIHtcblxuICAgICAgICAgICAgICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICAgICAgICAgICAgICBodG1sOiByZXNwb25zZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ2xvZ2luLWRpYWxvZycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnNjcm9sbFRvcCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5maW5kKCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lcicpLmF0dHIoJ2RhdGEtY29udHJvbGxlcicsIGNvbnRyb2xsZXIpLmF0dHIoJ2RhdGEtYWN0aW9uJywgYWN0aW9uKS5hdHRyKCdkYXRhLXByb2R1Y3QnLCBwcm9kdWN0SUQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmZpbmQoJy5sb2dpbi1kaWFsb2ctZm9ybXMtY29udGFpbmVyIGZvcm0nKS5lYWNoKGZ1bmN0aW9uKGksIGZvcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhY3Rpb25VcmwgPSAkKGZvcm0pLmF0dHIoJ2FjdGlvbicpICsgJz9sb2dpbkRpYWxvZz10cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZm9ybSkuYXR0cignYWN0aW9uJywgYWN0aW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuZmluZCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpLmF0dHIoJ2RhdGEtbmV4dC1jb250cm9sbGVyLXVybCcsIGNvbXBsZXRlVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRwYXNzd29yZFJlc2V0ID0gJCh0aGlzKS5maW5kKCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lciAjcGFzc3dvcmQtcmVzZXQtYnV0dG9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYXNzd29yZFJlc2V0LmF0dHIoJ2RhdGEtdGFyZ2V0JywgJHBhc3N3b3JkUmVzZXQuYXR0cignZGF0YS10YXJnZXQnKSArICc/bG9naW5EaWFsb2c9dHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXHRcdFx0fVxuXHRcdH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgYWNjb3VudC1sb2dpbiBkaWFsb2dcbiAgICAgKi9cbiAgICBjbG9zZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsb2dpbkRpYWxvZzsiLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyksXG4gICAgYm9udXNQcm9kdWN0c1ZpZXcgPSByZXF1aXJlKCcuL2JvbnVzLXByb2R1Y3RzLXZpZXcnKTtcblxudmFyIHRpbWVyID0ge1xuICAgIGlkOiBudWxsLFxuICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlkKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuaWQpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuaWQ7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHN0YXJ0OiBmdW5jdGlvbiAoZHVyYXRpb24sIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuaWQgPSBzZXRUaW1lb3V0KGNhbGxiYWNrLCBkdXJhdGlvbik7XG4gICAgfVxufTtcblxudmFyIG1pbmljYXJ0ID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kZWwgPSAkKCcjbWluaS1jYXJ0Jyk7XG4gICAgICAgIHRoaXMuJGNvbnRlbnQgPSB0aGlzLiRlbC5maW5kKCcubWluaS1jYXJ0LWNvbnRlbnQnKTtcblxuICAgICAgICAkKCcubWluaS1jYXJ0LXByb2R1Y3QnKS5lcSgwKS5maW5kKCcubWluaS1jYXJ0LXRvZ2dsZScpLmFkZENsYXNzKCdmYS1jYXJldC1kb3duJyk7XG4gICAgICAgICQoJy5taW5pLWNhcnQtcHJvZHVjdCcpLm5vdCgnOmZpcnN0JykuYWRkQ2xhc3MoJ2NvbGxhcHNlZCcpXG4gICAgICAgICAgICAuZmluZCgnLm1pbmktY2FydC10b2dnbGUnKS5hZGRDbGFzcygnZmEtY2FyZXQtcmlnaHQnKTtcblxuICAgICAgICAkKCcubWluaS1jYXJ0LXRvZ2dsZScpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykudG9nZ2xlQ2xhc3MoJ2ZhLWNhcmV0LWRvd24gZmEtY2FyZXQtcmlnaHQnKTtcbiAgICAgICAgICAgICQodGhpcykuY2xvc2VzdCgnLm1pbmktY2FydC1wcm9kdWN0JykudG9nZ2xlQ2xhc3MoJ2NvbGxhcHNlZCcpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBldmVudHNcbiAgICAgICAgdGhpcy4kZWwuZmluZCgnLm1pbmktY2FydC10b3RhbCcpLm9uKCdtb3VzZWVudGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuJGNvbnRlbnQubm90KCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zbGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgICAgIHRoaXMuJGNvbnRlbnQub24oJ21vdXNlZW50ZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aW1lci5jbGVhcigpO1xuICAgICAgICB9KS5vbignbW91c2VsZWF2ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRpbWVyLmNsZWFyKCk7XG4gICAgICAgICAgICB0aW1lci5zdGFydCgzMCwgdGhpcy5jbG9zZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgXG4gICAgICAgICQoZG9jdW1lbnQpLm9uKCdtaW5pY2FydDp1cGRhdGUnLCBmdW5jdGlvbigpe1xuICAgICAgICBcdC8vaW1wbGVtZW50IG1pbmljYXJ0IHVwZGF0ZSBoZXJlXG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFNob3dzIHRoZSBnaXZlbiBjb250ZW50IGluIHRoZSBtaW5pIGNhcnRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gQSBIVE1MIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IHdoaWNoIHdpbGwgYmUgc2hvd25cbiAgICAgKi9cbiAgICBzaG93OiBmdW5jdGlvbiAoaHRtbCkge1xuICAgICAgICB0aGlzLiRlbC5odG1sKGh0bWwpO1xuICAgICAgICB1dGlsLnNjcm9sbEJyb3dzZXIoMCk7XG4gICAgICAgIHRoaXMuaW5pdCgpO1xuICAgICAgICB0aGlzLnNsaWRlKCk7XG4gICAgICAgIGJvbnVzUHJvZHVjdHNWaWV3LmxvYWRCb251c09wdGlvbigpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFNsaWRlcyBkb3duIGFuZCBzaG93IHRoZSBjb250ZW50cyBvZiB0aGUgbWluaSBjYXJ0XG4gICAgICovXG4gICAgc2xpZGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGltZXIuY2xlYXIoKTtcbiAgICAgICAgLy8gc2hvdyB0aGUgaXRlbVxuICAgICAgICB0aGlzLiRjb250ZW50LnNsaWRlRG93bignc2xvdycpO1xuICAgICAgICAvLyBhZnRlciBhIHRpbWUgb3V0IGF1dG9tYXRpY2FsbHkgY2xvc2UgaXRcbiAgICAgICAgdGltZXIuc3RhcnQoNjAwMCwgdGhpcy5jbG9zZS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBDbG9zZXMgdGhlIG1pbmkgY2FydCB3aXRoIGdpdmVuIGRlbGF5XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbGF5IFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHNcbiAgICAgKi9cbiAgICBjbG9zZTogZnVuY3Rpb24gKGRlbGF5KSB7XG4gICAgICAgIHRpbWVyLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuJGNvbnRlbnQuc2xpZGVVcChkZWxheSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBtaW5pY2FydDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxudmFyIHBhZ2UgPSB7XG4gICAgdGl0bGU6ICcnLFxuICAgIHR5cGU6ICcnLFxuICAgIHBhcmFtczogdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoLnN1YnN0cigxKSksXG4gICAgcmVkaXJlY3Q6IGZ1bmN0aW9uIChuZXdVUkwpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IG5ld1VSTDtcbiAgICAgICAgfSwgMCk7XG4gICAgfSxcbiAgICByZWZyZXNoOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmFzc2lnbih3aW5kb3cubG9jYXRpb24uaHJlZik7XG4gICAgICAgIH0sIDUwMCk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBwYWdlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xuXG52YXIgJGF1dGhlbnRpY2F0aW9uQ29udGFpbmVyID0gJCgnLmF1dGhlbnRpY2F0aW9uLWZvcm0tY29udGFpbmVyJyk7XG52YXIgJGF1dGhlbnRpY2F0aW9uRm9ybSA9ICRhdXRoZW50aWNhdGlvbkNvbnRhaW5lci5jbG9zZXN0KCdmb3JtJyk7XG52YXIgJGF1dGhlbnRpY2F0aW9uRW1haWxBZGRyZXNzID0gJGF1dGhlbnRpY2F0aW9uRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiQXV0aGVudGljYXRpb25FbWFpbEFkZHJlc3NcIl0nKTtcbnZhciBhdXRoZW50aWNhdGlvblZhbGlkYXRvcjtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXHQkYXV0aGVudGljYXRpb25Db250YWluZXIub24oJ2NsaWNrJywgJ2lucHV0W3R5cGU9XCJzdWJtaXRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcblx0ICAgIGF1dGhlbnRpY2F0aW9uVmFsaWRhdG9yID0gJGF1dGhlbnRpY2F0aW9uRm9ybS52YWxpZGF0ZSgpO1xuXHQgICAgJGF1dGhlbnRpY2F0aW9uRW1haWxBZGRyZXNzLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuRW1haWwpO1xuXHQgICAgYXV0aGVudGljYXRpb25WYWxpZGF0b3IuZm9ybSgpO1xuXHQgICAgXG5cdCAgICBpZiAoYXV0aGVudGljYXRpb25WYWxpZGF0b3IudmFsaWQoKSkge1xuXHQgICAgXHQkKCc8aW5wdXQgLz4nKS5hdHRyKCd0eXBlJywgJ2hpZGRlbicpLmF0dHIoJ25hbWUnLCAnaXNNb2JpbGUnKS5hdHRyKCd2YWx1ZScsICQoJ2h0bWwuc2l6ZS1tb2JpbGUnKS5sZW5ndGggPiAwKS5hcHBlbmRUbygkYXV0aGVudGljYXRpb25Gb3JtKTtcblx0ICAgIFx0JGF1dGhlbnRpY2F0aW9uRm9ybS5zdWJtaXQoKTtcblx0ICAgIH1cdFxuICAgIH0pO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nO1xudmFyIEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2c7XG52YXIgQWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyJyk7XG52YXJcdGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpO1xudmFyXHRmaW5kTW9yZVN0b3JlcyA9IHJlcXVpcmUoJy4uL2ZpbmRNb3JlU3RvcmVzJyk7XG52YXJcdG9yZGVyU3RhdHVzRm9ybSA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvT3JkZXJTdGF0dXNGb3JtJyk7XG52YXJcdGdpZnRjZXJ0ID0gcmVxdWlyZSgnLi4vZ2lmdGNlcnQnKTtcbnZhclx0cGFnZSA9IHJlcXVpcmUoJy4uL3BhZ2UnKTtcbnZhciByZWNhcHRjaGEgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL1JlY2FwdGNoYScpO1xudmFyXHR0b29sdGlwID0gcmVxdWlyZSgnLi4vdG9vbHRpcCcpO1xudmFyXHR1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyXHR2YWxpZGF0b3IgPSByZXF1aXJlKCcuLi92YWxpZGF0b3InKTtcblxudmFyIFBheW1lbnRNZXRob2RDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuUGF5bWVudE1ldGhvZHM7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgZGF0YUJ1ZmZlciA9IHt9O1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgZXZlbnRzIG9uIHRoZSBhZGRyZXNzIGZvcm0gKGFwcGx5LCBjYW5jZWwsIGRlbGV0ZSlcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSB3aGljaCB3aWxsIGJlIGluaXRpYWxpemVkXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVBZGRyZXNzRm9ybSgpIHtcbiAgICB2YXIgJGFkZHJlc3NFZGl0Rm9ybSA9ICQoJyNlZGl0LWFkZHJlc3MtZm9ybScpO1xuXHQkYWRkcmVzc0VkaXRGb3JtLm9uKCdjbGljaycsICcuc3VibWl0LXNoaXBwaW5nJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyIGFkZHJlc3NUeXBlID0gJGFkZHJlc3NFZGl0Rm9ybS5hdHRyKCdhZGRyZXNzLXR5cGUnKSA/ICRhZGRyZXNzRWRpdEZvcm0uYXR0cignYWRkcmVzcy10eXBlJykgOiAnc2F2ZWQnO1xuXHRcdHZhciBhZGRyZXNzRGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHQkYWRkcmVzc0VkaXRGb3JtLnN1Ym1pdCgpO1xuXHRcdH1cblx0XHR2YXIgYWRkcmVzc05vdERlbGl2ZXJhYmxlID0gZnVuY3Rpb24gKGFkZHJlc3NWZXJpZnlEYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgYWRkcmVzc1R5cGUsIGFkZHJlc3NWZXJpZnlEYXRhKTtcdFx0XHRcblx0XHR9XG5cdFx0dmFyIGNvdW50cnkgPSAkYWRkcmVzc0VkaXRGb3JtLmZpbmQoJ1tpZCo9XCJfY291bnRyeVwiXScpLnZhbCgpO1xuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCAmJiBjb3VudHJ5LnRvVXBwZXJDYXNlKCkgPT0gJ1VTJyAmJiAkYWRkcmVzc0VkaXRGb3JtLmZpbmQoJy5zdWJtaXQtc2hpcHBpbmcnKS5hdHRyKCd2ZXJpZmllZCcpICE9ICd0cnVlJykge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5WZXJpZnlBZGRyZXNzKCRhZGRyZXNzRWRpdEZvcm0sIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0RlbGl2ZXJhYmxlLCBhZGRyZXNzTm90RGVsaXZlcmFibGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhZGRyZXNzRGVsaXZlcmFibGUoKTtcblx0XHR9XG4gICAgfSk7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0JChkb2N1bWVudCkub24oJ2tleXVwLkFkZHJlc3NBdXRvY29tcGxldGUnLCAnI2VkaXQtYWRkcmVzcy1mb3JtIGlucHV0W3R5cGU9XCJ0ZXh0XCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyIGZvcm1WYWxpZGF0b3IgPSAkYWRkcmVzc0VkaXRGb3JtLnZhbGlkYXRlKCk7XG5cblx0XHRcdGlmIChldmVudC5rZXlDb2RlID09IDggfHwgZXZlbnQua2V5Q29kZSA9PSA0Nikge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKCFmb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICgkdGhpcy5hdHRyKCdpZCcpLmluZGV4T2YoJ19hZGRyZXNzMScpID49IDAgfHwgJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfYWRkcmVzczInKSA+PSAwIHx8ICR0aGlzLmF0dHIoJ2lkJykuaW5kZXhPZignX2NpdHknKSA+PSAwIHx8ICR0aGlzLmF0dHIoJ2lkJykuaW5kZXhPZignX3Bvc3RhbCcpID49IDApKSB7XG5cdFx0XHRcdHZhciBhZGRyZXNzQXV0b2NvbXBsZXRlSGFuZGxlciA9IGZ1bmN0aW9uIChhZGRyZXNzQXV0b2NvbXBsZXRlRGF0YSkge1xuXHRcdFx0XHRcdEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cuaW5pdGlhbGl6ZShvcHRpb25zLCBhZGRyZXNzQXV0b2NvbXBsZXRlRGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdFxuXHRcdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLkF1dG9jb21wbGV0ZUFkZHJlc3MoJGFkZHJlc3NFZGl0Rm9ybSwgJHRoaXMsIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0F1dG9jb21wbGV0ZUhhbmRsZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JHRoaXMucGFyZW50KCkuZmluZCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLm9uKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NBdXRvY29tcGxldGUnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGEpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nKGRhdGEuJGZvcm0sIGRhdGEuQWRkcmVzcyk7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHQkKGRvY3VtZW50KS5vbignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJywgZnVuY3Rpb24gKGV2ZW50LCBhZGRyZXNzRGF0YSkge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coJGFkZHJlc3NFZGl0Rm9ybSwgYWRkcmVzc0RhdGEpO1xuXHRcdFx0JGFkZHJlc3NFZGl0Rm9ybS5zdWJtaXQoKTtcblx0XHR9KTtcblx0fVxuXG4gICAgdmFsaWRhdG9yLmluaXQoKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFRvZ2dsZXMgdGhlIGxpc3Qgb2YgT3JkZXJzXG4gKi9cbmZ1bmN0aW9uIHRvZ2dsZUZ1bGxPcmRlciAoKSB7XG4gICAgJCgnLm9yZGVyLWl0ZW1zJylcbiAgICAgICAgLmZpbmQoJ2xpLmhpZGRlbjpmaXJzdCcpXG4gICAgICAgIC5wcmV2KCdsaScpXG4gICAgICAgIC5hcHBlbmQoJzxhIGNsYXNzPVwidG9nZ2xlXCI+VmlldyBBbGw8L2E+JylcbiAgICAgICAgLmNoaWxkcmVuKCcudG9nZ2xlJylcbiAgICAgICAgLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykucGFyZW50KCkuc2libGluZ3MoJ2xpLmhpZGRlbicpLnNob3coKTtcbiAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGV2ZW50cyBvbiB0aGUgYWRkcmVzcyBmb3JtIChlZGl0LCBjcmVhdGUsIGRlbGV0ZSlcbiAqL1xuZnVuY3Rpb24gaW5pdEFkZHJlc3NFdmVudHMoKSB7XG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtcbiAgICBcdGlmICggJCgnLmFkZHJlc3MtZmllbGQtY29udGFpbmVyIGZvcm0gc2VsZWN0JykubGVuZ3RoID4gMCApIHtcbiAgICAgICAgXHQkKCcuYWRkcmVzcy1maWVsZC1jb250YWluZXIgZm9ybSBzZWxlY3QnKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICAgIFx0XHQkKHRoaXMpLnNlbGVjdG1lbnUoe30pO1xuICAgICAgICBcdH0pO1xuICAgICAgICB9XG4gICAgXHRcbiAgICBcdCQoXCIjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9iZXJld2FyZGVkXCIpLm9uKFwiY2xpY2tcIixmdW5jdGlvbigpe1xuICAgICAgICBcdGlmICggJCh0aGlzKS5pcygnOmNoZWNrZWQnKSApIHtcbiAgICAgICAgXHRcdCQoJy5yZXdhcmRzTnVtYmVyQ29udGFpbmVyJykuc2xpZGVEb3duKCk7XG4gICAgICAgIFx0fSBlbHNlIHtcbiAgICAgICAgXHRcdCQoJy5yZXdhcmRzTnVtYmVyQ29udGFpbmVyJykuc2xpZGVVcCgpO1xuICAgICAgICBcdH1cbiAgICBcdH0pO1xuXG5cdFx0aWYgKCQoJyNlZGl0LWFkZHJlc3MtZm9ybScpLmxlbmd0aCA+IDApIHtcblx0XHRcdGluaXRpYWxpemVBZGRyZXNzRm9ybSgpO1xuXHRcdH1cbiAgICB9KTtcbiAgICBcbiAgICAkKHdpbmRvdykub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICBcdCQoJyNwcmltYXJ5ICNlZGl0LWFkZHJlc3MtZm9ybSBpbnB1dFtuYW1lPVwiZHdmcm1fcHJvZmlsZV9hZGRyZXNzX3JlbW92ZVwiXScpLm9mZignY2xpY2snKTtcbiAgICBcdCQoJyNwcmltYXJ5ICNlZGl0LWFkZHJlc3MtZm9ybSBpbnB1dFtuYW1lPVwiZHdmcm1fcHJvZmlsZV9hZGRyZXNzX3JlbW92ZVwiXScpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcdHZhciAkZm9ybSA9ICQodGhpcykucGFyZW50cygnZm9ybScpO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfQUREUkVTUykpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5kZWxldGVBZGRyZXNzLCB7XG4gICAgICAgICAgICAgICAgICAgIEFkZHJlc3NJRDogJGZvcm0uZmluZCgnI2FkZHJlc3NpZCcpLnZhbCgpLFxuICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6ICdhamF4J1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJ1xuICAgICAgICAgICAgICAgIH0pLmRvbmUoZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuc3RhdHVzLnRvTG93ZXJDYXNlKCkgPT09ICdvaycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHFQYXJhbXMgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHFQYXJhbXMuY2lkICE9PSBudWxsICYmIHFQYXJhbXMuY2lkID09ICdiaWxsaW5nJyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdGxvY2F0aW9uLmhyZWYgPSBVcmxzLnBheW1lbnRzTGlzdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdGxvY2F0aW9uLmhyZWYgPSBVcmxzLmFkZHJlc3Nlc0xpc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEubWVzc2FnZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IFVybHMuYWRkcmVzc2VzTGlzdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgIFx0fSk7XG4gICAgfSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBCaW5kcyB0aGUgZXZlbnRzIG9mIHRoZSBwYXltZW50IG1ldGhvZHMgbGlzdCAoZGVsZXRlIGNhcmQpXG4gKi9cbmZ1bmN0aW9uIGluaXRQYXltZW50RXZlbnRzKCkge1xuXHR2YXIgJGNyZWRpdENhcmRUeXBlU2VsZWN0ID0gJCgnc2VsZWN0W2lkKj1cImNyZWRpdGNhcmRfdHlwZVwiXScpO1xuXHRcblx0Ly8gUmVtb3ZlIGRpYWxvZyBwYXltZW50IGFkZC9lZGl0IGltcGxlbWVudGF0aW9uIHRvIHVzZSBwYWdlIHJlZGlyZWN0IGluc3RlYWRcbiAgICAvKiQoJy5hZGQtY2FyZCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdXJsOiAkKGUudGFyZ2V0KS5hdHRyKCdocmVmJylcbiAgICAgICAgfSk7XG4gICAgfSk7Ki9cblxuXHQkY3JlZGl0Q2FyZFR5cGVTZWxlY3Qub2ZmKCdjaGFuZ2UuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nKS5vbignY2hhbmdlLkNyZWRpdENhcmRUeXBlRGV0ZWN0aW9uJywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBwYXltZW50SW5zdHJ1bWVudFR5cGUgPSAkdGhpcy52YWwoKTtcblx0XHR2YXIgJGFsbGlhbmNlRGF0YUZpZWxkRGVsdGEgPSAkKCdpbnB1dFtuYW1lKj1cIl9vd25lclwiXSwgc2VsZWN0W25hbWUqPVwiX21vbnRoXCJdLCBzZWxlY3RbbmFtZSo9XCJfeWVhclwiXSwgbGFiZWwuZXhwaXJhdGlvbi1kYXRlJyk7XG5cdFx0dmFyICRhbGxpYW5jZURhdGFEaXNwbGF5RGVsdGEgPSAkKCdsYWJlbC5leHBpcmF0aW9uLWRhdGUnKTtcblx0XHRcblx0ICAgIHN3aXRjaCAocGF5bWVudEluc3RydW1lbnRUeXBlKSB7XG5cdFx0XHRjYXNlIFBheW1lbnRNZXRob2RDb25zdGFudHMuQWxsaWFuY2VEYXRhOlxuXHRcdFx0XHQkYWxsaWFuY2VEYXRhRmllbGREZWx0YS5yZW1vdmVDbGFzcygncmVxdWlyZWQnKS5jbG9zZXN0KCcuZm9ybWZpZWxkJykuaGlkZSgpO1xuXHRcdFx0XHQkYWxsaWFuY2VEYXRhRGlzcGxheURlbHRhLmhpZGUoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFxuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0JGFsbGlhbmNlRGF0YUZpZWxkRGVsdGEuYWRkQ2xhc3MoJ3JlcXVpcmVkJykuY2xvc2VzdCgnLmZvcm1maWVsZCcpLnNob3coKTtcblx0XHRcdFx0JGFsbGlhbmNlRGF0YURpc3BsYXlEZWx0YS5zaG93KCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fSk7XG5cdFxuXHQkKCcuY2MtbnVtYmVyLWNvbnRhaW5lciBpbnB1dFt0eXBlPVwidGV4dFwiXScpLm9mZigna2V5dXAuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nKS5vbigna2V5dXAuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBzZWxlY3RlZENyZWRpdENhcmRUeXBlID0gdXRpbC5nZXRDcmVkaXRDYXJkVHlwZSgkKHRoaXMpLnZhbCgpKTtcblx0XHRcblx0XHRpZiAoc2VsZWN0ZWRDcmVkaXRDYXJkVHlwZSkge1xuXHRcdFx0JGNyZWRpdENhcmRUeXBlU2VsZWN0LnZhbChzZWxlY3RlZENyZWRpdENhcmRUeXBlLlBheW1lbnRDYXJkRGlzcGxheUtleSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRjcmVkaXRDYXJkVHlwZVNlbGVjdC52YWwoJycpO1xuXHRcdH1cblx0XHRcblx0XHQkY3JlZGl0Q2FyZFR5cGVTZWxlY3QudHJpZ2dlcignY2hhbmdlLkNyZWRpdENhcmRUeXBlRGV0ZWN0aW9uJyk7XG5cdH0pO1xuICAgIFxuICAgICRjcmVkaXRDYXJkVHlwZVNlbGVjdC50cmlnZ2VyKCdjaGFuZ2UuQ3JlZGl0Q2FyZFR5cGVEZXRlY3Rpb24nKTtcblx0XG5cdHZhciBwYXltZW50TGlzdCA9ICQoJy5wYXltZW50LWxpc3QnKTtcbiAgICBpZiAocGF5bWVudExpc3QubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuXHRcbiAgICAkKCdmb3JtW25hbWU9XCJwYXltZW50LXJlbW92ZVwiXSBidXR0b25bdHlwZT1cInN1Ym1pdFwiXScpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIG92ZXJyaWRlIGZvcm0gc3VibWlzc2lvbiBpbiBvcmRlciB0byBwcmV2ZW50IHJlZnJlc2ggaXNzdWVzXG4gICAgICAgIHZhciAkYnV0dG9uID0gJChlLnRhcmdldCk7XG4gICAgICAgIFxuICAgICAgICAvLyBjb25maXJtIGRlbGV0ZVxuICAgICAgICBpZiAoJGJ1dHRvbi5oYXNDbGFzcygnZGVsZXRlJykpIHtcbiAgICAgICAgXHRpZiAoIXdpbmRvdy5jb25maXJtKFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfQ1JFRElUQ0FSRCkpKSB7XG4gICAgICAgIFx0XHRyZXR1cm4gZmFsc2U7XG4gICAgICAgIFx0fVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICB2YXIgJGZvcm0gPSAkKHRoaXMpLmNsb3Nlc3QoJ2Zvcm0nKTsgXG4gICAgICAgIFxuICAgICAgICAkKCc8aW5wdXQvPicpLmF0dHIoe1xuICAgICAgICAgICAgdHlwZTogJ2hpZGRlbicsXG4gICAgICAgICAgICBuYW1lOiAkYnV0dG9uLmF0dHIoJ25hbWUnKSxcbiAgICAgICAgICAgIHZhbHVlOiAkYnV0dG9uLmF0dHIoJ3ZhbHVlJykgfHwgJ2RlbGV0ZSBjYXJkJ1xuICAgICAgICB9KS5hcHBlbmRUbygkZm9ybSk7XG4gICAgICAgIHZhciBkYXRhID0gJGZvcm0uc2VyaWFsaXplKCk7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICB1cmw6ICRmb3JtLmF0dHIoJ2FjdGlvbicpLFxuICAgICAgICAgICAgZGF0YTogZGF0YVxuICAgICAgICB9KVxuICAgICAgICAuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwYWdlLnJlZGlyZWN0KFVybHMucGF5bWVudHNMaXN0KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBpbml0IGV2ZW50cyBmb3IgdGhlIGxvZ2luUGFnZVxuICovXG5mdW5jdGlvbiBpbml0TG9naW5QYWdlKCkge1xuICAgIC8vby1hdXRoIGJpbmRpbmcgZm9yIHdoaWNoIGljb24gaXMgY2xpY2tlZFxuICAgICQoJy5vQXV0aEljb24nKS5iaW5kKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnI09BdXRoUHJvdmlkZXInKS52YWwodGhpcy5pZCk7XG4gICAgfSk7XG4gICAgJCgnLmJ0bi1sb29rdXAtb3JkZXInKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICQoJ2Rpdi5jaGVjay1vcmRlci1jb250ZW50Jykuc2xpZGVEb3duKCk7XG4gICAgICAgICQodGhpcykuc2xpZGVVcCgpO1xuICAgIH0pO1xuICAgICQoJyNwYXNzd29yZC1yZXNldC1yZXdhcmRzJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICB1cmw6ICQoZS50YXJnZXQpLmF0dHIoJ2hyZWYnKSxcbiAgICAgICAgICAgIHRhcmdldCA6ICQoXCIucGFzc3dvcmQtcmVzZXQtZGlhbG9nLWNvbnRhaW5lclwiKSxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIFx0ZGlhbG9nQ2xhc3M6ICdzZWxlY3QtcmV3YXJkcy1udW1iZXItcG9wdXAnLFxuICAgICAgICAgICAgXHR3aWR0aDogMzg1LFxuICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yLmluaXQoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRyZXF1ZXN0UGFzc3dvcmRGb3JtID0gJCgnW25hbWUkPVwiX3JlcXVlc3RwYXNzd29yZFwiXScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgJHN1Ym1pdCA9ICRyZXF1ZXN0UGFzc3dvcmRGb3JtLmZpbmQoJ1tuYW1lJD1cIl9yZXF1ZXN0cGFzc3dvcmRfc2VuZFwiXScpLFxuICAgICAgICAgICAgICAgICAgICBcdCRyZXNldFBhc3N3b3JkRm9ybSA9ICQoJ1tuYW1lJD1cIl9yZXNldHBhc3N3b3JkXCJdJyk7XG4gICAgICAgICAgICAgICAgICAgICQoJHN1Ym1pdCkub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghJHJlcXVlc3RQYXNzd29yZEZvcm0udmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICggJHJlc2V0UGFzc3dvcmRGb3JtLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgICAgICAgICAgIFx0JHJlc2V0UGFzc3dvcmRGb3JtLmZpbmQoXCJidXR0b25bdHlwZT1zdWJtaXRdXCIpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIFx0XHR2YXIgbmFtZUF0dHIgPSAkKHRoaXMpLmF0dHIoJ25hbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgXHRcdGRpYWxvZy5zdWJtaXQobmFtZUF0dHIpO1xuICAgICAgICAgICAgICAgICAgICBcdH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICQoXCIucmVzZXQtcGFzc3dvcmQtaGVhZGluZy1jbG9zZS1idG5cIikub24oJ2NsaWNrJyxmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAgICAgJChcImJ1dHRvbi51aS1kaWFsb2ctdGl0bGViYXItY2xvc2VcIikuY2xpY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGV4ZWNCYXJDb2RlR2VuZXJhdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgaWYgKCAkKCcjcGFzc3dvcmQtcmVzZXQtcmV3YXJkcycpLmxlbmd0aCA+IDAgKSB7XG4gICAgXHR2YXIgY3QgPSAwO1xuICAgIFx0d2hpbGUoY3QgPCAyKSB7XG4gICAgXHRcdGN0Kys7XG4gICAgXHRcdCQoJyNwYXNzd29yZC1yZXNldC1yZXdhcmRzJykuY2xpY2soKTtcbiAgICBcdH1cbiAgICB9XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBldmVudHMgb2YgdGhlIG9yZGVyLCBhZGRyZXNzIGFuZCBwYXltZW50IHBhZ2VzXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgdG9nZ2xlRnVsbE9yZGVyKCk7XG4gICAgaW5pdEFkZHJlc3NFdmVudHMoKTtcbiAgICBpbml0UGF5bWVudEV2ZW50cygpO1xuICAgIGluaXRMb2dpblBhZ2UoKTtcblx0aW5pdENyZWF0ZUFjY291bnRFdmVudEhhbmRsZXJzKCk7XG4gICAgaWYgKHV0aWwuaXNNb2JpbGUoKSkge1xuICAgIFx0dXRpbC5saW1pdElucHV0VG9MZW5ndGgoJyNDcmVkaXRDYXJkRm9ybSBpbnB1dFtuYW1lKj1cIl9udW1iZXJcIl0nLCAxNik7XG4gICAgfVxuXG5cdHZhciBibHVyRmllbGRzID0gXCIjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9lbWFpbCwgI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfZW1haWxjb25maXJtLCBpbnB1dFtpZCo9ZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZF9dLCBpbnB1dFtpZCo9ZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZGNvbmZpcm1fXVwiO1xuICAgICQoYmx1ckZpZWxkcykuYmx1cihmdW5jdGlvbigpe1xuICAgICAgICBpZiAoICQodGhpcykudmFsKCkgPT0gJycgKSB7XG4gICAgICAgICAgICBpZiAoICQodGhpcykucGFyZW50cygnLmZvcm0tcm93JykuZmluZCggJy5mb3JtLWNhcHRpb24uZXJyb3ItbWVzc2FnZScgKS5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgJCh0aGlzKS5wYXJlbnRzKCcuZm9ybS1yb3cnKS5maW5kKCAnLmZvcm0tY2FwdGlvbi5lcnJvci1tZXNzYWdlJyApLmh0bWwoJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGV4ZWNCYXJDb2RlR2VuZXJhdGlvbigpIHtcblx0aWYgKCQoJy5yZXdhcmRzcmVnaXN0cmF0aW9uY29uZmlybWF0aW9uJykubGVuZ3RoID4gMCkge1xuXHRcdHZhciBiYXJjb2RlTnVtYmVyID0gXCJcIiskKCcucmV3YXJkc3JlZ2lzdHJhdGlvbmNvbmZpcm1hdGlvbicpLmZpbmQoXCJbZGF0YS1yZXdhcmRzbnVtYmVyXVwiKS5kYXRhKCdyZXdhcmRzbnVtYmVyJyk7XG5cdFx0dmFyIGJhcmNvZGVUeXBlID0gJ2NvZGUxMjgnO1xuXHRcdFxuXHRcdCQoXCIjYmFyY29kZVRhcmdldFwiKS5iYXJjb2RlKGJhcmNvZGVOdW1iZXIsIGJhcmNvZGVUeXBlLCB7XG5cdFx0XHRiYXJIZWlnaHQ6Jzc1Jyxcblx0XHRcdGJhcldpZHRoOicyJyxcblx0XHRcdGZvbnRTaXplOicxNCcsXG5cdFx0XHRmb250V2VpZ2h0Oidib2xkJyxcblx0XHRcdG91dHB1dDonYm1wJ1xuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRSZXdhcmRzUGFnZSgpIHtcblx0JCh3aW5kb3cpLm9uKCdsb2FkJywgZnVuY3Rpb24oKSB7XG5cdFx0ZXhlY0JhckNvZGVHZW5lcmF0aW9uKCk7XG5cdH0pO1xufVxuXG4kKHdpbmRvdykub24oXCJtZXNzYWdlXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICB2YXIgZGF0YSA9IGUub3JpZ2luYWxFdmVudC5kYXRhO1xuICAgIGlmKGRhdGEgPT0gXCJlcnJvclwiKXtcbiAgICBcdCQoXCIubWVudS11dGlsaXR5LXVzZXJcIikuYWRkQ2xhc3MoXCJsb2dpbkVycm9yXCIpO1xuICAgIH1cbn0pO1xuXG5mdW5jdGlvbiByZW5kZXJPcHRpb25zKG9wdGlvblBhcmVudCwgb3B0aW9uc1N0b3JlSWQpIHtcblx0dmFyIG9wdGlvbnMgPSAnJztcblx0dmFyIHN0YXRlc0xpc3QgPSBKU09OLnBhcnNlKCQob3B0aW9uc1N0b3JlSWQgKyAnIG9wdGlvbjpzZWxlY3RlZCcpLmRhdGEoJ29wdGlvbnMnKS5yZXBsYWNlKC9cXCcvZywgJ1xcXCInKSk7XG5cdFxuXHRzdGF0ZXNMaXN0LmZvckVhY2goZnVuY3Rpb24oc3RhdGUpe1xuXHRcdG9wdGlvbnMgKz0gJzxvcHRpb24gY2xhc3M9XCJzZWxlY3Qtb3B0aW9uXCIgbGFiZWw9XCInK3N0YXRlLmxhYmVsKydcIiB2YWx1ZT1cIicrc3RhdGUuY29kZSsnXCI+JytzdGF0ZS5sYWJlbCsnPC9vcHRpb24+Jztcblx0fSk7XG5cdCQob3B0aW9uUGFyZW50KS5lbXB0eSgpLmFwcGVuZChvcHRpb25zKTtcblx0XG5cdGlmIChzdGF0ZXNMaXN0Lmxlbmd0aCA8PSAxKSB7XG5cdFx0JChvcHRpb25QYXJlbnQpLnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpLmhpZGUoKTtcblx0XHQkKG9wdGlvblBhcmVudCArICdfc2JtJykudmFsKCQob3B0aW9uUGFyZW50KS52YWwoKSkuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdH0gZWxzZSB7XG5cdFx0JChvcHRpb25QYXJlbnQpLnBhcmVudCgpLnBhcmVudCgpLnBhcmVudCgpLnNob3coKTtcblx0XHQkKG9wdGlvblBhcmVudCArICdfc2JtJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0UmV3YXJkUmVnaXN0ZXJGb3JtKCkge1xuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHR2YXIgJHJld2FyZFJlZ2lzdGVyRm9ybSA9ICQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uJyk7XG5cdFx0aWYgKCRyZXdhcmRSZWdpc3RlckZvcm0ubGVuZ3RoID4gMCkge1xuXHRcdFx0JHJld2FyZFJlZ2lzdGVyRm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfcGhvbmUnKS5ydWxlcygnYWRkJywge1xuXHRcdFx0XHRwaG9uZTogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkUmVnaXN0ZXJGb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcmFkZHJlc3NfemlwY29kZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBvc3RhbDogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkUmVnaXN0ZXJGb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9lbWFpbCcpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHJlcXVpcmVFbWFpbEV4dGVuc2lvbjogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkUmVnaXN0ZXJGb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9lbWFpbGNvbmZpcm0nKS5ydWxlcygnYWRkJywge1xuXHRcdFx0XHRyZXF1aXJlRW1haWxFeHRlbnNpb246IHRydWUsXG5cdFx0XHRcdGVxdWFsVG86ICcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfZW1haWwnXG5cdFx0XHR9KTtcblxuXHRcdFx0JHJld2FyZFJlZ2lzdGVyRm9ybS5vbigna2V5dXAnLCAnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2VtYWlsJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0dmFyIHNlcnZlckVycm9yTWVzc2FnZSA9ICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCcuZm9ybS1yb3cnKS5maW5kKCcuZXJyb3ItbWVzc2FnZScpO1xuXHRcdFx0XHRpZiAoc2VydmVyRXJyb3JNZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRzZXJ2ZXJFcnJvck1lc3NhZ2UucmVtb3ZlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRSZXdhcmRzQXR0YWNoZWQoKSB7XG5cdCQod2luZG93KS5vbignbG9hZCcsIGZ1bmN0aW9uKCkge1xuXHRcdGlmICgkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAjZmllbGRSZXdhcmRzTnVtYmVyJykudmFsKCkgIT0gJycpIHtcblx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0nKS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHBhc3NCcmVhZFNldHVwKHJld2FyZHNOdW1iZXIpIHtcblx0QnJlYWRQYXltZW50cy5zZXR1cCh7XG5cdFx0bG95YWx0eUlEOiByZXdhcmRzTnVtYmVyLFxuXHRcdHN0b3JlTnVtYmVyOiB1dGlsLmlzTW9iaWxlKCkgPyBTaXRlUHJlZmVyZW5jZXMuUExDQ19TVE9SRV9OVU1CRVJfTU9CSUxFIDogU2l0ZVByZWZlcmVuY2VzLlBMQ0NfU1RPUkVfTlVNQkVSX1dFQixcblx0XHRleGlzdGluZ0NhcmRIb2xkZXI6IGZhbHNlLFxuXHRcdGVudjogU2l0ZVByZWZlcmVuY2VzLlBMQ0NfRU5WSVJPTk1FTlQsXG5cdH0pO1xufVxuXG5mdW5jdGlvbiBpbml0RGlzcGxheVJld2FyZHNEYXRhKCkge1xuXHQkLmFqYXgoe1xuXHRcdHVybDogVXJscy5nZXRSZXdhcmRJbmZvRm9yUmVnaXN0ZXJlZCxcblx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdGRhdGEgOiB7XG5cdFx0XHQnY3NyZl90b2tlbic6ICAkKCcuYWNjb3VudC1vdmVydmlldyBpbnB1dFtuYW1lPVwiY3NyZl90b2tlblwiXScpLnZhbCgpLFxuXHRcdFx0J3Jld2FyZHNOdW1iZXInOiAkKCcuYXR0YWNoZWQtcmV3YXJkcy1hY2NvdW50IC5yZXdhcmRzLW51bWJlcicpLnRleHQoKSxcdFx0XHRcblx0XHRcdCdlbWFpbCc6ICQoJy5hdHRhY2hlZC1yZXdhcmRzLWFjY291bnQuZW1haWwtYWRkcmVzcycpLnRleHQoKSxcblx0XHRcdCd6aXBjb2RlJzogJCgnLmF0dGFjaGVkLXJld2FyZHMtYWNjb3VudC56aXAtY29kZScpLnRleHQoKSxcblx0XHRcdCdwaG9uZSc6ICQoJy5hdHRhY2hlZC1yZXdhcmRzLWFjY291bnQucGhvbmUtbnVtYmVyJykudGV4dCgpXG5cdFx0fSxcblx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0aWYgKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhWydlcnJvciddKSB7XG5cdFx0XHRcdCQoJy5teWFjY291bnQtY29udGFjdC1jdXN0c2VydicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcdFx0XHRcdFxuXHRcdFx0fSBlbHNlIHtcdFx0XHRcblx0XHRcdFx0aWYgKGRhdGEuc2VjdXJpdHlSaXNrKSB7XHRcdFx0XHRcdFxuXHRcdFx0XHRcdCQoJy5teWFjY291bnQtY29udGFjdC1jdXN0c2VydicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcjYWN0aXZlLXJld2FyZHMnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0JCgnLmF0dGFjaGVkLXJld2FyZHMtYWNjb3VudC5hdmFpbGFibGUtcmV3YXJkcycpLmh0bWwoXCIkXCIgKyBwYXJzZUZsb2F0KGRhdGEuY3JlZGl0QW1vdW50KS50b0ZpeGVkKDApKTtcblx0XHRcdFx0XHQkKCcuYXR0YWNoZWQtcmV3YXJkcy1hY2NvdW50LmN1cnJlbnQtcG9pbnRzJykuaHRtbChkYXRhLnBvaW50QmFsYW5jZSk7XG5cdFx0XHRcdH1cdFx0XG5cdFx0XHR9XG5cdFx0XHRpZiAoJCgnI2FjdGl2ZS1yZXdhcmRzJykubGVuZ3RoID49IDEpIHtcblx0XHRcdFx0cGFzc0JyZWFkU2V0dXAoZGF0YS5yZXdhcmRzTnVtYmVyKTtcblx0XHRcdFx0QnJlYWRQYXltZW50cy5yZWdpc3RlclBsYWNlbWVudHMoW2Rhc2hib2FyZFBsYWNlbWVudF0pO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Y29tcGxldGU6IGZ1bmN0aW9uKGRhdGEsIHN0YXR1cywgeGhyKSB7XG5cdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gMzAyICYmIGRhdGEucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBpbml0UmV3YXJkQ2hlY2tGb3JtKCkge1xuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQkKCcjcmV3YXJkc1NlbGVjdDEnKS5zZWxlY3RtZW51KCk7XG5cdFx0JCgnI3Jld2FyZHNTZWxlY3QyJykuc2VsZWN0bWVudSgpO1xuXHRcdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI3Jld2FyZHNTZWxlY3QxLW1lbnUgLnVpLW1lbnUtaXRlbS13cmFwcGVyJywgZnVuY3Rpb24oKXtcblx0XHRcdHZhciBzZWxlY3QxdGV4dCA9ICQodGhpcykudGV4dCgpO1xuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MXRleHQgPT0gXCJCIFJld2FyZGVkXCIgfHwgc2VsZWN0MXRleHQgPT0gXCJSZXdhcmRzIE51bWJlclwiICkge1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuYnJld2FyZGVkLW51bWJlcicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgLnJld2FyZHMtbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuZW1haWwtYWRkcmVzcycpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNTZWxlY3QxLWJ1dHRvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHNlbGVjdDF0ZXh0ID09IFwiRW1haWwgQWRkcmVzc1wiKSB7XG5cdFx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlIC5lbWFpbC1hZGRyZXNzJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuYnJld2FyZGVkLW51bWJlcicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgLnJld2FyZHMtbnVtYmVyJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc1NlbGVjdDEtYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVx0XG5cdFx0fSk7XG5cdFx0XG5cdFx0JCgnYm9keScpLm9uKCdjbGljaycsICcjcmV3YXJkc1NlbGVjdDItbWVudSAudWktbWVudS1pdGVtLXdyYXBwZXInLCBmdW5jdGlvbigpe1xuXHRcdFx0dmFyIHNlbGVjdDJ0ZXh0ID0gJCh0aGlzKS50ZXh0KCk7XG5cdFx0XHRcblx0XHRcdGlmIChzZWxlY3QydGV4dCA9PSBcIlppcCBDb2RlXCIpIHtcblx0XHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgLnppcC1jb2RlJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAucGhvbmUtbnVtYmVyJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc1NlbGVjdDItYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MnRleHQgPT0gXCJQaG9uZSBOdW1iZXJcIikge1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAucGhvbmUtbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjcmV3YXJkc0NoZWNrQmFsYW5jZSAuemlwLWNvZGUnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNyZXdhcmRzU2VsZWN0Mi1idXR0b24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XHRcblx0XHR9KTtcblx0XHRcblx0XHR2YXIgJHJld2FyZENoZWNrRm9ybSA9ICQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlJyk7XG5cdFx0aWYgKCRyZXdhcmRDaGVja0Zvcm0ubGVuZ3RoID4gMCkge1xuXHRcdFx0JHJld2FyZENoZWNrRm9ybS5maW5kKCcjZmllbGRSZXdhcmRzTnVtYmVyJykucnVsZXMoJ2FkZCcsIHtcblx0XHRcdFx0cG9zaXRpdmVudW1iZXI6IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0JHJld2FyZENoZWNrRm9ybS5maW5kKCcjZmllbGRSZXdhcmRzRW1haWwnKS5ydWxlcygnYWRkJywge1xuXHRcdFx0XHRyZXF1aXJlRW1haWxFeHRlbnNpb246IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0JHJld2FyZENoZWNrRm9ybS5maW5kKCcjZmllbGRSZXdhcmRzWmlwY29kZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBvc3RhbDogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNQaG9uZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBob25lOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgI3Jlc2V0UmV3YXJkc0lucXVpcnknKS5vbignY2xpY2snLCAgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0JCgnLnVpLXNlbGVjdG1lbnUtdGV4dCcpLnRleHQoJ1NlbGVjdCBPbmUnKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNTZWxlY3QxLWJ1dHRvbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNTZWxlY3QyLWJ1dHRvbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI3Jld2FyZHNDaGVja0JhbGFuY2UgLmZvcm0tcm93JykuYWRkQ2xhc3MoJ2hpZGRlbicpLmZpbmQoJ2lucHV0LmlucHV0LXRleHQnKS52YWwoJycpO1xuXHRcdFx0XHQkKCcjc2VuZFJld2FyZHNJbnF1aXJ5JykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0XHRcdFx0JCgnLnJld2FyZHMtcmVzdWx0cycpLmh0bWwoJycpO1xuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdCQoJyNyZXdhcmRzQ2hlY2tCYWxhbmNlJykub24oJ2NoYW5nZScsICdpbnB1dC5pbnB1dC10ZXh0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggJCgnI2ZpZWxkUmV3YXJkc051bWJlcicpLnZhbCgpIHx8ICQoJyNmaWVsZFJld2FyZHNFbWFpbCcpLnZhbCgpICkge1xuXHRcdFx0XHRcdGlmICggJCgnI2ZpZWxkUmV3YXJkc1ppcGNvZGUnKS52YWwoKSB8fCAkKCcjZmllbGRSZXdhcmRzUGhvbmUnKS52YWwoKSApe1x0XHRcdFx0XHRcblx0XHRcdFx0XHRcdCQoJyNzZW5kUmV3YXJkc0lucXVpcnknKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdCRyZXdhcmRDaGVja0Zvcm0uZmluZCgnaW5wdXQjc2VuZFJld2FyZHNJbnF1aXJ5Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0dmFyICRyZXN1bHRzQ29udGFpbmVyID0gJCgnLnJld2FyZHMtcmVzdWx0cycpO1xuXG5cdFx0XHRcdCRyZXN1bHRzQ29udGFpbmVyLmh0bWwoJycpO1xuXG5cdFx0XHRcdGlmICghJHJld2FyZENoZWNrRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdFx0dXJsOiBVcmxzLmdldFJld2FyZEluZm8sXG5cdFx0XHRcdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0XHRcdCdjc3JmX3Rva2VuJzogICRyZXdhcmRDaGVja0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdFx0J3Jld2FyZHNOdW1iZXInOiAkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNOdW1iZXInKS52YWwoKSxcblx0XHRcdFx0XHRcdFx0J2VtYWlsJzogJHJld2FyZENoZWNrRm9ybS5maW5kKCcjZmllbGRSZXdhcmRzRW1haWwnKS52YWwoKSxcblx0XHRcdFx0XHRcdFx0J3ppcGNvZGUnOiAkcmV3YXJkQ2hlY2tGb3JtLmZpbmQoJyNmaWVsZFJld2FyZHNaaXBjb2RlJykudmFsKCksXG5cdFx0XHRcdFx0XHRcdCdwaG9uZSc6ICRyZXdhcmRDaGVja0Zvcm0uZmluZCgnI2ZpZWxkUmV3YXJkc1Bob25lJykudmFsKClcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0XHRpZiAoJ2Vycm9yJyBpbiBkYXRhICYmIGRhdGFbJ2Vycm9yJ10pIHtcblx0XHRcdFx0XHRcdFx0XHQkcmVzdWx0c0NvbnRhaW5lci5hcHBlbmQoJzxwIGNsYXNzPVwiZXJyb3ItYmxvY2tcIj4nK2RhdGFbJ21lc3NhZ2UnXSsnPC9wPicpO1xuXHRcdFx0XHRcdFx0XHRcdCQoJy5yZXdhcmRzLWNvbnRhY3QtY3VzdHNlcnYnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHQkKCcjcmV3YXJkcy1kYXNoYm9hcmQnKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRhdGEuc2VjdXJpdHlSaXNrKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkKCcucmV3YXJkcy1jb250YWN0LWN1c3RzZXJ2JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkKCcuZGlzcGxheS1yZXdhcmRzJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCAkKCcjZ29Ub0NyZWRpdFR3bycpLmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJlbmRlclJld2FyZENoZWNrUmVzdWx0cyhkYXRhLCAkcmVzdWx0c0NvbnRhaW5lcik7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdCQoJy5yZXdhcmRzLWRldGFpbHMnKS5oaWRlKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZW5kZXJSZXdhcmRDaGVja1Jlc3VsdHMoZGF0YSwgJHJlc3VsdHNDb250YWluZXIpIHtcblx0dmFyIHJld2FyZHNDcmVkaXRBbW91bnQgPSAkKCcuYXZhaWxhYmxlLXJld2FyZHMnKS5kYXRhKCdjcmVkaXQnKTtcblx0dmFyIHBvaW50c1JlcXVpcmVkID0gJCgnLmF2YWlsYWJsZS1yZXdhcmRzJykuZGF0YSgncmVxdWlyZWQnKTtcblx0dmFyIHBvaW50c05lZWRlZCA9IHBvaW50c1JlcXVpcmVkLWRhdGEucG9pbnRCYWxhbmNlO1xuXHR2YXIgcG9pbnRzVGV4dCA9IGRhdGEucG9pbnRCYWxhbmNlID09IDEgPyAnIFBUICcgOiAnIFBUUyAnO1xuXHRcblx0JCgnI3Jld2FyZHMtbnVtYmVyJykudGV4dChcIiNcIiArIGRhdGEucmV3YXJkc051bWJlcikucmVtb3ZlQ2xhc3MoJ2xvYWRlcicpO1xuXHQkKCcjcmV3YXJkcy1lYXJuZWQnKS50ZXh0KFwiJFwiICsgKE1hdGguZmxvb3IocGFyc2VGbG9hdChkYXRhLnBvaW50c0Vhcm5lZEluTGFzdFllYXIvcG9pbnRzUmVxdWlyZWQpKSoxNSkudG9GaXhlZCgyKSk7XG5cdCQoJy5yZXdhcmRzLW1lc3NhZ2UgZGl2JykucmVtb3ZlQ2xhc3MoJ2xvYWRlcicpO1xuXHQkKCcjcmV3YXJkcy1jcmVkaXQnKS5zaG93KCkuaHRtbChcIiRcIiArIHBhcnNlRmxvYXQoZGF0YS5jcmVkaXRBbW91bnQpLnRvRml4ZWQoMCkpLnJlbW92ZUNsYXNzKCdsb2FkZXInKTtcblx0aWYgKGRhdGEuY3JlZGl0QW1vdW50ICE9IDApe1x0XHRcblx0XHQkKCcjcmV3YXJkcy1leHBpcmF0aW9uJykuc2hvdygpLmZpbmQoJ3NwYW4nKS50ZXh0KGRhdGEuY3JlZGl0RXhwaXJhdGlvbkRhdGUpO1x0XHRcblx0fSBlbHNlIHtcblx0XHQkKCcucmV3YXJkcy16ZXJvLW1lc3NhZ2UnKS5zaG93KCk7XG5cdH1cblx0JCgnLmF2YWlsYWJsZS1wb2ludHMgZGl2JykucmVtb3ZlQ2xhc3MoJ2xvYWRlcicpO1xuXHQkKCcucG9pbnRzLWFjY3J1ZWQnKS5yZW1vdmVDbGFzcygnbG9hZGVyJykuaHRtbChkYXRhLnBvaW50QmFsYW5jZSk7XG5cdFxuXHRwYXNzQnJlYWRTZXR1cChkYXRhLnJld2FyZHNOdW1iZXIpO1xuXHRCcmVhZFBheW1lbnRzLnJlZ2lzdGVyUGxhY2VtZW50cyhbbG95YWx0eVBsYWNlbWVudF0pO1xufVxuXG5mdW5jdGlvbiBpbml0RGlzcGxheUxveWFsdHlEYXRhKCkge1xuXHRpZiAoJCgnLnB0X2FjY291bnQnKS5sZW5ndGggPiAwKSB7XG5cdFx0JC5hamF4KHtcblx0XHRcdHVybDogVXJscy5sb3lhbHR5Q2hlY2ssXG5cdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRkYXRhOiB7XG5cdFx0XHRcdCdsb3lhbHR5TnVtYmVyJzogJCgnLnNldHRpbmdzLS1sb3lhbHR5JykuYXR0cignZGF0YS1udW1iZXInKSxcblx0XHRcdFx0J2xveWFsdHlaaXAnOiAkKCcuc2V0dGluZ3MtLWxveWFsdHknKS5hdHRyKCdkYXRhLXppcCcpXG5cdFx0XHR9LFx0XHRcdFx0XHRcdFxuXHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0aWYgKCgnZXJyb3InIGluIGRhdGEgJiYgZGF0YVsnZXJyb3InXSkpIHtcblx0XHRcdFx0XHQkKCcubG95YWx0eS1lcnJvcicpLnRleHQoZGF0YS5tZXNzYWdlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZW5kZXJMb3lhbHR5SW5mbyhkYXRhLnN0YXR1cyk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlckxveWFsdHlJbmZvKGRhdGEpIHtcblx0dmFyIG9wdGluU3RhdHVzID0gZGF0YS5vcHRJbjtcblx0XG5cdGlmIChvcHRpblN0YXR1cyl7XG5cdFx0JCgnLmxveWFsdHktbnVtYmVyIHNwYW4udmFsdWUnKS50ZXh0KGRhdGEubG95YWx0eU1lbWJlck51bWJlcik7XG5cdFx0JCgnLmN1cnJlbnQtcG9pbnRzIHNwYW4udmFsdWUnKS50ZXh0KE1hdGguZmxvb3IoZGF0YS5wb2ludHMpKTtcblx0XHQkKCcuYXZhaWxhYmxlLXJld2FyZHMgc3Bhbi52YWx1ZScpLnRleHQoXCIkXCIgKyBkYXRhLnRvdGFsUmV3YXJkcyk7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLnNldHRpbmdzLS1sb3lhbHR5JykuaGlkZSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGNsZWFyTG95YWx0eUZvcm0oKSB7XG5cdCQoJy5jaGVjay1teS1iYWxhbmNlJykuc2hvdygpO1xuXHQkKCcubXktYmFsYW5jZScpLmhpZGUoKTtcblx0JCgnLnVpLXNlbGVjdG1lbnUtdGV4dCcpLnRleHQoJ1NlbGVjdCBPbmUnKTtcblx0JCgnI2xveWFsdHlTZWxlY3QxLWJ1dHRvbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0JCgnI2xveWFsdHlTZWxlY3QyLWJ1dHRvbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmZvcm0tcm93JykuYWRkQ2xhc3MoJ2hpZGRlbicpLmZpbmQoJ2lucHV0LmlucHV0LXRleHQnKS52YWwoJycpO1xuXHQkKCcjc2VuZExveWFsdHlJbnF1aXJ5JykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0JCgnLmxveWFsdHktcmVzdWx0cyBzcGFuJykudGV4dCgnJyk7XG5cdCQoJy5sb3lhbHR5LWVycm9yJykuaHRtbCgnJyk7XG59XG5cbmZ1bmN0aW9uIGluaXRMb3lhbHR5Q2hlY2tGb3JtKCkge1xuXHRpZiAoJCgnLnB0X2xveWFsdHknKS5sZW5ndGggPiAwKSB7XG5cdFx0JCgnI2xveWFsdHlTZWxlY3QxJykuc2VsZWN0bWVudSgpO1xuXHRcdCQoJyNsb3lhbHR5U2VsZWN0MicpLnNlbGVjdG1lbnUoKTtcblx0XHRcblx0XHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyNsb3lhbHR5U2VsZWN0MS1tZW51IC51aS1tZW51LWl0ZW0td3JhcHBlcicsIGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgc2VsZWN0MXRleHQgPSAkKHRoaXMpLnRleHQoKTtcblx0XHRcdFxuXHRcdFx0aWYgKHNlbGVjdDF0ZXh0ID09IFwiTG95YWx0eSBOdW1iZXJcIiApIHtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmJyZXdhcmRlZC1udW1iZXInKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlIC5sb3lhbHR5LW51bWJlcicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmVtYWlsLWFkZHJlc3MnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNsb3lhbHR5U2VsZWN0MS1idXR0b24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChzZWxlY3QxdGV4dCA9PSBcIkVtYWlsIEFkZHJlc3NcIikge1xuXHRcdFx0XHQkKCcjbG95YWx0eUNoZWNrQmFsYW5jZSAuZW1haWwtYWRkcmVzcycpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLmJyZXdhcmRlZC1udW1iZXInKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlIC5sb3lhbHR5LW51bWJlcicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlTZWxlY3QxLWJ1dHRvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cdFxuXHRcdH0pO1xuXHRcdFxuXHRcdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI2xveWFsdHlTZWxlY3QyLW1lbnUgLnVpLW1lbnUtaXRlbS13cmFwcGVyJywgZnVuY3Rpb24oKXtcblx0XHRcdHZhciBzZWxlY3QydGV4dCA9ICQodGhpcykudGV4dCgpO1xuXHRcdFx0XG5cdFx0XHRpZiAoc2VsZWN0MnRleHQgPT0gXCJaaXAgQ29kZVwiKSB7XG5cdFx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlIC56aXAtY29kZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLnBob25lLW51bWJlcicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlTZWxlY3QyLWJ1dHRvbicpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHNlbGVjdDJ0ZXh0ID09IFwiUGhvbmUgTnVtYmVyXCIpIHtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLnBob25lLW51bWJlcicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnI2xveWFsdHlDaGVja0JhbGFuY2UgLnppcC1jb2RlJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkKCcjbG95YWx0eVNlbGVjdDItYnV0dG9uJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0fVx0XG5cdFx0fSk7XG5cdFx0XG5cdFx0dmFyICRsb3lhbHR5Q2hlY2tGb3JtID0gJCgnI2xveWFsdHlDaGVja0JhbGFuY2UnKTtcblx0XHRpZiAoJGxveWFsdHlDaGVja0Zvcm0ubGVuZ3RoID4gMCkge1xuXHRcdFx0JGxveWFsdHlDaGVja0Zvcm0uZmluZCgnI2ZpZWxkTG95YWx0eU51bWJlcicpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBvc2l0aXZlbnVtYmVyOiB0cnVlXG5cdFx0XHR9KTtcblx0XHRcdCRsb3lhbHR5Q2hlY2tGb3JtLmZpbmQoJyNmaWVsZExveWFsdHlFbWFpbCcpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHJlcXVpcmVFbWFpbEV4dGVuc2lvbjogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5WmlwY29kZScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0XHRcdHBvc3RhbDogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHQkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5UGhvbmUnKS5ydWxlcygnYWRkJywge1xuXHRcdFx0XHRwaG9uZTogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlICNyZXNldExveWFsdHlJbnF1aXJ5Jykub24oJ2NsaWNrJywgIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdGNsZWFyTG95YWx0eUZvcm0oKTtcdFx0XHRcblx0XHRcdH0pO1xuXHRcdFx0XG5cdFx0XHR2YXIgc2Nyb2xsTWludXMgPSAwO1xuXHRcdFx0aWYgKCQoJy52b3VjaGVyJykubGVuZ3RoID4gOCApe1xuXHRcdFx0XHRzY3JvbGxNaW51cyA9IDEwMDtcblx0XHRcdH1cblx0XHRcdGlmICgkKHdpbmRvdykud2lkdGgoKSA8IDc2Nykge1xuXHRcdFx0XHRzY3JvbGxNaW51cyA9IDE5MDtcblx0XHRcdH1cdFx0XG5cdFx0XHRcblx0XHRcdCQoJy5teS1iYWxhbmNlICNzdGFydE92ZXJMb3lhbHR5Jykub24oJ2NsaWNrJywgIGZ1bmN0aW9uKCkge1x0XHRcdFx0XHRcdFxuXHRcdFx0XHRjbGVhckxveWFsdHlGb3JtKCk7XG5cdFx0XHRcdGlmIChzY3JvbGxNaW51cyA+IDApIHtcblx0XHRcdFx0XHQkKCdodG1sLGJvZHknKS5hbmltYXRlKHtzY3JvbGxUb3A6ICQoXCIudGFiXCIpLm9mZnNldCgpLnRvcCAtIHNjcm9sbE1pbnVzfSwgMjAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdCQoJyNsb3lhbHR5Q2hlY2tCYWxhbmNlJykub24oJ2NoYW5nZScsICdpbnB1dC5pbnB1dC10ZXh0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggJCgnI2ZpZWxkTG95YWx0eU51bWJlcicpLnZhbCgpIHx8ICQoJyNmaWVsZExveWFsdHlFbWFpbCcpLnZhbCgpICkge1xuXHRcdFx0XHRcdGlmICggJCgnI2ZpZWxkTG95YWx0eVppcGNvZGUnKS52YWwoKSB8fCAkKCcjZmllbGRMb3lhbHR5UGhvbmUnKS52YWwoKSApe1x0XHRcdFx0XHRcblx0XHRcdFx0XHRcdCQoJyNzZW5kTG95YWx0eUlucXVpcnknKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFxuXHRcdFx0JGxveWFsdHlDaGVja0Zvcm0uZmluZCgnaW5wdXQjc2VuZExveWFsdHlJbnF1aXJ5Jykub24oJ2NsaWNrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XG5cdFx0XHRcdGlmICghJGxveWFsdHlDaGVja0Zvcm0udmFsaWQoKSkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR1cmw6IFVybHMubG95YWx0eUNoZWNrLFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0J2xveWFsdHlOdW1iZXInOiAkbG95YWx0eUNoZWNrRm9ybS5maW5kKCcjZmllbGRMb3lhbHR5TnVtYmVyJykudmFsKCksXG5cdFx0XHRcdFx0XHQnbG95YWx0eUVtYWlsJzogJGxveWFsdHlDaGVja0Zvcm0uZmluZCgnI2ZpZWxkTG95YWx0eUVtYWlsJykudmFsKCksXG5cdFx0XHRcdFx0XHQnbG95YWx0eVppcCc6ICRsb3lhbHR5Q2hlY2tGb3JtLmZpbmQoJyNmaWVsZExveWFsdHlaaXBjb2RlJykudmFsKCksXG5cdFx0XHRcdFx0XHQnbG95YWx0eVBob25lJzogJGxveWFsdHlDaGVja0Zvcm0uZmluZCgnI2ZpZWxkTG95YWx0eVBob25lJykudmFsKClcblx0XHRcdFx0XHR9LFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHRpZiAoKCdlcnJvcicgaW4gZGF0YSAmJiBkYXRhWydlcnJvciddKSkge1xuXHRcdFx0XHRcdFx0XHQkKCcubG95YWx0eS1lcnJvcicpLnRleHQoZGF0YS5tZXNzYWdlKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0cmVuZGVyTG95YWx0eUNoZWNrUmVzdWx0cyhkYXRhLnN0YXR1cyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyTG95YWx0eUNoZWNrUmVzdWx0cyhkYXRhKSB7XG5cdHZhciBvcHRpblN0YXR1cyA9IGRhdGEub3B0SW47XG5cdHZhciBjdXJyZW50U2l0ZSA9ICcnO1xuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcbiAgICBcdGN1cnJlbnRTaXRlID0gUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuTm90T3B0ZWRJblNIRVA7XG4gICAgfVxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcbiAgICBcdGN1cnJlbnRTaXRlID0gUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuTm90T3B0ZWRJbkNPO1xuICAgIH1cblx0XG5cdGlmIChvcHRpblN0YXR1cyl7XG5cdFx0JCgnLmNoZWNrLW15LWJhbGFuY2UnKS5oaWRlKCk7XG5cdFx0JCgnLm15LWJhbGFuY2UnKS5yZW1vdmVDbGFzcygnaGlkZGVuJykuc2hvdygpO1xuXHRcdCQoJy5sb3lhbHR5LW51bWJlciBzcGFuJykudGV4dChkYXRhLmxveWFsdHlNZW1iZXJOdW1iZXIpO1xuXHRcdCQoJy5jdXJyZW50LXBvaW50cyBzcGFuJykudGV4dChNYXRoLmZsb29yKGRhdGEucG9pbnRzKSk7XG5cdFx0JCgnLmF2YWlsYWJsZS1yZXdhcmRzIHNwYW4nKS50ZXh0KFwiJFwiICsgZGF0YS50b3RhbFJld2FyZHMpO1xuXHRcdHZhciBkZXRhaWxzID0gJyc7XG5cdFx0dmFyIHZvdWNoZXJzID0gZGF0YS5yZXdhcmRJbmZvO1xuXHRcdFxuXHRcdHZvdWNoZXJzLmZvckVhY2goZnVuY3Rpb24odm91Y2hlcil7XG5cdFx0XHRkZXRhaWxzICs9ICc8ZGl2IGNsYXNzPVwidm91Y2hlclwiPjxzcGFuIGNsYXNzPVwicmV3YXJkLWFtb3VudFwiPlJld2FyZCBBbW91bnQ6IDxiPiQnK3ZvdWNoZXIucmV3YXJkQW1vdW50Kyc8L2I+PC9zcGFuPjxzcGFuIGNsYXNzPVwiZXhwaXJhdGlvblwiPkV4cGlyYXRpb24gRGF0ZTogPGI+Jyt2b3VjaGVyLmV4cGlyYXRpb25EYXRlKyc8L2I+PC9zcGFuPjwvZGl2Pic7XG5cdFx0fSk7XG5cdFx0XG5cdFx0JCgnLmRldGFpbHMnKS5odG1sKGRldGFpbHMpO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5sb3lhbHR5LWVycm9yJykudGV4dChjdXJyZW50U2l0ZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdExveWFsdHlTb2NpYWwoKSB7XG5cdHZhciBoYW5kbGUgPSAnJztcblx0XG5cdCQoJ2JvZHknKS5vbignZm9jdXMnLCAnI2ZpZWxkTG95YWx0eVNvY2lhbEhhbmRsZUluc3RhZ3JhbScsIGZ1bmN0aW9uKCkge1xuXHRcdCQoJy5oYW5kbGUtZXJyb3InKS50ZXh0KCcnKTtcblx0fSk7XG5cblx0JCgnYm9keScpLm9uKCdjbGljaycsICcjdXBkYXRlSW5zdGFncmFtSGFuZGxlJywgZnVuY3Rpb24oKXtcblx0XHQkKCcuaGFuZGxlLWRpc3BsYXknKS5yZW1vdmVDbGFzcygnc2hvdy1oYW5kbGUnKS5hZGRDbGFzcygnc2hvdy1mb3JtJyk7XG5cdFx0JCgnLmZvcm0tZGlzcGxheScpLnJlbW92ZUNsYXNzKCdzaG93LWhhbmRsZScpLmFkZENsYXNzKCdzaG93LWZvcm0nKTtcblx0fSk7XG5cdFxuXHQkKCdib2R5Jykub24oJ2NsaWNrJywgJyNhZGRJbnN0YWdyYW1IYW5kbGUnLCBmdW5jdGlvbigpe1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0dmFyIGZvcm1WYWxpZGF0aW9uID0gdHJ1ZTtcblx0XHR2YXIgaGFuZGxlID0gJCgnI2ZpZWxkTG95YWx0eVNvY2lhbEhhbmRsZUluc3RhZ3JhbScpLnZhbCgpO1xuXHRcdHZhciByZWdleEhhbmRsZSA9IC9eQChbYS16QS1aMC05XXxbLl9dKD8hWy5fXSkpezIsMzB9JC87XG5cdFx0aWYgKFN0cmluZyhoYW5kbGUpLm1hdGNoKHJlZ2V4SGFuZGxlKSA9PSBudWxsICkge1xuXHRcdFx0Zm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoZm9ybVZhbGlkYXRpb24pIHtcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLmxveWFsdHlPcHRpbixcblx0XHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHQnZW1haWwnOiAkKCcuc2V0dGluZ3MtLWxveWFsdHknKS5hdHRyKCdkYXRhLWVtYWlsJyksXG5cdFx0XHRcdFx0J2R3Q3VzdG9tZXJJRCc6ICQoJy5zZXR0aW5ncy0tbG95YWx0eScpLmF0dHIoJ2RhdGEtZHdpZCcpLFxuXHRcdFx0XHRcdCdpbnN0YUhhbmRsZSc6IGhhbmRsZSxcblx0XHRcdFx0XHQnb3B0U3RhdHVzJzogJCgnLnNldHRpbmdzLS1sb3lhbHR5JykuYXR0cignZGF0YS1vcHRpbicpXG5cdFx0XHRcdH0sXHRcdFx0XHRcdFx0XG5cdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKCgnZXJyb3InIGluIGRhdGEgJiYgZGF0YVsnZXJyb3InXSkpIHtcblx0XHRcdFx0XHRcdCQoJy5oYW5kbGUtZXJyb3InKS50ZXh0KGRhdGEubWVzc2FnZSk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0JCgnLmhhbmRsZS1kaXNwbGF5JykucmVtb3ZlQ2xhc3MoJ3Nob3ctZm9ybScpLmFkZENsYXNzKCdzaG93LWhhbmRsZScpO1xuXHRcdFx0XHRcdFx0JCgnLmhhbmRsZS1kaXNwbGF5IC52YWx1ZScpLnRleHQoaGFuZGxlKTtcblx0XHRcdFx0XHRcdCQoJy5mb3JtLWRpc3BsYXknKS5yZW1vdmVDbGFzcygnc2hvdy1mb3JtJykuYWRkQ2xhc3MoJ3Nob3ctaGFuZGxlJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmhhbmRsZS1lcnJvcicpLnRleHQoJ1BsZWFzZSBlbnRlciBhIHZhbGlkIHNvY2lhbCBoYW5kbGUuJyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdEFkZHJlc3NGb3JtRXZlbnRzKCkge1xuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpe1xuXHRcdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnI2R3ZnJtX3Byb2ZpbGVfYWRkcmVzc19jb3VudHJ5JywgZnVuY3Rpb24oKXtcblx0XHRcdHJlbmRlck9wdGlvbnMoJyNkd2ZybV9wcm9maWxlX2FkZHJlc3Nfc3RhdGVzX3N0YXRlJywgJyNkd2ZybV9wcm9maWxlX2FkZHJlc3NfY291bnRyeScpO1xuXHRcdFx0dmFyICRpbml0aWFsU3RhdGUgPSAkKCcjZHdmcm1fcHJvZmlsZV9hZGRyZXNzX3N0YXRlc19zdGF0ZV9zYm0nKTtcblx0XHRcdFxuXHRcdFx0aWYgKCRpbml0aWFsU3RhdGUubGVuZ3RoID4gMCAmJiAkaW5pdGlhbFN0YXRlLnZhbCgpICE9ICcnKSB7XG5cdFx0XHRcdCQoJyNkd2ZybV9wcm9maWxlX2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykudmFsKCRpbml0aWFsU3RhdGUudmFsKCkpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdCQoJyNkd2ZybV9wcm9maWxlX2FkZHJlc3NfY291bnRyeScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuZmluZC1tb3JlLXN0b3JlcyBhJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0ZmluZE1vcmVTdG9yZXMuaW5pdGlhbGl6ZSh7IHZpZXc6ICdhY2NvdW50JyB9KTtcblx0XHR9KTtcblx0XHRcblx0XHQkKGRvY3VtZW50KS5vbignb3BjLlNldFNoaXBwaW5nQWRkcmVzcycsIGZ1bmN0aW9uIChlLCBhZGRyZXNzKSB7XG5cdFx0XHR2YXIgJGNsb3Nlc3RTdG9yZXMgPSAkKCcjY2xvc2VzdFN0b3JlcycpO1xuXHRcdFx0dmFyICRtYWtlVGhpc015c3RvcmUgPSAkKCcjc3RvcmVDb250cm9scycpLmZpbmQoJ1tkYXRhLWFjdGlvbj1cIm1ha2V0aGlzbXlzdG9yZVwiXScpO1xuXHRcdFx0XG5cdFx0XHQkY2xvc2VzdFN0b3Jlcy5maW5kKCdvcHRpb24uZmluZC1tb3JlLXN0b3JlcycpLnJlbW92ZSgpO1xuXHRcdFx0aWYgKCRjbG9zZXN0U3RvcmVzLmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBhZGRyZXNzLnN0b3JlSWQgKyAnXCJdJykubGVuZ3RoID09IDApIHtcblx0XHRcdFx0JGNsb3Nlc3RTdG9yZXMuZmluZCgnb3B0aW9uJykuZmlyc3QoKS5hZnRlcignPG9wdGlvbiBjbGFzcz1cImZpbmQtbW9yZS1zdG9yZXNcIiB2YWx1ZT1cIicgKyBhZGRyZXNzLnN0b3JlSWQgKyAnXCI+JyArIGFkZHJlc3MuZmlyc3ROYW1lICsgJyAtICcgKyBhZGRyZXNzLmxhYmVsVGV4dCArICc8L29wdGlvbj4nKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JGNsb3Nlc3RTdG9yZXMudmFsKGFkZHJlc3Muc3RvcmVJZCk7XG5cdFx0XHQkY2xvc2VzdFN0b3Jlcy50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdGlmICgkbWFrZVRoaXNNeXN0b3JlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JG1ha2VUaGlzTXlzdG9yZS50cmlnZ2VyKCdjbGljaycpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5hZGRyZXNzLXRpbGUgLmFkZHJlc3MtZGVsZXRlJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIWNvbmZpcm0oU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ09ORklSTV9ERUxFVEUsIFJlc291cmNlcy5USVRMRV9BRERSRVNTKSkpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gdmVyaWZ5QWNjb3VudENvZGUoKSB7ICBcblx0Ly8gJ2VudGVyLWNvZGUnIHJ1bGVzIHdpbGwgYmUgYXBwbGllZCB0byByZXdhcmRzIHZlcmlmaWNhdGlvbiBwYWdlIHdpdGggdGhpcyBjb2RlLiBTZWUgbG9naW5EaWFsb2cuanMgZm9yIHRoZSBydWxlcyBhZGRlZCBhZnRlciBhY2NvdW50IGRpYWxvZyBpcyBvcGVuZWQuXHRcblx0JCgnI3ZlcmlmeS1jb2RlJykuZmluZCgnI2VudGVyLWNvZGUnKS5ydWxlcygnYWRkJywge1xuXHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdGRpZ2l0czogdHJ1ZSxcblx0XHRtaW5sZW5ndGg6IDYsXG5cdFx0bWVzc2FnZXM6IHtcblx0XHRcdHJlcXVpcmVkOiBSZXNvdXJjZXMuVkFMSURBVEVfQ09ERSxcblx0XHRcdG1pbmxlbmd0aDogUmVzb3VyY2VzLlZBTElEQVRFX0NPREVcblx0XHR9LFxuXHRcdG5vcm1hbGl6ZXI6IGZ1bmN0aW9uKHZhbHVlKSB7XG5cdFx0XHRyZXR1cm4gJC50cmltKHZhbHVlKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vKiBPbiB0aGUgQWNjb3VudCByZWdpc3RyYXRpb24gKGFrYSBzZXR0aW5ncykgcGFnZSwgaG9vayB1cCB0aGUgZXZlbnQgaGFuZGxlciB0byB1cGRhdGUgdGhlIGhpZGRlbiBmb3JtIGZpZWxkXG4gKiBmb3IgJ015IFN0b3JlIE51bWJlcicgd2hlbiB0aGUgKGR5bmFtaWNhbGx5IHBvcHVsYXRlZCkgQ2xvc2VzdCBTdG9yZXMgZHJvcCBkb3duIGlzIGNoYW5nZWQuIFxuICogQWxzbywgc2V0IHRoZSB2YWx1ZSBvZiB0aGUgc2VsZWN0ZWQgb3B0aW9uIGluIHRoZSBkcm9wIGRvd24sIG9yIHRoZSB2YWx1ZSBpbiAnTXkgU3RvcmUgTnVtYmVyJ1xuICogYXBwcm9wcmlhdGVseSBvbiBsb2FkIChiYXNlZCBvbiBpZiBjcmVhdGluZyBhbiBBY2NvdW50IG9yIGVkaXRpbmcgb25lLiBcbiAqL1xuZnVuY3Rpb24gaW5pdENyZWF0ZUFjY291bnRFdmVudEhhbmRsZXJzKCl7XG5cdHZhciAkY2xvc2VzdFN0b3JlcyA9ICQoJyNjbG9zZXN0U3RvcmVzJyk7XG5cdHZhciAkc3RvcmVDb250cm9scyA9ICQoJyNzdG9yZUNvbnRyb2xzJyk7XG5cdGlmICgkY2xvc2VzdFN0b3JlcyAhPSB1bmRlZmluZWQgJiYgJGNsb3Nlc3RTdG9yZXMgIT0gbnVsbCl7XG5cdFx0dmFyIGxlbmd0aFN0b3JlcyA9ICRjbG9zZXN0U3RvcmVzLmZpbmQoJ29wdGlvbicpLmxlbmd0aDtcblx0XHRpZiAobGVuZ3RoU3RvcmVzID4gMCkge1xuXHRcdFx0dmFyIHN0b3JlZFZhbHVlID0gJCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbXlTdG9yZU51bWJlcicpLnZhbCgpO1xuXHRcdFx0JGNsb3Nlc3RTdG9yZXMub24oJ2NoYW5nZScsIGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0dmFyIG5ld1ZhbHVlID0gJCh0aGlzKS52YWwoKTtcblx0XHRcdFx0JCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbXlTdG9yZU51bWJlcicpLnZhbChuZXdWYWx1ZSk7XG5cdFx0XHRcdHVwZGF0ZVNlbGVjdGVkU3RvcmVQcmV2aWV3KCQoZS50YXJnZXQpLmZpbmQoJzpzZWxlY3RlZCcpKTtcblxuXHRcdFx0XHRpZiAoc3RvcmVkVmFsdWUgIT09IG5ld1ZhbHVlKSB7XG5cdFx0XHRcdFx0JHN0b3JlQ29udHJvbHMucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCRzdG9yZUNvbnRyb2xzLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdHNldFNlbGVjdGVkU3RvcmVEcm9wZG93bk9yTXlTdG9yZU51bWJlcigpO1xuXHRcdH1cblx0XHQkc3RvcmVDb250cm9scy5vbignY2xpY2snLCAnYScsIGZ1bmN0aW9uKGUpIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHZhciBzdG9yZUlkID0gJCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbXlTdG9yZU51bWJlcicpLnZhbCgpO1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsIDogVXJscy5hc3NpZ25TdG9yZUlkLFxuXHRcdFx0XHRkYXRhIDogeyBzdG9yZV9pZCA6IHN0b3JlSWQgfSxcblx0XHRcdFx0bWV0aG9kIDogXCJQT1NUXCIsXG5cdFx0XHRcdGRhdGFUeXBlIDogXCJKU09OXCIsXG5cdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0aWYgKCAnc3VjY2VzcycgaW4gZGF0YSAmJiBkYXRhWydzdWNjZXNzJ10gPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdGxvY2F0aW9uLnJlbG9hZCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cbn1cblxuLyogQ2hlY2sgYW5kIHNlZSBpZiB0aGUgcHJvZmlsZSBoYXMgYSB2YWx1ZSBmb3IgJ015IFN0b3JlIE51bWJlcicsIHdoaWNoIGl0IG1pZ2h0IGlmIG9uIHRoZSBBY2NvdW50IEVkaXQgcGFnZS5cbiAqIElmIHNvLCB0aGVuIHNldCB0aGUgc3RvcmUgZHJvcCBkb3duIHRvIHRoZSBzdG9yZSBvbiB0aGUgcHJvZmlsZS5cbiAqIElmIG5vdCwgdGhlbiBzZXQgdGhlIGhpZGRlbiBmb3JtIGZpZWxkIGZvciAnTXkgU3RvcmUgTnVtYmVyJyB0byB0aGUgc2VsZWN0ZWQgc3RvcmUgaW4gdGhlIGRyb3AgZG93biwgd2hpY2ggd2lsbCBiZSB0aGUgZmlyc3Qgb25lIHdoZW4gb24gdGhlIENyZWF0ZSBBY2NvdW50IHBhZ2UuICBcbiAqL1xuZnVuY3Rpb24gc2V0U2VsZWN0ZWRTdG9yZURyb3Bkb3duT3JNeVN0b3JlTnVtYmVyKCkge1xuXHR2YXIgJG15U3RvcmVOdW1iZXJTZWxlY3RlZCA9ICQoJyNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX215U3RvcmVOdW1iZXInKTtcblx0aWYgKCRteVN0b3JlTnVtYmVyU2VsZWN0ZWQgIT0gdW5kZWZpbmVkICYmICRteVN0b3JlTnVtYmVyU2VsZWN0ZWQgIT0gbnVsbCl7XG5cdFx0dmFyIGN1cnJlbnRNeVN0b3JlVmFsdWUgPSAkbXlTdG9yZU51bWJlclNlbGVjdGVkLnZhbCgpOyBcblx0XHRpZiAoY3VycmVudE15U3RvcmVWYWx1ZSA9PSB1bmRlZmluZWQgfHwgY3VycmVudE15U3RvcmVWYWx1ZSA9PSBudWxsIHx8IGN1cnJlbnRNeVN0b3JlVmFsdWUubGVuZ3RoID09IDApe1xuXHRcdFx0JG15U3RvcmVOdW1iZXJTZWxlY3RlZC52YWwoJCgnI2Nsb3Nlc3RTdG9yZXMnKS52YWwoKSk7XHRcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI2Nsb3Nlc3RTdG9yZXMgb3B0aW9uW3ZhbHVlPScgKyBjdXJyZW50TXlTdG9yZVZhbHVlICsgJ10nKS5hdHRyKCdzZWxlY3RlZCcsJ3NlbGVjdGVkJyk7XG5cdFx0XHR1cGRhdGVTZWxlY3RlZFN0b3JlUHJldmlldygkKCcjY2xvc2VzdFN0b3JlcyBvcHRpb25bdmFsdWU9JyArIGN1cnJlbnRNeVN0b3JlVmFsdWUgKyAnXScpKTtcblx0XHR9XG4gICAgICAgICQoJyNzdG9yZVNlY3Rpb24nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlU2VsZWN0ZWRTdG9yZVByZXZpZXcoJHN0b3JlKSB7XG5cdGlmICgkKCcjc2VsZWN0ZWRTdG9yZScpLmxlbmd0aCA+IDApIHtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAubmFtZScpLnRleHQoJHN0b3JlLmRhdGEoJ25hbWUnKSk7XG5cdFx0JCgnI3NlbGVjdGVkU3RvcmUgLmFkZHJlc3MxJykudGV4dCgkc3RvcmUuZGF0YSgnYWRkcmVzczEnKSk7XG5cdFx0aWYgKCRzdG9yZS5kYXRhKCdhZGRyZXNzMicpICYmICRzdG9yZS5kYXRhKCdhZGRyZXNzMicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJyNzZWxlY3RlZFN0b3JlIC5hZGRyZXNzMicpLnRleHQoJHN0b3JlLmRhdGEoJ2FkZHJlc3MyJykpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI3NlbGVjdGVkU3RvcmUgLmFkZHJlc3MyJykudGV4dCgnJykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdH1cblx0XHRcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAuY2l0eScpLnRleHQoJHN0b3JlLmRhdGEoJ2NpdHknKSk7XG5cdFx0JCgnI3NlbGVjdGVkU3RvcmUgLnN0YXRlQ29kZScpLnRleHQoJHN0b3JlLmRhdGEoJ3N0YXRlY29kZScpKTtcblx0XHQkKCcjc2VsZWN0ZWRTdG9yZSAucG9zdGFsQ29kZScpLnRleHQoJHN0b3JlLmRhdGEoJ3Bvc3RhbGNvZGUnKSk7XG5cdFx0JCgnI3NlbGVjdGVkU3RvcmUgLmNvdW50cnlDb2RlJykudGV4dCgkc3RvcmUuZGF0YSgnY291bnRyeWNvZGUnKSk7XG5cdFx0JCgnI3NlbGVjdGVkU3RvcmUgLnBob25lJykudGV4dCgkc3RvcmUuZGF0YSgncGhvbmUnKSk7XG5cdH1cbn1cblxuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uIChvcHRpb25zUGFyYW1ldGVyKSB7XG5cdFx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cgPSByZXF1aXJlKCcuLi9Mb2IvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nJyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0XHRBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nID0gcmVxdWlyZSgnLi4vTG9iL0FkZHJlc3NBdXRvY29tcGxldGUvQWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZycpO1xuXHRcdH1cblxuICAgICAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgICAgIGdpZnRjZXJ0LmluaXQoKTtcbiAgICAgICAgaW5pdEFkZHJlc3NGb3JtRXZlbnRzKCk7XG4gICAgICAgIGluaXRSZXdhcmRSZWdpc3RlckZvcm0oKTtcbiAgICAgICAgaW5pdFJld2FyZENoZWNrRm9ybSgpO1xuICAgICAgICBpbml0TG95YWx0eUNoZWNrRm9ybSgpO1xuICAgICAgICBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcbiAgICAgICAgXHRpbml0RGlzcGxheVJld2FyZHNEYXRhKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUyB8fCBwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykgJiYgU2l0ZVByZWZlcmVuY2VzLkxPWUFMVFlfRU5BQkxFRCkge1xuICAgICAgICBcdGluaXREaXNwbGF5TG95YWx0eURhdGEoKTtcbiAgICAgICAgXHRpbml0TG95YWx0eVNvY2lhbCgpO1xuICAgICAgICB9XG4gICAgICAgIGluaXRSZXdhcmRzQXR0YWNoZWQoKTtcblx0XHR2ZXJpZnlBY2NvdW50Q29kZSgpO1xuICAgICAgICBvcmRlclN0YXR1c0Zvcm0uaW5pdGlhbGl6ZSgkKCcjZHdmcm1fb3JkZXJ0cmFjaycpKTsgICAgICBcbiAgICB9LFxuICAgIGluaXRDYXJ0TG9naW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaW5pdExvZ2luUGFnZSgpO1xuICAgICAgICBpbml0UmV3YXJkc1BhZ2UoKTtcbiAgICB9XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJvcGlzID0gcmVxdWlyZSgnLi4vYm9waXMvY29tcG9uZW50cy9Mb2NhdGlvblNlYXJjaCcpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuXHR2YXIgYm9waXNXYXlzVG9TaG9wID0gbmV3IGJvcGlzKCk7XG5cdHZhciBib3Bpc0Zvb3RlciA9IG5ldyBib3BpcygpO1xuXHRcblx0aWYgKCQoJy53YXlzdG9zaG9wIC5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5sZW5ndGggPiAwKSB7XG5cdFx0Ym9waXNXYXlzVG9TaG9wLmluaXRpYWxpemUoJCgnLndheXN0b3Nob3AgLmJvcGlzLXN0b3JlLXNlYXJjaCcpLCAkLmV4dGVuZChvcHRpb25zLkJvcGlzLCB7IENoYW5uZWw6IG9wdGlvbnMuQ2hhbm5lbCB9KSk7XG5cdH1cblx0aWYgKCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gtY29udGFpbmVyIC5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5sZW5ndGggPiAwKSB7XG5cdFx0Ym9waXNGb290ZXIuaW5pdGlhbGl6ZSgkKCcuYm9waXMtc3RvcmUtc2VhcmNoLWNvbnRhaW5lciAuYm9waXMtc3RvcmUtc2VhcmNoJyksICQuZXh0ZW5kKG9wdGlvbnMuQm9waXMsIHsgQ2hhbm5lbDogb3B0aW9ucy5DaGFubmVsIH0pKTtcblx0fVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcbnZhciBWYWxpZGF0aW9uU2V0dGluZ3MgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5TZXR0aW5ncztcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyO1xudmFyICRjb250YWluZXI7XG52YXIgJHN0ZXA7XG52YXIgdGVtcGxhdGVzO1xudmFyIGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncztcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0aWYgKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0XHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0fSBlbHNlIHtcblx0XHRvcHRpb25zID0ge307XG5cdH1cblx0JGNvbnRhaW5lciA9ICQoJy5ib290ZmluZGVyJyk7XG5cdCRzdGVwID0gJGNvbnRhaW5lci5maW5kKCdbc3RlcF0nKTtcblx0ZGF0YUJ1ZmZlciA9IHtcblx0XHRzdGVwOiAwLFxuXHRcdHN0ZXBEYXRhOiB7fVxuXHR9O1xuXHR0ZW1wbGF0ZXMgPSB7XG5cdFx0c2VjdGlvbkNvbnRhaW5lcjogXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9vdGZpbmRlci1zZWN0aW9uLWNvbnRhaW5lcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSxcblx0XHRzZWN0aW9uOiBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib290ZmluZGVyLXNlY3Rpb24nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyksXG5cdFx0b3B0aW9uOiBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1ib290ZmluZGVyLW9wdGlvbicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSxcblx0XHRvcHRpb25JbWFnZTogXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9vdGZpbmRlci1vcHRpb24taW1hZ2UnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyksXG5cdFx0cmVzdWx0czogXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9vdGZpbmRlci1yZXN1bHRzJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpXG5cdH1cblx0bG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2Vcblx0fTtcblx0XG5cdCRjb250YWluZXIub2ZmKCdjbGljay5Cb290RmluZGVyU3RlcERlbHRhJykub24oJ2NsaWNrLkJvb3RGaW5kZXJTdGVwRGVsdGEnLCAnW3N0ZXAtZGVsdGFdJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBzdGVwRGVsdGEgPSBwYXJzZUludCgkdGhpcy5hdHRyKCdzdGVwLWRlbHRhJyksIDEwKTtcblx0XHRkYXRhQnVmZmVyLnN0ZXBEZWx0YSA9IHN0ZXBEZWx0YTtcblx0XHR2YXIgc3RlcCA9IGRhdGFCdWZmZXIuc3RlcCArIGRhdGFCdWZmZXIuc3RlcERlbHRhO1xuXHRcdGlmIChzdGVwID49IDAgJiYgc3RlcCA8PSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMubGVuZ3RoKSB7XG5cdFx0XHRkYXRhQnVmZmVyLnN0ZXAgPSBzdGVwO1xuXHRcdH1cblx0XHRyZW5kZXIoKTtcblx0fSk7XG5cblx0Ly8gJGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJTdGVwSW5kZXgnKS5vbignY2xpY2suQm9vdEZpbmRlclN0ZXBJbmRleCcsICdbc3RlcC1pbmRleF0nLCBmdW5jdGlvbihldmVudCkge1xuXHQvLyBcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdC8vIFx0dmFyIHN0ZXAgPSBwYXJzZUludCgkdGhpcy5hdHRyKCdzdGVwLWluZGV4JyksIDEwKTtcblx0Ly8gXHRpZiAoc3RlcCA+PSAwICYmIHN0ZXAgPD0gb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzLmxlbmd0aCkge1xuXHQvLyBcdFx0ZGF0YUJ1ZmZlci5zdGVwID0gc3RlcDtcblx0Ly8gXHR9XG5cdC8vIFx0cmVuZGVyKCk7XG5cdC8vIH0pO1xuXG5cdCRjb250YWluZXIub2ZmKCdjbGljay5Cb290RmluZGVyU3RlcE9wdGlvbnMnKS5vbignY2xpY2suQm9vdEZpbmRlclN0ZXBPcHRpb25zJywgJ1tzdGVwXSAub3B0aW9ucyAub3B0aW9uJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBzZWN0aW9uSW5kZXggPSBwYXJzZUludCgkdGhpcy5jbG9zZXN0KCdbc2VjdGlvbl0nKS5hdHRyKCdzZWN0aW9uJyksIDEwKTtcblx0XHRpZiAoJHRoaXMuaGFzQ2xhc3MoJ3NlbGVjdGVkJykgJiYgIW9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uU2VsZWN0UmVxdWlyZWQpIHtcblx0XHRcdCR0aGlzLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xuXHRcdFx0aWYgKGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF1bc2VjdGlvbkluZGV4XSkge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRJbmRleCA9IGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXVtzZWN0aW9uSW5kZXhdLmluZGV4T2YoJHRoaXMuYXR0cigndmFsdWUnKSk7XG5cdFx0XHRcdGlmIChzZWxlY3RlZEluZGV4ID4gLTEpIHtcblx0XHRcdFx0XHRkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF1bc2VjdGlvbkluZGV4XS5zcGxpY2Uoc2VsZWN0ZWRJbmRleCwgMSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmIChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlJlZmluZW1lbnQgPT0gJ3NpemUnIHx8IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uUmVmaW5lbWVudCA9PSAnd2lkdGgnKSB7XG5cdFx0XHRcdHVwZGF0ZVNpemVzKHNlY3Rpb25JbmRleCwgb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICghb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5TZWxlY3RNdWx0aXBsZSkge1xuXHRcdFx0XHQkdGhpcy5jbG9zZXN0KCcub3B0aW9ucycpLmZpbmQoJy5vcHRpb24nKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcblx0XHRcdH1cblx0XHRcdGlmIChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlNlbGVjdFJlc2V0ICYmIChkYXRhQnVmZmVyLnN0ZXAgKyAxKSA8PSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMubGVuZ3RoKSB7XG5cdFx0XHRcdGZvciAodmFyIHN0ZXBJbmRleCA9IChkYXRhQnVmZmVyLnN0ZXAgKyAxKTsgc3RlcEluZGV4IDw9IG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcy5sZW5ndGg7IHN0ZXBJbmRleCsrKSB7XG5cdFx0XHRcdFx0ZGF0YUJ1ZmZlci5zdGVwRGF0YVtzdGVwSW5kZXhdID0ge307XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdCR0aGlzLmFkZENsYXNzKCdzZWxlY3RlZCcpO1xuXHRcdFx0aWYgKCFkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF0pIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdID0ge31cblx0XHRcdH1cblx0XHRcdGlmICghZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdW3NlY3Rpb25JbmRleF0gfHwgIW9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uU2VsZWN0TXVsdGlwbGUpIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlci5zdGVwRGF0YVtkYXRhQnVmZmVyLnN0ZXBdW3NlY3Rpb25JbmRleF0gPSBbXTtcblx0XHRcdH1cblx0XHRcdHZhciBzZWN0aW9uRGF0YSA9IGRhdGFCdWZmZXIuc3RlcERhdGFbZGF0YUJ1ZmZlci5zdGVwXVtzZWN0aW9uSW5kZXhdO1xuXHRcdFx0c2VjdGlvbkRhdGFbc2VjdGlvbkRhdGEubGVuZ3RoXSA9ICR0aGlzLmF0dHIoJ3ZhbHVlJyk7XG5cdFx0XHRpZiAob3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5SZWZpbmVtZW50ID09ICdzaXplJyB8fCBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlJlZmluZW1lbnQgPT0gJ3dpZHRoJykge1xuXHRcdFx0XHR1cGRhdGVTaXplcyhzZWN0aW9uSW5kZXgsIHNlY3Rpb25EYXRhKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIW9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0uU2VsZWN0TXVsdGlwbGUgJiYgJHRoaXMuY2xvc2VzdCgnLm9wdGlvbnMnKS5maW5kKCcuc2VsZWN0ZWQnKS5sZW5ndGggPiAwICYmIGRhdGFCdWZmZXIuc3RlcCA8IChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMubGVuZ3RoIC0gMSkpIHtcblx0XHRcdGRhdGFCdWZmZXIuc3RlcERlbHRhID0gMTtcblx0XHRcdGRhdGFCdWZmZXIuc3RlcCArPSBkYXRhQnVmZmVyLnN0ZXBEZWx0YTtcblx0XHRcdHJlbmRlcigpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNvbnRhaW5lci5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJTZW5kUmVzdWx0c0VtYWlsJykub24oJ2NsaWNrLkJvb3RGaW5kZXJTZW5kUmVzdWx0c0VtYWlsJywgJy5zZW5kLXJlc3VsdHMtZW1haWwnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGZvcm0gPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG5cdFx0aWYgKGRhdGFCdWZmZXIuJGVtYWlsRm9ybSAmJiBkYXRhQnVmZmVyLiRlbWFpbEZvcm0udmFsaWQoKSkge1xuXHRcdFx0dmFyIHVybCA9IGJ1aWxkVXJsKCk7XG5cdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnYm9vdGZpbmRlcmVtYWlsJyk7XG5cblx0XHRcdHZhciBwYXlsb2FkID0ge1xuXHRcdFx0XHRlbWFpbDogJGZvcm0uZmluZCgnaW5wdXRbdHlwZT1cImVtYWlsXCJdJykudmFsKCksXG5cdFx0XHRcdHVybDogdXJsXG5cdFx0XHR9XG5cdFx0XHQkc3RlcC5sb2FkaW5nKCQuZXh0ZW5kKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncywge1xuXHRcdFx0XHRJc0xhYmVsU2hvd246IHRydWUsXG5cdFx0XHRcdENvbnRlbnQ6ICdTZW5kaW5nIEVtYWlsLi4uJ1xuXHRcdFx0fSkpO1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dHlwZTogJ3Bvc3QnLFxuXHRcdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0XHR1cmw6IGJ1aWxkVXJsKFVybHMuQm9vdEZpbmRlci5TZW5kUmVzdWx0c0VtYWlsKSxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChkYXRhICYmIGRhdGEuc3VjY2Vzcykge1xuXHRcdFx0XHRcdFx0JHN0ZXAuZmluZCgnLmxvYWRpbmctaW5kaWNhdG9yJykuZmluZCgnLmNvbnRlbnQnKS5odG1sKCdFbWFpbCBTZW50ITxici8+TG9hZGluZyBSZXN1bHRzLi4uJyk7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24gPSAkKCcudmlldy1yZXN1bHRzJykuYXR0cignaHJlZicpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkY29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpLmh0bWwoJzxzcGFuIGNsYXNzPVwiZXJyb3JcIj5BbiBlcnJvciBvY2N1cnJlZCBzZW5kaW5nIHRoZSBlbWFpbC4gUGxlYXNlIHRyeSBhZ2Fpbi48L3NwYW4+Jyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xuXG5cdCRjb250YWluZXIub2ZmKCdjbGljay5Cb290RmluZGVyVmlld1Jlc3VsdHMnKS5vbignY2xpY2suQm9vdEZpbmRlclZpZXdSZXN1bHRzJywgJy52aWV3LXJlc3VsdHMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICghJHN0ZXAuYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHQkc3RlcC5sb2FkaW5nKCQuZXh0ZW5kKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncywge1xuXHRcdFx0XHRDb250ZW50OiAnTG9hZGluZyBSZXN1bHRzLi4uJ1xuXHRcdFx0fSkpO1xuXHRcdFx0dmFyIHVybCA9IGJ1aWxkVXJsKCk7XG5cdFx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnYm9vdGZpbmRlcnZpZXdyZXN1bHRzJyk7XG5cdFx0XHR3aW5kb3cubG9jYXRpb24gPSB1cmw7XG5cdFx0fVxuXHR9KTtcblxuXHQkKHdpbmRvdykub2ZmKCdsb2FkLkJvb3RGaW5kZXIgcmVzaXplLkJvb3RGaW5kZXInKS5vbignbG9hZC5Cb290RmluZGVyIHJlc2l6ZS5Cb290RmluZGVyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoJCh3aW5kb3cpLm91dGVyV2lkdGgoKSA8PSA3NjgpIHtcblx0XHRcdCRjb250YWluZXIuY3NzKCdtaW4taGVpZ2h0JywgJCh3aW5kb3cpLm91dGVySGVpZ2h0KCkgLSAkKCcuaGVhZGVyLXdyYXBwZXInKS5oZWlnaHQoKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRjb250YWluZXIuY3NzKCdtaW4taGVpZ2h0JywgMCk7XG5cdFx0fVxuXHR9KTtcblxuXHR2YXIgc3RlcExpc3RIdG1sID0gJyc7XG5cdGZvciAodmFyIHN0ZXBJbmRleCBpbiBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHMpIHtcblx0XHRzdGVwTGlzdEh0bWwgKz0gJzxhIHN0ZXAtaW5kZXg9XCInICsgc3RlcEluZGV4ICsgJ1wiPjwvYT4nO1xuXHR9XG5cdCRjb250YWluZXIuZmluZCgnLnN0ZXAtbGlzdCcpLmh0bWwoc3RlcExpc3RIdG1sKTtcblx0cmVuZGVyKCk7XG59O1xuXG5mdW5jdGlvbiByZW5kZXIoKSB7XG5cdCRzdGVwLmhlaWdodCgkc3RlcC5vdXRlckhlaWdodCgpKTtcblx0JHN0ZXAuaHRtbCgnJyk7XG5cdCRzdGVwLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0JCgnaHRtbCcpLmFuaW1hdGUoeyBzY3JvbGxUb3A6IDAgfSwgMjUwKTtcblx0aWYgKGRhdGFCdWZmZXIuc3RlcCA9PSAob3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzLmxlbmd0aCAtIDEpKSB7XG5cdFx0JGNvbnRhaW5lci5maW5kKCcubmV4dCcpLmhpZGUoKTtcblx0XHQkY29udGFpbmVyLmZpbmQoJy52aWV3LXJlc3VsdHMnKS5zaG93KCk7XG5cdH0gZWxzZSB7XG5cdFx0JGNvbnRhaW5lci5maW5kKCcubmV4dCcpLnNob3coKTtcblx0XHQkY29udGFpbmVyLmZpbmQoJy52aWV3LXJlc3VsdHMnKS5oaWRlKCk7XG5cdH1cblx0cmVuZGVyU3RlcCgpO1xuXHRzZW5kRGF0YUxheWVyKCk7XG5cdGlmICgkY29udGFpbmVyLmhhc0NsYXNzKCdyZXN1bHRzJykpIHtcblx0XHQkY29udGFpbmVyLnJlbW92ZUNsYXNzKCdyZXN1bHRzJyk7XG5cdH1cblxuXHQkY29udGFpbmVyLmZpbmQoJy5zdGVwLWxpc3QgYScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0JGNvbnRhaW5lci5maW5kKCcuc3RlcC1saXN0IGE6bnRoLWNoaWxkKCcgKyAoZGF0YUJ1ZmZlci5zdGVwICsgMSkgKyAnKScpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0JGNvbnRhaW5lci5maW5kKCdbc3RlcF0nKS5hdHRyKCdzdGVwJywgZGF0YUJ1ZmZlci5zdGVwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlU2l6ZXMoc2VjdGlvbkluZGV4LCBzZWN0aW9uRGF0YSkge1xuXHRyZXR1cm4gZ2V0UmVmaW5lbWVudENvdW50c0ZvclNlY3Rpb24oc2VjdGlvbkluZGV4LCBzZWN0aW9uRGF0YSkudGhlbihmdW5jdGlvbihkYXRhKSB7XG5cdFx0aWYgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0gJiYgb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XS5SZWZpbmVtZW50ID09ICdzaXplJykge1xuXHRcdFx0dmFyICRzZWxlY3RlZExlbmd0aHMgPSAkKCdbc2VjdGlvbj1cIicgKyBzZWN0aW9uSW5kZXggKyAnXCJdIC5vcHRpb25zJykuZmluZCgnLm9wdGlvbi5zZWxlY3RlZCcpO1xuXHRcdFx0dmFyICR3aWR0aHMgPSAkKCdbc2VjdGlvbj1cIicgKyAoc2VjdGlvbkluZGV4ICsgMSkgKyAnXCJdIC5vcHRpb25zIC5vcHRpb24nKTtcblx0XHRcdGlmICgkc2VsZWN0ZWRMZW5ndGhzICYmICRzZWxlY3RlZExlbmd0aHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkd2lkdGhzLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdFx0XHQkc2VsZWN0ZWRMZW5ndGhzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0dmFyIHNlbGVjdGVkTGVuZ3RoID0gJCh0aGlzKS5hdHRyKCd2YWx1ZScpO1xuXHRcdFx0XHRcdCR3aWR0aHMuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHZhciB3aWR0aCA9ICQodGhpcykuYXR0cigndmFsdWUnKTtcblx0XHRcdFx0XHRcdHZhciBzaXplID0gc2VsZWN0ZWRMZW5ndGggKyAnICcgKyB3aWR0aDtcblx0XHRcdFx0XHRcdGlmIChkYXRhQnVmZmVyLlJlZmluZW1lbnRzICYmIGRhdGFCdWZmZXIuUmVmaW5lbWVudHMuc2l6ZSAmJiBkYXRhQnVmZmVyLlJlZmluZW1lbnRzLnNpemVbc2l6ZV0pIHtcblx0XHRcdFx0XHRcdFx0JHdpZHRocy5maWx0ZXIoJ1t2YWx1ZT1cIicgKyB3aWR0aCArICdcIl0nKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkd2lkdGhzLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAob3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnNbc2VjdGlvbkluZGV4XSAmJiBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdLlJlZmluZW1lbnQgPT0gJ3dpZHRoJykge1xuXHRcdFx0dmFyICRzZWxlY3RlZFdpZHRocyA9ICQoJ1tzZWN0aW9uPVwiJyArIHNlY3Rpb25JbmRleCArICdcIl0gLm9wdGlvbnMnKS5maW5kKCcub3B0aW9uLnNlbGVjdGVkJyk7XG5cdFx0XHR2YXIgJGxlbmd0aHMgPSAkKCdbc2VjdGlvbj1cIicgKyAoc2VjdGlvbkluZGV4IC0gMSkgKyAnXCJdIC5vcHRpb25zIC5vcHRpb24nKTtcblx0XHRcdGlmICgkc2VsZWN0ZWRXaWR0aHMgJiYgJHNlbGVjdGVkV2lkdGhzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JGxlbmd0aHMuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdCRzZWxlY3RlZFdpZHRocy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciBzZWxlY3RlZFdpZHRoID0gJCh0aGlzKS5hdHRyKCd2YWx1ZScpO1xuXHRcdFx0XHRcdCRsZW5ndGhzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgbGVuZ3RoID0gJCh0aGlzKS5hdHRyKCd2YWx1ZScpO1xuXHRcdFx0XHRcdFx0dmFyIHNpemUgPSBsZW5ndGggKyAnICcgKyBzZWxlY3RlZFdpZHRoO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGFCdWZmZXIuUmVmaW5lbWVudHMgJiYgZGF0YUJ1ZmZlci5SZWZpbmVtZW50cy5zaXplICYmIGRhdGFCdWZmZXIuUmVmaW5lbWVudHMuc2l6ZVtzaXplXSkge1xuXHRcdFx0XHRcdFx0XHQkbGVuZ3Rocy5maWx0ZXIoJ1t2YWx1ZT1cIicgKyBsZW5ndGggKyAnXCJdJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGxlbmd0aHMucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU3RlcCgpIHtcblx0dmFyIHN0ZXAgPSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXTtcblx0dmFyIHN0ZXBEYXRhO1xuXHRpZiAoZGF0YUJ1ZmZlci5zdGVwRGF0YSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF0pIHtcblx0IFx0c3RlcERhdGEgPSBkYXRhQnVmZmVyLnN0ZXBEYXRhW2RhdGFCdWZmZXIuc3RlcF07XG5cdH1cblx0ZGF0YUJ1ZmZlci5zZWN0aW9uUmVuZGVyQ291bnQgPSAwO1xuXHRmb3IgKHZhciBzZWN0aW9uSW5kZXggaW4gc3RlcC5TZWN0aW9ucykge1xuXHRcdHZhciBzZWN0aW9uID0gc3RlcC5TZWN0aW9uc1tzZWN0aW9uSW5kZXhdO1xuXHRcdHZhciBjb2x1bW5zID0gMTtcblx0XHRpZiAoc2VjdGlvbi5Db2x1bW5zKSB7XG5cdFx0XHRjb2x1bW5zID0gc2VjdGlvbi5Db2x1bW5zO1xuXHRcdH1cblx0XHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwXScpLmFwcGVuZCh0ZW1wbGF0ZXMuc2VjdGlvbkNvbnRhaW5lcih7XG5cdFx0XHRTZWN0aW9uOiBzZWN0aW9uSW5kZXgsXG5cdFx0XHRDb2x1bW5zOiBjb2x1bW5zXG5cdFx0fSkpO1xuXG5cdFx0dmFyIG9wdGlvbnNIdG1sID0gJyc7XG5cdFx0aWYgKHNlY3Rpb24uT3B0aW9ucykge1xuXHRcdFx0dmFyIHNlY3Rpb25PcHRpb25zO1xuXHRcdFx0aWYgKHR5cGVvZiBzZWN0aW9uLk9wdGlvbnMgPT0gJ29iamVjdCcgJiYgc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblN0ZXAgIT0gdW5kZWZpbmVkICYmIHNlY3Rpb24uT3B0aW9uc1JlbGF0ZWRTZWxlY3Rpb25TZWN0aW9uICE9IHVuZGVmaW5lZCAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblN0ZXBdICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblN0ZXBdW3NlY3Rpb24uT3B0aW9uc1JlbGF0ZWRTZWxlY3Rpb25TZWN0aW9uXSkge1xuXHRcdFx0XHR2YXIgb3B0aW9uc1JlbGF0ZWRTZWxlY3Rpb25WYWx1ZSA9IGRhdGFCdWZmZXIuc3RlcERhdGFbc2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblN0ZXBdW3NlY3Rpb24uT3B0aW9uc1JlbGF0ZWRTZWxlY3Rpb25TZWN0aW9uXTtcblx0XHRcdFx0c2VjdGlvbk9wdGlvbnMgPSBzZWN0aW9uLk9wdGlvbnNbb3B0aW9uc1JlbGF0ZWRTZWxlY3Rpb25WYWx1ZV07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWN0aW9uT3B0aW9ucyA9IHNlY3Rpb24uT3B0aW9ucztcblx0XHRcdH1cblx0XHRcdGZvciAodmFyIG9wdGlvbkluZGV4IGluIHNlY3Rpb25PcHRpb25zKSB7XG5cdFx0XHRcdHZhciBvcHRpb24gPSBzZWN0aW9uT3B0aW9uc1tvcHRpb25JbmRleF07XG5cdFx0XHRcdGlmIChvcHRpb24uVGV4dCkge1xuXHRcdFx0XHRcdHZhciBjc3NDbGFzcyA9ICcnO1xuXHRcdFx0XHRcdGlmIChzdGVwRGF0YSAmJiBzdGVwRGF0YVtzZWN0aW9uSW5kZXhdICYmICdpbmRleE9mJyBpbiBzdGVwRGF0YVtzZWN0aW9uSW5kZXhdICYmIHN0ZXBEYXRhW3NlY3Rpb25JbmRleF0uaW5kZXhPZihvcHRpb24uVGV4dCkgPiAtMSkge1xuXHRcdFx0XHRcdFx0Y3NzQ2xhc3MgPSAnc2VsZWN0ZWQnO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdG9wdGlvbnNIdG1sICs9IHRlbXBsYXRlcy5vcHRpb24oe1xuXHRcdFx0XHRcdFx0SW1hZ2U6ICcnLFxuXHRcdFx0XHRcdFx0VGV4dDogb3B0aW9uLlRleHQsXG5cdFx0XHRcdFx0XHRWYWx1ZTogb3B0aW9uLlRleHQsXG5cdFx0XHRcdFx0XHRDc3NDbGFzczogY3NzQ2xhc3Ncblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmVuZGVyU2VjdGlvbihzZWN0aW9uSW5kZXgsIHNlY3Rpb24uSGVhZGVyLCBzZWN0aW9uLlRleHQsIG9wdGlvbnNIdG1sKTtcblx0XHR9IGVsc2UgaWYgKHNlY3Rpb24uUmVmaW5lbWVudCAmJiBzZWN0aW9uLlJlZmluZW1lbnQgIT0gJ3dpZHRoJykge1xuXHRcdFx0Z2V0UmVmaW5lbWVudENvdW50c0ZvclNlY3Rpb24oc2VjdGlvbkluZGV4LCBzZWN0aW9uKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0dmFyIG9wdGlvbnNIdG1sSW5uZXIgPSAnJztcblx0XHRcdFx0aWYgKGRhdGEuU2VjdGlvbi5SZWZpbmVtZW50ID09ICdzaXplJykge1xuXHRcdFx0XHRcdHZhciBsZW5ndGhzID0gW107XG5cdFx0XHRcdFx0dmFyIHdpZHRocyA9IFtdO1xuXHRcdFx0XHRcdHZhciB3aWR0aFJlZ2V4ID0gLyBbXFx3XFwvXSsvZ2k7XG5cdFx0XHRcdFx0Zm9yICh2YXIgcmVmaW5lbWVudEtleSBpbiBkYXRhLlJlZmluZW1lbnRzKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVmaW5lbWVudENvdW50ID0gZGF0YS5SZWZpbmVtZW50c1tyZWZpbmVtZW50S2V5XTtcblx0XHRcdFx0XHRcdGlmIChyZWZpbmVtZW50Q291bnQpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHdpZHRoUmVnZXhSZXN1bHQgPSByZWZpbmVtZW50S2V5Lm1hdGNoKHdpZHRoUmVnZXgpO1xuXHRcdFx0XHRcdFx0XHR2YXIgbGVuZ3RoO1xuXHRcdFx0XHRcdFx0XHR2YXIgd2lkdGg7XG5cdFx0XHRcdFx0XHRcdGlmICh3aWR0aFJlZ2V4UmVzdWx0ICYmIHdpZHRoUmVnZXhSZXN1bHQubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRcdFx0d2lkdGggPSB3aWR0aFJlZ2V4UmVzdWx0W3dpZHRoUmVnZXhSZXN1bHQubGVuZ3RoIC0gMV0udHJpbSgpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmICh3aWR0aCkge1xuXHRcdFx0XHRcdFx0XHRcdGxlbmd0aCA9IHJlZmluZW1lbnRLZXkucmVwbGFjZSh3aWR0aCwgJycpLnRyaW0oKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRpZiAobGVuZ3RoICYmIGxlbmd0aHMuaW5kZXhPZihsZW5ndGgpIDwgMCkge1xuXHRcdFx0XHRcdFx0XHRcdGxlbmd0aHNbbGVuZ3Rocy5sZW5ndGhdID0gbGVuZ3RoO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmICh3aWR0aCAmJiB3aWR0aHMuaW5kZXhPZih3aWR0aCkgPCAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0d2lkdGhzW3dpZHRocy5sZW5ndGhdID0gd2lkdGg7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bGVuZ3Rocy5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG5cdFx0XHRcdFx0XHR2YXIgbGVmdFZhbHVlID0gbGVmdC5yZXBsYWNlKC8gKjFcXC8yLywgJy41Jyk7XG5cdFx0XHRcdFx0XHR2YXIgcmlnaHRWYWx1ZSA9IHJpZ2h0LnJlcGxhY2UoLyAqMVxcLzIvLCAnLjUnKTtcblx0XHRcdFx0XHRcdHJldHVybiBwYXJzZUZsb2F0KGxlZnRWYWx1ZSkgLSBwYXJzZUZsb2F0KHJpZ2h0VmFsdWUpO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0d2lkdGhzLnNvcnQoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcblx0XHRcdFx0XHRcdHZhciBsZWZ0VmFsdWUgPSBwYXJzZUludChsZWZ0LCAxMCk7XG5cdFx0XHRcdFx0XHR2YXIgcmlnaHRWYWx1ZSA9IHBhcnNlSW50KHJpZ2h0LCAxMCk7XG5cdFx0XHRcdFx0XHRpZiAobGVmdFZhbHVlKSB7XG5cdFx0XHRcdFx0XHRcdGxlZnRWYWx1ZSA9ICcnLnBhZFN0YXJ0KGxlZnRWYWx1ZSwgbGVmdC5yZXBsYWNlKC9cXGQvZywgJycpWzBdKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGxlZnRWYWx1ZSA9IGxlZnQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAocmlnaHRWYWx1ZSkge1xuXHRcdFx0XHRcdFx0XHRyaWdodFZhbHVlID0gJycucGFkU3RhcnQocmlnaHRWYWx1ZSwgcmlnaHQucmVwbGFjZSgvXFxkL2csICcnKVswXSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRyaWdodFZhbHVlID0gcmlnaHQ7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHZhciBsZWZ0V2lkdGhEZXNjcmlwdGlvbjtcblx0XHRcdFx0XHRcdGlmIChvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV0gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV1bJ0Jvb3QnXVtsZWZ0XSkge1xuXHRcdFx0XHRcdFx0XHRsZWZ0V2lkdGhEZXNjcmlwdGlvbiA9IG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV1bJ0Jvb3QnXVtsZWZ0XTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0dmFyIHJpZ2h0V2lkdGhEZXNjcmlwdGlvbjtcblx0XHRcdFx0XHRcdGlmIChvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV0gJiYgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV1bJ0Jvb3QnXVtyaWdodF0pIHtcblx0XHRcdFx0XHRcdFx0cmlnaHRXaWR0aERlc2NyaXB0aW9uID0gb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddW3JpZ2h0XTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKGxlZnRXaWR0aERlc2NyaXB0aW9uID09ICdNZWRpdW0nICYmIHJpZ2h0V2lkdGhEZXNjcmlwdGlvbiAhPSAnTWVkaXVtJykge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGxlZnRXaWR0aERlc2NyaXB0aW9uICE9ICdNZWRpdW0nICYmIHJpZ2h0V2lkdGhEZXNjcmlwdGlvbiA9PSAnTWVkaXVtJykge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gMTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChsZWZ0V2lkdGhEZXNjcmlwdGlvbiA9PSAnV2lkZScgJiYgcmlnaHRXaWR0aERlc2NyaXB0aW9uICE9ICdXaWRlJykge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGxlZnRXaWR0aERlc2NyaXB0aW9uICE9ICdXaWRlJyAmJiByaWdodFdpZHRoRGVzY3JpcHRpb24gPT0gJ1dpZGUnKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0cmV0dXJuIGxlZnRWYWx1ZS5sb2NhbGVDb21wYXJlKHJpZ2h0VmFsdWUpO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0Zm9yICh2YXIgbGVuZ3RoSW5kZXggaW4gbGVuZ3Rocykge1xuXHRcdFx0XHRcdFx0dmFyIGxlbmd0aCA9IGxlbmd0aHNbbGVuZ3RoSW5kZXhdO1xuXHRcdFx0XHRcdFx0dmFyIGNzc0NsYXNzID0gJyc7XG5cdFx0XHRcdFx0XHRpZiAoc3RlcERhdGEgJiYgc3RlcERhdGFbZGF0YS5TZWN0aW9uSW5kZXhdICYmICdpbmRleE9mJyBpbiBzdGVwRGF0YVtkYXRhLlNlY3Rpb25JbmRleF0gJiYgc3RlcERhdGFbZGF0YS5TZWN0aW9uSW5kZXhdLmluZGV4T2YobGVuZ3RoKSA+IC0xKSB7XG5cdFx0XHRcdFx0XHRcdGNzc0NsYXNzID0gJ3NlbGVjdGVkJztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG9wdGlvbnNIdG1sSW5uZXIgKz0gdGVtcGxhdGVzLm9wdGlvbih7XG5cdFx0XHRcdFx0XHRcdEltYWdlOiAnJyxcblx0XHRcdFx0XHRcdFx0VGV4dDogbGVuZ3RoLFxuXHRcdFx0XHRcdFx0XHRWYWx1ZTogbGVuZ3RoLFxuXHRcdFx0XHRcdFx0XHRDc3NDbGFzczogY3NzQ2xhc3Ncblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkYXRhQnVmZmVyLmxlbmd0aHMgPSBsZW5ndGhzO1xuXHRcdFx0XHRcdHJlbmRlclNlY3Rpb24oZGF0YS5TZWN0aW9uSW5kZXgsIGRhdGEuU2VjdGlvbi5IZWFkZXIsIGRhdGEuU2VjdGlvbi5UZXh0LCBvcHRpb25zSHRtbElubmVyKTtcblxuXHRcdFx0XHRcdHZhciB3aWR0aHNIdG1sID0gJyc7XG5cdFx0XHRcdFx0dmFyIHdpZHRoU2VjdGlvbkluZGV4ID0gcGFyc2VJbnQoZGF0YS5TZWN0aW9uSW5kZXgsIDEwKSArIDE7XG5cdFx0XHRcdFx0Zm9yICh2YXIgd2lkdGhJbmRleCBpbiB3aWR0aHMpIHtcblx0XHRcdFx0XHRcdHZhciB3aWR0aCA9IHdpZHRoc1t3aWR0aEluZGV4XTtcblx0XHRcdFx0XHRcdHZhciBjc3NDbGFzcyA9ICcnO1xuXHRcdFx0XHRcdFx0aWYgKHN0ZXBEYXRhICYmIHN0ZXBEYXRhW3dpZHRoU2VjdGlvbkluZGV4XSAmJiAnaW5kZXhPZicgaW4gc3RlcERhdGFbd2lkdGhTZWN0aW9uSW5kZXhdICYmIHN0ZXBEYXRhW3dpZHRoU2VjdGlvbkluZGV4XS5pbmRleE9mKHdpZHRoKSA+IC0xKSB7XG5cdFx0XHRcdFx0XHRcdGNzc0NsYXNzID0gJ3NlbGVjdGVkJztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHZhciB3aWR0aERlc2NyaXB0aW9uID0gJyc7XG5cdFx0XHRcdFx0XHRpZiAob3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbiAmJiBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dICYmIG9wdGlvbnMuV2lkdGhEZXNjcmlwdGlvbkNvbmZpZ3VyYXRpb25bZGF0YUJ1ZmZlci5zdGVwRGF0YVswXVswXV1bJ0Jvb3QnXSAmJiBvcHRpb25zLldpZHRoRGVzY3JpcHRpb25Db25maWd1cmF0aW9uW2RhdGFCdWZmZXIuc3RlcERhdGFbMF1bMF1dWydCb290J11bd2lkdGhdKSB7XG5cdFx0XHRcdFx0XHRcdHdpZHRoRGVzY3JpcHRpb24gPSAnICgnICsgb3B0aW9ucy5XaWR0aERlc2NyaXB0aW9uQ29uZmlndXJhdGlvbltkYXRhQnVmZmVyLnN0ZXBEYXRhWzBdWzBdXVsnQm9vdCddW3dpZHRoXSArICcpJztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHdpZHRoc0h0bWwgKz0gdGVtcGxhdGVzLm9wdGlvbih7XG5cdFx0XHRcdFx0XHRcdEltYWdlOiAnJyxcblx0XHRcdFx0XHRcdFx0VGV4dDogd2lkdGggKyB3aWR0aERlc2NyaXB0aW9uLFxuXHRcdFx0XHRcdFx0XHRWYWx1ZTogd2lkdGgsXG5cdFx0XHRcdFx0XHRcdENzc0NsYXNzOiBjc3NDbGFzc1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFCdWZmZXIud2lkdGhzID0gd2lkdGhzO1xuXHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnW3NlY3Rpb249XCInICsgd2lkdGhTZWN0aW9uSW5kZXggKyAnXCJdIC5vcHRpb25zJykuaHRtbCh3aWR0aHNIdG1sKTtcblx0XHRcdFx0XHR1cGRhdGVTaXplcyhzZWN0aW9uSW5kZXgsIG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwc1tkYXRhQnVmZmVyLnN0ZXBdLlNlY3Rpb25zW3NlY3Rpb25JbmRleF0pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGZvciAodmFyIHJlZmluZW1lbnRLZXkgaW4gZGF0YS5SZWZpbmVtZW50cykge1xuXHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRDb3VudCA9IGRhdGEuUmVmaW5lbWVudHNbcmVmaW5lbWVudEtleV07XG5cdFx0XHRcdFx0XHRpZiAocmVmaW5lbWVudENvdW50KSB7XG5cdFx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50VGV4dDtcblx0XHRcdFx0XHRcdFx0aWYgKGRhdGFCdWZmZXIuRGlzcGxheVZhbHVlc1tkYXRhLlNlY3Rpb24uUmVmaW5lbWVudF0gJiYgZGF0YUJ1ZmZlci5EaXNwbGF5VmFsdWVzW2RhdGEuU2VjdGlvbi5SZWZpbmVtZW50XVtyZWZpbmVtZW50S2V5XSkge1xuXHRcdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRUZXh0ID0gZGF0YUJ1ZmZlci5EaXNwbGF5VmFsdWVzW2RhdGEuU2VjdGlvbi5SZWZpbmVtZW50XVtyZWZpbmVtZW50S2V5XTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50VGV4dCA9IHJlZmluZW1lbnRLZXk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHR2YXIgY3NzQ2xhc3MgPSAnJztcblx0XHRcdFx0XHRcdFx0aWYgKHN0ZXBEYXRhICYmIHN0ZXBEYXRhW2RhdGEuU2VjdGlvbkluZGV4XSAmJiAnaW5kZXhPZicgaW4gc3RlcERhdGFbZGF0YS5TZWN0aW9uSW5kZXhdICYmIHN0ZXBEYXRhW2RhdGEuU2VjdGlvbkluZGV4XS5pbmRleE9mKHJlZmluZW1lbnRLZXkpID4gLTEpIHtcblx0XHRcdFx0XHRcdFx0XHRjc3NDbGFzcyA9ICdzZWxlY3RlZCc7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHR2YXIgc2VjdGlvbkltYWdlcztcblx0XHRcdFx0XHRcdFx0aWYgKHR5cGVvZiBzZWN0aW9uLkltYWdlcyA9PSAnb2JqZWN0JyAmJiBzZWN0aW9uLkltYWdlc1JlbGF0ZWRTZWxlY3Rpb25TdGVwICE9IHVuZGVmaW5lZCAmJiBzZWN0aW9uLkltYWdlc1JlbGF0ZWRTZWxlY3Rpb25TZWN0aW9uICE9IHVuZGVmaW5lZCAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbc2VjdGlvbi5JbWFnZXNSZWxhdGVkU2VsZWN0aW9uU3RlcF0gJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtzZWN0aW9uLkltYWdlc1JlbGF0ZWRTZWxlY3Rpb25TdGVwXVtzZWN0aW9uLkltYWdlc1JlbGF0ZWRTZWxlY3Rpb25TZWN0aW9uXSkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBpbWFnZXNSZWxhdGVkU2VsZWN0aW9uVmFsdWUgPSBkYXRhQnVmZmVyLnN0ZXBEYXRhW3NlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblN0ZXBdW3NlY3Rpb24uSW1hZ2VzUmVsYXRlZFNlbGVjdGlvblNlY3Rpb25dO1xuXHRcdFx0XHRcdFx0XHRcdHNlY3Rpb25JbWFnZXMgPSBzZWN0aW9uLkltYWdlc1tpbWFnZXNSZWxhdGVkU2VsZWN0aW9uVmFsdWVdO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHNlY3Rpb25JbWFnZXMgPSBzZWN0aW9uLkltYWdlcztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR2YXIgaW1hZ2VIdG1sID0gJyc7XG5cdFx0XHRcdFx0XHRcdGlmIChzZWN0aW9uSW1hZ2VzICYmIHNlY3Rpb25JbWFnZXNbcmVmaW5lbWVudEtleV0pIHtcblx0XHRcdFx0XHRcdFx0XHRpbWFnZUh0bWwgPSB0ZW1wbGF0ZXMub3B0aW9uSW1hZ2Uoe1xuXHRcdFx0XHRcdFx0XHRcdFx0SW1hZ2VVcmw6IHNlY3Rpb25JbWFnZXNbcmVmaW5lbWVudEtleV1cblx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0fVx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdG9wdGlvbnNIdG1sSW5uZXIgKz0gdGVtcGxhdGVzLm9wdGlvbih7XG5cdFx0XHRcdFx0XHRcdFx0SW1hZ2U6IGltYWdlSHRtbCxcblx0XHRcdFx0XHRcdFx0XHRUZXh0OiByZWZpbmVtZW50VGV4dCxcblx0XHRcdFx0XHRcdFx0XHRWYWx1ZTogcmVmaW5lbWVudEtleSxcblx0XHRcdFx0XHRcdFx0XHRDc3NDbGFzczogY3NzQ2xhc3Ncblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJlbmRlclNlY3Rpb24oZGF0YS5TZWN0aW9uSW5kZXgsIGRhdGEuU2VjdGlvbi5IZWFkZXIsIGRhdGEuU2VjdGlvbi5UZXh0LCBvcHRpb25zSHRtbElubmVyKTtcblx0XHRcdFx0fVxuXHRcdFx0fSkuY2F0Y2goKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVuZGVyU2VjdGlvbihzZWN0aW9uSW5kZXgsIHNlY3Rpb24uSGVhZGVyLCBzZWN0aW9uLlRleHQsIG9wdGlvbnNIdG1sKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyU2VjdGlvbihpbmRleCwgaGVhZGVyLCB0ZXh0UGFyYW1ldGVyLCBzZWN0aW9uT3B0aW9ucykge1xuXHRkYXRhQnVmZmVyLnNlY3Rpb25SZW5kZXJDb3VudCsrO1xuXHR2YXIgdGV4dCA9ICcnO1xuXHRpZiAodGV4dFBhcmFtZXRlcikge1xuXHRcdHRleHQgPSAnPHA+JyArIHRleHRQYXJhbWV0ZXIgKyAnPC9wPic7XG5cdH1cblx0JGNvbnRhaW5lci5maW5kKCdbc2VjdGlvbj1cIicgKyBpbmRleCArICdcIl0nKS5odG1sKHRlbXBsYXRlcy5zZWN0aW9uKHtcblx0XHRIZWFkZXI6IGhlYWRlcixcblx0XHRUZXh0OiB0ZXh0LFxuXHRcdE9wdGlvbnM6IHNlY3Rpb25PcHRpb25zXG5cdH0pKTtcblxuXHRpZiAoZGF0YUJ1ZmZlci5zZWN0aW9uUmVuZGVyQ291bnQgPT0gb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzW2RhdGFCdWZmZXIuc3RlcF0uU2VjdGlvbnMubGVuZ3RoKSB7XG5cdFx0aWYgKCRzdGVwLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0JHN0ZXAuY3NzKCdoZWlnaHQnLCAnJyk7XG5cdFx0XHQkc3RlcC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHQkKCdodG1sJykuYW5pbWF0ZSh7IHNjcm9sbFRvcDogMCB9LCAyNTApO1xuXHRcdH1cblx0XHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwLWRlbHRhXScpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdGlmIChvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbZGF0YUJ1ZmZlci5zdGVwXS5TZWN0aW9uc1tpbmRleF0uU2VsZWN0UmVxdWlyZWQgJiYgJCgnLm9wdGlvbnMnKS5sZW5ndGggIT0gJCgnLm9wdGlvbnMnKS5maW5kKCcuc2VsZWN0ZWQnKS5sZW5ndGgpIHtcblx0XHRcdCRjb250YWluZXIuZmluZCgnLm5leHQnKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0XHR9XHRcblx0XHRpZiAoZGF0YUJ1ZmZlci5zdGVwID09IDApIHtcblx0XHRcdCRjb250YWluZXIuZmluZCgnLmJhY2snKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0XHR9XG5cdFx0aWYgKCRjb250YWluZXIuZmluZCgnLm9wdGlvbicpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRpZiAoZGF0YUJ1ZmZlci5zdGVwIDwgKG9wdGlvbnMuQ29uZmlndXJhdGlvbi5TdGVwcy5sZW5ndGggLSAxKSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyLnN0ZXAgKz0gZGF0YUJ1ZmZlci5zdGVwRGVsdGE7XG5cdFx0XHRcdHJlbmRlcigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnc2VjdGlvbiBoZWFkZXIgaDInKS50ZXh0KCdObyBtb3JlIG9wdGlvbnMgdG8gY2hvb3NlIGZyb20sIGNsaWNrIHRoZSBWaWV3IFJlc3VsdHMgYnV0dG9uIScpXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclJlc3VsdHMoKSB7XG5cdHZhciB1cmwgPSBidWlsZFVybCgpO1xuXHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnYm9vdGZpbmRlcnZpZXdyZXN1bHRzJyk7XG5cblx0JGNvbnRhaW5lci5maW5kKCdbc3RlcF0nKS5odG1sKHRlbXBsYXRlcy5yZXN1bHRzKHtcblx0XHRVcmw6IHVybFxuXHR9KSk7XG5cblx0ZGF0YUJ1ZmZlci4kZW1haWxGb3JtID0gJGNvbnRhaW5lci5maW5kKCdmb3JtLmVtYWlsJyk7XG5cdGRhdGFCdWZmZXIuZW1haWxWYWxpZGF0b3IgPSBkYXRhQnVmZmVyLiRlbWFpbEZvcm0udmFsaWRhdGUoVmFsaWRhdGlvblNldHRpbmdzLkdsb2JhbCk7XG5cdGRhdGFCdWZmZXIuJGVtYWlsRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiZW1haWxcIl0nKS5ydWxlcygnYWRkJywgJC5leHRlbmQoVmFsaWRhdGlvblJ1bGVzLkVtYWlsLCB7XG5cdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0bWVzc2FnZXM6IHtcblx0XHRcdHJlcXVpcmVkOiAkLnZhbGlkYXRvci5mb3JtYXQoJ1BsZWFzZSBlbnRlciBhbiBlbWFpbCBhZGRyZXNzLicpXG5cdFx0fVxuXHR9KSk7XG5cdGRhdGFCdWZmZXIuJGVtYWlsRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwidXNlcmFncmVlbWVudFwiXScpLnJ1bGVzKCdhZGQnLCB7XG5cdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0bWVzc2FnZXM6IHtcblx0XHRcdHJlcXVpcmVkOiAkLnZhbGlkYXRvci5mb3JtYXQoJ1BsZWFzZSBhZ3JlZSB0byB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMuJylcblx0XHR9XG5cdH0pO1xuXG5cdGlmICgkc3RlcC5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHQkc3RlcC5jc3MoJ2hlaWdodCcsICcnKTtcblx0XHQkc3RlcC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0JCgnaHRtbCcpLmFuaW1hdGUoeyBzY3JvbGxUb3A6IDAgfSwgMjUwKTtcblx0fVxuXHQkY29udGFpbmVyLmZpbmQoJ1tzdGVwLWRlbHRhXScpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHQkY29udGFpbmVyLmZpbmQoJy5uZXh0JykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVXJsKHVybFBhcmFtZXRlciwgaW5jbHVkZUFkZGl0aW9uYWxEYXRhKSB7XG5cdHZhciB1cmw7XG5cdGlmIChkYXRhQnVmZmVyICYmIGRhdGFCdWZmZXIuc3RlcERhdGFbb3B0aW9ucy5Db25maWd1cmF0aW9uLkNhdGVnb3J5U2VsZWN0aW9uU3RlcF0gJiYgZGF0YUJ1ZmZlci5zdGVwRGF0YVtvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TdGVwXVtvcHRpb25zLkNvbmZpZ3VyYXRpb24uQ2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uXSkge1xuXHRcdHZhciBjYXRlZ29yeVNlbGVjdGlvblNlY3Rpb24gPSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbb3B0aW9ucy5Db25maWd1cmF0aW9uLkNhdGVnb3J5U2VsZWN0aW9uU3RlcF0uU2VjdGlvbnNbb3B0aW9ucy5Db25maWd1cmF0aW9uLkNhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbl07XG5cdFx0dmFyIG9wdGlvblJlbGF0ZWRTZWxlY3Rpb24gPSBkYXRhQnVmZmVyLnN0ZXBEYXRhW2NhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblN0ZXBdW2NhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbi5PcHRpb25zUmVsYXRlZFNlbGVjdGlvblNlY3Rpb25dWzBdO1xuXHRcdHZhciBjYXRlZ29yeVNlbGVjdGlvbiA9IGRhdGFCdWZmZXIuc3RlcERhdGFbb3B0aW9ucy5Db25maWd1cmF0aW9uLkNhdGVnb3J5U2VsZWN0aW9uU3RlcF1bb3B0aW9ucy5Db25maWd1cmF0aW9uLkNhdGVnb3J5U2VsZWN0aW9uU2VjdGlvbl1bMF07XG5cblx0XHR2YXIgY2F0ZWdvcnlTZWxlY3Rpb25JbmRleDtcblx0XHR2YXIgb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbkluZGV4ID0gMDtcblx0XHR2YXIgb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbnMgPSBjYXRlZ29yeVNlbGVjdGlvblNlY3Rpb24uT3B0aW9uc1tvcHRpb25SZWxhdGVkU2VsZWN0aW9uXTtcblx0XHR3aGlsZSAoIWNhdGVnb3J5U2VsZWN0aW9uSW5kZXggJiYgb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbkluZGV4IDw9IG9wdGlvblJlbGF0ZWRTZWxlY3Rpb25PcHRpb25zLmxlbmd0aCkge1xuXHRcdFx0aWYgKG9wdGlvblJlbGF0ZWRTZWxlY3Rpb25PcHRpb25zW29wdGlvblJlbGF0ZWRTZWxlY3Rpb25PcHRpb25JbmRleF0gJiYgb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbnNbb3B0aW9uUmVsYXRlZFNlbGVjdGlvbk9wdGlvbkluZGV4XS5UZXh0ID09IGNhdGVnb3J5U2VsZWN0aW9uKSB7XG5cdFx0XHRcdGNhdGVnb3J5U2VsZWN0aW9uSW5kZXggPSBvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRvcHRpb25SZWxhdGVkU2VsZWN0aW9uT3B0aW9uSW5kZXgrKztcblx0XHR9XG5cblx0XHR2YXIgY2F0ZWdvcnlTZWxlY3Rpb25EYXRhID0gY2F0ZWdvcnlTZWxlY3Rpb25TZWN0aW9uLk9wdGlvbnNbb3B0aW9uUmVsYXRlZFNlbGVjdGlvbl1bY2F0ZWdvcnlTZWxlY3Rpb25JbmRleF07XG5cdFx0aWYgKHVybFBhcmFtZXRlcikge1xuXHRcdFx0dXJsID0gdXJsUGFyYW1ldGVyO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR1cmwgPSBjYXRlZ29yeVNlbGVjdGlvbkRhdGEuVXJsO1xuXHRcdH1cblx0XHR2YXIgcGFyYW1ldGVySW5kZXggPSAxO1xuXHRcdGZvciAodmFyIGNhdGVnb3J5U2VsZWN0aW9uRGF0YUtleSBpbiBjYXRlZ29yeVNlbGVjdGlvbkRhdGEpIHtcblx0XHRcdHZhciBjYXRlZ29yeVNlbGVjdGlvbkRhdGFWYWx1ZSA9IGNhdGVnb3J5U2VsZWN0aW9uRGF0YVtjYXRlZ29yeVNlbGVjdGlvbkRhdGFLZXldO1xuXHRcdFx0aWYgKHVybFBhcmFtZXRlciAmJiBjYXRlZ29yeVNlbGVjdGlvbkRhdGFLZXkgPT0gJ2NnaWQnKSB7XG5cdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdjZ2lkJywgY2F0ZWdvcnlTZWxlY3Rpb25EYXRhVmFsdWUpO1xuXHRcdFx0fSBlbHNlIGlmIChjYXRlZ29yeVNlbGVjdGlvbkRhdGFLZXkgIT0gJ1RleHQnICYmIGNhdGVnb3J5U2VsZWN0aW9uRGF0YUtleSAhPSAnVXJsJyAmJiBjYXRlZ29yeVNlbGVjdGlvbkRhdGFLZXkgIT0gJ2NnaWQnKSB7XG5cdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmbicgKyBwYXJhbWV0ZXJJbmRleCwgY2F0ZWdvcnlTZWxlY3Rpb25EYXRhS2V5KTtcblx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZ2JyArIHBhcmFtZXRlckluZGV4LCBjYXRlZ29yeVNlbGVjdGlvbkRhdGFWYWx1ZSk7XG5cdFx0XHRcdHBhcmFtZXRlckluZGV4Kys7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Zm9yICh2YXIgc3RlcEluZGV4SW5uZXIgaW4gb3B0aW9ucy5Db25maWd1cmF0aW9uLlN0ZXBzKSB7XG5cdFx0XHRpZiAoc3RlcEluZGV4SW5uZXIgPD0gZGF0YUJ1ZmZlci5zdGVwKSB7XG5cdFx0XHRcdHZhciBzdGVwSW5uZXIgPSBvcHRpb25zLkNvbmZpZ3VyYXRpb24uU3RlcHNbc3RlcEluZGV4SW5uZXJdO1xuXHRcdFx0XHRmb3IgKHZhciBzZWN0aW9uSW5kZXhJbm5lciBpbiBzdGVwSW5uZXIuU2VjdGlvbnMpIHtcblx0XHRcdFx0XHR2YXIgc2VjdGlvbklubmVyID0gc3RlcElubmVyLlNlY3Rpb25zW3NlY3Rpb25JbmRleElubmVyXTtcblx0XHRcdFx0XHRpZiAoc2VjdGlvbklubmVyLlJlZmluZW1lbnQgJiYgc2VjdGlvbklubmVyLlJlZmluZW1lbnQgIT0gJ3dpZHRoJykge1xuXHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZXM7XG5cdFx0XHRcdFx0XHRpZiAoZGF0YUJ1ZmZlci5zdGVwRGF0YSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW3N0ZXBJbmRleElubmVyXSAmJiBkYXRhQnVmZmVyLnN0ZXBEYXRhW3N0ZXBJbmRleElubmVyXVtzZWN0aW9uSW5kZXhJbm5lcl0pIHtcblx0XHRcdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlcyA9IGRhdGFCdWZmZXIuc3RlcERhdGFbc3RlcEluZGV4SW5uZXJdW3NlY3Rpb25JbmRleElubmVyXTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJlZmluZW1lbnRWYWx1ZXMgPSBbXTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKHNlY3Rpb25Jbm5lci5SZWZpbmVtZW50ID09ICdzaXplJykge1xuXHRcdFx0XHRcdFx0XHR2YXIgd2lkdGhTZWN0aW9uSW5kZXggPSBwYXJzZUludChzZWN0aW9uSW5kZXhJbm5lciwgMTApICsgMTtcblx0XHRcdFx0XHRcdFx0dmFyIHNlbGVjdGVkV2lkdGhzID0gZGF0YUJ1ZmZlci5zdGVwRGF0YVtzdGVwSW5kZXhJbm5lcl1bd2lkdGhTZWN0aW9uSW5kZXhdO1xuXHRcdFx0XHRcdFx0XHR2YXIgaXNEYXRhYnVmZmVyV2lkdGhzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdGlmICghc2VsZWN0ZWRXaWR0aHMgfHwgIXNlbGVjdGVkV2lkdGhzLmxlbmd0aCkge1xuXHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkV2lkdGhzID0gZGF0YUJ1ZmZlci53aWR0aHM7XG5cdFx0XHRcdFx0XHRcdFx0aXNEYXRhYnVmZmVyV2lkdGhzID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR2YXIgaXNEYXRhYnVmZmVyTGVuZ3RocyA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRpZiAoIXJlZmluZW1lbnRWYWx1ZXMgfHwgIXJlZmluZW1lbnRWYWx1ZXMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlcyA9IGRhdGFCdWZmZXIubGVuZ3Rocztcblx0XHRcdFx0XHRcdFx0XHRpc0RhdGFidWZmZXJMZW5ndGhzID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRTaXplcyA9IFtdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIWlzRGF0YWJ1ZmZlcldpZHRocyB8fCAhaXNEYXRhYnVmZmVyTGVuZ3Rocykge1xuXHRcdFx0XHRcdFx0XHRcdGZvciAodmFyIHJlZmluZW1lbnRJbmRleCBpbiByZWZpbmVtZW50VmFsdWVzKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRMZW5ndGggPSByZWZpbmVtZW50VmFsdWVzW3JlZmluZW1lbnRJbmRleF07XG5cdFx0XHRcdFx0XHRcdFx0XHRmb3IgKHZhciB3aWR0aEluZGV4IGluIHNlbGVjdGVkV2lkdGhzKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBzZWxlY3RlZFdpZHRoID0gc2VsZWN0ZWRXaWR0aHNbd2lkdGhJbmRleF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBzZWxlY3RlZFNpemUgPSBzZWxlY3RlZExlbmd0aCArICcgJyArIHNlbGVjdGVkV2lkdGg7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChzZWxlY3RlZFNpemVzLmluZGV4T2Yoc2VsZWN0ZWRTaXplKSA8IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZFNpemVzW3NlbGVjdGVkU2l6ZXMubGVuZ3RoXSA9IHNlbGVjdGVkU2l6ZTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZWZpbmVtZW50VmFsdWVzID0gc2VsZWN0ZWRTaXplcztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYgKHJlZmluZW1lbnRWYWx1ZXMgJiYgcmVmaW5lbWVudFZhbHVlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChzZWN0aW9uSW5uZXIuUmVmaW5lbWVudCA9PSAnUHJpY2UnKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRhdGFCdWZmZXIuVGhyZXNob2xkcyAmJiBkYXRhQnVmZmVyLlRocmVzaG9sZHNbc2VjdGlvbklubmVyLlJlZmluZW1lbnRdICYmIGRhdGFCdWZmZXIuVGhyZXNob2xkc1tzZWN0aW9uSW5uZXIuUmVmaW5lbWVudF1bcmVmaW5lbWVudFZhbHVlc10pIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhciB0aHJlc2hvbGQgPSBkYXRhQnVmZmVyLlRocmVzaG9sZHNbc2VjdGlvbklubmVyLlJlZmluZW1lbnRdW3JlZmluZW1lbnRWYWx1ZXNbMF1dO1xuXHRcdFx0XHRcdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3BtaW4nLCB0aHJlc2hvbGQudmFsdWVGcm9tKTtcblx0XHRcdFx0XHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwbWF4JywgdGhyZXNob2xkLnZhbHVlVG8pO1x0XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmbicgKyBwYXJhbWV0ZXJJbmRleCwgc2VjdGlvbklubmVyLlJlZmluZW1lbnQpO1xuXHRcdFx0XHRcdFx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmdicgKyBwYXJhbWV0ZXJJbmRleCwgcmVmaW5lbWVudFZhbHVlcy5qb2luKCd8JykpO1xuXHRcdFx0XHRcdFx0XHRcdHBhcmFtZXRlckluZGV4Kys7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKGluY2x1ZGVBZGRpdGlvbmFsRGF0YSkge1xuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ2Rpc3BsYXl2YWx1ZXMnLCAnUHJpY2UnKTtcblx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICd0aHJlc2hvbGRzJywgJ1ByaWNlJyk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHVybDtcbn1cblxuZnVuY3Rpb24gZ2V0UmVmaW5lbWVudENvdW50c0ZvclNlY3Rpb24oc2VjdGlvbkluZGV4LCBzZWN0aW9uKSB7XG5cdHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0JC5hamF4KHtcblx0XHRcdHR5cGU6ICdnZXQnLFxuXHRcdFx0dXJsOiBidWlsZFVybChVcmxzLmdldFJlZmluZW1lbnRDb3VudHMsIHRydWUpLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyID0gJC5leHRlbmQoZGF0YUJ1ZmZlciwgZGF0YSk7XG5cblx0XHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdFx0U2VjdGlvbkluZGV4OiBzZWN0aW9uSW5kZXgsXG5cdFx0XHRcdFx0U2VjdGlvbjogc2VjdGlvblxuXHRcdFx0XHR9O1xuXHRcdFx0XHRpZiAoc2VjdGlvbiAmJiBzZWN0aW9uLlJlZmluZW1lbnQpIHtcblx0XHRcdFx0XHRwYXlsb2FkLlJlZmluZW1lbnRzID0gZGF0YS5SZWZpbmVtZW50c1tzZWN0aW9uLlJlZmluZW1lbnRdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlc29sdmUocGF5bG9hZCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdHJldHVybiBwcm9taXNlO1xufVxuXG5mdW5jdGlvbiBzZW5kRGF0YUxheWVyKCkge1xuXHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JFdmVudCgnYm9vdGZpbmRlcnF1aXonLCB7XG5cdFx0c3RlcDogZGF0YUJ1ZmZlci5zdGVwLFxuXHRcdHN0ZXBEYXRhOiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGRhdGFCdWZmZXIuc3RlcERhdGEpKVxuXHR9LCBudWxsLCAnR29vZ2xlQW5hbHl0aWNzNCcpO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIHF1YW50aXR5U3RlcHBlciA9IHJlcXVpcmUoJy4uL3F1YW50aXR5U3RlcHBlcicpO1xudmFyIGFjY291bnQgPSByZXF1aXJlKCcuL2FjY291bnQnKTtcbnZhciBBcHBsZVBheSA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvQXBwbGVQYXknKTtcbnZhciBib251c1Byb2R1Y3RzVmlldyA9IHJlcXVpcmUoJy4uL2JvbnVzLXByb2R1Y3RzLXZpZXcnKTtcbnZhciBxdWlja3ZpZXcgPSByZXF1aXJlKCcuLi9xdWlja3ZpZXcnKTtcbnZhciBjYXJ0U3RvcmVJbnZlbnRvcnkgPSByZXF1aXJlKCcuLi9zdG9yZWludmVudG9yeS9jYXJ0Jyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uL2FqYXgnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIGZvcm1QcmVwYXJlID0gcmVxdWlyZSgnLi9jaGVja291dC9mb3JtUHJlcGFyZScpO1xudmFyIHBhZ2UgPSByZXF1aXJlKCcuLi9wYWdlJyk7XG52YXIgdG9vbHRpcCA9IHJlcXVpcmUoJy4uL3Rvb2x0aXAnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcbnZhciBDaGVja291dENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQ2hlY2tvdXRDb25zdGFudHMnKTtcbnZhciBEYXRhTGF5ZXJDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0RhdGFMYXllckNvbnN0YW50cycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFBheW1lbnRNZXRob2RDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuUGF5bWVudE1ldGhvZHM7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFJlcXVlc3RIZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9oZWxwZXJzL1JlcXVlc3RIZWxwZXInKTtcblxudmFyIGlzQ2FydFBhZ2UgPSBmYWxzZTtcbnZhciBkYXRhQnVmZmVyID0ge307XG52YXIgb3B0aW9ucztcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgZXZlbnRzIHRvIHRoZSBjYXJ0IHBhZ2UgKGVkaXQgaXRlbSdzIGRldGFpbHMsIGJvbnVzIGl0ZW0ncyBhY3Rpb25zLCBjb3Vwb24gY29kZSBlbnRyeSlcbiAqLyBcbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XHRcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJyNjYXJ0LXRhYmxlIC5pdGVtLWVkaXQtZGV0YWlscyBhJykub24oJ2NsaWNrJywgJyNjYXJ0LXRhYmxlIC5pdGVtLWVkaXQtZGV0YWlscyBhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBcbiAgICAgICAgcXVpY2t2aWV3LnNob3coe1xuICAgICAgICAgICAgdXJsOiBlLnRhcmdldC5ocmVmLFxuICAgICAgICAgICAgc291cmNlOiAnY2FydCdcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljaycsICcjY2FydC10YWJsZSAuYm9udXMtaXRlbS1hY3Rpb25zIGEsICNjYXJ0LXRhYmxlIC5pdGVtLWRldGFpbHMgLmJvbnVzcHJvZHVjdHMgYScpLm9uKCdjbGljaycsICcjY2FydC10YWJsZSAuYm9udXMtaXRlbS1hY3Rpb25zIGEsICNjYXJ0LXRhYmxlIC5pdGVtLWRldGFpbHMgLmJvbnVzcHJvZHVjdHMgYScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgXG4gICAgICAgIGJvbnVzUHJvZHVjdHNWaWV3LnNob3codGhpcy5ocmVmKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2tleWRvd24nLCAnZm9ybSBpbnB1dFtuYW1lJD1cIl9jb3Vwb25Db2RlXCJdJykub24oJ2tleWRvd24nLCAnZm9ybSBpbnB1dFtuYW1lJD1cIl9jb3Vwb25Db2RlXCJdJywgZnVuY3Rpb24gKGUpIHsgICBcdFxuICAgIFx0aWYgKGUud2hpY2ggPT09IFNpdGVDb25zdGFudHMuS2V5Q29kZXMuRW50ZXIpIHtcbiAgICBcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XHRcbiAgICBcdFx0JCgnLmVycm9yLmNvdXBvbi1lcnJvcicpLnJlbW92ZSgpO1xuICAgIFx0XHRpZiAoJChkb2N1bWVudC5hY3RpdmVFbGVtZW50KS52YWwoKS5sZW5ndGggPT09IDAgfHwgZS53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5FbnRlciAmJiAkKHRoaXMpLnZhbCgpLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHQkKCc8c3Bhbi8+Jywge1wiY2xhc3NcIjpcImVycm9yIGNvdXBvbi1lcnJvclwiLCB0ZXh0IDogUmVzb3VyY2VzLkNPVVBPTl9BRERfRVJST1J9KS5pbnNlcnRBZnRlcignLmNhcnQtY291cG9uLWNvZGUgLnBjb2RlLWNvdXBvbicpO1xuXHRcdFx0XHRcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ICQoJ2J1dHRvbltuYW1lJD1cImFkZENvdXBvblwiXScpLnRyaWdnZXIoJ2NsaWNrJyk7XG5cdFx0XHR9XG4gICAgXHR9ICAgXHQgXG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImRlbGV0ZVByb2R1Y3RcIl0nKS5vbignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiZGVsZXRlUHJvZHVjdFwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcbiAgICBcdHVwZGF0ZUNhcnQoJCh0aGlzKS5hdHRyKCduYW1lJykpO1xuICAgIH0pO1xuICAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImFkZENvdXBvblwiXScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJhZGRDb3Vwb25cIl0nLCBmdW5jdGlvbiAoZSkge1xuXHQgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0ICAgXHRcblx0ICAgXHQkKCcuZXJyb3IuY291cG9uLWVycm9yJykudGV4dCgnJyk7XG5cdCAgIFx0dmFyICRmb3JtID0gJCgnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0nKTtcblx0XHR2YXIgbmFtZSA9ICQodGhpcykuYXR0cignbmFtZScpO1xuXHRcdFxuXHRcdChmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG5cdCAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcblx0ICAgICAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5vbmVQYWdlU3VibWl0KSxcblx0ICAgICAgICAgICAgZGF0YTogJGZvcm0uc2VyaWFsaXplKCkgKyAnJicgKyBuYW1lICsgJz0nICsgbmFtZSArICcmcmVzcFR5cGU9anNvbidcblx0ICAgICAgICB9KSlcblx0XHR9KCkpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRpZiAocmVzcG9uc2Uuc3VjY2VzcyAmJiByZXNwb25zZS5zdWNjZXNzICE9PSBDaGVja291dENvbnN0YW50cy5SZXNwb25zZUNvZGVzLkFscmVhZHlJbkJhc2tldCkge1x0XHRcdFx0XG5cdFx0XHRcdHZhciBjb3Vwb25Db2RlID0gJCgnLnBjb2RlLWNvdXBvbiBpbnB1dFtuYW1lKj1cIl9jb3Vwb25Db2RlXCJdJykudmFsKCk7XG5cblx0XHRcdFx0dmFyIGRhdGFPYmplY3QgPSB7XG5cdFx0XHRcdFx0Y3JlYXRpdmVfbmFtZTogY291cG9uQ29kZSxcblx0XHRcdFx0XHRjcmVhdGl2ZV9zbG90OiAnY291cG9uY29kZScsXG5cdFx0XHRcdFx0cHJvbW90aW9uX2lkOiByZXNwb25zZS5Qcm9tb3Rpb24gJiYgcmVzcG9uc2UuUHJvbW90aW9uLklEID8gcmVzcG9uc2UuUHJvbW90aW9uLklEIDogJycsXG5cdFx0XHRcdFx0cHJvbW90aW9uX25hbWU6IHJlc3BvbnNlLlByb21vdGlvbiAmJiByZXNwb25zZS5Qcm9tb3Rpb24uTmFtZSA/IHJlc3BvbnNlLlByb21vdGlvbi5OYW1lIDogJydcblx0XHRcdFx0fVxuXG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1NlbGVjdFByb21vdGlvbicsIGRhdGFPYmplY3QpO1xuXHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdFx0fSBlbHNlIHsxXG5cdFx0XHRcdHZhciBtZXNzYWdlID0gcmVzcG9uc2Uuc3VjY2VzcyA9PSBDaGVja291dENvbnN0YW50cy5SZXNwb25zZUNvZGVzLkFscmVhZHlJbkJhc2tldCA/IFJlc291cmNlcy5DT1VQT05fQUREX0VSUk9SX0RVUCA6IFJlc291cmNlcy5DT1VQT05fQUREX0VSUk9SO1xuXHRcdFx0XHQkKCc8c3Bhbi8+JywgeydjbGFzcyc6ICdlcnJvciBjb3Vwb24tZXJyb3InLCAndGV4dCc6IG1lc3NhZ2V9KS5pbnNlcnRBZnRlcignLmNhcnQtY291cG9uLWNvZGUgLnBjb2RlLWNvdXBvbicpO1xuXHRcdFx0fVxuXHQgICAgfS5iaW5kKHRoaXMpKTtcblx0fSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImRlbGV0ZUNvdXBvblwiXScpLm9uKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJkZWxldGVDb3Vwb25cIl0nLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG5cdFx0dmFyIG5hbWUgPSAkKHRoaXMpLmF0dHIoJ25hbWUnKTtcblx0XHQoZnVuY3Rpb24oKXtcblx0XHRcdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG5cdCAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcblx0ICAgICAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoVXJscy5vbmVQYWdlU3VibWl0KSxcblx0ICAgICAgICAgICAgZGF0YTogJCgnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0nKS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lICsgJyZyZXNwVHlwZT1qc29uJ1xuXHQgICAgICAgIH0pKVxuXHRcdH0oKSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdCAgICB9LmJpbmQodGhpcykpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZigncmVmcmVzaC1yZXF1aXJlZCcpLm9uKCdyZWZyZXNoLXJlcXVpcmVkJywgZnVuY3Rpb24oKXtcbiAgICBcdGlmICgkKCdmb3JtI2NhcnQtaXRlbXMtZm9ybSBpbnB1dFtuYW1lJD1cIl9xdWFudGl0eVwiXScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoIGZ1bmN0aW9uKCl7IFxuICAgICAgICAgICAgICAgICQoJ2Zvcm0jY2FydC1pdGVtcy1mb3JtIGlucHV0W25hbWUkPVwiX3F1YW50aXR5XCJdOmZpcnN0JykudHJpZ2dlcignZm9jdXMnKS50cmlnZ2VyKCdibHVyJyk7XG4gICAgICAgICAgICB9LCAzMDApO1xuICAgIFx0fVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCh0aGlzKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcblx0XHQkKCcjZHdmcm1fZ3Vlc3RjaGVja291dCBzcGFuLmVycm9yJykucmVtb3ZlKCk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdrZXlkb3duJywgJ2Zvcm0gaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXScpLm9uKCdrZXlkb3duJywgJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0nLCBmdW5jdGlvbiAoZSkgeyAgIFx0XG4gICAgXHRpZiAoZS53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5FbnRlcikge1x0XHRcbiAgICBcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XHQkKCcjZHdmcm1fZ3Vlc3RjaGVja291dCBzcGFuLmVycm9yJykucmVtb3ZlKCk7XG4gICAgXHRcdFxuICAgIFx0XHR2YXIgJGZvcm0gPSAkKCdmb3JtLmd1ZXN0LWNoZWNrb3V0Jyk7XG4gICAgXHRcdCRmb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgIFx0XHRcbiAgICBcdFx0dmFyIGVtYWlsID0gJChkb2N1bWVudC5hY3RpdmVFbGVtZW50KS52YWwoKTtcbiAgICBcdFx0dmFyIGlzRW1haWxWYWxpZCA9IHZhbGlkYXRlRW1haWwoZW1haWwpO1xuICAgIFx0XHRcbiAgICBcdFx0aWYgKCRmb3JtLnZhbGlkKCkgJiYgaXNFbWFpbFZhbGlkICYmICQoJyNkd2ZybV9ndWVzdGNoZWNrb3V0IHNwYW4uZXJyb3InKS5sZW5ndGggPCAxICkge1xuICAgIFx0XHRcdHJlbmRlckd1ZXN0Q2hlY2tvdXQoZW1haWwpXG4gICAgXHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0aWYgKCQoJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0uZXJyb3InKS5sZW5ndGggPT0gMCkge1xuICAgIFx0XHRcdFx0aW52YWxpZGF0ZUd1ZXN0Q2hlY2tvdXQoKTtcbiAgICBcdFx0XHR9XG4gICAgXHRcdH1cbiAgICBcdH0gICBcdCBcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbiNndWVzdENoZWNrb3V0Jykub24oJ2NsaWNrJywgJ2J1dHRvbiNndWVzdENoZWNrb3V0JywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHQkKCcjZHdmcm1fZ3Vlc3RjaGVja291dCBzcGFuLmVycm9yJykucmVtb3ZlKCk7XG5cdFx0XG5cdFx0dmFyICRmb3JtID0gJCgnZm9ybS5ndWVzdC1jaGVja291dCcpO1xuXHRcdCRmb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcdFxuXHRcdHZhciBlbWFpbCA9ICQoJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0nKS52YWwoKTtcblx0XHRpZiAoJCgnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXS52YWxpZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBlbWFpbCA9ICQoJ2lucHV0W25hbWVePVwiZHdmcm1fZ3Vlc3RjaGVja291dF91c2VybmFtZV9cIl0udmFsaWQnKS52YWwoKTtcblx0XHR9XG5cdFx0XG5cdFx0dmFyIGlzRW1haWxWYWxpZCA9IHZhbGlkYXRlRW1haWwoZW1haWwpO1xuICAgIFx0XG5cdFx0aWYgKCRmb3JtLnZhbGlkKCkgJiYgaXNFbWFpbFZhbGlkICYmICQoJyNkd2ZybV9ndWVzdGNoZWNrb3V0IHNwYW4uZXJyb3InKS5sZW5ndGggPCAxICkge1x0XHRcdFxuXHRcdFx0cmVuZGVyR3Vlc3RDaGVja291dChlbWFpbCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICgkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2d1ZXN0Y2hlY2tvdXRfdXNlcm5hbWVfXCJdLmVycm9yJykubGVuZ3RoID09IDApIHtcblx0XHRcdFx0aW52YWxpZGF0ZUd1ZXN0Q2hlY2tvdXQoKTtcblx0XHRcdH1cblx0XHR9XG4gICAgfSk7XG4gICBcblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICcub3JkZXItdG90YWwtcGF5bWVudHMgW3BheW1lbnQtbWV0aG9kXSAucmVtb3ZlJykub24oJ2NsaWNrJywgJy5vcmRlci10b3RhbC1wYXltZW50cyBbcGF5bWVudC1tZXRob2RdIC5yZW1vdmUnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBwYXltZW50SW5zdHJ1bWVudFVVSUQgPSAkKGUuY3VycmVudFRhcmdldCkuY2xvc2VzdCgnW3BheW1lbnQtbWV0aG9kJykuYXR0cigndXVpZCcpO1xuXHRcblx0XHRpZiAocGF5bWVudEluc3RydW1lbnRVVUlEKSB7XG5cdFx0XHR2YXIgcmVxdWVzdFBheWxvYWQgPSB7XG5cdFx0XHRcdFVVSUQ6IHBheW1lbnRJbnN0cnVtZW50VVVJRFxuXHRcdFx0fVxuXHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLnJlbW92ZVBheW1lbnRJbnN0cnVtZW50LFxuXHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHJlcXVlc3RQYXlsb2FkKSxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdHVwZGF0ZUNhcnQoJ2R3ZnJtX2NhcnRfdXBkYXRlQ2FydCcpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdDYXJ0LlVwZGF0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuICAgIFx0dXBkYXRlQ2FydCgnZHdmcm1fY2FydF91cGRhdGVDYXJ0JywgZGF0YSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlRW1haWwoZW1haWwpIHtcblx0dmFyIGlzRW1haWxWYWxpZCA9IHRydWU7XG5cdFxuXHRpZiAoZW1haWwubGVuZ3RoID09IDApe1xuXHRcdGlzRW1haWxWYWxpZCA9IHRydWU7XG5cdH1cblx0XG5cdHZhciByZWdleEVtYWlsID0gL14oPzpbYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKD86XFwuW2EtejAtOSEjJCUmJyorLz0/Xl9ge3x9fi1dKykqfFwiKD86W1xceDAxLVxceDA4XFx4MGJcXHgwY1xceDBlLVxceDFmXFx4MjFcXHgyMy1cXHg1YlxceDVkLVxceDdmXXxcXFxcW1xceDAxLVxceDA5XFx4MGJcXHgwY1xceDBlLVxceDdmXSkqXCIpQCg/Oig/OlthLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT9cXC4pK1thLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT98XFxbKD86KD86KDIoNVswLTVdfFswLTRdWzAtOV0pfDFbMC05XVswLTldfFsxLTldP1swLTldKSlcXC4pezN9KD86KDIoNVswLTVdfFswLTRdWzAtOV0pfDFbMC05XVswLTldfFsxLTldP1swLTldKXxbYS16MC05LV0qW2EtejAtOV06KD86W1xceDAxLVxceDA4XFx4MGJcXHgwY1xceDBlLVxceDFmXFx4MjEtXFx4NWFcXHg1My1cXHg3Zl18XFxcXFtcXHgwMS1cXHgwOVxceDBiXFx4MGNcXHgwZS1cXHg3Zl0pKylcXF0pJC87XG5cdGlmIChlbWFpbC5sZW5ndGggPiAwICYmIGVtYWlsLm1hdGNoKHJlZ2V4RW1haWwpID09IG51bGwpIHtcblx0XHRpc0VtYWlsVmFsaWQgPSBmYWxzZTtcblx0XHRpbnZhbGlkYXRlR3Vlc3RDaGVja291dCgpO1xuXHR9XG5cdFxuXHRyZXR1cm4gaXNFbWFpbFZhbGlkO1xufVxuXG5mdW5jdGlvbiBpbnZhbGlkYXRlR3Vlc3RDaGVja291dCgpIHtcblx0JCgnaW5wdXRbbmFtZV49XCJkd2ZybV9ndWVzdGNoZWNrb3V0X3VzZXJuYW1lX1wiXScpLnJlbW92ZUNsYXNzKCd2YWxpZCcpLmFkZENsYXNzKCdlcnJvcicpO1xuXHQkKCcuZ3Vlc3QtY2hlY2tvdXQgLmZpZWxkLXdyYXBwZXInKS5hcHBlbmQoJzxzcGFuIGNsYXNzPVwiZXJyb3IgY3VzdG9tLWd1ZXN0Y2hlY2tvdXQtZXJyb3JcIiBzdHlsZT1cImRpc3BsYXk6YmxvY2sgIWltcG9ydGFudDtcIj4nICsgUmVzb3VyY2VzLlZBTElEQVRFX0VNQUlMICsgJzwvc3Bhbj4nKTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyR3Vlc3RDaGVja291dChlbWFpbCkge1xuXHRcblx0aWYoZW1haWwubGVuZ3RoID4gMCl7XG5cdFx0dmFyIG9wdEluID0gZmFsc2U7XG5cdFx0XG5cdFx0aWYoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCl7XG5cdFx0XHR2YXIgc2lnbnVwRXZlbnQgPSAnJztcblx0XHRcdFxuXHRcdFx0dmFyIGF1dGhfZGF0YSA9IHtcblx0XHRcdFx0ZW1haWw6IGVtYWlsXG5cdFx0XHR9XG5cdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHQnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdFx0J2VtYWlsJzoge1xuXHRcdFx0XHRcdFx0J2FkZHJlc3MnOiBlbWFpbCxcblx0XHRcdFx0XHRcdCdzdWJzY3JpYmVTdGF0dXMnOiAnbm9uZSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXHRcdFx0XHQgICAgXG5cdFx0XHRcdCd3b3JrZmxvd19jaGVja291dF9hYmFuZG9uJzogdHJ1ZVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0dmFyIGd1ZXN0UHJvcGVydGllcyA9IHtcblx0XHRcdFx0J2VtYWlsJzogZW1haWwsXG5cdFx0XHRcdCd3b3JrZmxvd19jaGVja291dF9hYmFuZG9uJzogdHJ1ZVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0aWYgKCQoJyNndWVzdF9jaGVja291dF9vcHRpbicpLnByb3AoXCJjaGVja2VkXCIpKSB7XG5cdFx0XHRcdHZhciBhdXRoX2RhdGEgPSB7XG5cdFx0XHRcdFx0ZW1haWw6IGVtYWlsXG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdFx0XHQnY2hhbm5lbHMnOiB7XG5cdFx0XHRcdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdFx0XHRcdCdhZGRyZXNzJzogZW1haWwsXG5cdFx0XHRcdFx0XHRcdCdzdWJzY3JpYmVTdGF0dXMnOiAnc3Vic2NyaWJlZCdcdFx0XHRcdCAgICAgICAgICAgIFxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXHRcdFx0XHQgICAgXG5cdFx0XHRcdFx0J3NpZ251cF9zb3VyY2UnOiAnY2hlY2tvdXQnLFxuXHRcdFx0XHRcdCd3ZWxjb21lX3NpZ251cCc6IHRydWUsXG5cdFx0XHRcdFx0J3dvcmtmbG93X2NoZWNrb3V0X2FiYW5kb24nOiB0cnVlXG5cdFx0XHRcdH07XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgcHJvcGVydGllcyA9IHtcblx0XHRcdFx0XHQnc2lnbnVwX3NvdXJjZSc6ICdjaGVja291dCcsXG5cdFx0XHRcdFx0J3dlbGNvbWVfc2lnbnVwJzogdHJ1ZSxcblx0XHRcdFx0XHQnd29ya2Zsb3dfY2hlY2tvdXRfYWJhbmRvbic6IHRydWVcblx0XHRcdFx0fTtcblx0XHRcdFx0XG5cdFx0XHRcdHZhciBzaWdudXBFdmVudCA9IFsnZXZlbnQnLCAnZW1haWxfc2lnbnVwJywgcHJvcGVydGllc107XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdFJlcXVlc3RIZWxwZXIuVmFsaWRhdGUoJ0NvcmRpYWwtRW1haWxTaWdudXAnKS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0Y3JkbChbXG5cdFx0XHRcdFx0XHRbJ2NvbnRhY3QnLCBhdXRoX2RhdGEsIGNvbnRhY3RfZGF0YV0sXG5cdFx0XHRcdFx0XHRbJ2V2ZW50JywgJ2d1ZXN0X2NoZWNrb3V0JywgZ3Vlc3RQcm9wZXJ0aWVzXSxcblx0XHRcdFx0XHRcdHNpZ251cEV2ZW50XG5cdFx0XHRcdFx0XSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pLmNhdGNoKCk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHZhciBvcHRJbiA9ICQoJyNndWVzdF9jaGVja291dF9vcHRpbicpLnByb3AoXCJjaGVja2VkXCIpO1xuXHR9XG5cdFxuXHQkLmFqYXgoe1xuXHRcdHVybDogVXJscy5zZXRFbWFpbE9uQ2FydCxcblx0XHR0eXBlOiBcImdldFwiLFxuXHRcdGRhdGE6IHtlbWFpbDogZW1haWx9LFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblx0XHRcdFx0XG5cdFx0XHRpZiAoZGF0YS5zdGF0dXMgPT0gJ3N1Y2Nlc3MnKSB7XG5cdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5vbmVQYWdlICsgKCh3aW5kb3cuaW5uZXJXaWR0aCA8IFNpdGVDb25zdGFudHMuUmVzcG9uc2l2ZS5XaWR0aHMuTW9iaWxlKSA/ICcjYWRkcmVzc2luZm8nIDogJycpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0ZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuXHRcdFx0Y29uc29sZS5sb2codGV4dFN0YXR1cywgZXJyb3JUaHJvd24pO1xuXHRcdH1cblx0fSk7XG5cdFxuXHQkLmFqYXgoe1xuXHRcdHVybDogVXJscy5zZXRFbWFpbE9wdGluLFxuXHRcdHR5cGU6IFwiZ2V0XCIsXG5cdFx0ZGF0YToge29wdEluOiBvcHRJbn0sXG5cdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXHRcdFx0XHRcblx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLm9uZVBhZ2UgKyAoKHdpbmRvdy5pbm5lcldpZHRoIDwgU2l0ZUNvbnN0YW50cy5SZXNwb25zaXZlLldpZHRocy5Nb2JpbGUpID8gJyNhZGRyZXNzaW5mbycgOiAnJyk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRjb25zb2xlLmxvZyh0ZXh0U3RhdHVzLCBlcnJvclRocm93bik7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gdHJpZ2dlclJlYWN0V2Vidmlld0V2ZW50KCkge1xuXHRpZiAoJ1JlYWN0TmF0aXZlV2ViVmlldycgaW4gd2luZG93KSB7XG5cdFx0d2luZG93LlJlYWN0TmF0aXZlV2ViVmlldy5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeSh7IGFjdGlvbjogJ2NhcnQtcmVmcmVzaCcgfSkpO1xuXHR9XG59XG5cbnZhciB1cGRhdGVDYXJ0QnVmZmVyO1xudmFyIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlcjtcbmZ1bmN0aW9uIHVwZGF0ZUNhcnQodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHRpZiAodXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyKSB7XG5cdFx0Zm9yICh2YXIgdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0S2V5IGluIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlcikge1xuXHRcdFx0dmFyIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdCA9IHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclt1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RLZXldO1xuXHRcdFx0XG5cdFx0XHRpZiAodXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0LnJlYWR5U3RhdGUgIT09IDQpIHsgXG5cdFx0XHRcdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdC5hYm9ydCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXIgPSBbXTtcblx0dXBkYXRlQ2FydEJ1ZmZlciA9IFtdO1xuXG5cdGdldENhcnRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHRpZiAoIWlzQ2FydFBhZ2UpIHtcblx0XHRnZXRPcmRlclN1bW1hcnlDYWxsb3V0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRDYXJ0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKSB7XG4gICAgdmFyIGZvcm0gPSAkKFwiLnVwZGF0ZS1jYXJ0LWJ1dHRvblwiKS5wYXJlbnRzKCdmb3JtJyk7XG4gICAgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydCddID0gbnVsbDtcblxuXHRpZiAoZm9ybS5hdHRyKCdhY3Rpb24nKSkge1xuXHRcdGlmIChpc0NhcnRQYWdlID09IHVuZGVmaW5lZCkge1xuXHRcdFx0aXNDYXJ0UGFnZSA9ICQoJy5wdF9jYXJ0JykubGVuZ3RoID4gMDtcblx0XHR9XG5cblx0XHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbJ2dldENhcnRIdG1sJ10gPSAkLmFqYXgoe1xuXHQgICAgICAgIHVybCA6IGZvcm0uYXR0cignYWN0aW9uJyksXG5cdFx0ICAgIHR5cGUgOiBcIlBPU1RcIixcblx0ICAgICAgICBkYXRhIDogdHJpZ2dlckVsZW1lbnROYW1lICsgJz0nICsgdHJpZ2dlckVsZW1lbnROYW1lICsgJyZzZWxlY3RlZFBheW1lbnRNZXRob2Q9JyArICQoJ2lucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCkgKyAnJmZvcm1hdD1hamF4Jyxcblx0XHQgICAgc3VjY2VzcyA6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0ICAgIFx0dXBkYXRlQ2FydEJ1ZmZlclsnQ2FydCddID0gZGF0YTtcblx0XHRcdFx0Z2V0Q2FydERhdGEodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdFx0XHRcdHVwZGF0ZUNhcnRSZW5kZXIodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdFx0ICAgIH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRPcmRlclN1bW1hcnlDYWxsb3V0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKSB7XG4gICAgdXBkYXRlQ2FydEJ1ZmZlclsnT3JkZXJTdW1tYXJ5Q2FsbG91dCddID0gbnVsbDtcblxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbJ2dldE9yZGVyU3VtbWFyeUNhbGxvdXRIdG1sJ10gPSAkLmFqYXgoe1xuXHRcdHVybDogVXJscy5nZXRPcmRlclN1bW1hcnlDYWxsb3V0Q29udGVudFNsb3QsXG5cdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0dXBkYXRlQ2FydEJ1ZmZlclsnT3JkZXJTdW1tYXJ5Q2FsbG91dCddID0gZGF0YTtcblx0XHRcdHVwZGF0ZUNhcnRSZW5kZXIodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2FydERhdGEodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddID0gbnVsbDtcblxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbJ2dldENhcnREYXRhJ10gPSAkLmFqYXgoe1xuXHQgICAgdXJsIDogVXJscy5nZXRDYXJ0RGF0YSxcblx0XHR0eXBlIDogXCJQT1NUXCIsXG5cdFx0ZGF0YToge1xuXHRcdFx0aXNDYXJ0OiBpc0NhcnRQYWdlXG5cdFx0fSxcblx0ICAgIHN1Y2Nlc3MgOiBmdW5jdGlvbiAoZGF0YSkge1xuXHQgICAgXHQkKCdbaGFzLWxvY2FsLWRlbGl2ZXJ5LXNoaXBtZW50XScpLmF0dHIoJ2hhcy1sb2NhbC1kZWxpdmVyeS1zaGlwbWVudCcsIGRhdGEuSGFzTG9jYWxEZWxpdmVyeVNoaXBtZW50IHx8IGZhbHNlKTtcblx0ICAgIFx0JCgnW2hhcy1waHlzaWNhbC1zaGlwbWVudF0nKS5hdHRyKCdoYXMtcGh5c2ljYWwtc2hpcG1lbnQnLCBkYXRhLkhhc1BoeXNpY2FsU2hpcG1lbnQgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy13YXJlaG91c2Utc2hpcG1lbnRdJykuYXR0cignaGFzLXdhcmVob3VzZS1zaGlwbWVudCcsIGRhdGEuSGFzV2FyZWhvdXNlU2hpcG1lbnQgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy13YXJlaG91c2Utc2hpcG1lbnRdJykuYXR0cignaGFzLXNoaXBwaW5nLW1ldGhvZHMnLCBkYXRhLlNoaXBwaW5nTWV0aG9kcyA/IGRhdGEuU2hpcHBpbmdNZXRob2RzLmpvaW4oJyAnKSA6IGZhbHNlKTtcblx0ICAgIFx0JCgnW2hhcy1naWZ0LWNhcmRzXScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzJywgZGF0YS5IYXNHaWZ0Q2FyZHMgfHwgZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLWdpZnQtY2FyZHMtb25seV0nKS5hdHRyKCdoYXMtZ2lmdC1jYXJkcy1vbmx5JywgZGF0YS5IYXNHaWZ0Q2FyZHNPbmx5IHx8IGZhbHNlKTtcblx0XHRcdCQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50XScpLmF0dHIoJ2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQnLCAoZGF0YS5Cb3BpcyAmJiBkYXRhLkJvcGlzLkhhc1N0b3JlUGlja3VwU2hpcG1lbnQpIHx8IGZhbHNlKTtcblx0XHRcdCQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHldJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5JywgKGRhdGEuQm9waXMgJiYgZGF0YS5Cb3Bpcy5IYXNTdG9yZVBpY2t1cFNoaXBtZW50T25seSkgfHwgZmFsc2UpO1xuXG5cdFx0XHRpZiAoZGF0YS5Cb3BpcyAmJiBkYXRhLkJvcGlzLkhhc1N0b3JlUGlja3VwU2hpcG1lbnRPbmx5KSB7XG5cdFx0XHRcdCQoJyNpc1NoaXBwaW5nQWRkcmVzc1NhbWVBc0JpbGxpbmdBZGRyZXNzJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHRcdH1cblxuXHQgICAgXHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0RGF0YS5VcGRhdGUnLCBkYXRhKTtcblxuXHQgICAgXHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddID0gZGF0YTtcblx0ICAgIFx0aWYgKGRhdGEuQm9waXMpIHtcblx0ICAgIFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddID0gZGF0YS5Cb3Bpcztcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aWYgKCFkYXRhLklzR2xvYmFsZVZhbGlkT3JJbmFjdGl2ZSkge1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykuYWRkQ2xhc3MoJ2dsb2JhbC1lLXZhbGlkYXRpb24tZXJyb3InKTtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLmZpbmQoJy5jYXJ0LWVycm9ycycpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLnJlbW92ZUNsYXNzKCdnbG9iYWwtZS12YWxpZGF0aW9uLWVycm9yJyk7XG5cdCAgICBcdFx0JCgnLnNlY3Rpb24tY2hlY2tvdXQnKS5maW5kKCcuY2FydC1lcnJvcnMnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdCAgICBcdH1cblxuXHQgICAgXHRpZiAoKCFkYXRhLk9yZGVyVG90YWwgfHwgIWRhdGEuT3JkZXJUb3RhbC5iYWxhbmNlQXZhaWxhYmxlKSB8fCAoZGF0YS5TaGlwcGluZ1Jlc3RyaWN0aW9ucyAmJiBkYXRhLlNoaXBwaW5nUmVzdHJpY3Rpb25zLlN0YXR1cyA9PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpKSB7XG5cdFx0XHRcdGlmICghaXNDYXJ0UGFnZSkge1xuXHRcdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZHMtc2VjdGlvbicpLmhpZGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKGlzQ2FydFBhZ2UpIHtcblx0XHRcdFx0XHQkKCcuZ3Vlc3QtY2hlY2tvdXQgLmVycm9yLWZvcm0nKS5yZW1vdmUoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2RzLXNlY3Rpb24nKS5zaG93KCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0ICAgIFx0XG5cdCAgICBcdGhhbmRsZU9yZGVyVG90YWwodHJpZ2dlckVsZW1lbnROYW1lLCB1cGRhdGVDYXJ0T3B0aW9ucywgaXNDYXJ0UGFnZSk7XG5cdCAgICB9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVPcmRlclRvdGFsKHRyaWdnZXJFbGVtZW50TmFtZSwgdXBkYXRlQ2FydE9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcblx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gPSBudWxsO1xuXHR2YXIgcmVtb3ZlQWN0aW9uID0gJzxhIGNsYXNzPVwicmVtb3ZlXCI+UmVtb3ZlPC9hPic7XG5cdHZhciByZXdhcmRzUHJvZ3JhbSA9ICcnO1xuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuXHRcdHJld2FyZHNQcm9ncmFtID0gJ0NsdWIgQ08nO1xuXHR9XG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG5cdFx0cmV3YXJkc1Byb2dyYW0gPSAnU2hlcGxlcnMnO1xuXHR9XG5cdFxuXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gPSAnJztcblx0XG5cdFx0Zm9yICh2YXIgcGF5bWVudEluc3RydW1lbnRLZXkgaW4gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cykge1xuXHRcdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50ID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50c1twYXltZW50SW5zdHJ1bWVudEtleV07XG5cdFx0XHR2YXIgcGF5bWVudEluc3RydW1lbnRVVUlEQXR0cmlidXRlID0gJ3V1aWQ9XCInICsgcGF5bWVudEluc3RydW1lbnQuVVVJRCArICdcIic7XG5cdFx0XHRcblx0XHRcdHN3aXRjaCAocGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCkge1xuXHRcdFx0XHRjYXNlIFBheW1lbnRNZXRob2RDb25zdGFudHMuUmV3YXJkc0NyZWRpdDpcblx0XHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddICs9ICc8ZGl2ICcgKyBwYXltZW50SW5zdHJ1bWVudFVVSURBdHRyaWJ1dGUgKyAnIHBheW1lbnQtbWV0aG9kPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuSWQgKyAnXCIgYWxsb3ctcmVtb3ZlPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LmFsbG93UmVtb3ZlICsgJ1wiPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPjxzcGFuIGNsYXNzPVwibmFtZVwiPkIgUmV3YXJkZWQ8L3NwYW4+Jm5ic3A7PHNwYW4gY2xhc3M9XCJudW1iZXJcIj5SZXdhcmQ8L3NwYW4+PC9zcGFuPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiPicgKyBwYXltZW50SW5zdHJ1bWVudC5hbW91bnREaXNwbGF5ICsgJzwvc3Bhbj4nICtcblx0XHQgICAgXHRcdCc8L2Rpdj4nO1xuXHRcdCAgICBcdGJyZWFrO1xuXHRcdCAgICBcdFxuXHRcdFx0XHRjYXNlIFBheW1lbnRNZXRob2RDb25zdGFudHMuTG95YWx0eUNyZWRpdDpcblx0XHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddICs9ICc8ZGl2ICcgKyBwYXltZW50SW5zdHJ1bWVudFVVSURBdHRyaWJ1dGUgKyAnIHBheW1lbnQtbWV0aG9kPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuSWQgKyAnXCIgYWxsb3ctcmVtb3ZlPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LmFsbG93UmVtb3ZlICsgJ1wiPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPjxzcGFuIGNsYXNzPVwibmFtZVwiPicrcmV3YXJkc1Byb2dyYW0rJzwvc3Bhbj4mbmJzcDs8c3BhbiBjbGFzcz1cIm51bWJlclwiPlJld2FyZDwvc3Bhbj48L3NwYW4+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LmFtb3VudERpc3BsYXkgKyAnPC9zcGFuPicgK1xuXHRcdCAgICBcdFx0JzwvZGl2Pic7XG5cdFx0ICAgIFx0YnJlYWs7XG5cdFx0XHRcblx0XHRcdFx0ZGVmYXVsdDpcblx0XHQgICAgXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddICs9ICc8ZGl2ICcgKyBwYXltZW50SW5zdHJ1bWVudFVVSURBdHRyaWJ1dGUgKyAnIHBheW1lbnQtbWV0aG9kPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuSWQgKyAnXCIgYWxsb3ctcmVtb3ZlPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LmFsbG93UmVtb3ZlICsgJ1wiPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJsYWJlbFwiPjxzcGFuIGNsYXNzPVwibmFtZVwiPicgKyBwYXltZW50SW5zdHJ1bWVudC5wYXltZW50TWV0aG9kLk5hbWUgKyAnPC9zcGFuPiZuYnNwOzxzcGFuIGNsYXNzPVwibnVtYmVyXCI+JyArIHBheW1lbnRJbnN0cnVtZW50Lm51bWJlciArICc8L3NwYW4+JyArIHJlbW92ZUFjdGlvbiArICc8L3NwYW4+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LmFtb3VudERpc3BsYXkgKyAnPC9zcGFuPicgK1xuXHRcdCAgICBcdFx0JzwvZGl2Pic7XG5cdFx0ICAgIFx0YnJlYWs7XG5cdFx0ICAgIH1cblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignR2lmdENhcmQuQ2xlYXInKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdSZXdhcmRzQ3JlZGl0LkNsZWFyJyk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignTG95YWx0eUNyZWRpdC5DbGVhcicpO1xuXHR9XG5cdFxuXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwudG90YWwpIHtcblx0XHR1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddID0gJzxzcGFuIGNsYXNzPVwibGFiZWxcIj5CYWxhbmNlIER1ZTwvc3Bhbj4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlRGlzcGxheSArICc8L3NwYW4+Jztcblx0fVxuXHRcblx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIHVwZGF0ZUNhcnRPcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gJiYgKGlzQ2FydFBhZ2UgfHwgKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSAmJiB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddKSkpIHtcblx0XHR2YXIgJGJhc2tldENvbnRhaW5lckh0bWwgPSAkKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnQnXSk7XG5cdFxuXHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbCkge1xuXHRcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFsLXByaWNlIC52YWx1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnRvdGFsRGlzcGxheSk7XG5cdCAgICBcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLXRvdGFsLXByaWNlIC52YWx1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnRvdGFsRGlzcGxheSk7XG5cdFx0XG5cdFx0XHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5hdHRyKCdwYXltZW50cy1hcHBsaWVkJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGgpO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hdHRyKCdwYXltZW50cy1hcHBsaWVkJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLnBheW1lbnRJbnN0cnVtZW50cy5sZW5ndGgpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5yZW1vdmVBdHRyKCdwYXltZW50cy1hcHBsaWVkJyk7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUF0dHIoJ3BheW1lbnRzLWFwcGxpZWQnKTtcblx0ICAgIFx0fVxuXHRcdFxuXHRcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLXRvdGFscy10YWJsZScpLmF0dHIoJ2JhbGFuY2UtZHVlJywgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UpO1xuXHQgICAgXHQkKCdib2R5JykuYXR0cignYmFsYW5jZS1kdWUnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSk7XG5cdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYXR0cignYmFsYW5jZS1kdWUnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSk7XG5cdFx0XG5cdFx0XHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPiAwKSB7XG5cdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZC1vcHRpb25zJykuc2hvdygpO1xuXHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uLWZvb3RlcltkYXRhLW1ldGhvZD1cIlBheVBhbFwiXSBidXR0b24nKS5oaWRlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2Qtb3B0aW9ucycpLmhpZGUoKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbi1mb290ZXJbZGF0YS1tZXRob2Q9XCJQYXlQYWxcIl0gYnV0dG9uJykuc2hvdygpO1xuXHRcdFx0fVxuXHRcdFxuXHQgICAgXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQmFsYW5jZUR1ZUh0bWwnXSkge1x0XG5cdCAgICBcdFx0JGJhc2tldENvbnRhaW5lckh0bWwuZmluZCgnLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddKTtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uIC5vcmRlci1iYWxhbmNlLWR1ZScpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnQmFsYW5jZUR1ZUh0bWwnXSk7ICAgIFx0XHRcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uIC5vcmRlci1iYWxhbmNlLWR1ZScpLmh0bWwoJycpO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10pIHtcblx0ICAgIFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItdG90YWwtcGF5bWVudHMnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddKTtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uIC5vcmRlci10b3RhbC1wYXltZW50cycpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10pO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLXRvdGFsLXBheW1lbnRzJykuaHRtbCgnJyk7XG5cdCAgICBcdH1cblx0XHR9XG5cblx0XHQkKCcuYmFza2V0LWNvbnRhaW5lcicpLmh0bWwoJGJhc2tldENvbnRhaW5lckh0bWwpO1xuXHRcdFxuXHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddKSB7XG5cdFx0XHR2YXIgb3JkZXJUb3RhbEZvckFmZmlybSA9IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlO1xuXHRcdFx0aWYgKCFvcmRlclRvdGFsRm9yQWZmaXJtICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5hZGp1c3RlZE1lcmNoYW5kaXplVG90YWxQcmljZSkge1xuXHRcdFx0XHRvcmRlclRvdGFsRm9yQWZmaXJtID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCdhZmZpcm0nIGluIHdpbmRvdyAmJiAndWknIGluIGFmZmlybSAmJiAncmVmcmVzaCcgaW4gYWZmaXJtLnVpICYmIG9yZGVyVG90YWxGb3JBZmZpcm0gPj0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5BZmZpcm1NaW5pbXVtT3JkZXJUb3RhbCkge1xuXHRcdFx0XHQkKCcuYWZmaXJtLXByb2R1Y3QtbW9kYWwnKS5hdHRyKCdkYXRhLWFtb3VudCcsIG9yZGVyVG90YWxGb3JBZmZpcm0gKiAxMDApO1xuXHRcdFx0XHRhZmZpcm0udWkucmVmcmVzaCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JCgnLmFmZmlybS1wcm9kdWN0LW1vZGFsJykuYXR0cignZGF0YS1hbW91bnQnLCA1MDAwKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoJCgnLmJhc2tldC1jb250YWluZXInKS5maW5kKCcucHJvZHVjdC1hdmFpbGFiaWxpdHktbGlzdCAubm90LWF2YWlsYWJsZScpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50LCAjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG5cdFx0XHQkKCcjZXJyb3JCb3hPUEMnKS5yZW1vdmUoKTtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50JykuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj4nICsgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuUHJvZHVjdHMuQXZhaWxhYmlsaXR5ICsgJzo8L2I+ICcgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5Qcm9kdWN0cy5BdmFpbGFiaWxpdHlFeGNlZWRlZCArICc8L2Rpdj4nKTtcblx0XHR9IGVsc2UgaWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0JvcGlzJ10gJiYgdXBkYXRlQ2FydEJ1ZmZlclsnQm9waXMnXS5OdW1iZXJPZkJvcGlzU3RvcmVzSW5DYXJ0ID4gdXBkYXRlQ2FydEJ1ZmZlclsnQm9waXMnXS5NYXhpbXVtTnVtYmVyT2ZCb3Bpc1N0b3Jlc0luQ2FydCkge1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQsICNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0XHRcdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQnKS5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwLTIgbXQtMlwiIHJvbGU9XCJhbGVydFwiIHRhYmluZGV4PVwiMFwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPicgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5HZW5lcmFsLkNhcnRMaW1pdCArICc6PC9iPiAnICsgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuQm9waXMuTWF4aW11bVN0b3Jlc0V4Y2VlZGVkICsgJzwvZGl2PicpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCwgI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10pIHtcdFxuXHRcdFx0JCgnLmNhbGxvdXQtb3JkZXJzdW1tYXJ5JykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10pO1xuXHRcdH1cblx0XHRcblx0ICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuU1RPUkVfUElDS1VQKSB7XG5cdCAgICAgICAgY2FydFN0b3JlSW52ZW50b3J5LmluaXQoKTtcblx0ICAgIH1cblx0ICAgIFxuXHQgICAgYWNjb3VudC5pbml0Q2FydExvZ2luKCk7XG5cdCAgICBjaGVja0NoZWNrb3V0QWNjZXNzaWJpbGl0eSgpO1xuXG5cdFx0dmFyICRjYXJ0TWluaUNhcnRCdXR0b24gPSAkKCcuYmFubmVyLWNhcnQtaG9sZGVyIC5idG4tbWluaWNhcnQnKTtcblx0ICAgIGlmICgkY2FydE1pbmlDYXJ0QnV0dG9uLmxlbmd0aCA+IDApIHtcblx0XHRcdCQuYWpheCh7dXJsIDogVXJscy5jYXJ0TWluaUNhcnQsIGRhdGEgOiB7ZGVza3RvcDogJzEnfSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0ICAgICAgICAgICAgJCgnLmJhbm5lci1jYXJ0LWhvbGRlcicpLmh0bWwoZGF0YSk7XG5cdCAgICAgICAgfX0pO1xuXHRcdFx0XG5cdCAgICBcdCQuYWpheCh7dXJsIDogVXJscy5jYXJ0TWluaUNhcnQsIGRhdGFUeXBlOiAnaHRtbCcsIHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdCAgICBcdFx0dmFyIHBhcmVudE1pbmlDYXJ0ID0gJChcIi50b3AtYmFubmVyLWlubmVyLWxpbmtzICNtaW5pLWNhcnRcIik7XG5cdCAgICBcdFx0XG5cdCAgICBcdFx0aWYgKHBhcmVudE1pbmlDYXJ0Lmxlbmd0aCA+IDApIHtcblx0ICAgIFx0XHRcdHBhcmVudE1pbmlDYXJ0Lmh0bWwoZGF0YSk7XG5cdCAgICBcdFx0fVxuXHQgICAgICAgIH19KTtcblx0XHR9XG5cdCAgICBcbiAgICAgICAgJC5hamF4KHt1cmw6IFVybHMuY2FydEl0ZW1RdWFudGl0eSwgZGF0YToge2Rlc2t0b3A6ICcxJ30sIGRhdGFUeXBlOiAnaHRtbCcsIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIFx0JCgnLmNvbmZpcm1hdGlvbi1tZXNzYWdlIC5pdGVtLWNvdW50JykuaHRtbChkYXRhKTtcblx0ICAgICAgICBcblx0ICAgICAgICB2YXIgcXVhbnRpdHkgPSBwYXJzZUludCgkKCcuY29uZmlybWF0aW9uLW1lc3NhZ2UgLml0ZW0tY291bnQnKS5maW5kKCdzcGFuJykudGV4dCgpLCAxMCk7XG5cdCAgICAgICAgaWYgKCFxdWFudGl0eSkge1xuXHQgICAgICAgICAgICAkKCcuY2hlY2tvdXQtYnV0dG9ucy5tb2JpbGUtb25seScpLmhpZGUoKTtcdCAgICAgICAgICAgIFxuXHRcdFx0fVxuXHRcdH19KTtcblx0XHRcblx0ICAgIFxuXHQgICAgaWYgKHRyaWdnZXJFbGVtZW50TmFtZS5pbmRleE9mKCdkZWxldGVQcm9kdWN0JykgPiAtMSkge1xuXHQgICAgXHQkKGRvY3VtZW50KS50cmlnZ2VyKCdyZWZyZXNoLXJlcXVpcmVkJyk7XG5cdCAgICB9XG5cblx0XHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuRXZlbnRUcmlnZ2VycyB8fCBvcHRpb25zLkV2ZW50VHJpZ2dlcnNbJ3VwZGF0ZS1zdW1tYXJ5J10pIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VwZGF0ZS1zdW1tYXJ5Jyk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5FdmVudFRyaWdnZXJzIHx8IG9wdGlvbnMuRXZlbnRUcmlnZ2Vyc1sndXBkYXRlLXNoaXBwaW5nJ10pIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VwZGF0ZS1zaGlwcGluZycpO1xuXHRcdH1cblx0ICAgIFxuXHQgICAgJCgnW21pbmltdW0tY2FydC10b3RhbF0sIFttYXhpbXVtLWNhcnQtdG90YWxdJykuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHQgICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHQgICAgXHR2YXIgcGF5bWVudE1ldGhvZENhcnRUb3RhbE1pbmltdW0gPSBwYXJzZUZsb2F0KCR0aGlzLmF0dHIoJ21pbmltdW0tY2FydC10b3RhbCcpKTtcblx0ICAgIFx0dmFyIHBheW1lbnRNZXRob2RDYXJ0VG90YWxNYXhpbXVtID0gcGFyc2VGbG9hdCgkdGhpcy5hdHRyKCdtYXhpbXVtLWNhcnQtdG90YWwnKSk7XG5cdCAgICBcblx0ICAgIFx0dmFyIGlzQ2FydFRvdGFsTWluaW11bVZhbGlkID0gZmFsc2U7XG5cdCAgICBcdGlmIChpc05hTihwYXltZW50TWV0aG9kQ2FydFRvdGFsTWluaW11bSkgfHwgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPj0gcGF5bWVudE1ldGhvZENhcnRUb3RhbE1pbmltdW0pIHtcblx0ICAgIFx0XHRpc0NhcnRUb3RhbE1pbmltdW1WYWxpZCA9IHRydWU7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdHZhciBpc0NhcnRUb3RhbE1heGltdW1WYWxpZCA9IGZhbHNlO1xuXHQgICAgXHRpZiAoaXNOYU4ocGF5bWVudE1ldGhvZENhcnRUb3RhbE1heGltdW0pIHx8IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlIDw9IHBheW1lbnRNZXRob2RDYXJ0VG90YWxNYXhpbXVtKSB7XG5cdCAgICBcdFx0aXNDYXJ0VG90YWxNYXhpbXVtVmFsaWQgPSB0cnVlO1xuXHQgICAgXHR9XG5cdCAgICBcdFxuXHQgICAgXHRpZiAoaXNDYXJ0VG90YWxNaW5pbXVtVmFsaWQgJiYgaXNDYXJ0VG90YWxNYXhpbXVtVmFsaWQpIHtcblx0ICAgIFx0XHQkdGhpcy5jbG9zZXN0KCcucGF5bWVudC1tZXRob2Qtb3B0aW9uJykuYXR0cigndmFsaWQtZm9yLWJhbGFuY2UtZHVlJywgJ3RydWUnKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkdGhpcy5jbG9zZXN0KCcucGF5bWVudC1tZXRob2Qtb3B0aW9uJykuYXR0cigndmFsaWQtZm9yLWJhbGFuY2UtZHVlJywgJ2ZhbHNlJyk7XG5cdCAgICBcdH1cblx0ICAgIH0pO1xuXHRcdFxuXHQgICAgaWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10gJiYgIXVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uSGFzUGh5c2ljYWxTaGlwbWVudCAmJiAkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dDpjaGVja2VkJykudmFsKCkgIT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuQ3VzdG9tZXIpIHtcblx0ICAgIFx0JCgnLnNpbmdsZS5zaGlwcGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXRbdmFsdWU9XCInICsgU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuQ3VzdG9tZXIgKyAnXCJdJykuY2xpY2soKTtcblx0ICAgIH1cblx0XHRcblx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0aXRlbXM6ICcuc2hpcHBpbmctbWV0aG9kLXRvb2x0aXAnLFxuXHRcdFx0dG9vbHRpcENsYXNzOiAnc2hpcHBpbmctbWV0aG9kLXRvb2x0aXAnXG5cdFx0fSwgJCgnW3NoaXBwaW5nLW1ldGhvZF0nKSk7XG5cblx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0aXRlbXM6ICcudG9vbHRpcCdcblx0XHR9KTtcblxuXHRcdHRyaWdnZXJSZWFjdFdlYnZpZXdFdmVudCgpO1xuXHRcdHRyaWdnZXJTckZvY3VzKCk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignUXVhbnRpdHlTdGVwcGVyLlRhcmdldEZvY3VzJyk7XG5cdCAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZVN1Y2Nlc3MnKTtcblx0fVxufVxuXG5mdW5jdGlvbiB0cmlnZ2VyU3JGb2N1cygpIHtcblx0JCgnW3JvbGU9XCJhbGVydFwiXTp2aXNpYmxlJykubGFzdCgpLmZvY3VzKCkuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrQ2hlY2tvdXRBY2Nlc3NpYmlsaXR5KCkge1xuXHRpZiAoJCgnLm9yZGVyLWl0ZW0nKS5sZW5ndGggPT0gMCkge1xuXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0ID4gZGl2JykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZm9ybSwgLnNoaXBwaW5nLWFkZHJlc3MtY29udCwgLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmhpZGUoKTtcblx0XHQkKCcuZm9ybS1jaGVja291dC5sb2dpbi1lbGVtZW50LCAuc2VjdGlvbi1jaGVja291dCcpLmFkZENsYXNzKCdlbXB0eS1jYXJ0Jyk7XG5cdH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIGdldCBjdXN0b21lciBkYXRhXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGZvcm0gVGhlIGZvcm0gZWxlbWVudCB0aGF0IGNvbnRhaW5zIHRoZSBpdGVtIHF1YW50aXR5IGFuZCBJRCBkYXRhXG4gKiBAcGFyYW0ge0VsZW1lbnR9IEFjdGlvbiBuYW1lIHRvIGFwcGx5IHRvIGZvcm1cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgdXBkYXRlQ3VzdG9tZXJEZXRhaWxzID0gZnVuY3Rpb24gKGZvcm0sIG5hbWUpIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm0pO1xuXG4gICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLm9uZVBhZ2VMb2dpbiksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWVcbiAgICB9KSk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gcmVzZXQgY3VzdG9tZXIgcGFzc3dvcmRcbiAqIEBwYXJhbSB7U3RyaW5nfSByZWdpc3RlcmVkIGN1c3RvbWVyIGVtYWlsXG4gKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAqL1xudmFyIHJlc2V0Q3VzdG9tZXJQYXNzd29yZCA9IGZ1bmN0aW9uIChlbWFpbCkge1xuXHRyZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMucmVzZXRPUENQYXNzKSxcbiAgICAgICAgZGF0YTogJ2VtYWlsPScrIGVtYWlsXG4gICAgfSkpO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIHJlc2V0IGN1c3RvbWVyIHBhc3N3b3JkXG4gKiBAcGFyYW0ge1N0cmluZ30gZXJyb3IgbWVzc2FnZVxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IHRvIGFkZCBlcnJvciBhZnRlclxuICogQHJldHVybnMge1ZvaWR9XG4gKi9cbnZhciBzaG93RXJyb3IgPSBmdW5jdGlvbihtZXNzYWdlLCBzZWxlY3Rvcil7XG5cdHZhciAkZXJyb3JDb250YWluZXIgPSBzZWxlY3Rvci5jbG9zZXN0KCdmaWVsZC13cmFwcGVyJykubmV4dCgnLmVycm9yJyk7XG5cblx0aWYgKCEkZXJyb3JDb250YWluZXIucHJvcCgnZGVmYXVsdFRleHQnKSB8fCAkZXJyb3JDb250YWluZXIudGV4dCgpICE9IG1lc3NhZ2UpIHtcblx0XHRzZWxlY3Rvci5wcm9wKCdkZWZhdWx0VGV4dCcsICRlcnJvckNvbnRhaW5lci50ZXh0KCkpO1xuXHR9XG5cdFxuXHQkZXJyb3JDb250YWluZXIudGV4dChtZXNzYWdlKS5zaG93KCk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gcmVzZXQgY3VzdG9tZXIgcGFzc3dvcmRcbiAqIEBwYXJhbSB7U3RyaW5nfSBub3RpZmljYXRpb24gdGV4dFxuICogQHBhcmFtIHtFbGVtZW50fSBzZWxlY3RvciB0byBhcHBseSBtZXNzYWdlXG4gKiBAcGFyYW0ge1N0cmluZ30gbm90aWZpY2F0aW9uIHR5cGU6IGVycm9yIG9yIHN1Y2Nlc3NcbiAqIEByZXR1cm5zIHtWb2lkfVxuICovXG5mdW5jdGlvbiBzaG93Tm90aWZpY2F0aW9uKHRleHQsIHNlbGVjdG9yLCBtc2dUeXBlKSB7XG5cdHZhciAkc2VsZWN0b3IgPSAkKHNlbGVjdG9yKTtcblx0aWYgKCRzZWxlY3Rvci5sZW5ndGggPT0gMCkge1xuXHRcdHZhciAkZm9ybSA9ICQoJ2Zvcm0ub3BjLWxvZ2luJyk7XG5cdFx0JHNlbGVjdG9yID0gJCgnPHNwYW4vPicsIHsnY2xhc3MnOiAnbG9naW4tbm90aWZpY2F0aW9uJ30pLndyYXAoJzxkaXYgY2xhc3M9XCJmb3JtZmllbGQgY2xlYXJmaXggZXJyb3ItYm94XCI+PGRpdiBjbGFzcz1cImZvcm0tcm93IHJlcXVpcmVkXCI+PGRpdiBjbGFzcz1cImZpZWxkLXdyYXBwZXJcIj48L2Rpdj48L2Rpdj48L2Rpdj4nKTtcblxuXHRcdCRzZWxlY3Rvci5wYXJlbnQoKS5wYXJlbnQoKS5wYXJlbnQoKS5pbnNlcnRCZWZvcmUoJ2Zvcm0ub3BjLWxvZ2luIC5mb3JtLXJvdy1idXR0b24nKTtcblx0XHQkc2VsZWN0b3IgPSAkKHNlbGVjdG9yKTtcblx0fVxuXG5cdCRzZWxlY3Rvci5yZW1vdmVDbGFzcygnc3VjY2VzcyBlcnJvcicpLmFkZENsYXNzKG1zZ1R5cGUpLnRleHQodGV4dCk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gcmVzZXQgY3VzdG9tZXIgcGFzc3dvcmRcbiAqIEBwYXJhbSB7RWxlbWVudH0gc2VsZWN0b3IgdG8gY2xlYXIgbm90aWZpY2F0aW9uIHR5cGU6IGVycm9yIG9yIHN1Y2Nlc3NcbiAqIEByZXR1cm5zIHtWb2lkfVxuICovXG5mdW5jdGlvbiBjbGVhck5vdGlmaWNhdGlvbihzZWxlY3Rvcil7XG5cdGlmIChzZWxlY3Rvci5sZW5ndGgpIHtcblx0XHQkKCcuZm9ybWZpZWxkLmVycm9yLWJveCcpLnJlbW92ZSgpO1xuXHRcdHNlbGVjdG9yLnJlbW92ZUNsYXNzKCdzdWNjZXNzIGVycm9yJyk7XG5cdH1cbn07XG5cbmV4cG9ydHMudXBkYXRlQ2FydCA9IHVwZGF0ZUNhcnQ7XG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5pc0NhcnRQYWdlKSB7XG4gICAgXHRpc0NhcnRQYWdlID0gdHJ1ZTtcbiAgICB9XG4gICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuU1RPUkVfUElDS1VQKSB7XG4gICAgICAgIGNhcnRTdG9yZUludmVudG9yeS5pbml0KCk7XG4gICAgfVxuXHRBcHBsZVBheS5pbml0aWFsaXplKG9wdGlvbnMpO1xuICAgIGFjY291bnQuaW5pdENhcnRMb2dpbigpO1xuXHRxdWFudGl0eVN0ZXBwZXIuaW5pdCh1cGRhdGVDYXJ0KTtcbiAgICB1cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnLCBudWxsLCBvcHRpb25zLmlzQ2FydFBhZ2UpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBhZGRUb0NhcnQgPSByZXF1aXJlKCcuL3Byb2R1Y3QvYWRkVG9DYXJ0Jyk7XG52YXIgcXVhbnRpdHlTdGVwcGVyID0gcmVxdWlyZSgnLi4vcXVhbnRpdHlTdGVwcGVyJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcblxudmFyIGh0bWwgPSB7fTtcbnZhciBvcHRpb25zID0ge307XG52YXIgZGF0YSA9IHt9O1xudmFyIHRlbXBsYXRlcyA9IHt9O1xuXG52YXIgdmlkZW87XG52YXIgc3RyZWFtO1xudmFyIGJhcmNvZGVEZXRlY3RvcjtcbnZhciBiYXJjb2RlRGV0ZWN0b3JJbnRlcnZhbDtcbnZhciBiYXJjb2RlU2NhbklucHV0QWRkUHJvZHVjdFRpbWVyO1xudmFyIGJhcmNvZGVTY2FuSW5wdXRGb2N1c0ludGVydmFsO1xudmFyIHByb2R1Y3RTZWFyY2hJbnB1dEZvY3VzSW50ZXJ2YWw7XG5cbnZhciAkcHJvZHVjdEZpbmRlcjtcbnZhciAkYmFyY29kZVNjYW5uZXI7XG52YXIgJGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXI7XG52YXIgJGJhcmNvZGVTY2FubmVySW5wdXQ7XG52YXIgJGJhcmNvZGVTY2FubmVyRXJyb3JDb250YWluZXI7XG52YXIgJGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uO1xudmFyICRiYXJjb2RlU2Nhbm5lckFkZEJ1dHRvblRleHQ7XG52YXIgJGJhcmNvZGVTY2FubmVyU3RhcnRCdXR0b247XG52YXIgJGJhcmNvZGVTY2FubmVyU3RhcnRCdXR0b25UZXh0O1xudmFyICRiYXJjb2RlU2Nhbm5lck1vZGFsO1xudmFyICRwcm9kdWN0U2VhcmNoO1xudmFyICRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXI7XG52YXIgJHByb2R1Y3RTZWFyY2hJbnB1dDtcbnZhciAkcHJvZHVjdFNlYXJjaEVycm9yQ29udGFpbmVyO1xudmFyICRwcm9kdWN0U2VhcmNoU2VhcmNoQnV0dG9uO1xudmFyICRwcm9kdWN0U2VhcmNoU2VhcmNoQnV0dG9uVGV4dDtcbnZhciAkcHJvZHVjdFNlYXJjaFJlc3VsdHNDb250YWluZXI7XG52YXIgJHByb2R1Y3RTZWFyY2hSZXN1bHRzO1xudmFyICRwcm9kdWN0U2VhcmNoUmVzdWx0c0Zvb3RlcjtcbnZhciAkcHJvZHVjdFNlYXJjaFJlc3VsdHNMb2FkTW9yZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zKSB7XG5cdCRwcm9kdWN0RmluZGVyID0gJCgnLnByb2R1Y3QtZmluZGVyJyk7XG5cdCRiYXJjb2RlU2Nhbm5lciA9ICRwcm9kdWN0RmluZGVyLmZpbmQoJy5zZWN0aW9uLnNjYW4nKTtcblx0JGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIgPSAkYmFyY29kZVNjYW5uZXIuZmluZCgnLmlucHV0Jyk7XG5cdCRiYXJjb2RlU2Nhbm5lcklucHV0ID0gJGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIuZmluZCgnaW5wdXQnKTtcblx0JGJhcmNvZGVTY2FubmVyRXJyb3JDb250YWluZXIgPSAkYmFyY29kZVNjYW5uZXIuZmluZCgnLmVycm9yJyk7XG5cdCRiYXJjb2RlU2Nhbm5lckFkZEJ1dHRvbiA9ICRiYXJjb2RlU2Nhbm5lci5maW5kKCcuYWN0aW9uLmFkZCcpO1xuXHQkYmFyY29kZVNjYW5uZXJBZGRCdXR0b25UZXh0ID0gJGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uLmZpbmQoJ3NwYW4nKTtcblx0JGJhcmNvZGVTY2FubmVyU3RhcnRCdXR0b24gPSAkYmFyY29kZVNjYW5uZXIuZmluZCgnLmFjdGlvbi5zdGFydCcpO1xuXHQkYmFyY29kZVNjYW5uZXJTdGFydEJ1dHRvblRleHQgPSAkYmFyY29kZVNjYW5uZXJTdGFydEJ1dHRvbi5maW5kKCdzcGFuJyk7XG5cdCRiYXJjb2RlU2Nhbm5lck1vZGFsID0gJGJhcmNvZGVTY2FubmVyLmZpbmQoJy5tb2RhbCcpO1xuXHQkcHJvZHVjdFNlYXJjaCA9ICRwcm9kdWN0RmluZGVyLmZpbmQoJy5zZWN0aW9uLnNlYXJjaCcpO1xuXHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyID0gJHByb2R1Y3RTZWFyY2guZmluZCgnLmlucHV0Jyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXQgPSAkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmZpbmQoJ2lucHV0Jyk7XG5cdCRwcm9kdWN0U2VhcmNoRXJyb3JDb250YWluZXIgPSAkcHJvZHVjdFNlYXJjaC5maW5kKCcuZXJyb3InKTtcblx0JHByb2R1Y3RTZWFyY2hTZWFyY2hCdXR0b24gPSAkcHJvZHVjdFNlYXJjaC5maW5kKCcuYWN0aW9uLnNlYXJjaCcpO1xuXHQkcHJvZHVjdFNlYXJjaFNlYXJjaEJ1dHRvblRleHQgPSAkcHJvZHVjdFNlYXJjaFNlYXJjaEJ1dHRvbi5maW5kKCdzcGFuJyk7XG5cdCRwcm9kdWN0U2VhcmNoUmVzdWx0c0NvbnRhaW5lciA9ICRwcm9kdWN0U2VhcmNoLmZpbmQoJy5yZXN1bHRzLWNvbnRhaW5lcicpO1xuXHQkcHJvZHVjdFNlYXJjaFJlc3VsdHMgPSAkcHJvZHVjdFNlYXJjaFJlc3VsdHNDb250YWluZXIuZmluZCgnLnJlc3VsdHMnKTtcblx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzRm9vdGVyID0gJHByb2R1Y3RTZWFyY2hSZXN1bHRzQ29udGFpbmVyLmZpbmQoJ2Zvb3RlcicpO1xuXHQkcHJvZHVjdFNlYXJjaFJlc3VsdHNMb2FkTW9yZSA9ICRwcm9kdWN0U2VhcmNoUmVzdWx0c0NvbnRhaW5lci5maW5kKCcubG9hZC1tb3JlJyk7XG5cblx0aWYgKCgnQmFyY29kZURldGVjdG9yJyBpbiB3aW5kb3cpKSB7XG5cdFx0JGJhcmNvZGVTY2FubmVyLmFkZENsYXNzKCdiYXJjb2RlLWRldGVjdG9yJyk7XG5cdH1cblxuXHRkYXRhWydQcm9kdWN0U2VhcmNoUGFnZVNpemUnXSA9IDU7XG5cbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvbnMnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvciddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3RvcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0dGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckF0dHJpYnV0ZUd1aWRlJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLWF0dHJpYnV0ZS1ndWlkZScpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3ItZHJvcGRvd24nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duT3B0aW9uJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLWRyb3Bkb3duLW9wdGlvbicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb25TZWxlY3RlZCddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1kcm9wZG93bi1vcHRpb24tc2VsZWN0ZWQnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaCddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1zd2F0Y2gnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaE9wdGlvbiddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1zd2F0Y2gtb3B0aW9uJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb25VbnNlbGVjdGFibGUnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3Itc3dhdGNoLW9wdGlvbi11bnNlbGVjdGFibGUnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cblx0Ly8gJChkb2N1bWVudCkub2ZmKCdrZXl1cC5CYXJjb2RlU2Nhbm5lcklucHV0Jykub24oJ2tleXVwLkJhcmNvZGVTY2FubmVySW5wdXQnLCAnLmlucHV0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0Ly8gXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG5cdC8vIFx0JGJhcmNvZGVTY2FubmVyRXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG5cdC8vIFx0aWYgKGJhcmNvZGVTY2FuSW5wdXRBZGRQcm9kdWN0VGltZXIpIHtcblx0Ly8gXHRcdGNsZWFyVGltZW91dChiYXJjb2RlU2NhbklucHV0QWRkUHJvZHVjdFRpbWVyKTtcblx0Ly8gXHR9XG5cblx0Ly8gXHRiYXJjb2RlU2NhbklucHV0QWRkUHJvZHVjdFRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0Ly8gXHRcdGFkZFByb2R1Y3RXaXRoVXBjKCR0aGlzLnZhbCgpKTtcblx0Ly8gXHR9LCAyNTApO1xuXHQvLyB9KTtcblxuXHQkcHJvZHVjdEZpbmRlci5vZmYoJ2NsaWNrLkFkZCcpLm9uKCdjbGljay5BZGQnLCAnLmFjdGlvbi5hZGQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0YWRkUHJvZHVjdFdpdGhVcGMoJGJhcmNvZGVTY2FubmVySW5wdXQudmFsKCkpO1xuXHR9KTtcblxuXHQkcHJvZHVjdEZpbmRlci5vZmYoJ2NsaWNrLk9wdGlvbnNUb2dnbGUnKS5vbignY2xpY2suT3B0aW9uc1RvZ2dsZScsICcuYWN0aW9uLm9wdGlvbnMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdCQodGhpcykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHR9KTtcblxuXHQkcHJvZHVjdEZpbmRlci5vZmYoJ2NsaWNrLk1vZGVTZXQnKS5vbignY2xpY2suTW9kZVNldCcsICcub3B0aW9ucyBbc2V0LW1vZGVdJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5odG1sKCcnKTtcblx0XHQkcHJvZHVjdFNlYXJjaEVycm9yQ29udGFpbmVyLmh0bWwoJycpO1xuXHRcdCQoJy5wcm9kdWN0LWZpbmRlcicpLmF0dHIoJ21vZGUnLCAkKHRoaXMpLmF0dHIoJ3NldC1tb2RlJykpO1xuXHRcdCQoJy5hY3Rpb24ub3B0aW9ucycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5PcHRpb25zQ2xvc2UnKS5vbignY2xpY2suT3B0aW9uc0Nsb3NlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRhcmdldCA9ICQoZXZlbnQudGFyZ2V0KTtcblx0XHRpZiAoISR0YXJnZXQuaGFzQ2xhc3MoJ29wdGlvbnMnKSAmJiAkdGFyZ2V0LmNsb3Nlc3QoJy5vcHRpb25zJykubGVuZ3RoID09IDApIHtcblx0XHRcdCQoJy5hY3Rpb24ub3B0aW9ucycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHR9XG5cdH0pO1xuXG5cdCRiYXJjb2RlU2Nhbm5lci5vZmYoJ2NsaWNrLktleWJvYXJkVG9nZ2xlJykub24oJ2NsaWNrLktleWJvYXJkVG9nZ2xlJywgJy5vcHRpb25zIC5rZXlib2FyZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCQodGhpcykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHQkKHRoaXMpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdCRiYXJjb2RlU2Nhbm5lcklucHV0LmF0dHIoJ2lucHV0bW9kZScsICdub25lJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQodGhpcykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXQuYXR0cignaW5wdXRtb2RlJywgJGJhcmNvZGVTY2FubmVySW5wdXQuYXR0cigndHlwZScpKTtcblx0XHR9XG5cdFx0JCgnLmFjdGlvbi5vcHRpb25zJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHR9KTtcblxuXHQkYmFyY29kZVNjYW5uZXIub2ZmKCdjbGljay5CYXJjb2RlU2Nhbm5lclN0YXJ0Jykub24oJ2NsaWNrLkJhcmNvZGVTY2FubmVyU3RhcnQnLCAnLmFjdGlvbi5zdGFydCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCEoJ0JhcmNvZGVEZXRlY3RvcicgaW4gd2luZG93KSkge1xuXHRcdFx0YWxlcnQoJ0JhcmNvZGUgRGV0ZWN0b3IgaXMgbm90IHN1cHBvcnRlZCBieSB0aGlzIGJyb3dzZXIuJyk7XG4gIFx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnNlY3Rpb24uc2NhbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcblxuXHRcdFx0aWYgKCFiYXJjb2RlRGV0ZWN0b3IpIHtcblx0XHRcdFx0YmFyY29kZURldGVjdG9yID0gbmV3IEJhcmNvZGVEZXRlY3RvcigpO1xuXHRcdFx0fVxuXG5cdFx0XHR2aWRlbyA9ICRiYXJjb2RlU2Nhbm5lck1vZGFsLmZpbmQoJ3ZpZGVvJylbMF07XG5cdFx0XHR2aWRlby5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJycpO1xuXHRcdFx0dmlkZW8uc2V0QXR0cmlidXRlKCdhdXRvcGxheScsICcnKTtcblx0XHRcdHZpZGVvLnNldEF0dHJpYnV0ZSgnbXV0ZWQnLCAnJyk7XG5cdFx0XHR2aWRlby5zdHlsZS53aWR0aCA9ICcxMDAlJztcblx0XHRcdHZpZGVvLnN0eWxlLmhlaWdodCA9ICcxMDAlJztcblxuXHRcdFx0dmFyIGNvbnN0cmFpbnRzID0ge1xuXHRcdFx0XHRhdWRpbzogZmFsc2UsXG5cdFx0XHRcdHZpZGVvOiB7XG5cdFx0XHRcdFx0ZmFjaW5nTW9kZTogJ2Vudmlyb25tZW50J1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHRuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiBzdWNjZXNzKG1lZGlhU3RyZWFtKSB7XG5cdFx0XHRcdHN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuXHRcdFx0XHR2aWRlby5zcmNPYmplY3QgPSBzdHJlYW07XG5cdFx0XHR9KTtcblxuXHRcdFx0dmlkZW8ub25sb2FkZWRtZXRhZGF0YSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdGJhcmNvZGVEZXRlY3RvckludGVydmFsID0gc2V0SW50ZXJ2YWwoZGV0ZWN0QmFyY29kZSwgNTAwKTtcblx0XHRcdH07XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkJhcmNvZGVTY2FubmVyU3RvcCcpLm9uKCdjbGljay5CYXJjb2RlU2Nhbm5lclN0b3AnLCAnLm1vZGFsIC5jbG9zZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0Y2xvc2VCYXJjb2RlU2Nhbm5lcigpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ3Bhc3RlLlVQQycpLm9uKCdwYXN0ZS5VUEMnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICghJGJhcmNvZGVTY2FubmVySW5wdXQuaXMoXCI6Zm9jdXNcIikgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJy5wcm9kdWN0LWZpbmRlcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdGdldENsaXBib2FyZFZhbHVlKGV2ZW50LCB0aGlzLCBmdW5jdGlvbih1cGMpIHtcblx0XHRcdFx0JGJhcmNvZGVTY2FubmVyRXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG5cdFx0XHRcdGFkZFByb2R1Y3RXaXRoVXBjKHVwYyk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH0pO1xuXG5cdCRwcm9kdWN0U2VhcmNoSW5wdXQub2ZmKCdrZXl1cC5Qcm9kdWN0U2VhcmNoQ2hhbmdlJykub24oJ2tleXVwLlByb2R1Y3RTZWFyY2hDaGFuZ2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHVwZGF0ZVByb2R1Y3RTZWFyY2hBY3Rpb24oKTtcblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2gub2ZmKCdjbGljay5Qcm9kdWN0U2VhcmNoU3RhcnQnKS5vbignY2xpY2suUHJvZHVjdFNlYXJjaFN0YXJ0JywgJy5hY3Rpb24uc2VhcmNoJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciBxdWVyeSA9ICRwcm9kdWN0U2VhcmNoSW5wdXQudmFsKCk7XG5cdFx0aWYgKHF1ZXJ5KSB7XG5cdFx0XHRpZiAoJHByb2R1Y3RTZWFyY2hJbnB1dENvbnRhaW5lci5hdHRyKCdhY3Rpb24nKSA9PSAnc2VhcmNoJykge1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHMuaHRtbCgnJyk7XG5cdFx0XHRcdCRwcm9kdWN0U2VhcmNoLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0ZGF0YVsnUHJvZHVjdFNlYXJjaFBhZ2UnXSA9IDE7XG5cdFx0XHRcdHNlYXJjaFByb2R1Y3RzV2l0aFF1ZXJ5KHF1ZXJ5KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlc2V0UHJvZHVjdFNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2gub2ZmKCdjbGljay5Qcm9kdWN0U2VhcmNoTG9hZE1vcmUnKS5vbignY2xpY2suUHJvZHVjdFNlYXJjaExvYWRNb3JlJywgJy5sb2FkLW1vcmUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBxdWVyeSA9ICRwcm9kdWN0U2VhcmNoSW5wdXQudmFsKCk7XG5cdFx0aWYgKHF1ZXJ5KSB7XG5cdFx0XHRkYXRhWydQcm9kdWN0U2VhcmNoUGFnZSddICs9IDE7XG5cdFx0XHRzZWFyY2hQcm9kdWN0c1dpdGhRdWVyeShxdWVyeSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkcHJvZHVjdFNlYXJjaC5vZmYoJ2NsaWNrLlByb2R1Y3RTZWFyY2hQcm9kdWN0U2VsZWN0Jykub24oJ2NsaWNrLlByb2R1Y3RTZWFyY2hQcm9kdWN0U2VsZWN0JywgJy5ncmlkLXRpbGUgLnByb2R1Y3QtdGlsZSBhJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGdyaWRUaWxlID0gJHRoaXMuY2xvc2VzdCgnLmdyaWQtdGlsZScpO1xuXHRcdHZhciAkcHJvZHVjdFRpbGUgPSAkdGhpcy5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyk7XG5cdFx0aWYgKCRncmlkVGlsZS5maW5kKCcucHJvZHVjdC12YXJpYXRpb25zJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JGdyaWRUaWxlLmZpbmQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKS5yZW1vdmUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Z2V0U3R5bGVzRm9yUHJvZHVjdCgkcHJvZHVjdFRpbGUuZGF0YSgnaXRlbWlkJykpO1xuXHRcdH1cblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2gub2ZmKCdjaGFuZ2UuUHJvZHVjdFNlYXJjaEF0dHJpYnV0ZVNlbGVjdCcpLm9uKCdjaGFuZ2UuUHJvZHVjdFNlYXJjaEF0dHJpYnV0ZVNlbGVjdCcsICcuZ3JpZC10aWxlIC5wcm9kdWN0LXZhcmlhdGlvbnMgc2VsZWN0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHByb2R1Y3RUaWxlID0gJCh0aGlzKS5jbG9zZXN0KCcuZ3JpZC10aWxlJykuZmluZCgnLnByb2R1Y3QtdGlsZScpO1xuXHRcdGdldFN0eWxlc0ZvclByb2R1Y3QoJHByb2R1Y3RUaWxlLmRhdGEoJ2l0ZW1pZCcpKTtcblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2gub2ZmKCdjbGljay5Qcm9kdWN0U2VhcmNoUHJvZHVjdEFkZCcpLm9uKCdjbGljay5Qcm9kdWN0U2VhcmNoUHJvZHVjdEFkZCcsICcuZ3JpZC10aWxlIC5wcm9kdWN0LXZhcmlhdGlvbnMgLmJ0bi5hZGQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0aWYgKCR0aGlzLmF0dHIoJ3BpZCcpKSB7XG5cdFx0XHRhZGRQcm9kdWN0V2l0aFByb2R1Y3RJZCgkdGhpcy5hdHRyKCdwaWQnKSwgJHRoaXMpO1xuXHRcdH1cblx0fSk7XG5cblx0JHByb2R1Y3RTZWFyY2gub2ZmKCdjbGljay5Qcm9kdWN0U2VhcmNoQ2xvc2UnKS5vbignY2xpY2suUHJvZHVjdFNlYXJjaENsb3NlJywgJy5yZXN1bHRzLWNvbnRhaW5lciAuY2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygncHJvZHVjdC1zZWFyY2gnKTtcblx0fSk7XG5cblx0aWYgKCFvcHRpb25zIHx8IG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gIT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHRiYXJjb2RlU2NhbklucHV0Rm9jdXNJbnRlcnZhbCA9IHNldEludGVydmFsKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCEkYmFyY29kZVNjYW5uZXJJbnB1dC5pcygnOnZpc2libGU6Zm9jdXMnKSAmJiAkYmFyY29kZVNjYW5uZXIuZmluZCgnOmZvY3VzJykubGVuZ3RoID09IDApIHtcblx0XHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXQuZm9jdXMoKTtcblx0XHRcdH1cblx0XHR9LCA1MDApO1xuXHRcblx0XHRwcm9kdWN0U2VhcmNoSW5wdXRGb2N1c0ludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoISRwcm9kdWN0U2VhcmNoSW5wdXQuaXMoJzp2aXNpYmxlOmZvY3VzJykgJiYgISRwcm9kdWN0U2VhcmNoLmhhc0NsYXNzKCdhY3RpdmUnKSAmJiAkcHJvZHVjdFNlYXJjaC5maW5kKCc6Zm9jdXMnKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaElucHV0LmZvY3VzKCk7XG5cdFx0XHR9XG5cdFx0fSwgNTAwKTtcblxuXHRcdCQoZG9jdW1lbnQpLm9mZignY2xpY2suQ2hlY2tvdXQnKS5vbignY2xpY2suQ2hlY2tvdXQnLCAnLmNoZWNrb3V0IC5idG4uYnRuLWNoZWNrb3V0JywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHQkKHRoaXMpLmxvYWRpbmcoe1xuXHRcdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0cXVhbnRpdHlTdGVwcGVyLmluaXQobnVsbCwgcmVuZGVyQ2FydCk7XG5cdFx0YWRkVG9DYXJ0KCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlUHJvZHVjdFNlYXJjaEFjdGlvbigpIHtcblx0dmFyIHByb2R1Y3RTZWFyY2hJbnB1dFZhbHVlID0gJHByb2R1Y3RTZWFyY2hJbnB1dC52YWwoKTtcblx0aWYgKHByb2R1Y3RTZWFyY2hJbnB1dFZhbHVlKSB7XG5cdFx0cHJvZHVjdFNlYXJjaElucHV0VmFsdWUgPSBwcm9kdWN0U2VhcmNoSW5wdXRWYWx1ZS50b0xvd2VyQ2FzZSgpO1xuXHR9XG5cdHZhciBwcm9kdWN0U2VhcmNoUXVlcnlWYWx1ZSA9ICRwcm9kdWN0U2VhcmNoSW5wdXRDb250YWluZXIuYXR0cigncXVlcnknKTtcblx0aWYgKHByb2R1Y3RTZWFyY2hRdWVyeVZhbHVlKSB7XG5cdFx0cHJvZHVjdFNlYXJjaFF1ZXJ5VmFsdWUgPSBwcm9kdWN0U2VhcmNoUXVlcnlWYWx1ZS50b0xvd2VyQ2FzZSgpO1xuXHR9XG5cblx0aWYgKHByb2R1Y3RTZWFyY2hJbnB1dFZhbHVlICYmIHByb2R1Y3RTZWFyY2hRdWVyeVZhbHVlICYmIHByb2R1Y3RTZWFyY2hJbnB1dFZhbHVlID09IHByb2R1Y3RTZWFyY2hRdWVyeVZhbHVlKSB7XG5cdFx0JHByb2R1Y3RTZWFyY2hJbnB1dENvbnRhaW5lci5hdHRyKCdhY3Rpb24nLCAncmVzZXQnKTtcblx0fSBlbHNlIHtcblx0XHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ2FjdGlvbicsICdzZWFyY2gnKTtcblx0fVxufVxuXG5mdW5jdGlvbiBzZWFyY2hQcm9kdWN0c1dpdGhRdWVyeShxdWVyeSkge1xuXHQkcHJvZHVjdFNlYXJjaEVycm9yQ29udGFpbmVyLmh0bWwoJycpO1xuXHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ3F1ZXJ5JywgcXVlcnkpO1xuXHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2UsXG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZVxuXHR9KTtcblx0JHByb2R1Y3RTZWFyY2hTZWFyY2hCdXR0b24ubG9hZGluZyh7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fSk7XG5cdGlmICgkcHJvZHVjdFNlYXJjaFJlc3VsdHNMb2FkTW9yZS5pcygnOnZpc2libGUnKSkge1xuXHRcdCRwcm9kdWN0U2VhcmNoUmVzdWx0c0xvYWRNb3JlLmxvYWRpbmcoe1xuXHRcdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdH0pO1xuXHR9XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblxuXHQkLmFqYXgoe1xuXHRcdHR5cGU6ICdHRVQnLFxuXHRcdHVybDogVXJscy5TZWFyY2guU2hvdyxcblx0XHRkYXRhOiB7XG5cdFx0XHRmb3JtYXQ6ICdhamF4Jyxcblx0XHRcdHE6IHF1ZXJ5LFxuXHRcdFx0Ly8gcHJlZm4xOiAnYXZhaWxhYmxlU3RvcmVzJyxcblx0XHRcdC8vIHByZWZ2MTogb3B0aW9ucy5BZ2VudFN0b3JlSUQsXG5cdFx0XHRzdGFydDogcGFyc2VJbnQoKGRhdGFbJ1Byb2R1Y3RTZWFyY2hQYWdlJ10gLSAxKSAqIGRhdGFbJ1Byb2R1Y3RTZWFyY2hQYWdlU2l6ZSddLCAxMCksXG5cdFx0XHRzejogZGF0YVsnUHJvZHVjdFNlYXJjaFBhZ2VTaXplJ11cblx0XHR9LFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgJGh0bWwgPSAkKHJlc3BvbnNlKTtcblx0XHRcdHZhciAkcHJvZHVjdEdyaWQgPSAkaHRtbC5maW5kKCcjc2VhcmNoLXJlc3VsdC1pdGVtcycpO1xuXHRcdFx0dmFyICRwYWdpbmF0aW9uID0gJGh0bWwuZmluZCgnLnNlYXJjaC1yZXN1bHQtb3B0aW9ucyAucGFnaW5hdGlvbltjb3VudF0nKS5maXJzdCgpO1xuXHRcdFx0dmFyIHByb2R1Y3RUaWxlQ291bnQgPSAkcHJvZHVjdEdyaWQuZmluZCgnLmdyaWQtdGlsZScpLmxlbmd0aCArICQoJy5zZWN0aW9uLnNlYXJjaCAucmVzdWx0cy1jb250YWluZXInKS5maW5kKCcuZ3JpZC10aWxlJykubGVuZ3RoO1xuXHRcdFx0dmFyIHByb2R1Y3RUb3RhbENvdW50ID0gMDtcblx0XHRcdGlmICgkcGFnaW5hdGlvbi5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHByb2R1Y3RUb3RhbENvdW50ID0gcGFyc2VJbnQoJGh0bWwuZmluZCgnLnNlYXJjaC1yZXN1bHQtb3B0aW9ucyAucGFnaW5hdGlvbltjb3VudF0nKS5maXJzdCgpLmF0dHIoJ2NvdW50JykucmVwbGFjZSgvXFxEL2csICcnKSwgMTApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAocHJvZHVjdFRpbGVDb3VudCA+IDApIHtcblx0XHRcdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzLmFwcGVuZCgkcHJvZHVjdEdyaWQuaHRtbCgpKTtcblx0XHRcdFx0aWYgKHByb2R1Y3RUaWxlQ291bnQgPCBwcm9kdWN0VG90YWxDb3VudCkge1xuXHRcdFx0XHRcdCRwcm9kdWN0U2VhcmNoUmVzdWx0c0Zvb3Rlci5zaG93KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzRm9vdGVyLmhpZGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzLmFwcGVuZCgkKCc8bGkgY2xhc3M9XCJuby1yZXN1bHRzXCI+Tm8gcHJvZHVjdHMgZm91bmQgZm9yIHlvdXIgc2VhcmNoLjwvbGk+JykpO1xuXHRcdFx0XHQkcHJvZHVjdFNlYXJjaFJlc3VsdHNGb290ZXIuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdFx0JHByb2R1Y3RTZWFyY2guYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH0sXG5cdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0JHByb2R1Y3RTZWFyY2hJbnB1dENvbnRhaW5lci5hdHRyKCd1cGMnLCAnJyk7XG5cdFx0XHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdCRwcm9kdWN0U2VhcmNoU2VhcmNoQnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdGlmICgkcHJvZHVjdFNlYXJjaFJlc3VsdHNMb2FkTW9yZS5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0JHByb2R1Y3RTZWFyY2hSZXN1bHRzTG9hZE1vcmUubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdFx0JHByb2R1Y3RTZWFyY2hJbnB1dC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHRcdFx0dXBkYXRlUHJvZHVjdFNlYXJjaEFjdGlvbigpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldFN0eWxlc0ZvclByb2R1Y3QocHJvZHVjdElkKSB7XG5cdHZhciAkcHJvZHVjdFRpbGUgPSAkcHJvZHVjdFNlYXJjaFJlc3VsdHMuZmluZCgnLnByb2R1Y3QtdGlsZVtkYXRhLWl0ZW1pZD1cIicgKyBwcm9kdWN0SWQgKyAnXCJdJyk7XG5cblx0aWYgKCRwcm9kdWN0VGlsZS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyICRncmlkVGlsZSA9ICRwcm9kdWN0VGlsZS5jbG9zZXN0KCcuZ3JpZC10aWxlJyk7XG5cblx0XHRpZiAoJGdyaWRUaWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBpc0ZpcnN0TG9hZCA9IGZhbHNlO1xuXHRcdFx0dmFyICRwcm9kdWN0VmFyaWF0aW9ucztcblx0XHRcdGlmICgkZ3JpZFRpbGUuZmluZCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JHByb2R1Y3RWYXJpYXRpb25zID0gJGdyaWRUaWxlLmZpbmQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlzRmlyc3RMb2FkID0gdHJ1ZTtcblx0XHRcdFx0JHByb2R1Y3RWYXJpYXRpb25zID0gJGdyaWRUaWxlLmFwcGVuZCgnPGRpdiBjbGFzcz1cInByb2R1Y3QtdmFyaWF0aW9uc1wiPjwvZGl2PicpLmZpbmQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKTtcblx0XHRcdH1cblx0XHRcdCRwcm9kdWN0VmFyaWF0aW9ucy5sb2FkaW5nKHtcblx0XHRcdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRcdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdFx0XHR9KTtcblx0XHRcdGlmICgkZ3JpZFRpbGUuZmluZCgnLmJ0bi5hZGQnKS5pcygnOnZpc2libGUnKSkge1xuXHRcdFx0XHQkZ3JpZFRpbGUuZmluZCgnLmJ0bi5hZGQnKS5sb2FkaW5nKHtcblx0XHRcdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdGRhdGFbJ2F0dHJpYnV0ZUd1aWRlcyddID0ge307XG5cblx0XHRcdHZhciBwYXlsb2FkID0ge1xuXHRcdFx0XHRwaWQ6ICRwcm9kdWN0VGlsZS5kYXRhKCdpdGVtaWQnKVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIWlzRmlyc3RMb2FkKSB7XG5cdFx0XHRcdHZhciAkcHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZXNTZWxlY3RlZCA9ICRwcm9kdWN0VmFyaWF0aW9ucy5maW5kKCdbYXR0cmlidXRlXSBvcHRpb24uc2VsZWN0YWJsZTpjaGVja2VkJyk7XG5cdFx0XHRcdCRwcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlc1NlbGVjdGVkLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRcdFx0XHR2YXIgcHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZUlkID0gJHRoaXMuY2xvc2VzdCgnW2F0dHJpYnV0ZV0nKS5hdHRyKCdhdHRyaWJ1dGUnKTtcblx0XHRcdFx0XHR2YXIgcHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZVZhbHVlID0gJHRoaXMudmFsKCk7XG5cdFx0XHRcdFx0cGF5bG9hZFsnZHd2YXJfJyArIHBheWxvYWQucGlkICsgJ18nICsgcHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZUlkXSA9IHByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGVWYWx1ZTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdG1ldGhvZDogJ3Bvc3QnLFxuXHRcdFx0XHR1cmw6IFVybHMuZ2V0VmFyaWF0aW9uQXR0cmlidXRlcyxcblx0XHRcdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcnMnXSA9ICcnO1xuXHRcdFx0XHRcdGZvciAodmFyIHZhcmlhdGlvbiBpbiByZXNwb25zZS52YXJpYXRpb25zKSB7XG5cdFx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YSA9IHJlc3BvbnNlLnZhcmlhdGlvbnNbdmFyaWF0aW9uXTtcblx0XHRcdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZCA9IG51bGw7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0T3B0aW9ucyddID0gJyc7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgdmFyaWF0aW9uVmFsdWUgaW4gdmFyaWF0aW9uRGF0YS52YWx1ZXMpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZSA9IHZhcmlhdGlvbkRhdGEudmFsdWVzW3ZhcmlhdGlvblZhbHVlXTtcblx0XHRcdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0dmFyIHZhcmlhdGlvbkRhdGFWYWx1ZVBheWxvYWQgPSB7XG5cdFx0XHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhVmFsdWUuYXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0XHRcdHZhbHVlSWQ6IHZhcmlhdGlvbkRhdGFWYWx1ZS52YWx1ZUlkLFxuXHRcdFx0XHRcdFx0XHRcdHZhbHVlOiB2YXJpYXRpb25EYXRhVmFsdWUudmFsdWUsXG5cdFx0XHRcdFx0XHRcdFx0dGl0bGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS50aXRsZSxcblx0XHRcdFx0XHRcdFx0XHR0ZXh0OiB2YXJpYXRpb25EYXRhVmFsdWUudGV4dCxcblx0XHRcdFx0XHRcdFx0XHRzdG9jazogdmFyaWF0aW9uRGF0YVZhbHVlLnN0b2NrLFxuXHRcdFx0XHRcdFx0XHRcdHNoaXBwaW5nOiB2YXJpYXRpb25EYXRhVmFsdWUuc2hpcHBpbmcsXG5cdFx0XHRcdFx0XHRcdFx0aXNTYW1lRGF5U2hpcHBpbmdXaW5kb3c6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pc1NhbWVEYXlTaGlwcGluZ1dpbmRvdyxcblx0XHRcdFx0XHRcdFx0XHRxdWFudGl0eVNvdXJjZVR5cGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5xdWFudGl0eVNvdXJjZVR5cGUsXG5cdFx0XHRcdFx0XHRcdFx0aHJlZjogdmFyaWF0aW9uRGF0YVZhbHVlLmhyZWYsXG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0YWJsZTogdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGFibGUgPyAnc2VsZWN0YWJsZScgOiAndW5zZWxlY3RhYmxlJyxcblx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZDogIWlzRmlyc3RMb2FkICYmIHZhcmlhdGlvbkRhdGFWYWx1ZS5zZWxlY3RlZCA/ICdzZWxlY3RlZCcgOiAnJyxcblx0XHRcdFx0XHRcdFx0XHRzd2F0Y2hJbWFnZVVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5zd2F0Y2gudXJsLFxuXHRcdFx0XHRcdFx0XHRcdGxhcmdlU3dhdGNoSW1hZ2VVcmw6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2VTd2F0Y2gudXJsLFxuXHRcdFx0XHRcdFx0XHRcdGhyZWZBdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5zZWxlY3RhYmxlID8gJ2hyZWYnIDogJ3hocmVmJ1xuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGEudHlwZSA9PSAnc3dhdGNoJykge1xuXHRcdFx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhVmFsdWUuc2VsZWN0YWJsZSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGUgPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoT3B0aW9uJ107XG5cdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVQYXlsb2FkLmltYWdlTGFyZ2UgPSBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZS51cmwsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRpdGxlOiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmxhcmdlLnRpdGxlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRhbHQ6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2UuYWx0LFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRoaXJlczogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5oaXJlcy51cmxcblx0XHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb25VbnNlbGVjdGFibGUnXTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGUgPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb24nXTtcblx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZCA9IHZhcmlhdGlvbkRhdGFWYWx1ZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldE9wdGlvbnMnXSArPSB2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSh2YXJpYXRpb25EYXRhVmFsdWVQYXlsb2FkKTtcblx0XHRcdFx0XHRcdH1cdFxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YS50eXBlID09ICdzd2F0Y2gnKSB7XG5cdFx0XHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0J10gPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoJ10oe1xuXHRcdFx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0XHRcdG9wdGlvbnM6IGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0T3B0aW9ucyddXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dmFyIHBsYWNlaG9sZGVyID0gdmFyaWF0aW9uRGF0YS5sYWJlbC5wbGFjZWhvbGRlcjtcblx0XHRcdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0cGxhY2Vob2xkZXIgPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb25TZWxlY3RlZCddKHtcblx0XHRcdFx0XHRcdFx0XHRcdHRleHQ6IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnRleHQsXG5cdFx0XHRcdFx0XHRcdFx0XHRzdG9jazogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQuc3RvY2ssXG5cdFx0XHRcdFx0XHRcdFx0XHRzaGlwcGluZzogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQuc2hpcHBpbmcsXG5cdFx0XHRcdFx0XHRcdFx0XHRpc1NhbWVEYXlTaGlwcGluZ1dpbmRvdzogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQuaXNTYW1lRGF5U2hpcHBpbmdXaW5kb3csXG5cdFx0XHRcdFx0XHRcdFx0XHRxdWFudGl0eVNvdXJjZVR5cGU6IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnF1YW50aXR5U291cmNlVHlwZVxuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldCddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duJ10oe1xuXHRcdFx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0XHRcdHRleHQ6IHBsYWNlaG9sZGVyLFxuXHRcdFx0XHRcdFx0XHRcdG9wdGlvbnM6IGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0T3B0aW9ucyddXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRodG1sWydhdHRyaWJ1dGVHdWlkZSddID0gJyc7XG5cdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YS5hdHRyaWJ1dGVHdWlkZSkge1xuXHRcdFx0XHRcdFx0XHRkYXRhWydhdHRyaWJ1dGVHdWlkZXMnXVt2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGVdID0gdmFyaWF0aW9uRGF0YS5hdHRyaWJ1dGVHdWlkZTtcblx0XHRcdFx0XHRcdFx0aHRtbFsnYXR0cmlidXRlR3VpZGUnXSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JBdHRyaWJ1dGVHdWlkZSddKF8uZXh0ZW5kKHZhcmlhdGlvbkRhdGEuYXR0cmlidXRlR3VpZGUsIHsgQXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUgfSkpO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvciddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvciddKHtcblx0XHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHRcdGxhYmVsOiB7XG5cdFx0XHRcdFx0XHRcdFx0dGV4dDogdmFyaWF0aW9uRGF0YS5sYWJlbC50ZXh0LFxuXHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2U6IHZhcmlhdGlvbkRhdGEubGFiZWwubWVzc2FnZVxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRzZWxlY3RvcjogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXQnXSxcblx0XHRcdFx0XHRcdFx0Z3VpZGU6IGh0bWxbJ2F0dHJpYnV0ZUd1aWRlJ11cblx0XHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcnMnXSArPSBodG1sWyd2YXJpYXRpb25TZWxlY3RvciddO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcblx0XHRcdFx0XHRodG1sWydzZWxlY3RvcnMnXSA9IHRlbXBsYXRlc1sndmFyaWF0aW9ucyddKHtcblx0XHRcdFx0XHRcdHNlbGVjdG9yczogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JzJ11cblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdCRwcm9kdWN0VmFyaWF0aW9ucy5odG1sKGh0bWxbJ3NlbGVjdG9ycyddKS5hZGRDbGFzcygnbG9hZGVkJyk7XG5cdFx0XHRcdFx0aWYgKHJlc3BvbnNlLnBpZCkge1xuXHRcdFx0XHRcdFx0JGdyaWRUaWxlLmZpbmQoJy5idG4uYWRkJykuYXR0cigncGlkJywgcmVzcG9uc2UucGlkKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JGdyaWRUaWxlLmZpbmQoJy5idG4uYWRkJykucmVtb3ZlQXR0cigncGlkJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cdFx0XHRcdFx0JHByb2R1Y3RWYXJpYXRpb25zLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHJlc2V0UHJvZHVjdFNlYXJjaCgpIHtcblx0JHByb2R1Y3RTZWFyY2gucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHQkcHJvZHVjdFNlYXJjaElucHV0Q29udGFpbmVyLmF0dHIoJ3F1ZXJ5JywgJycpO1xuXHQkcHJvZHVjdFNlYXJjaElucHV0LnZhbCgnJyk7XG5cdCRwcm9kdWN0U2VhcmNoSW5wdXQuZm9jdXMoKTtcblx0dXBkYXRlUHJvZHVjdFNlYXJjaEFjdGlvbigpO1xufVxuXG5mdW5jdGlvbiBhZGRQcm9kdWN0V2l0aFByb2R1Y3RJZChwcm9kdWN0SWQsICRncmlkVGlsZUFkZEJ1dHRvbikge1xuXHRpZiAoJGdyaWRUaWxlQWRkQnV0dG9uKSB7XG5cdFx0JGdyaWRUaWxlQWRkQnV0dG9uLmxvYWRpbmcoe1xuXHRcdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdH0pO1xuXHR9XG5cdCRwcm9kdWN0U2VhcmNoRXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG5cblx0YWRkUHJvZHVjdCh7XG5cdFx0cGF5bG9hZDoge1xuXHRcdFx0cGlkOiBwcm9kdWN0SWRcblx0XHR9LFxuXHRcdGNvbXBsZXRlOiBmdW5jdGlvbih4aHIpIHtcblx0XHRcdGlmICgkZ3JpZFRpbGVBZGRCdXR0b24gJiYgJGdyaWRUaWxlQWRkQnV0dG9uLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHQkZ3JpZFRpbGVBZGRCdXR0b24ubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdFx0cmVzZXRQcm9kdWN0U2VhcmNoKCk7XG5cdFx0XHRyZW5kZXJDYXJ0KCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZGV0ZWN0QmFyY29kZSgpIHtcblx0dmFyIGNhbnZhcyA9ICRiYXJjb2RlU2Nhbm5lck1vZGFsLmZpbmQoJ2NhbnZhcycpWzBdO1xuXHRjYW52YXMud2lkdGggPSB2aWRlby52aWRlb1dpZHRoO1xuXHRjYW52YXMuaGVpZ2h0ID0gdmlkZW8udmlkZW9IZWlnaHQ7XG5cblx0dmFyIGNhbnZhc0NvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblx0Y2FudmFzQ29udGV4dC5kcmF3SW1hZ2UodmlkZW8sIDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cblx0dmFyIGJhcmNvZGVEZXRlY3RvciA9IG5ldyBCYXJjb2RlRGV0ZWN0b3IoKTtcblx0YmFyY29kZURldGVjdG9yLmRldGVjdChjYW52YXNDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpKS50aGVuKGJhcmNvZGVzID0+IHtcblx0XHQkYmFyY29kZVNjYW5uZXJNb2RhbC5hZGRDbGFzcygnc2Nhbm5lZCcpO1xuXHRcdFxuXHRcdGJhcmNvZGVzLmZvckVhY2goZnVuY3Rpb24oYmFyY29kZSkge1xuXHRcdFx0dmFyIGJhcmNvZGVWYWx1ZTtcblx0XHRcdGlmICgncmF3VmFsdWUnIGluIGJhcmNvZGUpIHtcblx0XHRcdFx0YmFyY29kZVZhbHVlID0gYmFyY29kZS5yYXdWYWx1ZTtcblx0XHRcdH0gZWxzZSBpZiAoJ3Jhd0RhdGEnIGluIGJhcmNvZGUpIHtcblx0XHRcdFx0YmFyY29kZVZhbHVlID0gYmFyY29kZS5yYXdEYXRhO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRjbG9zZUJhcmNvZGVTY2FubmVyKCk7XG5cdFx0XHRhZGRQcm9kdWN0V2l0aFVwYyhiYXJjb2RlVmFsdWUpO1xuXHRcdH0pO1xuXHR9KS5jYXRjaChlcnJvciA9PiB7XG5cdFx0Ly8gYWxlcnQoZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gY2xvc2VCYXJjb2RlU2Nhbm5lcigpIHtcblx0JCgnLnNlY3Rpb24uc2NhbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0aWYgKGJhcmNvZGVEZXRlY3RvckludGVydmFsKSB7XG5cdFx0YmFyY29kZURldGVjdG9ySW50ZXJ2YWwgPSBjbGVhckludGVydmFsKGJhcmNvZGVEZXRlY3RvckludGVydmFsKTtcblx0fVxuXHRzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuXHRcdHRyYWNrLnN0b3AoKTtcblx0fSk7XG5cdHZpZGVvLnNyY09iamVjdCA9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGdldENsaXBib2FyZFZhbHVlKGV2ZW50LCBlbGVtZW50LCBjYWxsYmFjaykge1xuXHRpZiAobmF2aWdhdG9yLmNsaXBib2FyZCAmJiBuYXZpZ2F0b3IuY2xpcGJvYXJkLnJlYWRUZXh0KSB7XG5cdCAgXHQvLyBtb2Rlcm4gYXBwcm9hY2ggd2l0aCBDbGlwYm9hcmQgQVBJXG5cdCAgXHRuYXZpZ2F0b3IuY2xpcGJvYXJkLnJlYWRUZXh0KCkudGhlbihjYWxsYmFjayk7XG5cdH0gZWxzZSBpZiAoZXZlbnQub3JpZ2luYWxFdmVudCAmJiBldmVudC5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEpIHtcblx0ICBcdC8vIE9yaWdpbmFsRXZlbnQgaXMgYSBwcm9wZXJ0eSBmcm9tIGpRdWVyeSwgbm9ybWFsaXppbmcgdGhlIGV2ZW50IG9iamVjdFxuXHQgIFx0Y2FsbGJhY2soZXZlbnQub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhLmdldERhdGEoJ3RleHQnKSk7XG5cdH0gZWxzZSBpZiAoZXZlbnQuY2xpcGJvYXJkRGF0YSkge1xuXHQgIFx0Ly8gdXNlZCBpbiBzb21lIGJyb3dzZXJzIGZvciBjbGlwYm9hcmREYXRhXG5cdCAgXHRjYWxsYmFjayhldmVudC5jbGlwYm9hcmREYXRhLmdldERhdGEoJ3RleHQvcGxhaW4nKSk7XG5cdH0gZWxzZSBpZiAod2luZG93LmNsaXBib2FyZERhdGEpIHtcblx0ICBcdC8vIE9sZGVyIGNsaXBib2FyZERhdGEgdmVyc2lvbiBmb3IgSW50ZXJuZXQgRXhwbG9yZXIgb25seVxuXHQgIFx0Y2FsbGJhY2sod2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YSgnVGV4dCcpKTtcblx0fSBlbHNlIHtcblx0ICBcdC8vIExhc3QgcmVzb3J0IGZhbGxiYWNrLCB1c2luZyBhIHRpbWVyXG5cdCAgXHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0Y2FsbGJhY2soZWxlbWVudC52YWx1ZSlcblx0ICBcdH0sIDEwMCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gYWRkUHJvZHVjdFdpdGhVcGModXBjKSB7XG5cdCRiYXJjb2RlU2Nhbm5lcklucHV0Q29udGFpbmVyLmF0dHIoJ3VwYycsIHVwYyk7XG5cdCRiYXJjb2RlU2Nhbm5lcklucHV0Q29udGFpbmVyLmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2UsXG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZVxuXHR9KTtcblx0JGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uLmxvYWRpbmcoe1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdH0pO1xuXHQkYmFyY29kZVNjYW5uZXJJbnB1dC52YWwoJycpO1xuXHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5odG1sKCcnKTtcblx0JGJhcmNvZGVTY2FubmVySW5wdXQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblxuXHRhZGRQcm9kdWN0KHtcblx0XHRwYXlsb2FkOiB7XG5cdFx0XHR1cGM6IHVwY1xuXHRcdH0sXG5cdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdGlmIChyZXNwb25zZSAmJiAhcmVzcG9uc2UuSXNQcm9kdWN0SW5Qcm9kdWN0U2VydmljZSkge1xuXHRcdFx0XHQkYmFyY29kZVNjYW5uZXJFcnJvckNvbnRhaW5lci5hcHBlbmQoJzxwPlByb2R1Y3Qgbm90IGZvdW5kIGluIHNlcnZpY2UhPC9wPicpO1x0XG5cdFx0XHR9IGVsc2UgaWYgKHJlc3BvbnNlICYmICFyZXNwb25zZS5Jc1Byb2R1Y3RJbkNhdGFsb2cpIHtcblx0XHRcdFx0JGJhcmNvZGVTY2FubmVyRXJyb3JDb250YWluZXIuYXBwZW5kKCc8cD5Qcm9kdWN0IG5vdCBmb3VuZCBpbiBjYXRhbG9nITwvcD4nKTtcdFxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIuYXR0cigndXBjJywgJycpO1xuXHRcdFx0JGJhcmNvZGVTY2FubmVySW5wdXRDb250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0JGJhcmNvZGVTY2FubmVyQWRkQnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdCRiYXJjb2RlU2Nhbm5lcklucHV0LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHRyZW5kZXJDYXJ0KCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gYWRkUHJvZHVjdChwYXJhbWV0ZXJzKSB7XG5cdHZhciBwYXlsb2FkID0gJC5leHRlbmQocGFyYW1ldGVycy5wYXlsb2FkIHx8IHt9LCB7XG5cdFx0Zm9ybWF0OiAnYWpheCcsXG5cdFx0UXVhbnRpdHk6IDEsXG5cdFx0Y2FydEFjdGlvbjogJ2FkZCcsXG5cdFx0Y3NyZl90b2tlbjogb3B0aW9ucy5Ub2tlbixcblx0XHRjaGFubmVsOiAnRWNobycsXG5cdFx0Ym9waXNfc3RvcmU6ICcnLFxuXHRcdGJvcGlzX3F1YW50aXR5X2F2YWlsYWJsZTogJycsXG5cdFx0Ym9waXNfc2hpcHBpbmdfb3B0aW9uOiAnJ1xuXHR9KTtcblxuXHRpZiAocGF5bG9hZC5waWQgfHwgcGF5bG9hZC51cGMpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLmFkZFByb2R1Y3QsXG5cdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdFx0aWYgKHBhcmFtZXRlcnMuc3VjY2VzcyAmJiB0eXBlb2YgcGFyYW1ldGVycy5zdWNjZXNzID09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRwYXJhbWV0ZXJzLnN1Y2Nlc3MocmVzcG9uc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0XHRpZiAocGFyYW1ldGVycy5jb21wbGV0ZSAmJiB0eXBlb2YgcGFyYW1ldGVycy5jb21wbGV0ZSA9PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0cGFyYW1ldGVycy5jb21wbGV0ZSh4aHIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyQ2FydCgpIHtcblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdGxvY2F0aW9uLnJlbG9hZCgpO1xuXHR9IGVsc2Uge1xuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnR0VUJyxcblx0XHRcdHVybDogVXJscy5DYXJ0LkdldENhcnRCb2R5UHJvZHVjdExpbmVJdGVtcyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRcdCQoJyN3cmFwcGVyID4gLmNhcnQgPiBmb3JtJykuaHRtbChyZXNwb25zZSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0dXJsOiBVcmxzLmdldENhcnREYXRhLFxuXHRcdFx0ZGF0YToge1xuXHRcdFx0XHRpc0NhcnQ6IHRydWVcblx0XHRcdH0sXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0XHRpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuT3JkZXJUb3RhbCAmJiByZXNwb25zZS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlKSB7XG5cdFx0XHRcdFx0JCgnLm9yZGVyLXN1YnRvdGFsIC5vcmRlci12YWx1ZScpLnRleHQocmVzcG9uc2UuT3JkZXJUb3RhbC5hZGp1c3RlZE1lcmNoYW5kaXplVG90YWxQcmljZURpc3BsYXkpO1xuXHRcdFx0XHRcdCQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JCgnLm9yZGVyLXRvdGFscy10YWJsZScpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlQ1NSRlRva2VuKCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNTUkZUb2tlbigpIHtcbiAgICAkLmFqYXgoe1xuICAgIFx0bWV0aG9kOiAnZ2V0JyxcbiAgICBcdHVybDogVXJscy5DU1JGVG9rZW4uR2V0LFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG4gICAgXHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgIFx0XHRvcHRpb25zLlRva2VuID0gcmVzcG9uc2UudG9rZW47XG4gICAgXHR9XG4gICAgfSk7XG59XG5cbmV4cG9ydHMucmVuZGVyQ2FydCA9IHJlbmRlckNhcnQ7XG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlcjtcblx0aW5pdGlhbGl6ZShvcHRpb25zKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIHNpemVSZWZpbmVtZW50cyA9IHJlcXVpcmUoJy4uL3NpemUtcmVmaW5lbWVudHMnKTtcbnZhciBzbGlkZXJzID0gcmVxdWlyZSgnLi4vc2xpZGVycycpO1xudmFyIHN0eWxlQ291bnRzID0gcmVxdWlyZSgnLi4vc3R5bGUtY291bnRzJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXHRzdHlsZUNvdW50cy5yZW5kZXIob3B0aW9ucy5TdHlsZUNvdW50Q2FjaGUpO1xuXHRzaXplUmVmaW5lbWVudHMuaW5pdCgpO1xuXHRzbGlkZXJzLmluaXRpYWxpemVDYXRlZ29yeVNsaWRlcnMoJy5tYWluLWNvbnRlbnQgLmNhdGVnb3J5LWxhbmRpbmctc2xpZGVyOm5vdCguc2xpY2staW5pdGlhbGl6ZWQpJyk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyIGFwcGxlUGF5U2Vzc2lvbjtcbnZhciBvcHRpb25zID0ge307XG52YXIgYnVmZmVyID0ge307XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlciB8fCB7fTtcblxuXHQkKCdbcGF5bWVudC1tZXRob2QtY29udGFpbmVyPVwiRFdfQVBQTEVfUEFZXCJdJykuYXR0cignY2FuLW1ha2UtcGF5bWVudHMnLCAnQXBwbGVQYXlTZXNzaW9uJyBpbiB3aW5kb3cgJiYgJ2Nhbk1ha2VQYXltZW50cycgaW4gQXBwbGVQYXlTZXNzaW9uICYmIEFwcGxlUGF5U2Vzc2lvbi5jYW5NYWtlUGF5bWVudHMoKSk7XG5cdCQoJ1twYXltZW50LW1ldGhvZC1ncm91cC1jb250YWluZXI9XCJEV19BUFBMRV9QQVlcIl0nKS5hdHRyKCdjYW4tbWFrZS1wYXltZW50cycsICdBcHBsZVBheVNlc3Npb24nIGluIHdpbmRvdyAmJiAnY2FuTWFrZVBheW1lbnRzJyBpbiBBcHBsZVBheVNlc3Npb24gJiYgQXBwbGVQYXlTZXNzaW9uLmNhbk1ha2VQYXltZW50cygpKTtcblx0XG5cdGdldEFwcGxlUGF5UGF5bWVudFJlcXVlc3QoKTtcblx0JChkb2N1bWVudCkub2ZmKCdBcHBsZVBheS5HZXRQYXltZW50UmVxdWVzdCcpLm9uKCdBcHBsZVBheS5HZXRQYXltZW50UmVxdWVzdCBDYXJ0LlVwZGF0ZVN1Y2Nlc3MnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGdldEFwcGxlUGF5UGF5bWVudFJlcXVlc3QoKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5BcHBsZVBheScpLm9uKCdjbGljay5BcHBsZVBheScsICcuc3VibWl0LWFwcGxlcGF5LWJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uID0gbmV3IEFwcGxlUGF5U2Vzc2lvbigxLCBidWZmZXJbJ2FwcGxlUGF5UmVxdWVzdCddKTtcblx0XHRhcHBsZVBheVNlc3Npb24ub252YWxpZGF0ZW1lcmNoYW50ID0gdmFsaWRhdGVNZXJjaGFudDtcblx0XHRhcHBsZVBheVNlc3Npb24ub25zaGlwcGluZ2NvbnRhY3RzZWxlY3RlZCA9IHNoaXBwaW5nQ29udGFjdFNlbGVjdGVkO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbnNoaXBwaW5nbWV0aG9kc2VsZWN0ZWQgPSBzaGlwcGluZ01ldGhvZFNlbGVjdGVkO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbnBheW1lbnRtZXRob2RzZWxlY3RlZCA9IHBheW1lbnRNZXRob2RTZWxlY3RlZDtcblx0XHRhcHBsZVBheVNlc3Npb24ub25jb3Vwb25jb2RlY2hhbmdlZCA9IGNvdXBvbkNvZGVDaGFuZ2VkO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5vbnBheW1lbnRhdXRob3JpemVkID0gcGF5bWVudEF1dGhvcml6ZWQ7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLm9uY2FuY2VsID0gY2FuY2VsO1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5iZWdpbigpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVNZXJjaGFudChldmVudCkge1xuXHRmZXRjaChVcmxzLkFwcGxlUGF5LlZhbGlkYXRlTWVyY2hhbnQsIGdldEZldGNoT3B0aW9ucygnUE9TVCcsIGV2ZW50KSlcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsgXG5cdFx0cmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcblx0fSlcblx0LnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRhcHBsZVBheVNlc3Npb24uY29tcGxldGVNZXJjaGFudFZhbGlkYXRpb24ocmVzcG9uc2UpO1xuXHR9KVxuXHQuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKCdBcHBsZVBheS1WYWxpZGF0ZU1lcmNoYW50JywgZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2hpcHBpbmdDb250YWN0U2VsZWN0ZWQoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5TaGlwcGluZ0NvbnRhY3RTZWxlY3RlZCwgZ2V0RmV0Y2hPcHRpb25zKCdQT1NUJywgZXZlbnQpKVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkgeyBcblx0XHRyZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuXHR9KVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQ29udGFjdFNlbGVjdGlvbihyZXNwb25zZSk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0fSlcblx0LmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcignQXBwbGVQYXktU2hpcHBpbmdDb250YWN0U2VsZWN0ZWQnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzaGlwcGluZ01ldGhvZFNlbGVjdGVkKGV2ZW50KSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuU2hpcHBpbmdNZXRob2RTZWxlY3RlZCwgZ2V0RmV0Y2hPcHRpb25zKCdQT1NUJywgZXZlbnQpKVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkgeyBcblx0XHRyZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuXHR9KVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nTWV0aG9kU2VsZWN0aW9uKHJlc3BvbnNlKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHR9KVxuXHQuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKCdBcHBsZVBheS1TaGlwcGluZ01ldGhvZFNlbGVjdGVkJywgZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcGF5bWVudE1ldGhvZFNlbGVjdGVkKGV2ZW50KSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuUGF5bWVudE1ldGhvZFNlbGVjdGVkLCBnZXRGZXRjaE9wdGlvbnMoJ1BPU1QnLCBldmVudCkpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmNvbXBsZXRlUGF5bWVudE1ldGhvZFNlbGVjdGlvbihyZXNwb25zZSk7XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LVBheW1lbnRNZXRob2RTZWxlY3RlZCcsIGVycm9yKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGNvdXBvbkNvZGVDaGFuZ2VkKGV2ZW50KSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuQ291cG9uQ29kZUNoYW5nZWQpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0YXBwbGVQYXlTZXNzaW9uLmNvbXBsZXRlQ291cG9uQ29kZUNoYW5nZShyZXNwb25zZSk7XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LUNvdXBvbkNvZGVDaGFuZ2VkJywgZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcGF5bWVudEF1dGhvcml6ZWQoZXZlbnQpIHtcblx0ZmV0Y2goVXJscy5BcHBsZVBheS5QYXltZW50QXV0aG9yaXplZCwgZ2V0RmV0Y2hPcHRpb25zKCdQT1NUJywgZXZlbnQpKVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkgeyBcblx0XHRyZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuXHR9KVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdGFwcGxlUGF5U2Vzc2lvbi5jb21wbGV0ZVBheW1lbnQocmVzcG9uc2UpO1xuXHR9KVxuXHQudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdGlmIChldmVudC5wYXltZW50KSB7XG5cdFx0XHRpZiAoZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdCkge1xuXHRcdFx0XHR2YXIgYmlsbGluZ0FkZHJlc3NPYmplY3QgPSB7fTtcblx0XHRcdFx0YmlsbGluZ0FkZHJlc3NPYmplY3QuRmlyc3ROYW1lID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5naXZlbk5hbWU7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0Lkxhc3ROYW1lID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5mYW1pbHlOYW1lO1xuXHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5QcmltYXJ5TGluZSA9IGV2ZW50LnBheW1lbnQuYmlsbGluZ0NvbnRhY3QuYWRkcmVzc0xpbmVzWzBdIHx8ICcnO1xuXHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5TZWNvbmRhcnlMaW5lID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5hZGRyZXNzTGluZXNbMV0gfHwgJyc7XG5cdFx0XHRcdGJpbGxpbmdBZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9IGV2ZW50LnBheW1lbnQuYmlsbGluZ0NvbnRhY3QuYWRtaW5pc3RyYXRpdmVBcmVhO1xuXHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5Qb3N0YWxDb2RlID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5wb3N0YWxDb2RlO1xuXHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5DaXR5ID0gZXZlbnQucGF5bWVudC5iaWxsaW5nQ29udGFjdC5sb2NhbGl0eTtcblxuXHRcdFx0XHRpZiAoZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QgJiYgZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QucGhvbmUpIHtcblx0XHRcdFx0XHRiaWxsaW5nQWRkcmVzc09iamVjdC5QaG9uZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LnBob25lLnJlcGxhY2UoJysnLCcnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChvcHRpb25zLmlzQ2hlY2tvdXRQYWdlKSB7XG5cdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJywgJC5leHRlbmQoYmlsbGluZ0FkZHJlc3NPYmplY3QsIHsgQWRkcmVzc1R5cGU6ICdiaWxsaW5nJyB9KSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0KSB7XG5cdFx0XHRcdHZhciBzaGlwcGluZ0FkZHJlc3NPYmplY3QgPSB7fTtcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0LkZpcnN0TmFtZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LmdpdmVuTmFtZTtcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0Lkxhc3ROYW1lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QuZmFtaWx5TmFtZTtcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lID0gZXZlbnQucGF5bWVudC5zaGlwcGluZ0NvbnRhY3QuYWRkcmVzc0xpbmVzWzBdIHx8ICcnO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuU2Vjb25kYXJ5TGluZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LmFkZHJlc3NMaW5lc1sxXSB8fCAnJztcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LmFkbWluaXN0cmF0aXZlQXJlYTtcblx0XHRcdFx0c2hpcHBpbmdBZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUgPSBldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdC5wb3N0YWxDb2RlO1xuXHRcdFx0XHRzaGlwcGluZ0FkZHJlc3NPYmplY3QuQ2l0eSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LmxvY2FsaXR5O1xuXG5cdFx0XHRcdGlmIChldmVudC5wYXltZW50LnNoaXBwaW5nQ29udGFjdC5waG9uZSkge1xuXHRcdFx0XHRcdHNoaXBwaW5nQWRkcmVzc09iamVjdC5QaG9uZSA9IGV2ZW50LnBheW1lbnQuc2hpcHBpbmdDb250YWN0LnBob25lLnJlcGxhY2UoJysnLCcnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChvcHRpb25zLmlzQ2hlY2tvdXRQYWdlKSB7XG5cdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJywgJC5leHRlbmQoc2hpcHBpbmdBZGRyZXNzT2JqZWN0LCB7IEFkZHJlc3NUeXBlOiAnc2hpcHBpbmcnIH0pKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmlzQ2hlY2tvdXRQYWdlKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cubG9jYXRpb24gPSBVcmxzLm9uZVBhZ2U7XG5cdFx0fVxuXG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LVBheW1lbnRBdXRob3JpemVkJywgZXJyb3IpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gY2FuY2VsKGV2ZW50KSB7XG5cdGZldGNoKFVybHMuQXBwbGVQYXkuQ2FuY2VsLCBnZXRGZXRjaE9wdGlvbnMoJ1BPU1QnKSlcblx0LnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0Ly8gYXBwbGVQYXlTZXNzaW9uLmFib3J0KCk7XG5cdFx0aWYgKG9wdGlvbnMuaXNDaGVja291dFBhZ2UpIHtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0fVxuXHR9KVxuXHQuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKCdBcHBsZVBheS1DYW5jZWwnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRBcHBsZVBheVBheW1lbnRSZXF1ZXN0KCkge1xuXHRmZXRjaChVcmxzLkFwcGxlUGF5LkdldFJlcXVlc3QpXG5cdC50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7IFxuXHRcdHJldHVybiByZXNwb25zZS5qc29uKCk7XG5cdH0pXG5cdC50aGVuKGZ1bmN0aW9uKGFwcGxlUGF5UmVxdWVzdCkge1xuXHRcdGJ1ZmZlclsnYXBwbGVQYXlSZXF1ZXN0J10gPSBhcHBsZVBheVJlcXVlc3Q7XG5cdH0pXG5cdC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoJ0FwcGxlUGF5LUdldFJlcXVlc3QnLCBlcnJvcik7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRGZXRjaE9wdGlvbnMobWV0aG9kLCBib2R5KSB7XG5cdHZhciBmZXRjaE9wdGlvbnMgPSB7XG5cdFx0Y3JlZGVudGlhbHM6ICdpbmNsdWRlJ1xuXHR9O1xuXHRpZiAobWV0aG9kKSB7XG5cdFx0ZmV0Y2hPcHRpb25zLm1ldGhvZCA9IG1ldGhvZDtcblx0fVxuXHRpZiAoYm9keSkge1xuXHRcdGZldGNoT3B0aW9ucy5oZWFkZXJzID0ge1xuXHRcdFx0J0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdCdBY2NlcHQnOiAnYXBwbGljYXRpb24vanNvbidcblx0XHR9XG5cdFx0ZmV0Y2hPcHRpb25zLmJvZHkgPSBKU09OLnN0cmluZ2lmeShmaWx0ZXJFdmVudChib2R5KSk7XG5cdH1cblxuXHRyZXR1cm4gZmV0Y2hPcHRpb25zO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJFdmVudChldmVudCkge1xuXHR2YXIgZXZlbnRGaWx0ZXJlZCA9IHt9O1xuXHRmb3IgKHZhciBwcm9wZXJ0eSBpbiBldmVudCkge1xuXHRcdGlmICghRXZlbnQucHJvdG90eXBlLmhhc093blByb3BlcnR5KHByb3BlcnR5KSkge1xuXHRcdFx0ZXZlbnRGaWx0ZXJlZFtwcm9wZXJ0eV0gPSBldmVudFtwcm9wZXJ0eV07XG5cdFx0fVxuXHR9XG5cdHJldHVybiBldmVudEZpbHRlcmVkO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgZ2lmdENhcmRCYWxhbmNlSW5xdWlyeURpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvR2lmdENhcmRCYWxhbmNlSW5xdWlyeURpYWxvZycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFRlbXBsYXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9UZW1wbGF0ZUNvbnN0YW50cycpO1xudmFyIFZhbGlkYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL3NjcmlwdHMvdXRpbC9WYWxpZGF0aW9uSGVscGVyJyk7XG52YXIgVmFsaWRhdGlvblJ1bGVzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9WYWxpZGF0aW9uQ29uc3RhbnRzJykuUnVsZXM7XG52YXIgb3BjcGF5bWVudCA9IHJlcXVpcmUoJy4vb3BjcGF5bWVudCcpO1xuXG5leHBvcnRzLmluaXRpYWxpemUgPSBpbml0aWFsaXplO1xuXG52YXIgJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lciA9ICQoJ1twYXltZW50LW1ldGhvZD1cIlNWU19HaWZ0X0NhcmRcIl0nKTtcbnZhciAkZ2lmdENhcmRQYXltZW50Rm9ybSA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnZm9ybScpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyID0gJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lJD1cImdpZnRDYXJkX251bWJlclwiXScpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRQaW5OdW1iZXIgPSAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmZpbmQoJ2lucHV0W25hbWUkPVwiZ2lmdENhcmRfcGluXCJdJyk7XG52YXIgJGdpZnRDYXJkUGF5bWVudE1lc3NhZ2UgPSAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmZpbmQoJy5tZXNzYWdlcycpO1xudmFyICRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UgPSAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmZpbmQoJ3NwYW4uZXJyb3InKTtcbnZhciAkZ2lmdENhcmRQYXltZW50QXBwbGllZCA9ICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIuZmluZCgnLmZvcm0tZ2lmdGNhcmRzLWFwcGxpZWQnKTtcbnZhciAkZ2lmdENhcmRQYXltZW50QXBwbHlCdXR0b24gPSAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLmZpbmQoJy5hcHBseScpO1xudmFyIGdpZnRDYXJkVmFsaWRhdG9yO1xudmFyIGdpZnRDYXJkUmVjYXB0Y2hhO1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBsb2FkZWQgPSB7fTtcblxuZnVuY3Rpb24gcmVuZGVyUmVjYXB0Y2hhKCkge1xuXHRpZiAobG9hZGVkLlJlY2FwdGNoYSAmJiAkZ2lmdENhcmRQYXltZW50QXBwbHlCdXR0b24ubGVuZ3RoID4gMCAmJiBvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JHaWZ0Q2FyZHMgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdGdpZnRDYXJkUmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ3N2cy1naWZ0LWNhcmQtYXBwbHktYnV0dG9uJywge1xuXHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdCAgICAgICAgY2FsbGJhY2s6IHN1Ym1pdEdpZnRDYXJkLFxuXHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0ICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlciB8fCB7fTtcblx0XG5cdHJlbmRlclJlY2FwdGNoYSgpO1xuXHQkKGRvY3VtZW50KS5vbignUmVjYXB0Y2hhLkxvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRsb2FkZWQuUmVjYXB0Y2hhID0gdHJ1ZTtcblx0ICAgICAgICByZW5kZXJSZWNhcHRjaGEoKTtcblx0ICAgIH1cblx0fSk7XG5cdFxuICAgICRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5hcHBseTpub3QoW2xvYWRpbmddKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcbiAgICAgICAgaWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLlJlY2FwdGNoYSB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckdpZnRDYXJkcyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignR2lmdENhcmQuQXBwbHknKTtcbiAgICAgICAgfVxuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdHaWZ0Q2FyZC5BcHBseScsIGZ1bmN0aW9uKGV2ZW50KSB7XHRcdFxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGlmIChwYXJzZUZsb2F0KCQoJ1tiYWxhbmNlLWR1ZV0nKS5maXJzdCgpLmF0dHIoJ2JhbGFuY2UtZHVlJykpIDw9IDApIHtcbiAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuUmV3YXJkc0NyZWRpdC5Ob0JhbGFuY2VEdWUpLnNob3coKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKGdpZnRDYXJkUmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGdpZnRDYXJkUmVjYXB0Y2hhKTtcblx0XHRcdH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICAgICAgZ2lmdENhcmRWYWxpZGF0b3IgPSAkZ2lmdENhcmRQYXltZW50Rm9ybS52YWxpZGF0ZSgpO1xuXHRcdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdnaWZ0Q2FyZE51bWJlckxlbmd0aCcsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVHaWZ0Q2FyZE51bWJlckxlbmd0aCwgUmVzb3VyY2VzLlZhbGlkYXRpb24uTWVzc2FnZXMuR2lmdENhcmQuTnVtYmVyLkxlbmd0aCk7XG5cdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ2dpZnRDYXJkTnVtYmVyVmFsdWVzJywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZUdpZnRDYXJkTnVtYmVyVmFsdWVzLCBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5HaWZ0Q2FyZC5OdW1iZXIuVmFsdWVzKTtcbiAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuR2lmdENhcmQuTnVtYmVyKTtcbiAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRQaW5OdW1iZXIucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5HaWZ0Q2FyZC5QaW4pO1xuICAgICAgICAgICAgZ2lmdENhcmRWYWxpZGF0b3IuZm9ybSgpO1xuXG4gICAgICAgICAgICAvLyBBZGRpbmcgQURBIGNvbXBsaWFuY2UgZXJyb3IgbWVzc2FnZXMgZm9yIGdpZnRDYXJkUGF5bWVudCBzZWN0aW9uXG4gICAgICAgICAgICBpZiAoJGdpZnRDYXJkUGF5bWVudEZvcm0uZmluZCgnLmZpZWxkLmVycm9yJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGdpZnRDYXJkUGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzID0gb3BjcGF5bWVudC5nZXRFcnJvck1lc3NhZ2VzKCRnaWZ0Q2FyZFBheW1lbnRGb3JtKTtcbiAgICAgICAgICAgICAgICB2YXIgZ2lmdENhcmRQYXltZW50Rm9ybUVycm9yQm94ID0gb3BjcGF5bWVudC5lcnJvckJveCgnQ2Fubm90IFByb2NlZWQnLCAnUGxlYXNlIGZpeCB0aGUgZm9sbG93aW5nIGVycm9yczonLCBnaWZ0Q2FyZFBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyk7XG4gICAgICAgICAgICAgICAgaWYgKGdpZnRDYXJkUGF5bWVudEZvcm1FcnJvckJveCkge1xuICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50QXBwbGllZC5hZnRlcihnaWZ0Q2FyZFBheW1lbnRGb3JtRXJyb3JCb3gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKFVybHMgJiYgVXJscy5HaWZ0Q2FyZC5BcHBseSAmJiBnaWZ0Q2FyZFZhbGlkYXRvci52YWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdpZnRDYXJkUm93Q29udGFpbmVySHRtbCA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWdpZnQtY2FyZC1yb3ctY29udGFpbmVyJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpKCk7XG4gICAgICAgICAgICAgICAgdmFyICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQgPSAkKGdpZnRDYXJkUm93Q29udGFpbmVySHRtbCkuYXBwZW5kVG8oJGdpZnRDYXJkUGF5bWVudEFwcGxpZWQpO1xuXG4gICAgICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcob3B0aW9ucy5Mb2FkaW5nSW5kaWNhdG9yIHx8IHtcbiAgICAgICAgICAgICAgICAgICAgSXNJbWFnZVNob3duOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgTGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLlByb2Nlc3NpbmdcbiAgICAgICAgICAgICAgICB9KTtcblx0XHRcdFx0aWYgKCFvcHRpb25zLkxvYWRpbmdJbmRpY2F0b3IpIHtcblx0XHRcdFx0XHQkZ2lmdENhcmRQYXltZW50QXBwbGllZEdpZnRDYXJkLmxvYWRpbmcob3B0aW9ucy5Mb2FkaW5nSW5kaWNhdG9yIHx8IHtcblx0XHRcdFx0XHRcdExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5HaWZ0Q2FyZC5BcHBseWluZ1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIgPSAkZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlci52YWwoKS5tYXRjaCgvKFxcZCkvZyk7XG5cdFx0XHRcdGlmIChnaWZ0Q2FyZFBheW1lbnRDYXJkTnVtYmVyICYmIGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIubGVuZ3RoKSB7XG5cdFx0XHRcdFx0Z2lmdENhcmRQYXltZW50Q2FyZE51bWJlciA9IGdpZnRDYXJkUGF5bWVudENhcmROdW1iZXIuam9pbignJyk7XG5cdFx0XHRcdH1cblxuICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMuR2lmdENhcmQuQXBwbHksXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bWJlcjogZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBpbjogJGdpZnRDYXJkUGF5bWVudFBpbk51bWJlci52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFtb3VudDogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0XHRcdGlmICgkZ2lmdENhcmRQYXltZW50QXBwbHlCdXR0b24uYXR0cignbG9hZGluZycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdCRnaWZ0Q2FyZFBheW1lbnRBcHBseUJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoJGdpZnRDYXJkUGF5bWVudEFwcGxpZWRHaWZ0Q2FyZC5hdHRyKCdsb2FkaW5nJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0JGdpZnRDYXJkUGF5bWVudEFwcGxpZWRHaWZ0Q2FyZC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50Q2FyZE51bWJlci52YWwoJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRQaW5OdW1iZXIudmFsKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5hbW91bnRBcHBsaWVkICYmIGRhdGEuYW1vdW50QXBwbGllZC52YWx1ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdCRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkLmZpbmQoJ1tkYXRhLWlkPVwiJyArIGRhdGEuaWQgKyAnXCJdJykucmVtb3ZlKCk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQuYXR0cignZGF0YS1pZCcsIGRhdGEuaWQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnaWZ0Q2FyZFJvd0NvbnRlbnRIdG1sID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtZ2lmdC1jYXJkLXJvdy1jb250ZW50JykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmROdW1iZXI6IGRhdGEubnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW1vdW50QXBwbGllZDogZGF0YS5hbW91bnRBcHBsaWVkLmRpc3BsYXlWYWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZ2lmdENhcmRQYXltZW50QXBwbGllZEdpZnRDYXJkLmh0bWwoZ2lmdENhcmRSb3dDb250ZW50SHRtbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdCRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLm1lc3NhZ2UpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cblx0XHRcdFx0XHRcdFx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5yZWxvYWQoKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdGlmIChkYXRhLm1lc3NhZ2UgPT0gJ0ludmFsaWQgTWVzc2FnZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0XHRkYXRhLm1lc3NhZ2UgPSBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYztcdFxuICAgICAgICAgICAgICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICAgICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFBheW1lbnRBcHBsaWVkR2lmdENhcmQucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEubWVzc2FnZSB8fCBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG5cdFx0XHRcdFx0XHRpZiAoZ2lmdENhcmRSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQoZ2lmdENhcmRSZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdFx0XHRcdFx0dmFsdWU6IGRhdGEuYW1vdW50QXBwbGllZC52YWx1ZSxcblx0XHRcdFx0XHRcdFx0cGF5bWVudF90eXBlOiAnR2lmdCBDYXJkIFNWUydcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFBheW1lbnRJbmZvJywgZGF0YU9iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCRnaWZ0Q2FyZFBheW1lbnRBcHBseUJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHQkZ2lmdENhcmRQYXltZW50QXBwbGllZEdpZnRDYXJkLnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0JGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmIChnaWZ0Q2FyZFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChnaWZ0Q2FyZFJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBcdGlmIChnaWZ0Q2FyZFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGdpZnRDYXJkUmVjYXB0Y2hhKTtcblx0XHRcdFx0fVx0XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9mZignbW91c2Vkb3duLkdpZnRDYXJkUGF5bWVudFBhbmVsJykub24oJ21vdXNlZG93bi5HaWZ0Q2FyZFBheW1lbnRQYW5lbCcsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoZ2lmdENhcmRWYWxpZGF0b3IgJiYgJChldmVudC50YXJnZXQpLmNsb3Nlc3QoJGdpZnRDYXJkUGF5bWVudENvbnRhaW5lcikubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIGdpZnRDYXJkVmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuICAgICAgICAgICAgJGdpZnRDYXJkUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKCcnKS5oaWRlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdDYXJ0RGF0YS5VcGRhdGUnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGEpIHtcbiAgICBcdCQoJ1toYXMtZ2lmdC1jYXJkc10nKS5hdHRyKCdoYXMtZ2lmdC1jYXJkcycsIGRhdGEuSGFzR2lmdENhcmRzIHx8IGZhbHNlKTtcblx0ICAgICQoJ1toYXMtZ2lmdC1jYXJkcy1vbmx5XScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzLW9ubHknLCBkYXRhLkhhc0dpZnRDYXJkc09ubHkgfHwgZmFsc2UpO1xuXHQgICAgXG5cdCAgICBpZiAoZGF0YS5IYXNHaWZ0Q2FyZHMgJiYgIWRhdGEuQWxsb3dHaWZ0Q2FyZFB1cmNoYXNlV2l0aEdpZnRDYXJkKSB7XG5cdCAgICBcdCRnaWZ0Q2FyZFBheW1lbnRNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkdpZnRDYXJkLkdpZnRDYXJkUHVyY2hhc2VXaXRoR2lmdENhcmROb3RBbGxvd2VkKTtcblx0ICAgIFx0JGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5hdHRyKCdzdGF0dXMnLCAnbG9ja2VkJyk7XG5cdCAgICB9IGVsc2Uge1xuXHQgICAgXHQkZ2lmdENhcmRQYXltZW50TWVzc2FnZS5odG1sKCcnKTtcblx0ICAgIFx0JGdpZnRDYXJkUGF5bWVudENvbnRhaW5lci5hdHRyKCdzdGF0dXMnLCAnYWN0aXZlJyk7XG5cdCAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ0dpZnRDYXJkLkNsZWFyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkZ2lmdENhcmRQYXltZW50QXBwbGllZC5odG1sKCcnKTtcbiAgICAgICAgJCgnLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCgnJyk7XG4gICAgfSk7XG5cbiAgICAkZ2lmdENhcmRQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcucmVtb3ZlOm5vdChbbG9hZGluZ10pJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgdmFyICRnaWZ0Q2FyZFJvdyA9ICQodGhpcykuY2xvc2VzdCgnLmZvcm0tZ2lmdGNhcmQtYXBwbGllZCcpO1xuICAgICAgICAkZ2lmdENhcmRSb3cubG9hZGluZyhvcHRpb25zLkxvYWRpbmdJbmRpY2F0b3IgfHwge1xuICAgICAgICAgICAgTGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkdpZnRDYXJkLlJlbW92aW5nXG4gICAgICAgIH0pO1xuICAgICAgICAkZ2lmdENhcmRQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsIDogVXJscy5HaWZ0Q2FyZC5SZW1vdmUsXG4gICAgICAgICAgICB0eXBlIDogJ1BPU1QnLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICBpZDogJGdpZnRDYXJkUm93LmRhdGEoJ2lkJylcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgZGF0YVR5cGUgOiAnanNvbicsXG4gICAgICAgICAgICBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgXHQkZ2lmdENhcmRSb3cubG9hZGluZygnZGVzdHJveScpO1xuICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgICRnaWZ0Q2FyZFJvdy5yZW1vdmUoKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdFx0XHRcdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgXHQkZ2lmdENhcmRQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5lcnJvciB8fCBSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRnaWZ0Q2FyZFJvdy5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdCRnaWZ0Q2FyZFBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0fVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljay5CYWxhbmNlSW5xdWlyeScsICdbcGF5bWVudC1tZXRob2Q9XCJTVlNfR2lmdF9DYXJkXCJdIC5iYWxhbmNlLWlucXVpcnkgYScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBnaWZ0Q2FyZEJhbGFuY2VJbnF1aXJ5RGlhbG9nLmluaXRpYWxpemUoKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnLmZvcm0tbGFiZWwuZXhwYW5kZXInLCBmdW5jdGlvbigpe1xuICAgIFx0JCgnZm9ybS5zdnMtZ2lmdC1jYXJkLWluZm9ybWF0aW9uJykuc2xpZGVUb2dnbGUoKTtcbiAgICBcdCRnaWZ0Q2FyZFBheW1lbnRDb250YWluZXIudG9nZ2xlQ2xhc3MoJ3N2cy1jb2xsYXBzZWQnKTtcbiAgICB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0Jztcbi8qIGdsb2JhbCBSZXNvdXJjZXMsIFVybHMgKi9cblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBvcGNwYXltZW50ID0gcmVxdWlyZSgnLi9vcGNwYXltZW50Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbmV4cG9ydHMuaW5pdGlhbGl6ZSA9IGluaXRpYWxpemU7XG5cbnZhciAkbG95YWx0eVBheW1lbnRDb250YWluZXIgPSAkKCdbcGF5bWVudC1tZXRob2Q9XCJMT1lBTFRZX0NSRURJVFwiXScpO1xudmFyICRsb3lhbHR5UGF5bWVudHNGb3JtID0gJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmZpbmQoJ2Zvcm0nKTtcbnZhciAkbG95YWx0eVBheW1lbnRzQXBwbGllZCA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcubG95YWx0eS1hcHBsaWVkJyk7XG52YXIgJGxveWFsdHlQYXltZW50SW5wdXQgPSAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfbG95YWx0eV9sb3lhbHR5TnVtYmVyJyk7XG52YXIgJGxveWFsdHlQaG9uZU51bWJlcklucHV0ID0gJGxveWFsdHlQYXltZW50Q29udGFpbmVyLmZpbmQoJyNkd2ZybV9iaWxsaW5nX2xveWFsdHlfbG95YWx0eVBob25lTnVtYmVyJyk7XG52YXIgJGxveWFsdHlaaXBDb2RlSW5wdXQgPSAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfbG95YWx0eV9sb3lhbHR5WmlwQ29kZScpO1xudmFyICRsb3lhbHR5UGF5bWVudFNlY29uZGFyeUNvbnRhaW5lciA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCcubG95YWx0eS1zZWNvbmRhcnknKTtcbnZhciAkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlTZWxlY3QgPSAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnI2xveWFsdHktc2Vjb25kYXJ5LXNlbGVjdCcpO1xudmFyICRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZSA9ICRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5maW5kKCdzcGFuLmVycm9yJyk7XG52YXIgbG95YWx0eUNyZWRpdFZhbGlkYXRvcjtcbnZhciBsb3lhbHR5Q3JlZGl0Um93VGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1sb3lhbHR5LWNyZWRpdC1yb3cnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG52YXIgbG95YWx0eUNyZWRpdFJlY2FwdGNoYTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYSgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI2xveWFsdHktY3JlZGl0LWFkZC1idXR0b24nKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvcmxveWFsdHlDcmVkaXQgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdGxveWFsdHlDcmVkaXRSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcignbG95YWx0eS1jcmVkaXQtYWRkLWJ1dHRvbicsIHtcblx0ICAgICAgICBzaXRla2V5OiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRMb3lhbHR5Q3JlZGl0LFxuXHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0ICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlciB8fCB7fTtcblx0dmFyIGN1cnJlbnRTaXRlID0gJyc7XG5cdGlmICgkKFwiLmxvZ28uc2hlcFwiKS5sZW5ndGggPiAwKXtcbiAgICBcdGN1cnJlbnRTaXRlID0gUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuTm90T3B0ZWRJblNIRVA7XG4gICAgfVxuXHRpZiAoJChcIi5sb2dvLmNvXCIpLmxlbmd0aCA+IDApe1xuICAgIFx0Y3VycmVudFNpdGUgPSBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob3RPcHRlZEluQ087XG4gICAgfVxuXHRcblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcblx0XG5cdGlmICgkKFwiLmxveWFsdHktcm93W3N0YXR1cz0nYXBwbGllZCddXCIpLmxlbmd0aCA+IDApe1xuXHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLmhpZGUoKTtcblx0fVxuXG5cdGlmICgkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlTZWxlY3QuY2xvc2VzdCgnLm9wYy1zdW1tYXJ5JykubGVuZ3RoID4gMCkge1xuXHRcdCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeVNlbGVjdC5zZWxlY3RtZW51KHtcblx0XHRcdHdpZHRoOiAnMTAwJScsXG5cdFx0XHRhcHBlbmRUbzogJ1twYXltZW50LW1ldGhvZD1cIkxPWUFMVFlfQ1JFRElUXCJdIC5sb3lhbHR5LXNlY29uZGFyeScsXG5cdFx0XHRjaGFuZ2U6IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHQkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlDb250YWluZXIuYXR0cignc2Vjb25kYXJ5JywgdWkgJiYgdWkuaXRlbSAmJiB1aS5pdGVtLnZhbHVlID8gdWkuaXRlbS52YWx1ZSA6ICcnKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRcblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcucmVzZXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0cmVzZXRTZWNvbmRhcnlTZWxlY3QoKTtcblx0fSk7XG5cblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcuYWRkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuICAgICAgICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUmV3YXJkc0NyZWRpdCB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignTG95YWx0eUNyZWRpdC5BZGQnKTsgXG4gICAgICAgIH1cblx0fSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignTG95YWx0eUNyZWRpdC5BZGQnLCBmdW5jdGlvbihldmVudCwgZGF0YSkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRpZiAocGFyc2VGbG9hdCgkKCdbYmFsYW5jZS1kdWVdJykuZmlyc3QoKS5hdHRyKCdiYWxhbmNlLWR1ZScpKSA8PSAwKSB7XG5cdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5Ob0JhbGFuY2VEdWUpLnNob3coKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIGxveWFsdHlTZWNvbmRhcnlGYWN0b3IgPSAkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlDb250YWluZXIuYXR0cignc2Vjb25kYXJ5Jyk7XG5cdFx0XHRsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yID0gJGxveWFsdHlQYXltZW50c0Zvcm0udmFsaWRhdGUoKTtcbiAgICAgICAgICAgICRsb3lhbHR5UGF5bWVudElucHV0LnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuTG95YWx0eUNyZWRpdC5OdW1iZXIpO1xuXG5cdFx0XHRzd2l0Y2ggKGxveWFsdHlTZWNvbmRhcnlGYWN0b3IpIHtcblx0XHRcdFx0Y2FzZSBcInppcGNvZGVcIjpcblx0XHRcdFx0XHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ppcENvZGUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlWmlwQ29kZSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVEFMX0NPREUpO1xuXHRcdFx0XHRcdCRsb3lhbHR5WmlwQ29kZUlucHV0LnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuWmlwQ29kZSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuICAgICAgICAgICAgbG95YWx0eUNyZWRpdFZhbGlkYXRvci5mb3JtKCk7XG5cblx0XHRcdC8vIEFkZGluZyBBREEgY29tcGxpYW5jZSBlcnJvciBtZXNzYWdlcyBmb3IgZ2lmdENhcmRQYXltZW50IHNlY3Rpb25cbiAgICAgICAgICAgIGlmICgkbG95YWx0eVBheW1lbnRzRm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGxveWFsdHlQYXltZW50Rm9ybUVycm9yTWVzc2FnZXMgPSBvcGNwYXltZW50LmdldEVycm9yTWVzc2FnZXMoJGxveWFsdHlQYXltZW50c0Zvcm0pO1xuICAgICAgICAgICAgICAgIHZhciBsb3lhbHR5UGF5bWVudEZvcm1FcnJvckJveCA9IG9wY3BheW1lbnQuZXJyb3JCb3goJ0Nhbm5vdCBQcm9jZWVkJywgJ1BsZWFzZSBmaXggdGhlIGZvbGxvd2luZyBlcnJvcnM6JywgbG95YWx0eVBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyk7XG4gICAgICAgICAgICAgICAgaWYgKGxveWFsdHlQYXltZW50Rm9ybUVycm9yQm94KSB7XG4gICAgICAgICAgICAgICAgICAgICRsb3lhbHR5UGF5bWVudHNBcHBsaWVkLmFmdGVyKGxveWFsdHlQYXltZW50Rm9ybUVycm9yQm94KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cdFx0XHRcbiAgICAgICAgICAgIGlmIChVcmxzICYmIFVybHMuY2hlY2tMb3lhbHR5ICYmIGxveWFsdHlDcmVkaXRWYWxpZGF0b3IudmFsaWQoKSkge1xuICAgICAgICAgICAgXHQkbG95YWx0eVBheW1lbnRzRm9ybS5oaWRlKCk7XG4gICAgICAgICAgICBcdFxuXHRcdFx0XHR2YXIgJGxveWFsdHlDcmVkaXRSb3cgPSAkKGxveWFsdHlDcmVkaXRSb3dUZW1wbGF0ZSgpKTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cgPSAkbG95YWx0eUNyZWRpdFJvdy5hcHBlbmRUbygkbG95YWx0eVBheW1lbnRzQXBwbGllZCk7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdwZW5kaW5nJyk7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5TnVtYmVyJykuaHRtbCh1dGlsLmdldE1hc2tlZE51bWJlcigkbG95YWx0eVBheW1lbnRJbnB1dC52YWwoKSwgNCwgJ3h4eHguLi4gJykpO1xuXHRcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKHtMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuTG95YWx0eUNyZWRpdC5Mb2FkaW5nfSk7XG5cdFxuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybDogVXJscy5jaGVja0xveWFsdHksXG5cdFx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdGNzcmZfdG9rZW46ICAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdGxveWFsdHlOdW1iZXI6ICRsb3lhbHR5UGF5bWVudElucHV0LnZhbCgpLFxuXHRcdFx0XHRcdFx0bG95YWx0eVBob25lTnVtYmVyOiAkbG95YWx0eVBob25lTnVtYmVySW5wdXQudmFsKCksXG5cdFx0XHRcdFx0XHRsb3lhbHR5WmlwQ29kZTogJGxveWFsdHlaaXBDb2RlSW5wdXQudmFsKClcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0JGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0XG5cdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFxuXHRcdFx0XHRcdFx0aWYgKGRhdGEuZXJyb3IgIT09ICd1bmRlZmluZWQnICYmIGRhdGEuZXJyb3IgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5lcnJvck1zZykuc2hvdygpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmICghZGF0YS5vcHRpblN0YXR1cykge1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRDb250YWluZXIuYXR0cignaGFzLWxveWFsdHludW1iZXInLCAnZmFsc2UnKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ21lc3NhZ2UnKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLm1lc3NhZ2UnKS5odG1sKGN1cnJlbnRTaXRlKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAocGFyc2VGbG9hdChkYXRhLmNyZWRpdEFtb3VudCkgPD0gMCkge1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRDb250YWluZXIuYXR0cignaGFzLWxveWFsdHludW1iZXInLCAndHJ1ZScpO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnbWVzc2FnZScpO1xuXHRcdFx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcubWVzc2FnZScpLmh0bWwoUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuTm9CYWxhbmNlQXZhaWxhYmxlKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicsICd0cnVlJyk7XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdkYXRhLWxveWFsdHknLCBkYXRhLm9wdEluKTtcblx0XHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJhc2tldExveWFsdHlBbW91bnQnKS5odG1sKGRhdGEuY3JlZGl0QW1vdW50Rm9ybWF0dGVkKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdHZhciBkZXRhaWxzID0gJyc7XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHR2YXIgdm91Y2hlcnMgPSBkYXRhLmNyZWRpdFZvdWNoZXJzO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0dm91Y2hlcnMucmV2ZXJzZSgpLmZvckVhY2goZnVuY3Rpb24odm91Y2hlcil7XG5cdFx0XHRcdFx0XHRcdFx0ZGV0YWlscyArPSAnPGRpdiBjbGFzcz1cInZvdWNoZXJcIj48c3BhbiBjbGFzcz1cInJld2FyZC1hbW91bnRcIj48Yj4kJyt2b3VjaGVyLnJld2FyZEFtb3VudCsnPC9iPjwvc3Bhbj48c3BhbiBjbGFzcz1cImV4cGlyYXRpb25cIj48aT5FeHBpcmVzICcrdm91Y2hlci5leHBpcmF0aW9uRGF0ZSsnPC9pPjwvc3Bhbj48L2Rpdj4nO1xuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy52b3VjaGVycycpLmh0bWwoZGV0YWlscyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGlmIChsb3lhbHR5Q3JlZGl0UmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KGxveWFsdHlDcmVkaXRSZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAobG95YWx0eUNyZWRpdFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChsb3lhbHR5Q3JlZGl0UmVjYXB0Y2hhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbihkYXRhLCBzdGF0dXMsIHhocikge1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcbiAgICAgICAgICAgIH1cblx0XHR9XG5cdH0pO1xuXG5cdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLmFwcGx5JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICRsb3lhbHR5Q3JlZGl0Um93ID0gJCh0aGlzKS5jbG9zZXN0KCcubG95YWx0eS1yb3cnKTtcblx0XHRcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLmFkZENsYXNzKCdoaWRlJyk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLnZvdWNoZXInKS5hZGRDbGFzcygnaGlkZScpO1xuXHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKHtJc0xhYmVsU2hvd246IGZhbHNlfSk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKHtMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuTG95YWx0eUNyZWRpdC5BcHBseWluZ30pO1xuXG5cdFx0JC5hamF4KHtcblx0XHRcdHVybDogVXJscy5hcHBseUxveWFsdHksXG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRkYXRhOiB7XG5cdFx0XHRcdGNzcmZfdG9rZW46ICAkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKSxcblx0XHRcdFx0bG95YWx0eU51bWJlcjogJGxveWFsdHlQYXltZW50SW5wdXQudmFsKCksXG5cdFx0XHRcdGxveWFsdHlQaG9uZU51bWJlcjogJGxveWFsdHlQaG9uZU51bWJlcklucHV0LnZhbCgpLFxuXHRcdFx0XHRsb3lhbHR5WmlwQ29kZTogJGxveWFsdHlaaXBDb2RlSW5wdXQudmFsKClcblx0XHRcdH0sXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXG5cdFx0XHRcdGlmIChkYXRhLmVycm9yICE9PSAndW5kZWZpbmVkJyAmJiBkYXRhLmVycm9yID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ21lc3NhZ2UnKTtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LnJlbW92ZSgpO1xuXHRcdFx0XHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLmVycm9yTXNnKS5zaG93KCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ2FwcGxpZWQnKTtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRzRm9ybS5oaWRlKCk7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLnZvdWNoZXInKS5yZW1vdmVDbGFzcygnaGlkZScpO1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5iYXNrZXRMb3lhbHR5TnVtYmVyJykuaHRtbCh1dGlsLmdldE1hc2tlZE51bWJlcihkYXRhLmxveWFsdHlOdW1iZXIsIDQsICd4eHh4Li4uICcpKTtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLnJlbW92ZUNsYXNzKCdoaWRlJykuaHRtbChkYXRhLmxveWFsdHlDcmVkaXRVc2VkRm9ybWF0dGVkKS5hdHRyKCdsYWJlbCcsIFJlc291cmNlcy5Mb3lhbHR5Q3JlZGl0LlJld2FyZEFwcGxpZWQpO1xuXG5cdFx0XHRcdFx0dmFyIGRhdGFPYmplY3QgPSB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogZGF0YS5yZXdhcmRzQ3JlZGl0VXNlZCxcblx0XHRcdFx0XHRcdHBheW1lbnRfdHlwZTogJ0xveWFsdHknXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFBheW1lbnRJbmZvJywgZGF0YU9iamVjdCk7XG5cblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnbWVzc2FnZScpO1xuXHRcdFx0XHQkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0XHRyZXNldEZvcm0odHJ1ZSk7XG5cdFx0XHR9LFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKGRhdGEsIHN0YXR1cywgeGhyKSB7XG5cdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0XHRsb2NhdGlvbi5ocmVmID0gZGF0YS5yZXNwb25zZVRleHQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljayBMb3lhbHR5Q3JlZGl0LlJlbW92ZScsICcucmVtb3ZlJywgZnVuY3Rpb24oZXZlbnQsIGRhdGEpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICRsb3lhbHR5Q3JlZGl0Um93ID0gJCh0aGlzKS5jbG9zZXN0KCcubG95YWx0eS1yb3cnKTtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLmFkZENsYXNzKCdoaWRlJyk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLnZvdWNoZXInKS5hZGRDbGFzcygnaGlkZScpO1xuXHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKHtJc0xhYmVsU2hvd246IGZhbHNlfSk7XG5cdFx0JGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKHtMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuTG95YWx0eUNyZWRpdC5SZW1vdmluZ30pO1xuXG5cdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRsb3lhbHR5TnVtYmVyOiAkKCdpbnB1dCNkd2ZybV9iaWxsaW5nX2xveWFsdHlfbG95YWx0eU51bWJlcicpLnZhbCgpXG5cdFx0fVxuXG5cdFx0aWYgKGRhdGEgJiYgZGF0YS5SZXNldFNlc3Npb25EYXRhKSB7XG5cdFx0XHRwYXlsb2FkLnJlc2V0U2Vzc2lvbkRhdGEgPSB0cnVlXG5cdFx0fVxuXG5cdFx0JC5hamF4KHtcblx0XHRcdHVybDogVXJscy5yZW1vdmVMb3lhbHR5LFxuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdGRhdGE6IHBheWxvYWQsXG5cdFx0XHRzdWNjZXNzOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblxuXHRcdFx0XHRpZiAoJGxveWFsdHlDcmVkaXRSb3cuZmluZCgnLmJ0bltsb2FkaW5nXScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICgkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9sc1tsb2FkaW5nXScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICgkbG95YWx0eVBheW1lbnRDb250YWluZXIuYXR0cignaGFzLWxveWFsdHludW1iZXInKSAhPT0gJ3RydWUnKSB7XG5cdFx0XHRcdFx0JGxveWFsdHlQYXltZW50SW5wdXQudmFsKCcnKTtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0XHRcdFx0JGxveWFsdHlDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ2Zvcm0nKTtcblx0XHRcdFx0XHQkbG95YWx0eVBheW1lbnRzQXBwbGllZC5odG1sKCcnKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAncGVuZGluZycpO1xuXHRcdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy52b3VjaGVyJykucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcblx0XHRcdFx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLnJlbW92ZUNsYXNzKCdoaWRlJykuYXR0cignbGFiZWwnLCBSZXNvdXJjZXMuTG95YWx0eUNyZWRpdC5SZXdhcmQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdCRsb3lhbHR5Q3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXG5cdFx0XHRcdCRsb3lhbHR5UGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXHRcblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcuY2hhbmdlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuXHRcdCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicsICdmYWxzZScpO1xuXHRcdGlmICgkbG95YWx0eVBheW1lbnRzQXBwbGllZC5maW5kKCcubG95YWx0eS1yb3cnKS5hdHRyKCdzdGF0dXMnKSA9PT0gJ2FwcGxpZWQnKSB7XG5cdFx0XHQkbG95YWx0eVBheW1lbnRDb250YWluZXIuZmluZCgnLnJlbW92ZScpLnRyaWdnZXIoJ0xveWFsdHlDcmVkaXQuUmVtb3ZlJyk7XG5cdFx0fVxuXHRcdHJlc2V0Rm9ybSgpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ21vdXNlZG93bi5Mb3lhbHR5Q3JlZGl0UGF5bWVudFBhbmVsJykub24oJ21vdXNlZG93bi5Mb3lhbHR5Q3JlZGl0UGF5bWVudFBhbmVsJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yICYmICQoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCRsb3lhbHR5UGF5bWVudENvbnRhaW5lcikubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIGxveWFsdHlDcmVkaXRWYWxpZGF0b3IucmVzZXRGb3JtKCk7XG4gICAgICAgICAgICAkbG95YWx0eVBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignTG95YWx0eUNyZWRpdC5DbGVhcicsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRyZXNldEZvcm0oKTtcblx0fSk7XG5cblx0JGxveWFsdHlQYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcucmVzZXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JGxveWFsdHlQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdCRsb3lhbHR5UGhvbmVOdW1iZXJJbnB1dC52YWwoJycpO1xuXHRcdCRsb3lhbHR5WmlwQ29kZUlucHV0LnZhbCgnJyk7XG5cdH0pO1xuXHRcblx0aWYgKCRsb3lhbHR5UGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtbG95YWx0eW51bWJlcicpID09PSAndHJ1ZScgJiYgJGxveWFsdHlQYXltZW50c0FwcGxpZWQuZmluZCgnLmxveWFsdHktcm93JykubGVuZ3RoID09IDAgJiYgJCgnW2NoZWNrb3V0LW1vZGVdJykuYXR0cignY2hlY2tvdXQtbW9kZScpICE9ICdlY2hvJykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0xveWFsdHlDcmVkaXQuQWRkJywgeyBSZWdpc3RlcmVkOiB0cnVlIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlc2V0Rm9ybShzaG93RXJyb3JNZXNzYWdlKSB7XG5cdGlmIChsb3lhbHR5Q3JlZGl0VmFsaWRhdG9yKSB7XG5cdFx0bG95YWx0eUNyZWRpdFZhbGlkYXRvci5yZXNldEZvcm0oKTtcblx0fVxuXHRcblx0aWYgKCFzaG93RXJyb3JNZXNzYWdlKSB7XG5cdFx0JGxveWFsdHlQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0fVxuXHRcblx0dmFyICRsb3lhbHR5Q3JlZGl0Um93ID0gJGxveWFsdHlQYXltZW50c0FwcGxpZWQuZmluZCgnLmxveWFsdHktcm93Jyk7XG5cdGlmICgkbG95YWx0eVBheW1lbnRDb250YWluZXIuYXR0cignaGFzLWxveWFsdHludW1iZXInKSAhPT0gJ3RydWUnKSB7XG5cdFx0JGxveWFsdHlQYXltZW50SW5wdXQudmFsKCcnKTtcblx0XHQkbG95YWx0eVBob25lTnVtYmVySW5wdXQudmFsKCcnKTtcblx0XHQkbG95YWx0eVppcENvZGVJbnB1dC52YWwoJycpO1xuXHRcdFxuXHRcdCRsb3lhbHR5UGF5bWVudHNGb3JtLnNob3coKTtcblx0XHQkbG95YWx0eVBheW1lbnRzQXBwbGllZC5odG1sKCcnKTtcblx0fSBlbHNlIHtcblx0XHQkbG95YWx0eUNyZWRpdFJvdy5maW5kKCcuYmFza2V0TG95YWx0eUFtb3VudCcpLmF0dHIoJ2xhYmVsJywgUmVzb3VyY2VzLkxveWFsdHlDcmVkaXQuUmV3YXJkKTtcblx0fVxuXG5cdHJlc2V0U2Vjb25kYXJ5U2VsZWN0KCk7XG59XG5cbmZ1bmN0aW9uIHJlc2V0U2Vjb25kYXJ5U2VsZWN0KCkge1xuXHQkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlTZWxlY3QucHJvcCgnc2VsZWN0ZWRJbmRleCcsIDApO1xuXHRpZiAoJGxveWFsdHlQYXltZW50U2Vjb25kYXJ5U2VsZWN0LmNsb3Nlc3QoJy5vcGMtc3VtbWFyeScpLmxlbmd0aCA+IDApIHtcblx0XHQkbG95YWx0eVBheW1lbnRTZWNvbmRhcnlTZWxlY3Quc2VsZWN0bWVudSgncmVmcmVzaCcpO1xuXHR9XG5cdCRsb3lhbHR5UGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknLCAnJyk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyICRwYXltZW50Q29udGFpbmVyID0gJCgnW3BheW1lbnQtbWV0aG9kPVwiQjJCX1BheW1lbnRfVm91Y2hlclwiXScpO1xudmFyICRwYXltZW50Rm9ybSA9ICRwYXltZW50Q29udGFpbmVyLmZpbmQoJ2Zvcm0nKTtcbnZhciAkcGF5bWVudFZvdWNoZXJOdW1iZXIgPSAkcGF5bWVudENvbnRhaW5lci5maW5kKCdpbnB1dFtuYW1lPVwicGF5bWVudHZvdWNoZXJjb2RlXCJdJyk7XG52YXIgJHBheW1lbnRNZXNzYWdlID0gJHBheW1lbnRDb250YWluZXIuZmluZCgnLm1lc3NhZ2VzJyk7XG52YXIgJHBheW1lbnRFcnJvck1lc3NhZ2UgPSAkcGF5bWVudENvbnRhaW5lci5maW5kKCdzcGFuLmVycm9yJyk7XG52YXIgJHBheW1lbnRzQXBwbGllZCA9ICRwYXltZW50Q29udGFpbmVyLmZpbmQoJy5mb3JtLXBheW1lbnRzLWFwcGxpZWQnKTtcbnZhciAkcGF5bWVudEFwcGx5QnV0dG9uID0gJHBheW1lbnRDb250YWluZXIuZmluZCgnLmFwcGx5Jyk7XG52YXIgdmFsaWRhdG9yO1xudmFyIHJlY2FwdGNoYTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYSgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJHBheW1lbnRBcHBseUJ1dHRvbi5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBheW1lbnRWb3VjaGVycyAmJiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0cmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ3BheW1lbnQtdm91Y2hlci1hcHBseS1idXR0b24nLCB7XG5cdCAgICAgICAgc2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0ICAgICAgICBjYWxsYmFjazogc3VibWl0UGF5bWVudFZvdWNoZXIsXG5cdCAgICAgICAgYmFkZ2U6ICdib3R0b21sZWZ0J1xuXHQgICAgfSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zUGFyYW1ldGVyKSB7XG5cdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyIHx8IHt9O1xuXG5cdHJlbmRlclJlY2FwdGNoYSgpO1xuXHQkKGRvY3VtZW50KS5vbignUmVjYXB0Y2hhLkxvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRsb2FkZWQuUmVjYXB0Y2hhID0gdHJ1ZTtcblx0ICAgICAgICByZW5kZXJSZWNhcHRjaGEoKTtcblx0ICAgIH1cblx0fSk7XG5cdFxuICAgICRwYXltZW50Q29udGFpbmVyLm9uKCdjbGljaycsICcuYXBwbHk6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFxuICAgICAgICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGF5bWVudFZvdWNoZXJzIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdQYXltZW50Vm91Y2hlci5BcHBseScpO1xuICAgICAgICB9XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ1BheW1lbnRWb3VjaGVyLkFwcGx5JywgZnVuY3Rpb24oZXZlbnQpIHtcdFx0XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgaWYgKHBhcnNlRmxvYXQoJCgnW2JhbGFuY2UtZHVlXScpLmZpcnN0KCkuYXR0cignYmFsYW5jZS1kdWUnKSkgPD0gMCkge1xuICAgICAgICAgICAgJHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuUGF5bWVudFZvdWNoZXIuTm9CYWxhbmNlRHVlKS5zaG93KCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIChyZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQocmVjYXB0Y2hhKTtcblx0XHRcdH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgICAgIHZhbGlkYXRvciA9ICRwYXltZW50Rm9ybS52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgJHBheW1lbnRWb3VjaGVyTnVtYmVyLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUGF5bWVudFZvdWNoZXIuTnVtYmVyKTtcbiAgICAgICAgICAgIHZhbGlkYXRvci5jaGVja0Zvcm0oKTtcblxuICAgICAgICAgICAgaWYgKFVybHMgJiYgVXJscy5QYXltZW50Vm91Y2hlci5BcHBseSAmJiB2YWxpZGF0b3IudmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHZhciByb3dDb250YWluZXJIdG1sID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtcGF5bWVudHZvdWNoZXItcm93LWNvbnRhaW5lcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSgpO1xuICAgICAgICAgICAgICAgIHZhciAkcGF5bWVudEFwcGxpZWQgPSAkKHJvd0NvbnRhaW5lckh0bWwpLmFwcGVuZFRvKCRwYXltZW50c0FwcGxpZWQpO1xuXG4gICAgICAgICAgICAgICAgJHBheW1lbnRBcHBseUJ1dHRvbi5sb2FkaW5nKHtcbiAgICAgICAgICAgICAgICAgICAgSXNJbWFnZVNob3duOiB0cnVlLFxuXHRcdFx0XHRcdElzTGFiZWxTaG93bjogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGxpZWQubG9hZGluZyh7XG4gICAgICAgICAgICAgICAgICAgIExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5QYXltZW50Vm91Y2hlci5BcHBseWluZ1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgIHVybDogVXJscy5QYXltZW50Vm91Y2hlci5BcHBseSxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyOiAkcGF5bWVudFZvdWNoZXJOdW1iZXIudmFsKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBhbW91bnQ6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRwYXltZW50QXBwbGllZC5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudFZvdWNoZXJOdW1iZXIudmFsKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5hbW91bnRBcHBsaWVkICYmIGRhdGEuYW1vdW50QXBwbGllZC52YWx1ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdCRwYXltZW50c0FwcGxpZWQuZmluZCgnW2RhdGEtaWQ9XCInICsgZGF0YS5pZCArICdcIl0nKS5yZW1vdmUoKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBheW1lbnRBcHBsaWVkLmF0dHIoJ2RhdGEtaWQnLCBkYXRhLmlkKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcm93Q29udGVudEh0bWwgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1wYXltZW50dm91Y2hlci1yb3ctY29udGVudCcpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50TnVtYmVyOiBkYXRhLm51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFtb3VudEFwcGxpZWQ6IGRhdGEuYW1vdW50QXBwbGllZC5kaXNwbGF5VmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBheW1lbnRBcHBsaWVkLmh0bWwocm93Q29udGVudEh0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5tZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXHQkcGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEubWVzc2FnZSkuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiAoZGF0YS5tZXNzYWdlID09ICdJbnZhbGlkIE1lc3NhZ2UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdFx0ZGF0YS5tZXNzYWdlID0gUmVzb3VyY2VzLkVycm9yLkdlbmVyaWM7XHRcbiAgICAgICAgICAgICAgICAgICAgICAgIFx0fVxuICAgICAgICAgICAgICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGF5bWVudEFwcGxpZWQucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChkYXRhLm1lc3NhZ2UgfHwgUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuXHRcdFx0XHRcdFx0aWYgKHJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHQkcGF5bWVudEFwcGx5QnV0dG9uLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdCRwYXltZW50QXBwbGllZC5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdCRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYgKHJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZWNhcHRjaGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBcdGlmIChyZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZWNhcHRjaGEpO1xuXHRcdFx0XHR9XHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24ucGF5bWVudFBhbmVsJykub24oJ21vdXNlZG93bi5wYXltZW50UGFuZWwnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKHZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgkcGF5bWVudENvbnRhaW5lcikubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHZhbGlkYXRvci5yZXNldEZvcm0oKTtcbiAgICAgICAgICAgICRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ0NhcnREYXRhLlVwZGF0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuICAgIFx0JCgnW2hhcy1naWZ0LWNhcmRzXScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzJywgZGF0YS5IYXNHaWZ0Q2FyZHMgfHwgZmFsc2UpO1xuXHQgICAgJCgnW2hhcy1naWZ0LWNhcmRzLW9ubHldJykuYXR0cignaGFzLWdpZnQtY2FyZHMtb25seScsIGRhdGEuSGFzR2lmdENhcmRzT25seSB8fCBmYWxzZSk7XG5cdCAgICBcblx0ICAgIGlmIChkYXRhLkhhc0dpZnRDYXJkcyAmJiAhZGF0YS5BbGxvd3B1cmNoYXNlV2l0aEdpZnRDYXJkKSB7XG5cdCAgICBcdCRwYXltZW50TWVzc2FnZS5odG1sKFJlc291cmNlcy5HaWZ0Q2FyZC5wdXJjaGFzZVdpdGhHaWZ0Q2FyZE5vdEFsbG93ZWQpO1xuXHQgICAgXHQkcGF5bWVudENvbnRhaW5lci5hdHRyKCdzdGF0dXMnLCAnbG9ja2VkJyk7XG5cdCAgICB9IGVsc2Uge1xuXHQgICAgXHQkcGF5bWVudE1lc3NhZ2UuaHRtbCgnJyk7XG5cdCAgICBcdCRwYXltZW50Q29udGFpbmVyLmF0dHIoJ3N0YXR1cycsICdhY3RpdmUnKTtcblx0ICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignR2lmdENhcmQuQ2xlYXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICRwYXltZW50c0FwcGxpZWQuaHRtbCgnJyk7XG4gICAgICAgICQoJy5vcmRlci1iYWxhbmNlLWR1ZScpLmh0bWwoJycpO1xuICAgIH0pO1xuXG4gICAgJHBheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5yZW1vdmU6bm90KFtsb2FkaW5nXSknLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB2YXIgJHJvdyA9ICQodGhpcykuY2xvc2VzdCgnLmZvcm0tcGF5bWVudC1hcHBsaWVkJyk7XG4gICAgICAgICRyb3cubG9hZGluZyh7XG4gICAgICAgICAgICBMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuR2lmdENhcmQuUmVtb3ZpbmdcbiAgICAgICAgfSk7XG4gICAgICAgICRwYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsIDogVXJscy5QYXltZW50Vm91Y2hlci5SZW1vdmUsXG4gICAgICAgICAgICB0eXBlIDogJ1BPU1QnLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICBpZDogJHJvdy5kYXRhKCdpZCcpXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGRhdGFUeXBlIDogJ2pzb24nLFxuICAgICAgICAgICAgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIFx0JHJvdy5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICBcdFxuICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgJHJvdy5yZW1vdmUoKTtcblxuICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgXHQkcGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEuZXJyb3IgfHwgUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkcm93LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0JHBheW1lbnRFcnJvck1lc3NhZ2UuaHRtbChSZXNvdXJjZXMuRXJyb3IuR2VuZXJpYykuc2hvdygpO1xuXHRcdFx0fVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cbiIsIid1c2Ugc3RyaWN0Jztcbi8qIGdsb2JhbCBSZXNvdXJjZXMsIFVybHMgKi9cblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG52YXIgVmFsaWRhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2Uvc2NyaXB0cy91dGlsL1ZhbGlkYXRpb25IZWxwZXInKTtcbnZhciBWYWxpZGF0aW9uUnVsZXMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1ZhbGlkYXRpb25Db25zdGFudHMnKS5SdWxlcztcbnZhciBvcGNwYXltZW50ID0gcmVxdWlyZSgnLi9vcGNwYXltZW50Jyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuZXhwb3J0cy5pbml0aWFsaXplID0gaW5pdGlhbGl6ZTtcblxudmFyICRyZXdhcmRzUGF5bWVudENvbnRhaW5lciA9ICQoJ1twYXltZW50LW1ldGhvZD1cIlJFV0FSRFNfQ1JFRElUXCJdW2hhcy1yZXdhcmRzbnVtYmVyXScpO1xudmFyICRyZXdhcmRzUGF5bWVudHNGb3JtID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJ2Zvcm0nKTtcbnZhciAkcmV3YXJkc1BheW1lbnRzQXBwbGllZCA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcucmV3YXJkcy1hcHBsaWVkJyk7XG52YXIgJHJld2FyZHNQYXltZW50SW5wdXQgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJyk7XG52YXIgJHJld2FyZHNFbWFpbElucHV0ID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc0VtYWlsJyk7XG52YXIgJHJld2FyZHNQaG9uZU51bWJlcklucHV0ID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc1Bob25lTnVtYmVyJyk7XG52YXIgJHJld2FyZHNaaXBDb2RlSW5wdXQgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzWmlwQ29kZScpO1xudmFyICRyZXdhcmRzUGF5bWVudFNlY29uZGFyeUNvbnRhaW5lciA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCcucmV3YXJkcy1zZWNvbmRhcnknKTtcbnZhciAkcmV3YXJkc1BheW1lbnRTZWNvbmRhcnlTZWxlY3QgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnI3Jld2FyZHMtc2Vjb25kYXJ5LXNlbGVjdCcpO1xudmFyICRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZSA9ICRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5maW5kKCdzcGFuLmVycm9yJyk7XG52YXIgcmV3YXJkc0NyZWRpdFZhbGlkYXRvcjtcbnZhciByZXdhcmRzQ3JlZGl0Um93VGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1yZXdhcmRzLWNyZWRpdC1yb3cnKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG52YXIgcmV3YXJkc0NyZWRpdFJlY2FwdGNoYTtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cbmZ1bmN0aW9uIHJlbmRlclJlY2FwdGNoYSgpIHtcblx0aWYgKGxvYWRlZC5SZWNhcHRjaGEgJiYgJCgnI3Jld2FyZHMtY3JlZGl0LWFkZC1idXR0b24nKS5sZW5ndGggPiAwICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclJld2FyZHNDcmVkaXQgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdHJld2FyZHNDcmVkaXRSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcigncmV3YXJkcy1jcmVkaXQtYWRkLWJ1dHRvbicsIHtcblx0ICAgICAgICBzaXRla2V5OiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgIGNhbGxiYWNrOiBzdWJtaXRSZXdhcmRzQ3JlZGl0LFxuXHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0ICAgIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemUob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlciB8fCB7fTtcblx0XG5cdHJlbmRlclJlY2FwdGNoYSgpO1xuXHQkKGRvY3VtZW50KS5vbignUmVjYXB0Y2hhLkxvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRsb2FkZWQuUmVjYXB0Y2hhID0gdHJ1ZTtcblx0ICAgICAgICByZW5kZXJSZWNhcHRjaGEoKTtcblx0ICAgIH1cblx0fSk7XG5cblx0aWYgKCRyZXdhcmRzUGF5bWVudFNlY29uZGFyeVNlbGVjdC5jbG9zZXN0KCcub3BjLXN1bW1hcnknKS5sZW5ndGggPiAwKSB7XG5cdFx0JHJld2FyZHNQYXltZW50U2Vjb25kYXJ5U2VsZWN0LnNlbGVjdG1lbnUoe1xuXHRcdFx0d2lkdGg6ICcxMDAlJyxcblx0XHRcdGFwcGVuZFRvOiAnW3BheW1lbnQtbWV0aG9kPVwiUkVXQVJEU19DUkVESVRcIl0gLnJld2FyZHMtc2Vjb25kYXJ5Jyxcblx0XHRcdGNoYW5nZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdCRyZXdhcmRzUGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknLCB1aSAmJiB1aS5pdGVtICYmIHVpLml0ZW0udmFsdWUgPyB1aS5pdGVtLnZhbHVlIDogJycpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdFxuXHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5yZXNldCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRyZXNldFNlY29uZGFyeVNlbGVjdCgpO1xuXHR9KTtcblxuXHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5hZGQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG4gICAgICAgIGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5SZWNhcHRjaGEgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JSZXdhcmRzQ3JlZGl0IHx8ICFvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdSZXdhcmRzQ3JlZGl0LkFkZCcpOyBcbiAgICAgICAgfVxuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdSZXdhcmRzQ3JlZGl0LkFkZCcsIGZ1bmN0aW9uKGV2ZW50LCBkYXRhKSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdGlmIChwYXJzZUZsb2F0KCQoJ1tiYWxhbmNlLWR1ZV0nKS5maXJzdCgpLmF0dHIoJ2JhbGFuY2UtZHVlJykpIDw9IDApIHtcblx0XHRcdCRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5SZXdhcmRzQ3JlZGl0Lk5vQmFsYW5jZUR1ZSkuc2hvdygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgcmV3YXJkc1NlY29uZGFyeUZhY3RvciA9ICRyZXdhcmRzUGF5bWVudFNlY29uZGFyeUNvbnRhaW5lci5hdHRyKCdzZWNvbmRhcnknKTtcblx0XHRcdHJld2FyZHNDcmVkaXRWYWxpZGF0b3IgPSAkcmV3YXJkc1BheW1lbnRzRm9ybS52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgJHJld2FyZHNQYXltZW50SW5wdXQucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXdhcmRzQ3JlZGl0Lk51bWJlcik7XG5cblx0XHRcdHN3aXRjaCAocmV3YXJkc1NlY29uZGFyeUZhY3Rvcikge1xuXHRcdFx0XHRjYXNlIFwiemlwY29kZVwiOlxuXHRcdFx0XHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnemlwQ29kZScsIFZhbGlkYXRpb25IZWxwZXIuVmFsaWRhdGVaaXBDb2RlLCBSZXNvdXJjZXMuSU5WQUxJRF9QT1NUQUxfQ09ERSk7XG5cdFx0XHRcdFx0JHJld2FyZHNaaXBDb2RlSW5wdXQucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5aaXBDb2RlKTtcblx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG4gICAgICAgICAgICByZXdhcmRzQ3JlZGl0VmFsaWRhdG9yLmZvcm0oKTtcblxuXHRcdFx0Ly8gQWRkaW5nIEFEQSBjb21wbGlhbmNlIGVycm9yIG1lc3NhZ2VzIGZvciBnaWZ0Q2FyZFBheW1lbnQgc2VjdGlvblxuICAgICAgICAgICAgaWYgKCRyZXdhcmRzUGF5bWVudHNGb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JCgnLnBheW1lbnQtZGVjbGluZWQnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB2YXIgcmV3YXJkc1BheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyA9IG9wY3BheW1lbnQuZ2V0RXJyb3JNZXNzYWdlcygkcmV3YXJkc1BheW1lbnRzRm9ybSk7XG4gICAgICAgICAgICAgICAgdmFyIHJld2FyZHNQYXltZW50Rm9ybUVycm9yQm94ID0gb3BjcGF5bWVudC5lcnJvckJveCgnQ2Fubm90IFByb2NlZWQnLCAnUGxlYXNlIGZpeCB0aGUgZm9sbG93aW5nIGVycm9yczonLCByZXdhcmRzUGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcbiAgICAgICAgICAgICAgICBpZiAocmV3YXJkc1BheW1lbnRGb3JtRXJyb3JCb3gpIHtcbiAgICAgICAgICAgICAgICAgICAgJHJld2FyZHNQYXltZW50c0FwcGxpZWQuYWZ0ZXIocmV3YXJkc1BheW1lbnRGb3JtRXJyb3JCb3gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblx0XHRcdFxuICAgICAgICAgICAgaWYgKFVybHMgJiYgVXJscy5jaGVja1Jld2FyZHMgJiYgcmV3YXJkc0NyZWRpdFZhbGlkYXRvci52YWxpZCgpKSB7XG4gICAgICAgICAgICBcdCRyZXdhcmRzUGF5bWVudHNGb3JtLmhpZGUoKTtcbiAgICAgICAgICAgIFx0XG5cdFx0XHRcdHZhciAkcmV3YXJkc0NyZWRpdFJvdyA9ICQocmV3YXJkc0NyZWRpdFJvd1RlbXBsYXRlKCkpO1xuXHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdyA9ICRyZXdhcmRzQ3JlZGl0Um93LmFwcGVuZFRvKCRyZXdhcmRzUGF5bWVudHNBcHBsaWVkKTtcblx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuYXR0cignc3RhdHVzJywgJ3BlbmRpbmcnKTtcblx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZE51bWJlcicpLmh0bWwodXRpbC5nZXRNYXNrZWROdW1iZXIoJHJld2FyZHNQYXltZW50SW5wdXQudmFsKCksIDQsICd4eHh4Li4uICcpKTtcblx0XG5cdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKHtJc0xhYmVsU2hvd246IGZhbHNlfSk7XG5cdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZyh7TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLlJld2FyZHNDcmVkaXQuTG9hZGluZ30pO1xuXHRcblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR1cmw6IGRhdGEgJiYgZGF0YS5SZWdpc3RlcmVkID8gVXJscy5jaGVja1Jld2FyZHNGb3JSZWdpc3RlcmVkIDogVXJscy5jaGVja1Jld2FyZHMsXG5cdFx0XHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdGNzcmZfdG9rZW46ICAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdHJld2FyZHNOdW1iZXI6ICRyZXdhcmRzUGF5bWVudElucHV0LnZhbCgpLFxuXHRcdFx0XHRcdFx0cmV3YXJkc0VtYWlsOiAkcmV3YXJkc0VtYWlsSW5wdXQudmFsKCksXG5cdFx0XHRcdFx0XHRyZXdhcmRzUGhvbmVOdW1iZXI6ICRyZXdhcmRzUGhvbmVOdW1iZXJJbnB1dC52YWwoKSxcblx0XHRcdFx0XHRcdHJld2FyZHNaaXBDb2RlOiAkcmV3YXJkc1ppcENvZGVJbnB1dC52YWwoKVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXHRcblx0XHRcdFx0XHRcdGlmICgkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHRpZiAoZGF0YSAmJiBkYXRhLmVycm9yICE9PSAndW5kZWZpbmVkJyAmJiBkYXRhLmVycm9yID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKGRhdGEuZXJyb3JNc2cpLnNob3coKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoZGF0YSAmJiBwYXJzZUZsb2F0KGRhdGEuY3JlZGl0QW1vdW50KSA8PSAwKSB7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtcmV3YXJkc251bWJlcicsICd0cnVlJyk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdtZXNzYWdlJyk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5tZXNzYWdlJykuaHRtbChSZXNvdXJjZXMuUmV3YXJkc0NyZWRpdC5Ob0JhbGFuY2VBdmFpbGFibGUpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhICYmIGRhdGEuY3JlZGl0QW1vdW50Rm9ybWF0dGVkKSB7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtcmV3YXJkc251bWJlcicsICd0cnVlJyk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5iYXNrZXRSZXdhcmRBbW91bnQnKS5odG1sKGRhdGEuY3JlZGl0QW1vdW50Rm9ybWF0dGVkLnJlcGxhY2UoJy4wMCcsICcnKSk7XG5cdFx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5leHBpcmF0aW9uLWRhdGUnKS5odG1sKGRhdGEuY3JlZGl0RXhwaXJhdGlvbkRhdGUpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRpZiAocmV3YXJkc0NyZWRpdFJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChyZXdhcmRzQ3JlZGl0UmVjYXB0Y2hhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0JHJld2FyZHNQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdFx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYgKHJld2FyZHNDcmVkaXRSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQocmV3YXJkc0NyZWRpdFJlY2FwdGNoYSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAzMDIgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG4gICAgICAgICAgICB9XG5cdFx0fVxuXHR9KTtcblxuXHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5hcHBseScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkcmV3YXJkc0NyZWRpdFJvdyA9ICQodGhpcykuY2xvc2VzdCgnLnJld2FyZC1yb3cnKTtcblxuXHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKHtJc0xhYmVsU2hvd246IGZhbHNlfSk7XG5cdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKHtMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuUmV3YXJkc0NyZWRpdC5BcHBseWluZ30pO1xuXG5cdFx0JC5hamF4KHtcblx0XHRcdHVybDogVXJscy5hcHBseVJld2FyZHMsXG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRkYXRhOiB7XG5cdFx0XHRcdGNzcmZfdG9rZW46ICAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnaW5wdXRbbmFtZT1cImNzcmZfdG9rZW5cIl0nKS52YWwoKSxcblx0XHRcdFx0cmV3YXJkc051bWJlcjogJHJld2FyZHNQYXltZW50SW5wdXQudmFsKCksXG5cdFx0XHRcdHJld2FyZHNFbWFpbDogJHJld2FyZHNFbWFpbElucHV0LnZhbCgpLFxuXHRcdFx0XHRyZXdhcmRzUGhvbmVOdW1iZXI6ICRyZXdhcmRzUGhvbmVOdW1iZXJJbnB1dC52YWwoKSxcblx0XHRcdFx0cmV3YXJkc1ppcENvZGU6ICRyZXdhcmRzWmlwQ29kZUlucHV0LnZhbCgpXG5cdFx0XHR9LFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG5bbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoJHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHNbbG9hZGluZ10nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmZvcm0tY29udHJvbHMnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoZGF0YS5lcnJvciAhPT0gJ3VuZGVmaW5lZCcgJiYgZGF0YS5lcnJvciA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdtZXNzYWdlJyk7XG5cdFx0XHRcdFx0JHJld2FyZHNQYXltZW50SW5wdXQudmFsKCcnKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5yZW1vdmUoKTtcblx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRzRm9ybS5zaG93KCk7XG5cdFx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoZGF0YS5lcnJvck1zZykuc2hvdygpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdhcHBsaWVkJyk7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZE51bWJlcicpLmh0bWwodXRpbC5nZXRNYXNrZWROdW1iZXIoZGF0YS5yZXdhcmRzTnVtYmVyLCA0LCAneHh4eC4uLiAnKSk7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZEFtb3VudCcpLmh0bWwoZGF0YS5yZXdhcmRzQ3JlZGl0VXNlZEZvcm1hdHRlZCkuYXR0cignbGFiZWwnLCBSZXNvdXJjZXMuUmV3YXJkc0NyZWRpdC5SZXdhcmRBcHBsaWVkKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZXhwaXJhdGlvbi1kYXRlJykuaHRtbChkYXRhLmNyZWRpdEV4cGlyYXRpb25EYXRlKTtcblxuXHRcdFx0XHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0XHRcdFx0dmFsdWU6IGRhdGEucmV3YXJkc0NyZWRpdFVzZWQsXG5cdFx0XHRcdFx0XHRwYXltZW50X3R5cGU6ICdCIFJld2FyZGVkJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdBZGRQYXltZW50SW5mbycsIGRhdGFPYmplY3QpO1xuXHRcdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJyk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdtZXNzYWdlJyk7XG5cdFx0XHRcdCRyZXdhcmRzUGF5bWVudEVycm9yTWVzc2FnZS5odG1sKFJlc291cmNlcy5FcnJvci5HZW5lcmljKS5zaG93KCk7XG5cdFx0XHRcdHJlc2V0Rm9ybSh0cnVlKTtcblx0XHRcdH0sXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdFx0aWYgKGRhdGEuc3RhdHVzID09IDMwMiAmJiBkYXRhLnJlc3BvbnNlVGV4dCkge1xuXHRcdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSBkYXRhLnJlc3BvbnNlVGV4dDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIub24oJ2NsaWNrIFJld2FyZHNDcmVkaXQuUmVtb3ZlJywgJy5yZW1vdmUnLCBmdW5jdGlvbihldmVudCwgZGF0YSkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHJld2FyZHNDcmVkaXRSb3cgPSAkKHRoaXMpLmNsb3Nlc3QoJy5yZXdhcmQtcm93Jyk7XG5cdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJ0bicpLmxvYWRpbmcoe0lzTGFiZWxTaG93bjogZmFsc2V9KTtcblx0XHQkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuZm9ybS1jb250cm9scycpLmxvYWRpbmcoe0xhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5SZXdhcmRzQ3JlZGl0LlJlbW92aW5nfSk7XG5cblx0XHR2YXIgcGF5bG9hZCA9IHtcblx0XHRcdHJld2FyZHNOdW1iZXI6ICQoJ2lucHV0I2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzTnVtYmVyJykudmFsKClcblx0XHR9XG5cblx0XHRpZiAoZGF0YSAmJiBkYXRhLlJlc2V0U2Vzc2lvbkRhdGEpIHtcblx0XHRcdHBheWxvYWQucmVzZXRTZXNzaW9uRGF0YSA9IHRydWVcblx0XHR9XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLnJlbW92ZVJld2FyZHMsXG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkcmV3YXJkc1BheW1lbnRFcnJvck1lc3NhZ2UuaHRtbCgnJykuaGlkZSgpO1xuXG5cdFx0XHRcdGlmICgkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtcmV3YXJkc251bWJlcicpICE9PSAndHJ1ZScpIHtcblx0XHRcdFx0XHQkcmV3YXJkc1BheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudHNGb3JtLnNob3coKTtcblx0XHRcdFx0XHQkcmV3YXJkc0NyZWRpdFJvdy5hdHRyKCdzdGF0dXMnLCAnZm9ybScpO1xuXHRcdFx0XHRcdCRyZXdhcmRzUGF5bWVudHNBcHBsaWVkLmh0bWwoJycpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmF0dHIoJ3N0YXR1cycsICdwZW5kaW5nJyk7XG5cdFx0XHRcdFx0JHJld2FyZHNDcmVkaXRSb3cuZmluZCgnLmJhc2tldFJld2FyZEFtb3VudCcpLmF0dHIoJ2xhYmVsJywgUmVzb3VyY2VzLlJld2FyZHNDcmVkaXQuUmV3YXJkKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdH0sXG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICgkcmV3YXJkc0NyZWRpdFJvdy5maW5kKCcuYnRuW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5idG4nKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzW2xvYWRpbmddJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5mb3JtLWNvbnRyb2xzJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoUmVzb3VyY2VzLkVycm9yLkdlbmVyaWMpLnNob3coKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdFxuXHQkcmV3YXJkc1BheW1lbnRDb250YWluZXIub24oJ2NsaWNrJywgJy5jaGFuZ2UnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0JHJld2FyZHNQYXltZW50Q29udGFpbmVyLmF0dHIoJ2hhcy1yZXdhcmRzbnVtYmVyJywgJ2ZhbHNlJyk7XG5cdFx0aWYgKCRyZXdhcmRzUGF5bWVudHNBcHBsaWVkLmZpbmQoJy5yZXdhcmQtcm93JykuYXR0cignc3RhdHVzJykgPT09ICdhcHBsaWVkJykge1xuXHRcdFx0JHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJy5yZW1vdmUnKS50cmlnZ2VyKCdSZXdhcmRzQ3JlZGl0LlJlbW92ZScpO1xuXHRcdH1cblx0XHRyZXNldEZvcm0oKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdtb3VzZWRvd24uUmV3YXJkc0NyZWRpdFBheW1lbnRQYW5lbCcpLm9uKCdtb3VzZWRvd24uUmV3YXJkc0NyZWRpdFBheW1lbnRQYW5lbCcsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAocmV3YXJkc0NyZWRpdFZhbGlkYXRvciAmJiAkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgkcmV3YXJkc1BheW1lbnRDb250YWluZXIpLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICByZXdhcmRzQ3JlZGl0VmFsaWRhdG9yLnJlc2V0Rm9ybSgpO1xuICAgICAgICAgICAgJHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ1Jld2FyZHNDcmVkaXQuQ2xlYXInLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0cmVzZXRGb3JtKCk7XG5cdH0pO1xuXG5cdCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5vbignY2xpY2snLCAnLnJlc2V0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdCRyZXdhcmRzUGF5bWVudHNGb3JtLnNob3coKTtcblx0XHQkcmV3YXJkc1Bob25lTnVtYmVySW5wdXQudmFsKCcnKTtcblx0XHQkcmV3YXJkc1ppcENvZGVJbnB1dC52YWwoJycpO1xuXHR9KTtcblx0XG5cdGlmICgkcmV3YXJkc1BheW1lbnRDb250YWluZXIuYXR0cignaGFzLXJld2FyZHNudW1iZXInKSA9PT0gJ3RydWUnICYmICRyZXdhcmRzUGF5bWVudHNBcHBsaWVkLmZpbmQoJy5yZXdhcmQtcm93JykubGVuZ3RoID09IDAgJiYgJCgnW2NoZWNrb3V0LW1vZGVdJykuYXR0cignY2hlY2tvdXQtbW9kZScpICE9ICdlY2hvJykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Jld2FyZHNDcmVkaXQuQWRkJywgeyBSZWdpc3RlcmVkOiB0cnVlIH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlc2V0Rm9ybShzaG93RXJyb3JNZXNzYWdlKSB7XG5cdGlmIChyZXdhcmRzQ3JlZGl0VmFsaWRhdG9yKSB7XG5cdFx0cmV3YXJkc0NyZWRpdFZhbGlkYXRvci5yZXNldEZvcm0oKTtcblx0fVxuXHRcblx0aWYgKCFzaG93RXJyb3JNZXNzYWdlKSB7XG5cdFx0JHJld2FyZHNQYXltZW50RXJyb3JNZXNzYWdlLmh0bWwoJycpLmhpZGUoKTtcblx0fVxuXHRcblx0dmFyICRyZXdhcmRzQ3JlZGl0Um93ID0gJHJld2FyZHNQYXltZW50c0FwcGxpZWQuZmluZCgnLnJld2FyZC1yb3cnKTtcblx0aWYgKCRyZXdhcmRzUGF5bWVudENvbnRhaW5lci5hdHRyKCdoYXMtcmV3YXJkc251bWJlcicpICE9PSAndHJ1ZScpIHtcblx0XHQkcmV3YXJkc1BheW1lbnRJbnB1dC52YWwoJycpO1xuXHRcdCRyZXdhcmRzUGhvbmVOdW1iZXJJbnB1dC52YWwoJycpO1xuXHRcdCRyZXdhcmRzWmlwQ29kZUlucHV0LnZhbCgnJyk7XG5cdFx0XG5cdFx0JHJld2FyZHNQYXltZW50c0Zvcm0uc2hvdygpO1xuXHRcdCRyZXdhcmRzUGF5bWVudHNBcHBsaWVkLmh0bWwoJycpO1xuXHR9IGVsc2Uge1xuXHRcdCRyZXdhcmRzQ3JlZGl0Um93LmZpbmQoJy5iYXNrZXRSZXdhcmRBbW91bnQnKS5hdHRyKCdsYWJlbCcsIFJlc291cmNlcy5SZXdhcmRzQ3JlZGl0LlJld2FyZCk7XG5cdH1cblxuXHRyZXNldFNlY29uZGFyeVNlbGVjdCgpO1xufVxuXG5mdW5jdGlvbiByZXNldFNlY29uZGFyeVNlbGVjdCgpIHtcblx0JHJld2FyZHNQYXltZW50U2Vjb25kYXJ5U2VsZWN0LnByb3AoJ3NlbGVjdGVkSW5kZXgnLCAwKTtcblx0aWYgKCRyZXdhcmRzUGF5bWVudFNlY29uZGFyeVNlbGVjdC5jbG9zZXN0KCcub3BjLXN1bW1hcnknKS5sZW5ndGggPiAwKSB7XG5cdFx0JHJld2FyZHNQYXltZW50U2Vjb25kYXJ5U2VsZWN0LnNlbGVjdG1lbnUoJ3JlZnJlc2gnKTtcblx0fVxuXHQkcmV3YXJkc1BheW1lbnRTZWNvbmRhcnlDb250YWluZXIuYXR0cignc2Vjb25kYXJ5JywgJycpO1xufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG52YXIgc2hpcHBpbmcgPSByZXF1aXJlKCcuL3NoaXBwaW5nJyk7XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gU2VsZWN0cyB0aGUgZmlyc3QgYWRkcmVzcyBmcm9tIHRoZSBsaXN0IG9mIGFkZHJlc3Nlc1xuICovXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRmb3JtID0gJCgnLmFkZHJlc3MnKTtcbiAgICAvLyBzZWxlY3QgYWRkcmVzcyBmcm9tIGxpc3RcbiAgICAkKCdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0xpc3RcIl0nLCAkZm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoc2VsZWN0ZWQpLmRhdGEoJ2FkZHJlc3MnKTtcbiAgICAgICAgaWYgKCFzZWxlY3RlZEFkZHJlc3MpIHsgcmV0dXJuOyB9XG4gICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCAkZm9ybSk7XG4gICAgICAgIHNoaXBwaW5nLnVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgpO1xuICAgICAgICAvLyByZS12YWxpZGF0ZSB0aGUgZm9ybVxuICAgICAgICAkZm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpO1xudmFyIGZvcm1QcmVwYXJlID0gcmVxdWlyZSgnLi9mb3JtUHJlcGFyZScpO1xudmFyIGdpZnRjYXJkID0gcmVxdWlyZSgnLi4vLi4vZ2lmdGNhcmQnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG52YXIgUGF5bWVudE1ldGhvZENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvUGF5bWVudEluc3RydW1lbnRDb25zdGFudHMnKS5QYXltZW50TWV0aG9kcztcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBGaWxscyB0aGUgQ3JlZGl0IENhcmQgZm9ybSB3aXRoIHRoZSBwYXNzZWQgZGF0YS1wYXJhbWV0ZXIgYW5kIGNsZWFycyB0aGUgZm9ybWVyIGN2biBpbnB1dFxuICogQHBhcmFtIHtPYmplY3R9IGRhdGEgVGhlIENyZWRpdCBDYXJkIGRhdGEgKGhvbGRlciwgdHlwZSwgbWFza2VkIG51bWJlciwgZXhwaXJhdGlvbiBtb250aC95ZWFyKVxuICovXG5mdW5jdGlvbiBzZXRDQ0ZpZWxkcyhkYXRhKSB7XG4gICAgdmFyICRjcmVkaXRDYXJkID0gJCgnW2RhdGEtbWV0aG9kPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCArICdcIl0nKTtcbiAgICAkY3JlZGl0Q2FyZC5maW5kKCdpbnB1dFtuYW1lJD1cImNyZWRpdENhcmRfb3duZXJcIl0nKS52YWwoZGF0YS5ob2xkZXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICRjcmVkaXRDYXJkLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl90eXBlXCJdJykudmFsKGRhdGEudHlwZSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF9udW1iZXJcIl0nKS52YWwoZGF0YS5tYXNrZWROdW1iZXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICRjcmVkaXRDYXJkLmZpbmQoJ1tuYW1lJD1cIl9tb250aFwiXScpLnZhbChkYXRhLmV4cGlyYXRpb25Nb250aCkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnW25hbWUkPVwiX3llYXJcIl0nKS52YWwoZGF0YS5leHBpcmF0aW9uWWVhcikudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnaW5wdXRbbmFtZSQ9XCJfY3ZuXCJdJykudmFsKCcnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIHRoZSBjcmVkaXQgY2FyZCBmb3JtIHdpdGggdGhlIGF0dHJpYnV0ZXMgb2YgYSBnaXZlbiBjYXJkXG4gKiBAcGFyYW0ge1N0cmluZ30gY2FyZElEIHRoZSBjcmVkaXQgY2FyZCBJRCBvZiBhIGdpdmVuIGNhcmRcbiAqL1xuZnVuY3Rpb24gcG9wdWxhdGVDcmVkaXRDYXJkRm9ybShjYXJkSUQpIHtcbiAgICAvLyBsb2FkIGNhcmQgZGV0YWlsc1xuICAgIHZhciB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoVXJscy5iaWxsaW5nU2VsZWN0Q0MsICdjcmVkaXRDYXJkVVVJRCcsIGNhcmRJRCk7XG4gICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5DQ19MT0FEX0VSUk9SKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXRDQ0ZpZWxkcyhkYXRhKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5cbmZ1bmN0aW9uIHBvcHVsYXRlUHJpdmF0ZUxhYmVsQ2FyZEZvcm0oY2FyZElEKSB7XG4gICAgLy8gbG9hZCBjYXJkIGRldGFpbHNcbiAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMuYmlsbGluZ1NlbGVjdFByaXZhdGVMYWJlbCwgJ2NyZWRpdENhcmRVVUlEJywgY2FyZElEKTtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkNDX0xPQURfRVJST1IpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciAkcHJpdmF0ZUxhYmVsQ2FyZCA9ICQoJ1tkYXRhLW1ldGhvZD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkFsbGlhbmNlRGF0YSArICdcIl0nKTtcbiAgICAgICAgICAgICRwcml2YXRlTGFiZWxDYXJkLmZpbmQoJ2lucHV0W25hbWUqPVwiX3ByaXZhdGVMYWJlbENyZWRpdF9udW1iZXJcIl0nKS52YWwoZGF0YS5tYXNrZWROdW1iZXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBDaGFuZ2VzIHRoZSBwYXltZW50IG1ldGhvZCBmb3JtIGRlcGVuZGluZyBvbiB0aGUgcGFzc2VkIHBheW1lbnRNZXRob2RJRFxuICogQHBhcmFtIHtTdHJpbmd9IHBheW1lbnRNZXRob2RJRCB0aGUgSUQgb2YgdGhlIHBheW1lbnQgbWV0aG9kLCB0byB3aGljaCB0aGUgcGF5bWVudCBtZXRob2QgZm9ybSBzaG91bGQgYmUgY2hhbmdlZCB0b1xuICovXG5mdW5jdGlvbiB1cGRhdGVQYXltZW50TWV0aG9kKHBheW1lbnRNZXRob2RJRCkge1xuICAgIHZhciAkcGF5bWVudE1ldGhvZHMgPSAkKCcucGF5bWVudC1tZXRob2QnKTtcbiAgICAkcGF5bWVudE1ldGhvZHMucmVtb3ZlQ2xhc3MoJ3BheW1lbnQtbWV0aG9kLWV4cGFuZGVkJyk7XG5cbiAgICB2YXIgJHNlbGVjdGVkUGF5bWVudE1ldGhvZCA9ICRwYXltZW50TWV0aG9kcy5maWx0ZXIoJ1tkYXRhLW1ldGhvZD1cIicgKyBwYXltZW50TWV0aG9kSUQgKyAnXCJdJyk7XG4gICAgaWYgKCRzZWxlY3RlZFBheW1lbnRNZXRob2QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICRzZWxlY3RlZFBheW1lbnRNZXRob2QgPSAkKCdbZGF0YS1tZXRob2Q9XCJDdXN0b21cIl0nKTtcbiAgICB9XG4gICAgJHNlbGVjdGVkUGF5bWVudE1ldGhvZC5hZGRDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKTtcblxuICAgIC8vIGVuc3VyZSBjaGVja2JveCBvZiBwYXltZW50IG1ldGhvZCBpcyBjaGVja2VkXG4gICAgJCgnaW5wdXRbbmFtZSQ9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS5yZW1vdmVBdHRyKCdjaGVja2VkJyk7XG4gICAgJCgnaW5wdXRbdmFsdWU9JyArIHBheW1lbnRNZXRob2RJRCArICddJykucHJvcCgnY2hlY2tlZCcsICdjaGVja2VkJyk7XG5cbiAgICBmb3JtUHJlcGFyZS52YWxpZGF0ZUZvcm0oKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBsb2FkcyBiaWxsaW5nIGFkZHJlc3MsIEdpZnQgQ2VydGlmaWNhdGVzLCBDb3Vwb24gYW5kIFBheW1lbnQgbWV0aG9kc1xuICovXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRjaGVja291dEZvcm0gPSAkKCcuY2hlY2tvdXQtYmlsbGluZycpO1xuICAgIHZhciAkYWRkR2lmdENlcnQgPSAkKCcjYWRkLWdpZnRjZXJ0Jyk7XG4gICAgdmFyICRnaWZ0Q2VydENvZGUgPSAkKCdpbnB1dFtuYW1lJD1cIl9naWZ0Q2VydENvZGVcIl0nKTtcbiAgICB2YXIgJGFkZENvdXBvbiA9ICQoJyNhZGQtY291cG9uJyk7XG4gICAgdmFyICRjb3Vwb25Db2RlID0gJCgnaW5wdXRbbmFtZSQ9XCJfY291cG9uQ29kZVwiXScpO1xuICAgIHZhciAkc2VsZWN0UGF5bWVudE1ldGhvZCA9ICQoJy5wYXltZW50LW1ldGhvZC1vcHRpb25zJyk7XG4gICAgdmFyIHNlbGVjdGVkUGF5bWVudE1ldGhvZCA9ICRzZWxlY3RQYXltZW50TWV0aG9kLmZpbmQoJzpjaGVja2VkJykudmFsKCk7XG5cbiAgICBmb3JtUHJlcGFyZS5pbml0KHtcbiAgICAgICAgZm9ybVNlbGVjdG9yOiAnZm9ybVtpZCQ9XCJiaWxsaW5nXCJdJyxcbiAgICAgICAgY29udGludWVTZWxlY3RvcjogJ1tuYW1lJD1cImJpbGxpbmdfc2F2ZVwiXSdcbiAgICB9KTtcblxuICAgIC8vIGRlZmF1bHQgcGF5bWVudCBtZXRob2QgdG8gJ0NSRURJVF9DQVJEJ1xuICAgIHVwZGF0ZVBheW1lbnRNZXRob2QoKHNlbGVjdGVkUGF5bWVudE1ldGhvZCkgPyBzZWxlY3RlZFBheW1lbnRNZXRob2QgOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQpO1xuICAgICRzZWxlY3RQYXltZW50TWV0aG9kLm9uKCdjbGljaycsICdpbnB1dFt0eXBlPVwicmFkaW9cIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHVwZGF0ZVBheW1lbnRNZXRob2QoJCh0aGlzKS52YWwoKSk7XG4gICAgfSk7XG5cbiAgICAvLyBzZWxlY3QgY3JlZGl0IGNhcmQgZnJvbSBsaXN0XG4gICAgdmFyICRjcmVkaXRDYXJkTGlzdCA9ICQoJyNjcmVkaXRDYXJkTGlzdCcpO1xuICAgICRjcmVkaXRDYXJkTGlzdC5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2FyZFVVSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoIWNhcmRVVUlEKSB7cmV0dXJuO31cbiAgICAgICAgcG9wdWxhdGVDcmVkaXRDYXJkRm9ybShjYXJkVVVJRCk7XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNlcnZlciBzaWRlIGVycm9yXG4gICAgICAgICQoJy5yZXF1aXJlZC5lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgICAgICAkKCcuZXJyb3ItbWVzc2FnZScpLnJlbW92ZSgpO1xuICAgIH0pO1xuICAgIFxuICAgIC8vcHJlc2VsZWN0IGRlZmF1bHQgY3JlZGl0IGNhcmRcbiAgICBpZigkY3JlZGl0Q2FyZExpc3QubGVuZ3RoID4gMCl7XG5cdFx0JGNyZWRpdENhcmRMaXN0LmZpbmQoJ29wdGlvbicpLmVxKDEpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0JGNyZWRpdENhcmRMaXN0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9XG5cbiAgICBcbiAgICAvLyBzZWxlY3QgcHJpdmF0ZSBsYWJlbCBjYXJkIGZyb20gbGlzdFxuICAgIHZhciAkcHJpdmF0ZUxhYmVsQ2FyZExpc3QgPSAkKCcjcHJpdmF0ZUxhYmVsQ2FyZExpc3QnKTtcbiAgICAkcHJpdmF0ZUxhYmVsQ2FyZExpc3Qub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhcmRVVUlEID0gJCh0aGlzKS52YWwoKTtcbiAgICAgICAgaWYgKCFjYXJkVVVJRCkge3JldHVybjt9XG4gICAgICAgIHBvcHVsYXRlUHJpdmF0ZUxhYmVsQ2FyZEZvcm0oY2FyZFVVSUQpO1xuXG4gICAgICAgIC8vIHJlbW92ZSBzZXJ2ZXIgc2lkZSBlcnJvclxuICAgICAgICAkKCcucmVxdWlyZWQuZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICAgICAgJCgnLmVycm9yLW1lc3NhZ2UnKS5yZW1vdmUoKTtcbiAgICB9KTtcblxuICAgIC8vIHByZXNlbGVjdCBkZWZhdWx0IHByaXZhdGUgbGFiZWwgY2FyZFxuICAgIGlmKCRwcml2YXRlTGFiZWxDYXJkTGlzdC5sZW5ndGggPiAwKXtcbiAgICBcdCRwcml2YXRlTGFiZWxDYXJkTGlzdC5maW5kKCdvcHRpb24nKS5lcSgxKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuICAgIFx0JHByaXZhdGVMYWJlbENhcmRMaXN0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9IFxuICAgIFxuICAgICQoJyNjaGVjay1naWZ0Y2VydCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyICRiYWxhbmNlID0gJCgnLmJhbGFuY2UnKTtcbiAgICAgICAgaWYgKCRnaWZ0Q2VydENvZGUubGVuZ3RoID09PSAwIHx8ICRnaWZ0Q2VydENvZGUudmFsKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSAkYmFsYW5jZS5maW5kKCdzcGFuLmVycm9yJyk7XG4gICAgICAgICAgICBpZiAoZXJyb3IubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgZXJyb3IgPSAkKCc8c3Bhbj4nKS5hZGRDbGFzcygnZXJyb3InKS5hcHBlbmRUbygkYmFsYW5jZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlcnJvci5odG1sKFJlc291cmNlcy5HSUZUX0NFUlRfTUlTU0lORyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBnaWZ0Y2FyZC5jaGVja0JhbGFuY2UoJGdpZnRDZXJ0Q29kZS52YWwoKSwgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSB8fCAhZGF0YS5naWZ0Q2VydGlmaWNhdGUpIHtcbiAgICAgICAgICAgICAgICAkYmFsYW5jZS5odG1sKFJlc291cmNlcy5HSUZUX0NFUlRfSU5WQUxJRCkucmVtb3ZlQ2xhc3MoJ3N1Y2Nlc3MnKS5hZGRDbGFzcygnZXJyb3InKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkYmFsYW5jZS5odG1sKFJlc291cmNlcy5HSUZUX0NFUlRfQkFMQU5DRSArICcgJyArIGRhdGEuZ2lmdENlcnRpZmljYXRlLmJhbGFuY2UpLnJlbW92ZUNsYXNzKCdlcnJvcicpLmFkZENsYXNzKCdzdWNjZXNzJyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJGFkZEdpZnRDZXJ0Lm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIGNvZGUgPSAkZ2lmdENlcnRDb2RlLnZhbCgpLFxuICAgICAgICAgICAgJGVycm9yID0gJGNoZWNrb3V0Rm9ybS5maW5kKCcuZ2lmdGNlcnQtZXJyb3InKTtcbiAgICAgICAgaWYgKGNvZGUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAkZXJyb3IuaHRtbChSZXNvdXJjZXMuR0lGVF9DRVJUX01JU1NJTkcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5yZWRlZW1HaWZ0Q2VydCwge2dpZnRDZXJ0Q29kZTogY29kZSwgZm9ybWF0OiAnYWpheCd9KTtcbiAgICAgICAgJC5nZXRKU09OKHVybCwgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIHZhciBmYWlsID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgbXNnID0gJyc7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSBSZXNvdXJjZXMuQkFEX1JFU1BPTlNFO1xuICAgICAgICAgICAgICAgIGZhaWwgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gZGF0YS5tZXNzYWdlLnNwbGl0KCc8Jykuam9pbignJmx0OycpLnNwbGl0KCc+Jykuam9pbignJmd0OycpO1xuICAgICAgICAgICAgICAgIGZhaWwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZhaWwpIHtcbiAgICAgICAgICAgICAgICAkZXJyb3IuaHRtbChtc2cpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmFzc2lnbihVcmxzLmJpbGxpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgICRhZGRDb3Vwb24ub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgJGVycm9yID0gJGNoZWNrb3V0Rm9ybS5maW5kKCcuY291cG9uLWVycm9yJyksXG4gICAgICAgICAgICBjb2RlID0gJGNvdXBvbkNvZGUudmFsKCk7XG4gICAgICAgIGlmIChjb2RlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgJGVycm9yLmh0bWwoUmVzb3VyY2VzLkNPVVBPTl9DT0RFX01JU1NJTkcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5hZGRDb3Vwb24sIHtjb3Vwb25Db2RlOiBjb2RlLCBmb3JtYXQ6ICdhamF4J30pO1xuICAgICAgICAkLmdldEpTT04odXJsLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgdmFyIGZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBtc2cgPSAnJztcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIG1zZyA9IFJlc291cmNlcy5CQURfUkVTUE9OU0U7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSBkYXRhLm1lc3NhZ2Uuc3BsaXQoJzwnKS5qb2luKCcmbHQ7Jykuc3BsaXQoJz4nKS5qb2luKCcmZ3Q7Jyk7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmFpbCkge1xuICAgICAgICAgICAgICAgICRlcnJvci5odG1sKG1zZyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvL2Jhc2tldCBjaGVjayBmb3IgZGlzcGxheWluZyB0aGUgcGF5bWVudCBzZWN0aW9uLCBpZiB0aGUgYWRqdXN0ZWQgdG90YWwgb2YgdGhlIGJhc2tldCBpcyAwIGFmdGVyIGFwcGx5aW5nIHRoZSBjb3Vwb25cbiAgICAgICAgICAgIC8vdGhpcyB3aWxsIGZvcmNlIGEgcGFnZSByZWZyZXNoIHRvIGRpc3BsYXkgdGhlIGNvdXBvbiBtZXNzYWdlIGJhc2VkIG9uIGEgcGFyYW1ldGVyIG1lc3NhZ2VcbiAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MgJiYgZGF0YS5iYXNrZXR0b3RhbCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5hc3NpZ24oVXJscy5iaWxsaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyB0cmlnZ2VyIGV2ZW50cyBvbiBlbnRlclxuICAgICRjb3Vwb25Db2RlLm9uKCdrZXlkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUud2hpY2ggPT09IDEzKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAkYWRkQ291cG9uLmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICAkZ2lmdENlcnRDb2RlLm9uKCdrZXlkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUud2hpY2ggPT09IDEzKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAkYWRkR2lmdENlcnQuY2xpY2soKTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxudmFyICRmb3JtLCAkY29udGludWUsICRyZXF1aXJlZElucHV0cywgdmFsaWRhdG9yO1xuXG52YXIgaGFzRW1wdHlSZXF1aXJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBmaWx0ZXIgb3V0IG9ubHkgdGhlIHZpc2libGUgZmllbGRzXG4gICAgdmFyIHJlcXVpcmVkVmFsdWVzID0gJHJlcXVpcmVkSW5wdXRzLmZpbHRlcignOnZpc2libGUnKS5tYXAoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gJCh0aGlzKS52YWwoKTtcbiAgICB9KTtcbiAgICByZXR1cm4gXyhyZXF1aXJlZFZhbHVlcykuY29udGFpbnMoJycpO1xufTtcblxudmFyIHZhbGlkYXRlRm9ybSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBvbmx5IHZhbGlkYXRlIGZvcm0gd2hlbiBhbGwgcmVxdWlyZWQgZmllbGRzIGFyZSBmaWxsZWQgdG8gYXZvaWRcbiAgICAvLyB0aHJvd2luZyBlcnJvcnMgb24gZW1wdHkgZm9ybVxuICAgIGlmICghdmFsaWRhdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFoYXNFbXB0eVJlcXVpcmVkKCkpIHtcbiAgICAgICAgaWYgKHZhbGlkYXRvci5mb3JtKCkpIHtcbiAgICAgICAgICAgICRjb250aW51ZS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJGNvbnRpbnVlLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgfVxufTtcblxudmFyIHZhbGlkYXRlRWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCQodGhpcykudmFsKCkgPT09ICcnKSB7XG4gICAgICAgICRjb250aW51ZS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGVuYWJsZSBjb250aW51ZSBidXR0b24gb24gbGFzdCByZXF1aXJlZCBmaWVsZCB0aGF0IGlzIHZhbGlkXG4gICAgICAgIC8vIG9ubHkgdmFsaWRhdGUgc2luZ2xlIGZpZWxkXG4gICAgICAgIGlmICh2YWxpZGF0b3IuZWxlbWVudCh0aGlzKSAmJiAhaGFzRW1wdHlSZXF1aXJlZCgpKSB7XG4gICAgICAgICAgICAkY29udGludWUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRjb250aW51ZS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxudmFyIGluaXQgPSBmdW5jdGlvbiAob3B0cykge1xuICAgIGlmICghb3B0cy5mb3JtU2VsZWN0b3IgfHwgIW9wdHMuY29udGludWVTZWxlY3Rvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZm9ybSBhbmQgY29udGludWUgYWN0aW9uIHNlbGVjdG9ycy4nKTtcbiAgICB9XG4gICAgJGZvcm0gPSAkKG9wdHMuZm9ybVNlbGVjdG9yKTtcbiAgICAkY29udGludWUgPSAkKG9wdHMuY29udGludWVTZWxlY3Rvcik7XG4gICAgdmFsaWRhdG9yID0gJGZvcm0udmFsaWRhdGUoKTtcbiAgICAkcmVxdWlyZWRJbnB1dHMgPSAkKCcucmVxdWlyZWQnLCAkZm9ybSkuZmluZCgnOmlucHV0Jyk7XG4gICAgdmFsaWRhdGVGb3JtKCk7XG4gICAgLy8gc3RhcnQgbGlzdGVuaW5nXG4gICAgJHJlcXVpcmVkSW5wdXRzLm9uKCdjaGFuZ2UnLCB2YWxpZGF0ZUVsKTtcbiAgICAkcmVxdWlyZWRJbnB1dHMuZmlsdGVyKCdpbnB1dCcpLm9uKCdrZXl1cCcsIF8uZGVib3VuY2UodmFsaWRhdGVFbCwgMjAwKSk7XG59O1xuXG5leHBvcnRzLmluaXQgPSBpbml0O1xuZXhwb3J0cy52YWxpZGF0ZUZvcm0gPSB2YWxpZGF0ZUZvcm07XG5leHBvcnRzLnZhbGlkYXRlRWwgPSB2YWxpZGF0ZUVsO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRkcmVzcyA9IHJlcXVpcmUoJy4vYWRkcmVzcycpLFxuICAgIGJpbGxpbmcgPSByZXF1aXJlKCcuL2JpbGxpbmcnKSxcbiAgICBtdWx0aXNoaXAgPSByZXF1aXJlKCcuL211bHRpc2hpcCcpLFxuICAgIHNoaXBwaW5nID0gcmVxdWlyZSgnLi9zaGlwcGluZycpO1xuXG4vKipcbiAqIEBmdW5jdGlvbiBJbml0aWFsaXplcyB0aGUgcGFnZSBldmVudHMgZGVwZW5kaW5nIG9uIHRoZSBjaGVja291dCBzdGFnZSAoc2hpcHBpbmcvYmlsbGluZylcbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGFkZHJlc3MuaW5pdCgpO1xuICAgIGlmICgkKCcuY2hlY2tvdXQtc2hpcHBpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHNoaXBwaW5nLmluaXQoKTtcbiAgICB9IGVsc2UgaWYgKCQoJy5jaGVja291dC1tdWx0aS1zaGlwcGluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbXVsdGlzaGlwLmluaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBiaWxsaW5nLmluaXQoKTtcbiAgICB9XG5cbiAgICAvL2lmIG9uIHRoZSBvcmRlciByZXZpZXcgcGFnZSBhbmQgdGhlcmUgYXJlIHByb2R1Y3RzIHRoYXQgYXJlIG5vdCBhdmFpbGFibGUgZGlhYmxlIHRoZSBzdWJtaXQgb3JkZXIgYnV0dG9uXG4gICAgaWYgKCQoJy5vcmRlci1zdW1tYXJ5LWZvb3RlcicpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKCQoJy5ub3RhdmFpbGFibGUnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkKCcub3JkZXItc3VtbWFyeS1mb290ZXIgLnN1Ym1pdC1vcmRlciAuYnV0dG9uLWZhbmN5LWxhcmdlJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhZGRyZXNzID0gcmVxdWlyZSgnLi9hZGRyZXNzJyksXG4gICAgZm9ybVByZXBhcmUgPSByZXF1aXJlKCcuL2Zvcm1QcmVwYXJlJyksXG4gICAgZGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vZGlhbG9nJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBnaWZ0IG1lc3NhZ2UgYm94IGZvciBtdWx0aXNoaXAgc2hpcHBpbmcsIHRoZSBtZXNzYWdlIGJveCBzdGFydHMgb2ZmIGFzIGhpZGRlbiBhbmQgdGhpcyB3aWxsIGRpc3BsYXkgaXQgaWYgdGhlIHJhZGlvIGJ1dHRvbiBpcyBjaGVja2VkIHRvIHllcywgYWxzbyBhZGRlZCBldmVudCBoYW5kbGVyIHRvIGxpc3RlbiBmb3Igd2hlbiBhIHJhZGlvIGJ1dHRvbiBpcyBwcmVzc2VkIHRvIGRpc3BsYXkgdGhlIG1lc3NhZ2UgYm94XG4gKi9cbmZ1bmN0aW9uIGluaXRNdWx0aUdpZnRNZXNzYWdlQm94KCkge1xuICAgICQuZWFjaCgkKCcuaXRlbS1saXN0JyksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRnaWZ0TWVzc2FnZSA9ICR0aGlzLmZpbmQoJy5naWZ0LW1lc3NhZ2UtdGV4dCcpO1xuXG4gICAgICAgIC8vaGFuZGxlIGluaXRpYWwgbG9hZFxuICAgICAgICAkZ2lmdE1lc3NhZ2UudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsICQoJ2lucHV0W25hbWUkPVwiX2lzR2lmdFwiXTpjaGVja2VkJywgdGhpcykudmFsKCkgIT09ICd0cnVlJyk7XG5cbiAgICAgICAgLy9zZXQgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgICR0aGlzLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkZ2lmdE1lc3NhZ2UudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsICQoJ2lucHV0W25hbWUkPVwiX2lzR2lmdFwiXTpjaGVja2VkJywgdGhpcykudmFsKCkgIT09ICd0cnVlJyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gY2FwdHVyZSBhZGQgZWRpdCBhZGRkcmVzcyBmb3JtIGV2ZW50c1xuICovXG5mdW5jdGlvbiBhZGRFZGl0QWRkcmVzcyh0YXJnZXQpIHtcbiAgICB2YXIgJGFkZHJlc3NGb3JtID0gJCgnZm9ybVtuYW1lJD1cIm11bHRpc2hpcHBpbmdfZWRpdEFkZHJlc3NcIl0nKSxcbiAgICAgICAgJGFkZHJlc3NEcm9wZG93biA9ICRhZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbbmFtZSQ9X2FkZHJlc3NMaXN0XScpLFxuICAgICAgICAkYWRkcmVzc0xpc3QgPSAkYWRkcmVzc0Zvcm0uZmluZCgnLmFkZHJlc3MtbGlzdCcpLFxuICAgICAgICBhZGQgPSB0cnVlLFxuICAgICAgICBzZWxlY3RlZEFkZHJlc3NVVUlEID0gJCh0YXJnZXQpLnBhcmVudCgpLnNpYmxpbmdzKCcuc2VsZWN0LWFkZHJlc3MnKS52YWwoKTtcblxuICAgICRhZGRyZXNzRHJvcGRvd24ub24oJ2NoYW5nZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICRhZGRyZXNzTGlzdC5maW5kKCdzZWxlY3QnKS52YWwoKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkQWRkcmVzcyAhPT0gJ25ld0FkZHJlc3MnKSB7XG4gICAgICAgICAgICBzZWxlY3RlZEFkZHJlc3MgPSAkLmdyZXAoJGFkZHJlc3NMaXN0LmRhdGEoJ2FkZHJlc3NlcycpLCBmdW5jdGlvbiAoYWRkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFkZC5VVUlEID09PSBzZWxlY3RlZEFkZHJlc3M7XG4gICAgICAgICAgICB9KVswXTtcbiAgICAgICAgICAgIGFkZCA9IGZhbHNlO1xuICAgICAgICAgICAgLy8gcHJvY2VlZCB0byBmaWxsIHRoZSBmb3JtIHdpdGggdGhlIHNlbGVjdGVkIGFkZHJlc3NcbiAgICAgICAgICAgIHV0aWwuZmlsbEFkZHJlc3NGaWVsZHMoc2VsZWN0ZWRBZGRyZXNzLCAkYWRkcmVzc0Zvcm0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9yZXNldCB0aGUgZm9ybSBpZiB0aGUgdmFsdWUgb2YgdGhlIG9wdGlvbiBpcyBub3QgYSBVVUlEXG4gICAgICAgICAgICAkYWRkcmVzc0Zvcm0uZmluZCgnLmlucHV0LXRleHQsIC5pbnB1dC1zZWxlY3QnKS52YWwoJycpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkYWRkcmVzc0Zvcm0ub24oJ2NsaWNrJywgJy5jYW5jZWwnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgJGFkZHJlc3NGb3JtLm9uKCdzdWJtaXQnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICQuZ2V0SlNPTihVcmxzLmFkZEVkaXRBZGRyZXNzLCAkYWRkcmVzc0Zvcm0uc2VyaWFsaXplKCksIGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgLy8gQFRPRE86IGZpZ3VyZSBvdXQgYSB3YXkgdG8gaGFuZGxlIGVycm9yIG9uIHRoZSBmb3JtXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGFkZHJlc3MgPSByZXNwb25zZS5hZGRyZXNzLFxuICAgICAgICAgICAgICAgICRzaGlwcGluZ0FkZHJlc3MgPSAkKHRhcmdldCkuY2xvc2VzdCgnLnNoaXBwaW5nYWRkcmVzcycpLFxuICAgICAgICAgICAgICAgICRzZWxlY3QgPSAkc2hpcHBpbmdBZGRyZXNzLmZpbmQoJy5zZWxlY3QtYWRkcmVzcycpLFxuICAgICAgICAgICAgICAgICRzZWxlY3RlZCA9ICRzZWxlY3QuZmluZCgnb3B0aW9uOnNlbGVjdGVkJyksXG4gICAgICAgICAgICAgICAgbmV3T3B0aW9uID0gJzxvcHRpb24gdmFsdWU9XCInICsgYWRkcmVzcy5VVUlEICsgJ1wiPicgK1xuICAgICAgICAgICAgICAgICAgICAoKGFkZHJlc3MuSUQpID8gJygnICsgYWRkcmVzcy5JRCArICcpJyA6IGFkZHJlc3MuZmlyc3ROYW1lICsgJyAnICsgYWRkcmVzcy5sYXN0TmFtZSkgKyAnLCAnICtcbiAgICAgICAgICAgICAgICAgICAgYWRkcmVzcy5hZGRyZXNzMSArICcsICcgKyBhZGRyZXNzLmNpdHkgKyAnLCAnICsgYWRkcmVzcy5zdGF0ZUNvZGUgKyAnLCAnICsgYWRkcmVzcy5wb3N0YWxDb2RlICtcbiAgICAgICAgICAgICAgICAgICAgJzwvb3B0aW9uPic7XG4gICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIGlmIChhZGQpIHtcbiAgICAgICAgICAgICAgICAkKCcuc2hpcHBpbmdhZGRyZXNzIHNlbGVjdCcpLnJlbW92ZUNsYXNzKCduby1vcHRpb24nKS5hcHBlbmQobmV3T3B0aW9uKTtcbiAgICAgICAgICAgICAgICAkKCcubm8tYWRkcmVzcycpLmhpZGUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJCgnLnNoaXBwaW5nYWRkcmVzcyBzZWxlY3QnKS5maW5kKCdvcHRpb25bdmFsdWU9XCInICsgYWRkcmVzcy5VVUlEICsgJ1wiXScpLmh0bWwobmV3T3B0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHRoZXJlJ3Mgbm8gcHJldmlvdXNseSBzZWxlY3RlZCBvcHRpb24sIHNlbGVjdCBpdFxuICAgICAgICAgICAgaWYgKCRzZWxlY3RlZC5sZW5ndGggPT09IDAgfHwgJHNlbGVjdGVkLnZhbCgpID09PSAnJykge1xuICAgICAgICAgICAgICAgICRzZWxlY3QuZmluZCgnb3B0aW9uW3ZhbHVlPVwiJyArIGFkZHJlc3MuVVVJRCArICdcIl0nKS5wcm9wKCdzZWxlY3RlZCcsICdzZWxlY3RlZCcpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vcHJlc2VydmUgdGhlIHV1aWQgb2YgdGhlIG9wdGlvbiBmb3IgdGhlIGhvcCB1cCBmb3JtXG4gICAgaWYgKHNlbGVjdGVkQWRkcmVzc1VVSUQpIHtcbiAgICAgICAgLy91cGRhdGUgdGhlIGZvcm0gd2l0aCBzZWxlY3RlZCBhZGRyZXNzXG4gICAgICAgICRhZGRyZXNzTGlzdC5maW5kKCdvcHRpb24nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vY2hlY2sgdGhlIHZhbHVlcyBvZiB0aGUgb3B0aW9uc1xuICAgICAgICAgICAgaWYgKCQodGhpcykuYXR0cigndmFsdWUnKSA9PT0gc2VsZWN0ZWRBZGRyZXNzVVVJRCkge1xuICAgICAgICAgICAgICAgICQodGhpcykucHJvcCgnc2VsZWN0ZWQnLCAnc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICAkYWRkcmVzc0Ryb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gc2hvd3MgZ2lmdCBtZXNzYWdlIGJveCBpbiBtdWx0aXNoaXAsIGFuZCBpZiB0aGUgcGFnZSBpcyB0aGUgbXVsdGkgc2hpcHBpbmcgYWRkcmVzcyBwYWdlIGl0IHdpbGwgY2FsbCBpbml0bXVsdGlzaGlwc2hpcGFkZHJlc3MoKSB0byBpbml0aWFsaXplIHRoZSBmb3JtXG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpbml0TXVsdGlHaWZ0TWVzc2FnZUJveCgpO1xuICAgIGlmICgkKCcuY2FydC1yb3cgLnNoaXBwaW5nYWRkcmVzcyAuc2VsZWN0LWFkZHJlc3MnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvcm1QcmVwYXJlLmluaXQoe1xuICAgICAgICAgICAgY29udGludWVTZWxlY3RvcjogJ1tuYW1lJD1cImFkZHJlc3NTZWxlY3Rpb25fc2F2ZVwiXScsXG4gICAgICAgICAgICBmb3JtU2VsZWN0b3I6ICdbaWQkPVwibXVsdGlzaGlwcGluZ19hZGRyZXNzU2VsZWN0aW9uXCJdJ1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgJCgnLmVkaXQtYWRkcmVzcycpLm9uKCdjbGljaycsICdhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZGlhbG9nLm9wZW4oe3VybDogdGhpcy5ocmVmLCBvcHRpb25zOiB7b3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYWRkcmVzcy5pbml0KCk7XG4gICAgICAgICAgICBhZGRFZGl0QWRkcmVzcyhlLnRhcmdldCk7XG4gICAgICAgIH19fSk7XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4uLy4uL2FqYXgnKSxcblx0Zm9ybVByZXBhcmUgPSByZXF1aXJlKCcuL2Zvcm1QcmVwYXJlJyksXG5cdHByb2dyZXNzID0gcmVxdWlyZSgnLi4vLi4vcHJvZ3Jlc3MnKSxcbiAgICB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpLFxuXHRcdHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyksXG5cdFx0Y2FydCA9IHJlcXVpcmUoJy4uL2NhcnQnKSxcblx0c2hpcHBpbmcgPSByZXF1aXJlKCcuL3NoaXBwaW5nJyksXG5cdFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xuXG52YXIgc2hpcHBpbmdNZXRob2RzO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19jb3VudHJ5JywgZnVuY3Rpb24oKXtcblx0XHRyZW5kZXJPcHRpb25zKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJywgJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19jb3VudHJ5Jyk7XG5cdFx0dmFyICRpbml0aWFsU3RhdGUgPSAkKCcuYmlsbC1hZGRyZXNzLWZpZWxkcyAuaW5pdGlhbC1zdGF0ZScpO1xuXHRcdGlmICgkaW5pdGlhbFN0YXRlLmxlbmd0aCA+IDAgJiYgJGluaXRpYWxTdGF0ZS52YWwoKSAhPSAnJykge1xuXHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLnZhbCgkaW5pdGlhbFN0YXRlLnZhbCgpKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy52YWx1ZSAhPT0gJ1VTJyAmJiB0aGlzLnZhbHVlICE9PSAnQ0EnKSB7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykucGFyZW50cygnLmZvcm1maWVsZCcpLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLnBhcmVudHMoJy5mb3JtZmllbGQnKS5zaG93KCk7XG5cdFx0fVxuXHR9KTtcblx0JCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblxuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfY291bnRyeScsIGZ1bmN0aW9uKCl7XG5cdFx0cmVuZGVyT3B0aW9ucygnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnLCAnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19jb3VudHJ5Jyk7XG5cdFx0dmFyICRpbml0aWFsU3RhdGUgPSAkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcgLmluaXRpYWwtc3RhdGUnKTtcblx0XHRpZiAoJGluaXRpYWxTdGF0ZS5sZW5ndGggPiAwICYmICRpbml0aWFsU3RhdGUudmFsKCkgIT0gJycpIHtcblx0XHRcdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykudmFsKCRpbml0aWFsU3RhdGUudmFsKCkpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLnZhbHVlICE9PSAnVVMnICYmIHRoaXMudmFsdWUgIT09ICdDQScpIHtcblx0XHRcdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc3RhdGVzX3N0YXRlJykucGFyZW50cygnLmZvcm1maWVsZCcpLmhpZGUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnKS5wYXJlbnRzKCcuZm9ybWZpZWxkJykuc2hvdygpO1xuXHRcdH1cblxuXHRcdGlmKCQodGhpcykudmFsKCkudG9VcHBlckNhc2UoKSA9PSAnVVMnKXtcblx0XHRcdCQoJyNzaGlwcGluZy1pbnRlcm5hdGlvbmFsLWluZm8nKS5oaWRlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJyNzaGlwcGluZy1pbnRlcm5hdGlvbmFsLWluZm8nKS5zaG93KCk7XG5cdFx0fVxuXHR9KTtcblx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19jb3VudHJ5JykudHJpZ2dlcignY2hhbmdlJyk7XG5cblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICdmb3JtIFtpZCo9XCJfcG9zdGFsXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0JHRoaXMudmFsKCR0aGlzLnZhbCgpLnRvVXBwZXJDYXNlKCkpO1xuXHR9KTtcblxuXHQkKCcuYWRkcmVzcy1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXG5cdCQoJy5zaGlwcGluZy1zYW1lJykub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcblx0XHQvLyQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0Ly8kKCcjc3VibWl0QmlsbGluZycpLnNob3coKTtcblx0XHRpZigkKCcuc2hpcHBpbmctc2FtZScpLmlzKCc6Y2hlY2tlZCcpKXtcblx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0fVxuXG5cdH0pO1xuXG5cdCQoJy5hZGQtZGlmZicpLm9uKCdjbGljaycsIGZ1bmN0aW9uKCl7XG5cdFx0Ly8kKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdC8vJCgnI3N1Ym1pdEJpbGxpbmcnKS5oaWRlKCk7XG5cdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHR9KTtcblxuXHQvKkJPT1QtMTE4NiBleHBsYWlucyBiZWhhdmlvciBjaGVjayBiZWZvcmUgdXBkYXRlKi9cblx0JCgnLmJpbGxpbmctYWRkcmVzcy1mb3JtJykub24oJ2NsaWNrJywgJy5lZGl0LWFkZHJlc3MtZGV0JywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRpZigkKCcuYmlsbGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXQ6Y2hlY2tlZCcpLnZhbCgpID09IDEpe1xuXHRcdFx0JCgnLmJpbGxpbmctc2VsZWN0LWFkZHJlc3MnKS5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5iaWxsLWFkZHJlc3MtZmllbGRzJykuc2hvdygpO1xuXHRcdFx0JCgnLmJpbGxpbmctc2VsZWN0LWFkZHJlc3MnKS5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1wcmV2aWV3JykuaGlkZSgpO1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1mb3JtJykuc2hvdygpO1xuXHRcdCQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKS5zaG93KCk7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZm9ybScpLmRhdGEoJ2hpZGRlbi1lZGl0YWJsZScsICQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgpLmxlbmd0aCA/IHRydWUgOiBmYWxzZSkuaGlkZSgpO1xuXHRcdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHR9KTtcblxuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykub24oJ2NsaWNrJywgJy5lZGl0LWFkZHJlc3MtZGV0JywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1mb3JtJykuZGF0YSgnaGlkZGVuLWVkaXRhYmxlJywgdHJ1ZSkuaGlkZSgpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5oaWRlKCk7XG5cdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZm9ybScpLnNob3coKTtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuY3NzKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG5cdFx0JCgnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdH0pO1xuXG5cdCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUsIHNhdmVGb3JtVmFscyl7XG5cdFx0dmFyIHYgPSAkKHRoaXMpLnZhbCgpO1xuXHRcdHZhciAkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzID0gJCgnI2JpbGxpbmdBZGRyZXNzRm9ybSAuYmlsbC1hZGRyZXNzLWZpZWxkcycpO1xuXHRcdGlmKHYgPT0gMSl7XG5cdFx0XHQkKCcuc2hpcHBpbmctc2FtZScpLnByb3AoJ2NoZWNrZWQnLCAkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzLmRhdGEoJ3NhbWUtY2hlY2tlZCcpIHx8IGZhbHNlKTtcblx0XHRcdCQoJy5iaWxsaW5nLXNlbGVjdC1hZGRyZXNzJykuc2hvdygpO1xuXHRcdFx0JCgnLmJpbGwtYWRkcmVzcy1maWVsZHMnKS5hZGRDbGFzcygnY29sbGFwc2VkJyk7XG5cdFx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLXByZXZpZXcnKS5zaG93KCk7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpLmh0bWwoJCgnI2R3ZnJtX2JpbGxpbmdfYWRkcmVzc0xpc3Qgb3B0aW9uOm50aCgwKScpKTtcblx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtcHJldmlldycpLmhpZGUoKTtcblx0XHRcdHZhciAkZm9ybSA9ICQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKTtcblx0XHRcdHZhciBzZWxlY3RlZEFkZHJlc3MgPSAkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCBvcHRpb246bnRoKDApJykuZGF0YSgnYWRkcmVzcycpO1xuXHRcdFx0dXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3MsICRmb3JtKTtcblxuXHRcdH0gZWxzZSBpZih2ID09IDIpe1xuXHRcdFx0JGJpbGxpbmdBZGRyZXNzRm9ybUZpZWxkcy5kYXRhKCdzYW1lLWNoZWNrZWQnLCAkKCcuc2hpcHBpbmctc2FtZScpLnByb3AoJ2NoZWNrZWQnKSk7XG5cdFx0XHQkKCcuYmlsbC1hZGRyZXNzLWZpZWxkcyAuaW5pdGlhbC1zdGF0ZScpLnZhbCgnJyk7XG5cdFx0XHQkKCcuYmlsbGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtcHJldmlldycpLmhpZGUoKTtcblx0XHRcdCQoJy5iaWxsLWFkZHJlc3MtZmllbGRzJykucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlZCcpO1xuXHRcdFx0aWYodHlwZW9mIHNhdmVGb3JtVmFscyA9PSAndW5kZWZpbmVkJyB8fCAhc2F2ZUZvcm1WYWxzKXtcblx0XHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdfYWRkcmVzc0xpc3QnKS52YWwoJycpO1xuXHRcdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ2lucHV0OnRleHQsIGlucHV0OnBhc3N3b3JkLCBpbnB1dDpmaWxlLCB0ZXh0YXJlYScpLm5vdCgnaW5wdXRbbmFtZSo9XCJfZW1haWxcIl0nKS52YWwoJycpO1xuXHRcdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ3NlbGVjdCBvcHRpb246c2VsZWN0ZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpO1xuXHRcdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ2lucHV0OmNoZWNrYm94LCBpbnB1dDpyYWRpbycpLnJlbW92ZUF0dHIoJ2NoZWNrZWQnKTtcblx0XHRcdH1cblx0XHRcdCQoJy5zaGlwcGluZy1zYW1lJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHR9XG5cdFx0aWYoJCgnLnNoaXBwaW5nLXNhbWUnKS5pcygnOmNoZWNrZWQnKSl7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdH1cblx0fSk7XG5cblx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uKCl7XG5cdFx0dmFyIHYgPSAkKHRoaXMpLnZhbCgpO1xuXHRcdHZhciAkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcyA9ICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtIC5lZGl0YWRkcmVzcy1zaGlwcGluZycpO1xuXHRcdGlmKHYgPT0gMSl7XG5cdFx0XHQkKCcuc2hpcHBpbmctc2VsZWN0LWFkZHJlc3MnKS5zaG93KCk7XG5cdFx0XHQkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcnKS5hZGRDbGFzcygnY29sbGFwc2VkJyk7XG5cdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1wcmV2aWV3JykuaHRtbCgnJykuc2hvdygpO1xuXHRcdH0gZWxzZSBpZih2ID09IDIpe1xuXHRcdFx0JCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nIC5pbml0aWFsLXN0YXRlJykudmFsKCcnKTtcblx0XHRcdCQoJy5zaGlwcGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXByZXZpZXcnKS5oaWRlKCk7XG5cdFx0XHQkKCcuZWRpdGFkZHJlc3Mtc2hpcHBpbmcnKS5yZW1vdmVDbGFzcygnY29sbGFwc2VkJyk7XG5cdFx0XHQkKCcjZHdmcm1fc2luZ2xlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS52YWwoJycpO1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnaW5wdXQ6dGV4dCwgaW5wdXQ6cGFzc3dvcmQsIGlucHV0OmZpbGUsIHRleHRhcmVhJykudmFsKCcnKTtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ3NlbGVjdCBvcHRpb246c2VsZWN0ZWQnKS5yZW1vdmVBdHRyKCdzZWxlY3RlZCcpO1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnaW5wdXQ6Y2hlY2tib3gsIGlucHV0OnJhZGlvJykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuXHRcdFx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19jb3VudHJ5JykudHJpZ2dlcignY2hhbmdlJyk7XG5cblx0XHR9XG5cdH0pO1xuXHQvKipcblx0ICogQGZ1bmN0aW9uXG5cdCAqIEBkZXNjcmlwdGlvbiBTZWxlY3RzIHRoZSBmaXJzdCBhZGRyZXNzIGZyb20gdGhlIGxpc3Qgb2YgYWRkcmVzc2VzXG5cdCAqL1xuXHR2YXIgJGZvcm0gPSAkKCcjYmlsbGluZ0FkZHJlc3NGb3JtJyk7XG4gICAgLy8gc2VsZWN0IGFkZHJlc3MgZnJvbSBsaXN0XG4gICAgJCgnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NMaXN0XCJdJywgJGZvcm0pLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9ICQodGhpcykuY2hpbGRyZW4oJzpzZWxlY3RlZCcpLmZpcnN0KCk7XG4gICAgICAgIHZhciBzZWxlY3RlZEFkZHJlc3MgPSAkKHNlbGVjdGVkKS5kYXRhKCdhZGRyZXNzJyk7XG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7IHJldHVybjsgfVxuICAgICAgICB1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJGZvcm0pO1xuXG4gICAgICAgICRmb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgIH0pO1xuXG4gICAgdmFyIHNoaXBwaW5nQWRkckZvcm0gPSAkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpO1xuICAgICQoJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzTGlzdFwiXScsIHNoaXBwaW5nQWRkckZvcm0pLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9ICQodGhpcykuY2hpbGRyZW4oJzpzZWxlY3RlZCcpLmZpcnN0KCk7XG4gICAgICAgIHZhciBzZWxlY3RlZEFkZHJlc3MgPSAkKHNlbGVjdGVkKS5kYXRhKCdhZGRyZXNzJyk7XG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7IHJldHVybjsgfVxuICAgICAgICB1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgc2hpcHBpbmdBZGRyRm9ybSk7XG5cbiAgICAgICAgc2hpcHBpbmdBZGRyRm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcbiAgICB9KTtcblxuICAgIC8vYWRkcmVzcyBzdWJtaXNzaW9uXG4gICAgJCgnI3N1Ym1pdEJpbGxpbmcnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKXtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICBcdCQoJyNzdWJtaXRCaWxsaW5nJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICBcdHByb2dyZXNzLnNob3coKTtcblxuICAgIFx0Ly8gcHJldmVudCBzdWJtaXR0aW5nIHNhdmVkIGFkZHJlc3Mgdy9vdXQgYSBzZWxlY3Rpb25cbiAgICBcdGlmICgkKCcuYmlsbGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXRbdmFsdWU9MV0nKS5wcm9wKCdjaGVja2VkJykgJiYgJCgnI2R3ZnJtX2JpbGxpbmdfYWRkcmVzc0xpc3QnKS52YWwoKSA9PSAnJykge1xuICAgIFx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuICAgIFx0XHRyZXR1cm47XG4gICAgXHR9XG5cbiAgICBcdGlmKCQoJy5zaGlwcGluZy1zYW1lJykuaXMoJzpjaGVja2VkJykpe1xuXHRcdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHR9XG5cbiAgICBcdHZhciAkZm9ybSA9ICQoJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKSxcbiAgICBcdFx0YWN0aW9uTmFtZSA9ICQoJyNzZWxlY3RPcGNBZGRyZXNzJykuYXR0cignbmFtZScpO1xuICAgIFx0JGZvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXCI6bm90KC5yZXF1aXJlZClcIl07XG4gICAgXHQkZm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblxuICAgIFx0JCgnLmN1c3RvbS1lbWFpbC1lcnJvcicpLnJlbW92ZSgpO1xuXG4gICAgXHR2YXIgaXNFbWFpbFZhbGlkID0gdXRpbC52YWxpZGF0ZUVtYWlsKCQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19lbWFpbCcpLnZhbCgpKTtcblxuICAgIFx0aWYoJGZvcm0udmFsaWQoKSAmJiBpc0VtYWlsVmFsaWQpe1xuICAgIFx0XHQvL3NldCBiaWxsaW5nIGFkZHJlc3NcbiAgICBcdFx0c2V0T1BDQWRkcmVzcygnI2JpbGxpbmdBZGRyZXNzRm9ybScsIGFjdGlvbk5hbWUpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgXHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblxuICAgIFx0XHRcdGlmKGRhdGEuc3RhdHVzID09ICdzdWNjZXNzJyl7XG4gICAgXHRcdFx0XHR1cGRhdGVTdW1tYXJ5KCk7XG4gICAgXHRcdFx0XHQkKCcjYmlsbGluZ0FkZHJlc3NGb3JtJykuaGlkZSgpO1xuXHQgICAgICAgIFx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEnKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2soJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKSkuc2hvdygpO1xuXG4gICAgXHRcdFx0XHRpZigkKCcuc2hpcHBpbmctc2FtZScpLnByb3AoJ2NoZWNrZWQnKSl7XG4gICAgXHRcdFx0XHRcdHBvcHVsYXRlQmlsbGluZ1RvU2hpcHBpbmcoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJywgJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKTtcbiAgICAgICAgXHQgICAgXHR9XG4gICAgXHRcdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXG4gICAgXHRcdFx0XHR2YXIgJHNoaXBwaW5nQWRkcmVzc0Zvcm0gPSAkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpO1xuICAgIFx0XHRcdFx0aWYoU2l0ZVByZWZlcmVuY2VzLkJZUEFTU19TSElQUElORyAmJiAkKCcuc2hpcHBpbmctc2FtZScpLnByb3AoJ2NoZWNrZWQnKSl7XG4gICAgXHRcdFx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgnI2JpbGxpbmdBZGRyZXNzRm9ybScpO1xuICAgIFx0XHRcdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpKS5zaG93KCk7XG4gICAgXHRcdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcbiAgICBcdFx0XHRcdFx0JCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcbiAgICBcdFx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICBcdFx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgXHQgICAgICAgIFx0JCgnLnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICBcdFx0XHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5zaG93KCk7XG4gICAgXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWZvcm0nKS5zaG93KCk7XG4gICAgXHRcdFx0XHR9XG5cbiAgICBcdFx0XHRcdGlmKCQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykuZGF0YSgnc2hpcHBpbmctZmlsbGVkJykgPT0gdHJ1ZSl7XG4gICAgXHRcdFx0XHRcdCQoJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgIFx0XHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG4gICAgXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG4gICAgXHRcdFx0XHR9XG5cbiAgICBcdFx0XHR9IGVsc2UgaWYoZGF0YS5zdGF0dXMgPT0gJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InKSB7XG5cdFx0XHRcdFx0b3BlblJlc3RyaWN0aW9uc1BvcHVwKGRhdGEpO1xuICAgIFx0XHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0XHRjb25zb2xlLmxvZygnc3VibWlzc2lvbiBlcnJvcicpO1xuICAgIFx0XHRcdH1cblxuICAgIFx0XHRcdHByb2dyZXNzLmhpZGUoKTtcbiAgICBcdFx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuICAgIFx0ICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICBcdH0gZWxzZSB7XG4gICAgXHRcdHByb2dyZXNzLmhpZGUoKTtcbiAgICBcdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuICAgIFx0XHRpZiAoIWlzRW1haWxWYWxpZCAmJiAkZm9ybS52YWxpZCgpKSB7XG4gICAgXHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2VtYWlsJykucGFyZW50KCkuYXBwZW5kKCc8c3BhbiBjbGFzcz1cImVycm9yIGN1c3RvbS1lbWFpbC1lcnJvclwiPicgKyBSZXNvdXJjZXMuVkFMSURBVEVfRU1BSUwgKyAnPC9zcGFuPicpO1xuICAgIFx0XHR9XG4gICAgXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT1cIjJcIl0nKS50cmlnZ2VyKCdjbGljaycsIFt0cnVlXSk7XG4gICAgXHR9XG4gICAgfSk7XG5cbiAgICAkKCcjc3VibWl0U2hpcHBpbmcnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKXtcbiAgICBcdHZhciAkZm9ybSA9ICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyksXG5cdFx0XHRhY3Rpb25OYW1lID0gJCh0aGlzKS5hdHRyKCduYW1lJyk7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgIFx0cHJvZ3Jlc3Muc2hvdygpO1xuXG4gICAgXHQvLyBwcmV2ZW50IHN1Ym1pdHRpbmcgc2F2ZWQgYWRkcmVzcyB3L291dCBhIHNlbGVjdGlvblxuICAgIFx0aWYgKCQoJy5zaGlwcGluZy1hZGRyZXNzLXR5cGUtc2VsZWN0b3IgaW5wdXRbdmFsdWU9MV0nKS5wcm9wKCdjaGVja2VkJykgJiYgJCgnI2R3ZnJtX3NpbmdsZXNoaXBwaW5nX2FkZHJlc3NMaXN0JykudmFsKCkgPT0gJycpIHtcbiAgICBcdFx0JCgnI3N1Ym1pdFNoaXBwaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgXHRcdHJldHVybjtcbiAgICBcdH1cblxuICAgIFx0JGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgXHRpZigkZm9ybS52YWxpZCgpKXtcbiAgICBcdFx0c2V0T1BDQWRkcmVzcygnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nLCBhY3Rpb25OYW1lKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgIFx0XHRcdHZhciBkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cbiAgICBcdFx0XHRpZihkYXRhLnN0YXR1cyA9PSAnc3VjY2Vzcycpe1xuICAgIFx0XHRcdFx0dXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpO1xuICAgIFx0XHRcdFx0JCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcbiAgICAgICAgXHRcdFx0JCgnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKS5oaWRlKCk7XG4gICAgICAgICAgICBcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YScpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9jaygnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSkuc2hvdygpO1xuICAgICAgICAgICAgXHRcdC8vYmVmb3JlIHByb2NlZWQgdG8gcGF5bWVudCBjaGVjayBpZiBiaWxsaW5nIGFkZHJlc3MgaXMgY29ycmVjdFxuICAgICAgICAgICAgXHRcdHZhciBiaWxGb3JtID0gJCgnI2JpbGxpbmdBZGRyZXNzRm9ybScpO1xuICAgICAgICAgICAgXHRcdGJpbEZvcm0udmFsaWRhdGUoKS5zZXR0aW5ncy5pZ25vcmUgPSBbXCI6bm90KC5yZXF1aXJlZClcIl07XG5cbiAgICAgICAgICAgIFx0XHRpZihiaWxGb3JtLnZhbGlkKCkpe1xuICAgICAgICAgICAgXHRcdFx0aWYoJCgnI2lzU2hpcHBpbmdBZGRyZXNzU2FtZUFzQmlsbGluZ0FkZHJlc3MnKS5pcyhcIjpjaGVja2VkXCIpKSB7ICQoJyNpc1NoaXBwaW5nQWRkcmVzc1NhbWVBc0JpbGxpbmdBZGRyZXNzJykuY2xpY2soKTsgfVxuICAgICAgICAgICAgXHRcdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5jbGljaygpO1xuXHQgICAgICAgICAgICBcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0ICAgICAgICAgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICAgICAgXHR9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHQgICAgICAgICAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0ICAgICAgICAgICAgXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdCAgICAgICAgICAgIFx0XHR2YXIgZm9ybUJvZHkgPSAkKCcuYmlsbGluZy1hZGRyZXNzLWZvcm0nKTtcblx0ICAgICAgICAgICAgXHRcdGZvcm1Cb2R5LnNob3coKTtcblx0ICAgICAgICAgICAgXHRcdGZvcm1Cb2R5LmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICBcdH1cbiAgICAgICAgXHRcdFx0dXBkYXRlU3VtbWFyeSgpO1xuICAgIFx0XHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0XHRjb25zb2xlLmxvZygnc3VibWlzc2lvbiBlcnJvcicpO1xuICAgIFx0XHRcdFx0c3dpdGNoIChkYXRhLnN0YXR1cykge1xuICAgIFx0XHRcdFx0XHRjYXNlICdzaGlwcGluZ1Jlc3RyaWN0aW9uc0Vycm9yJzoge1xuICAgIFx0XHRcdFx0XHRcdG9wZW5SZXN0cmljdGlvbnNQb3B1cChkYXRhKTtcbiAgICBcdFx0XHRcdFx0fVxuICAgIFx0XHRcdFx0fVxuICAgIFx0XHRcdH1cbiAgICBcdFx0XHRwcm9ncmVzcy5oaWRlKCk7XG4gICAgXHRcdFx0JCgnI3N1Ym1pdFNoaXBwaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG4gICAgXHQgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0cHJvZ3Jlc3MuaGlkZSgpO1xuICAgIFx0XHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcbiAgICBcdH1cblxuICAgIH0pO1xuXG5cdCQoJy50b2dnbGUudG9wLCAudG9nZ2xlLmJvdHRvbScpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0JCgnI2ludGVybmF0aW9uYWxpbmZvJykuc2xpZGVUb2dnbGUoKTtcblx0fSk7XG5cblxuXHR2YXIgYmlsbGluZ1NhdmVkQWRkckRyb3Bkb3duID0gJCgnI2R3ZnJtX2JpbGxpbmdfYWRkcmVzc0xpc3QnKTtcblx0Ly9wcmVzZXQgZGVmYXVsdCBhZGRyZXNzIGlmIGV4aXN0c1xuXHRpZihiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24ubGVuZ3RoID4gMCAmJiBiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24udmFsKCkgIT09ICcnKXtcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHQvL3Bhc3MgY3VzdG9tZXIgdG8gc2Vjb25kIHN0ZXAgaW4gdGhpcyBjYXNlXG5cdFx0XHQkKCcjYmlsbGluZ0FkZHJlc3NGb3JtJykuaGlkZSgpO1xuICAgIFx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEnKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2soJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKSkuc2hvdygpO1xuICAgIFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuICAgIFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH0sIDEzKTtcblxuXHR9XG5cblx0dmFyIHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24gPSAkKCcjZHdmcm1fc2luZ2xlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKTtcblx0aWYoc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5sZW5ndGggPiAwICYmIHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24udmFsKCkgIT09ICcnKXtcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyk7XG5cdFx0XHQvL3Bhc3MgY3VzdG9tZXIgdG8gdGhpcmQgc3RlcCBpbiB0aGlzIGNhc2Vcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5odG1sKCcnKS5hcHBlbmQoYnVpbGREZXRhaWxzQmxvY2soJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykpLnNob3coKTtcblx0ICAgICAgICAkKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScpLmhpZGUoKTtcblx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHQkKCcuc2hpcHBpbmctcGF5bWVudC1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdCQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykuZGF0YSgnc2hpcHBpbmctZmlsbGVkJywgdHJ1ZSk7XG5cdCAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xuXHRcdH0sIDEzKTtcblx0fVxuXG5cdC8vZHJhdyBhZGRyZXNzIHByZXZpZXcgb24gY2hhbmdlXG5cdGJpbGxpbmdTYXZlZEFkZHJEcm9wZG93bi5vbignY2hhbmdlJywgZnVuY3Rpb24oKXtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpLFxuXHRcdFx0dXBkID0gZnVuY3Rpb24oKXtcblx0XHRcdFx0dmFyIGVsID0gJCgnLmJpbGxpbmctYWRkcmVzcy1wcmV2aWV3JykuaHRtbCgnJyk7XG5cdFx0XHRcdCR0aGlzLnZhbCgpICYmIGVsLmFwcGVuZChidWlsZERldGFpbHNCbG9jaygnI2JpbGxpbmdBZGRyZXNzRm9ybScsIHRydWUpKS5zaG93KCk7XG5cdFx0XHR9O1xuXG5cdFx0c2V0VGltZW91dCh1cGQsIDEzKTtcblxuXHR9KTtcblx0YmlsbGluZ1NhdmVkQWRkckRyb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuXG5cdC8vZHJhdyBhZGRyZXNzIHByZXZpZXcgb24gY2hhbmdlXG5cdHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24ub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCl7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKSxcblx0XHRcdHVwZCA9IGZ1bmN0aW9uKCl7XG5cdFx0XHRcdHZhciBlbCA9ICQoJy5zaGlwcGluZy1hZGRyZXNzLXByZXZpZXcnKS5odG1sKCcnKTtcblx0XHRcdFx0JHRoaXMudmFsKCkgJiYgZWwuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrKCcjc2hpcHBpbmdBZGRyZXNzRm9ybScsIHRydWUpKS5zaG93KCk7XG5cdFx0XHR9O1xuXG5cdFx0c2V0VGltZW91dCh1cGQsIDEzKTtcblx0fSk7XG5cblx0aWYgKHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24ubGVuZ3RoICYmIHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24ucGFyZW50cygnZm9ybScpLmZpbmQoJ2lucHV0W2lkKj1fYWRkcmVzczFdJykudmFsKCkgPT0gJycpIHtcblx0XHRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9XG5cblx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuXHRcdGlmKCQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtIGlucHV0W2lkKj1fZmlyc3ROYW1lXScpLnZhbCgpICE9ICcnKXtcblx0XHRcdHZhciAkZm9ybSA9ICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyksXG5cdFx0XHRhY3Rpb25OYW1lID0gXCJkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc2F2ZW9wY2FkZHJlc3NcIjtcblxuXHRcdFx0JGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0XHRpZigkZm9ybS52YWxpZCgpKXtcblx0XHRcdFx0c2V0T1BDQWRkcmVzcygnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nLCBhY3Rpb25OYW1lKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0XHRcdHZhciBkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cblx0XHRcdFx0XHRpZihkYXRhLnN0YXR1cyAhPSAnc3VjY2Vzcycpe1xuXHRcdFx0XHRcdFx0Y29uc29sZS5sb2coJ3N1Ym1pc3Npb24gZXJyb3InKTtcblx0XHRcdFx0XHR9XG5cdFx0XHQgICAgfS5iaW5kKHRoaXMpKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sIDMwKTtcblxufVxuXG4vKipcbiAqIGNyZWF0ZSBhZGRyZXNzIG9iamVjdCBmcm9tIGZvcm1cbiAqIEBwYXJhbSBmb3JtU2VsZWN0b3JcbiAqIEByZXR1cm5zIEFkZHJlc3MgT2JqZWN0XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUFkZHJlc3NPYmooZm9ybVNlbGVjdG9yKXtcblx0dmFyICRmb3JtID0gJChmb3JtU2VsZWN0b3IpO1xuXHRyZXR1cm4ge1xuXHRcdGZpcnN0TmFtZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2ZpcnN0TmFtZVwiXScpLnZhbCgpKSxcblx0XHRsYXN0TmFtZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2xhc3ROYW1lXCJdJykudmFsKCkpLFxuXHRcdGFkZHJlc3MxOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSksXG5cdFx0YWRkcmVzczI6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpKSxcblx0XHRhZGRyZXNzMzogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MzXCJdJykudmFsKCkpLFxuXHRcdGNvdW50cnlDb2RlOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9jb3VudHJ5XCJdJykudmFsKCkpLFxuXHRcdHN0YXRlQ29kZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKSksXG5cdFx0cG9zdGFsQ29kZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgpLnRvVXBwZXJDYXNlKCkpLFxuXHRcdGNpdHk6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykudmFsKCkpLFxuXHRcdHBob25lOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcGhvbmVcIl0nKS52YWwoKSksXG5cdFx0ZW1haWw6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9lbWFpbFwiXScpLnZhbCgpKVxuXHR9O1xufVxuXG5mdW5jdGlvbiBwb3B1bGF0ZUJpbGxpbmdUb1NoaXBwaW5nKHNoaXBwaW5nQWRkckZvcm1TZWxlY3RvciwgYmlsbGluZ0FkZHJGb3JtU2VsZWN0b3Ipe1xuXHR2YXIgc2hpcHBpbmdBZGRyRm9ybSA9ICQoc2hpcHBpbmdBZGRyRm9ybVNlbGVjdG9yKTtcblx0dmFyIGJpbGxpbmdBZGRyT2JqID0gY3JlYXRlQWRkcmVzc09iaihiaWxsaW5nQWRkckZvcm1TZWxlY3Rvcik7XG4gICAgc2hpcHBpbmdBZGRyRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9maXJzdE5hbWVcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmouZmlyc3ROYW1lKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2xhc3ROYW1lXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLmxhc3ROYW1lKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLmFkZHJlc3MxKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLmFkZHJlc3MyKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MzXCJdJykudmFsKGJpbGxpbmdBZGRyT2JqLmFkZHJlc3MzKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbChiaWxsaW5nQWRkck9iai5wb3N0YWxDb2RlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoYmlsbGluZ0FkZHJPYmouY2l0eSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgc2hpcHBpbmdBZGRyRm9ybS5maW5kKCdzZWxlY3RbaWQkPWNvdW50cnldJykudmFsKGJpbGxpbmdBZGRyT2JqLmNvdW50cnlDb2RlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBzaGlwcGluZ0FkZHJGb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9c3RhdGVdJykudmFsKGJpbGxpbmdBZGRyT2JqLnN0YXRlQ29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgc2hpcHBpbmdBZGRyRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9waG9uZVwiXScpLnZhbChiaWxsaW5nQWRkck9iai5waG9uZSkudHJpZ2dlcignY2hhbmdlJyk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRGV0YWlsc0Jsb2NrKGZvcm1TZWxlY3RvciwgY29tcGFjdCl7XG5cdHZhciAkZm9ybSA9ICQoZm9ybVNlbGVjdG9yKSxcbiAgICBcdGRhdGEgPSBjcmVhdGVBZGRyZXNzT2JqKCRmb3JtKSxcbiAgICBcdGh0bWxUZXh0ID0gJCgnPGRpdi8+Jywge1wiY2xhc3NcIjogXCJhZGRyZXNzLWRldGFpbHMtc3RcIn0pLFxuICAgIFx0aXNDb21wYWN0ID0gdHlwZW9mIGNvbXBhY3QgIT0gdW5kZWZpbmVkICYmIGNvbXBhY3QgPT0gdHJ1ZSxcbiAgICBcdGhlYWRlciA9IGlzQ29tcGFjdCA/ICcnIDogJGZvcm0uYXR0cignaWQnKSA9PSAnYmlsbGluZ0FkZHJlc3NGb3JtJz8gJzxoNj5CaWxsaW5nIFJlY2lwaWVudDwvaDY+JyA6ICc8aDY+U2hpcCBUbzo8L2g2PicsXG4gICAgXHRlZGl0QnV0dG9uID0gaXNDb21wYWN0ID8gJycgOiAnPHAgY2xhc3M9XCJ0ZXh0LXJpZ2h0XCI+PGEgaHJlZj1cIiNcIiBjbGFzcz1cImVkaXQtYWRkcmVzcy1kZXRcIiB0YWJpbmRleD1cIjBcIj5FZGl0PHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj4mbmJzcDtBZGRyZXNzIEluZm9ybWF0aW9uPC9zcGFuPjwvYT48L3A+JztcblxuICAgIGlmKCFpc0NvbXBhY3QgJiYgJGZvcm0uYXR0cignaWQnKSA9PSAnc2hpcHBpbmdBZGRyZXNzRm9ybScpIHtcbiAgICBcdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgfVxuICAgIGZvciAoIHZhciBfayBpbiBkYXRhICkge1xuICAgIFx0aWYgKCBkYXRhW19rXSAhPSBudWxsICYmIGRhdGFbX2tdLnNlYXJjaCgvXFxeLykgIT0gLTEgKSB7XG4gICAgXHRcdGRhdGFbX2tdID0gZGF0YVtfa10ucmVwbGFjZSgvXFxeL2dpLFwiJ1wiKTtcbiAgICBcdH1cbiAgICB9XG4gICAgaWYgKGRhdGEuZW1haWwpIHtcblxuICAgIFx0dmFyIGh0bWxjb250ZW50ID0gaGVhZGVyO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nK2RhdGEuZmlyc3ROYW1lICsgJyAnICsgZGF0YS5sYXN0TmFtZSArICcgPC9kaXY+JztcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEuYWRkcmVzczEgKyAnIDwvZGl2Pic7XG4gICAgXHRcdGlmIChkYXRhLmFkZHJlc3MyICE9PSAnJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmFkZHJlc3MyICsgJyA8L2Rpdj4nO1xuICAgIFx0XHR9XG4gICAgXHRcdGlmIChkYXRhLmFkZHJlc3MzICE9PSAnJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmFkZHJlc3MzICsgJyA8L2Rpdj4nO1xuICAgIFx0XHR9XG5cbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEuY2l0eTtcblxuXG4gICAgXHRcdGlmKGRhdGEuc3RhdGVDb2RlICE9IG51bGwgJiYgZGF0YS5zdGF0ZUNvZGUgIT0gJycgJiYgZGF0YS5zdGF0ZUNvZGUgIT0gdW5kZWZpbmVkICYmIGRhdGEuc3RhdGVDb2RlLnRvVXBwZXJDYXNlKCkgIT0gJ09USEVSJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICcgJyArIGRhdGEuc3RhdGVDb2RlO1xuICAgIFx0XHR9XG5cbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgZGF0YS5wb3N0YWxDb2RlO1xuICAgIFx0XHRodG1sY29udGVudCArPSAnICcgKyBkYXRhLmNvdW50cnlDb2RlICsgJzwvZGl2Pic7XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLnBob25lICsgJzwvZGl2Pic7XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicrZGF0YS5lbWFpbCsnPC9kaXY+JyArIGVkaXRCdXR0b247XG5cbiAgICBcdGh0bWxUZXh0Lmh0bWwoaHRtbGNvbnRlbnQpO1xuXG4gICAgfSBlbHNlIHtcbiAgICBcdHZhciBodG1sY29udGVudCA9IGhlYWRlcjtcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JytkYXRhLmZpcnN0TmFtZSArICcgJyArIGRhdGEubGFzdE5hbWUgKyAnIDwvZGl2Pic7XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBkYXRhLmFkZHJlc3MxICsgJyA8L2Rpdj4nO1xuICAgIFx0XHRpZiAoZGF0YS5hZGRyZXNzMiAhPT0gJycpIHtcbiAgICBcdFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5hZGRyZXNzMiArICcgPC9kaXY+JztcbiAgICBcdFx0fVxuICAgIFx0XHRpZiAoZGF0YS5hZGRyZXNzMyAhPT0gJycpIHtcbiAgICBcdFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5hZGRyZXNzMyArICcgPC9kaXY+JztcbiAgICBcdFx0fVxuICAgIFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgZGF0YS5jaXR5O1xuXG4gICAgXHRcdGlmKGRhdGEuc3RhdGVDb2RlICE9IG51bGwgJiYgZGF0YS5zdGF0ZUNvZGUgIT0gJycgJiYgZGF0YS5zdGF0ZUNvZGUgIT0gdW5kZWZpbmVkICYmIGRhdGEuc3RhdGVDb2RlLnRvVXBwZXJDYXNlKCkgIT0gJ09USEVSJykge1xuICAgIFx0XHRcdGh0bWxjb250ZW50ICs9ICcgJyArIGRhdGEuc3RhdGVDb2RlO1xuICAgIFx0XHR9XG4gICAgXHRcdGh0bWxjb250ZW50ICs9ICcgJyArIGRhdGEucG9zdGFsQ29kZTtcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgZGF0YS5jb3VudHJ5Q29kZSArICAnPC9kaXY+JztcbiAgICBcdFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGRhdGEucGhvbmUgKyAnPC9kaXY+JyArIGVkaXRCdXR0b247XG5cbiAgICBcdGh0bWxUZXh0Lmh0bWwoaHRtbGNvbnRlbnQpO1xuICAgIH1cblxuICAgIHJldHVybiBodG1sVGV4dDtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBIZWxwZXIgbWV0aG9kIHdoaWNoIGNvbnN0cnVjdHMgYSBVUkwgZm9yIGFuIEFKQVggcmVxdWVzdCB1c2luZyB0aGVcbiAqIGVudGVyZWQgYWRkcmVzcyBpbmZvcm1hdGlvbiBhcyBVUkwgcmVxdWVzdCBwYXJhbWV0ZXJzLlxuICovXG5mdW5jdGlvbiBnZXRTaGlwcGluZ01ldGhvZFVSTChmb3JtU2VsZWN0b3IsIHVybCwgZXh0cmFQYXJhbXMpIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm1TZWxlY3Rvcik7XG5cbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBhZGRyZXNzMTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSxcbiAgICAgICAgYWRkcmVzczI6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCksXG4gICAgICAgIGFkZHJlc3MzOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzM1wiXScpLnZhbCgpLFxuICAgICAgICBjb3VudHJ5Q29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9jb3VudHJ5XCJdJykudmFsKCksXG4gICAgICAgIHN0YXRlQ29kZTogJGZvcm0uZmluZCgnc2VsZWN0W2lkJD1cIl9zdGF0ZVwiXScpLnZhbCgpLFxuICAgICAgICBwb3N0YWxDb2RlOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoKSxcbiAgICAgICAgY2l0eTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpXG4gICAgfTtcbiAgICByZXR1cm4gdXRpbC5hcHBlbmRQYXJhbXNUb1VybCh1cmwsICQuZXh0ZW5kKHBhcmFtcywgZXh0cmFQYXJhbXMpKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KHNlbCkge1xuICAgIHZhciAkc2hpcHBpbmdNZXRob2RMaXN0ID0gJCgnI3NoaXBwaW5nLW1ldGhvZC1saXN0Jyk7XG4gICAgaWYgKCEkc2hpcHBpbmdNZXRob2RMaXN0IHx8ICRzaGlwcGluZ01ldGhvZExpc3QubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuICAgIHZhciB1cmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChzZWwsIFVybHMuc2hpcHBpbmdNZXRob2RzSlNPTik7XG5cbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3QgZ2V0IGxpc3Qgb2YgYXBwbGljYWJsZSBzaGlwcGluZyBtZXRob2RzLicpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB1cGRhdGUgdGhlIFVJLiAgVGhlIGxpc3QgaGFzIGNoYW5nZWQuXG4gICAgICAgICAgICAvLyBDYWNoZSB0aGUgYXJyYXkgb2YgcmV0dXJuZWQgc2hpcHBpbmcgbWV0aG9kcy5cbiAgICAgICAgICAgIHNoaXBwaW5nTWV0aG9kcyA9IGRhdGE7XG4gICAgICAgICAgICAvLyBpbmRpY2F0ZSBwcm9ncmVzc1xuICAgICAgICAgICAgcHJvZ3Jlc3Muc2hvdygkc2hpcHBpbmdNZXRob2RMaXN0KTtcblxuICAgICAgICAgICAgdmFyIHNoaXBwaW5nTWV0aG9kTGlzdERhdGEgPSB7XG4gICAgICAgIFx0XHRzZWxlY3RlZFBheW1lbnRNZXRob2Q6ICQoJyNwYXltZW50U2VjdGlvbiBpbnB1dDpjaGVja2VkJykudmFsKClcbiAgICAgICAgXHR9XG5cbiAgICAgICAgICAgIC8vIGxvYWQgdGhlIHNoaXBwaW5nIG1ldGhvZCBmb3JtXG4gICAgICAgICAgICB2YXIgc21sVXJsID0gZ2V0U2hpcHBpbmdNZXRob2RVUkwoc2VsLCBVcmxzLnNoaXBwaW5nTWV0aG9kc0xpc3QpO1xuXG4gICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmxvYWQoc21sVXJsLCBzaGlwcGluZ01ldGhvZExpc3REYXRhLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5mYWRlSW4oJ2Zhc3QnKTtcbiAgICAgICAgICAgICAgICAvLyByZWJpbmQgdGhlIHJhZGlvIGJ1dHRvbnMgb25jbGljayBmdW5jdGlvbiB0byBhIGhhbmRsZXIuXG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCdbbmFtZSQ9XCJfc2hpcHBpbmdNZXRob2RJRFwiXScpLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBcdCQoJ1tuYW1lJD1cIl9zaGlwcGluZ01ldGhvZElEXCJdJykucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBcdHNlbGVjdFNoaXBwaW5nTWV0aG9kKCQodGhpcykudmFsKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRvb2x0aXAuaW5pdCgpO1xuICAgICAgICAgICAgICAgIC8vaWYgbm90aGluZyBpcyBzZWxlY3RlZCBpbiB0aGUgc2hpcHBpbmcgbWV0aG9kcyBzZWxlY3QgdGhlIGZpcnN0IG9uZVxuICAgICAgICAgICAgICAgIGlmICgkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJy5pbnB1dC1yYWRpbzpjaGVja2VkJykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICRzaGlwcGluZ01ldGhvZExpc3QuZmluZCgnLmlucHV0LXJhZGlvOmZpcnN0JykucHJvcCgnY2hlY2tlZCcsICdjaGVja2VkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGVzIHRoZSBvcmRlciBzdW1tYXJ5IGJhc2VkIG9uIGEgcG9zc2libHkgcmVjYWxjdWxhdGVkIGJhc2tldCBhZnRlciBhIHNoaXBwaW5nIHByb21vdGlvbiBoYXMgYmVlbiBhcHBsaWVkXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVN1bW1hcnkoKSB7XG4gICAgY2FydC51cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnKTtcblxuICAgIHJldHVybjtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBzZWxlY3RzIGEgc2hpcHBpbmcgbWV0aG9kIGZvciB0aGUgZGVmYXVsdCBzaGlwbWVudCBhbmQgdXBkYXRlcyB0aGUgc3VtbWFyeSBzZWN0aW9uIG9uIHRoZSByaWdodCBoYW5kIHNpZGVcbiAqIEBwYXJhbVxuICovXG5mdW5jdGlvbiBzZWxlY3RTaGlwcGluZ01ldGhvZChzaGlwcGluZ01ldGhvZElEKSB7XG4gICAgLy8gbm90aGluZyBlbnRlcmVkXG4gICAgaWYgKCFzaGlwcGluZ01ldGhvZElEKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBhdHRlbXB0IHRvIHNldCBzaGlwcGluZyBtZXRob2RcbiAgICB2YXIgdXJsID0gZ2V0U2hpcHBpbmdNZXRob2RVUkwoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJywgVXJscy5zZWxlY3RTaGlwcGluZ01ldGhvZHNMaXN0LCB7c2hpcHBpbmdNZXRob2RJRDogc2hpcHBpbmdNZXRob2RJRH0pO1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcblxuICAgICAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xuICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLnNoaXBwaW5nTWV0aG9kSUQpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3Qgc2VsZWN0IHNoaXBwaW5nIG1ldGhvZC4nKTtcbiAgICAgICAgICAgICAgICAkKCdbbmFtZSQ9XCJfc2hpcHBpbmdNZXRob2RJRFwiXScpLnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRpc3BsYXkgcHJvbW90aW9uIGluIFVJIGFuZCB1cGRhdGUgdGhlIHN1bW1hcnkgc2VjdGlvbixcbiAgICAgICAgICAgIC8vIGlmIHNvbWUgcHJvbW90aW9ucyB3ZXJlIGFwcGxpZWRcbiAgICAgICAgICAgICQoJy5zaGlwcGluZ3Byb21vdGlvbnMnKS5lbXB0eSgpO1xuXG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIHNldCBhZGRyZXNzIGRhdGFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgcHJlc2VudCBhZGRyZXNzIG9iamVjdFxuICogQHBhcmFtIHtFbGVtZW50fSBBY3Rpb24gbmFtZSB0byBhcHBseSB0byBmb3JtXG4gKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAqL1xudmFyIHNldE9QQ0FkZHJlc3MgPSBmdW5jdGlvbiAoZm9ybSwgbmFtZSkge1xuICAgIHZhciAkZm9ybSA9ICQoZm9ybSksXG4gICAgXHR1cmwgPSAoZm9ybSA9PSAnI2JpbGxpbmdBZGRyZXNzRm9ybScpID8gVXJscy5zZXRPcGNBZGRyZXNzIDogICRmb3JtLmF0dHIoJ2FjdGlvbicpO1xuXG4gICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IHV0aWwuYWpheFVybCh1cmwpLFxuICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lXG4gICAgfSkpO1xufTtcblxudmFyIG9wZW5SZXN0cmljdGlvbnNQb3B1cCA9IGZ1bmN0aW9uIChkYXRhKSB7XG5cdHZhciBwYXlsb2FkID0gSlNPTi5wYXJzZShkYXRhLnBheWxvYWQpO1xuXHR2YXIgcG9wdXAgPSByZXF1aXJlKCcuLi8uLi9wb3B1cCcpO1xuXG5cdHZhciBsaXN0ID0gJC5tYXAocGF5bG9hZC5saXN0LCBmdW5jdGlvbiAoZWwpIHtcblx0XHRyZXR1cm4gJzxsaT4nICsgZWwubmFtZSArICc6PGJyPicgKyBlbC5tZXNzYWdlICsgJzwvbGk+Jztcblx0fSkuam9pbignJyk7XG5cblx0cG9wdXAuaW5pdCh7XG5cdFx0dGl0bGU6IHBheWxvYWQudGl0bGUsXG5cdFx0Y29udGVudDogcGF5bG9hZC5tZXNzYWdlICsgJzx1bCBjbGFzcz1cInNoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cF9fbGlzdFwiPicgKyBsaXN0ICsgJzwvdWw+Jyxcblx0fSkuc2hvd1BvcHVwKCk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlck9wdGlvbnMob3B0aW9uUGFyZW50LCBvcHRpb25zU3RvcmVJZCkge1xuXHR2YXIgb3B0aW9ucyA9ICcnO1xuXHR2YXIgb3B0aW9uc1N0b3JlT3B0aW9ucyA9ICQob3B0aW9uc1N0b3JlSWQgKyAnIG9wdGlvbjpzZWxlY3RlZCcpLmRhdGEoJ29wdGlvbnMnKTtcblx0dmFyIHN0YXRlc0xpc3Q7XG5cblx0aWYgKG9wdGlvbnNTdG9yZU9wdGlvbnMpIHtcblx0XHRzdGF0ZXNMaXN0ID0gSlNPTi5wYXJzZShvcHRpb25zU3RvcmVPcHRpb25zLnJlcGxhY2UoL1xcJy9nLCAnXFxcIicpKTtcblxuXHRcdHN0YXRlc0xpc3QuZm9yRWFjaChmdW5jdGlvbiAoc3RhdGUpIHtcblx0XHRcdG9wdGlvbnMgKz0gJzxvcHRpb24gY2xhc3M9XCJzZWxlY3Qtb3B0aW9uXCIgbGFiZWw9XCInICsgc3RhdGUubGFiZWwgKyAnXCIgdmFsdWU9XCInICsgc3RhdGUuY29kZSArICdcIj4nICsgc3RhdGUubGFiZWwgKyAnPC9vcHRpb24+Jztcblx0XHR9KTtcblxuXHRcdCQob3B0aW9uUGFyZW50KS5lbXB0eSgpLmFwcGVuZChvcHRpb25zKTtcblxuXHRcdGlmIChzdGF0ZXNMaXN0Lmxlbmd0aCA8PSAxKSB7XG5cdFx0XHQkKG9wdGlvblBhcmVudCkucmVtb3ZlQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHQkKG9wdGlvblBhcmVudCkucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuaGlkZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkKG9wdGlvblBhcmVudCkuYWRkQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHQkKG9wdGlvblBhcmVudCkucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuc2hvdygpO1xuXHRcdH1cblx0fVxufVxuXG4kKGRvY3VtZW50KS5vbigndXBkYXRlLXNoaXBwaW5nJywgZnVuY3Rpb24oKSB7XG5cdGlmKCQoJy5zaGlwcGluZy1tZXRob2RzLXNlY3Rpb24nKS5sZW5ndGggPT0gMCl7IHJldHVybjsgfVxuXG5cdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJyk7XG5cdH0sIDEwMCk7XG59KTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuXHRpbml0aWFsaXplRXZlbnRzKCk7XG59O1xuXG5leHBvcnRzLnVwZGF0ZVN1bW1hcnkgPSB1cGRhdGVTdW1tYXJ5OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpO1xudmFyIGZpbmRNb3JlU3RvcmVzID0gcmVxdWlyZSgnLi4vLi4vZmluZE1vcmVTdG9yZXMnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG52YXIgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG52YXIgQWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZztcbnZhciBBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nO1xudmFyIEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlcicpO1xudmFyIENoZWNrb3V0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9DaGVja291dENvbnN0YW50cycpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBWYWxpZGF0aW9uSGVscGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9zY3JpcHRzL3V0aWwvVmFsaWRhdGlvbkhlbHBlcicpO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xuXG52YXIgc2hpcHBpbmdNZXRob2RzO1xudmFyIGlzU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5O1xudmFyIG9wdGlvbnMgPSB7fTtcbnZhciBkYXRhQnVmZmVyID0ge307XG5cbnZhciBiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXJTZWxlY3RvciA9ICcuYmlsbGluZy1hZGRyZXNzLWZvcm0nO1xudmFyICRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIgPSAkKGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lclNlbGVjdG9yKTtcbnZhciBiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciA9ICcjYmlsbGluZ0FkZHJlc3NGb3JtJztcbnZhciAkYmlsbGluZ0FkZHJlc3NGb3JtID0gJChiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3Rvcik7XG52YXIgc2hpcHBpbmdBZGRyZXNzU2VjdGlvblNlbGVjdG9yID0gJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbic7XG52YXIgJHNoaXBwaW5nQWRkcmVzc1NlY3Rpb24gPSAkKHNoaXBwaW5nQWRkcmVzc1NlY3Rpb25TZWxlY3Rvcik7XG52YXIgc2hpcHBpbmdBZGRyZXNzRm9ybUNvbnRhaW5lclNlbGVjdG9yID0gJy5zaGlwcGluZy1hZGRyZXNzLWZvcm0nO1xudmFyICRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyID0gJChzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyU2VsZWN0b3IpO1xudmFyIHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciA9ICcjc2hpcHBpbmdBZGRyZXNzRm9ybSc7XG52YXIgJHNoaXBwaW5nQWRkcmVzc0Zvcm0gPSAkKHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3Rvcik7XG52YXIgcGF5bWVudEZvcm1Db250YWluZXJTZWxlY3RvciA9ICcucGF5bWVudC1zZWN0aW9uJztcbnZhciAkcGF5bWVudEZvcm1Db250YWluZXIgPSAkKHBheW1lbnRGb3JtQ29udGFpbmVyU2VsZWN0b3IpO1xudmFyIHBheW1lbnRGb3JtU2VsZWN0b3IgPSAnI3BheW1lbnRTZWN0aW9uJztcbnZhciAkcGF5bWVudEZvcm0gPSAkKHBheW1lbnRGb3JtU2VsZWN0b3IpO1xudmFyICRzZWN0aW9uQ2hlY2tvdXQgPSAkKCcuc2VjdGlvbi1jaGVja291dCcpO1xudmFyICRzaGlwcGluZ01ldGhvZExpc3QgPSAkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24gI3NoaXBwaW5nLW1ldGhvZC1saXN0Jyk7XG5cbnZhciBzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yO1xudmFyIGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvcjtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcblx0JHNlY3Rpb25DaGVja291dC5vbignY2xpY2snLCAnLmZpbmQtbW9yZS1zdG9yZXMgYScsIGZ1bmN0aW9uICgpIHtcblx0XHRmaW5kTW9yZVN0b3Jlcy5pbml0aWFsaXplKHsgdmlldzogJ2NoZWNrb3V0Jywgc3RvcmVRdWVyeTogU3RvcmVRdWVyeUZpbHRlcnMuU2hpcFRvU3RvcmVFbmFibGVkIH0pO1xuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcuaW50ZXJuYXRpb25hbC1jaGVja291dCcsIGZ1bmN0aW9uKCkge1xuXHRcdGxvY2F0aW9uLnJlbG9hZCgpO1xuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnZm9ybSBbaWQqPVwiX2NvdW50cnlcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGZvcm0gPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG5cdFx0dmFyICRzdGF0ZURyb3Bkb3duID0gJGZvcm0uZmluZCgnW2lkKj1cInN0YXRlc19zdGF0ZVwiXScpO1xuXG5cdFx0cmVuZGVyT3B0aW9ucygnIycgKyAkc3RhdGVEcm9wZG93bi5hdHRyKCdpZCcpLCAnIycgKyAkdGhpcy5hdHRyKCdpZCcpKTtcblxuXHRcdHZhciAkaW5pdGlhbFN0YXRlID0gJGZvcm0uZmluZCgnLmluaXRpYWwtc3RhdGUnKTtcblx0XHR2YXIgaW5pdGlhbFN0YXRlVmFsdWUgPSAkaW5pdGlhbFN0YXRlLnZhbCgpO1xuXHRcdHZhciAkc2VsZWN0ZWRTdGF0ZU9wdGlvbiA9ICRzdGF0ZURyb3Bkb3duLmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBpbml0aWFsU3RhdGVWYWx1ZSArICdcIl0nKTtcblx0XHRpZiAoJHNlbGVjdGVkU3RhdGVPcHRpb24ubGVuZ3RoID4gMCkge1xuXHRcdFx0JHN0YXRlRHJvcGRvd24udmFsKGluaXRpYWxTdGF0ZVZhbHVlKTtcblx0XHRcdCRzZWxlY3RlZFN0YXRlT3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0aWYgKCRmb3JtLmF0dHIoJ2lkJykgPT0gJHNoaXBwaW5nQWRkcmVzc0Zvcm0uYXR0cignaWQnKSAmJiAkdGhpcy52YWwoKSkge1xuXHRcdFx0aWYgKCR0aGlzLnZhbCgpLnRvVXBwZXJDYXNlKCkgPT0gU2l0ZUNvbnN0YW50cy5Db3VudHJ5Q29kZXMuVW5pdGVkU3RhdGVzKSB7XG5cdFx0XHRcdCQoJyNzaGlwcGluZy1pbnRlcm5hdGlvbmFsLWluZm8nKS5oaWRlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcjc2hpcHBpbmctaW50ZXJuYXRpb25hbC1pbmZvJykuc2hvdygpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICdmb3JtIFtpZCo9XCJfcG9zdGFsXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0JHRoaXMudmFsKCR0aGlzLnZhbCgpLnRvVXBwZXJDYXNlKCkpO1xuXHR9KTtcblxuXHQkKCcuc2hpcHBpbmctc2FtZScpLm9uKCdjbGljaycsIGZ1bmN0aW9uKCl7XG5cdFx0aWYoJCgnLnNoaXBwaW5nLXNhbWUnKS5pcygnOmNoZWNrZWQnKSl7XG5cdFx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlQXNTaGlwcGluZ0FkZHJlc3NcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdH1cblx0fSk7XG5cblx0JCgnLmFkZC1kaWZmJykub24oJ2NsaWNrJywgZnVuY3Rpb24oKXtcblx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VBc1NoaXBwaW5nQWRkcmVzc1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdH0pO1xuXG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIub24oJ2NsaWNrJywgJy5lZGl0LWFkZHJlc3MtZGV0JywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZWRpdEJpbGxpbmdBZGRyZXNzKCk7XG5cdH0pO1xuXG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIub24oJ2NsaWNrJywgJy5jYW5jZWwtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdCQoJy5iaWxsLWFkZHJlc3MtZmllbGRzJykuYWRkQ2xhc3MoJ2NvbGxhcHNlZCcpLmhpZGUoKTtcblx0XHQkKCcuYmlsbGluZy1zZWxlY3QtYWRkcmVzcycpLnNob3coKTtcblxuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtcHJldmlldycpLnNob3coKTtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuc2hvdygpO1xuXG5cdFx0JGJpbGxpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuc2hvdygpO1xuXG5cdFx0JHNoaXBwaW5nQWRkcmVzc1NlY3Rpb24uYWRkQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cblx0XHRpZiAoJHNoaXBwaW5nQWRkcmVzc1NlY3Rpb24uYXR0cigncGFuZWwtbW9kZScpICE9ICd2aWV3Jykge1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdFx0XHQkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCQoJy5zaGlwcGluZy1tZXRob2RzLXNlY3Rpb24gLnNoaXBwaW5nLXJlc3RyaWN0aW9ucycpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHQkKCcucGF5bWVudC1tZXRob2RzLXNlY3Rpb24nKS5zaG93KCk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykub24oJ2NsaWNrJywgJy5lZGl0LWFkZHJlc3MtZGV0JywgZnVuY3Rpb24gKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZWRpdFNoaXBwaW5nQWRkcmVzcygpO1xuXHR9KTtcblxuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykub24oJ2NsaWNrJywgJy5hZGQtYWRkcmVzcy1kZXQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHdyaXRlU2hpcHBpbmdBZGRyZXNzRm9ybVRvQnVmZmVyKCk7XG5cblx0XHQkKCcuZm9ybS1jaGVja291dC5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdwYW5lbC1tb2RlJywgJ2FkZCcpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmRhdGEoJ2hpZGRlbi1lZGl0YWJsZScsIHRydWUpLmhpZGUoKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuaGlkZSgpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLnNob3coKTtcblxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnJlbW92ZUNsYXNzKCdhZGQgZWRpdCcpLmFkZENsYXNzKCdhZGQnKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiYWN0aW9uXCJdJykudmFsKCdhZGQnKTtcblxuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5jc3MoJ2Rpc3BsYXknLCAnYmxvY2snKTtcblx0XHQkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblxuXHRcdHZhciAkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcyA9ICRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZycpO1xuXHRcdCQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZyAuaW5pdGlhbC1zdGF0ZScpLnZhbCgnJyk7XG5cblx0XHQkKCcuc2hpcHBpbmctc2VsZWN0LWFkZHJlc3MnKS5oaWRlKCk7XG5cdFx0JCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nJykucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlZCcpO1xuXHRcdCQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnZhbCgnJyk7XG5cblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybUZpZWxkcy5maW5kKCdpbnB1dDp0ZXh0LCBpbnB1dDpwYXNzd29yZCwgaW5wdXQ6ZmlsZSwgdGV4dGFyZWEnKS52YWwoJycpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtRmllbGRzLmZpbmQoJ29wdGlvbltkZWZhdWx0XScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm1GaWVsZHMuZmluZCgnaW5wdXQ6Y2hlY2tib3gsIGlucHV0OnJhZGlvJykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuXG5cdFx0JCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19jb3VudHJ5JykudHJpZ2dlcignY2hhbmdlJyk7XG5cdH0pO1xuXG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5vbignY2xpY2snLCAnLmNhbmNlbC1hZGRyZXNzLWRldCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0d3JpdGVCdWZmZXJUb1NoaXBwaW5nQWRkcmVzc0Zvcm0oKTtcbiAgIFx0XHRzdWJtaXRTaGlwcGluZyh0cnVlKTtcblx0fSk7XG5cbiAgICAkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2hpcHBpbmdBZGRyZXNzVHlwZSA9ICQodGhpcykudmFsKCk7XG4gICAgICAgIHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuZm9ybSgpO1xuXHRcdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAnYmxhbmsnKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250IHNwYW4uZXJyb3InKS5yZW1vdmUoKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250IGlucHV0LCAuc2hpcHBpbmctYWRkcmVzcy1jb250IHNlbGVjdCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuXHRcdFxuICAgICAgICBpZiAoc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikge1xuICAgICAgICBcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQgaW5wdXRbdHlwZT1cInRleHRcIl0sIC5mb3JtZmllbGQgc2VsZWN0Jykubm90KCdbZGlzYWJsZWRdJykubm90KCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX215U3RvcmVJRCcpLnZhbCgnJyk7XG4gICAgICAgIFx0JCgnLmZvcm0tY2hlY2tvdXQuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYXR0cignc2hpcHBpbmctYWRkcmVzcy10eXBlJywgJ215LWFkZHJlc3MnKS5hdHRyKCd2YWx1ZScsICdmYWxzZScpO1xuICAgICAgICBcdFxuICAgICAgICBcdGlmICgkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCBvcHRpb24nKS5sZW5ndGggPiAwIHx8IGRhdGFCdWZmZXIuc2hpcHBpbmdBZGRyZXNzRmllbGRzICYmIGRhdGFCdWZmZXIuc2hpcHBpbmdBZGRyZXNzRmllbGRzWydkd2ZybV9zaGlwcGluZ2FkZHJlc3NfZmlyc3ROYW1lJ10pIHtcblx0XHRcdFx0d3JpdGVCdWZmZXJUb1NoaXBwaW5nQWRkcmVzc0Zvcm0oKTtcbiAgICAgICAgXHRcdFxuXHRcdFx0XHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSkge1xuXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkc2hpcHBpbmdBZGRyZXNzRm9ybSkpO1xuXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG5cdFx0XHRcdFxuXHRcdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0XHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTsgXG5cdFx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZGF0YSgnc2hpcHBpbmctZmlsbGVkJywgdHJ1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmICgkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCBvcHRpb24nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0JCgnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZCBvcHRpb25bZGVmYXVsdF0nKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXHRcdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCBmYWxzZSk7XG5cdFx0XHRcdCQoJy5mb3JtLWNoZWNrb3V0LmFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAndmlldycpO1xuXG5cdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmRhdGEoJ2hpZGRlbi1lZGl0YWJsZScsIHRydWUpLmhpZGUoKTtcblx0XHRcdFx0JCgnLnNoaXBwaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLnNob3coKTtcblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0ucmVtb3ZlQ2xhc3MoJ2FkZCBlZGl0JykuYWRkQ2xhc3MoJ2VkaXQnKTtcblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFjdGlvblwiXScpLnZhbCgnZWRpdCcpO1xuXG5cdFx0XHRcdCQoJy5lZGl0YWRkcmVzcy1zaGlwcGluZycpLnJlbW92ZUNsYXNzKCdjb2xsYXBzZWQnKTtcblx0XHRcdFx0c2V0U2hpcFRvU3RvcmUoZmFsc2UpO1xuXHRcdFx0fVxuXG5cdFx0XHRzZXRTaGlwVG9TdG9yZShpc1NoaXBUb1N0b3JlRW5hYmxlZCgpKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cblx0XHRcdGlmIChzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpKSB7XG5cdFx0XHRcdHNldE9QQ0FkZHJlc3Moc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yLCAnZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3NhdmVvcGNhZGRyZXNzJykudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgIFx0XHRcdFx0aGFuZGxlU2hpcHBpbmdSZXN0cmljdGlvbnMoZGF0YSk7XHRcblx0XHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cblx0XHRcdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUsIG51bGwpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgdHJ1ZSwgbnVsbCk7XG5cdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cblx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5jc3MoJ2Rpc3BsYXknLCAnYmxvY2snKTtcblxuICAgICAgICAgICAgaWYgKCQoJy5tdWx0aXBsZS5zZWxlY3QtYWRkcmVzcyBvcHRpb24nKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBcdCQoJy5tdWx0aXBsZS5zZWxlY3QtYWRkcmVzcycpLnNob3coKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBcdCQoJy5tdWx0aXBsZS5zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICBcdCQoJy5zaW5nbGUuc2VsZWN0LWFkZHJlc3MnKS5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5TdG9yZSkge1xuXHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuICAgICAgICAgICAgJCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nJykuYWRkQ2xhc3MoJ2NvbGxhcHNlZCcpO1xuICAgICAgICAgICAgJCgnLm11bHRpcGxlLnNlbGVjdC1hZGRyZXNzJykuaGlkZSgpO1xuXG4gICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkVOQUJMRV9TSElQX1RPX1NUT1JFX1NFTEVDVElPTikge1xuICAgICAgICAgICAgICAgICQoJy5zaW5nbGUuc2VsZWN0LWFkZHJlc3MnKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0XHQkKCcjbXlzdG9yZXNfYWRkcmVzc0xpc3QnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgJCgnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NMaXN0XCJdJywgJGJpbGxpbmdBZGRyZXNzRm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoc2VsZWN0ZWQpLmRhdGEoJ2FkZHJlc3MnKTtcblxuICAgICAgICBpZiAoIXNlbGVjdGVkQWRkcmVzcykgeyByZXR1cm47IH1cblxuICAgICAgICB1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJGJpbGxpbmdBZGRyZXNzRm9ybSk7XG4gICAgICAgIGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5mb3JtKCk7XG4gICAgfSk7XG5cbiAgICAkKCdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0xpc3RcIl0nLCAkc2hpcHBpbmdBZGRyZXNzRm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcyA9ICQoc2VsZWN0ZWQpLmRhdGEoJ2FkZHJlc3MnKTtcblxuICAgICAgICBpZiAoIXNlbGVjdGVkQWRkcmVzcykgeyByZXR1cm47IH1cblxuICAgICAgICB1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJHNoaXBwaW5nQWRkcmVzc0Zvcm0pO1xuICAgICAgICBzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmZvcm0oKTtcbiAgICB9KTtcblxuICAgICQoJyNzdWJtaXRCaWxsaW5nJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRzdWJtaXRCaWxsaW5nKCk7XG4gICAgfSk7XG5cbiAgICAkKCcjc3VibWl0U2hpcHBpbmcnKS5vbignY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRzdWJtaXRTaGlwcGluZygpO1xuICAgIH0pO1xuXG5cdCQoJy50b2dnbGUudG9wLCAudG9nZ2xlLmJvdHRvbScpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0JCgnI2ludGVybmF0aW9uYWxpbmZvJykuc2xpZGVUb2dnbGUoKTtcblx0fSk7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0JChkb2N1bWVudCkub2ZmKCdrZXl1cC5BZGRyZXNzQXV0b2NvbXBsZXRlJykub24oJ2tleXVwLkFkZHJlc3NBdXRvY29tcGxldGUnLCBiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciArICcgaW5wdXRbdHlwZT1cInRleHRcIl0sICcgKyBzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IgKyAnIGlucHV0W3R5cGU9XCJ0ZXh0XCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyICRmb3JtID0gJHRoaXMuY2xvc2VzdCgnZm9ybScpO1xuXHRcdFx0dmFyIGZvcm1WYWxpZGF0b3IgPSAkZm9ybS52YWxpZGF0ZSgpO1xuXG5cdFx0XHRpZiAoZXZlbnQua2V5Q29kZSA9PSA4IHx8IGV2ZW50LmtleUNvZGUgPT0gNDYpIHtcblx0XHRcdFx0JHRoaXMucGFyZW50KCkuZmluZCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdFx0fSBlbHNlIGlmICghZm9ybVZhbGlkYXRvci5jaGVja0Zvcm0oKSAmJiAoJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfYWRkcmVzczEnKSA+PSAwIHx8ICR0aGlzLmF0dHIoJ2lkJykuaW5kZXhPZignX2FkZHJlc3MyJykgPj0gMCkpIHtcblx0XHRcdFx0dmFyIGFkZHJlc3NBdXRvY29tcGxldGVIYW5kbGVyID0gZnVuY3Rpb24gKGFkZHJlc3NBdXRvY29tcGxldGVEYXRhKSB7XG5cdFx0XHRcdFx0QWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZy5pbml0aWFsaXplKG9wdGlvbnMsIGFkZHJlc3NBdXRvY29tcGxldGVEYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuQXV0b2NvbXBsZXRlQWRkcmVzcygkZm9ybSwgJHRoaXMsIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0F1dG9jb21wbGV0ZUhhbmRsZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JHRoaXMucGFyZW50KCkuZmluZCgnLmFkZHJlc3MtYXV0b2NvbXBsZXRlLWRpYWxvZycpLnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLm9mZignU2V0QWRkcmVzc0Zyb21BZGRyZXNzQXV0b2NvbXBsZXRlJykub24oJ1NldEFkZHJlc3NGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuXHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coZGF0YS4kZm9ybSwgZGF0YS5BZGRyZXNzKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NWZXJpZmljYXRpb24uRW5hYmxlZCkge1xuXHRcdCQoZG9jdW1lbnQpLm9mZignU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uJykub24oJ1NldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbicsIGZ1bmN0aW9uIChldmVudCwgYWRkcmVzc0RhdGEpIHtcblx0XHRcdGlmIChhZGRyZXNzRGF0YS5BZGRyZXNzVHlwZSA9PSAnYmlsbGluZycpIHtcblx0XHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2coJGJpbGxpbmdBZGRyZXNzRm9ybSwgYWRkcmVzc0RhdGEpO1xuXHRcdFx0XHRzdWJtaXRCaWxsaW5nKHRydWUpO1xuXHRcdFx0fSBlbHNlIGlmIChhZGRyZXNzRGF0YS5BZGRyZXNzVHlwZSA9PSAnc2hpcHBpbmcnKSB7XG5cdFx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuU2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nKCRzaGlwcGluZ0FkZHJlc3NGb3JtLCBhZGRyZXNzRGF0YSk7XG5cdFx0XHRcdHN1Ym1pdFNoaXBwaW5nKGZhbHNlLCB0cnVlKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdCQoZG9jdW1lbnQpLm9uKCdvcGMuU2V0U2hpcHBpbmdBZGRyZXNzJywgZnVuY3Rpb24gKGUsIGFkZHJlc3MpIHtcblx0XHR2YXIgdGVtcGxhdGVTZXR0aW5ncyA9IHtcblx0XHRcdFx0aW50ZXJwb2xhdGU6IC97eyhbXFxzXFxTXSs/KX19L2dcblx0ICAgIFx0fTtcblxuXHRcdHZhciB0ZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3Mtc2VsZWN0b3Itb3B0aW9uJykuaHRtbCgpLCB0ZW1wbGF0ZVNldHRpbmdzKTtcblxuXHRcdGFkZHJlc3MuSUQgPSBhZGRyZXNzLmtleTtcblx0XHRpZiAoYWRkcmVzcy5pc015U3RvcmUgJiYgIWFkZHJlc3MubXlTdG9yZUlEICYmIGFkZHJlc3Muc3RvcmVJZCkge1xuXHRcdFx0YWRkcmVzcy5teVN0b3JlSUQgPSBhZGRyZXNzLnN0b3JlSWQ7XG5cdFx0fVxuXG5cdFx0dmFyIHRlbXBsYXRlRGF0YSA9IF8uZXh0ZW5kKGFkZHJlc3MsIHtcblx0XHRcdGlkOiBhZGRyZXNzLlVVSUQsXG5cdFx0XHRjc3NDbGFzczogJ2ZpbmQtbW9yZS1zdG9yZS1vcHRpb24nLFxuXHRcdFx0c2VsZWN0ZWQ6ICdzZWxlY3RlZCcsXG5cdFx0XHR0ZXh0OiBhZGRyZXNzLmxhYmVsVGV4dFxuXHRcdH0pO1xuXG5cdFx0dmFyICRhZGRyZXNzTGlzdCA9ICQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpO1xuXG5cdFx0dmFyIGFkZHJlc3NJbmRleEluTGlzdCA9IG51bGw7XG5cdFx0JGFkZHJlc3NMaXN0LmZpbmQoJ29wdGlvbicpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBvYmplY3QpIHtcblx0XHRcdGlmIChhZGRyZXNzLklEID09ICQob2JqZWN0KS52YWwoKSkge1xuXHRcdFx0XHRhZGRyZXNzSW5kZXhJbkxpc3QgPSBpbmRleDtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdCAgICBpZiAoYWRkcmVzc0luZGV4SW5MaXN0KSB7XG5cdFx0XHQkYWRkcmVzc0xpc3QucHJvcCgnc2VsZWN0ZWRJbmRleCcsIGFkZHJlc3NJbmRleEluTGlzdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10gPSBkYXRhQnVmZmVyWydteXN0b3Jlc19hZGRyZXNzTGlzdCddLmZpbHRlcihmdW5jdGlvbiAoYWRkcmVzcykge1xuXHRcdFx0XHRyZXR1cm4gIWFkZHJlc3MuaXNUZW1wb3Jhcnk7XG5cdFx0XHR9KTtcblxuXHRcdFx0YWRkcmVzcy5pc1RlbXBvcmFyeSA9IHRydWU7XG5cdFx0XHRkYXRhQnVmZmVyWydteXN0b3Jlc19hZGRyZXNzTGlzdCddLnB1c2goYWRkcmVzcyk7XG5cdFx0XHRkYXRhQnVmZmVyWydzdG9yZV9uYW1lX2xvb2t1cCddW2FkZHJlc3MuZmlyc3ROYW1lXSA9IGFkZHJlc3MuZnVsbE5hbWU7XG5cdFx0XHRcblx0XHRcdCRhZGRyZXNzTGlzdC5maW5kKCcuZmluZC1tb3JlLXN0b3JlLW9wdGlvbicpLnJlbW92ZSgpO1xuXHRcdFx0JGFkZHJlc3NMaXN0LnByZXBlbmQodGVtcGxhdGUodGVtcGxhdGVEYXRhKSkucHJvcCgnc2VsZWN0ZWRJbmRleCcsIDApO1xuXHRcdH1cblxuXHQgICAgJCgnI215c3RvcmVzX2FkZHJlc3NMaXN0JykudHJpZ2dlcignY2hhbmdlJyk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QsICNteXN0b3Jlc19hZGRyZXNzTGlzdCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgYWN0aW9uTmFtZSA9ICdkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc2F2ZW9wY2FkZHJlc3MnO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc3Bhbi5lcnJvcicpLnJlbW92ZSgpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgaW5wdXQsIC5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG5cblx0XHR2YXIgJHRhcmdldCA9ICQoZS5jdXJyZW50VGFyZ2V0KTtcbiAgICAgICAgdmFyIHNlbGVjdGVkQWRkcmVzcztcblx0XHRpZiAoJHRhcmdldCAmJiAkdGFyZ2V0LmF0dHIoJ2lkJykpIHtcblx0XHRcdHZhciBkYXRhQnVmZmVyRm9yQWRkcmVzc0xpc3QgPSBkYXRhQnVmZmVyWyR0YXJnZXQuYXR0cignaWQnKV07XG5cdFx0XHRpZiAoZGF0YUJ1ZmZlckZvckFkZHJlc3NMaXN0KSB7XG5cdFx0XHRcdHNlbGVjdGVkQWRkcmVzcyA9IGRhdGFCdWZmZXJGb3JBZGRyZXNzTGlzdC5maWx0ZXIoZnVuY3Rpb24gKGFkZHJlc3MpIHtcblx0XHRcdFx0XHRyZXR1cm4gYWRkcmVzcy5VVUlEID09ICR0YXJnZXQudmFsKCk7XG5cdFx0XHRcdH0pWzBdO1xuXHRcdFx0fVxuXHRcdH1cblxuICAgICAgICBpZiAoIXNlbGVjdGVkQWRkcmVzcykge1xuICAgICAgICBcdHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG5cdFx0dmFyIGlzU3RvcmVBZGRyZXNzID0gZmFsc2U7XG5cdFx0dmFyIHN0b3JlSWQ7XG4gICAgICAgIGlmIChzZWxlY3RlZEFkZHJlc3MuaGFzT3duUHJvcGVydHkoJ2lzTXlTdG9yZScpICYmIHNlbGVjdGVkQWRkcmVzcy5teVN0b3JlSUQpIHtcblx0XHRcdGlzU3RvcmVBZGRyZXNzID0gc2VsZWN0ZWRBZGRyZXNzLmlzTXlTdG9yZTtcblx0XHRcdHN0b3JlSWQgPSBzZWxlY3RlZEFkZHJlc3MubXlTdG9yZUlEO1xuICAgICAgICB9XG5cblx0XHRzZXRTaGlwVG9TdG9yZShpc1N0b3JlQWRkcmVzcyk7XG5cblx0XHRpZiAoaXNTdG9yZUFkZHJlc3MpIHtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQubXlTdG9yZUlEIGlucHV0JykudmFsKHN0b3JlSWQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkIGlucHV0W3R5cGU9XCJ0ZXh0XCJdLCAuZm9ybWZpZWxkIHNlbGVjdCcpLm5vdCgnW2Rpc2FibGVkXScpLm5vdCgnI2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19teVN0b3JlSUQnKS52YWwoJycpO1xuXHRcdFx0dXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3MsICRzaGlwcGluZ0FkZHJlc3NGb3JtKTtcblx0XHR9XG5cdFx0JHRoaXMuZmluZCgnb3B0aW9uLnBsYWNlaG9sZGVyJykucmVtb3ZlKCk7XG5cblx0XHRzZXRPUENBZGRyZXNzKHNoaXBwaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciwgYWN0aW9uTmFtZSkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0aGFuZGxlU2hpcHBpbmdSZXN0cmljdGlvbnMoZGF0YSk7XG5cdFx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5kYXRhKCdzaGlwcGluZy1maWxsZWQnLCB0cnVlKTtcblx0XHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yQWRkcmVzcyhzZWxlY3RlZEFkZHJlc3MsIGZhbHNlLCBmYWxzZSwgJ3NoaXBwaW5nQWRkcmVzc0Zvcm0nKSk7XG5cdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuc2hvdygpO1xuXG5cdFx0XHRpZiAoYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnZhbGlkKCkpIHtcblx0XHRcdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdFx0JCgnLnBheW1lbnQtc2VjdGlvbicpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cblx0XHRcdFx0JGJpbGxpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5zaG93KCk7XG5cdFx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm1Db250YWluZXIuZmluZCgnaW5wdXQucmVxdWlyZWQuZmllbGQuZXJyb3InKS5lcSgwKS5mb2N1cygpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUsIGlzU3RvcmVBZGRyZXNzKTtcblx0XHR9LmJpbmQodGhpcykpO1xuXHR9KTtcblxuXHQkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpIHtcbiAgICBcdCQoJy5jdXN0b20tZW1haWwtZXJyb3InKS5yZW1vdmUoKTtcbiAgICBcdHZhciBpc0VtYWlsVmFsaWQgPSB1dGlsLnZhbGlkYXRlRW1haWwoJCgnI2R3ZnJtX2JpbGxpbmdhZGRyZXNzX2VtYWlsJykudmFsKCkpO1xuXG5cdFx0aWYgKCQodGhpcykudmFsKCkgJiYgYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnZhbGlkKCkgJiYgaXNFbWFpbFZhbGlkKSB7XG5cdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0XHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YScpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9ja0ZvckZvcm0oJGJpbGxpbmdBZGRyZXNzRm9ybSkpLnNob3coKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JCgnLmZvcm0tY2hlY2tvdXQuYWRkcmVzcy1zZWN0aW9uJykuYXR0cigncGFuZWwtbW9kZScsICd2aWV3JykuYXR0cigndmFsdWUnLCAndHJ1ZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlZGl0QmlsbGluZ0FkZHJlc3MoKTtcblx0XHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5TaGlwVG9TdG9yZS5DaGFuZ2UnKS5vbignY2xpY2suU2hpcFRvU3RvcmUuQ2hhbmdlJywgJ1tzaGlwcGluZy1tZXRob2RdIC5zdG9yZS1kZXRhaWxzIC5jaGFuZ2UnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkKHRoaXMpLmNsb3Nlc3QoJ1tzaGlwcGluZy1tZXRob2RdJyk7XG5cdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1kZXRhaWxzJykuaGlkZSgpO1xuXHRcdCRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3InKS5zaG93KCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2hhbmdlLlNoaXBUb1N0b3JlLkFwcGx5Jykub24oJ2NoYW5nZS5TaGlwVG9TdG9yZS5BcHBseScsICdbc2hpcHBpbmctbWV0aG9kXSAuc3RvcmUtc2VsZWN0b3Igc2VsZWN0JywgZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgJHNoaXBwaW5nTWV0aG9kID0gJCh0aGlzKS5jbG9zZXN0KCdbc2hpcHBpbmctbWV0aG9kXScpO1xuXHRcdHZhciAkc2VsZWN0ZWRTdG9yZSA9ICRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3Igb3B0aW9uOmNoZWNrZWQnKTtcblx0XHR2YXIgc3RvcmVJZCA9ICRzZWxlY3RlZFN0b3JlLnZhbCgpO1xuXHRcdFxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQubXlTdG9yZUlEIGlucHV0JykudmFsKHN0b3JlSWQpO1xuXG5cdFx0c2V0T1BDQWRkcmVzcyhzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IsICdkd2ZybV9zaGlwcGluZ2FkZHJlc3Nfc2F2ZW9wY2FkZHJlc3MnKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7IFxuXHRcdFx0dXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCRzaGlwcGluZ0FkZHJlc3NGb3JtLCB0cnVlKTtcblx0XHR9KTtcblxuXHRcdCRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtZGV0YWlscycpLnNob3coKTtcblx0XHQkc2hpcHBpbmdNZXRob2QuZmluZCgnLnN0b3JlLXNlbGVjdG9yJykuaGlkZSgpO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlNoaXBUb1N0b3JlLkNhbmNlbCcpLm9uKCdjbGljay5TaGlwVG9TdG9yZS5DYW5jZWwnLCAnW3NoaXBwaW5nLW1ldGhvZF0gLnN0b3JlLXNlbGVjdG9yIC5jYW5jZWwnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkc2hpcHBpbmdNZXRob2QgPSAkKHRoaXMpLmNsb3Nlc3QoJ1tzaGlwcGluZy1tZXRob2RdJyk7XG5cdFx0JHNoaXBwaW5nTWV0aG9kLmZpbmQoJy5zdG9yZS1kZXRhaWxzJykuc2hvdygpO1xuXHRcdCRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3InKS5oaWRlKCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2hpcHBpbmdNZXRob2QuU2VsZWN0Jykub24oJ2NsaWNrLlNoaXBwaW5nTWV0aG9kLlNlbGVjdCcsICdpbnB1dFtuYW1lKj1cIl9zaGlwcGluZ01ldGhvZElEXCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHNoaXBwaW5nTWV0aG9kID0gJHRoaXMuY2xvc2VzdCgnW3NoaXBwaW5nLW1ldGhvZF0nKTtcblx0XHR2YXIgJHNoaXBtZW50ID0gJHRoaXMuY2xvc2VzdCgnZm9ybScpO1xuXG5cdFx0aWYgKCRzaGlwcGluZ01ldGhvZC5hdHRyKCdzdGF0dXMnKSA9PSAnZGlzYWJsZWQnKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZWxlY3RTaGlwcGluZ01ldGhvZCgkc2hpcG1lbnQuYXR0cignc2hpcG1lbnQnKSwgJHRoaXMudmFsKCksICRzaGlwcGluZ01ldGhvZC5hdHRyKCdpcy1zaGlwLXRvLXN0b3JlJykgPT0gJ3RydWUnLCAkc2hpcHBpbmdNZXRob2QpOyBcblx0XHR9XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignZm9jdXMuQXV0b2ZpbGxIYW5kbGVyJykub24oJ2ZvY3VzLkF1dG9maWxsSGFuZGxlcicsICdkaXYuYmlsbGluZy1hZGRyZXNzLWZvcm0gaW5wdXRbdHlwZT1cInRleHRcIl0sIGRpdi5zaGlwcGluZy1hZGRyZXNzLWZvcm0gaW5wdXRbdHlwZT1cInRleHRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkZm9ybSA9ICR0aGlzLmNsb3Nlc3QoJ2Zvcm0nKTtcblx0XHR2YXIgYXV0b2ZpbGxDb3VudCA9ICRmb3JtLmZpbmQoJ2lucHV0Oi13ZWJraXQtYXV0b2ZpbGwnKS5sZW5ndGg7XG5cblx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gNzY4KSB7XG5cdFx0XHRpZiAoYXV0b2ZpbGxDb3VudCA9PSAwKSB7XG5cdFx0XHRcdCRmb3JtLmF0dHIoJ2F1dG8tZmlsbGVkJywgZmFsc2UpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoJGZvcm0uYXR0cignYXV0by1maWxsZWQnKSAhPSAndHJ1ZScpIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlci5BdXRvZmlsbERldGVjdG9ySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRhdXRvZmlsbENvdW50ID0gJGZvcm0uZmluZCgnaW5wdXQ6LXdlYmtpdC1hdXRvZmlsbCcpLmxlbmd0aDtcblx0XHRcdFx0XHRpZiAoYXV0b2ZpbGxDb3VudCA+IDAgJiYgJGZvcm0uYXR0cignYXV0by1maWxsZWQnKSAhPSAndHJ1ZScpIHtcblx0XHRcdFx0XHRcdCRmb3JtLmF0dHIoJ2F1dG8tZmlsbGVkJywgdHJ1ZSk7XG5cdFx0XHRcdFx0XHQkdGhpcy5hdHRyKCdpbnB1dG1vZGUnLCAnbm9uZScpO1xuXHRcdFx0XHRcdFx0JHRoaXMudHJpZ2dlcignYmx1cicpO1xuXHRcdFx0XHRcdFx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0JHRoaXMucmVtb3ZlQXR0cignaW5wdXRtb2RlJyk7XG5cdFx0XHRcdFx0XHR9LCAyNTApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSwgMjUwKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG4kKGRvY3VtZW50KS5vZmYoJ2JsdXIuQXV0b2ZpbGxIYW5kbGVyJykub24oJ2JsdXIuQXV0b2ZpbGxIYW5kbGVyJywgJ2Rpdi5iaWxsaW5nLWFkZHJlc3MtZm9ybSBpbnB1dFt0eXBlPVwidGV4dFwiXSwgZGl2LnNoaXBwaW5nLWFkZHJlc3MtZm9ybSBpbnB1dFt0eXBlPVwidGV4dFwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRpZiAoZGF0YUJ1ZmZlciAmJiBkYXRhQnVmZmVyLkF1dG9maWxsRGV0ZWN0b3JJbnRlcnZhbCkge1xuXHRcdGNsZWFySW50ZXJ2YWwoZGF0YUJ1ZmZlci5BdXRvZmlsbERldGVjdG9ySW50ZXJ2YWwpO1xuXHR9XG59KTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVVzZXJJbnRlcmZhY2UoKSB7XG5cdCQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfSUQnKS52YWwoJycpO1xuXHQkKCcuZm9ybS1jaGVja291dC5hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdwYW5lbC1tb2RlJywgJ2JsYW5rJyk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAnYmxhbmsnKS5hdHRyKCd2YWx1ZScsICdmYWxzZScpO1xuXG5cdHZhciBiaWxsaW5nQWRkcmVzcyA9IGdldEFkZHJlc3NGcm9tRm9ybSgkYmlsbGluZ0FkZHJlc3NGb3JtKTtcblx0dmFyIHNoaXBwaW5nQWRkcmVzcyA9IGdldEFkZHJlc3NGcm9tRm9ybSgkc2hpcHBpbmdBZGRyZXNzRm9ybSk7XG5cdHZhciAkYmlsbGluZ1NhdmVkQWRkckRyb3Bkb3duID0gJCgnI2R3ZnJtX2JpbGxpbmdfYWRkcmVzc0xpc3QnKTtcblx0dmFyIGRpZEJpbGxpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXJSdW4gPSBmYWxzZTtcblx0dmFyIGRpZFNoaXBwaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyUnVuID0gZmFsc2U7XG5cdFxuXHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfY291bnRyeScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2NvdW50cnknKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblxuXHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3JlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24nLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbiwgUmVzb3VyY2VzLklOVkFMSURfVkFMVUUpO1xuXHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc3RhbENvZGUnLCBWYWxpZGF0aW9uSGVscGVyLlZhbGlkYXRlUG9zdGFsQ29kZSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVEFMX0NPREUpO1xuXHQkLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc3RPZmZpY2VCb3hPbmx5JywgVmFsaWRhdGlvbkhlbHBlci5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seSwgUmVzb3VyY2VzLklOVkFMSURfUE9TVF9PRkZJQ0VfQk9YX09OTFkpO1xuXHRcblx0YmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yID0gJGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpO1xuXHRiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3Iuc2V0dGluZ3MuaWdub3JlID0gW1wiOm5vdCgucmVxdWlyZWQpXCJdO1xuXHRiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3Iuc2V0dGluZ3Mub25mb2N1c291dCA9IFZhbGlkYXRpb25TZXR0aW5ncy5DaGVja291dC5vbmZvY3Vzb3V0O1xuXHRiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3Iuc2V0dGluZ3MuZXJyb3JQbGFjZW1lbnQgPSBWYWxpZGF0aW9uU2V0dGluZ3MuQ2hlY2tvdXQuZXJyb3JQbGFjZW1lbnQ7XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9sYXN0TmFtZVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbik7XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seSk7XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5KTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXG5cdHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IgPSAkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpO1xuXHRzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLnNldHRpbmdzLmlnbm9yZSA9IFtcIjpub3QoLnJlcXVpcmVkKVwiXTtcblx0c2hpcHBpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5zZXR0aW5ncy5vbmZvY3Vzb3V0ID0gVmFsaWRhdGlvblNldHRpbmdzLkNoZWNrb3V0Lm9uZm9jdXNvdXQ7XG5cdHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3Iuc2V0dGluZ3MuZXJyb3JQbGFjZW1lbnQgPSBWYWxpZGF0aW9uU2V0dGluZ3MuQ2hlY2tvdXQuZXJyb3JQbGFjZW1lbnQ7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2ZpcnN0TmFtZVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuUmVxdWlyZWRFeGNsdWRpbmdQdW5jdHVhdGlvbik7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2xhc3ROYW1lXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS5ydWxlcygnYWRkJywgVmFsaWRhdGlvblJ1bGVzLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24pO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHkpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnJ1bGVzKCdhZGQnLCBWYWxpZGF0aW9uUnVsZXMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHkpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykucnVsZXMoJ2FkZCcsIFZhbGlkYXRpb25SdWxlcy5SZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKTtcblxuXHRpZiAoIWJpbGxpbmdBZGRyZXNzLmFkZHJlc3MxICYmICRiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24uZmluZCgnb3B0aW9uJykubGVuZ3RoICYmICRiaWxsaW5nU2F2ZWRBZGRyRHJvcGRvd24udmFsKCkpIHtcblx0XHQkYmlsbGluZ1NhdmVkQWRkckRyb3Bkb3duLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9IGVsc2Uge1xuXHRcdGlmIChiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkpIHtcblx0XHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXQuc2hpcHBpbmctc2FtZScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnNoaXBwaW5nLW5ld3NsZXR0ZXItc2lnbnVwJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHRcdGRpZEJpbGxpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXJSdW4gPSBiaWxsaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyKG51bGwsIHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlZGl0QmlsbGluZ0FkZHJlc3MoKTtcblx0XHR9XG5cdH1cblxuXHRyZW5kZXJNeVN0b3Jlc0FkZHJlc3NTZWxlY3RvcigpO1xuXHR2YXIgJHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24gPSAkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpO1xuXHRpZiAoYmlsbGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICFkaWRCaWxsaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyUnVuKSB7XG5cdFx0aWYgKCFzaGlwcGluZ0FkZHJlc3MuYWRkcmVzczEgJiYgJHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24uZmluZCgnb3B0aW9uJykubGVuZ3RoICYmICRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duLnZhbCgpKSB7XG5cdFx0XHQkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkpIHtcblx0XHRcdFx0ZGlkU2hpcHBpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXJSdW4gPSBzaGlwcGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlcih0cnVlKTtcblx0XHRcdFx0dmVyaWZ5U2hpcHBpbmcoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVkaXRTaGlwcGluZ0FkZHJlc3MoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbiAuc2VsZWN0LWFkZHJlc3MubXVsdGlwbGUnKS5zaG93KCk7XG5cdCQoJy5hZGRyZXNzLXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFxuXHRpZiAoZGlkQmlsbGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlclJ1biAmJiBzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmIHdpbmRvdy5pbm5lcldpZHRoIDw9IDc2Nykge1xuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHQkKFtkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIGRvY3VtZW50LmJvZHldKS5zY3JvbGxUb3AoJCgnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLmhlYWRlci13cmFwcGVyJykuaGVpZ2h0KCkgKyAyMCk7XG5cdFx0fSwgMTAwMCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gYmlsbGluZ0FkZHJlc3NTdWNjZXNzSGFuZGxlcihyZXNwb25zZURhdGEsIHNraXBVcGRhdGVTaGlwcGluZ01ldGhvZExpc3QsIGlzVmVyaWZpZWQpIHtcblx0dmFyICRzaGlwcGluZ1NhdmVkQWRkckRyb3Bkb3duID0gJCgnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKTtcblx0dmFyIHNoaXBwaW5nQWRkcmVzcyA9IGdldEFkZHJlc3NGcm9tRm9ybSgkc2hpcHBpbmdBZGRyZXNzRm9ybSk7XG5cblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5oaWRlKCk7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LmFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAndmlldycpLmF0dHIoJ3ZhbHVlJywgJ3RydWUnKTtcblx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhJykuaHRtbCgnJykuYXBwZW5kKGJ1aWxkRGV0YWlsc0Jsb2NrRm9yRm9ybSgkYmlsbGluZ0FkZHJlc3NGb3JtKSkuc2hvdygpO1xuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXG5cdGlmIChyZXNwb25zZURhdGEgJiYgcmVzcG9uc2VEYXRhLnN0YXR1cyA9PSAnc3VjY2VzcycgJiYgKCQoJyNpc1NoaXBwaW5nQWRkcmVzc1NhbWVBc0JpbGxpbmdBZGRyZXNzJykucHJvcCgnY2hlY2tlZCcpIHx8ICQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHldJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5JykgPT0gJ3RydWUnKSkge1xuXHRcdHBvcHVsYXRlQmlsbGluZ0FkZHJlc3NGb3JtVG9TaGlwcGluZ0FkZHJlc3NGb3JtKCk7XG5cdH1cblx0XG5cdGlmIChyZXNwb25zZURhdGEgJiYgcmVzcG9uc2VEYXRhLnN0YXR1cyA9PSAnc2hpcHBpbmdBZGRyZXNzVmFsaWRhdGlvbkVycm9yJykge1xuXHRcdGVkaXRTaGlwcGluZ0FkZHJlc3MoKTtcblx0fSBlbHNlIGlmIChTaXRlUHJlZmVyZW5jZXMuQllQQVNTX1NISVBQSU5HICYmICgkKCcjaXNTaGlwcGluZ0FkZHJlc3NTYW1lQXNCaWxsaW5nQWRkcmVzcycpLnByb3AoJ2NoZWNrZWQnKSB8fCAkKCdbaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5XScpLmF0dHIoJ2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQtb25seScpID09ICd0cnVlJykpIHtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9ja0ZvckZvcm0oJHNoaXBwaW5nQWRkcmVzc0Zvcm0pKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuc2hvdygpO1xuXG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcsIHRydWUpO1xuXHRcdCRwYXltZW50Rm9ybUNvbnRhaW5lci5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0JCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRzdWJtaXRTaGlwcGluZyhudWxsLCBpc1ZlcmlmaWVkKTtcblx0fSBlbHNlIGlmIChzaGlwcGluZ0FkZHJlc3NGb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpKSB7XG5cdFx0c2hpcHBpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXIoc2tpcFVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCk7XG5cdH0gZWxzZSBpZiAoIXNoaXBwaW5nQWRkcmVzcy5hZGRyZXNzMSAmJiAkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi5maW5kKCdvcHRpb24nKS5sZW5ndGggJiYgJHNoaXBwaW5nU2F2ZWRBZGRyRHJvcGRvd24udmFsKCkpIHtcblx0XHQkc2hpcHBpbmdTYXZlZEFkZHJEcm9wZG93bi50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fSBlbHNlIHtcblx0XHRlZGl0U2hpcHBpbmdBZGRyZXNzKCk7XG5cdH1cblxuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykuYWRkQ2xhc3MoJ2FjdGl2ZScpLnNob3coKTtcblxuXHRpZiAoIXNraXBVcGRhdGVTaGlwcGluZ01ldGhvZExpc3QpIHtcblx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUpO1xuXHR9XG5cblx0aWYgKCRzaGlwcGluZ0FkZHJlc3NGb3JtLmRhdGEoJ3NoaXBwaW5nLWZpbGxlZCcpID09IHRydWUpIHtcblx0XHQkcGF5bWVudEZvcm1Db250YWluZXIuYWRkQ2xhc3MoJ2FjdGl2ZScpLmZpbmQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5zaG93KCk7XG5cdH1cblxuXHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gNzY3KSB7XG5cdFx0JCh3aW5kb3cpLnNjcm9sbFRvcCgkKCcuc2hpcHBpbmctYWRkcmVzcy1zZWN0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLmhlYWRlci13cmFwcGVyJykuaGVpZ2h0KCkpO1xuXHR9XG5cdFxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gc2hpcHBpbmdBZGRyZXNzU3VjY2Vzc0hhbmRsZXIoc2tpcFVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCwgaXNDYW5jZWwsIGlzVmVyaWZpZWQpIHtcblx0dmFyIHNlbGVjdGVkQWRkcmVzc0lEO1xuXHR2YXIgY3VycmVudEFkZHJlc3NJRHMgPSBbXTtcblxuXHQkKCcuc2VsZWN0LWFkZHJlc3MuYWRkcmVzcy1zZWxlY3RvciBzZWxlY3Qgb3B0aW9uJykubWFwKGZ1bmN0aW9uKCkgeyBjdXJyZW50QWRkcmVzc0lEcy5wdXNoKCQodGhpcykudmFsKCkpOyB9KTtcblxuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGFzQ2xhc3MoJ2FkZCcpIHx8ICgkc2hpcHBpbmdBZGRyZXNzRm9ybS5oYXNDbGFzcygnZWRpdCcpICYmICEkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuc2V0LWRlZmF1bHQtc2hpcHBpbmcgaW5wdXQnKS5wcm9wKCdjaGVja2VkJykpKSB7XG5cdFx0c2VsZWN0ZWRBZGRyZXNzSUQgPSBcIm5ld1wiO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX0lEXCJdJykudmFsKCcnKTtcblxuXHRcdGlmICgkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLmZpbmQoJ29wdGlvbi5wbGFjZWhvbGRlcicpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHQkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnByZXBlbmQoJzxvcHRpb24gY2xhc3M9XCJwbGFjZWhvbGRlclwiPicgKyBSZXNvdXJjZXMuT1BDX1NFTEVDVF9BRERSICsgJzwvb3B0aW9uPicpLnByb3AoJ3NlbGVjdGVkSW5kZXgnLCAwKTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0c2VsZWN0ZWRBZGRyZXNzSUQgPSAkKCcuc2VsZWN0LWFkZHJlc3MuYWRkcmVzcy1zZWxlY3RvciBzZWxlY3QnKS52YWwoKTtcblx0fVxuXG5cdHdyaXRlU2hpcHBpbmdBZGRyZXNzRm9ybVRvQnVmZmVyKCk7XG5cdHZhciBwYW5lbE1vZGUgPSAkc2hpcHBpbmdBZGRyZXNzU2VjdGlvbi5hdHRyKCdwYW5lbC1tb2RlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnJlbW92ZUNsYXNzKCdhZGQgZWRpdCcpO1xuXHQkKCcuZm9ybS1jaGVja291dC5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdwYW5lbC1tb2RlJywgJ3ZpZXcnKTtcblxuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuYWRkLXRvLWFkZHJlc3MtYm9vayBpbnB1dCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5zZXQtZGVmYXVsdC1zaGlwcGluZyBpbnB1dCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFxuXHR2YXIgcmVuZGVyQWRkcmVzc1NlbGVjdG9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZGF0YSgnc2hpcHBpbmctZmlsbGVkJywgdHJ1ZSk7XG5cdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uaGlkZSgpO1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJhY3Rpb25cIl0nKS52YWwoJycpO1xuXG5cdFx0aWYgKCFpc0NhbmNlbCAmJiAocGFuZWxNb2RlID09ICdhZGQnIHx8IHBhbmVsTW9kZSA9PSAnZWRpdCcpKSB7XG5cdFx0XHQkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcpLnByb3AoJ3NlbGVjdGVkSW5kZXgnLCAwKTtcblx0XHR9XG5cblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmh0bWwoJycpLmFwcGVuZChidWlsZERldGFpbHNCbG9ja0ZvckZvcm0oJHNoaXBwaW5nQWRkcmVzc0Zvcm0pKTtcblx0XHQkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhJykuc2hvdygpO1xuXHRcdGlmICghaXNWZXJpZmllZCkge1xuXHRcdFx0dmVyaWZ5U2hpcHBpbmcoaXNDYW5jZWwsIGlzVmVyaWZpZWQpO1xuXHRcdH1cblxuXHRcdGlmIChiaWxsaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuY2hlY2tGb3JtKCkpIHtcblx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5zaGlwcGluZy1wYXltZW50LWNvbnQnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblxuXHRcdFx0dmFyIGZvcm1Cb2R5ID0gJCgnLmJpbGxpbmctYWRkcmVzcy1mb3JtJyk7XG5cdFx0XHRmb3JtQm9keS5zaG93KCk7XG5cdFx0XHRmb3JtQm9keS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCFza2lwVXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KSB7XG5cdFx0XHR1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoJHNoaXBwaW5nQWRkcmVzc0Zvcm0sIHRydWUsIG51bGwsIHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdHZhciBpc0F1dGhlbnRpY2F0ZWQgPSAkc2VjdGlvbkNoZWNrb3V0LmF0dHIoJ2lzLWF1dGhlbnRpY2F0ZWQnKSA9PSBcInRydWVcIjtcblx0aWYgKGlzQXV0aGVudGljYXRlZCkge1xuXHRcdHJlbmRlckFkZHJlc3NTZWxlY3Rvcih7XG5cdFx0XHRjb250YWluZXI6ICcuc2VsZWN0LWFkZHJlc3MuYWRkcmVzcy1zZWxlY3RvcicsXG5cdFx0XHRlbDogJy5zZWxlY3QtYWRkcmVzcy5hZGRyZXNzLXNlbGVjdG9yIC5maWVsZC13cmFwcGVyJyxcblx0XHRcdGlkOiAnZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCcsXG5cdFx0XHRzZWxlY3RlZDogc2VsZWN0ZWRBZGRyZXNzSUQsXG5cdFx0XHRjdXJyZW50QWRkcmVzc2VzOiBjdXJyZW50QWRkcmVzc0lEcyxcblx0XHRcdGNhbGxiYWNrOiByZW5kZXJBZGRyZXNzU2VsZWN0b3JDYWxsYmFja1xuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdHJlbmRlckFkZHJlc3NTZWxlY3RvckNhbGxiYWNrKCk7XG5cdH1cblxuXHRpZiAod2luZG93LmlubmVyV2lkdGggPD0gNzY3KSB7XG5cdFx0JCh3aW5kb3cpLnNjcm9sbFRvcCgkKCcucGF5bWVudC1zZWN0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLmhlYWRlci13cmFwcGVyJykuaGVpZ2h0KCkpO1xuXHR9XG5cdFxuXHRyZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gc3VibWl0QmlsbGluZyhpc1ZlcmlmaWVkKSB7XG5cdCQoJyNzdWJtaXRCaWxsaW5nJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0aWYgKCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT0xXScpLnByb3AoJ2NoZWNrZWQnKSAmJiAkKCcjZHdmcm1fYmlsbGluZ19hZGRyZXNzTGlzdCcpLnZhbCgpID09ICcnKSB7XG5cdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpZiAoJCgnI2lzU2hpcHBpbmdBZGRyZXNzU2FtZUFzQmlsbGluZ0FkZHJlc3MnKS5pcygnOmNoZWNrZWQnKSB8fCAkKCdbaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5XScpLmF0dHIoJ2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQtb25seScpID09ICd0cnVlJykge1xuXHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHR9IGVsc2Uge1xuXHRcdCQoJ2lucHV0W25hbWUkPVwiX3VzZUFzU2hpcHBpbmdBZGRyZXNzXCJdJykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0fVxuXG5cdGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci5mb3JtKCk7XG5cdCQoJy5jdXN0b20tZW1haWwtZXJyb3InKS5yZW1vdmUoKTtcblxuXHR2YXIgaXNFbWFpbFZhbGlkID0gdXRpbC52YWxpZGF0ZUVtYWlsKCQoJyNkd2ZybV9iaWxsaW5nYWRkcmVzc19lbWFpbCcpLnZhbCgpKTtcblx0aWYgKGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci52YWxpZCgpICYmIGlzRW1haWxWYWxpZCkge1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0gPSAkKGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcblx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpLnJlbW92ZUF0dHIoJ3JvbGUnKS5oaWRlKCk7XG5cdFx0dmVyaWZ5QmlsbGluZyhudWxsLCBpc1ZlcmlmaWVkKTtcblx0fSBlbHNlIHtcblx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpLmF0dHIoJ3JvbGUnLCdhbGVydCcpLnNob3coKTtcblx0XHQkKCcjc3VibWl0QmlsbGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdGlmICghaXNFbWFpbFZhbGlkICYmIGJpbGxpbmdBZGRyZXNzRm9ybVZhbGlkYXRvci52YWxpZCgpKSB7XG5cdFx0XHQkKCcjZHdmcm1fYmlsbGluZ2FkZHJlc3NfZW1haWwnKS5hZGRDbGFzcygnZXJyb3InKS5wYXJlbnQoKS5hcHBlbmQoJzxzcGFuIGNsYXNzPVwiZXJyb3IgY3VzdG9tLWVtYWlsLWVycm9yXCI+JyArIFJlc291cmNlcy5WQUxJREFURV9FTUFJTCArICc8L3NwYW4+Jyk7XG5cdFx0fVxuXHRcdCQoJy5iaWxsaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT1cIjJcIl0nKS50cmlnZ2VyKCdjbGljaycsIFt0cnVlXSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdmVyaWZ5QmlsbGluZyhpc0NhbmNlbCwgaXNWZXJpZmllZCkge1xuXHR2YXIgYWRkcmVzc0RlbGl2ZXJhYmxlID0gZnVuY3Rpb24gKCkge1xuXHRcdHNldE9QQ0FkZHJlc3MoYmlsbGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IsICQoJyNzZWxlY3RPcGNBZGRyZXNzJykuYXR0cignbmFtZScpKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRiaWxsaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyKGRhdGEsIG51bGwsIHRydWUpO1xuXHRcdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHR9KTtcblx0fVxuXG5cdHZhciBhZGRyZXNzTm90RGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoYWRkcmVzc1ZlcmlmeURhdGEpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgJ2JpbGxpbmcnLCBhZGRyZXNzVmVyaWZ5RGF0YSk7XG5cdFx0JCgnI3N1Ym1pdEJpbGxpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0fVxuXG5cdHZhciBjb3VudHJ5ID0gJGJpbGxpbmdBZGRyZXNzRm9ybS5maW5kKCdbaWQqPVwiX2NvdW50cnlcIl0nKS52YWwoKTtcblx0aWYgKCFpc1ZlcmlmaWVkICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc1ZlcmlmaWNhdGlvbi5FbmFibGVkICYmIGNvdW50cnkudG9VcHBlckNhc2UoKSA9PSAnVVMnKSB7XG5cdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5WZXJpZnlBZGRyZXNzKCRiaWxsaW5nQWRkcmVzc0Zvcm0sIG9wdGlvbnMpLnRoZW4oYWRkcmVzc0RlbGl2ZXJhYmxlLCBhZGRyZXNzTm90RGVsaXZlcmFibGUpO1xuXHR9IGVsc2Uge1xuXHRcdGFkZHJlc3NEZWxpdmVyYWJsZSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdFNoaXBwaW5nKGlzQ2FuY2VsLCBpc1ZlcmlmaWVkKSB7XG5cdCQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQgc3Bhbi5lcnJvcicpLnJlbW92ZSgpO1xuXHQkKCcuc2hpcHBpbmctYWRkcmVzcy1jb250IGlucHV0LCAuc2hpcHBpbmctYWRkcmVzcy1jb250IHNlbGVjdCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuXG5cdHNoaXBwaW5nQWRkcmVzc0Zvcm1WYWxpZGF0b3IuZm9ybSgpO1xuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSkge1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpLnJlbW92ZUF0dHIoJ3JvbGUnKS5oaWRlKCk7XG5cdFx0dmVyaWZ5U2hpcHBpbmcoaXNDYW5jZWwsIGlzVmVyaWZpZWQpO1xuXHR9IGVsc2Uge1xuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpLmF0dHIoJ3JvbGUnLCdhbGVydCcpLnNob3coKTtcblx0XHQkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0fVxufVxuXG5mdW5jdGlvbiB2ZXJpZnlTaGlwcGluZyhpc0NhbmNlbCwgaXNWZXJpZmllZCkge1xuXHR2YXIgYWRkcmVzc0RlbGl2ZXJhYmxlID0gZnVuY3Rpb24gKCkge1xuXHRcdHNldE9QQ0FkZHJlc3Moc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yLCAkKCcjc3VibWl0U2hpcHBpbmcnKS5hdHRyKCduYW1lJykpLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdHZhciBpc1NoaXBwaW5nUmVzdHJpY3RlZCA9IGhhbmRsZVNoaXBwaW5nUmVzdHJpY3Rpb25zKGRhdGEpO1xuXHRcdFx0JCgnI3N1Ym1pdFNoaXBwaW5nJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdFx0XHRpZiAoIWlzU2hpcHBpbmdSZXN0cmljdGVkKSB7XG5cdFx0XHRcdHNoaXBwaW5nQWRkcmVzc1N1Y2Nlc3NIYW5kbGVyKGZhbHNlLCBpc0NhbmNlbCwgdHJ1ZSk7XG5cdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZHMtc2VjdGlvbicpLnNob3coKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHZhciBhZGRyZXNzTm90RGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoYWRkcmVzc1ZlcmlmeURhdGEpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgJ3NoaXBwaW5nJywgYWRkcmVzc1ZlcmlmeURhdGEpO1xuXHRcdCQoJyNzdWJtaXRTaGlwcGluZycpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHR9XG5cblx0dmFyIGNvdW50cnkgPSAkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdbaWQqPVwiX2NvdW50cnlcIl0nKS52YWwoKTtcblx0aWYgKCFpc1ZlcmlmaWVkICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc1ZlcmlmaWNhdGlvbi5FbmFibGVkICYmIGNvdW50cnkudG9VcHBlckNhc2UoKSA9PSAnVVMnKSB7XG5cdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5WZXJpZnlBZGRyZXNzKCRzaGlwcGluZ0FkZHJlc3NGb3JtLCBvcHRpb25zKS50aGVuKGFkZHJlc3NEZWxpdmVyYWJsZSwgYWRkcmVzc05vdERlbGl2ZXJhYmxlKTtcblx0fSBlbHNlIHtcblx0XHRhZGRyZXNzRGVsaXZlcmFibGUoKTtcblx0fVxufVxuXG5mdW5jdGlvbiB3cml0ZUJ1ZmZlclRvQWRkcmVzc0Zvcm0obmFtZSwgJHNlbGVjdG9yKSB7XG5cdGlmIChkYXRhQnVmZmVyW25hbWVdKSB7XG5cdFx0JHNlbGVjdG9yLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHR2YXIgJGZpZWxkID0gJChlbGVtZW50KTtcblx0XHRcdCRmaWVsZC52YWwoZGF0YUJ1ZmZlcltuYW1lXVskZmllbGQuYXR0cignbmFtZScpXSB8fCAnJyk7XG5cdFx0fSk7XG5cdFx0XG5cdFx0aWYgKG5hbWUgPT0gJ3NoaXBwaW5nQWRkcmVzc0ZpZWxkcycpIHtcblx0XHRcdHZhciAkZm9ybSA9ICQoJy5zaGlwcGluZy1hZGRyZXNzLWZvcm0nKTtcblx0XHRcdHZhciAkY291bnRyeURyb3Bkb3duID0gJGZvcm0uZmluZCgnW2lkKj1cIl9jb3VudHJ5XCJdJyk7XG5cdFx0XHR2YXIgJHN0YXRlRHJvcGRvd24gPSAkZm9ybS5maW5kKCdbaWQqPVwic3RhdGVzX3N0YXRlXCJdJyk7XG5cdFx0XHRyZW5kZXJPcHRpb25zKCcjJyArICRzdGF0ZURyb3Bkb3duLmF0dHIoJ2lkJyksICcjJyArICRjb3VudHJ5RHJvcGRvd24uYXR0cignaWQnKSk7XG5cdFx0XHRcblx0XHRcdGlmICgkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLmxlbmd0aCA+IDAgJiYgZGF0YUJ1ZmZlclsnc2hpcHBpbmdBZGRyZXNzRmllbGRzJ11bJ2R3ZnJtX3NoaXBwaW5nYWRkcmVzc19zdGF0ZXNfc3RhdGUnXSkge1xuXHRcdFx0XHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZScpLnZhbChkYXRhQnVmZmVyWydzaGlwcGluZ0FkZHJlc3NGaWVsZHMnXVsnZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3N0YXRlc19zdGF0ZSddKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gd3JpdGVCdWZmZXJUb1NoaXBwaW5nQWRkcmVzc0Zvcm0oKSB7XG5cdHZhciAkc2hpcHBpbmdBZGRyZXNzRmllbGRzID0gJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZCBpbnB1dFt0eXBlPVwidGV4dFwiXSwgLmZvcm1maWVsZCBzZWxlY3QnKS5ub3QoJ1tkaXNhYmxlZF0nKS5ub3QoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfbXlTdG9yZUlEJyk7XG5cdHdyaXRlQnVmZmVyVG9BZGRyZXNzRm9ybSgnc2hpcHBpbmdBZGRyZXNzRmllbGRzJywgJHNoaXBwaW5nQWRkcmVzc0ZpZWxkcyk7XG59XG5cbmZ1bmN0aW9uIHdyaXRlQWRkcmVzc0Zvcm1Ub0J1ZmZlcihuYW1lLCAkc2VsZWN0b3IsIGRvQ2xlYXIpIHtcblx0JHNlbGVjdG9yLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyICRmaWVsZCA9ICQoZWxlbWVudCk7XG5cblx0XHRpZiAoJGZpZWxkLnZhbCgpKSB7XG5cdFx0XHRpZiAoIWRhdGFCdWZmZXJbbmFtZV0pIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlcltuYW1lXSA9IHt9O1xuXHRcdFx0fVxuXG5cdFx0XHRkYXRhQnVmZmVyW25hbWVdWyRmaWVsZC5hdHRyKCduYW1lJyldID0gJGZpZWxkLnZhbCgpO1xuXHRcdH1cblx0fSk7XG5cblx0aWYgKGRvQ2xlYXIpIHtcblx0XHQkc2VsZWN0b3IudmFsKCcnKTtcblx0XHQkc2VsZWN0b3IuZmluZCgnb3B0aW9uW2RlZmF1bHRdJykucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0fVxufVxuXG5mdW5jdGlvbiB3cml0ZVNoaXBwaW5nQWRkcmVzc0Zvcm1Ub0J1ZmZlcihkb0NsZWFyKSB7XG5cdHZhciAkc2hpcHBpbmdBZGRyZXNzRmllbGRzID0gJHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZCBpbnB1dFt0eXBlPVwidGV4dFwiXSwgLmZvcm1maWVsZCBzZWxlY3QnKS5ub3QoJ1tkaXNhYmxlZF0nKS5ub3QoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfbXlTdG9yZUlEJyk7XG5cdHdyaXRlQWRkcmVzc0Zvcm1Ub0J1ZmZlcignc2hpcHBpbmdBZGRyZXNzRmllbGRzJywgJHNoaXBwaW5nQWRkcmVzc0ZpZWxkcywgZG9DbGVhcik7XG59XG5cbi8qKlxuICogY3JlYXRlIGFkZHJlc3Mgb2JqZWN0IGZyb20gZm9ybVxuICogQHBhcmFtICRmb3JtXG4gKiBAcmV0dXJucyBBZGRyZXNzIE9iamVjdFxuICovXG5mdW5jdGlvbiBnZXRBZGRyZXNzRnJvbUZvcm0oJGZvcm0pIHtcblx0cmV0dXJuIHtcblx0XHRJRDogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX0lEXCJdJykudmFsKCkpLFxuXHRcdGlzU3RvcmU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9pc1N0b3JlXCJdJykucHJvcCgnY2hlY2tlZCcpKSxcblx0XHRmaXJzdE5hbWU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9maXJzdE5hbWVcIl0nKS52YWwoKSksXG5cdFx0bGFzdE5hbWU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9sYXN0TmFtZVwiXScpLnZhbCgpKSxcblx0XHRhZGRyZXNzMTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCkpLFxuXHRcdGFkZHJlc3MyOiB1dGlsLmh0bWxFbmNvZGUoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoKSksXG5cdFx0YWRkcmVzczM6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzM1wiXScpLnZhbCgpKSxcblx0XHRjb3VudHJ5Q29kZTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfY291bnRyeVwiXScpLnZhbCgpKSxcblx0XHRzdGF0ZUNvZGU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX3N0YXRlXCJdJykudmFsKCkpLFxuXHRcdHBvc3RhbENvZGU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgpID8gdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgpLnRvVXBwZXJDYXNlKCkpIDogJycsXG5cdFx0Y2l0eTogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoKSksXG5cdFx0cGhvbmU6IHV0aWwuaHRtbEVuY29kZSgkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9waG9uZVwiXScpLnZhbCgpKSxcblx0XHRlbWFpbDogdXRpbC5odG1sRW5jb2RlKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2VtYWlsXCJdJykudmFsKCkpXG5cdH07XG59XG5cbmZ1bmN0aW9uIHBvcHVsYXRlQmlsbGluZ0FkZHJlc3NGb3JtVG9TaGlwcGluZ0FkZHJlc3NGb3JtKCkge1xuXHR2YXIgYmlsbGluZ0FkZHJlc3MgPSBnZXRBZGRyZXNzRnJvbUZvcm0oJGJpbGxpbmdBZGRyZXNzRm9ybSk7XG5cblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfSURcIl0nKS52YWwoJycpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9maXJzdE5hbWVcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MuZmlyc3ROYW1lKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MubGFzdE5hbWUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5hZGRyZXNzMSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKGJpbGxpbmdBZGRyZXNzLmFkZHJlc3MyKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczNcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MuYWRkcmVzczMpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MucG9zdGFsQ29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoYmlsbGluZ0FkZHJlc3MuY2l0eSkudHJpZ2dlcignY2hhbmdlJyk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9Y291bnRyeV0nKS52YWwoYmlsbGluZ0FkZHJlc3MuY291bnRyeUNvZGUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdzZWxlY3RbaWQkPXN0YXRlXScpLnZhbChiaWxsaW5nQWRkcmVzcy5zdGF0ZUNvZGUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9waG9uZVwiXScpLnZhbChiaWxsaW5nQWRkcmVzcy5waG9uZSkudHJpZ2dlcignY2hhbmdlJyk7XG5cbiAgICBpZiAoJCgnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS5maW5kKCdvcHRpb24ucGxhY2Vob2xkZXInKS5sZW5ndGggPT0gMCkge1xuICAgIFx0JCgnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS5wcmVwZW5kKCc8b3B0aW9uIGNsYXNzPVwicGxhY2Vob2xkZXJcIj4nICsgUmVzb3VyY2VzLk9QQ19TRUxFQ1RfQUREUiArICc8L29wdGlvbj4nKS5wcm9wKCdzZWxlY3RlZEluZGV4JywgMCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBidWlsZERldGFpbHNCbG9ja0ZvckZvcm0oJGZvcm0sIGlzQ29tcGFjdCwgaGlkZU5pY2tuYW1lKSB7XG5cdHZhciBhZGRyZXNzID0gZ2V0QWRkcmVzc0Zyb21Gb3JtKCRmb3JtKTtcblx0Zm9yICh2YXIgYWRkcmVzc0tleSBpbiBhZGRyZXNzKSB7XG4gICAgXHRpZiAoYWRkcmVzc1thZGRyZXNzS2V5XSAhPSBudWxsICYmIGFkZHJlc3NbYWRkcmVzc0tleV0uc2VhcmNoKC9cXF4vKSAhPSAtMSkge1xuICAgIFx0XHRhZGRyZXNzW2FkZHJlc3NLZXldID0gYWRkcmVzc1thZGRyZXNzS2V5XS5yZXBsYWNlKC9cXF4vZ2ksXCInXCIpO1xuICAgIFx0fVxuICAgIH1cblxuXHRyZXR1cm4gYnVpbGREZXRhaWxzQmxvY2tGb3JBZGRyZXNzKGFkZHJlc3MsIGlzQ29tcGFjdCwgaGlkZU5pY2tuYW1lLCAkZm9ybS5hdHRyKCdpZCcpKTtcbn1cblxuZnVuY3Rpb24gYnVpbGREZXRhaWxzQmxvY2tGb3JBZGRyZXNzKGFkZHJlc3MsIGlzQ29tcGFjdCwgaGlkZU5pY2tuYW1lLCBmb3JtSWQpIHtcblx0dmFyIHNoaXBwaW5nQWRkcmVzc1R5cGUgPSBnZXRTaGlwcGluZ0FkZHJlc3NUeXBlKCk7XG4gICAgdmFyIGh0bWxUZXh0ID0gJCgnPGRpdi8+Jywge1wiY2xhc3NcIjogXCJhZGRyZXNzLWRldGFpbHMtc3RcIn0pO1xuICAgIHZhciBoZWFkZXIgPSBpc0NvbXBhY3QgPyAnJyA6IGZvcm1JZCA9PSAnYmlsbGluZ0FkZHJlc3NGb3JtJyA/ICc8aDY+QmlsbGluZyBSZWNpcGllbnQ8L2g2PicgOiBmb3JtSWQgPT0gJ3NoaXBwaW5nQWRkcmVzc0Zvcm0nID8gJzxoNj5TaGlwIFRvOjwvaDY+JyA6ICcnO1xuICAgIHZhciBlZGl0QnV0dG9uID0gKCFpc0NvbXBhY3QgJiYgIXNoaXBwaW5nQWRkcmVzc1R5cGUgfHwgc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikgPyAnPHAgY2xhc3M9XCJ0ZXh0LXJpZ2h0IGVkaXQtYWRkcmVzcy1jb250YWluZXJcIj48YSBjbGFzcz1cImVkaXQtYWRkcmVzcy1kZXRcIiB0YWJpbmRleD1cIjBcIj5FZGl0PHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj4mbmJzcDtBZGRyZXNzIEluZm9ybWF0aW9uPC9zcGFuPjwvYT48L3A+JyA6ICcnO1xuICAgIHZhciBhZGROZXdCdXR0b24gPSAnJztcblx0dmFyIGFkZHJlc3NOaWNrbmFtZSA9ICcnO1xuXHRcblx0aWYgKGZvcm1JZCA9PSAnc2hpcHBpbmdBZGRyZXNzRm9ybScpIHtcblx0XHRpZiAoYWRkcmVzcy5hZGRyZXNzMSAmJiAhaGlkZU5pY2tuYW1lKSB7XG5cdFx0XHRpZiAoYWRkcmVzcy5JRCAmJiAhYWRkcmVzcy5teVN0b3JlSUQpIHtcblx0XHRcdFx0YWRkcmVzc05pY2tuYW1lID0gYWRkcmVzcy5JRDtcblx0XHRcdH0gZWxzZSBpZiAoZm9ybUlkID09ICdzaGlwcGluZ0FkZHJlc3NGb3JtJyAmJiBzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyICYmIGRhdGFCdWZmZXJbJ2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnXSkge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRBZGRyZXNzRnJvbURyb3Bkb3duID0gZGF0YUJ1ZmZlclsnZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdCddLmZpbHRlcihmdW5jdGlvbiAoYWRkcmVzc09wdGlvbikge1xuXHRcdFx0XHRcdHJldHVybiBhZGRyZXNzT3B0aW9uLlVVSUQgPT0gJCgnI2R3ZnJtX211bHRpcGxlc2hpcHBpbmdfYWRkcmVzc0xpc3QnKS52YWwoKTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoc2VsZWN0ZWRBZGRyZXNzRnJvbURyb3Bkb3duLmxlbmd0aCA+IDAgJiYgc2VsZWN0ZWRBZGRyZXNzRnJvbURyb3Bkb3duWzBdLmRpc3BsYXlWYWx1ZSAmJiAkKCdbaGFzLXdhcmVob3VzZS1zaGlwbWVudF0nKS5hdHRyKCdoYXMtd2FyZWhvdXNlLXNoaXBtZW50JykgPT0gJ3RydWUnKSB7XG5cdFx0XHRcdFx0dXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3NGcm9tRHJvcGRvd25bMF0sICQoJyNzaGlwcGluZ0FkZHJlc3NGb3JtJykpO1xuXHRcdFx0XHRcdHdyaXRlU2hpcHBpbmdBZGRyZXNzRm9ybVRvQnVmZmVyKCk7XG5cdFx0XHRcdFx0YWRkcmVzc05pY2tuYW1lID0gc2VsZWN0ZWRBZGRyZXNzRnJvbURyb3Bkb3duWzBdLmRpc3BsYXlWYWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoYWRkcmVzc05pY2tuYW1lKSB7XG5cdFx0XHRcdGFkZHJlc3NOaWNrbmFtZSA9ICc8c3BhbiBjbGFzcz1cImFkZHJlc3Mtbmlja25hbWVcIj4nICsgYWRkcmVzc05pY2tuYW1lICsgJzwvc3Bhbj4nO1xuXHRcdFx0fVxuXG5cdFx0XHQkKCcuZm9ybS1jaGVja291dC5zaGlwcGluZy1hZGRyZXNzLXNlY3Rpb24nKS5hdHRyKCdwYW5lbC1tb2RlJywgJ3ZpZXcnKS5hdHRyKCd2YWx1ZScsICd0cnVlJyk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICghaXNDb21wYWN0ICYmIHNoaXBwaW5nQWRkcmVzc1R5cGUgPT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuQ3VzdG9tZXIpIHtcblx0XHRcdGFkZE5ld0J1dHRvbiA9ICc8cCBjbGFzcz1cImFkZC1hZGRyZXNzLWNvbnRhaW5lclwiPjxhIGNsYXNzPVwiYWRkLWFkZHJlc3MtZGV0XCIgdGFiaW5kZXg9XCIwXCI+KyBBZGQgTmV3IEFkZHJlc3M8L2E+PC9wPic7XG5cdFx0fVxuXHR9XG5cdFxuICAgIHZhciBodG1sY29udGVudCA9ICcnO1xuICAgIGlmIChhZGRyZXNzLmFkZHJlc3MxKSB7XG5cdCAgICBodG1sY29udGVudCArPSBoZWFkZXI7XG5cdCAgICBodG1sY29udGVudCArPSAnPGRpdiBjbGFzcz1cImFkZHJlc3NcIiB0YWJpbmRleD1cIjBcIj48ZGl2PicgKyAoYWRkcmVzcy5teVN0b3JlSUQgPyBhZGRyZXNzLmZ1bGxOYW1lIDogYWRkcmVzcy5maXJzdE5hbWUpICsgJyAnICsgYWRkcmVzcy5sYXN0TmFtZSArIGFkZHJlc3NOaWNrbmFtZSArICcgPC9kaXY+Jztcblx0ICAgIGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBhZGRyZXNzLmFkZHJlc3MxICsgJyA8L2Rpdj4nO1xuXHQgICAgaWYgKGFkZHJlc3MuYWRkcmVzczIpIHtcblx0ICAgIFx0aHRtbGNvbnRlbnQgKz0gJzxkaXY+JyArIGFkZHJlc3MuYWRkcmVzczIgKyAnIDwvZGl2Pic7XG5cdCAgICB9XG5cblx0ICAgIGlmIChhZGRyZXNzLmFkZHJlc3MzKSB7XG5cdCAgICBcdGh0bWxjb250ZW50ICs9ICc8ZGl2PicgKyBhZGRyZXNzLmFkZHJlc3MzICsgJyA8L2Rpdj4nO1xuXHQgICAgfVxuXG5cdCAgICBodG1sY29udGVudCArPSAnPGRpdj4nICsgYWRkcmVzcy5jaXR5O1xuXG5cdCAgICBpZiAoYWRkcmVzcy5zdGF0ZUNvZGUgJiYgYWRkcmVzcy5zdGF0ZUNvZGUudG9VcHBlckNhc2UoKSAhPSAnT1RIRVInKSB7XG5cdCAgICBcdGh0bWxjb250ZW50ICs9ICcgJyArIGFkZHJlc3Muc3RhdGVDb2RlO1xuXHQgICAgfVxuXG5cdCAgICBodG1sY29udGVudCArPSAnICcgKyBhZGRyZXNzLnBvc3RhbENvZGU7XG5cdFx0aHRtbGNvbnRlbnQgKz0gJyAnICsgYWRkcmVzcy5jb3VudHJ5Q29kZSArICc8L2Rpdj4nO1xuXHRcdGlmIChhZGRyZXNzLnBob25lKSB7XG5cdFx0XHRodG1sY29udGVudCArPSAnPGRpdj4nICsgYWRkcmVzcy5waG9uZSArICc8L2Rpdj4nO1xuXHRcdH1cblxuXHQgICAgaWYgKGFkZHJlc3MuZW1haWwpIHtcblx0ICAgIFx0aHRtbGNvbnRlbnQgKz0gJzxkaXYgY2xhc3M9XCJiaWxsaW5nLWVtYWlsLWFkZHJlc3NcIj4nICsgYWRkcmVzcy5lbWFpbCArICc8L2Rpdj4nO1xuXHRcdH1cblx0XHRodG1sY29udGVudCArPSAnPC9kaXY+JztcblxuXHQgICAgaHRtbGNvbnRlbnQgKz0gZWRpdEJ1dHRvbjtcblx0ICAgIGh0bWxjb250ZW50ICs9IGFkZE5ld0J1dHRvbjtcbiAgICB9XG5cbiAgICBodG1sVGV4dC5odG1sKGh0bWxjb250ZW50KTtcblxuICAgIHJldHVybiBodG1sVGV4dDtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBIZWxwZXIgbWV0aG9kIHdoaWNoIGNvbnN0cnVjdHMgYSBVUkwgZm9yIGFuIEFKQVggcmVxdWVzdCB1c2luZyB0aGVcbiAqIGVudGVyZWQgYWRkcmVzcyBpbmZvcm1hdGlvbiBhcyBVUkwgcmVxdWVzdCBwYXJhbWV0ZXJzLlxuICovXG5mdW5jdGlvbiBnZXRTaGlwcGluZ01ldGhvZFVSTCgkZm9ybSwgdXJsLCBleHRyYVBhcmFtcykge1xuICAgIHZhciBwYXJhbXMgPSB7XG5cdFx0aXNTdG9yZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfaXNTdG9yZVwiXScpLnByb3AoJ2NoZWNrZWQnKSxcblx0XHRteVN0b3JlSUQ6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX215U3RvcmVJRFwiXScpLnZhbCgpLFxuICAgIFx0YWRkcmVzczE6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCksXG4gICAgICAgIGFkZHJlc3MyOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpLFxuICAgICAgICBhZGRyZXNzMzogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczNcIl0nKS52YWwoKSxcbiAgICAgICAgY291bnRyeUNvZGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfY291bnRyeVwiXScpLnZhbCgpLFxuICAgICAgICBzdGF0ZUNvZGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKSxcbiAgICAgICAgcG9zdGFsQ29kZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCksXG4gICAgICAgIGNpdHk6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoKVxuICAgIH07XG5cbiAgICByZXR1cm4gdXRpbC5hcHBlbmRQYXJhbXNUb1VybCh1cmwsICQuZXh0ZW5kKHBhcmFtcywgZXh0cmFQYXJhbXMpKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCRmb3JtLCBkb1VwZGF0ZVN1bW1hcnksIGlzTXlTdG9yZSwgZG9EYXRhTGF5ZXJQdXNoLCAkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZCkge1xuXHRpZiAoISRzaGlwcGluZ01ldGhvZExpc3QgfHwgJHNoaXBwaW5nTWV0aG9kTGlzdC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG5cdFxuXHR2YXIgc2hpcHBpbmdNZXRob2RMaXN0RGF0YSA9IHtcblx0XHRzZWxlY3RlZFBheW1lbnRNZXRob2Q6ICRwYXltZW50Rm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbCgpXG5cdH1cblxuXHR2YXIgJHNoaXBUb1N0b3JlT3B0aW9uSW5BZGRyZXNzUGFuZWwgPSAkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvcicpO1xuXHRpZiAoJHNoaXBUb1N0b3JlT3B0aW9uSW5BZGRyZXNzUGFuZWwubGVuZ3RoID4gMCkge1xuXHRcdGlmICgkc2hpcFRvU3RvcmVPcHRpb25JbkFkZHJlc3NQYW5lbC5maW5kKCdpbnB1dDpjaGVja2VkJykudmFsKCkgPT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuU3RvcmUpIHtcblx0XHRcdHNoaXBwaW5nTWV0aG9kTGlzdERhdGEuU2hpcFRvU3RvcmVPbmx5ID0gdHJ1ZTtcblxuXHRcdFx0aWYgKGRhdGFCdWZmZXJbQ2hlY2tvdXRDb25zdGFudHMuVXNlci5TZWxlY3RlZFN0b3JlU2hpcHBpbmdNZXRob2RdKSB7XG5cdFx0XHRcdHNoaXBwaW5nTWV0aG9kTGlzdERhdGEuU2VsZWN0U2hpcHBpbmdNZXRob2QgPSBkYXRhQnVmZmVyW0NoZWNrb3V0Q29uc3RhbnRzLlVzZXIuU2VsZWN0ZWRTdG9yZVNoaXBwaW5nTWV0aG9kXTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKCRzaGlwVG9TdG9yZU9wdGlvbkluQWRkcmVzc1BhbmVsLmZpbmQoJ2lucHV0OmNoZWNrZWQnKS52YWwoKSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikge1xuXHRcdFx0c2hpcHBpbmdNZXRob2RMaXN0RGF0YS5TaGlwVG9TdG9yZUV4Y2x1ZGUgPSB0cnVlO1xuXG5cdFx0XHRpZiAoZGF0YUJ1ZmZlcltDaGVja291dENvbnN0YW50cy5Vc2VyLlNlbGVjdGVkQ3VzdG9tZXJTaGlwcGluZ01ldGhvZF0pIHtcblx0XHRcdFx0c2hpcHBpbmdNZXRob2RMaXN0RGF0YS5TZWxlY3RTaGlwcGluZ01ldGhvZCA9IGRhdGFCdWZmZXJbQ2hlY2tvdXRDb25zdGFudHMuVXNlci5TZWxlY3RlZEN1c3RvbWVyU2hpcHBpbmdNZXRob2RdO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmIChpc015U3RvcmUpIHtcblx0XHRzaGlwcGluZ01ldGhvZExpc3REYXRhLlNoaXBUb1N0b3JlT25seSA9IHRydWU7XG5cdH1cblxuXHR2YXIgc2hpcHBpbmdNZXRob2RMaXN0VXJsID0gZ2V0U2hpcHBpbmdNZXRob2RVUkwoJGZvcm0sIFVybHMuc2hpcHBpbmdNZXRob2RzTGlzdCk7XG5cdCRzaGlwcGluZ01ldGhvZExpc3QubG9hZChzaGlwcGluZ01ldGhvZExpc3RVcmwsIHNoaXBwaW5nTWV0aG9kTGlzdERhdGEsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgc2VsZWN0ZWRTdG9yZSA9ICRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQubXlTdG9yZUlEIGlucHV0JykudmFsKCk7XG5cdFx0dmFyICRzaGlwVG9TdG9yZVNoaXBwaW5nTWV0aG9kcztcblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkFnZW50U3RvcmUgJiYgb3B0aW9ucy5BZ2VudFN0b3JlLlN0b3JlU2hpcHBpbmdBZGRyZXNzT25seSkge1xuXHRcdFx0JHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzID0gJCgnW3NoaXBwaW5nLW1ldGhvZF0nKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzID0gJCgnW3NoaXBwaW5nLW1ldGhvZF1baXMtc2hpcC10by1zdG9yZT1cInRydWVcIl0nKTtcblx0XHR9XG5cblx0XHRpZiAoJHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBzZWxlY3RlZFN0b3JlRnJvbVNoaXBwaW5nTWV0aG9kID0gJHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzLmZpbmQoJy5zdG9yZS1zZWxlY3RvciBzZWxlY3QnKS52YWwoKTtcblxuXHRcdFx0aWYgKHNlbGVjdGVkU3RvcmVGcm9tU2hpcHBpbmdNZXRob2QgJiYgc2VsZWN0ZWRTdG9yZUZyb21TaGlwcGluZ01ldGhvZCAhPSBzZWxlY3RlZFN0b3JlICYmICRzaGlwVG9TdG9yZVNoaXBwaW5nTWV0aG9kcy5maW5kKCcuaW5wdXQtcmFkaW8nKS5pcygnOmNoZWNrZWQnKSkge1xuXHRcdFx0XHRzZWxlY3RlZFN0b3JlID0gc2VsZWN0ZWRTdG9yZUZyb21TaGlwcGluZ01ldGhvZDtcblx0XHRcdFx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnLmZvcm1maWVsZC5teVN0b3JlSUQgaW5wdXQnKS52YWwoc2VsZWN0ZWRTdG9yZSk7XG5cdFx0XHRcdHNldE9QQ0FkZHJlc3Moc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yLCAnZHdmcm1fc2hpcHBpbmdhZGRyZXNzX3NhdmVvcGNhZGRyZXNzJykudGhlbihmdW5jdGlvbiAoZGF0YSkgeyB9KTtcblx0XHRcdH1cblxuXHRcdFx0YnVpbGRTaGlwVG9TdG9yZURldGFpbHMoJHNoaXBUb1N0b3JlU2hpcHBpbmdNZXRob2RzKTtcblx0XHR9XG5cblx0XHRpZiAoc2VsZWN0ZWRTdG9yZSAmJiBkYXRhQnVmZmVyICYmIGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10pIHtcblx0XHRcdHZhciBzZWxlY3RlZFN0b3JlSW5CdWZmZXIgPSBkYXRhQnVmZmVyWydteXN0b3Jlc19hZGRyZXNzTGlzdCddLmZpbHRlcihmdW5jdGlvbiAoYWRkcmVzcykge1xuXHRcdFx0XHRyZXR1cm4gYWRkcmVzcy5teVN0b3JlSUQgPT0gc2VsZWN0ZWRTdG9yZTtcblx0XHRcdH0pWzBdO1xuXG5cdFx0XHRpZiAoc2VsZWN0ZWRTdG9yZUluQnVmZmVyICYmIHNlbGVjdGVkU3RvcmVJbkJ1ZmZlci5VVUlEICE9ICQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpLnZhbCgpKSB7XG5cdFx0XHRcdCQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpLnZhbChzZWxlY3RlZFN0b3JlSW5CdWZmZXIuVVVJRCk7XG5cdFx0XHRcdHZhciBzaGlwcGluZ0FkZHJlc3NUeXBlID0gZ2V0U2hpcHBpbmdBZGRyZXNzVHlwZSgpO1xuXHRcdFx0XHRpZiAoc2hpcHBpbmdBZGRyZXNzVHlwZSA9PSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5TdG9yZSkge1xuXHRcdFx0XHRcdCQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHRcdGRvVXBkYXRlU3VtbWFyeSA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdCRzaGlwcGluZ01ldGhvZExpc3QuZmFkZUluKCdmYXN0Jyk7XG5cblx0XHRpZiAoZG9VcGRhdGVTdW1tYXJ5KSB7XG5cdFx0XHR1cGRhdGVTdW1tYXJ5KCk7XG5cdFx0fVxuXHRcdFxuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy5zaGlwcGluZy1tZXRob2QtdG9vbHRpcCcsXG5cdFx0XHR0b29sdGlwQ2xhc3M6ICdzaGlwcGluZy1tZXRob2QtdG9vbHRpcCdcblx0XHR9LCAkKCdbc2hpcHBpbmctbWV0aG9kXScpKTtcblx0XHR0b29sdGlwLmluaXQoe1xuXHRcdFx0aXRlbXM6ICcudG9vbHRpcC5SZXdhcmRzQ3JlZGl0Jyxcblx0XHRcdHRvb2x0aXBDbGFzczogJ1Jld2FyZHNDcmVkaXQnXG5cdFx0fSwgJCgnW3BheW1lbnQtbWV0aG9kPVwiUkVXQVJEU19DUkVESVRcIl0nKSk7XG5cdFx0dG9vbHRpcC5pbml0KHtcblx0XHRcdGl0ZW1zOiAnLnRvb2x0aXAuTG95YWx0eUNyZWRpdCcsXG5cdFx0XHR0b29sdGlwQ2xhc3M6ICdMb3lhbHR5Q3JlZGl0J1xuXHRcdH0sICQoJ1twYXltZW50LW1ldGhvZD1cIkxPWUFMVFlfQ1JFRElUXCJdJykpO1xuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy50b29sdGlwJ1xuXHRcdH0sICQoJy5mb3JtLXJvdy5jdm4nKSk7XG5cblx0XHR2YXIgaXNTdG9yZUFkZHJlc3MgPSBpc1NoaXBUb1N0b3JlRW5hYmxlZCgpO1xuXHRcdHNldFNoaXBUb1N0b3JlKGlzU3RvcmVBZGRyZXNzKTtcblxuXHRcdGlmIChkb0RhdGFMYXllclB1c2gpIHtcblx0XHRcdHB1c2hEYXRhTGF5ZXJGb3JTaGlwcGluZ01ldGhvZHMoJHNoaXBwaW5nTWV0aG9kTGlzdCwgJHNlbGVjdGVkU2hpcHBpbmdNZXRob2QpO1xuXHRcdH1cblx0fSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gdXBkYXRlcyB0aGUgb3JkZXIgc3VtbWFyeSBiYXNlZCBvbiBhIHBvc3NpYmx5IHJlY2FsY3VsYXRlZCBiYXNrZXQgYWZ0ZXIgYSBzaGlwcGluZyBwcm9tb3Rpb24gaGFzIGJlZW4gYXBwbGllZFxuICovXG5mdW5jdGlvbiB1cGRhdGVTdW1tYXJ5KCkge1xuICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlJywge1xuXHRcdCdFdmVudFRyaWdnZXJzJzoge1xuXHRcdFx0J3VwZGF0ZS1zaGlwcGluZyc6IGZhbHNlXG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZ2V0U2hpcHBpbmdBZGRyZXNzVHlwZSgpIHtcblx0dmFyIHNoaXBwaW5nQWRkcmVzc1R5cGUgPSAkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dDpjaGVja2VkJykudmFsKCk7XG5cdGlmICghc2hpcHBpbmdBZGRyZXNzVHlwZSkge1xuXHRcdHNoaXBwaW5nQWRkcmVzc1R5cGUgPSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcjtcblx0fVxuXHRyZXR1cm4gc2hpcHBpbmdBZGRyZXNzVHlwZTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyTXlTdG9yZXNBZGRyZXNzU2VsZWN0b3IocGFyYW1ldGVycykge1xuXHR2YXIgdGVtcGxhdGVTZXR0aW5ncyA9IHtcbiAgICBcdGludGVycG9sYXRlOiAve3soW1xcc1xcU10rPyl9fS9nXG4gICAgfTtcblxuICAgIHZhciB0ZW1wbGF0ZXMgPSBbXTtcblx0dGVtcGxhdGVzWydvcHRpb24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3Mtc2VsZWN0b3Itb3B0aW9uJykuaHRtbCgpLCB0ZW1wbGF0ZVNldHRpbmdzKTtcblxuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdHVybDogVXJscy5nZXRNeVN0b3Jlc0FkZHJlc3NMaXN0LFxuXHRcdGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG5cdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoeyBzdG9yZVF1ZXJ5OiBTdG9yZVF1ZXJ5RmlsdGVycy5TaGlwVG9TdG9yZUVuYWJsZWQgfSksXG5cdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHR2YXIgaHRtbCA9IFtdO1xuXHRcdFx0aHRtbFsnb3B0aW9ucyddID0gJyc7XG5cblx0XHRcdGRhdGFCdWZmZXJbJ215c3RvcmVzX2FkZHJlc3NMaXN0J10gPSBkYXRhLmFkZHJlc3Nlcztcblx0XHRcdGRhdGFCdWZmZXJbJ3N0b3JlX25hbWVfbG9va3VwJ10gPSB7fTtcblx0XHRcdGRhdGEuYWRkcmVzc2VzLm1hcChmdW5jdGlvbiAoZWxlbWVudCkge1xuXHRcdFx0XHRkYXRhQnVmZmVyWydzdG9yZV9uYW1lX2xvb2t1cCddW2VsZW1lbnQubXlTdG9yZUlEXSA9IGVsZW1lbnQuZnVsbE5hbWU7XG5cdFx0XHR9KTtcblxuXHRcdFx0dmFyIGlzU3RvcmVBZGRyZXNzU2VsZWN0ZWQgPSBmYWxzZTtcblx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBkYXRhLmFkZHJlc3Nlcy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdFx0dmFyIGFkZHJlc3MgPSBkYXRhLmFkZHJlc3Nlc1tpbmRleF07XG5cblx0XHRcdFx0aWYgKGFkZHJlc3MuaXNTZWxlY3RlZCkge1xuXHRcdFx0XHRcdGlzU3RvcmVBZGRyZXNzU2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgb3B0aW9uRGF0YSA9IF8uZXh0ZW5kKGFkZHJlc3MsIHtcblx0XHRcdFx0XHRpZDogYWRkcmVzcy5VVUlELFxuXHRcdFx0XHRcdGNzc0NsYXNzOiAnJyxcblx0XHRcdFx0XHRzZWxlY3RlZDogYWRkcmVzcy5pc1NlbGVjdGVkID8gJ3NlbGVjdGVkJyA6ICcnLFxuXHRcdFx0XHRcdHRleHQ6IGFkZHJlc3MubGFiZWxUZXh0XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdG9wdGlvbkRhdGEuSUQgPSBhZGRyZXNzLm15U3RvcmVJRDtcblx0XHRcdFx0aHRtbFsnb3B0aW9ucyddICs9IHRlbXBsYXRlc1snb3B0aW9uJ10ob3B0aW9uRGF0YSk7XG5cdFx0XHR9XG5cblx0XHRcdCQoJyNteXN0b3Jlc19hZGRyZXNzTGlzdCcpLmh0bWwoaHRtbFsnb3B0aW9ucyddKTtcblxuXHRcdFx0aWYgKGlzU3RvcmVBZGRyZXNzU2VsZWN0ZWQpIHtcblx0XHRcdFx0c2V0U2hpcFRvU3RvcmUodHJ1ZSk7XG5cdFx0XHRcdCQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0W3ZhbHVlPVwiJyArIFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLlN0b3JlICsgJ1wiXScpLmNsaWNrKCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChwYXJhbWV0ZXJzICYmIHBhcmFtZXRlcnMuY2FsbGJhY2spIHtcblx0XHRcdFx0cGFyYW1ldGVycy5jYWxsYmFjaygpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckFkZHJlc3NTZWxlY3RvcihwYXJhbWV0ZXJzKSB7XG5cdHZhciB0ZW1wbGF0ZVNldHRpbmdzID0ge1xuICAgIFx0aW50ZXJwb2xhdGU6IC97eyhbXFxzXFxTXSs/KX19L2dcbiAgICB9O1xuXG4gICAgdmFyIHRlbXBsYXRlcyA9IFtdO1xuICAgIHRlbXBsYXRlc1snc2VsZWN0b3InXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWFkZHJlc3Mtc2VsZWN0b3InKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1snb3B0aW9uJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1hZGRyZXNzLXNlbGVjdG9yLW9wdGlvbicpLmh0bWwoKSwgdGVtcGxhdGVTZXR0aW5ncyk7XG5cblx0JC5hamF4KHtcblx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHR1cmw6IFVybHMuZ2V0QWRkcmVzc0xpc3QsXG5cdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeSh7IHN0b3JlUXVlcnk6IFN0b3JlUXVlcnlGaWx0ZXJzLlNoaXBUb1N0b3JlRW5hYmxlZCB9KSxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdHZhciBodG1sID0gW107XG5cdFx0XHR2YXIgaGFzQWRkcmVzc0Jvb2tBZGRyZXNzZXMgPSBmYWxzZTtcblx0XHRcdHZhciBzZWxlY3RlZEFkZHJlc3NJRCA9IG51bGw7XG5cblx0XHRcdGRhdGFCdWZmZXJbcGFyYW1ldGVycy5pZF0gPSBkYXRhLmFkZHJlc3NlcztcblxuXHRcdFx0dmFyIGlzQWRkcmVzc1NlbGVjdGVkSW5EYXRhID0gZmFsc2U7XG5cdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgZGF0YS5hZGRyZXNzZXMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdHZhciBhZGRyZXNzID0gZGF0YS5hZGRyZXNzZXNbaW5kZXhdO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKGFkZHJlc3MuaXNTZWxlY3RlZCkge1xuXHRcdFx0XHRcdGlzQWRkcmVzc1NlbGVjdGVkSW5EYXRhID0gdHJ1ZTtcblx0XHRcdFx0XHRzZWxlY3RlZEFkZHJlc3NJRCA9IGFkZHJlc3MuSUQ7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aHRtbFsnb3B0aW9ucyddID0gJyc7XG5cdFx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgZGF0YS5hZGRyZXNzZXMubGVuZ3RoOyBpbmRleCsrKSB7XG5cdFx0XHRcdHZhciBhZGRyZXNzID0gZGF0YS5hZGRyZXNzZXNbaW5kZXhdO1xuXG5cdFx0XHRcdGlmIChhZGRyZXNzLmlzU2hpcHBpbmdBZGRyZXNzKSB7XG5cdFx0XHRcdFx0dmFyIGFkZHJlc3NJZCA9IGFkZHJlc3Mua2V5ID8gYWRkcmVzcy5rZXkgOiBhZGRyZXNzLklEO1xuXHRcdFx0XHRcdHZhciBpc1NlbGVjdGVkID0gZmFsc2U7XG5cblx0XHRcdFx0XHRpZiAoISRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCkgJiYgJCgnW2hhcy13YXJlaG91c2Utc2hpcG1lbnRdJykuYXR0cignaGFzLXdhcmVob3VzZS1zaGlwbWVudCcpID09ICd0cnVlJykge1xuXHRcdFx0XHRcdFx0aWYgKCFpc0FkZHJlc3NTZWxlY3RlZEluRGF0YSkge1xuXHRcdFx0XHRcdFx0XHRpZiAoIXNlbGVjdGVkQWRkcmVzc0lEICYmIHBhcmFtZXRlcnMuY3VycmVudEFkZHJlc3NlcyAmJiBwYXJhbWV0ZXJzLmN1cnJlbnRBZGRyZXNzZXMubGVuZ3RoID4gMCAmJiBwYXJhbWV0ZXJzLmN1cnJlbnRBZGRyZXNzZXMuaW5kZXhPZihhZGRyZXNzLlVVSUQpID49IDApIHtcblx0XHRcdFx0XHRcdFx0XHRpc1NlbGVjdGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRzZWxlY3RlZEFkZHJlc3NJRCA9IGFkZHJlc3MuSUQ7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIXNlbGVjdGVkQWRkcmVzc0lEICYmIHBhcmFtZXRlcnMuc2VsZWN0ZWQgJiYgYWRkcmVzcy5JRCA9PSBwYXJhbWV0ZXJzLnNlbGVjdGVkICYmIHBhcmFtZXRlcnMuc2VsZWN0ZWQgIT0gXCJuZXdcIikge1xuXHRcdFx0XHRcdFx0XHRcdGlzU2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkQWRkcmVzc0lEID0gYWRkcmVzcy5JRDtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICghc2VsZWN0ZWRBZGRyZXNzSUQgJiYgYWRkcmVzcy5JRCA9PSAkKCcjZHdmcm1fbXVsdGlwbGVzaGlwcGluZ19hZGRyZXNzTGlzdDp2aXNpYmxlIG9wdGlvbicpLnZhbCgpICYmIHBhcmFtZXRlcnMuc2VsZWN0ZWQgIT0gXCJuZXdcIikge1xuXHRcdFx0XHRcdFx0XHRcdGlzU2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdHNlbGVjdGVkQWRkcmVzc0lEID0gYWRkcmVzcy5JRDtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICghc2VsZWN0ZWRBZGRyZXNzSUQgJiYgYWRkcmVzcy5pc0RlZmF1bHQgJiYgcGFyYW1ldGVycy5zZWxlY3RlZCAhPSBcIm5ld1wiKSB7XG5cdFx0XHRcdFx0XHRcdFx0aXNTZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRBZGRyZXNzSUQgPSBhZGRyZXNzLklEO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIG9wdGlvbkRhdGEgPSBfLmV4dGVuZChhZGRyZXNzLCB7XG5cdFx0XHRcdFx0XHRpZDogYWRkcmVzcy5VVUlELFxuXHRcdFx0XHRcdFx0Y3NzQ2xhc3M6ICcnLFxuXHRcdFx0XHRcdFx0c2VsZWN0ZWQ6IGlzU2VsZWN0ZWQgfHwgYWRkcmVzcy5pc1NlbGVjdGVkID8gJ3NlbGVjdGVkJyA6ICcnLFxuXHRcdFx0XHRcdFx0dGV4dDogJygnICsgKCFhZGRyZXNzLmRpc3BsYXlWYWx1ZSA/IGFkZHJlc3NJZCA6IGFkZHJlc3MuZGlzcGxheVZhbHVlKSArICcpICcgKyBhZGRyZXNzLmxhYmVsVGV4dFxuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0aWYgKCFhZGRyZXNzLmlzTXlTdG9yZSkge1xuXHRcdFx0XHRcdFx0aGFzQWRkcmVzc0Jvb2tBZGRyZXNzZXMgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGh0bWxbJ29wdGlvbnMnXSArPSB0ZW1wbGF0ZXNbJ29wdGlvbiddKG9wdGlvbkRhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChoYXNBZGRyZXNzQm9va0FkZHJlc3Nlcykge1xuXHRcdFx0XHRodG1sWydzZWxlY3RvciddID0gdGVtcGxhdGVzWydzZWxlY3RvciddKHtcblx0XHRcdFx0XHRpZDogcGFyYW1ldGVycy5pZCxcblx0XHRcdFx0XHRvcHRpb25zOiBodG1sWydvcHRpb25zJ11cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0dmFyICRodG1sID0gJChodG1sWydzZWxlY3RvciddKTtcblxuXHRcdFx0XHRpZiAoaXNTZWxlY3RlZCB8fCBhZGRyZXNzLmlzU2VsZWN0ZWQpIHtcblx0XHRcdFx0XHQkaHRtbC5maW5kKCdvcHRpb24ucGxhY2Vob2xkZXInKS5yZW1vdmUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQocGFyYW1ldGVycy5lbCkuaHRtbCgkaHRtbCk7XG5cdFx0XHRcdCQocGFyYW1ldGVycy5jb250YWluZXIpLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQocGFyYW1ldGVycy5jb250YWluZXIpLmhpZGUoKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHBhcmFtZXRlcnMgJiYgcGFyYW1ldGVycy5jYWxsYmFjaykge1xuXHRcdFx0XHRwYXJhbWV0ZXJzLmNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcdFxufVxuXG5mdW5jdGlvbiBlZGl0QmlsbGluZ0FkZHJlc3MoKSB7XG5cdCQoJy5iaWxsLWFkZHJlc3MtZmllbGRzJykucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlZCcpLnNob3coKTtcblx0JCgnLmJpbGxpbmctc2VsZWN0LWFkZHJlc3MnKS5oaWRlKCk7XG5cdFxuXHQkKCcuYmlsbGluZy1hZGRyZXNzLXByZXZpZXcnKS5oaWRlKCk7XG5cdCQoJy5iaWxsaW5nLWFkZHJlc3MtZGF0YS5mb3JtLWluZm8nKS5oaWRlKCk7XG5cdFxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLnNob3coKTtcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS5zaG93KCk7XG5cdFxuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5kYXRhKCdoaWRkZW4tZWRpdGFibGUnLCAkKCcuc2hpcHBpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmh0bWwoKS5sZW5ndGggPyB0cnVlIDogZmFsc2UpLmhpZGUoKTtcblx0XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcuc2hpcHBpbmctYWRkcmVzcy1jb250JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHQkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcbn1cblxuZnVuY3Rpb24gZWRpdFNoaXBwaW5nQWRkcmVzcygpIHtcblx0d3JpdGVTaGlwcGluZ0FkZHJlc3NGb3JtVG9CdWZmZXIoKTtcblx0b3BlblNoaXBwaW5nQWRkcmVzc0Zvcm0oKTtcbn1cblxuZnVuY3Rpb24gb3BlblNoaXBwaW5nQWRkcmVzc0Zvcm0oKSB7XG5cdCQoJy5mb3JtLWNoZWNrb3V0LnNoaXBwaW5nLWFkZHJlc3Mtc2VjdGlvbicpLmF0dHIoJ3BhbmVsLW1vZGUnLCAnZWRpdCcpO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybUNvbnRhaW5lci5kYXRhKCdoaWRkZW4tZWRpdGFibGUnLCB0cnVlKS5oaWRlKCk7XG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEnKS5oaWRlKCk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtQ29udGFpbmVyLnNob3coKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0ucmVtb3ZlQ2xhc3MoJ2FkZCBlZGl0JykuYWRkQ2xhc3MoJ2VkaXQnKTtcblx0JHNoaXBwaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXRbbmFtZT1cImFjdGlvblwiXScpLnZhbCgnZWRpdCcpO1xuXHRcdFxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLmhpZGUoKTtcblx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmNzcygnZGlzcGxheScsICdibG9jaycpO1xuXHQkKCcuZm9ybS1jaGVja291dC5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVDbGFzcygnYWN0aXZlJykuZmluZCgnLnNoaXBwaW5nLXBheW1lbnQtY29udCcpLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0XG5cdCQoJy5zaGlwcGluZy1zZWxlY3QtYWRkcmVzcycpLmhpZGUoKTtcblx0JCgnLmVkaXRhZGRyZXNzLXNoaXBwaW5nJykucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlZCcpO1xufVxuXG5mdW5jdGlvbiBzZXRTaGlwVG9TdG9yZShpc1N0b3JlQWRkcmVzcykge1xuXHQkc2VjdGlvbkNoZWNrb3V0LmF0dHIoJ2lzLW15LXN0b3JlJywgaXNTdG9yZUFkZHJlc3MpO1xuXHQkKCcjZHdmcm1fc2hpcHBpbmdhZGRyZXNzX2lzU3RvcmUnKS5wcm9wKCdjaGVja2VkJywgaXNTdG9yZUFkZHJlc3MpO1xufVxuXG5mdW5jdGlvbiBpc1NoaXBUb1N0b3JlRW5hYmxlZCgpIHtcblx0cmV0dXJuICQoJyNkd2ZybV9zaGlwcGluZ2FkZHJlc3NfaXNTdG9yZScpLnByb3AoJ2NoZWNrZWQnKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRTaGlwVG9TdG9yZURldGFpbHMoJHNoaXBwaW5nTWV0aG9kcykge1xuXHQkc2hpcHBpbmdNZXRob2RzLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHNoaXBwaW5nTWV0aG9kID0gJChlbGVtZW50KTtcblx0XHR2YXIgJHNlbGVjdGVkU3RvcmUgPSAkc2hpcHBpbmdNZXRob2QuZmluZCgnLnN0b3JlLXNlbGVjdG9yIG9wdGlvbjpjaGVja2VkJyk7XG5cdFx0dmFyIHN0b3JlU2VsZWN0b3JDb3VudCA9ICRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtc2VsZWN0b3Igb3B0aW9uJykubGVuZ3RoO1xuXHRcdHZhciBzdG9yZURhdGEgPSAkc2VsZWN0ZWRTdG9yZS5kYXRhKCdhZGRyZXNzJyk7XG5cdFx0aWYgKHN0b3JlRGF0YSAmJiBzdG9yZURhdGEuYWRkcmVzczEpIHtcblx0XHRcdHZhciBzdG9yZUh0bWwgPSAnPHA+JyArIHN0b3JlRGF0YS5uYW1lICsgJzwvcD4nICtcblx0XHRcdFx0XHRcdFx0JzxwPicgKyBzdG9yZURhdGEuYWRkcmVzczEgKyAnPC9wPic7XG5cdFx0XHRpZiAoc3RvcmVEYXRhLmFkZHJlc3MyKSB7XG5cdFx0XHRcdHN0b3JlSHRtbCArPSAnPHA+JyArIHN0b3JlRGF0YS5hZGRyZXNzMiArICc8L3A+Jztcblx0XHRcdH1cblx0XHRcdHN0b3JlSHRtbCArPSAnPHA+JyArIHN0b3JlRGF0YS5jaXR5ICsgJywgJyArIHN0b3JlRGF0YS5zdGF0ZSArICcgJyArIHN0b3JlRGF0YS5wb3N0YWxDb2RlICsgJzwvcD4nO1xuXHRcblx0XHRcdGlmIChzdG9yZVNlbGVjdG9yQ291bnQgPiAxICYmIFNpdGVQcmVmZXJlbmNlcy5FTkFCTEVfU0hJUF9UT19TVE9SRV9TRUxFQ1RJT04gJiYgIWlzU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5KSB7XG5cdFx0XHRcdHN0b3JlSHRtbCArPSAnPGEgY2xhc3M9XCJhY3Rpb24gY2hhbmdlXCIgdGFiaW5kZXg9XCIwXCI+Q2hhbmdlIFN0b3JlPC9hPic7XG5cdFx0XHR9XG5cblx0XHRcdCRzaGlwcGluZ01ldGhvZC5maW5kKCcuc3RvcmUtZGV0YWlscycpLmh0bWwoc3RvcmVIdG1sKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHNlbGVjdHMgYSBzaGlwcGluZyBtZXRob2QgZm9yIHRoZSBkZWZhdWx0IHNoaXBtZW50IGFuZCB1cGRhdGVzIHRoZSBzdW1tYXJ5IHNlY3Rpb24gb24gdGhlIHJpZ2h0IGhhbmQgc2lkZVxuICogQHBhcmFtXG4gKi9cbmZ1bmN0aW9uIHNlbGVjdFNoaXBwaW5nTWV0aG9kKHNoaXBtZW50SUQsIHNoaXBwaW5nTWV0aG9kSUQsIGlzU2hpcFRvU3RvcmUsICRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kKSB7XG4gICAgdmFyIHNoaXBwaW5nQWRkcmVzc1R5cGUgPSBnZXRTaGlwcGluZ0FkZHJlc3NUeXBlKCk7XG5cdGlmIChzaGlwcGluZ0FkZHJlc3NUeXBlID09IFNpdGVDb25zdGFudHMuQWRkcmVzc1R5cGVzLkN1c3RvbWVyKSB7XG5cdFx0ZGF0YUJ1ZmZlcltDaGVja291dENvbnN0YW50cy5Vc2VyLlNlbGVjdGVkQ3VzdG9tZXJTaGlwcGluZ01ldGhvZF0gPSBzaGlwcGluZ01ldGhvZElEO1xuXHR9IGVsc2UgaWYgKHNoaXBwaW5nQWRkcmVzc1R5cGUgPT0gU2l0ZUNvbnN0YW50cy5BZGRyZXNzVHlwZXMuU3RvcmUpIHtcblx0XHRkYXRhQnVmZmVyW0NoZWNrb3V0Q29uc3RhbnRzLlVzZXIuU2VsZWN0ZWRTdG9yZVNoaXBwaW5nTWV0aG9kXSA9IHNoaXBwaW5nTWV0aG9kSUQ7XG5cdH1cblxuXHRpZiAoaXNTaGlwVG9TdG9yZSB8fCBpc1N0b3JlU2hpcHBpbmdBZGRyZXNzT25seSkge1xuXHRcdHNldFNoaXBUb1N0b3JlKHRydWUpOyBcblx0fSBlbHNlIHtcblx0XHRzZXRTaGlwVG9TdG9yZShmYWxzZSk7XG5cdH1cblxuICAgIC8vIGF0dGVtcHQgdG8gc2V0IHNoaXBwaW5nIG1ldGhvZFxuICAgIHZhciB1cmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTCgkc2hpcHBpbmdBZGRyZXNzRm9ybSwgVXJscy5zZWxlY3RTaGlwcGluZ01ldGhvZHNMaXN0LCB7c2hpcG1lbnRJRDogc2hpcG1lbnRJRCwgc2hpcHBpbmdNZXRob2RJRDogc2hpcHBpbmdNZXRob2RJRH0pO1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIC8vIGRpc3BsYXkgcHJvbW90aW9uIGluIFVJIGFuZCB1cGRhdGUgdGhlIHN1bW1hcnkgc2VjdGlvbixcbiAgICAgICAgICAgIC8vIGlmIHNvbWUgcHJvbW90aW9ucyB3ZXJlIGFwcGxpZWRcbiAgICAgICAgICAgICQoJy5zaGlwcGluZ3Byb21vdGlvbnMnKS5lbXB0eSgpO1xuXG4gICAgICAgICAgICAkKCdbbmFtZSo9XCJfc2hpcHBpbmdNZXRob2RJRFwiXScpLnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpO1xuICAgICAgICAgICAgdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCRzaGlwcGluZ0FkZHJlc3NGb3JtLCB0cnVlLCBudWxsLCB0cnVlLCAkc2VsZWN0ZWRTaGlwcGluZ01ldGhvZCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIHNldCBhZGRyZXNzIGRhdGFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgcHJlc2VudCBhZGRyZXNzIG9iamVjdFxuICogQHBhcmFtIHtFbGVtZW50fSBBY3Rpb24gbmFtZSB0byBhcHBseSB0byBmb3JtXG4gKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAqL1xudmFyIHNldE9QQ0FkZHJlc3MgPSBmdW5jdGlvbiAoZm9ybSwgbmFtZSkge1xuXHR2YXIgJGZvcm0gPSAkKGZvcm0pO1xuXHR2YXIgdXJsID0gKGZvcm0gPT0gJyNiaWxsaW5nQWRkcmVzc0Zvcm0nKSA/IFVybHMuc2V0T3BjQWRkcmVzcyA6ICRmb3JtLmF0dHIoJ2FjdGlvbicpO1xuXHR2YXIgc2FuaXRpemVkRm9ybURhdGEgPSB7fTtcblx0dmFyIHNlcmlhbGl6ZWRGb3JtRGF0YUFycmF5ID0gJGZvcm0uc2VyaWFsaXplQXJyYXkoKTtcblx0dmFyIGhhc0NvdW50cnlGaWVsZCA9IGZhbHNlO1xuXHRmb3IgKHZhciBzZXJpYWxpemVkRm9ybURhdGFLZXkgaW4gc2VyaWFsaXplZEZvcm1EYXRhQXJyYXkpIHtcblx0XHR2YXIgc2VyaWFsaXplZEZvcm1FbGVtZW50ID0gc2VyaWFsaXplZEZvcm1EYXRhQXJyYXlbc2VyaWFsaXplZEZvcm1EYXRhS2V5XTtcblx0XHRpZiAoc2VyaWFsaXplZEZvcm1FbGVtZW50ICYmIHNlcmlhbGl6ZWRGb3JtRWxlbWVudC5uYW1lICYmIHNhbml0aXplZEZvcm1EYXRhW3NlcmlhbGl6ZWRGb3JtRWxlbWVudC5uYW1lXSkge1xuXHRcdFx0c2FuaXRpemVkRm9ybURhdGFbc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWVdICs9ICcsJyArIHNlcmlhbGl6ZWRGb3JtRWxlbWVudC52YWx1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c2FuaXRpemVkRm9ybURhdGFbc2VyaWFsaXplZEZvcm1FbGVtZW50Lm5hbWVdID0gc2VyaWFsaXplZEZvcm1FbGVtZW50LnZhbHVlO1xuXHRcdH1cblx0XHRpZiAoc2VyaWFsaXplZEZvcm1FbGVtZW50ICYmIHNlcmlhbGl6ZWRGb3JtRWxlbWVudC5uYW1lICYmIHNlcmlhbGl6ZWRGb3JtRWxlbWVudC5uYW1lLmluZGV4T2YoJ19jb3VudHJ5JykgPCAwKSB7XG5cdFx0XHRoYXNDb3VudHJ5RmllbGQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXHRpZiAoaGFzQ291bnRyeUZpZWxkKSB7XG5cdFx0dmFyICRjb3VudHJ5RmllbGQgPSAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfY291bnRyeVwiXScpO1xuXHRcdHNhbml0aXplZEZvcm1EYXRhWyRjb3VudHJ5RmllbGQuYXR0cignbmFtZScpXSA9ICRjb3VudHJ5RmllbGQudmFsKCk7XG5cdH1cblx0c2FuaXRpemVkRm9ybURhdGFbbmFtZV0gPSBuYW1lO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0dXJsOiB1dGlsLmFqYXhVcmwodXJsKSxcblx0XHRcdGRhdGE6IHNhbml0aXplZEZvcm1EYXRhLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0fSxcblx0XHRcdGVycm9yOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdHJlamVjdChkYXRhKTtcblx0XHRcdH1cblx0XHR9KTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXJGb3JTaGlwcGluZ01ldGhvZHMoJHNoaXBwaW5nTWV0aG9kTGlzdCwgJHNlbGVjdGVkU2hpcHBpbmdNZXRob2QpIHtcblx0dmFyICRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kcztcblx0aWYgKCRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kKSB7XG5cdFx0JHNlbGVjdGVkU2hpcHBpbmdNZXRob2RzID0gJHNlbGVjdGVkU2hpcHBpbmdNZXRob2Q7XG5cdH0gZWxzZSB7XG5cdFx0JHNlbGVjdGVkU2hpcHBpbmdNZXRob2RzID0gJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCdpbnB1dFt0eXBlPVwicmFkaW9cIl06Y2hlY2tlZCcpO1xuXHR9XG5cdCRzZWxlY3RlZFNoaXBwaW5nTWV0aG9kcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHNoaXBwaW5nTWV0aG9kID0gJHRoaXMuY2xvc2VzdCgnW3NoaXBwaW5nLW1ldGhvZF0nKTtcblx0XHR2YXIgZGF0YU9iamVjdCA9IHtcblx0XHRcdHZhbHVlOiBwYXJzZUZsb2F0KCRzaGlwcGluZ01ldGhvZC5hdHRyKCdhbW91bnQnKSksXG5cdFx0XHRzaGlwcGluZ190aWVyOiAkc2hpcHBpbmdNZXRob2QuYXR0cignc2hpcHBpbmctbWV0aG9kJylcblx0XHR9XG5cblx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdBZGRTaGlwcGluZ0luZm8nLCBkYXRhT2JqZWN0LCB7IENvbnRhaW5lclNlbGVjdG9yOiAnLm9yZGVyLWl0ZW1bc2hpcG1lbnQ9XCInICsgJHNoaXBwaW5nTWV0aG9kLmNsb3Nlc3QoJ2Zvcm0nKS5hdHRyKCdzaGlwbWVudCcpICsgJ1wiXScgfSkuY2F0Y2goZnVuY3Rpb24oKSB7fSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTaGlwcGluZ1Jlc3RyaWN0aW9ucyhkYXRhKSB7XG5cdCQoJy5zaGlwcGluZy1hZGRyZXNzLWNvbnQnKS5maW5kKCc+IC5lcnJvcicpLnJlbW92ZSgpO1xuXHR2YXIgaGFzU2hpcHBpbmdSZXN0cmljdGlvbnMgPSBkYXRhLnN0YXR1cyA9PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcic7XG5cdGlmIChoYXNTaGlwcGluZ1Jlc3RyaWN0aW9ucykge1xuXHRcdG9wZW5SZXN0cmljdGlvbnNQb3B1cChkYXRhKTtcblx0fVxuXG5cdHJldHVybiBoYXNTaGlwcGluZ1Jlc3RyaWN0aW9ucztcbn1cblxuZnVuY3Rpb24gb3BlblJlc3RyaWN0aW9uc1BvcHVwKGRhdGEpIHtcblx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cdHZhciBwb3B1cCA9IHJlcXVpcmUoJy4uLy4uL3BvcHVwJyk7XG5cdFxuXHR2YXIgcmVzdHJpY3Rpb25MaXN0ID0gJyc7XG5cdGlmIChwYXlsb2FkLmxpc3QgJiYgcGF5bG9hZC5saXN0Lmxlbmd0aCA+IDApIHtcblx0XHR2YXIgbGlzdCA9ICQubWFwKHBheWxvYWQubGlzdCwgZnVuY3Rpb24gKGVsKSB7XG5cdFx0XHR2YXIgcmVzdHJpY3Rpb25OYW1lID0gZWwubmFtZSA/IGVsLm5hbWUgKyAnOjxici8+JyA6ICcnO1xuXHRcdFx0XG5cdFx0XHRyZXR1cm4gJzxsaT4nICsgcmVzdHJpY3Rpb25OYW1lICsgZWwubWVzc2FnZSArICc8L2xpPic7XG5cdFx0fSkuam9pbignJyk7XG5cdFx0XG5cdFx0cmVzdHJpY3Rpb25MaXN0ID0gJzx1bCBjbGFzcz1cInNoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cF9fbGlzdFwiPicgKyBsaXN0ICsgJzwvdWw+Jztcblx0fVxuXHRcblx0cG9wdXAuaW5pdCh7XG5cdFx0dGl0bGU6IHBheWxvYWQudGl0bGUsXG5cdFx0Y29udGVudDogcGF5bG9hZC5tZXNzYWdlICsgcmVzdHJpY3Rpb25MaXN0XG5cdH0pLnNob3dQb3B1cCgpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJPcHRpb25zKG9wdGlvblBhcmVudCwgb3B0aW9uc1N0b3JlSWQpIHtcblx0dmFyIG9wdGlvbnNIdG1sO1xuXHR2YXIgb3B0aW9uc1N0b3JlT3B0aW9ucyA9ICQob3B0aW9uc1N0b3JlSWQgKyAnIG9wdGlvbjpzZWxlY3RlZCcpLmRhdGEoJ29wdGlvbnMnKTtcblx0dmFyIHN0YXRlc0xpc3Q7XG5cdFxuXHRpZiAob3B0aW9uc1N0b3JlT3B0aW9ucykge1xuXHRcdHN0YXRlc0xpc3QgPSBKU09OLnBhcnNlKG9wdGlvbnNTdG9yZU9wdGlvbnMucmVwbGFjZSgvXFwnL2csICdcXFwiJykpO1xuXHRcdFxuXHRcdGlmIChzdGF0ZXNMaXN0Lmxlbmd0aCA+IDEpIHtcblx0XHRcdG9wdGlvbnNIdG1sICs9ICc8b3B0aW9uIHZhbHVlPVwiXCI+JyArIFJlc291cmNlcy5TZWxlY3RQbGFjZWhvbGRlciArICc8L29wdGlvbj4nO1xuXHRcdH1cblx0XHRcblx0XHRzdGF0ZXNMaXN0LmZvckVhY2goZnVuY3Rpb24gKHN0YXRlKSB7XG5cdFx0XHRvcHRpb25zSHRtbCArPSAnPG9wdGlvbiBjbGFzcz1cInNlbGVjdC1vcHRpb25cIiBsYWJlbD1cIicgKyBzdGF0ZS5sYWJlbCArICdcIiB2YWx1ZT1cIicgKyBzdGF0ZS5jb2RlICsgJ1wiPicgKyBzdGF0ZS5sYWJlbCArICc8L29wdGlvbj4nO1xuXHRcdH0pO1xuXG5cdFx0dmFyICRvcHRpb25QYXJlbnQgPSAkKG9wdGlvblBhcmVudCk7XG5cdFx0JG9wdGlvblBhcmVudC5lbXB0eSgpLmFwcGVuZChvcHRpb25zSHRtbCk7XG5cblx0XHRpZiAoc3RhdGVzTGlzdC5sZW5ndGggPD0gMSkge1xuXHRcdFx0JG9wdGlvblBhcmVudC5wcm9wKCdzZWxlY3RlZEluZGV4Jywgc3RhdGVzTGlzdC5sZW5ndGggLSAxKTtcblx0XHRcdCRvcHRpb25QYXJlbnQucmVtb3ZlQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHQkb3B0aW9uUGFyZW50LmNsb3Nlc3QoJy5mb3JtZmllbGQnKS5oaWRlKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRvcHRpb25QYXJlbnQuYWRkQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHQkb3B0aW9uUGFyZW50LmNsb3Nlc3QoJy5mb3JtZmllbGQnKS5zaG93KCk7XG5cdFx0fVxuXHR9XG59XG5cbiQoZG9jdW1lbnQpLm9uKCd1cGRhdGUtc2hpcHBpbmcnLCBmdW5jdGlvbigpIHtcblx0aWYgKCQoJy5zaGlwcGluZy1tZXRob2RzLXNlY3Rpb24nKS5sZW5ndGggPT0gMCkgeyByZXR1cm47IH1cblx0dXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCRzaGlwcGluZ0FkZHJlc3NGb3JtKTtcbn0pO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRvcHRpb25zID0gb3B0aW9uc1BhcmFtZXRlciB8fCB7fTtcblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vTG9iL0FkZHJlc3NWZXJpZmljYXRpb24vQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZycpO1xuXHR9XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc0F1dG9jb21wbGV0ZS5FbmFibGVkKSB7XG5cdFx0QWRkcmVzc0F1dG9jb21wbGV0ZURpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL0xvYi9BZGRyZXNzQXV0b2NvbXBsZXRlL0FkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cnKTtcblx0fVxuXG5cdGlzU3RvcmVTaGlwcGluZ0FkZHJlc3NPbmx5ID0gISEob3B0aW9ucyAmJiBvcHRpb25zLkFnZW50U3RvcmUgJiYgb3B0aW9ucy5BZ2VudFN0b3JlLlN0b3JlU2hpcHBpbmdBZGRyZXNzT25seSk7XG5cdGlmIChpc1N0b3JlU2hpcHBpbmdBZGRyZXNzT25seSkge1xuXHRcdHNldFNoaXBUb1N0b3JlKHRydWUpO1xuXHR9XG5cdGluaXRpYWxpemVFdmVudHMoKTtcblx0aW5pdGlhbGl6ZVVzZXJJbnRlcmZhY2UoKTtcbn07XG5cbmV4cG9ydHMudXBkYXRlU3VtbWFyeSA9IHVwZGF0ZVN1bW1hcnk7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgJGVycm9yQm94ID0gJCgnPGRpdiAvPicsIHsgJ2lkJzogJ2Vycm9yQm94T1BDJywgJ2NsYXNzJzogJ3BheW1lbnQtZGVjbGluZWQgcC0yIG10LTInLCAncm9sZSc6ICdhbGVydCcsICd0YWJpbmRleCc6ICcwJyB9KTtcbnZhciAkZXJyb3JCb3hJY29uID0gJCgnPGkgLz4nLCB7ICdjbGFzcyc6ICdmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZScsICdyb2xlJzogJ3ByZXNlbnRhdGlvbicgfSk7XG52YXIgJGVycm9yQm94SGVhZGxpbmUgPSAkKCc8c3BhbiAvPicsIHsgJ2NsYXNzJzogJ29wYy1lcnJvci1ib3gtaGVhZGxpbmUnIH0pO1xudmFyICRlcnJvckJveE1lc3NhZ2UgPSAkKCc8c3BhbiAvPicsIHsgJ2NsYXNzJzogJ29wYy1lcnJvci1ib3gtbWVzc2FnZScgfSk7XG5cbmZ1bmN0aW9uIGdldEVycm9yTWVzc2FnZShmaWVsZFR5cGUpIHtcblx0dmFyIGVycm9yTWVzc2FnZTtcblx0c3dpdGNoICh0cnVlKSB7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19sb3lhbHR5TnVtYmVyJykgPiAtMSk6XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19MT1lBTFRZX05VTUJFUl9FUlJPUjtcbiAgICAgICAgICAgIGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfbG95YWx0eVppcENvZGUnKSA+IC0xKTpcblx0XHRcdGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX0xPWUFMVFlfWklQX0VSUk9SO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19sb3lhbHR5UGhvbmVOdW1iZXInKSA+IC0xKTpcblx0XHRcdGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX0xPWUFMVFlfUEhPTkVfRVJST1I7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX3Jld2FyZHNOdW1iZXInKSA+IC0xKTpcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX1JFV0FSRFNfTlVNQkVSX0VSUk9SO1xuICAgICAgICAgICAgYnJlYWs7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19yZXdhcmRzWmlwQ29kZScpID4gLTEpOlxuXHRcdFx0ZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfUkVXQVJEU19aSVBfRVJST1I7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX3Jld2FyZHNQaG9uZU51bWJlcicpID4gLTEpOlxuXHRcdFx0ZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfUkVXQVJEU19QSE9ORV9FUlJPUjtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgKGZpZWxkVHlwZS5pbmRleE9mKCdfZ2lmdENhcmRfbnVtYmVyJykgPiAtMSk6XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19HSUZUX0NBUkRfRVJST1I7XG4gICAgICAgICAgICBicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2dpZnRDYXJkX3BpbicpID4gLTEpOlxuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfR0lGVF9DQVJEX1BJTl9FUlJPUjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX3ByaXZhdGVMYWJlbENyZWRpdF9udW1iZXInKSA+IC0xKTpcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IHdpbmRvdy5SZXNvdXJjZXMuT1BDX1BSSVZBVEVfTEFCRUxfRVJST1I7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19jcmVkaXRDYXJkX293bmVyJykgPiAtMSk6XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19DQVJEX09XTkVSX0VSUk9SO1xuICAgICAgICAgICAgYnJlYWs7XG5cdFx0Y2FzZSAoZmllbGRUeXBlLmluZGV4T2YoJ19jcmVkaXRDYXJkX251bWJlcicpID4gLTEpOlxuXHRcdFx0ZXJyb3JNZXNzYWdlID0gd2luZG93LlJlc291cmNlcy5PUENfQ0FSRF9OVU1CRVJfRVJST1I7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIChmaWVsZFR5cGUuaW5kZXhPZignX2NyZWRpdENhcmRfY3ZuJykgPiAtMSk6XG5cdFx0XHRlcnJvck1lc3NhZ2UgPSB3aW5kb3cuUmVzb3VyY2VzLk9QQ19TRUNVUklUWV9DT0RFX0VSUk9SO1xuXHRcdFx0YnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgfVxuXHRyZXR1cm4gZXJyb3JNZXNzYWdlO1xufVxuXG5mdW5jdGlvbiBnZXRQYXltZW50Rm9ybUVycm9yTWVzc2FnZXMoJGZvcm0pIHtcblx0aWYgKCEkZm9ybSB8fCAkZm9ybS5sZW5ndGggPT0gMCB8fCAkZm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5sZW5ndGggPT0gMCkge1xuXHRcdHJldHVybjtcblx0fVxuXHR2YXIgZXJyb3JzTGlzdCA9IG5ldyBBcnJheSgpO1xuXHQkZm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciBlcnJvck1lc3NhZ2UgPSBnZXRFcnJvck1lc3NhZ2UoJChlbGVtZW50KS5hdHRyKCduYW1lJykpO1xuXHRcdGlmIChlcnJvck1lc3NhZ2UpIHtcblx0XHRcdGVycm9yc0xpc3QucHVzaChlcnJvck1lc3NhZ2UpO1xuXHRcdH1cblx0fSk7XG5cdHJldHVybiBlcnJvcnNMaXN0O1xufVxuXG5mdW5jdGlvbiBwYXltZW50RXJyb3JCb3goaGVhZGxpbmUsIG1lc3NhZ2UsIGVycm9ySXRlbXMpIHtcblx0JGVycm9yQm94Lmh0bWwoJycpO1xuXG5cdGlmICghaGVhZGxpbmUgfHwgIW1lc3NhZ2UpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQkZXJyb3JCb3hIZWFkbGluZS5odG1sKCcmbmJzcDsnICsgaGVhZGxpbmUgKyAnOiZuYnNwOycpO1xuXHQkZXJyb3JCb3hNZXNzYWdlLmh0bWwobWVzc2FnZSArICcmbmJzcDsnKTtcblx0JGVycm9yQm94LmFwcGVuZCgkZXJyb3JCb3hJY29uKS5hcHBlbmQoJGVycm9yQm94SGVhZGxpbmUpLmFwcGVuZCgkZXJyb3JCb3hNZXNzYWdlKTtcblxuXHRpZiAoZXJyb3JJdGVtcyAmJiBlcnJvckl0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGVycm9ySXRlbXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciAkbmV3RXJyb3JJdGVtID0gZXJyb3JMaXN0SXRlbShlcnJvckl0ZW1zW2ldKTtcblx0XHRcdCRlcnJvckJveC5hcHBlbmQoJG5ld0Vycm9ySXRlbSk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuICRlcnJvckJveDtcbn1cblxuZnVuY3Rpb24gZXJyb3JMaXN0SXRlbShlcnJvck1zZykge1xuXHR2YXIgJGVycm9yTGlzdEl0ZW0gPSAkKCc8c3BhbiAvPicsIHsgJ2NsYXNzJzogJ29wYy1lcnJvci1ib3gtaXRlbScgfSk7XG5cdFx0JGVycm9yTGlzdEl0ZW0uaHRtbChlcnJvck1zZyArICcmbmJzcDsnKTtcblxuXHRyZXR1cm4gJGVycm9yTGlzdEl0ZW07XG59XG5cbmV4cG9ydHMuZ2V0RXJyb3JNZXNzYWdlcyA9IGdldFBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcztcbmV4cG9ydHMuZXJyb3JCb3ggPSBwYXltZW50RXJyb3JCb3g7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4uLy4uL2FqYXgnKSxcbiAgICBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vZm9ybVByZXBhcmUnKSxcbiAgICBwcm9ncmVzcyA9IHJlcXVpcmUoJy4uLy4uL3Byb2dyZXNzJyksXG4gICAgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG52YXIgc2hpcHBpbmdNZXRob2RzO1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBnaWZ0IG1lc3NhZ2UgYm94LCBpZiBzaGlwbWVudCBpcyBnaWZ0XG4gKi9cbmZ1bmN0aW9uIGdpZnRNZXNzYWdlQm94KCkge1xuICAgIC8vIHNob3cgZ2lmdCBtZXNzYWdlIGJveCwgaWYgc2hpcG1lbnQgaXMgZ2lmdFxuICAgICQoJy5naWZ0LW1lc3NhZ2UtdGV4dCcpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nLCAkKCdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdOmNoZWNrZWQnKS52YWwoKSAhPT0gJ3RydWUnKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGVzIHRoZSBvcmRlciBzdW1tYXJ5IGJhc2VkIG9uIGEgcG9zc2libHkgcmVjYWxjdWxhdGVkIGJhc2tldCBhZnRlciBhIHNoaXBwaW5nIHByb21vdGlvbiBoYXMgYmVlbiBhcHBsaWVkXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVN1bW1hcnkoKSB7XG4gICAgdmFyICRzdW1tYXJ5ID0gJCgnI3NlY29uZGFyeS5zdW1tYXJ5Jyk7XG4gICAgLy8gaW5kaWNhdGUgcHJvZ3Jlc3NcbiAgICBwcm9ncmVzcy5zaG93KCRzdW1tYXJ5KTtcblxuICAgIC8vIGxvYWQgdGhlIHVwZGF0ZWQgc3VtbWFyeSBhcmVhXG4gICAgJHN1bW1hcnkubG9hZChVcmxzLnN1bW1hcnlSZWZyZXNoVVJMLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGhpZGUgZWRpdCBzaGlwcGluZyBtZXRob2QgbGlua1xuICAgICAgICAkc3VtbWFyeS5mYWRlSW4oJ2Zhc3QnKTtcbiAgICAgICAgJHN1bW1hcnkuZmluZCgnLmNoZWNrb3V0LW1pbmktY2FydCAubWluaXNoaXBtZW50IC5oZWFkZXIgYScpLmhpZGUoKTtcbiAgICAgICAgJHN1bW1hcnkuZmluZCgnLm9yZGVyLXRvdGFscy10YWJsZSAub3JkZXItc2hpcHBpbmcgLmxhYmVsIGEnKS5oaWRlKCk7XG4gICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VwZGF0ZS1zdW1tYXJ5Jyk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSGVscGVyIG1ldGhvZCB3aGljaCBjb25zdHJ1Y3RzIGEgVVJMIGZvciBhbiBBSkFYIHJlcXVlc3QgdXNpbmcgdGhlXG4gKiBlbnRlcmVkIGFkZHJlc3MgaW5mb3JtYXRpb24gYXMgVVJMIHJlcXVlc3QgcGFyYW1ldGVycy5cbiAqL1xuZnVuY3Rpb24gZ2V0U2hpcHBpbmdNZXRob2RVUkwodXJsLCBleHRyYVBhcmFtcykge1xuICAgIHZhciAkZm9ybSA9ICQoJy5hZGRyZXNzJyk7XG4gICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgYWRkcmVzczE6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCksXG4gICAgICAgIGFkZHJlc3MyOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpLFxuICAgICAgICBhZGRyZXNzMzogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczNcIl0nKS52YWwoKSxcbiAgICAgICAgY291bnRyeUNvZGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfY291bnRyeVwiXScpLnZhbCgpLFxuICAgICAgICBzdGF0ZUNvZGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKSxcbiAgICAgICAgcG9zdGFsQ29kZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKCksXG4gICAgICAgIGNpdHk6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoKVxuICAgIH07XG4gICAgcmV0dXJuIHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwodXJsLCAkLmV4dGVuZChwYXJhbXMsIGV4dHJhUGFyYW1zKSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gc2VsZWN0cyBhIHNoaXBwaW5nIG1ldGhvZCBmb3IgdGhlIGRlZmF1bHQgc2hpcG1lbnQgYW5kIHVwZGF0ZXMgdGhlIHN1bW1hcnkgc2VjdGlvbiBvbiB0aGUgcmlnaHQgaGFuZCBzaWRlXG4gKiBAcGFyYW1cbiAqL1xuZnVuY3Rpb24gc2VsZWN0U2hpcHBpbmdNZXRob2Qoc2hpcHBpbmdNZXRob2RJRCkge1xuICAgIC8vIG5vdGhpbmcgZW50ZXJlZFxuICAgIGlmICghc2hpcHBpbmdNZXRob2RJRCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGF0dGVtcHQgdG8gc2V0IHNoaXBwaW5nIG1ldGhvZFxuICAgIHZhciB1cmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChVcmxzLnNlbGVjdFNoaXBwaW5nTWV0aG9kc0xpc3QsIHtzaGlwcGluZ01ldGhvZElEOiBzaGlwcGluZ01ldGhvZElEfSk7XG4gICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xuICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLnNoaXBwaW5nTWV0aG9kSUQpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3Qgc2VsZWN0IHNoaXBwaW5nIG1ldGhvZC4nKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBkaXNwbGF5IHByb21vdGlvbiBpbiBVSSBhbmQgdXBkYXRlIHRoZSBzdW1tYXJ5IHNlY3Rpb24sXG4gICAgICAgICAgICAvLyBpZiBzb21lIHByb21vdGlvbnMgd2VyZSBhcHBsaWVkXG4gICAgICAgICAgICAkKCcuc2hpcHBpbmdwcm9tb3Rpb25zJykuZW1wdHkoKTtcblxuICAgICAgICAgICAgLy8gVE9ETyB0aGUgZm9yIGxvb3AgYmVsb3cgaXNuJ3QgZG9pbmcgYW55dGhpbmc/XG4gICAgICAgICAgICAvLyBpZiAoZGF0YS5zaGlwcGluZ1ByaWNlQWRqdXN0bWVudHMgJiYgZGF0YS5zaGlwcGluZ1ByaWNlQWRqdXN0bWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLy8gICAgIHZhciBsZW4gPSBkYXRhLnNoaXBwaW5nUHJpY2VBZGp1c3RtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICAvLyAgICAgZm9yICh2YXIgaT0wOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIC8vICAgICAgICAgdmFyIHNwYSA9IGRhdGEuc2hpcHBpbmdQcmljZUFkanVzdG1lbnRzW2ldO1xuICAgICAgICAgICAgLy8gICAgIH1cbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIE1ha2UgYW4gQUpBWCByZXF1ZXN0IHRvIHRoZSBzZXJ2ZXIgdG8gcmV0cmlldmUgdGhlIGxpc3Qgb2YgYXBwbGljYWJsZSBzaGlwcGluZyBtZXRob2RzXG4gKiBiYXNlZCBvbiB0aGUgbWVyY2hhbmRpc2UgaW4gdGhlIGNhcnQgYW5kIHRoZSBjdXJyZW50bHkgZW50ZXJlZCBzaGlwcGluZyBhZGRyZXNzXG4gKiAodGhlIGFkZHJlc3MgbWF5IGJlIG9ubHkgcGFydGlhbGx5IGVudGVyZWQpLiAgSWYgdGhlIGxpc3Qgb2YgYXBwbGljYWJsZSBzaGlwcGluZyBtZXRob2RzXG4gKiBoYXMgY2hhbmdlZCBiZWNhdXNlIG5ldyBhZGRyZXNzIGluZm9ybWF0aW9uIGhhcyBiZWVuIGVudGVyZWQsIHRoZW4gaXNzdWUgYW5vdGhlciBBSkFYXG4gKiByZXF1ZXN0IHdoaWNoIHVwZGF0ZXMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzaGlwcGluZyBtZXRob2QgKGlmIG5lZWRlZCkgYW5kIGFsc28gdXBkYXRlc1xuICogdGhlIFVJLlxuICovXG5mdW5jdGlvbiB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoKSB7XG4gICAgdmFyICRzaGlwcGluZ01ldGhvZExpc3QgPSAkKCcjc2hpcHBpbmctbWV0aG9kLWxpc3QnKTtcbiAgICBpZiAoISRzaGlwcGluZ01ldGhvZExpc3QgfHwgJHNoaXBwaW5nTWV0aG9kTGlzdC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG4gICAgdmFyIHVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKFVybHMuc2hpcHBpbmdNZXRob2RzSlNPTik7XG5cbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3QgZ2V0IGxpc3Qgb2YgYXBwbGljYWJsZSBzaGlwcGluZyBtZXRob2RzLicpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzaGlwcGluZ01ldGhvZHMgJiYgc2hpcHBpbmdNZXRob2RzLnRvU3RyaW5nKCkgPT09IGRhdGEudG9TdHJpbmcoKSkge1xuICAgICAgICAgICAgICAgIC8vIE5vIG5lZWQgdG8gdXBkYXRlIHRoZSBVSS4gIFRoZSBsaXN0IGhhcyBub3QgY2hhbmdlZC5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB1cGRhdGUgdGhlIFVJLiAgVGhlIGxpc3QgaGFzIGNoYW5nZWQuXG4gICAgICAgICAgICAvLyBDYWNoZSB0aGUgYXJyYXkgb2YgcmV0dXJuZWQgc2hpcHBpbmcgbWV0aG9kcy5cbiAgICAgICAgICAgIHNoaXBwaW5nTWV0aG9kcyA9IGRhdGE7XG4gICAgICAgICAgICAvLyBpbmRpY2F0ZSBwcm9ncmVzc1xuICAgICAgICAgICAgcHJvZ3Jlc3Muc2hvdygkc2hpcHBpbmdNZXRob2RMaXN0KTtcblxuICAgICAgICAgICAgLy8gbG9hZCB0aGUgc2hpcHBpbmcgbWV0aG9kIGZvcm1cbiAgICAgICAgICAgIHZhciBzbWxVcmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChVcmxzLnNoaXBwaW5nTWV0aG9kc0xpc3QpO1xuICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5sb2FkKHNtbFVybCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICRzaGlwcGluZ01ldGhvZExpc3QuZmFkZUluKCdmYXN0Jyk7XG4gICAgICAgICAgICAgICAgLy8gcmViaW5kIHRoZSByYWRpbyBidXR0b25zIG9uY2xpY2sgZnVuY3Rpb24gdG8gYSBoYW5kbGVyLlxuICAgICAgICAgICAgICAgICRzaGlwcGluZ01ldGhvZExpc3QuZmluZCgnW25hbWUkPVwiX3NoaXBwaW5nTWV0aG9kSURcIl0nKS5jbGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdFNoaXBwaW5nTWV0aG9kKCQodGhpcykudmFsKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSBzdW1tYXJ5XG4gICAgICAgICAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xuICAgICAgICAgICAgICAgIHByb2dyZXNzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0b29sdGlwLmluaXQoKTtcbiAgICAgICAgICAgICAgICAvL2lmIG5vdGhpbmcgaXMgc2VsZWN0ZWQgaW4gdGhlIHNoaXBwaW5nIG1ldGhvZHMgc2VsZWN0IHRoZSBmaXJzdCBvbmVcbiAgICAgICAgICAgICAgICBpZiAoJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCcuaW5wdXQtcmFkaW86Y2hlY2tlZCcpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJy5pbnB1dC1yYWRpbzpmaXJzdCcpLnByb3AoJ2NoZWNrZWQnLCAnY2hlY2tlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBmb3JtUHJlcGFyZS5pbml0KHtcbiAgICAgICAgY29udGludWVTZWxlY3RvcjogJ1tuYW1lJD1cInNoaXBwaW5nQWRkcmVzc19zYXZlXCJdJyxcbiAgICAgICAgZm9ybVNlbGVjdG9yOidbaWQkPVwic2luZ2xlc2hpcHBpbmdfc2hpcHBpbmdBZGRyZXNzXCJdJ1xuICAgIH0pO1xuICAgICQoJ2lucHV0W25hbWUkPVwiX3NoaXBwaW5nQWRkcmVzc19pc0dpZnRcIl0nKS5vbignY2xpY2snLCBnaWZ0TWVzc2FnZUJveCk7XG5cbiAgICAkKCcuYWRkcmVzcycpLm9uKCdjaGFuZ2UnLFxuICAgICAgICAnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMVwiXSwgaW5wdXRbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMlwiXSwgaW5wdXRbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc19hZGRyZXNzM1wiXSwgc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NGaWVsZHNfc3RhdGVzX3N0YXRlXCJdLCBpbnB1dFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX2NpdHlcIl0sIGlucHV0W25hbWUkPVwiX2FkZHJlc3NGaWVsZHNfemlwXCJdJyxcbiAgICAgICAgdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0XG4gICAgKTtcblxuICAgIGdpZnRNZXNzYWdlQm94KCk7XG4gICAgdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCk7XG59O1xuXG5leHBvcnRzLnVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCA9IHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nO1xudmFyIEFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2c7XG52YXIgQWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQWRkcmVzc1ZlcmlmaWNhdGlvbi9BZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyJyk7XG52YXIgQXBwbGVQYXkgPSByZXF1aXJlKCcuL2NoZWNrb3V0L0FwcGxlUGF5Jyk7XG52YXIgQ2hlY2tvdXRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL0NoZWNrb3V0Q29uc3RhbnRzJyk7XG52YXIgR2lmdENhcmQgPSByZXF1aXJlKCcuL2NoZWNrb3V0L0dpZnRDYXJkUGF5bWVudFBhbmVsJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvTG9hZGluZ0luZGljYXRvcicpO1xudmFyIFBheW1lbnRNZXRob2RDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuUGF5bWVudE1ldGhvZHM7XG52YXIgUmV3YXJkc0NyZWRpdCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvUmV3YXJkc0NyZWRpdCcpO1xudmFyIFNpdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1NpdGVDb25zdGFudHMnKTtcbnZhciBUZW1wbGF0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVGVtcGxhdGVDb25zdGFudHMnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vdG9vbHRpcCcpO1xudmFyIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbnZhciBjaGVja291dEZvcm1TZWxlY3RvciA9ICcjY2hlY2tvdXQtZm9ybSc7XG52YXIgJGNoZWNrb3V0Rm9ybSA9ICQoY2hlY2tvdXRGb3JtU2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRUeXBlTGlzdFNlbGVjdG9yID0gJy5wYXltZW50LWNhcmQtbGlzdCc7XG52YXIgJGNyZWRpdENhcmRUeXBlTGlzdCA9ICQoY3JlZGl0Q2FyZFR5cGVMaXN0U2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmROdW1iZXJJbnB1dFNlbGVjdG9yID0gJy5mb3JtZmllbGQuY2FyZC1udW1iZXIgaW5wdXQnO1xudmFyICRjcmVkaXRDYXJkTnVtYmVySW5wdXQgPSAkKGNyZWRpdENhcmROdW1iZXJJbnB1dFNlbGVjdG9yKTtcbnZhciBjcmVkaXRDYXJkRXhwaXJhdGlvbk1vbnRoSW5wdXRTZWxlY3RvciA9ICcubW9udGhmaWVsZCBpbnB1dCc7XG52YXIgJGNyZWRpdENhcmRFeHBpcmF0aW9uTW9udGhJbnB1dCA9ICQoY3JlZGl0Q2FyZEV4cGlyYXRpb25Nb250aElucHV0U2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRFeHBpcmF0aW9uWWVhcklucHV0U2VsZWN0b3IgPSAnLnllYXJmaWVsZCBpbnB1dCc7XG52YXIgJGNyZWRpdENhcmRFeHBpcmF0aW9uWWVhcklucHV0ID0gJChjcmVkaXRDYXJkRXhwaXJhdGlvblllYXJJbnB1dFNlbGVjdG9yKTtcbnZhciBjcmVkaXRDYXJkQ1ZWSW5wdXRTZWxlY3RvciA9ICcuZm9ybS1yb3cuY3ZuIGlucHV0JztcbnZhciAkY3JlZGl0Q2FyZENWVklucHV0ID0gJChjcmVkaXRDYXJkQ1ZWSW5wdXRTZWxlY3Rvcik7XG52YXIgYWRkcmVzc0lucHV0U2VsZWN0b3IgPSAnLmZvcm1maWVsZC5hZGRyZXNzMSBpbnB1dCc7XG52YXIgJGFkZHJlc3NJbnB1dCA9ICQoYWRkcmVzc0lucHV0U2VsZWN0b3IpO1xudmFyIHN1Ym1pdFBheW1lbnRTZWxlY3RvciA9ICcjc3VibWl0T1BDUGF5bWVudCc7XG52YXIgJHN1Ym1pdFBheW1lbnQgPSAkKHN1Ym1pdFBheW1lbnRTZWxlY3Rvcik7XG52YXIgJHJld2FyZHNBY2NvcmRpb24gPSAkKCcucmV3YXJkcycpO1xudmFyICRyZXdhcmRzUGF5bWVudENvbnRhaW5lciA9ICRyZXdhcmRzQWNjb3JkaW9uLmZpbmQoJ1twYXltZW50LW1ldGhvZD1cIlJFV0FSRFNfQ1JFRElUXCJdJyk7XG52YXIgJHJld2FyZHNGb3JtID0gJHJld2FyZHNQYXltZW50Q29udGFpbmVyLmZpbmQoJy5yZXdhcmRzLWZvcm0nKTtcbnZhciAkcmV3YXJkc0FwcGxpZWQgPSAkcmV3YXJkc1BheW1lbnRDb250YWluZXIuZmluZCgnLnJld2FyZHMtYXBwbGllZCcpO1xuXG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGRhdGFCdWZmZXIgPSB7fTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZShvcHRpb25zKSB7XG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgc3VibWl0UGF5bWVudFNlbGVjdG9yLCBmdW5jdGlvbihldmVudCkge1xuICAgIFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciBhZGRyZXNzRGVsaXZlcmFibGUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRzdWJtaXRQYXltZW50KCk7XG5cdFx0fVxuXHRcblx0XHR2YXIgYWRkcmVzc05vdERlbGl2ZXJhYmxlID0gZnVuY3Rpb24gKGFkZHJlc3NWZXJpZnlEYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgJ2JpbGxpbmcnLCBhZGRyZXNzVmVyaWZ5RGF0YSk7XG5cdFx0fVxuXHRcblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHRcdEFkZHJlc3NWZXJpZmljYXRpb25IZWxwZXIuVmVyaWZ5QWRkcmVzcygkY2hlY2tvdXRGb3JtLCBvcHRpb25zKS50aGVuKGFkZHJlc3NEZWxpdmVyYWJsZSwgYWRkcmVzc05vdERlbGl2ZXJhYmxlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YWRkcmVzc0RlbGl2ZXJhYmxlKCk7XG5cdFx0fVxuICAgIH0pO1xuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NBdXRvY29tcGxldGUuRW5hYmxlZCkge1xuXHRcdCRjaGVja291dEZvcm0ub2ZmKCdrZXl1cC5BZGRyZXNzQXV0b2NvbXBsZXRlJykub24oJ2tleXVwLkFkZHJlc3NBdXRvY29tcGxldGUnLCAnaW5wdXRbdHlwZT1cInRleHRcIl0nLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHR2YXIgJGZvcm0gPSAkdGhpcy5jbG9zZXN0KCdmb3JtJyk7XG5cdFx0XHR2YXIgZm9ybVZhbGlkYXRvciA9ICRmb3JtLnZhbGlkYXRlKCk7XG5cblx0XHRcdGlmIChldmVudC5rZXlDb2RlID09IDggfHwgZXZlbnQua2V5Q29kZSA9PSA0Nikge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKCFmb3JtVmFsaWRhdG9yLmNoZWNrRm9ybSgpICYmICgkdGhpcy5hdHRyKCdpZCcpLmluZGV4T2YoJ19hZGRyZXNzMScpID49IDAgfHwgJHRoaXMuYXR0cignaWQnKS5pbmRleE9mKCdfYWRkcmVzczInKSA+PSAwKSkge1xuXHRcdFx0XHR2YXIgYWRkcmVzc0F1dG9jb21wbGV0ZUhhbmRsZXIgPSBmdW5jdGlvbiAoYWRkcmVzc0F1dG9jb21wbGV0ZURhdGEpIHtcblx0XHRcdFx0XHRBZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nLmluaXRpYWxpemUob3B0aW9ucywgYWRkcmVzc0F1dG9jb21wbGV0ZURhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHRcblx0XHRcdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkhlbHBlci5BdXRvY29tcGxldGVBZGRyZXNzKCRmb3JtLCAkdGhpcywgb3B0aW9ucykudGhlbihhZGRyZXNzQXV0b2NvbXBsZXRlSGFuZGxlcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnQoKS5maW5kKCcuYWRkcmVzcy1hdXRvY29tcGxldGUtZGlhbG9nJykucmVtb3ZlKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0XG5cdFx0JChkb2N1bWVudCkub2ZmKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NBdXRvY29tcGxldGUnKS5vbignU2V0QWRkcmVzc0Zyb21BZGRyZXNzQXV0b2NvbXBsZXRlJywgZnVuY3Rpb24gKGV2ZW50LCBkYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZyhkYXRhLiRmb3JtLCBkYXRhLkFkZHJlc3MpO1xuXHRcdFx0JGNoZWNrb3V0Rm9ybS5maW5kKCcjZHdmcm1fYmlsbGluZ19iaWxsaW5nQWRkcmVzc19lbWFpbF9lbWFpbEFkZHJlc3MsIGlucHV0LnBob25lLCBpbnB1dC5wb3N0YWwnKS50cmlnZ2VyKCdibHVyLlJld2FyZHNBY2NvdW50U2VhcmNoJyk7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLkxvYiAmJiBvcHRpb25zLkxvYi5BZGRyZXNzVmVyaWZpY2F0aW9uLkVuYWJsZWQpIHtcblx0XHQkKGRvY3VtZW50KS5vZmYoJ1NldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbicpLm9uKCdTZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoZXZlbnQsIGFkZHJlc3NEYXRhKSB7XG5cdFx0XHRBZGRyZXNzVmVyaWZpY2F0aW9uSGVscGVyLlNldEFkZHJlc3NGcm9tQWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZygkY2hlY2tvdXRGb3JtLCBhZGRyZXNzRGF0YSk7XG5cdFx0XHRzdWJtaXRQYXltZW50KCk7XG5cdFx0fSk7XG5cdH1cblxuXHQkY2hlY2tvdXRGb3JtLm9mZignYmx1ci5SZXdhcmRzQWNjb3VudFNlYXJjaCcpLm9uKCdibHVyLlJld2FyZHNBY2NvdW50U2VhcmNoJywgJyNkd2ZybV9iaWxsaW5nX2JpbGxpbmdBZGRyZXNzX2VtYWlsX2VtYWlsQWRkcmVzcywgaW5wdXQucGhvbmUsIGlucHV0LnBvc3RhbCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddICYmIGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddLnJlYWR5U3RhdGUgIT09IDQpIHtcblx0XHRcdGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddLmFib3J0KCk7XG5cdFx0XHRkYXRhQnVmZmVyWydSZXdhcmRzQWNjb3VudFNlYXJjaFJlcXVlc3QnXSA9IG51bGw7XG5cdFx0fVxuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgZmllbGQgPSAkdGhpcy5jbG9zZXN0KCdbZmllbGRdJykuYXR0cignZmllbGQnKTtcblx0XHR2YXIgdmFsdWUgPSAkdGhpcy52YWwoKTtcblx0XHRpZiAoZmllbGQgJiYgdmFsdWUpIHtcblx0XHRcdGlmICghZGF0YUJ1ZmZlclsnUmV3YXJkc0RhdGEnXSkge1xuXHRcdFx0XHRkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddID0ge307XG5cdFx0XHR9XG5cdFx0XHRkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddW2ZpZWxkXSA9IHZhbHVlO1xuXG5cdFx0XHRzd2l0Y2ggKGZpZWxkKSB7XG5cdFx0XHRcdGNhc2UgJ2VtYWlsQWRkcmVzcyc6XG5cdFx0XHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc0VtYWlsJykudmFsKHZhbHVlKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAncGhvbmUnOlxuXHRcdFx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuZmllbGQucGhvbmVudW1iZXInKS52YWwodmFsdWUpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdwb3N0YWwnOlxuXHRcdFx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuZmllbGQuemlwY29kZScpLnZhbCh2YWx1ZSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBpc1Jld2FyZHNEYXRhUmVhZHkgPSBkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddWydlbWFpbEFkZHJlc3MnXSAmJiBkYXRhQnVmZmVyWydSZXdhcmRzRGF0YSddWydwaG9uZSddICYmIGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ11bJ3Bvc3RhbCddO1xuXHRcdFx0dmFyIGlzUmV3YXJkc051bWJlckZpZWxkRW1wdHkgPSAhJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgpO1xuXHRcdFx0aWYgKGlzUmV3YXJkc0RhdGFSZWFkeSAmJiBpc1Jld2FyZHNOdW1iZXJGaWVsZEVtcHR5KSB7XG5cdFx0XHRcdHZhciBwYXlsb2FkID0ge1xuXHRcdFx0XHRcdEVtYWlsQWRkcmVzczogZGF0YUJ1ZmZlclsnUmV3YXJkc0RhdGEnXVsnZW1haWxBZGRyZXNzJ10sXG5cdFx0XHRcdFx0UGhvbmVOdW1iZXI6IGRhdGFCdWZmZXJbJ1Jld2FyZHNEYXRhJ11bJ3Bob25lJ10sXG5cdFx0XHRcdFx0WmlwQ29kZTogZGF0YUJ1ZmZlclsnUmV3YXJkc0RhdGEnXVsncG9zdGFsJ10sXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgpKSB7XG5cdFx0XHRcdFx0cGF5bG9hZC5SZXdhcmRzTnVtYmVyID0gJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10gPSAkLmFqYXgoe1xuXHRcdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0XHR1cmw6IFVybHMuc2VhcmNoRm9yUmV3YXJkcyxcblx0XHRcdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0cmVuZGVyUmV3YXJkc0RhdGEoZGF0YSk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24oeGhyKSB7XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0JHJld2FyZHNGb3JtLm9mZigna2V5dXAuUmV3YXJkc1Jlc2V0IGNoYW5nZS5SZXdhcmRzUmVzZXQnKS5vbigna2V5dXAuUmV3YXJkc1Jlc2V0IGNoYW5nZS5SZXdhcmRzUmVzZXQnLCAnaW5wdXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBpc1Jld2FyZHNGb3JtUG9wdWxhdGVkID0gZmFsc2U7XG5cdFx0JHJld2FyZHNGb3JtLmZpbmQoJ2lucHV0JykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGlmICgkKHRoaXMpLnZhbCgpKSB7XG5cdFx0XHRcdGlzUmV3YXJkc0Zvcm1Qb3B1bGF0ZWQgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdGlmIChpc1Jld2FyZHNGb3JtUG9wdWxhdGVkKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmJ0bi5yZXNldC1lY2hvJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5idG4ucmVzZXQtZWNobycpLmF0dHIoJ2Rpc2FibGVkJywgJ3RydWUnKTtcblx0XHR9XG5cdH0pO1xuXG5cdCRyZXdhcmRzRm9ybS5vZmYoJ2NsaWNrLlJld2FyZHNSZXNldCcpLm9uKCdjbGljay5SZXdhcmRzUmVzZXQnLCAnLmJ0bi5yZXNldC1lY2hvJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0aWYgKCRyZXdhcmRzQXBwbGllZC5maW5kKCcucmV3YXJkLXJvd1tzdGF0dXM9XCJhcHBsaWVkXCJdJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JHJld2FyZHNBcHBsaWVkLmZpbmQoJy5yZXdhcmQtcm93W3N0YXR1cz1cImFwcGxpZWRcIl0gLmJ0bi5yZW1vdmUnKS50cmlnZ2VyKCdSZXdhcmRzQ3JlZGl0LlJlbW92ZScsIHsgUmVzZXRTZXNzaW9uRGF0YTogdHJ1ZSB9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLnJlc2V0UmV3YXJkc1Nlc3Npb25EYXRhLFxuXHRcdFx0XHR0eXBlOiAnUE9TVCdcblx0XHRcdH0pO1xuXHRcdH1cblx0XHQkcmV3YXJkc0FwcGxpZWQuaHRtbCgnJyk7XG5cdFx0JHJld2FyZHNGb3JtLmZpbmQoJ2lucHV0JykudmFsKCcnKTtcblx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmJ0bi5yZXNldC1lY2hvJykuYXR0cignZGlzYWJsZWQnLCAndHJ1ZScpO1xuXHRcdCRyZXdhcmRzRm9ybS5maW5kKCdbbWF0Y2hdJykucmVtb3ZlQXR0cignbWF0Y2gnKTtcblx0XHQkcmV3YXJkc0FjY29yZGlvbi5yZW1vdmVBdHRyKCdyZXdhcmRzLWZvdW5kJyk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignUmV3YXJkc0FjY291bnRTZWFyY2gnKS5vbignUmV3YXJkc0FjY291bnRTZWFyY2gnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHNlYXJjaFJld2FyZHMoKTtcblx0fSk7XG5cblx0dXBkYXRlQ2FydCgnZHdmcm1fY2FydF91cGRhdGVDYXJ0Jyk7XG5cblx0JHJld2FyZHNGb3JtLm9mZignY2xpY2suUmV3YXJkc0FjY291bnRTZWFyY2gnKS5vbignY2xpY2suUmV3YXJkc0FjY291bnRTZWFyY2gnLCAnLmJ0bi5zZWFyY2gtZWNobycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRzZWFyY2hSZXdhcmRzKCk7XG5cdH0pO1xuXG5cdCRjcmVkaXRDYXJkTnVtYmVySW5wdXQub2ZmKCdrZXlkb3duLkNyZWRpdENhcmROdW1iZXJIYW5kbGVyJykub24oJ2tleWRvd24uQ3JlZGl0Q2FyZE51bWJlckhhbmRsZXInLCBmdW5jdGlvbihldmVudCkge1xuXHRcdCRjcmVkaXRDYXJkVHlwZUxpc3QudmFsKCcnKTtcblx0fSk7XG5cblx0JGNyZWRpdENhcmROdW1iZXJJbnB1dC5vZmYoJ2tleXVwLkNyZWRpdENhcmROdW1iZXJIYW5kbGVyJykub24oJ2tleXVwLkNyZWRpdENhcmROdW1iZXJIYW5kbGVyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBjcmVkaXRDYXJkTnVtYmVyID0gJHRoaXMudmFsKCk7XG5cdFx0XG5cdFx0dmFyIHNlbGVjdGVkQ2FyZCA9IHV0aWwuZ2V0Q3JlZGl0Q2FyZFR5cGUoY3JlZGl0Q2FyZE51bWJlcik7XG5cdFx0aWYgKHNlbGVjdGVkQ2FyZCkge1xuXHRcdFx0aWYgKCRjcmVkaXRDYXJkTnVtYmVySW5wdXQuZmlsdGVyKCc6dmlzaWJsZScpLmxlbmd0aCA8IDEpIHtcblx0XHRcdFx0JGNyZWRpdENhcmROdW1iZXJJbnB1dC52YWwoY3JlZGl0Q2FyZE51bWJlcik7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCQoJ2lucHV0W25hbWUqPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLnZhbChzZWxlY3RlZENhcmQuUGF5bWVudENhcmQpO1xuXHRcdFx0JCgnaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoc2VsZWN0ZWRDYXJkLlBheW1lbnRNZXRob2QpO1xuXHRcdFx0JGNyZWRpdENhcmRUeXBlTGlzdC5maW5kKCdpbnB1dFt0eXBlPVwicmFkaW9cIl1bdmFsdWU9XCInICsgc2VsZWN0ZWRDYXJkLlBheW1lbnRDYXJkRGlzcGxheUtleSArICdcIl0nKS5maXJzdCgpLnByb3AoJ2NoZWNrZWQnLCB0cnVlKS50cmlnZ2VyKCdjaGFuZ2UnLCB7IGRvUmVzZXQ6IGZhbHNlIH0pO1xuXHRcdFx0dmFyICRwYXltZW50Q2FyZEltYWdlID0gJGNyZWRpdENhcmRUeXBlTGlzdC5maW5kKCdpbnB1dFt2YWx1ZT1cIicgKyBzZWxlY3RlZENhcmQuUGF5bWVudENhcmREaXNwbGF5S2V5ICsgJ1wiXScpO1xuXHRcdFx0dmFyIHBheW1lbnRDYXJkSW1hZ2VVcmw7XG5cdFx0XHRpZiAoJHBheW1lbnRDYXJkSW1hZ2UgJiYgJHBheW1lbnRDYXJkSW1hZ2UubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRwYXltZW50Q2FyZEltYWdlVXJsID0gJHBheW1lbnRDYXJkSW1hZ2UuYXR0cigncGF5bWVudC1jYXJkLWltYWdlJyk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChwYXltZW50Q2FyZEltYWdlVXJsKSB7XG5cdFx0XHRcdCRjcmVkaXRDYXJkTnVtYmVySW5wdXQuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ3VybCgnICsgcGF5bWVudENhcmRJbWFnZVVybCArICcpJyk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChjcmVkaXRDYXJkTnVtYmVyLmxlbmd0aCA+PSAxNikge1xuXHRcdFx0XHQkY3JlZGl0Q2FyZEV4cGlyYXRpb25Nb250aElucHV0LmZvY3VzKCk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoc2VsZWN0ZWRDYXJkLlBheW1lbnRNZXRob2QgPT0gJ0FsbGlhbmNlX0RhdGEnKSB7XG5cdFx0XHRcdCQoJy5mb3JtZmllbGQuY2FyZC1uYW1lJykuaGlkZSgpO1xuXHRcdFx0XHQkKCcuZm9ybWZpZWxkLmNhcmQtbmFtZSBpbnB1dCcpLnJlbW92ZUNsYXNzKCdyZXF1aXJlZCcpO1xuXHRcdFx0XHQkKCcuY2FyZC1leHBpcmF0aW9uLWFuZC1jdm4nKS5hZGRDbGFzcygnbnVtYmVyLW9ubHknKTtcblx0XHRcdFx0JCgnLmNhcmQtZXhwaXJhdGlvbi1hbmQtY3ZuIGlucHV0JykucmVtb3ZlQ2xhc3MoJ3JlcXVpcmVkJyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRjcmVkaXRDYXJkVHlwZUxpc3QuZmluZCgnaW5wdXQnKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0JGNyZWRpdENhcmRUeXBlTGlzdC5maW5kKCdvcHRpb24nKS5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcblx0XHRcdCRjcmVkaXRDYXJkTnVtYmVySW5wdXQuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJycpO1xuXHRcdFx0JCgnLmZvcm1maWVsZC5jYXJkLW5hbWUnKS5zaG93KCk7XG5cdFx0XHQkKCcuZm9ybWZpZWxkLmNhcmQtbmFtZSBpbnB1dCcpLmFkZENsYXNzKCdyZXF1aXJlZCcpO1xuXHRcdFx0JCgnLmNhcmQtZXhwaXJhdGlvbi1hbmQtY3ZuJykucmVtb3ZlQ2xhc3MoJ251bWJlci1vbmx5Jyk7XG5cdFx0XHQkKCcuY2FyZC1leHBpcmF0aW9uLWFuZC1jdm4gaW5wdXQnKS5hZGRDbGFzcygncmVxdWlyZWQnKTtcblx0XHR9XG5cdH0pO1xuXG5cdCRjcmVkaXRDYXJkRXhwaXJhdGlvbk1vbnRoSW5wdXQub2ZmKCdrZXlkb3duLkZpZWxkQmxvY2snKS5vbigna2V5cHJlc3MuRmllbGRCbG9jaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCQodGhpcykudmFsKCkubGVuZ3RoID49IDIpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHR9XG5cdH0pO1xuXG5cdCRjcmVkaXRDYXJkRXhwaXJhdGlvbk1vbnRoSW5wdXQub2ZmKCdrZXl1cC5GaWVsZFNoaWZ0Jykub24oJ2tleXVwLkZpZWxkU2hpZnQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGlmICgkKHRoaXMpLnZhbCgpLmxlbmd0aCA+PSAyKSB7XG5cdFx0XHQkY3JlZGl0Q2FyZEV4cGlyYXRpb25ZZWFySW5wdXQuZm9jdXMoKTtcblx0XHR9XG5cdH0pO1xuXG5cdCRjcmVkaXRDYXJkRXhwaXJhdGlvblllYXJJbnB1dC5vZmYoJ2tleWRvd24uRmllbGRCbG9jaycpLm9uKCdrZXlwcmVzcy5GaWVsZEJsb2NrJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoJCh0aGlzKS52YWwoKS5sZW5ndGggPj0gMikge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNyZWRpdENhcmRFeHBpcmF0aW9uWWVhcklucHV0Lm9mZigna2V5dXAuRmllbGRTaGlmdCcpLm9uKCdrZXl1cC5GaWVsZFNoaWZ0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoJCh0aGlzKS52YWwoKS5sZW5ndGggPj0gMikge1xuXHRcdFx0JGNyZWRpdENhcmRDVlZJbnB1dC5mb2N1cygpO1xuXHRcdH1cblx0fSk7XG5cblx0JGNyZWRpdENhcmRDVlZJbnB1dC5vZmYoJ2tleXVwLkZpZWxkU2hpZnQnKS5vbigna2V5dXAuRmllbGRTaGlmdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIGN2dkxlbmd0aCA9ICQoJ2lucHV0W25hbWUqPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLnZhbCgpID09ICdBbWV4JyA/IDQgOiAzO1xuXG5cdFx0aWYgKCQodGhpcykudmFsKCkubGVuZ3RoID49IGN2dkxlbmd0aCkge1xuXHRcdFx0JGFkZHJlc3NJbnB1dC5mb2N1cygpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5hY2NvcmRpb24taGVhZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0JCh0aGlzKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiYWRkQ291cG9uXCJdJykub24oJ2NsaWNrJywgJ2J1dHRvbltuYW1lJD1cImFkZENvdXBvblwiXScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJy5jYXJ0LWNvdXBvbi1jb2RlJyk7XG5cdFx0dmFyICRhcHBseUJ1dHRvbiA9ICRjb250YWluZXIuZmluZCgnLmJ0bi1jb3Vwb24tY29kZScpO1xuXHRcdCQoJy5lcnJvci5jb3Vwb24tZXJyb3InKS50ZXh0KCcnKTtcblx0XHRcblx0XHQoZnVuY3Rpb24oKSB7XG5cdFx0XHQkYXBwbHlCdXR0b24ubG9hZGluZyh7XG5cdFx0XHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0dXJsOiB1dGlsLmFqYXhVcmwoVXJscy5vbmVQYWdlU3VibWl0KSxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdGR3ZnJtX2NhcnRfYWRkQ291cG9uOiAnZHdmcm1fY2FydF9hZGRDb3Vwb24nLFxuXHRcdFx0XHRcdGR3ZnJtX2NhcnRfY291cG9uQ29kZTogJCgnLmFjY29yZGlvbi5jb3Vwb24gI2R3ZnJtX2NhcnRfY291cG9uQ29kZScpLnZhbCgpLFxuXHRcdFx0XHRcdHJlc3BUeXBlOiAnanNvbidcblx0XHRcdFx0fVxuXHRcdFx0fSkpO1xuXHRcdH0oKSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdGlmIChyZXNwb25zZS5zdWNjZXNzICYmIHJlc3BvbnNlLnN1Y2Nlc3MgIT09IENoZWNrb3V0Q29uc3RhbnRzLlJlc3BvbnNlQ29kZXMuQWxyZWFkeUluQmFza2V0KSB7XHRcdFx0XHRcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2FydC5VcGRhdGUnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gcmVzcG9uc2Uuc3VjY2VzcyA9PSBDaGVja291dENvbnN0YW50cy5SZXNwb25zZUNvZGVzLkFscmVhZHlJbkJhc2tldCA/IFJlc291cmNlcy5DT1VQT05fQUREX0VSUk9SX0RVUCA6IFJlc291cmNlcy5DT1VQT05fQUREX0VSUk9SO1xuXHRcdFx0XHQkKCc8c3Bhbi8+JywgeydjbGFzcyc6ICdlcnJvciBjb3Vwb24tZXJyb3InLCAndGV4dCc6IG1lc3NhZ2V9KS5pbnNlcnRBZnRlcignLmFjY29yZGlvbi5jb3Vwb24gLmNhcnQtY291cG9uLWNvZGUgLnBjb2RlLWNvdXBvbicpO1xuXHRcdFx0XHRpZiAoJGFwcGx5QnV0dG9uLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRcdCRhcHBseUJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljaycsICdidXR0b25bbmFtZSQ9XCJkZWxldGVDb3Vwb25cIl0nKS5vbignY2xpY2snLCAnYnV0dG9uW25hbWUkPVwiZGVsZXRlQ291cG9uXCJdJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRjb250YWluZXIgPSAkdGhpcy5jbG9zZXN0KCcuY291cG9uJyk7XG5cdFx0dmFyIG5hbWUgPSAkdGhpcy5hdHRyKCduYW1lJyk7XG5cdFx0KGZ1bmN0aW9uKCl7XG5cdFx0XHQkY29udGFpbmVyLmxvYWRpbmcoe1xuXHRcdFx0XHRJc0xhYmVsU2hvd246IGZhbHNlLFxuXHRcdFx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0XHRcdH0pO1xuXG5cdFx0XHRyZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuXHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdHVybDogdXRpbC5hamF4VXJsKFVybHMub25lUGFnZVN1Ym1pdCksXG5cdFx0XHRcdGRhdGE6ICQoJ2Zvcm0jY2FydC1pdGVtcy1mb3JtJykuc2VyaWFsaXplKCkgKyAnJicgKyBuYW1lICsgJz0nICsgbmFtZSArICcmcmVzcFR5cGU9anNvbidcblx0XHRcdH0pKTtcblx0XHR9KCkpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0LlVwZGF0ZScpO1xuXHRcdH0pO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJy5vcmRlci10b3RhbC1wYXltZW50cyBbcGF5bWVudC1tZXRob2RdIC5yZW1vdmUnKS5vbignY2xpY2snLCAnLm9yZGVyLXRvdGFsLXBheW1lbnRzIFtwYXltZW50LW1ldGhvZF0gLnJlbW92ZScsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50VVVJRCA9ICQoZS5jdXJyZW50VGFyZ2V0KS5jbG9zZXN0KCdbcGF5bWVudC1tZXRob2QnKS5hdHRyKCd1dWlkJyk7XG5cdFxuXHRcdGlmIChwYXltZW50SW5zdHJ1bWVudFVVSUQpIHtcblx0XHRcdHZhciByZXF1ZXN0UGF5bG9hZCA9IHtcblx0XHRcdFx0VVVJRDogcGF5bWVudEluc3RydW1lbnRVVUlEXG5cdFx0XHR9XG5cdFx0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMucmVtb3ZlUGF5bWVudEluc3RydW1lbnQsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdFBheWxvYWQpLFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0bG9jYXRpb24ucmVsb2FkKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdDYXJ0LlVwZGF0ZScpLm9uKCdDYXJ0LlVwZGF0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuICAgIFx0dXBkYXRlQ2FydCgnZHdmcm1fY2FydF91cGRhdGVDYXJ0JywgZGF0YSk7XG4gICAgfSk7XG5cblx0c2VhcmNoUmV3YXJkcygpO1xuXHR1cGRhdGVDYXJ0KCdkd2ZybV9jYXJ0X3VwZGF0ZUNhcnQnKTtcbn1cblxudmFyIHVwZGF0ZUNhcnRCdWZmZXI7XG52YXIgdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyO1xuZnVuY3Rpb24gdXBkYXRlQ2FydCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcblx0aWYgKHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlcikge1xuXHRcdGZvciAodmFyIHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEtleSBpbiB1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXIpIHtcblx0XHRcdHZhciB1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3QgPSB1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbdXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0S2V5XTtcblx0XHRcdFxuXHRcdFx0aWYgKHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdC5yZWFkeVN0YXRlICE9PSA0KSB7IFxuXHRcdFx0XHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3QuYWJvcnQoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0dXBkYXRlQ2FydFhtbEh0dHBSZXF1ZXN0QnVmZmVyID0gW107XG5cdHVwZGF0ZUNhcnRCdWZmZXIgPSBbXTtcblxuXHRnZXRDYXJ0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHRpZiAoIWlzQ2FydFBhZ2UpIHtcblx0XHRnZXRPcmRlclN1bW1hcnlDYWxsb3V0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGdldENhcnRIdG1sKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuICAgIHZhciAkZm9ybSA9ICQoJyNjaGVja291dC1mb3JtJyk7XG4gICAgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydCddID0gbnVsbDtcblxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbJ2dldENhcnRIdG1sJ10gPSAkLmFqYXgoe1xuXHRcdHVybDogVXJscy5vbmVQYWdlU3VibWl0LFxuXHRcdHR5cGU6IFwiUE9TVFwiLFxuXHRcdGRhdGE6IHRyaWdnZXJFbGVtZW50TmFtZSArICc9JyArIHRyaWdnZXJFbGVtZW50TmFtZSArICcmc2VsZWN0ZWRQYXltZW50TWV0aG9kPScgKyAkKCdpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbCgpICsgJyZmb3JtYXQ9YWpheCcsXG5cdFx0c3VjY2VzcyA6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10gPSBkYXRhO1xuXHRcdFx0Z2V0Q2FydERhdGEodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0XHRcdHVwZGF0ZUNhcnRSZW5kZXIodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRPcmRlclN1bW1hcnlDYWxsb3V0SHRtbCh0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpIHtcbiAgICB1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10gPSBudWxsO1xuXG5cdHVwZGF0ZUNhcnRYbWxIdHRwUmVxdWVzdEJ1ZmZlclsnZ2V0T3JkZXJTdW1tYXJ5Q2FsbG91dEh0bWwnXSA9ICQuYWpheCh7XG5cdFx0dXJsOiBVcmxzLmdldE9yZGVyU3VtbWFyeUNhbGxvdXRDb250ZW50U2xvdCxcblx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10gPSBkYXRhO1xuXHRcdFx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGdldENhcnREYXRhKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddID0gbnVsbDtcblxuXHR1cGRhdGVDYXJ0WG1sSHR0cFJlcXVlc3RCdWZmZXJbJ2dldENhcnREYXRhJ10gPSAkLmFqYXgoe1xuXHQgICAgdXJsIDogVXJscy5nZXRDYXJ0RGF0YSxcblx0XHR0eXBlIDogXCJQT1NUXCIsXG5cdFx0ZGF0YToge1xuXHRcdFx0aXNDYXJ0OiBpc0NhcnRQYWdlXG5cdFx0fSxcblx0ICAgIHN1Y2Nlc3MgOiBmdW5jdGlvbiAoZGF0YSkge1xuXHQgICAgXHQkKCdbaGFzLWxvY2FsLWRlbGl2ZXJ5LXNoaXBtZW50XScpLmF0dHIoJ2hhcy1sb2NhbC1kZWxpdmVyeS1zaGlwbWVudCcsIGRhdGEuSGFzTG9jYWxEZWxpdmVyeVNoaXBtZW50IHx8IGZhbHNlKTtcblx0ICAgIFx0JCgnW2hhcy1waHlzaWNhbC1zaGlwbWVudF0nKS5hdHRyKCdoYXMtcGh5c2ljYWwtc2hpcG1lbnQnLCBkYXRhLkhhc1BoeXNpY2FsU2hpcG1lbnQgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy13YXJlaG91c2Utc2hpcG1lbnRdJykuYXR0cignaGFzLXdhcmVob3VzZS1zaGlwbWVudCcsIGRhdGEuSGFzV2FyZWhvdXNlU2hpcG1lbnQgfHwgZmFsc2UpO1xuXHRcdFx0JCgnW2hhcy13YXJlaG91c2Utc2hpcG1lbnRdJykuYXR0cignaGFzLXNoaXBwaW5nLW1ldGhvZHMnLCBkYXRhLlNoaXBwaW5nTWV0aG9kcyA/IGRhdGEuU2hpcHBpbmdNZXRob2RzLmpvaW4oJyAnKSA6IGZhbHNlKTtcblx0ICAgIFx0JCgnW2hhcy1naWZ0LWNhcmRzXScpLmF0dHIoJ2hhcy1naWZ0LWNhcmRzJywgZGF0YS5IYXNHaWZ0Q2FyZHMgfHwgZmFsc2UpO1xuXHQgICAgXHQkKCdbaGFzLWdpZnQtY2FyZHMtb25seV0nKS5hdHRyKCdoYXMtZ2lmdC1jYXJkcy1vbmx5JywgZGF0YS5IYXNHaWZ0Q2FyZHNPbmx5IHx8IGZhbHNlKTtcblx0XHRcdCQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50XScpLmF0dHIoJ2hhcy1zdG9yZS1waWNrdXAtc2hpcG1lbnQnLCAoZGF0YS5Cb3BpcyAmJiBkYXRhLkJvcGlzLkhhc1N0b3JlUGlja3VwU2hpcG1lbnQpIHx8IGZhbHNlKTtcblx0XHRcdCQoJ1toYXMtc3RvcmUtcGlja3VwLXNoaXBtZW50LW9ubHldJykuYXR0cignaGFzLXN0b3JlLXBpY2t1cC1zaGlwbWVudC1vbmx5JywgKGRhdGEuQm9waXMgJiYgZGF0YS5Cb3Bpcy5IYXNTdG9yZVBpY2t1cFNoaXBtZW50T25seSkgfHwgZmFsc2UpO1xuXHQgICAgXHQkKGRvY3VtZW50KS50cmlnZ2VyKCdDYXJ0RGF0YS5VcGRhdGUnLCBkYXRhKTtcblxuXHQgICAgXHR1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddID0gZGF0YTtcblx0ICAgIFx0aWYgKGRhdGEuQm9waXMpIHtcblx0ICAgIFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddID0gZGF0YS5Cb3Bpcztcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0aWYgKCFkYXRhLklzR2xvYmFsZVZhbGlkT3JJbmFjdGl2ZSkge1xuXHQgICAgXHRcdCQoJy5zZWN0aW9uLWNoZWNrb3V0JykuYWRkQ2xhc3MoJ2dsb2JhbC1lLXZhbGlkYXRpb24tZXJyb3InKTtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLmZpbmQoJy5jYXJ0LWVycm9ycycpLmFkZENsYXNzKCdhY3RpdmUnKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkKCcuc2VjdGlvbi1jaGVja291dCcpLnJlbW92ZUNsYXNzKCdnbG9iYWwtZS12YWxpZGF0aW9uLWVycm9yJyk7XG5cdCAgICBcdFx0JCgnLnNlY3Rpb24tY2hlY2tvdXQnKS5maW5kKCcuY2FydC1lcnJvcnMnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdCAgICBcdH1cblxuXHQgICAgXHRpZiAoZGF0YS5TaGlwcGluZ1Jlc3RyaWN0aW9ucyAmJiBkYXRhLlNoaXBwaW5nUmVzdHJpY3Rpb25zLlN0YXR1cyA9PSAnc2hpcHBpbmdSZXN0cmljdGlvbnNFcnJvcicpIHtcblx0XHRcdFx0aWYgKGlzQ2FydFBhZ2UpIHtcblx0XHRcdFx0XHQkKCcub3BjbG9naW4tYnV0dG9ucycpLmFkZENsYXNzKCdoaWRlJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kcy1zZWN0aW9uJykuaGlkZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoaXNDYXJ0UGFnZSkge1xuXHRcdFx0XHRcdCQoJy5vcGNsb2dpbi1idXR0b25zJykucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcblx0XHRcdFx0XHQkKCcuZ3Vlc3QtY2hlY2tvdXQgLmVycm9yLWZvcm0nKS5yZW1vdmUoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2RzLXNlY3Rpb24nKS5zaG93KCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0ICAgIFx0XG5cdCAgICBcdGhhbmRsZU9yZGVyVG90YWwodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKTtcblx0ICAgIH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU9yZGVyVG90YWwodHJpZ2dlckVsZW1lbnROYW1lLCBvcHRpb25zLCBpc0NhcnRQYWdlKSB7XG5cdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddID0gbnVsbDtcblx0dmFyIHJlbW92ZUFjdGlvbiA9ICc8YSBjbGFzcz1cInJlbW92ZVwiPlJlbW92ZTwvYT4nO1xuXHRcblx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHMubGVuZ3RoID4gMCkge1xuXHRcdHVwZGF0ZUNhcnRCdWZmZXJbJ1BheW1lbnRJbnN0cnVtZW50SHRtbCddID0gJyc7XG5cdFxuXHRcdGZvciAodmFyIHBheW1lbnRJbnN0cnVtZW50S2V5IGluIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHMpIHtcblx0XHRcdHZhciBwYXltZW50SW5zdHJ1bWVudCA9IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHNbcGF5bWVudEluc3RydW1lbnRLZXldO1xuXHRcdFx0dmFyIHBheW1lbnRJbnN0cnVtZW50VVVJREF0dHJpYnV0ZSA9ICd1dWlkPVwiJyArIHBheW1lbnRJbnN0cnVtZW50LlVVSUQgKyAnXCInO1xuXHRcdFx0XG5cdFx0XHRzd2l0Y2ggKHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuSWQpIHtcblx0XHRcdFx0Y2FzZSBQYXltZW50TWV0aG9kQ29uc3RhbnRzLlJld2FyZHNDcmVkaXQ6XG5cdFx0ICAgIFx0XHR1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSArPSAnPGRpdiAnICsgcGF5bWVudEluc3RydW1lbnRVVUlEQXR0cmlidXRlICsgJyBwYXltZW50LW1ldGhvZD1cIicgKyBwYXltZW50SW5zdHJ1bWVudC5wYXltZW50TWV0aG9kLklkICsgJ1wiIGFsbG93LXJlbW92ZT1cIicgKyBwYXltZW50SW5zdHJ1bWVudC5hbGxvd1JlbW92ZSArICdcIj4nICtcblx0XHQgICAgXHRcdFx0JzxzcGFuIGNsYXNzPVwibGFiZWxcIj48c3BhbiBjbGFzcz1cIm5hbWVcIj5CIFJld2FyZGVkPC9zcGFuPiZuYnNwOzxzcGFuIGNsYXNzPVwibnVtYmVyXCI+UmV3YXJkPC9zcGFuPjwvc3Bhbj4nICtcblx0XHQgICAgXHRcdFx0JzxzcGFuIGNsYXNzPVwidmFsdWVcIj4nICsgcGF5bWVudEluc3RydW1lbnQuYW1vdW50RGlzcGxheSArICc8L3NwYW4+JyArXG5cdFx0ICAgIFx0XHQnPC9kaXY+Jztcblx0XHQgICAgXHRicmVhaztcblx0XHRcdFxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdCAgICBcdFx0dXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10gKz0gJzxkaXYgJyArIHBheW1lbnRJbnN0cnVtZW50VVVJREF0dHJpYnV0ZSArICcgcGF5bWVudC1tZXRob2Q9XCInICsgcGF5bWVudEluc3RydW1lbnQucGF5bWVudE1ldGhvZC5JZCArICdcIiBhbGxvdy1yZW1vdmU9XCInICsgcGF5bWVudEluc3RydW1lbnQuYWxsb3dSZW1vdmUgKyAnXCI+JyArXG5cdFx0ICAgIFx0XHRcdCc8c3BhbiBjbGFzcz1cImxhYmVsXCI+PHNwYW4gY2xhc3M9XCJuYW1lXCI+JyArIHBheW1lbnRJbnN0cnVtZW50LnBheW1lbnRNZXRob2QuTmFtZSArICc8L3NwYW4+Jm5ic3A7PHNwYW4gY2xhc3M9XCJudW1iZXJcIj4nICsgcGF5bWVudEluc3RydW1lbnQubnVtYmVyTGFzdEZvdXIgKyAnPC9zcGFuPicgKyByZW1vdmVBY3Rpb24gKyAnPC9zcGFuPicgK1xuXHRcdCAgICBcdFx0XHQnPHNwYW4gY2xhc3M9XCJ2YWx1ZVwiPicgKyBwYXltZW50SW5zdHJ1bWVudC5hbW91bnREaXNwbGF5ICsgJzwvc3Bhbj4nICtcblx0XHQgICAgXHRcdCc8L2Rpdj4nO1xuXHRcdCAgICBcdGJyZWFrO1xuXHRcdCAgICB9XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0dpZnRDYXJkLkNsZWFyJyk7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignUmV3YXJkc0NyZWRpdC5DbGVhcicpO1xuXHR9XG5cdFxuXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwudG90YWwpIHtcblx0XHR1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddID0gJzxzcGFuIGNsYXNzPVwibGFiZWxcIj5CYWxhbmNlIER1ZTwvc3Bhbj4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInZhbHVlXCI+JyArIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlRGlzcGxheSArICc8L3NwYW4+Jztcblx0fVxuXHRcblx0dXBkYXRlQ2FydFJlbmRlcih0cmlnZ2VyRWxlbWVudE5hbWUsIG9wdGlvbnMsIGlzQ2FydFBhZ2UpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVDYXJ0UmVuZGVyKHRyaWdnZXJFbGVtZW50TmFtZSwgb3B0aW9ucywgaXNDYXJ0UGFnZSkge1xuXHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydCddICYmIChpc0NhcnRQYWdlIHx8ICh1cGRhdGVDYXJ0QnVmZmVyWydPcmRlclN1bW1hcnlDYWxsb3V0J10gJiYgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXSkpKSB7XG5cdFx0dmFyICRiYXNrZXRDb250YWluZXJIdG1sID0gJCh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0J10pO1xuXHRcblx0XHRpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXSAmJiB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwpIHtcblx0XHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbC1wcmljZSAudmFsdWUnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC50b3RhbERpc3BsYXkpO1xuXHQgICAgXHQkKCcucGF5bWVudC1zZWN0aW9uIC5vcmRlci10b3RhbC1wcmljZSAudmFsdWUnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC50b3RhbERpc3BsYXkpO1xuXHRcdFxuXHRcdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItdG90YWxzLXRhYmxlJykuYXR0cigncGF5bWVudHMtYXBwbGllZCcsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHMubGVuZ3RoKTtcblx0ICAgIFx0XHQkKCcucGF5bWVudC1zZWN0aW9uJykuYXR0cigncGF5bWVudHMtYXBwbGllZCcsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5wYXltZW50SW5zdHJ1bWVudHMubGVuZ3RoKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItdG90YWxzLXRhYmxlJykucmVtb3ZlQXR0cigncGF5bWVudHMtYXBwbGllZCcpO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5yZW1vdmVBdHRyKCdwYXltZW50cy1hcHBsaWVkJyk7XG5cdCAgICBcdH1cblx0XHRcblx0XHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUnKS5hdHRyKCdiYWxhbmNlLWR1ZScsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlKTtcblx0XHRcdCQoJyN3cmFwcGVyJykuYXR0cignYmFsYW5jZS1kdWUnLCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSk7XG5cdCAgICBcdCQoJy5wYXltZW50LXNlY3Rpb24nKS5hdHRyKCdiYWxhbmNlLWR1ZScsIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlKTtcblx0XHRcblx0XHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA+IDApIHtcblx0XHRcdFx0JCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbnMnKS5zaG93KCk7XG5cdFx0XHRcdCQoJy5wYXltZW50LXNlY3Rpb24tZm9vdGVyW2RhdGEtbWV0aG9kPVwiUGF5UGFsXCJdIGJ1dHRvbicpLmhpZGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCQoJy5wYXltZW50LW1ldGhvZC1vcHRpb25zJykuaGlkZSgpO1xuXHRcdFx0XHQkKCcucGF5bWVudC1zZWN0aW9uLWZvb3RlcltkYXRhLW1ldGhvZD1cIlBheVBhbFwiXSBidXR0b24nKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0XG5cdCAgICBcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddKSB7XHRcblx0ICAgIFx0XHQkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcub3JkZXItYmFsYW5jZS1kdWUnKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ0JhbGFuY2VEdWVIdG1sJ10pO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydCYWxhbmNlRHVlSHRtbCddKTsgICAgXHRcdFxuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLWJhbGFuY2UtZHVlJykuaHRtbCgnJyk7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSkge1xuXHQgICAgXHRcdCRiYXNrZXRDb250YWluZXJIdG1sLmZpbmQoJy5vcmRlci10b3RhbC1wYXltZW50cycpLmh0bWwodXBkYXRlQ2FydEJ1ZmZlclsnUGF5bWVudEluc3RydW1lbnRIdG1sJ10pO1xuXHQgICAgXHRcdCQoJy5wYXltZW50LXNlY3Rpb24gLm9yZGVyLXRvdGFsLXBheW1lbnRzJykuaHRtbCh1cGRhdGVDYXJ0QnVmZmVyWydQYXltZW50SW5zdHJ1bWVudEh0bWwnXSk7XG5cdCAgICBcdH0gZWxzZSB7XG5cdCAgICBcdFx0JCgnLnBheW1lbnQtc2VjdGlvbiAub3JkZXItdG90YWwtcGF5bWVudHMnKS5odG1sKCcnKTtcblx0ICAgIFx0fVxuXHRcdH1cblxuXHRcdCQoJy5hY2NvcmRpb24uY291cG9uIC5jYXJ0LWNvdXBvbi1jb2RlJykuaHRtbCgkYmFza2V0Q29udGFpbmVySHRtbC5maW5kKCcuY2FydC1jb3Vwb24tY29kZScpLmZpcnN0KCkuaHRtbCgpKTtcblx0XHQkKCcuYmFza2V0LWNvbnRhaW5lcicpLmh0bWwoJGJhc2tldENvbnRhaW5lckh0bWwpO1xuXHRcdFxuXHRcdGlmICh1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddKSB7XG5cdFx0XHR2YXIgb3JkZXJUb3RhbEZvckFmZmlybSA9IHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5iYWxhbmNlO1xuXHRcdFx0aWYgKCFvcmRlclRvdGFsRm9yQWZmaXJtICYmIHVwZGF0ZUNhcnRCdWZmZXJbJ0NhcnREYXRhJ10uT3JkZXJUb3RhbC5hZGp1c3RlZE1lcmNoYW5kaXplVG90YWxQcmljZSkge1xuXHRcdFx0XHRvcmRlclRvdGFsRm9yQWZmaXJtID0gdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmFkanVzdGVkTWVyY2hhbmRpemVUb3RhbFByaWNlO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkgJiYgb3JkZXJUb3RhbEZvckFmZmlybSA+PSB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLkFmZmlybU1pbmltdW1PcmRlclRvdGFsKSB7XG5cdFx0XHRcdCQoJy5hZmZpcm0tcHJvZHVjdC1tb2RhbCcpLmF0dHIoJ2RhdGEtYW1vdW50Jywgb3JkZXJUb3RhbEZvckFmZmlybSAqIDEwMCk7XG5cdFx0XHRcdGFmZmlybS51aS5yZWZyZXNoKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCcuYWZmaXJtLXByb2R1Y3QtbW9kYWwnKS5hdHRyKCdkYXRhLWFtb3VudCcsIDUwMDApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICgkKCcuYmFza2V0LWNvbnRhaW5lcicpLmZpbmQoJy5wcm9kdWN0LWF2YWlsYWJpbGl0eS1saXN0IC5ub3QtYXZhaWxhYmxlJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQsICNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcblx0XHRcdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXHRcdFx0JCgnI3N1Ym1pdE9QQ1BheW1lbnQnKS5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwLTIgbXQtMlwiIHJvbGU9XCJhbGVydFwiIHRhYmluZGV4PVwiMFwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPicgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5Qcm9kdWN0cy5BdmFpbGFiaWxpdHkgKyAnOjwvYj4gJyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLlByb2R1Y3RzLkF2YWlsYWJpbGl0eUV4Y2VlZGVkICsgJzwvZGl2PicpO1xuXHRcdH0gZWxzZSBpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQm9waXMnXSAmJiB1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddLk51bWJlck9mQm9waXNTdG9yZXNJbkNhcnQgPiB1cGRhdGVDYXJ0QnVmZmVyWydCb3BpcyddLk1heGltdW1OdW1iZXJPZkJvcGlzU3RvcmVzSW5DYXJ0KSB7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCwgI3N1Ym1pdE9QQ1BheW1lbnRQcml2YXRlTGFiZWwnKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuXHRcdFx0JCgnI2Vycm9yQm94T1BDJykucmVtb3ZlKCk7XG5cdFx0XHQkKCcjc3VibWl0T1BDUGF5bWVudCcpLmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+JyArIFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLkdlbmVyYWwuQ2FydExpbWl0ICsgJzo8L2I+ICcgKyBSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5Cb3Bpcy5NYXhpbXVtU3RvcmVzRXhjZWVkZWQgKyAnPC9kaXY+Jyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJyNzdWJtaXRPUENQYXltZW50LCAjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0XHQkKCcjZXJyb3JCb3hPUEMnKS5yZW1vdmUoKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSkge1x0XG5cdFx0XHQkKCcuY2FsbG91dC1vcmRlcnN1bW1hcnknKS5odG1sKHVwZGF0ZUNhcnRCdWZmZXJbJ09yZGVyU3VtbWFyeUNhbGxvdXQnXSk7XG5cdFx0fVxuXG5cdCAgICBpZiAoJCgnLmJhbm5lci1jYXJ0LWhvbGRlciAuYnRuLW1pbmljYXJ0JykubGVuZ3RoID4gMCkge1xuXHRcdFx0JC5hamF4KHt1cmwgOiBVcmxzLmNhcnRNaW5pQ2FydCwgZGF0YSA6IHtkZXNrdG9wOiAnMSd9LCBkYXRhVHlwZTogJ2h0bWwnLCBzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHQgICAgICAgICAgICAkKCcuYmFubmVyLWNhcnQtaG9sZGVyJykuaHRtbChkYXRhKTtcblx0ICAgICAgICB9fSk7XG5cdFx0XHRcblx0ICAgIFx0JC5hamF4KHt1cmwgOiBVcmxzLmNhcnRNaW5pQ2FydCwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0ICAgIFx0XHR2YXIgcGFyZW50TWluaUNhcnQgPSAkKFwiLnRvcC1iYW5uZXItaW5uZXItbGlua3MgI21pbmktY2FydFwiKTtcblx0ICAgIFx0XHRcblx0ICAgIFx0XHRpZiAocGFyZW50TWluaUNhcnQubGVuZ3RoID4gMCkge1xuXHQgICAgXHRcdFx0cGFyZW50TWluaUNhcnQuaHRtbChkYXRhKTtcblx0ICAgIFx0XHR9XG5cdCAgICAgICAgfX0pO1xuXHRcdH1cblx0ICAgIFxuICAgICAgICAkLmFqYXgoe3VybDogVXJscy5jYXJ0SXRlbVF1YW50aXR5LCBkYXRhOiB7ZGVza3RvcDogJzEnfSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgXHQkKCcuY29uZmlybWF0aW9uLW1lc3NhZ2UgLml0ZW0tY291bnQnKS5odG1sKGRhdGEpO1xuXHQgICAgICAgIFxuXHQgICAgICAgIHZhciBxdWFudGl0eSA9IHBhcnNlSW50KCQoJy5jb25maXJtYXRpb24tbWVzc2FnZSAuaXRlbS1jb3VudCcpLmZpbmQoJ3NwYW4nKS50ZXh0KCksIDEwKTtcblx0ICAgICAgICBpZiAoIXF1YW50aXR5KSB7XG5cdCAgICAgICAgICAgICQoJy5jaGVja291dC1idXR0b25zLm1vYmlsZS1vbmx5JykuaGlkZSgpO1x0ICAgICAgICAgICAgXG5cdFx0XHR9XG5cdFx0fX0pO1xuXHRcdFxuXHQgICAgXG5cdCAgICBpZiAodHJpZ2dlckVsZW1lbnROYW1lLmluZGV4T2YoJ2RlbGV0ZVByb2R1Y3QnKSA+IC0xKSB7XG5cdCAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ3JlZnJlc2gtcmVxdWlyZWQnKTtcblx0ICAgIH1cblxuXHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5FdmVudFRyaWdnZXJzIHx8IG9wdGlvbnMuRXZlbnRUcmlnZ2Vyc1sndXBkYXRlLXN1bW1hcnknXSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXN1bW1hcnknKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLkV2ZW50VHJpZ2dlcnMgfHwgb3B0aW9ucy5FdmVudFRyaWdnZXJzWyd1cGRhdGUtc2hpcHBpbmcnXSkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcigndXBkYXRlLXNoaXBwaW5nJyk7XG5cdFx0fVxuXHQgICAgXG5cdCAgICAkKCdbbWluaW11bS1jYXJ0LXRvdGFsXSwgW21heGltdW0tY2FydC10b3RhbF0nKS5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdCAgICBcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdCAgICBcdHZhciBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWluaW11bSA9IHBhcnNlRmxvYXQoJHRoaXMuYXR0cignbWluaW11bS1jYXJ0LXRvdGFsJykpO1xuXHQgICAgXHR2YXIgcGF5bWVudE1ldGhvZENhcnRUb3RhbE1heGltdW0gPSBwYXJzZUZsb2F0KCR0aGlzLmF0dHIoJ21heGltdW0tY2FydC10b3RhbCcpKTtcblx0ICAgIFxuXHQgICAgXHR2YXIgaXNDYXJ0VG90YWxNaW5pbXVtVmFsaWQgPSBmYWxzZTtcblx0ICAgIFx0aWYgKGlzTmFOKHBheW1lbnRNZXRob2RDYXJ0VG90YWxNaW5pbXVtKSB8fCB1cGRhdGVDYXJ0QnVmZmVyWydDYXJ0RGF0YSddLk9yZGVyVG90YWwuYmFsYW5jZSA+PSBwYXltZW50TWV0aG9kQ2FydFRvdGFsTWluaW11bSkge1xuXHQgICAgXHRcdGlzQ2FydFRvdGFsTWluaW11bVZhbGlkID0gdHJ1ZTtcblx0ICAgIFx0fVxuXHQgICAgXHRcblx0ICAgIFx0dmFyIGlzQ2FydFRvdGFsTWF4aW11bVZhbGlkID0gZmFsc2U7XG5cdCAgICBcdGlmIChpc05hTihwYXltZW50TWV0aG9kQ2FydFRvdGFsTWF4aW11bSkgfHwgdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5PcmRlclRvdGFsLmJhbGFuY2UgPD0gcGF5bWVudE1ldGhvZENhcnRUb3RhbE1heGltdW0pIHtcblx0ICAgIFx0XHRpc0NhcnRUb3RhbE1heGltdW1WYWxpZCA9IHRydWU7XG5cdCAgICBcdH1cblx0ICAgIFx0XG5cdCAgICBcdGlmIChpc0NhcnRUb3RhbE1pbmltdW1WYWxpZCAmJiBpc0NhcnRUb3RhbE1heGltdW1WYWxpZCkge1xuXHQgICAgXHRcdCR0aGlzLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5hdHRyKCd2YWxpZC1mb3ItYmFsYW5jZS1kdWUnLCAndHJ1ZScpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdCR0aGlzLmNsb3Nlc3QoJy5wYXltZW50LW1ldGhvZC1vcHRpb24nKS5hdHRyKCd2YWxpZC1mb3ItYmFsYW5jZS1kdWUnLCAnZmFsc2UnKTtcblx0ICAgIFx0fVxuXHQgICAgfSk7XG5cdFx0XG5cdCAgICBpZiAodXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXSAmJiAhdXBkYXRlQ2FydEJ1ZmZlclsnQ2FydERhdGEnXS5IYXNQaHlzaWNhbFNoaXBtZW50ICYmICQoJy5zaW5nbGUuc2hpcHBpbmctYWRkcmVzcy10eXBlLXNlbGVjdG9yIGlucHV0OmNoZWNrZWQnKS52YWwoKSAhPSBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lcikge1xuXHQgICAgXHQkKCcuc2luZ2xlLnNoaXBwaW5nLWFkZHJlc3MtdHlwZS1zZWxlY3RvciBpbnB1dFt2YWx1ZT1cIicgKyBTaXRlQ29uc3RhbnRzLkFkZHJlc3NUeXBlcy5DdXN0b21lciArICdcIl0nKS5jbGljaygpO1xuXHQgICAgfVxuXHRcdFxuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy5zaGlwcGluZy1tZXRob2QtdG9vbHRpcCcsXG5cdFx0XHR0b29sdGlwQ2xhc3M6ICdzaGlwcGluZy1tZXRob2QtdG9vbHRpcCdcblx0XHR9LCAkKCdbc2hpcHBpbmctbWV0aG9kXScpKTtcblxuXHRcdHRvb2x0aXAuaW5pdCh7XG5cdFx0XHRpdGVtczogJy50b29sdGlwJ1xuXHRcdH0pO1xuXG5cdFx0dHJpZ2dlclNyRm9jdXMoKTtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdRdWFudGl0eVN0ZXBwZXIuVGFyZ2V0Rm9jdXMnKTtcblx0ICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ0NhcnQuVXBkYXRlU3VjY2VzcycpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHRyaWdnZXJTckZvY3VzKCkge1xuXHQkKCdbcm9sZT1cImFsZXJ0XCJdJykubGFzdCgpLmZvY3VzKCk7XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdFBheW1lbnQoZGF0YSkge1xuXHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKHtcblx0XHRJc0ltYWdlU2hvd246IGZhbHNlLFxuXHRcdExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5DaGVja291dC5QbGFjaW5nT3JkZXJcblx0fSk7XG5cdCRzdWJtaXRQYXltZW50LmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXG5cdCRjaGVja291dEZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XHRcblx0JGNoZWNrb3V0Rm9ybS52YWxpZGF0ZSgpLnNldHRpbmdzLmlnbm9yZSA9IFtdO1xuXHRcblx0aWYgKCRjaGVja291dEZvcm0udmFsaWQoKSkge1xuXHRcdHNldE9QQ1BheW1lbnREYXRhKCRjaGVja291dEZvcm0sICRzdWJtaXRQYXltZW50LmF0dHIoJ25hbWUnKSkudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0dmFyIGRhdGE7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGRhdGEgPSByZXNwb25zZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2U7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnYWZmaXJtUmVkaXJlY3QnKSB7XG5cdFx0XHRcdHZhciBfYWZmaXJtX2NvbmZpZyA9IHtcblx0XHRcdFx0XHRwdWJsaWNfYXBpX2tleTogZGF0YS5hZmZpcm0uUHVibGljQXBpS2V5LFxuXHRcdFx0XHRcdHNjcmlwdDogZGF0YS5hZmZpcm0uU2NyaXB0XG5cdFx0XHRcdH07XG5cdFx0XHRcdChmdW5jdGlvbihsLGcsbSxlLGEsZixiKXt2YXIgZCxjPWxbbV18fHt9LGg9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChmKSxuPWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKGYpWzBdLGs9ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBmdW5jdGlvbigpe2FbYl0uXy5wdXNoKFtjLGFyZ3VtZW50c10pfX07Y1tlXT1rKGMsZSxcInNldFwiKTtkPWNbZV07Y1thXT17fTtjW2FdLl89W107ZC5fPVtdO2NbYV1bYl09ayhjLGEsYik7YT0wO2ZvcihiPVwic2V0IGFkZCBzYXZlIHBvc3Qgb3BlbiBlbXB0eSByZXNldCBvbiBvZmYgdHJpZ2dlciByZWFkeSBzZXRQcm9kdWN0XCIuc3BsaXQoXCIgXCIpO2E8Yi5sZW5ndGg7YSsrKWRbYlthXV09ayhjLGUsYlthXSk7YT0wO2ZvcihiPVtcImdldFwiLFwidG9rZW5cIixcInVybFwiLFwiaXRlbXNcIl07YTxiLmxlbmd0aDthKyspZFtiW2FdXT1mdW5jdGlvbigpe307aC5hc3luYz0hMDtoLnNyYz1nW2ZdO24ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoaCxuKTtkZWxldGUgZ1tmXTtkKGcpO2xbbV09Y30pKHdpbmRvdyxfYWZmaXJtX2NvbmZpZyxcImFmZmlybVwiLFwiY2hlY2tvdXRcIixcInVpXCIsXCJzY3JpcHRcIixcInJlYWR5XCIpO1xuXHRcdFx0XHRcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0KEpTT04ucGFyc2UoZGF0YS5hZmZpcm0uQWZmaXJtQ2hlY2tvdXQpKTtcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0LnBvc3QoKTtcblx0XHRcdFx0YWZmaXJtLnVpLnJlYWR5KFxuXHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0YWZmaXJtLnVpLmVycm9yLm9uKFwiY2xvc2VcIiwgZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdFx0Ly8gd2luZG93LmxvY2F0aW9uLnJlcGxhY2UoZGF0YS5hZmZpcm0uUmVkaXJlY3RVcmwpO1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHQpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InKXtcblx0XHRcdFx0dmFyIHBvcHVwID0gcmVxdWlyZSgnLi4vcG9wdXAnKTtcblx0XHRcdFx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cblx0XHRcdFx0dmFyIGxpc3QgPSAkLm1hcChwYXlsb2FkLmxpc3QsIGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0XHRcdHJldHVybiAnPGxpPicgKyBlbC5uYW1lICsgJzo8YnI+JyArIGVsLm1lc3NhZ2UgKyAnPC9saT4nO1xuXHRcdFx0XHR9KS5qb2luKCcnKTtcblx0XHRcdFx0XG5cdFx0XHRcdHBvcHVwLmluaXQoe1xuXHRcdFx0XHRcdHRpdGxlOiBwYXlsb2FkLnRpdGxlLFxuXHRcdFx0XHRcdGNvbnRlbnQ6IHBheWxvYWQubWVzc2FnZSArICc8dWwgY2xhc3M9XCJzaGlwcGluZy1yZXN0cmljdGlvbnMtcG9wdXBfX2xpc3RcIj4nICsgbGlzdCArICc8L3VsPicsXG5cdFx0XHRcdH0pLnNob3dQb3B1cCgpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ1ZhbGlkYXRpb25FcnJvcicpIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+VmFsaWRhdGlvbiBFcnJvcjo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+UGF5bWVudCBEZWNsaW5lZDo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHQkc3VibWl0UGF5bWVudC5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHR9KS5jYXRjaChmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyA9PSAzMDIgJiYgcmVzcG9uc2UucmVzcG9uc2VUZXh0KSB7XG5cdFx0XHRcdGxvY2F0aW9uLmhyZWYgPSByZXNwb25zZS5yZXNwb25zZVRleHQ7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0gZWxzZSB7XG5cdFx0JHN1Ym1pdFBheW1lbnQubG9hZGluZygnZGVzdHJveScpO1xuXHRcdCRzdWJtaXRQYXltZW50LmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHR9XG59XG5cbnZhciBzZXRPUENQYXltZW50RGF0YSA9IGZ1bmN0aW9uICgkZm9ybSwgbmFtZSkge1xuXHR2YXIgcGF5bG9hZCA9ICRmb3JtLnNlcmlhbGl6ZSgpICsgJyYnICsgbmFtZSArICc9JyArIG5hbWU7XG5cdHZhciAkY2hlY2tvdXRWYXJpYWJsZXMgPSAkKCcuYnV0dG9uLWFuZC10ZXJtcyBpbnB1dFt0eXBlPVwiaGlkZGVuXCJdJyk7XG5cdCRjaGVja291dFZhcmlhYmxlcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0cGF5bG9hZCArPSAnJicgKyAkdGhpcy5hdHRyKCduYW1lJykgKyAnPScgKyAkdGhpcy52YWwoKTtcblx0fSk7XG5cbiAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuc2V0T3BjQWRkcmVzcyksXG4gICAgICAgIGRhdGE6IHBheWxvYWRcbiAgICB9KSk7XG59O1xuXG5mdW5jdGlvbiBzZWFyY2hSZXdhcmRzKCkge1xuXHRpZiAoZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10gJiYgZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10ucmVhZHlTdGF0ZSAhPT0gNCkge1xuXHRcdGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddLmFib3J0KCk7XG5cdFx0ZGF0YUJ1ZmZlclsnUmV3YXJkc0FjY291bnRTZWFyY2hSZXF1ZXN0J10gPSBudWxsO1xuXHR9XG5cdCRyZXdhcmRzQXBwbGllZC5odG1sKCcnKTtcblxuXHR2YXIgcGF5bG9hZCA9IHtcblx0XHRFbWFpbEFkZHJlc3M6ICRyZXdhcmRzRm9ybS5maW5kKCcjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNFbWFpbCcpLnZhbCgpLFxuXHRcdFBob25lTnVtYmVyOiAkcmV3YXJkc0Zvcm0uZmluZCgnLmZpZWxkLnBob25lbnVtYmVyJykudmFsKCksXG5cdFx0WmlwQ29kZTogJHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC56aXBjb2RlJykudmFsKCksXG5cdH1cblxuXHRpZiAoJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgpKSB7XG5cdFx0cGF5bG9hZC5SZXdhcmRzTnVtYmVyID0gJHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbCgpO1xuXHR9XG5cblx0JCgnLmJ0bi5zZWFyY2gtZWNobycpLmxvYWRpbmcoe1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdH0pO1xuXG5cdGRhdGFCdWZmZXJbJ1Jld2FyZHNBY2NvdW50U2VhcmNoUmVxdWVzdCddID0gJC5hamF4KHtcblx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0dXJsOiBVcmxzLnNlYXJjaEZvclJld2FyZHMsXG5cdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHBheWxvYWQpLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdHJlbmRlclJld2FyZHNEYXRhKGRhdGEpO1xuXHRcdH0sXG5cdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0aWYgKCQoJy5idG4uc2VhcmNoLWVjaG8nKS5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0JCgnLmJ0bi5zZWFyY2gtZWNobycpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZW5kZXJSZXdhcmRzRGF0YShkYXRhKSB7XG5cdGlmIChkYXRhLk1hdGNoICYmIGRhdGEuUmV3YXJkcykge1xuXHRcdGlmIChkYXRhLlJld2FyZHMucmV3YXJkc051bWJlcikge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc051bWJlcicpLnZhbChkYXRhLlJld2FyZHMucmV3YXJkc051bWJlcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcjZHdmcm1fYmlsbGluZ19yZXdhcmRzX3Jld2FyZHNOdW1iZXInKS52YWwoJycpO1xuXHRcdH1cblx0XHRpZiAoZGF0YS5SZXdhcmRzLmVtYWlsKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnI2R3ZnJtX2JpbGxpbmdfcmV3YXJkc19yZXdhcmRzRW1haWwnKS52YWwoZGF0YS5SZXdhcmRzLmVtYWlsKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJyNkd2ZybV9iaWxsaW5nX3Jld2FyZHNfcmV3YXJkc0VtYWlsJykudmFsKCcnKTtcblx0XHR9XG5cdFx0aWYgKGRhdGEuUmV3YXJkcy5waG9uZSkge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC5waG9uZW51bWJlcicpLnZhbChkYXRhLlJld2FyZHMucGhvbmUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmZpZWxkLnBob25lbnVtYmVyJykudmFsKCcnKTtcblx0XHR9XG5cdFx0aWYgKGRhdGEuUmV3YXJkcy56aXBWYWx1ZSkge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5maWVsZC56aXBjb2RlJykudmFsKGRhdGEuUmV3YXJkcy56aXBWYWx1ZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuZmllbGQuemlwY29kZScpLnZhbCgnJyk7XG5cdFx0fVxuXG5cdFx0aWYgKGRhdGEuTWF0Y2guUmV3YXJkc0VtYWlsKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLnJld2FyZHMtZW1haWwtY29udGFpbmVyJykuYXR0cignbWF0Y2gnLCAndHJ1ZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLnJld2FyZHMtZW1haWwtY29udGFpbmVyJykuYXR0cignbWF0Y2gnLCAnZmFsc2UnKTtcblx0XHR9XG5cdFx0aWYgKGRhdGEuTWF0Y2guUmV3YXJkc1Bob25lKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmlucHV0LWNvbnRhaW5lci5waG9uZScpLmF0dHIoJ21hdGNoJywgJ3RydWUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5pbnB1dC1jb250YWluZXIucGhvbmUnKS5hdHRyKCdtYXRjaCcsICdmYWxzZScpO1xuXHRcdH1cblx0XHRpZiAoZGF0YS5NYXRjaC5SZXdhcmRzWmlwKSB7XG5cdFx0XHQkcmV3YXJkc0Zvcm0uZmluZCgnLmlucHV0LWNvbnRhaW5lci56aXAnKS5hdHRyKCdtYXRjaCcsICd0cnVlJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXdhcmRzRm9ybS5maW5kKCcuaW5wdXQtY29udGFpbmVyLnppcCcpLmF0dHIoJ21hdGNoJywgJ2ZhbHNlJyk7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciByZXdhcmRzUm93VGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1yZXdhcmRzLWNyZWRpdC1yb3ctZWNobycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcblx0XHR2YXIgc3RhdHVzID0gJyc7XG5cdFx0dmFyIG1lc3NhZ2UgPSAnJztcblx0XHRpZiAocGFyc2VGbG9hdChkYXRhLlJld2FyZHMuY3JlZGl0QW1vdW50KSA8PSAwKSB7XG5cdFx0XHRzdGF0dXMgPSAnbWVzc2FnZSc7XG5cdFx0XHRtZXNzYWdlID0gJ25vIHJld2FyZHMgYXZhaWxhYmxlJztcblx0XHR9IGVsc2UgaWYgKCRyZXdhcmRzRm9ybS5jbG9zZXN0KCdbaXMtYXBwbGllZF0nKS5hdHRyKCdpcy1hcHBsaWVkJykgPT0gJ3RydWUnKSB7XG5cdFx0XHRzdGF0dXMgPSAnYXBwbGllZCc7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHN0YXR1cyA9ICdwZW5kaW5nJztcblx0XHR9XG5cblx0XHR2YXIgYWRkaXRpb25hbERhdGEgPSAnPHRhYmxlIGNsYXNzPVwicmV3YXJkcy1pbmZvcm1hdGlvblwiPicgK1xuXHRcdFx0XHRcdFx0XHRcdCc8dHI+PHRkPkFkZHJlc3M8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLmFkZHJlc3MgKyAnPC90ZD48L3RyPicgK1xuXHRcdFx0XHRcdFx0XHRcdCc8dHI+PHRkPkNpdHk8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLmNpdHkgKyAnPC90ZD48L3RyPicgK1xuXHRcdFx0XHRcdFx0XHRcdCc8dHI+PHRkPlN0YXRlPC90ZD48dGQ+JyArIGRhdGEuUmV3YXJkcy5zdGF0ZSArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+WmlwPC90ZD48dGQ+JyArIGRhdGEuUmV3YXJkcy56aXBWYWx1ZSArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+Q291bnRyeTwvdGQ+PHRkPicgKyBkYXRhLlJld2FyZHMuY291bnRyeSArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdFx0Jzx0cj48dGQ+UGhvbmU8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLnBob25lICsgJzwvdGQ+PC90cj4nICtcblx0XHRcdFx0XHRcdFx0JzwvdGFibGU+PHRhYmxlIGNsYXNzPVwicmV3YXJkcy1wb2ludHNcIj4nICtcblx0XHRcdFx0XHRcdFx0XHQnPHRyPjx0ZD5Qb2ludHM8L3RkPjx0ZD4nICsgZGF0YS5SZXdhcmRzLnBvaW50QmFsYW5jZSArICc8L3RkPjwvdHI+JyArXG5cdFx0XHRcdFx0XHRcdCc8L3RhYmxlPic7XG5cblx0XHQkcmV3YXJkc0FwcGxpZWQuaHRtbChyZXdhcmRzUm93VGVtcGxhdGUoe1xuXHRcdFx0U3RhdHVzOiBzdGF0dXMsXG5cdFx0XHRSZXdhcmRzTnVtYmVyOiBkYXRhLlJld2FyZHMucmV3YXJkc051bWJlcixcblx0XHRcdE5hbWU6IGRhdGEuUmV3YXJkcy5mdWxsTmFtZSxcblx0XHRcdEVtYWlsOiBkYXRhLlJld2FyZHMuZW1haWwsXG5cdFx0XHRSZXdhcmRzQXZhaWxhYmxlOiBkYXRhLlJld2FyZHMuY3JlZGl0QW1vdW50Rm9ybWF0dGVkLnJlcGxhY2UoJy4wMCcsICcnKSxcblx0XHRcdFJld2FyZHNFeHBpcmF0aW9uRGF0ZTogZGF0YS5SZXdhcmRzLmNyZWRpdEV4cGlyYXRpb25EYXRlIHx8ICduL2EnLFxuXHRcdFx0TWVzc2FnZTogbWVzc2FnZSxcblx0XHRcdEFkZGl0aW9uYWxEYXRhOiBhZGRpdGlvbmFsRGF0YVxuXHRcdH0pKTtcblx0XHRpZiAoJHJld2FyZHNBY2NvcmRpb24uZmluZCgnaGVhZGVyIC5yZXdhcmRzLXBvaW50cycpLmxlbmd0aCkge1xuXHRcdFx0JHJld2FyZHNBY2NvcmRpb24uZmluZCgnaGVhZGVyIC5yZXdhcmRzLXBvaW50cycpLnRleHQoZGF0YS5SZXdhcmRzLnBvaW50QmFsYW5jZSk7XG5cdFx0fVxuXG5cdFx0JHJld2FyZHNBY2NvcmRpb24uYXR0cigncmV3YXJkcy1mb3VuZCcsICd0cnVlJyk7XG5cdFx0JHJld2FyZHNGb3JtLmZpbmQoJy5idG4ucmVzZXQtZWNobycpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdFx0aWYgKCEkKCcuYWNjb3JkaW9uLnJld2FyZHMgLmFjY29yZGlvbi1oZWFkJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG5cdFx0XHQkKCcuYWNjb3JkaW9uLnJld2FyZHMgLmFjY29yZGlvbi1oZWFkJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHQkcmV3YXJkc0FjY29yZGlvbi5yZW1vdmVBdHRyKCdyZXdhcmRzLWZvdW5kJyk7XG5cdFx0JHJld2FyZHNBcHBsaWVkLmh0bWwoJzxwIGNsYXNzPVwibm8tcmVzdWx0c1wiPm5vIHJld2FyZHMgZm91bmQ8L3A+Jyk7XG5cdH1cbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Mb2IgJiYgb3B0aW9ucy5Mb2IuQWRkcmVzc1ZlcmlmaWNhdGlvbi5FbmFibGVkKSB7XG5cdFx0QWRkcmVzc1ZlcmlmaWNhdGlvbkRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvcmUvY2FydHJpZGdlL2pzL0xvYi9BZGRyZXNzVmVyaWZpY2F0aW9uL0FkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cnKTtcblx0fVxuXG5cdGlmIChvcHRpb25zICYmIG9wdGlvbnMuTG9iICYmIG9wdGlvbnMuTG9iLkFkZHJlc3NBdXRvY29tcGxldGUuRW5hYmxlZCkge1xuXHRcdEFkZHJlc3NBdXRvY29tcGxldGVEaWFsb2cgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9hcHBfc3RvcmVmcm9udF9jb3JlL2NhcnRyaWRnZS9qcy9Mb2IvQWRkcmVzc0F1dG9jb21wbGV0ZS9BZGRyZXNzQXV0b2NvbXBsZXRlRGlhbG9nJyk7XG5cdH1cblxuXHRHaWZ0Q2FyZC5pbml0aWFsaXplKCQuZXh0ZW5kKHsgTG9hZGluZ0luZGljYXRvcjoge1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdH19LCBvcHRpb25zKSk7XG5cblx0UmV3YXJkc0NyZWRpdC5pbml0aWFsaXplKCQuZXh0ZW5kKHsgTG9hZGluZ0luZGljYXRvcjoge1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0QmFja2dyb3VuZENvbG9yOiAndHJhbnNwYXJlbnQnXG5cdH19LCBvcHRpb25zKSk7XG5cblx0QXBwbGVQYXkuaW5pdGlhbGl6ZShvcHRpb25zKTtcblxuICAgIGluaXRpYWxpemUob3B0aW9ucyk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZFByb2R1Y3RUb0NhcnQgPSByZXF1aXJlKCcuL3Byb2R1Y3QvYWRkVG9DYXJ0JyksXG4gICAgYWpheCA9IHJlcXVpcmUoJy4uL2FqYXgnKSxcbiAgICBwYWdlID0gcmVxdWlyZSgnLi4vcGFnZScpLFxuICAgIHByb2R1Y3RUaWxlID0gcmVxdWlyZSgnLi4vcHJvZHVjdC10aWxlJyksXG4gICAgcXVpY2t2aWV3ID0gcmVxdWlyZSgnLi4vcXVpY2t2aWV3Jyk7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBjbGljayBldmVudHMgdG8gdGhlIHJlbW92ZS1saW5rIGFuZCBxdWljay12aWV3IGJ1dHRvblxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgICQoJyNjb21wYXJlLXRhYmxlJykub24oJ2NsaWNrJywgJy5yZW1vdmUtbGluaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgYWpheC5nZXRKc29uKHtcbiAgICAgICAgICAgIHVybDogdGhpcy5ocmVmLFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSlcbiAgICAub24oJ2NsaWNrJywgJy5vcGVuLXF1aWNrLXZpZXcnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciB1cmwgPSAkKHRoaXMpLmNsb3Nlc3QoJy5wcm9kdWN0JykuZmluZCgnLnRodW1iLWxpbmsnKS5hdHRyKCdocmVmJyk7XG4gICAgICAgIHF1aWNrdmlldy5zaG93KHtcbiAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgc291cmNlOiAncXVpY2t2aWV3J1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgICQoJyNjb21wYXJlLWNhdGVnb3J5LWxpc3QnKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKHRoaXMpLmNsb3Nlc3QoJ2Zvcm0nKS5zdWJtaXQoKTtcbiAgICB9KTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIHByb2R1Y3RUaWxlLmluaXQoKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgYWRkUHJvZHVjdFRvQ2FydCgpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyXHR1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIHBhZ2UgPSByZXF1aXJlKCcuLi9wYWdlJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCl7XG5cdFxuXHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgJ3BhZ2VQYXRoJyBpbiBwYWdlQ29udGV4dCAmJiAocGFnZUNvbnRleHQucGFnZVBhdGggPT0gJ0JSZXdhcmRlZEJhbGFuY2VDaGVjaycgfHwgcGFnZUNvbnRleHQucGFnZVBhdGggPT0gJ0FjY291bnRWaWV3JyB8fCBwYWdlQ29udGV4dC5wYWdlUGF0aCA9PSAnUmV3YXJkc1Byb2dyYW0nKSkge1xuICAgIFx0cGFzc0JyZWFkU2V0dXAoKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBwYXNzQnJlYWRTZXR1cCgpIHtcblx0dmFyIHJld2FyZHNOdW1iZXIgPSAkKCcuY3VzdG9tZXItcmV3YXJkcy1udW1iZXInKS50ZXh0KCk7XG5cblx0QnJlYWRQYXltZW50cy5zZXR1cCh7XG5cdFx0bG95YWx0eUlEOiByZXdhcmRzTnVtYmVyLFxuXHRcdHN0b3JlTnVtYmVyOiB1dGlsLmlzTW9iaWxlKCkgPyBTaXRlUHJlZmVyZW5jZXMuUExDQ19TVE9SRV9OVU1CRVJfTU9CSUxFIDogU2l0ZVByZWZlcmVuY2VzLlBMQ0NfU1RPUkVfTlVNQkVSX1dFQixcblx0XHRleGlzdGluZ0NhcmRIb2xkZXI6IGZhbHNlLFxuXHRcdGVudjogU2l0ZVByZWZlcmVuY2VzLlBMQ0NfRU5WSVJPTk1FTlQsXG5cdH0pO1xuXG5cdEJyZWFkUGF5bWVudHMucmVnaXN0ZXJQbGFjZW1lbnRzKFtsYW5kaW5nUGxhY2VtZW50XSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7ICAgIFxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHF1aWNrdmlldyA9IHJlcXVpcmUoJy4uL3F1aWNrdmlldycpO1xudmFyIGJvbnVzUHJvZHVjdHNWaWV3ID0gcmVxdWlyZSgnLi4vYm9udXMtcHJvZHVjdHMtdmlldycpO1xudmFyIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXIgYWRkcmVzc2VzID0gU2l0ZVByZWZlcmVuY2VzLkVOQUJMRV9FTkhBTkNFRF9DSEVDS09VVCA/IHJlcXVpcmUoJy4vY2hlY2tvdXQvb3BjYWRkcmVzc19lbmhhbmNlZCcpIDogcmVxdWlyZSgnLi9jaGVja291dC9vcGNhZGRyZXNzJyk7XG52YXIgZm9ybVByZXBhcmUgPSByZXF1aXJlKCcuL2NoZWNrb3V0L2Zvcm1QcmVwYXJlJyk7XG52YXIgY2FydCA9IHJlcXVpcmUoJy4vY2FydCcpO1xudmFyIG9wY3BheW1lbnQgPSByZXF1aXJlKCcuL2NoZWNrb3V0L29wY3BheW1lbnQnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgR2lmdENhcmQgPSByZXF1aXJlKCcuL2NoZWNrb3V0L0dpZnRDYXJkUGF5bWVudFBhbmVsJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgcmVjYXB0Y2hhID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9SZWNhcHRjaGEnKTtcbnZhciBSZXdhcmRzQ3JlZGl0ID0gcmVxdWlyZSgnLi9jaGVja291dC9SZXdhcmRzQ3JlZGl0Jyk7XG52YXIgTG95YWx0eUNyZWRpdCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvTG95YWx0eUNyZWRpdCcpO1xudmFyIENoZWNrb3V0Q29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9DaGVja291dENvbnN0YW50cycpO1xudmFyIFBheW1lbnRNZXRob2RDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuUGF5bWVudE1ldGhvZHM7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgY2FydEl0ZW1zRm9ybVNlbGVjdG9yID0gJ2Zvcm0jY2FydC1pdGVtcy1mb3JtJztcbnZhciBiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3RvciA9ICcjYmlsbGluZ0FkZHJlc3NGb3JtJztcbnZhciAkYmlsbGluZ0FkZHJlc3NGb3JtID0gJChiaWxsaW5nQWRkcmVzc0Zvcm1TZWxlY3Rvcik7XG52YXIgc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yID0gJyNzaGlwcGluZ0FkZHJlc3NGb3JtJztcbnZhciAkc2hpcHBpbmdBZGRyZXNzRm9ybSA9ICQoc2hpcHBpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcbnZhciBwYXltZW50U2VjdGlvblNlbGVjdG9yID0gJy5mb3JtLWNoZWNrb3V0LnBheW1lbnQtc2VjdGlvbic7XG52YXIgJHBheW1lbnRTZWN0aW9uID0gJChwYXltZW50U2VjdGlvblNlbGVjdG9yKTtcbnZhciBwYXltZW50Rm9ybVNlbGVjdG9yID0gJyNwYXltZW50U2VjdGlvbic7XG52YXIgJHBheW1lbnRGb3JtID0gJChwYXltZW50Rm9ybVNlbGVjdG9yKTtcbnZhciBjcmVkaXRDYXJkTGlzdFNlbGVjdG9yID0gJyNjcmVkaXRDYXJkTGlzdCc7XG52YXIgJGNyZWRpdENhcmRMaXN0ID0gJChjcmVkaXRDYXJkTGlzdFNlbGVjdG9yKTtcbnZhciBzdWJtaXRQYXltZW50U2VsZWN0b3IgPSAnLnBheW1lbnQtc2VjdGlvbi1mb290ZXIgYnV0dG9uW25hbWUqPVwiX3N1Ym1pdFBheW1lbnRcIl06bm90KCNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsKSc7XG52YXIgJHN1Ym1pdFBheW1lbnQgPSAkKHN1Ym1pdFBheW1lbnRTZWxlY3Rvcik7XG52YXIgc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudFNlbGVjdG9yID0gJyNzdWJtaXRPUENQYXltZW50UHJpdmF0ZUxhYmVsJztcbnZhciAkc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudCA9ICQoc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudFNlbGVjdG9yKTtcbnZhciBiYXNrZXRDb250YWluZXJTZWxlY3RvciA9ICcuYmFza2V0LWNvbnRhaW5lcic7XG52YXIgJGJhc2tldENvbnRhaW5lciA9ICQoYmFza2V0Q29udGFpbmVyU2VsZWN0b3IpO1xuXG52YXIgcGxhY2VPcmRlclJlY2FwdGNoYTtcbnZhciBwbGFjZU9yZGVyUmVjYXB0Y2hhUGF5cGFsO1xudmFyIHBsYWNlT3JkZXJSZWNhcHRjaGFBZmZpcm07XG52YXIgcGxhY2VPcmRlclJlY2FwdGNoYVByaXZhdGVMYWJlbDtcbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGVkID0ge307XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEV2ZW50cyBzaG91bGQgYmUgZGl2aWRlZCB0byBtb2R1bGVzLiBUaGlzIGFsbG93cyByZWluaXRpYWxpemUgZXZlbnRzIGJ5IHNlY3Rpb25zIGFmdGVyIHBhcnRpYWwgcmVsb2FkXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZXZlbnRzIGZvciB0aGUgZ2lmdCByZWdpc3RyYXRpb25cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cyhvcHRpb25zKSB7XG5cdGluaXRpYWxpemVDYXJ0RXZlbnRzKG9wdGlvbnMpO1xuXHRpbml0aWFsaXplUGF5bWVudE1ldGhvZHNFdmVudHMoKTtcblx0XG5cdHJlbmRlclJlY2FwdGNoYSgpO1xuXHQkKGRvY3VtZW50KS5vbignUmVjYXB0Y2hhLkxvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0aWYgKCFsb2FkZWQuUmVjYXB0Y2hhKSB7XG5cdFx0XHRsb2FkZWQuUmVjYXB0Y2hhID0gdHJ1ZTtcblx0ICAgICAgICByZW5kZXJSZWNhcHRjaGEoKTtcblx0ICAgIH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVDYXJ0RXZlbnRzKG9wdGlvbnMpIHtcbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCAnYS5hZGQtdG8td2lzaGxpc3QnLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0LypyZW1vdmUgbmV4dCBsaW5lIHRvIHVzZSBkZWZhdWx0IGR3IHdpc2hsaXN0IGZ1bmN0aW9uYWxpdHkqL1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgXHRpZihDdXN0b21lci5hdXRoZW50aWNhdGVkID09IHRydWUpe1xuICAgIFx0XHQvL3Bvc3QgZm9ybSBoZXJlXG4gICAgXHR9IGVsc2Uge1xuICAgIFx0XHQkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7IHNjcm9sbFRvcDogJCgnLmxvZ2luLWZvcm0nKS5lcSgwKS5vZmZzZXQoKS50b3B9LCAxMDAwKTtcbiAgICBcdH1cbiAgICB9KTtcbiAgICBcbiAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkFMVEVSTkFURV9QSUNLVVBfRU5BQkxFRCkge1xuXHRcdHJlbmRlckFsdGVybmF0ZVBpY2t1cCgpO1xuXHR9XG5cblx0JHBheW1lbnRGb3JtLm9uKCdjaGFuZ2UnLCAnW25hbWUkPVwiX2NyZWRpdENhcmRfdHlwZVwiXScsIGZ1bmN0aW9uKCkge1xuXHRcdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoZmFsc2UpO1xuXHRcdCQodGhpcykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuZmluZCgnZGl2LmZpZWxkLXdyYXBwZXIuZXJyb3InKS5yZW1vdmUoKTtcblx0fSk7XG5cblx0JHN1Ym1pdFBheW1lbnQub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcblx0XHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikge1xuXHRcdFx0c3VibWl0UGF5bWVudCgpO1xuXHRcdH1cbiAgICB9KTtcblxuXHQkKGRvY3VtZW50KS5vbignQ2hlY2tvdXQuU3VibWl0UGF5bWVudCcsIGZ1bmN0aW9uICgpIHtcblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikge1xuXHRcdFx0c3VibWl0UGF5bWVudCgpO1xuXHRcdH1cblx0fSk7XG5cdFxuICAgICRzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50Lm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikge1xuXHRcdFx0c3VibWl0UGF5bWVudFByaXZhdGVMYWJlbCgpO1x0XG5cdFx0fVxuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdDaGVja291dC5TdWJtaXRQYXltZW50UHJpdmF0ZUxhYmVsJywgZnVuY3Rpb24gKCkge1xuICAgIFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIpIHtcblx0XHRcdHN1Ym1pdFBheW1lbnRQcml2YXRlTGFiZWwoKTtcblx0XHR9XG5cdH0pO1xuICAgIFxuICAgIHZhciBnZXRDcmVkaXRDYXJkSW5mbyA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLmJpbGxpbmdTZWxlY3RDQyksXG4gICAgICAgICAgICBkYXRhOiB7Y2NJRDogaWR9XG4gICAgICAgIH0pKTtcbiAgICB9O1xuXG4gICAgJGNyZWRpdENhcmRMaXN0Lm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpIHtcbiAgICBcdHZhciBjY0lEID0gJCh0aGlzKS52YWwoKTtcbiAgICBcdGlmIChjY0lELmxlbmd0aCA8PSAwKSB7XG4gICAgXHRcdHJldHVybjtcbiAgICBcdH1cbiAgICBcdGdldENyZWRpdENhcmRJbmZvKGNjSUQpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YSA9IHJlc3BvbnNlO1xuXHRcdFx0aWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ21hc2tlZE51bWJlcicpKSB7XG5cdFx0XHRcdCQoJyNkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfb3duZXInKS52YWwoZGF0YS5ob2xkZXIpLnZhbGlkKCk7XG5cdFx0XHRcdCQoJyNkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfdHlwZVt2YWx1ZT1cIicrZGF0YS50eXBlKydcIl0nKVxuXHRcdFx0XHRcdC5maXJzdCgpXG5cdFx0XHRcdFx0LnByb3AoJ2NoZWNrZWQnLCB0cnVlKVxuXHRcdFx0XHRcdC50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdFx0JChcIltpZF49J2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9udW1iZXInXVwiKS5maXJzdCgpLnZhbChkYXRhLm1hc2tlZE51bWJlcikudmFsaWQoKTtcblx0XHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX21vbnRoJykudmFsKGRhdGEuZXhwaXJhdGlvbk1vbnRoKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdFx0JCgnI2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX3llYXInKS52YWwoZGF0YS5leHBpcmF0aW9uWWVhcikudHJpZ2dlcignY2hhbmdlJyk7XG5cdFx0XHRcdCQoJ2lucHV0W25hbWVePWR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9jdm5dJykudmFsKCcnKTtcblx0XHRcdH1cblx0XHR9LmJpbmQodGhpcykpO1xuXG4gICAgfSk7XG5cbiAgICAvL3ByZXNlbGVjdCBkZWZhdWx0IGNyZWRpdCBjYXJkXG5cdGlmKCRjcmVkaXRDYXJkTGlzdC5sZW5ndGggPiAwICYmICQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoKSA9PSBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQpIHtcblx0XHQkY3JlZGl0Q2FyZExpc3QuZmluZCgnb3B0aW9uJykuZXEoMSkucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHQkY3JlZGl0Q2FyZExpc3QudHJpZ2dlcignY2hhbmdlJyk7XG5cdH1cblxuICAgIHZhciBnZXRQcml2YXRlTGFiZWxDYXJkSW5mbyA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLmJpbGxpbmdTZWxlY3RQcml2YXRlTGFiZWwpLFxuICAgICAgICAgICAgZGF0YToge2NhcmRJZDogaWR9XG4gICAgICAgIH0pKTtcbiAgICB9O1xuXG4gICAgdmFyICRwcml2YXRlTGFiZWxDYXJkTGlzdCA9ICQoJyNwcml2YXRlTGFiZWxDYXJkTGlzdCcpO1xuICAgICRwcml2YXRlTGFiZWxDYXJkTGlzdC5vbignY2hhbmdlJywgZnVuY3Rpb24oKSB7XG4gICAgXHR2YXIgY2FyZElkID0gJCgnI3ByaXZhdGVMYWJlbENhcmRMaXN0JykudmFsKCk7XG4gICAgXHRpZiAoY2FyZElkLmxlbmd0aCA8PSAwKSB7XG4gICAgXHRcdHJldHVybjtcbiAgICBcdH1cbiAgICBcdGdldFByaXZhdGVMYWJlbENhcmRJbmZvKGNhcmRJZCkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdHZhciBkYXRhID0gcmVzcG9uc2U7XG5cdFx0XHRpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWFza2VkTnVtYmVyJykpIHtcblx0XHRcdFx0JChcIltpZF49J2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfcHJpdmF0ZUxhYmVsQ2FyZF9udW1iZXInXVwiKS5maXJzdCgpLnZhbChkYXRhLm1hc2tlZE51bWJlcikudmFsaWQoKTtcblx0XHRcdH1cblx0XHR9LmJpbmQodGhpcykpO1xuXG4gICAgfSk7XG5cblx0Ly8gcHJlc2VsZWN0IGRlZmF1bHQgcHJpdmF0ZSBsYWJlbCBjYXJkXG5cdGlmICgkcHJpdmF0ZUxhYmVsQ2FyZExpc3QubGVuZ3RoID4gMCkge1xuXHRcdCRwcml2YXRlTGFiZWxDYXJkTGlzdC5maW5kKCdvcHRpb24nKS5lcSgxKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXHRcdCRwcml2YXRlTGFiZWxDYXJkTGlzdC50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fVxuXG4gICAgYWRkcmVzc2VzLmluaXQob3B0aW9ucyk7XG4gICAgY2FydC5pbml0KG9wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJBbHRlcm5hdGVQaWNrdXAoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJykub24oJ2NsaWNrJywgJ2J1dHRvbi5hbHQtcGlja3VwLWJ1dHRvbicsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JCgnI2FsdC1waWNrdXAtbW9kYWwnKS5hZGRDbGFzcygnYWN0aXZlLW1vZGFsJykuc2hvdygpO1xuXHRcdCQoJ2ZpZWxkc2V0IHNwYW4nKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnI2FsdC1waWNrdXAtbW9kYWwgLmNsb3NlLW1vZGFsJykub24oJ2NsaWNrJywgJyNhbHQtcGlja3VwLW1vZGFsIC5jbG9zZS1tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JCgnI2FsdC1waWNrdXAtbW9kYWwnKS5yZW1vdmVDbGFzcygnYWN0aXZlLW1vZGFsJykuaGlkZSgpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdmb2N1cycsICdpbnB1dFtuYW1lPVwiZmlyc3ROYW1lXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5maXJzdG5hbWUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJsYXN0TmFtZVwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcubGFzdG5hbWUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJlbWFpbFwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcuZW1haWwtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdmb2N1cycsICdpbnB1dFtuYW1lPVwicGhvbmVcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCgnLnBob25lLWVycm9yJykucmVtb3ZlQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdCQoJy5vbmUtcmVxdWlyZWQnKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbiNhbHRQaWNrdXBTdWJtaXQnKS5vbignY2xpY2snLCAnYnV0dG9uI2FsdFBpY2t1cFN1Ym1pdCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG4gICAgXHR2YXIgaXNGaXJzdE5hbWVWYWxpZCA9IHRydWU7XG5cdFx0dmFyIGZpcnN0TmFtZSA9ICQoJ2lucHV0W25hbWU9XCJmaXJzdE5hbWVcIl0nKS52YWwoKTtcblx0XHR2YXIgcmVnZXhOYW1lID0gL15bYS16ICwuJy1dKyQvaTtcblx0XHRpZiAoZmlyc3ROYW1lLmxlbmd0aCA9PSAwIHx8IGZpcnN0TmFtZS5tYXRjaChyZWdleE5hbWUpID09IG51bGwpIHtcblx0XHRcdGlzRmlyc3ROYW1lVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5maXJzdG5hbWUtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciBpc0xhc3ROYW1lVmFsaWQgPSB0cnVlO1x0XHRcblx0XHR2YXIgbGFzdE5hbWUgPSQoJ2lucHV0W25hbWU9XCJsYXN0TmFtZVwiXScpLnZhbCgpO1xuXHRcdGlmIChsYXN0TmFtZS5sZW5ndGggPT0gMCB8fCBsYXN0TmFtZS5tYXRjaChyZWdleE5hbWUpID09IG51bGwpIHtcblx0XHRcdGlzTGFzdE5hbWVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLmxhc3RuYW1lLWVycm9yJykuYWRkQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgaXNFbWFpbFZhbGlkID0gdHJ1ZTtcdFx0XG5cdFx0dmFyIGVtYWlsID0gJCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykudmFsKCk7XG5cdFx0dmFyIHJlZ2V4RW1haWwgPSAvXlthLXpBLVowLTkuISMkJSYnKisvPT9eX2B7fH1+LV0rQFthLXpBLVowLTktXSsoPzpcXC5bYS16QS1aMC05LV0rKSokL2c7XG5cdFx0aWYgKGVtYWlsLmxlbmd0aCA+IDAgJiYgZW1haWwubWF0Y2gocmVnZXhFbWFpbCkgPT0gbnVsbCkge1xuXHRcdFx0aXNFbWFpbFZhbGlkID0gZmFsc2U7XG5cdFx0XHQkKCcuZW1haWwtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXG5cdFx0dmFyIGlzUGhvbmVWYWxpZCA9IHRydWU7XG5cdFx0dmFyIHBob25lID0gJCgnaW5wdXRbbmFtZT1cInBob25lXCJdJykudmFsKCkucmVwbGFjZSgvXFxEL2csICcnKTtcblx0XHR2YXIgcmVnZXhQaG9uZSA9IC9eXFwrP1xcKD8oWzAtOV1bMC04XVswLTldKVxcKT9bXFwtXFwuIF0/KFsyLTldWzAtOV17Mn0pW1xcLVxcLiBdPyhbMC05XXs0fSkoXFxzKnhbMC05XSspPyQvZztcblx0XHRpZiAocGhvbmUubGVuZ3RoID4gMCAmJiBwaG9uZS5tYXRjaChyZWdleFBob25lKSA9PSBudWxsKSB7XG5cdFx0XHRpc1Bob25lVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5waG9uZS1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cdFx0XG4gICAgXHRpZiAoZW1haWwubGVuZ3RoID09IDAgJiYgcGhvbmUubGVuZ3RoID09IDApIHtcbiAgICBcdFx0JCgnLm9uZS1yZXF1aXJlZCcpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgIFx0XHRpc0VtYWlsVmFsaWQgPSBmYWxzZTtcbiAgICBcdFx0aXNQaG9uZVZhbGlkID0gZmFsc2U7XG4gICAgXHR9XG4gICAgXHRcbiAgICBcdGlmICghaXNFbWFpbFZhbGlkIHx8ICFpc1Bob25lVmFsaWQpIHtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuICAgIFx0XG5cdFx0aWYgKGlzRmlyc3ROYW1lVmFsaWQgJiYgaXNMYXN0TmFtZVZhbGlkICYmIChpc0VtYWlsVmFsaWQgfHwgaXNQaG9uZVZhbGlkKSkge1xuXHRcdFx0dmFyIGNsZWFuUGhvbmUgPSBwaG9uZS5yZXBsYWNlKC9cXEQvZywgJycpO1xuXHRcdFx0dmFyIHNoaXBtZW50SUQgPSAkKCcuYWx0ZXJuYXRlLXBpY2t1cCcpLmNsb3Nlc3QoXCJmb3JtXCIpLmF0dHIoJ3NoaXBtZW50Jyk7XG5cdFx0XHRcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHVybDogVXJscy5zZXRBbHRlcm5hdGVQaWNrdXAsXG5cdFx0XHRcdHR5cGU6IFwiZ2V0XCIsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRzaGlwbWVudElEOiBzaGlwbWVudElELFxuXHRcdFx0XHRcdGFsdFBpY2t1cEZpcnN0TmFtZTogZmlyc3ROYW1lLFxuXHRcdFx0XHRcdGFsdFBpY2t1cExhc3ROYW1lOiBsYXN0TmFtZSxcblx0XHRcdFx0XHRhbHRQaWNrdXBFbWFpbDogZW1haWwsXG5cdFx0XHRcdFx0YWx0UGlja3VwUGhvbmU6IGNsZWFuUGhvbmVcblx0XHRcdFx0fSxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0XHRcdCQoJ3NwYW4uYWx0LXBlcnNvbicpLmF0dHIoJ2RhdGEtZmlyc3RuYW1lJywgZmlyc3ROYW1lKS5hdHRyKCdkYXRhLWxhc3RuYW1lJywgbGFzdE5hbWUpLmF0dHIoJ2RhdGEtZW1haWwnLCBlbWFpbCkuYXR0cignZGF0YS1waG9uZScsIGNsZWFuUGhvbmUpO1xuXHRcdFx0XHRcdFx0ZGlzcGxheUFsdGVybmF0ZVBpY2t1cCAoZmlyc3ROYW1lICsgJyAnICsgbGFzdE5hbWUpXG5cdFx0XHRcdFx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUtbW9kYWwnKS5oaWRlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRcdFx0Y29uc29sZS5sb2codGV4dFN0YXR1cywgZXJyb3JUaHJvd24pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRpc3BsYXlBbHRlcm5hdGVQaWNrdXAgKGZ1bGxOYW1lKSB7XG5cdCQoJy5hbHRlcm5hdGUtcGlja3VwIHNwYW4uYWx0LXBlcnNvbicpLnRleHQoZnVsbE5hbWUpO1xuXHQkKCdzcGFuLmFsdC1oZWFkZXInKS5zaG93KCk7XG5cdCQoJ2J1dHRvbi5hbHQtcGlja3VwLWJ1dHRvbicpLnRleHQoJ1VQREFURScpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJSZWNhcHRjaGEoKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdGlmICgkKCcjc3VibWl0T1BDUGF5bWVudCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBsYWNlT3JkZXJSZWNhcHRjaGEgPSBncmVjYXB0Y2hhLnJlbmRlcignc3VibWl0T1BDUGF5bWVudCcsIHtcblx0XHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdFx0ICAgICAgICBjYWxsYmFjazogc3VibWl0UGF5bWVudCxcblx0XHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0XHQgICAgfSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICgkKCcjc3VibWl0T1BDUGF5bWVudFBheXBhbCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBsYWNlT3JkZXJSZWNhcHRjaGFQYXlwYWwgPSBncmVjYXB0Y2hhLnJlbmRlcignc3VibWl0T1BDUGF5bWVudFBheXBhbCcsIHtcblx0XHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdFx0ICAgICAgICBjYWxsYmFjazogc3VibWl0UGF5bWVudCxcblx0XHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0XHQgICAgfSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICgkKCcjc3VibWl0T1BDUGF5bWVudEZvckFmZmlybScpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBsYWNlT3JkZXJSZWNhcHRjaGFBZmZpcm0gPSBncmVjYXB0Y2hhLnJlbmRlcignc3VibWl0T1BDUGF5bWVudEZvckFmZmlybScsIHtcblx0XHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdFx0ICAgICAgICBjYWxsYmFjazogc3VibWl0UGF5bWVudCxcblx0XHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0XHQgICAgfSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICgkKCcjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBsYWNlT3JkZXJSZWNhcHRjaGFQcml2YXRlTGFiZWwgPSBncmVjYXB0Y2hhLnJlbmRlcignc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcsIHtcblx0XHQgICAgICAgIHNpdGVrZXk6IG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXksXG5cdFx0ICAgICAgICBjYWxsYmFjazogc3VibWl0UGF5bWVudFByaXZhdGVMYWJlbCxcblx0XHQgICAgICAgIGJhZGdlOiAnYm90dG9tbGVmdCdcblx0XHQgICAgfSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGxveWFsdHlPcHRpbigpIHtcblx0aWYgKFNpdGVQcmVmZXJlbmNlcy5MT1lBTFRZX0VOQUJMRUQpIHtcblx0XHR2YXIgb3B0X2VtYWlsID0gJCgnLmJpbGxpbmctZW1haWwtYWRkcmVzcycpLnRleHQoKTtcblx0XHR2YXIgb3B0X3N0YXR1cyA9ICQoJyNsb3lhbHR5X29wdGluJykucHJvcCgnY2hlY2tlZCcpO1xuXHRcdHZhciBkd19jdXN0b21lcl9pZCA9IChDdXN0b21lci5hdXRoZW50aWNhdGVkID09IHRydWUpID8gJCgnLnNlY3Rpb24tY2hlY2tvdXQnKS5hdHRyKCdkYXRhLWN1c3RvbWVyaWQnKSA6ICcnO1xuXHRcdFxuXHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG5cdFx0XHRpZiAob3B0X3N0YXR1cyA9PSBmYWxzZSkge1xuXHRcdFx0XHQvLyB0cmFjayBDb3JkaWFsIGxveWFsdHkgb3B0b3V0IGV2ZW50XG5cdFx0XHRcdHZhciBhdXRoX2RhdGEgPSB7XG5cdFx0XHRcdFx0ZW1haWw6IG9wdF9lbWFpbFxuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0XHQgICAgJ2NoYW5uZWxzJzoge1xuXHRcdFx0XHQgICAgICAgICdlbWFpbCc6IHtcblx0XHRcdFx0ICAgICAgICAgICAgJ2FkZHJlc3MnOiBvcHRfZW1haWwgICAgICAgICBcblx0XHRcdFx0ICAgICAgICB9XG5cdFx0XHRcdCAgICB9XG5cdFx0XHRcdH07XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgcHJvcGVydGllcyA9IHtcblx0XHRcdFx0ICAgICdlbWFpbCc6IG9wdF9lbWFpbFxuXHRcdFx0XHR9O1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRcdGNyZGwoW1xuXHRcdFx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRcdFx0WydldmVudCcsICdsb3lhbHR5X29wdG91dCcsIHByb3BlcnRpZXNdXG5cdFx0XHRcdFx0XSk7XHRcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHRyZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLmxveWFsdHlPcHRpbixcblx0XHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0J2VtYWlsJzogb3B0X2VtYWlsLFxuXHRcdFx0XHQnZHdDdXN0b21lcklEJzogZHdfY3VzdG9tZXJfaWQsXG5cdFx0XHRcdCdvcHRTdGF0dXMnOiBvcHRfc3RhdHVzXG5cdFx0XHR9LFx0XHRcdFx0XHRcdFxuXHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0aWYgKCgnZXJyb3InIGluIGRhdGEgJiYgZGF0YVsnZXJyb3InXSkpIHtcblx0XHRcdFx0XHRjb25zb2xlLmxvZyhkYXRhLm1lc3NhZ2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSkpO1xuXHR9IGVsc2Uge1xuXHRcdFRQcm9taXNlLnJlc29sdmUoKTtcblx0fVxufVxuXG5mdW5jdGlvbiBzdWJtaXRQYXltZW50KCkge1xuXHR2YXIgYmFsYW5jZUR1ZSA9IHBhcnNlRmxvYXQoJHBheW1lbnRTZWN0aW9uLmF0dHIoJ2JhbGFuY2UtZHVlJykpO1xuXHQkc3VibWl0UGF5bWVudC5maWx0ZXIoJzp2aXNpYmxlJykubG9hZGluZyh7XG5cdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRMYWJlbDogUmVzb3VyY2VzLkxvYWRpbmcuQ2hlY2tvdXQuUGxhY2luZ09yZGVyXG5cdH0pO1xuXHRcblx0c2V0UGxhY2VPcmRlckJ1dHRvbnNEaXNhYmxlZCh0cnVlKTtcblx0XG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcblx0dmFyICRjcmVkaXRDYXJkVHlwZSA9ICRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0aWYgKGJhbGFuY2VEdWUgPiAwKSB7XG5cdFx0JHBheW1lbnRGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcdFxuXHRcdGlmICh0eXBlb2YgJGNyZWRpdENhcmRUeXBlID09PSAndW5kZWZpbmVkJykge1xuICAgIFx0XHQkcGF5bWVudEZvcm0uZmluZCgnW25hbWUkPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLmNsb3Nlc3QoJ2Rpdi5mb3JtLXJvdycpLmZpbmQoJ2Rpdi5maWVsZC13cmFwcGVyLmVycm9yJykucmVtb3ZlKCk7XG4gICAgXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICBcdFx0XHQkcGF5bWVudEZvcm0uZmluZCgnW25hbWUkPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLmNsb3Nlc3QoJ2Rpdi5mb3JtLXJvdycpLmFwcGVuZCgnPGRpdiBjbGFzcz1cImZpZWxkLXdyYXBwZXIgZXJyb3JcIiBzdHlsZT1cImhlaWdodDowcHg7XCI+PHNwYW4gY2xhc3M9XCJlcnJvclwiPicgKyBSZXNvdXJjZXMuUkVRVUlSRURfRklFTEQgKyAnPC9zcGFuPjwvZGl2PicpO1xuICAgIFx0XHR9LCA1MCk7XG4gICAgXHR9XG5cdH1cblx0XG5cdC8vY2hlY2sgZmlyc3QgaWYgYWRkcmVzc2VzIGFyZSB2YWxpZFxuXHR2YXIgaXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdHZhciBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdFxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdFxuXHRpZiAoJGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0aXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gdHJ1ZTtcblx0fSBlbHNlIHtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXQucmVxdWlyZWQuZmllbGQuZXJyb3InKS5lcSgwKS5mb2N1cygpO1xuXHR9XG5cdFxuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSkge1xuXHRcdGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgPSB0cnVlO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnNob3coKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdH1cblx0XG5cdGlmIChpc0JpbGxpbmdBZGRyZXNzVmFsaWQgJiYgaXNTaGlwcGluZ0FkZHJlc3NWYWxpZCAmJiAkKCcjc2hpcHBpbmctbWV0aG9kLWxpc3QgaW5wdXQ6Y2hlY2tlZCcpLmxlbmd0aCAmJiAoYmFsYW5jZUR1ZSA9PSAwIHx8ICRwYXltZW50Rm9ybS52YWxpZCgpKSkge1xuXHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG5cdFx0XG5cdFx0dmFyIGFjdGlvbk5hbWUgPSAkc3VibWl0UGF5bWVudC5maWx0ZXIoJzp2aXNpYmxlJykuYXR0cignbmFtZScpO1xuXHRcdHNldE9QQ1BheW1lbnREYXRhKCRwYXltZW50Rm9ybSwgYWN0aW9uTmFtZSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblx0XHRcdHZhciBkYXRhO1xuICAgICAgICAgICAgdHJ5IHtcblx0XHRcdFx0ZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRkYXRhID0gcmVzcG9uc2U7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3N1Y2Nlc3MnKSB7XG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFBheW1lbnRJbmZvJykudGhlbihsb3lhbHR5T3B0aW4pLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKG9wdGlvbnMuQ2hlY2tvdXRNb2RlID09ICdNb2JpbGVBcHAnKSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZUZvck1vYmlsZUFwcDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KS5jYXRjaChmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAob3B0aW9ucy5DaGVja291dE1vZGUgPT0gJ01vYmlsZUFwcCcpIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlRm9yTW9iaWxlQXBwO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ2FmZmlybVJlZGlyZWN0Jykge1xuXHRcdFx0XHR2YXIgX2FmZmlybV9jb25maWcgPSB7XG5cdFx0XHRcdFx0cHVibGljX2FwaV9rZXk6IGRhdGEuYWZmaXJtLlB1YmxpY0FwaUtleSxcblx0XHRcdFx0ICAgIHNjcmlwdDogZGF0YS5hZmZpcm0uU2NyaXB0XG5cdFx0XHRcdH07XG5cdFx0XHRcdChmdW5jdGlvbihsLGcsbSxlLGEsZixiKXt2YXIgZCxjPWxbbV18fHt9LGg9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChmKSxuPWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKGYpWzBdLGs9ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBmdW5jdGlvbigpe2FbYl0uXy5wdXNoKFtjLGFyZ3VtZW50c10pfX07Y1tlXT1rKGMsZSxcInNldFwiKTtkPWNbZV07Y1thXT17fTtjW2FdLl89W107ZC5fPVtdO2NbYV1bYl09ayhjLGEsYik7YT0wO2ZvcihiPVwic2V0IGFkZCBzYXZlIHBvc3Qgb3BlbiBlbXB0eSByZXNldCBvbiBvZmYgdHJpZ2dlciByZWFkeSBzZXRQcm9kdWN0XCIuc3BsaXQoXCIgXCIpO2E8Yi5sZW5ndGg7YSsrKWRbYlthXV09ayhjLGUsYlthXSk7YT0wO2ZvcihiPVtcImdldFwiLFwidG9rZW5cIixcInVybFwiLFwiaXRlbXNcIl07YTxiLmxlbmd0aDthKyspZFtiW2FdXT1mdW5jdGlvbigpe307aC5hc3luYz0hMDtoLnNyYz1nW2ZdO24ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoaCxuKTtkZWxldGUgZ1tmXTtkKGcpO2xbbV09Y30pKHdpbmRvdyxfYWZmaXJtX2NvbmZpZyxcImFmZmlybVwiLFwiY2hlY2tvdXRcIixcInVpXCIsXCJzY3JpcHRcIixcInJlYWR5XCIpO1xuXHRcdFx0XHRcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0KEpTT04ucGFyc2UoZGF0YS5hZmZpcm0uQWZmaXJtQ2hlY2tvdXQpKTtcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0LnBvc3QoKTtcblx0XHRcdFx0YWZmaXJtLnVpLnJlYWR5KFxuXHRcdFx0XHQgICAgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCAgICAgICAgYWZmaXJtLnVpLmVycm9yLm9uKFwiY2xvc2VcIiwgZnVuY3Rpb24oKXtcblx0XHRcdFx0ICAgICAgICAgICAgLy8gd2luZG93LmxvY2F0aW9uLnJlcGxhY2UoZGF0YS5hZmZpcm0uUmVkaXJlY3RVcmwpO1xuXHRcdFx0XHQgICAgICAgIH0pO1xuXHRcdFx0XHQgICAgfVxuXHRcdFx0XHQpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InKXtcblx0XHRcdFx0dmFyIHBvcHVwID0gcmVxdWlyZSgnLi4vcG9wdXAnKTtcblx0XHRcdFx0dmFyIHBheWxvYWQgPSBKU09OLnBhcnNlKGRhdGEucGF5bG9hZCk7XG5cblx0XHRcdFx0dmFyIGxpc3QgPSAkLm1hcChwYXlsb2FkLmxpc3QsIGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0XHRcdHJldHVybiAnPGxpPicgKyBlbC5uYW1lICsgJzo8YnI+JyArIGVsLm1lc3NhZ2UgKyAnPC9saT4nO1xuXHRcdFx0XHR9KS5qb2luKCcnKTtcblx0XHRcdFx0XG5cdFx0XHRcdHBvcHVwLmluaXQoe1xuXHRcdFx0XHRcdHRpdGxlOiBwYXlsb2FkLnRpdGxlLFxuXHRcdFx0XHRcdGNvbnRlbnQ6IHBheWxvYWQubWVzc2FnZSArICc8dWwgY2xhc3M9XCJzaGlwcGluZy1yZXN0cmljdGlvbnMtcG9wdXBfX2xpc3RcIj4nICsgbGlzdCArICc8L3VsPicsXG5cdFx0XHRcdH0pLnNob3dQb3B1cCgpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ0JpbGxpbmdBZGRyZXNzRXJyb3InKSB7XG5cdFx0XHRcdHZhciBtZXNzYWdlID0gZGF0YS5oYXNPd25Qcm9wZXJ0eSgnbWVzc2FnZScpID8gZGF0YS5tZXNzYWdlIDogUmVzb3VyY2VzLkNoZWNrb3V0LkNvbmZpcm0uRXJyb3IuR2VuZXJpYztcblx0XHRcdFx0JHN1Ym1pdFBheW1lbnQuYWZ0ZXIoJzxkaXYgaWQ9XCJlcnJvckJveE9QQ1wiIGNsYXNzPVwicGF5bWVudC1kZWNsaW5lZCBwLTIgbXQtMlwiPjxpIGNsYXNzPVwiZmEgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGVcIj48L2k+IDxiPkJpbGxpbmcgQWRkcmVzcyBFcnJvcjo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ1NoaXBwaW5nQWRkcmVzc0Vycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5TaGlwcGluZyBBZGRyZXNzIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnVmFsaWRhdGlvbkVycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5WYWxpZGF0aW9uIEVycm9yOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5QYXltZW50IERlY2xpbmVkOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdCRzdWJtaXRQYXltZW50LmZpbHRlcignOnZpc2libGUnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRzZXRQbGFjZU9yZGVyQnV0dG9uc0Rpc2FibGVkKGZhbHNlKTtcblx0XHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGEpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAocGxhY2VPcmRlclJlY2FwdGNoYVBheXBhbCAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0Z3JlY2FwdGNoYS5yZXNldChwbGFjZU9yZGVyUmVjYXB0Y2hhUGF5cGFsKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHBsYWNlT3JkZXJSZWNhcHRjaGFBZmZpcm0gIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYUFmZmlybSk7XG5cdFx0XHR9XG5cdFx0fSkuY2F0Y2goZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdGlmIChyZXNwb25zZS5zdGF0dXMgPT0gMzAyICYmIHJlc3BvbnNlLnJlc3BvbnNlVGV4dCkgeyBcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IHJlc3BvbnNlLnJlc3BvbnNlVGV4dDtcblx0XHRcdH1cblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHQkc3VibWl0UGF5bWVudC5maWx0ZXIoJzp2aXNpYmxlJykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoZmFsc2UpO1xuXG5cdFx0Ly8gQWRkaW5nIEFEQSBjb21wbGlhbmNlIGVycm9yIG1lc3NhZ2VzIGZvciBzdWJtaXRQYXltZW50IHNlY3Rpb25cblx0XHQkcGF5bWVudEZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0aWYgKCRwYXltZW50Rm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkKCcucGF5bWVudC1kZWNsaW5lZCcpLnJlbW92ZSgpO1xuXHRcdFx0dmFyIHBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyA9IG9wY3BheW1lbnQuZ2V0RXJyb3JNZXNzYWdlcygkcGF5bWVudEZvcm0pO1xuXHRcdFx0dmFyIHBheW1lbnRGb3JtRXJyb3JCb3ggPSBvcGNwYXltZW50LmVycm9yQm94KCdDYW5ub3QgUHJvY2VlZCcsICdQbGVhc2UgZml4IHRoZSBmb2xsb3dpbmcgZXJyb3JzOicsIHBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyk7XG5cdFx0XHRpZiAocGF5bWVudEZvcm1FcnJvckJveCkge1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcihwYXltZW50Rm9ybUVycm9yQm94KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0aWYgKHBsYWNlT3JkZXJSZWNhcHRjaGEgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGEpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAocGxhY2VPcmRlclJlY2FwdGNoYVBheXBhbCAhPSB1bmRlZmluZWQpIHtcblx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYVBheXBhbCk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhQWZmaXJtICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0Z3JlY2FwdGNoYS5yZXNldChwbGFjZU9yZGVyUmVjYXB0Y2hhQWZmaXJtKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gc3VibWl0UGF5bWVudFByaXZhdGVMYWJlbCgpIHtcblx0dmFyIGJhbGFuY2VEdWUgPSBwYXJzZUZsb2F0KCRwYXltZW50Rm9ybS5maW5kKCdbYmFsYW5jZS1kdWVdJykuYXR0cignYmFsYW5jZS1kdWUnKSk7XG5cdCRzdWJtaXRQcml2YXRlTGFiZWxQYXltZW50LmxvYWRpbmcoe1xuXHRcdElzSW1hZ2VTaG93bjogZmFsc2UsXG5cdFx0TGFiZWw6IFJlc291cmNlcy5Mb2FkaW5nLkNoZWNrb3V0LlBsYWNpbmdPcmRlclxuXHR9KTtcblx0XG5cdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQodHJ1ZSk7XG5cdFxuXHR2YXIgaXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdHZhciBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkID0gZmFsc2U7XG5cdFxuXHQkYmlsbGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuc2V0dGluZ3MuaWdub3JlID0gW107XG5cdFxuXHRpZiAoJGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZCgpKSB7XG5cdFx0aXNCaWxsaW5nQWRkcmVzc1ZhbGlkID0gdHJ1ZTtcblx0fSBlbHNlIHtcblx0XHQkKCcuYmlsbGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uc2hvdygpO1xuXHRcdCRiaWxsaW5nQWRkcmVzc0Zvcm0uZmluZCgnaW5wdXQucmVxdWlyZWQuZmllbGQuZXJyb3InKS5lcSgwKS5mb2N1cygpO1xuXHR9XG5cdFxuXHRpZiAoJHNoaXBwaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSkge1xuXHRcdGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgPSB0cnVlO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnNob3coKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdH1cblx0XG5cdGlmIChpc0JpbGxpbmdBZGRyZXNzVmFsaWQgJiYgaXNTaGlwcGluZ0FkZHJlc3NWYWxpZCAmJiAkKCcjc2hpcHBpbmctbWV0aG9kLWxpc3QgaW5wdXQ6Y2hlY2tlZCcpLmxlbmd0aCAmJiAoYmFsYW5jZUR1ZSA9PSAwIHx8ICRwYXltZW50Rm9ybS52YWxpZCgpKSkge1xuXHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG5cdFx0XG5cdFx0dmFyIGFjdGlvbk5hbWUgPSAkKCcjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmF0dHIoJ25hbWUnKTtcblx0XHRzZXRPUENQYXltZW50RGF0YSgkcGF5bWVudEZvcm0sIGFjdGlvbk5hbWUpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHR2YXIgZGF0YSA9IEpTT04ucGFyc2UocmVzcG9uc2UpO1xuXG5cdFx0XHRpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdzdWNjZXNzJykge1xuXHRcdFx0XHRjb25zb2xlLmxvZygncGF5bWVudCBkYXRhbGF5ZXInKTtcblx0XHRcdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnQWRkUGF5bWVudEluZm8nKS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmIChvcHRpb25zLkNoZWNrb3V0TW9kZSA9PSAnTW9iaWxlQXBwJykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2VGb3JNb2JpbGVBcHA7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSkuY2F0Y2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKG9wdGlvbnMuQ2hlY2tvdXRNb2RlID09ICdNb2JpbGVBcHAnKSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZUZvck1vYmlsZUFwcDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdzaGlwcGluZ1Jlc3RyaWN0aW9uc0Vycm9yJyl7XG5cdFx0XHRcdHZhciBwb3B1cCA9IHJlcXVpcmUoJy4uL3BvcHVwJyk7XG5cdFx0XHRcdHZhciBwYXlsb2FkID0gSlNPTi5wYXJzZShkYXRhLnBheWxvYWQpO1xuXG5cdFx0XHRcdHZhciBsaXN0ID0gJC5tYXAocGF5bG9hZC5saXN0LCBmdW5jdGlvbiAoZWwpIHtcblx0XHRcdFx0XHRyZXR1cm4gJzxsaT4nICsgZWwubmFtZSArICc6PGJyPicgKyBlbC5tZXNzYWdlICsgJzwvbGk+Jztcblx0XHRcdFx0fSkuam9pbignJyk7XG5cblx0XHRcdFx0cG9wdXAuaW5pdCh7XG5cdFx0XHRcdFx0dGl0bGU6IHBheWxvYWQudGl0bGUsXG5cdFx0XHRcdFx0Y29udGVudDogcGF5bG9hZC5tZXNzYWdlICsgJzx1bCBjbGFzcz1cInNoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cF9fbGlzdFwiPicgKyBsaXN0ICsgJzwvdWw+Jyxcblx0XHRcdFx0fSkuc2hvd1BvcHVwKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdGlmIChkYXRhLmhhc093blByb3BlcnR5KCdlcnJvck1lc3NhZ2UnKSkge1xuXHRcdFx0XHRcdG1lc3NhZ2UgPSBkYXRhLmVycm9yTWVzc2FnZTtcblx0XHRcdFx0fSBlbHNlIGlmKGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSkge1xuXHRcdFx0XHRcdG1lc3NhZ2UgPSBkYXRhLm1lc3NhZ2U7XG5cdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAkKCcjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIiByb2xlPVwiYWxlcnRcIiB0YWJpbmRleD1cIjBcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5QYXltZW50IERlY2xpbmVkOjwvYj4gJyArIG1lc3NhZ2UgKyAnPC9kaXY+Jyk7XG5cdFx0XHR9XG5cdFx0XHQkc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRzZXRQbGFjZU9yZGVyQnV0dG9uc0Rpc2FibGVkKGZhbHNlKTtcblx0XHRcdGlmIChwbGFjZU9yZGVyUmVjYXB0Y2hhUHJpdmF0ZUxhYmVsICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGFQcml2YXRlTGFiZWwpO1xuXHRcdFx0fVxuXHRcdH0uYmluZCh0aGlzKSk7XG5cdH0gZWxzZSB7XG5cdFx0JHN1Ym1pdFByaXZhdGVMYWJlbFBheW1lbnQubG9hZGluZygnZGVzdHJveScpO1xuXHRcdHNldFBsYWNlT3JkZXJCdXR0b25zRGlzYWJsZWQoZmFsc2UpO1xuXG5cdFx0Ly8gQWRkaW5nIEFEQSBjb21wbGlhbmNlIGVycm9yIG1lc3NhZ2VzIGZvciBzdWJtaXRQYXltZW50IHNlY3Rpb25cblx0XHQkcGF5bWVudEZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdFx0aWYgKCRwYXltZW50Rm9ybS5maW5kKCcuZmllbGQuZXJyb3InKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkKCcucGF5bWVudC1kZWNsaW5lZCcpLnJlbW92ZSgpO1xuXHRcdFx0dmFyIHBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyA9IG9wY3BheW1lbnQuZ2V0RXJyb3JNZXNzYWdlcygkcGF5bWVudEZvcm0pO1xuXHRcdFx0dmFyIHBheW1lbnRGb3JtRXJyb3JCb3ggPSBvcGNwYXltZW50LmVycm9yQm94KCdDYW5ub3QgUHJvY2VlZCcsICdQbGVhc2UgZml4IHRoZSBmb2xsb3dpbmcgZXJyb3JzOicsIHBheW1lbnRGb3JtRXJyb3JNZXNzYWdlcyk7XG5cdFx0XHRpZiAocGF5bWVudEZvcm1FcnJvckJveCkge1xuXHRcdFx0XHQkc3VibWl0UHJpdmF0ZUxhYmVsUGF5bWVudC5hZnRlcihwYXltZW50Rm9ybUVycm9yQm94KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAocGxhY2VPcmRlclJlY2FwdGNoYVByaXZhdGVMYWJlbCAhPSB1bmRlZmluZWQpIHtcblx0XHRcdGdyZWNhcHRjaGEucmVzZXQocGxhY2VPcmRlclJlY2FwdGNoYVByaXZhdGVMYWJlbCk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQYXltZW50TWV0aG9kc0V2ZW50cyAoKSB7XG5cdHZhciBjY0xpc3RTZWxlY3RvciA9ICcjb3BjLWNjLWxpc3QgaW5wdXRbdHlwZT1cInJhZGlvXCJdJyxcblx0XHRjY051bWJlclNlbGVjdG9yID0gJ2lucHV0W25hbWVePVwiZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX251bWJlclwiXSc7XG5cblx0JChjY051bWJlclNlbGVjdG9yKS5wYXJlbnQoKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJjYy1pbWFnZVwiPjwvZGl2PicpO1xuXHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfcHJpdmF0ZUxhYmVsQ3JlZGl0X251bWJlclwiXScpLnBhcmVudCgpLmFwcGVuZCgnPGRpdiBjbGFzcz1cImNjLWltYWdlXCI+PC9kaXY+Jyk7XG5cdFxuXHQkcGF5bWVudEZvcm0uYXR0cignc2VsZWN0ZWQtcGF5bWVudC1tZXRob2QnLCAkKCcuaW5wdXQtcmFkaW8ucGF5bWVudC1tZXRob2Qtc2VsZWN0b3I6Y2hlY2tlZCcpLnZhbCgpKTtcblxuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgY2NMaXN0U2VsZWN0b3IsIGZ1bmN0aW9uICgpIHtcblx0XHQkKGNjTnVtYmVyU2VsZWN0b3IpXG5cdFx0XHQucGFyZW50KClcblx0XHRcdC5maW5kKCcuY2MtaW1hZ2UnKVxuXHRcdFx0LmNzcygnYmFja2dyb3VuZC1pbWFnZScsICd1cmwoJyArICQodGhpcykubmV4dCgpLmF0dHIoJ3NyYycpICsgJyknKTtcblx0fSk7XG5cblx0aWYgKCQoY2NMaXN0U2VsZWN0b3IgKyAnOmNoZWNrZWQnKS52YWwoKSkge1xuXHRcdCQoY2NMaXN0U2VsZWN0b3IgKyAnOmNoZWNrZWQnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0fVxuXHRcblx0JHBheW1lbnRGb3JtLm9uKCdjbGljaycsICcucGF5bWVudC1tZXRob2Qtc2VsZWN0b3InLCBmdW5jdGlvbiAoZSkge1xuXHQgICAgdmFyIHBheW1lbnRNZXRob2RJZCA9ICgnJyArICQodGhpcykuYXR0cignaWQnKSkucmVwbGFjZSgnaXMtJywnJyk7XG5cdFx0XG5cdFx0Ly8gUmVzZXQgcGF5bWVudEZvcm0gZXJyb3JzIHdoZW4gY2hhbmdpbmcgcGF5bWVudCBtZXRob2QgZ3JvdXBzIFxuXHRcdCRwYXltZW50Rm9ybS52YWxpZGF0ZSgpLnJlc2V0Rm9ybSgpO1xuXHQgICAgXG5cdCAgICBpZiAocGF5bWVudE1ldGhvZElkKSB7XG5cdCAgICBcdCQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwocGF5bWVudE1ldGhvZElkKTtcblx0XHRcdCRwYXltZW50Rm9ybS5hdHRyKCdzZWxlY3RlZC1wYXltZW50LW1ldGhvZCcsIHBheW1lbnRNZXRob2RJZCk7XG5cdCAgICBcdFxuXHRcdCAgICAkcGF5bWVudEZvcm0uZmluZCgnLnBheW1lbnQtbWV0aG9kJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHQgICAgICAgICQodGhpcykucmVtb3ZlQ2xhc3MoJ3BheW1lbnQtbWV0aG9kLWV4cGFuZGVkJyk7XG5cdFx0ICAgICAgICBcblx0XHQgICAgICAgIGlmICgkKHRoaXMpLmF0dHIoJ2RhdGEtbWV0aG9kJykgPT0gcGF5bWVudE1ldGhvZElkKSB7XG5cdFx0ICAgICAgICAgICAgJCh0aGlzKS5hZGRDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKTtcblx0XHQgICAgICAgIH1cblx0XHQgICAgfSk7XG5cdFx0ICAgIFxuXHRcdCAgICB2YXIgJHBheW1lbnRNZXRob2RQYW5lbCA9ICQoJy5wYXltZW50LW1ldGhvZFtkYXRhLW1ldGhvZD1cIicgKyBwYXltZW50TWV0aG9kSWQgKyAnXCJdJyk7XG5cdFx0ICAgIGlmICgkcGF5bWVudE1ldGhvZFBhbmVsLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpKSB7XG5cdFx0ICAgIFx0JHBheW1lbnRNZXRob2RQYW5lbC5maW5kKCcuY2MtaW1hZ2UnKS5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAndXJsKCcgKyAkcGF5bWVudE1ldGhvZFBhbmVsLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpICsgJyknKTtcblx0ICAgIFx0fVxuXHQgICAgfVxuXHQgICAgXG5cdCAgICBpZiAod2luZG93LmlubmVyV2lkdGggPD0gNzY3KSB7XG5cdFx0XHQkKFtkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIGRvY3VtZW50LmJvZHldKS5hbmltYXRlKHtcblx0XHRcdFx0Ly8gc2Nyb2xsVG9wOiAkKCcucGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKS5jbG9zZXN0KCcucGF5bWVudC1tZXRob2Qtb3B0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLnRvcC1iYW5uZXInKS5oZWlnaHQoKSArIDIwXG5cdFx0XHRcdHNjcm9sbFRvcDogJCgnI3BheW1lbnRTZWN0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLnRvcC1iYW5uZXInKS5oZWlnaHQoKSAtIDE1XG5cdFx0XHR9LCAyNTApO1xuXHQgICAgfVxuXHQgICAgXG5cdCAgICBhZGRyZXNzZXMudXBkYXRlU3VtbWFyeSgpO1xuXHR9KTtcblxuXHQkKGNjTnVtYmVyU2VsZWN0b3IpLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuXHRcdCRjcmVkaXRDYXJkTGlzdC52YWwoJycpO1xuXHR9KTtcblx0XG5cdCQoY2NOdW1iZXJTZWxlY3Rvcikub24oJ2tleXVwJywgZnVuY3Rpb24oZSl7XG5cdFx0dmFyIGNyZWRpdENhcmROdW1iZXIgPSAkKHRoaXMpLnZhbCgpO1xuXHRcdFxuXHRcdHZhciBzZWxlY3RlZENhcmQgPSB1dGlsLmdldENyZWRpdENhcmRUeXBlKGNyZWRpdENhcmROdW1iZXIpO1xuXHRcdGlmIChzZWxlY3RlZENhcmQpIHtcblx0XHRcdCQoY2NMaXN0U2VsZWN0b3IpLmZpbHRlcihcIlt2YWx1ZT0nXCIrIHNlbGVjdGVkQ2FyZC5QYXltZW50Q2FyZERpc3BsYXlLZXkgK1wiJ11cIikuZXEoMCkudHJpZ2dlcignY2xpY2snKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmNjLWNhcmRsaXN0LXNlbGVjdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQXR0cignc2VsZWN0ZWQnKS52YWwoJycpO1xuXHRcdFx0JChjY0xpc3RTZWxlY3RvcikucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHRcdCRwYXltZW50Rm9ybS5maW5kKCcucGF5bWVudC1tZXRob2RbZGF0YS1tZXRob2Q9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXSAuY2MtaW1hZ2UnKS5jc3MoJ2JhY2tncm91bmQtaW1hZ2UnLCAnJyk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKCcuYWRkLW5ldy1jYXJkJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSl7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0JCgnaW5wdXRbbmFtZV49XCJkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfb3duZXJcIl0nKS52YWwoJycpO1xuXHRcdCQoJ2lucHV0W25hbWVePVwiZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX251bWJlclwiXScpLnZhbCgnJyk7XG5cdFx0JCgnaW5wdXRbbmFtZV49XCJkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfY3ZuXCJdJykudmFsKCcnKTtcblx0XHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX21vbnRoXCJdJykudmFsKCcnKTtcblx0XHQkKCdpbnB1dFtuYW1lXj1cImR3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX3llYXJcIl0nKS52YWwoJycpO1xuXHRcdCQoJyNvcGMtY2MtbGlzdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJyk7XG5cdFx0JCgnLmNjLWNhcmRsaXN0LXNlbGVjdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQXR0cignc2VsZWN0ZWQnKS52YWwoJycpO1xuXHRcdCQoJy5jYy1pbWFnZScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICdub25lJyk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzZXRQbGFjZU9yZGVyQnV0dG9uc0Rpc2FibGVkKGlzRGlzYWJsZWQpIHtcblx0JHN1Ym1pdFBheW1lbnQuYXR0cignZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcdFxuXHQkKCcjc3VibWl0T1BDUGF5bWVudFByaXZhdGVMYWJlbCcpLmF0dHIoJ2Rpc2FibGVkJywgaXNEaXNhYmxlZCk7XHRcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIHNldCBjYXJ0IGRhdGFcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgcHJlc2VudCBhZGRyZXNzIG9iamVjdFxuICogQHBhcmFtIHtFbGVtZW50fSBBY3Rpb24gbmFtZSB0byBhcHBseSB0byBmb3JtXG4gKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAqL1xudmFyIHNldE9QQ1BheW1lbnREYXRhID0gZnVuY3Rpb24gKGZvcm0sIG5hbWUpIHtcbiAgICB2YXIgJGZvcm0gPSAkKGZvcm0pO1xuXG4gICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLnNldE9wY0FkZHJlc3MpLFxuICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lXG4gICAgfSkpO1xufTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdFxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiAob3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIgfHwgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclJld2FyZHNDcmVkaXQgfHwgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckdpZnRDYXJkcykpIHtcbiAgICBcdHJlY2FwdGNoYS5pbml0aWFsaXplKCk7XG5cdH1cblx0R2lmdENhcmQuaW5pdGlhbGl6ZShvcHRpb25zKTtcblx0UmV3YXJkc0NyZWRpdC5pbml0aWFsaXplKG9wdGlvbnMpO1xuXHRMb3lhbHR5Q3JlZGl0LmluaXRpYWxpemUob3B0aW9ucyk7XG4gICAgaW5pdGlhbGl6ZUV2ZW50cyhvcHRpb25zKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcXVpY2t2aWV3ID0gcmVxdWlyZSgnLi4vcXVpY2t2aWV3Jyk7XG52YXIgYm9udXNQcm9kdWN0c1ZpZXcgPSByZXF1aXJlKCcuLi9ib251cy1wcm9kdWN0cy12aWV3Jyk7XG52YXIgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcbnZhciBhZGRyZXNzZXMgPSBTaXRlUHJlZmVyZW5jZXMuRU5BQkxFX0VOSEFOQ0VEX0NIRUNLT1VUID8gcmVxdWlyZSgnLi9jaGVja291dC9vcGNhZGRyZXNzX2VuaGFuY2VkJykgOiByZXF1aXJlKCcuL2NoZWNrb3V0L29wY2FkZHJlc3MnKTtcbnZhciBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvZm9ybVByZXBhcmUnKTtcbnZhciBjYXJ0ID0gcmVxdWlyZSgnLi9jYXJ0Jyk7XG52YXIgb3BjcGF5bWVudCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvb3BjcGF5bWVudCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHaWZ0Q2FyZCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvR2lmdENhcmRQYXltZW50UGFuZWwnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBQYXltZW50Vm91Y2hlclBhbmVsO1xudmFyIHJlY2FwdGNoYSA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudHMvUmVjYXB0Y2hhJyk7XG52YXIgUmV3YXJkc0NyZWRpdCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvUmV3YXJkc0NyZWRpdCcpO1xudmFyIExveWFsdHlDcmVkaXQgPSByZXF1aXJlKCcuL2NoZWNrb3V0L0xveWFsdHlDcmVkaXQnKTtcbnZhciBDaGVja291dENvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvQ2hlY2tvdXRDb25zdGFudHMnKTtcbnZhciBQYXltZW50TWV0aG9kQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9QYXltZW50SW5zdHJ1bWVudENvbnN0YW50cycpLlBheW1lbnRNZXRob2RzO1xudmFyIEJvcGlzUHJvZHVjdExpbmVJdGVtSGVscGVyID0gcmVxdWlyZSgnLi4vYm9waXMvY29tcG9uZW50cy9Qcm9kdWN0TGluZUl0ZW1IZWxwZXInKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBjYXJ0SXRlbXNGb3JtU2VsZWN0b3IgPSAnZm9ybSNjYXJ0LWl0ZW1zLWZvcm0nO1xudmFyIGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yID0gJyNiaWxsaW5nQWRkcmVzc0Zvcm0nO1xudmFyICRiaWxsaW5nQWRkcmVzc0Zvcm0gPSAkKGJpbGxpbmdBZGRyZXNzRm9ybVNlbGVjdG9yKTtcbnZhciBzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IgPSAnI3NoaXBwaW5nQWRkcmVzc0Zvcm0nO1xudmFyICRzaGlwcGluZ0FkZHJlc3NGb3JtID0gJChzaGlwcGluZ0FkZHJlc3NGb3JtU2VsZWN0b3IpO1xudmFyIHBheW1lbnRTZWN0aW9uU2VsZWN0b3IgPSAnLmZvcm0tY2hlY2tvdXQucGF5bWVudC1zZWN0aW9uJztcbnZhciAkcGF5bWVudFNlY3Rpb24gPSAkKHBheW1lbnRTZWN0aW9uU2VsZWN0b3IpO1xudmFyIHBheW1lbnRGb3JtU2VsZWN0b3IgPSAnI3BheW1lbnRTZWN0aW9uJztcbnZhciAkcGF5bWVudEZvcm0gPSAkKHBheW1lbnRGb3JtU2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRMaXN0U2VsZWN0b3IgPSAnI2NyZWRpdENhcmRMaXN0JztcbnZhciAkY3JlZGl0Q2FyZExpc3QgPSAkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpO1xudmFyIGNyZWRpdENhcmRTYXZlQ2hlY2tib3hDb250YWluZXJTZWxlY3RvciA9ICdkaXZbZmllbGQ9XCJzYXZlQ2FyZFwiXSc7XG52YXIgJGNyZWRpdENhcmRTYXZlQ2hlY2tib3hDb250YWluZXIgPSAkKGNyZWRpdENhcmRTYXZlQ2hlY2tib3hDb250YWluZXJTZWxlY3Rvcik7XG52YXIgY3JlZGl0Q2FyZFNhdmVDaGVja2JveFNlbGVjdG9yID0gJyNkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfc2F2ZUNhcmQnO1xudmFyICRjcmVkaXRDYXJkU2F2ZUNoZWNrYm94ID0gJChjcmVkaXRDYXJkU2F2ZUNoZWNrYm94U2VsZWN0b3IpO1xudmFyIHN1Ym1pdFBheW1lbnRTZWxlY3RvciA9ICcjc3VibWl0T1BDUGF5bWVudCc7XG52YXIgJHN1Ym1pdFBheW1lbnQgPSAkKHN1Ym1pdFBheW1lbnRTZWxlY3Rvcik7XG52YXIgYmFza2V0Q29udGFpbmVyU2VsZWN0b3IgPSAnLmJhc2tldC1jb250YWluZXInO1xudmFyICRiYXNrZXRDb250YWluZXIgPSAkKGJhc2tldENvbnRhaW5lclNlbGVjdG9yKTtcblxudmFyIHBsYWNlT3JkZXJSZWNhcHRjaGE7XG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFdmVudHMgc2hvdWxkIGJlIGRpdmlkZWQgdG8gbW9kdWxlcy4gVGhpcyBhbGxvd3MgcmVpbml0aWFsaXplIGV2ZW50cyBieSBzZWN0aW9ucyBhZnRlciBwYXJ0aWFsIHJlbG9hZCBcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBldmVudHMgZm9yIHRoZSBnaWZ0IHJlZ2lzdHJhdGlvblxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKG9wdGlvbnMpIHtcblx0aW5pdGlhbGl6ZUNhcnRFdmVudHMob3B0aW9ucyk7XG5cdGluaXRpYWxpemVQYXltZW50TWV0aG9kc0V2ZW50cygpO1xuXHRcblx0cmVuZGVyUmVjYXB0Y2hhKCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdSZWNhcHRjaGEuTG9hZGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIWxvYWRlZC5SZWNhcHRjaGEpIHtcblx0XHRcdGxvYWRlZC5SZWNhcHRjaGEgPSB0cnVlO1xuXHQgICAgICAgIHJlbmRlclJlY2FwdGNoYSgpO1xuXHQgICAgfVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUNhcnRFdmVudHMob3B0aW9ucykge1xuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnYS5hZGQtdG8td2lzaGxpc3QnLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0LypyZW1vdmUgbmV4dCBsaW5lIHRvIHVzZSBkZWZhdWx0IGR3IHdpc2hsaXN0IGZ1bmN0aW9uYWxpdHkqL1xuICAgIFx0cmV0dXJuIGZhbHNlO1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHRpZiAoQ3VzdG9tZXIuYXV0aGVudGljYXRlZCA9PSB0cnVlKSB7XG4gICAgXHRcdC8vIHBvc3QgZm9ybSBoZXJlXG4gICAgXHR9IGVsc2Uge1xuICAgIFx0XHQkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7IHNjcm9sbFRvcDogJCgnLmxvZ2luLWZvcm0nKS5lcSgwKS5vZmZzZXQoKS50b3B9LCAxMDAwKTtcbiAgICBcdH1cbiAgICB9KTtcblx0XG5cdGlmIChTaXRlUHJlZmVyZW5jZXMuQUxURVJOQVRFX1BJQ0tVUF9FTkFCTEVEKSB7XG5cdFx0cmVuZGVyQWx0ZXJuYXRlUGlja3VwKCk7XG5cdH1cblxuICAgICRwYXltZW50Rm9ybS5vbignY2hhbmdlJywgJ1tuYW1lJD1cIl9jcmVkaXRDYXJkX3R5cGVcIl0nLCBmdW5jdGlvbigpIHtcbiAgICBcdCRzdWJtaXRQYXltZW50LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgXHQkKHRoaXMpLmNsb3Nlc3QoJ2Rpdi5mb3JtLXJvdycpLmZpbmQoJ2Rpdi5maWVsZC13cmFwcGVyLmVycm9yJykucmVtb3ZlKCk7XG4gICAgfSk7XG5cbiAgICAkKGRvY3VtZW50KS5vbignY2xpY2snLCBzdWJtaXRQYXltZW50U2VsZWN0b3IsIGZ1bmN0aW9uKGUpIHtcbiAgICBcdGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIFx0aWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLlJlY2FwdGNoYSB8fCAhb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIpIHtcblx0XHRcdHN1Ym1pdFBheW1lbnQoKTtcdFxuXHRcdH1cbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vbignQ2hlY2tvdXQuU3VibWl0UGF5bWVudCcsIGZ1bmN0aW9uIChldmVudCwgZGF0YSkge1xuXHRcdGlmICgob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiBvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yUGxhY2VPcmRlcikgfHwgKGRhdGEgJiYgZGF0YS5TdWJtaXRQYXltZW50Rm9yQm9waXMpKSB7XG5cdFx0XHRzdWJtaXRQYXltZW50KGRhdGEpO1xuXHRcdH1cblx0fSk7XG4gICAgXG4gICAgdmFyIGdldENyZWRpdENhcmRJbmZvID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuYmlsbGluZ0dldENyZWRpdENhcmQpLFxuICAgICAgICAgICAgZGF0YTogeyBjcmVkaXRDYXJkVVVJRDogaWQgfVxuICAgICAgICB9KSk7XG4gICAgfTtcbiAgICBcbiAgICAkY3JlZGl0Q2FyZExpc3Qub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCkge1xuICAgIFx0dmFyIGNyZWRpdENhcmRVVUlEID0gJCh0aGlzKS52YWwoKTtcbiAgICBcdFxuICAgIFx0aWYgKGNyZWRpdENhcmRVVUlELmxlbmd0aCA8PSAwKSB7XG4gICAgXHRcdHJldHVybjtcbiAgICBcdH1cbiAgICBcdFxuICAgIFx0Z2V0Q3JlZGl0Q2FyZEluZm8oY3JlZGl0Q2FyZFVVSUQpLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdGlmIChkYXRhICYmIGRhdGEuaGFzT3duUHJvcGVydHkoJ21hc2tlZE51bWJlcicpKSB7XG5cdFx0XHRcdHZhciAkcGF5bWVudE1ldGhvZEdyb3VwID0gJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCArICdcIl0nKTtcblx0XHRcdFx0dmFyICRwYXltZW50TWV0aG9kID0gJHBheW1lbnRNZXRob2RHcm91cC5maW5kKCcucGF5bWVudC1tZXRob2RbcGF5bWVudC1tZXRob2Q9XCInICsgZGF0YS5wYXltZW50TWV0aG9kICsgJ1wiXScpO1xuXG5cdFx0XHRcdHZhciBwYXltZW50TWV0aG9kUmFkaW9Ub1NlbGVjdCA9IGRhdGEucGF5bWVudE1ldGhvZCA9PSBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgPyBkYXRhLnR5cGUgOiBkYXRhLnBheW1lbnRNZXRob2Q7XG5cdFx0XHRcdCRwYXltZW50TWV0aG9kR3JvdXAuZmluZCgnaW5wdXRbdHlwZT1cInJhZGlvXCJdW3ZhbHVlPVwiJyArIHBheW1lbnRNZXRob2RSYWRpb1RvU2VsZWN0ICsgJ1wiXScpLmZpcnN0KCkucHJvcCgnY2hlY2tlZCcsIHRydWUpLnRyaWdnZXIoJ2NoYW5nZScsIHsgZG9SZXNldDogZmFsc2UgfSk7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoJHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX293bmVyXCJdJykubGVuZ3RoID4gMCAmJiBkYXRhLmhhc093blByb3BlcnR5KCdob2xkZXInKSkge1xuXHRcdFx0XHRcdCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9vd25lclwiXScpLnZhbChkYXRhLmhvbGRlcikudmFsaWQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykudmFsKGRhdGEudHlwZSk7XG5cdFx0XHRcdCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfbnVtYmVyXCJdJykudmFsKGRhdGEubWFza2VkTnVtYmVyKS52YWxpZCgpO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX21vbnRoXCJdJykubGVuZ3RoID4gMCAmJiBkYXRhLmhhc093blByb3BlcnR5KCdleHBpcmF0aW9uTW9udGgnKSkge1xuXHRcdFx0XHRcdCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX21vbnRoXCJdJykudmFsKGRhdGEuZXhwaXJhdGlvbk1vbnRoKS50cmlnZ2VyKCdjaGFuZ2UnKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCRwYXltZW50TWV0aG9kLmZpbmQoJ1tpZCo9XCJfY3JlZGl0Q2FyZF9leHBpcmF0aW9uX3llYXJcIl0nKS5sZW5ndGggPiAwICYmIGRhdGEuaGFzT3duUHJvcGVydHkoJ2V4cGlyYXRpb25ZZWFyJykpIHtcblx0XHRcdFx0XHQkcGF5bWVudE1ldGhvZC5maW5kKCdbaWQqPVwiX2NyZWRpdENhcmRfZXhwaXJhdGlvbl95ZWFyXCJdJykudmFsKGRhdGEuZXhwaXJhdGlvblllYXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAoJHBheW1lbnRNZXRob2QuZmluZCgnW2lkKj1cIl9jcmVkaXRDYXJkX2N2blwiXScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkcGF5bWVudE1ldGhvZC5maW5kKCdbaWQqPVwiX2NyZWRpdENhcmRfY3ZuXCJdJykudmFsKCcnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCRjcmVkaXRDYXJkU2F2ZUNoZWNrYm94Q29udGFpbmVyLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9LmJpbmQodGhpcykpO1x0XG4gICAgfSk7XG4gICAgXG5cdGlmICgkY3JlZGl0Q2FyZExpc3QubGVuZ3RoID4gMCAmJiAoJCgnLnB0X29uZXBjaGVja291dCBpbnB1dFtuYW1lKj1cIl9zZWxlY3RlZFBheW1lbnRNZXRob2RJRFwiXScpLnZhbCgpID09IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCB8fCAkKCcucHRfb25lcGNoZWNrb3V0IGlucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCkgPT0gUGF5bWVudE1ldGhvZENvbnN0YW50cy5BbGxpYW5jZURhdGEpKSB7XG5cdFx0JGNyZWRpdENhcmRMaXN0LmZpbmQoJ29wdGlvbicpLmVxKDEpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0JGNyZWRpdENhcmRMaXN0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdCRjcmVkaXRDYXJkU2F2ZUNoZWNrYm94Q29udGFpbmVyLmhpZGUoKTtcblx0fSBlbHNlIHtcblx0XHQkY3JlZGl0Q2FyZFNhdmVDaGVja2JveENvbnRhaW5lci5zaG93KCk7XG5cdH1cblx0XG4gICAgYWRkcmVzc2VzLmluaXQob3B0aW9ucyk7XG4gICAgY2FydC5pbml0KG9wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJBbHRlcm5hdGVQaWNrdXAoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnYnV0dG9uLmFsdC1waWNrdXAtYnV0dG9uJykub24oJ2NsaWNrJywgJ2J1dHRvbi5hbHQtcGlja3VwLWJ1dHRvbicsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JCgnI2FsdC1waWNrdXAtbW9kYWwnKS5hZGRDbGFzcygnYWN0aXZlLW1vZGFsJykuc2hvdygpO1xuXHRcdCQoJ2ZpZWxkc2V0IHNwYW4nKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnI2FsdC1waWNrdXAtbW9kYWwgLmNsb3NlLW1vZGFsJykub24oJ2NsaWNrJywgJyNhbHQtcGlja3VwLW1vZGFsIC5jbG9zZS1tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0JCgnI2FsdC1waWNrdXAtbW9kYWwnKS5yZW1vdmVDbGFzcygnYWN0aXZlLW1vZGFsJykuaGlkZSgpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdmb2N1cycsICdpbnB1dFtuYW1lPVwiZmlyc3ROYW1lXCJdJywgZnVuY3Rpb24gKCkge1xuXHRcdCQoJy5maXJzdG5hbWUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJsYXN0TmFtZVwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcubGFzdG5hbWUtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2ZvY3VzJywgJ2lucHV0W25hbWU9XCJlbWFpbFwiXScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcuZW1haWwtZXJyb3InKS5yZW1vdmVDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0JCgnLm9uZS1yZXF1aXJlZCcpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdmb2N1cycsICdpbnB1dFtuYW1lPVwicGhvbmVcIl0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0JCgnLnBob25lLWVycm9yJykucmVtb3ZlQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdCQoJy5vbmUtcmVxdWlyZWQnKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICB9KTtcbiAgICBcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrJywgJ2J1dHRvbiNhbHRQaWNrdXBTdWJtaXQnKS5vbignY2xpY2snLCAnYnV0dG9uI2FsdFBpY2t1cFN1Ym1pdCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XG4gICAgXHR2YXIgaXNGaXJzdE5hbWVWYWxpZCA9IHRydWU7XG5cdFx0dmFyIGZpcnN0TmFtZSA9ICQoJ2lucHV0W25hbWU9XCJmaXJzdE5hbWVcIl0nKS52YWwoKTtcblx0XHR2YXIgcmVnZXhOYW1lID0gL15bYS16ICwuJy1dKyQvaTtcblx0XHRpZiAoZmlyc3ROYW1lLmxlbmd0aCA9PSAwIHx8IGZpcnN0TmFtZS5tYXRjaChyZWdleE5hbWUpID09IG51bGwpIHtcblx0XHRcdGlzRmlyc3ROYW1lVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5maXJzdG5hbWUtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciBpc0xhc3ROYW1lVmFsaWQgPSB0cnVlO1x0XHRcblx0XHR2YXIgbGFzdE5hbWUgPSQoJ2lucHV0W25hbWU9XCJsYXN0TmFtZVwiXScpLnZhbCgpO1xuXHRcdGlmIChsYXN0TmFtZS5sZW5ndGggPT0gMCB8fCBsYXN0TmFtZS5tYXRjaChyZWdleE5hbWUpID09IG51bGwpIHtcblx0XHRcdGlzTGFzdE5hbWVWYWxpZCA9IGZhbHNlO1xuXHRcdFx0JCgnLmxhc3RuYW1lLWVycm9yJykuYWRkQ2xhc3MoJ2Vycm9yLW1zZycpO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgaXNFbWFpbFZhbGlkID0gdHJ1ZTtcdFx0XG5cdFx0dmFyIGVtYWlsID0gJCgnaW5wdXRbbmFtZT1cImVtYWlsXCJdJykudmFsKCk7XG5cdFx0dmFyIHJlZ2V4RW1haWwgPSAvXlthLXpBLVowLTkuISMkJSYnKisvPT9eX2B7fH1+LV0rQFthLXpBLVowLTktXSsoPzpcXC5bYS16QS1aMC05LV0rKSokL2c7XG5cdFx0aWYgKGVtYWlsLmxlbmd0aCA+IDAgJiYgZW1haWwubWF0Y2gocmVnZXhFbWFpbCkgPT0gbnVsbCkge1xuXHRcdFx0aXNFbWFpbFZhbGlkID0gZmFsc2U7XG5cdFx0XHQkKCcuZW1haWwtZXJyb3InKS5hZGRDbGFzcygnZXJyb3ItbXNnJyk7XG5cdFx0fVxuXG5cdFx0dmFyIGlzUGhvbmVWYWxpZCA9IHRydWU7XG5cdFx0dmFyIHBob25lID0gJCgnaW5wdXRbbmFtZT1cInBob25lXCJdJykudmFsKCkucmVwbGFjZSgvXFxEL2csICcnKTtcblx0XHR2YXIgcmVnZXhQaG9uZSA9IC9eXFwrP1xcKD8oWzAtOV1bMC04XVswLTldKVxcKT9bXFwtXFwuIF0/KFsyLTldWzAtOV17Mn0pW1xcLVxcLiBdPyhbMC05XXs0fSkoXFxzKnhbMC05XSspPyQvZztcblx0XHRpZiAocGhvbmUubGVuZ3RoID4gMCAmJiBwaG9uZS5tYXRjaChyZWdleFBob25lKSA9PSBudWxsKSB7XG5cdFx0XHRpc1Bob25lVmFsaWQgPSBmYWxzZTtcblx0XHRcdCQoJy5waG9uZS1lcnJvcicpLmFkZENsYXNzKCdlcnJvci1tc2cnKTtcblx0XHR9XG5cdFx0XG4gICAgXHRpZiAoZW1haWwubGVuZ3RoID09IDAgJiYgcGhvbmUubGVuZ3RoID09IDApIHtcbiAgICBcdFx0JCgnLm9uZS1yZXF1aXJlZCcpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgIFx0XHRpc0VtYWlsVmFsaWQgPSBmYWxzZTtcbiAgICBcdFx0aXNQaG9uZVZhbGlkID0gZmFsc2U7XG4gICAgXHR9XG4gICAgXHRcbiAgICBcdGlmICghaXNFbWFpbFZhbGlkIHx8ICFpc1Bob25lVmFsaWQpIHtcbiAgICBcdFx0cmV0dXJuO1xuICAgIFx0fVxuICAgIFx0XG5cdFx0aWYgKGlzRmlyc3ROYW1lVmFsaWQgJiYgaXNMYXN0TmFtZVZhbGlkICYmIChpc0VtYWlsVmFsaWQgfHwgaXNQaG9uZVZhbGlkKSkge1xuXHRcdFx0dmFyIGNsZWFuUGhvbmUgPSBwaG9uZS5yZXBsYWNlKC9cXEQvZywgJycpO1xuXHRcdFx0dmFyIHNoaXBtZW50SUQgPSAkKCcuYWx0ZXJuYXRlLXBpY2t1cCcpLmNsb3Nlc3QoXCJmb3JtXCIpLmF0dHIoJ3NoaXBtZW50Jyk7XG5cdFx0XHRcblx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdHVybDogVXJscy5zZXRBbHRlcm5hdGVQaWNrdXAsXG5cdFx0XHRcdHR5cGU6IFwiZ2V0XCIsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRzaGlwbWVudElEOiBzaGlwbWVudElELFxuXHRcdFx0XHRcdGFsdFBpY2t1cEZpcnN0TmFtZTogZmlyc3ROYW1lLFxuXHRcdFx0XHRcdGFsdFBpY2t1cExhc3ROYW1lOiBsYXN0TmFtZSxcblx0XHRcdFx0XHRhbHRQaWNrdXBFbWFpbDogZW1haWwsXG5cdFx0XHRcdFx0YWx0UGlja3VwUGhvbmU6IGNsZWFuUGhvbmVcblx0XHRcdFx0fSxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGEgPSBKU09OLnBhcnNlKHJlc3BvbnNlKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdGlmIChkYXRhLnN0YXR1cyA9PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0XHRcdCQoJ3NwYW4uYWx0LXBlcnNvbicpLmF0dHIoJ2RhdGEtZmlyc3RuYW1lJywgZmlyc3ROYW1lKS5hdHRyKCdkYXRhLWxhc3RuYW1lJywgbGFzdE5hbWUpLmF0dHIoJ2RhdGEtZW1haWwnLCBlbWFpbCkuYXR0cignZGF0YS1waG9uZScsIGNsZWFuUGhvbmUpO1xuXHRcdFx0XHRcdFx0ZGlzcGxheUFsdGVybmF0ZVBpY2t1cCAoZmlyc3ROYW1lICsgJyAnICsgbGFzdE5hbWUpXG5cdFx0XHRcdFx0XHQkKCcjYWx0LXBpY2t1cC1tb2RhbCcpLnJlbW92ZUNsYXNzKCdhY3RpdmUtbW9kYWwnKS5oaWRlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRcdFx0Y29uc29sZS5sb2codGV4dFN0YXR1cywgZXJyb3JUaHJvd24pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRpc3BsYXlBbHRlcm5hdGVQaWNrdXAgKGZ1bGxOYW1lKSB7XG5cdCQoJy5hbHRlcm5hdGUtcGlja3VwIHNwYW4uYWx0LXBlcnNvbicpLnRleHQoZnVsbE5hbWUpO1xuXHQkKCdzcGFuLmFsdC1oZWFkZXInKS5zaG93KCk7XG5cdCQoJ2J1dHRvbi5hbHQtcGlja3VwLWJ1dHRvbicpLnRleHQoJ1VQREFURScpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJSZWNhcHRjaGEoKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmICQoJyNzdWJtaXRPUENQYXltZW50JykubGVuZ3RoID4gMCAmJiBvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkgJiYgcGxhY2VPcmRlclJlY2FwdGNoYSA9PSB1bmRlZmluZWQpIHtcblx0XHRwbGFjZU9yZGVyUmVjYXB0Y2hhID0gZ3JlY2FwdGNoYS5yZW5kZXIoJ3N1Ym1pdE9QQ1BheW1lbnQnLCB7XG5cdCAgICAgICAgJ3NpdGVrZXknOiBvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5LFxuXHQgICAgICAgICdjYWxsYmFjayc6IHN1Ym1pdFBheW1lbnQsXG5cdCAgICAgICAgJ2JhZGdlJzogJ2JvdHRvbWxlZnQnXG5cdCAgICB9KTtcblx0fVxufVxuXG5mdW5jdGlvbiBzdWJtaXRQYXltZW50UmVjYXB0Y2hhRXJyb3IoKSB7XG5cdGlmIChsb2FkZWQuUmVjYXB0Y2hhICYmICQoJyNzdWJtaXRPUENQYXltZW50JykubGVuZ3RoID4gMCAmJiBvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JQbGFjZU9yZGVyICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkdvb2dsZVNpdGVLZXkgJiYgcGxhY2VPcmRlclJlY2FwdGNoYSAhPSB1bmRlZmluZWQpIHtcblx0XHRncmVjYXB0Y2hhLnJlc2V0KHBsYWNlT3JkZXJSZWNhcHRjaGEpO1xuXHRcdHJlbmRlclJlY2FwdGNoYSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHN1Ym1pdFBheW1lbnQoZGF0YSkge1xuXHR2YXIgYmFsYW5jZUR1ZSA9IHBhcnNlRmxvYXQoJHBheW1lbnRTZWN0aW9uLmF0dHIoJ2JhbGFuY2UtZHVlJykpO1xuXHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKHtcblx0XHRJc0ltYWdlU2hvd246IGZhbHNlLFxuXHRcdExhYmVsOiBSZXNvdXJjZXMuTG9hZGluZy5DaGVja291dC5QbGFjaW5nT3JkZXJcblx0fSk7XG5cdCRzdWJtaXRQYXltZW50LmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdCQoJyNlcnJvckJveE9QQycpLnJlbW92ZSgpO1xuXG5cdCRiaWxsaW5nQWRkcmVzc0Zvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG5cdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcblx0dmFyICRjcmVkaXRDYXJkVHlwZSA9ICRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0aWYgKGJhbGFuY2VEdWUgPiAwKSB7XG5cdFx0JHBheW1lbnRGb3JtLnZhbGlkYXRlKCkuZm9ybSgpO1xuXHRcdFxuXHRcdGlmICh0eXBlb2YgJGNyZWRpdENhcmRUeXBlID09PSAndW5kZWZpbmVkJykge1xuICAgIFx0XHQkcGF5bWVudEZvcm0uZmluZCgnW25hbWUkPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLmNsb3Nlc3QoJ2Rpdi5mb3JtLXJvdycpLmZpbmQoJ2Rpdi5maWVsZC13cmFwcGVyLmVycm9yJykucmVtb3ZlKCk7XG5cbiAgICBcdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgIFx0XHRcdCRwYXltZW50Rm9ybS5maW5kKCdbbmFtZSQ9XCJfY3JlZGl0Q2FyZF90eXBlXCJdJykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuYXBwZW5kKCc8ZGl2IGNsYXNzPVwiZmllbGQtd3JhcHBlciBlcnJvclwiIHN0eWxlPVwiaGVpZ2h0OjBweDtcIj48c3BhbiBjbGFzcz1cImVycm9yXCI+JyArIFJlc291cmNlcy5SRVFVSVJFRF9GSUVMRCArICc8L3NwYW4+PC9kaXY+Jyk7XG4gICAgXHRcdH0sIDUwKTtcblx0XHR9XG5cdH1cblx0XG5cdC8vIGNoZWNrIGZpcnN0IGlmIGFkZHJlc3NlcyBhcmUgdmFsaWRcblx0dmFyIGlzQmlsbGluZ0FkZHJlc3NWYWxpZCA9IGZhbHNlO1xuXHR2YXIgaXNTaGlwcGluZ0FkZHJlc3NWYWxpZCA9IGZhbHNlO1xuXHRcblx0JGJpbGxpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpLnNldHRpbmdzLmlnbm9yZSA9IFtdO1xuXHQkc2hpcHBpbmdBZGRyZXNzRm9ybS52YWxpZGF0ZSgpLnNldHRpbmdzLmlnbm9yZSA9IFtdO1xuXHRcblx0aWYgKCRiaWxsaW5nQWRkcmVzc0Zvcm0udmFsaWQoKSkge1xuXHRcdGlzQmlsbGluZ0FkZHJlc3NWYWxpZCA9IHRydWU7XG5cdH0gZWxzZSB7XG5cdFx0JCgnLmJpbGxpbmctYWRkcmVzcy1kYXRhLmZvcm0taW5mbycpLmhpZGUoKTtcblx0XHRcblx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtLnNob3coKTtcblx0XHQkYmlsbGluZ0FkZHJlc3NGb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkLmZpZWxkLmVycm9yJykuZXEoMCkuZm9jdXMoKTtcblx0fVxuXHRcblx0aWYgKCRzaGlwcGluZ0FkZHJlc3NGb3JtLnZhbGlkKCkgfHwgKCRzaGlwcGluZ0FkZHJlc3NGb3JtLmZpbmQoJy5mb3JtZmllbGQuaXNTdG9yZSBpbnB1dCcpLnByb3AoJ2NoZWNrZWQnKSAmJiAkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCcuZm9ybWZpZWxkLm15U3RvcmVJRCBpbnB1dCcpLnZhbCgpKSkge1xuXHRcdGlzU2hpcHBpbmdBZGRyZXNzVmFsaWQgPSB0cnVlO1xuXHR9IGVsc2Uge1xuXHRcdCQoJy5zaGlwcGluZy1hZGRyZXNzLWRhdGEuZm9ybS1pbmZvJykuaGlkZSgpO1xuXHRcdFxuXHRcdCRzaGlwcGluZ0FkZHJlc3NGb3JtLnNob3coKTtcblx0XHQkc2hpcHBpbmdBZGRyZXNzRm9ybS5maW5kKCdpbnB1dC5yZXF1aXJlZC5maWVsZC5lcnJvcicpLmVxKDApLmZvY3VzKCk7XG5cdH1cblx0XG5cdHZhciBpc0JvcGlzVmFsaWQgPSBmYWxzZTtcblx0aWYgKGRhdGEgJiYgZGF0YS5TdWJtaXRQYXltZW50Rm9yQm9waXMpIHtcblx0XHRpc0JvcGlzVmFsaWQgPSBkYXRhLklzQm9waXNJbnZlbnRvcnlWYWxpZDtcblx0fSBlbHNlIHtcblx0XHR2YXIgJGJvcGlzUHJvZHVjdExpbmVJdGVtcyA9ICQoY2FydEl0ZW1zRm9ybVNlbGVjdG9yKS5maW5kKCcuYm9waXMtcHJvZHVjdC1saW5lLWl0ZW1bc2t1XVtzdG9yZV0nKTtcblx0XHRcblx0XHRpZiAoJGJvcGlzUHJvZHVjdExpbmVJdGVtcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRCb3Bpc1Byb2R1Y3RMaW5lSXRlbUhlbHBlci5WYWxpZGF0ZVByb2R1Y3RMaW5lSXRlbXMoJChjYXJ0SXRlbXNGb3JtU2VsZWN0b3IpLmZpbmQoJy5ib3Bpcy1wcm9kdWN0LWxpbmUtaXRlbVtza3VdW3N0b3JlXScpLCB7IFN1Y2Nlc3NFdmVudDogJ0NoZWNrb3V0LlN1Ym1pdFBheW1lbnQnIH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpc0JvcGlzVmFsaWQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXHRcblx0aWYgKGlzQmlsbGluZ0FkZHJlc3NWYWxpZCAmJiBpc1NoaXBwaW5nQWRkcmVzc1ZhbGlkICYmIGlzQm9waXNWYWxpZCAmJiAkKCcjc2hpcHBpbmctbWV0aG9kLWxpc3QgaW5wdXQ6Y2hlY2tlZCcpLmxlbmd0aCAmJiAoYmFsYW5jZUR1ZSA9PSAwIHx8ICRwYXltZW50Rm9ybS52YWxpZCgpKSkge1xuXHRcdHZhciAkcGF5bWVudEZvcm1Ub1NldCA9ICRwYXltZW50Rm9ybS5jbG9uZSgpO1xuXHRcdHZhciBhY3Rpb25OYW1lID0gJHN1Ym1pdFBheW1lbnQuYXR0cignbmFtZScpO1xuXHRcdFxuXHRcdHZhciBzZWxlY3RlZFBheW1lbnRNZXRob2RJZCA9ICRwYXltZW50Rm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cInNlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCk7XG5cdFx0JHBheW1lbnRGb3JtVG9TZXQuZmluZCgnZGl2W3BheW1lbnQtbWV0aG9kXScpLm5vdCgnZGl2W3BheW1lbnQtbWV0aG9kPVwiJyArIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkICsgJ1wiXScpLnJlbW92ZSgpO1xuXHRcdFxuXHRcdCRwYXltZW50Rm9ybVRvU2V0LmZpbmQoJ3NlbGVjdCcpLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XG5cdFx0XHQkKHRoaXMpLnZhbCgkcGF5bWVudEZvcm0uZmluZCgnIycgKyAkKHRoaXMpLmF0dHIoJ2lkJykpLnZhbCgpKTtcblx0XHR9KTtcblx0XHRcblx0XHRzZXRPUENQYXltZW50RGF0YSgkcGF5bWVudEZvcm1Ub1NldCwgYWN0aW9uTmFtZSkudGhlbihmdW5jdGlvbihyZXNwb25zZSkge1xuXHRcdFx0dmFyIGRhdGE7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRkYXRhID0gSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGRhdGEgPSByZXNwb25zZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnc3VjY2VzcycpIHtcblx0XHRcdFx0dmFyIGRhdGFPYmplY3QgPSB7XG5cdFx0XHRcdFx0dmFsdWU6IGJhbGFuY2VEdWUsXG5cdFx0XHRcdFx0cGF5bWVudF90eXBlOiBzZWxlY3RlZFBheW1lbnRNZXRob2RJZFxuXHRcdFx0XHR9XG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FkZFBheW1lbnRJbmZvJywgZGF0YU9iamVjdCkudGhlbihmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAob3B0aW9ucy5DaGVja291dE1vZGUgPT0gJ01vYmlsZUFwcCcpIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlRm9yTW9iaWxlQXBwO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuY29uZmlybWF0aW9uUGFnZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmIChvcHRpb25zLkNoZWNrb3V0TW9kZSA9PSAnTW9iaWxlQXBwJykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmNvbmZpcm1hdGlvblBhZ2VGb3JNb2JpbGVBcHA7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gVXJscy5jb25maXJtYXRpb25QYWdlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2UgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpICYmIGRhdGEuc3RhdHVzID09PSAnYWZmaXJtUmVkaXJlY3QnKSB7XG5cdFx0XHRcdHZhciBfYWZmaXJtX2NvbmZpZyA9IHtcblx0XHRcdFx0XHRwdWJsaWNfYXBpX2tleTogZGF0YS5hZmZpcm0uUHVibGljQXBpS2V5LFxuXHRcdFx0XHRcdHNjcmlwdDogZGF0YS5hZmZpcm0uU2NyaXB0XG5cdFx0XHRcdH07XG5cdFx0XHRcdChmdW5jdGlvbihsLGcsbSxlLGEsZixiKXt2YXIgZCxjPWxbbV18fHt9LGg9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChmKSxuPWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKGYpWzBdLGs9ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBmdW5jdGlvbigpe2FbYl0uXy5wdXNoKFtjLGFyZ3VtZW50c10pfX07Y1tlXT1rKGMsZSxcInNldFwiKTtkPWNbZV07Y1thXT17fTtjW2FdLl89W107ZC5fPVtdO2NbYV1bYl09ayhjLGEsYik7YT0wO2ZvcihiPVwic2V0IGFkZCBzYXZlIHBvc3Qgb3BlbiBlbXB0eSByZXNldCBvbiBvZmYgdHJpZ2dlciByZWFkeSBzZXRQcm9kdWN0XCIuc3BsaXQoXCIgXCIpO2E8Yi5sZW5ndGg7YSsrKWRbYlthXV09ayhjLGUsYlthXSk7YT0wO2ZvcihiPVtcImdldFwiLFwidG9rZW5cIixcInVybFwiLFwiaXRlbXNcIl07YTxiLmxlbmd0aDthKyspZFtiW2FdXT1mdW5jdGlvbigpe307aC5hc3luYz0hMDtoLnNyYz1nW2ZdO24ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoaCxuKTtkZWxldGUgZ1tmXTtkKGcpO2xbbV09Y30pKHdpbmRvdyxfYWZmaXJtX2NvbmZpZyxcImFmZmlybVwiLFwiY2hlY2tvdXRcIixcInVpXCIsXCJzY3JpcHRcIixcInJlYWR5XCIpO1xuXHRcdFx0XHRcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0KEpTT04ucGFyc2UoZGF0YS5hZmZpcm0uQWZmaXJtQ2hlY2tvdXQpKTtcblx0XHRcdFx0YWZmaXJtLmNoZWNrb3V0LnBvc3QoKTtcblx0XHRcdFx0YWZmaXJtLnVpLnJlYWR5KFxuXHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0YWZmaXJtLnVpLmVycm9yLm9uKFwiY2xvc2VcIiwgZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdFx0Ly8gd2luZG93LmxvY2F0aW9uLnJlcGxhY2UoZGF0YS5hZmZpcm0uUmVkaXJlY3RVcmwpO1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHQpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ3NoaXBwaW5nUmVzdHJpY3Rpb25zRXJyb3InKSB7XG5cdFx0XHRcdHZhciBwb3B1cCA9IHJlcXVpcmUoJy4uL3BvcHVwJyk7XG5cdFx0XHRcdHZhciBwYXlsb2FkID0gSlNPTi5wYXJzZShkYXRhLnBheWxvYWQpO1xuXG5cdFx0XHRcdHZhciBsaXN0ID0gJC5tYXAocGF5bG9hZC5saXN0LCBmdW5jdGlvbiAoZWwpIHtcblx0XHRcdFx0XHRyZXR1cm4gJzxsaT4nICsgZWwubmFtZSArICc6PGJyPicgKyBlbC5tZXNzYWdlICsgJzwvbGk+Jztcblx0XHRcdFx0fSkuam9pbignJyk7XG5cdFx0XHRcdFxuXHRcdFx0XHRwb3B1cC5pbml0KHtcblx0XHRcdFx0XHR0aXRsZTogcGF5bG9hZC50aXRsZSxcblx0XHRcdFx0XHRjb250ZW50OiBwYXlsb2FkLm1lc3NhZ2UgKyAnPHVsIGNsYXNzPVwic2hpcHBpbmctcmVzdHJpY3Rpb25zLXBvcHVwX19saXN0XCI+JyArIGxpc3QgKyAnPC91bD4nLFxuXHRcdFx0XHR9KS5zaG93UG9wdXAoKTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdCaWxsaW5nQWRkcmVzc0Vycm9yJykge1xuXHRcdFx0XHR2YXIgbWVzc2FnZSA9IGRhdGEuaGFzT3duUHJvcGVydHkoJ21lc3NhZ2UnKSA/IGRhdGEubWVzc2FnZSA6IFJlc291cmNlcy5DaGVja291dC5Db25maXJtLkVycm9yLkdlbmVyaWM7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKCc8ZGl2IGlkPVwiZXJyb3JCb3hPUENcIiBjbGFzcz1cInBheW1lbnQtZGVjbGluZWQgcC0yIG10LTJcIj48aSBjbGFzcz1cImZhIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlXCI+PC9pPiA8Yj5CaWxsaW5nIEFkZHJlc3MgRXJyb3I6PC9iPiAnICsgbWVzc2FnZSArICc8L2Rpdj4nKTtcblx0XHRcdH0gZWxzZSBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgnc3RhdHVzJykgJiYgZGF0YS5zdGF0dXMgPT09ICdTaGlwcGluZ0FkZHJlc3NFcnJvcicpIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+U2hpcHBpbmcgQWRkcmVzcyBFcnJvcjo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fSBlbHNlIGlmIChkYXRhLmhhc093blByb3BlcnR5KCdzdGF0dXMnKSAmJiBkYXRhLnN0YXR1cyA9PT0gJ1ZhbGlkYXRpb25FcnJvcicpIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+VmFsaWRhdGlvbiBFcnJvcjo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyIG1lc3NhZ2UgPSBkYXRhLmhhc093blByb3BlcnR5KCdtZXNzYWdlJykgPyBkYXRhLm1lc3NhZ2UgOiBSZXNvdXJjZXMuQ2hlY2tvdXQuQ29uZmlybS5FcnJvci5HZW5lcmljO1xuXHRcdFx0XHQkc3VibWl0UGF5bWVudC5hZnRlcignPGRpdiBpZD1cImVycm9yQm94T1BDXCIgY2xhc3M9XCJwYXltZW50LWRlY2xpbmVkIHAtMiBtdC0yXCIgcm9sZT1cImFsZXJ0XCIgdGFiaW5kZXg9XCIwXCI+PGkgY2xhc3M9XCJmYSBmYS1leGNsYW1hdGlvbi10cmlhbmdsZVwiPjwvaT4gPGI+UGF5bWVudCBEZWNsaW5lZDo8L2I+ICcgKyBtZXNzYWdlICsgJzwvZGl2PicpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHQkc3VibWl0UGF5bWVudC5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHRcdHN1Ym1pdFBheW1lbnRSZWNhcHRjaGFFcnJvcigpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG5cdFx0XHRpZiAocmVzcG9uc2Uuc3RhdHVzID09IDMwMiAmJiByZXNwb25zZS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IHJlc3BvbnNlLnJlc3BvbnNlVGV4dDtcblx0XHRcdH1cblx0XHR9KTtcblx0fSBlbHNlIHtcblx0XHQkc3VibWl0UGF5bWVudC5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0JHN1Ym1pdFBheW1lbnQuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHQvLyBBZGRpbmcgQURBIGNvbXBsaWFuY2UgZXJyb3IgbWVzc2FnZXMgZm9yIHN1Ym1pdFBheW1lbnQgc2VjdGlvblxuXHRcdCRwYXltZW50Rm9ybS52YWxpZGF0ZSgpLmZvcm0oKTtcblx0XHRpZiAoJHBheW1lbnRGb3JtLmZpbmQoJy5maWVsZC5lcnJvcicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJy5wYXltZW50LWRlY2xpbmVkJykucmVtb3ZlKCk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzID0gb3BjcGF5bWVudC5nZXRFcnJvck1lc3NhZ2VzKCRwYXltZW50Rm9ybSk7XG5cdFx0XHR2YXIgcGF5bWVudEZvcm1FcnJvckJveCA9IG9wY3BheW1lbnQuZXJyb3JCb3goJ0Nhbm5vdCBQcm9jZWVkJywgJ1BsZWFzZSBmaXggdGhlIGZvbGxvd2luZyBlcnJvcnM6JywgcGF5bWVudEZvcm1FcnJvck1lc3NhZ2VzKTtcblx0XHRcdGlmIChwYXltZW50Rm9ybUVycm9yQm94KSB7XG5cdFx0XHRcdCRzdWJtaXRQYXltZW50LmFmdGVyKHBheW1lbnRGb3JtRXJyb3JCb3gpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHN1Ym1pdFBheW1lbnRSZWNhcHRjaGFFcnJvcigpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQYXltZW50TWV0aG9kc0V2ZW50cygpIHtcblx0dmFyIGNyZWRpdENhcmRMaXN0U2VsZWN0b3IgPSAnLnBheW1lbnQtY2FyZC1saXN0IHNlbGVjdCwgLnBheW1lbnQtY2FyZC1saXN0IGlucHV0W3R5cGU9XCJyYWRpb1wiXSc7XG5cdHZhciBjcmVkaXRDYXJkTnVtYmVySW5wdXQgPSAnaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF9udW1iZXJcIl0sIGlucHV0W25hbWUqPVwiX3ByaXZhdGVMYWJlbENyZWRpdF9udW1iZXJcIl0nO1xuXHRcblx0JChjcmVkaXRDYXJkTnVtYmVySW5wdXQpLnBhcmVudCgpLmFwcGVuZCgnPGRpdiBjbGFzcz1cImNjLWltYWdlXCI+PC9kaXY+Jyk7XG5cdFxuXHQkKGRvY3VtZW50KS5vbignY2hhbmdlJywgY3JlZGl0Q2FyZExpc3RTZWxlY3RvciwgZnVuY3Rpb24gKGUsIG9wdGlvbnMpIHtcdFxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cblx0XHRvcHRpb25zID0gb3B0aW9ucyAhPSB1bmRlZmluZWQgPyBvcHRpb25zIDoge307XG5cdFx0b3B0aW9ucy5kb1Jlc2V0ID0gb3B0aW9ucy5kb1Jlc2V0ICE9IHVuZGVmaW5lZCA/IG9wdGlvbnMuZG9SZXNldCA6IHRydWU7XG5cdFx0XG5cdFx0dmFyIHNlbGVjdGVkQ3JlZGl0Q2FyZFR5cGUgPSAkdGhpcy52YWwoKTtcblx0XHRcblx0XHRpZiAoc2VsZWN0ZWRDcmVkaXRDYXJkVHlwZSkge1xuXHRcdFx0dmFyIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkID0gJHRoaXMuYXR0cigncGF5bWVudC1tZXRob2QnKSB8fCAkdGhpcy5maW5kKCc6c2VsZWN0ZWQnKS5hdHRyKCdwYXltZW50LW1ldGhvZCcpO1xuXHRcdFx0dmFyIHNlbGVjdGVkUGF5bWVudENhcmRJbWFnZVVybCA9ICR0aGlzLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpIHx8ICR0aGlzLmZpbmQoJzpzZWxlY3RlZCcpLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpO1xuXHRcdFx0XG5cdFx0XHQkcGF5bWVudEZvcm0uYXR0cignc2VsZWN0ZWQtcGF5bWVudC1tZXRob2QnLCBzZWxlY3RlZFBheW1lbnRNZXRob2RJZCk7XG5cdFx0XHQkdGhpcy5jbG9zZXN0KCdbcGF5bWVudC1tZXRob2QtZ3JvdXBdJykuYXR0cigncGF5bWVudC1tZXRob2QnLCBzZWxlY3RlZFBheW1lbnRNZXRob2RJZCk7XG5cdFx0XHRcblx0XHRcdCQoJy5wdF9vbmVwY2hlY2tvdXQgaW5wdXRbbmFtZSo9XCJfc2VsZWN0ZWRQYXltZW50TWV0aG9kSURcIl0nKS52YWwoc2VsZWN0ZWRQYXltZW50TWV0aG9kSWQpO1xuXG5cdFx0XHRpZiAoISQoJ1twYXltZW50LW1ldGhvZD1cIicgKyBzZWxlY3RlZFBheW1lbnRNZXRob2RJZCArICdcIl0ucGF5bWVudC1tZXRob2QnKS5oYXNDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKSkge1xuXHRcdFx0XHQkKCcucGF5bWVudC1tZXRob2QnKS5yZW1vdmVDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKS5oaWRlKCk7XG5cdFx0XHRcdCQoJ1twYXltZW50LW1ldGhvZD1cIicgKyBzZWxlY3RlZFBheW1lbnRNZXRob2RJZCArICdcIl0ucGF5bWVudC1tZXRob2QnKS5hZGRDbGFzcygncGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKS5zaG93KCk7XHRcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JCgnLnBheW1lbnQtY2FyZC1saXN0LmdyaWQnKS5maW5kKCdbcGF5bWVudC1jYXJkXScpLmhpZGUoKTtcblx0XHRcdCQoJy5wYXltZW50LWNhcmQtbGlzdC5ncmlkJykuZmluZCgnW3BheW1lbnQtY2FyZD1cIicgKyBzZWxlY3RlZENyZWRpdENhcmRUeXBlICsgJ1wiXScpLnNob3coKTtcblx0XHRcdFxuXHRcdFx0JChjcmVkaXRDYXJkTGlzdFNlbGVjdG9yKS5maWx0ZXIoJ2lucHV0W3ZhbHVlPVwiJyArIHNlbGVjdGVkQ3JlZGl0Q2FyZFR5cGUgKyAnXCJdJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXHRcdFx0JChjcmVkaXRDYXJkTGlzdFNlbGVjdG9yKS5maW5kKCdvcHRpb25bdmFsdWU9XCInICsgc2VsZWN0ZWRDcmVkaXRDYXJkVHlwZSArICdcIl0nKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXG5cdFx0XHQkcGF5bWVudEZvcm0uZmluZCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCArICdcIl0gLmNjLWltYWdlJykuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ3VybCgnICsgc2VsZWN0ZWRQYXltZW50Q2FyZEltYWdlVXJsICsgJyknKTtcblx0XHRcdFxuXHRcdFx0aWYgKG9wdGlvbnMuZG9SZXNldCkge1xuXHRcdFx0XHRyZXNldENyZWRpdENhcmRGaWVsZHMoJCgnW3BheW1lbnQtbWV0aG9kPVwiJyArIHNlbGVjdGVkUGF5bWVudE1ldGhvZElkICsgJ1wiXS5wYXltZW50LW1ldGhvZCcpKTtcblx0XHRcdFx0JGNyZWRpdENhcmRMaXN0LnZhbCgnJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcblx0XG5cdCRwYXltZW50Rm9ybS5vbignY2xpY2snLCAnLnBheW1lbnQtbWV0aG9kLWdyb3VwLXNlbGVjdG9yJywgZnVuY3Rpb24gKGUpIHtcblx0ICAgIHZhciBwYXltZW50TWV0aG9kR3JvdXBJZCA9ICQodGhpcykudmFsKCk7XG5cdCAgICBcblx0ICAgIGlmIChwYXltZW50TWV0aG9kR3JvdXBJZCkge1xuXHQgICAgXHQkcGF5bWVudEZvcm0uYXR0cignc2VsZWN0ZWQtcGF5bWVudC1tZXRob2QtZ3JvdXAnLCBwYXltZW50TWV0aG9kR3JvdXBJZCk7XG5cdFx0ICAgIFxuXHRcdCAgICAkKCcucHRfb25lcGNoZWNrb3V0IGlucHV0W25hbWUqPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykudmFsKCQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBwYXltZW50TWV0aG9kR3JvdXBJZCArICdcIl0nKS5hdHRyKCdwYXltZW50LW1ldGhvZCcpKTtcblx0XHQgICAgXG5cdFx0ICAgICQoJ1twYXltZW50LW1ldGhvZC1ncm91cF0nKS5oaWRlKCkucmVtb3ZlQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0ICAgICQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBwYXltZW50TWV0aG9kR3JvdXBJZCArICdcIl0nKS5zaG93KCkuYWRkQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0ICAgIFxuXHRcdCAgICBpZiAoJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIHBheW1lbnRNZXRob2RHcm91cElkICsgJ1wiXScpLmZpbmQoJy5wYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLmxlbmd0aCA8IDEpIHtcblx0XHQgICAgXHR2YXIgJGRlZmF1bHRQYXltZW50TWV0aG9kID0gJCgnW3BheW1lbnQtbWV0aG9kLWdyb3VwPVwiJyArIHBheW1lbnRNZXRob2RHcm91cElkICsgJ1wiXScpLmZpbmQoJy5wYXltZW50LW1ldGhvZCcpLmZpcnN0KCk7XG5cdFx0ICAgIFx0XG5cdFx0ICAgIFx0JGRlZmF1bHRQYXltZW50TWV0aG9kLmFkZENsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpLnNob3coKTtcblx0XHQgICAgXHRcblx0XHQgICAgXHRpZiAoJGRlZmF1bHRQYXltZW50TWV0aG9kLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpKSB7XG5cdFx0ICAgIFx0XHQkZGVmYXVsdFBheW1lbnRNZXRob2QuZmluZCgnLmNjLWltYWdlJykuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgJ3VybCgnICsgJGRlZmF1bHRQYXltZW50TWV0aG9kLmF0dHIoJ3BheW1lbnQtY2FyZC1pbWFnZScpICsgJyknKTtcblx0XHQgICAgXHR9XG5cdFx0ICAgIH1cblx0XHQgICAgXG5cdFx0ICAgIGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRcdFx0JChbZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCBkb2N1bWVudC5ib2R5XSkuYW5pbWF0ZSh7XG5cdFx0XHRcdFx0Ly8gc2Nyb2xsVG9wOiAkKCcucGF5bWVudC1tZXRob2QtZXhwYW5kZWQnKS5jbG9zZXN0KCcucGF5bWVudC1tZXRob2Qtb3B0aW9uJykub2Zmc2V0KCkudG9wIC0gJCgnLnRvcC1iYW5uZXInKS5oZWlnaHQoKSArIDIwXG5cdFx0XHRcdFx0c2Nyb2xsVG9wOiAkKCcjcGF5bWVudFNlY3Rpb24nKS5vZmZzZXQoKS50b3AgLSAkKCcudG9wLWJhbm5lcicpLmhlaWdodCgpIC0gMTVcblx0XHRcdFx0fSwgMjUwKTtcblx0XHQgICAgfVxuXHRcdCAgICBcblx0XHQgICAgLy8gYWRkcmVzc2VzLnVwZGF0ZVN1bW1hcnkoKTtcblx0ICAgIH1cblx0fSk7XG5cdFxuXHQkKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXSBbY3JlZGl0LWNhcmQtbnVtYmVyLWlucHV0XScpLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuXHRcdCRjcmVkaXRDYXJkTGlzdC52YWwoJycpO1xuXHR9KTtcblxuXHQkKCdbcGF5bWVudC1tZXRob2QtZ3JvdXA9XCInICsgUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkICsgJ1wiXSBbY3JlZGl0LWNhcmQtbnVtYmVyLWlucHV0XScpLm9uKCdrZXl1cCcsIGZ1bmN0aW9uKGUpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBjcmVkaXRDYXJkTnVtYmVyID0gJHRoaXMudmFsKCk7XG5cdFx0XG5cdFx0dmFyIHNlbGVjdGVkQ2FyZCA9IHV0aWwuZ2V0Q3JlZGl0Q2FyZFR5cGUoY3JlZGl0Q2FyZE51bWJlcik7XG5cdFx0aWYgKHNlbGVjdGVkQ2FyZCkge1xuXHRcdFx0dmFyICRzZWxlY3RlZENhcmROdW1iZXJJbnB1dCA9ICQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgKyAnXCJdIFtwYXltZW50LW1ldGhvZD1cIicgKyBzZWxlY3RlZENhcmQuUGF5bWVudE1ldGhvZCArICdcIl0gW2NyZWRpdC1jYXJkLW51bWJlci1pbnB1dF0nKTtcblx0XHRcdFxuXHRcdFx0aWYgKCRzZWxlY3RlZENhcmROdW1iZXJJbnB1dC5maWx0ZXIoJzp2aXNpYmxlJykubGVuZ3RoIDwgMSkge1xuXHRcdFx0XHQkc2VsZWN0ZWRDYXJkTnVtYmVySW5wdXQudmFsKGNyZWRpdENhcmROdW1iZXIpO1xuXHRcdFx0fVxuXG5cdFx0XHQkKCcucHRfb25lcGNoZWNrb3V0IGlucHV0W25hbWUqPVwiX2NyZWRpdENhcmRfdHlwZVwiXScpLnZhbChzZWxlY3RlZENhcmQuUGF5bWVudENhcmQpO1xuXHRcdFx0JChjcmVkaXRDYXJkTGlzdFNlbGVjdG9yKS5maWx0ZXIoJ2lucHV0W3R5cGU9XCJyYWRpb1wiXVt2YWx1ZT1cIicgKyBzZWxlY3RlZENhcmQuUGF5bWVudENhcmREaXNwbGF5S2V5ICsgJ1wiXScpLmZpcnN0KCkucHJvcCgnY2hlY2tlZCcsIHRydWUpLnRyaWdnZXIoJ2NoYW5nZScsIHsgZG9SZXNldDogZmFsc2UgfSk7XG5cdFx0XHRcblx0XHRcdGlmICgkc2VsZWN0ZWRDYXJkTnVtYmVySW5wdXQuZmlsdGVyKCc6Zm9jdXMnKS5sZW5ndGggPCAxKSB7XG5cdFx0XHRcdCRzZWxlY3RlZENhcmROdW1iZXJJbnB1dC5mb2N1cygpLnZhbChjcmVkaXRDYXJkTnVtYmVyKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLmNjLWNhcmRsaXN0LXNlbGVjdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQXR0cignc2VsZWN0ZWQnKS52YWwoJycpO1xuXHRcdFx0JCgnLnBheW1lbnQtY2FyZC1saXN0LmdyaWQnKS5maW5kKCdbcGF5bWVudC1jYXJkXScpLnNob3coKTtcblx0XHRcdCQoY3JlZGl0Q2FyZExpc3RTZWxlY3RvcikuZmlsdGVyKCdpbnB1dCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdFx0XHQkKGNyZWRpdENhcmRMaXN0U2VsZWN0b3IpLmZpbmQoJ29wdGlvbicpLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xuXHRcdFx0JHBheW1lbnRGb3JtLmZpbmQoJ1twYXltZW50LW1ldGhvZC1ncm91cD1cIicgKyBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQgKyAnXCJdIC5jYy1pbWFnZScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICcnKTtcblx0XHR9XG5cblx0XHQkY3JlZGl0Q2FyZFNhdmVDaGVja2JveENvbnRhaW5lci5zaG93KCk7XG5cdH0pO1xuXHRcblx0JCgnLmFkZC1uZXctY2FyZCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpIHtcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRyZXNldENyZWRpdENhcmRGaWVsZHMoJCh0aGlzKS5jbG9zZXN0KCdbcGF5bWVudC1tZXRob2RdJykpO1xuXHRcdCQoJyNvcGMtY2MtbGlzdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJyk7XG5cdFx0JCgnLmNjLWNhcmRsaXN0LXNlbGVjdCA6aW5wdXQnKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQXR0cignc2VsZWN0ZWQnKS52YWwoJycpO1xuXHRcdCQoJy5jYy1pbWFnZScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICdub25lJyk7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5wYXltZW50LW1ldGhvZC1vcHRpb24uYWNjb3JkaW9uIC5mb3JtLWxhYmVsJywgZnVuY3Rpb24gKCkge1xuXHRcdCQodGhpcykuY2xvc2VzdCgnLmFjY29yZGlvbicpLnRvZ2dsZUNsYXNzKCdvcGVuJyk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiByZXNldENyZWRpdENhcmRGaWVsZHMoJHBheW1lbnRNZXRob2QpIHtcblx0JHBheW1lbnRNZXRob2QuZmluZCgnaW5wdXRbbmFtZSo9XCJfb3duZXJcIl0nKS52YWwoJycpO1xuXHQkcGF5bWVudE1ldGhvZC5maW5kKCdpbnB1dFtuYW1lKj1cIl9udW1iZXJcIl0nKS52YWwoJycpO1xuXHQkcGF5bWVudE1ldGhvZC5maW5kKCdpbnB1dFtuYW1lKj1cIl9jdm5cIl0nKS52YWwoJycpO1xuXHQkcGF5bWVudE1ldGhvZC5maW5kKCdpbnB1dFtuYW1lKj1cIl9tb250aFwiXScpLnZhbCgnJyk7XG5cdCRwYXltZW50TWV0aG9kLmZpbmQoJ2lucHV0W25hbWUqPVwiX3llYXJcIl0nKS52YWwoJycpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIHRoZSBBSkFYIHJlcXVlc3QgdG8gc2V0IGNhcnQgZGF0YVxuICogQHBhcmFtIHtFbGVtZW50fSBmb3JtIFRoZSBmb3JtIGVsZW1lbnQgdGhhdCBwcmVzZW50IGFkZHJlc3Mgb2JqZWN0XG4gKiBAcGFyYW0ge0VsZW1lbnR9IEFjdGlvbiBuYW1lIHRvIGFwcGx5IHRvIGZvcm1cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgc2V0T1BDUGF5bWVudERhdGEgPSBmdW5jdGlvbiAoZm9ybVNlbGVjdG9yLCBuYW1lKSB7XG4gICAgdmFyICRmb3JtID0gJChmb3JtU2VsZWN0b3IpO1xuXG4gICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLnNldE9wY0FkZHJlc3MpLFxuICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIG5hbWUgKyAnPScgKyBuYW1lXG4gICAgfSkpO1xufTtcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdFxuXHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2FwdGNoYSAmJiAob3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclBsYWNlT3JkZXIgfHwgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvclJld2FyZHNDcmVkaXQgfHwgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvckdpZnRDYXJkcykpIHtcbiAgICBcdHJlY2FwdGNoYS5pbml0aWFsaXplKCk7XG5cdH1cblx0XG5cdGlmIChvcHRpb25zLkIyQiAmJiBvcHRpb25zLkIyQi5FbmFibGVkKSB7XG5cdFx0UGF5bWVudFZvdWNoZXJQYW5lbCA9IHJlcXVpcmUoJy4vY2hlY2tvdXQvUGF5bWVudFZvdWNoZXJQYXltZW50UGFuZWwnKTtcblx0XHRQYXltZW50Vm91Y2hlclBhbmVsLmluaXRpYWxpemUoKTtcblx0fVxuXHRHaWZ0Q2FyZC5pbml0aWFsaXplKG9wdGlvbnMpO1xuXHRSZXdhcmRzQ3JlZGl0LmluaXRpYWxpemUob3B0aW9ucyk7XG5cdExveWFsdHlDcmVkaXQuaW5pdGlhbGl6ZShvcHRpb25zKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKG9wdGlvbnMpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vdG9vbHRpcCcpO1xuXG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGJ1ZmZlciA9IHt9O1xuXG5mdW5jdGlvbiB0cmlnZ2VyUmVhY3RXZWJ2aWV3RXZlbnQoKSB7XG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cpIHtcblx0XHR3aW5kb3cuUmVhY3ROYXRpdmVXZWJWaWV3LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHsgYWN0aW9uOiAnb3JkZXItcGFnZScgfSkpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQcmljZVNwaWRlck9yZGVyVHJhY2tpbmcoKSB7XG5cdCQoZG9jdW1lbnQpLm9uKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGZ1bmN0aW9uIChldmVudCwgZGF0YUxheWVyKSB7XG5cdFx0dmFyIHBzcmlkID0gc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbSgncHNyaWQnKTtcblx0XHRpZiAocHNyaWQgJiYgZGF0YUxheWVyICYmICdldmVudCcgaW4gZGF0YUxheWVyICYmIGRhdGFMYXllci5ldmVudCA9PSAncHVyY2hhc2UnKSB7XHRcblx0XHRcdHZhciBpdGVtc1RpdGxlID0gW107XG5cdFx0XHR2YXIgaXRlbXNQcmljZSA9IFtdO1xuXHRcdFx0dmFyIGl0ZW1zUXVhbnRpdHkgPSBbXTtcblx0XHRcdHZhciBpdGVtc1NrdSA9IFtdO1xuXHRcdFx0dmFyIGl0ZW1zTWFudWZhY3R1cmVyID0gW107XG5cdFx0XHR2YXIgaXRlbUVsZW1lbnRzID0gZGF0YUxheWVyLml0ZW1zO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBpdGVtRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0aXRlbXNUaXRsZS5wdXNoKGl0ZW1FbGVtZW50c1tpXS5pdGVtX25hbWUpO1xuXHRcdFx0XHRpdGVtc1F1YW50aXR5LnB1c2goaXRlbUVsZW1lbnRzW2ldLnF1YW50aXR5KTtcblx0XHRcdFx0aXRlbXNQcmljZS5wdXNoKGl0ZW1FbGVtZW50c1tpXS5wcmljZSk7XG5cdFx0XHRcdGl0ZW1zU2t1LnB1c2goaXRlbUVsZW1lbnRzW2ldLml0ZW1faWQpO1xuXHRcdFx0XHRpdGVtc01hbnVmYWN0dXJlci5wdXNoKGl0ZW1FbGVtZW50c1tpXS5pdGVtX2JyYW5kKTtcblx0XHRcdH1cblx0XHRcdHZhciBvcmRlciA9IHBzd3RiLnB1cmNoYXNlVHJhY2tpbmcuY3JlYXRlT3JkZXIoKTtcblx0XHRcdG9yZGVyLmN1cnJlbmN5Q29kZSA9IGRhdGFMYXllci5jdXJyZW5jeTtcblx0XHRcdG9yZGVyLnB1cmNoYXNlVG90YWwgPSBkYXRhTGF5ZXIudmFsdWU7XG5cdFx0XHR2YXIgaXRlbXNEZXRhaWxzID0gW107XG5cdFx0XHRmb3IgKHZhciB5ID0gMDsgeSA8IGl0ZW1zVGl0bGUubGVuZ3RoOyB5KyspIHtcblx0XHRcdFx0aXRlbXNEZXRhaWxzLnB1c2goe1xuXHRcdFx0XHRcdFwicHJvZHVjdE5hbWVcIjogaXRlbXNUaXRsZVt5XSxcblx0XHRcdFx0XHRcInF1YW50aXR5XCI6IGl0ZW1zUXVhbnRpdHlbeV0sXG5cdFx0XHRcdFx0XCJ1bml0UHJpY2VcIjogaXRlbXNQcmljZVt5XSAvIGl0ZW1zUXVhbnRpdHlbeV0sXG5cdFx0XHRcdFx0XCJtYW51ZmFjdHVyZXJcIjogaXRlbXNNYW51ZmFjdHVyZXJbeV0sXG5cdFx0XHRcdFx0XCJza3VcIjogaXRlbXNTa3VbeV1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHRvcmRlci5kZXRhaWxzID0gaXRlbXNEZXRhaWxzO1xuXHRcdFx0b3JkZXIucmVkaXJlY3RUb2tlbiA9IHBzcmlkO1xuXHRcdFx0b3JkZXIuc3VibWl0KCk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVZXT09yZGVyVHJhY2tpbmcoKSB7XG5cdGJ1ZmZlclsnaXRlbXMnXSA9IG51bGw7XG5cdGlmIChTaXRlUHJlZmVyZW5jZXMuVldPX0VOQUJMRUQgJiYgU2l0ZVByZWZlcmVuY2VzLlZXT19QVVJDSEFTRV9UUkFDS0lOR19FTkFCTEVEKSB7XG5cdFx0YnVmZmVyWyd2d29Mb2FkZWRJbnRlcnZhbCddID0gc2V0SW50ZXJ2YWwodHJpZ2dlclZXT09yZGVyVHJhY2tpbmcsIDEwMCk7XG5cblx0XHQkKGRvY3VtZW50KS5vbignRGF0YUxheWVyLk9yZGVyQ29tcGxldGUnLCBmdW5jdGlvbiAoZXZlbnQsIGRhdGFMYXllcikge1xuXHRcdFx0dmFyIGl0ZW1zID0gW107XG5cdFx0XHR2YXIgcGF5bWVudE1ldGhvZHMgPSAnJztcblx0XHRcdGlmIChwYWdlQ29udGV4dC5QYXltZW50TWV0aG9kcykge1xuXHRcdFx0XHRwYXltZW50TWV0aG9kcyA9IHBhZ2VDb250ZXh0LlBheW1lbnRNZXRob2RzLmpvaW4oJyB8ICcpO1xuXHRcdFx0fVxuXHRcdFx0JCgnLnByb2R1Y3RDYXJkTWV0YWRhdGEnKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XHR2YXIgaXRlbURhdGFMYXllcjtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRpdGVtRGF0YUxheWVyID0gSlNPTi5wYXJzZSgkdGhpcy5hdHRyKCdkYXRhLXByb2R1Y3QtZ2E0LWpzb24nKSk7XG5cdFx0XHRcdH0gY2F0Y2goZXhjZXB0aW9uKSB7fVxuXHRcdFx0XHRpZiAoaXRlbURhdGFMYXllcikge1xuXHRcdFx0XHRcdHZhciByZXZlbnVlID0gaXRlbURhdGFMYXllci5wcmljZTtcblx0XHRcdFx0XHR2YXIgcHJpY2UgPSByZXZlbnVlO1xuXHRcdFx0XHRcdGlmIChpdGVtRGF0YUxheWVyLmRpc2NvdW50KSB7XG5cdFx0XHRcdFx0XHRwcmljZSArPSBpdGVtRGF0YUxheWVyLmRpc2NvdW50O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpdGVtcy5wdXNoKHtcblx0XHRcdFx0XHRcdFwicHJpY2VcIjogcHJpY2UudG9GaXhlZCgyKSxcblx0XHRcdFx0XHRcdFwiaXRlbVwiOiBpdGVtRGF0YUxheWVyLml0ZW1faWQsXG5cdFx0XHRcdFx0XHRcInBheW1lbnRNZXRob2RcIjogcGF5bWVudE1ldGhvZHMsXG5cdFx0XHRcdFx0XHRcInJlZ2lzdGVyZWRVc2VyXCI6IEN1c3RvbWVyLnJlZ2lzdGVyZWQsXG5cdFx0XHRcdFx0XHRcInJldmVudWVcIjogcmV2ZW51ZVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0aWYgKGl0ZW1zICYmIGl0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0YnVmZmVyWydpdGVtcyddID0gaXRlbXM7XG5cdFx0XHRcdHRyaWdnZXJWV09PcmRlclRyYWNraW5nKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJpZ2dlclZXT09yZGVyVHJhY2tpbmcoKSB7XG5cdGlmIChidWZmZXJbJ2l0ZW1zJ10gJiYgd2luZG93LlZXTyAmJiB3aW5kb3cuVldPLmV2ZW50ICYmIHR5cGVvZiB3aW5kb3cuVldPLmV2ZW50ID09ICdmdW5jdGlvbicpIHtcblx0XHRjbGVhckludGVydmFsKGJ1ZmZlclsndndvTG9hZGVkSW50ZXJ2YWwnXSk7XG5cdFx0Zm9yICh2YXIgaXRlbUluZGV4ID0gMDsgaXRlbUluZGV4IDwgYnVmZmVyWydpdGVtcyddLmxlbmd0aDsgaXRlbUluZGV4KyspIHtcblx0XHRcdHZhciBpdGVtID0gYnVmZmVyWydpdGVtcyddW2l0ZW1JbmRleF07XG5cdFx0XHRWV08uZXZlbnQoXCJwdXJjaGFzZVwiLCBpdGVtKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cblx0dG9vbHRpcC5pbml0KHtcblx0XHRpdGVtczogJy50b29sdGlwJ1xuXHR9KTtcblx0dHJpZ2dlclJlYWN0V2Vidmlld0V2ZW50KCk7XG5cdGluaXRpYWxpemVQcmljZVNwaWRlck9yZGVyVHJhY2tpbmcoKTtcblx0aW5pdGlhbGl6ZVZXT09yZGVyVHJhY2tpbmcoKTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG52YXIgYWpheCA9IHJlcXVpcmUoJy4uLy4uL2FqYXgnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBtaW5pY2FydCA9IHJlcXVpcmUoJy4uLy4uL21pbmljYXJ0Jyk7XG52YXIgcGFnZSA9IHJlcXVpcmUoJy4uLy4uL3BhZ2UnKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxudmFyIGRhdGFCdWZmZXIgPSB7fTtcblxuLyoqXG4gKiBXcmFwcyB0aGUgZGlhbG9nIGNsb3NlIGZ1bmN0aW9uYWxpdHkgaW4gYSBmdW5jdGlvbiBzbyB0aGF0IHdlIGNhbiBob29rIGludG8gdGhlIHRyYW5zaXRpb25FbmQgZXZlbnRcbiAqIHRvIGZpcmUgdGhlIGNsb3NlIGV2ZW50IG9uIHRoZSBkaWFsb2cuXG4gKiBUaGlzIGFsbG93cyBmb3IgYW4gYW5pbWF0aW9uIHRvIGNvbXBsZXRlIGJlZm9yZSB0aGUgZGlhbG9nIGlzIGNsb3NlZCBhbmQgcmVtb3ZlZCBmcm9tIHRoZSBkb21cbiAqL1xuIHZhciBjbG9zZUFkZFRvQ2FydE1vZGFsID0gZnVuY3Rpb24gKCkge1xuXHQvLyBzYXZlIG92ZXJhbHkgZm9yIGNsYXNzIGFkZGl0aW9uc1xuXHR2YXIgJG92ZXJsYXkgPSAkKCcuYWRkLXRvLWNhcnQtbW9kYWwtd3JhcHBlcicpLnBhcmVudCgpLmZpbmQoJy51aS13aWRnZXQtb3ZlcmxheScpO1xuXHRcblx0Ly8gaG9vayBpbnRvIHRyYW5zaXRpb24gZW5kXG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5Sc3BVUykge1xuXHRcdHZhciBjdXJyZW50TW9kYWwgPSAkKCcjZGlhbG9nLWNvbnRhaW5lcicpO1xuXHRcdGlmIChjdXJyZW50TW9kYWwuZGlhbG9nKCdpc09wZW4nKSkge1xuXHRcdFx0Y3VycmVudE1vZGFsLmRpYWxvZygnY2xvc2UnKTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXInKS5vbmUoJ3RyYW5zaXRpb25lbmQgd2Via2l0VHJhbnNpdGlvbkVuZCBvVHJhbnNpdGlvbkVuZCcsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHR2YXIgY3VycmVudE1vZGFsID0gJCh0aGlzKS5maW5kKCcjZGlhbG9nLWNvbnRhaW5lcicpO1xuXHRcdFx0aWYgKGN1cnJlbnRNb2RhbC5kaWFsb2coJ2lzT3BlbicpKSB7XG5cdFx0XHRcdGN1cnJlbnRNb2RhbC5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblx0XG5cdCRvdmVybGF5LnJlbW92ZUNsYXNzKCdzaG93Jyk7XG5cdCQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIGFkZCBhbiBpdGVtIHRvIGNhcnRcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGl0ZW0gcXVhbnRpdHkgYW5kIElEIGRhdGFcbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgYWRkSXRlbVRvQ2FydCA9IGZ1bmN0aW9uIChmb3JtKSB7XG4gICAgdmFyICRmb3JtID0gJChmb3JtKSxcbiAgICAgICAgJHF0eSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJRdWFudGl0eVwiXScpO1xuICAgIGlmICgkcXR5Lmxlbmd0aCA9PT0gMCB8fCBpc05hTigkcXR5LnZhbCgpKSB8fCBwYXJzZUludCgkcXR5LnZhbCgpLCAxMCkgPT09IDApIHtcbiAgICAgICAgJHF0eS52YWwoJzEnKTtcbiAgICB9XG4gICAgcmV0dXJuIFRQcm9taXNlLnJlc29sdmUoJC5hamF4KHtcbiAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICB1cmw6IHV0aWwuYWpheFVybChVcmxzLmFkZFByb2R1Y3QpLFxuICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKVxuICAgIH0pKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgdG8gaGFuZGxlIHRoZSBhZGQgdG8gY2FydCBldmVudFxuICovXG52YXIgYWRkVG9DYXJ0ID0gZnVuY3Rpb24oZXZlbnQsIGRhdGEpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHR2YXIgJGh0bWwgPSAkKCdodG1sJyk7XG5cdHZhciAkY29udGFpbmVyID0gJCgnI3dyYXBwZXInKTtcbiAgICB2YXIgJGZvcm0gPSAkKCcucGRwRm9ybScpO1xuICAgIHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cbiAgICBpZiAoIWlzU2l6ZVNlbGVjdGVkKSB7XG4gICAgXHRkaWFsb2cub3Blbih7XG5cdFx0XHRodG1sOiAnUGxlYXNlIHNlbGVjdCBhIHNpemUnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRkaWFsb2dDbGFzczogJ2RpYWxvZy1hbGVydCcsXG5cdFx0XHRcdGRyYWdnYWJsZTogZmFsc2Vcblx0XHRcdH1cblx0XHR9KTtcbiAgICBcdHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoISQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGgpIHtcbiAgICBcdGRpYWxvZy5vcGVuKHtcblx0XHRcdGh0bWw6ICdQbGVhc2Ugc2VsZWN0IGEgY29sb3InLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRkaWFsb2dDbGFzczogJ2RpYWxvZy1hbGVydCcsXG5cdFx0XHRcdGRyYWdnYWJsZTogZmFsc2Vcblx0XHRcdH1cblx0XHR9KTtcbiAgICBcdHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgaXNCb3BpcyA9IGZhbHNlO1xuXHR2YXIgJGJvcGlzQWRkVG9DYXJ0T3B0aW9ucyA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLWNvbnRhaW5lcicpO1xuXHR2YXIgJGJvcGlzQWRkVG9DYXJ0T3B0aW9uO1xuXHRpZiAoJGJvcGlzQWRkVG9DYXJ0T3B0aW9ucy5sZW5ndGggPiAwKSB7XG5cdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblJzcFVTKSB7XG5cdFx0XHQkYm9waXNBZGRUb0NhcnRPcHRpb25zLmZpbmQoJ2lucHV0W25hbWU9XCJBZGRUb0NhcnRPcHRpb25cIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0JChldmVudC5jdXJyZW50VGFyZ2V0KS5jbG9zZXN0KCdsaScpLmZpbmQoJ2lucHV0W25hbWU9XCJBZGRUb0NhcnRPcHRpb25cIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0XHQkYm9waXNBZGRUb0NhcnRPcHRpb25zID0gJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtY29udGFpbmVyJyk7XG5cdFx0fVxuXHRcdCRib3Bpc0FkZFRvQ2FydE9wdGlvbiA9ICRib3Bpc0FkZFRvQ2FydE9wdGlvbnMuZmluZCgnaW5wdXRbbmFtZT1cIkFkZFRvQ2FydE9wdGlvblwiXTpjaGVja2VkJyk7XG5cdFx0dmFyICRib3Bpc0FkZFRvQ2FydExhYmVsID0gJGJvcGlzQWRkVG9DYXJ0T3B0aW9uLmNsb3Nlc3QoJ2xpJyk7XG5cdFx0dmFyICRib3Bpc09wdGlvbmFsTWVzc2FnZSA9ICRib3Bpc0FkZFRvQ2FydExhYmVsLmZpbmQoJy5hZGQtdG8tY2FydC1vcHRpb25hbC1tZXNzYWdlJyk7XG5cdFx0aWYgKCRib3Bpc09wdGlvbmFsTWVzc2FnZS5sZW5ndGggPiAwKSB7XG5cdFx0XHRkYXRhQnVmZmVyWydPcHRpb25hbE1lc3NhZ2UnXSA9ICRib3Bpc09wdGlvbmFsTWVzc2FnZS5maXJzdCgpLmh0bWwoKS50cmltKCk7XG5cdFx0fVxuXHR9XG5cbiAgICBpZiAoJChldmVudC5jdXJyZW50VGFyZ2V0KS5oYXNDbGFzcygnYm9waXMnKSB8fCAoZGF0YSAmJiBkYXRhLmJvcGlzKSkge1xuICAgIFx0aXNCb3BpcyA9IHRydWU7XG4gICAgfSBlbHNlIGlmICgkYm9waXNBZGRUb0NhcnRPcHRpb25zLmxlbmd0aCA+IDApIHtcblx0XHR2YXIgYm9waXNTaGlwcGluZ09wdGlvbiA9ICRib3Bpc0FkZFRvQ2FydE9wdGlvbi52YWwoKTtcblx0XHRpZiAoYm9waXNTaGlwcGluZ09wdGlvbiA9PSAnZGVsaXZlcnknKSB7XG5cdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdCb3Bpcy5Mb2NhbERlbGl2ZXJ5LkRpc3BsYXknLCB7IE9wdGlvbmFsTWVzc2FnZTogZGF0YUJ1ZmZlclsnT3B0aW9uYWxNZXNzYWdlJ10gfSk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSBlbHNlIGlmIChib3Bpc1NoaXBwaW5nT3B0aW9uID09ICdzaGlwdG9zdG9yZXBpY2t1cCcpIHtcblx0XHRcdGlzQm9waXMgPSB0cnVlO1xuXHRcdFx0ZGF0YSA9IGRhdGEgfHwge307XG5cdFx0XHRkYXRhLmJvcGlzU3RvcmUgPSAkYm9waXNBZGRUb0NhcnRPcHRpb25zLmZpbmQoJy5zZWxlY3RlZC1zdG9yZVtzdG9yZS1pZF0nKS5hdHRyKCdzdG9yZS1pZCcpO1xuXHRcdFx0ZGF0YS5zaGlwcGluZ09wdGlvbiA9IGJvcGlzU2hpcHBpbmdPcHRpb247XG5cdFx0fSBlbHNlIGlmIChib3Bpc1NoaXBwaW5nT3B0aW9uID09ICdwaWNrdXAnKSB7XG5cdFx0XHRpc0JvcGlzID0gdHJ1ZTtcblx0XHRcdHZhciBzdG9yZURhdGE7XG5cdFx0XHR2YXIgJHN0b3JlRGF0YSA9ICRib3Bpc0FkZFRvQ2FydE9wdGlvbnMuZmluZCgnLnNlbGVjdGVkLXN0b3JlW3N0b3JlLWRhdGFdJyk7XG5cdFx0XHRpZiAoJHN0b3JlRGF0YS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHN0b3JlRGF0YSA9IEpTT04ucGFyc2UoJHN0b3JlRGF0YS5hdHRyKCdzdG9yZS1kYXRhJykpXG5cdFx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXHRcdFx0XHRkYXRhLmJvcGlzU3RvcmUgPSBzdG9yZURhdGEubG9jYXRpb24uY29kZTtcblx0XHRcdFx0ZGF0YS5xdWFudGl0eUF2YWlsYWJsZSA9IHN0b3JlRGF0YS5kZXRhaWwucXVhbnRpdHk7XG5cdFx0XHRcdGRhdGEuc2hpcHBpbmdPcHRpb24gPSBib3Bpc1NoaXBwaW5nT3B0aW9uO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG4gICAgdmFyICRib3Bpc1N0b3JlO1xuICAgIGlmIChpc0JvcGlzKSB7XG4gICAgXHQkYm9waXNTdG9yZSA9ICQoJ2lucHV0W25hbWU9XCJCb3Bpc19TdG9yZVNlYXJjaF9TdG9yZUlkXCJdOmNoZWNrZWQnKTtcblx0XHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfc3RvcmVcIl0nKS52YWwoZGF0YS5ib3Bpc1N0b3JlID8gZGF0YS5ib3Bpc1N0b3JlIDogJGJvcGlzU3RvcmUudmFsKCkpO1xuICAgIFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImJvcGlzX3F1YW50aXR5X2F2YWlsYWJsZVwiXScpLnZhbChkYXRhLnF1YW50aXR5QXZhaWxhYmxlICE9IHVuZGVmaW5lZCA/IGRhdGEucXVhbnRpdHlBdmFpbGFibGUgOiAkYm9waXNTdG9yZS5hdHRyKCdxdWFudGl0eS1hdmFpbGFibGUnKSk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfc2hpcHBpbmdfb3B0aW9uXCJdJykudmFsKGRhdGEuc2hpcHBpbmdPcHRpb24gPyBkYXRhLnNoaXBwaW5nT3B0aW9uIDogJycpO1xuICAgIFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImJvcGlzX2RlbGl2ZXJ5X2FkZHJlc3NcIl0nKS52YWwoZGF0YS5kZWxpdmVyeUFkZHJlc3MgPyBkYXRhLmRlbGl2ZXJ5QWRkcmVzcyA6ICcnKTtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19kZWxpdmVyeV9ub3RlXCJdJykudmFsKGRhdGEuZGVsaXZlcnlOb3RlID8gZGF0YS5kZWxpdmVyeU5vdGUgOiAnJyk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfZGVsaXZlcnlfZ2lmdF9tZXNzYWdlXCJdJykudmFsKGRhdGEuZ2lmdE1lc3NhZ2UgPyBkYXRhLmdpZnRNZXNzYWdlIDogJycpO1xuICAgIFx0JCgnLm9wdGlvbi1kcm9wZG93biBzZWxlY3RbbmFtZSo9XCJfQm9waXNcIl0nKS52YWwoJ1llcycpO1xuICAgIH0gZWxzZSB7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfc3RvcmVcIl0nKS52YWwoJycpO1xuICAgIFx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImJvcGlzX3F1YW50aXR5X2F2YWlsYWJsZVwiXScpLnZhbCgnJyk7XG4gICAgXHQkKCcucHJvZHVjdC1hZGQtdG8tY2FydCBpbnB1dFtuYW1lPVwiYm9waXNfc2hpcHBpbmdfb3B0aW9uXCJdJykudmFsKCcnKTtcbiAgICBcdCQoJy5wcm9kdWN0LWFkZC10by1jYXJ0IGlucHV0W25hbWU9XCJib3Bpc19kZWxpdmVyeV9hZGRyZXNzXCJdJykudmFsKCcnKTtcbiAgICBcdCQoJy5vcHRpb24tZHJvcGRvd24gc2VsZWN0W25hbWUqPVwiX0JvcGlzXCJdJykudmFsKCdObycpO1xuXHR9XG5cblx0JCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgaW5wdXRbbmFtZT1cImNoYW5uZWxcIl0nKS52YWwoZGF0YSAmJiBkYXRhLmNoYW5uZWwgPyBkYXRhLmNoYW5uZWwgOiAnJyk7XG5cdGlmIChkYXRhICYmICdjc3JmX3Rva2VuJyBpbiBkYXRhICYmIGRhdGEuY3NyZl90b2tlbikge1xuXHRcdCQoJyNjc3JmdG9rZW4nKS52YWwoZGF0YS5jc3JmX3Rva2VuKTtcblx0fVxuICAgIFxuICAgIGlmIChzaXplU2VsZWN0ZWQuaGFzQ2xhc3MoXCJ0ZW1wc2VsZWN0aW9uXCIpKSB7XG4gICAgXHRzaXplU2VsZWN0ZWQuYWRkQ2xhc3MoJ2VudGVyU2VsZWN0ZWQnKTtcbiAgICBcdHNpemVTZWxlY3RlZC50cmlnZ2VyKCdjbGljaycpO1xuICAgIFx0c2l6ZVNlbGVjdGVkLmZpbmQoJy5zd2F0Y2hhbmNob3InKS50cmlnZ2VyKCdjbGljaycpO1xuICAgIFx0c2V0VGltZW91dCggZnVuY3Rpb24oKXskKFwiI2FkZC10by1jYXJ0XCIpLmNsaWNrKCl9LCAxMDAgKTtcbiAgICBcdHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRhdGFMYXllciAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHR2YXIgcXR5ID0gJCgnLnB0X3Byb2R1Y3QtZGV0YWlscyAucGRwRm9ybSAucHJvZHVjdC1hZGQtdG8tY2FydCBzZWxlY3RbaWQ9UXVhbnRpdHldJykudmFsKCk7XG5cdFx0dmFyIHZhcmlhdGlvbkF0dHIgPSAkKCcucHJvZHVjdC12YXJpYXRpb25zJykuZGF0YSgnYXR0cmlidXRlcycpO1xuXHRcdHZhciBzaXplQXR0clZhbHVlID0gdmFyaWF0aW9uQXR0ci5zaXplLmRpc3BsYXlWYWx1ZTtcblx0XHRpZiAoc2l6ZUF0dHJWYWx1ZSA9PSAnJyB8fCBzaXplQXR0clZhbHVlID09IG51bGwgKSB7XG5cdFx0XHRpZiAoc2l6ZVNlbGVjdGVkLmhhc0NsYXNzKFwidGVtcHNlbGVjdGlvblwiKSAmJiBzaXplU2VsZWN0ZWQuZmluZCgnYS5zd2F0Y2hhbmNob3InKS5kYXRhKCkgIT0gbnVsbCApIHtcblx0XHRcdFx0c2l6ZVNlbGVjdGVkLmFkZENsYXNzKCdlbnRlclNlbGVjdGVkJyk7XG5cdFx0XHRcdHZhciBzaXplT2JqUmVmID0gc2l6ZVNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykuZGF0YSgpO1xuXHRcdFx0XHRzaXplQXR0clZhbHVlID0gc2l6ZU9ialJlZi5zaXplTmFtZTtcblx0XHRcdFx0c2l6ZVNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykudHJpZ2dlcignY2xpY2snKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdBZGRUb0NhcnQnKTtcblxuXHRcdGZvciAodmFyIGk9MDsgaSA8IGRhdGFMYXllci5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGRhdGFMYXllcltpXS5ldmVudCA9PSAncGRwRGlzcGxheScpIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkSXRlbSA9IGRhdGFMYXllcltpXS5lY29tbWVyY2UuZGV0YWlsLnByb2R1Y3RzWzBdO1xuXHRcdFx0XHR2YXIgaXRlbVByaWNlID0gKHNlbGVjdGVkSXRlbS5zaWxob3VldHRlID09ICdHaWZ0IENhcmQnKSA/ICBwYXJzZUludCgodmFyaWF0aW9uQXR0ci5zaXplLnZhbHVlKS5yZXBsYWNlKCckJywnJykpIDogc2VsZWN0ZWRJdGVtLnByaWNlO1xuXHRcdFx0XHR2YXIgc2t1SUQgPSAkKCcjcGlkJykudmFsKCk7XG5cdFx0XHRcdHZhciBpbWFnZSA9ICQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2NsYXNzKj1cIi1zbGlkZVwiXSAucHJpbWFyeS1pbWFnZS5maXJzdCcpLmZpbmQoJ2EnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdGlmICghaW1hZ2UgfHwgaW1hZ2UgPT0gdW5kZWZpbmVkIHx8IGltYWdlID09IG51bGwpIHtcblx0XHRcdFx0XHRpbWFnZSA9ICQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2NsYXNzKj1cIi1zbGlkZVwiXSAucHJpbWFyeS1pbWFnZS5maXJzdCcpLmZpbmQoJ2ltZycpLmF0dHIoJ3NyYycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5DT1JESUFMX0VOQUJMRUQpIHtcdFx0XHRcdFxuXHRcdFx0XHRcdHZhciBjYXJ0X2RhdGEgPSBbe1xuXHRcdFx0XHRcdCAgICAncHJvZHVjdElEJzogc2VsZWN0ZWRJdGVtLmlkLFxuXHRcdFx0XHRcdCAgICAnc2t1Jzogc2t1SUQsXG5cdFx0XHRcdFx0ICAgICdjYXRlZ29yeSc6IChzZWxlY3RlZEl0ZW0uY2F0ZWdvcnkpLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XHRcdFx0ICAgICduYW1lJzogKHNlbGVjdGVkSXRlbS5uYW1lKS5yZXBsYWNlKC9cXFxcL2csIFwiXCIpLFxuXHRcdFx0XHRcdCAgICAncXR5JzogcXR5LCBcblx0XHRcdFx0XHQgICAgJ2l0ZW1QcmljZSc6IGl0ZW1QcmljZSxcblx0XHRcdFx0XHQgICAgJ2ltYWdlJzogaW1hZ2UsXG5cdFx0XHRcdFx0ICAgICd1cmwnOiQobG9jYXRpb24pLmF0dHIoXCJocmVmXCIpLnNwbGl0KFwiP3V0bVwiKVswXS5zcGxpdChcIiN1dG1cIilbMF0uc3BsaXQoXCImdXRtXCIpWzBdLFxuXHRcdFx0XHRcdCAgICAnYXR0cic6IHtcblx0XHRcdFx0XHQgICAgICAgICdtYW51ZmFjdHVyZXInOiBzZWxlY3RlZEl0ZW0uYnJhbmQsXG5cdFx0XHRcdFx0ICAgIFx0J2NvbG9yJzogdmFyaWF0aW9uQXR0ci5jb2xvci5kaXNwbGF5VmFsdWUsXG5cdFx0XHRcdFx0ICAgICAgICAnc2l6ZSc6IHZhcmlhdGlvbkF0dHIuc2l6ZS5kaXNwbGF5VmFsdWVcblx0XHRcdFx0XHQgICAgfVxuXHRcdFx0XHRcdH1dO1xuXHRcblx0XHRcdFx0XHRpZiAodHlwZW9mIGNyZGwgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBjcmRsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0XHRjcmRsKFtcblx0XHRcdFx0XHRcdFx0WydjYXJ0JywgJ3VwZGF0ZSddLFxuXHRcdFx0XHRcdFx0XHRbJ2NhcnRpdGVtJywgJ2FkZCcgLCBjYXJ0X2RhdGFdLCBcblx0XHRcdFx0XHRcdFx0WydldmVudCcsICdjYXJ0J11cblx0XHRcdFx0XHRcdF0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0dmFyIGRhdGVUaW1lID0gTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCk7XG5cdFx0XHRcdHZhciBldmVudElEID0gJ2FkZHRvY2FydC0nICsgc2VsZWN0ZWRJdGVtLmlkICsgJy0nICsgZGF0ZVRpbWU7XG5cdFx0XHRcdFxuXHRcdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgU2l0ZVByZWZlcmVuY2VzLlBJTlRFUkVTVF9FTkFCTEVEKSB7XG5cdFx0XHRcdFx0cGludHJrKCd0cmFjaycsICdhZGR0b2NhcnQnLCB7XG5cdFx0XHRcdFx0XHRldmVudF9pZDogZXZlbnRJRCxcblx0XHRcdFx0XHRcdHZhbHVlOiBpdGVtUHJpY2UgKiBxdHksXG5cdFx0XHRcdFx0XHRvcmRlcl9xdWFudGl0eTogcXR5LFxuXHRcdFx0XHRcdFx0Y3VycmVuY3k6ICQoJ21ldGFbaXRlbXByb3A9XCJwcmljZUN1cnJlbmN5XCJdJykuYXR0cignY29udGVudCcpLFxuXHRcdFx0XHRcdFx0bGluZV9pdGVtczogW1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF9uYW1lOiAoc2VsZWN0ZWRJdGVtLm5hbWUpLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF9pZDogc2VsZWN0ZWRJdGVtLmlkLFxuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RfY2F0ZWdvcnk6IChzZWxlY3RlZEl0ZW0uY2F0ZWdvcnkpLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF92YXJpYW50X2lkOiBza3VJRCxcblx0XHRcdFx0XHRcdFx0XHRwcm9kdWN0X3ByaWNlOiBpdGVtUHJpY2UsXG5cdFx0XHRcdFx0XHRcdFx0cHJvZHVjdF9xdWFudGl0eTogcXR5LFxuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RfYnJhbmQ6IHNlbGVjdGVkSXRlbS5icmFuZFxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRdXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG4gICAgfVxuXG4gICAgYWRkSXRlbVRvQ2FydCgkZm9ybSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICBcdCQuYWpheCh7dXJsIDogVXJscy5jYXJ0SXRlbUNvdW50LCBtZXRob2Q6ICdQT1NUJywgZGF0YVR5cGU6ICdqc29uJywgc3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdGlmIChkYXRhICYmIGRhdGEuUHJvZHVjdENvdW50ICE9IHVuZGVmaW5lZCkge1xuICAgIFx0XHRcdCQoJy5idG4tbWluaWNhcnQgc3BhbicpLmh0bWwoTWF0aC5yb3VuZChkYXRhLlByb2R1Y3RDb3VudCkpO1xuXHRcdFx0fVxuICAgIFx0fX0pO1xuICAgICAgICB2YXIgJHV1aWQgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwidXVpZFwiXScpO1xuICAgICAgICBpZiAoJHV1aWQubGVuZ3RoID4gMCAmJiAkdXVpZC52YWwoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgfSBlbHNlIGlmKFNpdGVQcmVmZXJlbmNlcy5SRURJUkVDVF9UT19DQVJUICYmICghcGFnZUNvbnRleHQub3B0aW9ucyB8fCBwYWdlQ29udGV4dC5vcHRpb25zLlN0b3JlVUlWZXJzaW9uICE9ICcyMDI0UmVkZXNpZ24nKSl7XG4gICAgXHRcdHZhciByZWRpcmVjdFVybCA9IChTaXRlUHJlZmVyZW5jZXMuSElERV9CQVNLRVQpID8gVXJscy5vbmVQYWdlIDogVXJscy5jYXJ0U2hvdztcbiAgICBcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSByZWRpcmVjdFVybDtcbiAgICBcdH0gZWxzZSB7XG5cdFx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLkFERF9UT19DQVJUX01PREFMIHx8IChwYWdlQ29udGV4dC5vcHRpb25zICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicpKSB7XG5cdFx0XHRcdHZhciBxdHlBZGRlZCA9ICQoJy5wdF9wcm9kdWN0LWRldGFpbHMgLnBkcEZvcm0gLnByb2R1Y3QtYWRkLXRvLWNhcnQgc2VsZWN0W2lkPVF1YW50aXR5XScpLnZhbCgpO1xuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybDogVXJscy5hZGRUb0NhcnRNb2RhbERpc3BsYXksXG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0c3RvcmV1aXZlcnNpb246IHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA/IHBhZ2VDb250ZXh0Lm9wdGlvbnMuU3RvcmVVSVZlcnNpb24gOiBudWxsLFxuXHRcdFx0XHRcdFx0c2hpcHBpbmdvcHRpb246IGJvcGlzU2hpcHBpbmdPcHRpb25cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnaHRtbCcsXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24obW9kYWxDb250ZW50KSB7XG5cdFx0XHRcdFx0XHRpZiAobW9kYWxDb250ZW50Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0dmFyICRtb2RhbENvbnRlbnQgPSAkKG1vZGFsQ29udGVudCk7XG5cdFx0XHRcdFx0XHRcdHZhciAkcmVjc0NvbnRlbnQ7XG5cdFx0XHRcdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuXHRcdFx0XHRcdFx0XHRcdCRyZWNzQ29udGVudCA9ICQoJyNiZXN0X3NlbGxpbmdfcHJvZHVjdHMuYWNjb3JkaW9uLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zJykucmVtb3ZlQ2xhc3MoJ2FjY29yZGlvbicpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY3NDb250ZW50ID0gJCgnLnJlY29tbS1wcm9kLXBkcC1hMmMtc2xvdCAuYWNjb3JkaW9uLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zJykucmVtb3ZlQ2xhc3MoJ2FjY29yZGlvbicpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdCRyZWNzQ29udGVudCA9ICQoJy5tYWluIC5hY2NvcmRpb24ucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMnKS5yZW1vdmVDbGFzcygnYWNjb3JkaW9uJyk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0JHJlY3NDb250ZW50LmZpbmQoJy5hY2NvcmRpb24taGVhZCcpLnJlbW92ZUNsYXNzKCdhY2NvcmRpb24taGVhZCcpO1xuXHRcdFx0XHRcdFx0XHQkcmVjc0NvbnRlbnQuZmluZCgnLmFjY29yZGlvbi1ib2R5JykucmVtb3ZlQ2xhc3MoJ2FjY29yZGlvbi1ib2R5Jyk7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCRyZWNzQ29udGVudC5maW5kKCcuc2xpY2stbGlzdCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgJHJlY29tbWVuZGF0aW9uc0NvbnRlbnRIdG1sID0gJCgkcmVjc0NvbnRlbnRbMF0ub3V0ZXJIVE1MKTtcblx0XHRcdFx0XHRcdFx0XHR2YXIgJHJlY29tbWVuZGF0aW9uc1NsaWRlcyA9ICRyZWNvbW1lbmRhdGlvbnNDb250ZW50SHRtbC5maW5kKCcuc2xpZGUnKTtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmVjb21tZW5kYXRpb25zU2xpZGVzSHRtbCA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdCRyZWNvbW1lbmRhdGlvbnNTbGlkZXMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmVjb21tZW5kYXRpb25zU2xpZGVzSHRtbCArPSAkKHRoaXMpWzBdLm91dGVySFRNTDtcblx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHQkcmVjb21tZW5kYXRpb25zQ29udGVudEh0bWwuZmluZCgnLnNsaWRlcycpLmh0bWwocmVjb21tZW5kYXRpb25zU2xpZGVzSHRtbCk7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY29tbWVuZGF0aW9uc0NvbnRlbnRIdG1sLmZpbmQoJy5zbGlkZXMnKS5yZW1vdmVDbGFzcygnc2xpY2staW5pdGlhbGl6ZWQgc2xpY2stc2xpZGVyJyk7XG5cdFx0XHRcdFx0XHRcdFx0JHJlY29tbWVuZGF0aW9uc0NvbnRlbnRIdG1sLmZpbmQoJy5zbGlkZScpLnJlbW92ZUNsYXNzKCdzbGljay1zbGlkZSBzbGljay1jdXJyZW50IHNsaWNrLWFjdGl2ZSBzbGljay1jbG9uZWQnKS5jc3MoJ3dpZHRoJywgJycpO1xuXHRcdFx0XHRcdFx0XHRcdCRtb2RhbENvbnRlbnQuZmluZCgnLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zLWNvbnRhaW5lcicpLmh0bWwoJHJlY29tbWVuZGF0aW9uc0NvbnRlbnRIdG1sKTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmIChkYXRhQnVmZmVyWydPcHRpb25hbE1lc3NhZ2UnXSkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBvcHRpb25hbE1lc3NhZ2VIdG1sID0gJzxkaXYgY2xhc3M9XCJhZGQtdG8tY2FydC1tb2RhbC1vcHRpb25hbC1tZXNzYWdlXCI+JyArIGRhdGFCdWZmZXJbJ09wdGlvbmFsTWVzc2FnZSddICsgJzwvZGl2Pic7XG5cdFx0XHRcdFx0XHRcdFx0JG1vZGFsQ29udGVudC5maW5kKCcuYWRkZWQtbWVzc2FnZScpLmFwcGVuZChvcHRpb25hbE1lc3NhZ2VIdG1sKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHQkbW9kYWxDb250ZW50LmF0dHIoJ2JvcGlzLXNoaXBwaW5nLW9wdGlvbicsIGJvcGlzU2hpcHBpbmdPcHRpb24pO1xuXG5cdFx0XHRcdFx0XHRcdHZhciBzY3JvbGxUb3AgPSBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wO1xuXG5cdFx0XHRcdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHRcdFx0XHRodG1sOiAkbW9kYWxDb250ZW50LFxuXHRcdFx0XHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdFx0XHRcdGRpYWxvZ0NsYXNzOiAnYWRkLXRvLWNhcnQtbW9kYWwnLFxuXHRcdFx0XHRcdFx0XHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdFx0XHRcdFx0XHRcdHJlc2l6YWJsZTogZmFsc2UsXG5cdFx0XHRcdFx0XHRcdFx0XHR3aWR0aDogMTA5MCxcblx0XHRcdFx0XHRcdFx0XHRcdG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRkYXRhQnVmZmVyWyd3cmFwcGVyU2Nyb2xsVG9wJ10gPSBzY3JvbGxUb3A7XG4gICAgXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YUJ1ZmZlclsnd3JhcHBlck1hcmdpblRvcCddID0gJGNvbnRhaW5lci5jc3MoJ21hcmdpbi10b3AnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lci5hdHRyKCdidWZmZXItc2Nyb2xsVG9wJywgc2Nyb2xsVG9wKTtcblxuICAgIFx0XHRcdFx0XHRcdFx0XHRcdCRjb250YWluZXIuY3NzKCdtYXJnaW4tdG9wJywgcGFyc2VGbG9hdCgkY29udGFpbmVyLmNzcygnbWFyZ2luLXRvcCcpKSAtIHNjcm9sbFRvcCk7XG4gICAgXHRcdFx0XHRcdFx0XHRcdFx0ZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wID0gMDtcbiAgICBcdFx0XHRcdFx0XHRcdFx0XHQkaHRtbC5hZGRDbGFzcygnc2Nyb2xsLWxvY2snKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsJykud3JhcCgnPGRpdiBjbGFzcz1cImFkZC10by1jYXJ0LW1vZGFsLXdyYXBwZXJcIj48L2Rpdj4nKTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhZGQgd3JhcHBlciB0byBjbG9zZSBidXR0b24gXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykub2ZmKCdjbGljay5EaWFsb2cuQ2xvc2VCdXR0b25zJykub24oJ2NsaWNrLkRpYWxvZy5DbG9zZUJ1dHRvbnMnLCAnLnVpLWRpYWxvZy10aXRsZWJhci1jbG9zZSwgLmJ0bi5jb250aW51ZS1zaG9wcGluZycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y2xvc2VBZGRUb0NhcnRNb2RhbCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhZGQgJ3Nob3cnIGNsYXNzIHRvIG92ZXJsYXkgZm9yIG5pY2UgYW5pbWF0ZSBpblxuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgJG92ZXJsYXkgPSAkKCcuYWRkLXRvLWNhcnQtbW9kYWwtd3JhcHBlcicpLnBhcmVudCgpLmZpbmQoJy51aS13aWRnZXQtb3ZlcmxheScpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkb3ZlcmxheS5hZGRDbGFzcygnYWRkLXRvLWNhcnQtb3ZlcmxheScpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQkb3ZlcmxheS5hZGRDbGFzcygnc2hvdycpO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykub2ZmKCdjbGljay5EaWFsb2cuQ2xvc2UnKS5vbignY2xpY2suRGlhbG9nLkNsb3NlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBvbmx5IGNhbGwgdGhpcyBibG9jayBpZiB0aGUgdWktd2lkZ2V0IGJhY2tncm91bmQgaXMgY2xpY2tlZFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgnLmFkZC10by1jYXJ0LW1vZGFsJykubGVuZ3RoIDw9IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGNsb3NlQWRkVG9DYXJ0TW9kYWwoKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChwYXJzZUZsb2F0KCQoJy5hZGQtdG8tY2FydC1tb2RhbCcpLmNzcygndG9wJykpIDwgMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbCcpLmNzcygndG9wJywgJzAnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIG1vdmUgdGl0bGUgZnJvbSBtYWluIGNvbnRlbnQgdG8gdG9wIG9mIHRoZSBtb2RhbFxuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgJGFkZE1lc3NhZ2UgPSAkKCcuYWRkLXRvLWNhcnQtbW9kYWwtY29udGVudCAubWFpbi1jb250ZW50IC5hZGRlZC1tZXNzYWdlJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICgkYWRkTWVzc2FnZS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLWNvbnRlbnQnKS5wcmVwZW5kKCRhZGRNZXNzYWdlKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBmdWxmaWxsbWVudFR5cGUgPSAkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXInKS5maW5kKCdpbnB1dFtuYW1lPVwiQWRkVG9DYXJ0T3B0aW9uXCJdOmNoZWNrZWQnKS52YWwoKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgaXNCb3BpcyA9IGZ1bGZpbGxtZW50VHlwZSAmJiAoZnVsZmlsbG1lbnRUeXBlID09ICdzaGlwdG9zdG9yZXBpY2t1cCcgfHwgZnVsZmlsbG1lbnRUeXBlID09ICdwaWNrdXAnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgYm9waXNTdG9yZU5hbWUgPSAnJztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgYm9waXNTdG9yZUFkZHJlc3MgPSAnJztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoaXNCb3Bpcykge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ym9waXNTdG9yZU5hbWUgPSAkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1zdG9yZS1zZWxlY3RvciAuc2VsZWN0ZWQtc3RvcmUnKS5hdHRyKCdzdG9yZS1uYW1lJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRib3Bpc1N0b3JlQWRkcmVzcyA9ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLXN0b3JlLXNlbGVjdG9yIC5zZWxlY3RlZC1zdG9yZScpLmF0dHIoJ3N0b3JlLWFkZHJlc3MnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChib3Bpc1N0b3JlQWRkcmVzcyAmJiBib3Bpc1N0b3JlQWRkcmVzcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5tb2RhbC1taW5pLWNhcnQtc3RvcmUtbWVzc2FnZS1jb250YWluZXInKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5tb2RhbC1taW5pLWNhcnQtc3RvcmUtbWVzc2FnZS1jb250YWluZXInKS5maW5kKCcubW9kYWwtbWluaS1jYXJ0LXN0b3JlLWRldGFpbHMnKS5odG1sKCc8c3Ryb25nPicgK2JvcGlzU3RvcmVOYW1lKyAnPC9zdHJvbmc+PGJyIC8+JyArYm9waXNTdG9yZUFkZHJlc3MpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciAkY29udGFpbmVycyA9ICQoJy5hZGQtdG8tY2FydC1tb2RhbCcpLmZpbmQoJy5hY2NvcmRpb24sIC5zZWN0aW9uLW9mZmVycycpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoJGNvbnRhaW5lcnMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCRjb250YWluZXJzLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgJGNvbnRhaW5lciA9ICQodGhpcyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoJGNvbnRhaW5lci5maW5kKCcucHJvZHVjdC10aWxlJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgJGNvbnRhaW5lckhlYWRlciA9ICRjb250YWluZXIuZmluZCgnLmFjY29yZGlvbi1oZWFkIGg1LCAuc2VjdGlvbi1oZWFkIGgyJykuZmlyc3QoKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyICRjb250YWluZXJIZWFkZXJDaGVjayA9ICRjb250YWluZXJIZWFkZXIuZmluZCgnc3BhbicpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoJGNvbnRhaW5lckhlYWRlckNoZWNrLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQkY29udGFpbmVySGVhZGVyID0gJGNvbnRhaW5lckhlYWRlckNoZWNrO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoJGNvbnRhaW5lckhlYWRlci5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIGRhdGFPYmplY3QgPSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwcm9tb3Rpb25faWQ6ICdhZGR0b2NhcnRtb2RhbCcsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwcm9tb3Rpb25fbmFtZTogJ0FkZCB0byBDYXJ0IE1vZGFsJ1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKCdWaWV3UHJvbW90aW9uJywgZGF0YU9iamVjdCwgeyBDb250YWluZXI6ICRjb250YWluZXIgfSk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbC13cmFwcGVyJykuYWRkQ2xhc3MoJ3Nob3cnKTtcblx0XHRcdFx0XHRcdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0XHQgICAgICAgICAgICBcdHZhciAkaHRtbCA9ICQoJ2h0bWwnKTtcblx0XHRcdFx0XHRcdFx0XHQgICAgXHR2YXIgJGNvbnRhaW5lciA9ICQoJyN3cmFwcGVyJyk7XG5cblx0XHRcdFx0XHRcdFx0XHQgICAgXHQkaHRtbC5yZW1vdmVDbGFzcygnc2Nyb2xsLWxvY2snKTtcblxuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgXHRpZiAoZGF0YUJ1ZmZlclsnd3JhcHBlclNjcm9sbFRvcCddID4gMCkge1xuXHRcdFx0XHRcdFx0XHQgICAgXHRcdFx0ZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wID0gZGF0YUJ1ZmZlclsnd3JhcHBlclNjcm9sbFRvcCddO1xuXHRcdFx0XHRcdFx0XHQgICAgXHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lci5jc3MoJ21hcmdpbi10b3AnLCBwYXJzZUZsb2F0KGRhdGFCdWZmZXJbJ3dyYXBwZXJNYXJnaW5Ub3AnXSkpO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbCcpLnVud3JhcCgpO1xuXHRcdFx0XHRcdFx0ICAgICAgICAgICAgfVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsIC5hZGRlZC1tZXNzYWdlIC5jb3VudCcpLnRleHQoJ0l0ZW0nKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAkKCcuYmFubmVyLWNhcnQtaG9sZGVyIC5idG4tbWluaWNhcnQnKS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybCA6IFVybHMuY2FydE1pbmlDYXJ0LFxuXHRcdFx0XHRcdGRhdGEgOiB7ZGVza3RvcDogJzEnfSxcblx0XHRcdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHQkKCcuYmFubmVyLWNhcnQtaG9sZGVyIC5idG4tbWluaWNhcnQnKS5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdCQoJy5iYW5uZXItY2FydC1ob2xkZXInKS5hcHBlbmQoZGF0YSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR1cmwgOiBVcmxzLmNhcnRNaW5pQ2FydCxcblx0XHRcdFx0XHRkYXRhVHlwZTogJ2h0bWwnLFxuXHRcdFx0XHRcdHN1Y2Nlc3MgOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0XHR2YXIgcGFyZW50TWluaUNhcnQgPSAkKCcudG9wLWJhbm5lci1pbm5lci1saW5rcyAjbWluaS1jYXJ0Jyk7XG5cdFx0XHRcdFx0XHRpZiAocGFyZW50TWluaUNhcnQubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHQkKCcudG9wLWJhbm5lci1pbm5lci1saW5rcyAjbWluaS1jYXJ0IGEubWluaS1jYXJ0LWxpbmsnKS5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdFx0cGFyZW50TWluaUNhcnQuYXBwZW5kKGRhdGEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHQvLyBkbyBub3QgY2xvc2UgcXVpY2t2aWV3IGlmIGFkZGluZyBpbmRpdmlkdWFsIGl0ZW0gdGhhdCBpcyBwYXJ0IG9mIHByb2R1Y3Qgc2V0XG5cdFx0XHQvLyBAVE9ETyBzaG91bGQgbm90aWZ5IHRoZSB1c2VyIHNvbWUgb3RoZXIgd2F5IHRoYXQgdGhlIGFkZCBhY3Rpb24gaGFzIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHlcblx0XHRcdGlmICghJCh0aGlzKS5oYXNDbGFzcygnc3ViLXByb2R1Y3QtaXRlbScpKSB7XG5cdFx0XHRcdGRpYWxvZy5jbG9zZSgpO1xuXHRcdFx0fVxuXHRcdFx0aWYoU2l0ZVByZWZlcmVuY2VzLkFERF9UT19DQVJUX01PREFMICE9IHRydWUpe1xuXHRcdFx0XHRtaW5pY2FydC5zaG93KHJlc3BvbnNlKTtcblx0XHRcdH1cbiAgICAgICAgfVxuICAgIH0uYmluZCh0aGlzKSk7XG5cbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgdG8gaGFuZGxlIHRoZSBhZGQgYWxsIGl0ZW1zIHRvIGNhcnQgZXZlbnRcbiAqL1xudmFyIGFkZEFsbFRvQ2FydCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciAkcHJvZHVjdEZvcm1zID0gJCgnI3Byb2R1Y3Qtc2V0LWxpc3QnKS5maW5kKCdmb3JtJykudG9BcnJheSgpO1xuICAgIFRQcm9taXNlLmFsbChfLm1hcCgkcHJvZHVjdEZvcm1zLCBhZGRJdGVtVG9DYXJ0KSlcbiAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlcykge1xuICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICAvLyBzaG93IHRoZSBmaW5hbCByZXNwb25zZSBvbmx5LCB3aGljaCB3b3VsZCBpbmNsdWRlIGFsbCB0aGUgb3RoZXIgaXRlbXNcbiAgICAgICAgICAgIG1pbmljYXJ0LnNob3cocmVzcG9uc2VzW3Jlc3BvbnNlcy5sZW5ndGggLSAxXSk7XG4gICAgICAgIH0pO1xufTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBCaW5kcyB0aGUgY2xpY2sgZXZlbnQgdG8gYSBnaXZlbiB0YXJnZXQgZm9yIHRoZSBhZGQtdG8tY2FydCBoYW5kbGluZ1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcuYWRkLXRvLWNhcnRbZGlzYWJsZWRdJykuYXR0cigndGl0bGUnLCAkKCcuYXZhaWxhYmlsaXR5LW1zZycpLnRleHQoKSk7XG4gICAgJCgnLnByb2R1Y3QtZGV0YWlsJykub24oJ2NsaWNrJywgJy5hZGQtdG8tY2FydDpub3QoW2Rpc2FibGVkXSk6bm90KFtsb2FkaW5nXSknLCBhZGRUb0NhcnQpO1xuXHQkKGRvY3VtZW50KS5vbignUHJvZHVjdERldGFpbFBhZ2UuQm9waXMuQWRkSXRlbVRvQ2FydCcsIGFkZEl0ZW1Ub0NhcnQpO1xuICAgICQoZG9jdW1lbnQpLm9uKCdQcm9kdWN0RGV0YWlsUGFnZS5Cb3Bpcy5BZGRUb0NhcnQnLCBhZGRUb0NhcnQpO1xuXHQkKCcjYWRkLWFsbC10by1jYXJ0Jykub24oJ2NsaWNrJywgYWRkQWxsVG9DYXJ0KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gIHJlcXVpcmUoJy4uLy4uL2FqYXgnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG52YXIgdXBkYXRlQ29udGFpbmVyID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgJGF2YWlsYWJpbGl0eU1zZyA9ICQoJyNwZHBNYWluIC5hdmFpbGFiaWxpdHkgLmF2YWlsYWJpbGl0eS1tc2cnKTtcbiAgICB2YXIgbWVzc2FnZTsgLy8gdGhpcyBzaG91bGQgYmUgbGV4aWNhbGx5IHNjb3BlZCwgd2hlbiBgbGV0YCBpcyBzdXBwb3J0ZWQgKEVTNilcbiAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5odG1sKFJlc291cmNlcy5JVEVNX1NUQVRVU19OT1RBVkFJTEFCTEUpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgICRhdmFpbGFiaWxpdHlNc2cuZW1wdHkoKTtcbiAgICAvLyBMb29rIHRocm91Z2ggbGV2ZWxzIC4uLiBpZiBtc2cgaXMgbm90IGVtcHR5LCB0aGVuIGNyZWF0ZSBzcGFuIGVsXG4gICAgaWYgKGRhdGEubGV2ZWxzLklOX1NUT0NLID4gMCkge1xuICAgICAgICBpZiAoZGF0YS5sZXZlbHMuUFJFT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuQkFDS09SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLk5PVF9BVkFJTEFCTEUgPT09IDApIHtcbiAgICAgICAgICAgIC8vIEp1c3QgaW4gc3RvY2tcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBSZXNvdXJjZXMuSU5fU1RPQ0s7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJbiBzdG9jayB3aXRoIGNvbmRpdGlvbnMgLi4uXG4gICAgICAgICAgICBtZXNzYWdlID0gZGF0YS5pblN0b2NrTXNnO1xuICAgICAgICB9XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuYXBwZW5kKCc8cCBjbGFzcz1cImluLXN0b2NrLW1zZ1wiPicgKyBtZXNzYWdlICsgJzwvcD4nKTtcbiAgICB9XG4gICAgaWYgKGRhdGEubGV2ZWxzLlBSRU9SREVSID4gMCkge1xuICAgICAgICBpZiAoZGF0YS5sZXZlbHMuSU5fU1RPQ0sgPT09IDAgJiYgZGF0YS5sZXZlbHMuQkFDS09SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLk5PVF9BVkFJTEFCTEUgPT09IDApIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBSZXNvdXJjZXMuUFJFT1JERVI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gZGF0YS5wcmVPcmRlck1zZztcbiAgICAgICAgfVxuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmFwcGVuZCgnPHAgY2xhc3M9XCJwcmVvcmRlci1tc2dcIj4nICsgbWVzc2FnZSArICc8L3A+Jyk7XG4gICAgfVxuICAgIGlmIChkYXRhLmxldmVscy5CQUNLT1JERVIgPiAwKSB7XG4gICAgICAgIGlmIChkYXRhLmxldmVscy5JTl9TVE9DSyA9PT0gMCAmJiBkYXRhLmxldmVscy5QUkVPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5OT1RfQVZBSUxBQkxFID09PSAwKSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gUmVzb3VyY2VzLkJBQ0tPUkRFUjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBkYXRhLmJhY2tPcmRlck1zZztcbiAgICAgICAgfVxuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmFwcGVuZCgnPHAgY2xhc3M9XCJiYWNrb3JkZXItbXNnXCI+JyArIG1lc3NhZ2UgKyAnPC9wPicpO1xuICAgIH1cbiAgICBpZiAoZGF0YS5pblN0b2NrRGF0ZSAhPT0gJycpIHtcbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5hcHBlbmQoJzxwIGNsYXNzPVwiaW4tc3RvY2stZGF0ZS1tc2dcIj4nICsgU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuSU5fU1RPQ0tfREFURSwgZGF0YS5pblN0b2NrRGF0ZSkgKyAnPC9wPicpO1xuICAgIH1cbiAgICBpZiAoZGF0YS5sZXZlbHMuTk9UX0FWQUlMQUJMRSA+IDApIHtcbiAgICAgICAgaWYgKGRhdGEubGV2ZWxzLlBSRU9SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLkJBQ0tPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5JTl9TVE9DSyA9PT0gMCkge1xuICAgICAgICAgICAgbWVzc2FnZSA9IFJlc291cmNlcy5OT1RfQVZBSUxBQkxFO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWVzc2FnZSA9IFJlc291cmNlcy5SRU1BSU5fTk9UX0FWQUlMQUJMRTtcbiAgICAgICAgfVxuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmFwcGVuZCgnPHAgY2xhc3M9XCJub3QtYXZhaWxhYmxlLW1zZ1wiPicgKyBtZXNzYWdlICsgJzwvcD4nKTtcbiAgICB9XG59O1xuXG52YXIgZ2V0QXZhaWxhYmlsaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmdldEF2YWlsYWJpbGl0eSwge1xuICAgICAgICAgICAgcGlkOiAkKCcjcGlkJykudmFsKCksXG4gICAgICAgICAgICBRdWFudGl0eTogJCh0aGlzKS52YWwoKVxuICAgICAgICB9KSxcbiAgICAgICAgLy9jYWxsYmFjazogdXBkYXRlQ29udGFpbmVyXG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcjcGRwTWFpbicpLm9uKCdjaGFuZ2UnLCAnLnBkcEZvcm0gaW5wdXRbbmFtZT1cIlF1YW50aXR5XCJdJywgZ2V0QXZhaWxhYmlsaXR5KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vZGlhbG9nJyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbnZhciB6b29tTWVkaWFRdWVyeSA9IG1hdGNoTWVkaWEoJyhtaW4td2lkdGg6IDk2MHB4KScpO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbmFibGVzIHRoZSB6b29tIHZpZXdlciBvbiB0aGUgcHJvZHVjdCBkZXRhaWwgcGFnZVxuICogQHBhcmFtIHptcSB7TWVkaWEgUXVlcnkgTGlzdH1cbiAqL1xudmFyIGxvYWRab29tID0gZnVuY3Rpb24gKHptcSkge1xuICAgIHZhciAkaW1nWm9vbSA9ICQoJyNwZHBNYWluIC5tYWluLWltYWdlJyksXG4gICAgICAgIGhpcmVzVXJsO1xuICAgIGlmICghem1xKSB7XG4gICAgICAgIHptcSA9IHpvb21NZWRpYVF1ZXJ5O1xuICAgIH1cbiAgICBpZiAoJGltZ1pvb20ubGVuZ3RoID09PSAwIHx8IGRpYWxvZy5pc0FjdGl2ZSgpIHx8IHV0aWwuaXNNb2JpbGUoKSB8fCAhem9vbU1lZGlhUXVlcnkubWF0Y2hlcykge1xuICAgICAgICAvLyByZW1vdmUgem9vbVxuICAgICAgICAkaW1nWm9vbS50cmlnZ2VyKCd6b29tLmRlc3Ryb3knKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBoaXJlc1VybCA9ICRpbWdab29tLmF0dHIoJ2hyZWYnKTtcblxuICAgIGlmIChoaXJlc1VybCAmJiBoaXJlc1VybCAhPT0gJ251bGwnICYmIGhpcmVzVXJsLmluZGV4T2YoJ25vaW1hZ2VsYXJnZScpID09PSAtMSAmJiB6b29tTWVkaWFRdWVyeS5tYXRjaGVzKSB7XG4gICAgICAgICRpbWdab29tLnpvb20oe1xuICAgICAgICAgICAgdXJsOiBoaXJlc1VybFxuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG56b29tTWVkaWFRdWVyeS5hZGRMaXN0ZW5lcihsb2FkWm9vbSk7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1haW4gaW1hZ2UgYXR0cmlidXRlcyBhbmQgdGhlIGhyZWYgZm9yIHRoZSBzdXJyb3VuZGluZyA8YT4gdGFnXG4gKiBAcGFyYW0ge09iamVjdH0gYXR0cyBPYmplY3Qgd2l0aCB1cmwsIGFsdCwgdGl0bGUgYW5kIGhpcmVzIHByb3BlcnRpZXNcbiAqL1xudmFyIHNldE1haW5JbWFnZSA9IGZ1bmN0aW9uIChhdHRzKSB7XG4gICAgJCgnI3BkcE1haW4gLnByaW1hcnktaW1hZ2UnKS5hdHRyKHtcbiAgICAgICAgc3JjOiBhdHRzLnVybCxcbiAgICAgICAgYWx0OiBhdHRzLmFsdCxcbiAgICAgICAgdGl0bGU6IGF0dHMudGl0bGVcbiAgICB9KTtcbiAgICBpZiAoIWRpYWxvZy5pc0FjdGl2ZSgpICYmICF1dGlsLmlzTW9iaWxlKCkpIHtcbiAgICAgICAgJCgnI3BkcE1haW4gLm1haW4taW1hZ2UnKS5hdHRyKCdocmVmJywgYXR0cy5oaXJlcyk7XG4gICAgfVxuICAgIGxvYWRab29tKCk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXBsYWNlcyB0aGUgaW1hZ2VzIGluIHRoZSBpbWFnZSBjb250YWluZXIsIGZvciBlZy4gd2hlbiBhIGRpZmZlcmVudCBjb2xvciB3YXMgY2xpY2tlZC5cbiAqL1xuXG52YXIgcmVwbGFjZUltYWdlcyA9IGZ1bmN0aW9uICgpIHtcblx0XG4gICAgdmFyICRuZXdJbWFnZXMgPSAkKCcjdXBkYXRlLWltYWdlcycpLFxuICAgICAgICAkd2luID0gJCh3aW5kb3cpLFxuICAgICAgICAkaW1hZ2VDb250YWluZXIsXG4gICAgICAgICRoZWFkZXIsXG4gICAgICAgICRwcm9tb3NDbG9uZSxcbiAgICAgICAgJHByb21vc0Nsb25lTW9iaWxlLFxuICAgICAgICBuZXdJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgIFxuICAgIGlmICgkd2luLndpZHRoKCkgPD0gMTAyNCkge1xuICAgIFx0JGhlYWRlciA9ICAkKCcjcGRwTWFpbiAucHJvZHVjdC1pbWFnZS1jb250YWluZXInKS5maW5kKCdoZWFkZXInKS5jbG9uZSgpO1xuICAgIH1cbiAgICBpZiAoJG5ld0ltYWdlcy5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG5cbiAgICAvLyBwcm9kdWN0IGNvbnRhaW5lciBjbGFzc2VzIHRvIGhhbmRsZSBzdHlsZXMgd2hpbGUgaW1hZ2UgaXMgbG9hZGluZ1xuICAgICQoJyNwZHBNYWluIC5wcm9kdWN0LWltYWdlLWNvbnRhaW5lcicpLmFkZENsYXNzKCdsb2FkaW5nLWltYWdlJyk7XG4gICAgbmV3SW1hZ2Uuc3JjID0gJG5ld0ltYWdlcy5maW5kKCcucHJvZHVjdC1wcmltYXJ5LWltYWdlIFtjbGFzcyo9XCJzbGlkZVwiXScpLmZpcnN0KCkuZmluZCgnaW1nJykuYXR0cignc3JjJyk7XG4gICAgbmV3SW1hZ2Uub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICQoJyNwZHBNYWluIC5wcm9kdWN0LWltYWdlLWNvbnRhaW5lcicpLnJlbW92ZUNsYXNzKCdsb2FkaW5nLWltYWdlJyk7XG4gICAgfVxuICAgIFxuICAgIHZhciBhdHRhY2hQcm9tb3NNb2JpbGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTIHx8IHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG4gICAgICAgICAgICB2YXIgJGltYWdlQ29udGFpbmVyTW9iaWxlID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgJGltYWdlQ29udGFpbmVyTW9iaWxlID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyLW1vYmlsZScpO1xuICAgICAgICB9XG4gICAgICAgIHZhciAkcHJvbW9NZXNzYWdlc01vYmlsZSA9ICQoJyNwZHBNYWluIC5wcm9kdWN0LWltYWdlLWNvbnRhaW5lci1tb2JpbGUgLnByb21vLW1lc3NhZ2VzJyksXG4gICAgICAgICAgICAkcHJvbW9zQ2xvbmVNb2JpbGUgPSAkcHJvbW9NZXNzYWdlc01vYmlsZS5maW5kKCcucHJvbW8tbWVzc2FnZXMnKS5jbG9uZSgpO1xuICAgICAgICBcbiAgICAgICAgaWYgKCRwcm9tb01lc3NhZ2VzTW9iaWxlLmlzKCc6ZW1wdHknKSAmJiAkcHJvbW9zQ2xvbmVNb2JpbGUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGltYWdlQ29udGFpbmVyTW9iaWxlLmh0bWwoJG5ld0ltYWdlcy5odG1sKCkpO1xuICAgICAgICAgICAgJChcIjxkaXYgY2xhc3M9J3Byb21vLW1lc3NhZ2VzJz48L2Rpdj5cIikucHJlcGVuZFRvKCRpbWFnZUNvbnRhaW5lck1vYmlsZSk7XG4gICAgICAgICAgICAkcHJvbW9zQ2xvbmVNb2JpbGUucHJlcGVuZFRvKCRwcm9tb01lc3NhZ2VzTW9iaWxlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICRpbWFnZUNvbnRhaW5lck1vYmlsZS5odG1sKCRuZXdJbWFnZXMuaHRtbCgpKTtcbiAgICAgICAgICAgICRwcm9tb3NDbG9uZU1vYmlsZS5wcmVwZW5kVG8oJGltYWdlQ29udGFpbmVyTW9iaWxlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgYXR0YWNoUHJvbW9zRGVza3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgJGltYWdlQ29udGFpbmVyID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtaW1hZ2UtY29udGFpbmVyJyksXG4gICAgICAgICAgICAkcHJvbW9NZXNzYWdlcyA9ICQoJyNwZHBNYWluIC5wcm9kdWN0LWltYWdlLWNvbnRhaW5lciAucHJvbW8tbWVzc2FnZXMnKSxcbiAgICAgICAgICAgICRwcm9tb3NDbG9uZSA9ICRwcm9tb01lc3NhZ2VzLmNsb25lKCk7XG4gICAgICAgIFxuICAgICAgICAvL3dpbmRvdy5jb25zb2xlLmxvZyhcIiRwcm9tb01lc3NhZ2VzOiBcIiwkcHJvbW9NZXNzYWdlcy5sZW5ndGgsIFwiICRwcm9tb3NDbG9uZS5sZW5ndGg6IFwiLCAkcHJvbW9zQ2xvbmUubGVuZ3RoKTtcbiAgICAgICAgXG4gICAgICAgIGlmICgkcHJvbW9NZXNzYWdlcy5pcygnOmVtcHR5JykgJiYgJHByb21vc0Nsb25lLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRpbWFnZUNvbnRhaW5lci5odG1sKCRuZXdJbWFnZXMuaHRtbCgpKTtcbiAgICAgICAgICAgICQoXCI8ZGl2IGNsYXNzPSdwcm9tby1tZXNzYWdlcyc+PC9kaXY+XCIpLnByZXBlbmRUbygkaW1hZ2VDb250YWluZXIpO1xuICAgICAgICAgICAgJHByb21vc0Nsb25lLnByZXBlbmRUbygkcHJvbW9NZXNzYWdlcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAkaW1hZ2VDb250YWluZXIuaHRtbCgkbmV3SW1hZ2VzLmh0bWwoKSk7XG4gICAgICAgICAgICAkcHJvbW9zQ2xvbmUucHJlcGVuZFRvKCRpbWFnZUNvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKCR3aW4ud2lkdGgoKSA8PSA3NjcgKSB7XG4gICAgICAgIGF0dGFjaFByb21vc01vYmlsZSgpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYXR0YWNoUHJvbW9zRGVza3RvcCgpO1xuICAgIH1cbiAgICBcbiAgICAkbmV3SW1hZ2VzLnJlbW92ZSgpO1xuICAgIGxvYWRab29tKCk7XG59O1xuXG4vKiBAbW9kdWxlIGltYWdlXG4gKiBAZGVzY3JpcHRpb24gdGhpcyBtb2R1bGUgaGFuZGxlcyB0aGUgcHJpbWFyeSBpbWFnZSB2aWV3ZXIgb24gUERQXG4gKiovXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIGJ5IGRlZmF1bHQsIHRoaXMgZnVuY3Rpb24gc2V0cyB1cCB6b29tIGFuZCBldmVudCBoYW5kbGVyIGZvciB0aHVtYm5haWwgY2xpY2tcbiAqKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmIChkaWFsb2cuaXNBY3RpdmUoKSB8fCB1dGlsLmlzTW9iaWxlKCkpIHtcbiAgICAgICAgJCgnI3BkcE1haW4gLm1haW4taW1hZ2UnKS5yZW1vdmVBdHRyKCdocmVmJyk7XG4gICAgfVxuICAgIGxvYWRab29tKCk7XG4gICAgLy8gaGFuZGxlIHByb2R1Y3QgdGh1bWJuYWlsIGNsaWNrIGV2ZW50XG4gICAgJCgnI3BkcE1haW4nKS5vbignY2xpY2snLCAnLnByb2R1Y3R0aHVtYm5haWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHN3aXRjaCBpbmRpY2F0b3JcbiAgICAgICAgJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC10aHVtYm5haWxzJykuZmluZCgnLnRodW1iLnNlbGVjdGVkJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICQodGhpcykuY2xvc2VzdCgnLnRodW1iJykuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cbiAgICAgICAgc2V0TWFpbkltYWdlKCQodGhpcykuZGF0YSgnbGdpbWcnKSk7XG4gICAgfSk7XG59O1xubW9kdWxlLmV4cG9ydHMubG9hZFpvb20gPSBsb2FkWm9vbTtcbm1vZHVsZS5leHBvcnRzLnNldE1haW5JbWFnZSA9IHNldE1haW5JbWFnZTtcbm1vZHVsZS5leHBvcnRzLnJlcGxhY2VJbWFnZXMgPSByZXBsYWNlSW1hZ2VzO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vZGlhbG9nJyk7XG52YXIgcHJvZHVjdFN0b3JlSW52ZW50b3J5ID0gcmVxdWlyZSgnLi4vLi4vc3RvcmVpbnZlbnRvcnkvcHJvZHVjdCcpO1xudmFyIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBhZGRUb0NhcnQgPSByZXF1aXJlKCcuL2FkZFRvQ2FydCcpO1xudmFyIGF2YWlsYWJpbGl0eSA9IHJlcXVpcmUoJy4vYXZhaWxhYmlsaXR5Jyk7XG52YXIgaW1hZ2UgPSByZXF1aXJlKCcuL2ltYWdlJyk7XG52YXIgdmlkZW8gPSByZXF1aXJlKCcuL3ZpZGVvJyk7XG52YXIgcHJvZHVjdFNldCA9IHJlcXVpcmUoJy4vcHJvZHVjdFNldCcpO1xudmFyIHZhcmlhbnQgPSByZXF1aXJlKCcuL3ZhcmlhbnQnKTtcbnZhciByZXF1ZXN0R2lmdCA9IHJlcXVpcmUoJy4vcmVxdWVzdEdpZnQnKTtcbnZhciByZWNhcHRjaGEgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL1JlY2FwdGNoYScpO1xudmFyIHJlY2VudGx5Vmlld2VkUHJvZHVjdHMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL1JlY2VudGx5Vmlld2VkUHJvZHVjdHMnKTtcbnZhciByZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL1JlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucycpO1xudmFyIHNhbWVEYXlTaGlwcGluZ0NvdW50ZG93biA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvU2FtZURheVNoaXBwaW5nQ291bnRkb3duJyk7XG52YXIgU2hvcFBheSA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2ludF9zaG9wcGF5X3NmcmEvY2FydHJpZGdlL2NsaWVudC9kZWZhdWx0L2pzL2NhcnQvaW5pdFNob3BQYXlDYXJ0Jyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgb3B0aW9ucyA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xudmFyIGRhdGFCdWZmZXIgPSB7fTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZSBwcm9kdWN0IGRldGFpbCBwYWdlIHdpdGggcmV2aWV3cywgcmVjb21tZW5kYXRpb24gYW5kIHByb2R1Y3QgbmF2aWdhdGlvbi5cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZURvbShvcHRpb25zKSB7XG5cdHRvb2x0aXAuaW5pdCgpO1xuXG5cdHZhciAkc2FtZURheVNoaXBwaW5nQ291bnRkb3duQ29udGFpbmVyID0gJCgnLnNhbWUtZGF5LXNoaXBwaW5nLWNvdW50ZG93bicpO1xuXHRpZiAoJHNhbWVEYXlTaGlwcGluZ0NvdW50ZG93bkNvbnRhaW5lci5sZW5ndGggPiAwICYmICghb3B0aW9ucyB8fCBvcHRpb25zLkNoYW5uZWwgIT0gJ0Jvb3RCYXJuRXhwcmVzcycpKSB7XG5cdFx0c2FtZURheVNoaXBwaW5nQ291bnRkb3duLmluaXRpYWxpemUoJHNhbWVEYXlTaGlwcGluZ0NvdW50ZG93bkNvbnRhaW5lciwgb3B0aW9ucy5TYW1lRGF5U2hpcHBpbmcpO1xuXHR9XG5cblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgd2luZG93LmlubmVyV2lkdGggPiA3NjgpIHtcblx0XHQkKGRvY3VtZW50KS5maW5kKCcuYWNjb3JkaW9uLWhlYWQnKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0JChkb2N1bWVudCkuZmluZCgnLmFjY29yZGlvbi1ib2R5JykuY3NzKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG5cdH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZSBldmVudCBoYW5kbGVycyBvbiBwcm9kdWN0IGRldGFpbCBwYWdlXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMob3B0aW9ucykge1xuICAgIHZhciAkcGRwTWFpbiA9ICQoJyNwZHBNYWluJyk7XG5cbiAgICBhZGRUb0NhcnQoKTtcbiAgICBhdmFpbGFiaWxpdHkoKTtcbiAgICBpbWFnZSgpO1xuICAgIHZpZGVvKCk7XG4gICAgcHJvZHVjdFNldCgpO1xuICAgIHJlcXVlc3RHaWZ0KHsgUmVjYXB0Y2hhOiBvcHRpb25zLlJlY2FwdGNoYSB9KTtcblxuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuU1RPUkVfUElDS1VQKSB7XG4gICAgICAgIHByb2R1Y3RTdG9yZUludmVudG9yeS5pbml0KCk7XG4gICAgfVxuXG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcucHJvZHVjdC1zd2F0Y2hlcy1hY2NvcmRpb24tYnV0dG9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGFjY29yZGlvbiA9ICQodGhpcykuY2xvc2VzdCgnLmFjY29yZGlvbicpO1xuXG4gICAgICAgIGlmICgkYWNjb3JkaW9uLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRhY2NvcmRpb24udG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgdG8gV2lzaGxpc3QgYW5kIEFkZCB0byBHaWZ0IFJlZ2lzdHJ5IGxpbmtzIGJlaGF2aW9yc1xuICAgICRwZHBNYWluLm9uKCdjbGljaycsICdbZGF0YS1hY3Rpb249XCJnaWZ0LXJlZ2lzdHJ5XCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGF0YSA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMoJCgnLnBkcEZvcm0nKS5zZXJpYWxpemUoKSk7XG4gICAgICAgIGlmIChkYXRhLmNhcnRBY3Rpb24pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBkYXRhLmNhcnRBY3Rpb247XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwodGhpcy5ocmVmLCBkYXRhKTtcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2hyZWYnLCB1cmwpO1xuICAgIH0pO1xuXG4gICAgLy8gcHJvZHVjdCBvcHRpb25zXG4gICAgJHBkcE1haW4ub24oJ2NoYW5nZScsICcucHJvZHVjdC1vcHRpb25zIHNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNhbGVzUHJpY2UgPSAkcGRwTWFpbi5maW5kKCcucHJvZHVjdC1hZGQtdG8tY2FydCAucHJpY2Utc2FsZXMnKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkSXRlbSA9ICQodGhpcykuY2hpbGRyZW4oKS5maWx0ZXIoJzpzZWxlY3RlZCcpLmZpcnN0KCk7XG4gICAgICAgIHNhbGVzUHJpY2UudGV4dChzZWxlY3RlZEl0ZW0uZGF0YSgnY29tYmluZWQnKSk7XG4gICAgfSk7XG5cbiAgICAvLyBwcmV2ZW50IGRlZmF1bHQgYmVoYXZpb3Igb2YgdGh1bWJuYWlsIGxpbmsgYW5kIGFkZCB0aGlzIEJ1dHRvblxuICAgICRwZHBNYWluLm9uKCdjbGljaycsICcudGh1bWJuYWlsLWxpbmssIC51bnNlbGVjdGFibGUgYScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9KTtcblxuICAgICRwZHBNYWluLm9uKCdjbGljaycsICdhLnNpemUtY2hhcnQtbGluaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdXJsOiAkKGUudGFyZ2V0KS5hdHRyKCdocmVmJylcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBUZWNobm9sb2d5IEZlYXR1cmVzIFRvb2x0aXBcbiAgICAvLyAkKCcubGlzdC1wcm9kdWN0LWluZm8gZmlndXJlIGltZycpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgLy8gXHR2YXIgJGltZyA9ICQodGhpcyksXG4gICAgLy8gXHRcdCR0YXJnZXQgPSAkaW1nLnBhcmVudHMoJ2xpJykuZmlyc3QoKS5maW5kKCcudG9vbHRpcC1jb250ZW50IGltZycpO1xuXG4gICAgLy8gXHQkdGFyZ2V0LmF0dHIoXCJzcmNcIiwgJGltZy5kYXRhKCdob3ZlcicpKS5hdHRyKFwiYWx0XCIsICRpbWcuYXR0cihcImFsdFwiKSkuYXR0cihcIndpZHRoXCIsIFwiMjM2cHhcIik7XG4gICAgLy8gfSk7XG5cbiAgICAvLyAkKCcubGlzdC1wcm9kdWN0LWluZm8nKS50b29sdGlwKHtcbiAgICAvLyAgICAgaXRlbXM6ICdsaScsXG4gICAgLy8gICAgIHRvb2x0aXBDbGFzczogJ3RlY2hmZWF0dXJlLXRvb2x0aXAnLFxuICAgIC8vICAgICB0cmFjazogdHJ1ZSxcbiAgICAvLyAgICAgY29udGVudDogZnVuY3Rpb24gKCkge1xuICAgIC8vICAgICAgICAgcmV0dXJuICQodGhpcykuZmluZCgnLnRvb2x0aXAtY29udGVudCcpLmh0bWwoKTtcbiAgICAvLyAgICAgfVxuICAgIC8vIH0pO1xuXG5cblx0JChkb2N1bWVudCkub24oJ2NsaWNrJywnLnNlYXJjaGFnYWluLWJ0bicsZnVuY3Rpb24oKSB7XG5cdFx0JCgnI2RpYWxvZy1jb250YWluZXIgLmZpbmRTdG9yZS1yZXN1bHQnKS5oaWRlKCk7XG5cdFx0JCgnI2RpYWxvZy1jb250YWluZXIgLnVpLWRpYWxvZy1mb290ZXInKS5zaG93KCk7XG5cdFx0JCgnLnVpLWRpYWxvZycpLmNzcyh7J2hlaWdodCcgOiAnMjMwcHggIWltcG9ydGFudCcsJ3RvcCc6JzI2MHB4ICFpbXBvcnRhbnQnfSk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9uKCdjbGljaycsJy5maW5kLXN0b3JlLWJ0bicsZnVuY3Rpb24oKSB7XG5cdFx0ZGlhbG9nLm9wZW4oe1xuXHRcdFx0aHRtbDooJCgnLmZpbmRTdG9yZURpYWxvZycpLmh0bWwoKSkucmVwbGFjZSgvc2VsZWN0LWhvbGRlci9nLCcnKSxcblx0XHRcdGNhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JChkb2N1bWVudCkub24oJ2NsaWNrJywnLmZpbmRzdG9yZS1mb3JtQ29udGFpbmVyIC5maW5kU3RvcmUtYnRuJyxmdW5jdGlvbigpIHtcblx0XHRcdFx0XHR2YXIgemlwY29kZSAgICA9ICQoJyNkaWFsb2ctY29udGFpbmVyIGlucHV0LnppcGNvZGUnKS52YWwoKSxcblx0XHRcdFx0XHRcdHJhZGl1cyAgICAgPSAkKCcjZGlhbG9nLWNvbnRhaW5lciBzZWxlY3QucmFkaXVzJykudmFsKCksXG5cdFx0XHRcdFx0XHRwb3N0YWxjb2RlID0gJCgnI2RpYWxvZy1jb250YWluZXIgLnBvc3RhbGNvZGUgc2VsZWN0JykudmFsKCksXG5cdFx0XHRcdFx0XHRzdGF0ZWNvZGUgPSAkKCcjZGlhbG9nLWNvbnRhaW5lciAuc3RhdGVjb2RlIHNlbGVjdCcpLnZhbCgpLFxuXHRcdFx0XHRcdFx0cGlkICAgICAgICA9ICQoJyNkaWFsb2ctY29udGFpbmVyICNwaWQnKS52YWwoKSxcblx0XHRcdFx0XHRcdHZhbHVlcyBcdCAgID0ge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRwaWQgOiBwaWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHppcENvZGUgOiB6aXBjb2RlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyYWRpdXMgOiByYWRpdXMsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHN0YXRlY29kZSA6IHN0YXRlY29kZSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0cG9zdGFsY29kZSA6IHBvc3RhbGNvZGVcblx0XHRcdFx0XHRcdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdCQuYWpheCh7XG5cdFx0XHRcdFx0XHR1cmw6IFVybHMuc3RvcmVhdmFpbGFiaWxpdHksXG5cdFx0XHRcdFx0XHR0eXBlOiBcIkdFVFwiLFxuXHRcdFx0XHRcdFx0ZGF0YTogdmFsdWVzICxcblx0XHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0XHRcdFx0XHQkKCcjZGlhbG9nLWNvbnRhaW5lciAuZmluZFN0b3JlLXJlc3VsdCcpLnNob3coKTtcblx0XHRcdFx0XHRcdFx0JCgnI2RpYWxvZy1jb250YWluZXIgLnVpLWRpYWxvZy1mb290ZXInKS5oaWRlKCk7XG5cdFx0XHRcdFx0XHRcdCQoJyNkaWFsb2ctY29udGFpbmVyIC5maW5kU3RvcmUtcmVzdWx0JykuaHRtbChyZXNwb25zZSkudGV4dCgpO1xuXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuXHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyh0ZXh0U3RhdHVzLCBlcnJvclRocm93bik7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0dGl0bGU6IFJlc291cmNlcy5GSU5EU1RPUkVfVElUTEVcblx0XHRcdH0sXG5cdFx0fSk7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5vZmYoJ1JlY2VudGx5Vmlld2VkUHJvZHVjdHMuRG9uZScpLm9uKCdSZWNlbnRseVZpZXdlZFByb2R1Y3RzLkRvbmUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGxvYWRlZC5SZWNlbnRseVZpZXdlZFByb2R1Y3RzID0gdHJ1ZTtcblx0XHRhZGRQcm9tb3Rpb25EYXRhTGF5ZXJzKCk7XG5cdH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignRWluc3RlaW5Qcm9kdWN0UmVjb21tZW5kYXRpb25zLkRvbmUnKS5vbignRWluc3RlaW5Qcm9kdWN0UmVjb21tZW5kYXRpb25zLkRvbmUnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGxvYWRlZC5FaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMgPSB0cnVlO1xuXHRcdGFkZFByb21vdGlvbkRhdGFMYXllcnMoKTtcblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdSZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuRG9uZScpLm9uKCdSZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuRG9uZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0bG9hZGVkLlJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucyArPSAxO1xuXHRcdGFkZFByb21vdGlvbkRhdGFMYXllcnMoKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGFkZFByb21vdGlvbkRhdGFMYXllcnMoKSB7XG5cdGlmIChsb2FkZWQuUmVjZW50bHlWaWV3ZWRQcm9kdWN0cyAmJiBsb2FkZWQuRWluc3RlaW5Qcm9kdWN0UmVjb21tZW5kYXRpb25zICYmIGxvYWRlZC5SZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMgPT0gZGF0YUJ1ZmZlclsnUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zQ291bnQnXSkge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0dvb2dsZVRhZ01hbmFnZXIuQWRkUHJvbW90aW9uRGF0YUxheWVycycpO1xuXHR9XG59XG5cbnZhciBwcm9kdWN0ID0ge1xuICAgIGluaXRpYWxpemVFdmVudHM6IGluaXRpYWxpemVFdmVudHMsXG4gICAgaW5pdDogZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcbiAgICBcdG9wdGlvbnMgPSBvcHRpb25zUGFyYW1ldGVyO1xuXHRcdGxvYWRlZCA9IHtcblx0XHRcdFJlY2VudGx5Vmlld2VkUHJvZHVjdHM6IGZhbHNlLFxuXHRcdFx0RWluc3RlaW5Qcm9kdWN0UmVjb21tZW5kYXRpb25zOiBmYWxzZSxcblx0XHRcdFJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9uczogMFxuXHRcdH07XG5cdFx0ZGF0YUJ1ZmZlciA9IHtcblx0XHRcdFJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9uc0NvdW50OiAwXG5cdFx0fTtcblxuICAgIFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5SZWNhcHRjaGEgJiYgb3B0aW9ucy5SZWNhcHRjaGEuRW5hYmxlZEZvck1lcnJ5TWFpbCkge1xuICAgICAgICBcdHJlY2FwdGNoYS5pbml0aWFsaXplKCk7XG4gICAgXHR9XG5cblx0XHRpZiAob3B0aW9ucyAmJiBvcHRpb25zLlJlY2VudGx5Vmlld2VkUHJvZHVjdHMpIHtcbiAgICBcdFx0cmVjZW50bHlWaWV3ZWRQcm9kdWN0cy5pbml0aWFsaXplKG9wdGlvbnMuUmVjZW50bHlWaWV3ZWRQcm9kdWN0cyk7XG4gICAgXHR9IGVsc2Uge1xuXHRcdFx0bG9hZGVkLlJlY2VudGx5Vmlld2VkUHJvZHVjdHMgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICghb3B0aW9ucyB8fCAhb3B0aW9ucy5FaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMpIHtcblx0XHRcdGxvYWRlZC5FaW5zdGVpblByb2R1Y3RSZWNvbW1lbmRhdGlvbnMgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zICYmIG9wdGlvbnMuUmVsZXZhbnRQcm9kdWN0UmVjb21tZW5kYXRpb25zKSB7XG5cdFx0XHRkYXRhQnVmZmVyWydSZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnNDb3VudCddID0gb3B0aW9ucy5SZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuQ29udGFpbmVycy5sZW5ndGg7XG5cdFx0XHRyZWxldmFudFByb2R1Y3RSZWNvbW1lbmRhdGlvbnMuaW5pdGlhbGl6ZShvcHRpb25zLlJlbGV2YW50UHJvZHVjdFJlY29tbWVuZGF0aW9ucyk7XG5cdFx0fVxuXG5cdFx0dmFyaWFudC5pbml0aWFsaXplKG9wdGlvbnMpO1xuXG5cdFx0aW5pdGlhbGl6ZURvbShvcHRpb25zKTtcblx0XHRpbml0aWFsaXplRXZlbnRzKG9wdGlvbnMpO1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHByb2R1Y3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpLFxuICAgIHRvb2x0aXAgPSByZXF1aXJlKCcuLi8uLi90b29sdGlwJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRhZGRUb0NhcnQgPSAkKCcjYWRkLXRvLWNhcnQnKSxcbiAgICAgICAgJGFkZEFsbFRvQ2FydCA9ICQoJyNhZGQtYWxsLXRvLWNhcnQnKSxcbiAgICAgICAgJHByb2R1Y3RTZXRMaXN0ID0gJCgnI3Byb2R1Y3Qtc2V0LWxpc3QnKTtcblxuICAgIHZhciB1cGRhdGVBZGRUb0NhcnRCdXR0b25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoJHByb2R1Y3RTZXRMaXN0LmZpbmQoJy5hZGQtdG8tY2FydFtkaXNhYmxlZF0nKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkYWRkQWxsVG9DYXJ0LmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAvLyBwcm9kdWN0IHNldCBkb2VzIG5vdCBoYXZlIGFuIGFkZC10by1jYXJ0IGJ1dHRvbiwgYnV0IHByb2R1Y3QgYnVuZGxlIGRvZXNcbiAgICAgICAgICAgICRhZGRUb0NhcnQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRhZGRBbGxUb0NhcnQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICRhZGRUb0NhcnQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoJHByb2R1Y3RTZXRMaXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgdXBkYXRlQWRkVG9DYXJ0QnV0dG9ucygpO1xuICAgIH1cbiAgICAvLyBjbGljayBvbiBzd2F0Y2ggZm9yIHByb2R1Y3Qgc2V0XG4gICAgJHByb2R1Y3RTZXRMaXN0Lm9uKCdjbGljaycsICcucHJvZHVjdC1zZXQtaXRlbSAuc3dhdGNoYW5jaG9yJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoJCh0aGlzKS5wYXJlbnRzKCdsaScpLmhhc0NsYXNzKCd1bnNlbGVjdGFibGUnKSkgeyByZXR1cm47IH1cbiAgICAgICAgdmFyIHVybCA9IFVybHMuZ2V0U2V0SXRlbSArIHRoaXMuc2VhcmNoO1xuICAgICAgICB2YXIgJGNvbnRhaW5lciA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3Qtc2V0LWl0ZW0nKTtcbiAgICAgICAgdmFyIHF0eSA9ICRjb250YWluZXIuZmluZCgnZm9ybSBpbnB1dFtuYW1lPVwiUXVhbnRpdHlcIl0nKS5maXJzdCgpLnZhbCgpO1xuXG4gICAgICAgIGFqYXgubG9hZCh7XG4gICAgICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdRdWFudGl0eScsIGlzTmFOKHF0eSkgPyAnMScgOiBxdHkpLFxuICAgICAgICAgICAgdGFyZ2V0OiAkY29udGFpbmVyLFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVBZGRUb0NhcnRCdXR0b25zKCk7XG4gICAgICAgICAgICAgICAgdG9vbHRpcC5pbml0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpO1xudmFyIHBhZ2UgPSByZXF1aXJlKCcuLi8uLi9wYWdlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBUUHJvbWlzZSA9IHJlcXVpcmUoJ3Byb21pc2UnKTtcbnZhciB2YWxpZGF0b3IgPSByZXF1aXJlKCcuLi8uLi92YWxpZGF0b3InKTtcblxudmFyIG9wdGlvbnM7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgcHJvZHVjdCBpbmZvcm1hdGlvblxuICogQHBhcmFtIHtldmVudH0gZSBUaGUgY2xpY2sgZXZlbnQgZnJvbSB0aGUgcmVxdWVzdCBnaWZ0IGJ1dHRvblxuICogQHJldHVybnMge29iamVjdH0gcHJvZHVjdEluZm9cbiAqL1xudmFyIGdldFByb2R1Y3RJbmZvID0gZnVuY3Rpb24oZSkge1xuXHR2YXIgcHJvZHVjdEluZm87XG5cdHZhciBzaXplU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCcpO1xuXHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIGlzU2l6ZVNlbGVjdGVkID0gc2l6ZVNlbGVjdGVkLmxlbmd0aCB8fCAobGVuZ3RoU2VsZWN0ZWQgJiYgd2lkdGhTZWxlY3RlZCk7XG5cblx0aWYgKCFpc1NpemVTZWxlY3RlZCkge1xuXHRcdGFsZXJ0KCdQbGVhc2Ugc2VsZWN0IGEgc2l6ZScpO1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpZiAoISQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGgpIHtcblx0XHRhbGVydCgnUGxlYXNlIHNlbGVjdCBhIGNvbG9yJyk7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Ly8gZ2V0IHByb2R1Y3QgaW5mb1xuXHRpZiAodHlwZW9mIGRhdGFMYXllciAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHR2YXIgdmFyaWF0aW9uQXR0cmlidXRlID0gJCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLmRhdGEoJ2F0dHJpYnV0ZXMnKTtcblx0XHR2YXIgc2l6ZUF0dHJpYnV0ZVZhbHVlID0gdmFyaWF0aW9uQXR0cmlidXRlLnNpemUuZGlzcGxheVZhbHVlO1xuXHRcdGlmICggc2l6ZUF0dHJpYnV0ZVZhbHVlID09ICcnIHx8IHNpemVBdHRyaWJ1dGVWYWx1ZSA9PSBudWxsICkge1xuXHRcdFx0aWYgKHNpemVTZWxlY3RlZC5oYXNDbGFzcyhcInRlbXBzZWxlY3Rpb25cIikgJiYgc2l6ZVNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykuZGF0YSgpICE9IG51bGwgKSB7XG5cdFx0XHRcdHNpemVTZWxlY3RlZC5hZGRDbGFzcygnZW50ZXJTZWxlY3RlZCcpO1xuXHRcdFx0XHR2YXIgc2l6ZU9iamVjdFJlZmVyZW5jZSA9IHNpemVTZWxlY3RlZC5maW5kKCdhLnN3YXRjaGFuY2hvcicpLmRhdGEoKTtcblx0XHRcdFx0c2l6ZUF0dHJpYnV0ZVZhbHVlID0gc2l6ZU9iamVjdFJlZmVyZW5jZS5zaXplTmFtZTtcblx0XHRcdFx0c2l6ZVNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykudHJpZ2dlcignY2xpY2snKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmb3IodmFyIGk9MDtpPGRhdGFMYXllci5sZW5ndGg7aSsrKSB7XG5cdFx0XHRpZihkYXRhTGF5ZXJbaV0uZXZlbnQgPT0gJ3BkcERpc3BsYXknKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZEl0ZW0gPSBkYXRhTGF5ZXJbaV0uZWNvbW1lcmNlLmRldGFpbC5wcm9kdWN0c1swXTtcblx0XHRcdFx0dmFyIGlzU3dpcGVyID0gJCgnLnByb2R1Y3QtcHJpbWFyeS1pbWFnZSBbY2xhc3MqPVwiLWluaXRpYWxpemVkXCJdJykuZmlyc3QoKS5oYXNDbGFzcygnc3dpcGVyLWluaXRpYWxpemVkJyk7XG5cdFx0XHRcdHZhciBhY3RpdmVJbWFnZSA9IGlzU3dpcGVyID8gJChlLnRhcmdldCkuY2xvc2VzdCgnI3BkcE1haW4nKS5maW5kKCcucHJvZHVjdC1wcmltYXJ5LWltYWdlIC5zd2lwZXItc2xpZGUtYWN0aXZlIGltZycpLmF0dHIoJ3NyYycpIDogJChlLnRhcmdldCkuY2xvc2VzdCgnI3BkcE1haW4nKS5maW5kKCcucHJvZHVjdC1wcmltYXJ5LWltYWdlIC5zbGljay1hY3RpdmUgLnpvb21lZEltYWdlJykuYXR0cignaHJlZicpO1xuXHRcdFx0XHRwcm9kdWN0SW5mbyA9IHtcblx0XHRcdFx0XHRcImlkXCI6IHNlbGVjdGVkSXRlbS5pZCxcblx0XHRcdFx0XHRcIm5hbWVcIjogc2VsZWN0ZWRJdGVtLm5hbWUsXG5cdFx0XHRcdFx0XCJpbWFnZVVybFwiOiBhY3RpdmVJbWFnZSxcblx0XHRcdFx0XHRcInNpemVcIjogc2l6ZUF0dHJpYnV0ZVZhbHVlLFxuXHRcdFx0XHRcdFwiY29sb3JcIjogdmFyaWF0aW9uQXR0cmlidXRlLmNvbG9yLmRpc3BsYXlWYWx1ZSxcblx0XHRcdFx0XHRcImNvbG9yQ29kZVwiOiB2YXJpYXRpb25BdHRyaWJ1dGUuY29sb3IudmFsdWVcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cdFxuXHR9XG5cdHJldHVybiBwcm9kdWN0SW5mbztcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEZvcm1hdHMgYSBVUkwgd2l0aCBwcmVzZXQgcHJvZHVjdCBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge29iamVjdH0gcHJvZHVjdEluZm8gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHByb2R1Y3QncyBhdHRyaWJ1dGVzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB1cmxcbiAqL1xudmFyIGNyZWF0ZVByb2R1Y3RVcmwgPSBmdW5jdGlvbihwcm9kdWN0SW5mbykge1xuXHR2YXIgdXJsID0gd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lICsgd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lO1xuXHRpZiAocHJvZHVjdEluZm8uaWQgJiYgcHJvZHVjdEluZm8uaWQubGVuZ3RoID4gMCkge1xuXHRcdHVybCA9IHVybCArICc/ZHd2YXJfJyArIHByb2R1Y3RJbmZvLmlkO1xuXHRcdGlmIChwcm9kdWN0SW5mby5jb2xvckNvZGUgJiYgcHJvZHVjdEluZm8uY29sb3JDb2RlLmxlbmd0aCA+IDApIHtcblx0XHRcdHVybCA9IHVybCArICdfY29sb3I9JyArIHByb2R1Y3RJbmZvLmNvbG9yQ29kZTtcblx0XHR9XG5cdFx0aWYgKHByb2R1Y3RJbmZvLnNpemUgJiYgcHJvZHVjdEluZm8uc2l6ZS5sZW5ndGggPiAwKSB7XG5cdFx0XHR1cmwgPSB1cmwgKyAnI3ByZWZuMT1zaXplJnByZWZ2MT0nICsgcHJvZHVjdEluZm8uc2l6ZTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHVybDtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE9wZW4gdGhlIHJlcXVlc3QgZ2lmdCBkaWFsb2dcbiAqIEBwYXJhbSB7ZXZlbnR9IGUgVGhlIGNsaWNrIGV2ZW50IGZyb20gdGhlIHJlcXVlc3QgZ2lmdCBidXR0b25cbiAqL1xudmFyIHJlcXVlc3RHaWZ0ID0gZnVuY3Rpb24oZSkge1xuXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFxuXHR2YXIgd2luZG93V2lkdGggPSAkKHdpbmRvdykud2lkdGgoKTtcblx0XG5cdGlmICh3aW5kb3dXaWR0aCA8PSA0ODApIHtcblx0XHR2YXIgZGlhbG9nV2lkdGggPSB3aW5kb3dXaWR0aCAtIDIwO1xuXHR9IGVsc2UgaWYgKHdpbmRvd1dpZHRoIDw9IDg0MCkge1xuXHRcdHZhciBkaWFsb2dXaWR0aCA9IHdpbmRvd1dpZHRoIC0gNDA7XG5cdH0gZWxzZSB7XG5cdFx0dmFyIGRpYWxvZ1dpZHRoID0gODAwO1xuXHR9XG5cblx0dmFyIHByb2R1Y3RJbmZvID0gZ2V0UHJvZHVjdEluZm8oZSk7XG5cdHZhciBkaWFsb2dDbGFzcyA9ICdnaWZ0LWRpYWxvZyc7XG5cdHZhciB0ZW1wbGF0ZVNldHRpbmdzID0ge2ludGVycG9sYXRlOiAve3soW1xcc1xcU10rPyl9fS9nfTtcblx0dmFyIGZvcm1UZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXBvcHVwLWZvcm0nKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuXHR2YXIgY29uZmlybWF0aW9uVGVtcGxhdGUgPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS1wb3B1cC1jb25maXJtYXRpb24nKS5odG1sKCksIHRlbXBsYXRlU2V0dGluZ3MpO1xuXG5cdGlmICghcHJvZHVjdEluZm8pIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRkaWFsb2cub3Blbih7XG5cdFx0aHRtbDogZm9ybVRlbXBsYXRlKHByb2R1Y3RJbmZvKSxcblx0XHRvcHRpb25zOiB7XG5cdFx0XHR0aXRsZTogJ1NlbmQgYSBoaW50Jyxcblx0XHRcdHdpZHRoOiBkaWFsb2dXaWR0aCxcblx0XHRcdGRpYWxvZ0NsYXNzOiBkaWFsb2dDbGFzcyxcblx0XHRcdGJ1dHRvbnM6IFtdLFxuXHRcdFx0bW9kYWw6IHRydWUsXG5cdFx0XHRvcGVuOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyICRmb3JtID0gJCh0aGlzKS5maW5kKCcjZ2lmdC1mb3JtJyk7XG5cdFx0XHRcdC8vIGpxdWVyeSB2YWxpZGF0ZSBkb2Vzbid0IHJlcXVpcmUgYW4gZW1haWwgZXh0ZW5zaW9uLCBzbyBhZGRpbmcgaXQgbWFudWFsbHlcblx0XHRcdFx0JC52YWxpZGF0b3IuYWRkTWV0aG9kKCdNZXJyeU1haWxWYWxpZGF0ZUVtYWlsJyxcblx0XHRcdFx0XHRmdW5jdGlvbih2YWx1ZSwgZWxlbWVudCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIC9eXFx3KyhbLSsuJ11cXHcrKSpAXFx3KyhbLS5dXFx3KykqXFwuXFx3KyhbLS5dXFx3KykqJC8udGVzdCh2YWx1ZSk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHQnUGxlYXNlIGVudGVyIGEgdmFsaWQgZW1haWwgYWRkcmVzcy4nXG5cdFx0XHRcdCk7XG5cdFx0XHRcdCQudmFsaWRhdG9yLmFkZE1ldGhvZCgnTWVycnlNYWlsVmFsaWRhdGVOYW1lJyxcblx0XHRcdFx0XHRmdW5jdGlvbih2YWx1ZSwgZWxlbWVudCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuICEoLzpcXC9cXC8vLnRlc3QodmFsdWUpKSAmJiAhKC9cXHcrKFstKy4nXFxzXVxcdykqQFxcdysoWy0uXVxcdyspKlxcLlxcdysoWy0uXVxcdyspKi8udGVzdCh2YWx1ZSkpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0J1BsZWFzZSBlbnRlciBhIHZhbGlkIG5hbWUuJ1xuXHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdCRmb3JtLnZhbGlkYXRlKHtcblx0XHRcdFx0XHRydWxlczoge1xuXHRcdFx0XHRcdFx0Y3VzdG9tTWVzc2FnZToge1xuXHRcdFx0XHRcdFx0XHRyZXF1aXJlZDoge1xuXHRcdFx0XHRcdFx0XHRcdGRlcGVuZHM6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwibWVzc2FnZVwiXVt2YWx1ZT1cImN1c3RvbVwiXScpLnByb3AoJ2NoZWNrZWQnKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRzZW5kZXJOYW1lOiB7XG5cdFx0XHRcdFx0XHRcdE1lcnJ5TWFpbFZhbGlkYXRlTmFtZTogdHJ1ZVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdHNlbmRlckVtYWlsOiB7XG5cdFx0XHRcdFx0XHRcdE1lcnJ5TWFpbFZhbGlkYXRlRW1haWw6IHRydWVcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRyZWNpcGllbnROYW1lOiB7XG5cdFx0XHRcdFx0XHRcdE1lcnJ5TWFpbFZhbGlkYXRlTmFtZTogdHJ1ZVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdHJlY2lwaWVudEVtYWlsOiB7XG5cdFx0XHRcdFx0XHRcdE1lcnJ5TWFpbFZhbGlkYXRlRW1haWw6IHRydWVcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGlmICgkKCcjbWVycnlNYWlsU3VibWl0QnV0dG9uJykubGVuZ3RoID4gMCAmJiBvcHRpb25zICYmIG9wdGlvbnMuUmVjYXB0Y2hhICYmIG9wdGlvbnMuUmVjYXB0Y2hhLkVuYWJsZWRGb3JNZXJyeU1haWwgJiYgb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSkge1xuXHRcdFx0XHRcdGdyZWNhcHRjaGEucmVuZGVyKCdtZXJyeU1haWxTdWJtaXRCdXR0b24nLCB7XG5cdFx0XHQgICAgICAgIFx0c2l0ZWtleTogb3B0aW9ucy5SZWNhcHRjaGEuR29vZ2xlU2l0ZUtleSxcblx0XHRcdCAgICAgICAgXHRjYWxsYmFjazogc3VibWl0TWVycnlNYWlsLFxuXHRcdFx0ICAgICAgICBcdGJhZGdlOiAnYm90dG9tbGVmdCdcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0Ly8gdHJpZ2dlciByYWRpbyBidXR0b24gc2VsZWN0aW9uIGlmIHVzZXIgY2xpY2tzIGludG8gY3VzdG9tIG1lc3NhZ2UgaW5wdXRcblx0XHRcdFx0JCh0aGlzKS5maW5kKCdpbnB1dFtuYW1lPVwiY3VzdG9tTWVzc2FnZVwiXScpLm9mZignZm9jdXMnKS5vbignZm9jdXMnLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdFx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIm1lc3NhZ2VcIl1bdmFsdWU9XCJjdXN0b21cIl0nKS5wcm9wKCdjaGVja2VkJywgdHJ1ZSkuY2hhbmdlKCk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdCQoZG9jdW1lbnQpLm9mZignTWVycnlNYWlsLlNlbmQnKS5vbignTWVycnlNYWlsLlNlbmQnLCBmdW5jdGlvbigpIHtcblx0XHRcdCAgICAgICAgaWYgKCEkZm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0ICAgICAgICBcblx0XHRcdFx0XHR2YXIgZm9ybURhdGEgPSB7XG5cdFx0XHRcdFx0XHRyZWNpcGllbnROYW1lOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwicmVjaXBpZW50TmFtZVwiXScpLnZhbCgpLFxuXHRcdFx0XHRcdFx0cmVjaXBpZW50TmFtZUNhcHM6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJyZWNpcGllbnROYW1lXCJdJykudmFsKCkudG9VcHBlckNhc2UoKSxcblx0XHRcdFx0XHRcdHJlY2lwaWVudEVtYWlsOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwicmVjaXBpZW50RW1haWxcIl0nKS52YWwoKSxcblx0XHRcdFx0XHRcdHNlbmRlck5hbWU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJzZW5kZXJOYW1lXCJdJykudmFsKCksXG5cdFx0XHRcdFx0XHRzZW5kZXJFbWFpbDogJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInNlbmRlckVtYWlsXCJdJykudmFsKCksXG5cdFx0XHRcdFx0XHRmcm9tRW1haWw6ICQoJyNtZXJyeS1tYWlsLWZyb20tZW1haWwnKS50ZXh0KCkubGVuZ3RoID4gMCA/ICQoJyNtZXJyeS1tYWlsLWZyb20tZW1haWwnKS50ZXh0KCkgOiAnbm8tcmVwbHlAZGVtYW5kd2FyZS5uZXQnLFxuXHRcdFx0XHRcdFx0c3ViamVjdDogJCgnI21lcnJ5LW1haWwtZW1haWwtc3ViamVjdCcpLnRleHQoKS5yZXBsYWNlKCdbc2VuZGVyX25hbWVdJywkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwic2VuZGVyTmFtZVwiXScpLnZhbCgpKSxcblx0XHRcdFx0XHRcdGJhc2VVcmw6ICQoJyNtZXJyeS1tYWlsLWJhc2UtdXJsJykudGV4dCgpLFxuXHRcdFx0XHRcdFx0dW5zdWJzY3JpYmVVcmw6ICQoJyNtZXJyeS1tYWlsLXVuc3Vic2NyaWJlLXVybCcpLnRleHQoKSxcblx0XHRcdFx0XHRcdG1lc3NhZ2U6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJtZXNzYWdlXCJdOmNoZWNrZWQnKS52YWwoKSA9PT0gJ2N1c3RvbScgPyAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwiY3VzdG9tTWVzc2FnZVwiXScpLnZhbCgpIDogJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIm1lc3NhZ2VcIl06Y2hlY2tlZCcpLnZhbCgpLFxuXHRcdFx0XHRcdFx0cHJvZHVjdElkOiBwcm9kdWN0SW5mby5pZCxcblx0XHRcdFx0XHRcdHByb2R1Y3RJbWFnZTogd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lICsgcHJvZHVjdEluZm8uaW1hZ2VVcmwsXG5cdFx0XHRcdFx0XHRwcm9kdWN0VXJsOiBjcmVhdGVQcm9kdWN0VXJsKHByb2R1Y3RJbmZvKSxcblx0XHRcdFx0XHRcdHByb2R1Y3ROYW1lOiBwcm9kdWN0SW5mby5uYW1lLnJlcGxhY2UoL1xcXFwoLikvbWcsIFwiJDFcIiksIC8vIGhhbmRsZSBiYWNrc2xhc2ggZXNjYXBpbmdcblx0XHRcdFx0XHRcdHNpemU6IHByb2R1Y3RJbmZvLnNpemUsXG5cdFx0XHRcdFx0XHRjb2xvcjogcHJvZHVjdEluZm8uY29sb3Jcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XG5cdFx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0XHRcdHVybDogVXJscy5zZW5kR2lmdFJlcXVlc3RFbWFpbCxcblx0XHRcdFx0XHRcdGRhdGE6IGZvcm1EYXRhLFxuXHRcdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBjb25maXJtTWVzc2FnZSA9ICQoJyNtZXJyeS1tYWlsLXN1Y2Nlc3MtbWVzc2FnZScpLmh0bWwoKS5yZXBsYWNlKCdbcmVjaXBpZW50X25hbWVdJyxmb3JtRGF0YS5yZWNpcGllbnROYW1lKTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGRpYWxvZy5vcGVuKHtcblx0XHRcdFx0XHRcdFx0XHRodG1sOiBjb25maXJtYXRpb25UZW1wbGF0ZSh7Y29uZmlybU1lc3NhZ2U6IGNvbmZpcm1NZXNzYWdlfSksXG5cdFx0XHRcdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0XHRcdFx0dGl0bGU6ICdTdWNjZXNzIScsXG5cdFx0XHRcdFx0XHRcdFx0XHR3aWR0aDogZGlhbG9nV2lkdGgsXG5cdFx0XHRcdFx0XHRcdFx0XHRkaWFsb2dDbGFzczogZGlhbG9nQ2xhc3MsXG5cdFx0XHRcdFx0XHRcdFx0XHRidXR0b25zOiBbe1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0ZXh0OiAnT0snLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRjbGljazogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0ZGlhbG9nLmNsb3NlKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdH1dXG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuR1RNX0VOQUJMRUQpIHtcblx0XHRcdFx0XHRcdFx0XHRkYXRhTGF5ZXIucHVzaCh7XG5cdFx0XHRcdFx0XHRcdFx0XHQnZXZlbnQnOiBTaXRlUHJlZmVyZW5jZXMuTUVSUllNQUlMX0dUTV9FVkVOVF9OQU1FLFxuXHRcdFx0XHRcdFx0XHRcdFx0J21lcnJ5TWFpbFByb2R1Y3QnOiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCduYW1lJyA6IGZvcm1EYXRhLnByb2R1Y3ROYW1lLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQndXJsJyA6IGZvcm1EYXRhLnByb2R1Y3RVcmxcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0ICAgIH0pO1xuXHRcdFx0XHRcblx0XHRcdFx0Ly8gaGFuZGxlIGNsaWNrIGV2ZW50cyBvbiBzdWJtaXQgYnV0dG9uXG5cdFx0XHRcdCRmb3JtLmZpbmQoJ2lucHV0W3R5cGU9XCJzdWJtaXRcIl0nKS5vZmYoJ2NsaWNrJykub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMuUmVjYXB0Y2hhIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5FbmFibGVkRm9yTWVycnlNYWlsIHx8ICFvcHRpb25zLlJlY2FwdGNoYS5Hb29nbGVTaXRlS2V5KSB7XG5cdFx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdNZXJyeU1haWwuU2VuZCcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcblx0XG5cdHBvcHVsYXRlTW9kYWxQcm9kdWN0Q29udGVudChwcm9kdWN0SW5mbyk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQb3B1bGF0ZXMgdGhlIG1vZGFsIHdpdGggYXBwbGljYWJsZSB2YXJpYW50L3Byb2R1Y3QgZGF0YVxuICovXG52YXIgcG9wdWxhdGVNb2RhbFByb2R1Y3RDb250ZW50ID0gZnVuY3Rpb24ocHJvZHVjdEluZm8pIHtcblx0dmFyIHByb2R1Y3RJbWFnZVVybCA9IHByb2R1Y3RJbmZvLmltYWdlVXJsO1xuXHR2YXIgY3VycmVudFByb2R1Y3RVcmwgPSBjcmVhdGVQcm9kdWN0VXJsKHByb2R1Y3RJbmZvKTtcblx0XG5cdCQoJy5naWZ0LWRpYWxvZ19fc2FtcGxlLW1lc3NhZ2UgLnByb2R1Y3QtaW1hZ2UnKS5yZXBsYWNlV2l0aCgnPGltZyBjbGFzcz1cInByb2R1Y3QtaW1hZ2VcIiBzcmM9XCInICsgcHJvZHVjdEltYWdlVXJsICsgJz9zdz01MDBcIiBhbHQ9XCJcIiAvPicpO1xuXHRcblx0dmFyIGhpbnRUZXh0ID0gJCgnc3Ryb25nLmhpbnQtaXRlbScpLmh0bWwoKTtcblx0JCgnc3Ryb25nLmhpbnQtaXRlbScpLnJlcGxhY2VXaXRoKCc8c3Ryb25nIGNsYXNzPVwiaGludC1pdGVtXCI+PGEgaHJlZj1cIicgKyBjdXJyZW50UHJvZHVjdFVybCArICdcIj4nICsgaGludFRleHQgKyAnPC9hPjwvc3Ryb25nPicpO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gdXBkYXRlcyB0aGUgc2VuZGVyIGFuZCByZWNpcGllbnQgbmFtZXMgaW4gdGhlIHNhbXBsZSBtZXNzYWdlIGFzIHRoZSB1c2VyIGVudGVycyB0aGF0IGluZm9ybWF0aW9uIGludG8gdGhlIGZvcm1cbiAqL1xudmFyIHVwZGF0ZVNlbmRlck5hbWUgPSBmdW5jdGlvbigpIHtcblx0dmFyIGN1cnJlbnRTZW5kZXJOYW1lID0gJCgnLmdpZnQtZm9ybV9faW5wdXRbbmFtZT1cInNlbmRlck5hbWVcIl0nKS52YWwoKTtcblx0XG5cdCQoJy5tZXJyeS1tYWlsLW1lc3NhZ2UtZnJvbScpLnJlcGxhY2VXaXRoKCc8c3BhbiBjbGFzcz1cIm1lcnJ5LW1haWwtbWVzc2FnZS1mcm9tIHJlcGxhY2VkXCI+JyArIGN1cnJlbnRTZW5kZXJOYW1lICsgJzwvc3Bhbj4nKTtcbn07XG5cbnZhciB1cGRhdGVSZWNpcGllbnROYW1lID0gZnVuY3Rpb24oKSB7XG5cdHZhciBjdXJyZW50UmVjaXBpZW50TmFtZSA9ICQoJy5naWZ0LWZvcm1fX2lucHV0W25hbWU9cmVjaXBpZW50TmFtZV0nKS52YWwoKTtcblx0XG5cdCQoJy5tZXJyeS1tYWlsLW1lc3NhZ2UtdG8nKS5yZXBsYWNlV2l0aCgnPHNwYW4gY2xhc3M9XCJtZXJyeS1tYWlsLW1lc3NhZ2UtdG8gcmVwbGFjZWRcIj4nICsgY3VycmVudFJlY2lwaWVudE5hbWUgKyAnPC9zcGFuPicpO1xufTtcblxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBjbGljayBldmVudCB0byB0aGUgYnV0dG9uIGZvciB0aGUgcmVxdWVzdCBnaWZ0IGhhbmRsaW5nXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdFxuXHQkKCcucHJvZHVjdC1kZXRhaWwnKS5vbignY2xpY2snLCAnW2RhdGEtYWN0aW9uPVwicmVxdWVzdEdpZnRcIl0nLCByZXF1ZXN0R2lmdCk7XG5cdCQoZG9jdW1lbnQpLm9uKCdjaGFuZ2UnLCAnaW5wdXQuc2VuZGVyLW5hbWUnLCB1cGRhdGVTZW5kZXJOYW1lKTtcblx0JChkb2N1bWVudCkub24oJ2NoYW5nZScsICdpbnB1dC5yZWNpcGllbnQtbmFtZScsIHVwZGF0ZVJlY2lwaWVudE5hbWUpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpO1xudmFyIGltYWdlID0gcmVxdWlyZSgnLi9pbWFnZScpO1xudmFyIEdvb2dsZVRhZ01hbmFnZXJDbGllbnQgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL3V0aWwvR29vZ2xlVGFnTWFuYWdlckNsaWVudCcpO1xudmFyIHByb2R1Y3RTdG9yZUludmVudG9yeSA9IHJlcXVpcmUoJy4uLy4uL3N0b3JlaW52ZW50b3J5L3Byb2R1Y3QnKTtcbnZhciByYXRpbmcgPSByZXF1aXJlKCcuLi8uLi9yYXRpbmcnKTtcbnZhciB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG52YXIgYm9waXNBZGRUb0NhcnRPcHRpb25zID0gcmVxdWlyZSgnLi4vLi4vYm9waXMvY29tcG9uZW50cy9BZGRUb0NhcnRPcHRpb25zJyk7XG52YXIgYm9waXNTdG9yZVNlYXJjaCA9IHJlcXVpcmUoJy4uLy4uL2JvcGlzL2NvbXBvbmVudHMvU3RvcmVTZWFyY2gnKTtcbnZhciB3aXNobGlzdCA9IHJlcXVpcmUoJy4uLy4uL3dpc2hsaXN0Jyk7XG52YXIgc2xpZGVycyA9IHJlcXVpcmUoJy4uLy4uL3NsaWRlcnMnKTtcbnZhciBpbWFnZUdhbGxlcnk7XG5cbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG5cbnZhciBodG1sID0ge307XG52YXIgZGF0YSA9IHt9O1xudmFyIGxvYWRlZCA9IHt9O1xudmFyIG9wdGlvbnM7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVEb20oKSB7XG5cdGxvYWRlZFsnY29udGVudCddID0gdHJ1ZTtcblx0XG5cdHVwZGF0ZUNTUkZUb2tlbigpO1xuXG5cdHZhciBzZWxlY3RvclBheWxvYWQgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKCQoJy5wZHBGb3JtJykuc2VyaWFsaXplKCkpO1xuXHRcblx0dmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXModXRpbC5nZXRRdWVyeVN0cmluZyh1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKHdpbmRvdy5sb2NhdGlvbi50b1N0cmluZygpLCBzZWxlY3RvclBheWxvYWQpKSk7XG5cdGZvciAodmFyIHBhcmFtZXRlciBpbiBxdWVyeVN0cmluZ1BhcmFtZXRlcnMpIHtcblx0XHRzZWxlY3RvclBheWxvYWRbcGFyYW1ldGVyXSA9IHF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1twYXJhbWV0ZXJdO1xuXHR9XG5cblx0dmFyIHNpemVWYWx1ZSA9IHV0aWwuZ2V0UHJlZmVyZW5jZVZhbHVlRnJvbVdpbmRvd0xvY2F0aW9uKCdzaXplJyk7XG5cdGlmIChzaXplVmFsdWUpIHtcblx0XHRzZWxlY3RvclBheWxvYWQuc2V0U2l6ZSA9IHNpemVWYWx1ZTtcblx0fVxuXHRcbiAgICBidWlsZFNlbGVjdG9ycyhzZWxlY3RvclBheWxvYWQpO1xuXHQkKCcuYnRuLmFkZC10by1jYXJ0JykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdsb2FkaW5nJykuZmluZCgnLmxvYWRpbmctaW5kaWNhdG9yLWNvbnRhaW5lcicpLnJlbW92ZSgpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVQcm9kdWN0SW5mbygpIHtcblx0JCgnbGkuc2VsZWN0ZWQtdmFsdWUnKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkc2VsZWN0ZWRJdGVtID0gJCh0aGlzKTtcblx0XHQkc2VsZWN0ZWRJdGVtLnBhcmVudHMoJy5hdHRyaWJ1dGUnKS5maXJzdCgpLmZpbmQoJy5sYWJlbCAuY3VycmVudCwgLnNlbGVjdC1kcm9wZG93biAuc2VsZWN0LXRleHQnKS5odG1sKCRzZWxlY3RlZEl0ZW0uaHRtbCgpKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNTUkZUb2tlbigpIHtcbiAgICAkLmFqYXgoe1xuICAgIFx0bWV0aG9kOiAnZ2V0JyxcbiAgICBcdHVybDogVXJscy5DU1JGVG9rZW4uR2V0LFxuXHRcdGRhdGFUeXBlOiAnanNvbicsXG4gICAgXHRzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgIFx0XHQkKCcjY3NyZnRva2VuJykudmFsKHJlc3BvbnNlLnRva2VuKTtcbiAgICBcdH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlUGlkKCkge1xuXHRpZiAoZGF0YVsncGlkJ10pIHtcblx0XHQkKCcjcGlkJykudmFsKGRhdGFbJ3BpZCddKTtcblx0fVxufVxuXG5mdW5jdGlvbiBidWlsZFNlbGVjdG9ycyhwYXlsb2FkKSB7XG5cdGxvYWRlZFsnc2VsZWN0b3JzJ10gPSBmYWxzZTtcblx0XG5cdGlmICghcGF5bG9hZCkge1xuXHRcdHBheWxvYWQgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKCQoJy5wZHBGb3JtJykuc2VyaWFsaXplKCkpO1xuXHR9XG4gICAgXG4gICAgdmFyIHRlbXBsYXRlcyA9IFtdO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9ucyddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucycpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuXHR0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yQXR0cmlidXRlR3VpZGUnXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtYXR0cmlidXRlLWd1aWRlJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93biddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1kcm9wZG93bicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb24nXSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLXZhcmlhdGlvbnMtc2VsZWN0b3ItZHJvcGRvd24tb3B0aW9uJykuaHRtbCgpLCBUZW1wbGF0ZUNvbnN0YW50cy5Mb2Rhc2guU2V0dGluZ3MpO1xuICAgIHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvblNlbGVjdGVkJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLWRyb3Bkb3duLW9wdGlvbi1zZWxlY3RlZCcpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLXN3YXRjaCcpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoT3B0aW9uJ10gPSBfLnRlbXBsYXRlKCQoJyN0ZW1wbGF0ZS12YXJpYXRpb25zLXNlbGVjdG9yLXN3YXRjaC1vcHRpb24nKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG4gICAgdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaE9wdGlvblVuc2VsZWN0YWJsZSddID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtdmFyaWF0aW9ucy1zZWxlY3Rvci1zd2F0Y2gtb3B0aW9uLXVuc2VsZWN0YWJsZScpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcbiAgICBcblx0ZGF0YVsnYXR0cmlidXRlR3VpZGVzJ10gPSB7fTtcblxuICAgICQuYWpheCh7XG4gICAgXHRtZXRob2Q6ICdwb3N0JyxcbiAgICBcdHVybDogVXJscy5nZXRWYXJpYXRpb25BdHRyaWJ1dGVzLFxuICAgIFx0ZGF0YTogcGF5bG9hZCxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuICAgIFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9ycyddID0gJyc7XG5cdFx0XHRkYXRhWydJc1Jlc3RyaWN0ZWRCeUdsb2JhbGUnXSA9IHJlc3BvbnNlLklzUmVzdHJpY3RlZEJ5R2xvYmFsZTtcblxuXHRcdFx0Ly8gQ29sb3IgU3dhdGNoIExlbmd0aCBDaGVja1xuXHRcdFx0dmFyIGlzTXVsdGlTd2F0Y2g7XG5cdFx0XHRpZiAocmVzcG9uc2UgJiYgJ3ZhcmlhdGlvbnMnIGluIHJlc3BvbnNlICYmIHJlc3BvbnNlLnZhcmlhdGlvbnMubGVuZ3RoKSB7XG5cdFx0XHRcdGlzTXVsdGlTd2F0Y2ggPSByZXNwb25zZS52YXJpYXRpb25zLmZpbHRlcihmdW5jdGlvbih2YXJpYW50R3JvdXApIHtcblx0XHRcdFx0XHRpZiAodmFyaWFudEdyb3VwICYmICd0eXBlJyBpbiB2YXJpYW50R3JvdXAgJiYgJ3ZhbHVlcycgaW4gdmFyaWFudEdyb3VwKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdmFyaWFudEdyb3VwLnR5cGUgPT0gJ3N3YXRjaCcgJiYgdmFyaWFudEdyb3VwLnZhbHVlcy5sZW5ndGggPiAxOyAvLyBDaGVjayBmb3IgbXVsdGlwbGUgY29sb3Igc3dhdGNoZXNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGhhc1NpemVBdHRyaWJ1dGUgPSBmYWxzZTtcblx0XHRcdGlmIChyZXNwb25zZSAmJiAndmFyaWF0aW9ucycgaW4gcmVzcG9uc2UgJiYgcmVzcG9uc2UudmFyaWF0aW9ucy5sZW5ndGgpIHtcblx0XHRcdFx0aGFzU2l6ZUF0dHJpYnV0ZSA9IHJlc3BvbnNlLnZhcmlhdGlvbnMuZmlsdGVyKGZ1bmN0aW9uKHZhcmlhbnRHcm91cCkge1xuXHRcdFx0XHRcdGlmICh2YXJpYW50R3JvdXAgJiYgJ3Byb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUnIGluIHZhcmlhbnRHcm91cCAmJiAndmFsdWVzJyBpbiB2YXJpYW50R3JvdXApIHtcblx0XHRcdFx0XHRcdHJldHVybiB2YXJpYW50R3JvdXAucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSA9PSAnc2l6ZScgJiYgdmFyaWFudEdyb3VwLnZhbHVlcy5sZW5ndGggPiAxO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cblx0XHRcdHZhciB2YXJpYXRpb25zO1xuXHRcdFx0aWYgKGhhc1NpemVBdHRyaWJ1dGUpIHtcblx0XHRcdFx0dmFyaWF0aW9ucyA9IHJlc3BvbnNlLnZhcmlhdGlvbnM7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YXJpYXRpb25zID0gcmVzcG9uc2UudmFyaWF0aW9ucztcblx0XHRcdH1cblx0XHRcdGZvciAodmFyIHZhcmlhdGlvbiBpbiByZXNwb25zZS52YXJpYXRpb25zKSB7XG5cdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhID0gcmVzcG9uc2UudmFyaWF0aW9uc1t2YXJpYXRpb25dO1xuXHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQgPSBudWxsO1xuXHRcdFx0XHRcblx0XHRcdFx0aHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ10gPSAnJztcblx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0Zm9yICh2YXIgdmFyaWF0aW9uVmFsdWUgaW4gdmFyaWF0aW9uRGF0YS52YWx1ZXMpIHtcblx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uRGF0YVZhbHVlID0gdmFyaWF0aW9uRGF0YS52YWx1ZXNbdmFyaWF0aW9uVmFsdWVdO1xuXHRcdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZTtcblx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uVGV4dCA9ICh2YXJpYXRpb25EYXRhVmFsdWUuYXR0cmlidXRlID09PSAnc2l6ZScpID8gdmFyaWF0aW9uRGF0YVZhbHVlLnRleHQucmVwbGFjZSgnIDEvMicsICdcXHUwMEJEJykgOiB2YXJpYXRpb25EYXRhVmFsdWUudGV4dDtcblx0XHRcdFx0XHR2YXIgd2lkdGhEZXNjcmlwdGlvbiA9IHZhcmlhdGlvbkRhdGFWYWx1ZS53aWR0aERlc2NyaXB0aW9uID8gJzxzcGFuIGNsYXNzPVwid2lkdGgtZGVzY3JpcHRpb25cIj4nICsgdmFyaWF0aW9uRGF0YVZhbHVlLndpZHRoRGVzY3JpcHRpb24gKyAnPC9zcGFuPicgOiAnJztcblx0XHRcdFx0XHR2YXIgb3B0aW9uQXJpYUxhYmVsID0gdmFyaWF0aW9uRGF0YVZhbHVlLnZhbHVlO1xuXHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhVmFsdWUuc2hpcHBpbmcpIHtcblx0XHRcdFx0XHRcdG9wdGlvbkFyaWFMYWJlbCArPSArICcgLSAnICsgdmFyaWF0aW9uRGF0YVZhbHVlLnNoaXBwaW5nO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciB2YXJpYXRpb25EYXRhVmFsdWVQYXlsb2FkID0ge1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhVmFsdWUuYXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0dmFsdWVJZDogdmFyaWF0aW9uRGF0YVZhbHVlLnZhbHVlSWQsXG5cdFx0XHRcdFx0XHR2YWx1ZTogdmFyaWF0aW9uRGF0YVZhbHVlLnZhbHVlLFxuXHRcdFx0XHRcdFx0dGl0bGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS50aXRsZSxcblx0XHRcdFx0XHRcdG9wdGlvbkFyaWFMYWJlbDogb3B0aW9uQXJpYUxhYmVsLFxuXHRcdFx0XHRcdFx0dGV4dDogdmFyaWF0aW9uVGV4dCxcblx0XHRcdFx0XHRcdHdpZHRoRGVzY3JpcHRpb246IHdpZHRoRGVzY3JpcHRpb24sXG5cdFx0XHRcdFx0XHRzdG9jazogdmFyaWF0aW9uRGF0YVZhbHVlLnN0b2NrLFxuXHRcdFx0XHRcdFx0c2hpcHBpbmc6IHZhcmlhdGlvbkRhdGFWYWx1ZS5zaGlwcGluZyxcblx0XHRcdFx0XHRcdGlzU2FtZURheVNoaXBwaW5nV2luZG93OiB2YXJpYXRpb25EYXRhVmFsdWUuaXNTYW1lRGF5U2hpcHBpbmdXaW5kb3csXG5cdFx0XHRcdFx0XHRxdWFudGl0eVNvdXJjZVR5cGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5xdWFudGl0eVNvdXJjZVR5cGUsXG5cdFx0XHRcdFx0XHRocmVmOiB2YXJpYXRpb25EYXRhVmFsdWUuaHJlZixcblx0XHRcdFx0XHRcdHNlbGVjdGFibGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5zZWxlY3RhYmxlID8gJ3NlbGVjdGFibGUnIDogJ3Vuc2VsZWN0YWJsZScsXG5cdFx0XHRcdFx0XHRzZWxlY3RlZDogdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGVkID8gJ3NlbGVjdGVkJyA6ICcnLFxuXHRcdFx0XHRcdFx0c3dhdGNoSW1hZ2VVcmw6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMuc3dhdGNoLnVybCxcblx0XHRcdFx0XHRcdGxhcmdlU3dhdGNoSW1hZ2VVcmw6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2VTd2F0Y2gudXJsLFxuXHRcdFx0XHRcdFx0aHJlZkF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGFibGUgPyAnaHJlZicgOiAneGhyZWYnXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YS50eXBlID09ICdzd2F0Y2gnKSB7XG5cdFx0XHRcdFx0XHRpZiAodmFyaWF0aW9uRGF0YVZhbHVlLnNlbGVjdGFibGUpIHtcblx0XHRcdFx0XHRcdFx0dmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGUgPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yU3dhdGNoT3B0aW9uJ107XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0dmFyaWF0aW9uRGF0YVZhbHVlUGF5bG9hZC5pbWFnZUxhcmdlID0gSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRcdFx0XHRcdHVybDogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5sYXJnZS51cmwsXG5cdFx0XHRcdFx0XHRcdFx0dGl0bGU6IHZhcmlhdGlvbkRhdGFWYWx1ZS5pbWFnZXMubGFyZ2UudGl0bGUsXG5cdFx0XHRcdFx0XHRcdFx0YWx0OiB2YXJpYXRpb25EYXRhVmFsdWUuaW1hZ2VzLmxhcmdlLmFsdCxcblx0XHRcdFx0XHRcdFx0XHRoaXJlczogdmFyaWF0aW9uRGF0YVZhbHVlLmltYWdlcy5oaXJlcy51cmxcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVUZW1wbGF0ZSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JTd2F0Y2hPcHRpb25VbnNlbGVjdGFibGUnXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dmFyaWF0aW9uRGF0YVZhbHVlVGVtcGxhdGUgPSB0ZW1wbGF0ZXNbJ3ZhcmlhdGlvblNlbGVjdG9yRHJvcGRvd25PcHRpb24nXTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZS5zZWxlY3RlZCkge1xuXHRcdFx0XHRcdFx0XHR2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZCA9IHZhcmlhdGlvbkRhdGFWYWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRcdGh0bWxbJ3ZhcmlhdGlvblNlbGVjdG9yV2lkZ2V0T3B0aW9ucyddICs9IHZhcmlhdGlvbkRhdGFWYWx1ZVRlbXBsYXRlKHZhcmlhdGlvbkRhdGFWYWx1ZVBheWxvYWQpO1x0XG5cdFx0XHRcdH1cdFxuXHRcdFx0XHRcblx0XHRcdFx0Ly8gQWRkIGNvbG9yIHN3YXRjaCBsZW5ndGggYm9vbGVhbiB0byB0ZW1wbGF0ZSBkYXRhXG5cdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhLnR5cGUgPT0gJ3N3YXRjaCcpIHtcblx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldCddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvclN3YXRjaCddKHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlLFxuXHRcdFx0XHRcdFx0b3B0aW9uczogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ10sXG5cdFx0XHRcdFx0XHRtdWx0aVN3YXRjaERpc3BsYXk6IGlzTXVsdGlTd2F0Y2gubGVuZ3RoID4gMCA/ICdkLWJsb2NrJyA6ICdkLW5vbmUnXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dmFyIHBsYWNlaG9sZGVyID0gdmFyaWF0aW9uRGF0YS5sYWJlbC5wbGFjZWhvbGRlcixcblx0XHRcdFx0XHRcdGFyaWFMYWJlbCA9IHZhcmlhdGlvbkRhdGEubGFiZWwucGxhY2Vob2xkZXI7XG5cblx0XHRcdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMgJiYgdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlID09PSAnc2l6ZScgJiYgdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQgPT09IG51bGwpIHtcblx0XHRcdFx0XHRcdHBsYWNlaG9sZGVyICs9ICcgKCcgKyB2YXJpYXRpb25EYXRhLmxhYmVsLm1lc3NhZ2UgKyAnKSc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkKSB7XG5cdFx0XHRcdFx0XHR2YXIgdmFyaWF0aW9uU2VsZWN0ZWRUZXh0ID0gKHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSA9PT0gJ3NpemUnKSA/IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnRleHQucmVwbGFjZSgnIDEvMicsICdcXHUwMEJEJykgOiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC50ZXh0O1xuXHRcdFx0XHRcdFx0dmFyIHdpZHRoRGVzY3JpcHRpb24gPSB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC53aWR0aERlc2NyaXB0aW9uID8gJzxzcGFuIGNsYXNzPVwid2lkdGgtZGVzY3JpcHRpb25cIj4nICsgdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQud2lkdGhEZXNjcmlwdGlvbiArICc8L3NwYW4+JyA6ICcnO1xuXG5cdFx0XHRcdFx0XHRwbGFjZWhvbGRlciA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JEcm9wZG93bk9wdGlvblNlbGVjdGVkJ10oe1xuXHRcdFx0XHRcdFx0XHR0ZXh0OiB2YXJpYXRpb25TZWxlY3RlZFRleHQsXG5cdFx0XHRcdFx0XHRcdHdpZHRoRGVzY3JpcHRpb246IHdpZHRoRGVzY3JpcHRpb24sXG5cdFx0XHRcdFx0XHRcdHN0b2NrOiB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5zdG9jayxcblx0XHRcdFx0XHRcdFx0c2hpcHBpbmc6IHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnNoaXBwaW5nLFxuXHRcdFx0XHRcdFx0XHRpc1NhbWVEYXlTaGlwcGluZ1dpbmRvdzogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQuaXNTYW1lRGF5U2hpcHBpbmdXaW5kb3csXG5cdFx0XHRcdFx0XHRcdHF1YW50aXR5U291cmNlVHlwZTogdmFyaWF0aW9uRGF0YVZhbHVlU2VsZWN0ZWQucXVhbnRpdHlTb3VyY2VUeXBlXG5cdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdFx0YXJpYUxhYmVsID0gJ0N1cnJlbnRseSBTZWxlY3RlZDogJyArIHZhcmlhdGlvbkRhdGFWYWx1ZVNlbGVjdGVkLnZhbHVlOyBcblx0XHRcdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5zaGlwcGluZykge1xuXHRcdFx0XHRcdFx0XHRhcmlhTGFiZWwgKz0gJyAtICcgKyB2YXJpYXRpb25EYXRhVmFsdWVTZWxlY3RlZC5zaGlwcGluZztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBBZGQgY29sb3Igc3dhdGNoIGxlbmd0aCBib29sZWFuIHRvIHRlbXBsYXRlIGRhdGFcblx0XHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcldpZGdldCddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvckRyb3Bkb3duJ10oe1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUsXG5cdFx0XHRcdFx0XHR0ZXh0OiBwbGFjZWhvbGRlcixcblx0XHRcdFx0XHRcdGFyaWFMYWJlbDogYXJpYUxhYmVsLFxuXHRcdFx0XHRcdFx0b3B0aW9uczogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXRPcHRpb25zJ10sXG5cdFx0XHRcdFx0XHRtdWx0aVN3YXRjaERpc3BsYXk6IGlzTXVsdGlTd2F0Y2gubGVuZ3RoID4gMCA/ICdkLWJsb2NrJyA6ICdkLW5vbmUnXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRodG1sWydhdHRyaWJ1dGVHdWlkZSddID0gJyc7XG5cdFx0XHRcdGlmICh2YXJpYXRpb25EYXRhLmF0dHJpYnV0ZUd1aWRlKSB7XG5cdFx0XHRcdFx0ZGF0YVsnYXR0cmlidXRlR3VpZGVzJ11bdmFyaWF0aW9uRGF0YS5wcm9kdWN0VmFyaWF0aW9uQXR0cmlidXRlXSA9IHZhcmlhdGlvbkRhdGEuYXR0cmlidXRlR3VpZGU7XG5cdFx0XHRcdFx0aHRtbFsnYXR0cmlidXRlR3VpZGUnXSA9IHRlbXBsYXRlc1sndmFyaWF0aW9uU2VsZWN0b3JBdHRyaWJ1dGVHdWlkZSddKF8uZXh0ZW5kKHZhcmlhdGlvbkRhdGEuYXR0cmlidXRlR3VpZGUsIHsgQXR0cmlidXRlOiB2YXJpYXRpb25EYXRhLnByb2R1Y3RWYXJpYXRpb25BdHRyaWJ1dGUgfSkpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvciddID0gdGVtcGxhdGVzWyd2YXJpYXRpb25TZWxlY3RvciddKHtcblx0XHRcdFx0XHRhdHRyaWJ1dGU6IHZhcmlhdGlvbkRhdGEucHJvZHVjdFZhcmlhdGlvbkF0dHJpYnV0ZSxcblx0XHRcdFx0XHRsYWJlbDoge1xuXHRcdFx0XHRcdFx0dGV4dDogdmFyaWF0aW9uRGF0YS5sYWJlbC50ZXh0LFxuXHRcdFx0XHRcdFx0bWVzc2FnZTogdmFyaWF0aW9uRGF0YS5sYWJlbC5tZXNzYWdlXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRzZWxlY3RvcjogaHRtbFsndmFyaWF0aW9uU2VsZWN0b3JXaWRnZXQnXSxcblx0XHRcdFx0XHRndWlkZTogaHRtbFsnYXR0cmlidXRlR3VpZGUnXVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRodG1sWyd2YXJpYXRpb25TZWxlY3RvcnMnXSArPSBodG1sWyd2YXJpYXRpb25TZWxlY3RvciddO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRodG1sWydzZWxlY3RvcnMnXSA9IHRlbXBsYXRlc1sndmFyaWF0aW9ucyddKHtcblx0XHRcdFx0c2VsZWN0b3JzOiBodG1sWyd2YXJpYXRpb25TZWxlY3RvcnMnXVxuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdGRhdGFbJ3NlbGVjdGVkJ10gPSByZXNwb25zZS5zZWxlY3RlZDtcblx0XHRcdGRhdGFbJ3BpZCddID0gcmVzcG9uc2UucGlkO1xuXHRcdFx0XG5cdFx0XHRsb2FkZWRbJ3NlbGVjdG9ycyddID0gdHJ1ZTtcblx0XHRcdHJlbmRlclZhcmlhdGlvblVwZGF0ZXMoKTtcbiAgICBcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHNldEFsdGVybmF0ZXMoKSB7XG5cdCQoJ3VsLmFsdGVybmF0ZS1pdGVtcyBsaScpLnNvcnQoZnVuY3Rpb24oYSxiKSB7IHJldHVybiAkKGEpLmRhdGEoJ2lkJykgLSAkKGIpLmRhdGEoJ2lkJyk7IH0pLmFwcGVuZFRvKCcuYWx0ZXJuYXRlLWl0ZW1zJyk7XG5cdHZhciBhbHRUeXBlID0gJCgndWwuYWx0ZXJuYXRlLWl0ZW1zJykuZGF0YSgnYWx0ZXJuYXRlJyk7XG5cdHZhciBhbHREZWZhdWx0ID0gJCgndWwuYWx0ZXJuYXRlLWl0ZW1zJykuZGF0YSgnZGVmYXVsdCcpO1xuXHR2YXIgYWx0ZXJuYXRlcyA9IFtdO1xuXG5cdHZhciBpc1N1YnNjcmlwdGlvblByb2R1Y3QgPSAkKCcucGRwLW1haW4nKS5oYXNDbGFzcygnc3Vic2NyaXB0aW9uLXByb2R1Y3QtdGVtcGxhdGUnKTtcblx0dmFyIGNvbG9yU2VsZWN0ZWQgPSAkKCcuY29sb3Itb3B0aW9ucyAuc2VsZWN0ZWQgYScpO1xuXHR2YXIgc2l6ZVNlbGVjdGVkID0gJCgnLnNpemUtb3B0aW9ucyAuc2VsZWN0ZWQgYScpLmRhdGEoJ3NpemUtaWQnKTtcblxuXHRpZiAoY29sb3JTZWxlY3RlZCAmJiBpc1N1YnNjcmlwdGlvblByb2R1Y3QpIHtcblx0XHRhbHRlcm5hdGVzLnB1c2goeydhbHRJRCc6ICQoY29sb3JTZWxlY3RlZCkucGFyZW50KCcuc2VsZWN0ZWQnKS5kYXRhKCdpZCcpLCAnYWx0VmFsdWUnOiAkKGNvbG9yU2VsZWN0ZWQpLmF0dHIoJ2RhdGEtY29sb3ItbmFtZScpfSk7XG5cdH1cblx0JCgndWwuYWx0ZXJuYXRlLWl0ZW1zIGxpJykuZWFjaChmdW5jdGlvbihpLCBlbGVtKSB7XG5cdFx0YWx0ZXJuYXRlcy5wdXNoKHsnYWx0SUQnOiAkKGVsZW0pLmRhdGEoJ2lkJyksICdhbHRWYWx1ZSc6ICQoZWxlbSkudGV4dCgpLnNwbGl0KCctJylbMV19KTtcblx0fSk7XG5cblx0aWYgKHNpemVTZWxlY3RlZCAmJiBzaXplU2VsZWN0ZWQubGVuZ3RoID4gMCAmJiAkKCcuYWx0ZXJuYXRlJykubGVuZ3RoID4gMCl7XG5cdFx0dXBkYXRlQWx0ZXJuYXRlcyhzaXplU2VsZWN0ZWQpO1xuXHR9IGVsc2UgaWYgKGFsdGVybmF0ZXMgJiYgYWx0ZXJuYXRlcy5sZW5ndGggPiAwKXtcblx0XHQkLmFqYXgoe1xuXHRcdFx0dXJsOiBVcmxzLmdldEl0ZW1BbHRlcm5hdGVzLFxuXHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0ZGF0YToge1xuXHRcdFx0XHQnYWx0ZXJuYXRlcyc6IEpTT04uc3RyaW5naWZ5KGFsdGVybmF0ZXMpXG5cdFx0XHR9LFxuXHRcdFx0c3VjY2VzcyA6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0dmFyIGFsdFN3YXRjaGVzID0gJyc7XG5cdFx0XHRcdHZhciBhbHRlcm5hdGUgPSBkYXRhLnJlc3VsdDtcblx0XHRcdFx0XG5cdFx0XHRcdCQuZWFjaChhbHRlcm5hdGUsIGZ1bmN0aW9uKGksIGUpe1xuXHRcdFx0XHRcdHZhciBpZCA9IGFsdGVybmF0ZVtpXS5pZDtcblx0XHRcdFx0XHR2YXIgdHlwZSA9IGFsdFR5cGUgPyBhbHRUeXBlIDogJ0NvbG9yJztcblx0XHRcdFx0XHR2YXIgdmFsdWUgPSBhbHRlcm5hdGVbaV0udmFsdWU7XG5cdFx0XHRcdFx0dmFyIGltYWdlID0gYWx0ZXJuYXRlW2ldLmltYWdlO1xuXHRcdFx0XHRcdHZhciB1cmwgPSAkKCcuYWx0ZXJuYXRlLWl0ZW1zIGxpW2RhdGEtaWQ9JytpZCsnXScpLmRhdGEoJ3VybCcpO1xuXHRcdFx0XHRcdHZhciBhbHRIaWRkZW4gPSAnc2hvdy1jb250ZW50Jztcblx0XHRcdFx0XHRpZiAoIGkgPj0gMTEgKXtcblx0XHRcdFx0XHRcdGFsdEhpZGRlbiA9ICdoaWRkZW4tY29udGVudCc7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggaXNTdWJzY3JpcHRpb25Qcm9kdWN0ICYmIGlkID09ICQoY29sb3JTZWxlY3RlZCkucGFyZW50KCcuc2VsZWN0ZWQnKS5kYXRhKCdpZCcpICl7XG5cdFx0XHRcdFx0XHQkKGNvbG9yU2VsZWN0ZWQpLmNzcygnYmFja2dyb3VuZCcsICd1cmwoJytpbWFnZSsnKScpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRhbHRTd2F0Y2hlcyArPSAnPGxpIGNsYXNzPVwidW5zZWxlY3RhYmxlIGFsdGVybmF0ZSAnICsgYWx0SGlkZGVuICsgJ1wiIGRhdGEtaWQ9XCInK2lkKydcIiBkYXRhLXR5cGU9XCInK2FsdFR5cGUrJ1wiIGRhdGEtdmFsdWU9XCInK3ZhbHVlKydcIj48YSBjbGFzcz1cInN3YXRjaGFuY2hvclwiIGhyZWY9XCInK3VybCsnXCIgdGl0bGU9XCJTZWxlY3QgJythbHRUeXBlKyc6ICcrdmFsdWUrJ1wiIHZhbHVlPVwiJyt2YWx1ZSsnXCIgc3R5bGU9XCJiYWNrZ3JvdW5kOiB1cmwoJytpbWFnZSsnP3N3PTcwJmFtcDtzaD03MCZhbXA7c209Zml0KTsgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsgYmFja2dyb3VuZC1zaXplOiBjb250YWluOyBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7XCI+PHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj5TZWxlY3QgJythbHRUeXBlKyc6Jyt2YWx1ZSsnPC9zcGFuPjwvYT48L2xpPic7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChhbHRTd2F0Y2hlcy5sZW5ndGggPiAwICl7XG5cdFx0XHRcdFx0JCgnLmNvbG9yLmNvbG9yLW9wdGlvbnMnKS5yZW1vdmVDbGFzcygnY29sb3ItZC1ub25lJykuYXBwZW5kKGFsdFN3YXRjaGVzKS5maW5kKCdsaScpLnNvcnQoZnVuY3Rpb24oYSxiKSB7IHJldHVybiAkKGEpLmRhdGEoJ2lkJykgLSAkKGIpLmRhdGEoJ2lkJyk7IH0pLmFwcGVuZFRvKCcuY29sb3Itb3B0aW9ucycpO1xuXHRcdFx0XHRcdGlmIChhbHRUeXBlICYmIGFsdERlZmF1bHQpe1xuXHRcdFx0XHRcdFx0JCgnLmNvbG9yLW9wdGlvbnMgLnNlbGVjdGVkJykuYXR0cignZGF0YS10eXBlJyxhbHRUeXBlKS5hdHRyKCdkYXRhLXZhbHVlJyxhbHREZWZhdWx0KS5maW5kKCdhLnN3YXRjaGFuY2hvcicpLmF0dHIoJ3RpdGxlJywnU2VsZWN0ICcrYWx0VHlwZSsnOiAnK2FsdERlZmF1bHQpO1xuXHRcdFx0XHRcdFx0dmFyIG5ld1RleHQgPSAnPHNwYW4gY2xhc3M9XCJ0ZXh0XCI+JythbHRUeXBlKyc8c3BhbiBjbGFzcz1cInNlcGFyYXRvclwiPjo8L3NwYW4+IDxzcGFuIGNsYXNzPVwiY3VycmVudCBjb2xvci1jdXJyZW50XCI+JythbHREZWZhdWx0Kyc8L3NwYW4+PC9zcGFuPic7XG5cdFx0XHRcdFx0XHQkKCcuYXR0cmlidXRlLWNvbG9yIC50ZXh0JykuaHRtbChuZXdUZXh0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdGlmIChzaXplU2VsZWN0ZWQgJiYgc2l6ZVNlbGVjdGVkLmxlbmd0aCA+IDApe1xuXHRcdFx0XHRcdHVwZGF0ZUFsdGVybmF0ZXMoc2l6ZVNlbGVjdGVkKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0dmFyIGFsdEhpZGRlbkNvdW50ID0gJCgnLmhpZGRlbi1jb250ZW50JykubGVuZ3RoO1xuXHRcdFx0XHR2YXIgYWx0SGlkZGVuVG9nZ2xlID0gJysgJyArIGFsdEhpZGRlbkNvdW50O1xuXHRcdFx0XHRpZiAoYWx0SGlkZGVuQ291bnQgPiAwKXtcblx0XHRcdFx0XHQkKCcuaGlkZGVuLWNvbnRlbnQnKS5oaWRlKCk7XG5cdFx0XHRcdFx0JCgnLmNvbG9yLmNvbG9yLW9wdGlvbnMnKS5hcHBlbmQoJzxidXR0b24gY2xhc3M9XCJhbHRCdXR0b25cIj4nICsgYWx0SGlkZGVuVG9nZ2xlICsgJzwvYnV0dG9uPicpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JCgnYnV0dG9uLmFsdEJ1dHRvbicpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuXHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJy5jb2xvci1vcHRpb25zJykuZmluZCgnLmhpZGRlbi1jb250ZW50JykudG9nZ2xlKCk7XG5cdFx0XHRcdFx0JCgnLmFsdEJ1dHRvbicpLmhpZGUoKTtcblx0XHRcdFx0fSlcblx0XHRcdFx0XG5cdFx0XHRcdCQoXCIuY29sb3Itb3B0aW9ucyBsaVwiKS5ob3ZlcihmdW5jdGlvbigpe1xuXHRcdFx0XHRcdHZhciBhbHRUaXRsZSA9ICQodGhpcykuZGF0YSgndHlwZScpO1xuXHRcdFx0XHRcdHZhciBhbHRWYWx1ZSA9ICQodGhpcykuZGF0YSgndmFsdWUnKTtcblx0XHRcdFx0XHR2YXIgbmV3VGV4dCA9ICc8c3BhbiBjbGFzcz1cInRleHRcIj4nK2FsdFR5cGUrJzxzcGFuIGNsYXNzPVwic2VwYXJhdG9yXCI+Ojwvc3Bhbj4gPHNwYW4gY2xhc3M9XCJjdXJyZW50IGNvbG9yLWN1cnJlbnRcIj4nK2FsdFZhbHVlKyc8L3NwYW4+PC9zcGFuPic7XG5cdFx0XHRcdFx0JCgnLmF0dHJpYnV0ZS1jb2xvciAudGV4dCcpLmh0bWwobmV3VGV4dCk7XG5cdFx0XHRcdH0sIGZ1bmN0aW9uKCl7XG5cdFx0XHRcdFx0dmFyIGFsdFRpdGxlID0gJCgnLmNvbG9yLW9wdGlvbnMgLnNlbGVjdGVkJykuZGF0YSgndHlwZScpO1xuXHRcdFx0XHRcdHZhciBhbHRWYWx1ZSA9ICQoJy5jb2xvci1vcHRpb25zIC5zZWxlY3RlZCcpLmRhdGEoJ3ZhbHVlJyk7XG5cdFx0XHRcdFx0dmFyIG5ld1RleHQgPSAnPHNwYW4gY2xhc3M9XCJ0ZXh0XCI+JythbHRUeXBlKyc8c3BhbiBjbGFzcz1cInNlcGFyYXRvclwiPjo8L3NwYW4+IDxzcGFuIGNsYXNzPVwiY3VycmVudCBjb2xvci1jdXJyZW50XCI+JythbHRWYWx1ZSsnPC9zcGFuPjwvc3Bhbj4nO1xuXHRcdFx0XHRcdCQoJy5hdHRyaWJ1dGUtY29sb3IgLnRleHQnKS5odG1sKG5ld1RleHQpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVBbHRlcm5hdGVzKHNpemVTZWxlY3RlZCkge1xuXHR2YXIgYWx0dXBkYXRlcyA9IFtdO1xuXHQkKCd1bC5jb2xvci1vcHRpb25zIGxpJykuZWFjaChmdW5jdGlvbihpLCBlbGVtKSB7XG5cdFx0YWx0dXBkYXRlcy5wdXNoKFN0cmluZygkKGVsZW0pLmRhdGEoJ2lkJykpKTtcblx0fSk7XG5cdFxuXHRpZihhbHR1cGRhdGVzICYmIGFsdHVwZGF0ZXMubGVuZ3RoID4gMCl7XG5cdFx0JC5hamF4KHtcblx0XHRcdHVybDogVXJscy51cGRhdGVJdGVtQWx0ZXJuYXRlcyxcblx0XHRcdGRhdGFUeXBlOiAnSlNPTicsXG5cdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdGRhdGE6IHtcblx0XHRcdFx0J2FsdHVwZGF0ZXMnOiBKU09OLnN0cmluZ2lmeShhbHR1cGRhdGVzKSxcblx0XHRcdFx0J3NpemUnOiBzaXplU2VsZWN0ZWRcblx0XHRcdH0sXG5cdFx0XHRzdWNjZXNzIDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHR2YXIgYWx0ZXJuYXRlID0gZGF0YS5yZXN1bHQ7XG5cdFx0XHRcdFxuXHRcdFx0XHQkLmVhY2goYWx0ZXJuYXRlLCBmdW5jdGlvbihpLCBlKXtcblx0XHRcdFx0XHR2YXIgaWQgPSBhbHRlcm5hdGVbaV0uaWQ7XG5cdFx0XHRcdFx0dmFyIGFwcGVuZFVSTCA9IGFsdGVybmF0ZVtpXS5hcHBlbmRVUkw7XG5cdFx0XHRcdFx0dmFyIHNpemVBdmFpbGFibGUgPSAhYWx0ZXJuYXRlW2ldLnNpemVBdmFpbGFibGU7XG5cdFx0XHRcdFx0dmFyIG9sZFVSTCA9ICQoJ3VsLmNvbG9yLW9wdGlvbnMgbGlbZGF0YS1pZD0nK2lkKyddIGEnKS5hdHRyKCdocmVmJyk7XG5cdFx0XHRcdFx0dmFyIG5ld1VSTCA9IG9sZFVSTCArIGFwcGVuZFVSTDtcblx0XHRcdFx0XHQkKCd1bC5jb2xvci1vcHRpb25zIGxpLmFsdGVybmF0ZVtkYXRhLWlkPVwiJytpZCsnXCJdIGEnKS5hdHRyKCdocmVmJyxuZXdVUkwpO1xuXHRcdFx0XHRcdGlmKGFwcGVuZFVSTCA9PSBudWxsIHx8ICh0eXBlb2YgYXBwZW5kVVJMID09PSBcInN0cmluZ1wiICYmIGFwcGVuZFVSTC50cmltKCkubGVuZ3RoID09PSAwKSl7XG5cdFx0XHRcdFx0XHQkKCd1bC5jb2xvci1vcHRpb25zIGxpW2RhdGEtaWQ9JytpZCsnXSBhJykuYWRkQ2xhc3MoJ25vLXNpemUnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclZhcmlhdGlvblVwZGF0ZXMoKSB7XG5cdGlmIChsb2FkZWRbJ2NvbnRlbnQnXSAmJiBsb2FkZWRbJ3NlbGVjdG9ycyddKSB7XG5cdFx0cmVuZGVyU2VsZWN0b3JzKCk7XG5cdFx0dXBkYXRlUGlkKCk7XG5cdFx0c2V0QWx0ZXJuYXRlcygpO1xuXHRcdFxuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1NhbWVEYXlTaGlwcGluZ0NvdW50ZG93bi5VcGRhdGUnKTtcblx0XHRcblx0XHR2YXIgc2l6ZVNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAuc2l6ZS5zaXplLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKTtcblx0XHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdHZhciBpc1NpemVTZWxlY3RlZCA9IHNpemVTZWxlY3RlZC5sZW5ndGggfHwgKGxlbmd0aFNlbGVjdGVkICYmIHdpZHRoU2VsZWN0ZWQpO1xuXHRcdHZhciBpc0NvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdFxuXHRcdHVwZGF0ZVdpc2hsaXN0QnV0dG9uKHNpemVTZWxlY3RlZCk7XG5cblx0XHRpZiAoaXNTaXplU2VsZWN0ZWQpIHtcblx0XHRcdCQoJy5hdHRyaWJ1dGUtc2l6ZScpLmFkZENsYXNzKCdzaXplLXNlbGVjdGVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5hdHRyaWJ1dGUtc2l6ZScpLnJlbW92ZUNsYXNzKCdzaXplLXNlbGVjdGVkJyk7XG5cdFx0fVxuXHQgICAgaWYgKGlzU2l6ZVNlbGVjdGVkICYmIGlzQ29sb3JTZWxlY3RlZCkge1xuXHRcdFx0JCgnLmJ0bi5zdG9yZS1zZWFyY2gnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXG5cdCAgICBcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLlZhcmlhbnQuU2VsZWN0ZWQnKTtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1Byb2R1Y3REZXRhaWxQYWdlLlZhcmlhbnQuQWRkVG9DYXJ0T3B0aW9ucycpO1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUHJvZHVjdERldGFpbFBhZ2UuVmFyaWFudC5TdG9yZVNlYXJjaCcpO1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ3VycmVuY3kuVXBkYXRlJywgJCgnI3Byb2R1Y3QtY29udGVudCcpKTtcblx0ICAgIH1cblx0ICAgIFxuICAgIFx0dmFyICRzZWxlY3RhYmxlQ291bnQgPSAwO1xuICAgIFx0JCgnLnByb2R1Y3Qtb3B0aW9ucyAuYXR0cmlidXRlLXNpemUgLnNlbGVjdC1kcm9wZG93biB1bC5zaXplLW9wdGlvbnMgbGksIC5wcm9kdWN0LW9wdGlvbnMgLmF0dHJpYnV0ZS1zaXplIC5zZWxlY3QtZHJvcGRvd24gdWwubGVuZ3RoLW9wdGlvbnMgbGknKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICBcdHZhciAkc2VsZWN0Q2xhc3MgPSAkKHRoaXMpLmF0dHIoJ2NsYXNzJykucmVwbGFjZSgnc2VsZWN0ZWQnLCcnKS50cmltKCk7XG4gICAgICAgIFx0aWYoICRzZWxlY3RDbGFzcyA9PSAnc2VsZWN0YWJsZScpe1xuICAgICAgICBcdFx0JHNlbGVjdGFibGVDb3VudCsrO1xuICAgICAgICBcdH0gICAgICAgIFxuICAgICAgICB9KTtcblxuXHRcdGlmIChkYXRhWydJc1Jlc3RyaWN0ZWRCeUdsb2JhbGUnXSB8fCAkc2VsZWN0YWJsZUNvdW50ID09IDApIHtcblx0XHRcdCQoJy5zYW1lLWRheS1zaGlwcGluZy1jb3VudGRvd24nKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHQkKCcucHJvZHVjdC1vcHRpb25zIC5hdHRyaWJ1dGUtc2l6ZSAuc2VsZWN0LWRyb3Bkb3duJykuY3NzKHtcInBvaW50ZXItZXZlbnRzXCI6IFwibm9uZVwiLCBcImN1cnNvclwiOiBcImRlZmF1bHRcIn0pO1xuXHRcdFx0JCgnLnByb2R1Y3QtdmFyaWF0aW9uJykuYWRkQ2xhc3MoJ25vdC1hdmFpbGFibGUnKTtcblx0XHRcdGlmICgkKCcuY29sb3Itb3B0aW9ucyAuc2VsZWN0YWJsZScpLmxlbmd0aCA+IDEgfHwgJCgnLmFsdGVybmF0ZS1pdGVtcyBsaScpLmxlbmd0aCA+IDEpIHtcblx0XHRcdFx0JCgnLnByb2R1Y3QtdmFyaWF0aW9uJykuYWRkQ2xhc3MoJ2NvbG9ycy1zZWxlY3RhYmxlJyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoZGF0YVsnSXNSZXN0cmljdGVkQnlHbG9iYWxlJ10pIHtcblx0XHRcdFx0JCgnLnByb2R1Y3QtZ2xvYmFsZS11bmF2YWlsYWJsZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH0gZWxzZSBpZiAoJHNlbGVjdGFibGVDb3VudCA9PSAwKSB7XG5cdFx0XHRcdCQoJy5wcm9kdWN0LW91dC1vZi1zdG9jaycpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQcm9kdWN0RGV0YWlsUGFnZS5WYXJpYW50LlVwZGF0ZWQnKTtcblx0fVxufVxuXG5mdW5jdGlvbiByZW5kZXJTZWxlY3RvcnMoKSB7XG5cdCQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKS5odG1sKGh0bWxbJ3NlbGVjdG9ycyddKTtcblx0JCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLmF0dHIoJ2RhdGEtYXR0cmlidXRlcycsIEpTT04uc3RyaW5naWZ5KGRhdGFbJ3NlbGVjdGVkJ10pKTtcblx0Y2hlY2tGb3JTZWxlY3RlZFN3YXRjaCgkKCcucHJvZHVjdC12YXJpYXRpb25zJykpO1xuXG5cdCQoJy5hdHRyaWJ1dGUtZ3VpZGUtbGluaycpLmZhbmN5Ym94KCk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrRm9yU2VsZWN0ZWRTd2F0Y2goJGNvbnRhaW5lcikge1xuXHR2YXIgc3dhdGNoSXNTZWxlY3RlZCA9ICRjb250YWluZXIuZmluZCgnLmNvbG9yLW9wdGlvbnMgLnNlbGVjdGFibGUuc2VsZWN0ZWQnKS5sZW5ndGggPiAwO1xuXHRpZiAoIXN3YXRjaElzU2VsZWN0ZWQpIHtcblx0XHQkY29udGFpbmVyLmZpbmQoJy5jb2xvci1vcHRpb25zIC5zZWxlY3RhYmxlOmZpcnN0LWNoaWxkPi5zd2F0Y2hhbmNob3InKS5tb3VzZWVudGVyKCk7XG5cdH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gdXBkYXRlIHByb2R1Y3QgY29udGVudCB3aXRoIG5ldyB2YXJpYW50IGZyb20gaHJlZiwgbG9hZCBuZXcgY29udGVudCB0byAjcHJvZHVjdC1jb250ZW50IHBhbmVsXG4gKiBAcGFyYW0ge1N0cmluZ30gaHJlZiAtIHVybCBvZiB0aGUgbmV3IHByb2R1Y3QgdmFyaWFudFxuICoqL1xudmFyIHVwZGF0ZUNvbnRlbnQgPSBmdW5jdGlvbiAoaHJlZikge1xuXHRsb2FkZWRbJ2NvbnRlbnQnXSA9IGZhbHNlO1xuXHQkKCcuYnRuLmFkZC10by1jYXJ0JykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKS5sb2FkaW5nKCk7XG5cdHZhciBib3Bpc1N0b3JlU2VhcmNoUG9zdGFsQ29kZSA9ICQoJy5ib3Bpcy1zdG9yZS1zZWFyY2ggaW5wdXRbbmFtZT1cIkJvcGlzX1N0b3JlU2VhcmNoX3Bvc3RhbENvZGVcIl0nKS52YWwoKTtcbiAgICB2YXIgJHBkcEZvcm0gPSAkKCcucGRwRm9ybScpO1xuICAgIHZhciBxdHkgPSAkcGRwRm9ybS5maW5kKCdzZWxlY3RbbmFtZT1cIlF1YW50aXR5XCJdJykuZmlyc3QoKS52YWwoKTtcbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBRdWFudGl0eTogaXNOYU4ocXR5KSA/ICcxJyA6IHF0eSxcbiAgICAgICAgZm9ybWF0OiAnYWpheCcsXG4gICAgICAgIHByb2R1Y3RsaXN0aWQ6ICRwZHBGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwaWRcIl0nKS5maXJzdCgpLnZhbCgpLFxuICAgICAgICBCb3Bpc0VuYWJsZWQ6ICQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5sZW5ndGggPiAwID8gdHJ1ZSA6IGZhbHNlLFxuXHRcdFRva2VuOiAkKCcuYm9waXMtc3RvcmUtc2VhcmNoIGlucHV0W25hbWU9XCJjc3JmX3Rva2VuXCJdJykudmFsKClcbiAgICB9O1xuXG4gICAgYnVpbGRTZWxlY3RvcnModXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh1dGlsLmdldFF1ZXJ5U3RyaW5nKHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoaHJlZiwgcGFyYW1zKSkpKTtcblx0JC5hamF4KHtcbiAgICBcdG1ldGhvZDogJ0dFVCcsXG4gICAgXHR1cmw6IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoaHJlZiwgcGFyYW1zKSxcbiAgICBcdGNvbXBsZXRlOiBmdW5jdGlvbihodG1sKSB7XG5cdFx0XHRsb2FkZWRbJ2NvbnRlbnQnXSA9IHRydWU7XG5cdFx0XHQkKCcjcHJvZHVjdC1jb250ZW50JykuaHRtbChodG1sLnJlc3BvbnNlVGV4dCk7XG5cdFx0XHRyZW5kZXJWYXJpYXRpb25VcGRhdGVzKCk7XG5cblx0XHRcdGlmIChib3Bpc1N0b3JlU2VhcmNoUG9zdGFsQ29kZSkge1xuICAgICAgICBcdFx0JCgnLmJvcGlzLXN0b3JlLXNlYXJjaCBpbnB1dFtuYW1lPVwiQm9waXNfU3RvcmVTZWFyY2hfcG9zdGFsQ29kZVwiXScpLnZhbChib3Bpc1N0b3JlU2VhcmNoUG9zdGFsQ29kZSk7XG4gICAgICAgIFx0fVxuICAgICAgICBcdFxuICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgICAgICAgICBwcm9kdWN0U3RvcmVJbnZlbnRvcnkuaW5pdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW1hZ2UucmVwbGFjZUltYWdlcygpO1xuICAgICAgICAgICAgdG9vbHRpcC5pbml0KCk7XG4gICAgICAgICAgICAvLyByYXRpbmcuaW5pdCgpO1xuICAgICAgICAgICAgdXBkYXRlUHJvZHVjdEluZm8oKTtcbiAgICAgICAgICAgIGluaXRpYWxpemVJbWFnZUdhbGxlcnkoKTsgICAgICAgICAgICBcblx0XHRcdHVwZGF0ZUNTUkZUb2tlbigpO1xuXHRcdFx0Ly8gR29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnVmlld0l0ZW0nKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpeyQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VwZGF0ZS1yZXZpZXctdGV4dCcpO30sIDUwMCk7XG5cbiAgICAgICAgICAgIGlmICgnYWZmaXJtJyBpbiB3aW5kb3cgJiYgJ3VpJyBpbiBhZmZpcm0gJiYgJ3JlZnJlc2gnIGluIGFmZmlybS51aSkge1xuXHRcdFx0ICAgIGFmZmlybS51aS5yZWZyZXNoKCk7XG5cdFx0XHR9XG4gICAgICAgICAgICBcblx0XHRcdHZhciB2YXJpYW50U2VsZWN0ZWQgPSBpc1ZhcmlhbnRTZWxlY3RlZCgpO1xuICAgICAgICAgICAgaWYgKCQoJy5ib3Bpcy1zdG9yZS1zZWFyY2gnKS5sZW5ndGggPiAwIHx8ICQoJy5ib3Bpcy1hZGQtdG8tY2FydC1vcHRpb25zLWNvbnRhaW5lcicpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIFx0aWYgKHZhcmlhbnRTZWxlY3RlZCkge1xuICAgICAgICAgICAgXHRcdG9wdGlvbnMuQm9waXMuSXNWYXJpYW50U2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgXHR9XG5cdFx0XHRcdGluaXRpYWxpemVCb3BpcygpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRcdFx0dXBkYXRlQWRkVG9DYXJ0UmVjb21tZW5kYXRpb25zKCk7XG5cdFx0XHR9XG5cdFx0XHQkKCcuYnRuLmFkZC10by1jYXJ0JykucmVtb3ZlQXR0cignZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdsb2FkaW5nJykuZmluZCgnLmxvYWRpbmctaW5kaWNhdG9yLWNvbnRhaW5lcicpLnJlbW92ZSgpOyAgICBcdFx0XG4gICAgXHR9XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBpc1ZhcmlhbnRTZWxlY3RlZCgpIHtcblx0dmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHR2YXIgbGVuZ3RoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5sZW5ndGgubGVuZ3RoLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdHZhciB3aWR0aFNlbGVjdGVkID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyAud2lkdGgud2lkdGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0dmFyIGNvbG9yU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5jb2xvci5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXG5cdHJldHVybiAoc2l6ZVNlbGVjdGVkIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKSkgJiYgY29sb3JTZWxlY3RlZDtcbn1cblxuZnVuY3Rpb24gdXBkYXRlQWRkVG9DYXJ0UmVjb21tZW5kYXRpb25zKCkge1xuXHR2YXIgaW50ZXJ2YWxDb3VudCA9IDA7XG5cdHZhciBhZGRUb0NhcnRSZWNvbW1lbmRhdGlvbnNDaGVjayA9IHNldEludGVydmFsKGZ1bmN0aW9uKCkge1xuXHRcdGlmICggJCgnLnJlY29tbS1wcm9kLXBkcC1hMmMtc2xvdCAuYWNjb3JkaW9uLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zJykubGVuZ3RoID4gMCApIHtcblx0XHRcdGNsZWFySW50ZXJ2YWwoYWRkVG9DYXJ0UmVjb21tZW5kYXRpb25zQ2hlY2spO1xuXHRcdFx0aW5pdFNsaWRlcigpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChpbnRlcnZhbENvdW50ID09PSA1MCkge1xuXHRcdFx0Y2xlYXJJbnRlcnZhbChhZGRUb0NhcnRSZWNvbW1lbmRhdGlvbnNDaGVjayk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aW50ZXJ2YWxDb3VudCsrO1xuXHR9LCAyMDApO1xuXG5cdGZ1bmN0aW9uIGluaXRTbGlkZXIoKSB7XG5cdFx0c2xpZGVycy5pbml0KCcucmVjb21tLXByb2QtcGRwLWEyYy1zbG90IC5hY2NvcmRpb24ucHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMgLnNsaWRlcycsIHticmVha3BvaW50czogezA6IHtzbGlkZXNUb1Nob3c6IDEsIGFycm93czogdHJ1ZSwgZG90czogdHJ1ZX0sIDc2ODoge3NsaWRlc1RvU2hvdzogMywgYXJyb3dzOiB0cnVlLCBkb3RzOiBmYWxzZX0sIDEwMjQ6IHtzbGlkZXNUb1Nob3c6IDQsIGFycm93czogdHJ1ZSwgZG90czogZmFsc2V9fX0sIHRydWUpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHNpemVNZW51T3BlbkNsb3NlKGV2ZW50LCBlbCwgb3Blbikge1xuXHR2YXIgJHRoaXMgPSBlbDtcblx0dmFyICRjb250YWluZXIgPSAkdGhpcy5jbG9zZXN0KCcuc2VsZWN0LWRyb3Bkb3duJyk7XG5cdHZhciAkbWVudSA9ICRjb250YWluZXIuZmluZCgnLnNlbGVjdC1kcm9wZG93bi1pbm5lcicpO1xuXHRcblx0aWYgKG9wZW4pIHtcblx0XHQkdGhpcy5hZGRDbGFzcygnYWN0aXZlJyk7XG5cdFx0JG1lbnUuYWRkQ2xhc3MoJ2V4cGFuZCcpO1xuXHRcdCRtZW51LmZpbmQoJ2xpLnNlbGVjdGFibGUgYScpLnJlbW92ZUF0dHIoJ3RhYmluZGV4Jyk7XG5cdH0gZWxzZSB7XG5cdFx0JHRoaXMucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdCRtZW51LnJlbW92ZUNsYXNzKCdleHBhbmQnKTtcblx0XHQkbWVudS5maW5kKCdsaS5zZWxlY3RhYmxlIGEnKS5hdHRyKCd0YWJpbmRleCcsICctMScpO1xuXHRcdGlmICgkbWVudS5maW5kKCcudGVtcHNlbGVjdGlvbicpLmxlbmd0aCA+IDApIHtcblx0XHRcdCRtZW51LmZpbmQoJy50ZW1wc2VsZWN0aW9uJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkIHRlbXBzZWxlY3Rpb24nKTtcblx0XHR9XG5cdFx0aWYgKGV2ZW50LmtleUNvZGUpIHtcblx0XHRcdCRjb250YWluZXIuYWRkQ2xhc3MoJ2ZvY3VzLXZpc2libGUtaW5kaWNhdG9yJykuZm9jdXMoKTtcblx0XHR9XG5cdH1cblxuXHRpZiAoJG1lbnUuaGFzQ2xhc3MoJ2V4cGFuZCcpKSB7XG5cdFx0c2Nyb2xsVG9DdXJyZW50U2l6ZSgpO1xuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdCRtZW51LmFkZENsYXNzKCdleHBhbmQtY2xvc2UnKTtcblx0XHR9LCAxMDApO1xuXHR9IGVsc2Uge1xuXHRcdCRtZW51LnJlbW92ZUNsYXNzKCdleHBhbmQtY2xvc2UnKTtcblx0fVxufVxuXG5mdW5jdGlvbiBzZWxlY3RTaXplT3B0aW9uKGVsKSB7XG5cdHZhciAkc2VsZWN0ZWQgPSAkKGVsKTtcblx0XG5cdCRzZWxlY3RlZFxuXHRcdC5hZGRDbGFzcygnc2VsZWN0ZWQnKVxuXHRcdC5zaWJsaW5ncygpXG5cdFx0LnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xuXG5cdCRzZWxlY3RlZFxuXHRcdC5jbG9zZXN0KCcuc2VsZWN0LWRyb3Bkb3duLWlubmVyJylcblx0XHQucmVtb3ZlQ2xhc3MoJ2V4cGFuZCcpXG5cdFx0LnJlbW92ZUNsYXNzKCdleHBhbmQtY2xvc2UnKVxuXHRcdC5wcmV2KCcuc2VsZWN0LXRleHQnKVxuXHRcdC5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVdpc2hsaXN0QnV0dG9uKHNpemVTZWxlY3RlZCkge1xuXHR2YXIgdmFyaWFudElkID0gJCgnI3BpZCcpLnZhbCgpO1xuXHR2YXIgaXNXaXNobGlzdEl0ZW0gPSB3aXNobGlzdC5jaGVja1dpc2hsaXN0Rm9ySXRlbSh2YXJpYW50SWQpO1xuXHR2YXIgc2l6ZVRleHQgPSAnJztcblxuXHRpZiAoc2l6ZVNlbGVjdGVkKSB7XG5cdFx0c2l6ZVRleHQgPSBzaXplU2VsZWN0ZWQuZmluZCgnLnNpemUnKS50ZXh0KCk7XG5cdH1cblx0aWYgKGlzV2lzaGxpc3RJdGVtKSB7IFxuXHRcdHdpc2hsaXN0LnByZXBhcmVXaXNobGlzdFJlbW92ZVVJKCQoJy5wZHAtbWFpbiAud2lzaGxpc3QtaXRlbS1zdGF0dXMtYnV0dG9uJyksIHNpemVUZXh0KTtcblx0fSBlbHNlIHtcblx0XHR3aXNobGlzdC5wcmVwYXJlV2lzaGxpc3RBZGRVSSgkKCcucGRwLW1haW4gLndpc2hsaXN0LWl0ZW0tc3RhdHVzLWJ1dHRvbicpLCBudWxsLCBzaXplVGV4dCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cyAoKSB7XG5cdHZhciAkcGRwTWFpbiA9ICQoJyNwZHBNYWluJyk7XG5cbiAgICAvLyBob3ZlciBvbiBzd2F0Y2ggLSBzaG91bGQgdXBkYXRlIG1haW4gaW1hZ2Ugd2l0aCBzd2F0Y2ggaW1hZ2UuXG4vLyAgICAkcGRwTWFpbi5vZmYoJ21vdXNlZW50ZXIuVmFyaWFudC5Td2F0Y2hBbmNob3InKS5vbignbW91c2VlbnRlci5WYXJpYW50LlN3YXRjaEFuY2hvcicsICcuY29sb3I+bGk+LnN3YXRjaGFuY2hvcicsIGZ1bmN0aW9uIChlKSB7XG4vLyAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuLy8gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7IHJldHVybjsgfVxuLy8gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3NlbGVjdGVkJykpIHsgcmV0dXJuOyB9XG4vLyAgICAgICAgdXBkYXRlQ29udGVudCh0aGlzLmhyZWYpO1xuLy8gICAgfSk7XG5cbiAgICAvLyBjbGljayBvbiBzd2F0Y2ggLSBzaG91bGQgdXBkYXRlIG1haW4gaW1hZ2Ugd2l0aCBzd2F0Y2ggaW1hZ2UuXG4gICAgJHBkcE1haW4ub2ZmKCdjbGljay5WYXJpYW50LlN3YXRjaEFuY2hvcicpLm9uKCdjbGljay5WYXJpYW50LlN3YXRjaEFuY2hvcicsICcucHJvZHVjdC1kZXRhaWwgLnN3YXRjaGFuY2hvcicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgZGlkUmVsb2FkID0gZmFsc2U7XG4gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7XG4gICAgICAgIFx0aWYgKCQodGhpcykucGFyZW50cygnbGknKS5oYXNDbGFzcygnYWx0ZXJuYXRlJykpIHtcbiAgICAgICAgXHRcdHZhciBhbHRVcmxMb2FkID0gJCh0aGlzKS5hdHRyKCdocmVmJyk7ICAgIFx0XHRcbiAgICAgICAgXHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gYWx0VXJsTG9hZDtcbiAgICAgICAgXHR9XG4gICAgICAgIFx0XG4gICAgICAgIFx0JCgnbGkuZHJvcC1kb3duLXNlbGVjdC12YWx1ZScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgXHRcdFx0dmFyICRzZWxlY3RlZEl0ZW0gPSAkKHRoaXMpO1xuICAgIFx0XHRcdCRzZWxlY3RlZEl0ZW0uc2libGluZ3MoJ2xpLnNlbGVjdGVkLXZhbHVlJykuaHRtbCgkc2VsZWN0ZWRJdGVtLmh0bWwoKSk7XG4gICAgICAgIFx0XHQkc2VsZWN0ZWRJdGVtLnBhcmVudHMoJy5hdHRyaWJ1dGUnKS5maXJzdCgpLmZpbmQoJy5sYWJlbCAuY3VycmVudCwgLnNlbGVjdC1kcm9wZG93biAuc2VsZWN0LXRleHQnKS5odG1sKCRzZWxlY3RlZEl0ZW0uaHRtbCgpKTtcbiAgICAgICAgXHRcdGlmICggJHNlbGVjdGVkSXRlbS5wYXJlbnRzKCcuc2VsZWN0LWRyb3Bkb3duLWlubmVyJykgIT0gbnVsbCApIHtcbiAgICAgICAgXHRcdFx0JHNlbGVjdGVkSXRlbS5wYXJlbnRzKCcuc2VsZWN0LWRyb3Bkb3duLWlubmVyJykuZmluZCggJ2xpLnNlbGVjdGVkJyApLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xuICAgICAgICBcdFx0fVxuICAgICAgICBcdH0pO1xuICAgIFx0XHRpZiAoICQodGhpcykuYXR0cigneGhyZWYnKSAhPSBudWxsICkge1xuICAgIFx0XHRcdHVwZGF0ZUNvbnRlbnQoJCh0aGlzKS5hdHRyKCd4aHJlZicpKTtcbiAgICBcdFx0XHRkaWRSZWxvYWQgPSB0cnVlO1xuICAgIFx0XHR9IGVsc2UgeyByZXR1cm47IH1cbiAgICBcdH1cbiAgICAgICAgaWYgKCAhZGlkUmVsb2FkICkge1xuXHQgICAgICAgIHZhciBsaW5rID0gdGhpcztcblx0ICAgICAgICBpZiAoIWxpbmsuaHJlZikge1xuXHQgICAgICAgIFx0bGluayA9ICQodGhpcykucGFyZW50KClbMF07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHVwZGF0ZUNvbnRlbnQobGluay5ocmVmKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gY2hhbmdlIGRyb3AgZG93biB2YXJpYXRpb24gYXR0cmlidXRlIC0gc2hvdWxkIHJlcGxhY2UgcHJvZHVjdCBjb250ZW50IHdpdGggbmV3IHZhcmlhbnRcbiAgICAkcGRwTWFpbi5vZmYoJ2NoYW5nZS5WYXJpYW50LlZhcmlhdGlvblNlbGVjdCcpLm9uKCdjaGFuZ2UuVmFyaWFudC5WYXJpYXRpb25TZWxlY3QnLCAnLnZhcmlhdGlvbi1zZWxlY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgkKHRoaXMpLnZhbCgpLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAgICAgdXBkYXRlQ29udGVudCgkKHRoaXMpLnZhbCgpKTtcbiAgICB9KTtcblxuXHQvLyBDdXN0b20gU2VsZWN0IERyb3Bkb3duXG4gICAgJHBkcE1haW4ub2ZmKCdjbGljay5WYXJpYW50LlNlbGVjdG9yLkV4cGFuZCcpLm9uKCdjbGljay5WYXJpYW50LlNlbGVjdG9yLkV4cGFuZCcsICcuc2VsZWN0LWRyb3Bkb3duIC5zZWxlY3QtdGV4dCcsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgdG9nZ2xlT3BlbiA9ICEkdGhpcy5oYXNDbGFzcygnYWN0aXZlJyk7XG5cdFx0c2l6ZU1lbnVPcGVuQ2xvc2UoZXZlbnQsICR0aGlzLCB0b2dnbGVPcGVuKTtcblx0fSk7XG5cbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlZhcmlhbnQuR2VuZXJhbC5DbG9zZScpLm9uKCdjbGljay5WYXJpYW50LkdlbmVyYWwuQ2xvc2UnLCBmdW5jdGlvbihldmVudCkge1xuICAgIFx0JCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyB1bC5zZWxlY3QtZHJvcGRvd24taW5uZXIuZXhwYW5kLWNsb3NlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgXHRcdCQodGhpcykuc2libGluZ3MoJy5zZWxlY3QtdGV4dCcpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgXHR9KTtcblx0fSk7XG5cblx0JHBkcE1haW4ub2ZmKCdjbGljay5WYXJpYW50LlNlbGVjdG9yLlNlbGVjdCcpLm9uKCdjbGljay5WYXJpYW50LlNlbGVjdG9yLlNlbGVjdCcsICcuc2VsZWN0LWRyb3Bkb3duIC5zZWxlY3RhYmxlJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNlbGVjdFNpemVPcHRpb24odGhpcyk7XG5cdH0pO1xuXG5cdC8vIENvbG9yIE9wdGlvbnNcbiAgICAkcGRwTWFpbi5vZmYoJ2NsaWNrLlZhcmlhbnQuQ29sb3IuU2VsZWN0Jykub24oJ2NsaWNrLlZhcmlhbnQuQ29sb3IuU2VsZWN0JywgJy5jb2xvci1vcHRpb25zIGEnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyIG5hbWVDb2xvciA9ICQodGhpcykuZGF0YSgnY29sb3ItbmFtZScpO1xuXG5cdFx0JCh0aGlzKVxuXHRcdFx0LnBhcmVudCgpXG5cdFx0XHQuYWRkQ2xhc3MoJ3NlbGVjdGVkJylcblx0XHRcdC5zaWJsaW5ncygpXG5cdFx0XHQucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG5cblx0XHQkKHRoaXMpXG5cdFx0XHQuY2xvc2VzdCgnLmF0dHJpYnV0ZScpXG5cdFx0XHQuZmluZCgnLmNvbG9yLWN1cnJlbnQnKVxuXHRcdFx0LnRleHQobmFtZUNvbG9yKTtcblx0fSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2tleXVwJywgJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgZGl2LnNlbGVjdC1kcm9wZG93bicsIGZ1bmN0aW9uKGUpIHtcblx0XHR2YXIgJGxpc3RDb250YWluZXIgPSAkKHRoaXMpLFxuXHRcdFx0JGxpc3RQYXJlbnQgPSAkbGlzdENvbnRhaW5lci5jaGlsZHJlbigndWwuc2VsZWN0LWRyb3Bkb3duLWlubmVyJyksXG5cdFx0XHQkZGVmYXVsdFRleHRFbGVtZW50ID0gJGxpc3RDb250YWluZXIuY2hpbGRyZW4oJy5zZWxlY3QtdGV4dCcpLFxuXHRcdFx0JHNpemVMaXN0ID0gJGxpc3RQYXJlbnQuZmluZCgnbGkuc2VsZWN0YWJsZScpLFxuXHRcdFx0JHNlbGVjdGVkID0gJHNpemVMaXN0LmZpbHRlcignLnNlbGVjdGVkJyksXG5cdFx0XHRpc01lbnVPcGVuID0gJGxpc3RQYXJlbnQuaGFzQ2xhc3MoJ2V4cGFuZCcpO1xuXG5cdFx0YW50aUhvdmVyLmluaXQoJGxpc3RQYXJlbnQud2lkdGgoKSwgJGxpc3RQYXJlbnQuaGVpZ2h0KCkpO1xuXG5cdFx0aWYgKGUuc2hpZnRLZXkgJiYgZS5rZXlDb2RlID09IDkgJiYgaXNNZW51T3BlbikgeyAvLyBUYWIgYmFja3dhcmRzXG5cdFx0XHRzZWxlY3RPcHRpb25LZXlkb3duKGUsICd1cCcsIGlzTWVudU9wZW4pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzd2l0Y2goZS5rZXlDb2RlKSB7XG5cdFx0XHRcdGNhc2UgMzg6IC8vIFVwIEFycm93XG5cdFx0XHRcdFx0c2VsZWN0T3B0aW9uS2V5ZG93bihlLCAndXAnLCBpc01lbnVPcGVuKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSA0MDogLy8gRG93biBBcnJvd1xuXHRcdFx0XHRcdGlmICghaXNNZW51T3Blbikge1xuXHRcdFx0XHRcdFx0c2l6ZU1lbnVPcGVuQ2xvc2UoZSwgJGRlZmF1bHRUZXh0RWxlbWVudCwgdHJ1ZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHNlbGVjdE9wdGlvbktleWRvd24oZSwgJ2Rvd24nLCBpc01lbnVPcGVuKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSA5OiAvLyBUYWIgZm9yd2FyZHNcblx0XHRcdFx0XHRpZiAoaXNNZW51T3Blbikge1xuXHRcdFx0XHRcdFx0c2VsZWN0T3B0aW9uS2V5ZG93bihlLCAnZG93bicsIGlzTWVudU9wZW4pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAyNzogLy8gRXNjYXBlIGtleVxuXHRcdFx0XHRcdGlmIChpc01lbnVPcGVuKSB7XG5cdFx0XHRcdFx0XHRzaXplTWVudU9wZW5DbG9zZShlLCAkZGVmYXVsdFRleHRFbGVtZW50LCBmYWxzZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDEzOiAvLyBFbnRlciBrZXlcblx0XHRcdFx0XHQkbGlzdENvbnRhaW5lci5maW5kKCcuc2VsZWN0LXRleHQnKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdFx0JGxpc3RQYXJlbnQudG9nZ2xlQ2xhc3MoJ2V4cGFuZCcpLnRvZ2dsZUNsYXNzKCdleHBhbmQtY2xvc2UnKS50b2dnbGVDbGFzcygnc2l6ZS1kLW5vbmUnKTtcblx0XHRcdFx0XHQkc2l6ZUxpc3QuZmluZCgnYVt0YWJpbmRleF0nKS5sZW5ndGggPiAwID8gJHNpemVMaXN0LmZpbmQoJ2EnKS5yZW1vdmVBdHRyKCd0YWJpbmRleCcpIDogJHNpemVMaXN0LmZpbmQoJ2EnKS5hdHRyKCd0YWJpbmRleCcsICctMScpO1x0XG5cdFx0XHRcdFx0aWYgKCEkc2VsZWN0ZWQpIHtcblx0XHRcdFx0XHRcdCRkZWZhdWx0VGV4dEVsZW1lbnQudHJpZ2dlcignY2xpY2snKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JHNlbGVjdGVkLmZpbmQoJ2Euc3dhdGNoYW5jaG9yJykudHJpZ2dlcignY2xpY2snKTtcblx0XHRcdFx0XHR9XHRcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZW1vdmUuVmFyaWFudC5BbnRpSG92ZXInKS5vbignbW91c2Vtb3ZlLlZhcmlhbnQuQW50aUhvdmVyJywgJyNhbnRpLWhvdmVyJywgZnVuY3Rpb24oZSkge1xuICAgIFx0YW50aUhvdmVyLm1vdmVyZW1vdmUocGFyc2VJbnQoZS5jbGllbnRYKSwgcGFyc2VJbnQoZS5jbGllbnRZKSk7XG4gICAgfSk7XG5cbiAgICB2YXIgc3dhdGNoZXMgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb24gdWwuY29sb3Itb3B0aW9ucyBsaS5zZWxlY3RhYmxlJyk7XG5cdGlmIChzd2F0Y2hlcy5sZW5ndGggJiYgIXN3YXRjaGVzLmlzKCcuc2VsZWN0ZWQnKSkge1xuXHRcdHNldENvbG9yKCk7XG5cdH1cblx0XG5cdHVwZGF0ZVByb2R1Y3RJbmZvKCk7XG4gICAgaW5pdGlhbGl6ZUltYWdlR2FsbGVyeSgpO1xufTtcblxuZnVuY3Rpb24gc2V0Q29sb3IoKXtcblx0dmFyIGQgPSBuZXcgJC5EZWZlcnJlZCgpO1xuXG5cdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICBcdHZhciBzd2F0Y2hlcyA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbiB1bC5jb2xvci1vcHRpb25zIGxpLnNlbGVjdGFibGUnKTtcbiAgICBcdGlmIChzd2F0Y2hlcy5sZW5ndGggJiYgIXN3YXRjaGVzLmlzKCcuc2VsZWN0ZWQnKSkge1xuICAgIFx0XHRzd2F0Y2hlcy5maXJzdCgpLmZpbmQoJ2EnKS50cmlnZ2VyKCdjbGljaycpO1xuICAgIFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7ZC5yZXNvbHZlKCl9LCAxNTApO1xuICAgIFx0fVxuICAgIFx0XG4gICAgfSwgNTApO1xuXHRcblx0cmV0dXJuIGQucHJvbWlzZSgpXG59XG5cbnZhciBhbnRpSG92ZXIgPSB7XG5cdCRhbnRpSG92ZXI6IG51bGwsXG5cdHBvc1g6IDAsXG5cdHBvc1k6IDAsXG5cdHJlbW92ZTogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHRoaXMuJGFudGlIb3ZlcikgdGhpcy4kYW50aUhvdmVyLnJlbW92ZSgpO1xuXHRcdHRoaXMucG9zWCA9IDA7XG5cdFx0dGhpcy5wb3NZID0gMDtcblx0fSxcblx0bW92ZXJlbW92ZTogZnVuY3Rpb24oeCwgeSkge1xuXHRcdHRoaXMucG9zWCA9ICh0aGlzLnBvc1ggPT0gMCkgPyB4IDogdGhpcy5wb3NYO1xuXHRcdHRoaXMucG9zWSA9ICh0aGlzLnBvc1kgPT0gMCkgPyB5IDogdGhpcy5wb3NZO1xuXHRcdGlmICh0aGlzLnBvc1ggIT0geCB8fCB0aGlzLnBvc1kgIT0geSkge1xuXHRcdFx0JCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyB1bC5zZWxlY3QtZHJvcGRvd24taW5uZXIgbGkuc2VsZWN0YWJsZScpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xuXHRcdFx0dGhpcy5yZW1vdmUoKTtcblx0XHR9XG5cdH0sXG5cdGNoZWNrOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gKHRoaXMuJGFudGlIb3ZlciAmJiB0aGlzLiRhbnRpSG92ZXIubGVuZ3RoKTtcblx0fSxcblx0aW5pdDogZnVuY3Rpb24odywgaCkge1xuXHRcdHRoaXMucmVtb3ZlKCk7XG5cdFx0JCgnLnZhbHVlLnNlbGVjdC1kcm9wZG93bicpLmFwcGVuZCgnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTtcIiBpZD1cImFudGktaG92ZXJcIj48L2Rpdj4nKTtcblx0XHR0aGlzLiRhbnRpSG92ZXIgPSAkKCcjYW50aS1ob3ZlcicpO1xuXHRcdHRoaXMuJGFudGlIb3ZlclxuXHRcdFx0LmNzcygnei1pbmRleCcsIDEwMDApXG5cdFx0XHQuY3NzKCdoZWlnaHQnLCBoKVxuXHRcdFx0LmNzcygnd2lkdGgnLCB3KTtcblx0fVxuXG59O1xuXG5mdW5jdGlvbiBzZWxlY3RPcHRpb25LZXlkb3duKGUsIGFjdGlvbiwgaXNNZW51T3Blbikge1xuXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0dmFyICRsaXN0UGFyZW50ID0gJCgnZGl2LnByb2R1Y3QtdmFyaWF0aW9ucyB1bC5zZWxlY3QtZHJvcGRvd24taW5uZXInKSxcblx0XHQkbGlzdENvbnRhaW5lciA9ICRsaXN0UGFyZW50LmNsb3Nlc3QoJy5zZWxlY3QtZHJvcGRvd24nKSxcblx0XHQkZGVmYXVsdFRleHRFbGVtZW50ID0gJGxpc3RDb250YWluZXIuY2hpbGRyZW4oJy5zZWxlY3QtdGV4dCcpLFxuXHRcdCRzaXplTGlzdCA9ICRsaXN0UGFyZW50LmZpbmQoJ2xpLnNlbGVjdGFibGUnKSxcblx0XHQkc2VsZWN0ZWQgPSAkc2l6ZUxpc3QuZmlsdGVyKCcuc2VsZWN0ZWQnKSxcblx0XHRoZWlnaHQgPSBwYXJzZUludCgkc2l6ZUxpc3QuZmlyc3QoKS5jc3MoJ2hlaWdodCcpLnJlcGxhY2UoL3B4LywgJycpKSxcblx0XHQkY3VycmVudDtcblxuXHRcdGlmICgkc2VsZWN0ZWQubGVuZ3RoIDw9IDApIHtcblx0XHRcdCRzZWxlY3RlZCA9ICRsaXN0UGFyZW50LmZpbmQoJy5mb2N1cy12aXNpYmxlLWluZGljYXRvcicpLmNsb3Nlc3QoJ2xpLnNlbGVjdGFibGUnKSA/ICRzZWxlY3RlZCA6IG51bGw7XG5cdFx0fVxuXHRcdGlmICghJHNlbGVjdGVkIHx8ICEkc2VsZWN0ZWQubGVuZ3RoKSB7XG5cdFx0XHQkY3VycmVudCA9ICRzaXplTGlzdC5lcSgwKTtcblx0XHR9IGVsc2UgaWYgKGFjdGlvbiA9PSAndXAnKSB7XG5cdFx0XHRpZiAoJHNlbGVjdGVkLmlzKCc6Zmlyc3QtY2hpbGQnKSkge1xuXHRcdFx0XHQkY3VycmVudCA9ICRzaXplTGlzdC5lcSgwKTtcblx0XHRcdFx0Ly8gSWYgdGhpcyBpcyBmaXJzdCBsaXN0IGl0ZW0sIGFuZCB1c2VyIHByZXNzZWQgVXAgQXJyb3csIHRoZW4gd2UgbmVlZCB0byBjbG9zZSB0aGUgbWVudVxuXHRcdFx0XHRzaXplTWVudU9wZW5DbG9zZShlLCAkZGVmYXVsdFRleHRFbGVtZW50LCBmYWxzZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkY3VycmVudCA9ICRzZWxlY3RlZC5wcmV2KCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICghJHNlbGVjdGVkLm5leHQoKS5oYXNDbGFzcygnc2VsZWN0YWJsZScpKSB7XG5cdFx0XHRcdCRjdXJyZW50ID0gJHNpemVMaXN0Lmxhc3QoKTtcblx0XHRcdFx0Ly8gSWYgdGhpcyBpcyBsYXN0IGxpc3QgaXRlbSwgYW5kIHVzZXIgcHJlc3NlZCBEb3duIEFycm93LCB0aGVuIHdlIG5lZWQgdG8gY2xvc2UgdGhlIG1lbnVcblx0XHRcdFx0c2l6ZU1lbnVPcGVuQ2xvc2UoZSwgJGRlZmF1bHRUZXh0RWxlbWVudCwgZmFsc2UpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGN1cnJlbnQgPSAkc2VsZWN0ZWQubmV4dCgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciBsaXN0UGFyZW50VG9wID0gMDtcblx0XHR2YXIgbGlzdFBhcmVudEJvdHRvbSA9IGxpc3RQYXJlbnRUb3AgKyAkbGlzdFBhcmVudC5oZWlnaHQoKTtcblx0XHR2YXIgY3VycmVudFRvcCA9ICRjdXJyZW50LnBvc2l0aW9uKCkudG9wO1xuXHRcdHZhciBjdXJyZW50Qm90dG9tID0gY3VycmVudFRvcCArICRjdXJyZW50LmhlaWdodCgpO1xuXHRcdHZhciBmYXVsdFB4ID0gMTA7XG5cdFx0aWYgKGN1cnJlbnRCb3R0b20gKyBmYXVsdFB4ID4gbGlzdFBhcmVudEJvdHRvbSkge1xuXHRcdFx0JGxpc3RQYXJlbnQuc2Nyb2xsVG9wKHBhcnNlSW50KCRsaXN0UGFyZW50LnNjcm9sbFRvcCgpKSArIGhlaWdodCk7XG5cdFx0fSBlbHNlIGlmIChjdXJyZW50VG9wIDwgbGlzdFBhcmVudFRvcCkge1xuXHRcdFx0JGxpc3RQYXJlbnQuc2Nyb2xsVG9wKHBhcnNlSW50KCRsaXN0UGFyZW50LnNjcm9sbFRvcCgpKSAtIGhlaWdodCk7XG5cdFx0fVx0XG5cblx0XHQvLyRjdXJyZW50LnBhcmVudHMoJy5hdHRyaWJ1dGUnKS5maXJzdCgpLmZpbmQoJy5sYWJlbCAuY3VycmVudCwgLnNlbGVjdC1kcm9wZG93biAuc2VsZWN0LXRleHQnKS5odG1sKCRjdXJyZW50LmZpbmQoJ2EnKS5odG1sKCkpO1xuXHRcdCRzaXplTGlzdC5yZW1vdmVDbGFzcygnc2VsZWN0ZWQgdGVtcHNlbGVjdGlvbicpO1xuXHRcdCRjdXJyZW50LmFkZENsYXNzKCdzZWxlY3RlZCB0ZW1wc2VsZWN0aW9uJykuZmluZCgnYScpLmFkZENsYXNzKCdmb2N1cy12aXNpYmxlLWluZGljYXRvcicpLmZvY3VzKCk7XG5cdFx0Ly8gTmVlZGVkIHRvIGNvbWJhdCBhdXRvLXNjcm9sbCBiZWhhdmlvciB0aGF0IGhhcHBlbnMgaW4gcHJldmlvdXMgbGluZSB3aGVuIGZvY3VzIGFkZGVkIHRvIDxhPlxuXHRcdGlmICgkY3VycmVudC5pcygnOmZpcnN0LWNoaWxkJykpIHtcblx0XHRcdCRsaXN0UGFyZW50LnNjcm9sbFRvcCgwKTtcblx0XHR9XG59XG5cbmZ1bmN0aW9uIHNjcm9sbFRvQ3VycmVudFNpemUoKSB7XG5cdHZhciAkbGlzdFBhcmVudCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgdWwuc2VsZWN0LWRyb3Bkb3duLWlubmVyJyksXG5cdFx0JHNpemVMaXN0ID0gJGxpc3RQYXJlbnQuZmluZCgnbGkuc2VsZWN0YWJsZScpLFxuXHRcdCRzZWxlY3RlZCA9ICRzaXplTGlzdC5maWx0ZXIoJy5zZWxlY3RlZCcpLFxuXHRcdGhlaWdodCA9ICRzaXplTGlzdC5maXJzdCgpLmNzcygnaGVpZ2h0JykucmVwbGFjZSgvcHgvLCAnJyk7XG5cblx0aWYgKCRzZWxlY3RlZCkge1xuXHRcdCRsaXN0UGFyZW50LnNjcm9sbFRvcChoZWlnaHQgKiAkc2l6ZUxpc3QuaW5kZXgoJHNlbGVjdGVkKSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUltYWdlR2FsbGVyeSgpIHtcblx0dmFyIHBhcmFtcztcblx0aWYgKFNpdGVQcmVmZXJlbmNlcy5QUklNQVJZX1BST0RVQ1RfU0xJREVSID09ICdzd2lwZXJKUycpIHsgXG5cdFx0aW1hZ2VHYWxsZXJ5ID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50cy9JbWFnZUdhbGxlcnkvU3dpcGVyJyk7XG5cdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5QUklNQVJZX1BST0RVQ1RfU0xJREVSX0NPTkZJRykge1xuXHRcdFx0cGFyYW1zID0gSlNPTi5wYXJzZShTaXRlUHJlZmVyZW5jZXMuUFJJTUFSWV9QUk9EVUNUX1NMSURFUl9DT05GSUcpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRpbWFnZUdhbGxlcnkgPSByZXF1aXJlKCcuLi8uLi9jb21wb25lbnRzL0ltYWdlR2FsbGVyeS9TbGlja0FuZEltZ1ZpZXdlcjInKTtcblx0fVxuXHRpbWFnZUdhbGxlcnkuaW5pdGlhbGl6ZShwYXJhbXMpO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplQm9waXMoKSB7XG5cdGlmICgkKCcuYm9waXMtYWRkLXRvLWNhcnQtb3B0aW9ucy1jb250YWluZXInKS5sZW5ndGggPiAwKSB7XG5cdFx0Ym9waXNBZGRUb0NhcnRPcHRpb25zLmluaXRpYWxpemUoJCgnLmJvcGlzLWFkZC10by1jYXJ0LW9wdGlvbnMtY29udGFpbmVyJyksICQuZXh0ZW5kKG9wdGlvbnMuQm9waXMsIHsgQ2hhbm5lbDogb3B0aW9ucy5DaGFubmVsLCBQcm9kdWN0SWQ6IG9wdGlvbnMuUHJvZHVjdElkLCBTdG9yZVVJVmVyc2lvbjogb3B0aW9ucy5TdG9yZVVJVmVyc2lvbiB9KSk7XG5cdH1cblx0XG5cdGlmICgkKCcuYm9waXMtc3RvcmUtc2VhcmNoJykubGVuZ3RoID4gMCkge1xuXHRcdGJvcGlzU3RvcmVTZWFyY2guaW5pdGlhbGl6ZSgkKCcuYm9waXMtc3RvcmUtc2VhcmNoJyksICQuZXh0ZW5kKG9wdGlvbnMuQm9waXMsIHsgQ2hhbm5lbDogb3B0aW9ucy5DaGFubmVsIH0pKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cdGluaXRpYWxpemVEb20oKTtcblx0aW5pdGlhbGl6ZUV2ZW50cygpO1xuXHRpbml0aWFsaXplQm9waXMoKTtcbn1cblxudmFyIHZhcmlhbnQgPSB7XG5cdGluaXRpYWxpemU6IGluaXRpYWxpemUsXG5cdGluaXRpYWxpemVEb206IGluaXRpYWxpemVEb20sXG5cdGluaXRpYWxpemVFdmVudHM6IGluaXRpYWxpemVFdmVudHNcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdmFyaWFudDsiLCIndXNlIHN0cmljdCc7XG52YXIgZGlyZWN0aW9uLCB2aWRlb0NvdW50LCB3aWR0aCwgaGVpZ2h0LCB2aWRlb0NvdW50ZXIgPSAwLCBwb3NWYWx1ZSA9IDAsIGxhc3RDb3VudGVyID0gMCwgYXJyb3dQb3M7XG5cbnZhciBzZXRDYXJvdXNlbCA9IGZ1bmN0aW9uKCl7XG5cdHZpZGVvQ291bnQgPSAkKCcudmlkZW8tY29udGFpbmVyIHVsIGxpJykubGVuZ3RoO1xuXHR3aWR0aCA9ICQoJy52aWRlby1jb250YWluZXInKS53aWR0aCgpO1xuXHRoZWlnaHQgPSB3aWR0aCAqIDMxNSAvIDQyMDtcblx0JCgnLnlvdXR1YmUtdmlkZW8gaWZyYW1lJykuY3NzKHsnd2lkdGgnOiB3aWR0aCArICdweCcsJ2hlaWdodCc6IGhlaWdodCArICdweCd9KTtcblx0d2lkdGggKz0gNDA7XG5cdGFycm93UG9zID0gaGVpZ2h0IC8gMiAtIDIwO1xuXHQkKCcudmlkZW8tY29udGFpbmVyIC5hcnJvd3MgLmFycm93JykuY3NzKCd0b3AnLCBhcnJvd1BvcyArICdweCcpO1xufTtcblxudmFyIGFycm93Q2xpY2sgPSBmdW5jdGlvbihhcnJvdyl7XG5cdGRpcmVjdGlvbiA9IGFycm93Lmhhc0NsYXNzKCdsZWZ0JykgPyAnbGVmdCcgOiAncmlnaHQnO1xuXHRsYXN0Q291bnRlciA9IHZpZGVvQ291bnRlcjtcblx0aWYoZGlyZWN0aW9uID09ICdyaWdodCcpe1xuXHRcdGlmKHZpZGVvQ291bnRlciA9PSAodmlkZW9Db3VudCAtIDEpKXtcblx0XHRcdHBvc1ZhbHVlID0gMDtcblx0XHRcdHZpZGVvQ291bnRlciA9IDA7XG5cdFx0fVxuXHRcdGVsc2V7XG5cdFx0XHR2aWRlb0NvdW50ZXIrKztcblx0XHRcdHBvc1ZhbHVlID0gdmlkZW9Db3VudGVyICogd2lkdGg7XG5cdFx0fVxuXHR9XG5cdGVsc2V7XG5cdFx0aWYodmlkZW9Db3VudGVyID09IDApe1xuXHRcdFx0cG9zVmFsdWUgPSAodmlkZW9Db3VudCAtIDEpICogd2lkdGg7XG5cdFx0XHR2aWRlb0NvdW50ZXIgPSB2aWRlb0NvdW50IC0gMTtcblx0XHR9XG5cdFx0ZWxzZXtcblx0XHRcdHZpZGVvQ291bnRlci0tO1xuXHRcdFx0cG9zVmFsdWUgPSB2aWRlb0NvdW50ZXIgKiB3aWR0aDtcblx0XHR9XG5cdH1cblx0JCgnLnZpZGVvLWNvbnRhaW5lciB1bCcpLmFuaW1hdGUoeydsZWZ0JzonLScgKyBwb3NWYWx1ZSArICdweCd9LCAnZmFzdCcpO1xuXHR2YXIgaWZyYW1lID0gJCgnLnlvdXR1YmUtdmlkZW8gaWZyYW1lOmVxKCcrIGxhc3RDb3VudGVyICsnKScpO1xuXHQkKGlmcmFtZSkuYXR0cignc3JjJywgJChpZnJhbWUpLmF0dHIoJ3NyYycpKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHRzZXRDYXJvdXNlbCgpO1xuICAgICQoJy52aWRlby1jb250YWluZXIgLmFycm93cyAuYXJyb3cnKS5vbignY2xpY2snLCBmdW5jdGlvbigpe1xuICAgIFx0YXJyb3dDbGljaygkKHRoaXMpKTtcbiAgICB9KTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRkUHJvZHVjdFRvQ2FydCA9IHJlcXVpcmUoJy4vcHJvZHVjdC9hZGRUb0NhcnQnKSxcbiAgICBhamF4ID0gcmVxdWlyZSgnLi4vYWpheCcpLFxuICAgIHF1aWNrdmlldyA9IHJlcXVpcmUoJy4uL3F1aWNrdmlldycpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gTG9hZHMgYWRkcmVzcyBkZXRhaWxzIHRvIGEgZ2l2ZW4gYWRkcmVzcyBhbmQgZmlsbHMgdGhlIGFkZHJlc3MgZm9ybVxuICogQHBhcmFtIHtTdHJpbmd9IGFkZHJlc3NJRCBUaGUgSUQgb2YgdGhlIGFkZHJlc3MgdG8gd2hpY2ggZGF0YSB3aWxsIGJlIGxvYWRlZFxuICovXG5mdW5jdGlvbiBwb3B1bGF0ZUZvcm0oYWRkcmVzc0lELCAkZm9ybSkge1xuICAgIC8vIGxvYWQgYWRkcmVzcyBkZXRhaWxzXG4gICAgdmFyIHVybCA9IFVybHMuZ2lmdFJlZ0FkZCArIGFkZHJlc3NJRDtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuYWRkcmVzcykge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuUkVHX0FERFJfRVJST1IpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGZpbGwgdGhlIGZvcm1cbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9hZGRyZXNzaWRcIl0nKS52YWwoZGF0YS5hZGRyZXNzLklEKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9maXJzdG5hbWVcIl0nKS52YWwoZGF0YS5hZGRyZXNzLmZpcnN0TmFtZSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfbGFzdG5hbWVcIl0nKS52YWwoZGF0YS5hZGRyZXNzLmxhc3ROYW1lKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbChkYXRhLmFkZHJlc3MuYWRkcmVzczEpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKGRhdGEuYWRkcmVzcy5hZGRyZXNzMik7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbChkYXRhLmFkZHJlc3MuY2l0eSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfY291bnRyeVwiXScpLnZhbChkYXRhLmFkZHJlc3MuY291bnRyeUNvZGUpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbChkYXRhLmFkZHJlc3MucG9zdGFsQ29kZSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfc3RhdGVcIl0nKS52YWwoZGF0YS5hZGRyZXNzLnN0YXRlQ29kZSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfcGhvbmVcIl0nKS52YWwoZGF0YS5hZGRyZXNzLnBob25lKTtcbiAgICAgICAgICAgIC8vICRmb3JtLnBhcmVudCgnZm9ybScpLnZhbGlkYXRlKCkuZm9ybSgpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGV2ZW50cyBmb3IgdGhlIGdpZnQgcmVnaXN0cmF0aW9uXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgdmFyICRldmVudEFkZHJlc3NGb3JtID0gJCgnZm9ybVtuYW1lJD1cIl9naWZ0cmVnaXN0cnlcIl0nKSxcbiAgICAgICAgJGJlZm9yZUFkZHJlc3MgPSAkZXZlbnRBZGRyZXNzRm9ybS5maW5kKCdmaWVsZHNldFtuYW1lPVwiYWRkcmVzcy1iZWZvcmVcIl0nKSxcbiAgICAgICAgJGFmdGVyQWRkcmVzcyA9ICRldmVudEFkZHJlc3NGb3JtLmZpbmQoJ2ZpZWxkc2V0W25hbWU9XCJhZGRyZXNzLWFmdGVyXCJdJyk7XG5cbiAgICAkKCcudXNlcHJlZXZlbnQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGZpbHRlciBvdXQgc3RvcmVmcm9udCB0b29sa2l0XG4gICAgICAgICQoJzppbnB1dCcsICRiZWZvcmVBZGRyZXNzKS5ub3QoJ1tpZF49XCJleHRcIl0nKS5ub3QoJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzQmVmb3JlTGlzdFwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGZpZWxkTmFtZSA9ICQodGhpcykuYXR0cignbmFtZScpLFxuICAgICAgICAgICAgICAgICRhZnRlckZpZWxkID0gJGFmdGVyQWRkcmVzcy5maW5kKCdbbmFtZT1cIicgKyBmaWVsZE5hbWUucmVwbGFjZSgnQmVmb3JlJywgJ0FmdGVyJykgKyAnXCJdJyk7XG4gICAgICAgICAgICAkYWZ0ZXJGaWVsZC52YWwoJCh0aGlzKS52YWwoKSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgICRldmVudEFkZHJlc3NGb3JtLm9uKCdjaGFuZ2UnLCAnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NCZWZvcmVMaXN0XCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWRkcmVzc0lEID0gJCh0aGlzKS52YWwoKTtcbiAgICAgICAgaWYgKGFkZHJlc3NJRC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG4gICAgICAgIHBvcHVsYXRlRm9ybShhZGRyZXNzSUQsICRiZWZvcmVBZGRyZXNzKTtcbiAgICB9KVxuICAgIC5vbignY2hhbmdlJywgJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzQWZ0ZXJMaXN0XCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWRkcmVzc0lEID0gJCh0aGlzKS52YWwoKTtcbiAgICAgICAgaWYgKGFkZHJlc3NJRC5sZW5ndGggPT09IDApIHsgcmV0dXJuOyB9XG4gICAgICAgIHBvcHVsYXRlRm9ybShhZGRyZXNzSUQsICRhZnRlckFkZHJlc3MpO1xuICAgIH0pO1xuXG4gICAgJCgnZm9ybVtuYW1lJD1cIl9naWZ0cmVnaXN0cnlfaXRlbXNcIl0nKS5vbignY2xpY2snLCAnLml0ZW0tZGV0YWlscyBhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgcHJvZHVjdExpc3RJRCA9ICQoJ2lucHV0W25hbWU9cHJvZHVjdExpc3RJRF0nKS52YWwoKTtcbiAgICAgICAgcXVpY2t2aWV3LnNob3coe1xuICAgICAgICAgICAgdXJsOiBlLnRhcmdldC5ocmVmLFxuICAgICAgICAgICAgc291cmNlOiAnZ2lmdHJlZ2lzdHJ5JyxcbiAgICAgICAgICAgIHByb2R1Y3RsaXN0aWQ6IHByb2R1Y3RMaXN0SURcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbiAgICBhZGRQcm9kdWN0VG9DYXJ0KCk7XG5cbiAgICB1dGlsLnNldERlbGV0ZUNvbmZpcm1hdGlvbignLml0ZW0tbGlzdCcsIFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfR0lGVFJFR0lTVFJZKSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYm9vdEJhcm5FeHByZXNzUmVmaW5lbWVudFdpemFyZCA9IHJlcXVpcmUoJy4uL0Jvb3RCYXJuRXhwcmVzcy9jb21wb25lbnRzL0Jvb3RCYXJuRXhwcmVzc1JlZmluZW1lbnRXaXphcmQnKTtcbnZhciBjb21wYXJlV2lkZ2V0ID0gcmVxdWlyZSgnLi4vY29tcGFyZS13aWRnZXQnKTtcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi9kaWFsb2cnKTtcbnZhciBHb29nbGVUYWdNYW5hZ2VyQ2xpZW50ID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy91dGlsL0dvb2dsZVRhZ01hbmFnZXJDbGllbnQnKTtcbnZhciBsb2FkaW5nSW5kaWNhdG9yID0gcmVxdWlyZSgnLi4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgcHJvZHVjdFRpbGUgPSByZXF1aXJlKCcuLi9wcm9kdWN0LXRpbGUnKTtcbnZhciBwYWdlID0gcmVxdWlyZSgnLi4vcGFnZScpO1xudmFyIHNpemVSZWZpbmVtZW50cyA9IHJlcXVpcmUoJy4uL3NpemUtcmVmaW5lbWVudHMnKTtcbnZhciBzdHlsZUNvdW50cyA9IHJlcXVpcmUoJy4uL3N0eWxlLWNvdW50cycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXIgd2lzaGxpc3QgPSByZXF1aXJlKCcuLi93aXNobGlzdCcpO1xudmFyIHNsaWRlcnMgPSByZXF1aXJlKCcuLi9zbGlkZXJzJyk7XG5cbnZhciBJbWFnZUNvbnN0YW50cztcblxudmFyIFJlZmluZW1lbnRVSVZlcnNpb25Db25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1JlZmluZW1lbnRDb25zdGFudHMnKS5SZWZpbmVtZW50c1VJVmVyc2lvbnM7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xudmFyIFZhbGlkYXRpb25TZXR0aW5ncyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlNldHRpbmdzO1xudmFyIFZhbGlkYXRpb25SdWxlcyA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvVmFsaWRhdGlvbkNvbnN0YW50cycpLlJ1bGVzO1xuXG52YXIgb3B0aW9ucztcbnZhciBkYXRhQnVmZmVyID0gW107XG52YXIgJGh0bWwgPSAkKCdodG1sJyk7XG52YXIgJHJlZmluZW1lbnRzSW5uZXIgPSAkKCcucmVmaW5lbWVudHMnKTtcbnZhciByZWZpbmVtZW50c0V4cGFuZGVkO1xudmFyIHJlZmluZW1lbnRzVmlld0FsbDtcbnZhciBsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3M7XG5cbnZhciAkYm9vdEZpbmRlckVtYWlsRm9ybTtcbnZhciBib290RmluZGVyRW1haWxWYWxpZGF0b3I7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHJlcGxhY2VzIGJyZWFkY3J1bWJzLCBsZWZ0aGFuZCBuYXYgYW5kIHByb2R1Y3QgbGlzdGluZyB3aXRoIGFqYXggYW5kIHB1dHMgYSBsb2FkaW5nIGluZGljYXRvciBvdmVyIHRoZSBwcm9kdWN0IGxpc3RpbmdcbiAqL1xuZnVuY3Rpb24gdXBkYXRlUHJvZHVjdExpc3RpbmcodXJsLCBjYWxsYmFjaywgaXNMb2FkTW9yZSkge1xuICAgIGlmICghdXJsIHx8IHVybCA9PT0gd2luZG93LmxvY2F0aW9uLmhyZWYpIHtcbiAgICBcdGlmICgkKCdib2R5JykuYXR0cignbG9hZGluZycpKSB7XG4gICAgXHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgXHR9XG5cdFx0aWYgKCQoJy5hcHBseS1yZWZpbmVtZW50cycpLmhhc0NsYXNzKCdsb2FkaW5nJykpIHtcbiAgICBcdFx0JCgnLmFwcGx5LXJlZmluZW1lbnRzJykubG9hZGluZygnZGVzdHJveScpO1xuICAgIFx0fVxuXHRcdGlmICh0eXBlb2YgY2FsbGJhY2sgPT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0Y2FsbGJhY2soKTtcblx0XHR9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cblx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicgfHwgKG9wdGlvbnMgJiYgb3B0aW9ucy5QYWdpbmF0aW9uICYmIG9wdGlvbnMuUGFnaW5hdGlvbi5Nb2RlID09ICdMb2FkTW9yZScpKSB7XG5cdFx0JCgnLmJ0bi5sb2FkLW1vcmUnKS5sb2FkaW5nKHsgSXNJbWFnZVNob3duOiBmYWxzZSB9KTtcblx0fVxuXG4gICAgdXBkYXRlSW52ZW50b3J5TWVzc2FnZXModXJsKTtcblx0c2F2ZUV4cGFuZGVkUmVmaW5lbWVudHMoKTtcblx0XG5cdCQuYWpheCh7XG5cdFx0dXJsOiB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnZm9ybWF0JywgJ2FqYXgnKSxcblx0XHR0eXBlOiAnR0VUJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3JlZmluZW1lbnRzLW1vYmlsZS1zY3JvbGwtbG9jaycpLmNzcygndG9wJywgJycpO1xuXHRcdFx0aWYgKCQoJ2JvZHknKS5hdHRyKCdsb2FkaW5nJykgPT0gJ2xvYWRpbmcnKSB7XG5cdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cblx0XHRcdGhpc3RvcnkucHVzaFN0YXRlKHt9LCAnJywgdXJsKTtcblx0XHRcdHZhciAkY29udGVudCA9ICQoZGF0YSk7XG5cdFx0XHRpZiAoaXNMb2FkTW9yZSkge1xuXHRcdFx0XHR2YXIgJHByb2R1Y3RHcmlkID0gJGNvbnRlbnQuZmluZCgnI3NlYXJjaC1yZXN1bHQtaXRlbXMnKTtcblx0XHRcdFx0dmFyIHByb2R1Y3RUaWxlQ291bnQgPSAkcHJvZHVjdEdyaWQuZmluZCgnLmdyaWQtdGlsZScpLmxlbmd0aCArICQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zJykuZmluZCgnLmdyaWQtdGlsZScpLmxlbmd0aDtcblx0XHRcdFx0dmFyIHByb2R1Y3RUb3RhbENvdW50ID0gcGFyc2VJbnQoJGNvbnRlbnQuZmluZCgnLnNlYXJjaC1yZXN1bHQtb3B0aW9ucy5ib3R0b20gLmNvdW50JykudGV4dCgpLnJlcGxhY2UoL1xcRC9nLCAnJyksIDEwKTtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkNvdW50J10gPSBwcm9kdWN0VG90YWxDb3VudDtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkluZGV4J10gKz0gb3B0aW9ucy5QYWdpbmF0aW9uLlNpemU7XG5cdFx0XHRcdCQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zJykuYXBwZW5kKCRwcm9kdWN0R3JpZC5odG1sKCkpO1xuXHRcdFx0XHQkKCcuc2VhcmNoLXJlc3VsdC1vcHRpb25zIC5kaXNwbGF5LWNvdW50JykudGV4dChwcm9kdWN0VGlsZUNvdW50KTtcblxuXHRcdFx0XHRpZiAocHJvZHVjdFRpbGVDb3VudCA+PSBkYXRhQnVmZmVyWydQYWdpbmF0aW9uQ291bnQnXSkge1xuXHRcdFx0XHRcdCQoJy5idG4ubG9hZC1tb3JlJykuaGlkZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoJy5idG4ubG9hZC1tb3JlJykuc2hvdygpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicgfHwgKG9wdGlvbnMgJiYgb3B0aW9ucy5QYWdpbmF0aW9uICYmIG9wdGlvbnMuUGFnaW5hdGlvbi5Nb2RlID09ICdMb2FkTW9yZScpKSB7XG5cdFx0XHRcdFx0JCgnLmJ0bi5sb2FkLW1vcmUnKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFCdWZmZXJbJ1BhZ2luYXRpb25JbmRleCddID0gMDtcblx0XHRcdFx0JCgnI21haW4nKS5odG1sKCRjb250ZW50KTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykge1xuXHRcdFx0XHRcdCQoJyNncmlkLXNvcnQtaGVhZGVyJykuc2VsZWN0bWVudSh7XG5cdFx0XHRcdFx0XHQnd2lkdGgnOiAyMDVcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICgndmFyaWFudEludmVudG9yeU1lc3NhZ2luZ1VybCcgaW4gcGFnZSAmJiBwYWdlLnZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmdVcmwpIHtcblx0XHRcdFx0XHRzaG93VmFyaWFudEludmVudG9yeU1lc3NhZ2luZygpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCFjaGVja0ZvclVwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKSAmJiAkKCcjcHJpbWFyeScpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHQkKCdodG1sLGJvZHknKS5hbmltYXRlKHtcblx0XHRcdFx0XHRcdHNjcm9sbFRvcDogJCgnI3ByaW1hcnknKS5vZmZzZXQoKS50b3Bcblx0XHRcdFx0XHR9LCAxMDAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQkcmVmaW5lbWVudHNJbm5lciA9ICQoJy5yZWZpbmVtZW50cycpO1xuXHRcdFx0cmVkcmF3VXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygkY29udGVudCwgdXJsKTtcdFx0XHRcdFxuXHRcdFx0Y29tcGFyZVdpZGdldC5pbml0KCk7XG5cdFx0XHRwcm9kdWN0VGlsZS5pbml0KCk7XG5cdFx0XHRzaXplUmVmaW5lbWVudHMuaW5pdCgpO1xuXHRcdFx0aW5pdGlhbGl6ZVJlZmluZW1lbnRDb250cm9scygpO1x0XHRcdFxuXHRcdFx0cmVkcmF3U2hvcE15U3RvcmUoKTtcblx0XHRcdHNsaWRlcnMuaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycygnLm1haW4tY29udGVudCAuY2F0ZWdvcnktbGFuZGluZy1zbGlkZXI6bm90KC5zbGljay1pbml0aWFsaXplZCknKTtcblx0XHRcdHdpc2hsaXN0LnJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucygpO1xuXG5cdFx0XHRpZiAoJ2FmZmlybScgaW4gd2luZG93ICYmICd1aScgaW4gYWZmaXJtICYmICdyZWZyZXNoJyBpbiBhZmZpcm0udWkpIHtcblx0XHRcdFx0YWZmaXJtLnVpLnJlZnJlc2goKTtcblx0XHRcdH1cblxuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignQ2F0ZWdvcnlIZWFkZXJTbGlkZXJzLkluaXRpYWxpemUnKTtcblx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ0VpbnN0ZWluUHJvZHVjdFJlY29tbWVuZGF0aW9ucy5Jbml0aWFsaXplJyk7XG5cdFx0XHRpZiAoJCgnI2NhdGVnb3J5VGl0bGUnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXt3aW5kb3cudG9wLmRvY3VtZW50LnRpdGxlID0gJCgnI2NhdGVnb3J5VGl0bGUnKS5kYXRhKCd0aXRsZScpO30sIDMwMDApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGluaXRpYWxpemVUaHVtYkRhdGFMYXllcih1cmwpO1xuXG5cdFx0XHRpZiAob3B0aW9ucy5TdHlsZUNvdW50Q2FjaGUpIHtcblx0XHRcdFx0c3R5bGVDb3VudHMucmVuZGVyKG9wdGlvbnMuU3R5bGVDb3VudENhY2hlKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjb21wbGV0ZTogZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCB4aHIpIHtcblx0XHRcdGlmICgoZGF0YS5zdGF0dXMgPT0gMzAxIHx8IGRhdGEuc3RhdHVzID09IDMwMikgJiYgZGF0YS5yZXNwb25zZVRleHQpIHtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IGRhdGEucmVzcG9uc2VUZXh0O1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUludmVudG9yeU1lc3NhZ2VzKHVybCwgY2FsbGJhY2spIHtcblx0dmFyIHVybFBhcmFtcyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXModXJsKTtcblxuXHR2YXIgaW52ZW50b3J5TGlua1VybCA9IFVybHMuZ2V0SW52ZW50b3J5TGluaztcblx0Zm9yICh2YXIgdXJsUGFyYW1ldGVyIGluIHVybFBhcmFtcykge1xuXHRcdGlmICh1cmxQYXJhbXNbdXJsUGFyYW1ldGVyXSkge1xuXHRcdFx0aW52ZW50b3J5TGlua1VybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChpbnZlbnRvcnlMaW5rVXJsLCB1cmxQYXJhbWV0ZXIsIHVybFBhcmFtc1t1cmxQYXJhbWV0ZXJdKTtcblx0XHR9XG5cdH1cblxuXHQkLnBvc3QoaW52ZW50b3J5TGlua1VybCwgZnVuY3Rpb24oZGF0YSkge1xuXHRcdHZhciBkYXRhT2JqID0gSlNPTi5wYXJzZShkYXRhKTtcblx0XHRcblx0XHRpZiAoZGF0YU9iai5zdGF0dXMgJiYgZGF0YU9iai51cmwubGVuZ3RoKSB7XG5cdFx0XHR2YXIgbmV3VXJsID0gZGF0YU9iai51cmw7XG5cdFx0XHRcblx0XHRcdGlmICh1cmxQYXJhbXMuaGFzT3duUHJvcGVydHkoJ3N0YXJ0JykgJiYgdXJsUGFyYW1zLnN0YXJ0ID4gMCkge1xuXHRcdFx0XHRuZXdVcmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwobmV3VXJsLCAnc3RhcnQnLCB1cmxQYXJhbXMuc3RhcnQpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAodXJsUGFyYW1zLmhhc093blByb3BlcnR5KCdzeicpKSB7XG5cdFx0XHRcdG5ld1VybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChuZXdVcmwsICdzeicsIHVybFBhcmFtcy5zeik7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHBhZ2UudmFyaWFudEludmVudG9yeU1lc3NhZ2luZ1VybCA9IG5ld1VybDtcblx0XHR9XG5cdFx0IFxuXHRcdHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nICYmIGNhbGxiYWNrKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRVcmxQYXJhbXModXJsKSB7XG5cdHZhciB2YXJzID0ge307XG5cblx0dmFyIHBhcnRzID0gdXJsLnJlcGxhY2UoL1s/Jl0rKFtePSZdKyk9KFteJl0qKS9naSwgZnVuY3Rpb24obSwga2V5LCB2YWx1ZSkge1xuXHRcdHZhcnNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuXG5cdHJldHVybiB2YXJzO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplVGh1bWJEYXRhTGF5ZXIodXJsKSB7XG5cdHZhciBkYXRhID0ge307XG5cdFxuXHR2YXIgY3VycmVudENhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0aWYgKGN1cnJlbnRDYXRlZ29yeUlkICYmIGN1cnJlbnRDYXRlZ29yeUlkICE9ICdudWxsJykge1xuXHRcdGRhdGEuY2dpZCA9IGN1cnJlbnRDYXRlZ29yeUlkO1xuXHR9XG5cdFxuXHRpZiAoZ2V0VXJsUGFyYW1zKHVybClbJ3N6J10pIHtcblx0XHRkYXRhLnN6ID0gZ2V0VXJsUGFyYW1zKHVybClbJ3N6J107XG5cdH1cblx0XG5cdGlmIChnZXRVcmxQYXJhbXModXJsKVsnc3RhcnQnXSkge1xuXHRcdGRhdGEuc3RhcnQgPSBnZXRVcmxQYXJhbXModXJsKVsnc3RhcnQnXTtcblx0fVxuXHRcblx0aWYgKGdldFVybFBhcmFtcyh1cmwpWydxJ10pIHtcblx0XHRkYXRhLnEgPSBkZWNvZGVVUklDb21wb25lbnQoZ2V0VXJsUGFyYW1zKHVybClbJ3EnXSk7XG5cdH1cblx0XG5cdGlmIChnZXRVcmxQYXJhbXModXJsKVsnc3J1bGUnXSkge1xuXHRcdGRhdGEuc3J1bGUgPSBkZWNvZGVVUklDb21wb25lbnQoZ2V0VXJsUGFyYW1zKHVybClbJ3NydWxlJ10pO1xuXHR9XG5cdFxuXHRmb3IgKHZhciBwcmVmZXJlbmNlSW5kZXggPSAxOyBwcmVmZXJlbmNlSW5kZXggPCA5OyBwcmVmZXJlbmNlSW5kZXgrKykge1xuXHRcdGlmIChnZXRVcmxQYXJhbXModXJsKVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSkge1xuXHRcdFx0ZGF0YVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSA9IGRlY29kZVVSSUNvbXBvbmVudChnZXRVcmxQYXJhbXModXJsKVsncHJlZm4nICsgcHJlZmVyZW5jZUluZGV4XSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChnZXRVcmxQYXJhbXModXJsKVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSkge1xuXHRcdFx0ZGF0YVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSA9IGRlY29kZVVSSUNvbXBvbmVudChnZXRVcmxQYXJhbXModXJsKVsncHJlZnYnICsgcHJlZmVyZW5jZUluZGV4XSk7XG5cdFx0fVxuXHR9XG5cdFxuXHRHb29nbGVUYWdNYW5hZ2VyQ2xpZW50LlB1c2hEYXRhTGF5ZXJGb3JQYWdlKHBhZ2VDb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gZmlsdGVyUmVmaW5lbWVudHMoY29udGFpbmVyLCBmaWx0ZXJUZXh0KSB7XG5cdGNvbnRhaW5lci5maW5kKCcuY2hlY2tzIGxhYmVsJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJGZpbHRlciA9ICQodGhpcyk7XG5cdFx0aWYgKGZpbHRlclRleHQgPT09IFwiXCIpIHtcblx0XHRcdC8vIFJlc2V0IGZpbHRlclxuXHRcdFx0JGZpbHRlci5wYXJlbnQoKS5zaG93KCk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0dmFyIGxhYmVsVGV4dCA9ICRmaWx0ZXIuaHRtbCgpLnRyaW0oKS50b1VwcGVyQ2FzZSgpO1xuXHRcdFx0aWYgKGxhYmVsVGV4dC5pbmRleE9mKGZpbHRlclRleHQpID4gLTEpIHtcblx0XHRcdFx0JGZpbHRlci5wYXJlbnQoKS5zaG93KCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0JGZpbHRlci5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIGZvbGxvd2luZyBzZWFyY2ggcmVmaW5lbWVudCBjb250cm9sczo8YnIvPlxuICogPHA+c2Nyb2xsIGJhcjwvcD5cbiAqIDxwPnNlY3Rpb24gZHJvcGRvd25zPC9wPlxuICogPHA+cmFuZ2Ugc2xpZGVyPC9wPlxuICogPHA+dGV4dGJveCBmaWx0ZXI8L3A+XG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVSZWZpbmVtZW50Q29udHJvbHMoKSB7XG5cdGlmICgkKCcucmVmaW5lbWVudHMgLnJlZmluZW1lbnQ6dmlzaWJsZScpLmxlbmd0aCA+IDIpIHtcblx0XHQkKCcucmVmaW5lbWVudHMgLnNob3ctYWxsLXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXHR9XG5cdFxuXHRpZiAoJCgnLnJlZmluZW1lbnQgaW5wdXQ6Y2hlY2tlZCwgLnJlZmluZW1lbnQgW3JlZmluZW1lbnQtdmFsdWVdLm1vZGlmaWVkOm5vdCg6Y2hlY2tlZCknKS5sZW5ndGggPiAwKSB7XG5cdFx0JCgnLnJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ3JlZmluZW1lbnRzLWFwcGxpZWQnKTtcblx0fVxuXHRcblx0Ly8gaGFuZGxlIHRvZ2dsZSByZWZpbmVtZW50IGJsb2Nrc1xuXHQkKCcucmVmaW5lbWVudDpub3QoLmRpc2FibGVkKSAudG9nZ2xlJykub2ZmKCdjbGljaycpO1xuXHQkKCcucmVmaW5lbWVudDpub3QoLmRpc2FibGVkKSAudG9nZ2xlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJHJlZmluZW1lbnRCb2R5ID0gJHRoaXMucGFyZW50KCkuZmluZCgnLnJlZmluZW1lbnQtYm9keScpO1xuXG5cdFx0aWYgKCEkdGhpcy5oYXNDbGFzcygnZXhwYW5kZWQnKSkge1xuXHRcdFx0JHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKS5hZGRDbGFzcygnZXhwYW5kZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKS5yZW1vdmVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRcdFxuXHRcdH1cblx0XHQkdGhpcy50b2dnbGVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRpZiAoJHRoaXMuaGFzQ2xhc3MoJ2V4cGFuZGVkJykpIHtcblx0XHQgICAgJHJlZmluZW1lbnRCb2R5LnN0b3AoKS5zaG93KCk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHQkcmVmaW5lbWVudEJvZHkuc3RvcCgpLmhpZGUoKTtcbiAgICAgICAgfVxuXHRcdFxuXHRcdGlmICgkKCcucmVmaW5lbWVudC5leHBhbmRlZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdCQoJy5yZWZpbmVtZW50cycpLmFkZENsYXNzKCdyZWZpbmVtZW50LWV4cGFuZGVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJy5yZWZpbmVtZW50cycpLnJlbW92ZUNsYXNzKCdyZWZpbmVtZW50LWV4cGFuZGVkJyk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICgkdGhpcy5jbG9zZXN0KCcuc2hvdy1hbGwtcmVmaW5lbWVudHMnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkdGhpcy5wYXJlbnQoKS50b2dnbGVDbGFzcygnZXhwYW5kZWQnKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRzYXZlRXhwYW5kZWRSZWZpbmVtZW50cygpO1xuXHRcdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHR1cGRhdGVTZWxlY3RlZFJlZmluZW1lbnRzKCk7XG5cdFx0fVxuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ1N0aWNreVJlZmluZW1lbnRzLlJlZnJlc2gnKTtcblx0XHRcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgY3NzQ2xhc3MgPSAkdGhpcy5wYXJlbnQoKS5hdHRyKCdjbGFzcycpO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRHcm91cCA9ICQudHJpbShjc3NDbGFzcy5yZXBsYWNlKC9yZWZpbmVtZW50LywgJycpKTtcblx0XHRcdHJlZkdyb3Vwc1N0YXRlcy5zYXZlU3RhdGUocmVmaW5lbWVudEdyb3VwLCAkdGhpcy5oYXNDbGFzcygnZXhwYW5kZWQnKSk7XG5cdFx0fS5iaW5kKHRoaXMpLCAzMCk7XG5cdH0pO1xuXG5cdC8vIFJhbmdlIFNsaWRlclxuXHQkKCcucmFuZ2Utc2xpZGVyJykuZWFjaChmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1pblZhbHVlID0gKyQodGhpcykuZGF0YSgnbWluJyksXG5cdFx0XHRtYXhWYWx1ZSA9ICskKHRoaXMpLmRhdGEoJ21heCcpO1xuXHRcdCQodGhpcykuc2xpZGVyKHtcblx0XHRcdHJhbmdlOiBcdHRydWUsXG5cdFx0XHRtaW46IFx0bWluVmFsdWUsXG5cdFx0XHRtYXg6IFx0bWF4VmFsdWUsXG5cdFx0XHR2YWx1ZXM6IFtnZXRVcmxWYXJzKClbJ3BtaW4nXSB8fCBtaW5WYWx1ZSwgZ2V0VXJsVmFycygpWydwbWF4J10gfHwgbWF4VmFsdWVdLFxuXHRcdFx0c2xpZGU6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cdFx0XHRcdCQodGhpcykuY2hpbGRyZW4oJy5wcmljZS1taW4nKS5odG1sKCckJyArIHVpLnZhbHVlc1swXSk7XG5cdFx0XHRcdCQodGhpcykuY2hpbGRyZW4oJy5wcmljZS1tYXgnKS5odG1sKCckJyArIHVpLnZhbHVlc1sxXSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdHZhciB0aW1lb3V0O1xuXHQkKCcucmFuZ2Utc2xpZGVyJykub24oJ3NsaWRlY2hhbmdlJywgZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblx0XHRjbGVhclRpbWVvdXQodGltZW91dCk7XG5cdFx0dGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGNnaWQgPSBnZXRVcmxWYXJzKClbJ2NnaWQnXSxcblx0XHRcdFx0c2l0ZUxvY2F0aW9uID0gd2luZG93LmxvY2F0aW9uO1xuXHRcdFx0c2l0ZUxvY2F0aW9uLmFzc2lnbiggc2l0ZUxvY2F0aW9uLnByb3RvY29sICsgJy8vJyArIHNpdGVMb2NhdGlvbi5ob3N0bmFtZSArIHNpdGVMb2NhdGlvbi5wYXRobmFtZSArICc/Y2dpZD0nICsgY2dpZCArICcmcG1pbj0nICsgdWkudmFsdWVzWzBdICsgJyZwbWF4PScgKyB1aS52YWx1ZXNbMV0pO1xuXHRcdH0sIDIwMDApO1xuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHRpZiAoJCgnLnJhbmdlLXNsaWRlcicpLmxlbmd0aCA+IDAgJiYgZ2V0VXJsVmFycygpWydwbWluJ10pIHtcblx0XHRcdHZhciBzbGlkZXIgPSAkKCcucmFuZ2Utc2xpZGVyJyk7XG5cdFx0XHRzbGlkZXIuY2hpbGRyZW4oJy5wcmljZS1taW4nKS5odG1sKCckJyArIGdldFVybFZhcnMoKVsncG1pbiddKTtcblx0XHRcdHNsaWRlci5jaGlsZHJlbignLnByaWNlLW1heCcpLmh0bWwoJyQnICsgZ2V0VXJsVmFycygpWydwbWF4J10pO1xuXHRcdFx0JCgnLnNsaWRlci10b2dnbGUnKS50b2dnbGVDbGFzcygnZXhwYW5kZWQnKVxuXHRcdFx0XHRcdFx0XHRcdC5wYXJlbnQoKVxuXHRcdFx0XHRcdFx0XHRcdC5maW5kKCcucmVmaW5lbWVudC1ib2R5Jylcblx0XHRcdFx0XHRcdFx0XHQuc3RvcCgpXG5cdFx0XHRcdFx0XHRcdFx0LnRvZ2dsZSgpO1xuXHRcdH1cblxuXHR9KTtcblxuXHQkKCcucmVmaW5lbWVudCAuZm9ybS1yb3cgaW5wdXRbdHlwZT10ZXh0XScpLm9uKCdpbnB1dCcsIGZ1bmN0aW9uKCkge1xuXHRcdHZhciAkaW5wdXQgPSAkKHRoaXMpO1xuXG5cdCAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KCRpbnB1dC5kYXRhKFwidGltZW91dFwiKSk7XG5cdCAgICAkaW5wdXQuZGF0YShcInRpbWVvdXRcIiwgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdCAgICBcdGZpbHRlclJlZmluZW1lbnRzKCRpbnB1dC5wYXJlbnRzKCcucmVmaW5lbWVudCcpLmZpcnN0KCksICRpbnB1dC52YWwoKS50cmltKCkudG9VcHBlckNhc2UoKSk7XG5cdCAgICB9LCAxMDAwKSk7XG5cdH0pO1xuXG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGV2ZW50cyBmb3IgdGhlIGZvbGxvd2luZyBlbGVtZW50czo8YnIvPlxuICogPHA+cmVmaW5lbWVudCBibG9ja3M8L3A+XG4gKiA8cD51cGRhdGluZyBncmlkOiByZWZpbmVtZW50cywgcGFnaW5hdGlvbiwgYnJlYWRjcnVtYjwvcD5cbiAqIDxwPml0ZW0gY2xpY2s8L3A+XG4gKiA8cD5zb3J0aW5nIGNoYW5nZXM8L3A+XG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG5cdC8qXG5cdCAqIEFkZGVkIGEgSlMgZm9yIHNlYXJjaCByZXN1bHQgcGFnZSB0byBwcmV2ZW50IHJlZmluZW1lbnQgZnJvbSBoYXZpbmcgYSBtYXJnaW4tdG9wIGV2ZW4gdGhlIGhlYWRlciBpcyBub3Qgc2hvd2luZ1xuXHQgKi9cblx0aWYgKChvcHRpb25zLlJlZmluZW1lbnRzVUlWZXJzaW9uICE9IFJlZmluZW1lbnRVSVZlcnNpb25Db25zdGFudHMuVXBkYXRlZCkgJiYgd2luZG93LmlubmVyV2lkdGggPCA3NjcpIHtcblx0XHRpZigkKFwiLnNlYXJjaC1waHJhc2UtY29udGFpbmVyXCIpLmxlbmd0aCkge1xuXHRcdFx0JCgnLnB0X3Byb2R1Y3Qtc2VhcmNoLXJlc3VsdCAjc2Vjb25kYXJ5IC5yZWZpbmVtZW50cy1pbm5lcicpLmNzcyh7J21hcmdpbi10b3AnOiAnNjBweCd9KTtcblx0XHR9XG5cdH1cblxuXHQkKHdpbmRvdykub24oJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuXHRcdGlmICgob3B0aW9ucy5SZWZpbmVtZW50c1VJVmVyc2lvbiA9PSBSZWZpbmVtZW50VUlWZXJzaW9uQ29uc3RhbnRzLlVwZGF0ZWQpICYmIHdpbmRvdy5pbm5lcldpZHRoID4gNzY3KSB7XG5cdFx0XHQkKCcubW9kaWZpZWQnKS5yZW1vdmVDbGFzcygnbW9kaWZpZWQnKS5wcm9wKCdjaGVja2VkJywgISQoJy5tb2RpZmllZCcpLnByb3AoJ2NoZWNrZWQnKSk7XG5cdFx0fVxuXHR9KTtcblxuXHQkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQkKFwiYm9keVwiKS5kZWxlZ2F0ZShcIi5wcm9kdWN0LXN3YXRjaGVzLWFsbFwiLCBcImNsaWNrXCIsIGZ1bmN0aW9uKCkge1xuXHRcdFx0JCh0aGlzKS5wYXJlbnQoKS5maW5kKFwiLnN3YXRjaC1saXN0IGxpXCIpLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdHZhciAkbWFpbiA9ICQoJyNtYWluJyk7XG4gICAgLy8gY29tcGFyZSBjaGVja2VkXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJ2lucHV0W3R5cGU9XCJjaGVja2JveFwiXS5jb21wYXJlLWNoZWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2IgPSAkKHRoaXMpO1xuICAgICAgICB2YXIgdGlsZSA9IGNiLmNsb3Nlc3QoJy5wcm9kdWN0LXRpbGUnKTtcblxuICAgICAgICB2YXIgZnVuYyA9IHRoaXMuY2hlY2tlZCA/IGNvbXBhcmVXaWRnZXQuYWRkUHJvZHVjdCA6IGNvbXBhcmVXaWRnZXQucmVtb3ZlUHJvZHVjdDtcbiAgICAgICAgdmFyIGl0ZW1JbWcgPSB0aWxlLmZpbmQoJy5wcm9kdWN0LWltYWdlIGEgaW1nJykuZmlyc3QoKTtcbiAgICAgICAgZnVuYyh7XG4gICAgICAgICAgICBpdGVtaWQ6IHRpbGUuZGF0YSgnaXRlbWlkJyksXG4gICAgICAgICAgICB1dWlkOiB0aWxlWzBdLmlkLFxuICAgICAgICAgICAgaW1nOiBpdGVtSW1nLFxuICAgICAgICAgICAgY2I6IGNiXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljay5Ub2dnbGUuUmVmaW5lbWVudHMnKS5vbignY2xpY2suVG9nZ2xlLlJlZmluZW1lbnRzJywgJy50b2dnbGUtcmVmaW5lbWVudHMnLCBmdW5jdGlvbihldmVudCkge1xuICAgIFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBcdFxuICAgIFx0aWYgKCEkKCcucmVmaW5lbWVudHMtaW5uZXItY29udGFpbmVyJykuaGFzQ2xhc3MoJ29wZW4nKSkge1xuXHQgICAgIFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lcicpLmZpbmQoJy50b2dnbGUuZXhwYW5kZWQsIC50b2dnbGUuc2VsZWN0ZWQsIC5yZWZpbmVtZW50LmV4cGFuZGVkJykucmVtb3ZlQ2xhc3MoJ2V4cGFuZGVkIHNlbGVjdGVkJyk7XG5cdCAgICAgXHQkKCcucmVmaW5lbWVudHMnKS5yZW1vdmVDbGFzcygncmVmaW5lbWVudC1leHBhbmRlZCcpO1xuXHQgICAgIFx0JCgnLnJlZmluZW1lbnQtYm9keScpLmhpZGUoKTtcbiAgICBcdH1cbiAgICBcdFxuICAgIFx0dG9nZ2xlQm9keVNjcm9sbExvY2soKTtcbiAgICBcdCQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXInKS50b2dnbGVDbGFzcygnb3BlbicpO1xuICAgIFx0cmVkcmF3VXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpO1xuICAgIH0pO1xuICAgIFxuICAgICRtYWluLm9mZignY2xpY2suVG9nZ2xlLlNvcnRpbmcnKS5vbignY2xpY2suVG9nZ2xlLlNvcnRpbmcnLCAnLnRvZ2dsZS1zb3J0JywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICBcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcblx0XHQkKCcuc29ydC1ieS5tb2RhbCcpLnRvZ2dsZSgpO1xuXHRcdCQoJy5zb3J0LWJ5Lm1vZGFsJykudG9nZ2xlQ2xhc3MoJ29wZW4nKTtcblx0XHQkKCcjc2VhcmNoLXJlc3VsdCcpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcbiAgICB9KTtcbiAgICBcbiAgICAkbWFpbi5vZmYoJ2NsaWNrLlNlbGVjdC5Tb3J0aW5nJykub24oJ2NsaWNrLlNlbGVjdC5Tb3J0aW5nJywgJy5zb3J0LWJ5Lm1vZGFsIGlucHV0JywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICBcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgIFx0XG4gICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdCQoJy5zb3J0LWJ5Lm1vZGFsJykudG9nZ2xlKCk7XG5cdFx0JCgnLnNvcnQtYnkubW9kYWwnKS50b2dnbGVDbGFzcygnb3BlbicpO1xuXHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcoJHRoaXMudmFsKCkpO1xuICAgIH0pO1xuICAgIFxuICAgIC8vIGhhbmRsZSBldmVudHMgZm9yIHVwZGF0aW5nIGdyaWRcbiAgICAkbWFpbi5vbignY2xpY2snLCAnLnJlZmluZW1lbnRzLWhlYWQgYSwgLnJlZmluZW1lbnRzLWlubmVyIGEsIC5wYWdpbmF0aW9uLWJhciBhLCAuYnJlYWRjcnVtYi1yZWZpbmVtZW50LXZhbHVlIGEnLCBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cbiAgICBcdGlmICghJHRoaXMuaGFzQ2xhc3MoJ3JlZi1maWx0ZXInKSAmJiBjaGVja0ZvclVwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKSkge1xuICAgIFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgXHRcdHZhciByZWZpbmVtZW50VmFsdWUgPSAkdGhpcy5hdHRyKCd2YWx1ZScpO1xuICAgIFx0XHRcbiAgICBcdFx0JHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQtYm9keS1pbm5lcicpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWU9XCInICsgcmVmaW5lbWVudFZhbHVlICsgJ1wiXSwgYVt2YWx1ZT1cIicgKyByZWZpbmVtZW50VmFsdWUgKyAnXCJdJykudG9nZ2xlQ2xhc3MoJ21vZGlmaWVkJyk7XG4gICAgXHRcdHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKTtcbiAgICBcdFx0cmV0dXJuO1x0XG4gICAgXHR9XG4gICAgXHRcbiAgICAgICAgLy8gZG9uJ3QgaW50ZXJjZXB0IGZvciBjYXRlZ29yeSBhbmQgZm9sZGVyIHJlZmluZW1lbnRzLCBhcyB3ZWxsIGFzIHVuc2VsZWN0YWJsZVxuICAgICAgICBpZiAoJHRoaXMucGFyZW50cygnLmNhdGVnb3J5LXJlZmluZW1lbnQnKS5sZW5ndGggPiAwIHx8ICR0aGlzLnBhcmVudHMoJy5mb2xkZXItcmVmaW5lbWVudCcpLmxlbmd0aCA+IDAgfHwgJHRoaXMucGFyZW50KCkuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyIGFjdGl2ZVJlZmluZW1lbnRzQ291bnQgPSAkKCdbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGggLSAkKCcuc3dhdGNoZXNbY2xhc3MqPVwicG9wdWxhci1cIl0gW3JlZmluZW1lbnQtdmFsdWVdLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdGlmICgkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnc2VsZWN0ZWQnKSAmJiBhY3RpdmVSZWZpbmVtZW50c0NvdW50ID09IDEgJiYgb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudCAmJiBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50LlVybCkge1xuXHRcdFx0bG9jYXRpb24uaHJlZiA9IG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQuVXJsO1xuICAgIFx0XHRyZXR1cm47XG5cdFx0fVxuXG4gICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygnYnJlYWRjcnVtYi1lbGVtZW50JykgJiYgJHRoaXMuYXR0cignaHJlZicpICE9IG51bGwpIHtcbiAgICBcdFx0bG9jYXRpb24uaHJlZiA9IHRoaXMuaHJlZjtcbiAgICBcdFx0cmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaGlkZSBvciBzaG93L2V4cGFuZCBhbGwgcmVmaW5lbWVudCBpdGVtc1xuICAgICAgICBpZiAoJHRoaXMuaGFzQ2xhc3MoJ3JlZi1maWx0ZXInKSkge1xuICAgICAgICBcdHZhciByZWYgPSAnLicgKyAkKHRoaXMpLmRhdGEoJ3JlZicpO1xuICAgICAgICBcdCQocmVmKS5maW5kKCcudG9nZ2xlYWJsZScpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgXHRpZiAoJHRoaXMuaGFzQ2xhc3MoJ21vcmUtbGluaycpKSB7XG4gICAgICAgIFx0XHQkdGhpcy5wYXJlbnRzKCdsaScpLmhpZGUoKS5jbG9zZXN0KCcucmVmaW5lbWVudCcpLmFkZENsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG4gICAgICAgIFx0fSBlbHNlIHtcbiAgICAgICAgXHRcdCQocmVmKS5maW5kKCcubW9yZS1saW5rJykucGFyZW50cygnbGknKS5zaG93KCkuY2xvc2VzdCgnLnJlZmluZW1lbnQnKS5yZW1vdmVDbGFzcygnbW9yZS1leHBhbmRlZCcpO1xuICAgICAgICBcdH1cblx0XHRcdHNhdmVFeHBhbmRlZFJlZmluZW1lbnRzKCk7XG4gICAgICAgIFx0cmV0dXJuO1xuICAgICAgICB9XG5cblx0XHRpZiAoJHRoaXMubGVuZ3RoID4gMCAmJiAhJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpKSB7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdH1cblxuXHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuR0FfTkVXX0FDVElPTlNfRU5BQkxFRCkge1xuXHRcdFx0dmFyIHJlZmluZW1lbnRJZCA9ICR0aGlzLmNsb3Nlc3QoJ1tyZWZpbmVtZW50LWlkXScpLmF0dHIoJ3JlZmluZW1lbnQtaWQnKSB8fCBudWxsO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRWYWx1ZSA9ICR0aGlzLmF0dHIoJ3ZhbHVlJykgPyAkdGhpcy5hdHRyKCd2YWx1ZScpLnJlcGxhY2UoJ1wiJyxcIiBJTkNIXCIpIDogbnVsbDtcblx0XHRcdGlmIChyZWZpbmVtZW50SWQgJiYgcmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHRcdHZhciByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEgPSAgeyBcblx0XHRcdFx0XHQnYWN0aW9uX3ZhbHVlJzogeyAncmVmaW5lbWVudF9jYXRlZ29yeSc6IHJlZmluZW1lbnRJZCB9LCBcblx0XHRcdFx0XHQnYWN0aW9uX2l0ZW1zJzogeyAncmVmaW5lbWVudF92YWx1ZSc6IHJlZmluZW1lbnRWYWx1ZSB9XG5cdFx0XHRcdH07XG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FwcGx5UmVmaW5lbWVudCcsIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSk7XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHRoaXMuaHJlZik7XG5cblx0XHR2YXIgc2VsZWN0aW9uID0gJCgnZGl2LnByb2R1Y3Qtc2VsZWN0aW9ucyB1bCBsaScpO1xuXHRcdHZhciByZWZHcm91cCA9ICQoc2VsZWN0aW9uW3NlbGVjdGlvbi5sZW5ndGgtMl0pLmZpbmQoJ3NwYW46Zmlyc3QnKS5kYXRhKCdyZWZncm91cC1pZCcpO1xuXHRcdGlmIChyZWZHcm91cCAmJiByZWZHcm91cC5sZW5ndGggPiAwICYmIHJlZkdyb3Vwc1N0YXRlcy5jaGVja1N0YXRlKHJlZkdyb3VwKSkge1xuXHRcdFx0JCgnI3JlZmluZW1lbnRzLWlubmVyIC5yZWZpbmVtZW50LicrcmVmR3JvdXArJyAudG9nZ2xlJylbMF0uY2xpY2soKTtcblx0XHR9XG4gICAgfSk7XG5cbiAgICAvLyBoYW5kbGUgZXZlbnRzIGl0ZW0gY2xpY2suIGFwcGVuZCBwYXJhbXMuXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5wcm9kdWN0LXRpbGUgYTpub3QoXCIjcXVpY2t2aWV3YnV0dG9uXCIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYSA9ICQodGhpcyk7XG4gICAgICAgIC8vIGdldCBjdXJyZW50IHBhZ2UgcmVmaW5lbWVudCB2YWx1ZXNcbiAgICAgICAgdmFyIHdsID0gd2luZG93LmxvY2F0aW9uO1xuXG4gICAgICAgIHZhciBxc1BhcmFtcyA9ICh3bC5zZWFyY2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLnNlYXJjaC5zdWJzdHIoMSkpIDoge307XG4gICAgICAgIHZhciBoYXNoUGFyYW1zID0gKHdsLmhhc2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLmhhc2guc3Vic3RyKDEpKSA6IHt9O1xuXG4gICAgICAgIC8vIG1lcmdlIGhhc2ggcGFyYW1zIHdpdGggcXVlcnlzdHJpbmcgcGFyYW1zXG4gICAgICAgIHZhciBwYXJhbXMgPSAkLmV4dGVuZChoYXNoUGFyYW1zLCBxc1BhcmFtcyk7XG4gICAgICAgIGlmICghcGFyYW1zLnN0YXJ0KSB7XG4gICAgICAgICAgICBwYXJhbXMuc3RhcnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGdldCB0aGUgaW5kZXggb2YgdGhlIHNlbGVjdGVkIGl0ZW0gYW5kIHNhdmUgYXMgc3RhcnQgcGFyYW1ldGVyXG4gICAgICAgIHZhciB0aWxlID0gYS5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIHZhciBpZHggPSB0aWxlLmRhdGEoJ2lkeCcpID8gKyB0aWxlLmRhdGEoJ2lkeCcpIDogMDtcblxuICAgICAgICAvLyBjb252ZXJ0IHBhcmFtcy5zdGFydCB0byBpbnRlZ2VyIGFuZCBhZGQgaW5kZXhcbiAgICAgICAgcGFyYW1zLnN0YXJ0ID0gKCtwYXJhbXMuc3RhcnQpICsgKGlkeCArIDEpO1xuICAgICAgICAvLyBzZXQgdGhlIGhhc2ggYW5kIGFsbG93IG5vcm1hbCBhY3Rpb24gdG8gY29udGludWVcbiAgICAgICAgYVswXS5oYXNoID0gJC5wYXJhbShwYXJhbXMpO1xuICAgIH0pO1xuXG4gICAgLy8gaGFuZGxlIHNvcnRpbmcgY2hhbmdlXG4gICAgJG1haW4ub24oJ2NoYW5nZScsICcuc29ydC1ieSBzZWxlY3QnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIFxuXHRcdGlmICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdHZhciBpc1NvcnRpbmdDaGFuZ2VkID0gZmFsc2U7XG5cdFx0XHR2YXIgJHNvcnRpbmdSdWxlID0gJCgnLm1vZGFsLm9wZW4gLnNvcnQtYnkgb3B0aW9uOmNoZWNrZWQnKTtcblx0XHRcdGlmICgkc29ydGluZ1J1bGUgJiYgJHNvcnRpbmdSdWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0aXNTb3J0aW5nQ2hhbmdlZCA9ICEkc29ydGluZ1J1bGUuYXR0cignc2VsZWN0ZWQnKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGlzU29ydGluZ0NoYW5nZWQgfHwgJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdLm1vZGlmaWVkLCAubGlzdC1zZWxlY3Rpb25zIC52YWx1ZS5wZW5kaW5nLWNsZWFyJykubGVuZ3RoID4gMCkge1xuXHRcdFx0XHQkcmVmaW5lbWVudHNJbm5lci5hZGRDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkcmVmaW5lbWVudHNJbm5lci5yZW1vdmVDbGFzcygncmVmaW5lbWVudHMtbW9kaWZpZWQnKTtcblx0XHRcdFx0JCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1mb290ZXIgLmFwcGx5LXJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XHRcdFxuXHRcdFx0dmFyIHNlbGVjdGVkU29ydCA9ICQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCk7XG5cdFx0XHRpZiAoJCh0aGlzKS5hdHRyKCdpZCcpID09ICdtb2JpbGUtc29ydCcpe1xuXHRcdFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZyhzZWxlY3RlZFNvcnQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG5cdFx0XHRcdFx0dXBkYXRlUHJvZHVjdExpc3Rpbmcoc2VsZWN0ZWRTb3J0KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gc2VsZWN0ZWRTb3J0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuICAgIH0pO1xuXG5cdCQoJy5zZWFyY2gtcmVzdWx0LXBhZ2UnKS5vbignY2xpY2snLCAnI2dyaWQtc29ydC1oZWFkZXItbWVudSBsaScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCcuc29ydC1ieSBzZWxlY3QnKS5wcm9wKCdzZWxlY3RlZEluZGV4JywgJCh0aGlzKS5pbmRleCgpKS5maXJzdCgpLnRyaWdnZXIoJ2NoYW5nZScpO1xuXHR9KTtcblxuICAgICRtYWluLm9uKCdjaGFuZ2UnLCAnLml0ZW1zLXBlci1wYWdlIHNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlZmluZVVybCA9ICQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCk7XG4gICAgICAgIGlmIChyZWZpbmVVcmwgPT09ICdJTkZJTklURV9TQ1JPTEwnKSB7XG4gICAgICAgICAgICAkKCdodG1sJykuYWRkQ2xhc3MoJ2luZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJCgnaHRtbCcpLmFkZENsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdpbmZpbml0ZS1zY3JvbGwnKTtcbiAgICAgICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHJlZmluZVVybCk7XG4gICAgICAgIH1cblx0fSk7XG5cblx0JG1haW4ub24oJ2NsaWNrJywgJy5tb2JpbGUtcmVmaW5lbWVudHMgLnRvZ2dsZS1idXR0b24nLCBmdW5jdGlvbigpIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgJiYgb3B0aW9ucy5SZWZpbmVtZW50c1VJVmVyc2lvbiAhPSBSZWZpbmVtZW50VUlWZXJzaW9uQ29uc3RhbnRzLlVwZGF0ZWQpIHtcblx0XHRcdGlmICgkKHRoaXMpLmhhc0NsYXNzKCdzb3J0LWJ5LXRvZ2dsZScpKSB7XG5cdFx0XHRcdFxuXHRcdFx0XHQvL0Vuc3VyZSBib3RoIHNvcnQtYnkgYW5kIHJlZmluZW1lbnRzIGFyZW4ndCBvcGVuIHNpbXVsdGFuZW91c2x5IFxuXHRcdFx0XHQkKCcjc2Vjb25kYXJ5LnJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0XHQkKCcubW9iaWxlLXJlZmluZW1lbnRzIC5yZWZpbmUtdG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuXG5cdFx0XHRcdC8vY29udGFpbmVyIGZvciBuZXcgc29ydGluZyBvcHRpb25zXG5cdFx0XHRcdHZhciBzb3J0QnlPcHRpb25zQ29udGFpbmVyID0gJCgnLm1vYmlsZS1yZWZpbmVtZW50cyAuc29ydC1ieS1vcHRpb25zJyk7XG5cdFx0XHRcdGlmKHNvcnRCeU9wdGlvbnNDb250YWluZXIuaHRtbCgpLmxlbmd0aCA8IDEpIHtcblxuXHRcdFx0XHRcdC8vc29ydC1ieSBmb3JtIGZvciByZWZlcmVuY2UgYW5kIHB1bGxpbmcgb3B0aW9uc1xuXHRcdFx0XHRcdHZhciBjdXJyZW50U29ydEJ5T3B0aW9ucyA9ICQoJy5tb2JpbGUtcmVmaW5lbWVudHMgI3NvcnQtYnkgI2dyaWQtc29ydC1oZWFkZXIgb3B0aW9uJyk7XG5cblx0XHRcdFx0XHRzb3J0QnlPcHRpb25zQ29udGFpbmVyLmFwcGVuZChcIjx1bCBjbGFzcz0nc29ydC1ieS1saXN0Jz48L3VsPlwiKTtcblxuXHRcdFx0XHRcdC8vY3JlYXRlIG5ldyBsaXN0IHdpdGggZGF0YSBsaW5rZWQgdG8gZm9ybVxuXHRcdFx0XHRcdGN1cnJlbnRTb3J0QnlPcHRpb25zLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgc2VsZWN0ZWRWYWx1ZSA9ICQodGhpcykucHJvcCgnc2VsZWN0ZWQnKTtcblxuXHRcdFx0XHRcdFx0aWYgKHR5cGVvZiBzZWxlY3RlZFZhbHVlICE9PSB0eXBlb2YgdW5kZWZpbmVkICYmIHNlbGVjdGVkVmFsdWUgIT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRcdHZhciBuZXdPcHRpb24gPSAnPGxpIGNsYXNzPVwic2VsZWN0YWJsZS1vcHRpb24gc2VsZWN0ZWRcIiBkYXRhLW9wdGlvbi1mb3I9XCInICArICQodGhpcykuYXR0cigndmFsdWUnKSArICdcIj4nICsgJCh0aGlzKS50ZXh0KCkgKyAnPC9saT4nO1xuXHRcdFx0XHRcdFx0XHRzb3J0QnlPcHRpb25zQ29udGFpbmVyLmZpbmQoJ3VsJykuYXBwZW5kKG5ld09wdGlvbik7XG5cdFx0XHRcdFx0XHR9IGVsc2UgIHtcblx0XHRcdFx0XHRcdFx0dmFyIG5ld09wdGlvbiA9ICc8bGkgY2xhc3M9XCJzZWxlY3RhYmxlLW9wdGlvblwiIGRhdGEtb3B0aW9uLWZvcj1cIicgICsgJCh0aGlzKS5hdHRyKCd2YWx1ZScpICsgJ1wiPicgKyAkKHRoaXMpLnRleHQoKSArICc8L2xpPic7XG5cdFx0XHRcdFx0XHRcdHNvcnRCeU9wdGlvbnNDb250YWluZXIuZmluZCgndWwnKS5hcHBlbmQobmV3T3B0aW9uKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcblx0XHRcdFx0fVxuXHRcdFx0XHQvL3RvZ2dsZSBzb3J0LWJ5IG9wdGlvbnMgdG8gYWN0aXZlIHN0YXRlXG5cdFx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnktb3B0aW9ucycpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCh0aGlzKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHR9IGVsc2UgaWYgKCQodGhpcykuaGFzQ2xhc3MoJ3JlZmluZS10b2dnbGUnKSkge1xuXHRcdFx0XHQvL0Vuc3VyZSBib3RoIHNvcnQtYnkgYW5kIHJlZmluZW1lbnRzIGFyZW4ndCBvcGVuIHNpbXVsdGFuZW91c2x5XG5cdFx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnktb3B0aW9ucycpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblx0XHRcdFx0JCgnLm1vYmlsZS1yZWZpbmVtZW50cyAuc29ydC1ieS10b2dnbGUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdC8vdG9nZ2xlIHJlZmluZW1lbnRzIG9wdGlvbnMgdG8gYWN0aXZlIHN0YXRlXG5cdFx0XHRcdCQoJyNzZWNvbmRhcnkucmVmaW5lbWVudHMnKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG5cdFx0XHRcdCQodGhpcykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuXHRcdFx0fVxuXHRcdH1cdFxuXHR9KTtcblx0JG1haW4ub24oJ2NsaWNrJywgJy5zb3J0LWJ5LW9wdGlvbnMgLnNvcnQtYnktbGlzdCAuc2VsZWN0YWJsZS1vcHRpb24nLCBmdW5jdGlvbigpIHtcblx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHRcdC8vc2V0IGNvcnJlY3Qgc29ydC1ieSBmb3JtIG9wdGlvbiBhcyBzZWxlY3RlZFxuXHRcdFx0dmFyIG9wdGlvblZhbHVlID0gJCh0aGlzKS5hdHRyKCdkYXRhLW9wdGlvbi1mb3InKTtcblx0XHRcdCQoJy5tb2JpbGUtcmVmaW5lbWVudHMgLnNvcnQtYnkjc29ydC1ieSBmb3JtICNncmlkLXNvcnQtaGVhZGVyIG9wdGlvblt2YWx1ZT1cIicrb3B0aW9uVmFsdWUrJ1wiXScpLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XG5cdFx0XHQvL1RyaWdnZXIgZm9ybSBjaGFuZ2UgdG8gZmlyZSBzb3J0LWJ5IGNoYW5nZSB3YXRjaGVyXG5cdFx0XHQkKCcubW9iaWxlLXJlZmluZW1lbnRzIC5zb3J0LWJ5I3NvcnQtYnkgZm9ybSAjZ3JpZC1zb3J0LWhlYWRlciBvcHRpb24nKS5jaGFuZ2UoKTtcblx0XHR9XG5cdH0pO1xuXG4gICAgLy8gcmVmaW5lbWVudCBjaGVja2JveGVzXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5yZWZpbmVtZW50IC5jaGVja3MgaW5wdXQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkcmVmaW5lbWVudCA9ICR0aGlzLmNsb3Nlc3QoJ1tyZWZpbmVtZW50LXZhbHVlXScpO1xuXHRcdGlmICgkcmVmaW5lbWVudC5sZW5ndGggPiAwICYmICEkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cdFx0fVxuXG5cdFx0aWYgKCR0aGlzLmNsb3Nlc3QoJy5yZWZpbmVtZW50LnNvcnQtYnknKS5sZW5ndGggPiAwKSB7XG5cdFx0XHQkdGhpcy5jbG9zZXN0KCcucmVmaW5lbWVudC1ib2R5JykuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdIGlucHV0Jykubm90KCR0aGlzKS5yZW1vdmVDbGFzcygnbW9kaWZpZWQnKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdFx0JHRoaXMudG9nZ2xlQ2xhc3MoJ21vZGlmaWVkJyk7XG5cdFx0fVxuICAgIFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG5cdFx0XHR2YXIgcmVmaW5lbWVudFZhbHVlID0gJHRoaXMudmFsKCkucmVwbGFjZSgnXCInLFwiIElOQ0hcIik7XG4gICAgXHRcdGlmICgkdGhpcy5jbG9zZXN0KCdbaXMtcHJpY2UtcmVmaW5lbWVudD1cInRydWVcIl0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCQoJ1tpcy1wcmljZS1yZWZpbmVtZW50PVwidHJ1ZVwiXSBpbnB1dCcpLm5vdCgkdGhpcykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKS5yZW1vdmVBdHRyKCdjaGVja2VkJykucmVtb3ZlQ2xhc3MoJ21vZGlmaWVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnRvZ2dsZUNsYXNzKCdtb2RpZmllZCcpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFyICRlcXVhbFZhbHVlSW5wdXRzID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQtYm9keScpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlPVwiJyArIHJlZmluZW1lbnRWYWx1ZSArICdcIl0nKTtcblx0ICAgIFx0XHQkZXF1YWxWYWx1ZUlucHV0cy50b2dnbGVDbGFzcygnbW9kaWZpZWQnKTtcblx0ICAgIFx0XHQkZXF1YWxWYWx1ZUlucHV0cy5ub3QoJHRoaXMpLnByb3AoJ2NoZWNrZWQnLCAkdGhpcy5wcm9wKCdjaGVja2VkJykpO1xuICAgIFx0XHR9XG4gICAgXHRcdHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKTtcbiAgICBcdFx0cmV0dXJuO1x0XG4gICAgXHR9XG5cblx0XHRpZiAoU2l0ZVByZWZlcmVuY2VzLkdBX05FV19BQ1RJT05TX0VOQUJMRUQgJiYgJHRoaXMuaXMoJzpjaGVja2VkJykpIHtcblx0XHRcdHZhciByZWZpbmVtZW50SWQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC1pZF0nKS5hdHRyKCdyZWZpbmVtZW50LWlkJykgfHwgbnVsbDtcblx0XHRcdHZhciByZWZpbmVtZW50VmFsdWUgPSAkdGhpcy52YWwoKSA/ICR0aGlzLnZhbCgpLnJlcGxhY2UoJ1wiJyxcIiBJTkNIXCIpIDogbnVsbDtcblx0XHRcdGlmIChyZWZpbmVtZW50SWQgJiYgcmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHRcdHZhciByZWZpbmVtZW50QW5hbHl0aWNzVGFnZ2luZ0RhdGEgPSAgeyBcblx0XHRcdFx0XHQnYWN0aW9uX3ZhbHVlJzogeyAncmVmaW5lbWVudF9jYXRlZ29yeSc6IHJlZmluZW1lbnRJZCB9LCBcblx0XHRcdFx0XHQnYWN0aW9uX2l0ZW1zJzogeyAncmVmaW5lbWVudF92YWx1ZSc6IHJlZmluZW1lbnRWYWx1ZSB9XG5cdFx0XHRcdH07XG5cdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FwcGx5UmVmaW5lbWVudCcsIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIHVybCA9ICQodGhpcykucGFyZW50cygnbGknKS5maXJzdCgpLmZpbmQoJy52aXN1YWxseS1oaWRkZW4gPiBhJykuZmlyc3QoKS5hdHRyKCdocmVmJyk7XG5cdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcodXJsKTtcbiAgICB9KTtcblxuICAgICRtYWluLm9uKCdjbGljaycsICcucmVzdWx0LW9wdGlvbnMgLnN3aXRjaCBpbnB1dFtuYW1lPVwiZmllbGQtc3dpdGNoXCJdJywgZnVuY3Rpb24gKCkge1xuICAgIFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG4gICAgXHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKCQodGhpcykucGFyZW50cygnLnN3aXRjaCcpLmZpbmQoJy52aXN1YWxseS1oaWRkZW4gaW5wdXRbbmFtZT1cImZpZWxkLXRydWVcIl0gKyBhJykuZmlyc3QoKS5hdHRyKCdocmVmJykpO1xuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0ZG9jdW1lbnQubG9jYXRpb24gPSAkKHRoaXMpLnBhcmVudHMoJy5zd2l0Y2gnKS5maW5kKCcudmlzdWFsbHktaGlkZGVuIGlucHV0W25hbWU9XCJmaWVsZC10cnVlXCJdICsgYScpLmZpcnN0KCkuYXR0cignaHJlZicpO1xuICAgIFx0fVxuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5saXN0LXNlbGVjdGlvbnMgbGk6bm90KC5wZW5kaW5nLXNlbGVjdGlvbnMpIGEuY2xvc2UtYnRuLCAuY2xlYXItYWxsIC5jbG9zZS1idG4nLCBmdW5jdGlvbiAoZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgIFx0aWYgKCR0aGlzLmNsb3Nlc3QoJy52YWx1ZScpLmhhc0NsYXNzKCdhcHBsaWVkJykgJiYgJHRoaXMuY2xvc2VzdCgnLm1vZGFsJykubGVuZ3RoID4gMCkge1xuICAgIFx0XHQkdGhpcy5jbG9zZXN0KCcudmFsdWUnKS50b2dnbGVDbGFzcygncGVuZGluZy1jbGVhcicpO1xuICAgIFx0XHRyZWRyYXdVcGRhdGVkUmVmaW5lbWVudEhhbmRsaW5nKCk7XG4gICAgXHRcdHJldHVybjtcdFxuICAgIFx0fVxuXG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblx0XHR2YXIgYWN0aXZlUmVmaW5lbWVudHNDb3VudCA9ICQoJ1tyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxlbmd0aCAtICQoJy5zd2F0Y2hlc1tjbGFzcyo9XCJwb3B1bGFyLVwiXSBbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKS5sZW5ndGg7XG5cdFx0aWYgKGFjdGl2ZVJlZmluZW1lbnRzQ291bnQgPT0gMSAmJiBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50ICYmIG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQuVXJsKSB7XG5cdFx0XHRsb2NhdGlvbi5ocmVmID0gb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudC5Vcmw7XG4gICAgXHRcdHJldHVybjtcblx0XHR9XG5cbiAgICBcdHZhciBocmVmID0gJHRoaXMuYXR0cignaHJlZicpO1xuICAgIFx0aWYgKGhyZWYgPT0gbnVsbCB8fCBocmVmID09ICdudWxsJykge1xuICAgIFx0XHR2YXIgc2VhcmNoID0gZG9jdW1lbnQubG9jYXRpb24uc2VhcmNoO1xuICAgIFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZyhkb2N1bWVudC5sb2NhdGlvbi5wYXRobmFtZSArIHNlYXJjaC5zdWJzdHIoMCwgc2VhcmNoLmluZGV4T2YoJyYnKSkpO1xuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0dXBkYXRlUHJvZHVjdExpc3RpbmcoaHJlZik7XG4gICAgXHR9XG5cdH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICcubGlzdC1zZWxlY3Rpb25zIGxpLnBlbmRpbmctc2VsZWN0aW9ucyBhLmNsb3NlLWJ0bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBcdHZhciBwZW5kaW5nUmVmaW5lbWVudElkID0gJCh0aGlzKS5jbG9zZXN0KCdbZGF0YS1yZWZncm91cC1pZF0nKS5hdHRyKCdkYXRhLXJlZmdyb3VwLWlkJyk7XG4gICAgXHR2YXIgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSA9ICQodGhpcykuY2xvc2VzdCgnc3BhbicpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKTtcblx0XHR2YXIgc2VsZWN0b3IgPSAnW3JlZmluZW1lbnQtaWQ9XCInICsgcGVuZGluZ1JlZmluZW1lbnRJZCArICdcIl0gdWwgW3JlZmluZW1lbnQtdmFsdWU9XCInICsgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSArICdcIl0nO1xuXG4gICAgXHR2YXIgJHBlbmRpbmdSZWZpbmVtZW50SW5wdXQgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKHNlbGVjdG9yKTsgICAgXHRcbiAgICBcdGlmICgkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdpbnB1dCcpLmxlbmd0aCA+IDApIHtcbiAgICBcdFx0JHBlbmRpbmdSZWZpbmVtZW50SW5wdXQuZmluZCgnaW5wdXQnKS5jbGljaygpO1xuICAgIFx0fSBlbHNlIGlmICgkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdhJykubGVuZ3RoID4gMCkge1xuICAgIFx0XHQkcGVuZGluZ1JlZmluZW1lbnRJbnB1dC5maW5kKCdhJykuY2xpY2soKTtcbiAgICBcdH1cblx0fSk7XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5wcm9kdWN0LXN3YXRjaGVzLWFjY29yZGlvbi1idXR0b24nLCBmdW5jdGlvbiAoKSB7XG4gICAgXHR2YXIgJGFjY29yZGlvbiA9ICQodGhpcykuY2xvc2VzdCgnLmFjY29yZGlvbicpO1xuICAgIFx0XG4gICAgXHRpZiAoJGFjY29yZGlvbi5sZW5ndGggPiAwKSB7XG4gICAgXHRcdCRhY2NvcmRpb24udG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIFx0fVxuICAgIH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2hvcE15U3RvcmUnLCAnLnNob3AtbXktc3RvcmUgLmNoZWNrYm94LXRvZ2dsZSBpbnB1dCcpLm9uKCdjbGljay5TaG9wTXlTdG9yZScsICcuc2hvcC1teS1zdG9yZSAuY2hlY2tib3gtdG9nZ2xlIGlucHV0JywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXG5cdFx0dmFyIHVybDtcblx0XHRpZiAoJHRoaXMucHJvcCgnY2hlY2tlZCcpKSAge1xuXHRcdFx0dXJsID0gJHRoaXMuYXR0cignaHJlZi1yZWZpbmUnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dXJsID0gJHRoaXMuYXR0cignaHJlZi1yZWxheCcpO1xuXHRcdFx0JCgnYm9keScpLmF0dHIoJ2lzLXNob3AtbXktc3RvcmUtYWN0aXZlJywgZmFsc2UpO1xuXHRcdH1cblxuXHRcdGlmICh1cmwpIHtcblx0XHRcdCQoJy5zaG9wLW15LXN0b3JlIC5jaGVja2JveC10b2dnbGUnKS5sb2FkaW5nKHsgSXNMYWJlbFNob3duOiBmYWxzZSwgSXNJbWFnZVNob3duOiBmYWxzZSB9KTtcblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKGxvYWRpbmdJbmRpY2F0b3JTZXR0aW5ncyk7XG5cblx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ1Nob3BZb3VyU3RvcmUnLCB7IGVuYWJsZWQ6ICR0aGlzLnByb3AoJ2NoZWNrZWQnKSB9KTtcblxuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3Nob3BteXN0b3JlJywgJHRoaXMucHJvcCgnY2hlY2tlZCcpKTtcblx0XHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuICAgIH0pO1xuXG5cdCQoZG9jdW1lbnQpLm9mZignU2hvcE15U3RvcmUuVXBkYXRlJykub24oJ1Nob3BNeVN0b3JlLlVwZGF0ZScsIGZ1bmN0aW9uKGV2ZW50LCBzdG9yZUlkKSB7XG5cdFx0aWYgKCQoJy5zaG9wLW15LXN0b3JlIC5jaGVja2JveC10b2dnbGUgaW5wdXQnKS5wcm9wKCdjaGVja2VkJykpIHtcblx0XHRcdHZhciB1cmwgPSBsb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyBsb2NhdGlvbi5ob3N0bmFtZSArIGxvY2F0aW9uLnBhdGhuYW1lO1xuXHRcdFx0dmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycyA9IHV0aWwuZ2V0UXVlcnlTdHJpbmdQYXJhbXMobG9jYXRpb24uc2VhcmNoKTtcblx0XHRcdGZvciAodmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyS2V5IGluIHF1ZXJ5U3RyaW5nUGFyYW1ldGVycykge1xuXHRcdFx0XHR2YXIgcXVlcnlTdHJpbmdQYXJhbWV0ZXJWYWx1ZSA9IHF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1txdWVyeVN0cmluZ1BhcmFtZXRlcktleV07XG5cdFx0XHRcdGlmIChxdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlICYmIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUuaW5kZXhPZignYXZhaWxhYmxlU3RvcmVzJykgPiAtMSkge1xuXHRcdFx0XHRcdHZhciByZWZpbmVtZW50SW5kZXg7XG5cdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRJbmRleE1hdGNoID0gcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXkubWF0Y2goL3ByZWZuKFswLTldKSsvKTtcblx0XHRcdFx0XHRpZiAocmVmaW5lbWVudEluZGV4TWF0Y2ggJiYgcmVmaW5lbWVudEluZGV4TWF0Y2gubGVuZ3RoID4gMSkge1xuXHRcdFx0XHRcdFx0cmVmaW5lbWVudEluZGV4ID0gcmVmaW5lbWVudEluZGV4TWF0Y2hbMV07XG5cdFx0XHRcdFx0fVx0XHRcdFx0XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHRpZiAocmVmaW5lbWVudEluZGV4ICYmIHN0b3JlSWQpIHtcblx0XHRcdFx0cXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydwcmVmdicgKyByZWZpbmVtZW50SW5kZXhdID0gc3RvcmVJZDtcblx0XHRcdH1cblx0XG5cdFx0XHRmb3IgKHZhciBxdWVyeVN0cmluZ1BhcmFtZXRlcktleSBpbiBxdWVyeVN0cmluZ1BhcmFtZXRlcnMpIHtcblx0XHRcdFx0dmFyIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUgPSBxdWVyeVN0cmluZ1BhcmFtZXRlcnNbcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXldO1xuXHRcdFx0XHRpZiAocXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXkgIT0gJ3N0YXJ0JyAmJiBxdWVyeVN0cmluZ1BhcmFtZXRlcktleSAhPSAnc3onKSB7XG5cdFx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgcXVlcnlTdHJpbmdQYXJhbWV0ZXJLZXksIHF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKHtcblx0XHRcdFx0SXNJbWFnZVNob3duOiBmYWxzZSxcblx0XHRcdFx0Q29udGVudDogJzxoNj5Ib2xkIFlvdXIgSG9yc2VzITwvaDY+PHA+WW91ciBzZWxlY3Rpb25zIGFyZSBsb2FkaW5nLi4uPC9wPicsXG5cdFx0XHRcdENzc0NsYXNzOiAnc2hvcHlvdXJzdG9yZScsXG5cdFx0XHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSk7XG5cblx0XHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlZHJhd1Nob3BNeVN0b3JlKCk7XG5cdFx0fVxuXHR9KTtcblxuICAgIHNlYXJjaFN0b3JlcygpO1xuICAgIGluaXRpYWxpemVSZWZpbmVtZW50Q29udHJvbHMoKTtcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Cb290QmFyblVTKSB7XG5cdFx0JCgnI2dyaWQtc29ydC1oZWFkZXInKS5zZWxlY3RtZW51KHtcblx0XHRcdCd3aWR0aCc6IDIwNVxuXHRcdH0pO1xuXHR9XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5hcHBseS1yZWZpbmVtZW50czpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50c0RlbHRhID0gJCgnI3NlY29uZGFyeSBbcmVmaW5lbWVudC12YWx1ZV06bm90KC5zZWxlY3RlZCk6bm90KFtjbGFzcyo9XCJwb3B1bGFyXCJdKS5tb2RpZmllZCcpLmxlbmd0aCAtICQoJyNzZWNvbmRhcnkgW3JlZmluZW1lbnQtdmFsdWVdLnNlbGVjdGVkOm5vdChbY2xhc3MqPVwicG9wdWxhclwiXSkubW9kaWZpZWQnKS5sZW5ndGg7XG5cdFx0dmFyIGFjdGl2ZVJlZmluZW1lbnRzQ291bnQgPSAkKCcjc2Vjb25kYXJ5IFtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxlbmd0aCAtICQoJyNzZWNvbmRhcnkgLnN3YXRjaGVzW2NsYXNzKj1cInBvcHVsYXItXCJdIFtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZCcpLmxlbmd0aCAtICQoJyNzZWNvbmRhcnkgLmxpc3Qtc2VsZWN0aW9ucyAucGVuZGluZy1jbGVhcicpLmxlbmd0aCArIHBlbmRpbmdSZWZpbmVtZW50c0RlbHRhO1xuXHRcdGlmIChhY3RpdmVSZWZpbmVtZW50c0NvdW50ID09IDAgJiYgb3B0aW9ucy5DYXRlZ29yeUxhbmRpbmdQYWdlQ29udGVudCAmJiBvcHRpb25zLkNhdGVnb3J5TGFuZGluZ1BhZ2VDb250ZW50LlVybCkge1xuXHRcdFx0bG9jYXRpb24uaHJlZiA9IG9wdGlvbnMuQ2F0ZWdvcnlMYW5kaW5nUGFnZUNvbnRlbnQuVXJsO1xuICAgIFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5HQV9ORVdfQUNUSU9OU19FTkFCTEVEKSB7XG5cdFx0XHR2YXIgJHJlZmluZW1lbnQgPSAgJCgnLnJlZmluZW1lbnRzJykuZmluZCgnW3JlZmluZW1lbnQtaWRdOm5vdCguc29ydC1ieSknKTtcblx0XHRcdHZhciAkc2VsZWN0ZWRSZWZpbmVtZW50cyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsOm5vdChbY2xhc3MqPVwicG9wdWxhclwiXSkgbGlbcmVmaW5lbWVudC12YWx1ZV06bm90KC5zZWxlY3RlZCkubW9kaWZpZWQsIHVsOm5vdChbY2xhc3MqPVwicG9wdWxhclwiXSkgbGlbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQ6bm90KC5tb2RpZmllZCknKTtcblx0XHRcdGlmICgkc2VsZWN0ZWRSZWZpbmVtZW50cy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdHZhciByZWZpbmVtZW50SWQsIHJlZmluZW1lbnRWYWx1ZTtcblx0XHRcdFx0JHNlbGVjdGVkUmVmaW5lbWVudHMuZWFjaChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0cmVmaW5lbWVudElkID0gJCh0aGlzKS5jbG9zZXN0KCdbcmVmaW5lbWVudC1pZF0nKS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlID0gcmVmaW5lbWVudElkLnRvVXBwZXJDYXNlKCkgPT0gJ1BSSUNFJyA/ICQodGhpcykuZmluZCgnLnJlZmluZW1lbnQtbGFiZWwnKS50ZXh0KCkucmVwbGFjZSgvXFxzKy9nLCAnICcpLnRyaW0oKSA6ICQodGhpcykuYXR0cigncmVmaW5lbWVudC12YWx1ZScpLnJlcGxhY2UoJyBJTkNIJywnXCInKTtcblx0XHRcdFx0XHRpZiAocmVmaW5lbWVudElkICYmIHJlZmluZW1lbnRWYWx1ZSkge1xuXHRcdFx0XHRcdFx0dmFyIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSA9ICB7IFxuXHRcdFx0XHRcdFx0XHQnYWN0aW9uX3ZhbHVlJzogeyAncmVmaW5lbWVudF9jYXRlZ29yeSc6IHJlZmluZW1lbnRJZCB9LCBcblx0XHRcdFx0XHRcdFx0J2FjdGlvbl9pdGVtcyc6IHsgJ3JlZmluZW1lbnRfdmFsdWUnOiByZWZpbmVtZW50VmFsdWUgfVxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoJ0FwcGx5UmVmaW5lbWVudCcsIHJlZmluZW1lbnRBbmFseXRpY3NUYWdnaW5nRGF0YSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG4gICAgXHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuICAgIFx0dXBkYXRlUHJvZHVjdExpc3RpbmcoYnVpbGRVcmxGb3JTZWxlY3RlZFJlZmluZW1lbnRzKG51bGwsIG51bGwsIGZhbHNlLCB0cnVlKSk7XG4gICAgfSk7XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5jbGVhci1yZWZpbmVtZW50czpub3QoLmRpc2FibGVkKScsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XG4gICAgXHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgIFx0dmFyIGhyZWYgPSAkdGhpcy5hdHRyKCdocmVmJyk7XG4gICAgXHR2YXIgJHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucyA9ICQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItaGVhZGVyIC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcbiAgICBcdFxuICAgIFx0aWYgKCRyZWZpbmVtZW50c01vZGFsUHJvZHVjdFNlbGVjdGlvbnMuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyAudmFsdWUuYXBwbGllZCcpLmxlbmd0aCA+IDApIHtcbiAgICBcdFx0aWYgKGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpKSB7XG4gICAgXHRcdFx0JCgnLmNsZWFyLXJlZmluZW1lbnRzJykubG9hZGluZyh7XG4gICAgXHRcdFx0XHRJc0ltYWdlU2hvd246IGZhbHNlXHRcbiAgICBcdFx0XHR9KTtcbiAgICBcdFx0XHR1cGRhdGVQcm9kdWN0TGlzdGluZygkKHRoaXMpLmF0dHIoJ2hyZWYnKSk7XG4gICAgXHRcdH0gZWxzZSB7XG4gICAgXHRcdFx0ZG9jdW1lbnQubG9jYXRpb24gPSAkKHRoaXMpLmF0dHIoJ2hyZWYnKTtcbiAgICBcdFx0fVxuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0JCgnLnJlZmluZW1lbnRbdXVpZF0nKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXTpub3QoLnNlbGVjdGVkKS5tb2RpZmllZCcpLnJlbW92ZUNsYXNzKCdtb2RpZmllZCcpO1xuICAgIFx0XHQkKCcucmVmaW5lbWVudFt1dWlkXScpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpJykuZmluZCgnaW5wdXQ6Y2hlY2tlZCcpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG4gICAgXHRcdHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoKTtcbiAgICBcdH1cbiAgICB9KTtcblxuXHQkKGRvY3VtZW50KS5vbignY2xpY2snLCAnI21haW4gLmJ0bi5sb2FkLW1vcmU6bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dmFyICRsb2FkTW9yZUJ1dHRvbiA9ICQodGhpcyk7XG5cblx0XHQvLyBMZXQncyBkaXNhYmxlIHRoZSBidXR0b24gYWZ0ZXIgZmlyc3QgY2xpY2ssIHNvIHRoYXQgZnVuY3Rpb25hbGl0eSBjYW4gY29tcGxldGUgYmVmb3JlIGJlaW5nIHJlLWVuYWJsZWRcblx0XHQkbG9hZE1vcmVCdXR0b24uYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cblx0XHRpZiAoIWRhdGFCdWZmZXJbJ1BhZ2luYXRpb25JbmRleCddKSB7XG5cdFx0XHRkYXRhQnVmZmVyWydQYWdpbmF0aW9uSW5kZXgnXSA9IG9wdGlvbnMuUGFnaW5hdGlvbi5TdGFydDtcblx0XHR9XG5cdFx0aWYgKCFkYXRhQnVmZmVyWydQYWdpbmF0aW9uQ291bnQnXSkge1xuXHRcdFx0ZGF0YUJ1ZmZlclsnUGFnaW5hdGlvbkNvdW50J10gPSBvcHRpb25zLlBhZ2luYXRpb24uQ291bnQ7XG5cdFx0fVxuXHRcdFxuXHRcdHZhciB1cmwgPSBkb2N1bWVudC5sb2NhdGlvbi5ocmVmO1xuXHRcdHZhciBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh1dGlsLmdldFF1ZXJ5U3RyaW5nKHVybCkpO1xuXHRcdGlmIChjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydzdGFydCddKSB7XG5cdFx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdzdGFydCcpO1xuXHRcdH1cblx0XHR1cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwodXJsLCAnc3RhcnQnLCBkYXRhQnVmZmVyWydQYWdpbmF0aW9uSW5kZXgnXSArIG9wdGlvbnMuUGFnaW5hdGlvbi5TaXplKTtcblxuXHRcdHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHVybCwgZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBVc2UgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIHJlLWVuYWJsZSB0aGUgTG9hZCBNb3JlIGJ1dHRvblxuXHRcdFx0JGxvYWRNb3JlQnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHRcdH0sIHRydWUpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gdG9nZ2xlQm9keVNjcm9sbExvY2soKSB7XG5cdHZhciAkYm9keSA9ICQoJ2JvZHknKTtcblx0dmFyIGJvZHlTY3JvbGxMb2NrQ2xhc3MgPSAncmVmaW5lbWVudHMtbW9iaWxlLXNjcm9sbC1sb2NrJztcblxuXHRpZiAoJGJvZHkuaGFzQ2xhc3MoYm9keVNjcm9sbExvY2tDbGFzcykpIHtcblx0XHQkYm9keS5yZW1vdmVDbGFzcyhib2R5U2Nyb2xsTG9ja0NsYXNzKTtcblx0XHQkYm9keS5jc3MoJ3RvcCcsICcnKTtcblx0XHRkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPSBkYXRhQnVmZmVyWydzY3JvbGxUb3AnXTtcblx0fSBlbHNlIHtcblx0XHR2YXIgc2Nyb2xsVG9wID0gZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcDtcbiAgICBcdGRhdGFCdWZmZXJbJ3Njcm9sbFRvcCddID0gc2Nyb2xsVG9wO1xuICAgIFx0JGJvZHkuY3NzKCd0b3AnLCAwIC0gc2Nyb2xsVG9wKTtcbiAgICBcdCRib2R5LmFkZENsYXNzKGJvZHlTY3JvbGxMb2NrQ2xhc3MpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVXJsRm9yU2VsZWN0ZWRSZWZpbmVtZW50cyhiYXNlVXJsLCB1cmxGb3JQYXJhbWV0ZXJzLCBpbmNsdWRlQ2F0ZWdvcnksIGluY2x1ZGVTb3J0KSB7XG5cdHZhciByZWZpbmVtZW50VmFsdWVzQnVmZmVyID0ge307XG5cdFxuXHQkcmVmaW5lbWVudHNJbm5lci5maW5kKCdbcmVmaW5lbWVudC1pZF06bm90KC5wcmljZS1yZWZpbmVtZW50KTpub3QoLnNvcnQtYnkpJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJHJlZmluZW1lbnQgPSAkKHRoaXMpO1xuXHRcdHZhciAkc2VsZWN0ZWRSZWZpbmVtZW50cyA9ICRyZWZpbmVtZW50LmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdOm5vdCguc2VsZWN0ZWQpLm1vZGlmaWVkLCBsaVtyZWZpbmVtZW50LXZhbHVlXS5zZWxlY3RlZDpub3QoLm1vZGlmaWVkKScpO1xuXHRcdFxuXHRcdGlmICgkc2VsZWN0ZWRSZWZpbmVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgXHRcdHZhciByZWZpbmVtZW50SWQgPSAkcmVmaW5lbWVudC5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG4gICAgXHRcdHZhciBtYXBwZWRSZWZpbmVtZW50SWQ7XG5cdFx0XHRpZiAocmVmaW5lbWVudElkID09ICdhdmFpbGFibGVTdG9yZXMyJyB8fCByZWZpbmVtZW50SWQgPT0gJ2F2YWlsYWJsZVN0b3JlczMnKSB7XG5cdFx0XHRcdG1hcHBlZFJlZmluZW1lbnRJZCA9ICdhdmFpbGFibGVTdG9yZXMnO1x0XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXBwZWRSZWZpbmVtZW50SWQgPSByZWZpbmVtZW50SWQ7XG5cdFx0XHR9XG4gICAgXHRcdFxuICAgIFx0XHRpZiAoIXJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbbWFwcGVkUmVmaW5lbWVudElkXSkge1xuICAgIFx0XHRcdHJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbbWFwcGVkUmVmaW5lbWVudElkXSA9IFtdO1xuICAgIFx0XHR9XG4gICAgXHRcdFxuICAgIFx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50cy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBcdFx0XHR2YXIgdmFsdWUgPSAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKS5yZXBsYWNlKCcgSU5DSCcsJ1wiJyk7XG4gICAgXHRcdFx0dmFyIGlzTmV3VmFsdWUgPSB0cnVlO1xuICAgIFx0XHRcdGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCByZWZpbmVtZW50VmFsdWVzQnVmZmVyW21hcHBlZFJlZmluZW1lbnRJZF0ubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgXHRcdFx0XHRpZiAocmVmaW5lbWVudFZhbHVlc0J1ZmZlclttYXBwZWRSZWZpbmVtZW50SWRdW2luZGV4XSA9PSB2YWx1ZSkge1xuICAgIFx0XHRcdFx0XHRpc05ld1ZhbHVlID0gZmFsc2U7XG4gICAgXHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0XG4gICAgXHRcdFx0aWYgKGlzTmV3VmFsdWUgJiYgJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyBbZGF0YS1yZWZncm91cC1pZD1cIicgKyByZWZpbmVtZW50SWQgKyAnXCJdIFt2YWx1ZT1cIicgKyAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKS5yZXBsYWNlKC9bXCInXS9nLCBcIlwiKSArICdcIl0ucGVuZGluZy1jbGVhcicpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdFx0cmVmaW5lbWVudFZhbHVlc0J1ZmZlclttYXBwZWRSZWZpbmVtZW50SWRdLnB1c2godmFsdWUpO1xuICAgIFx0XHRcdH1cbiAgICBcdFx0fSk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdHZhciB1cmwgPSBiYXNlVXJsIHx8IG9wdGlvbnMuU2VhcmNoVXJsO1xuXHR2YXIgY3VycmVudENhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0aWYgKGluY2x1ZGVDYXRlZ29yeSAmJiBjdXJyZW50Q2F0ZWdvcnlJZCAmJiBjdXJyZW50Q2F0ZWdvcnlJZCAhPSAnbnVsbCcpIHtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdjZ2lkJyk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSk7XG5cdH1cblx0XG5cdHZhciBjdXJyZW50UXVlcnlTdHJpbmcgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nKHVybEZvclBhcmFtZXRlcnMgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZik7XG5cdHZhciBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyhjdXJyZW50UXVlcnlTdHJpbmcpO1xuXHRpZiAoY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1sncSddKSB7XG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncScpO1xuXHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdxJywgb3B0aW9ucy5TZWFyY2hQaHJhc2UpO1xuXHR9XG5cdFxuXHRpZiAoY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1snc3J1bGUnXSkge1xuXHRcdHVybCA9IHV0aWwucmVtb3ZlUGFyYW1Gcm9tVVJMKHVybCwgJ3NydWxlJyk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NydWxlJywgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyc1snc3J1bGUnXSk7XG5cdH1cblxuXHR2YXIgYXZhaWxhYmxlU3RvcmVzVmFsdWU7XG5cdHZhciBhY3RpdmVSZWZpbmVtZW50SW5kZXggPSAxO1xuXHR3aGlsZSAodXJsLmluZGV4T2YoJ3ByZWZuJyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleCkgPj0gMCkge1xuXHRcdGlmIChjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzWydwcmVmbicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXhdID09ICdhdmFpbGFibGVTdG9yZXMnKSB7XG5cdFx0XHRhdmFpbGFibGVTdG9yZXNWYWx1ZSA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnNbJ3ByZWZ2JyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleF07XG5cdFx0fVxuXG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncHJlZm4nICsgYWN0aXZlUmVmaW5lbWVudEluZGV4KTtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdwcmVmdicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXgpO1xuXHRcdGFjdGl2ZVJlZmluZW1lbnRJbmRleCsrO1xuXHR9XG5cblx0dmFyIGF2YWlsYWJsZVN0b3Jlc1JlZmluZW1lbnRJbmRleDtcblx0Zm9yICh2YXIgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyS2V5IGluIGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnMpIHtcblx0XHR2YXIgY3VycmVudFF1ZXJ5U3RyaW5nUGFyYW1ldGVyVmFsdWUgPSBjdXJyZW50UXVlcnlTdHJpbmdQYXJhbWV0ZXJzW2N1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcktleV07XG5cdFx0aWYgKGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlICYmIGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlclZhbHVlLmluZGV4T2YoJ2F2YWlsYWJsZVN0b3JlcycpID4gLTEpIHtcblx0XHRcdHZhciByZWZpbmVtZW50SW5kZXhNYXRjaCA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcktleS5tYXRjaCgvcHJlZm4oWzAtOV0pKy8pO1xuXHRcdFx0aWYgKHJlZmluZW1lbnRJbmRleE1hdGNoICYmIHJlZmluZW1lbnRJbmRleE1hdGNoLmxlbmd0aCA+IDEpIHtcblx0XHRcdFx0YXZhaWxhYmxlU3RvcmVzUmVmaW5lbWVudEluZGV4ID0gcmVmaW5lbWVudEluZGV4TWF0Y2hbMV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aWYgKCFhdmFpbGFibGVTdG9yZXNWYWx1ZSAmJiBhdmFpbGFibGVTdG9yZXNSZWZpbmVtZW50SW5kZXgpIHtcblx0XHRhdmFpbGFibGVTdG9yZXNWYWx1ZSA9IGN1cnJlbnRRdWVyeVN0cmluZ1BhcmFtZXRlcnNbJ3ByZWZ2JyArIGF2YWlsYWJsZVN0b3Jlc1JlZmluZW1lbnRJbmRleF07XG5cdH1cblxuXHRpZiAoYXZhaWxhYmxlU3RvcmVzVmFsdWUgJiYgIXJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbJ2F2YWlsYWJsZVN0b3JlcyddKSB7XG5cdFx0cmVmaW5lbWVudFZhbHVlc0J1ZmZlclsnYXZhaWxhYmxlU3RvcmVzJ10gPSBbXTtcblx0XHRyZWZpbmVtZW50VmFsdWVzQnVmZmVyWydhdmFpbGFibGVTdG9yZXMnXS5wdXNoKGF2YWlsYWJsZVN0b3Jlc1ZhbHVlKTtcblx0fVxuXHRcblx0dmFyIGFjdGl2ZVJlZmluZW1lbnRJbmRleCA9IDE7XG5cdGZvciAodmFyIHJlZmluZW1lbnRJZCBpbiByZWZpbmVtZW50VmFsdWVzQnVmZmVyKSB7XG5cdFx0aWYgKHJlZmluZW1lbnRJZCAmJiByZWZpbmVtZW50VmFsdWVzQnVmZmVyW3JlZmluZW1lbnRJZF0ubGVuZ3RoID4gMCkge1xuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3ByZWZuJyArIGFjdGl2ZVJlZmluZW1lbnRJbmRleCwgcmVmaW5lbWVudElkKTtcblx0XHRcdHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcmVmdicgKyBhY3RpdmVSZWZpbmVtZW50SW5kZXgsIHJlZmluZW1lbnRWYWx1ZXNCdWZmZXJbcmVmaW5lbWVudElkXS5qb2luKCd8JykpO1xuXHRcdFx0YWN0aXZlUmVmaW5lbWVudEluZGV4Kys7XG5cdFx0fVxuXHR9XG5cdFxuXHRpZiAoJCgnW2lzLXByaWNlLXJlZmluZW1lbnQ9XCJ0cnVlXCJdIGlucHV0OmNoZWNrZWQnKS5sZW5ndGggPiAwKSB7XG5cdFx0dXJsID0gdXRpbC5yZW1vdmVQYXJhbUZyb21VUkwodXJsLCAncG1pbicpO1xuXHRcdHVybCA9IHV0aWwucmVtb3ZlUGFyYW1Gcm9tVVJMKHVybCwgJ3BtYXgnKTtcblx0XHRcblx0XHR2YXIgJHJlZmluZW1lbnRQcmljZSA9ICQoJ1tpcy1wcmljZS1yZWZpbmVtZW50PVwidHJ1ZVwiXSBpbnB1dDpjaGVja2VkJykuY2xvc2VzdCgnW2lzLXByaWNlLXJlZmluZW1lbnQ9XCJ0cnVlXCJdJyk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3BtaW4nLCAkcmVmaW5lbWVudFByaWNlLmF0dHIoJ3BtaW4nKSk7XG5cdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3BtYXgnLCAkcmVmaW5lbWVudFByaWNlLmF0dHIoJ3BtYXgnKSk7XG5cdH1cblxuXHRpZiAoaW5jbHVkZVNvcnQgJiYgY2hlY2tGb3JVcGRhdGVkUmVmaW5lbWVudEhhbmRsaW5nKCkpIHtcblx0XHR1cmwgPSB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh1cmwsICdzcnVsZScpO1xuXHRcdFxuXHRcdHZhciAkc29ydGluZ1J1bGUgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCcuc29ydC1ieSBvcHRpb246Y2hlY2tlZCwgLnNvcnQtYnkgaW5wdXQ6Y2hlY2tlZCcpO1xuXHRcdGlmICgkc29ydGluZ1J1bGUgJiYgJHNvcnRpbmdSdWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciBzb3J0aW5nUnVsZSA9ICRzb3J0aW5nUnVsZS5hdHRyKCdzb3J0aW5nLXJ1bGUnKTtcblxuXHRcdFx0aWYgKHNvcnRpbmdSdWxlICYmIHNvcnRpbmdSdWxlLmluZGV4T2YoJ0RlZmF1bHQnKSA8IDApIHtcblx0XHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NydWxlJywgc29ydGluZ1J1bGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB1cmw7XG59XG5cbmZ1bmN0aW9uIGNoZWNrRm9yVXBkYXRlZFJlZmluZW1lbnRIYW5kbGluZygpIHtcblx0aWYgKChvcHRpb25zLlJlZmluZW1lbnRzVUlWZXJzaW9uID09IFJlZmluZW1lbnRVSVZlcnNpb25Db25zdGFudHMuVXBkYXRlZCkgJiYgJGh0bWwuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykgJiYgKHBhZ2VDb250ZXh0LnNpdGUgIT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuUnNwVVMgfHwgb3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykpIHtcbiAgICBcdHJldHVybiB0cnVlO1xuXHR9XG5cdFxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJlZHJhd1VwZGF0ZWRSZWZpbmVtZW50SGFuZGxpbmcoJGNvbnRlbnRQYXJhbWV0ZXIsIHVybEZvclBhcmFtZXRlcnMpIHtcblx0dmFyICRjb250ZW50O1xuXHRpZiAoJGNvbnRlbnRQYXJhbWV0ZXIgJiYgJGNvbnRlbnRQYXJhbWV0ZXIubGVuZ3RoID4gMCkge1xuXHRcdCRjb250ZW50ID0gJGNvbnRlbnRQYXJhbWV0ZXIuZmluZCgnLnJlZmluZW1lbnRzJyk7XG5cdH1cblx0aWYgKCEkY29udGVudCB8fCAkY29udGVudC5sZW5ndGggPT0gMCkge1xuXHRcdCRjb250ZW50ID0gJHJlZmluZW1lbnRzSW5uZXI7XG5cdH1cblxuXHR1cGRhdGVSZWZpbmVtZW50Q291bnRzKCRjb250ZW50LCB1cmxGb3JQYXJhbWV0ZXJzKTtcblx0aWYgKG9wdGlvbnMuU3RvcmVVSVZlcnNpb24gPT0gJzIwMjRSZWRlc2lnbicpIHtcblx0XHR1cGRhdGVTZWxlY3RlZFJlZmluZW1lbnRzKCk7XG5cdH1cblx0dXBkYXRlUGVuZGluZ1JlZmluZW1lbnRzKCk7XG5cblx0dmFyIGlzU29ydGluZ0NoYW5nZWQgPSBmYWxzZTtcblx0dmFyICRzb3J0aW5nUnVsZSA9ICQoJy5tb2RhbC5vcGVuIC5zb3J0LWJ5IG9wdGlvbjpjaGVja2VkLCAubW9kYWwub3BlbiAuc29ydC1ieSBpbnB1dDpjaGVja2VkJyk7XG5cdGlmICgkc29ydGluZ1J1bGUgJiYgJHNvcnRpbmdSdWxlLmxlbmd0aCA+IDApIHtcblx0XHRpc1NvcnRpbmdDaGFuZ2VkID0gISRzb3J0aW5nUnVsZS5hdHRyKCdzZWxlY3RlZCcpO1xuXHR9XG5cblx0aWYgKGlzU29ydGluZ0NoYW5nZWQgfHwgJGNvbnRlbnQuZmluZCgnW3JlZmluZW1lbnQtdmFsdWVdLm1vZGlmaWVkLCAubGlzdC1zZWxlY3Rpb25zIC52YWx1ZS5wZW5kaW5nLWNsZWFyJykubGVuZ3RoID4gMCkge1xuXHRcdCRjb250ZW50LmFkZENsYXNzKCdyZWZpbmVtZW50cy1tb2RpZmllZCcpO1xuXHRcdCQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItZm9vdGVyIC5hcHBseS1yZWZpbmVtZW50cycpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHR9IGVsc2Uge1xuXHRcdCRjb250ZW50LnJlbW92ZUNsYXNzKCdyZWZpbmVtZW50cy1tb2RpZmllZCcpO1xuXHRcdCQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItZm9vdGVyIC5hcHBseS1yZWZpbmVtZW50cycpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHR9XG5cdFxuXHRpZiAoJCgnW2lzLXByaWNlLXJlZmluZW1lbnQ9XCJ0cnVlXCJdIGlucHV0OmNoZWNrZWQnKS5sZW5ndGggPiAwKSB7XG5cdFx0JGNvbnRlbnQuYWRkQ2xhc3MoJ3ByaWNlLXNlbGVjdGVkJyk7XG5cdH0gZWxzZSB7XG5cdFx0JGNvbnRlbnQucmVtb3ZlQ2xhc3MoJ3ByaWNlLXNlbGVjdGVkJyk7XG5cdH1cblx0XG5cdHZhciAkcmVmaW5lbWVudHNNb2RhbFByb2R1Y3RTZWxlY3Rpb25zID0gJCgnLnJlZmluZW1lbnRzLWlubmVyLWNvbnRhaW5lci1oZWFkZXIgLnByb2R1Y3Qtc2VsZWN0aW9ucycpO1x0XG5cdGlmICgoJHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucy5maW5kKCcubGlzdC1zZWxlY3Rpb25zIC52YWx1ZS5hcHBsaWVkJykubGVuZ3RoICsgJHJlZmluZW1lbnRzTW9kYWxQcm9kdWN0U2VsZWN0aW9ucy5maW5kKCcubGlzdC1zZWxlY3Rpb25zID4gLnBlbmRpbmctc2VsZWN0aW9ucyA+IHNwYW4nKS5sZW5ndGgpID4gMCkge1xuXHRcdCRyZWZpbmVtZW50c01vZGFsUHJvZHVjdFNlbGVjdGlvbnMuc2hvdygpO1xuXHRcdCQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItZm9vdGVyIC5jbGVhci1yZWZpbmVtZW50cycpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHR9IGVsc2Uge1xuXHRcdCRyZWZpbmVtZW50c01vZGFsUHJvZHVjdFNlbGVjdGlvbnMuaGlkZSgpO1xuXHRcdCQoJy5yZWZpbmVtZW50cy1pbm5lci1jb250YWluZXItZm9vdGVyIC5jbGVhci1yZWZpbmVtZW50cycpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuXHR9XG5cdHZhciAkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lcjtcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG5cdFx0JHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIgPSAkKCcucHJpbWFyeS1jb250ZW50ID4gLnNvcnQtYW5kLXJlZmluZSA+IC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0fSBlbHNlIHtcblx0XHQkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lciA9ICQoJy5wcmltYXJ5LWNvbnRlbnQgPiAucHJvZHVjdC1zZWxlY3Rpb25zJyk7XG5cdH1cblxuXHRpZiAoJHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyAudmFsdWUuYXBwbGllZCcpLmxlbmd0aCA+IDApIHtcblx0XHQkcHJvZHVjdFNlbGVjdGlvbkNvbnRhaW5lci5zaG93KCk7XG5cdH0gZWxzZSB7XG5cdFx0JHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIuaGlkZSgpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVNlbGVjdGVkUmVmaW5lbWVudHMoKSB7XG5cdHZhciAkcmVmaW5lbWVudHMgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCcucmVmaW5lbWVudFt1dWlkXS5leHBhbmRlZCcpO1xuXHQkcmVmaW5lbWVudHMuZWFjaChmdW5jdGlvbigpIHtcblx0XHR2YXIgJHJlZmluZW1lbnQgPSAkKHRoaXMpO1xuXG5cdFx0dmFyICRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgnLnRvZ2dsZScpLmZpbmQoJy5saXN0LXNlbGVjdGlvbnMnKTtcblx0XHRpZiAoISRzZWxlY3RlZFJlZmluZW1lbnRzQ29udGFpbmVyIHx8ICEkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lci5sZW5ndGgpIHtcblx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUnKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJwcm9kdWN0LXNlbGVjdGlvbnNcIj48dWwgY2xhc3M9XCJsaXN0LXNlbGVjdGlvbnNcIi8+PC9kaXY+Jyk7XG5cdFx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lciA9ICRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUgLmxpc3Qtc2VsZWN0aW9ucycpO1xuXHRcdH1cblxuXHRcdHZhciAkc2VsZWN0ZWRSZWZpbmVtZW50c1ZhbHVlcztcblx0XHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdFx0JHNlbGVjdGVkUmVmaW5lbWVudHNWYWx1ZXMgPSAkcmVmaW5lbWVudC5maW5kKCd1bDpub3QoLnBvcHVsYXIpJykuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHNlbGVjdGVkUmVmaW5lbWVudHNWYWx1ZXMgPSAkcmVmaW5lbWVudC5maW5kKCd1bDpub3QoLnBvcHVsYXIpJykuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV0uc2VsZWN0ZWQsIGlucHV0OmNoZWNrZWQ6bm90KC5tb2RpZmllZCknKTtcblx0XHR9XG5cdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudHNCdWZmZXIgPSBbXTtcblx0XHQkc2VsZWN0ZWRSZWZpbmVtZW50c1ZhbHVlcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudElkID0gJHRoaXMuY2xvc2VzdCgnW3JlZmluZW1lbnQtaWRdJykuYXR0cigncmVmaW5lbWVudC1pZCcpO1xuXHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlID0gJHRoaXMuY2xvc2VzdCgnW3JlZmluZW1lbnQtdmFsdWVdJykuYXR0cigncmVmaW5lbWVudC12YWx1ZScpO1xuXHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudFRleHQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC12YWx1ZV0nKS5hdHRyKCdkaXNwbGF5LXZhbHVlJykgfHwgc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWU7XG5cdFx0XHRcblx0XHRcdGlmICghc2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRJZF0pIHtcblx0XHRcdFx0c2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRJZF0gPSBbXTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0dmFyIGlzTmV3VmFsdWUgPSB0cnVlO1xuXHRcdFx0Zm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IHNlbGVjdGVkUmVmaW5lbWVudHNCdWZmZXJbc2VsZWN0ZWRSZWZpbmVtZW50SWRdLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0XHRpZiAoc2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRJZF1baW5kZXhdLlZhbHVlID09IHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlKSB7XG5cdFx0XHRcdFx0aXNOZXdWYWx1ZSA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmIChpc05ld1ZhbHVlKSB7XG5cdFx0XHRcdHNlbGVjdGVkUmVmaW5lbWVudHNCdWZmZXJbc2VsZWN0ZWRSZWZpbmVtZW50SWRdLnB1c2goe1xuXHRcdFx0XHRcdFRleHQ6IHNlbGVjdGVkUmVmaW5lbWVudFRleHQsXG5cdFx0XHRcdFx0VmFsdWU6IHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudHNIdG1sID0gJyc7XG5cdFx0Zm9yICh2YXIgc2VsZWN0ZWRSZWZpbmVtZW50RWxlbWVudCBpbiBzZWxlY3RlZFJlZmluZW1lbnRzQnVmZmVyKSB7XG5cdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50ID0gc2VsZWN0ZWRSZWZpbmVtZW50c0J1ZmZlcltzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50XTtcblx0XHRcdFxuXHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlc0h0bWwgPSAnJztcblx0XHRcdGZvciAodmFyIHNlbGVjdGVkUmVmaW5lbWVudERhdGFFbGVtZW50IGluIHNlbGVjdGVkUmVmaW5lbWVudCkge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50RGF0YSA9IHNlbGVjdGVkUmVmaW5lbWVudFtzZWxlY3RlZFJlZmluZW1lbnREYXRhRWxlbWVudF07XG5cdFx0XHRcdHZhciBzZWxlY3RlZFJlZmluZW1lbnRUZXh0ID0gc2VsZWN0ZWRSZWZpbmVtZW50RGF0YS5UZXh0O1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWRSZWZpbmVtZW50VmFsdWUgPSBzZWxlY3RlZFJlZmluZW1lbnREYXRhLlZhbHVlO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlc0h0bWwpIHtcblx0XHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8c3BhbiBjbGFzcz1cImRlbGltaXRlclwiPiw8L3NwYW4+Jztcblx0XHRcdFx0fVxuXHRcdFx0XHRcblx0XHRcdFx0dmFyIHNlbGVjdGVkUmVmaW5lbWVudERpc3BsYXlWYWx1ZSA9IHNlbGVjdGVkUmVmaW5lbWVudFZhbHVlO1xuXHRcdFx0XHRpZiAoc2VsZWN0ZWRSZWZpbmVtZW50RWxlbWVudCA9PSAnUHJpY2UnKSB7XG5cdFx0XHRcdFx0c2VsZWN0ZWRSZWZpbmVtZW50RGlzcGxheVZhbHVlID0gJHJlZmluZW1lbnRzSW5uZXIuZmluZCgnW3JlZmluZW1lbnQtaWQ9XCInICsgc2VsZWN0ZWRSZWZpbmVtZW50RWxlbWVudCArICdcIl0nKS5hdHRyKCdkaXNwbGF5LXZhbHVlJyk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoc2VsZWN0ZWRSZWZpbmVtZW50RWxlbWVudCA9PSAnc2l6ZScpIHtcblx0XHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnREaXNwbGF5VmFsdWUgPSAnU2l6ZSAnICsgc2VsZWN0ZWRSZWZpbmVtZW50RGlzcGxheVZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZXNIdG1sICs9ICc8c3BhbiBjbGFzcz1cInZhbHVlXCIgcmVmaW5lbWVudC12YWx1ZT1cIicgKyBzZWxlY3RlZFJlZmluZW1lbnRWYWx1ZSArICdcIj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRSZWZpbmVtZW50VGV4dCArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8YSBjbGFzcz1cImNsb3NlLWJ0blwiPjxpIGNsYXNzPVwiZmEgZmEtY2xvc2VcIj48L2k+PC9hPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Jzwvc3Bhbj4nO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRzZWxlY3RlZFJlZmluZW1lbnRzSHRtbCArPSAnPHNwYW4gZGF0YS1yZWZncm91cC1pZD1cIicgKyBzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50ICsgJ1wiPicgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8c3BhbiBjbGFzcz1cImtleVwiPicgKyBzZWxlY3RlZFJlZmluZW1lbnRFbGVtZW50ICsgJzwvc3Bhbj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnPHNwYW4gY2xhc3M9XCJjb2xvblwiPjo8L3NwYW4+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRSZWZpbmVtZW50VmFsdWVzSHRtbCArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCc8L3NwYW4+Jztcblx0XHR9XG5cdFx0XG5cdFx0JHNlbGVjdGVkUmVmaW5lbWVudHNDb250YWluZXIuaHRtbChzZWxlY3RlZFJlZmluZW1lbnRzSHRtbCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVQZW5kaW5nUmVmaW5lbWVudHMoKSB7XG5cdHZhciAkcGVuZGluZ1JlZmluZW1lbnRzQ29udGFpbmVyO1xuXHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdHZhciAkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lciA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50LmV4cGFuZGVkIC50b2dnbGUnKS5maW5kKCcucHJvZHVjdC1zZWxlY3Rpb25zJyk7XG5cdFx0aWYgKCEkc2VsZWN0ZWRSZWZpbmVtZW50c0NvbnRhaW5lciB8fCAhJHNlbGVjdGVkUmVmaW5lbWVudHNDb250YWluZXIubGVuZ3RoKSB7XG5cdFx0XHQkcmVmaW5lbWVudHNJbm5lci5maW5kKCcucmVmaW5lbWVudC5leHBhbmRlZCAudG9nZ2xlJykuYXBwZW5kKCc8ZGl2IGNsYXNzPVwicHJvZHVjdC1zZWxlY3Rpb25zXCI+PHVsIGNsYXNzPVwibGlzdC1zZWxlY3Rpb25zXCIvPjwvZGl2PicpO1xuXHRcdH1cblxuXHRcdCRwZW5kaW5nUmVmaW5lbWVudHNDb250YWluZXIgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCcucmVmaW5lbWVudC5leHBhbmRlZCAudG9nZ2xlJykuZmluZCgnLnBlbmRpbmctc2VsZWN0aW9ucycpO1xuXHRcdGlmICghJHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lciB8fCAhJHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lci5sZW5ndGgpIHtcblx0XHRcdCRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50LmV4cGFuZGVkIC50b2dnbGUgLmxpc3Qtc2VsZWN0aW9ucycpLmFwcGVuZCgnPGxpIGNsYXNzPVwicGVuZGluZy1zZWxlY3Rpb25zXCIvPicpO1xuXHRcdFx0JHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lciA9ICRyZWZpbmVtZW50c0lubmVyLmZpbmQoJy5yZWZpbmVtZW50LmV4cGFuZGVkIC50b2dnbGUgLmxpc3Qtc2VsZWN0aW9ucyAucGVuZGluZy1zZWxlY3Rpb25zJyk7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdCRwZW5kaW5nUmVmaW5lbWVudHNDb250YWluZXIgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCcucGVuZGluZy1zZWxlY3Rpb25zJyk7XG5cdH1cblx0XG5cdHZhciAkcGVuZGluZ1JlZmluZW1lbnRzVmFsdWVzO1xuXHRpZiAob3B0aW9ucy5TdG9yZVVJVmVyc2lvbiA9PSAnMjAyNFJlZGVzaWduJykge1xuXHRcdCRwZW5kaW5nUmVmaW5lbWVudHNWYWx1ZXMgPSAkKCcucmVmaW5lbWVudFt1dWlkXS5leHBhbmRlZCB1bDpub3QoLnBvcHVsYXIpJykuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV06bm90KC5zZWxlY3RlZCkubW9kaWZpZWQsIGlucHV0Lm1vZGlmaWVkOm5vdChbY2hlY2tlZD1cImNoZWNrZWRcIl0pJyk7XG5cdH0gZWxzZSB7XG5cdFx0JHBlbmRpbmdSZWZpbmVtZW50c1ZhbHVlcyA9ICQoJy5yZWZpbmVtZW50W3V1aWRdIHVsOm5vdCgucG9wdWxhciknKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXTpub3QoLnNlbGVjdGVkKS5tb2RpZmllZCcpO1xuXHR9XG5cdHZhciBwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXIgPSBbXTtcblxuXHQkcGVuZGluZ1JlZmluZW1lbnRzVmFsdWVzLmVhY2goZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudElkID0gJHRoaXMuY2xvc2VzdCgnW3JlZmluZW1lbnQtaWRdJykuYXR0cigncmVmaW5lbWVudC1pZCcpO1xuXHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudFZhbHVlID0gJHRoaXMuY2xvc2VzdCgnW3JlZmluZW1lbnQtdmFsdWVdJykuYXR0cigncmVmaW5lbWVudC12YWx1ZScpO1xuXHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudFRleHQgPSAkdGhpcy5jbG9zZXN0KCdbcmVmaW5lbWVudC12YWx1ZV0nKS5hdHRyKCdkaXNwbGF5LXZhbHVlJykgfHwgcGVuZGluZ1JlZmluZW1lbnRWYWx1ZTtcblx0XHRcblx0XHRpZiAoIXBlbmRpbmdSZWZpbmVtZW50c0J1ZmZlcltwZW5kaW5nUmVmaW5lbWVudElkXSkge1xuXHRcdFx0cGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyW3BlbmRpbmdSZWZpbmVtZW50SWRdID0gW107XG5cdFx0fVxuXHRcdFxuXHRcdHZhciBpc05ld1ZhbHVlID0gdHJ1ZTtcblx0XHRmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgcGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyW3BlbmRpbmdSZWZpbmVtZW50SWRdLmxlbmd0aDsgaW5kZXgrKykge1xuXHRcdFx0aWYgKHBlbmRpbmdSZWZpbmVtZW50c0J1ZmZlcltwZW5kaW5nUmVmaW5lbWVudElkXVtpbmRleF0uVmFsdWUgPT0gcGVuZGluZ1JlZmluZW1lbnRWYWx1ZSkge1xuXHRcdFx0XHRpc05ld1ZhbHVlID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdGlmIChpc05ld1ZhbHVlKSB7XG5cdFx0XHRwZW5kaW5nUmVmaW5lbWVudHNCdWZmZXJbcGVuZGluZ1JlZmluZW1lbnRJZF0ucHVzaCh7XG5cdFx0XHRcdFRleHQ6IHBlbmRpbmdSZWZpbmVtZW50VGV4dCxcblx0XHRcdFx0VmFsdWU6IHBlbmRpbmdSZWZpbmVtZW50VmFsdWVcblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cdFxuXHR2YXIgcGVuZGluZ1JlZmluZW1lbnRzSHRtbCA9ICcnO1xuXHRmb3IgKHZhciBwZW5kaW5nUmVmaW5lbWVudEVsZW1lbnQgaW4gcGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyKSB7XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50ID0gcGVuZGluZ1JlZmluZW1lbnRzQnVmZmVyW3BlbmRpbmdSZWZpbmVtZW50RWxlbWVudF07XG5cdFx0XG5cdFx0dmFyIHBlbmRpbmdSZWZpbmVtZW50VmFsdWVzSHRtbCA9ICcnO1xuXHRcdGZvciAodmFyIHBlbmRpbmdSZWZpbmVtZW50RGF0YUVsZW1lbnQgaW4gcGVuZGluZ1JlZmluZW1lbnQpIHtcblx0XHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudERhdGEgPSBwZW5kaW5nUmVmaW5lbWVudFtwZW5kaW5nUmVmaW5lbWVudERhdGFFbGVtZW50XTtcblx0XHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudFRleHQgPSBwZW5kaW5nUmVmaW5lbWVudERhdGEuVGV4dDtcblx0XHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudFZhbHVlID0gcGVuZGluZ1JlZmluZW1lbnREYXRhLlZhbHVlO1xuXHRcdFx0XG5cdFx0XHRpZiAocGVuZGluZ1JlZmluZW1lbnRWYWx1ZXNIdG1sKSB7XG5cdFx0XHRcdHBlbmRpbmdSZWZpbmVtZW50VmFsdWVzSHRtbCArPSAnPHNwYW4gY2xhc3M9XCJkZWxpbWl0ZXJcIj4sPC9zcGFuPic7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHZhciBwZW5kaW5nUmVmaW5lbWVudERpc3BsYXlWYWx1ZSA9IHBlbmRpbmdSZWZpbmVtZW50VmFsdWU7XG5cdFx0XHRpZiAocGVuZGluZ1JlZmluZW1lbnRFbGVtZW50ID09ICdQcmljZScpIHtcblx0XHRcdFx0cGVuZGluZ1JlZmluZW1lbnREaXNwbGF5VmFsdWUgPSAkcmVmaW5lbWVudHNJbm5lci5maW5kKCdbcmVmaW5lbWVudC1pZD1cIicgKyBwZW5kaW5nUmVmaW5lbWVudEVsZW1lbnQgKyAnXCJdJykuYXR0cignZGlzcGxheS12YWx1ZScpO1xuXHRcdFx0fSBlbHNlIGlmIChwZW5kaW5nUmVmaW5lbWVudEVsZW1lbnQgPT0gJ3NpemUnKSB7XG5cdFx0XHRcdHBlbmRpbmdSZWZpbmVtZW50RGlzcGxheVZhbHVlID0gJ1NpemUgJyArIHBlbmRpbmdSZWZpbmVtZW50RGlzcGxheVZhbHVlO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRwZW5kaW5nUmVmaW5lbWVudFZhbHVlc0h0bWwgKz0gJzxzcGFuIGNsYXNzPVwidmFsdWVcIiByZWZpbmVtZW50LXZhbHVlPVwiJyArIHBlbmRpbmdSZWZpbmVtZW50VmFsdWUgKyAnXCI+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwZW5kaW5nUmVmaW5lbWVudFRleHQgK1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0JzxhIGNsYXNzPVwiY2xvc2UtYnRuXCI+PGkgY2xhc3M9XCJmYSBmYS1jbG9zZVwiPjwvaT48L2E+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Jzwvc3Bhbj4nO1xuXHRcdH1cblx0XHRcblx0XHRwZW5kaW5nUmVmaW5lbWVudHNIdG1sICs9ICc8c3BhbiBkYXRhLXJlZmdyb3VwLWlkPVwiJyArIHBlbmRpbmdSZWZpbmVtZW50RWxlbWVudCArICdcIj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JzxzcGFuIGNsYXNzPVwia2V5XCI+JyArIHBlbmRpbmdSZWZpbmVtZW50RWxlbWVudCArICc8L3NwYW4+JyArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCc8c3BhbiBjbGFzcz1cImNvbG9uXCI+Ojwvc3Bhbj4nICtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cGVuZGluZ1JlZmluZW1lbnRWYWx1ZXNIdG1sICtcblx0XHRcdFx0XHRcdFx0XHRcdCc8L3NwYW4+Jztcblx0fVxuXHRcblx0JHBlbmRpbmdSZWZpbmVtZW50c0NvbnRhaW5lci5odG1sKHBlbmRpbmdSZWZpbmVtZW50c0h0bWwpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50Q291bnRzKCRjb250ZW50UGFyYW1ldGVyKSB7XG5cdHZhciB1cmwgPSBidWlsZFVybEZvclNlbGVjdGVkUmVmaW5lbWVudHMoVXJscy5nZXRSZWZpbmVtZW50Q291bnRzLCBudWxsLCB0cnVlKTtcblx0dmFyICRjb250ZW50ID0gJGNvbnRlbnRQYXJhbWV0ZXIgfHwgJChkb2N1bWVudCk7XG5cdHZhciAkcmVmaW5lbWVudHMgPSAkY29udGVudC5maW5kKCcucmVmaW5lbWVudFt1dWlkXScpO1xuXHR2YXIgJHJlZmluZW1lbnRQcm9kdWN0Q291bnQgPSAkY29udGVudC5maW5kKCcucmVmaW5lbWVudCAudG9nZ2xlIC5wcm9kdWN0LWNvdW50Jyk7XG5cdCRyZWZpbmVtZW50UHJvZHVjdENvdW50LmxvYWRpbmcoKTtcblxuXHR2YXIgcmVmaW5lbWVudEdyb3VwcyA9IFtdO1xuXHR2YXIgcmVmaW5lbWVudEdyb3VwSW5kZXggPSAwO1xuXHR2YXIgcmVmaW5lbWVudEdyb3VwU2l6ZUxpbWl0ID0gMjAwMDtcblx0dmFyIHJlZmluZW1lbnRHcm91cFNpemVDdXJyZW50ID0gMDtcblx0JC5lYWNoKCRyZWZpbmVtZW50cywgZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHJlZmluZW1lbnQgPSAkKGVsZW1lbnQpO1xuXHRcdHZhciByZWZpbmVtZW50VmFsdWVDb3VudCA9ICRyZWZpbmVtZW50LmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlXScpLmxlbmd0aDtcblx0XHRpZiAoKHJlZmluZW1lbnRWYWx1ZUNvdW50ICsgcmVmaW5lbWVudEdyb3VwU2l6ZUN1cnJlbnQpID49IHJlZmluZW1lbnRHcm91cFNpemVMaW1pdCkge1xuXHRcdFx0cmVmaW5lbWVudEdyb3VwSW5kZXgrKztcblx0XHRcdHJlZmluZW1lbnRHcm91cFNpemVDdXJyZW50ID0gMDtcblx0XHR9XG5cblx0XHRpZiAoIXJlZmluZW1lbnRHcm91cHNbcmVmaW5lbWVudEdyb3VwSW5kZXhdKSB7XG5cdFx0XHRyZWZpbmVtZW50R3JvdXBzW3JlZmluZW1lbnRHcm91cEluZGV4XSA9ICRyZWZpbmVtZW50O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZWZpbmVtZW50R3JvdXBzW3JlZmluZW1lbnRHcm91cEluZGV4XSA9IHJlZmluZW1lbnRHcm91cHNbcmVmaW5lbWVudEdyb3VwSW5kZXhdLmFkZCgkcmVmaW5lbWVudCk7XG5cdFx0fVxuXG5cdFx0cmVmaW5lbWVudEdyb3VwU2l6ZUN1cnJlbnQgKz0gcmVmaW5lbWVudFZhbHVlQ291bnQ7XG5cdH0pO1xuXG5cdGRhdGFCdWZmZXJbJ3VwZGF0ZVJlZmluZW1lbnRDb3VudHNSZWZpbmVtZW50R3JvdXBJbmRleCddID0gMDtcblx0ZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cENvdW50J10gPSByZWZpbmVtZW50R3JvdXBzLmxlbmd0aDtcblxuXHQkLmVhY2gocmVmaW5lbWVudEdyb3VwcywgZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHR2YXIgJHJlZmluZW1lbnRHcm91cCA9ICQoZWxlbWVudCk7XG5cdFx0dXBkYXRlUmVmaW5lbWVudENvdW50c0ZvclJlZmluZW1lbnRzKHVybCwgJHJlZmluZW1lbnRHcm91cCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50Q291bnRzRm9yUmVmaW5lbWVudHModXJsLCAkcmVmaW5lbWVudHMpIHtcblx0dmFyIHJlZmluZW1lbnRJZHMgPSAkcmVmaW5lbWVudHMubWFwKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0cmV0dXJuICQoZWxlbWVudCkuYXR0cigncmVmaW5lbWVudC1pZCcpO1xuXHR9KS5nZXQoKTtcblxuXHRpZiAocmVmaW5lbWVudElkcykge1xuXHRcdHZhciAkcmVmaW5lbWVudFByb2R1Y3RDb3VudCA9ICRyZWZpbmVtZW50cy5maW5kKCcudG9nZ2xlIC5wcm9kdWN0LWNvdW50Jyk7XG5cdFx0JHJlZmluZW1lbnRQcm9kdWN0Q291bnQubG9hZGluZygpO1xuXG5cdFx0aWYgKGRhdGFCdWZmZXJbJ3VwZGF0ZVJlZmluZW1lbnRDb3VudHNSZWZpbmVtZW50R3JvdXBDb3VudCddICYmIGRhdGFCdWZmZXJbJ3VwZGF0ZVJlZmluZW1lbnRDb3VudHNSZWZpbmVtZW50R3JvdXBDb3VudCddID4gMSkge1xuXHRcdFx0dXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3JlZmluZW1lbnRzJywgcmVmaW5lbWVudElkcy5qb2luKCkpO1xuXHRcdH1cblxuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnZ2V0Jyxcblx0XHRcdHVybDogdXJsLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHQkcmVmaW5lbWVudHMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdFx0XHRcdHZhciAkcmVmaW5lbWVudCA9ICQoZWxlbWVudCk7XG5cdFx0XHRcdFx0aWYgKGRhdGEpIHtcblx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50SWQgPSAkcmVmaW5lbWVudC5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdFx0XHRcdFx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZXMgPSAkcmVmaW5lbWVudC5maW5kKCd1bCBsaVtyZWZpbmVtZW50LXZhbHVlXScpO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEuUmVmaW5lbWVudHNbcmVmaW5lbWVudElkXSkge1xuXHRcdFx0XHRcdFx0XHQkLmVhY2goJHJlZmluZW1lbnRWYWx1ZXMsIGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyICRyZWZpbmVtZW50VmFsdWUgPSAkKGVsZW1lbnQpO1xuXHRcdFx0XHRcdFx0XHRcdHZhciByZWZpbmVtZW50VmFsdWUgPSAkcmVmaW5lbWVudFZhbHVlLmF0dHIoJ3JlZmluZW1lbnQtdmFsdWUnKTtcblx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdGlmICgkcmVmaW5lbWVudFZhbHVlLmZpbmQoJ2lucHV0W3R5cGU9XCJjaGVja2JveFwiXScpLnByb3AoJ2NoZWNrZWQnKSB8fCBkYXRhLlJlZmluZW1lbnRzW3JlZmluZW1lbnRJZF1bcmVmaW5lbWVudFZhbHVlXSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0JHJlZmluZW1lbnRWYWx1ZS5hdHRyKCdyZWZpbmVtZW50LWNvdW50JywgZGF0YS5SZWZpbmVtZW50c1tyZWZpbmVtZW50SWRdW3JlZmluZW1lbnRWYWx1ZV0pLmZpbmQoJy5yZWZpbmVtZW50LWNvdW50JykuaHRtbChkYXRhLlJlZmluZW1lbnRzW3JlZmluZW1lbnRJZF1bcmVmaW5lbWVudFZhbHVlXSk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdCRyZWZpbmVtZW50VmFsdWUuYXR0cigncmVmaW5lbWVudC1jb3VudCcsIDApLmZpbmQoJy5yZWZpbmVtZW50LWNvdW50JykuaHRtbCgnMCcpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdFx0dmFyICRwb3B1bGFyUmVmaW5lbWVudFZhbHVlcyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsLnBvcHVsYXItc2l6ZXMsIHVsLnBvcHVsYXInKS5maW5kKCdsaVtyZWZpbmVtZW50LXZhbHVlXScpO1xuXHRcdFx0XHRcdFx0XHR2YXIgJHBvcHVsYXJSZWZpbmVtZW50VmFsdWVzQ2hlY2tzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgnLmNoZWNrcy1jb250YWluZXIucG9wdWxhcicpO1xuXHRcdFx0XHRcdFx0XHR2YXIgaGFzUG9wdWxhclJlZmluZW1lbnRWYWx1ZXMgPSAkcG9wdWxhclJlZmluZW1lbnRWYWx1ZXMuZmlsdGVyKCc6bm90KFtyZWZpbmVtZW50LWNvdW50PVwiMFwiXSknKS5sZW5ndGggPiAwIHx8ICRwb3B1bGFyUmVmaW5lbWVudFZhbHVlcy5maWx0ZXIoJzpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpLmZpbmQoJ2lucHV0OmNoZWNrZWQnKS5sZW5ndGggPiAwO1xuXHRcdFx0XHRcdFx0XHRpZiAoaGFzUG9wdWxhclJlZmluZW1lbnRWYWx1ZXMpIHtcblx0XHRcdFx0XHRcdFx0XHQkcG9wdWxhclJlZmluZW1lbnRWYWx1ZXNDaGVja3NDb250YWluZXIuc2hvdygpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdCRwb3B1bGFyUmVmaW5lbWVudFZhbHVlc0NoZWNrc0NvbnRhaW5lci5oaWRlKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdHZhciAkbm9ybWFsUmVmaW5lbWVudFZhbHVlcyA9ICRyZWZpbmVtZW50LmZpbmQoJ3VsOm5vdCgucG9wdWxhci1zaXplcyk6bm90KC5wb3B1bGFyKScpLmZpbmQoJ2xpW3JlZmluZW1lbnQtdmFsdWVdJyk7XG5cdFx0XHRcdFx0XHRcdHZhciAkbm9ybWFsUmVmaW5lbWVudFZhbHVlc0NoZWNrc0NvbnRhaW5lciA9ICRyZWZpbmVtZW50LmZpbmQoJy5jaGVja3MtY29udGFpbmVyOm5vdCgucG9wdWxhciknKTtcblx0XHRcdFx0XHRcdFx0dmFyIGhhc05vcm1hbFJlZmluZW1lbnRWYWx1ZXMgPSAkbm9ybWFsUmVmaW5lbWVudFZhbHVlcy5maWx0ZXIoJzpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpLmxlbmd0aCA+IDAgfHwgJG5vcm1hbFJlZmluZW1lbnRWYWx1ZXMuZmlsdGVyKCc6bm90KFtyZWZpbmVtZW50LWNvdW50PVwiMFwiXSknKS5maW5kKCdpbnB1dDpjaGVja2VkJykubGVuZ3RoID4gMDtcblx0XHRcdFx0XHRcdFx0aWYgKGhhc05vcm1hbFJlZmluZW1lbnRWYWx1ZXMpIHtcblx0XHRcdFx0XHRcdFx0XHQkbm9ybWFsUmVmaW5lbWVudFZhbHVlc0NoZWNrc0NvbnRhaW5lci5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JG5vcm1hbFJlZmluZW1lbnRWYWx1ZXNDaGVja3NDb250YWluZXIuaGlkZSgpO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYgKGhhc05vcm1hbFJlZmluZW1lbnRWYWx1ZXMgfHwgaGFzUG9wdWxhclJlZmluZW1lbnRWYWx1ZXMpIHtcblx0XHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0JHJlZmluZW1lbnQuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGlmICgkcmVmaW5lbWVudC5maW5kKCd1bC5jaGVja3MsIHVsLnN3YXRjaGVzJykuZmluZCgnbGknKS5sZW5ndGggPT0gMCkge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUF0dHIoJ2xvYWRpbmcnKTtcblx0XHRcdFx0XHR1cGRhdGVNb3JlTGVzcygkcmVmaW5lbWVudCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSxcblx0XHRcdGNvbXBsZXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGF0YUJ1ZmZlclsndXBkYXRlUmVmaW5lbWVudENvdW50c1JlZmluZW1lbnRHcm91cEluZGV4J10rKztcblx0XHRcdFx0aWYgKCRyZWZpbmVtZW50UHJvZHVjdENvdW50LmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50UHJvZHVjdENvdW50LmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR1cGRhdGVSZWZpbmVtZW50Q291bnRzQ29tcGxldGUoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50Q291bnRzQ29tcGxldGUoKSB7XG5cdGlmIChkYXRhQnVmZmVyWyd1cGRhdGVSZWZpbmVtZW50Q291bnRzUmVmaW5lbWVudEdyb3VwSW5kZXgnXSA9PSBkYXRhQnVmZmVyWyd1cGRhdGVSZWZpbmVtZW50Q291bnRzUmVmaW5lbWVudEdyb3VwQ291bnQnXSkge1xuXHRcdHVwZGF0ZVByb2R1Y3RDb3VudEluSGVhZGVyKCk7XG5cdFx0dXBkYXRlUmVmaW5lbWVudHNJbkhlYWRlcigpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb2R1Y3RDb3VudEluSGVhZGVyKCkge1xuXHR2YXIgJHJlZmluZW1lbnRzUHJvZHVjdENvdW50ID0gJCgnLnJlZmluZW1lbnRzIC5zbG90LWdyaWQtc3ViaGVhZGVyIC5wcm9kdWN0LWNvdW50IHNwYW4nKTtcblx0dmFyICRoZWFkZXJQcm9kdWN0Q291bnQgPSAkKCcudG9wLWJhbm5lciAuc2xvdC1ncmlkLXN1YmhlYWRlciAucHJvZHVjdC1jb3VudCBzcGFuJyk7XG5cblx0aWYgKCRyZWZpbmVtZW50c1Byb2R1Y3RDb3VudC5sZW5ndGggPiAwICYmICRoZWFkZXJQcm9kdWN0Q291bnQubGVuZ3RoID4gMCkge1xuXHRcdCRoZWFkZXJQcm9kdWN0Q291bnQudGV4dCgkcmVmaW5lbWVudHNQcm9kdWN0Q291bnQudGV4dCgpKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWZpbmVtZW50c0luSGVhZGVyKCkge1xuXHR2YXIgJHJlZmluZW1lbnRzUmVmaW5lbWVudHMgPSAkKCcucHJpbWFyeS1jb250ZW50IC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0dmFyICRoZWFkZXJSZWZpbmVtZW50cyA9ICQoJy50b3AtYmFubmVyIC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblxuXHRpZiAoJHJlZmluZW1lbnRzUmVmaW5lbWVudHMubGVuZ3RoID4gMCAmJiAkaGVhZGVyUmVmaW5lbWVudHMubGVuZ3RoID4gMCkge1xuXHRcdCRoZWFkZXJSZWZpbmVtZW50cy5odG1sKCRyZWZpbmVtZW50c1JlZmluZW1lbnRzLmh0bWwoKSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlTW9yZUxlc3MoJHJlZmluZW1lbnQpIHtcblx0dmFyIHJlZmluZW1lbnRJZCA9ICRyZWZpbmVtZW50LmF0dHIoJ3JlZmluZW1lbnQtaWQnKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyID0gJHJlZmluZW1lbnQuZmluZCgndWw6bm90KC5wb3B1bGFyLXNpemVzKTpub3QoLnBvcHVsYXIpJyk7XG5cdHZhciAkcmVmaW5lbWVudENvbnRhaW5lciA9ICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmNsb3Nlc3QoJy5yZWZpbmVtZW50LWJvZHktaW5uZXInKTtcblx0dmFyICRtb3JlTGluayA9ICRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmZpbmQoJy5yZWYtZmlsdGVyLm1vcmUtbGluaycpLmNsb3Nlc3QoJ2xpJykuZGV0YWNoKCkuZmlyc3QoKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzID0gJHJlZmluZW1lbnRWYWx1ZXNDb250YWluZXIuZmluZCgnbGlbcmVmaW5lbWVudC12YWx1ZV0nKTtcblx0dmFyICRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZSA9ICRyZWZpbmVtZW50VmFsdWVzLmZpbHRlcignOm5vdChbcmVmaW5lbWVudC1jb3VudD1cIjBcIl0pJyk7XG5cblx0aWYgKCRtb3JlTGluay5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIG1vcmVMZXNzQ291bnQ7XG5cdFx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMgJiYgJHJlZmluZW1lbnQuYXR0cigncmVmaW5lbWVudC1pZCcpID09ICdzaXplJykge1xuXHRcdFx0bW9yZUxlc3NDb3VudCA9IDEyO1xuXHRcdH0gZWxzZSBpZiAocGFnZUNvbnRleHQuc2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5Sc3BVUyAmJiBvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRtb3JlTGVzc0NvdW50ID0gMTAwMDAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtb3JlTGVzc0NvdW50ID0gOTtcblx0XHR9XG5cblx0XHRpZiAoJHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmxlbmd0aCA+IG1vcmVMZXNzQ291bnQpIHtcblx0XHRcdHZhciBtb3JlTGVzc0luZGV4ID0gJHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmluZGV4KCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5lcShtb3JlTGVzc0NvdW50KSk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlc1Zpc2libGUuc2xpY2UoMCwgbW9yZUxlc3NJbmRleCkucmVtb3ZlQ2xhc3MoJ3RvZ2dsZWFibGUgaGlkZGVuJyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlc1Zpc2libGUuc2xpY2UobW9yZUxlc3NJbmRleCwgJHJlZmluZW1lbnRWYWx1ZXMubGVuZ3RoKS5hZGRDbGFzcygndG9nZ2xlYWJsZSBoaWRkZW4nKTtcblx0XHRcdCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5lcShtb3JlTGVzc0luZGV4IC0gMSkuYWZ0ZXIoJG1vcmVMaW5rKTtcblx0XHRcdCRyZWZpbmVtZW50VmFsdWVzQ29udGFpbmVyLmZpbmQoJy5tb3JlLWxpbmstY29udGFpbmVyJykuc2hvdygpO1xuXHRcdFx0JHJlZmluZW1lbnRDb250YWluZXIuZmluZCgnLmxlc3MtcmVmaW5lbWVudCcpLnNob3coKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLnJlbW92ZUNsYXNzKCd0b2dnbGVhYmxlIGhpZGRlbicpO1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNWaXNpYmxlLmVxKCRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5sZW5ndGggLSAxKS5hZnRlcigkbW9yZUxpbmspO1xuXHRcdFx0JHJlZmluZW1lbnRWYWx1ZXNDb250YWluZXIuZmluZCgnLm1vcmUtbGluay1jb250YWluZXInKS5oaWRlKCk7XG5cdFx0XHQkcmVmaW5lbWVudENvbnRhaW5lci5maW5kKCcubGVzcy1yZWZpbmVtZW50JykuaGlkZSgpO1xuXHRcdH1cblx0fVxuXG5cdGlmICghJCgnaHRtbCcpLmhhc0NsYXNzKCdzaXplLW1vYmlsZScpIHx8IHdpbmRvdy5pbm5lcldpZHRoID4gNzY3KSB7XG5cdFx0aWYgKHJlZmluZW1lbnRzRXhwYW5kZWQpIHtcblx0XHRcdGlmIChyZWZpbmVtZW50c0V4cGFuZGVkLmluZGV4T2YocmVmaW5lbWVudElkKSA+IC0xKSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmFkZENsYXNzKCdleHBhbmRlZCcpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcudG9nZ2xlJykuYWRkQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUtY29udGVudCcpLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUNsYXNzKCdleHBhbmRlZCcpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcudG9nZ2xlJykucmVtb3ZlQ2xhc3MoJ2V4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGUtY29udGVudCcpLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCQoJy5yZWZpbmVtZW50LmV4cGFuZGVkJykubGVuZ3RoID4gMCkge1xuXHRcdFx0JCgnLnJlZmluZW1lbnRzJykuYWRkQ2xhc3MoJ3JlZmluZW1lbnQtZXhwYW5kZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCgnLnJlZmluZW1lbnRzJykucmVtb3ZlQ2xhc3MoJ3JlZmluZW1lbnQtZXhwYW5kZWQnKTtcblx0XHR9XG5cblx0XHRpZiAocmVmaW5lbWVudHNWaWV3QWxsICYmICRyZWZpbmVtZW50VmFsdWVzVmlzaWJsZS5sZW5ndGggPiBtb3JlTGVzc0NvdW50KSB7XG5cdFx0XHRpZiAocmVmaW5lbWVudHNWaWV3QWxsLmluZGV4T2YocmVmaW5lbWVudElkKSA+IC0xKSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmFkZENsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy50b2dnbGVhYmxlJykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcubW9yZS1saW5rLWNvbnRhaW5lcicpLmNzcygnZGlzcGxheScsICdub25lJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy5sZXNzLXJlZmluZW1lbnQudG9nZ2xlYWJsZScpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRyZWZpbmVtZW50LnJlbW92ZUNsYXNzKCdtb3JlLWV4cGFuZGVkJyk7XG5cdFx0XHRcdCRyZWZpbmVtZW50LmZpbmQoJy5tb3JlLWxpbmstY29udGFpbmVyJykuY3NzKCdkaXNwbGF5JywgJ2xpc3QtaXRlbScpO1xuXHRcdFx0XHQkcmVmaW5lbWVudC5maW5kKCcubGVzcy1yZWZpbmVtZW50LnRvZ2dsZWFibGUnKS5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGdldFVybFZhcnMoKSB7XG4gICAgdmFyIHZhcnMgPSBbXSwgaGFzaDtcbiAgICB2YXIgaGFzaGVzID0gd2luZG93LmxvY2F0aW9uLmhyZWYuc2xpY2Uod2luZG93LmxvY2F0aW9uLmhyZWYuaW5kZXhPZignPycpICsgMSkuc3BsaXQoJyYnKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgaGFzaGVzLmxlbmd0aDsgaSsrKVxuXHQgICAge1xuXHQgICAgICAgIGhhc2ggPSBoYXNoZXNbaV0uc3BsaXQoJz0nKTtcblx0ICAgICAgICB2YXJzLnB1c2goaGFzaFswXSk7XG5cdCAgICAgICAgdmFyc1toYXNoWzBdXSA9IGhhc2hbMV07XG5cdCAgICB9XG4gICAgcmV0dXJuIHZhcnM7XG59XG5cbnZhciByZWZHcm91cHNTdGF0ZXMgPSB7XG5cdFx0Y29va2llUmVmR3JvdXBzS2V5OiAncmVmZ3JvdXAnLFxuXHRcdHNhdmVTdGF0ZTogZnVuY3Rpb24ocmVmZ3JvdXAsIHZpc2libGUpIHtcblx0XHRcdGlmICh0aGlzLmdldENvb2tpZSgnZHdfY29va2llc19hY2NlcHRlZCcpKSB7XG5cdFx0XHRcdHZhciBnZXRSZWZHcm91cENvb2tpZSA9IHRoaXMuZ2V0Q29va2llKHRoaXMuY29va2llUmVmR3JvdXBzS2V5KSB8fCAne30nO1xuXHRcdFx0XHR2YXIgZ2V0UmVmR3JvdXBPYmogPSBKU09OLnBhcnNlKGdldFJlZkdyb3VwQ29va2llKTtcblx0XHRcdFx0Z2V0UmVmR3JvdXBPYmpbcmVmZ3JvdXBdID0gdmlzaWJsZTtcblx0XHRcdFx0Z2V0UmVmR3JvdXBDb29raWUgPSBKU09OLnN0cmluZ2lmeShnZXRSZWZHcm91cE9iaik7XG5cdFx0XHRcdHRoaXMuc2V0Q29va2llKCdyZWZncm91cCcsIGdldFJlZkdyb3VwQ29va2llKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGNoZWNrU3RhdGU6IGZ1bmN0aW9uKHJlZmdyb3VwKSB7XG5cdFx0XHRpZiAodGhpcy5nZXRDb29raWUoJ2R3X2Nvb2tpZXNfYWNjZXB0ZWQnKSkge1xuXHRcdFx0XHR2YXIgZ2V0UmVmR3JvdXBDb29raWUgPSB0aGlzLmdldENvb2tpZSh0aGlzLmNvb2tpZVJlZkdyb3Vwc0tleSk7XG5cdFx0XHRcdGlmIChnZXRSZWZHcm91cENvb2tpZSkge1xuXHRcdFx0XHRcdHZhciBnZXRSZWZHcm91cE9iaiA9IEpTT04ucGFyc2UoZ2V0UmVmR3JvdXBDb29raWUpO1xuXHRcdFx0XHRcdGlmIChnZXRSZWZHcm91cE9ialtyZWZncm91cF0gIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZ2V0UmVmR3JvdXBPYmpbcmVmZ3JvdXBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblx0XHRnZXRDb29raWU6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHQgICAgdmFyIGNvb2tpZXMgPSBkb2N1bWVudC5jb29raWUuc3BsaXQoJzsnKTtcblx0XHQgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb29raWVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0ICAgICAgICB2YXIgdG9rZW5zID0gY29va2llc1tpXS5zcGxpdCgnPScpO1xuXHRcdCAgICAgICAgdmFyIGNvb2tpZUtleSA9IHRva2Vuc1swXS50cmltKCk7XG5cdFx0ICAgICAgICBpZiAoY29va2llS2V5ID09PSBrZXkpIHtcblx0XHQgICAgICAgICAgICByZXR1cm4gdG9rZW5zWzFdO1xuXHRcdCAgICAgICAgfVxuXHRcdCAgICB9XG5cdFx0ICAgIHJldHVybiAnJztcblx0XHR9LFxuXHRcdHNldENvb2tpZTogZnVuY3Rpb24oa2V5LCB2YWx1ZSwgbWludXRlcykge1xuXHRcdCAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0ICAgIGRhdGUuc2V0VGltZShkYXRlICsgKG1pbnV0ZXMgKiA2MCAqIDEwMDApKTtcblx0XHQgICAgZG9jdW1lbnQuY29va2llID0ga2V5ICsgJz0nICsgdmFsdWUgKyAnOyBleHBpcmVzPScgKyBkYXRlLnRvR01UU3RyaW5nKCkgKyAnOyBwYXRoPS8nO1xuXHRcdH1cbn1cblxuZnVuY3Rpb24gc2VhcmNoU3RvcmVzKCkge1xuXHR2YXIgc2VhcmNoU3RvcmVzUXVlcnkgPSAkKCcuc2VhcmNoLXN0b3Jlcy1xdWVyeScpO1xuXG5cdCQoJy5nby1maW5kLXN0b3JlcycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGVsID0gJChlLnRhcmdldCksXG5cdFx0XHRkYXRhID0ge1xuXHRcdFx0XHR0eXBlS2V5OiBlbC5hdHRyKCd0eXBlJylcblx0XHRcdH07XG5cblx0XHRpZiAoZWwuYXR0cigndHlwZScpID09PSAnZ2VvJykge1xuXHRcdFx0aWYgKG5hdmlnYXRvci5nZW9sb2NhdGlvbikge1xuXHRcdFx0XHRuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG5cdFx0XHRcdFx0ZGF0YS5sb25naXR1ZGUgPSBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlO1xuXHRcdFx0XHRcdGRhdGEubGF0aXR1ZGUgPSBwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGU7XG5cblx0XHRcdFx0XHRzZWFyY2hTdG9yZXNBSkFYKGRhdGEpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFsZXJ0KCdZb3VyIGJyb3dzZXIgbm90IHN1cHBvcnRlZCBnZW9sb2NhdGlvbicpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRhLnNlYXJjaEtleSA9IHNlYXJjaFN0b3Jlc1F1ZXJ5LnZhbCgpLnRyaW0oKTtcblxuXHRcdFx0dmFyIGdlb2NvZGVyID0gbmV3IGdvb2dsZS5tYXBzLkdlb2NvZGVyKCk7XG5cdFx0XHRnZW9jb2Rlci5nZW9jb2RlKCB7ICdhZGRyZXNzJzogc2VhcmNoU3RvcmVzUXVlcnkudmFsKCkudHJpbSgpfSwgZnVuY3Rpb24ocmVzdWx0cywgc3RhdHVzKSB7XG5cdFx0XHRcdGlmIChzdGF0dXMgPT0gZ29vZ2xlLm1hcHMuR2VvY29kZXJTdGF0dXMuT0spIHtcblx0XHRcdFx0ICBcdGRhdGEubG9uZ2l0dWRlID0gcmVzdWx0c1swXS5nZW9tZXRyeS5sb2NhdGlvbi5sbmcoKTtcblx0XHRcdFx0ICBcdGRhdGEubGF0aXR1ZGUgPSByZXN1bHRzWzBdLmdlb21ldHJ5LmxvY2F0aW9uLmxhdCgpO1xuXG5cdFx0XHRcdCAgXHRzZWFyY2hTdG9yZXNBSkFYKGRhdGEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGFsZXJ0KFwiR2VvY29kZSB3YXMgbm90IHN1Y2Nlc3NmdWwgZm9yIHRoZSBmb2xsb3dpbmcgcmVhc29uOiBcIiArIHN0YXR1cyk7XG5cdFx0XHRcdH1cblx0XHQgICAgfSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2VhcmNoU3RvcmVzQUpBWChwYXJhbXMpIHtcblx0JC5hamF4KHtcblx0XHR0eXBlOiAnZ2V0Jyxcblx0XHR1cmw6IFVybHMuc2VhcmNoU3RvcmVzLFxuXHRcdGRhdGE6IHBhcmFtcyxcblxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR2YXIgcG9wdXBMaXN0ID0gJCgnLmNhdGVnb3J5LXBvcHVwLWxpc3Qtc3RvcmVzJyk7XG5cblx0XHRcdCQoJy5ncmlkLXBhZ2Utc3RvcmVzZWxlY3Rvci1wb3B1cCcpLmRpYWxvZygnY2xvc2UnKTtcblx0XHRcdHBvcHVwTGlzdFxuXHRcdFx0XHQuaHRtbChkYXRhKVxuXHRcdFx0XHQuZGlhbG9nKHtcblx0XHRcdFx0XHR3aWR0aDogNDUwLFxuXHRcdFx0XHRcdGF1dG9PcGVuOiBmYWxzZSxcblx0XHRcdFx0XHRtb2RhbDogdHJ1ZSxcblx0XHRcdFx0XHRyZXNpemFibGU6IGZhbHNlXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRwb3B1cExpc3QucGFyZW50KCkuZmluZCgnLnVpLWRpYWxvZy10aXRsZScpLmh0bWwoZGF0YS5tYXRjaCgvU3RvcmVzIG5lYXIuezAsfS9taSlbMF0ucmVwbGFjZSgnPC9zcGFuPicsICcnKSk7XG5cdFx0XHRwb3B1cExpc3QuZGlhbG9nKCdvcGVuJyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2hvd1ZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmcoKSB7XG4gIFx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5Cb3BpcyAmJiBvcHRpb25zLkJvcGlzLklzTG9jYXRpb25TZWFyY2hGaWx0ZXJlZCkge1xuXHRcdHJldHVybjtcblx0fVxuXG4gICQuYWpheCh7XG4gICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgdXJsOiBwYWdlLnZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmdVcmwsXG4gICAgICBhc3luYzogdHJ1ZVxuICB9KVxuICAvLyBzdWNjZXNzXG4gIC5kb25lKGZ1bmN0aW9uICh2YWx1ZXMpIHtcblx0ICBpZiAodmFsdWVzKSB7XG5cdFx0ICB2YWx1ZXMuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuXHRcdFx0ICB2YXIgJHRpbGUgPSAkKCdbZGF0YS1pdGVtaWQ9XCInICsgdmFsLm1hc3RlclByb2R1Y3RJRCArICdcIl0nKTtcblx0XHRcdCAgaWYgKCR0aWxlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0ICBpZiAoIHR5cGVvZiB2YWwudXJsSGFzaCAhPSAndW5kZWZpbmVkJyApIHtcblx0XHRcdFx0XHQgIHZhciBmaWx0ZXJQID0gdmFsLnVybEhhc2gucmVwbGFjZSgnIycsJycpLnNwbGl0KCc9JylbMF07XG5cdFx0XHRcdFx0ICB2YXIgcnIgPSBuZXcgUmVnRXhwKFwicHJlZm5bMC05XT1cIitmaWx0ZXJQKTtcblx0XHRcdFx0XHQgIGlmICggbG9jYXRpb24uaHJlZi5tYXRjaChycikgKSB7XG5cdFx0XHRcdFx0XHQgIGlmIChwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUykge1xuXHRcdFx0XHRcdFx0XHQvL1B1dCB0aGUgaW52ZW50b3J5IG1lc3NhZ2UgaW4gdGhlIHByb2R1Y3QgYmFkZ2UgaWYgdmFyaWFudFdoc0luU3RvY2sgaXMgZmFsc2Vcblx0XHRcdFx0XHRcdFx0dmFyIHByb2R1Y3RCYWRnZSA9ICR0aWxlLmZpbmQoJy5wcm9kdWN0LWJhZGdlLndocy1pbi1zdG9jaycpO1xuXHRcdFx0XHRcdFx0XHRpZiAodmFsLnZhcmlhbnRXaHNJblN0b2NrID09ICd0cnVlJykge1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAodmFsLmRyb3BzaGlwTGVhZCA8PSAxMCkge1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS50ZXh0KHZhbC5pbnZlbnRvcnlNc2cpO1xuXHRcdFx0XHRcdFx0XHRcdHByb2R1Y3RCYWRnZS5yZW1vdmVDbGFzcygnd2hzLWluLXN0b2NrJykuYWRkQ2xhc3MoJ2F2YWlsYWJpbGl0eS1tc2cnKS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0ICB9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR2YXIgJG1zZyA9ICQoJzxkaXYgLz4nKS5hdHRyKCdjbGFzcycsICdhdmFpbGFiaWxpdHktbXNnJykudGV4dCh2YWwuaW52ZW50b3J5TXNnKTsgXG5cdFx0XHRcdFx0XHRcdCR0aWxlLmZpbmQoJy5wcm9kdWN0LXByaWNpbmcnKS5hcHBlbmQoJG1zZyk7XG5cdFx0XHRcdFx0XHRcdGlmICh2YWwudmFyaWFudFdoc0luU3RvY2sgPT0gJ3RydWUnKSB7XG5cdFx0XHRcdFx0XHRcdFx0JHRpbGUuZmluZCgnLndocy1pbi1zdG9jaycpLnNob3coKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ICB9XG5cdFx0XHRcdFx0ICB9XG5cdFx0XHRcdCAgfVxuXHRcdFx0ICB9XG5cdFx0ICB9KTtcblx0ICB9XG4gIH0pXG4gIC5mYWlsKGZ1bmN0aW9uICh4aHIsIHRleHRTdGF0dXMpIHtcbiAgICAgIGlmICh0ZXh0U3RhdHVzID09PSAncGFyc2VyZXJyb3InKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ0ludmVudG9yeSBNZXNzYWdpbmcgRXJyb3IgJyArIFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gc2F2ZVNjcm9sbFBvc2l0aW9uKCkge1xuXHRpZiAoc2Vzc2lvblN0b3JhZ2UpIHtcblx0XHQkKGRvY3VtZW50KS5vZmYoJ3Njcm9sbC5TY3JvbGxQb3NpdGlvblNhdmUnKS5vbignc2Nyb2xsLlNjcm9sbFBvc2l0aW9uU2F2ZScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHR2YXIgY2F0ZWdvcnlJZCA9ICQoJy5jdXJyQ0dJRCcpLnZhbCgpO1xuXHRcdFx0dmFyIHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb247XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID0gSlNPTi5wYXJzZShzZXNzaW9uU3RvcmFnZS5TY3JvbGxQb3NpdGlvbik7XG5cdFx0XHR9IGNhdGNoKGV4Y2VwdGlvbikge31cblx0XHRcdGlmICghc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiB8fCB0eXBlb2Ygc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiAhPSAnb2JqZWN0JyB8fCAhc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbltjYXRlZ29yeUlkXSkge1xuXHRcdFx0XHRzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID0ge307XHRcblx0XHRcdH1cblx0XHRcdHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb25bY2F0ZWdvcnlJZF0gPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCk7XG5cdFx0XHRzZXNzaW9uU3RvcmFnZS5TY3JvbGxQb3NpdGlvbiA9IEpTT04uc3RyaW5naWZ5KHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb24pO1xuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGxvYWRTY3JvbGxQb3NpdGlvbigpIHtcblx0aWYgKHNlc3Npb25TdG9yYWdlKSB7XG5cdFx0dmFyIGNhdGVnb3J5SWQgPSAkKCcuY3VyckNHSUQnKS52YWwoKTtcblx0XHR2YXIgc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbjtcblx0XHR0cnkge1xuXHRcdFx0c2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbiA9IEpTT04ucGFyc2Uoc2Vzc2lvblN0b3JhZ2UuU2Nyb2xsUG9zaXRpb24pO1xuXHRcdH0gY2F0Y2goZXhjZXB0aW9uKSB7fVxuXHRcdGlmIChzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uICYmIHR5cGVvZiBzZXNzaW9uU3RvcmFnZVNjcm9sbFBvc2l0aW9uID09ICdvYmplY3QnICYmIHNlc3Npb25TdG9yYWdlU2Nyb2xsUG9zaXRpb25bY2F0ZWdvcnlJZF0pIHtcblx0XHRcdCQod2luZG93KS5zY3JvbGxUb3Aoc2Vzc2lvblN0b3JhZ2VTY3JvbGxQb3NpdGlvbltjYXRlZ29yeUlkXSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVTdGlja3lSZWZpbmVtZW50cygpIHtcblx0JChkb2N1bWVudCkub2ZmKCdzY3JvbGwuU3RpY2t5UmVmaW5lbWVudHMgU3RpY2t5UmVmaW5lbWVudHMuUmVmcmVzaCcpLm9uKCdzY3JvbGwuU3RpY2t5UmVmaW5lbWVudHMgU3RpY2t5UmVmaW5lbWVudHMuUmVmcmVzaCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyICRyZWZpbmVtZW50cyA9ICQoJyNzZWNvbmRhcnknKTtcblx0XHR2YXIgJHByaW1hcnkgPSAkKCcjcHJpbWFyeScpO1xuXG5cdFx0aWYgKCQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSB8fCB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjcpIHtcblx0XHRcdCRyZWZpbmVtZW50cy5jc3MoJ3RyYW5zZm9ybScsICcnKTtcblx0XHRcdCRyZWZpbmVtZW50cy5zY3JvbGxUb3AoMCk7XG5cdFx0XHQkcmVmaW5lbWVudHMuaGVpZ2h0KCdhdXRvJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBkb2N1bWVudFNjcm9sbFRvcCA9IHBhcnNlSW50KCQoZG9jdW1lbnQpLnNjcm9sbFRvcCgpLCAxMCk7XG5cdFx0XHR2YXIgZG9jdW1lbnRTY3JvbGxEZWx0YSA9IDA7XG5cdFx0XHRpZiAoZGF0YUJ1ZmZlclsnZG9jdW1lbnRTY3JvbGxUb3AnXSkge1xuXHRcdFx0XHRkb2N1bWVudFNjcm9sbERlbHRhID0gZG9jdW1lbnRTY3JvbGxUb3AgLSBkYXRhQnVmZmVyWydkb2N1bWVudFNjcm9sbFRvcCddO1xuXHRcdFx0fVxuXHRcdFx0dmFyIHdpbmRvd0hlaWdodCA9IHBhcnNlSW50KCQod2luZG93KS5oZWlnaHQoKSwgMTApO1xuXHRcdFx0dmFyIHdpbmRvd0JvdHRvbSA9IGRvY3VtZW50U2Nyb2xsVG9wICsgd2luZG93SGVpZ2h0O1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0ID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzWzBdLnNjcm9sbEhlaWdodCwgMTApO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzT2Zmc2V0VG9wID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzLm9mZnNldCgpLnRvcCwgMTApO1xuXHRcdFx0dmFyIHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tID0gcGFyc2VJbnQoJHJlZmluZW1lbnRzLm9mZnNldCgpLnRvcCArIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0LCAxMCk7XG5cdFx0XHR2YXIgcHJpbWFyeVRvcCA9IHBhcnNlSW50KCRwcmltYXJ5Lm9mZnNldCgpLnRvcCwgMTApO1xuXHRcdFx0dmFyIHByaW1hcnlCb3R0b20gPSBwcmltYXJ5VG9wICsgcGFyc2VJbnQoJHByaW1hcnkub3V0ZXJIZWlnaHQoKSwgMTApO1xuXHRcdFx0dmFyIGRvY3VtZW50U2Nyb2xsVG9wRnJvbVByaW1hcnlUb3AgPSBkb2N1bWVudFNjcm9sbFRvcCAtIHByaW1hcnlUb3A7XG4gICAgICAgICAgICBpZiAoZG9jdW1lbnRTY3JvbGxUb3BGcm9tUHJpbWFyeVRvcCA8IDApIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudFNjcm9sbFRvcEZyb21QcmltYXJ5VG9wID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB3aW5kb3dCb3R0b21Gcm9tUHJpbWFyeUJvdHRvbSA9IHdpbmRvd0JvdHRvbSAtIHByaW1hcnlCb3R0b207XG4gICAgICAgICAgICBpZiAod2luZG93Qm90dG9tRnJvbVByaW1hcnlCb3R0b20gPCAwKSB7XG4gICAgICAgICAgICAgICAgd2luZG93Qm90dG9tRnJvbVByaW1hcnlCb3R0b20gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlZmluZW1lbnRzT2Zmc2V0VG9wTmV3O1xuICAgICAgICAgICAgdmFyIHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tTmV3O1xuICAgICAgICAgICAgaWYgKGRvY3VtZW50U2Nyb2xsRGVsdGEpIHtcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50c09mZnNldFRvcE5ldyA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wICsgZG9jdW1lbnRTY3JvbGxEZWx0YTtcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50c09mZnNldEJvdHRvbU5ldyA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wTmV3ICsgcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG4gICAgICAgICAgICB9XG5cblx0XHRcdHZhciByZWZpbmVtZW50c1RyYW5zbGF0ZVk7XG5cdFx0XHRpZiAoJHJlZmluZW1lbnRzLm91dGVySGVpZ2h0KCkgPj0gJHByaW1hcnkub3V0ZXJIZWlnaHQoKSkge1xuXHRcdFx0XHRyZWZpbmVtZW50c1RyYW5zbGF0ZVkgPSAwO1xuXHRcdFx0fSBlbHNlIGlmIChkb2N1bWVudFNjcm9sbERlbHRhID49IDApIHtcblx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcmVmaW5lbWVudHNPZmZzZXRUb3AgLSBwcmltYXJ5VG9wO1xuXG5cdFx0XHRcdGlmICgkcmVmaW5lbWVudHMuaGFzQ2xhc3MoJ3RvcCcpKSB7XG5cdFx0XHRcdFx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCdzdGlja3ktcmVmaW5lbWVudHMnKTtcblx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRyZWZpbmVtZW50c1RyYW5zbGF0ZVkgPSByZWZpbmVtZW50c1RyYW5zbGF0ZVkgLSBkb2N1bWVudFNjcm9sbERlbHRhO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHJlZmluZW1lbnRzT2Zmc2V0Qm90dG9tID49IHByaW1hcnlCb3R0b20pIHtcblx0XHRcdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHByaW1hcnlCb3R0b20gLSBwcmltYXJ5VG9wIC0gcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVmaW5lbWVudHNPZmZzZXRCb3R0b20gPCB3aW5kb3dCb3R0b20gJiYgcHJpbWFyeUJvdHRvbSA+PSB3aW5kb3dCb3R0b20pIHtcblx0XHRcdFx0XHRpZiAocmVmaW5lbWVudHNTY3JvbGxIZWlnaHQgPiB3aW5kb3dIZWlnaHQpIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygnYm90dG9tJyk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChkb2N1bWVudFNjcm9sbFRvcCA+PSBwcmltYXJ5VG9wKSB7XG5cdFx0XHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMuYWRkQ2xhc3MoJ3RvcCcpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmIChyZWZpbmVtZW50c09mZnNldEJvdHRvbSA8IHdpbmRvd0JvdHRvbSAmJiBwcmltYXJ5Qm90dG9tIDwgd2luZG93Qm90dG9tKSB7XG5cdFx0XHRcdFx0aWYgKChkb2N1bWVudFNjcm9sbFRvcCArIHJlZmluZW1lbnRzU2Nyb2xsSGVpZ2h0KSA+IHByaW1hcnlCb3R0b20pIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHByaW1hcnlCb3R0b20gLSBwcmltYXJ5VG9wIC0gcmVmaW5lbWVudHNTY3JvbGxIZWlnaHQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0XHQkcmVmaW5lbWVudHMucmVtb3ZlQ2xhc3MoJ3RvcCBib3R0b20nKTtcblx0XHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygndG9wJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKGRvY3VtZW50U2Nyb2xsRGVsdGEgPCAwKSB7XG5cdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IHJlZmluZW1lbnRzT2Zmc2V0VG9wIC0gcHJpbWFyeVRvcDtcblxuXHRcdFx0XHRpZiAoJHJlZmluZW1lbnRzLmhhc0NsYXNzKCdib3R0b20nKSkge1xuXHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcmVmaW5lbWVudHNUcmFuc2xhdGVZIC0gZG9jdW1lbnRTY3JvbGxEZWx0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChyZWZpbmVtZW50c09mZnNldFRvcCA8PSBwcmltYXJ5VG9wICYmIGRvY3VtZW50U2Nyb2xsVG9wIDw9IHByaW1hcnlUb3ApIHtcblx0XHRcdFx0XHQkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdHJlZmluZW1lbnRzVHJhbnNsYXRlWSA9IDA7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVmaW5lbWVudHNPZmZzZXRCb3R0b20gPj0gcHJpbWFyeUJvdHRvbSAmJiByZWZpbmVtZW50c09mZnNldFRvcCA8PSBkb2N1bWVudFNjcm9sbFRvcCkge1xuXHRcdFx0XHRcdCQoJ2JvZHknKS5yZW1vdmVDbGFzcygnc3RpY2t5LXJlZmluZW1lbnRzJyk7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRzLnJlbW92ZUNsYXNzKCd0b3AgYm90dG9tJyk7XG5cdFx0XHRcdFx0cmVmaW5lbWVudHNUcmFuc2xhdGVZID0gcHJpbWFyeUJvdHRvbSAtIHByaW1hcnlUb3AgLSByZWZpbmVtZW50c1Njcm9sbEhlaWdodDtcblx0XHRcdFx0fSBlbHNlIGlmIChyZWZpbmVtZW50c09mZnNldFRvcCA+PSBkb2N1bWVudFNjcm9sbFRvcCAmJiByZWZpbmVtZW50c09mZnNldFRvcCA+IHByaW1hcnlUb3ApIHtcblx0XHRcdFx0XHQkKCdib2R5JykuYWRkQ2xhc3MoJ3N0aWNreS1yZWZpbmVtZW50cycpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5yZW1vdmVDbGFzcygndG9wIGJvdHRvbScpO1xuXHRcdFx0XHRcdCRyZWZpbmVtZW50cy5hZGRDbGFzcygndG9wJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKHJlZmluZW1lbnRzVHJhbnNsYXRlWSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdFx0JHJlZmluZW1lbnRzLmNzcygndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZVkoJyArIHJlZmluZW1lbnRzVHJhbnNsYXRlWSArICdweCknKTtcblx0XHRcdH1cblxuXHRcdFx0ZGF0YUJ1ZmZlclsnZG9jdW1lbnRTY3JvbGxUb3AnXSA9IGRvY3VtZW50U2Nyb2xsVG9wO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVTdGlja3lTdWJoZWFkZXIoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignc2Nyb2xsLlN0aWNreVN1YmhlYWRlcicpLm9uKCdzY3JvbGwuU3RpY2t5U3ViaGVhZGVyJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgJHNsb3RHcmlkU3ViaGVhZGVyID0gJCgnLnNsb3QtZ3JpZC1zdWJoZWFkZXInKTtcblx0XHR2YXIgJHNsb3RHcmlkU3ViaGVhZGVyRml4ZWQgPSAkKCcuc2xvdC1ncmlkLXN1YmhlYWRlci1maXhlZCcpO1xuXHRcdGlmICgkc2xvdEdyaWRTdWJoZWFkZXIubGVuZ3RoID4gMCAmJiAkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5sZW5ndGggPiAwKSB7XG5cdFx0XHR2YXIgJHByaW1hcnkgPSAkKCcjcHJpbWFyeScpO1xuXHRcdFx0dmFyIGRvY3VtZW50U2Nyb2xsVG9wID0gJChkb2N1bWVudCkuc2Nyb2xsVG9wKCk7XG5cdFx0XHR2YXIgd2luZG93SGVpZ2h0ID0gJCh3aW5kb3cpLmhlaWdodCgpO1xuXHRcdFx0dmFyIHdpbmRvd0JvdHRvbSA9IGRvY3VtZW50U2Nyb2xsVG9wICsgd2luZG93SGVpZ2h0O1xuXHRcdFx0dmFyIHByaW1hcnlUb3AgPSAkcHJpbWFyeS5vZmZzZXQoKS50b3A7XG5cdFx0XHR2YXIgcHJpbWFyeUJvdHRvbSA9IHByaW1hcnlUb3AgKyAkcHJpbWFyeS5vdXRlckhlaWdodCgpO1xuXG5cdFx0XHRpZiAocHJpbWFyeUJvdHRvbSA8IHdpbmRvd0JvdHRvbSkge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9IGVsc2UgaWYgKCRzbG90R3JpZFN1YmhlYWRlci5vZmZzZXQoKS50b3AgPCBkb2N1bWVudFNjcm9sbFRvcCkge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkc2xvdEdyaWRTdWJoZWFkZXJGaXhlZC5hZGRDbGFzcygnaGlkZGVuJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVJlZmluZW1lbnRGaWx0ZXJCeVRleHQoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZigna2V5dXAuUmVmaW5lbWVudEZpbHRlclRleHQnKS5vbigna2V5dXAuUmVmaW5lbWVudEZpbHRlclRleHQnLCAnLnJlZmluZW1lbnQgLnJlZmluZW1lbnQtZmlsdGVyLXRleHQgaW5wdXQnLCBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyIGZpbHRlclRleHQgPSAkdGhpcy52YWwoKTtcblx0XHR2YXIgZmlsdGVyVGV4dFJlZ0V4O1xuXHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQtZmlsdGVyLXRleHQnKTtcblx0XHR2YXIgJHJlc2V0ID0gJGNvbnRhaW5lci5maW5kKCdhLnJlc2V0Jyk7XG5cdFx0dmFyICRub1Jlc3VsdHMgPSAkY29udGFpbmVyLmZpbmQoJy5uby1yZXN1bHRzJyk7XG5cdFx0dmFyICRyZWZpbmVtZW50ID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKTtcblx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZXMgPSAkdGhpcy5jbG9zZXN0KCcuY2hlY2tzLWNvbnRhaW5lcicpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlXTpub3QoW3JlZmluZW1lbnQtY291bnQ9XCIwXCJdKScpO1xuXG5cdFx0aWYgKGZpbHRlclRleHQpIHtcblx0XHRcdGZpbHRlclRleHRSZWdFeCA9IG5ldyBSZWdFeHAoJ14nICsgZmlsdGVyVGV4dCArICd8ICcgKyBmaWx0ZXJUZXh0LCAnZ2knKTtcblx0XHRcdCRyZXNldC5hZGRDbGFzcygnc2hvdycpO1xuXHRcdFx0JHJlZmluZW1lbnQuYWRkQ2xhc3MoJ2ZpbHRlci10ZXh0Jyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlcy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG5cdFx0XHRcdHZhciAkcmVmaW5lbWVudFZhbHVlID0gJCh0aGlzKTtcblx0XHRcdFx0aWYgKCRyZWZpbmVtZW50VmFsdWUuYXR0cigncmVmaW5lbWVudC12YWx1ZScpLm1hdGNoKGZpbHRlclRleHRSZWdFeCkpIHtcblx0XHRcdFx0XHQkcmVmaW5lbWVudFZhbHVlLmFkZENsYXNzKCdmaWx0ZXItdGV4dC1zaG93Jyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHJlZmluZW1lbnRWYWx1ZS5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQtc2hvdycpLmhpZGUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAoJHJlZmluZW1lbnRWYWx1ZXMuZmlsdGVyKCc6dmlzaWJsZScpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHRcdCRub1Jlc3VsdHMuZmluZCgnc3BhbicpLnRleHQoZmlsdGVyVGV4dCk7XG5cdFx0XHRcdCRub1Jlc3VsdHMuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JG5vUmVzdWx0cy5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRyZXNldC5yZW1vdmVDbGFzcygnc2hvdycpO1xuXHRcdFx0JHJlZmluZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZpbHRlci10ZXh0Jyk7XG5cdFx0XHQkcmVmaW5lbWVudFZhbHVlcy5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQtc2hvdycpLmNzcygnZGlzcGxheScsICcnKTtcblx0XHRcdCRub1Jlc3VsdHMuaGlkZSgpO1xuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5SZWZpbmVtZW50RmlsdGVyVGV4dFJlc2V0Jykub24oJ2NsaWNrLlJlZmluZW1lbnRGaWx0ZXJUZXh0UmVzZXQnLCAnLnJlZmluZW1lbnQgLnJlZmluZW1lbnQtZmlsdGVyLXRleHQgYS5yZXNldCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHR2YXIgJGNvbnRhaW5lciA9ICR0aGlzLmNsb3Nlc3QoJy5yZWZpbmVtZW50LWZpbHRlci10ZXh0Jyk7XG5cdFx0dmFyICRub1Jlc3VsdHMgPSAkY29udGFpbmVyLmZpbmQoJy5uby1yZXN1bHRzJyk7XG5cdFx0dmFyICRyZWZpbmVtZW50ID0gJHRoaXMuY2xvc2VzdCgnLnJlZmluZW1lbnQnKTtcblx0XHR2YXIgJHJlZmluZW1lbnRWYWx1ZXMgPSAkdGhpcy5jbG9zZXN0KCcuY2hlY2tzLWNvbnRhaW5lcicpLmZpbmQoJ1tyZWZpbmVtZW50LXZhbHVlXScpO1xuXG5cdFx0JHRoaXMucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcblx0XHQkcmVmaW5lbWVudC5yZW1vdmVDbGFzcygnZmlsdGVyLXRleHQnKTtcblx0XHQkcmVmaW5lbWVudC5maW5kKCcucmVmaW5lbWVudC1maWx0ZXItdGV4dCBpbnB1dCcpLnZhbCgnJyk7XG5cdFx0JHJlZmluZW1lbnRWYWx1ZXMucmVtb3ZlQ2xhc3MoJ2ZpbHRlci10ZXh0LXNob3cnKS5jc3MoJ2Rpc3BsYXknLCAnJyk7XG5cdFx0JG5vUmVzdWx0cy5oaWRlKCk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBzYXZlRXhwYW5kZWRSZWZpbmVtZW50cygpIHtcblx0cmVmaW5lbWVudHNFeHBhbmRlZCA9ICQoJy5yZWZpbmVtZW50cyBbcmVmaW5lbWVudC1pZF0uZXhwYW5kZWQnKS5tYXAoZnVuY3Rpb24oaW5kZXgsIGVsZW1lbnQpIHtcblx0XHRyZXR1cm4gJCh0aGlzKS5hdHRyKCdyZWZpbmVtZW50LWlkJyk7XG5cdH0pLmdldCgpO1xuXG5cdHJlZmluZW1lbnRzVmlld0FsbCA9ICQoJy5yZWZpbmVtZW50cyBbcmVmaW5lbWVudC1pZF0ubW9yZS1leHBhbmRlZCcpLm1hcChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHJldHVybiAkKHRoaXMpLmF0dHIoJ3JlZmluZW1lbnQtaWQnKTtcblx0fSkuZ2V0KCk7XG59XG5cbmZ1bmN0aW9uIHJlZHJhd1Nob3BNeVN0b3JlKCkge1xuXHQkLmFqYXgoe1xuXHRcdG1ldGhvZDogJ0dFVCcsXG5cdFx0dXJsOiB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoVXJscy5TdG9yZXMuR2V0U2hvcE15U3RvcmVQYW5lbCArIGxvY2F0aW9uLnNlYXJjaCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSksXG5cdFx0ZGF0YVR5cGU6ICdodG1sJyxcblx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHQkKCcuc2hvcC1teS1zdG9yZScpLnJlcGxhY2VXaXRoKGRhdGEpO1xuXHRcdFx0dXBkYXRlU2hvcE15U3RvcmUoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTaG9wTXlTdG9yZSgpIHtcblx0aWYgKCQoJy5zaG9wLW15LXN0b3JlLXRvZ2dsZSBpbnB1dDpjaGVja2VkJykubGVuZ3RoID4gMCkge1xuXHRcdCQoJ2JvZHknKS5hdHRyKCdpcy1zaG9wLW15LXN0b3JlLWFjdGl2ZScsIHRydWUpO1xuXHR9IGVsc2Uge1xuXHRcdCQoJ2JvZHknKS5hdHRyKCdpcy1zaG9wLW15LXN0b3JlLWFjdGl2ZScsIGZhbHNlKTtcblx0fVxufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplUmFuZ2VmaW5kZXJFdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suUmVmaW5lbWVudEZpbHRlclRleHRSZXNldCcpLm9uKCdjbGljay5SZWZpbmVtZW50RmlsdGVyVGV4dFJlc2V0JywgJy5wcm9kdWN0LXRpbGUgYScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRwcm9kdWN0ID0gJHRoaXMuY2xvc2VzdCgnW2RhdGEtaXRlbWlkXScpO1xuXHRcdGlmICgkcHJvZHVjdC5sZW5ndGggPiAwKSB7XG5cdFx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdFx0ZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMucHJvZHVjdERldGFpbCwgJ3BpZCcsICRwcm9kdWN0LmF0dHIoJ2RhdGEtaXRlbWlkJykpLFxuXHRcdFx0XHRjYWxsYmFjazogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCgnYm9keScpLmxvYWRpbmcoJ2Rlc3Ryb3knKTtcblx0XHRcdFx0fVxuICAgICAgICAgICAgfSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUJvb3RGaW5kZXJFdmVudHMoKSB7XG5cdHZhciAkYm9vdEZpbmRlclJlc3VsdHNCYW5uZXIgPSAkKCcuYm9vdGZpbmRlci1yZXN1bHRzYmFubmVyJyk7XG5cdGlmICgkYm9vdEZpbmRlclJlc3VsdHNCYW5uZXIgJiYgJGJvb3RGaW5kZXJSZXN1bHRzQmFubmVyLmxlbmd0aCkge1xuXHRcdCRib290RmluZGVyRW1haWxGb3JtID0gJGJvb3RGaW5kZXJSZXN1bHRzQmFubmVyLmZpbmQoJ2Zvcm0uZW1haWwnKTtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3IgPSAkYm9vdEZpbmRlckVtYWlsRm9ybS52YWxpZGF0ZShWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsKTtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3Iuc2V0dGluZ3Mub25mb2N1c291dCA9IFZhbGlkYXRpb25TZXR0aW5ncy5HbG9iYWwub25mb2N1c291dDtcblx0XHRib290RmluZGVyRW1haWxWYWxpZGF0b3Iuc2V0dGluZ3MuZXJyb3JQbGFjZW1lbnQgPSBWYWxpZGF0aW9uU2V0dGluZ3MuR2xvYmFsLmVycm9yUGxhY2VtZW50O1xuXHRcdCRib290RmluZGVyRW1haWxGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJlbWFpbFwiXScpLnJ1bGVzKCdhZGQnLCAkLmV4dGVuZChWYWxpZGF0aW9uUnVsZXMuRW1haWwsIHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0bWVzc2FnZXM6IHtcblx0XHRcdFx0cmVxdWlyZWQ6ICQudmFsaWRhdG9yLmZvcm1hdCgnUGxlYXNlIGVudGVyIGFuIGVtYWlsIGFkZHJlc3MuJylcblx0XHRcdH1cblx0XHR9KSk7XG5cdFx0JGJvb3RGaW5kZXJFbWFpbEZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInVzZXJhZ3JlZW1lbnRcIl0nKS5ydWxlcygnYWRkJywge1xuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRtZXNzYWdlczoge1xuXHRcdFx0XHRyZXF1aXJlZDogJC52YWxpZGF0b3IuZm9ybWF0KCdQbGVhc2UgYWdyZWUgdG8gdGhlIHRlcm1zIGFuZCBjb25kaXRpb25zLicpXG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLkJvb3RGaW5kZXJSZXN1bHRzRW1haWwnKS5vbignY2xpY2suQm9vdEZpbmRlclJlc3VsdHNFbWFpbCcsICcuYm9vdGZpbmRlci1yZXN1bHRzYmFubmVyIC5idG4uc2VuZC1yZXN1bHRzLWVtYWlsJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGlmICgkYm9vdEZpbmRlckVtYWlsRm9ybSAmJiAkYm9vdEZpbmRlckVtYWlsRm9ybS52YWxpZCgpKSB7XG5cdFx0XHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0XHRcdHZhciAkY29udGFpbmVyID0gJHRoaXMuY2xvc2VzdCgnZm9ybScpO1xuXHRcdFx0XHQkY29udGFpbmVyLmxvYWRpbmcoJC5leHRlbmQobG9hZGluZ0luZGljYXRvclNldHRpbmdzLCB7XG5cdFx0XHRcdFx0SXNMYWJlbFNob3duOiB0cnVlLFxuXHRcdFx0XHRcdENvbnRlbnQ6ICdTZW5kaW5nIEVtYWlsLi4uJ1xuXHRcdFx0XHR9KSk7XG5cdFx0XHRcdHZhciB1cmxQYXJhbWV0ZXJzID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh3aW5kb3cubG9jYXRpb24uaHJlZik7XG5cdFx0XHRcdHZhciBib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCA9IFVybHMuQm9vdEZpbmRlci5TZW5kUmVzdWx0c0VtYWlsO1xuXHRcdFx0XHRib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCwgJ2NnaWQnLCAkKCcuY3VyckNHSUQnKS52YWwoKSk7XG5cdFx0XHRcdGZvciAodmFyIHVybFBhcmFtZXRlciBpbiB1cmxQYXJhbWV0ZXJzKSB7XG5cdFx0XHRcdFx0aWYgKHVybFBhcmFtZXRlcnNbdXJsUGFyYW1ldGVyXSkge1xuXHRcdFx0XHRcdFx0Ym9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWxVcmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoYm9vdEZpbmRlclNlbmRSZXN1bHRzRW1haWxVcmwsIHVybFBhcmFtZXRlciwgdXJsUGFyYW1ldGVyc1t1cmxQYXJhbWV0ZXJdKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdFx0ZW1haWw6ICRjb250YWluZXIuZmluZCgnaW5wdXRbdHlwZT1cImVtYWlsXCJdJykudmFsKCksXG5cdFx0XHRcdFx0dXJsOiB1dGlsLnJlbW92ZVBhcmFtRnJvbVVSTCh3aW5kb3cubG9jYXRpb24uaHJlZiwgJ2Jvb3RmaW5kZXJ2aWV3cmVzdWx0cycpXG5cdFx0XHRcdH1cblx0XHRcdFx0JC5hamF4KHtcblx0XHRcdFx0XHR0eXBlOiAncG9zdCcsXG5cdFx0XHRcdFx0dXJsOiBib290RmluZGVyU2VuZFJlc3VsdHNFbWFpbFVybCxcblx0XHRcdFx0XHRkYXRhOiBwYXlsb2FkLFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdCRjb250YWluZXIubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0aWYgKGRhdGEgJiYgZGF0YS5zdWNjZXNzKSB7XG5cdFx0XHRcdFx0XHRcdCRjb250YWluZXIuZmluZCgnLnZhbGlkYXRpb24tZXJyb3ItY29udGFpbmVyJykuaHRtbCgnPHNwYW4gY2xhc3M9XCJlcnJvclwiPkVtYWlsIHNlbnQhPC9zcGFuPicpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0JGNvbnRhaW5lci5maW5kKCcudmFsaWRhdGlvbi1lcnJvci1jb250YWluZXInKS5odG1sKCc8c3BhbiBjbGFzcz1cImVycm9yXCI+QW4gZXJyb3Igb2NjdXJyZWQgc2VuZGluZyB0aGUgZW1haWwuIFBsZWFzZSB0cnkgYWdhaW4uPC9zcGFuPicpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXIgfHwge307XG5cblx0SW1hZ2VDb25zdGFudHMgPSBwYWdlQ29udGV4dC5zaXRlID09PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUyA/IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2FwcF9zdG9yZWZyb250X2NvdW50cnlvdXRmaXR0ZXJzL2NhcnRyaWRnZS9qcy9JbWFnZUNvbnN0YW50cycpIDogcmVxdWlyZSgnLi4vLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9JbWFnZUNvbnN0YW50cycpO1xuXHRcbiAgICBjb21wYXJlV2lkZ2V0LmluaXQoKTtcbiAgICBpZiAoJ3ZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmdVcmwnIGluIHBhZ2UgJiYgcGFnZS52YXJpYW50SW52ZW50b3J5TWVzc2FnaW5nVXJsKSB7XG4gICAgXHR2YXIgdXJsUGFyYW1zID0gdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoLnN1YnN0cigxKSk7XG4gICAgXHRpZih1cmxQYXJhbXMuaGFzT3duUHJvcGVydHkoJ3N0YXJ0JykgJiYgdXJsUGFyYW1zLnN0YXJ0ID4gMCl7XG4gICAgXHRcdHVwZGF0ZUludmVudG9yeU1lc3NhZ2VzKHdpbmRvdy5sb2NhdGlvbi5ocmVmLCBzaG93VmFyaWFudEludmVudG9yeU1lc3NhZ2luZyk7XG4gICAgXHR9IGVsc2Uge1xuICAgICAgICAgICAgc2hvd1ZhcmlhbnRJbnZlbnRvcnlNZXNzYWdpbmcoKTtcbiAgICBcdH1cbiAgICB9XG5cbiAgICBwcm9kdWN0VGlsZS5pbml0KCk7XG4gICAgc2l6ZVJlZmluZW1lbnRzLmluaXQoKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG5cdHVwZGF0ZVNob3BNeVN0b3JlKCk7XG5cdHNsaWRlcnMuaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycygnLm1haW4tY29udGVudCAuY2F0ZWdvcnktbGFuZGluZy1zbGlkZXI6bm90KC5zbGljay1pbml0aWFsaXplZCknKTtcblx0aW5pdGlhbGl6ZVJlZmluZW1lbnRGaWx0ZXJCeVRleHQoKTtcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcblx0XHRpbml0aWFsaXplQm9vdEZpbmRlckV2ZW50cygpO1xuXHR9XG5cdGxvYWRTY3JvbGxQb3NpdGlvbigpO1xuXHRzYXZlU2Nyb2xsUG9zaXRpb24oKTtcblx0aWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpIHtcblx0XHRpbml0aWFsaXplU3RpY2t5UmVmaW5lbWVudHMoKTtcblx0XHQvLyBpbml0aWFsaXplU3RpY2t5U3ViaGVhZGVyKCk7XG5cdH1cblxuXHRsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MgPSB7XG5cdFx0SXNMYWJlbFNob3duOiBmYWxzZSxcblx0XHRDc3NDbGFzczogJ2Z1bGxzY3JlZW4nLFxuXHRcdEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xuXHR9O1xuXG5cdGlmIChwYWdlQ29udGV4dC5zaXRlID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5SYW5nZWZpbmRlcikge1xuXHRcdGluaXRpYWxpemVSYW5nZWZpbmRlckV2ZW50cygpO1xuXHR9XG5cblx0aWYgKG9wdGlvbnMpIHtcblx0XHRpZiAob3B0aW9ucy5TdHlsZUNvdW50Q2FjaGUpIHtcblx0XHRcdHN0eWxlQ291bnRzLnJlbmRlcihvcHRpb25zLlN0eWxlQ291bnRDYWNoZSk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuQm9waXMgJiYgb3B0aW9ucy5Cb3Bpcy5FbmFibGVkICYmIG9wdGlvbnMuQm9waXMuU2VsZWN0ZWRMb2NhdGlvbnMpIHtcblx0XHRcdGJvb3RCYXJuRXhwcmVzc1JlZmluZW1lbnRXaXphcmQuaW5pdGlhbGl6ZSgkKCcjZGlhbG9nLWJvb3RiYXJuZXhwcmVzcy1yZWZpbmVtZW50LXdpemFyZCcpLCBvcHRpb25zKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5SZWZpbmVtZW50c1VJVmVyc2lvbiA9PSBSZWZpbmVtZW50VUlWZXJzaW9uQ29uc3RhbnRzLlVwZGF0ZWQpIHtcblx0XHRcdHVwZGF0ZVJlZmluZW1lbnRDb3VudHMoKTtcblx0XHRcdGlmIChvcHRpb25zLlN0b3JlVUlWZXJzaW9uID09ICcyMDI0UmVkZXNpZ24nKSB7XG5cdFx0XHRcdHVwZGF0ZVNlbGVjdGVkUmVmaW5lbWVudHMoKTtcblx0XHRcdFx0dXBkYXRlUGVuZGluZ1JlZmluZW1lbnRzKCk7XG5cdFx0XHR9XG5cdFx0XG5cdFx0XHR2YXIgJHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXI7XG5cdFx0XHRpZiAocGFnZUNvbnRleHQuc2l0ZSA9PT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMpIHtcblx0XHRcdFx0JHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIgPSAkKCcucHJpbWFyeS1jb250ZW50ID4gLnNvcnQtYW5kLXJlZmluZSA+IC5wcm9kdWN0LXNlbGVjdGlvbnMnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRwcm9kdWN0U2VsZWN0aW9uQ29udGFpbmVyID0gJCgnLnByaW1hcnktY29udGVudCA+IC5wcm9kdWN0LXNlbGVjdGlvbnMnKVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoJHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIuZmluZCgnLmxpc3Qtc2VsZWN0aW9ucyAudmFsdWUuYXBwbGllZCcpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0JHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIuc2hvdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JHByb2R1Y3RTZWxlY3Rpb25Db250YWluZXIuaGlkZSgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIExvY2F0aW9uU2VhcmNoID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vYXBwX3N0b3JlZnJvbnRfY29yZS9jYXJ0cmlkZ2UvanMvYm9waXMvY29tcG9uZW50cy9Mb2NhdGlvblNlYXJjaCcpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuXHR2YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuXHRcdElzTGFiZWxTaG93bjogZmFsc2UsXG5cdFx0Q3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcblx0XHRCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcblx0fTtcblxuXHRpZiAoJCgnLnB0X3N0b3JlZnJvbnQgLnNlYXJjaC1zdG9yZXMnKS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIGxvY2F0aW9uU2VhcmNoID0gbmV3IExvY2F0aW9uU2VhcmNoKCk7XG5cdFx0JChkb2N1bWVudCkub2ZmKCdjbGljay5TdG9yZWZyb250LlN0b3JlU2VhcmNoJykub24oJ2NsaWNrLlN0b3JlZnJvbnQuU3RvcmVTZWFyY2gnLCAnLnB0X3N0b3JlZnJvbnQgLnNlYXJjaC1zdG9yZXM6bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0bG9jYXRpb25TZWFyY2guaW5pdGlhbGl6ZSgkKCcubG9jYXRpb24tc2VhcmNoLWRpYWxvZycpLCBvcHRpb25zKTtcblx0XHRcdCQoJy5sb2NhdGlvbi1zZWFyY2gtZGlhbG9nJykudHJpZ2dlcignTG9jYXRpb25TZWFyY2guRm9ybVN1Ym1pdCcpO1xuXHRcdH0pO1xuXHR9XG5cblx0JCgnLnB0X3N0b3JlZnJvbnQgLnNlY3Rpb24gLmJ0bjpub3QoLnNlYXJjaC1zdG9yZXMpJykub2ZmKCdjbGljay5Mb2FkaW5nSW5kaWNhdG9yJykub24oJ2NsaWNrLkxvYWRpbmdJbmRpY2F0b3InLCBmdW5jdGlvbigpIHtcblx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHR9KTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xudmFyIGxvYWRpbmdJbmRpY2F0b3IgPSByZXF1aXJlKCcuLi9jb21wb25lbnRzL0xvYWRpbmdJbmRpY2F0b3InKTtcbnZhciBHZW9sb2NhdGlvbkhlbHBlciA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvR2VvbG9jYXRpb24vR2VvbG9jYXRpb25IZWxwZXInKTtcbnZhciBzaG9wWW91clN0b3JlRGlhbG9nID0gcmVxdWlyZSgnLi4vYm9waXMvY29tcG9uZW50cy9TaG9wWW91clN0b3JlRGlhbG9nJyk7XG52YXIgVGVtcGxhdGVDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1RlbXBsYXRlQ29uc3RhbnRzJyk7XG5cbnZhciBvcHRpb25zO1xudmFyIGRhdGFCdWZmZXI7XG52YXIgaW5wdXRTZWFyY2hUaW1lcjtcblxudmFyICRjb250YWluZXI7XG52YXIgJGNvbnRlbnQ7XG52YXIgJHVzZU15TG9jYXRpb25CdXR0b247XG52YXIgJHNlYXJjaEJ1dHRvbjtcbnZhciAkbG9jYXRpb25TZWFyY2hSZXN1bHRzO1xudmFyIGxvY2F0aW9uU2VhcmNoUmVzdWx0Q29udGFpbmVyVGVtcGxhdGU7XG52YXIgbG9jYXRpb25TZWFyY2hSZXN1bHRJdGVtVGVtcGxhdGU7XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suU2hvcFlvdXJTdG9yZURpYWxvZycpLm9uKCdjbGljay5TaG9wWW91clN0b3JlRGlhbG9nJywgJy5zaG9wLXN0b3JlLWludmVudG9yeScsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciAkdGhpcyA9ICQodGhpcyk7XG5cdFx0dmFyICRzdG9yZSA9ICR0aGlzLmNsb3Nlc3QoJ1tzdG9yZS1pZF0nKTtcblx0XHRzaG9wWW91clN0b3JlRGlhbG9nLmluaXRpYWxpemUoe1xuXHRcdFx0U3RvcmVJZDogJHN0b3JlLmF0dHIoJ3N0b3JlLWlkJyksXG5cdFx0XHRTdG9yZU5hbWU6ICRzdG9yZS5hdHRyKCdzdG9yZS1uYW1lJylcblx0XHR9KTtcblx0fSk7XG5cblx0JCgnLnB0X3N0b3JlLWxvY2F0b3InKS5vZmYoJ2NsaWNrLlVzZU15TG9jYXRpb24nKS5vbignY2xpY2suVXNlTXlMb2NhdGlvbicsICcudXNlLW15LWxvY2F0aW9uJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdGRhdGFCdWZmZXIubGltaXQgPSB3aW5kb3cub3V0ZXJXaWR0aCA+PSAxMDI0ID8gMTAgOiA1O1xuXHRcdGRhdGFCdWZmZXIub2Zmc2V0ID0gMDtcblx0XHRkYXRhQnVmZmVyLnF1ZXJ5ID0gJyc7XG5cdFx0JCgnLnN0b3JlLWZpbHRlci1jb250YWluZXIgW3R5cGU9XCJ0ZXh0XCJdJykudmFsKCcnKTtcblxuXHRcdCR1c2VNeUxvY2F0aW9uQnV0dG9uLmxvYWRpbmcoKTtcblx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmh0bWwoJycpO1xuXHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygpO1xuXHRcdEdlb2xvY2F0aW9uSGVscGVyLkdldFBvc2l0aW9uKCkudGhlbihmdW5jdGlvbihwb3NpdGlvbikge1xuXHRcdFx0ZGF0YUJ1ZmZlci5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuXHRcdFx0Z2V0U3RvcmVMaXN0KCk7XG5cdFx0fSkuY2F0Y2goZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoJGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHRcdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXG5cdCQoJy5wdF9zdG9yZS1sb2NhdG9yJykub2ZmKCdzdWJtaXQuU2VhcmNoJykub24oJ3N1Ym1pdC5TZWFyY2gnLCAnLnN0b3JlLWZpbHRlci1jb250YWluZXIgZm9ybScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0c2VhcmNoKCk7XG5cdH0pO1xuXG5cdCQoJy5wdF9zdG9yZS1sb2NhdG9yJykub2ZmKCdjbGljay5TZWFyY2gnKS5vbignY2xpY2suU2VhcmNoJywgJy5zdG9yZS1maWx0ZXItY29udGFpbmVyIC5idG4uYnRuLXByaW1hcnknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHNlYXJjaCgpO1xuXHR9KTtcblxuXHQkKCcucHRfc3RvcmUtbG9jYXRvcicpLm9mZignY2xpY2suTG9hZE1vcmUnKS5vbignY2xpY2suTG9hZE1vcmUnLCAnLmxvY2F0aW9uLXNlYXJjaC1yZXN1bHRzIC5sb2FkLW1vcmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblx0XHRkYXRhQnVmZmVyLmxpbWl0ID0gd2luZG93Lm91dGVyV2lkdGggPj0gMTAyNCA/IDEwIDogNTtcblx0XHRkYXRhQnVmZmVyLm9mZnNldCArPSBkYXRhQnVmZmVyLmxpbWl0O1xuXHRcdCR0aGlzLnBhcmVudCgpLmxvYWRpbmcoKTtcblx0XHRHZW9sb2NhdGlvbkhlbHBlci5HZXRQb3NpdGlvbigpLnRoZW4oZnVuY3Rpb24ocG9zaXRpb24pIHtcblx0XHRcdGRhdGFCdWZmZXIucG9zaXRpb24gPSBwb3NpdGlvbjtcblx0XHRcdGdldFN0b3JlTGlzdCgpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuYXR0cignbG9hZGluZycpKSB7XG5cdFx0XHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2VhcmNoKCkge1xuXHRkYXRhQnVmZmVyLmxpbWl0ID0gd2luZG93Lm91dGVyV2lkdGggPj0gMTAyNCA/IDEwIDogNTtcblx0ZGF0YUJ1ZmZlci5vZmZzZXQgPSAwO1xuXHRkYXRhQnVmZmVyLnF1ZXJ5ID0gJCgnLnN0b3JlLWZpbHRlci1jb250YWluZXIgW3R5cGU9XCJ0ZXh0XCJdJykudmFsKCk7XG5cblx0JHNlYXJjaEJ1dHRvbi5sb2FkaW5nKCk7XG5cdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuaHRtbCgnJyk7XG5cdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMubG9hZGluZygpO1xuXHRHZW9sb2NhdGlvbkhlbHBlci5HZXRQb3NpdGlvbigpLnRoZW4oZnVuY3Rpb24ocG9zaXRpb24pIHtcblx0XHRkYXRhQnVmZmVyLnBvc2l0aW9uID0gcG9zaXRpb247XG5cdFx0Z2V0U3RvcmVMaXN0KCk7XG5cdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdGlmICgkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmF0dHIoJ2xvYWRpbmcnKSkge1xuXHRcdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RvcmVMaXN0KCkge1xuXHR2YXIgZ2VvbG9jYXRpb25Qb3NpdGlvbjtcblx0aWYgKGRhdGFCdWZmZXIucG9zaXRpb24gJiYgZGF0YUJ1ZmZlci5wb3NpdGlvbi5jb29yZHMpIHtcblx0XHRnZW9sb2NhdGlvblBvc2l0aW9uID0ge1xuXHRcdFx0Y29vcmRzOiB7XG5cdFx0XHRcdGFjY3VyYWN5OiBkYXRhQnVmZmVyLnBvc2l0aW9uLmNvb3Jkcy5hY2N1cmFjeSxcblx0XHRcdFx0bGF0aXR1ZGU6IGRhdGFCdWZmZXIucG9zaXRpb24uY29vcmRzLmxhdGl0dWRlLFxuXHRcdFx0XHRsb25naXR1ZGU6IGRhdGFCdWZmZXIucG9zaXRpb24uY29vcmRzLmxvbmdpdHVkZVxuXHRcdFx0fSxcblx0XHRcdHRpbWVzdGFtcDogZGF0YUJ1ZmZlci5wb3NpdGlvbi50aW1lc3RhbXBcblx0XHR9O1xuXHR9XG5cblx0dmFyIHBheWxvYWQgPSB7XG5cdFx0U291cmNlOiAnU3RvcmVMb2NhdG9yUGFnZScsXG5cdFx0R2VvbG9jYXRpb25Qb3NpdGlvbjogZ2VvbG9jYXRpb25Qb3NpdGlvblxuXHR9O1xuXHRpZiAoZGF0YUJ1ZmZlci5xdWVyeSAhPSB1bmRlZmluZWQpIHtcblx0XHRwYXlsb2FkLlF1ZXJ5ID0gZGF0YUJ1ZmZlci5xdWVyeTtcblx0fVxuXHRpZiAoZGF0YUJ1ZmZlci5saW1pdCAhPSB1bmRlZmluZWQpIHtcblx0XHRwYXlsb2FkLkxpbWl0ID0gZGF0YUJ1ZmZlci5saW1pdDtcblx0fVxuXHRpZiAoZGF0YUJ1ZmZlci5vZmZzZXQgIT0gdW5kZWZpbmVkKSB7XG5cdFx0cGF5bG9hZC5PZmZzZXQgPSBkYXRhQnVmZmVyLm9mZnNldDtcblx0fVxuXG5cdCQuYWpheCh7XG5cdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0dXJsOiBVcmxzLkJvcGlzLkdldFN0b3Jlc0Zvckdlb2xvY2F0aW9uUG9zaXRpb24sXG5cdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRkYXRhOiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdHJlbmRlclN0b3JlTGlzdChkYXRhKTtcblx0XHR9LFxuXHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFxuXHRcdH1cblx0fSk7XHRcdFxufVxuXG5mdW5jdGlvbiByZW5kZXJTdG9yZUxpc3QoZGF0YSkge1xuXHR2YXIgbG9jYXRpb25EYXRhO1xuXHRpZiAoZGF0YSAmJiBkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQgJiYgZGF0YS5JbnF1aXJ5UmVzdWx0ICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5kYXRhLmxlbmd0aCA+IDApIHtcblx0XHRsb2NhdGlvbkRhdGEgPSBkYXRhLklucXVpcnlSZXN1bHQuZGF0YTtcblx0fVxuXG5cdCRjb250YWluZXIuYXR0cignc3RhdGUnLCAncmVzdWx0Jyk7XG5cdGlmIChsb2NhdGlvbkRhdGEgJiYgbG9jYXRpb25EYXRhLmxlbmd0aCA+IDApIHtcblx0XHRsb2NhdGlvbkRhdGEgPSBsb2NhdGlvbkRhdGEuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuXHRcdFx0cmV0dXJuIGxlZnQuZGlzdGFuY2UgLSByaWdodC5kaXN0YW5jZTtcblx0XHR9KTtcblx0XHRcblx0XHRkYXRhQnVmZmVyWydTdG9yZXNEaXNwbGF5ZWQnXSA9IFtdO1xuXHRcdCRjb250YWluZXIuYXR0cigncmVzdWx0LWNvdW50JywgbG9jYXRpb25EYXRhLmxlbmd0aCk7XG5cdFx0XG5cdFx0dmFyIHN0b3JlTGlzdEh0bWwgPSAnJztcblx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmZpbmQoJy5uby1yZXN1bHRzJykucmVtb3ZlKCk7XG5cdFx0Zm9yICh2YXIgbG9jYXRpb25FbGVtZW50IGluIGxvY2F0aW9uRGF0YSkge1xuXHRcdFx0dmFyIGxvY2F0aW9uID0gbG9jYXRpb25EYXRhW2xvY2F0aW9uRWxlbWVudF07XG5cdFx0XHRcblx0XHRcdGlmIChsb2NhdGlvbiAmJiAhZGF0YUJ1ZmZlclsnU3RvcmVzRGlzcGxheWVkJ11bbG9jYXRpb24uY29kZV0gJiYgbG9jYXRpb24uU3RvcmVJbmZvLlN0YXRlQ29kZVBhcnNlZCAmJiBsb2NhdGlvbi5TdG9yZUluZm8uUG9zdGFsQ29kZSkge1xuXHRcdFx0XHR2YXIgc3RvcmVQaG9uZSA9ICcnO1xuXHRcdFx0XHR2YXIgc3RvcmVPcGVuVW50aWwgPSAnJztcblx0XHRcdFx0aWYgKGxvY2F0aW9uLlN0b3JlSW5mbykge1xuXHRcdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uUGhvbmUpIHtcblx0XHRcdFx0XHRcdHN0b3JlUGhvbmUgPSBsb2NhdGlvbi5TdG9yZUluZm8uUGhvbmU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uT3BlblVudGlsKSB7XG5cdFx0XHRcdFx0XHRzdG9yZU9wZW5VbnRpbCA9IGxvY2F0aW9uLlN0b3JlSW5mby5PcGVuVW50aWw7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHR2YXIgc3RvcmVJbnZlbnRvcnlMaW5rID0gJyc7XG5cdFx0XHRcdGlmIChsb2NhdGlvbi5TdG9yZUluZm8uU3RvcmVJbnZlbnRvcnlMaW5rKSB7XG5cdFx0XHRcdFx0c3RvcmVJbnZlbnRvcnlMaW5rID0gJzxhIGNsYXNzPVwic2hvcC1zdG9yZS1pbnZlbnRvcnlcIj4nICsgUmVzb3VyY2VzLlN0b3Jlcy5TaG9wU3RvcmVJbnZlbnRvcnkgKyAnPC9hPic7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2YXIgZGlyZWN0aW9uc0xpbmsgPSAnJztcblx0XHRcdFx0aWYgKGxvY2F0aW9uLlN0b3JlSW5mby5EaXJlY3Rpb25zVXJsKSB7XG5cdFx0XHRcdFx0ZGlyZWN0aW9uc0xpbmsgPSAnPGEgY2xhc3M9XCJkaXJlY3Rpb25zXCIgaHJlZj1cIicgKyBsb2NhdGlvbi5TdG9yZUluZm8uRGlyZWN0aW9uc1VybCArICdcIiB0YXJnZXQ9XCJfYmxhbmtcIj5EaXJlY3Rpb25zPC9hPic7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRzdG9yZUxpc3RIdG1sICs9IGxvY2F0aW9uU2VhcmNoUmVzdWx0SXRlbVRlbXBsYXRlKHtcblx0XHRcdFx0XHRTdG9yZUlkOiBsb2NhdGlvbi5jb2RlLFxuXHRcdFx0XHRcdFN0b3JlTmFtZTogbG9jYXRpb24uU3RvcmVJbmZvLk5hbWUsXG5cdFx0XHRcdFx0RGlzdGFuY2U6IGxvY2F0aW9uLlN0b3JlSW5mby5EaXN0YW5jZS50b0ZpeGVkKDEpICsgJyBtaScsXG5cdFx0XHRcdFx0SHRtbDogJzxhIGhyZWY9XCInICsgVXJscy5zdG9yZURldGFpbHMgKyAnP1N0b3JlSUQ9JyArIGxvY2F0aW9uLmNvZGUgKyAnXCI+JyArIGxvY2F0aW9uLlN0b3JlSW5mby5OYW1lICsgJzwvYT48YnIvPicgK1xuXHRcdFx0XHRcdFx0XHRsb2NhdGlvbi5TdG9yZUluZm8uQWRkcmVzczEgKyAnPGJyLz4nICsgXG5cdFx0XHRcdFx0XHRcdGxvY2F0aW9uLlN0b3JlSW5mby5DaXR5ICsgJywgJyArIGxvY2F0aW9uLlN0b3JlSW5mby5TdGF0ZUNvZGVQYXJzZWQgKyAnICcgKyBsb2NhdGlvbi5TdG9yZUluZm8uUG9zdGFsQ29kZS5zdWJzdHIoMCwgNSkgKyAnPGJyLz4nICtcblx0XHRcdFx0XHRcdFx0c3RvcmVQaG9uZSArICc8YnIvPicgK1xuXHRcdFx0XHRcdFx0XHRzdG9yZU9wZW5VbnRpbCxcblx0XHRcdFx0XHREaXJlY3Rpb25zTGluazogZGlyZWN0aW9uc0xpbmssXG5cdFx0XHRcdFx0U3RvcmVJbnZlbnRvcnlMaW5rOiBzdG9yZUludmVudG9yeUxpbmtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGRhdGFCdWZmZXJbJ1N0b3Jlc0Rpc3BsYXllZCddW2xvY2F0aW9uLmNvZGVdID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKGRhdGEuSW5xdWlyeVJlc3VsdC5tZXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdC5tZXRhLnBhZ2UgPCBkYXRhLklucXVpcnlSZXN1bHQubWV0YS5wYWdlcykge1xuXHRcdFx0c3RvcmVMaXN0SHRtbCArPSAnPGxpIGNsYXNzPVwibG9hZC1tb3JlLWNvbnRhaW5lclwiPjxhIGNsYXNzPVwibG9hZC1tb3JlXCI+TG9hZCBNb3JlPC9hPjwvbGk+Jztcblx0XHR9XG5cdFx0XG5cdFx0dmFyIHJlc3VsdEh0bWwgPSBsb2NhdGlvblNlYXJjaFJlc3VsdENvbnRhaW5lclRlbXBsYXRlKHtcblx0XHRcdEh0bWw6IHN0b3JlTGlzdEh0bWxcblx0XHR9KTtcblx0XHQkbG9jYXRpb25TZWFyY2hSZXN1bHRzLmZpbmQoJy5sb2FkLW1vcmUtY29udGFpbmVyJykucmVtb3ZlKCk7XG5cdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5hcHBlbmQocmVzdWx0SHRtbCk7XG5cdH0gZWxzZSB7XG5cdFx0JGNvbnRhaW5lci5hdHRyKCdyZXN1bHQtY291bnQnLCAnMCcpO1xuXHRcdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuaHRtbCgnPGxpIGNsYXNzPVwibm8tcmVzdWx0c1wiPk5vIHN0b3JlcyBmb3VuZCEgUGxlYXNlIHRyeSBhIGRpZmZlcmVudCBzZWFyY2guPC9saT4nKTtcblx0fVxuXG5cdGlmICgkdXNlTXlMb2NhdGlvbkJ1dHRvbi5hdHRyKCdsb2FkaW5nJykpIHtcblx0XHQkdXNlTXlMb2NhdGlvbkJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdH1cblx0aWYgKCRzZWFyY2hCdXR0b24uYXR0cignbG9hZGluZycpKSB7XG5cdFx0JHNlYXJjaEJ1dHRvbi5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdH1cblx0aWYgKCRsb2NhdGlvblNlYXJjaFJlc3VsdHMuYXR0cignbG9hZGluZycpKSB7XG5cdFx0JGxvY2F0aW9uU2VhcmNoUmVzdWx0cy5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdH1cbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcblx0b3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXIgfHwge307XG5cdGRhdGFCdWZmZXIgPSB7XG5cdFx0b2Zmc2V0OiAwXG5cdH07XG5cblx0JGNvbnRhaW5lciA9ICQoJyNzdG9yZXNfbWFpbicpO1xuXHQkY29udGVudCA9ICRjb250YWluZXIuZmluZCgnLmNvbnRlbnQnKTtcblx0JHVzZU15TG9jYXRpb25CdXR0b24gPSAkKCcuc3RvcmUtZmlsdGVyLWNvbnRhaW5lciAudXNlLW15LWxvY2F0aW9uJyk7XG5cdCRzZWFyY2hCdXR0b24gPSAkKCcuc3RvcmUtZmlsdGVyLWNvbnRhaW5lciAuYnRuLmJ0bi1wcmltYXJ5Jyk7XG5cdCRsb2NhdGlvblNlYXJjaFJlc3VsdHMgPSAkKCcubG9jYXRpb24tc2VhcmNoLXJlc3VsdHMnKTtcblx0bG9jYXRpb25TZWFyY2hSZXN1bHRDb250YWluZXJUZW1wbGF0ZSA9IF8udGVtcGxhdGUoJCgnI3RlbXBsYXRlLWJvcGlzLXJlc3VsdC1jb250YWluZXInKS5odG1sKCksIFRlbXBsYXRlQ29uc3RhbnRzLkxvZGFzaC5TZXR0aW5ncyk7XG5cdGxvY2F0aW9uU2VhcmNoUmVzdWx0SXRlbVRlbXBsYXRlID0gXy50ZW1wbGF0ZSgkKCcjdGVtcGxhdGUtYm9waXMtcmVzdWx0LWl0ZW0tc3RvcmUtbG9jYXRvcicpLmh0bWwoKSwgVGVtcGxhdGVDb25zdGFudHMuTG9kYXNoLlNldHRpbmdzKTtcdFxuXG5cdGluaXRpYWxpemVFdmVudHMoKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcblx0XHJcblx0ZWxlbWVudFByZWZpeDogJ3NoaXBwaW5nLXJlc3RyaWN0aW9ucy1wb3B1cCcsXHJcblx0ZWxlbWVudDogbnVsbCxcclxuXHRkZWZhdWx0VGl0bGU6ICcnLFxyXG5cdGRlZmF1bHRDb250ZW50OiAnJyxcclxuXHRcclxuXHRpbml0OiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0aWYgKCEkKCAnLicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKS5sZW5ndGgpIHtcclxuXHRcdFx0JCgnYm9keScpLmFwcGVuZCgnPGRpdiBjbGFzcz1cIicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnXCI+PGRpdiBjbGFzcz1cIicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19wb3B1cFwiPjxoMiBjbGFzcz1cIicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19oMlwiPjwvaDI+PGEgY2xhc3M9XCInICsgdGhpcy5lbGVtZW50UHJlZml4ICsgJ19fY2xvc2VcIiBocmVmPVwiI1wiPiZ0aW1lczs8L2E+PGRpdiBjbGFzcz1cIicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19jb250ZW50XCI+PC9kaXY+PC9kaXY+PC9kaXY+Jyk7XHJcblx0XHRcdHRoaXMuZWxlbWVudCA9ICQoICcuJyArIHRoaXMuZWxlbWVudFByZWZpeCApO1xyXG5cdFx0XHR2YXIgZWwgPSB0aGlzO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnQuZmluZCgnLicgKyB0aGlzLmVsZW1lbnRQcmVmaXggKyAnX19jbG9zZScpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0ZWwuaGlkZVBvcHVwKGUpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHRcdHRoaXMuZWxlbWVudC5maW5kKCcuJyArIHRoaXMuZWxlbWVudFByZWZpeCArICdfX2gyJykuaHRtbChvcHRpb25zLnRpdGxlIHx8IHRoaXMuZGVmYXVsdFRpdGxlKTtcclxuXHRcdHRoaXMuZWxlbWVudC5maW5kKCcuJyArIHRoaXMuZWxlbWVudFByZWZpeCArICdfX2NvbnRlbnQnKS5odG1sKG9wdGlvbnMuY29udGVudCB8fCB0aGlzLmRlZmF1bHRDb250ZW50KTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblx0XHJcblx0c2hvd1BvcHVwOiBmdW5jdGlvbiAoKSB7XHJcbiAgICBcdHRoaXMuZWxlbWVudC5hZGRDbGFzcyh0aGlzLmVsZW1lbnRQcmVmaXggKyAnX192aXNpYmxlJyk7XHJcbiAgICBcdHJldHVybiB0aGlzO1xyXG4gICAgfSxcclxuICAgIFxyXG4gICAgaGlkZVBvcHVwOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBcdHRoaXMuZWxlbWVudC5yZW1vdmVDbGFzcyh0aGlzLmVsZW1lbnRQcmVmaXggKyAnX192aXNpYmxlJyk7XHJcbiAgICB9LFxyXG59O1xyXG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBpbWFnZXNMb2FkZWQgPSByZXF1aXJlKCdpbWFnZXNsb2FkZWQnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbmV4cG9ydHMuc3luY0hlaWdodE9mVGlsZXMgPSBzeW5jSGVpZ2h0T2ZUaWxlcztcblxudmFyIHdpbmRvd1dpZHRoO1xuXG5mdW5jdGlvbiBncmlkVmlld1RvZ2dsZSgpIHtcbiAgICAkKCcudG9nZ2xlLWdyaWQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJy5zZWFyY2gtcmVzdWx0LWNvbnRlbnQnKS50b2dnbGVDbGFzcygnd2lkZS10aWxlcycpO1xuICAgICAgICAkKHRoaXMpLnRvZ2dsZUNsYXNzKCd3aWRlJyk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGxpbmUgY2xhbXBpbmcgZm9yIHByb2R1Y3QgdGlsZSBwcm9kdWN0IHRpdGxlcy5cbiAqL1xuXG4gZnVuY3Rpb24gY2xhbXBQcm9kdWN0VGlsZVRpdGxlcygpIHtcbiAgICAkKCdoNi5wcm9kdWN0LW5hbWUgLm5hbWUtbGluaycpLmVhY2goZnVuY3Rpb24oaW5kZXgsIGNsYW1wVGl0bGUpIHtcbiAgICAgICAgJGNsYW1wKGNsYW1wVGl0bGUsIHtcbiAgICAgICAgICAgIGNsYW1wOiAyLFxuICAgICAgICAgICAgdXNlTmF0aXZlQ0xhbXA6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH0pO1xuIH1cbiBcbiBmdW5jdGlvbiBpbml0aWFsaXplU3dhdGNoZXMoKSB7XG5cdCAkKCcuZ3JpZC10aWxlJykuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdCQoZWxlbWVudCkuZmluZCgnLnllcy1hbHRzIHVsLnN3YXRjaC1saXN0IGxpJykuZWFjaChmdW5jdGlvbihpLCBlbGVtKSB7XG5cdFx0XHR2YXIgYWx0RGlzcGxheSA9ICdzaG93LWNvbnRlbnQnO1xuXHRcdFx0aWYgKCBpID49IDQgKXtcblx0XHRcdFx0YWx0RGlzcGxheSA9ICdoaWRkZW4tY29udGVudCc7XG5cdFx0XHR9XG5cdFx0XHQkKGVsZW0pLmFkZENsYXNzKGFsdERpc3BsYXkpO1xuXHRcdH0pO1xuXHRcdHZhciBhbHRIaWRkZW5Db3VudCA9ICQoZWxlbWVudCkuZmluZCgnLmhpZGRlbi1jb250ZW50JykubGVuZ3RoO1xuXHRcdHZhciBhbHRIaWRkZW5Ub2dnbGUgPSAnKyAnICsgYWx0SGlkZGVuQ291bnQ7XG5cdFx0dmFyIGFsdEJ1dHRvbkV4aXN0cyA9ICQoZWxlbWVudCkuZmluZCgnLmFsdEJ1dHRvbicpLmxlbmd0aDtcblx0XHRpZiAoYWx0SGlkZGVuQ291bnQgPiAwKXtcblx0XHRcdCQoZWxlbWVudCkuZmluZCgnLmhpZGRlbi1jb250ZW50JykuaGlkZSgpO1xuXHRcdFx0aWYgKGFsdEJ1dHRvbkV4aXN0cyA9PSAwKXtcblx0XHRcdFx0JChlbGVtZW50KS5maW5kKCcueWVzLWFsdHMgdWwuc3dhdGNoLWxpc3QnKS5hcHBlbmQoJzxidXR0b24gY2xhc3M9XCJhbHRCdXR0b25cIj4nICsgYWx0SGlkZGVuVG9nZ2xlICsgJzwvYnV0dG9uPicpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JChlbGVtZW50KS5maW5kKCcuYWx0QnV0dG9uJykudGV4dChhbHRIaWRkZW5Ub2dnbGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG4gfVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBldmVudHMgb24gdGhlIHByb2R1Y3QtdGlsZSBmb3IgdGhlIGZvbGxvd2luZyBlbGVtZW50czpcbiAqIC0gc3dhdGNoZXNcbiAqIC0gdGh1bWJuYWlsc1xuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgIGdyaWRWaWV3VG9nZ2xlKCk7XG4gICAgaW5pdGlhbGl6ZVN3YXRjaGVzKCk7XG4gICAgXG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG4gICAgXHQkKCcjc2VhcmNoLXJlc3VsdC1pdGVtcyAuZ3JpZC10aWxlJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICBcdFx0dmFyICRncmlkSXRlbSA9ICQodGhpcyksXG4gICAgXHRcdFx0JHByaW1hcnlDb2xvciA9ICRncmlkSXRlbS5kYXRhKCdwcmltYXJ5LWNvbG9yJyksXG4gICAgXHRcdFx0JHRodW1iID0gJGdyaWRJdGVtLmZpbmQoJy5wcm9kdWN0LWltYWdlIC50aHVtYi1saW5rIGltZycpLmVxKDApLFxuICAgIFx0XHRcdCR0aHVtYmxpbmsgPSAkZ3JpZEl0ZW0uZmluZCgnLnByb2R1Y3QtaW1hZ2UgYS50aHVtYi1saW5rJykuZXEoMCksXG4gICAgXHRcdFx0JG5hbWVsaW5rID0gJGdyaWRJdGVtLmZpbmQoJy5wcm9kdWN0LWNvbnRlbnQgLnByb2R1Y3QtbmFtZSBhLm5hbWUtbGluaycpLmVxKDApO1xuICAgIFx0XHQkZ3JpZEl0ZW0uZmluZCgnLnByb2R1Y3QtY29udGVudCAucHJvZHVjdC1zd2F0Y2hlcyAuc3dhdGNoLWxpc3QgbGknKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgIFx0XHRcdHZhciAkY3VycnN3YXRjaCA9ICQodGhpcyksXG4gICAgXHRcdFx0XHQkY3VycmhyZWYgPSAkY3VycnN3YXRjaC5maW5kKCdhLnN3YXRjaCcpLmF0dHIoJ2hyZWYnKSxcbiAgICBcdFx0XHRcdCRjdXJyY29sb3IgPSAkY3VycnN3YXRjaC5kYXRhKCdjb2xvcicpO1xuICAgIFx0XHRcdGlmICgkcHJpbWFyeUNvbG9yID09ICRjdXJyY29sb3IpIHtcbiAgICBcdFx0XHRcdHZhciAkZGF0YSA9ICRjdXJyc3dhdGNoLmZpbmQoJy5zd2F0Y2gtaW1hZ2UnKS5kYXRhKCd0aHVtYicpO1xuICAgIFx0XHRcdFx0XG4gICAgXHRcdFx0XHRpZiAoJHRodW1ibGluay5hdHRyKCdzZWxlY3RlZC1sb2NhdGlvbnMnKSkge1xuICAgIFx0XHRcdFx0XHQkY3VycmhyZWYgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoJGN1cnJocmVmLCAnc2VsZWN0ZWRMb2NhdGlvbnMnLCAkdGh1bWJsaW5rLmF0dHIoJ3NlbGVjdGVkLWxvY2F0aW9ucycpKTtcbiAgICBcdFx0XHRcdH1cbiAgICBcdFx0XHRcdFxuICAgIFx0XHRcdFx0JG5hbWVsaW5rLmF0dHIoJ2hyZWYnLCAkY3VycmhyZWYpO1xuICAgIFx0XHRcdFx0JHRodW1ibGluay5hdHRyKCdocmVmJywgJGN1cnJocmVmKTtcbiAgICBcdFx0XHRcdFxuXHRcdFx0XHRcdGlmICgkZGF0YSkge1xuXHRcdFx0XHRcdFx0JHRodW1iLmF0dHIoe1xuXHRcdFx0XHRcdFx0XHRzcmM6ICRkYXRhLnNyYyxcblx0XHRcdFx0XHRcdFx0YWx0OiAkZGF0YS5hbHQsXG5cdFx0XHRcdFx0XHRcdHRpdGxlOiAkZGF0YS50aXRsZVxuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuICAgIFx0XHRcdH1cbiAgICBcdFx0fSlcbiAgICBcdH0pO1xuXG5cdFx0JCh3aW5kb3cpLm9mZignbG9hZC5Qcm9kdWN0VGlsZSByZXNpemUuUHJvZHVjdFRpbGUnKS5vbignbG9hZC5Qcm9kdWN0VGlsZSByZXNpemUuUHJvZHVjdFRpbGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAod2luZG93V2lkdGggIT0gJCh3aW5kb3cpLndpZHRoKCkpIHtcblx0XHRcdCAgICBzeW5jSGVpZ2h0T2ZUaWxlcygpO1xuICAgICAgICAgICAgfVxuXHRcdH0pO1xuXG5cdFx0aW1hZ2VzTG9hZGVkKCQoJyNzZWFyY2gtcmVzdWx0LWl0ZW1zIC5ncmlkLXRpbGUnKSkub24oJ2RvbmUnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRzeW5jSGVpZ2h0T2ZUaWxlcygpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICBcblx0JCgnLnN3YXRjaC1saXN0IC5zd2F0Y2gnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIC8vIGdldCBjdXJyZW50IHRodW1iIGRldGFpbHNcbiAgICAgICAgdmFyICR0aWxlID0gJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyksXG4gICAgICAgICAgICAkdGh1bWIgPSAkdGlsZS5maW5kKCcucHJvZHVjdC1pbWFnZSAudGh1bWItbGluayBpbWcnKS5lcSgwKSxcbiAgICAgICAgICAgIGRhdGEgPSAkKHRoaXMpLmNoaWxkcmVuKCcuc3dhdGNoLWltYWdlJykuZmlsdGVyKCc6Zmlyc3QnKS5kYXRhKCd0aHVtYicpLFxuICAgICAgICAgICAgY3VycmVudCA9ICR0aHVtYi5kYXRhKCdjdXJyZW50Jyk7XG5cbiAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3QgdGltZSwgdGhlbiByZWNvcmQgdGhlIGN1cnJlbnQgaW1nXG4gICAgICAgIGlmICghY3VycmVudCkge1xuICAgICAgICAgICAgJHRodW1iLmRhdGEoJ2N1cnJlbnQnLCB7XG4gICAgICAgICAgICAgICAgc3JjOiAkdGh1bWJbMF0uc3JjLFxuICAgICAgICAgICAgICAgIGFsdDogJHRodW1iWzBdLmFsdCxcbiAgICAgICAgICAgICAgICB0aXRsZTogJHRodW1iWzBdLnRpdGxlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB0aGUgdGlsZSBpbWFnZSB0byB0aGUgdmFsdWVzIHByb3ZpZGVkIG9uIHRoZSBzd2F0Y2ggZGF0YSBhdHRyaWJ1dGVzXG5cdFx0aWYgKGRhdGEpIHtcblx0XHRcdCR0aHVtYi5hdHRyKHtcblx0XHRcdFx0c3JjOiBkYXRhLnNyYyxcblx0XHRcdFx0YWx0OiBkYXRhLmFsdCxcblx0XHRcdFx0dGl0bGU6IGRhdGEudGl0bGVcblx0XHRcdH0pO1xuXHRcdH1cbiAgICB9KTtcblx0XG4gICAgLy8gY2hlY2sgZXZlcnkgMiBzZWNzIGlmIEJWIHN0YXJzIGhhcyBhbHJlYWR5IGxvYWRlZFxuICAgIC8vIGluIGNhc2UgQlYgaXMganVzdCBkZWxheWVkIGluIHNob3dpbmcgdXAsIHdlIG5lZWQgdG8gY2hlY2sgdGhlIGludGVydmFsIGZvciBhdCBsZWFzdCA1eCB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BcbiAgICB2YXIgaGlkZVN0YXJzID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtcbiAgICBcdHZhciBjdHIgPSAwO1xuICAgIFx0JChcImRpdltpZF49QlZSUklubGluZVJhdGluZ11cIikuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgXHRcdGlmICgkKHRoaXMpLmZpbmQoXCIuYnYtcmF0aW5nLXN0YXJzLW9uXCIpLndpZHRoKCkgPiAwKSB7IH0gZWxzZSB7ICQodGhpcykuZmluZChcIi5idi1zdGFycy1jb250YWluZXJcIikuYXR0cihcInN0eWxlXCIsIFwiZGlzcGxheTpub25lICFpbXBvcnRhbnRcIik7IH1cbiAgICBcdFx0aWYgKCQodGhpcykuZmluZChcIi5idi1yYXRpbmctc3RhcnMtb25cIikubGVuZ3RoKSB7XG4gICAgXHRcdFx0Y2xlYXJJbnRlcnZhbChoaWRlU3RhcnMpO1xuICAgIFx0XHR9IGVsc2UgeyBjdHIrKztcdH1cbiAgICBcdH0pO1xuICAgIFx0aWYgKGN0cj4xMCkgeyBjbGVhckludGVydmFsKGhpZGVTdGFycyk7IH0gLy93ZSBuZWVkIHRvIHN0b3AgdGhlIGZ1bmN0aW9uIGlmIEJWIGlzIG5vdCBjb25maWd1cmVkLlxuICAgIH0sIDIwMDApO1xuXG4gICAgdmFyIGF0dGVtcHRzVG9DaGFuZ2VUZXh0ID0gMDtcbiAgICB2YXIgYWRkVGV4dFJldmlld3NUb0NvdW50UmV2aWV3cyA9IHNldEludGVydmFsKGZ1bmN0aW9uKCl7XG4gICAgXHRhdHRlbXB0c1RvQ2hhbmdlVGV4dCsrO1xuICAgIFx0JCgnZGl2W2lkXj1CVlJSSW5saW5lUmF0aW5nXScpLmVhY2goZnVuY3Rpb24oKXtcbiAgICBcdFx0dmFyICRyYXRpbmcgPSAkKHRoaXMpLmZpbmQoJ3NwYW4uYnYtcmF0aW5nLWxhYmVsJyk7XG4gICAgXHRcdGlmICgkcmF0aW5nLmxlbmd0aCkge1xuICAgIFx0XHRcdHZhciB0ZXh0ID0gJHJhdGluZy5odG1sKCk7XG4gICAgICAgIFx0XHRpZiAodGV4dC5pbmRleE9mKFJlc291cmNlcy5SRVZJRVdTKSA8IDApIHtcbiAgICAgICAgXHRcdFx0JHJhdGluZy5odG1sKHRleHQucmVwbGFjZSgnKScsICcgJyArIFJlc291cmNlcy5SRVZJRVdTICsgJyknKSk7XG4gICAgICAgIFx0XHRcdGNsZWFySW50ZXJ2YWwoYWRkVGV4dFJldmlld3NUb0NvdW50UmV2aWV3cyk7XG4gICAgICAgIFx0XHR9XG4gICAgXHRcdH1cbiAgICBcdH0pO1xuICAgIFx0aWYgKGF0dGVtcHRzVG9DaGFuZ2VUZXh0ID4gMTUpIHtcbiAgICBcdFx0Y2xlYXJJbnRlcnZhbChhZGRUZXh0UmV2aWV3c1RvQ291bnRSZXZpZXdzKTtcbiAgICBcdH1cbiAgICB9LCA1MDApO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsICdkaXYuYnYtY29tcGF0JywgZnVuY3Rpb24oKXtcbiAgICAgICAgdmFyICR0aWxlQmxvY2sgPSAkKHRoaXMpLmNsb3Nlc3QoJ2Rpdi5wcm9kdWN0LXRpbGUnKTtcbiAgICAgICAgaWYgKCR0aWxlQmxvY2spIHtcbiAgICAgICAgICAgIGxvY2F0aW9uLmhyZWYgPSAkdGlsZUJsb2NrLmZpbmQoJ2EudGh1bWItbGluaycpLmF0dHIoJ2hyZWYnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgY2xhbXBQcm9kdWN0VGlsZVRpdGxlcygpO1xufVxuXG5mdW5jdGlvbiBzeW5jSGVpZ2h0T2ZUaWxlcygpIHtcblx0dmFyICR0aWxlcyA9ICQoJy50aWxlcy1jb250YWluZXIgLnByb2R1Y3QtdGlsZScpO1xuICAgIGlmICgkdGlsZXMubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuXG5cdCR0aWxlcy5maW5kKCcucHJvZHVjdC1pbWFnZSAudGh1bWItbGluaycpLnN5bmNIZWlnaHRUb0F2ZXJhZ2UoKTtcblx0JHRpbGVzLmVhY2goZnVuY3Rpb24gKGlkeCkge1xuXHRcdCQodGhpcykuZGF0YSgnaWR4JywgaWR4KTtcblx0fSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB3aW5kb3dXaWR0aCA9ICQod2luZG93KS53aWR0aCgpO1xuXG4gICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG5cdFxyXG5cdGluaXQ6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRpZiAoJCgnLnJvdGF0ZS0zZF9faW1nJykubGVuZ3RoKSB7XHJcblx0XHRcdCQoJy5yb3RhdGUtM2RfX2NvbnRhaW5lcicpLnByZXBlbmQoJzxhIGhyZWY9XCIjXCIgY2xhc3M9XCJyb3RhdGUtM2RfX3JvdGF0ZSByb3RhdGUtM2RfX3JvdGF0ZUxlZnRcIj4mbmJzcDs8L2E+PGEgaHJlZj1cIiNcIiBjbGFzcz1cInJvdGF0ZS0zZF9fcm90YXRlIHJvdGF0ZS0zZF9fcm90YXRlUmlnaHRcIj4mbmJzcDs8L2E+Jyk7XHJcblx0XHRcdCQoJy5yb3RhdGUtM2RfX3JvdGF0ZUxlZnQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHQkKCcucm90YXRlLTNkX19pbWcnKS50cmlnZ2VyKFwic3RlcExlZnRcIik7XHJcblx0XHRcdH0pO1xyXG5cdFx0XHQkKCcucm90YXRlLTNkX19yb3RhdGVSaWdodCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdCQoJy5yb3RhdGUtM2RfX2ltZycpLnRyaWdnZXIoXCJzdGVwUmlnaHRcIik7XHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcbn07XHJcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyICRsb2FkZXI7XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gU2hvd3MgYW4gQUpBWC1sb2FkZXIgb24gdG9wIG9mIGEgZ2l2ZW4gY29udGFpbmVyXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRhaW5lciBUaGUgRWxlbWVudCBvbiB0b3Agb2Ygd2hpY2ggdGhlIEFKQVgtTG9hZGVyIHdpbGwgYmUgc2hvd25cbiAqL1xudmFyIHNob3cgPSBmdW5jdGlvbiAoY29udGFpbmVyLCBkaXNwbGF5SW5MaW5lKSB7XG4gICAgdmFyIHRhcmdldCA9ICghY29udGFpbmVyIHx8ICQoY29udGFpbmVyKS5sZW5ndGggPT09IDApID8gJCgnYm9keScpIDogJChjb250YWluZXIpO1xuICAgICRsb2FkZXIgPSAkbG9hZGVyIHx8ICQoJy5sb2FkZXInKTtcblxuICAgIGlmICgkbG9hZGVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAkbG9hZGVyID0gJCgnPGRpdi8+JykuYWRkQ2xhc3MoJ2xvYWRlcicpXG4gICAgICAgICAgICAuYXBwZW5kKCQoJzxkaXYvPicpLmFkZENsYXNzKCdsb2FkZXItaW5kaWNhdG9yJyksICQoJzxkaXYvPicpLmFkZENsYXNzKCdsb2FkZXItYmcnKSk7XG4gICAgfVxuXG4gICAgaWYgKGRpc3BsYXlJbkxpbmUpIHtcbiAgICAgICAgJGxvYWRlci5jc3MoJ2Rpc3BsYXknLCAnaW5saW5lLWJsb2NrJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJGxvYWRlci5jc3MoJ2Rpc3BsYXknLCAnYmxvY2snKTtcbiAgICB9XG4gICAgcmV0dXJuICRsb2FkZXIuYXBwZW5kVG8odGFyZ2V0KTtcbn07XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEhpZGVzIGFuIEFKQVgtbG9hZGVyXG4gKi9cbnZhciBoaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICgkbG9hZGVyKSB7XG4gICAgICAgICRsb2FkZXIuaGlkZSgpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuc2hvdyA9IHNob3c7XG5leHBvcnRzLmhpZGUgPSBoaWRlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpO1xudmFyIERhdGFMYXllckNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvRGF0YUxheWVyQ29uc3RhbnRzJyk7XG52YXIgR29vZ2xlVGFnTWFuYWdlckNsaWVudCA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvdXRpbC9Hb29nbGVUYWdNYW5hZ2VyQ2xpZW50Jyk7XG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG52YXIgaXNDaGVja291dCwgaXNFY2hvQ2FydCwgZm5VcGRhdGVDYXJ0LCBmblJlbmRlckNhcnQsICRmb2N1c2VkRWxlbWVudDtcbnZhciBsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MgPSB7XG4gICAgSXNMYWJlbFNob3duOiBmYWxzZSxcbiAgICBDc3NDbGFzczogJ2Z1bGxzY3JlZW4nLFxuICAgIEJhY2tncm91bmRDb2xvcjogJ3RyYW5zcGFyZW50J1xufTtcblxuZnVuY3Rpb24gdXBkYXRlU3RlcHBlclF0eVVJKCR0aGlzLCBpbmNyZW1lbnQpIHtcblx0dmFyICRxdWFudGl0eVN0ZXBwZXIgPSBpbmNyZW1lbnQgIT0gdW5kZWZpbmVkID8gJHRoaXMucGFyZW50KCcucXVhbnRpdHktc3RlcHBlcicpIDogJHRoaXM7XG5cdHZhciAkaW5wdXQgPSAkcXVhbnRpdHlTdGVwcGVyLmZpbmQoJ2lucHV0LmlucHV0LXRleHQnKTtcblx0dmFyIHF1YW50aXR5ID0gcGFyc2VJbnQoJGlucHV0LnZhbCgpKTtcblx0Ly8gT25seSBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IHF1YW50aXR5IGlmIGEgYm9vbGVhbiB3YXMgcGFzc2VkIGludG8gdGhlIGZ1bmN0aW9uXG5cdGlmIChpbmNyZW1lbnQgIT0gdW5kZWZpbmVkKSB7XG5cdFx0aW5jcmVtZW50ID8gcXVhbnRpdHkrKyA6IHF1YW50aXR5LS07XG5cdH1cblx0XG5cdC8vIEVuYWJsZSBvciBEaXNhYmxlIHRoZSBwbHVzL21pbnVzIHNpZ25zIG9uIHRoZSBxdWFudGl0eSBzdGVwcGVyXG5cdHZhciAkaW5jQnV0dG9uID0gJHF1YW50aXR5U3RlcHBlci5maW5kKCdidXR0b24uaW5jcmVhc2UucGx1cycpO1xuXHR2YXIgJGRlY0J1dHRvbiA9ICRxdWFudGl0eVN0ZXBwZXIuZmluZCgnYnV0dG9uLmRlY3JlYXNlLm1pbnVzJyk7XG5cblx0aWYgKHF1YW50aXR5IDw9IDEpIHtcblx0XHQkZGVjQnV0dG9uLmFkZENsYXNzKCdkaXNhYmxlZCcpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG5cdFx0JGluY0J1dHRvbi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuXHR9IGVsc2UgaWYgKHF1YW50aXR5ID4gMSkge1xuXHRcdCRkZWNCdXR0b24ucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblx0XHQkaW5jQnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG5cdH1cblxuXHQvLyBVcGRhdGUgdGhlIHZhbHVlIG9mIHRoZSBxdWFudGl0eSBzdGVwcGVyXG5cdCRpbnB1dC5hdHRyKCdxdWFudGl0eS1idWZmZXInLCBxdWFudGl0eSk7XG5cdCRpbnB1dC52YWwocXVhbnRpdHkpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVNaW5pQ2FydFVJKGluY3JlbWVudCwgJGxpbmVJdGVtKSB7XG5cdHZhciAkbWluaUNhcnRFbG0gPSAkKCcubWluaS1jYXJ0IC5taW5pY2FydC1xdWFudGl0eScpLmxlbmd0aCA+IDAgPyAkKCcubWluaS1jYXJ0IC5taW5pY2FydC1xdWFudGl0eScpIDogJCgnLm1pbmktY2FydCAuYnRuLW1pbmljYXJ0IC5idG4tbWluaWNhcnQtcXR5Jyk7XG5cdHZhciBtaW5pQ2FydFRvdGFsO1xuXHRpZiAoJG1pbmlDYXJ0RWxtLmxlbmd0aCA+IDApIHtcblx0XHRtaW5pQ2FydFRvdGFsID0gcGFyc2VJbnQoJG1pbmlDYXJ0RWxtLmh0bWwoKS50cmltKCkpO1xuXHR9XG5cblx0aWYgKChpbmNyZW1lbnQgIT0gbnVsbCAmJiB0eXBlb2YgaW5jcmVtZW50ID09PSBcImJvb2xlYW5cIikgJiYgISRsaW5lSXRlbSkge1xuXHRcdGluY3JlbWVudCA/IG1pbmlDYXJ0VG90YWwrKyA6IG1pbmlDYXJ0VG90YWwtLTtcblx0fSBlbHNlIGlmICgoaW5jcmVtZW50ID09IG51bGwgfHwgdHlwZW9mIGluY3JlbWVudCAhPSBcImJvb2xlYW5cIikgJiYgJGxpbmVJdGVtKSB7XG5cdFx0dmFyIGl0ZW1RdHkgPSBwYXJzZUludCgkbGluZUl0ZW0uZmluZCgnLm9wYy1xdHknKS52YWwoKSk7XG5cdFx0bWluaUNhcnRUb3RhbCA9IGl0ZW1RdHkgJiYgdHlwZW9mIGl0ZW1RdHkgPT0gJ251bWJlcicgJiYgaXRlbVF0eSA+IDAgPyBtaW5pQ2FydFRvdGFsIC0gaXRlbVF0eSA6IG1pbmlDYXJ0VG90YWw7XG5cdFx0JGxpbmVJdGVtLnJlbW92ZSgpO1xuXHR9XG5cdFxuXHQvLyBVcGRhdGUgdGhlIGJhc2tldCBxdWFudGl0eSBvbiB0aGUgbWFpbiBuYXZpZ2F0aW9uIGJhciA+IG1pbmljYXJ0IGljb25cblx0bWluaUNhcnRUb3RhbCA+PSAxID8gJG1pbmlDYXJ0RWxtLmh0bWwobWluaUNhcnRUb3RhbCkgOiAkbWluaUNhcnRFbG0uaHRtbCgwKTtcblxuXHQvLyBVcGRhdGUgdGhlIG1pbmljYXJ0IG1vZGFsLCBpZiBpdCdzIGN1cnJlbnRseSBvcGVuXG5cdGlmICgkKCcuYWRkLXRvLWNhcnQtbW9kYWwnKS5sZW5ndGggPiAwKSB7XG5cdFx0dmFyIHByb2R1Y3RSZWNvbW1lbmRhdGlvbnNIdG1sID0gJCgnLmFkZC10by1jYXJ0LW1vZGFsICAubWFpbi1jb250ZW50IC5wcm9kdWN0LXJlY29tbWVuZGF0aW9ucy1jb250YWluZXInKS5odG1sKCk7XG5cdFx0JC5hamF4KHt1cmwgOiBVcmxzLmFkZFRvQ2FydE1vZGFsRGlzcGxheSwgZGF0YVR5cGU6ICdodG1sJywgc3VjY2VzcyA6IGZ1bmN0aW9uKG1vZGFsQ29udGVudCkge1xuXHRcdFx0aWYgKG1vZGFsQ29udGVudC5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbCAudWktZGlhbG9nLWNvbnRlbnQnKS5odG1sKG1vZGFsQ29udGVudCk7XG5cdFx0XHRcdCQoJy5hZGQtdG8tY2FydC1tb2RhbC1jb250ZW50IC5tYWluLWNvbnRlbnQgLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zLWNvbnRhaW5lcicpLmFwcGVuZChwcm9kdWN0UmVjb21tZW5kYXRpb25zSHRtbCk7XG5cdFx0XHRcdC8vIFJlZmVyZW5jZSBhZGRUb0NhcnQuanMgPiBhZGRJdGVtVG9DYXJ0KCkgPiBsaW5lIDMxNCAoTW92ZSB0aXRsZSBmcm9tIG1haW4gY29udGVudCB0byB0b3Agb2YgdGhlIG1vZGFsKVxuXHRcdFx0XHRpZiAoJCgnLmFkZC10by1jYXJ0LW1vZGFsLWNvbnRlbnQnKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0dmFyICRhZGRNZXNzYWdlID0gJCgnLmFkZC10by1jYXJ0LW1vZGFsLWNvbnRlbnQgLm1haW4tY29udGVudCAuYWRkZWQtbWVzc2FnZScpO1xuXHRcdFx0XHRcdC8vIFJlZmVyZW5jZSBhZGRUb0NhcnQuanMgPiBhZGRJdGVtVG9DYXJ0KCkgPiBsaW5lIDM3NyAoSW5zZXJ0cyB0aGUgd29yZCAnSXRlbScgaW50byB0aGUgbWluaWNhcnQgdGl0bGUpXG5cdFx0XHRcdFx0JCgnLmFkZC10by1jYXJ0LW1vZGFsLWNvbnRlbnQgLmFkZGVkLW1lc3NhZ2UgLmNvdW50JykudGV4dCgnSXRlbScpO1xuXHRcdFx0XHRcdGlmICgkYWRkTWVzc2FnZS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHQkKCcuYWRkLXRvLWNhcnQtbW9kYWwtY29udGVudCcpLnByZXBlbmQoJGFkZE1lc3NhZ2UpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH19KTtcblx0fVxufVxuXG5mdW5jdGlvbiB1cGRhdGVDYXJ0VG90YWxzKCkge1xuXHRpZiAoaXNDaGVja291dCAmJiBmblVwZGF0ZUNhcnQpIHtcblx0XHRmblVwZGF0ZUNhcnQoJCgnLnVwZGF0ZS1jYXJ0LWJ1dHRvbicpLmF0dHIoJ25hbWUnKSk7XG5cdH1cblx0aWYgKGlzRWNob0NhcnQgJiYgZm5SZW5kZXJDYXJ0KSB7XG5cdFx0Zm5SZW5kZXJDYXJ0KCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlRnJvbUNhcnREYXRhTGF5ZXIoJHRoaXMpIHtcblx0dmFyICRpdGVtID0gJHRoaXMuY2xvc2VzdCgnW2RhdGEtdXVpZF0nKTtcblx0aWYgKCRpdGVtKSB7XG5cdFx0dmFyIHByb2R1Y3REYXRhRm9yVW5pdmVyc2FsQW5hbHl0aWNzID0gSlNPTi5wYXJzZSgkaXRlbS5maW5kKCdbZGF0YS1wcm9kdWN0LWd0bS1qc29uXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpKTtcblx0XHR2YXIgcHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0ID0gSlNPTi5wYXJzZSgkaXRlbS5maW5kKCdbZGF0YS1wcm9kdWN0LWdhNC1qc29uXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicpKTtcblxuXHRcdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFx0VW5pdmVyc2FsQW5hbHl0aWNzOiB7XG5cdFx0XHRcdGVjb21tZXJjZToge1xuXHRcdFx0XHRcdHJlbW92ZToge1xuXHRcdFx0XHRcdFx0cHJvZHVjdHM6IFtwcm9kdWN0RGF0YUZvclVuaXZlcnNhbEFuYWx5dGljc11cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXHRcdFx0XHRcdFx0XHRcblx0XHRcdEdvb2dsZUFuYWx5dGljczQ6IHtcblx0XHRcdFx0dmFsdWU6IHByb2R1Y3REYXRhRm9yR29vZ2xlQW5hbHl0aWNzNC5wcmljZSxcblx0XHRcdFx0aXRlbXM6IFtwcm9kdWN0RGF0YUZvckdvb2dsZUFuYWx5dGljczRdXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0R29vZ2xlVGFnTWFuYWdlckNsaWVudC5QdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZSgnUmVtb3ZlRnJvbUNhcnQnLCBkYXRhT2JqZWN0KTtcblx0fVxufVxuXG5mdW5jdGlvbiBxdWFudGl0eURhdGFsYXllckV2ZW50cygkdGhpcywgZXZlbnRUeXBlLCBxdWFudGl0eSkge1xuXHR2YXIgJGl0ZW0gPSAkdGhpcy5jbG9zZXN0KCdbZGF0YS11dWlkXScpO1xuXG5cdHZhciBldmVudE5hbWU7XG5cdHZhciBlY29tbWVyY2VLZXk7XG5cdGlmIChldmVudFR5cGUgPT0gRGF0YUxheWVyQ29uc3RhbnRzLkV2ZW50VHlwZXMuTWludXMpIHtcblx0XHRldmVudE5hbWUgPSBEYXRhTGF5ZXJDb25zdGFudHMuRXZlbnRzLkNhcnQuUmVtb3ZlRnJvbUNhcnQuTmFtZTtcblx0XHRlY29tbWVyY2VLZXkgPSAncmVtb3ZlJztcblx0fSBlbHNlIHtcblx0XHRldmVudE5hbWUgPSBEYXRhTGF5ZXJDb25zdGFudHMuRXZlbnRzLkNhcnQuQWRkVG9DYXJ0Lk5hbWU7XG5cdFx0ZWNvbW1lcmNlS2V5ID0gJ2FkZCc7XG5cdH0gXG5cdFxuXHR2YXIgcHJvZHVjdERhdGFGb3JVbml2ZXJzYWxBbmFseXRpY3MgPSBKU09OLnBhcnNlKCRpdGVtLmZpbmQoJ1tkYXRhLXByb2R1Y3QtZ3RtLWpzb25dJykuYXR0cignZGF0YS1wcm9kdWN0LWd0bS1qc29uJykpO1xuXHR2YXIgcHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0ID0gSlNPTi5wYXJzZSgkaXRlbS5maW5kKCdbZGF0YS1wcm9kdWN0LWdhNC1qc29uXScpLmF0dHIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicpKTtcblx0aWYgKHF1YW50aXR5KSB7XG5cdFx0cHJvZHVjdERhdGFGb3JVbml2ZXJzYWxBbmFseXRpY3MucXVhbnRpdHkgPSBxdWFudGl0eTtcblx0XHRwcm9kdWN0RGF0YUZvckdvb2dsZUFuYWx5dGljczQucXVhbnRpdHkgPSBxdWFudGl0eTtcblx0fVxuXG5cdHZhciBkYXRhT2JqZWN0ID0ge1xuXHRcdFVuaXZlcnNhbEFuYWx5dGljczoge1xuXHRcdFx0ZWNvbW1lcmNlOiB7fVxuXHRcdH0sXHRcdFx0XHRcdFx0XHRcblx0XHRHb29nbGVBbmFseXRpY3M0OiB7XG5cdFx0XHR2YWx1ZTogcHJvZHVjdERhdGFGb3JHb29nbGVBbmFseXRpY3M0LnByaWNlLFxuXHRcdFx0aXRlbXM6IFtwcm9kdWN0RGF0YUZvckdvb2dsZUFuYWx5dGljczRdXG5cdFx0fVxuXHR9XG5cblx0ZGF0YU9iamVjdC5Vbml2ZXJzYWxBbmFseXRpY3MuZWNvbW1lcmNlW2Vjb21tZXJjZUtleV0gPSB7XG5cdFx0cHJvZHVjdHM6IFtwcm9kdWN0RGF0YUZvclVuaXZlcnNhbEFuYWx5dGljc11cblx0fVxuXG5cdEdvb2dsZVRhZ01hbmFnZXJDbGllbnQuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUoZXZlbnROYW1lLCBkYXRhT2JqZWN0KTtcbn1cblxuZnVuY3Rpb24gcXVhbnRpdHlDaGFuZ2VFdmVudHMoJHRoaXMsIHF1YW50aXR5LCBpbmNyZW1lbnQpIHtcblx0dmFyIGV2ZW50VHlwZSA9IGluY3JlbWVudCA/IERhdGFMYXllckNvbnN0YW50cy5FdmVudFR5cGVzLlBsdXMgOiBEYXRhTGF5ZXJDb25zdGFudHMuRXZlbnRUeXBlcy5NaW51cztcblx0cXVhbnRpdHlEYXRhbGF5ZXJFdmVudHMoJHRoaXMsIGV2ZW50VHlwZSwgcXVhbnRpdHkpO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplKHVwZGF0ZUNhcnQsIHJlbmRlckNhcnQpIHtcblx0aXNDaGVja291dCA9IChwYWdlQ29udGV4dCAmJiBwYWdlQ29udGV4dC50eXBlID09ICdjYXJ0JyB8fCBwYWdlQ29udGV4dC50eXBlID09ICdvbmVwY2hlY2tvdXQnIHx8IHBhZ2VDb250ZXh0LnR5cGUgPT0gJ29uZXBjaGVja291dF9ncm91cHMnKSB8fCAocGFnZS5ucyAmJiBwYWdlLm5zID09ICdjYXJ0JyB8fCBwYWdlLm5zID09ICdvbmVwY2hlY2tvdXQnIHx8IHBhZ2UubnMgPT0gJ29uZXBjaGVja291dF9ncm91cHMnKTtcblx0aXNFY2hvQ2FydCA9IChwYWdlQ29udGV4dCAmJiAndHlwZScgaW4gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQudHlwZSA9PSAnY2FydF9lY2hvJykgfHwgKHBhZ2UubnMgJiYgcGFnZS5ucyA9PSAnY2FydF9lY2hvJyk7XG5cdGZuVXBkYXRlQ2FydCA9IHVwZGF0ZUNhcnQgJiYgdHlwZW9mIHVwZGF0ZUNhcnQgPT09ICdmdW5jdGlvbicgPyB1cGRhdGVDYXJ0IDogbnVsbDtcblx0Zm5SZW5kZXJDYXJ0ID0gcmVuZGVyQ2FydCAmJiB0eXBlb2YgcmVuZGVyQ2FydCA9PT0gJ2Z1bmN0aW9uJyA/IHJlbmRlckNhcnQgOiBudWxsO1xuXG5cdC8vIFJlbW92ZSBCdXR0b25cblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5RdWFudGl0eVN0ZXBwZXIuUHJvZHVjdFJlbW92ZScpLm9uKCdjbGljay5RdWFudGl0eVN0ZXBwZXIuUHJvZHVjdFJlbW92ZScsICcucXVhbnRpdHktc3RlcHBlci1yZW1vdmUgLnJlbW92ZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdHZhciAkaXRlbVJvdyA9ICR0aGlzLmNsb3Nlc3QoJ1tkYXRhLXV1aWRdJyk7XG5cdFx0dmFyIGlzTWluaUNhcnQgPSAkaXRlbVJvdy5hdHRyKCdjbGFzcycpLmluZGV4T2YoJ21pbmktY2FydCcpID4gLTE7XG5cdFx0JCgnYm9keScpLmxvYWRpbmcobG9hZGluZ0luZGljYXRvclNldHRpbmdzKTtcblxuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuQ2FydC5SZW1vdmVQcm9kdWN0LFxuXHRcdFx0Y29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcblx0XHRcdGRhdGE6IEpTT04uc3RyaW5naWZ5KHtcblx0XHRcdFx0UHJvZHVjdExpbmVJdGVtVVVJRDogJGl0ZW1Sb3cuZGF0YSgndXVpZCcpLFxuXHRcdFx0fSksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR1cGRhdGVDYXJ0VG90YWxzKCk7XG5cdFx0XHRcdGlmIChpc01pbmlDYXJ0KSB7XG5cdFx0XHRcdFx0dXBkYXRlTWluaUNhcnRVSShudWxsLCAkaXRlbVJvdyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVtb3ZlRnJvbUNhcnREYXRhTGF5ZXIoJHRoaXMpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblxuXHQvLyBQbHVzL01pbnVzIFF0eSBCdXR0b25zXG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2suUXVhbnRpdHlTdGVwcGVyLlF1YW50aXR5Q2hhbmdlJywgJy5xdWFudGl0eS1zdGVwcGVyIGJ1dHRvbjpub3QoXCIuZGlzYWJsZWRcIiknKS5vbignY2xpY2suUXVhbnRpdHlTdGVwcGVyLlF1YW50aXR5Q2hhbmdlJywgJy5xdWFudGl0eS1zdGVwcGVyIGJ1dHRvbjpub3QoXCIuZGlzYWJsZWRcIiknLCBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0dmFyICRzdGVwcGVyQnV0dG9uID0gJCh0aGlzKTtcblx0XHR2YXIgaXNJbmNyZW1lbnQgPSAkc3RlcHBlckJ1dHRvbi5oYXNDbGFzcygnaW5jcmVhc2UnKTtcblx0XHR2YXIgY2FydFF0eVVybCA9IGlzSW5jcmVtZW50ID8gVXJscy5DYXJ0LkFkZFByb2R1Y3RRdWFudGl0eSA6IFVybHMuQ2FydC5SZW1vdmVQcm9kdWN0UXVhbnRpdHk7XG5cblx0XHQkZm9jdXNlZEVsZW1lbnQgPSAkc3RlcHBlckJ1dHRvbjtcblx0XHQkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuXHRcdCQuYWpheCh7XG5cdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHR1cmw6IGNhcnRRdHlVcmwsXG5cdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuXHRcdFx0XHRQcm9kdWN0TGluZUl0ZW1VVUlEOiAkKHRoaXMpLmNsb3Nlc3QoJ1tkYXRhLXV1aWRdJykuZGF0YSgndXVpZCcpLFxuXHRcdFx0XHRRdWFudGl0eTogMVxuXHRcdFx0fSksXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0Y29tcGxldGU6IGZ1bmN0aW9uKHhocikge1xuXHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHR1cGRhdGVTdGVwcGVyUXR5VUkoJHN0ZXBwZXJCdXR0b24sIGlzSW5jcmVtZW50KTtcblx0XHRcdFx0dXBkYXRlTWluaUNhcnRVSShpc0luY3JlbWVudCk7XG5cdFx0XHRcdHVwZGF0ZUNhcnRUb3RhbHMoKTtcblx0XHRcdFx0cXVhbnRpdHlDaGFuZ2VFdmVudHMoJHN0ZXBwZXJCdXR0b24sIDEsIGlzSW5jcmVtZW50KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cblx0Ly8gT24gY2hhbmdlIG9mIHByb2R1Y3QgcXR5IGluIENhcnQsIGNoZWNrIHRoZSBVSSB2YWx1ZSBvZiBRdWFudGl0eSBTdGVwcGVyLCBhbmQgbWFrZSBxdHkgPSAxIGlmIHZhbHVlIGlzbid0IHZhbGlkXG5cdCQoZG9jdW1lbnQpLm9mZignY2hhbmdlLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScpLm9uKCdjaGFuZ2UuUXVhbnRpdHlTdGVwcGVyLlF1YW50aXR5Q2hhbmdlJywgJy5xdWFudGl0eS1zdGVwcGVyIGlucHV0W25hbWUkPV9xdWFudGl0eV0nLCBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKGlzTmFOKCQodGhpcykudmFsKCkpIHx8IHBhcnNlSW50KCQodGhpcykudmFsKCksIDEwKSA9PT0gMCkge1xuXHRcdFx0JCh0aGlzKS52YWwoJzEnKTtcblx0XHRcdCRmb2N1c2VkRWxlbWVudCA9ICQodGhpcyk7XG5cdFx0fVxuXHR9KTtcblxuXHQvLyBLZXlib2FyZCBldmVudHMgZm9yIFF1YW50aXR5IFN0ZXBwZXJcblx0JChkb2N1bWVudCkub2ZmKCdrZXlkb3duLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScpLm9uKCdrZXlkb3duLlF1YW50aXR5U3RlcHBlci5RdWFudGl0eUNoYW5nZScsICcucXVhbnRpdHktc3RlcHBlciBpbnB1dFtuYW1lJD1fcXVhbnRpdHldJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0dmFyICR0aGlzID0gJCh0aGlzKTtcblxuXHRcdGlmIChldmVudC53aGljaCA9PT0gU2l0ZUNvbnN0YW50cy5LZXlDb2Rlcy5FbnRlcikge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdCRmb2N1c2VkRWxlbWVudCA9ICR0aGlzO1xuXHRcdFx0aWYgKCQoZXZlbnQudGFyZ2V0KS52YWwoKSA+IDApIHtcblx0XHRcdFx0dmFyIHF1YW50aXR5RGVsdGEgPSBwYXJzZUludCgkdGhpcy52YWwoKSwgMTApIC0gcGFyc2VJbnQoJHRoaXMuYXR0cigncXVhbnRpdHktYnVmZmVyJyksIDEwKTtcblx0XHRcdFx0dXBkYXRlU3RlcHBlclF0eVVJKCR0aGlzLCB0cnVlKTtcblx0XHRcdFx0dXBkYXRlTWluaUNhcnRVSSh0cnVlKTtcblx0XHRcdFx0dXBkYXRlQ2FydFRvdGFscygpO1xuXHRcdFx0XHRxdWFudGl0eUNoYW5nZUV2ZW50cygkdGhpcywgTWF0aC5hYnMocXVhbnRpdHlEZWx0YSksIHF1YW50aXR5RGVsdGEgPiAwKTtcblx0XHRcdFx0JHRoaXMuYXR0cigncXVhbnRpdHktYnVmZmVyJywgJHRoaXMudmFsKCkpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0JChkb2N1bWVudCkub2ZmKCdRdWFudGl0eVN0ZXBwZXIuVGFyZ2V0Rm9jdXMnKS5vbignUXVhbnRpdHlTdGVwcGVyLlRhcmdldEZvY3VzJywgZnVuY3Rpb24gKCkge1xuXHRcdGlmICgkZm9jdXNlZEVsZW1lbnQpIHtcblx0XHRcdCRmb2N1c2VkRWxlbWVudC5mb2N1cygpO1xuXHRcdH1cblx0fSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGluaXRpYWxpemU7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi9kaWFsb2cnKSxcbiAgICBwcm9kdWN0ID0gcmVxdWlyZSgnLi9wYWdlcy9wcm9kdWN0JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxuXG52YXIgbWFrZVVybCA9IGZ1bmN0aW9uICh1cmwsIHNvdXJjZSwgcHJvZHVjdExpc3RJRCkge1xuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgICAgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NvdXJjZScsIHNvdXJjZSk7XG4gICAgfVxuICAgIGlmIChwcm9kdWN0TGlzdElEKSB7XG4gICAgICAgIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcm9kdWN0bGlzdGlkJywgcHJvZHVjdExpc3RJRCk7XG4gICAgfVxuICAgIHJldHVybiB1cmw7XG59O1xuXG52YXIgcmVtb3ZlUGFyYW0gPSBmdW5jdGlvbiAodXJsKSB7XG4gICAgaWYgKHVybC5pbmRleE9mKCc/JykgIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB1cmwuc3Vic3RyaW5nKDAsIHVybC5pbmRleE9mKCc/JykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfVxufTtcblxudmFyIHF1aWNrdmlldyA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5leGlzdHMoKSkge1xuICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyID0gJCgnPGRpdi8+JykuYXR0cignaWQnLCAnUXVpY2tWaWV3RGlhbG9nJykuYXBwZW5kVG8oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcm9kdWN0TGlua3MgPSAkKCcjc2VhcmNoLXJlc3VsdC1pdGVtcyAudGh1bWItbGluaycpLm1hcChmdW5jdGlvbiAoaW5kZXgsIHRodW1iTGluaykge1xuICAgICAgICAgICAgcmV0dXJuICQodGh1bWJMaW5rKS5hdHRyKCdocmVmJyk7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBzZXR1cDogZnVuY3Rpb24gKHF2VXJsKSB7XG5cbiAgICAgICAgcHJvZHVjdC5pbml0aWFsaXplRXZlbnRzKCk7XG5cbiAgICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBzdGVwIC0gSG93IG1hbnkgcHJvZHVjdHMgYXdheSBmcm9tIGN1cnJlbnQgcHJvZHVjdCB0byBuYXZpZ2F0ZSB0by4gTmVnYXRpdmUgbnVtYmVyIG1lYW5zIG5hdmlnYXRlIGJhY2t3YXJkXG4gICAgICovXG4gICAgbmF2aWdhdGVRdWlja3ZpZXc6IGZ1bmN0aW9uIChzdGVwKSB7XG4gICAgICAgIC8vIGRlZmF1bHQgc3RlcCB0byAwXG4gICAgICAgIHRoaXMucHJvZHVjdExpbmtJbmRleCArPSAoc3RlcCA/IHN0ZXAgOiAwKTtcbiAgICAgICAgdmFyIHVybCA9IG1ha2VVcmwodGhpcy5wcm9kdWN0TGlua3NbdGhpcy5wcm9kdWN0TGlua0luZGV4XSwgJ3F1aWNrdmlldycpO1xuICAgICAgICBkaWFsb2cucmVwbGFjZSh7XG4gICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgIGNhbGxiYWNrOiB0aGlzLnNldHVwLmJpbmQodGhpcywgdXJsKVxuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIHNob3cgcXVpY2sgdmlldyBkaWFsb2dcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCAtIHVybCBvZiB0aGUgcHJvZHVjdCBkZXRhaWxzXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuc291cmNlIC0gc291cmNlIG9mIHRoZSBkaWFsb2cgdG8gYmUgYXBwZW5kZWQgdG8gVVJMXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMucHJvZHVjdGxpc3RpZCAtIHRvIGJlIGFwcGVuZGVkIHRvIFVSTFxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdGlvbnMuY2FsbGJhY2sgLSBjYWxsYmFjayBvbmNlIHRoZSBkaWFsb2cgaXMgb3BlbmVkXG4gICAgICovXG4gICAgc2hvdzogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHVybDtcbiAgICAgICAgaWYgKCF0aGlzLmV4aXN0cygpKSB7XG4gICAgICAgICAgICB0aGlzLmluaXQoKTtcbiAgICAgICAgfVxuICAgICAgICB1cmwgPSBtYWtlVXJsKG9wdGlvbnMudXJsLCBvcHRpb25zLnNvdXJjZSwgb3B0aW9ucy5wcm9kdWN0bGlzdGlkKTtcblxuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICB0YXJnZXQ6IHRoaXMuJGNvbnRhaW5lcixcbiAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAxMDY4LFxuICAgICAgICAgICAgICAgIHRpdGxlOiBSZXNvdXJjZXMuUVVJQ0tfVklFV19QT1BVUCxcbiAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dXAodXJsKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7IG9wdGlvbnMuY2FsbGJhY2soKTsgfVxuICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGV4aXN0czogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kY29udGFpbmVyICYmICh0aGlzLiRjb250YWluZXIubGVuZ3RoID4gMCk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBxdWlja3ZpZXc7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogY29waWVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2Rhcmtza3lhcHAvc3RyaW5nLWhhc2hcbiAqL1xuZnVuY3Rpb24gaGFzaEZuKHN0cikge1xuICAgIHZhciBoYXNoID0gNTM4MSxcbiAgICAgICAgaSA9IHN0ci5sZW5ndGg7XG5cbiAgICB3aGlsZSAoaSkge1xuICAgICAgICBoYXNoID0gKGhhc2ggKiAzMykgXiBzdHIuY2hhckNvZGVBdCgtLWkpO1xuICAgIH1cbiAgICAvKiBKYXZhU2NyaXB0IGRvZXMgYml0d2lzZSBvcGVyYXRpb25zIChsaWtlIFhPUiwgYWJvdmUpIG9uIDMyLWJpdCBzaWduZWRcbiAgICAqIGludGVnZXJzLiBTaW5jZSB3ZSB3YW50IHRoZSByZXN1bHRzIHRvIGJlIGFsd2F5cyBwb3NpdGl2ZSwgY29udmVydCB0aGVcbiAgICAqIHNpZ25lZCBpbnQgdG8gYW4gdW5zaWduZWQgYnkgZG9pbmcgYW4gdW5zaWduZWQgYml0c2hpZnQuICovXG4gICAgcmV0dXJuIGhhc2ggPj4+IDA7XG59XG5cbi8qKlxuICogQ3JlYXRlIHJhdGluZyBiYXNlZCBvbiBoYXNoIHJhbmdpbmcgZnJvbSAyLTVcbiAqIEBwYXJhbSBwaWRcbiAqL1xuZnVuY3Rpb24gZ2V0UmF0aW5nKHBpZCkge1xuICAgIHJldHVybiBoYXNoRm4ocGlkLnRvU3RyaW5nKCkpICUgMzAgLyAxMCArIDI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnLnZhcmlhbnQtaW5mbyAucHJvZHVjdC1yZXZpZXcnKS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgcmV2aWV3KSB7XG4gICAgICAgICAgICB2YXIgcGlkID0gJChyZXZpZXcpLmRhdGEoJ3BpZCcpO1xuICAgICAgICAgICAgaWYgKCFwaWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByYXRpbmcgcmFuZ2UgZnJvbSAyIC0gNVxuICAgICAgICAgICAgdmFyIHJhdGluZyA9IGdldFJhdGluZyhwaWQpO1xuICAgICAgICAgICAgdmFyIGJhc2VSYXRpbmcgPSBNYXRoLmZsb29yKHJhdGluZyk7XG4gICAgICAgICAgICB2YXIgc3RhcnNDb3VudCA9IDA7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJhc2VSYXRpbmc7IGkrKykge1xuICAgICAgICAgICAgICAgICQoJy5yYXRpbmcnLCByZXZpZXcpLmFwcGVuZCgnPGkgY2xhc3M9XCJmYSBmYS1zdGFyXCI+PC9pPicpO1xuICAgICAgICAgICAgICAgIHN0YXJzQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGdpdmUgaGFsZiBzdGFyIGZvciBhbnl0aGluZyBpbiBiZXR3ZWVuXG4gICAgICAgICAgICBpZiAocmF0aW5nID4gYmFzZVJhdGluZykge1xuICAgICAgICAgICAgICAgICQoJy5yYXRpbmcnLCByZXZpZXcpLmFwcGVuZCgnPGkgY2xhc3M9XCJmYSBmYS1zdGFyLWhhbGYtb1wiPjwvaT4nKTtcbiAgICAgICAgICAgICAgICBzdGFyc0NvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhcnNDb3VudCA8IDUpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDUgLSBzdGFyc0NvdW50OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnLnJhdGluZycsIHJldmlldykuYXBwZW5kKCc8aSBjbGFzcz1cImZhIGZhLXN0YXItb1wiPjwvaT4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIFJFR0lTVEVSXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIGFsZXJ0ID0gcmVxdWlyZSgnLi9hbGVydCcpO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG52YXIgbG9hZGluZ0luZGljYXRvciA9IHJlcXVpcmUoJy4vY29tcG9uZW50cy9Mb2FkaW5nSW5kaWNhdG9yJyk7XG52YXIgd2lzaGxpc3QgPSByZXF1aXJlKCcuL3dpc2hsaXN0Jyk7XG5cbnZhciBSZXF1ZXN0SGVscGVyID0gcmVxdWlyZSgnLi9oZWxwZXJzL1JlcXVlc3RIZWxwZXInKTtcbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBvcHRpb25zID0ge307XG52YXIgbG9hZGluZ0luZGljYXRvclNldHRpbmdzID0ge1xuICAgIElzTGFiZWxTaG93bjogZmFsc2UsXG4gICAgQ3NzQ2xhc3M6ICdmdWxsc2NyZWVuJyxcbiAgICBCYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCdcbn07XG5cbmZ1bmN0aW9uIGVycm9ySGFuZGxpbmcoZGF0YSwgZGlhbG9nVGl0bGUsIGRpYWxvZ0h0bWwpIHtcbiAgICBpZiAoZGF0YSAmJiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgJ21lc3NhZ2UnIGluIGRhdGEpIHtcbiAgICAgICAgY29uc29sZS5sb2coZGF0YS5tZXNzYWdlKTtcbiAgICB9XG4gICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICBodG1sOiBkaWFsb2dIdG1sLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICB0aXRsZTogZGlhbG9nVGl0bGUsXG4gICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcbiAgICAgICAgICAgICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVSZWdpc3RyYXRpb25Gb3JtKCRmb3JtKSB7XHRcbiAgICB2YXIgcmV3YXJkc0Zvcm1GaWVsZHMgPSB7XG4gICAgICAgIGVtYWlsOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfZW1haWwnKSxcbiAgICAgICAgZmlyc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfZmlyc3RuYW1lJyksXG4gICAgICAgIGxhc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfbGFzdG5hbWUnKSxcbiAgICAgICAgcGhvbmU6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9waG9uZScpLFxuICAgICAgICB6aXA6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcmFkZHJlc3NfemlwY29kZScpLmxlbmd0aCA+IDAgPyAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJhZGRyZXNzX3ppcGNvZGUnKSA6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl96aXBjb2RlJylcbiAgICB9XG5cdGlmICgkZm9ybS5maW5kKCdpbnB1dFtuYW1lKj1cImR3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX3Bhc3N3b3JkXCJdJykubGVuZ3RoID4gMCkge1xuXHRcdHJld2FyZHNGb3JtRmllbGRzLnBhc3N3b3JkID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9wYXNzd29yZFwiXScpO1xuXHR9XG4gICAgdmFyIHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHMgPSB7XG4gICAgICAgIGVtYWlsOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9lbWFpbCcpLFxuICAgICAgICBjb25maXJtRW1haWw6ICRmb3JtLmZpbmQoJyNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2VtYWlsY29uZmlybScpLFxuICAgICAgICBmaXJzdE5hbWU6ICRmb3JtLmZpbmQoJyNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2ZpcnN0bmFtZScpLFxuICAgICAgICBsYXN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Byb2ZpbGVfY3VzdG9tZXJfbGFzdG5hbWUnKVxuICAgIH1cblx0aWYgKCRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZF9cIl0nKS5sZW5ndGggPiAwKSB7XG5cdFx0cmVnaXN0cmF0aW9uRm9ybUZpZWxkcy5wYXNzd29yZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZF9cIl0nKTtcblx0fVxuXHRpZiAoJGZvcm0uZmluZCgnaW5wdXRbbmFtZSo9XCJkd2ZybV9wcm9maWxlX2xvZ2luX3Bhc3N3b3JkY29uZmlybVwiXScpLmxlbmd0aCA+IDApIHtcblx0XHRyZWdpc3RyYXRpb25Gb3JtRmllbGRzLmNvbmZpcm1QYXNzd29yZCA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUqPVwiZHdmcm1fcHJvZmlsZV9sb2dpbl9wYXNzd29yZGNvbmZpcm1cIl0nKTtcblx0fVxuICAgIHZhciBjaGVja0Zvcm1GaWVsZHMgPSAkZm9ybS5hdHRyKCdpZCcpID09ICdkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uJyA/IHJld2FyZHNGb3JtRmllbGRzIDogcmVnaXN0cmF0aW9uRm9ybUZpZWxkcztcblx0dmFyIGZvcm1WYWxpZGF0aW9uID0gbmV3IEFycmF5KCk7XG4gICAgdmFyIHJlZ2V4RW1haWwgPSAvXlthLXpBLVowLTkuISMkJSYnKisvPT9eX2B7fH1+LV0rQFthLXpBLVowLTktXSsoPzpcXC5bYS16QS1aMC05LV0rKSokL2c7XG5cdHZhciByZWdleFBob25lID0gL15cXCs/XFwoPyhbMC05XVswLThdWzAtOV0pXFwpP1tcXC1cXC4gXT8oWzItOV1bMC05XXsyfSlbXFwtXFwuIF0/KFswLTldezR9KShcXHMqeFswLTldKyk/JC9nO1xuICAgIHZhciByZWdleFppcCA9IC9eKFxcZHs1fSkoLVxcZHs0fSk/JC9nO1xuICAgIHZhciByZWdleFBhc3N3b3JkID0gL14oPz0uKj9bQS16XSkoPz0uKj9bMC05XSkoPz0uKj9bIz8hXFw9XFwvXFwsXFwuXFx+XFxgXFwoXFwpXFx7XFx9XFxbXFxdXFxcXEBfJCVeJiotXSkuezgsMjB9JC9nO1xuXG4gICAgZm9yICh2YXIgZmllbGROYW1lIGluIGNoZWNrRm9ybUZpZWxkcykge1xuICAgICAgICB2YXIgZmllbGRWYWx1ZSA9IGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmxlbmd0aCA/IGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLnZhbCgpLnRyaW0oKSA6IG51bGw7XG5cbiAgICAgICAgaWYgKGZpZWxkVmFsdWUgIT0gbnVsbCAmJiBmaWVsZFZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlmIChmaWVsZE5hbWUgPT0gJ2VtYWlsJyB8fCBmaWVsZE5hbWUgPT0gJ2NvbmZpcm1FbWFpbCcpIHtcbiAgICAgICAgICAgICAgICBpZiAoU3RyaW5nKGZpZWxkVmFsdWUpLm1hdGNoKHJlZ2V4RW1haWwpID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24ucHVzaChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHRcdHZhciBlbWFpbEZvcm1hdEVycm9yQ2xhc3MgPSBmaWVsZE5hbWUgPT0gJ2VtYWlsJyA/ICdzcGFuLmludmFsaWQtZW1haWwtZm9ybWF0JyA6ICdzcGFuLmludmFsaWQtZW1haWwtY29uZmlybS1mb3JtYXQnO1xuXHRcdFx0XHRcdCQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yW2RhdGEtcmVsYXRpb249XCInK2ZpZWxkTmFtZSsnXCJdJykuZmluZChlbWFpbEZvcm1hdEVycm9yQ2xhc3MpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgICAgICAgICB9XG5cdFx0XHRcdGlmIChmaWVsZE5hbWUgPT0gJ2NvbmZpcm1FbWFpbCcgJiYgKGZpZWxkVmFsdWUgIT0gY2hlY2tGb3JtRmllbGRzWydlbWFpbCddLnZhbCgpLnRyaW0oKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24ucHVzaChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHRcdCQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yW2RhdGEtcmVsYXRpb249XCInK2ZpZWxkTmFtZSsnXCJdJykuZmluZCgnc3Bhbi5pbnZhbGlkLWVtYWlsLWNvbmZpcm0tbWlzbWF0Y2gnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpZWxkTmFtZSA9PSAncGhvbmUnKSB7XG4gICAgICAgICAgICAgICAgaWYgKFN0cmluZyhmaWVsZFZhbHVlKS5tYXRjaChyZWdleFBob25lKSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5hZGRDbGFzcygnZXJyb3InKTtcblx0XHRcdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoJ3NwYW4uaW52YWxpZC1waG9uZS1mb3JtYXQnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpZWxkTmFtZSA9PSAnemlwJykge1xuICAgICAgICAgICAgICAgIGlmIChTdHJpbmcoZmllbGRWYWx1ZSkubWF0Y2gocmVnZXhaaXApID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybVZhbGlkYXRpb24ucHVzaChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRm9ybUZpZWxkc1tmaWVsZE5hbWVdLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHRcdCQoJy5yZWdpc3RyYXRpb24tZGlhbG9nLWVycm9yW2RhdGEtcmVsYXRpb249XCInK2ZpZWxkTmFtZSsnXCJdJykuZmluZCgnc3Bhbi5pbnZhbGlkLXppcC1mb3JtYXQnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpZWxkTmFtZSA9PSAncGFzc3dvcmQnIHx8IGZpZWxkTmFtZSA9PSAnY29uZmlybVBhc3N3b3JkJykge1xuICAgICAgICAgICAgICAgIGlmIChTdHJpbmcoZmllbGRWYWx1ZSkubWF0Y2gocmVnZXhQYXNzd29yZCkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBmb3JtVmFsaWRhdGlvbi5wdXNoKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tGb3JtRmllbGRzW2ZpZWxkTmFtZV0uYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XHRcdFx0dmFyIHBhc3N3b3JkRm9ybWF0RXJyb3JDbGFzcyA9IGZpZWxkTmFtZSA9PSAncGFzc3dvcmQnID8gJ3NwYW4uaW52YWxpZC1wYXNzd29yZC1mb3JtYXQnIDogJ3NwYW4uaW52YWxpZC1wYXNzd29yZC1jb25maXJtLWZvcm1hdCc7XG5cdFx0XHRcdFx0JCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3JbZGF0YS1yZWxhdGlvbj1cIicrZmllbGROYW1lKydcIl0nKS5maW5kKHBhc3N3b3JkRm9ybWF0RXJyb3JDbGFzcykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmllbGROYW1lID09ICdjb25maXJtUGFzc3dvcmQnICYmIChmaWVsZFZhbHVlICE9IGNoZWNrRm9ybUZpZWxkc1sncGFzc3dvcmQnXS52YWwoKS50cmltKCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja0Zvcm1GaWVsZHNbZmllbGROYW1lXS5hZGRDbGFzcygnZXJyb3InKTtcblx0XHRcdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoJ3NwYW4uaW52YWxpZC1wYXNzd29yZC1jb25maXJtLW1pc21hdGNoJykucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1WYWxpZGF0aW9uLnB1c2goZmFsc2UpO1xuICAgICAgICAgICAgY2hlY2tGb3JtRmllbGRzW2ZpZWxkTmFtZV0uYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XHQkKCcucmVnaXN0cmF0aW9uLWRpYWxvZy1lcnJvcltkYXRhLXJlbGF0aW9uPVwiJytmaWVsZE5hbWUrJ1wiXScpLmZpbmQoJ3NwYW4uaW52YWxpZC1taXNzaW5nLWZpZWxkcycpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgfVxuICAgIH1cblx0XHRcdFxuXHRpZiAoZm9ybVZhbGlkYXRpb24ubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJGZvcm0uZmluZCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3Igc3BhbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG4vLyBDb3JkaWFsIHJld2FyZHMgcmVnaXN0cmF0aW9uIHRyYWNraW5nIChCQilcbmZ1bmN0aW9uIHJld2FyZHNSZWdpc3RlckNvcmRpYWxFdmVudCgkZm9ybSwgaXNSZWdpc3RlckRpYWxvZywgY2FsbGJhY2spIHtcbiAgICB2YXIgcmV3YXJkc0Zvcm1GaWVsZHMgPSB7XG4gICAgICAgIGVtYWlsOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJfZW1haWwnKS52YWwoKS50cmltKCksXG4gICAgICAgIGZpcnN0TmFtZTogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX2ZpcnN0bmFtZScpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgbGFzdE5hbWU6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9sYXN0bmFtZScpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgcGhvbmU6ICRmb3JtLmZpbmQoJyNkd2ZybV9yZXdhcmRzcmVnaXN0cmF0aW9uX3Jld2FyZHNjdXN0b21lcl9waG9uZScpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgemlwOiAkZm9ybS5maW5kKCcjZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbl9yZXdhcmRzY3VzdG9tZXJhZGRyZXNzX3ppcGNvZGUnKS5sZW5ndGggPiAwID8gJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyYWRkcmVzc196aXBjb2RlJykudmFsKCkudHJpbSgpIDogJGZvcm0uZmluZCgnI2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmV3YXJkc2N1c3RvbWVyX3ppcGNvZGUnKS52YWwoKS50cmltKClcbiAgICB9XG4gICAgdmFyIHNpZ251cEV2ZW50ID0gXCJcIjtcblxuXHR2YXIgYXV0aF9kYXRhID0ge1xuXHRcdGVtYWlsOiByZXdhcmRzRm9ybUZpZWxkc1snZW1haWwnXVxuXHR9XHRcdFxuXHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdCdjaGFubmVscyc6IHtcblx0XHRcdCdlbWFpbCc6IHtcblx0XHRcdFx0J2FkZHJlc3MnOiByZXdhcmRzRm9ybUZpZWxkc1snZW1haWwnXSAgICAgIFxuXHRcdFx0fVxuXHRcdH0sXHRcdCAgICBcblx0XHQnZmlyc3RfbmFtZSc6IHJld2FyZHNGb3JtRmllbGRzWydmaXJzdE5hbWUnXSxcblx0XHQnbGFzdF9uYW1lJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ2xhc3ROYW1lJ10sXG5cdFx0J3Bob25lJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ3Bob25lJ10sXG5cdFx0J3Bvc3RhbF9jb2RlJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ3ppcCddLFxuXHRcdCdzb3VyY2VfY3JlYXRlJzogJ215YWNjb3VudCcsXG5cdFx0J2dlb19sb2NhdGlvbic6IHtcblx0XHRcdCdwb3N0YWxfY29kZSc6IHJld2FyZHNGb3JtRmllbGRzWyd6aXAnXVxuXHRcdH1cblx0fTtcdFx0XHRcblx0dmFyIGxvZ2luUHJvcGVydGllcyA9IHtcblx0XHRcImVtYWlsXCI6IHJld2FyZHNGb3JtRmllbGRzWydlbWFpbCddLFxuXHRcdFwibG9naW5UeXBlXCI6IGlzUmVnaXN0ZXJEaWFsb2cgPyBcInJlZ2lzdHJhdGlvbi1kaWFsb2dcIiA6IFwicmVndWxhci1yZWdpc3RyYXRpb25cIlxuXHR9O1x0XG5cdHZhciByZWdpc3RlclByb3BlcnRpZXMgPSB7XG5cdFx0XCJlbWFpbFwiOiByZXdhcmRzRm9ybUZpZWxkc1snZW1haWwnXSxcblx0XHRcInJlZ2lzdGVyVHlwZVwiOiBpc1JlZ2lzdGVyRGlhbG9nID8gXCJyZWdpc3RyYXRpb24tZGlhbG9nXCIgOiBcInJlZ3VsYXItcmVnaXN0cmF0aW9uXCJcblx0fTtcdFx0XHRcblx0aWYgKCQoJ2lucHV0I2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb25fcmVjZWl2ZVJld2FyZHNFbWFpbCcpLmlzKCc6Y2hlY2tlZCcpKSB7XG5cdFx0dmFyIGNvbnRhY3RfZGF0YSA9IHtcblx0XHRcdCdjaGFubmVscyc6IHtcblx0XHRcdFx0J2VtYWlsJzoge1xuXHRcdFx0XHRcdCdhZGRyZXNzJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ2VtYWlsJ10sXG5cdFx0XHRcdFx0J3N1YnNjcmliZVN0YXR1cyc6ICdzdWJzY3JpYmVkJ1x0XHRcdFx0ICAgICAgICAgICAgXG5cdFx0XHRcdH1cblx0XHRcdH0sXHRcdCAgICBcblx0XHRcdCdmaXJzdF9uYW1lJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ2ZpcnN0TmFtZSddLFxuXHRcdFx0J2xhc3RfbmFtZSc6IHJld2FyZHNGb3JtRmllbGRzWydsYXN0TmFtZSddLFxuXHRcdFx0J3Bob25lJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ3Bob25lJ10sXG5cdFx0XHQncG9zdGFsX2NvZGUnOiByZXdhcmRzRm9ybUZpZWxkc1snemlwJ10sXG5cdFx0XHQnc2lnbnVwX3NvdXJjZSc6ICdyZXdhcmRzJyxcblx0XHRcdCdzb3VyY2VfY3JlYXRlJzogJ215YWNjb3VudCcsXG5cdFx0XHQnd2VsY29tZV9zaWdudXBfcmV3YXJkc19vbmxpbmUnOiB0cnVlLFxuXHRcdFx0J2dlb19sb2NhdGlvbic6IHtcblx0XHRcdFx0J3Bvc3RhbF9jb2RlJzogcmV3YXJkc0Zvcm1GaWVsZHNbJ3ppcCddXG5cdFx0XHR9XG5cdFx0fTtcdFx0XG5cdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHRcInNpZ251cF9zb3VyY2VcIjogJ3Jld2FyZHMnLFxuXHRcdFx0XCJ3ZWxjb21lX3NpZ251cF9yZXdhcmRzX29ubGluZVwiOiB0cnVlXG5cdFx0fTtcdFx0XG5cdFx0c2lnbnVwRXZlbnQgPSBbJ2V2ZW50JywgJ2VtYWlsX3NpZ251cCcsIHByb3BlcnRpZXNdO1xuXHR9XHRcblx0UmVxdWVzdEhlbHBlci5WYWxpZGF0ZSgnQ29yZGlhbC1FbWFpbFNpZ251cCcpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0Y3JkbChbXHRcdFx0XHRcblx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRbJ2V2ZW50JywgJ2FjY291bnRfY3JlYXRlJywgcmVnaXN0ZXJQcm9wZXJ0aWVzXSxcblx0XHRcdFx0WydldmVudCcsICdsb2dpbicsIGxvZ2luUHJvcGVydGllc10sXG5cdFx0XHRcdHNpZ251cEV2ZW50XG5cdFx0XHRdKTtcblx0XHR9XG5cdFx0aWYgKGNhbGxiYWNrKSBjYWxsYmFjaygpO1xuXHR9KS5jYXRjaCgpO1x0XG59XG5cbi8vIENvcmRpYWwgcmVnaXN0cmF0aW9uIHRyYWNraW5nIChTSFAgYW5kIENPKVxuZnVuY3Rpb24gcmVnaXN0ZXJDb3JkaWFsRXZlbnQoJGZvcm0sIGlzUmVnaXN0ZXJEaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgdmFyIHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHMgPSB7XG4gICAgICAgIGVtYWlsOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9lbWFpbCcpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgZmlyc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9maXJzdG5hbWUnKS52YWwoKS50cmltKCksXG4gICAgICAgIGxhc3ROYW1lOiAkZm9ybS5maW5kKCcjZHdmcm1fcHJvZmlsZV9jdXN0b21lcl9sYXN0bmFtZScpLnZhbCgpLnRyaW0oKVxuICAgIH1cblx0dmFyIHNpZ251cEV2ZW50ID0gXCJcIjtcdFxuXG5cdHZhciBhdXRoX2RhdGEgPSB7XG5cdFx0ZW1haWw6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHNbJ2VtYWlsJ11cblx0fVx0XHRcdFxuXHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdCdjaGFubmVscyc6IHtcblx0XHRcdCdlbWFpbCc6IHtcblx0XHRcdFx0J2FkZHJlc3MnOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydlbWFpbCddXHRcdFx0ICAgICAgICAgICAgXG5cdFx0XHR9XG5cdFx0fSxcdFx0ICAgIFxuXHRcdCdmaXJzdF9uYW1lJzogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZmlyc3ROYW1lJ10sXG5cdFx0J2xhc3RfbmFtZSc6IHJlZ2lzdHJhdGlvbkZvcm1GaWVsZHNbJ2xhc3ROYW1lJ10sXG5cdFx0J3NvdXJjZV9jcmVhdGUnOiAnbXlhY2NvdW50J1xuXHR9O1xuXHR2YXIgbG9naW5Qcm9wZXJ0aWVzID0ge1xuXHRcdFwiZW1haWxcIjogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZW1haWwnXSxcblx0XHRcImxvZ2luVHlwZVwiOiBpc1JlZ2lzdGVyRGlhbG9nID8gXCJyZWdpc3RyYXRpb24tZGlhbG9nXCIgOiBcInJlZ2lzdHJhdGlvblwiXG5cdH07XHRcdFxuXHR2YXIgcmVnaXN0ZXJQcm9wZXJ0aWVzID0ge1xuXHRcdFwiZW1haWxcIjogcmVnaXN0cmF0aW9uRm9ybUZpZWxkc1snZW1haWwnXSxcblx0XHRcInJlZ2lzdGVyVHlwZVwiOiBpc1JlZ2lzdGVyRGlhbG9nID8gXCJyZWdpc3RyYXRpb24tZGlhbG9nXCIgOiBcInJlZ2lzdHJhdGlvblwiXG5cdH07XHRcdFx0XHRcdFx0XG5cdGlmICgkKCdpbnB1dCNkd2ZybV9wcm9maWxlX2N1c3RvbWVyX2FkZHRvZW1haWxsaXN0JykuaXMoJzpjaGVja2VkJykpIHtcblx0XHR2YXIgY29udGFjdF9kYXRhID0ge1xuXHRcdFx0J2NoYW5uZWxzJzoge1xuXHRcdFx0XHQnZW1haWwnOiB7XG5cdFx0XHRcdFx0J2FkZHJlc3MnOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydlbWFpbCddLFxuXHRcdFx0XHRcdCdzdWJzY3JpYmVTdGF0dXMnOiAnc3Vic2NyaWJlZCdcblx0XHRcdFx0fVxuXHRcdFx0fSxcdFx0ICAgIFxuXHRcdFx0J2ZpcnN0X25hbWUnOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydmaXJzdE5hbWUnXSxcblx0XHRcdCdsYXN0X25hbWUnOiByZWdpc3RyYXRpb25Gb3JtRmllbGRzWydsYXN0TmFtZSddLFxuXHRcdFx0J3NpZ251cF9zb3VyY2UnOiAnbXlhY2NvdW50Jyxcblx0XHRcdCdzb3VyY2VfY3JlYXRlJzogJ215YWNjb3VudCcsXG5cdFx0XHQnd2VsY29tZV9zaWdudXAnOiB0cnVlXG5cdFx0fTtcdFx0XG5cdFx0dmFyIHByb3BlcnRpZXMgPSB7XG5cdFx0XHRcInNpZ251cF9zb3VyY2VcIjogXCJteWFjY291bnRcIixcblx0XHRcdFwicGFnZVwiOiBcIm15YWNjb3VudFwiLFxuXHRcdFx0XCJ3ZWxjb21lX3NpZ251cFwiOiB0cnVlXG5cdFx0fTtcblx0XHRzaWdudXBFdmVudCA9IFsnZXZlbnQnLCAnZW1haWxfc2lnbnVwJywgcHJvcGVydGllc107XG5cdH1cblx0UmVxdWVzdEhlbHBlci5WYWxpZGF0ZSgnQ29yZGlhbC1FbWFpbFNpZ251cCcpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHR5cGVvZiBjcmRsICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY3JkbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0Y3JkbChbXHRcdFx0XHRcblx0XHRcdFx0Wydjb250YWN0JywgYXV0aF9kYXRhLCBjb250YWN0X2RhdGFdLFxuXHRcdFx0XHRbJ2V2ZW50JywgJ2FjY291bnRfY3JlYXRlJywgcmVnaXN0ZXJQcm9wZXJ0aWVzXSxcblx0XHRcdFx0WydldmVudCcsICdsb2dpbicsIGxvZ2luUHJvcGVydGllc10sXG5cdFx0XHRcdHNpZ251cEV2ZW50XG5cdFx0XHRdKTtcblx0XHR9XG5cdFx0aWYgKGNhbGxiYWNrKSBjYWxsYmFjaygpO1xuXHR9KS5jYXRjaCgpO1x0XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGFkZCBydWxlcyB0byBjb2RlIGlucHV0IGZpZWxkXG4gKi9cbmZ1bmN0aW9uIGluaXRBZGRSdWxlc0ZvckNvZGVJbnB1dCgpIHtcbiAgICAkKCdmb3JtI3ZlcmlmeS1jb2RlJykudmFsaWRhdGUoKTtcbiAgICAkKCcjdmVyaWZ5LWNvZGUgI2VudGVyLWNvZGUnKS5ydWxlcygnYWRkJywge1xuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgZGlnaXRzOiB0cnVlLFxuICAgICAgICBtaW5sZW5ndGg6IDYsXG4gICAgICAgIG1lc3NhZ2VzOiB7XG4gICAgICAgICAgICByZXF1aXJlZDogUmVzb3VyY2VzLlZBTElEQVRFX0NPREUsXG4gICAgICAgICAgICBtaW5sZW5ndGg6IFJlc291cmNlcy5WQUxJREFURV9DT0RFXG4gICAgICAgIH0sXG4gICAgICAgIG5vcm1hbGl6ZXI6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gJC50cmltKHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBpbml0IHJlZ2lzdHJhdGlvbiBidXR0b24gZXZlbnQgZm9yIHJlZ2lzdHJhdGlvbiBwYWdlIGFuZCBkaWFsb2dcbiAqL1xuZnVuY3Rpb24gaW5pdFJlZ2lzdHJhdGlvbkJ1dHRvbigpIHtcbiAgICAkKGRvY3VtZW50KS5vZmYoJ2NsaWNrLlJlZ2lzdHJhdGlvbicpLm9uKCdjbGljay5SZWdpc3RyYXRpb24nLCAnLmFjY291bnRSZWdpc3RlckJ1dHRvbiwgLnNhdmVSZXdhcmRzUmVnaXN0cmF0aW9uLmJ0biwgLmNvbmZpcm1hdGlvblJlZ2lzdGVyQnV0dG9uJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdHZhciBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Pb3BzLCBzb21ldGhpbmcgd2VudCB3cm9uZyB3aXRoIHJlZ2lzdHJhdGlvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+JztcbiAgICAgICAgdmFyICRyZWdpc3RyYXRpb25CdXR0b24gPSAkKHRoaXMpO1xuXHRcdHZhciAkcmVnaXN0cmF0aW9uRm9ybSA9ICRyZWdpc3RyYXRpb25CdXR0b24uY2xvc2VzdCgnZm9ybVtkYXRhLWZvcm0tdHlwZT1cInJlZ2lzdGVyXCJdJyk7XG4gICAgICAgIHZhciBmb3JtVXJsID0gJHJlZ2lzdHJhdGlvbkZvcm0uYXR0cignYWN0aW9uJyk7XG5cdFx0dmFyIGlzQ29uZmlybWF0aW9uUGFnZSA9ICRyZWdpc3RyYXRpb25CdXR0b24uaGFzQ2xhc3MoJ2NvbmZpcm1hdGlvblJlZ2lzdGVyQnV0dG9uJyk7XG5cblx0XHQvLyBDbGVhciBwcmV2aW91cyBmb3JtIGVycm9yc1xuXHRcdCRyZWdpc3RyYXRpb25Gb3JtLmZpbmQoJ2lucHV0JykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0JHJlZ2lzdHJhdGlvbkZvcm0uZmluZCgnLnJlZ2lzdHJhdGlvbi1kaWFsb2ctZXJyb3Igc3BhbicpLmFkZENsYXNzKCdkLW5vbmUnKTtcblxuXHRcdHZhciBpc1ZhbGlkRm9ybSA9IHZhbGlkYXRlUmVnaXN0cmF0aW9uRm9ybSgkcmVnaXN0cmF0aW9uRm9ybSk7XG5cdFx0dmFyIGlzUmVnaXN0ZXJEaWFsb2cgPSBmb3JtVXJsLmluZGV4T2YoJ2xvZ2luRGlhbG9nJykgPj0gMDtcblx0XHR2YXIgZm9ybURhdGEgPSAkcmVnaXN0cmF0aW9uRm9ybS5zZXJpYWxpemUoKTsgXG5cdFx0Zm9ybURhdGEgKz0gJyYnICsgJHJlZ2lzdHJhdGlvbkJ1dHRvbi5hdHRyKCduYW1lJykgKyAnPScgKyAkcmVnaXN0cmF0aW9uQnV0dG9uLmF0dHIoJ3ZhbHVlJyk7XG5cdFx0aWYgKHBhZ2VDb250ZXh0Lm9wdGlvbnMuVG9rZW4pIHtcblx0XHRcdGZvcm1EYXRhICs9ICcmY3NyZl90b2tlbj0nICsgcGFnZUNvbnRleHQub3B0aW9ucy5Ub2tlbjtcblx0XHR9XG5cdFx0XG4gICAgICAgIC8vIFVzaW5nIEFKQVggaW5zdGVhZCBvZiBkZWZhdWx0IEhUTUwgYnV0dG9uIHN1Ym1pdCBmb3IgcmVnaXN0cmF0aW9uIGRpYWxvZyBhbmQgXCJDcmVhdGUgYW4gQWNjb3VudFwiIHBhZ2VcbiAgICAgICAgaWYgKGlzVmFsaWRGb3JtKSB7XG4gICAgICAgICAgICAkKCdib2R5JykubG9hZGluZyhsb2FkaW5nSW5kaWNhdG9yU2V0dGluZ3MpO1xuICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5SRVRFTlRJT05fQ09NX0VOQUJMRUQpIHtcbiAgICAgICAgICAgIFx0Z2VxLnN1cHByZXNzKCk7XG4gICAgICAgICAgICB9ICAgICAgICAgICBcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIHVybDogZm9ybVVybCxcbiAgICAgICAgICAgICAgICBkYXRhOiBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICdyZXN1bHQnIGluIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJlc3VsdCA9PSAnZXJyb3InKSB7XG5cdFx0XHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHRcdGlmIChpc1JlZ2lzdGVyRGlhbG9nIHx8IGlzQ29uZmlybWF0aW9uUGFnZSkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBlcnJvcnNGb3VuZDtcblx0XHRcdFx0XHRcdFx0XHRpZiAoZGF0YS52YWxpZGF0aW9uRXJyb3JzKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRlcnJvcnNGb3VuZCA9IEpTT04ucGFyc2UoZGF0YS52YWxpZGF0aW9uRXJyb3JzKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGVycm9yc0ZvdW5kICYmIE9iamVjdC5rZXlzKGVycm9yc0ZvdW5kKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRmb3IgKHZhciBmaWVsZE5hbWUgaW4gZXJyb3JzRm91bmQpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0JCgnW25hbWUqPVwiJyArZmllbGROYW1lKyAnXCJdJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCQoZXJyb3JzRm91bmRbZmllbGROYW1lXSkucmVtb3ZlQ2xhc3MoJ2Qtbm9uZScpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRlcnJvckhhbmRsaW5nKGRhdGEsICdSZWdpc3RlciAtIEVycm9yJywgZGlhbG9nSHRtbCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gZGF0YS5yZWdpc3RlckRpYWxvZ0NvbnRpbnVlVXJsO1xuXHRcdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEucmVzdWx0ID09ICdzdWNjZXNzJykge1xuXHRcdFx0XHRcdFx0XHQkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdFx0XHQvLyBJZiBhIHJld2FyZHMgYWNjb3VudCB3YXMgZm91bmQgaW4gcmV3YXJkcyBEQiwgdGhlbiB2ZXJpZnkgY3VzdG9tZXIgYW5kIHRpZSBuZXdseSByZWdpc3RlcmVkIGVtYWlsIGFkZHJlc3MgdG8gZXhpc2l0bmcgcmV3YXJkcyBhY2NvdW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCd2YWxpZGF0ZUN1c3RvbWVyJyBpbiBkYXRhICYmIGRhdGEudmFsaWRhdGVDdXN0b21lcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPUkRJQUxfRU5BQkxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRyZWdpc3RyYXRpb25Gb3JtLmF0dHIoJ2lkJykgPT0gJ2R3ZnJtX3Jld2FyZHNyZWdpc3RyYXRpb24nKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJld2FyZHNSZWdpc3RlckNvcmRpYWxFdmVudCgkcmVnaXN0cmF0aW9uRm9ybSwgaXNSZWdpc3RlckRpYWxvZyk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZWdpc3RlckNvcmRpYWxFdmVudCgkcmVnaXN0cmF0aW9uRm9ybSwgaXNSZWdpc3RlckRpYWxvZyk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0XHRcdFx0XHRcdFx0XHR2YXIgbmV3QXR0cmlidXRlcyA9IHtcblx0XHRcdFx0XHRcdFx0XHRcdFwiZGF0YS1tb2RhbC10eXBlXCI6IFwicmVnaXN0ZXJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1jb250aW51ZS11cmxcIjogJ3JlZ2lzdGVyRGlhbG9nQ29udGludWVVcmwnIGluIGRhdGEgPyBkYXRhLnJlZ2lzdGVyRGlhbG9nQ29udGludWVVcmwgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1maXJzdC1uYW1lXCI6ICdjdXN0b21lckZpcnN0TmFtZScgaW4gZGF0YSA/IGRhdGEuY3VzdG9tZXJGaXJzdE5hbWUgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1zdG9yZS1udW1iZXJcIjogJ3N0b3JlRnJvbVByb2ZpbGUnIGluIGRhdGEgPyBkYXRhLnN0b3JlRnJvbVByb2ZpbGUgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGF0YS1jYXJ0LXF1YW50aXR5XCI6ICdjYXJ0UXVhbnRpdHknIGluIGRhdGEgPyBkYXRhLmNhcnRRdWFudGl0eSA6ICcnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpLmh0bWwoZGF0YS52YWxpZGF0ZUN1c3RvbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLmxvZ2luLWRpYWxvZy12YWxpZGF0ZS1jdXN0b21lcicpLmFkZENsYXNzKCd2YWxpZGF0ZS1jdXN0b21lci1zaG93IGZvbGxvdy1hY2NvdW50LWRpYWxvZy1wYXRoJykuYXR0cihuZXdBdHRyaWJ1dGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9yIHJlZ2lzdGVyLWRpYWxvZyBiZWNhdXNlIHRoZSB2YWxpZGF0aW9uIGZvcm0gaXMgb25seSBsb2FkZWQgaW50byBwYWdlIHZpYSBBSkFYLCBzbyBydWxlcyBjYW4ndCBiZSBhZGRlZCB1bnRpbCBmb3JtIGlzIGxvYWRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0QWRkUnVsZXNGb3JDb2RlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGlmIChpc0NvbmZpcm1hdGlvblBhZ2UpIHtcblx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlZGlyZWN0IHRvIE15IEFjY291bnQgaWYgdGhpcyBpcyBhIHJlZ2lzdHJhdGlvbiBmcm9tIG9yZGVyIGNvbmZpcm1hdGlvbiBwYWdlXG5cdFx0XHRcdFx0XHRcdFx0XHRkYXRhLnJlZ2lzdGVyRGlhbG9nQ29udGludWVVcmwgPSBVcmxzLmFjY291bnQ7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGlmIChTaXRlUHJlZmVyZW5jZXMuQ09SRElBTF9FTkFCTEVEKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoJHJlZ2lzdHJhdGlvbkZvcm0uYXR0cignaWQnKSA9PSAnZHdmcm1fcmV3YXJkc3JlZ2lzdHJhdGlvbicpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV3YXJkc1JlZ2lzdGVyQ29yZGlhbEV2ZW50KCRyZWdpc3RyYXRpb25Gb3JtLCBpc1JlZ2lzdGVyRGlhbG9nLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplJywgeyByZXN1bHRzOiBkYXRhLCBpc0FjY291bnREaWFsb2c6IGlzUmVnaXN0ZXJEaWFsb2csIGRpc3BsYXlNZXNzYWdlOiAncmVnaXN0ZXInIH0pO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJlZ2lzdGVyQ29yZGlhbEV2ZW50KCRyZWdpc3RyYXRpb25Gb3JtLCBpc1JlZ2lzdGVyRGlhbG9nLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdQb3N0QWpheEF1dGhlbnRpY2F0aW9uQWN0aW9ucy5Jbml0aWFsaXplJywgeyByZXN1bHRzOiBkYXRhLCBpc0FjY291bnREaWFsb2c6IGlzUmVnaXN0ZXJEaWFsb2csIGRpc3BsYXlNZXNzYWdlOiAncmVnaXN0ZXInIH0pO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignUG9zdEFqYXhBdXRoZW50aWNhdGlvbkFjdGlvbnMuSW5pdGlhbGl6ZScsIHsgcmVzdWx0czogZGF0YSwgaXNBY2NvdW50RGlhbG9nOiBpc1JlZ2lzdGVyRGlhbG9nLCBkaXNwbGF5TWVzc2FnZTogJ3JlZ2lzdGVyJyB9KTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBcdGVycm9ySGFuZGxpbmcoZGF0YSwgJ1JlZ2lzdGVyIC0gRXJyb3InLCBkaWFsb2dIdG1sKTtcblx0XHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoJ2JvZHknKS5sb2FkaW5nKCdkZXN0cm95Jyk7XG5cdFx0XHRcdFx0XHRpZiAoaXNSZWdpc3RlckRpYWxvZykge1xuXHRcdFx0XHRcdFx0XHRlcnJvckhhbmRsaW5nKGRhdGEsICdSZWdpc3RlciAtIEVycm9yJywgZGlhbG9nSHRtbCk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IGxvY2F0aW9uLmhyZWY7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAkKCdib2R5JykubG9hZGluZygnZGVzdHJveScpO1xuXHRcdFx0XHRcdGlmICghaXNSZWdpc3RlckRpYWxvZykge1xuXHRcdFx0XHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXHRcdFx0XHRcdH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSAgXG5cdH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBkaXNwbGF5cyB0aGUgcmVnaXN0cmF0aW9uIGZvcm0gaW4gdGhlIGRpYWxvZyBvbiBidXR0b24gY2xpY2tcbiAqL1xuZnVuY3Rpb24gaW5pdFJlZ2lzdHJhdGlvbkZvcm0oKSB7XG5cdCQoJ2JvZHknKS5vbignY2xpY2snLCAnI3RvZ2dsZS1yZWdpc3RyYXRpb24nLCBmdW5jdGlvbihlKSB7XG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHZhciAkZGlhbG9nID0gJCh0aGlzKS5wYXJlbnRzKCcubG9naW4tZGlhbG9nJyk7XG5cdFx0dmFyICRkaWFsb2dUaXRsZWJhciA9ICRkaWFsb2cuZmluZCgnLnVpLWRpYWxvZy10aXRsZWJhcicpO1xuXHRcdHZhciAkZGlhbG9nQ29udGVudCA9ICRkaWFsb2cuZmluZCgnLnVpLWRpYWxvZy1jb250ZW50Jyk7XG5cdFx0dmFyICRkaWFsb2dGb3Jtc0NvbnRhaW5lciA9ICRkaWFsb2cuZmluZCgnLmxvZ2luLWRpYWxvZy1mb3Jtcy1jb250YWluZXInKTtcblx0XHR2YXIgY2FsY3VsYXRlZFNwYWNpbmcgPSAkKHdpbmRvdykuaGVpZ2h0KCkgKiAwLjIxO1xuXHRcdHZhciBuZXdEaWFsb2dIZWlnaHQgPSAkKHdpbmRvdykuaGVpZ2h0KCkgLSBjYWxjdWxhdGVkU3BhY2luZztcblx0XHR2YXIgbmV3VG9wVmFsdWUgPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCkgKyAoY2FsY3VsYXRlZFNwYWNpbmcgKiAwLjIzMyk7XG5cblx0XHRpZiAoJGRpYWxvZ1RpdGxlYmFyICYmICRkaWFsb2dUaXRsZWJhci5pcyhcIjp2aXNpYmxlXCIpKSB7XG5cdFx0XHRuZXdEaWFsb2dIZWlnaHQgPSBuZXdEaWFsb2dIZWlnaHQgKyAkZGlhbG9nVGl0bGViYXIub3V0ZXJIZWlnaHQoKTtcblx0XHR9XG5cblx0XHR2YXIgcGFkZGluZ1RvcCA9ICczMnB4Jztcblx0XHR2YXIgY3VycmVudFNpdGUgPSBwYWdlQ29udGV4dCAmJiBwYWdlQ29udGV4dC5zaXRlID8gcGFnZUNvbnRleHQuc2l0ZSA6IG51bGw7XG5cdFx0aWYgKChjdXJyZW50U2l0ZSAmJiBjdXJyZW50U2l0ZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5VUykgfHwgKHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lmlzc3RvcmVzaXRlKSkge1xuXHRcdFx0cGFkZGluZ1RvcCA9ICcyOHB4Jztcblx0XHR9XG5cblx0XHQkKCcubG9naW4tZGlhbG9nLXNpZ25pbi1jb250YWluZXIsICN0b2dnbGUtcmVnaXN0cmF0aW9uJykuaGlkZSgpO1xuXHRcdCQoJy5sb2dpbi1kaWFsb2ctcmVnaXN0ZXItZm9ybScpLmFkZENsYXNzKCdyZWdpc3Rlci1mb3JtLXNob3cnKTtcblx0XHQkZGlhbG9nLmNzcyh7XG5cdFx0XHQnaGVpZ2h0JzogbmV3RGlhbG9nSGVpZ2h0KydweCcsXG5cdFx0XHQndG9wJzogbmV3VG9wVmFsdWUrJ3B4Jyxcblx0XHRcdCdvdmVyZmxvdyc6ICd2aXNpYmxlJ1xuXHRcdCAgfSk7XG5cdFx0JGRpYWxvZ0NvbnRlbnQuY3NzKHtcblx0XHRcdCdoZWlnaHQnOiAnMTAwJScsXG5cdFx0XHQncGFkZGluZyc6ICcwIDExcHggMjBweCcsXG5cdFx0XHQncGFkZGluZy10b3AnOiBwYWRkaW5nVG9wXG5cdFx0fSk7XG5cdFx0JGRpYWxvZ0Zvcm1zQ29udGFpbmVyLmNzcygnaGVpZ2h0JywnMTAwJScpO1xuXHR9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKG9wdGlvbnNQYXJhbWV0ZXIpIHtcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnNQYXJhbWV0ZXI7XG5cblx0XHRpbml0UmVnaXN0cmF0aW9uRm9ybSgpO1xuICAgICAgICBpbml0UmVnaXN0cmF0aW9uQnV0dG9uKCk7XG4gICAgfVxufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBTaXRlQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9TaXRlQ29uc3RhbnRzJyk7XG5cbnZhciBzaXRlTmFtZTtcbnZhciAkd2luID0gJCh3aW5kb3cpO1xuXG5cbi8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBDb25maWd1cmVzIHBhcmFtZXRlcnMgYW5kIHJlcXVpcmVkIG9iamVjdCBpbnN0YW5jZXNcbiAgICAgKi9cbmZ1bmN0aW9uIGluaXQgKCkge1xuICAgIHNpdGVOYW1lID0gd2luZG93LnBhZ2VDb250ZXh0LnNpdGUgfHwgJyc7XG5cbiAgICAkKCcudG9wLWJhbm5lciAuaGVhZGVyLXNlYXJjaCBidXR0b24nKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgIHZhciAkc2VhcmNoRm9ybSA9ICR0aGlzLmNsb3Nlc3QoJ2Zvcm0nKTtcbiAgICAgICAgdmFyICRzZWFyY2hJbnB1dCA9ICRzZWFyY2hGb3JtLmZpbmQoJ1tuYW1lPVwicVwiXScpO1xuICAgICAgICB2YXIgYWN0aW9uID0gJHNlYXJjaEZvcm0uYXR0cignYWN0aW9uJyk7XG4gICAgICAgIHZhciBrZXl3b3JkID0gJHNlYXJjaElucHV0LnZhbCgpO1xuICAgICAgICB2YXIgdXJsID0gYWN0aW9uICsgXCI/cT1cIiArIGtleXdvcmQ7XG5cbiAgICAgICAgaWYgKGtleXdvcmQgJiYga2V5d29yZCAhPSAkc2VhcmNoSW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSkge1xuICAgICAgICAgICAgJHNlYXJjaEZvcm0uYXR0cignYWN0aW9uJywgdXJsKTtcbiAgICAgICAgICAgICRzZWFyY2hGb3JtLnN1Ym1pdCgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcbiAgICAgICAgJCgnLmhlYWRlci1zZWFyY2gnKS5vbignY2xpY2snLGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgJCgnLmhlYWRlci1zZWFyY2gnKS5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICQoJy5oZWFkZXItc2VhcmNoIGlucHV0I3EnKS5mb2N1c291dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICQoJy5oZWFkZXItc2VhcmNoJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5QUk9NT1RFRF9TRUFSQ0hFUykge1xuICAgICAgICAkKGRvY3VtZW50KS5vbignZm9jdXMgY2xpY2sga2V5ZG93bicsICcuaGVhZGVyLXNlYXJjaCBpbnB1dCNxLCAuaGVhZGVyLXNlYXJjaCBpbnB1dCNtb2JpbGUtcScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcHJvbW90ZWRTdWdnZXN0aW9ucygpO1xuICAgICAgICAgICAgLy8gVE8tRE86IFdoZW4gdGlja2V0IHBvcHMgdXAgZm9yIHN1Z2dlc3RlZCBzZWFyY2hlcywgY3JlYXRlIGFub3RoZXIgcHJlZmVyZW5jZSBhbmQgYWRkIHRoZSBJRiBzdGF0ZW1lbnQgaGVyZVxuICAgICAgICB9KTtcblxuICAgICAgICAkKGRvY3VtZW50KS5vbignbW91c2VsZWF2ZScsICcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lciwgLmhlYWRlci1zZWFyY2ggW25hbWU9XCJxXCJdJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgdmFyIHNlYXJjaEhlYWRlciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5oZWFkZXItc2VhcmNoJyk7XG4gICAgICAgICAgICBpZiAoIXNlYXJjaEhlYWRlci5jb250YWlucyhlLnJlbGF0ZWRUYXJnZXQpICYmICQoJy5zZWFyY2gtc3VnZ2VzdGlvbnMtY29udGFpbmVyJykuZmluZChlLnJlbGF0ZWRUYXJnZXQpLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgICAgICAgICAkKCcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lcicpLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgJChkb2N1bWVudCkub24oJ2NsaWNrJywgJy5jbG9zZS1zZWFyY2gtc3VnZ2VzdGlvbnMnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICQoJy5zZWFyY2gtc3VnZ2VzdGlvbnMtY29udGFpbmVyJykuaGlkZSgpO1xuICAgICAgICB9KTsgIFxuICAgICAgICBcbiAgICAgICAgJChkb2N1bWVudCkub2ZmKCdTZWFyY2hCYXIuRXhwYW5kJykub24oJ1NlYXJjaEJhci5FeHBhbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGV4cGFuZCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkKGRvY3VtZW50KS5vZmYoJ1NlYXJjaEJhci5TY3JvbGxUb3AnKS5vbignU2VhcmNoQmFyLlNjcm9sbFRvcCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2Nyb2xsVG9wKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICQoZG9jdW1lbnQpLm9mZignU2VhcmNoQmFyLkhpZGUnKS5vbignU2VhcmNoQmFyLkhpZGUnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGhpZGUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uXG4gKi9cbmZ1bmN0aW9uIGV4cGFuZCAoKSB7XG4gICAgJCgnLnRvcC1iYW5uZXInKS50b2dnbGVDbGFzcygnc2VhcmNoLWVuYWJsZWQnKTtcbiAgICB2YXIgJHRhcmdldCA9ICQoJy5oZWFkZXItc2VhcmNoJyk7XG4gICAgaWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5Db3VudHJ5T3V0Zml0dGVyc1VTKSB7XG4gICAgICAgICR0YXJnZXQgPSAkKCcuc2VhcmNoLWhvbGRlcicpO1xuICAgIH1cbiAgICAgICAgICAgIFxuICAgIGlmICgoc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLlNoZXBsZXJzVVMgfHwgc2l0ZU5hbWUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkNvdW50cnlPdXRmaXR0ZXJzVVMpICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSkge1xuICAgICAgICAkdGFyZ2V0LmNzcygndG9wJywgJCgnLnRvcC1iYW5uZXItYmFyJykub3V0ZXJIZWlnaHQoKSArICQoJy50b3AtYmFubmVyLWlubmVyJykub3V0ZXJIZWlnaHQoKSAtICR3aW4uc2Nyb2xsVG9wKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICR0YXJnZXQuY3NzKCd0b3AnLCAnJyk7XG4gICAgfVxuICAgICAgICAgICAgXG4gICAgaWYgKHNpdGVOYW1lID09IFNpdGVDb25zdGFudHMuU2l0ZUlkcy5TaGVwbGVyc1VTKSB7XG4gICAgICAgICR0YXJnZXQuZmluZCgnaW5wdXRbdHlwZT1cInRleHRcIl0nKS5mb2N1cygpO1xuICAgIH1cbiAgICAgICAgICAgIFxuICAgIGlmICgkKCcudG9wLWJhbm5lcicpLmhhc0NsYXNzKCdzZWFyY2gtZW5hYmxlZCcpICYmICQoJ2h0bWwnKS5oYXNDbGFzcygnc2l6ZS1tb2JpbGUnKSAmJiAkKCcudG9wLWJhbm5lci1iYXInKS5hdHRyKCdkYXRhLWhlYWRlci1mb3InKSA9PSAnYm9vdGJhcm5fdXMnKSB7XG4gICAgICAgICQoJyNzZWFyY2ggI3EnKS5mb2N1cygpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvblxuICovXG5mdW5jdGlvbiBzY3JvbGxUb3AgKCkge1xuICAgIGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuU2hlcGxlcnNVUyB8fCBzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuICAgICAgICB2YXIgJHRhcmdldCA9ICQoJy5oZWFkZXItc2VhcmNoJyk7XG4gICAgICAgIGlmIChzaXRlTmFtZSA9PSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQ291bnRyeU91dGZpdHRlcnNVUykge1xuICAgICAgICAgICAgJHRhcmdldCA9ICQoJy5zZWFyY2gtaG9sZGVyJyk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmICgkKCdodG1sJykuaGFzQ2xhc3MoJ3NpemUtbW9iaWxlJykpIHtcbiAgICAgICAgICAgICR0YXJnZXQuY3NzKCd0b3AnLCAkKCcudG9wLWJhbm5lci1iYXInKS5vdXRlckhlaWdodCgpICsgJCgnLnRvcC1iYW5uZXItaW5uZXInKS5vdXRlckhlaWdodCgpIC0gJHdpbi5zY3JvbGxUb3AoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkdGFyZ2V0LmNzcygndG9wJywgJycpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uXG4gKi9cbmZ1bmN0aW9uIGhpZGUgKCkge1xuICAgIGlmKCQoJy5oZWFkZXItc2VhcmNoJykuaGFzQ2xhc3MoJ3Nob3cnKSkge1xuICAgICAgICAkKCcuaGVhZGVyLXNlYXJjaCcpLnJlbW92ZUNsYXNzKCdzaG93Jyk7XG4gICAgICAgIGlmIChzaXRlTmFtZSAhPSBTaXRlQ29uc3RhbnRzLlNpdGVJZHMuQm9vdEJhcm5Sc3BVUykge1xuICAgICAgICAgICAgJCgnLnRvcC1iYW5uZXInKS5yZW1vdmVDbGFzcygnc2VhcmNoLWVuYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiB0cmlnZ2VyIHByb21vdGVkIHN1Z2dlc3Rpb25zIGZvciBzaXRlIHNlYXJjaFxuICovXG5mdW5jdGlvbiBwcm9tb3RlZFN1Z2dlc3Rpb25zICgpIHtcbiAgICB2YXIgaXNDb250ZW50UG9wdWxhdGVkID0gJCgnLnNlYXJjaC1zdWdnZXN0aW9ucy1jb250YWluZXIgPiBkaXYnKS5sZW5ndGggPiAwO1xuICAgIGlmICgkKCcuc2VhcmNoLXN1Z2dlc3Rpb25zLWNvbnRhaW5lcicpLmlzKCc6aGlkZGVuJykgJiYgaXNDb250ZW50UG9wdWxhdGVkKSB7XG4gICAgICAgICQoJy5zZWFyY2gtc3VnZ2VzdGlvbnMtY29udGFpbmVyJykuc2hvdygpO1xuICAgIH1cbn1cblxuZXhwb3J0cy5pbml0ID0gaW5pdDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgZXZlbnQgdG8gdGhlIHBsYWNlIGhvbGRlciAoLmJsdXIpXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgJCgnI3EnKS5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgIGlmIChpbnB1dC52YWwoKSA9PT0gaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSkge1xuICAgICAgICAgICAgaW5wdXQudmFsKCcnKTtcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLmJsdXIoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICBpZiAoaW5wdXQudmFsKCkgPT09ICcnIHx8IGlucHV0LnZhbCgpID09PSBpbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpKSB7XG4gICAgICAgICAgICBpbnB1dC52YWwoaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSk7XG4gICAgICAgIH1cbiAgICB9KVxuICAgIC5ibHVyKCk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGluaXRpYWxpemVFdmVudHM7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYWdlID0gcmVxdWlyZSgnLi9wYWdlJyk7XG5cbnZhciBpc1RvdWNoTW92ZWQgPSBmYWxzZTtcbnZhciBpc0N1cnJlbnRUYXJnZXRTd2F0Y2ggPSBmYWxzZTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcblx0JChkb2N1bWVudCkub2ZmKCdjbGljay5Td2F0Y2guTWVudS5DbG9zZScpLm9uKCdjbGljay5Td2F0Y2guTWVudS5DbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdHZhciAkY3VycmVudFRhcmdldCA9ICQoZXZlbnQuY3VycmVudFRhcmdldCk7XG5cdFx0XG5cdFx0aWYgKCRjdXJyZW50VGFyZ2V0LmNsb3Nlc3QoJy5zbGlkZS1kb3duLXN3YXRjaCcpLmxlbmd0aCA9PSAwKSB7XG5cdFx0XHQkKCcuc2xpZGUtZG93bi1zd2F0Y2ggdWwnKS5zbGlkZVVwKCk7XG5cdFx0fVxuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9mZigndG91Y2hzdGFydC5Td2F0Y2guTWVudS5DbG9zZScpLm9uKCd0b3VjaHN0YXJ0LlN3YXRjaC5NZW51LkNsb3NlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0dmFyICRjdXJyZW50VGFyZ2V0ID0gJChldmVudC5jdXJyZW50VGFyZ2V0KTtcblx0XHRcblx0XHRpc1RvdWNoTW92ZWQgPSBmYWxzZTtcblx0XHRpc0N1cnJlbnRUYXJnZXRTd2F0Y2ggPSAkY3VycmVudFRhcmdldC5jbG9zZXN0KCcuc2xpZGUtZG93bi1zd2F0Y2gnKS5sZW5ndGggPiAwO1xuXHR9KTtcblx0XG5cdCQoZG9jdW1lbnQpLm9mZigndG91Y2htb3ZlLlN3YXRjaC5NZW51LkNsb3NlJykub24oJ3RvdWNobW92ZS5Td2F0Y2guTWVudS5DbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGlzVG91Y2hNb3ZlZCA9IHRydWU7XG5cdH0pO1xuXHRcblx0JChkb2N1bWVudCkub2ZmKCd0b3VjaGVuZC5Td2F0Y2guTWVudS5DbG9zZScpLm9uKCd0b3VjaGVuZC5Td2F0Y2guTWVudS5DbG9zZScsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdGlmICghaXNDdXJyZW50VGFyZ2V0U3dhdGNoICYmICFpc1RvdWNoTW92ZWQpIHtcblx0XHRcdCQoJy5zbGlkZS1kb3duLXN3YXRjaCB1bCcpLnNsaWRlVXAoKTtcblx0XHR9XG5cdH0pO1xuXHRcblx0JCgnLnN3YXRjaGVzLnNpemUgPiBsaSA+IGEuc2xpZGUtZG93bicpLm9uKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0XG5cdFx0JCh0aGlzKVxuXHRcdC5uZXh0KCd1bCcpXG5cdFx0LnN0b3AoKVxuXHRcdC5zbGlkZVRvZ2dsZSgpXG5cdFx0LnBhcmVudCgpXG5cdFx0LnNpYmxpbmdzKClcblx0XHQuY2hpbGRyZW4oJ3VsJylcblx0XHQuc2xpZGVVcCgpXG5cdFx0LnByZXYoJy5zbGlkZS1kb3duJyk7XG5cdH0pO1xuXG5cdC8vIERlZmF1bHQgc2VsZWN0ZWQgdmFsdWUgYXMgc2xpZGUgZG93blxuXHQkKCcuc3dhdGNoZXMuc2l6ZSA+IGxpID4gYS5zbGlkZS1kb3duJylcblx0Lm5leHQoJ3VsJylcblx0LmZpbmQoJy5jdXJyZW50Jylcblx0LmNsb3Nlc3QoJ3VsJylcblx0LnByZXYoJy5zbGlkZS1kb3duJylcblx0LmFkZENsYXNzKCdjdXJyZW50Jylcblx0LmNsb3Nlc3QoJ2xpJykuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXG5cdCQoJy5yZWZpbmVtZW50cyAuc3dhdGNoZXMuc2l6ZSA+IGxpLmFjdGl2ZSA+IHVsJykuc2xpZGVEb3duKCk7XG5cblx0JCgnLnN3YXRjaGVzID4gbGkuc2xpZGUtZG93bi1zd2F0Y2ggPiB1bCcpLm9mZignY2xpY2snKTtcblxuXHQvLyBSZW1vdmUgZW1wdHkgdGlsZXMgXG5cdCQoJy5zd2F0Y2hlcy5zaXplID4gbGkgPiBhLnNsaWRlLWRvd24nKS5uZXh0KCd1bCcpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCQodGhpcykuZmluZCgnbGknKS5sZW5ndGggPT09IDApIHtcblx0XHRcdCQodGhpcykuY2xvc2VzdCgnbGknKS5yZW1vdmUoKTtcblx0XHR9XG5cdH0pO1xufVxuXG52YXIgc2l6ZVJlZmluZW1lbnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbigpIHtcblx0XHRpbml0aWFsaXplRXZlbnRzKCk7XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2l6ZVJlZmluZW1lbnRzOyIsIid1c2Ugc3RyaWN0JztcblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogQURBIFNsaWNrIE1vZHNcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiBpbml0ICgpIHtcbiAgICAkKGRvY3VtZW50KS5vZmYoJ1NsaWNrU2xpZGVyQWNjZXNzaWJpbGl0eU1vZHMnKS5vbignU2xpY2tTbGlkZXJBY2Nlc3NpYmlsaXR5TW9kcycsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICQoJy5zbGljay1zbGlkZXIgLnNsaWNrLXNsaWRlLCAuc2xpY2stc2xpZGVyIC5zbGljay1hY3RpdmUnKS5yZW1vdmVBdHRyKCdhcmlhLWRlc2NyaWJlZGJ5IHJvbGUgdGFiaW5kZXgnKTtcdFx0XHRcbiAgICAgICAgJCgnLnNsaWNrLXNsaWRlciAuc2xpY2stZG90cyBidXR0b24nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGJ1dHRvblZhbCA9ICQodGhpcykuaHRtbCgpO1xuICAgICAgICAgICAgdmFyIGFkZFNwYW4gPSAnPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj4nICsgYnV0dG9uVmFsICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgJCh0aGlzKS5odG1sKGFkZFNwYW4pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAtLSBTbGlkZXJzIC0tXG4gKiBcbiAqIENvbmZpZ3VyYXRpb24gT3B0aW9uczpcbiAqICAgICAgICAgICAgICAgIGxvb3A6ICBCT09MRUFOICBCb3RoOyBJZiBubyBvcHRpb24gZ2l2ZW4sIHByb2dyYW1tYXRpY2FsbHkgc2V0IHRvIHRydWUuXG4gKiAgICAgICAgICAgICAgICBkb3RzOiAgQk9PTEVBTiAgQm90aDsgSWYgbm8gb3B0aW9uIGdpdmVuLCBwcm9ncmFtbWF0aWNhbGx5IHNldCB0byB0cnVlLlxuICogICAgICAgICAgcGFnaW5hdGlvbjogIE9CSkVDVCAgIFN3aXBlciBvbmx5OyBJZiBubyBvcHRpb24gZ2l2ZW4sIHBhZ2luYXRpb24gaXMgb21pdHRlZCBmcm9tIHNsaWRlciBzZXR0aW5ncy5cbiAqICAgICAgICAgICAgICBhcnJvd3M6ICBCT09MRUFOICBCb3RoOyBJZiBubyBvcHRpb24gZ2l2ZW4sIGF1dG9tYXRpY2FsbHkgc2V0IHRvIHRydWUgaW4gd2lkZ2V0IGJhY2tncm91bmQuXG4gKiAgICAgIGFycm93c1Bvc2l0aW9uOiAgU1RSSU5HICAgWydpbnNpZGUnIG9yICdvdXRzaWRlJ10gU3dpcGVyIG9ubHk7IElmIG5vIG9wdGlvbiBnaXZlbiwgYXV0b21hdGljYWxseSBzZXQgdG8gdGhlIG91dHNpZGUuXG4gKiAgICAgICAgICBuYXZpZ2F0aW9uOiAgT0JKRUNUICAgU3dpcGVyIG9ubHk7IElmIG5vIG9wdGlvbiBnaXZlbiwgbmF2aWdhdGlvbiBpcyBvbWl0dGVkIGZyb20gc2xpZGVyIHNldHRpbmdzLlxuICogICAgICAgIHNsaWRlc1RvU2hvdzogIE5VTUJFUiAgIEJvdGg7IElmIG5vIG9wdGlvbiBnaXZlbiwgcHJvZ3JhbW1hdGljYWxseSBzZXQgdG8gMS5cbiAqICAgICAgc2xpZGVzVG9TY3JvbGw6ICBOVU1CRVIgICBCb3RoOyBJZiBubyBvcHRpb24gZ2l2ZW4sIHByb2dyYW1tYXRpY2FsbHkgc2V0IHRvIDEuXG4gKiAgICAgICAgICAgIGF1dG9wbGF5OiAgTlVNQkVSICAgQm90aDsgV2hlbiBnaXZlbiwgbnVtYmVyIGlzIHByb2dyYW1tYXRpY2FsbHkgc2V0IHRvIEF1dG9wbGF5IFNwZWVkIGFuZCBBdXRvcGxheSBpcyBzZXQgdG8gdHJ1ZS4gSWYgbm8gb3B0aW9uIGdpdmVuLCBhdXRvcGxheSBpcyBzZXQgdG8gZmFsc2UuXG4gKiAgICAgICAgIGJyZWFrcG9pbnRzOiAgT0JKRUNUICAgQm90aDsgUHJvcGVydGllcyBhcmUgbG9vcGVkIG92ZXIgdG8gYXBwbHkgdmFyaW91cyBicmVha3BvaW50IHNldHRpbmdzLiBJZiBubyBvcHRpb24gZ2l2ZW4sIGJyZWFrcG9pbnRzIGlzIG9taXR0ZWQgZnJvbSBzbGlkZXIgc2V0dGluZ3MuXG4gKiAgICAgXG4gKiBFeGFtcGxlIENvZGU6XG4gKiAgICAgICAgc2xpZGVycy5pbml0KCcuc29tZS1jbGFzcy1uYW1lJywgXG4gKiAgICAgICAge1xuICogICAgICAgICAgICAgbG9vcDogdHJ1ZSwgXG4gKiAgICAgICAgICAgICBkb3RzOiB0cnVlLCBcbiAqICAgICAgICAgICAgIHBhZ2luYXRpb246IHtlbDogJy5zd2lwZXItcGFnaW5hdGlvbicsIGNsaWNrYWJsZTogdHJ1ZX0sIFxuICogICAgICAgICAgICAgYXJyb3dzOiB0cnVlLFxuICogICAgICAgICAgICAgYXJyb3dzUG9zaXRpb246ICdpbnNpZGUnLFxuICogICAgICAgICAgICAgbmF2aWdhdGlvbjoge25leHRFbDogJy5zd2lwZXItYnV0dG9uLW5leHQnLCBwcmV2RWw6ICcuc3dpcGVyLWJ1dHRvbi1wcmV2J30sXG4gKiAgICAgICAgICAgICBzbGlkZXNUb1Nob3c6IDYsXG4gKiAgICAgICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcbiAqICAgICAgICAgICAgIGF1dG9wbGF5OiAzMDAwLFxuICogICAgICAgICAgICAgYnJlYWtwb2ludHM6IHswOiB7c2xpZGVzVG9TaG93OiAxfSwgNzY4OiB7c2xpZGVzVG9TaG93OiAzfX1cbiAqICAgICAgICB9KTtcbiAqIFxuICogXG4gKiBBZGRpdGlvbmFsIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBleGlzdCBmb3IgYm90aCBzbGlkZXJzLCBidXQgYWRkaXRpb25hbCBjb2RlIGNoYW5nZXMgd291bGQgYmUgbmVlZGVkIHRvIGluY2x1ZGUgdGhlbS4gXG4gKiBcbiAqIFJlZmVyZW5jZSBzbGlkZXIgZG9jdW1lbnRhdGlvbjpcbiAqIFxuICogU3dpcGVyIGRvY3VtZW50YXRpb24gLSBodHRwczovL3N3aXBlcmpzLmNvbS9zd2lwZXItYXBpXG4gKiBTbGljayBkb2N1bWVudGF0aW9uIC0gaHR0cHM6Ly9rZW53aGVlbGVyLmdpdGh1Yi5pby9zbGljay9cbiAqICBcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgU2l0ZUNvbnN0YW50cyA9IHJlcXVpcmUoJy4uLy4uLy4uL2JjX3NoZXBsZXJzYm9vdGJhcm5fY29yZS9jYXJ0cmlkZ2UvanMvU2l0ZUNvbnN0YW50cycpO1xuXG5leHBvcnRzLmluaXQgPSBpbml0O1xuZXhwb3J0cy5pbml0aWFsaXplQ2F0ZWdvcnlTbGlkZXJzID0gaW5pdGlhbGl6ZUNhdGVnb3J5U2xpZGVycztcbmV4cG9ydHMuaW5pdGlhbGl6ZVJlY29tbWVuZGF0aW9uU2xpZGVyID0gaW5pdGlhbGl6ZVJlY29tbWVuZGF0aW9uU2xpZGVyO1xuXG5mdW5jdGlvbiBnZXRVbmlxdWVOdW1iZXIoKSB7XG5cdHZhciBkYXRlT2JqZWN0ID0gbmV3IERhdGUoKTtcblx0dmFyIHVuaXF1ZU51bWJlciA9IGRhdGVPYmplY3QudmFsdWVPZigpO1xuICAgIHZhciBzdWZmaXhOdW1iZXIgPSAxICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwKTtcbiAgICB1bmlxdWVOdW1iZXIgPSB1bmlxdWVOdW1iZXIgKyBzdWZmaXhOdW1iZXI7XG5cdHJldHVybiB1bmlxdWVOdW1iZXI7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRlZFNsaWNrQnJlYWtwb2ludFNpemUoYnJlYWtwb2ludFNpemUsIGJyZWFrcG9pbnRTaXplQXJyYXkpIHtcbiAgICB2YXIgc29ydGVkQnJlYWtwb2ludFNpemVzID0gYnJlYWtwb2ludFNpemVBcnJheS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhIC0gYjsgfSk7XG4gICAgdmFyIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplO1xuICAgIFxuICAgIGlmIChicmVha3BvaW50U2l6ZSA9PSAwKSB7XG4gICAgICAgIHZhciBtb2JpbGVNYXhTaXplID0gc29ydGVkQnJlYWtwb2ludFNpemVzW3NvcnRlZEJyZWFrcG9pbnRTaXplcy5pbmRleE9mKDApICsgMV07XG4gICAgICAgIGlmIChtb2JpbGVNYXhTaXplKSB7XG4gICAgICAgICAgICBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9IG1vYmlsZU1heFNpemUgLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udmVydGVkQnJlYWtwb2ludFNpemUgPSA3Njc7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGJyZWFrcG9pbnRTaXplID09IDc2OCkge1xuICAgICAgICB2YXIgZGVza3RvcE1heFNpemUgPSBzb3J0ZWRCcmVha3BvaW50U2l6ZXNbc29ydGVkQnJlYWtwb2ludFNpemVzLmluZGV4T2YoNzY4KSArIDFdO1xuICAgICAgICBpZiAoZGVza3RvcE1heFNpemUpIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID0gZGVza3RvcE1heFNpemUgLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udmVydGVkQnJlYWtwb2ludFNpemUgPSA5OTk5O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGJyZWFrcG9pbnRNYXhTaXplID0gc29ydGVkQnJlYWtwb2ludFNpemVzW3NvcnRlZEJyZWFrcG9pbnRTaXplcy5pbmRleE9mKGJyZWFrcG9pbnRTaXplKSArIDFdO1xuICAgICAgICBpZiAoYnJlYWtwb2ludE1heFNpemUpIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID0gYnJlYWtwb2ludE1heFNpemUgLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udmVydGVkQnJlYWtwb2ludFNpemUgPSA5OTk5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplO1xufVxuXG5mdW5jdGlvbiBpbml0U2xpY2soZWxlbWVudFNlbGVjdG9yLCBzZXR0aW5ncykge1xuICAgIGlmICghZWxlbWVudFNlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgc2xpZGVyU2V0dGluZ3MgPSB7XG4gICAgICAgIGluZmluaXRlOiB0cnVlLFxuICAgICAgICBzbGlkZXNUb1Nob3c6IDEsXG4gICAgICAgIHNsaWRlc1RvU2Nyb2xsOiAxXG4gICAgfTtcbiAgICBpZiAoc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKCdsb29wJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuaW5maW5pdGUgPSBzZXR0aW5ncy5sb29wO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnZG90cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmRvdHMgPSBzZXR0aW5ncy5kb3RzO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnYXJyb3dzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXJyb3dzID0gc2V0dGluZ3MuYXJyb3dzO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnc2xpZGVzVG9TaG93JyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3Muc2xpZGVzVG9TaG93ID0gc2V0dGluZ3Muc2xpZGVzVG9TaG93O1xuICAgICAgICB9XG4gICAgICAgIGlmICgnc2xpZGVzVG9TY3JvbGwnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5zbGlkZXNUb1Njcm9sbCA9IHNldHRpbmdzLnNsaWRlc1RvU2Nyb2xsO1xuICAgICAgICB9XG4gICAgICAgIGlmICgnYXV0b3BsYXknIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5hdXRvcGxheVNwZWVkID0gc2V0dGluZ3MuYXV0b3BsYXk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdicmVha3BvaW50cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLnJlc3BvbnNpdmUgPSBbXTtcbiAgICAgICAgICAgIHZhciBicmVha3BvaW50U2l6ZUFycmF5ID0gT2JqZWN0LmtleXMoc2V0dGluZ3MuYnJlYWtwb2ludHMpLm1hcChmdW5jdGlvbiAoeCkgeyBcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQoeCk7IC8vIEV4dHJhIHByZWNhdXRpb24gb2Ygc2FuaXRpemluZyBkYXRhIGZvciB1c2UgaW4gbWF0aGVtYXRpY2FsIGVxdWF0aW9uc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmb3IgKHZhciBicmVha3BvaW50U2l6ZSBpbiBzZXR0aW5ncy5icmVha3BvaW50cykge1xuICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTaXplID0gcGFyc2VJbnQoYnJlYWtwb2ludFNpemUpO1xuICAgICAgICAgICAgICAgIHZhciBjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9IGNvbnZlcnRlZFNsaWNrQnJlYWtwb2ludFNpemUoYnJlYWtwb2ludFNpemUsIGJyZWFrcG9pbnRTaXplQXJyYXkpO1xuICAgICAgICAgICAgICAgIHZhciBicmVha3BvaW50U2V0dGluZ3NPYmplY3QgPSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnQ6IGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplLFxuICAgICAgICAgICAgICAgICAgICBzZXR0aW5nczoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHZhciBicmVha3BvaW50U2l6ZVNldHRpbmdzID0gc2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHNpemVTZXR0aW5nIGluIGJyZWFrcG9pbnRTaXplU2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCdsb29wJyA9PSBzaXplU2V0dGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0LnNldHRpbmdzLmluZmluaXRlID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdkb3RzJyA9PSBzaXplU2V0dGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0LnNldHRpbmdzLmRvdHMgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ2Fycm93cycgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdC5zZXR0aW5ncy5hcnJvd3MgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ3NsaWRlc1RvU2hvdycgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb252ZXJ0ZWRCcmVha3BvaW50U2l6ZSA9PSA5OTk5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3Muc2xpZGVzVG9TaG93ID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdC5zZXR0aW5ncy5zbGlkZXNUb1Nob3cgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ3NsaWRlc1RvU2Nyb2xsJyA9PSBzaXplU2V0dGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID09IDk5OTkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5zbGlkZXNUb1Njcm9sbCA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50U2V0dGluZ3NPYmplY3Quc2V0dGluZ3Muc2xpZGVzVG9TY3JvbGwgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ2F1dG9wbGF5JyA9PSBzaXplU2V0dGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnZlcnRlZEJyZWFrcG9pbnRTaXplID09IDk5OTkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXlTcGVlZCA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddLmF1dG9wbGF5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50U2V0dGluZ3NPYmplY3Quc2V0dGluZ3MuYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcG9pbnRTZXR0aW5nc09iamVjdC5zZXR0aW5ncy5hdXRvcGxheVNwZWVkID0gYnJlYWtwb2ludFNpemVTZXR0aW5nc1tzaXplU2V0dGluZ107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy9pZiAoY29udmVydGVkQnJlYWtwb2ludFNpemUgIT0gOTk5OSkge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5yZXNwb25zaXZlLnB1c2goYnJlYWtwb2ludFNldHRpbmdzT2JqZWN0KTtcbiAgICAgICAgICAgICAgICAvL31cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgICQoZWxlbWVudFNlbGVjdG9yKS5zbGljayhzbGlkZXJTZXR0aW5ncyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJChlbGVtZW50U2VsZWN0b3IpLnNsaWNrKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpbml0U3dpcGVyKGVsZW1lbnRTZWxlY3Rvciwgc2V0dGluZ3MsIGNsYXNzZXNGb3JTZXR0aW5ncykge1xuICAgIGlmICghZWxlbWVudFNlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgc2xpZGVyU2V0dGluZ3MgPSB7XG4gICAgICAgIGxvb3A6IHRydWUsXG4gICAgICAgIHNwYWNlQmV0d2VlbjogMjAsXG4gICAgICAgIHByZXZlbnRJbnRlcmFjdGlvbk9uVHJhbnNpdGlvbjogdHJ1ZSxcbiAgICAgICAgYTExeToge1xuICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgIGZpcnN0U2xpZGVNZXNzYWdlOiAnVGhpcyBpcyB0aGUgZmlyc3Qgc2xpZGUnLFxuICAgICAgICAgICAgbGFzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGxhc3Qgc2xpZGUnXG4gICAgICAgIH0sXG4gICAgICAgIGtleWJvYXJkOiB7XG5cdFx0XHRlbmFibGVkOiB0cnVlLFxuXHRcdFx0cGFnZVVwRG93bjogdHJ1ZVxuXHRcdH1cbiAgICB9O1xuICAgIGlmIChzZXR0aW5ncykge1xuICAgICAgICBpZiAoJ2xvb3AnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5sb29wID0gc2V0dGluZ3MubG9vcDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ3BhZ2luYXRpb24nIGluIHNldHRpbmdzIHx8ICdkb3RzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLnBhZ2luYXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoJ2VsJyBpbiBzZXR0aW5ncy5wYWdpbmF0aW9uICYmIHNldHRpbmdzLnBhZ2luYXRpb24uZWwubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5wYWdpbmF0aW9uID0gc2V0dGluZ3MucGFnaW5hdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzZXR0aW5ncy5kb3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLnBhZ2luYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbDogJy5zd2lwZXItcGFnaW5hdGlvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGlja2FibGU6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBcbiAgICAgICAgaWYgKCduYXZpZ2F0aW9uJyBpbiBzZXR0aW5ncyB8fCAnYXJyb3dzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLm5hdmlnYXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoJ25leHRFbCcgaW4gc2V0dGluZ3MubmF2aWdhdGlvbiAmJiBzZXR0aW5ncy5uYXZpZ2F0aW9uLm5leHRFbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLm5hdmlnYXRpb24gPSBzZXR0aW5ncy5uYXZpZ2F0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHNldHRpbmdzLmFycm93cykge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5uYXZpZ2F0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEVsOiAnLnN3aXBlci1idXR0b24tbmV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2RWw6ICcuc3dpcGVyLWJ1dHRvbi1wcmV2J1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICgnc2xpZGVzVG9TaG93JyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3Muc2xpZGVzUGVyVmlldyA9IHNldHRpbmdzLnNsaWRlc1RvU2hvdztcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2F1dG9wbGF5JyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXkgPSB7XG4gICAgICAgICAgICAgICAgZGVsYXk6IHNldHRpbmdzLmF1dG9wbGF5LFxuICAgICAgICAgICAgICAgIGRpc2FibGVPbkludGVyYWN0aW9uOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICgnYnJlYWtwb2ludHMnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50cyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYnJlYWtwb2ludFNpemUgaW4gc2V0dGluZ3MuYnJlYWtwb2ludHMpIHtcbiAgICAgICAgICAgICAgICBicmVha3BvaW50U2l6ZSA9IHBhcnNlSW50KGJyZWFrcG9pbnRTaXplKTtcbiAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgYnJlYWtwb2ludFNpemVTZXR0aW5ncyA9IHNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBzaXplU2V0dGluZyBpbiBicmVha3BvaW50U2l6ZVNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgnbG9vcCcgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmxvb3AgPSBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ2RvdHMnID09IHNpemVTZXR0aW5nICYmIGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddID09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXS5wYWdpbmF0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWQ6IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Nbc2l6ZVNldHRpbmddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsOiAnLnN3aXBlci1wYWdpbmF0aW9uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlja2FibGU6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlc0ZvclNldHRpbmdzICYmIGNsYXNzZXNGb3JTZXR0aW5ncy5wYWdpbmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdLnBhZ2luYXRpb24uZWwgPSBjbGFzc2VzRm9yU2V0dGluZ3MucGFnaW5hdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gIFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgnYXJyb3dzJyA9PSBzaXplU2V0dGluZyAmJiBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXSA9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0ubmF2aWdhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkOiBicmVha3BvaW50U2l6ZVNldHRpbmdzW3NpemVTZXR0aW5nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0RWw6ICcuc3dpcGVyLWJ1dHRvbi1uZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2RWw6ICcuc3dpcGVyLWJ1dHRvbi1wcmV2J1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzRm9yU2V0dGluZ3MgJiYgY2xhc3Nlc0ZvclNldHRpbmdzLm5leHQgJiYgY2xhc3Nlc0ZvclNldHRpbmdzLnByZXYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0ubmF2aWdhdGlvbi5uZXh0RWwgPSBjbGFzc2VzRm9yU2V0dGluZ3MubmV4dDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0ubmF2aWdhdGlvbi5wcmV2RWwgPSBjbGFzc2VzRm9yU2V0dGluZ3MucHJldjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoJ3NsaWRlc1RvU2hvdycgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXS5zbGlkZXNQZXJWaWV3ID0gYnJlYWtwb2ludFNpemVTZXR0aW5ncy5zbGlkZXNUb1Nob3c7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdzbGlkZXNUb1Njcm9sbCcgPT0gc2l6ZVNldHRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWRlclNldHRpbmdzLmJyZWFrcG9pbnRzW2JyZWFrcG9pbnRTaXplXS5zbGlkZXNQZXJHcm91cCA9IGJyZWFrcG9pbnRTaXplU2V0dGluZ3Muc2xpZGVzVG9TY3JvbGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCdhdXRvcGxheScgaW4gYnJlYWtwb2ludFNpemVTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpZGVyU2V0dGluZ3MuYXV0b3BsYXkgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXk6IGJyZWFrcG9pbnRTaXplU2V0dGluZ3MuYXV0b3BsYXksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZU9uSW50ZXJhY3Rpb246IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbGlkZXJTZXR0aW5ncy5icmVha3BvaW50c1ticmVha3BvaW50U2l6ZV0uYXV0b3BsYXkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gbmV3IFN3aXBlciAoZWxlbWVudFNlbGVjdG9yLCBzbGlkZXJTZXR0aW5ncyk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFNsaWNrSFRNTCgkZWxlbWVudCwgc2V0dGluZ3MsIGlzRWluc3RlaW4pIHtcbiAgICB2YXIgb3JpZ2luYWxTbGlkZUVsZW1lbnRzID0gJGVsZW1lbnQuY2hpbGRyZW4oKS50b0FycmF5KCk7XG4gICAgdmFyIHVuaXF1ZVNsaWRlcjtcblxuICAgIGlmICgkZWxlbWVudC5hdHRyKCdpZCcpICYmICRlbGVtZW50LmF0dHIoJ2lkJykuaW5kZXhPZignc2xpZGVyLWluZGV4JykgPiAtMSkge1xuICAgICAgICB1bmlxdWVTbGlkZXIgPSAkZWxlbWVudC5hdHRyKCdpZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaXF1ZVNsaWRlciA9ICdzbGlkZXItaW5kZXgtJyArIGdldFVuaXF1ZU51bWJlcigpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgJGVsZW1lbnQuYXR0cignaWQnLCB1bmlxdWVTbGlkZXIpO1xuXG4gICAgLy8gRWluc3RlaW4gQ1F1b3RpZW50IHNjcmlwdHMgYXJlIG1peGVkIGluIHdpdGggc2xpZGVzIGF0IHRpbWUgb2Ygc2xpZGVyIGluaXRpYWxpemF0aW9uLiBSZXdvcmsgdGhlIEhUTUwgc3RydWN0dXJlLlxuICAgIGlmIChvcmlnaW5hbFNsaWRlRWxlbWVudHMubGVuZ3RoID4gMCAmJiBpc0VpbnN0ZWluKSB7XG4gICAgICAgIHZhciBtb2RpZmllZFNsaWRlRWxlbWVudHMgPSBbXTtcbiAgICAgICAgdmFyIGNxU2NyaXB0cyA9IFtdO1xuXG4gICAgICAgICQuZWFjaChvcmlnaW5hbFNsaWRlRWxlbWVudHMsIGZ1bmN0aW9uKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdTQ1JJUFQnKSB7XG4gICAgICAgICAgICAgICAgY3FTY3JpcHRzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKSA9PT0gJ0xJJykge1xuICAgICAgICAgICAgICAgICAgICBtb2RpZmllZFNsaWRlRWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9ICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGNxU2NyaXB0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkZWxlbWVudC5jbG9zZXN0KCdkaXYuc2xpZGVyLWNsaXAnKS5hcHBlbmQoY3FTY3JpcHRzKTtcbiAgICAgICAgfVxuXG4gICAgICAgICRlbGVtZW50Lmh0bWwoJycpO1xuICAgICAgICAkZWxlbWVudC5hcHBlbmQobW9kaWZpZWRTbGlkZUVsZW1lbnRzKTtcbiAgICB9XG4gICAgcmV0dXJuO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRTd2lwZXJIVE1MKCRlbGVtZW50LCBzZXR0aW5ncywgaXNFaW5zdGVpbikge1xuICAgIHZhciBvcmlnaW5hbFNsaWRlRWxlbWVudHMgPSAkZWxlbWVudC5jaGlsZHJlbigpLnRvQXJyYXkoKTtcbiAgICB2YXIgdW5pcXVlU2xpZGVyLCBzb3J0ZWRTbGlkZXNQZXJWaWV3QXJyYXksIGFkZFNsaWRlcywgZmluYWxTbGlkZXM7XG4gICAgdmFyIGlzTG9vcCA9IHRydWU7XG4gICAgdmFyIHNsaWRlc1BlclZpZXdBcnJheSA9IFtdO1xuICAgIHZhciBjcVNjcmlwdHMgPSBbXTtcbiAgICB2YXIgbW9kaWZpZWRTbGlkZUVsZW1lbnRzID0gW107XG4gICAgdmFyIGR1cGxpY2F0ZWRTbGlkZUVsZW1lbnRzID0gW107XG4gICAgdmFyIGhhc1N3aXBlckhUTUwgPSAkZWxlbWVudC5oYXNDbGFzcygnc3dpcGVyLWZ1bGwtd3JhcHBlcicpICYmICRlbGVtZW50LmZpbmQoJy5zd2lwZXInKS5sZW5ndGggPiAwO1xuICAgIHZhciBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3MgPSB7fTtcblxuICAgIGlmICgkZWxlbWVudC5hdHRyKCdpZCcpICYmICRlbGVtZW50LmF0dHIoJ2lkJykuaW5kZXhPZignc2xpZGVyLWluZGV4JykgPiAtMSkge1xuICAgICAgICB1bmlxdWVTbGlkZXIgPSAkZWxlbWVudC5hdHRyKCdpZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaXF1ZVNsaWRlciA9ICdzbGlkZXItaW5kZXgtJyArIGdldFVuaXF1ZU51bWJlcigpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgdmFyICRzd2lwZXJQYXJlbnQgPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyJywgJ2lkJzogdW5pcXVlU2xpZGVyIH0pLFxuICAgICAgICAkc3dpcGVyUGFnaW5hdGlvbiA9ICQoJzxkaXYgLz4nLCB7ICdjbGFzcyc6ICdzd2lwZXItcGFnaW5hdGlvbiBzd2lwZXItcGFnaW5hdGlvbi0nICsgdW5pcXVlU2xpZGVyIH0pLFxuICAgICAgICAkc3dpcGVyTmF2aWdhdGlvbiA9ICQoJzxkaXYgLz4nLCB7ICdjbGFzcyc6ICdzd2lwZXItbmF2aWdhdGlvbi1idXR0b25zLWNvbnRhaW5lcicgfSksXG4gICAgICAgICRzd2lwZXJQcmV2QXJyb3cgPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLWJ1dHRvbi1wcmV2IHN3aXBlci1idXR0b24tcHJldi0nICsgdW5pcXVlU2xpZGVyIH0pLFxuICAgICAgICAkc3dpcGVyTmV4dEFycm93ID0gJCgnPGRpdiAvPicsIHsgJ2NsYXNzJzogJ3N3aXBlci1idXR0b24tbmV4dCBzd2lwZXItYnV0dG9uLW5leHQtJyArIHVuaXF1ZVNsaWRlciB9KSxcbiAgICAgICAgJHN3aXBlcldyYXBwZXIgPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLXdyYXBwZXInIH0pO1xuXG4gICAgaWYgKHNldHRpbmdzKSB7XG4gICAgICAgIGlmICgnYnJlYWtwb2ludHMnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBicmVha3BvaW50U2l6ZSBpbiBzZXR0aW5ncy5icmVha3BvaW50cykge1xuICAgICAgICAgICAgICAgIHZhciBicmVha3BvaW50U2l6ZVNldHRpbmdzID0gc2V0dGluZ3MuYnJlYWtwb2ludHNbYnJlYWtwb2ludFNpemVdO1xuXG4gICAgICAgICAgICAgICAgLyogLS0tIFN3aXBlciBBcnJvd3MgTmF2aWdhdGlvbiAtLS0gKi9cbiAgICAgICAgICAgICAgICAvLyBTd2lwZXIgZG9lcyBub3QgZGlzcGxheSBhcnJvd3MgYnkgZGVmYXVsdCB0aGUgd2F5IFNsaWNrIGRvZXMuIFdlIG11c3QgYWN0aXZlbHkgaW5jbHVkZSB0aGVtIHRvIG1hdGNoIHRoZSBkZWZhdWx0cyBvZiBTbGljay5cbiAgICAgICAgICAgICAgICB2YXIgbmF2RGlzcGxheUNsYXNzID0gYnJlYWtwb2ludFNpemUgPT0gJzAnID8gJ3Nob3ctbW9iaWxlLW5hdi1idXR0b25zJyA6ICdzaG93LWRlc2t0b3AtbmF2LWJ1dHRvbnMnO1xuICAgICAgICAgICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLmFkZENsYXNzKG5hdkRpc3BsYXlDbGFzcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBhcnJvd3Mgd2VyZSBkZWxpYmVyYXRlbHkgc2V0IHRvIGZhbHNlIGluIHNldHRpbmdzLCB0aGF0IG1lYW5zIGhpZGUgdGhlbSBmb3IgYWxsIGJyZWFrcG9pbnQgc2l6ZXMuXG4gICAgICAgICAgICAgICAgaWYgKCdhcnJvd3MnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXR0aW5ncy5hcnJvd3MgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLnJlbW92ZUNsYXNzKCdzaG93LW1vYmlsZS1uYXYtYnV0dG9ucyBzaG93LWRlc2t0b3AtbmF2LWJ1dHRvbnMnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEVsc2UgaWYgYXJyb3dzIHdlcmUgZGVsaWJlcmF0ZWx5IHNldCB0byBmYWxzZSBmb3Igc3BlY2lmaWMgYnJlYWtwb2ludCwgdGhlbiBoaWRlIGZvciB0aGF0IGJyZWFrcG9pbnQuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICgnYXJyb3dzJyBpbiBicmVha3BvaW50U2l6ZVNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChicmVha3BvaW50U2l6ZVNldHRpbmdzLmFycm93cyA9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHN3aXBlck5hdmlnYXRpb24ucmVtb3ZlQ2xhc3MobmF2RGlzcGxheUNsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8qIC0tLSBTd2lwZXIgRG90cyBQYWdpbmF0aW9uIC0tLSAqL1xuICAgICAgICAgICAgICAgIC8vIFN3aXBlciBkb2VzIG5vdCBkaXNwbGF5IHBhZ2luYXRpb24gZG90cyBieSBkZWZhdWx0IHRoZSB3YXkgU2xpY2sgZG9lcy4gV2UgbXVzdCBhY3RpdmVseSBpbmNsdWRlIHRoZW0gdG8gbWF0Y2ggdGhlIGRlZmF1bHRzIG9mIFNsaWNrLlxuICAgICAgICAgICAgICAgIHZhciBwYWdpbmF0aW9uRGlzcGxheUNsYXNzID0gYnJlYWtwb2ludFNpemUgPT0gJzAnID8gJ3Nob3ctbW9iaWxlLXBhZ2luYXRpb24nIDogJ3Nob3ctZGVza3RvcC1wYWduaWF0aW9uJztcbiAgICAgICAgICAgICAgICAkc3dpcGVyUGFnaW5hdGlvbi5hZGRDbGFzcyhwYWdpbmF0aW9uRGlzcGxheUNsYXNzKTtcblxuICAgICAgICAgICAgICAgIC8vIElmIGRvdHMgd2VyZSBkZWxpYmVyYXRlbHkgc2V0IHRvIGZhbHNlIGluIHNldHRpbmdzLCB0aGF0IG1lYW5zIGhpZGUgdGhlbSBmb3IgYWxsIGJyZWFrcG9pbnQgc2l6ZXMuXG4gICAgICAgICAgICAgICAgaWYgKCdkb3RzJyBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2V0dGluZ3MuZG90cyA9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHN3aXBlclBhZ2luYXRpb24ucmVtb3ZlQ2xhc3MoJ3Nob3ctbW9iaWxlLXBhZ2luYXRpb24gc2hvdy1kZXNrdG9wLXBhZ25pYXRpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEVsc2UgaWYgZG90cyB3ZXJlIGRlbGliZXJhdGVseSBzZXQgdG8gZmFsc2UgZm9yIHNwZWNpZmljIGJyZWFrcG9pbnQsIHRoZW4gaGlkZSBmb3IgdGhhdCBicmVha3BvaW50LlxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2RvdHMnIGluIGJyZWFrcG9pbnRTaXplU2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJyZWFrcG9pbnRTaXplU2V0dGluZ3MuZG90cyA9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHN3aXBlclBhZ2luYXRpb24ucmVtb3ZlQ2xhc3MocGFnaW5hdGlvbkRpc3BsYXlDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoJ3NsaWRlc1RvU2hvdycgaW4gYnJlYWtwb2ludFNpemVTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXNQZXJWaWV3QXJyYXkucHVzaChwYXJzZUludChicmVha3BvaW50U2l6ZVNldHRpbmdzLnNsaWRlc1RvU2hvdykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFN3aXBlciBkb2VzIG5vdCBkaXNwbGF5IGFycm93cyBieSBkZWZhdWx0IHRoZSB3YXkgU2xpY2sgZG9lcy4gV2UgbXVzdCBhY3RpdmVseSBpbmNsdWRlIHRoZW0gdG8gbWF0Y2ggdGhlIGRlZmF1bHRzIG9mIFNsaWNrLlxuICAgICAgICAgICAgJHN3aXBlck5hdmlnYXRpb24uYWRkQ2xhc3MoJ3Nob3ctbW9iaWxlLW5hdi1idXR0b25zIHNob3ctZGVza3RvcC1uYXYtYnV0dG9ucycpO1xuXG4gICAgICAgICAgICAvLyBJZiBhcnJvd3Mgd2VyZSBkZWxpYmVyYXRlbHkgc2V0IHRvIGZhbHNlIGluIHNldHRpbmdzLCB0aGF0IG1lYW5zIGhpZGUgdGhlbSBmb3IgYWxsIGJyZWFrcG9pbnQgc2l6ZXMuXG4gICAgICAgICAgICBpZiAoJ2Fycm93cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2V0dGluZ3MuYXJyb3dzID09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICRzd2lwZXJOYXZpZ2F0aW9uLnJlbW92ZUNsYXNzKCdzaG93LW1vYmlsZS1uYXYtYnV0dG9ucyBzaG93LWRlc2t0b3AtbmF2LWJ1dHRvbnMnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN3aXBlciBkb2VzIG5vdCBkaXNwbGF5IHBhZ2luYXRpb24gZG90cyBieSBkZWZhdWx0IHRoZSB3YXkgU2xpY2sgZG9lcy4gV2UgbXVzdCBhY3RpdmVseSBpbmNsdWRlIHRoZW0gdG8gbWF0Y2ggdGhlIGRlZmF1bHRzIG9mIFNsaWNrLlxuICAgICAgICAgICAgJHN3aXBlclBhZ2luYXRpb24uYWRkQ2xhc3MoJ3Nob3ctZGVza3RvcC1wYWduaWF0aW9uIHNob3ctbW9iaWxlLXBhZ2luYXRpb24nKTtcblxuICAgICAgICAgICAgLy8gSWYgZG90cyB3ZXJlIGRlbGliZXJhdGVseSBzZXQgdG8gZmFsc2UgaW4gc2V0dGluZ3MsIHRoYXQgbWVhbnMgaGlkZSB0aGVtIGZvciBhbGwgYnJlYWtwb2ludCBzaXplcy5cbiAgICAgICAgICAgIGlmICgnZG90cycgaW4gc2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2V0dGluZ3MuZG90cyA9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAkc3dpcGVyUGFnaW5hdGlvbi5yZW1vdmVDbGFzcygnc2hvdy1kZXNrdG9wLXBhZ25pYXRpb24gc2hvdy1tb2JpbGUtcGFnaW5hdGlvbicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoJ2xvb3AnIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICBpc0xvb3AgPSBzZXR0aW5ncy5sb29wO1xuICAgICAgICB9XG4gICAgfSAgICBcblxuICAgIGlmIChzbGlkZXNQZXJWaWV3QXJyYXkpIHtcbiAgICAgICAgc29ydGVkU2xpZGVzUGVyVmlld0FycmF5ID0gc2xpZGVzUGVyVmlld0FycmF5LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9KTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc1N3aXBlckhUTUwgJiYgb3JpZ2luYWxTbGlkZUVsZW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgJGVsZW1lbnQuYWRkQ2xhc3MoJ3N3aXBlci1mdWxsLXdyYXBwZXInKTtcblxuICAgICAgICAvLyBFaW5zdGVpbiBDUXVvdGllbnQgc2NyaXB0cyBhcmUgbWl4ZWQgaW4gd2l0aCBzbGlkZXMgYXQgdGltZSBvZiBzbGlkZXIgaW5pdGlhbGl6YXRpb24uIFJld29yayB0aGUgSFRNTCBzdHJ1Y3R1cmUuXG4gICAgICAgIGlmIChpc0VpbnN0ZWluKSB7XG4gICAgICAgICAgICAkLmVhY2gob3JpZ2luYWxTbGlkZUVsZW1lbnRzLCBmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKSA9PT0gJ1NDUklQVCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY3FTY3JpcHRzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZvcm1hdHRlZFNsaWRlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdESVYnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRTbGlkZSA9ICQoZWxlbWVudCkuYWRkQ2xhc3MoJ3N3aXBlci1zbGlkZScpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkU2xpZGUgPSAkKCc8ZGl2IC8+JywgeyAnY2xhc3MnOiAnc3dpcGVyLXNsaWRlJyB9KS5odG1sKCQoZWxlbWVudCkuaHRtbCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtb2RpZmllZFNsaWRlRWxlbWVudHMucHVzaChmb3JtYXR0ZWRTbGlkZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBQcm9jZWVkIHRvIG1vZGlmeSByZWd1bGFyIHNsaWRlIGVsZW1lbnRzIChub24tRWluc3RlaW4pXG4gICAgICAgICAgICBtb2RpZmllZFNsaWRlRWxlbWVudHMgPSBvcmlnaW5hbFNsaWRlRWxlbWVudHMubWFwKGZ1bmN0aW9uKGVsZW1lbnQsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b1VwcGVyQ2FzZSgpID09PSAnRElWJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJChlbGVtZW50KS5hZGRDbGFzcygnc3dpcGVyLXNsaWRlJylbMF07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQoJzxkaXYgLz4nLCB7ICdjbGFzcyc6ICdzd2lwZXItc2xpZGUnIH0pLmh0bWwoJChlbGVtZW50KS5odG1sKCkpWzBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGFkZGl0aW9uYWwgc2xpZGVzIChhY2NvcmRpbmcgdG8gbG93ZXN0IGNvbW1vbiBtdWx0aXBsZSkgdG8gZml4IGxvb3AgYnVnIGluIFN3aXBlclxuICAgICAgICBpZiAobW9kaWZpZWRTbGlkZUVsZW1lbnRzICYmIHNvcnRlZFNsaWRlc1BlclZpZXdBcnJheSAmJiBpc0xvb3ApIHtcbiAgICAgICAgICAgIHZhciBMQ00gPSBsZWFzdENvbW1vbk11bHRpcGxlKHNvcnRlZFNsaWRlc1BlclZpZXdBcnJheSk7XG4gICAgICAgICAgICBpZiAoc29ydGVkU2xpZGVzUGVyVmlld0FycmF5LmluZGV4T2YoTENNKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgYWRkU2xpZGVzID0gKExDTSAqIDIpIC0gbW9kaWZpZWRTbGlkZUVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWRkU2xpZGVzID0gTENNIC0gbW9kaWZpZWRTbGlkZUVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhZGRTbGlkZXMgPCAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIEhDTSA9IHNvcnRlZFNsaWRlc1BlclZpZXdBcnJheS5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEgKiBiOyB9KTtcbiAgICAgICAgICAgICAgICBhZGRTbGlkZXMgPSBIQ00gLSBtb2RpZmllZFNsaWRlRWxlbWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5lYWNoKG1vZGlmaWVkU2xpZGVFbGVtZW50cywgZnVuY3Rpb24oaWR4LCBpdGVtKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlkeCA8IGFkZFNsaWRlcykge1xuICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVkU2xpZGVFbGVtZW50cy5wdXNoKCQoaXRlbSkuY2xvbmUoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgZmluYWwgYXJyYXkgb2Ygc2xpZGUgZWxlbWVudHNcbiAgICAgICAgZmluYWxTbGlkZXMgPSAkLm1lcmdlKG1vZGlmaWVkU2xpZGVFbGVtZW50cywgZHVwbGljYXRlZFNsaWRlRWxlbWVudHMpO1xuXG4gICAgICAgIC8vIEFwcGVuZCBuZXcgc3dpcGVyIEhUTUwgZWxlbWVudHMgdG8gc3dpcGVyIHdyYXBwZXJcbiAgICAgICAgJHN3aXBlcldyYXBwZXIuYXBwZW5kKGZpbmFsU2xpZGVzKTtcbiAgICAgICAgJHN3aXBlck5hdmlnYXRpb24uYXBwZW5kKCRzd2lwZXJQcmV2QXJyb3cpLmFwcGVuZCgkc3dpcGVyTmV4dEFycm93KTtcbiAgICAgICAgJHN3aXBlclBhcmVudC5hcHBlbmQoJHN3aXBlcldyYXBwZXIpLmFwcGVuZCgkc3dpcGVyUGFnaW5hdGlvbik7XG5cbiAgICAgICAgLy8gU2V0IHNsaWRlIGFycm93cyBlaXRoZXIgaW5zaWRlIG9yIG91dHNpZGUgc2xpZGVyIGNvbnRhaW5lclxuICAgICAgICB2YXIgYXJyb3dzUG9zaXRpb24gPSBzZXR0aW5ncyAmJiAnYXJyb3dzUG9zaXRpb24nIGluIHNldHRpbmdzID8gc2V0dGluZ3MuYXJyb3dzUG9zaXRpb24gOiBudWxsO1xuICAgICAgICBpZiAoYXJyb3dzUG9zaXRpb24gJiYgYXJyb3dzUG9zaXRpb24gPT0gJ2luc2lkZScpIHtcbiAgICAgICAgICAgICRzd2lwZXJQYXJlbnQuYXBwZW5kKCRzd2lwZXJOYXZpZ2F0aW9uKS5hZGRDbGFzcygnc3dpcGVyLWluc2lkZS1uYXZpZ2F0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXBsYWNlIHN3aXBlciB3cmFwcGVyIGNvbnRlbnRzIHdpdGggbmV3IEhUTUxcbiAgICAgICAgJGVsZW1lbnQuaHRtbCgkc3dpcGVyUGFyZW50KTtcblxuICAgICAgICBpZiAoIWFycm93c1Bvc2l0aW9uIHx8IGFycm93c1Bvc2l0aW9uID09ICdvdXRzaWRlJykgeyAvLyBJZiBhcnJvd3MgYXJlIG91dHNpZGUsIHdlIGhhdmUgdG8gd2FpdCB1bnRpbCBzd2lwZXIgd3JhcHBlciBoYXMgY29udGVudCBpbiBsaW5lIGFib3ZlIGJlZm9yZSB3ZSBwcmVwZW5kXG4gICAgICAgICAgICAkZWxlbWVudC5wcmVwZW5kKCRzd2lwZXJOYXZpZ2F0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNFaW5zdGVpbiAmJiBjcVNjcmlwdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGVsZW1lbnQuYXBwZW5kKGNxU2NyaXB0cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHcmFiIHRoZSB1bmlxdWUgY2xhc3NlcyBmcm9tIGFsbCB0aGUgbmV3IGVsZW1lbnRzIGFib3ZlIGFuZCByZXR1cm4gZm9yIGZ1cnRoZXIgdXNlXG4gICAgICAgIHN3aXBlckNsYXNzZXNGb3JTZXR0aW5ncy5wYXJlbnQgPSAnIycgKyB1bmlxdWVTbGlkZXI7XG4gICAgICAgIHN3aXBlckNsYXNzZXNGb3JTZXR0aW5ncy5wYWdpbmF0aW9uID0gJy5zd2lwZXItcGFnaW5hdGlvbi0nICsgdW5pcXVlU2xpZGVyO1xuICAgICAgICBzd2lwZXJDbGFzc2VzRm9yU2V0dGluZ3MucHJldiA9ICcuc3dpcGVyLWJ1dHRvbi1wcmV2LScgKyB1bmlxdWVTbGlkZXI7XG4gICAgICAgIHN3aXBlckNsYXNzZXNGb3JTZXR0aW5ncy5uZXh0ID0gJy5zd2lwZXItYnV0dG9uLW5leHQtJyArIHVuaXF1ZVNsaWRlcjtcbiAgICB9XG4gICAgcmV0dXJuIHN3aXBlckNsYXNzZXNGb3JTZXR0aW5ncztcbn1cblxuZnVuY3Rpb24gaW5pdCAoZWxlbWVudENsYXNzLCBzZXR0aW5ncywgaXNFaW5zdGVpbikge1xuICAgIHZhciBzZWxlY3RvciA9IGVsZW1lbnRDbGFzcztcbiAgICBpZiAoIWVsZW1lbnRDbGFzcyB8fCAoJChlbGVtZW50Q2xhc3MpLmxlbmd0aCA9PSAwICYmIGVsZW1lbnRDbGFzcy5pbmRleE9mKCc6aGFzJykgPCAwKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09OVEVOVF9TTE9UX1NMSURFUiA9PSAnc3dpcGVySlMnKSB7IFxuICAgICAgICAkKGVsZW1lbnRDbGFzcykuZWFjaChmdW5jdGlvbihuLCBlbG0pIHtcbiAgICAgICAgICAgIHZhciAkZWxlbWVudCA9ICQoZWxtKTtcbiAgICAgICAgICAgIHZhciBoYXNTd2lwZXJIVE1MID0gJGVsZW1lbnQuZmluZCgnLnN3aXBlci1pbml0aWFsaXplZCcpLmxlbmd0aCA+IDA7XG5cbiAgICAgICAgICAgIGlmICghaGFzU3dpcGVySFRNTCkge1xuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzRm9yU2V0dGluZ3MgPSBmb3JtYXRTd2lwZXJIVE1MKCRlbGVtZW50LCBzZXR0aW5ncywgaXNFaW5zdGVpbik7XG4gICAgICAgICAgICAgICAgaWYgKCFzZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBzZXR0aW5ncyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlc0ZvclNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE92ZXJyaWRlIHNlbGVjdG9yIGNsYXNzIGZvciBJRCBpZiB3ZSBoYXZlIGl0XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yID0gY2xhc3Nlc0ZvclNldHRpbmdzLnBhcmVudCA/IGNsYXNzZXNGb3JTZXR0aW5ncy5wYXJlbnQgOiBzZWxlY3RvcjtcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MucGFnaW5hdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiBjbGFzc2VzRm9yU2V0dGluZ3MucGFnaW5hdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrYWJsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBzZXR0aW5ncy5uYXZpZ2F0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEVsOiBjbGFzc2VzRm9yU2V0dGluZ3MubmV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZFbDogY2xhc3Nlc0ZvclNldHRpbmdzLnByZXZcbiAgICAgICAgICAgICAgICAgICAgfTsgICAgXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBpbml0U3dpcGVyKHNlbGVjdG9yLCBzZXR0aW5ncywgY2xhc3Nlc0ZvclNldHRpbmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgJChlbGVtZW50Q2xhc3MpLmVhY2goZnVuY3Rpb24obiwgZWxtKSB7XG4gICAgICAgICAgICB2YXIgJGVsZW1lbnQgPSAkKGVsbSk7XG4gICAgICAgICAgICB2YXIgZWxlbWVudElkU2VsZWN0b3I7XG4gICAgICAgICAgICBmb3JtYXRTbGlja0hUTUwoJGVsZW1lbnQsIHNldHRpbmdzLCBpc0VpbnN0ZWluKTtcbiAgICAgICAgICAgIGVsZW1lbnRJZFNlbGVjdG9yID0gJyMnICsgJGVsZW1lbnQuYXR0cignaWQnKTtcbiAgICAgICAgICAgIGluaXRTbGljayhlbGVtZW50SWRTZWxlY3Rvciwgc2V0dGluZ3MpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxlYXN0Q29tbW9uTXVsdGlwbGUodmFsdWVzKSB7XG4gICAgZnVuY3Rpb24gZ2NkKGEsIGIpIHtcbiAgICAgICAgLy8gR3JlYXRlc3QgY29tbW9uIGRpdmlzb3Igb2YgMiBpbnRlZ2Vyc1xuICAgICAgICByZXR1cm4gIWIgPyBhIDogZ2NkKGIsIGEgJSBiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsY20oYSwgYikge1xuICAgICAgICAvLyBMZWFzdCBjb21tb24gbXVsdGlwbGUgb2YgMiBpbnRlZ2Vyc1xuICAgICAgICByZXR1cm4gKGEgKiBiKSAvIGdjZChhLCBiKTsgICBcbiAgICB9XG5cbiAgICB2YXIgbXVsdGlwbGUgPSB2YWx1ZXNbMF07XG4gICAgLy8gTGVhc3QgY29tbW9uIG11bHRpcGxlIG9mIGEgbGlzdCBvZiBpbnRlZ2Vyc1xuICAgIHZhbHVlcy5mb3JFYWNoKGZ1bmN0aW9uKG4pIHtcbiAgICAgICAgbXVsdGlwbGUgPSBsY20obXVsdGlwbGUsIG4pO1xuICAgIH0pO1xuXG4gICAgLy8gUmV0dXJuIGxlYXN0IGNvbW1vbiBtdWx0aXBsZSBmb3IgYXJyYXkgb2YgdmFsdWVzXG4gICAgcmV0dXJuIG11bHRpcGxlO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplQ2F0ZWdvcnlTbGlkZXJzKGVsZW1lbnRDbGFzcykge1xuXHR2YXIgJGNhdGVnb3J5U2xpZGVycyA9ICQoZWxlbWVudENsYXNzKTtcblx0aWYgKCRjYXRlZ29yeVNsaWRlcnMubGVuZ3RoID4gMCkge1xuXHRcdCRjYXRlZ29yeVNsaWRlcnMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdFx0dmFyICRlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICAgICAgICAgIHZhciBjYXRlZ29yeVNsaWRlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgYnJlYWtwb2ludHM6IHt9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIHVuaXF1ZVNsaWRlciA9ICdjYXRlZ29yeS1zbGlkZXItaW5kZXgtJyArIGdldFVuaXF1ZU51bWJlcigpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAkZWxlbWVudC5hZGRDbGFzcyh1bmlxdWVTbGlkZXIpO1xuXG5cdFx0XHQvLyBEZXNrdG9wIHNsb3QgY29uZmlnIG9wdGlvbnNcblx0XHRcdHZhciBjYXRlZ29yeVNsaWRlckRlc2t0b3BPcHRpb25zID0gJGVsZW1lbnQuYXR0cignc2xpZGVyLWRlc2t0b3Atb3B0aW9ucycpO1xuXHRcdFx0aWYgKGNhdGVnb3J5U2xpZGVyRGVza3RvcE9wdGlvbnMpIHtcblx0XHRcdFx0Y2F0ZWdvcnlTbGlkZXJEZXNrdG9wT3B0aW9ucyA9IEpTT04ucGFyc2UoY2F0ZWdvcnlTbGlkZXJEZXNrdG9wT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgY2F0ZWdvcnlTbGlkZXJPcHRpb25zLmJyZWFrcG9pbnRzW2NhdGVnb3J5U2xpZGVyRGVza3RvcE9wdGlvbnMuYnJlYWtwb2ludFNpemVdID0gY2F0ZWdvcnlTbGlkZXJEZXNrdG9wT3B0aW9ucztcblx0XHRcdH1cblx0XHRcdC8vIE1vYmlsZSBzbG90IGNvbmZpZyBvcHRpb25zXG5cdFx0XHR2YXIgY2F0ZWdvcnlTbGlkZXJNb2JpbGVPcHRpb25zID0gJGVsZW1lbnQuYXR0cignc2xpZGVyLW1vYmlsZS1vcHRpb25zJyk7XG5cdFx0XHRpZiAoY2F0ZWdvcnlTbGlkZXJNb2JpbGVPcHRpb25zKSB7XG5cdFx0XHRcdGNhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucyA9IEpTT04ucGFyc2UoY2F0ZWdvcnlTbGlkZXJNb2JpbGVPcHRpb25zKTtcbiAgICAgICAgICAgICAgICBjYXRlZ29yeVNsaWRlck9wdGlvbnMuYnJlYWtwb2ludHNbY2F0ZWdvcnlTbGlkZXJNb2JpbGVPcHRpb25zLmJyZWFrcG9pbnRTaXplXSA9IGNhdGVnb3J5U2xpZGVyTW9iaWxlT3B0aW9ucztcblx0XHRcdH1cblxuICAgICAgICAgICAgaW5pdCgnLicgKyB1bmlxdWVTbGlkZXIsIGNhdGVnb3J5U2xpZGVyT3B0aW9ucyk7XG5cdFx0fSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVJlY29tbWVuZGF0aW9uU2xpZGVyKCkge1xuXHR2YXIgYXR0ZW1wdE51bWJlciA9IDA7XG5cdHZhciB0aW1lciA9IHNldEludGVydmFsKHJlY29tbWVuZGF0aW9uU2xpZGVySW50ZXJ2YWxIYW5kbGVyLCA1MDApO1xuXHRmdW5jdGlvbiByZWNvbW1lbmRhdGlvblNsaWRlckludGVydmFsSGFuZGxlcigpIHtcbiAgICAgICAgdmFyIHNsaWRlckluaXRpYWxpemVkQ2xhc3MgPSBTaXRlUHJlZmVyZW5jZXMuQ09OVEVOVF9TTE9UX1NMSURFUiA9PSAnc3dpcGVySlMnID8gJ3N3aXBlci1pbml0aWFsaXplZCcgOiAnc2xpY2staW5pdGlhbGl6ZWQnO1xuICAgICAgICB2YXIgc2xpZGVyU2VsZWN0b3IgPSAnLnByb2R1Y3QtcmVjb21tZW5kYXRpb25zIC5zbGlkZXItcHJvZHVjdHMtcHJpbWFyeSAuc2xpZGVzJztcbiAgICAgICAgdmFyIHJlY29tbWVuZGF0aW9uU2xpZGVySW5pdGlhbGl6ZWQ7XG5cbiAgICAgICAgaWYgKHBhZ2VDb250ZXh0LnNpdGUgPT0gU2l0ZUNvbnN0YW50cy5TaXRlSWRzLkJvb3RCYXJuVVMpIHtcbiAgICAgICAgICAgIHNsaWRlclNlbGVjdG9yID0gJy5yZWNvbW0tcHJvZC1hbmNob3Itc2xvdCAnICsgc2xpZGVyU2VsZWN0b3I7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPTlRFTlRfU0xPVF9TTElERVIgPT0gJ3N3aXBlckpTJykge1xuICAgICAgICAgICAgcmVjb21tZW5kYXRpb25TbGlkZXJJbml0aWFsaXplZCA9ICQoc2xpZGVyU2VsZWN0b3IpLmZpbmQoJy4nICsgc2xpZGVySW5pdGlhbGl6ZWRDbGFzcykubGVuZ3RoID4gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlY29tbWVuZGF0aW9uU2xpZGVySW5pdGlhbGl6ZWQgPSAkKHNsaWRlclNlbGVjdG9yKS5maWx0ZXIoZnVuY3Rpb24oaW5kZXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJCh0aGlzKS5oYXNDbGFzcyhzbGlkZXJJbml0aWFsaXplZENsYXNzKTtcbiAgICAgICAgICAgIH0pLmxlbmd0aCA+IDA7XG4gICAgICAgIH1cblxuXHRcdGF0dGVtcHROdW1iZXIrKztcblx0XHRpZihyZWNvbW1lbmRhdGlvblNsaWRlckluaXRpYWxpemVkIHx8IGF0dGVtcHROdW1iZXIgPiAyMCkge1xuXHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignRWluc3RlaW5Qcm9kdWN0UmVjb21tZW5kYXRpb25zLkRvbmUnLCAkKCcjcHJvZHVjdC1yZWNvbW1lbmRhdGlvbnMnKSk7XG4gICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLkNPTlRFTlRfU0xPVF9TTElERVIgPT0gJ2ltZ1ZpZXdlcjJTbGljaycpIHsgXG5cdFx0XHQgICAgJChkb2N1bWVudCkudHJpZ2dlcignU2xpY2tTbGlkZXJBY2Nlc3NpYmlsaXR5TW9kcycpO1xuICAgICAgICAgICAgfVxuXHRcdFx0Y2xlYXJJbnRlcnZhbCh0aW1lcik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuICAgICAgICAkKCcuc2xpZGVyLXByb2R1Y3RzLXByaW1hcnknKS50cmlnZ2VyKCdpbml0LXNsaWRlcicpO1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW52ZW50b3J5ID0gcmVxdWlyZSgnLi8nKTtcblxudmFyIGNhcnRJbnZlbnRvcnkgPSB7XG4gICAgc2V0U2VsZWN0ZWRTdG9yZTogZnVuY3Rpb24gKHN0b3JlSWQpIHtcbiAgICAgICAgdmFyICRzZWxlY3RlZFN0b3JlID0gJCgnLnN0b3JlLXRpbGUuJyArIHN0b3JlSWQpLFxuICAgICAgICAgICAgJGxpbmVJdGVtID0gJCgnLmNhcnQtcm93W2RhdGEtdXVpZD1cIicgKyB0aGlzLnV1aWQgKyAnXCJdJyksXG4gICAgICAgICAgICBzdG9yZUFkZHJlc3MgPSAkc2VsZWN0ZWRTdG9yZS5maW5kKCcuc3RvcmUtYWRkcmVzcycpLmh0bWwoKSxcbiAgICAgICAgICAgIHN0b3JlU3RhdHVzID0gJHNlbGVjdGVkU3RvcmUuZmluZCgnLnN0b3JlLXN0YXR1cycpLmRhdGEoJ3N0YXR1cycpLFxuICAgICAgICAgICAgc3RvcmVTdGF0dXNUZXh0ID0gJHNlbGVjdGVkU3RvcmUuZmluZCgnLnN0b3JlLXN0YXR1cycpLnRleHQoKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFN0b3JlID0gc3RvcmVJZDtcblxuICAgICAgICAkbGluZUl0ZW0uZmluZCgnLmluc3RvcmUtZGVsaXZlcnkgLnNlbGVjdGVkLXN0b3JlLWFkZHJlc3MnKVxuICAgICAgICAgICAgLmRhdGEoJ3N0b3JlSWQnLCBzdG9yZUlkKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtc3RvcmUtaWQnLCBzdG9yZUlkKVxuICAgICAgICAgICAgLmh0bWwoc3RvcmVBZGRyZXNzKTtcbiAgICAgICAgJGxpbmVJdGVtLmZpbmQoJy5pbnN0b3JlLWRlbGl2ZXJ5IC5zZWxlY3RlZC1zdG9yZS1hdmFpbGFiaWxpdHknKVxuICAgICAgICAgICAgLmRhdGEoJ3N0YXR1cycsIHN0b3JlU3RhdHVzKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtc3RhdHVzJywgc3RvcmVTdGF0dXMpXG4gICAgICAgICAgICAudGV4dChzdG9yZVN0YXR1c1RleHQpO1xuICAgICAgICAkbGluZUl0ZW0uZmluZCgnLmluc3RvcmUtZGVsaXZlcnkgLmRlbGl2ZXJ5LW9wdGlvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJykudHJpZ2dlcignY2xpY2snKTtcbiAgICB9LFxuICAgIGNhcnRTZWxlY3RTdG9yZTogZnVuY3Rpb24gKHNlbGVjdGVkU3RvcmUpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMudXVpZCkudGhlbihmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgICAgICAgICBpbnZlbnRvcnkuc2VsZWN0U3RvcmVEaWFsb2coe1xuICAgICAgICAgICAgICAgIHN0b3Jlczogc3RvcmVzLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVJZDogc2VsZWN0ZWRTdG9yZSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZFN0b3JlVGV4dDogUmVzb3VyY2VzLlNFTEVDVEVEX1NUT1JFLFxuICAgICAgICAgICAgICAgIGNvbnRpbnVlQ2FsbGJhY2s6IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgICAgICAgICAgIHNlbGVjdFN0b3JlQ2FsbGJhY2s6IHNlbGYuc2V0U2VsZWN0ZWRTdG9yZS5iaW5kKHNlbGYpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuZG9uZSgpO1xuICAgIH0sXG4gICAgc2V0RGVsaXZlcnlPcHRpb246IGZ1bmN0aW9uICh2YWx1ZSwgc3RvcmVJZCkge1xuICAgICAgICAvLyBzZXQgbG9hZGluZyBzdGF0ZVxuICAgICAgICAkKCcuaXRlbS1kZWxpdmVyeS1vcHRpb25zJylcbiAgICAgICAgICAgIC5hZGRDbGFzcygnbG9hZGluZycpXG4gICAgICAgICAgICAuY2hpbGRyZW4oKS5oaWRlKCk7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB7XG4gICAgICAgICAgICBwbGlkOiB0aGlzLnV1aWQsXG4gICAgICAgICAgICBzdG9yZXBpY2t1cDogKHZhbHVlID09PSAnc3RvcmUnID8gdHJ1ZSA6IGZhbHNlKVxuICAgICAgICB9O1xuICAgICAgICBpZiAodmFsdWUgPT09ICdzdG9yZScpIHtcbiAgICAgICAgICAgIGRhdGEuc3RvcmVwaWNrdXAgPSB0cnVlO1xuICAgICAgICAgICAgZGF0YS5zdG9yZWlkID0gc3RvcmVJZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEuc3RvcmVwaWNrdXAgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLnNldFN0b3JlUGlja3VwLFxuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgbG9hZGluZyBzdGF0ZVxuICAgICAgICAgICAgICAgICQoJy5pdGVtLWRlbGl2ZXJ5LW9wdGlvbnMnKVxuICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcnKVxuICAgICAgICAgICAgICAgICAgICAuY2hpbGRyZW4oKS5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICQoJy5pdGVtLWRlbGl2ZXJ5LW9wdGlvbnMgLnNldC1wcmVmZXJyZWQtc3RvcmUnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgc2VsZi51dWlkID0gJCh0aGlzKS5kYXRhKCd1dWlkJyk7XG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRTdG9yZSA9ICQodGhpcykuY2xvc2VzdCgnLmluc3RvcmUtZGVsaXZlcnknKS5maW5kKCcuc2VsZWN0ZWQtc3RvcmUtYWRkcmVzcycpLmRhdGEoJ3N0b3JlSWQnKTtcbiAgICAgICAgICAgIGlmICghVXNlci56aXApIHtcbiAgICAgICAgICAgICAgICBpbnZlbnRvcnkuemlwUHJvbXB0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYXJ0U2VsZWN0U3RvcmUoc2VsZWN0ZWRTdG9yZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuY2FydFNlbGVjdFN0b3JlKHNlbGVjdGVkU3RvcmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCgnLml0ZW0tZGVsaXZlcnktb3B0aW9ucyAuZGVsaXZlcnktb3B0aW9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gcmVzZXQgdGhlIHV1aWRcbiAgICAgICAgICAgIHZhciBzZWxlY3RlZFN0b3JlID0gJCh0aGlzKS5jbG9zZXN0KCcuaW5zdG9yZS1kZWxpdmVyeScpLmZpbmQoJy5zZWxlY3RlZC1zdG9yZS1hZGRyZXNzJykuZGF0YSgnc3RvcmVJZCcpO1xuICAgICAgICAgICAgc2VsZi51dWlkID0gJCh0aGlzKS5jbG9zZXN0KCcuY2FydC1yb3cnKS5kYXRhKCd1dWlkJyk7XG4gICAgICAgICAgICBzZWxmLnNldERlbGl2ZXJ5T3B0aW9uKCQodGhpcykudmFsKCksIHNlbGVjdGVkU3RvcmUpO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNhcnRJbnZlbnRvcnk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gICAgZGlhbG9nID0gcmVxdWlyZSgnLi4vZGlhbG9nJyksXG4gICAgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxudmFyIG5ld0xpbmUgPSAnXFxuJztcbnZhciBzdG9yZVRlbXBsYXRlID0gZnVuY3Rpb24gKHN0b3JlLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJzxsaSBjbGFzcz1cInN0b3JlLXRpbGUgJyArIHN0b3JlLnN0b3JlSWQgKyAoc3RvcmUuc3RvcmVJZCA9PT0gc2VsZWN0ZWRTdG9yZUlkID8gJyBzZWxlY3RlZCcgOiAnJykgKyAnXCI+JyxcbiAgICAgICAgJyAgICA8cCBjbGFzcz1cInN0b3JlLWFkZHJlc3NcIj4nLFxuICAgICAgICAnICAgICAgICAnICsgc3RvcmUuYWRkcmVzczEgKyAnPGJyLz4nLFxuICAgICAgICAnICAgICAgICAnICsgc3RvcmUuY2l0eSArICcsICcgKyBzdG9yZS5zdGF0ZUNvZGUgKyAnICcgKyBzdG9yZS5wb3N0YWxDb2RlLFxuICAgICAgICAnICAgIDwvcD4nLFxuICAgICAgICAnICAgIDxwIGNsYXNzPVwic3RvcmUtc3RhdHVzXCIgZGF0YS1zdGF0dXM9XCInICsgc3RvcmUuc3RhdHVzY2xhc3MgKyAnXCI+JyArIHN0b3JlLnN0YXR1cyArICc8L3A+JyxcbiAgICAgICAgJyAgICA8YnV0dG9uIGNsYXNzPVwic2VsZWN0LXN0b3JlLWJ1dHRvblwiIGRhdGEtc3RvcmUtaWQ9XCInICsgc3RvcmUuc3RvcmVJZCArICdcIicgK1xuICAgICAgICAoc3RvcmUuc3RhdHVzY2xhc3MgIT09ICdzdG9yZS1pbi1zdG9jaycgPyAnZGlzYWJsZWQ9XCJkaXNhYmxlZFwiJyA6ICcnKSArICc+JyxcbiAgICAgICAgJyAgICAgICAgJyArIChzdG9yZS5zdG9yZUlkID09PSBzZWxlY3RlZFN0b3JlSWQgPyBzZWxlY3RlZFN0b3JlVGV4dCA6IFJlc291cmNlcy5TRUxFQ1RfU1RPUkUpLFxuICAgICAgICAnICAgIDwvYnV0dG9uPicsXG4gICAgICAgICc8L2xpPidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xuXG52YXIgc3RvcmVMaXN0VGVtcGxhdGUgPSBmdW5jdGlvbiAoc3RvcmVzLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KSB7XG4gICAgaWYgKHN0b3JlcyAmJiBzdG9yZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cInN0b3JlLWxpc3QtY29udGFpbmVyXCI+JyxcbiAgICAgICAgICAgICc8dWwgY2xhc3M9XCJzdG9yZS1saXN0XCI+JyxcbiAgICAgICAgICAgIF8ubWFwKHN0b3JlcywgZnVuY3Rpb24gKHN0b3JlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0b3JlVGVtcGxhdGUoc3RvcmUsIHNlbGVjdGVkU3RvcmVJZCwgc2VsZWN0ZWRTdG9yZVRleHQpO1xuICAgICAgICAgICAgfSkuam9pbihuZXdMaW5lKSxcbiAgICAgICAgICAgICc8L3VsPicsXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwic3RvcmUtbGlzdC1wYWdpbmF0aW9uXCI+JyxcbiAgICAgICAgICAgICc8L2Rpdj4nXG4gICAgICAgIF0uam9pbihuZXdMaW5lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJzxkaXYgY2xhc3M9XCJuby1yZXN1bHRzXCI+JyArIFJlc291cmNlcy5JTlZBTElEX1pJUCArICc8L2Rpdj4nO1xuICAgIH1cbn07XG5cbnZhciB6aXBQcm9tcHRUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAnPGRpdiBpZD1cInByZWZlcnJlZC1zdG9yZS1wYW5lbFwiPicsXG4gICAgICAgICcgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWQ9XCJ1c2VyLXppcFwiIHBsYWNlaG9sZGVyPVwiJyArIFJlc291cmNlcy5FTlRFUl9aSVAgKyAnXCIgbmFtZT1cInppcENvZGVcIi8+JyxcbiAgICAgICAgJzwvZGl2PidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB0ZXN0IHdoZXRoZXIgemlwY29kZSBpcyB2YWxpZCBmb3IgZWl0aGVyIFVTIG9yIENhbmFkYVxuICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB0aGUgemlwY29kZSBpcyB2YWxpZCBmb3IgZWl0aGVyIGNvdW50cnksIGZhbHNlIGlmIGl0J3MgaW52YWxpZCBmb3IgYm90aFxuICoqL1xudmFyIHZhbGlkYXRlWmlwQ29kZSA9IGZ1bmN0aW9uICh6aXBDb2RlKSB7XG4gICAgdmFyIHJlZ2V4ZXMgPSB7XG4gICAgICAgICAgICBjYW5hZGE6IC9eW0FCQ0VHSEpLTE1OUFJTVFZYWV1cXGRbQUJDRUdISktMTU5QUlNUVldYWVpdKCApP1xcZFtBQkNFR0hKS0xNTlBSU1RWV1hZWl1cXGQkL2ksXG4gICAgICAgICAgICB1c2E6IC9eXFxkezV9KC1cXGR7NH0pPyQvXG4gICAgICAgIH0sXG4gICAgICAgIHZhbGlkID0gZmFsc2U7XG4gICAgaWYgKCF6aXBDb2RlKSB7IHJldHVybjsgfVxuICAgIF8uZWFjaChyZWdleGVzLCBmdW5jdGlvbiAocmUpIHtcbiAgICAgICAgdmFyIHJlZ2V4cCA9IG5ldyBSZWdFeHAocmUpO1xuICAgICAgICB2YWxpZCA9IHJlZ2V4cC50ZXN0KHppcENvZGUpO1xuICAgIH0pO1xuICAgIHJldHVybiB2YWxpZDtcbn07XG5cbnZhciBzdG9yZWludmVudG9yeSA9IHtcbiAgICB6aXBQcm9tcHQ6IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIGh0bWw6IHppcFByb21wdFRlbXBsYXRlKCksXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFJlc291cmNlcy5TVE9SRV9ORUFSX1lPVSxcbiAgICAgICAgICAgICAgICB3aWR0aDogNTAwLFxuICAgICAgICAgICAgICAgIGJ1dHRvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IFJlc291cmNlcy5TRUFSQ0gsXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgemlwQ29kZSA9ICQoJyN1c2VyLXppcCcpLnZhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkYXRlWmlwQ29kZSh6aXBDb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc2V0VXNlclppcCh6aXBDb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soemlwQ29kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcjdXNlci16aXAnKS5vbigna2V5cHJlc3MnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT09IDEzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciB0aGUgc2VhcmNoIGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy51aS1kaWFsb2ctYnV0dG9uc2V0IC51aS1idXR0b24nKS50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZ2V0U3RvcmVzSW52ZW50b3J5OiBmdW5jdGlvbiAocGlkKSB7XG4gICAgICByZXR1cm4gVFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLnN0b3Jlc0ludmVudG9yeSwge1xuICAgICAgICAgICAgICBwaWQ6IHBpZCxcbiAgICAgICAgICAgICAgemlwQ29kZTogVXNlci56aXBcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nXG4gICAgICB9KSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gb3BlbiB0aGUgZGlhbG9nIHRvIHNlbGVjdCBzdG9yZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG9wdGlvbnMuc3RvcmVzXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuc2VsZWN0ZWRTdG9yZUlkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuc2VsZWN0ZWRTdG9yZVRleHRcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmNvbnRpbnVlQ2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLnNlbGVjdFN0b3JlQ2FsbGJhY2tcbiAgICAgKiovXG4gICAgc2VsZWN0U3RvcmVEaWFsb2c6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgICAgIHN0b3JlcyA9IG9wdGlvbnMuc3RvcmVzLFxuICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZUlkID0gb3B0aW9ucy5zZWxlY3RlZFN0b3JlSWQsXG4gICAgICAgICAgICBzZWxlY3RlZFN0b3JlVGV4dCA9IG9wdGlvbnMuc2VsZWN0ZWRTdG9yZVRleHQsXG4gICAgICAgICAgICBzdG9yZUxpc3QgPSBzdG9yZUxpc3RUZW1wbGF0ZShzdG9yZXMsIHNlbGVjdGVkU3RvcmVJZCwgc2VsZWN0ZWRTdG9yZVRleHQpO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICBodG1sOiBzdG9yZUxpc3QsXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFJlc291cmNlcy5TRUxFQ1RfU1RPUkUgKyAnIC0gJyArIFVzZXIuemlwLFxuICAgICAgICAgICAgICAgIGJ1dHRvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IFJlc291cmNlcy5DSEFOR0VfTE9DQVRJT04sXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnNldFVzZXJaaXAobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0cmlnZ2VyIHRoZSBldmVudCB0byBzdGFydCB0aGUgcHJvY2VzcyBhbGwgb3ZlciBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnNldC1wcmVmZXJyZWQtc3RvcmUnKS50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IFJlc291cmNlcy5DT05USU5VRSxcbiAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmNvbnRpbnVlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmNvbnRpbnVlQ2FsbGJhY2soc3RvcmVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcuc2VsZWN0LXN0b3JlLWJ1dHRvbicpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RvcmVJZCA9ICQodGhpcykuZGF0YSgnc3RvcmVJZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHN0b3JlIGlzIGFscmVhZHkgc2VsZWN0ZWQsIGRvbid0IHNlbGVjdCBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3JlSWQgPT09IHNlbGVjdGVkU3RvcmVJZCkgeyByZXR1cm47IH1cbiAgICAgICAgICAgICAgICAgICAgICAgICQoJy5zdG9yZS1saXN0IC5zdG9yZS10aWxlLnNlbGVjdGVkJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLnNlbGVjdC1zdG9yZS1idXR0b24nKS50ZXh0KFJlc291cmNlcy5TRUxFQ1RfU1RPUkUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS50ZXh0KHNlbGVjdGVkU3RvcmVUZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jbG9zZXN0KCcuc3RvcmUtdGlsZScpLmFkZENsYXNzKCdzZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc2VsZWN0U3RvcmVDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2VsZWN0U3RvcmVDYWxsYmFjayhzdG9yZUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHNldFVzZXJaaXA6IGZ1bmN0aW9uICh6aXApIHtcbiAgICAgICAgVXNlci56aXAgPSB6aXA7XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgIHVybDogVXJscy5zZXRaaXBDb2RlLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHppcENvZGU6IHppcFxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHNoaXBwaW5nTG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGNoZWNrb3V0Rm9ybSA9ICQoJy5hZGRyZXNzJyk7XG4gICAgICAgICRjaGVja291dEZvcm0ub2ZmKCdjbGljaycpO1xuICAgICAgICAkY2hlY2tvdXRGb3JtLm9uKCdjbGljaycsICdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS5wYXJlbnQoKS5zaWJsaW5ncygnLmdpZnQtbWVzc2FnZS10ZXh0JykudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsICQoJ2lucHV0W25hbWUkPVwiX3NoaXBwaW5nQWRkcmVzc19pc0dpZnRcIl06Y2hlY2tlZCcpLnZhbCgpKTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzdG9yZWludmVudG9yeTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcbiAgICBpbnZlbnRvcnkgPSByZXF1aXJlKCcuLycpO1xuXG52YXIgbmV3TGluZSA9ICdcXG4nO1xudmFyIHBkcFN0b3JlVGVtcGxhdGUgPSBmdW5jdGlvbiAoc3RvcmUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAnPGxpIGNsYXNzPVwic3RvcmUtbGlzdC1pdGVtICcgKyAoc3RvcmUuc3RvcmVJZCA9PT0gVXNlci5zdG9yZUlkID8gJyBzZWxlY3RlZCcgOiAnJykgKyAnXCI+JyxcbiAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwic3RvcmUtYWRkcmVzc1wiPicgKyBzdG9yZS5hZGRyZXNzMSArICcsICcgKyBzdG9yZS5jaXR5ICsgJyAnICsgc3RvcmUuc3RhdGVDb2RlICtcbiAgICAgICAgJyAnICsgc3RvcmUucG9zdGFsQ29kZSArICc8L2Rpdj4nLFxuICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJzdG9yZS1zdGF0dXNcIiBkYXRhLXN0YXR1cz1cIicgKyBzdG9yZS5zdGF0dXNjbGFzcyArICdcIj4nICsgc3RvcmUuc3RhdHVzICsgJzwvZGl2PicsXG4gICAgICAgICc8L2xpPidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xudmFyIHBkcFN0b3Jlc0xpc3RpbmdUZW1wbGF0ZSA9IGZ1bmN0aW9uIChzdG9yZXMpIHtcbiAgICBpZiAoc3RvcmVzICYmIHN0b3Jlcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwic3RvcmUtbGlzdC1wZHAtY29udGFpbmVyXCI+JyxcbiAgICAgICAgICAgIChzdG9yZXMubGVuZ3RoID4gMSA/ICcgICAgPGEgY2xhc3M9XCJzdG9yZXMtdG9nZ2xlIGNvbGxhcHNlZFwiIGhyZWY9XCIjXCI+JyArIFJlc291cmNlcy5TRUVfTU9SRSArICc8L2E+JyA6ICcnKSxcbiAgICAgICAgICAgICcgICAgPHVsIGNsYXNzPVwic3RvcmUtbGlzdC1wZHBcIj4nLFxuICAgICAgICAgICAgXy5tYXAoc3RvcmVzLCBwZHBTdG9yZVRlbXBsYXRlKS5qb2luKG5ld0xpbmUpLFxuICAgICAgICAgICAgJyAgICA8L3VsPicsXG4gICAgICAgICAgICAnPC9kaXY+J1xuICAgICAgICBdLmpvaW4obmV3TGluZSk7XG4gICAgfVxufTtcblxudmFyIHN0b3Jlc0xpc3RpbmcgPSBmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgLy8gbGlzdCBhbGwgc3RvcmVzIG9uIFBEUCBwYWdlXG4gICAgaWYgKCQoJy5zdG9yZS1saXN0LXBkcC1jb250YWluZXInKS5sZW5ndGgpIHtcbiAgICAgICAgJCgnLnN0b3JlLWxpc3QtcGRwLWNvbnRhaW5lcicpLnJlbW92ZSgpO1xuICAgIH1cbiAgICAkKCcuYXZhaWxhYmlsaXR5LXJlc3VsdHMnKS5hcHBlbmQocGRwU3RvcmVzTGlzdGluZ1RlbXBsYXRlKHN0b3JlcykpO1xufTtcblxudmFyIHByb2R1Y3RJbnZlbnRvcnkgPSB7XG4gICAgc2V0UHJlZmVycmVkU3RvcmU6IGZ1bmN0aW9uIChzdG9yZUlkKSB7XG4gICAgICAgIFVzZXIuc3RvcmVJZCA9IHN0b3JlSWQ7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IFVybHMuc2V0UHJlZmVycmVkU3RvcmUsXG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhOiB7c3RvcmVJZDogc3RvcmVJZH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwcm9kdWN0U2VsZWN0U3RvcmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMucGlkKS50aGVuKGZ1bmN0aW9uIChzdG9yZXMpIHtcbiAgICAgICAgICAgIGludmVudG9yeS5zZWxlY3RTdG9yZURpYWxvZyh7XG4gICAgICAgICAgICAgICAgc3RvcmVzOiBzdG9yZXMsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZUlkOiBVc2VyLnN0b3JlSWQsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZVRleHQ6IFJlc291cmNlcy5QUkVGRVJSRURfU1RPUkUsXG4gICAgICAgICAgICAgICAgY29udGludWVDYWxsYmFjazogc3RvcmVzTGlzdGluZyxcbiAgICAgICAgICAgICAgICBzZWxlY3RTdG9yZUNhbGxiYWNrOiBzZWxmLnNldFByZWZlcnJlZFN0b3JlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuZG9uZSgpO1xuICAgIH0sXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGF2YWlsYWJpbGl0eUNvbnRhaW5lciA9ICQoJy5hdmFpbGFiaWxpdHktcmVzdWx0cycpLFxuICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG4gICAgICAgIHRoaXMucGlkID0gJCgnaW5wdXRbbmFtZT1cInBpZFwiXScpLnZhbCgpO1xuXG4gICAgICAgICQoJyNwcm9kdWN0LWNvbnRlbnQgLnNldC1wcmVmZXJyZWQtc3RvcmUnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgaWYgKCFVc2VyLnppcCkge1xuICAgICAgICAgICAgICAgIGludmVudG9yeS56aXBQcm9tcHQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByb2R1Y3RTZWxlY3RTdG9yZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLnByb2R1Y3RTZWxlY3RTdG9yZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoJGF2YWlsYWJpbGl0eUNvbnRhaW5lci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChVc2VyLnN0b3JlSWQpIHtcbiAgICAgICAgICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMucGlkKS50aGVuKHN0b3Jlc0xpc3RpbmcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZWUgbW9yZSBvciBsZXNzIHN0b3JlcyBpbiB0aGUgbGlzdGluZ1xuICAgICAgICAgICAgJGF2YWlsYWJpbGl0eUNvbnRhaW5lci5vbignY2xpY2snLCAnLnN0b3Jlcy10b2dnbGUnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAkKCcuc3RvcmUtbGlzdC1wZHAgLnN0b3JlLWxpc3QtaXRlbScpLnRvZ2dsZUNsYXNzKCd2aXNpYmxlJyk7XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykuaGFzQ2xhc3MoJ2NvbGxhcHNlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudGV4dChSZXNvdXJjZXMuU0VFX0xFU1MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudGV4dChSZXNvdXJjZXMuU0VFX01PUkUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkKHRoaXMpLnRvZ2dsZUNsYXNzKCdjb2xsYXBzZWQnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBwcm9kdWN0SW52ZW50b3J5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVuZGVyID0gZnVuY3Rpb24oc3R5bGVDb3VudENhY2hlKSB7XG5cdGlmIChzdHlsZUNvdW50Q2FjaGUpIHtcblx0XHQkKCdbZGF0YS1saW5rLWNhdGVnb3J5XScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2F0ZWdvcnlJZCA9ICQodGhpcykuZGF0YSgnbGluay1jYXRlZ29yeScpO1xuXHRcdFx0XG5cdFx0XHRpZiAoY2F0ZWdvcnlJZCkge1xuXHRcdFx0XHR2YXIgY2F0ZWdvcnlSZWZpbmVtZW50cyA9IHN0eWxlQ291bnRDYWNoZS5DYXRlZ29yeUxpbmtzW2NhdGVnb3J5SWRdO1xuXHRcdFx0XHRpZiAoY2F0ZWdvcnlSZWZpbmVtZW50cyAmJiBjYXRlZ29yeVJlZmluZW1lbnRzLmNvdW50ID4gMCkge1xuXHRcdFx0XHRcdHZhciAkc3R5bGVDb3VudCA9ICQodGhpcykuZmluZCgnLnN0eWxlLW51bWJlcicpOyBcblx0XHRcdFx0XHR2YXIgbWVzc2FnZVRlbXBsYXRlID0gY2F0ZWdvcnlSZWZpbmVtZW50cy5jb3VudCA+IDEgPyBSZXNvdXJjZXMuU1RZTEVfUExVUkFMIDogUmVzb3VyY2VzLlNUWUxFX1NJTkdVTEFSO1xuXHRcdFx0XHRcdHZhciBtZXNzYWdlID0gbWVzc2FnZVRlbXBsYXRlLnJlcGxhY2UoJ3swfScsIGNhdGVnb3J5UmVmaW5lbWVudHMuY291bnQpO1xuXHRcdFx0XHRcdCRzdHlsZUNvdW50LmFkZENsYXNzKCd2aXNpYmxlJykudGV4dChtZXNzYWdlKTtcblxuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVx0XG5cdFx0XHR9XG5cblx0XHRcdCQodGhpcykuY2xvc2VzdCgnbGknKS5yZW1vdmUoKTtcblx0XHR9KTtcblxuXHRcdCQoJ1tkYXRhLWxpbmstYXR0cmlidXRlLWlkXScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2F0ZWdvcnlJZCA9ICQodGhpcykuZGF0YSgnbGluay1jZ2lkJyksXG5cdFx0XHRyZWZpbmVtZW50SWQgPSAkKHRoaXMpLmRhdGEoJ2xpbmstYXR0cmlidXRlLWlkJyksXG5cdFx0XHRyZWZpbmVtZW50VmFsdWUgPSAkKHRoaXMpLmRhdGEoJ2xpbmstYXR0cmlidXRlLXZhbHVlJyk7XG5cblx0XHRcdHZhciBjYXRlZ29yeVJlZmluZW1lbnRzID0gc3R5bGVDb3VudENhY2hlLlJlZmluZW1lbnRMaW5rc1tjYXRlZ29yeUlkXTtcblx0XHRcdGlmIChjYXRlZ29yeVJlZmluZW1lbnRzKSB7XG5cdFx0XHRcdHZhciBhdHRyaWJ1dGVSZWZpbmVtZW50cyA9IGNhdGVnb3J5UmVmaW5lbWVudHNbcmVmaW5lbWVudElkXTtcblx0XHRcdFx0aWYgKGF0dHJpYnV0ZVJlZmluZW1lbnRzKSB7XG5cdFx0XHRcdFx0dmFyIGF0dHJpYnV0ZVJlZmluZW1lbnQgPSBhdHRyaWJ1dGVSZWZpbmVtZW50c1tyZWZpbmVtZW50VmFsdWVdO1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdGlmIChhdHRyaWJ1dGVSZWZpbmVtZW50ICYmIGF0dHJpYnV0ZVJlZmluZW1lbnQuY291bnQgPiAwKSB7XG5cdFx0XHRcdFx0XHR2YXIgJHN0eWxlQ291bnQgPSAkKHRoaXMpLmZpbmQoJy5zdHlsZS1udW1iZXInKTtcblx0XHRcdFx0XHRcdHZhciBtZXNzYWdlVGVtcGxhdGUgPSBhdHRyaWJ1dGVSZWZpbmVtZW50LmNvdW50ID4gMSA/IFJlc291cmNlcy5TVFlMRV9QTFVSQUwgOiBSZXNvdXJjZXMuU1RZTEVfU0lOR1VMQVI7XG5cdFx0XHRcdFx0XHR2YXIgbWVzc2FnZSA9IG1lc3NhZ2VUZW1wbGF0ZS5yZXBsYWNlKCd7MH0nLCBhdHRyaWJ1dGVSZWZpbmVtZW50LmNvdW50KTtcblx0XHRcdFx0XHRcdCRzdHlsZUNvdW50LmFkZENsYXNzKCd2aXNpYmxlJykudGV4dChtZXNzYWdlKTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9ICAgICAgICAgXHRcdFxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkKHRoaXMpLmNsb3Nlc3QoJ2xpJykucmVtb3ZlKCk7XG5cdFx0fSk7XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMucmVuZGVyID0gcmVuZGVyOyIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBDaGVja3MgdGhlIFRMUyBhbmQgZGlzcGxheXMgYSB3YXJuaW5nIGlmIGFwcHJvcHJpYXRlXG4gKiBAZnVuY3Rpb24gZ2V0VXNlckFnZW50IENoZWNrcyB0aGUgVExTIGFuZCBkaXNwbGF5cyBhIHdhcm5pbmcgaWYgYXBwcm9wcmlhdGVcbiAqKi9cbmZ1bmN0aW9uIGdldFVzZXJBZ2VudCgpIHtcbiAgICAvLyBVc2UgYW4gZXh0ZXJuYWwgc2VydmljZSB0byBjaGVjayB0aGUgVExTIG9mIHRoZSBicm93c2VyXG4gICAgLy8gTk9URTogdGhpcyBpbXBsZW1lbnRhdGlvbiB1c2VzIGh0dHBzOi8vd3d3Lmhvd3NteXNzbC5jb21cbiAgICAvLyAgICAgeW91IG1heSBhbHNvIHdpc2ggdG8gY29uc2lkZXIgdGhlIEFQSSBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cuc3NsbGFicy5jb20vcHJvamVjdHMvc3NsbGFicy1hcGlzL2luZGV4Lmh0bWxcbiAgICB2YXIgdXJsID0gJ2h0dHBzOi8vd3d3Lmhvd3NteXNzbC5jb20vYS9jaGVjayc7XG4gICAgdmFyIGNvb2tpZU5hbWUgPSAnZHdfVExTV2FybmluZyc7XG4gICAgdmFyIGNvb2tpZVZhbHVlID0gZ2V0Q29va2llKGNvb2tpZU5hbWUpO1xuXG4gICAgLy8gVGVzdCB0byBzZWUgaWYgdGhpcyBicm93c2VyIGhhcyBhbHJlYWR5IGJlZW4gZmxhZ2dlZCBieSBsb29raW5nIGF0IGl0cyBjb29raWVzXG4gICAgaWYgKCFjb29raWVWYWx1ZSkge1xuICAgICAgICBnZXRUTFModXJsLCBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNob3dXYXJuaW5nKG1lc3NhZ2VbMF0pO1xuXG4gICAgICAgICAgICAgICAgLy8gdGhlIGJyb3dzZXIgaXMgYmFkIC0gc2V0IHRoZSBjb29raWUgdG8gdHJ1ZSAoZm9yIDE1IG1pbnV0ZXMpXG4gICAgICAgICAgICAgICAgc2V0Q29va2llKGNvb2tpZU5hbWUsICd0cnVlJywgMTUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBlbHNlIHRoZSBicm93c2VyIGlzIGdvb2QsIHNldCB0aGUgY29va2llIHRvIGZhbHNlIChmb3IgMzAgZGF5cykgc28gd2UgZG9uJ3QgY2hlY2sgYWdhaW5cbiAgICAgICAgICAgICAgICBzZXRDb29raWUoY29va2llTmFtZSwgJ2ZhbHNlJywgNjAgKiAyNCAqIDMwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChjb29raWVWYWx1ZSA9PT0gJ3RydWUnKSB7XG4gICAgICAgIC8vIGlmIHdlIGFscmVhZHkga25vdyB0aGF0IHRoaXMgaXMgYW4gaW52YWxpZCBicm93c2VyLCBzaG93IHRoZSB3YXJuaW5nXG4gICAgICAgIHNob3dXYXJuaW5nKFJlc291cmNlcy5UTFNfV0FSTklORyk7XG4gICAgfVxufVxuXG4vKipcbiAqIENhbGxzIG91dCB0byB0aGUgVExTIHNlcnZpY2UgYW5kIGNhbGxzIHRoZSBjYWxsYmFjayB3aXRoIGEgbWVzc2FnZSAoaWYgbmVjZXNzYXJ5KVxuICogQGZ1bmN0aW9uIGdldFRMU1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgLSBVUkwgb2YgZXh0ZXJuYWwgVExTLWNoZWNraW5nIEFQSVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBmdW5jdGlvbiB0byBjYWxsIHdpdGggcmVzcG9uc2VcbiAqKi9cbmZ1bmN0aW9uIGdldFRMUyh1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG1lc3NhZ2UgPSBbXTtcblxuICAgIC8vIEZpcnN0LCBzZWUgaWYgdGhlIGJyb3dzZXIgaXMgYW1vbmcgdGhlIHN1c3BlY3QgYnJvd3NlcnMgdG8gc2VlIGlmIGEgVExTIGNoZWNrIGlzIG5lY2Vzc2FyeVxuICAgIHZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuXG4gICAgLyoqIFRoaXMgbGlzdCBkZXJpdmVkIGZyb20gaHR0cHM6Ly93d3cuc3NsbGFicy5jb20vc3NsdGVzdC9jbGllbnRzLmh0bWwgKiovXG4gICAgdmFyIGJhZEJyb3dzZXJzID0gWydNU0lFIDYuMCcsJ01TSUUgNy4wJywnTVNJRSA4LjAnLCdNU0lFIDkuMCcsJ01TSUUgMTAuMCcsXG4gICAgICAgICAgICAgICAgICAgICAgICdBbmRyb2lkIDIuMy43JywgJ0FuZHJvaWQgNC4wLjQnLCAnQW5kcm9pZCA0LjEuMScsICdBbmRyb2lkIDQuMi4yJywgJ0FuZHJvaWQgNC4zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgJ1NhZmFyaSA1LjEuOSAvIE9TIFggMTAuNi44JywgJ1NhZmFyaSA2LjAuNCAvIE9TIFggMTAuOC40ICddO1xuICAgIGZ1bmN0aW9uIGNoZWNrVExTTGV2ZWwoZGF0YSkge1xuICAgICAgICAvLyBJZiB3ZSBjYW4gZGV0ZXJtaW5lIHRoZSBUTFMgbGV2ZWwsIGNoZWNrIHRvIHNlZSBpZiBpdCdzIGxlc3MgdGhhbiAxLjJcbiAgICAgICAgaWYgKHBhcnNlRmxvYXQoZGF0YS50bHNfdmVyc2lvbi5zcGxpdCgnICcpWzFdKSA8IDEuMSkge1xuICAgICAgICAgICAgbWVzc2FnZS5wdXNoKFJlc291cmNlcy5UTFNfV0FSTklORyk7XG4gICAgICAgICAgICBjYWxsYmFjayhtZXNzYWdlKTtcblxuICAgICAgICAgICAgLy9JZiB5b3Ugd2FudCB0byB0cmFjayBzdGF0aXN0aWNzIG9uIGJhZCBUTFMgaGl0cywgaW5jbHVkZSB0aGlzIGNhbGxcbiAgICAgICAgICAgICQuYWpheCh7dXJsOiBVcmxzLlRMU0JhZFRMU30pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVwb3J0QmFkQnJvd3NlciAoKSB7XG4gICAgICAgIC8vIElmIHRoZSBUTFMgbGV2ZWwgY2Fubm90IGJlIGRldGVybWluZWQganVzdCByZXBvcnQgdGhhdCB0aGlzIGJyb3dzZXIgaXMgc3VzcGVjdFxuICAgICAgICBtZXNzYWdlLnB1c2goUmVzb3VyY2VzLlRMU19XQVJOSU5HKTtcbiAgICAgICAgY2FsbGJhY2sobWVzc2FnZSk7XG5cbiAgICAgICAgLy9JZiB5b3Ugd2FudCB0byB0cmFjayBzdGF0aXN0aWNzIG9uIGRlcHJlY2F0ZWQgYnJvd3NlcnMsIGluY2x1ZGUgdGhpcyBjYWxsXG4gICAgICAgICQuYWpheCh7dXJsOiBVcmxzLlRMU0JhZEJyb3dzZXJ9KTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJhZEJyb3dzZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICh1c2VyQWdlbnQubWF0Y2goYmFkQnJvd3NlcnNbaV0pKSB7XG4gICAgICAgICAgICAvLyBJdCdzIGEgc3VzcGVjdCBicm93c2VyLCBsZXQncyBzZWUgd2hhdCBpdCdzIFRMUyBsZXZlbCBpc1xuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB1cmw6IHVybFxuICAgICAgICAgICAgfSkuZG9uZShjaGVja1RMU0xldmVsKS5mYWlsKHJlcG9ydEJhZEJyb3dzZXIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogRm9yIHRlc3RpbmcgcHVycG9zZXMsIHVuY29tbWVudCB0aGlzIGJsb2NrXG4gICAgICAgIG1lc3NhZ2UucHVzaChSZXNvdXJjZXMuVExTX1dBUk5JTkcpO1xuICAgICoqL1xuICAgIGNhbGxiYWNrKG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBzaG93V2FybmluZyB0dXJucyBvbiB0aGUgYnJvd3Nlci1jb21wYXRpYmlsaXR5LWFsZXJ0IGFuZCBzZXRzIHRoZSBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSB0aGUgbWVzc2FnZSB0aGF0IHdpbGwgYmUgc2hvd24gdXBvbiBkZXRlY3Rpb24gb2YgYSBiYWQgYnJvd3NlclxuICoqL1xuZnVuY3Rpb24gc2hvd1dhcm5pbmcobWVzc2FnZSkge1xuICAgICQoJzxkaXYvPicpLmFkZENsYXNzKCdicm93c2VyLWNvbXBhdGliaWxpdHktYWxlcnQnKS5hcHBlbmQoJCgnPHAvPicpLmFkZENsYXNzKCdicm93c2VyLWVycm9yJykuaHRtbChtZXNzYWdlKSkuYXBwZW5kVG8oJyNicm93c2VyLWNoZWNrJyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uIGdldENvb2tpZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgY29va2llIG5hbWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHZhbHVlIC0gdGhlIHZhbHVlIG9mIHRoZSBjb29raWUgaWYgZm91bmQsIG51bGwgb3RoZXJ3aXNlXG4gKiovXG5mdW5jdGlvbiBnZXRDb29raWUoa2V5KSB7XG4gICAgdmFyIGNvb2tpZXMgPSBkb2N1bWVudC5jb29raWUuc3BsaXQoJzsnKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvb2tpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRva2VucyA9IGNvb2tpZXNbaV0uc3BsaXQoJz0nKTtcbiAgICAgICAgdmFyIGNvb2tpZUtleSA9IHRva2Vuc1swXS50cmltKCk7XG4gICAgICAgIGlmIChjb29raWVLZXkgPT09IGtleSkge1xuICAgICAgICAgICAgcmV0dXJuIHRva2Vuc1sxXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJyc7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uIHNldENvb2tpZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgY29va2llIG5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSBjb29raWUgdmFsdWVcbiAqIEBwYXJhbSB7aW50ZWdlcn0gbWludXRlcyAtIFRoZSBudW1iZXIgb2YgbWludXRlcyB0byBleHBpcmUgdGhlIGNvb2tpZVxuICoqL1xuZnVuY3Rpb24gc2V0Q29va2llIChrZXksIHZhbHVlLCBtaW51dGVzKSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZSgpO1xuICAgIGRhdGUuc2V0VGltZShkYXRlICsgKG1pbnV0ZXMgKiA2MCAqIDEwMDApKTtcblxuICAgIGRvY3VtZW50LmNvb2tpZSA9IGtleSArICc9JyArIHZhbHVlICsgJzsgZXhwaXJlcz0nICsgZGF0ZS50b0dNVFN0cmluZygpICsgJzsgcGF0aD0vJztcbn1cblxuLyoqXG4gKiBFeHBvcnQgdGhlIGdldFVzZXJBZ2VudCBmdW5jdGlvblxuICovXG5cbmV4cG9ydHMuZ2V0VXNlckFnZW50ID0gZ2V0VXNlckFnZW50O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSB0b29sdGlwLWNvbnRlbnQgYW5kIGxheW91dFxuICovXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbihvcHRpb25zUGFyYW1ldGVyLCAkY29udGFpbmVyUGFyYW1ldGVyKSB7XG5cdHZhciBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgaXRlbXM6ICcudG9vbHRpcCcsXG4gICAgICAgIHRyYWNrOiB0cnVlLFxuICAgICAgICBjb250ZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJCh0aGlzKS5maW5kKCcudG9vbHRpcC1jb250ZW50JykuaHRtbCgpO1xuICAgICAgICB9XG4gICAgfTtcblx0XG5cdHZhciBvcHRpb25zO1xuXHRpZiAob3B0aW9uc1BhcmFtZXRlcikge1xuXHRcdG9wdGlvbnMgPSAkLmV4dGVuZChkZWZhdWx0T3B0aW9ucywgb3B0aW9uc1BhcmFtZXRlcik7XG5cdH0gZWxzZSB7XG5cdFx0b3B0aW9ucyA9IGRlZmF1bHRPcHRpb25zO1xuXHR9XG5cdFxuXHR2YXIgJGNvbnRhaW5lcjtcblx0aWYgKCRjb250YWluZXJQYXJhbWV0ZXIpIHtcblx0XHQkY29udGFpbmVyID0gJGNvbnRhaW5lclBhcmFtZXRlcjtcblx0fSBlbHNlIHtcblx0XHQkY29udGFpbmVyID0gJChkb2N1bWVudCk7XG5cdH1cblx0XG4gICAgJGNvbnRhaW5lci50b29sdGlwKG9wdGlvbnMpO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9mZignY2xpY2snLCAnLnRvb2x0aXAnKS5vbignY2xpY2snLCAnLnRvb2x0aXAnLCBmdW5jdGlvbihlKSB7XG4gICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSk7XG4gICAgXG4gICAgJChkb2N1bWVudCkub2ZmKCdjbGljaycsICcuc2hhcmUtbGluaycpLm9uKCdjbGljaycsICcuc2hhcmUtbGluaycsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdGFyZ2V0ID0gJCh0aGlzKS5kYXRhKCd0YXJnZXQnKTtcbiAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgICAgJCh0YXJnZXQpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcbnZhciBQYXltZW50TWV0aG9kQ29uc3RhbnRzID0gcmVxdWlyZSgnLi4vLi4vLi4vYmNfc2hlcGxlcnNib290YmFybl9jb3JlL2NhcnRyaWRnZS9qcy9QYXltZW50SW5zdHJ1bWVudENvbnN0YW50cycpLlBheW1lbnRNZXRob2RzO1xudmFyIENyZWRpdENhcmRDb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi8uLi9iY19zaGVwbGVyc2Jvb3RiYXJuX2NvcmUvY2FydHJpZGdlL2pzL1BheW1lbnRJbnN0cnVtZW50Q29uc3RhbnRzJykuQ3JlZGl0Q2FyZHM7XG5cbnZhciB1dGlsID0ge1xuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBhcHBlbmRzIHRoZSBwYXJhbWV0ZXIgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgdmFsdWUgdG8gdGhlIGdpdmVuIHVybCBhbmQgcmV0dXJucyB0aGUgY2hhbmdlZCB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIHRoZSB1cmwgdG8gd2hpY2ggdGhlIHBhcmFtZXRlciB3aWxsIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHBhcmFtZXRlclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSB0aGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlclxuICAgICAqL1xuICAgIGFwcGVuZFBhcmFtVG9VUkw6IGZ1bmN0aW9uICh1cmwsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIC8vIHF1aXQgaWYgdGhlIHBhcmFtIGFscmVhZHkgZXhpc3RzXG4gICAgICAgIGlmICh1cmwuaW5kZXhPZihuYW1lICsgJz0nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNlcGFyYXRvciA9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyYnIDogJz8nO1xuXHRcdHZhciBhbmNob3IgPSAnJztcblx0XHRpZiAodXJsLmluZGV4T2YoJyMnKSA+IC0xKSB7XG4gICAgICAgICAgICB2YXIgdXJsQW5kQW5jaG9yID0gdXJsLnNwbGl0KCcjJyk7XG5cdFx0XHR1cmwgPSB1cmxBbmRBbmNob3JbMF07XG5cdFx0XHRhbmNob3IgPSAnIycgKyB1cmxBbmRBbmNob3JbMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybCArIHNlcGFyYXRvciArIG5hbWUgKyAodmFsdWUgPyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpIDogJycpICsgYW5jaG9yO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gcmVtb3ZlIHRoZSBwYXJhbWV0ZXIgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBnaXZlbiB1cmwgYW5kIHJldHVybnMgdGhlIGNoYW5nZWQgdXJsXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybCB0aGUgdXJsIGZyb20gd2hpY2ggdGhlIHBhcmFtZXRlciB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiBwYXJhbWV0ZXIgdGhhdCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB1cmxcbiAgICAgKi9cbiAgICByZW1vdmVQYXJhbUZyb21VUkw6IGZ1bmN0aW9uICh1cmwsIG5hbWUpIHtcbiAgICAgICAgaWYgKHVybC5pbmRleE9mKCc/JykgPT09IC0xIHx8IHVybC5pbmRleE9mKG5hbWUgKyAnPScpID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaGFzaDtcbiAgICAgICAgdmFyIHBhcmFtcztcbiAgICAgICAgdmFyIGRvbWFpbiA9IHVybC5zcGxpdCgnPycpWzBdO1xuICAgICAgICB2YXIgcGFyYW1VcmwgPSB1cmwuc3BsaXQoJz8nKVsxXTtcbiAgICAgICAgdmFyIG5ld1BhcmFtcyA9IFtdO1xuICAgICAgICAvLyBpZiB0aGVyZSBpcyBhIGhhc2ggYXQgdGhlIGVuZCwgc3RvcmUgdGhlIGhhc2hcbiAgICAgICAgaWYgKHBhcmFtVXJsLmluZGV4T2YoJyMnKSA+IC0xKSB7XG4gICAgICAgICAgICBoYXNoID0gcGFyYW1Vcmwuc3BsaXQoJyMnKVsxXSB8fCAnJztcbiAgICAgICAgICAgIHBhcmFtVXJsID0gcGFyYW1Vcmwuc3BsaXQoJyMnKVswXTtcbiAgICAgICAgfVxuICAgICAgICBwYXJhbXMgPSBwYXJhbVVybC5zcGxpdCgnJicpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcmFtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gcHV0IGJhY2sgcGFyYW0gdG8gbmV3UGFyYW1zIGFycmF5IGlmIGl0IGlzIG5vdCB0aGUgb25lIHRvIGJlIHJlbW92ZWRcbiAgICAgICAgICAgIGlmIChwYXJhbXNbaV0uc3BsaXQoJz0nKVswXSAhPT0gbmFtZSkge1xuICAgICAgICAgICAgICAgIG5ld1BhcmFtcy5wdXNoKHBhcmFtc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRvbWFpbiArICc/JyArIG5ld1BhcmFtcy5qb2luKCcmJykgKyAoaGFzaCA/ICcjJyArIGhhc2ggOiAnJyk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBhcHBlbmRzIHRoZSBwYXJhbWV0ZXJzIHRvIHRoZSBnaXZlbiB1cmwgYW5kIHJldHVybnMgdGhlIGNoYW5nZWQgdXJsXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybCB0aGUgdXJsIHRvIHdoaWNoIHRoZSBwYXJhbWV0ZXJzIHdpbGwgYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gICAgICovXG4gICAgYXBwZW5kUGFyYW1zVG9Vcmw6IGZ1bmN0aW9uICh1cmwsIHBhcmFtcykge1xuICAgICAgICB2YXIgX3VybCA9IHVybDtcbiAgICAgICAgXy5lYWNoKHBhcmFtcywgZnVuY3Rpb24gKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgICAgICBfdXJsID0gdGhpcy5hcHBlbmRQYXJhbVRvVVJMKF91cmwsIG5hbWUsIHZhbHVlKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgcmV0dXJuIF91cmw7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gZXh0cmFjdCB0aGUgcXVlcnkgc3RyaW5nIGZyb20gVVJMXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybCB0aGUgdXJsIHRvIGV4dHJhIHF1ZXJ5IHN0cmluZyBmcm9tXG4gICAgICoqL1xuICAgIGdldFF1ZXJ5U3RyaW5nOiBmdW5jdGlvbiAodXJsKSB7XG4gICAgICAgIHZhciBxcztcbiAgICAgICAgaWYgKCFfLmlzU3RyaW5nKHVybCkpIHsgcmV0dXJuOyB9XG4gICAgICAgIHZhciBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgIGlmIChhLnNlYXJjaCkge1xuICAgICAgICAgICAgcXMgPSBhLnNlYXJjaC5zdWJzdHIoMSk7IC8vIHJlbW92ZSB0aGUgbGVhZGluZyA/XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHFzO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogQHBhcmFtIHtTdHJpbmd9XG4gICAgICogQHBhcmFtIHtTdHJpbmd9XG4gICAgICovXG4gICAgZWxlbWVudEluVmlld3BvcnQ6IGZ1bmN0aW9uIChlbCwgb2Zmc2V0VG9Ub3ApIHtcbiAgICAgICAgdmFyIHRvcCA9IGVsLm9mZnNldFRvcCxcbiAgICAgICAgICAgIGxlZnQgPSBlbC5vZmZzZXRMZWZ0LFxuICAgICAgICAgICAgd2lkdGggPSBlbC5vZmZzZXRXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodCA9IGVsLm9mZnNldEhlaWdodDtcblxuICAgICAgICB3aGlsZSAoZWwub2Zmc2V0UGFyZW50KSB7XG4gICAgICAgICAgICBlbCA9IGVsLm9mZnNldFBhcmVudDtcbiAgICAgICAgICAgIHRvcCArPSBlbC5vZmZzZXRUb3A7XG4gICAgICAgICAgICBsZWZ0ICs9IGVsLm9mZnNldExlZnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mKG9mZnNldFRvVG9wKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRvcCAtPSBvZmZzZXRUb1RvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh3aW5kb3cucGFnZVhPZmZzZXQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdG9wIDwgKHdpbmRvdy5wYWdlWU9mZnNldCArIHdpbmRvdy5pbm5lckhlaWdodCkgJiZcbiAgICAgICAgICAgICAgICBsZWZ0IDwgKHdpbmRvdy5wYWdlWE9mZnNldCArIHdpbmRvdy5pbm5lcldpZHRoKSAmJlxuICAgICAgICAgICAgICAgICh0b3AgKyBoZWlnaHQpID4gd2luZG93LnBhZ2VZT2Zmc2V0ICYmXG4gICAgICAgICAgICAgICAgKGxlZnQgKyB3aWR0aCkgPiB3aW5kb3cucGFnZVhPZmZzZXRcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZG9jdW1lbnQuY29tcGF0TW9kZSA9PT0gJ0NTUzFDb21wYXQnKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHRvcCA8ICh3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCArIHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KSAmJlxuICAgICAgICAgICAgICAgIGxlZnQgPCAod2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0ICsgd2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCkgJiZcbiAgICAgICAgICAgICAgICAodG9wICsgaGVpZ2h0KSA+IHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wICYmXG4gICAgICAgICAgICAgICAgKGxlZnQgKyB3aWR0aCkgPiB3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnRcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEFwcGVuZHMgdGhlIHBhcmFtZXRlciAnZm9ybWF0PWFqYXgnIHRvIGEgZ2l2ZW4gcGF0aFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoIHRoZSByZWxhdGl2ZSBwYXRoXG4gICAgICovXG4gICAgYWpheFVybDogZnVuY3Rpb24gKHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXBwZW5kUGFyYW1Ub1VSTChwYXRoLCAnZm9ybWF0JywgJ2FqYXgnKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICAgICAqL1xuICAgIHRvQWJzb2x1dGVVcmw6IGZ1bmN0aW9uICh1cmwpIHtcbiAgICAgICAgaWYgKHVybC5pbmRleE9mKCdodHRwJykgIT09IDAgJiYgdXJsLmNoYXJBdCgwKSAhPT0gJy8nKSB7XG4gICAgICAgICAgICB1cmwgPSAnLycgKyB1cmw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBMb2FkcyBjc3MgZHluYW1pY2FsbHkgZnJvbSBnaXZlbiB1cmxzXG4gICAgICogQHBhcmFtIHtBcnJheX0gdXJscyBBcnJheSBvZiB1cmxzIGZyb20gd2hpY2ggY3NzIHdpbGwgYmUgZHluYW1pY2FsbHkgbG9hZGVkLlxuICAgICAqL1xuICAgIGxvYWREeW5hbWljQ3NzOiBmdW5jdGlvbiAodXJscykge1xuICAgICAgICB2YXIgaSwgbGVuID0gdXJscy5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdGhpcy5sb2FkZWRDc3NGaWxlcy5wdXNoKHRoaXMubG9hZENzc0ZpbGUodXJsc1tpXSkpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBMb2FkcyBjc3MgZmlsZSBkeW5hbWljYWxseSBmcm9tIGdpdmVuIHVybFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgVGhlIHVybCBmcm9tIHdoaWNoIGNzcyBmaWxlIHdpbGwgYmUgZHluYW1pY2FsbHkgbG9hZGVkLlxuICAgICAqL1xuICAgIGxvYWRDc3NGaWxlOiBmdW5jdGlvbiAodXJsKSB7XG4gICAgICAgIHJldHVybiAkKCc8bGluay8+JykuYXBwZW5kVG8oJCgnaGVhZCcpKS5hdHRyKHtcbiAgICAgICAgICAgIHR5cGU6ICd0ZXh0L2NzcycsXG4gICAgICAgICAgICByZWw6ICdzdHlsZXNoZWV0J1xuICAgICAgICB9KS5hdHRyKCdocmVmJywgdXJsKTsgLy8gZm9yIGkuZS4gPDksIGhyZWYgbXVzdCBiZSBhZGRlZCBhZnRlciBsaW5rIGhhcyBiZWVuIGFwcGVuZGVkIHRvIGhlYWRcbiAgICB9LFxuICAgIC8vIGFycmF5IHRvIGtlZXAgdHJhY2sgb2YgdGhlIGR5bmFtaWNhbGx5IGxvYWRlZCBDU1MgZmlsZXNcbiAgICBsb2FkZWRDc3NGaWxlczogW10sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyBhbGwgY3NzIGZpbGVzIHdoaWNoIHdlcmUgZHluYW1pY2FsbHkgbG9hZGVkXG4gICAgICovXG4gICAgY2xlYXJEeW5hbWljQ3NzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpID0gdGhpcy5sb2FkZWRDc3NGaWxlcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlICgwID4gaS0tKSB7XG4gICAgICAgICAgICAkKHRoaXMubG9hZGVkQ3NzRmlsZXNbaV0pLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9hZGVkQ3NzRmlsZXMgPSBbXTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBFeHRyYWN0cyBhbGwgcGFyYW1ldGVycyBmcm9tIGEgZ2l2ZW4gcXVlcnkgc3RyaW5nIGludG8gYW4gb2JqZWN0XG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHFzIFRoZSBxdWVyeSBzdHJpbmcgZnJvbSB3aGljaCB0aGUgcGFyYW1ldGVycyB3aWxsIGJlIGV4dHJhY3RlZFxuICAgICAqL1xuICAgIGdldFF1ZXJ5U3RyaW5nUGFyYW1zOiBmdW5jdGlvbiAocXMpIHtcbiAgICAgICAgaWYgKCFxcyB8fCBxcy5sZW5ndGggPT09IDApIHsgcmV0dXJuIHt9OyB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB7fSxcbiAgICAgICAgICAgIHVuZXNjYXBlZFFTID0gdW5lc2NhcGUocXMpO1xuICAgICAgICAvLyBVc2UgdGhlIFN0cmluZzo6cmVwbGFjZSBtZXRob2QgdG8gaXRlcmF0ZSBvdmVyIGVhY2hcbiAgICAgICAgLy8gbmFtZS12YWx1ZSBwYWlyIGluIHRoZSBzdHJpbmcuXG4gICAgICAgIHVuZXNjYXBlZFFTLnJlcGxhY2UobmV3IFJlZ0V4cCgnKFtePz0mXSspKD0oW14mXSopKT8nLCAnZycpLFxuICAgICAgICAgICAgZnVuY3Rpb24gKCQwLCAkMSwgJDIsICQzKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zWyQxXSA9ICQzO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH0sXG5cbiAgICBmaWxsQWRkcmVzc0ZpZWxkczogZnVuY3Rpb24gKGFkZHJlc3MsICRmb3JtKSB7XG4gICAgICAgIGZvciAodmFyIGZpZWxkIGluIGFkZHJlc3MpIHtcbiAgICAgICAgICAgIGlmIChmaWVsZCA9PT0gJ1VVSUQnIHx8IGZpZWxkID09PSAna2V5Jykge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgdGhlIGtleSBpbiBhZGRyZXNzIG9iamVjdCBlbmRzIHdpdGggJ0NvZGUnLCByZW1vdmUgdGhhdCBzdWZmaXhcbiAgICAgICAgICAgIC8vIGtleXMgdGhhdCBlbmRzIHdpdGggJ0NvZGUnIGFyZSBwb3N0YWxDb2RlLCBzdGF0ZUNvZGUgYW5kIGNvdW50cnlDb2RlXG4gICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHN0YXRlIGZpZWxkc1xuICAgICAgICAgICAgaWYgKGZpZWxkID09PSAnY291bnRyeUNvZGUnKSB7XG4gICAgICAgICAgICBcdCRmb3JtLmZpbmQoJ1tuYW1lJD1cImNvdW50cnlcIl0nKS52YWwoYWRkcmVzc1snY291bnRyeUNvZGUnXS50b1VwcGVyQ2FzZSgpKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgICAgICAvLyByZXRyaWdnZXIgc3RhdGUgc2VsZWN0aW9uIGFmdGVyIGNvdW50cnkgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHJlc3VsdHMgaW4gZHVwbGljYXRpb24gb2YgdGhlIHN0YXRlIGNvZGUsIGJ1dCBpcyBhIG5lY2Vzc2FyeSBldmlsXG4gICAgICAgICAgICAgICAgLy8gZm9yIG5vdyBiZWNhdXNlIHNvbWV0aW1lcyBjb3VudHJ5Q29kZSBjb21lcyBhZnRlciBzdGF0ZUNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdFxuICAgICAgICAgICAgXHR2YXIgc2VsZWN0ZWRTdGF0ZVZhbHVlID0gYWRkcmVzc1snc3RhdGVDb2RlJ107XG4gICAgICAgICAgICBcdGlmICgkZm9ybS5maW5kKCdbbmFtZSQ9XCJzdGF0ZVwiXSBvcHRpb25bbGFiZWw9XCInICsgYWRkcmVzc1snc3RhdGVDb2RlJ10gKyAnXCJdJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgXHRcdHNlbGVjdGVkU3RhdGVWYWx1ZSA9ICRmb3JtLmZpbmQoJ1tuYW1lJD1cInN0YXRlXCJdIG9wdGlvbltsYWJlbD1cIicgKyBhZGRyZXNzWydzdGF0ZUNvZGUnXSArICdcIl0nKS52YWwoKTtcbiAgICAgICAgICAgIFx0fVxuICAgICAgICAgICAgXHRcbiAgICAgICAgICAgIFx0JGZvcm0uZmluZCgnW25hbWUkPVwic3RhdGVcIl0nKS52YWwoc2VsZWN0ZWRTdGF0ZVZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZmllbGQgPT09ICdzdGF0ZUNvZGUnKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZFN0YXRlVmFsdWUgPSBhZGRyZXNzWydzdGF0ZUNvZGUnXTtcbiAgICAgICAgICAgIFx0aWYgKCRmb3JtLmZpbmQoJ1tuYW1lJD1cInN0YXRlXCJdIG9wdGlvbltsYWJlbD1cIicgKyBhZGRyZXNzWydzdGF0ZUNvZGUnXSArICdcIl0nKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBcdFx0c2VsZWN0ZWRTdGF0ZVZhbHVlID0gJGZvcm0uZmluZCgnW25hbWUkPVwic3RhdGVcIl0gb3B0aW9uW2xhYmVsPVwiJyArIGFkZHJlc3NbJ3N0YXRlQ29kZSddICsgJ1wiXScpLnZhbCgpO1xuICAgICAgICAgICAgXHR9XG4gICAgICAgICAgICBcdFxuICAgICAgICAgICAgXHQkZm9ybS5maW5kKCdbbmFtZSQ9XCJzdGF0ZVwiXScpLnZhbChzZWxlY3RlZFN0YXRlVmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFx0aWYgKGFkZHJlc3NbZmllbGRdICE9IG51bGwpIHtcbiAgICAgICAgICAgIFx0XHQkZm9ybS5maW5kKCdbbmFtZSQ9XCJfJyArIGZpZWxkLnJlcGxhY2UoJ0NvZGUnLCAnJykgKyAnXCJdJykudmFsKCgnJythZGRyZXNzW2ZpZWxkXSkucmVwbGFjZSgvXFxeL2dpLFwiJ1wiKSk7XG4gICAgICAgICAgICBcdH0gZWxzZSB7XG4gICAgICAgICAgICBcdFx0JGZvcm0uZmluZCgnW25hbWUkPVwiXycgKyBmaWVsZC5yZXBsYWNlKCdDb2RlJywgJycpICsgJ1wiXScpLnZhbChhZGRyZXNzW2ZpZWxkXSk7XG4gICAgICAgICAgICBcdH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIG51bWJlciBvZiB0aGUgcmVtYWluaW5nIGNoYXJhY3RlclxuICAgICAqIGJhc2VkIG9uIHRoZSBjaGFyYWN0ZXIgbGltaXQgaW4gYSB0ZXh0IGFyZWFcbiAgICAgKi9cbiAgICBsaW1pdENoYXJhY3RlcnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnZm9ybScpLmZpbmQoJ3RleHRhcmVhW2RhdGEtY2hhcmFjdGVyLWxpbWl0XScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNoYXJhY3RlckxpbWl0ID0gJCh0aGlzKS5kYXRhKCdjaGFyYWN0ZXItbGltaXQnKTtcbiAgICAgICAgICAgIHZhciBjaGFyQ291bnRIdG1sID0gU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ0hBUl9MSU1JVF9NU0csXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiY2hhci1yZW1haW4tY291bnRcIj4nICsgY2hhcmFjdGVyTGltaXQgKyAnPC9zcGFuPicsXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiY2hhci1hbGxvd2VkLWNvdW50XCI+JyArIGNoYXJhY3RlckxpbWl0ICsgJzwvc3Bhbj4nKTtcbiAgICAgICAgICAgIHZhciBjaGFyQ291bnRDb250YWluZXIgPSAkKHRoaXMpLm5leHQoJ2Rpdi5jaGFyLWNvdW50Jyk7XG4gICAgICAgICAgICBpZiAoY2hhckNvdW50Q29udGFpbmVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNoYXJDb3VudENvbnRhaW5lciA9ICQoJzxkaXYgY2xhc3M9XCJjaGFyLWNvdW50XCIvPicpLmluc2VydEFmdGVyKCQodGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hhckNvdW50Q29udGFpbmVyLmh0bWwoY2hhckNvdW50SHRtbCk7XG4gICAgICAgICAgICAvLyB0cmlnZ2VyIHRoZSBrZXlkb3duIGV2ZW50IHNvIHRoYXQgYW55IGV4aXN0aW5nIGNoYXJhY3RlciBkYXRhIGlzIGNhbGN1bGF0ZWRcbiAgICAgICAgICAgICQodGhpcykuY2hhbmdlKCk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBvbmNsaWNrLWV2ZW50IHRvIGEgZGVsZXRlIGJ1dHRvbiBvbiBhIGdpdmVuIGNvbnRhaW5lcixcbiAgICAgKiB3aGljaCBvcGVucyBhIGNvbmZpcm1hdGlvbiBib3ggd2l0aCBhIGdpdmVuIG1lc3NhZ2VcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gY29udGFpbmVyIFRoZSBuYW1lIG9mIGVsZW1lbnQgdG8gd2hpY2ggdGhlIGZ1bmN0aW9uIHdpbGwgYmUgYmluZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRoZSB3aWxsIGJlIHNob3duIHVwb24gYSBjbGlja1xuICAgICAqL1xuICAgIHNldERlbGV0ZUNvbmZpcm1hdGlvbjogZnVuY3Rpb24gKGNvbnRhaW5lciwgbWVzc2FnZSkge1xuICAgICAgICAkKGNvbnRhaW5lcikub24oJ2NsaWNrJywgJy5kZWxldGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmNvbmZpcm0obWVzc2FnZSk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFNjcm9sbHMgYSBicm93c2VyIHdpbmRvdyB0byBhIGdpdmVuIHggcG9pbnRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gVGhlIHggY29vcmRpbmF0ZVxuICAgICAqL1xuICAgIHNjcm9sbEJyb3dzZXI6IGZ1bmN0aW9uICh4TG9jYXRpb24pIHtcbiAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoe3Njcm9sbFRvcDogeExvY2F0aW9ufSwgNTAwKTtcbiAgICB9LFxuICAgIFxuICAgIGlzVG91Y2hEZXZpY2U6IGZ1bmN0aW9uKCkge1xuICAgIFx0Ly9kZXRlY3QgdG91Y2gtYWJpbGl0eSAobWF4VG91Y2hQb2ludHMgZm9yIHdpbmRvd3Mgc3VyZmFjZSlcbiAgICBcdHJldHVybiAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93IHx8IG5hdmlnYXRvci5tc01heFRvdWNoUG9pbnRzIHx8IG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cyA+IDApO1xuICAgIH0sXG5cbiAgICBpc01vYmlsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbW9iaWxlQWdlbnRIYXNoID0gWydtb2JpbGUnLCAndGFibGV0JywgJ3Bob25lJywgJ2lwYWQnLCAnaXBvZCcsICdhbmRyb2lkJywgJ2JsYWNrYmVycnknLCAnd2luZG93cyBjZScsICdvcGVyYSBtaW5pJywgJ3BhbG0nXTtcbiAgICAgICAgdmFyICAgIGlkeCA9IDA7XG4gICAgICAgIHZhciBpc01vYmlsZSA9IGZhbHNlO1xuICAgICAgICB2YXIgdXNlckFnZW50ID0gKG5hdmlnYXRvci51c2VyQWdlbnQpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgd2hpbGUgKG1vYmlsZUFnZW50SGFzaFtpZHhdICYmICFpc01vYmlsZSkge1xuICAgICAgICAgICAgaXNNb2JpbGUgPSAodXNlckFnZW50LmluZGV4T2YobW9iaWxlQWdlbnRIYXNoW2lkeF0pID49IDApO1xuICAgICAgICAgICAgaWR4Kys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzTW9iaWxlO1xuICAgIH0sXG4gICAgXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFZhbGlkYXRlcyBlLW1haWwgYWRkcmVzc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBFLW1haWwgYWRkcmVzc1xuICAgICAqIEByZXR1cm5zIHtCb29sZWFufVxuICAgICAqL1xuICAgIHZhbGlkYXRlRW1haWw6IGZ1bmN0aW9uIChlbWFpbCkge1xuICAgICAgICB2YXIgcmUgPSAvXigoW148PigpXFxbXFxdXFxcXC4sOzpcXHNAXCJdKyhcXC5bXjw+KClcXFtcXF1cXFxcLiw7Olxcc0BcIl0rKSopfChcIi4rXCIpKUAoKFxcW1swLTldezEsM31cXC5bMC05XXsxLDN9XFwuWzAtOV17MSwzfVxcLlswLTldezEsM31dKXwoKFthLXpBLVpcXC0wLTldK1xcLikrW2EtekEtWl17Mix9KSkkLztcbiAgICAgICAgcmV0dXJuIHJlLnRlc3QoZW1haWwpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gSGVscGVyIG1ldGhvZCB0byBlbmNvZGUgaW5wdXRzIGFuZCBwcmV2ZW50IHhzc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtTdHJpbmd9XG4gICAgICovXG4gICAgaHRtbEVuY29kZTogZnVuY3Rpb24gKHZhbHVlKSB7IFxuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBqUXVlcnkoJzxkaXYvPicpLnRleHQodmFsdWUpLmh0bWwoKTsgXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIFxuICAgIC8qKlxuICAgICAqIExpbWl0cyBhIHRleHQgaW5wdXQgdG8gYSBkZWZpbmVkIGxlbmd0aC4gXG4gICAgICogQHBhcmFtIChTdHJpbmcpIGlucHV0U2VsZWN0b3IgLSBBIGpRdWVyeSBzZWxlY3RvciBmb3IgdGhlIGlucHV0IHRvIGxpbWl0LlxuICAgICAqIEBwYXJhbSAoTnVtYmVyKSBsZW5ndGhMaW1pdCAtIFRoZSBsZW5ndGggdG8gbGltaXQgdGhlIGlucHV0IHRvLlxuICAgICAqIEByZXR1cm4gdm9pZFxuICAgICAqL1xuICAgIGxpbWl0SW5wdXRUb0xlbmd0aDogZnVuY3Rpb24gKGlucHV0U2VsZWN0b3IsIGxlbmd0aExpbWl0KSB7XG4gICAgICAgICQoaW5wdXRTZWxlY3Rvcikub24oXCJrZXl1cCBjbGlja1wiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52YWx1ZS5sZW5ndGggPiBsZW5ndGhMaW1pdCkge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlLnN1YnN0cmluZygwLCBsZW5ndGhMaW1pdCk7XG4gICAgXHRcdH1cbiAgICBcdH0pO1xuICAgIH0sXG4gICAgXG4gICAgLyoqXG4gICAgICogRGV0ZWN0cyB0aGUgY3JlZGl0IGNhcmQgdHlwZSBiYXNlZCBvZmYgb2YgdGhlIHByb3ZpZGVkIGNyZWRpdCBjYXJkIG51bWJlci5cbiAgICAgKiBAcGFyYW0gKFN0cmluZykgY3JlZGl0Q2FyZE51bWJlciAtIFRoZSBjcmVkaXQgY2FyZCBudW1iZXIgdG8gZGV0ZWN0IHRoZSB0eXBlIGZvci5cbiAgICAgKiBAcmV0dXJuIChTdHJpbmcpIC0gVGhlIHR5cGUgb2YgY3JlZGl0IGNhcmQuXG4gICAgICovXG4gICAgZ2V0Q3JlZGl0Q2FyZFR5cGU6IGZ1bmN0aW9uIChjcmVkaXRDYXJkTnVtYmVyKSB7XG4gICAgICAgIGNyZWRpdENhcmROdW1iZXIgPSBjcmVkaXRDYXJkTnVtYmVyLnJlcGxhY2UoL1xcRC9nLCAnJyk7XG4gICAgICAgIFxuICAgICAgICBpZiAoY3JlZGl0Q2FyZE51bWJlci5sZW5ndGggPj0gNCkge1xuXHQgICAgICAgIHZhciBjcmVkaXRDYXJkVHlwZXMgPSBbXG5cdCAgICAgICAgXHR7XG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkOiBDcmVkaXRDYXJkQ29uc3RhbnRzLlZpc2EsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5WaXNhLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ140WzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5BbWVyaWNhbkV4cHJlc3MsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5BbWVyaWNhbkV4cHJlc3MsXG5cdCAgICAgICAgXHRcdFBheW1lbnRNZXRob2Q6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXjNbNDddWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5EaW5lcnMsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5EaXNjb3Zlcixcblx0ICAgICAgICBcdFx0UGF5bWVudE1ldGhvZDogUGF5bWVudE1ldGhvZENvbnN0YW50cy5DcmVkaXRDYXJkLFxuXHQgICAgICAgIFx0XHRQYXR0ZXJuOiBuZXcgUmVnRXhwKCdeMyg/OjBbMC01OV17MX18WzY4OV0pWzAtOV17MCx9JCcpXG5cdCAgICAgICAgXHR9LFxuXHQgICAgICAgIFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5KQ0IsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5KQ0IsXG5cdCAgICAgICAgXHRcdFBheW1lbnRNZXRob2Q6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXig/OjIxMzF8MTgwMHwzNSlbMC05XXswLH0kJylcblx0ICAgICAgICBcdH0sXG5cdCAgICAgICAgXHR7XG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkOiBDcmVkaXRDYXJkQ29uc3RhbnRzLk1hc3RlcmNhcmQsXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYXN0ZXJjYXJkLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14oNVsxLTVdKVswLTldezAsfSQnKVxuXHQgICAgICAgIFx0fSxcblx0XHRcdFx0e1xuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZDogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYXN0ZXJjYXJkU2VyaWVzMixcblx0ICAgICAgICBcdFx0UGF5bWVudENhcmREaXNwbGF5S2V5OiBDcmVkaXRDYXJkQ29uc3RhbnRzLk1hc3RlcmNhcmQsXG5cdCAgICAgICAgXHRcdFBheW1lbnRNZXRob2Q6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXigyMjJbMS05XXwyMlszLTldfDJbMy02XXwyN1swMV18MjcyMClbMC05XXswLH0kJylcblx0ICAgICAgICBcdH0sXG5cdCAgICAgICAgXHR7XG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkOiBDcmVkaXRDYXJkQ29uc3RhbnRzLkRpc2NvdmVyLFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IENyZWRpdENhcmRDb25zdGFudHMuRGlzY292ZXIsXG5cdCAgICAgICAgXHRcdFBheW1lbnRNZXRob2Q6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQ3JlZGl0Q2FyZCxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXig2MDExfDY1fDY0WzQtOV18NjIyMTJbNi05XXw2MjIxWzMtOV18NjIyWzItOF18NjIyOVswMV18NjIyOTJbMC01XSlbMC05XXswLH0kJylcblx0ICAgICAgICBcdH0sXG5cdCAgICAgICAgXHR7XG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkOiBDcmVkaXRDYXJkQ29uc3RhbnRzLk1hZXN0cm8sXG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkRGlzcGxheUtleTogQ3JlZGl0Q2FyZENvbnN0YW50cy5NYXN0ZXJjYXJkLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkNyZWRpdENhcmQsXG5cdCAgICAgICAgXHRcdFBhdHRlcm46IG5ldyBSZWdFeHAoJ14oNVswNjc4OV18NilbMC05XXswLH0kJylcblx0ICAgICAgICBcdH0sXG5cdCAgICAgICAgXHR7XG5cdCAgICAgICAgXHRcdFBheW1lbnRDYXJkOiBDcmVkaXRDYXJkQ29uc3RhbnRzLkJvb3RCYXJuQ3JlZGl0LFxuXHQgICAgICAgIFx0XHRQYXltZW50Q2FyZERpc3BsYXlLZXk6IFBheW1lbnRNZXRob2RDb25zdGFudHMuQWxsaWFuY2VEYXRhLFxuXHQgICAgICAgIFx0XHRQYXltZW50TWV0aG9kOiBQYXltZW50TWV0aG9kQ29uc3RhbnRzLkFsbGlhbmNlRGF0YSxcblx0ICAgICAgICBcdFx0UGF0dGVybjogbmV3IFJlZ0V4cCgnXjc3ODhbMC05XXswLH0kJylcblx0ICAgICAgICBcdH1cblx0ICAgICAgICBdXG5cdCAgICAgICAgXG5cdCAgICAgICAgZm9yICh2YXIgY3JlZGl0Q2FyZFR5cGVLZXkgaW4gY3JlZGl0Q2FyZFR5cGVzKSB7XG5cdCAgICAgICAgXHR2YXIgY3JlZGl0Q2FyZFR5cGUgPSBjcmVkaXRDYXJkVHlwZXNbY3JlZGl0Q2FyZFR5cGVLZXldO1xuXHQgICAgICAgIFx0XG5cdCAgICAgICAgXHRpZiAoY3JlZGl0Q2FyZFR5cGUuUGF0dGVybiAmJiBjcmVkaXRDYXJkTnVtYmVyLm1hdGNoKGNyZWRpdENhcmRUeXBlLlBhdHRlcm4pKSB7XG5cdCAgICAgICAgXHRcdHJldHVybiBjcmVkaXRDYXJkVHlwZTtcblx0ICAgICAgICBcdH1cblx0ICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICBcbiAgICAvKipcbiAgICAgKiBNYXNrcyBhIHByb3ZpZGVkIG51bWJlci5cbiAgICAgKiBAcGFyYW0gKE51bWJlciBvciBTdHJpbmcpIG51bWJlciAtIFRoZSBudW1iZXIgdG8gbWFzay5cbiAgICAgKiBAcGFyYW0gKE51bWJlcikgbGVuZ3RoVG9TaG93IC0gVGhlIGxlbmd0aCBvZiB0aGUgbnVtYmVyIHRvIGxlYXZlIHVubWFza2VkIGF0IGVuZC5cbiAgICAgKiBAcGFyYW0gKFN0cmluZykgbWFza0NoYXJhY3RlciAtIFRoZSBjaGFyYWN0ZXIgdG8gdXNlIGZvciBtYXNraW5nLiBEZWZhdWx0cyB0byAqLlxuICAgICAqIEByZXR1cm4gKFN0cmluZykgLSBUaGUgdHlwZSBvZiBjcmVkaXQgY2FyZC5cbiAgICAgKi9cbiAgICBnZXRNYXNrZWROdW1iZXI6IGZ1bmN0aW9uIChudW1iZXIsIGxlbmd0aFRvU2hvdywgbWFza1BhdHRlcm4pIHtcbiAgICBcdGlmICghbnVtYmVyKSB7XG4gICAgXHRcdHJldHVybiAnJztcdFxuICAgIFx0fVxuICAgIFx0XG4gICAgXHRsZW5ndGhUb1Nob3cgPSBsZW5ndGhUb1Nob3cgfHwgNDtcbiAgICBcdG1hc2tQYXR0ZXJuID0gbWFza1BhdHRlcm4gfHwgJyonO1xuICAgICAgIFx0XG4gICAgICAgXHR2YXIgbnVtYmVyTWFza2VkO1xuICAgIFx0aWYgKG1hc2tQYXR0ZXJuLmxlbmd0aCA+IDEpIHtcbiAgICBcdFx0bnVtYmVyTWFza2VkID0gbWFza1BhdHRlcm47XG4gICAgXHR9IGVsc2UgaWYgKG1hc2tQYXR0ZXJuLmxlbmd0aCA+PSAxKSB7XG4gICAgXHRcdG51bWJlck1hc2tlZCA9IG5ldyBBcnJheShudW1iZXIubGVuZ3RoICsgMSkuam9pbihtYXNrUGF0dGVybik7XG4gICAgXHR9XG4gICAgICAgICAgICBcbiAgICBcdG51bWJlciArPSAnJztcbiAgICBcdGlmIChudW1iZXIgIT0gbnVsbCAmJiBudW1iZXIgIT0gJycpIHsgXG4gICAgXHRcdG51bWJlck1hc2tlZCA9IG51bWJlck1hc2tlZC5zdWJzdHIoMCwgbnVtYmVyLmxlbmd0aCAtIGxlbmd0aFRvU2hvdyk7IFxuICAgIFx0XHRudW1iZXJNYXNrZWQgKz0gbnVtYmVyLnN1YnN0cihudW1iZXIubGVuZ3RoIC0gbGVuZ3RoVG9TaG93KTtcbiAgICBcdH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBudW1iZXJNYXNrZWQ7XG4gICAgfSxcblxuXHRnZXRQcmVmZXJlbmNlVmFsdWVGcm9tV2luZG93TG9jYXRpb246IGZ1bmN0aW9uIChwcmVmZXJlbmNlTmFtZSkge1xuXHRcdHZhciBoYXNoID0gd2luZG93LmxvY2F0aW9uLmhhc2guc3Vic3RyKDEpLFxuXHRcdFx0cHJlZmVyZW5jZVZhbHVlID0gJycsXG5cdFx0XHRoYXNoVGFibGUgPSBoYXNoLnNwbGl0KCcmJykucmVkdWNlKGZ1bmN0aW9uIChoYXNoVGFibGUsIGl0ZW0pIHtcblx0XHRcdFx0dmFyIHBhcnRzID0gaXRlbS5zcGxpdCgnPScpO1xuXHRcdFx0XHRoYXNoVGFibGVbcGFydHNbMF1dID0gZGVjb2RlVVJJQ29tcG9uZW50KHBhcnRzWzFdKS5yZXBsYWNlKC9bXFwrXFxzXSsvZywgJyAnKTtcblx0XHRcdFx0cmV0dXJuIGhhc2hUYWJsZTtcblx0XHRcdH0sIHt9KTtcblx0XHRcblx0XHRmb3IgKHZhciBpID0gMTsgaSA8PSA1OyBpKyspe1xuXHRcdFx0aWYoIWhhc2hUYWJsZS5oYXNPd25Qcm9wZXJ0eSgncHJlZm4nICsgaSkpeyAgIFx0XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fSBlbHNlIGlmKGhhc2hUYWJsZVsncHJlZm4nICsgaV0gPT0gcHJlZmVyZW5jZU5hbWUpe1xuXHRcdFx0XHRwcmVmZXJlbmNlVmFsdWUgPSBoYXNoVGFibGVbJ3ByZWZ2JyArIGldO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0cmV0dXJuIHByZWZlcmVuY2VWYWx1ZTtcblx0fVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB1dGlsO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbmFQaG9uZSA9IC9eXFwrP1xcKD8oWzAtOV1bMC04XVswLTldKVxcKT9bXFwtXFwuIF0/KFsyLTldWzAtOV17Mn0pW1xcLVxcLiBdPyhbMC05XXs0fSkoXFxzKnhbMC05XSspPyQvO1xudmFyIGludGVybmF0aW9uYWxOdW1iZXIgPSAvXig/OlxccypcXCspP1tcXGRcXHNcXC5cXC1cXChcXCldKyQvO1xudmFyIGRlZmF1bHRQb3N0YWwgPSAvXlxcZHszLDd9JC87XG52YXIgcmVnZXggPSB7XG4gICAgcGhvbmU6IHtcbiAgICAgICAgdXM6IG5hUGhvbmUsXG4gICAgICAgIGNhOiBpbnRlcm5hdGlvbmFsTnVtYmVyLFxuICAgICAgICBmcjogaW50ZXJuYXRpb25hbE51bWJlcixcbiAgICAgICAgaXQ6IGludGVybmF0aW9uYWxOdW1iZXIsXG4gICAgICAgIGpwOiBpbnRlcm5hdGlvbmFsTnVtYmVyLFxuICAgICAgICBjbjogLy4qLyxcbiAgICAgICAgZ2I6IGludGVybmF0aW9uYWxOdW1iZXJcbiAgICB9LFxuICAgIHBvc3RhbDoge1xuICAgICAgICB1czogL15cXGR7NX0oLVxcZHs0fSk/JC8sXG4gICAgICAgIGNhOiAvXltBQkNFR0hKS0xNTlBSU1RWWFldezF9XFxkezF9W0EtWl17MX0gKlxcZHsxfVtBLVpdezF9XFxkezF9JC9pLFxuICAgICAgICBmcjogL14oRi0pPygoMltBfEJdKXxbMC05XXsyfSlbMC05XXszfSQvLFxuICAgICAgICBpdDogL14oWzAtOV0pezV9JC8sXG4gICAgICAgIGpwOiAvXihbMC05XSl7M31bLV0oWzAtOV0pezR9JC8sXG4gICAgICAgIGNuOiAvXihbMC05XSl7Nn0kLyxcbiAgICAgICAgZ2I6IC9eKFtBLVBSLVVXWVowLTldW0EtSEstWTAtOV1bQUVITU5QUlRWWFkwLTldP1tBQkVITU5QUlZXWFkwLTldPyB7MSwyfVswLTldW0FCRC1ISkxOLVVXLVpdezJ9fEdJUiAwQUEpJC9pXG4gICAgfSxcbiAgICBub3RDQzogL14oPyEoKFswLTkgLV0pezEzLDE5fSkpLiokL1xufTtcbi8vIGdsb2JhbCBmb3JtIHZhbGlkYXRvciBzZXR0aW5nc1xudmFyIHNldHRpbmdzID0ge1xuICAgIGVycm9yQ2xhc3M6ICdlcnJvcicsXG4gICAgZXJyb3JFbGVtZW50OiAnc3BhbicsXG4gICAgb25rZXl1cDogZmFsc2UsXG4gICAgb25mb2N1c291dDogZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNoZWNrYWJsZShlbGVtZW50KSkge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBlcnJvclBsYWNlbWVudDogZnVuY3Rpb24gKGVycm9yLCBlbGVtZW50KSB7XG4gICAgXHRlcnJvci5hcHBlbmRUbyhlbGVtZW50LnBhcmVudCgpKTtcbiAgICB9XG59O1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgYSBnaXZlbiBwaG9uZSBudW1iZXIgYWdhaW5zdCB0aGUgY291bnRyaWVzIHBob25lIHJlZ2V4XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgVGhlIHBob25lIG51bWJlciB3aGljaCB3aWxsIGJlIHZhbGlkYXRlZFxuICogQHBhcmFtIHtTdHJpbmd9IGVsIFRoZSBpbnB1dCBmaWVsZFxuICovXG52YXIgdmFsaWRhdGVQaG9uZSA9IGZ1bmN0aW9uICh2YWx1ZSwgZWwpIHtcbiAgICB2YXIgY291bnRyeSA9ICQoZWwpLmNsb3Nlc3QoJ2Zvcm0nKS5maW5kKCcuY291bnRyeScpO1xuICAgIHZhciBjb3VudHJ5VmFsdWU7XG4gICAgaWYgKGNvdW50cnkubGVuZ3RoID4gMCkge1xuICAgICAgICBjb3VudHJ5VmFsdWUgPSBjb3VudHJ5LnZhbCgpO1xuICAgIH1cblxuICAgIGlmICghY291bnRyeVZhbHVlIHx8ICFyZWdleC5waG9uZVtjb3VudHJ5LnZhbCgpLnRvTG93ZXJDYXNlKCldKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciByZ3ggPSByZWdleC5waG9uZVtjb3VudHJ5LnZhbCgpLnRvTG93ZXJDYXNlKCldO1xuICAgIHZhciBpc09wdGlvbmFsID0gdGhpcy5vcHRpb25hbChlbCk7XG4gICAgdmFyIGlzVmFsaWQgPSByZ3gudGVzdCgkLnRyaW0odmFsdWUpKTtcblxuICAgIHJldHVybiBpc09wdGlvbmFsIHx8IGlzVmFsaWQ7XG59O1xuXG52YXIgdmFsaWRhdGVQb3N0YWwgPSBmdW5jdGlvbiAodmFsdWUsIGVsKSB7XG4gICAgdmFyIGNvdW50cnkgPSAkKGVsKS5jbG9zZXN0KCdmb3JtJykuZmluZCgnLmNvdW50cnknKTtcbiAgICB2YXIgY291bnRyeVZhbHVlO1xuICAgIGlmIChjb3VudHJ5Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgY291bnRyeVZhbHVlID0gY291bnRyeS52YWwoKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvdW50cnlWYWx1ZSB8fCAhcmVnZXgucG9zdGFsW2NvdW50cnkudmFsKCkudG9Mb3dlckNhc2UoKV0pIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdmFyIHJneCA9IHJlZ2V4LnBvc3RhbFtjb3VudHJ5VmFsdWUudG9Mb3dlckNhc2UoKV07XG4gICAgdmFyIGlzT3B0aW9uYWwgPSB0aGlzLm9wdGlvbmFsKGVsKTtcbiAgICB2YXIgaXNWYWxpZCA9IHJneC50ZXN0KCQudHJpbSh2YWx1ZSkpO1xuXG4gICAgcmV0dXJuIGlzT3B0aW9uYWwgfHwgaXNWYWxpZDtcbn07XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRlcyB0aGF0IGEgY3JlZGl0IGNhcmQgb3duZXIgaXMgbm90IGEgQ3JlZGl0IGNhcmQgbnVtYmVyXG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgVGhlIG93bmVyIGZpZWxkIHdoaWNoIHdpbGwgYmUgdmFsaWRhdGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gZWwgVGhlIGlucHV0IGZpZWxkXG4gKi9cbnZhciB2YWxpZGF0ZU93bmVyID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdmFyIGlzVmFsaWQgPSByZWdleC5ub3RDQy50ZXN0KCQudHJpbSh2YWx1ZSkpO1xuICAgIHJldHVybiBpc1ZhbGlkO1xufTtcblxuLyoqXG4gKiBBZGQgcGhvbmUgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdwaG9uZScgY3NzIGNsYXNzIHRvIGJlIHZhbGlkYXRlZCBhcyBwaG9uZVxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bob25lJywgdmFsaWRhdGVQaG9uZSwgUmVzb3VyY2VzLklOVkFMSURfUEhPTkUpO1xuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCdwb3N0YWwnLCB2YWxpZGF0ZVBvc3RhbCwgUmVzb3VyY2VzLklOVkFMSURfWklQKTtcblxuLyoqXG4gKiBBZGQgQ0NPd25lciB2YWxpZGF0aW9uIG1ldGhvZCB0byBqUXVlcnkgdmFsaWRhdGlvbiBwbHVnaW4uXG4gKiBUZXh0IGZpZWxkcyBtdXN0IGhhdmUgJ293bmVyJyBjc3MgY2xhc3MgdG8gYmUgdmFsaWRhdGVkIGFzIG5vdCBhIGNyZWRpdCBjYXJkXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgnb3duZXInLCB2YWxpZGF0ZU93bmVyLCBSZXNvdXJjZXMuSU5WQUxJRF9PV05FUik7XG5cbi8qKlxuICogQWRkIGdpZnQgY2VydCBhbW91bnQgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdnaWZ0LWNlcnQtYW1vbnQnIGNzcyBjbGFzcyB0byBiZSB2YWxpZGF0ZWRcbiAqL1xuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCdnaWZ0LWNlcnQtYW1vdW50JywgZnVuY3Rpb24gKHZhbHVlLCBlbCkge1xuICAgIHZhciBpc09wdGlvbmFsID0gdGhpcy5vcHRpb25hbChlbCk7XG4gICAgdmFyIGlzVmFsaWQgPSAoIWlzTmFOKHZhbHVlKSkgJiYgKHBhcnNlRmxvYXQodmFsdWUpID49IDUpICYmIChwYXJzZUZsb2F0KHZhbHVlKSA8PSA1MDAwKTtcbiAgICByZXR1cm4gaXNPcHRpb25hbCB8fCBpc1ZhbGlkO1xufSwgUmVzb3VyY2VzLkdJRlRfQ0VSVF9BTU9VTlRfSU5WQUxJRCk7XG5cbi8qKlxuICogQWRkIHBvc2l0aXZlIG51bWJlciB2YWxpZGF0aW9uIG1ldGhvZCB0byBqUXVlcnkgdmFsaWRhdGlvbiBwbHVnaW4uXG4gKiBUZXh0IGZpZWxkcyBtdXN0IGhhdmUgJ3Bvc2l0aXZlbnVtYmVyJyBjc3MgY2xhc3MgdG8gYmUgdmFsaWRhdGVkIGFzIHBvc2l0aXZlbnVtYmVyXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgncG9zaXRpdmVudW1iZXInLCBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICBpZiAoJC50cmltKHZhbHVlKS5sZW5ndGggPT09IDApIHsgcmV0dXJuIHRydWU7IH1cbiAgICByZXR1cm4gKCFpc05hTih2YWx1ZSkgJiYgTnVtYmVyKHZhbHVlKSA+PSAwKTtcbn0sIFJlc291cmNlcy5WQUxJREFURV9OVU1CRVIpO1xuXG4vKipcbiAqIEFkZCBtZXRob2QgdG8gY2hlY2sgZm9yIGVtYWlsIGV4dGVuc2lvbiB3aGVuIHZhbGlkYXRpbmcgZW1haWxzLFxuICogc2luY2UgZGVmYXVsdCBzZXR0aW5ncyBkb24ndCByZXF1aXJlIGFuIGV4dGVuc2lvblxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoXCJyZXF1aXJlRW1haWxFeHRlbnNpb25cIiwgZnVuY3Rpb24odmFsdWUsIGVsZW1lbnQpIHtcbiAgICBpZiAoJC50cmltKHZhbHVlKS5sZW5ndGggPT09IDApIHsgcmV0dXJuIHRydWU7IH1cbiAgICByZXR1cm4gL15cXHcrKFstKy4nXVxcdyspKkBcXHcrKFstLl1cXHcrKSpcXC5cXHcrKFstLl1cXHcrKSokLy50ZXN0KHZhbHVlKTtcbn0sIFJlc291cmNlcy5WQUxJREFURV9FTUFJTCk7XG5cbi8qXG4gKiBMZXRzIHlvdSBzYXkgXCJhdCBsZWFzdCBYIGlucHV0cyB0aGF0IG1hdGNoIHNlbGVjdG9yIFkgbXVzdCBiZSBmaWxsZWQuXCJcbiAqXG4gKiBUaGUgZW5kIHJlc3VsdCBpcyB0aGF0IG5laXRoZXIgb2YgdGhlc2UgaW5wdXRzOlxuICpcbiAqICA8aW5wdXQgY2xhc3M9XCJwcm9kdWN0aW5mb1wiIG5hbWU9XCJwYXJ0bnVtYmVyXCI+XG4gKiAgPGlucHV0IGNsYXNzPVwicHJvZHVjdGluZm9cIiBuYW1lPVwiZGVzY3JpcHRpb25cIj5cbiAqXG4gKiAgLi4ud2lsbCB2YWxpZGF0ZSB1bmxlc3MgYXQgbGVhc3Qgb25lIG9mIHRoZW0gaXMgZmlsbGVkLlxuICpcbiAqIHBhcnRudW1iZXI6ICB7cmVxdWlyZV9mcm9tX2dyb3VwOiBbMSxcIi5wcm9kdWN0aW5mb1wiXX0sXG4gKiBkZXNjcmlwdGlvbjoge3JlcXVpcmVfZnJvbV9ncm91cDogWzEsXCIucHJvZHVjdGluZm9cIl19XG4gKlxuICogb3B0aW9uc1swXTogbnVtYmVyIG9mIGZpZWxkcyB0aGF0IG11c3QgYmUgZmlsbGVkIGluIHRoZSBncm91cFxuICogb3B0aW9uc1sxXTogQ1NTIHNlbGVjdG9yIHRoYXQgZGVmaW5lcyB0aGUgZ3JvdXAgb2YgY29uZGl0aW9uYWxseSByZXF1aXJlZCBmaWVsZHNcbiAqL1xuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCBcInJlcXVpcmVfZnJvbV9ncm91cFwiLCBmdW5jdGlvbiggdmFsdWUsIGVsZW1lbnQsIG9wdGlvbnMgKSB7XG4gICAgdmFyICRmaWVsZHMgPSAkKG9wdGlvbnNbMV0sIGVsZW1lbnQuZm9ybSk7XG4gICAgdmFyICRmaWVsZHNGaXJzdCA9ICRmaWVsZHMuZXEoMCk7XG4gICAgdmFyIHZhbGlkYXRvciA9ICRmaWVsZHNGaXJzdC5kYXRhKFwidmFsaWRfcmVxX2dycFwiKSA/ICRmaWVsZHNGaXJzdC5kYXRhKFwidmFsaWRfcmVxX2dycFwiKSA6ICQuZXh0ZW5kKHt9LCB0aGlzKTtcbiAgICB2YXIgaXNWYWxpZCA9ICRmaWVsZHMuZmlsdGVyKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdmFsaWRhdG9yLmVsZW1lbnRWYWx1ZSh0aGlzKTtcbiAgICB9KS5sZW5ndGggPj0gb3B0aW9uc1swXTtcblxuICAgIC8vIFN0b3JlIHRoZSBjbG9uZWQgdmFsaWRhdG9yIGZvciBmdXR1cmUgdmFsaWRhdGlvblxuICAgICRmaWVsZHNGaXJzdC5kYXRhKFwidmFsaWRfcmVxX2dycFwiLCB2YWxpZGF0b3IpO1xuXG4gICAgLy8gSWYgZWxlbWVudCBpc24ndCBiZWluZyB2YWxpZGF0ZWQsIHJ1biBlYWNoIHJlcXVpcmVfZnJvbV9ncm91cCBmaWVsZCdzIHZhbGlkYXRpb24gcnVsZXNcbiAgICBpZiAoISQoZWxlbWVudCkuZGF0YShcImJlaW5nX3ZhbGlkYXRlZFwiKSkge1xuICAgICAgICAkZmllbGRzLmRhdGEoXCJiZWluZ192YWxpZGF0ZWRcIiwgdHJ1ZSk7XG4gICAgICAgICRmaWVsZHMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhbGlkYXRvci5lbGVtZW50KHRoaXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgJGZpZWxkcy5kYXRhKFwiYmVpbmdfdmFsaWRhdGVkXCIsIGZhbHNlKTtcbiAgICB9XG4gICAgcmV0dXJuIGlzVmFsaWQ7XG59LCAkLnZhbGlkYXRvci5mb3JtYXQoXCJQbGVhc2UgZmlsbCBhdCBsZWFzdCB7MH0gb2YgdGhlc2UgZmllbGRzLlwiKSk7XG5cbiQuZXh0ZW5kKCQudmFsaWRhdG9yLm1lc3NhZ2VzLCB7XG4gICAgcmVxdWlyZWQ6IFJlc291cmNlcy5WQUxJREFURV9SRVFVSVJFRCxcbiAgICByZW1vdGU6IFJlc291cmNlcy5WQUxJREFURV9SRU1PVEUsXG4gICAgZW1haWw6IFJlc291cmNlcy5WQUxJREFURV9FTUFJTCxcbiAgICB1cmw6IFJlc291cmNlcy5WQUxJREFURV9VUkwsXG4gICAgZGF0ZTogUmVzb3VyY2VzLlZBTElEQVRFX0RBVEUsXG4gICAgZGF0ZUlTTzogUmVzb3VyY2VzLlZBTElEQVRFX0RBVEVJU08sXG4gICAgbnVtYmVyOiBSZXNvdXJjZXMuVkFMSURBVEVfTlVNQkVSLFxuICAgIGRpZ2l0czogUmVzb3VyY2VzLlZBTElEQVRFX0RJR0lUUyxcbiAgICBjcmVkaXRjYXJkOiBSZXNvdXJjZXMuVkFMSURBVEVfQ1JFRElUQ0FSRCxcbiAgICBlcXVhbFRvOiBSZXNvdXJjZXMuVkFMSURBVEVfRVFVQUxUTyxcbiAgICBtYXhsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUFYTEVOR1RIKSxcbiAgICBtaW5sZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUlOTEVOR1RIKSxcbiAgICByYW5nZWxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WQUxJREFURV9SQU5HRUxFTkdUSCksXG4gICAgcmFuZ2U6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfUkFOR0UpLFxuICAgIG1heDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WQUxJREFURV9NQVgpLFxuICAgIG1pbjogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WQUxJREFURV9NSU4pXG59KTtcblxudmFyIHZhbGlkYXRvciA9IHtcbiAgICByZWdleDogcmVnZXgsXG4gICAgc2V0dGluZ3M6IHNldHRpbmdzLFxuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAkKCdmb3JtOm5vdCguc3VwcHJlc3MpJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkKHRoaXMpLnZhbGlkYXRlKHNlbGYuc2V0dGluZ3MpO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGluaXRGb3JtOiBmdW5jdGlvbiAoZikge1xuICAgICAgICAkKGYpLnZhbGlkYXRlKHRoaXMuc2V0dGluZ3MpO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdmFsaWRhdG9yO1xuIiwiLyogXG4gKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqIFxuICogd2F0ZXJtYXJrLmpzIC0gQ3JlYXRlIHdhdGVybWFya2VkIGltYWdlcyB3aXRoIENhbnZhcyBhbmQgSlNcbiAqXG4gKiBWZXJzaW9uOiAxICgyMDExLTA0LTA0KVxuICogQ29weXJpZ2h0IChjKSAyMDExXHRQYXRyaWNrIFdpZWQgKCBodHRwOi8vd3d3LnBhdHJpY2std2llZC5hdCApXG4gKiBUaGlzIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNSVQgTElDRU5TRVxuICpcbiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih3KXtcblx0dmFyIHcgPSB3aW5kb3c7XG5cdHZhciB3bSA9IChmdW5jdGlvbih3KXtcblx0XHR2YXIgZG9jID0gdy5kb2N1bWVudCxcblx0XHRnY2FudmFzID0ge30sXG5cdFx0Z2N0eCA9IHt9LFxuXHRcdGltZ1F1ZXVlID0gW10sXG5cdFx0Y2xhc3NOYW1lcyA9IFtcIndhdGVybWFya1wiXSxcblx0XHR3YXRlcm1hcmsgPSBmYWxzZSxcblx0XHR3YXRlcm1hcmtQb3NpdGlvbiA9IFwiYm90dG9tLXJpZ2h0XCIsXG5cdFx0d2F0ZXJtYXJrUGF0aCA9IFwid2F0ZXJtYXJrLnBuZz9cIisoKyhuZXcgRGF0ZSgpKSksXG5cdFx0b3BhY2l0eSA9ICgyNTUvKDEwMC81MCkpLCAvLyA1MCVcblx0XHRpbml0Q2FudmFzID0gZnVuY3Rpb24oKXtcblx0XHRcdGdjYW52YXMgPSBkb2MuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcblx0XHRcdGdjYW52YXMuc3R5bGUuY3NzVGV4dCA9IFwiZGlzcGxheTpub25lO1wiO1xuXHRcdFx0Z2N0eCA9IGdjYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuXHRcdFx0ZG9jLmJvZHkuYXBwZW5kQ2hpbGQoZ2NhbnZhcyk7XG5cdFx0fSxcblx0XHRpbml0V2F0ZXJtYXJrID0gZnVuY3Rpb24oKXtcblx0XHRcdHdhdGVybWFyayA9IG5ldyBJbWFnZSgpO1xuXHRcdFx0d2F0ZXJtYXJrLnNyYyA9IFwiXCI7XG5cdFx0XHR3YXRlcm1hcmsuc3JjID0gd2F0ZXJtYXJrUGF0aDtcblx0XHRcdFxuXHRcdFx0aWYob3BhY2l0eSAhPSAyNTUpe1xuXHRcdFx0XHRpZighd2F0ZXJtYXJrLmNvbXBsZXRlKVxuXHRcdFx0XHRcdHdhdGVybWFyay5vbmxvYWQgPSBmdW5jdGlvbigpe1x0XG5cdFx0XHRcdFx0XHRhcHBseVRyYW5zcGFyZW5jeSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdGFwcGx5VHJhbnNwYXJlbmN5KCk7XG5cdFx0XHRcdFxuXG5cdFx0XHR9ZWxzZXtcblx0XHRcdFx0YXBwbHlXYXRlcm1hcmtzKCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHR9LFxuXHRcdC8vIGZ1bmN0aW9uIGZvciBhcHBseWluZyB0cmFuc3BhcmVuY3kgdG8gdGhlIHdhdGVybWFya1xuXHRcdGFwcGx5VHJhbnNwYXJlbmN5ID0gZnVuY3Rpb24oKXtcblx0XHRcdHZhciB3ID0gd2F0ZXJtYXJrLndpZHRoIHx8IHdhdGVybWFyay5vZmZzZXRXaWR0aCxcblx0XHRcdGggPSB3YXRlcm1hcmsuaGVpZ2h0IHx8IHdhdGVybWFyay5vZmZzZXRIZWlnaHQ7XG5cdFx0XHRzZXRDYW52YXNTaXplKHcsIGgpO1xuXHRcdFx0Z2N0eC5kcmF3SW1hZ2Uod2F0ZXJtYXJrLCAwLCAwKTtcblx0XHRcdFx0XHRcblx0XHRcdHZhciBpbWFnZSA9IGdjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpO1xuXHRcdFx0dmFyIGltYWdlRGF0YSA9IGltYWdlLmRhdGEsXG5cdFx0XHRsZW5ndGggPSBpbWFnZURhdGEubGVuZ3RoO1xuXHRcdFx0Zm9yKHZhciBpPTM7IGkgPCBsZW5ndGg7IGkrPTQpeyAgXG5cdFx0XHRcdGltYWdlRGF0YVtpXSA9IChpbWFnZURhdGFbaV08b3BhY2l0eSk/aW1hZ2VEYXRhW2ldOm9wYWNpdHk7XG5cdFx0XHR9XG5cdFx0XHRpbWFnZS5kYXRhID0gaW1hZ2VEYXRhO1xuXHRcdFx0Z2N0eC5wdXRJbWFnZURhdGEoaW1hZ2UsIDAsIDApO1xuXHRcdFx0d2F0ZXJtYXJrLm9ubG9hZCA9IG51bGw7XG5cdFx0XHR3YXRlcm1hcmsuc3JjID0gXCJcIjtcblx0XHRcdHdhdGVybWFyay5zcmMgPSBnY2FudmFzLnRvRGF0YVVSTCgpO1xuXHRcdFx0Ly8gYXNzaWduIGltZyBhdHRyaWJ1dGVzIHRvIHRoZSB0cmFuc3BhcmVudCB3YXRlcm1hcmtcblx0XHRcdC8vIGJlY2F1c2UgYnJvd3NlcnMgcmVjYWxjdWxhdGlvbiBkb2Vzbid0IHdvcmsgYXMgZmFzdCBhcyBuZWVkZWRcblx0XHRcdHdhdGVybWFyay53aWR0aCA9IHc7XG5cdFx0XHR3YXRlcm1hcmsuaGVpZ2h0ID0gaDtcblxuXHRcdFx0YXBwbHlXYXRlcm1hcmtzKCk7XG5cdFx0fSxcblx0XHRjb25maWd1cmUgPSBmdW5jdGlvbihjb25maWcpe1xuXHRcdFx0aWYoY29uZmlnW1wid2F0ZXJtYXJrXCJdKVxuXHRcdFx0XHR3YXRlcm1hcmsgPSBjb25maWdbXCJ3YXRlcm1hcmtcIl07XG5cdFx0XHRpZihjb25maWdbXCJwYXRoXCJdKVxuXHRcdFx0XHR3YXRlcm1hcmtQYXRoID0gY29uZmlnW1wicGF0aFwiXTtcblx0XHRcdGlmKGNvbmZpZ1tcInBvc2l0aW9uXCJdKVxuXHRcdFx0XHR3YXRlcm1hcmtQb3NpdGlvbiA9IGNvbmZpZ1tcInBvc2l0aW9uXCJdO1xuXHRcdFx0aWYoY29uZmlnW1wib3BhY2l0eVwiXSlcblx0XHRcdFx0b3BhY2l0eSA9ICgyNTUvKDEwMC9jb25maWdbXCJvcGFjaXR5XCJdKSk7XG5cdFx0XHRpZihjb25maWdbXCJjbGFzc05hbWVzXCJdKVxuXHRcdFx0XHRjbGFzc05hbWVzID0gY29uZmlnW1wiY2xhc3NOYW1lc1wiXTtcblx0XHRcdFxuXHRcdFx0aW5pdENhbnZhcygpO1xuXHRcdFx0aW5pdFdhdGVybWFyaygpO1xuXHRcdH1cblx0XHRzZXRDYW52YXNTaXplID0gZnVuY3Rpb24odywgaCl7XG5cdFx0XHRnY2FudmFzLndpZHRoID0gdztcblx0XHRcdGdjYW52YXMuaGVpZ2h0ID0gaDtcblx0XHR9LFxuXHRcdGFwcGx5V2F0ZXJtYXJrID0gZnVuY3Rpb24oaW1nKXtcblx0XHRcdGdjYW52YXMud2lkdGggPSBpbWcubmF0dXJhbFdpZHRoIHx8IGltZy53aWR0aCB8fCBpbWcub2Zmc2V0V2lkdGg7XG5cdFx0XHRnY2FudmFzLmhlaWdodCA9IGltZy5uYXR1cmFsSGVpZ2h0IHx8IGltZy5oZWlnaHQgfHwgaW1nLm9mZnNldEhlaWdodDtcblx0XHRcdGdjdHguZHJhd0ltYWdlKGltZywgMCwgMCk7XG5cdFx0XHR2YXIgcG9zaXRpb24gPSB3YXRlcm1hcmtQb3NpdGlvbixcblx0XHRcdHggPSAwLFxuXHRcdFx0eSA9IDA7XG5cdFx0XHRpZihwb3NpdGlvbi5pbmRleE9mKFwidG9wXCIpIT0tMSlcblx0XHRcdFx0eSA9IDEwO1xuXHRcdFx0ZWxzZSBpZihwb3NpdGlvbi5pbmRleE9mKFwibWlkZGxlXCIpIT0tMSlcblx0XHRcdFx0eSA9IChnY2FudmFzLmhlaWdodC13YXRlcm1hcmsuaGVpZ2h0KSAvIDI7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHkgPSBnY2FudmFzLmhlaWdodC13YXRlcm1hcmsuaGVpZ2h0LTEwO1xuXHRcdFx0XG5cdFx0XHRpZihwb3NpdGlvbi5pbmRleE9mKFwibGVmdFwiKSE9LTEpXG5cdFx0XHRcdHggPSAxMDtcblx0XHRcdGVsc2UgaWYocG9zaXRpb24uaW5kZXhPZihcImNlbnRlclwiKSE9LTEpXG5cdFx0XHRcdHggPSAoZ2NhbnZhcy53aWR0aC13YXRlcm1hcmsud2lkdGgpIC8gMjtcblx0XHRcdGVsc2Vcblx0XHRcdFx0eCA9IGdjYW52YXMud2lkdGgtd2F0ZXJtYXJrLndpZHRoLTEwO1xuXG5cblx0XHRcdGdjdHguZHJhd0ltYWdlKHdhdGVybWFyaywgeCwgeSk7XG5cdFx0XHRpbWcub25sb2FkID0gbnVsbDtcblx0XG5cdFx0XHRpbWcuc3JjID0gZ2NhbnZhcy50b0RhdGFVUkwoKTtcblxuXHRcdH0sXG5cdFx0YXBwbHlXYXRlcm1hcmtzID0gZnVuY3Rpb24oKXtcblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdFx0Zm9yKHZhciBpID0gMDsgaSA8IGNsYXNzTmFtZXMubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHRcdHZhciBlbHMgPSBkb2MuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShjbGFzc05hbWVzW2ldKSxcblx0XHRcdFx0XHRsZW4gPSBlbHMubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlKGxlbi0tKXtcblx0XHRcdFx0XHRcdHZhciBpbWcgPSBlbHNbbGVuXTtcblx0XHRcdFx0XHRcdGlmKGltZy50YWdOYW1lLnRvVXBwZXJDYXNlKCkgIT0gXCJJTUdcIiB8fCAoaW1nLnRhZ05hbWUudG9VcHBlckNhc2UoKSA9PSBcIklNR1wiICYmIGltZy5nZXRBdHRyaWJ1dGUoJ3NyYycpLmluZGV4T2YoJ2RhdGE6aW1hZ2UvcG5nJykgPiAtMSkgfHwgaW1nLm5hdHVyYWxXaWR0aCA9PSAwKVxuXHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0aWYoIWltZy5jb21wbGV0ZSl7XG5cdFx0XHRcdFx0XHRcdGltZy5vbmxvYWQgPSBmdW5jdGlvbigpe1xuXHRcdFx0XHRcdFx0XHRcdGFwcGx5V2F0ZXJtYXJrKHRoaXMpO1xuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fWVsc2V7XG5cdFx0XHRcdFx0XHRcdGFwcGx5V2F0ZXJtYXJrKGltZyk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LDEwKTtcblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdHJldHVybiB7XG5cdFx0XHRpbml0OiBmdW5jdGlvbihjb25maWcpe1xuXHRcdFx0XHRjb25maWd1cmUoY29uZmlnKTtcblx0XHRcdH1cblx0XHR9O1xuXHR9KSh3KTtcblx0dy53bWFyayA9IHdtO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xudmFyIHByb2dyZXNzID0gcmVxdWlyZSgnLi9wcm9ncmVzcycpO1xudmFyIGxvZ2luRGlhbG9nID0gcmVxdWlyZSgnLi9sb2dpbkRpYWxvZycpO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBXSVNITElTVFxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbmZ1bmN0aW9uIGVycm9ySGFuZGxpbmcoZGF0YSwgZGlhbG9nVGl0bGUsIGRpYWxvZ0h0bWwpIHtcbiAgICBpZiAoZGF0YSAmJiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgJ21lc3NhZ2UnIGluIGRhdGEpIHtcbiAgICAgICAgY29uc29sZS5sb2coZGF0YS5tZXNzYWdlKTtcbiAgICB9XG4gICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICBodG1sOiBkaWFsb2dIdG1sLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICB0aXRsZTogZGlhbG9nVGl0bGUsXG4gICAgICAgICAgICBkcmFnZ2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24oZXZlbnQsIHVpKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdkaWFsb2ctb3BlbicpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbihldmVudCwgdWkpIHtcbiAgICAgICAgICAgICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ2RpYWxvZy1vcGVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlQ1NSRlRva2VuKCkge1xuXHRpZiAocGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucykge1xuXHRcdCQuYWpheCh7XG5cdFx0XHRtZXRob2Q6ICdnZXQnLFxuXHRcdFx0dXJsOiBVcmxzLkNTUkZUb2tlbi5HZXQsXG5cdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzcG9uc2UpIHtcblx0XHRcdFx0cGFnZUNvbnRleHQub3B0aW9ucy5Ub2tlbiA9IHJlc3BvbnNlLnRva2VuO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGNoZWNrV2lzaGxpc3RGb3JJdGVtKHdpc2hsaXN0SXRlbUlkKSB7XG4gICAgaWYgKCdsb2NhbFN0b3JhZ2UnIGluIHdpbmRvdyAmJiB3aW5kb3dbJ2xvY2FsU3RvcmFnZSddICE9PSBudWxsICYmICdXaXNobGlzdFByb2R1Y3RJRHMnIGluIHdpbmRvdy5sb2NhbFN0b3JhZ2UgJiYgd2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgd2lzaGxpc3RJdGVtcyA9IEpTT04ucGFyc2Uod2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMpO1xuICAgICAgICB2YXIgcGFnZVR5cGUgPSBwYWdlQ29udGV4dCAmJiAndHlwZScgaW4gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQudHlwZSA/IHBhZ2VDb250ZXh0LnR5cGUgOiAkKCcjd3JhcHBlcicpLmF0dHIoJ2NsYXNzJyk7XG4gICAgICAgIHZhciBpc1dpc2hsaXN0SXRlbSA9IHdpc2hsaXN0SXRlbXMuZmlsdGVyKGZ1bmN0aW9uKHByb2R1Y3RPYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChwcm9kdWN0T2JqZWN0LnByb2R1Y3RJRCA9PSB3aXNobGlzdEl0ZW1JZCkgeyByZXR1cm4gdHJ1ZSB9XG4gICAgICAgICAgICAvLyBJZiB0aGlzIGlzIE5PVCBhIFBEUCwgdGhlbiB3ZSBuZWVkIHRvIHJ1biBhZGRpdGlvbmFsIGNoZWNrcyB0byBzZWUgaWYgTWFzdGVyIFByb2R1Y3Qgb3IgYW55IG9mIHRoZSBWYXJpYXRpb25zIGFyZSBpbiB0aGUgd2lzaGxpc3RcbiAgICAgICAgICAgIGlmIChwYWdlVHlwZSAhPSAncHJvZHVjdCcpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvZHVjdE9iamVjdC5tYXN0ZXJJRCA9PSB3aXNobGlzdEl0ZW1JZCkgeyByZXR1cm4gdHJ1ZSB9XG4gICAgICAgICAgICAgICAgaWYgKHByb2R1Y3RPYmplY3QudmFyaWFudHMuaW5kZXhPZih3aXNobGlzdEl0ZW1JZCkgPiAtMSkgeyByZXR1cm4gdHJ1ZSB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gaXNXaXNobGlzdEl0ZW0ubGVuZ3RoID4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtb2RpZnlXaXNobGlzdEluU3RvcmFnZShkYXRhKSB7XG4gICAgaWYgKCdsb2NhbFN0b3JhZ2UnIGluIHdpbmRvdyAmJiB3aW5kb3dbJ2xvY2FsU3RvcmFnZSddICE9PSBudWxsKSB7XG4gICAgICAgIGlmICghd2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMpIHtcbiAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gJ1tdJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXRlbSA9ICdwcm9kdWN0RGF0YScgaW4gZGF0YSAmJiBkYXRhLnByb2R1Y3REYXRhLnByb2R1Y3RJRCA/IGRhdGEucHJvZHVjdERhdGEucHJvZHVjdElEIDogbnVsbDtcbiAgICAgICAgdmFyIGlzRGF0YUFjdGlvbiA9IGRhdGEuYWN0aW9uO1xuICAgICAgICB2YXIgd2lzaGxpc3RJdGVtcyA9IEpTT04ucGFyc2Uod2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMpO1xuXG4gICAgICAgIGlmIChpdGVtICYmIGlzRGF0YUFjdGlvbikge1xuICAgICAgICAgICAgaWYgKGlzRGF0YUFjdGlvbiA9PSAnd2lzaGxpc3RJdGVtQWRkZWQnKSB7XG4gICAgICAgICAgICAgICAgd2lzaGxpc3RJdGVtcy5wdXNoKGRhdGEucHJvZHVjdERhdGEpO1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gSlNPTi5zdHJpbmdpZnkod2lzaGxpc3RJdGVtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNEYXRhQWN0aW9uID09ICd3aXNobGlzdEl0ZW1SZW1vdmVkJyAmJiB3aXNobGlzdEl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgbW9kaWZpZWRXaXNobGlzdCA9IHdpc2hsaXN0SXRlbXMuZmlsdGVyKGZ1bmN0aW9uKHByb2R1Y3RPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2R1Y3RPYmplY3QucHJvZHVjdElEICE9IGl0ZW0pIHsgcmV0dXJuIHRydWUgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gSlNPTi5zdHJpbmdpZnkobW9kaWZpZWRXaXNobGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGFkZFdpc2hsaXN0RXZlbnQoZXZlbnQsIHByb2R1Y3RJRCkge1xuXHR2YXIgZXZlbnRUeXBlID0gXCJ3aXNobGlzdF9cIiArIGV2ZW50O1xuXHR2YXIgdXJsLCBpbWFnZTtcblx0dmFyIGltYWdlcyA9IFtdO1xuXHRcblx0dmFyIHRoaXNUaWxlID0gJCgnLnByb2R1Y3QtdGlsZVtkYXRhLWl0ZW1pZD1cIicrcHJvZHVjdElEKydcIl0nKTtcblx0dmFyIHRoaXNJdGVtID0gSlNPTi5wYXJzZSgkKCcucHJvZHVjdENhcmRNZXRhZGF0YS5ldmVudC1icm93c2VbZGF0YS1waWQ9XCInK3Byb2R1Y3RJRCsnXCJdJykuYXR0cignZGF0YS1wcm9kdWN0LWd0bS1qc29uJykpO1xuXHRpZiAodGhpc1RpbGUubGVuZ3RoID4gMCkge1xuXHRcdHVybCA9IHRoaXNUaWxlLmZpbmQoJy50aHVtYi1saW5rJykuYXR0cignaHJlZicpO1xuXHRcdGltYWdlID0gdGhpc1RpbGUuZmluZCgnLnRodW1iLWxpbmsgaW1nJykuYXR0cignc3JjJyk7XG5cdFx0aW1hZ2VzLnB1c2goaW1hZ2UpO1xuXHR9IGVsc2Uge1xuXHRcdHZhciBzZWxlY3RlZFNpemVPcHRpb24gPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC5zaXplLnNpemUtb3B0aW9ucyBsaS5zZWxlY3RlZCAuc3dhdGNoYW5jaG9yJyk7XG5cdFx0dmFyIHNlbGVjdGVkU2l6ZVVybCA9IHNlbGVjdGVkU2l6ZU9wdGlvbi5hdHRyKCdocmVmJykucmVwbGFjZSgnUHJvZHVjdC1WYXJpYXRpb24nLCAnUHJvZHVjdC1TaG93Jyk7XG5cdFx0dmFyIHNlbGVjdGVkU2l6ZVZhbHVlID0gc2VsZWN0ZWRTaXplT3B0aW9uLmF0dHIoJ2RhdGEtc2l6ZS1pZCcpLnJlcGxhY2UoLyAvZywgJyUyMCcpO1xuXHRcdHVybCA9IHNlbGVjdGVkU2l6ZVVybC5yZXBsYWNlKFwiX3NpemU9XCIsIFwiX3NpemU9XCIrc2VsZWN0ZWRTaXplVmFsdWUpO1xuXHRcdCQoJy5wcm9kdWN0LXByaW1hcnktaW1hZ2UgW2NsYXNzKj1cIi1zbGlkZVwiXScpLm5vdCgnLnNsaWNrLWNsb25lZCcpLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XG5cdFx0XHRpZihpbmRleCA+IC0xKSB7XG5cdFx0XHRcdHZhciBpbWFnZSA9ICQodGhpcykuZmluZCgnYScpLmF0dHIoJ2hyZWYnKTtcblx0XHRcdFx0aWYgKCFpbWFnZSB8fCBpbWFnZSA9PSB1bmRlZmluZWQgfHwgaW1hZ2UgPT0gbnVsbCkge1xuXHRcdFx0XHRcdGltYWdlID0gJCh0aGlzKS5maW5kKCdpbWcnKS5hdHRyKCdzcmMnKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoaW1hZ2VzLmluZGV4T2YoaW1hZ2UpID09PSAtMSkge1xuXHRcdFx0XHRcdGltYWdlcy5wdXNoKGltYWdlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cdFxuXHR2YXIgcHJvcGVydGllcyA9IHtcblx0XHRcInByb2R1Y3RJRFwiOiB0aGlzSXRlbVtcImlkXCJdLFxuXHRcdFwicHJvZHVjdE5hbWVcIjogdGhpc0l0ZW1bXCJuYW1lXCJdLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XCJjYXRlZ29yeVwiOiB0aGlzSXRlbVtcImNhdGVnb3J5XCJdLnJlcGxhY2UoL1xcXFwvZywgXCJcIiksXG5cdFx0XCJwcmljZVwiOiB0aGlzSXRlbVtcInByaWNlXCJdLFxuXHRcdFwiaW1hZ2VzXCI6IGltYWdlcyxcblx0XHRcInVybFwiOiB1cmwsXG5cdFx0XCJhdHRyXCI6IHtcblx0XHRcdFwibWFudWZhY3R1cmVyXCI6IHRoaXNJdGVtW1wiYnJhbmRcIl1cblx0XHR9LFxuXHR9O1xuXG5cdGlmICh0eXBlb2YgY3JkbCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNyZGwgPT09ICdmdW5jdGlvbicpIHtcblx0XHRjcmRsKCdldmVudCcsIGV2ZW50VHlwZSwgcHJvcGVydGllcyk7IFxuXHR9XHRcbn1cblxuZnVuY3Rpb24gcHJlcGFyZVdpc2hsaXN0QWRkVUkoYnV0dG9ucywgd2lzaGxpc3RJdGVtSWQsIHNpemVUZXh0KSB7XG4gICAgaWYgKCFidXR0b25zKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBidXR0b25zLmVhY2goZnVuY3Rpb24oaWR4LCBlbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgJGJ1dHRvbiA9ICQoZWxlbWVudCk7XG4gICAgICAgICAgICB2YXIgYWRkVXJsID0gVXJscy53aXNobGlzdEFkZCArICc/cGlkPScgKyAkYnV0dG9uLmF0dHIoJ2RhdGEtcGlkJyk7XG4gICAgICAgICAgICAkYnV0dG9uLnJlbW92ZUNsYXNzKCd3aXNobGlzdC1pdGVtLWFkZGVkJykuYWRkQ2xhc3MoJ3dpc2hsaXN0LWl0ZW0tcmVhZHknKTtcbiAgICAgICAgICAgICRidXR0b24uY3NzKCdkaXNwbGF5JywgJ2lubGluZS1ibG9jaycpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCdkYXRhLXVybCcsIGFkZFVybCk7XG4gICAgICAgICAgICAkYnV0dG9uLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ0FkZEludGVybmFsJyk7XG4gICAgICAgICAgICAkYnV0dG9uLmF0dHIoJ3RpdGxlJywgKCRidXR0b24uYXR0cignZGF0YS10aXRsZS1hZGQnKSArICcgLSAnICsgc2l6ZVRleHQpKTtcbiAgICAgICAgICAgIGlmICgkYnV0dG9uLmF0dHIoJ2lkJykgPT0gJ3dpc2hsaXN0LWJ1dHRvbicpIHtcbiAgICAgICAgICAgICAgICAkYnV0dG9uLmZpbmQoJ3NwYW4nKS5odG1sKCRidXR0b24uYXR0cignZGF0YS1hZGQtbWVzc2FnZScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIGlmICgkKCcucHRfd2lzaC1saXN0JykubGVuZ3RoID4gMCAmJiAod2lzaGxpc3RJdGVtSWQpKSB7XG4gICAgICAgIGlmICgnbG9jYWxTdG9yYWdlJyBpbiB3aW5kb3cgJiYgd2luZG93Wydsb2NhbFN0b3JhZ2UnXSAhPT0gbnVsbCAmJiAnV2lzaGxpc3RQcm9kdWN0SURzJyBpbiB3aW5kb3cubG9jYWxTdG9yYWdlICYmIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciB3aXNobGlzdEl0ZW1zID0gSlNPTi5wYXJzZSh3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyk7XG4gICAgICAgICAgICB2YXIgdmFyaWF0aW9uTW9kZWwgPSB3aXNobGlzdEl0ZW1zLmZpbHRlcihmdW5jdGlvbihwcm9kdWN0T2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb2R1Y3RPYmplY3QucHJvZHVjdElEID09IHdpc2hsaXN0SXRlbUlkIHx8IHByb2R1Y3RPYmplY3QubWFzdGVySUQgPT0gd2lzaGxpc3RJdGVtSWQgfHwgcHJvZHVjdE9iamVjdC52YXJpYW50cy5pbmRleE9mKHdpc2hsaXN0SXRlbUlkKSA+IC0xKSB7IFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvZHVjdE9iamVjdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICh2YXJpYXRpb25Nb2RlbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgd2lzaGxpc3RJdGVtc1RvUmVtb3ZlID0gdmFyaWF0aW9uTW9kZWxbMF07XG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHdpc2hsaXN0SXRlbXNUb1JlbW92ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSB3aXNobGlzdEl0ZW1zVG9SZW1vdmVba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgbWF0Y2hpbmcgdmFyaWFudCBvciBtYXN0ZXJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PSAncHJvZHVjdElEJyB8fCBrZXkgPT0gJ21hc3RlcklEJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnByb2R1Y3QtdGlsZVtkYXRhLWl0ZW1pZD1cIicrdmFsdWUrJ1wiXScpLnBhcmVudHMoJ2xpLndpc2hsaXN0LWl0ZW0nKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gRWxzZSwgY2hlY2sgdGhlIG90aGVyIHZhcmlhbnRzXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFyaWFudHMgPSB2YWx1ZS5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkgPCB2YXJpYW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFyaWFudElEID0gdmFyaWFudHNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnByb2R1Y3QtdGlsZVtkYXRhLWl0ZW1pZD1cIicrdmFyaWFudElEKydcIl0nKS5wYXJlbnRzKCdsaS53aXNobGlzdC1pdGVtJykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIElmIHVzZXIgcmVtb3ZlcyBhbGwgc2hhcmVhYmxlIHByb2R1Y3RzIGZyb20gd2lzaGxpc3QsIHRoZW4gaGlkZSB0aGUgc2hhcmUgdG9nZ2xlIGFuZCBzZXQgdGhlIHdpc2hsaXN0IHRvIHByaXZhdGVcbiAgICAgICAgICAgICAgICBpZiAoJCgnbGkud2lzaGxpc3QtaXRlbVtkYXRhLXNoYXJlYWJsZS1pdGVtPVwidHJ1ZVwiXScpLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnLndpc2hsaXN0LXNoYXJlLWNvbnRhaW5lcicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgJCgnLnNoYXJlLXdpc2hsaXN0LXRvZ2dsZSBpbnB1dFtuYW1lPVwic2hhcmUtd2lzaGxpc3QtY2hlY2tib3hcIl0nKS5wcm9wKCdjaGVja2VkJywgZmFsc2UpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoJCgnbGkud2lzaGxpc3QtaXRlbScpLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnLndpc2hsaXN0LW1lc3NhZ2UuZW1wdHktd2lzaGxpc3QnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwcmVwYXJlV2lzaGxpc3RSZW1vdmVVSShidXR0b25zLCBzaXplVGV4dCkge1xuICAgIGlmICghYnV0dG9ucykge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKGlkeCwgZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKGVsZW1lbnQpO1xuICAgICAgICAgICAgdmFyIHJlbW92ZVVybCA9IFVybHMud2lzaGxpc3RSZW1vdmUgKyAnP3BpZD0nICsgJGJ1dHRvbi5hdHRyKCdkYXRhLXBpZCcpO1xuICAgICAgICAgICAgJGJ1dHRvbi5yZW1vdmVDbGFzcygnd2lzaGxpc3QtaXRlbS1yZWFkeScpLmFkZENsYXNzKCd3aXNobGlzdC1pdGVtLWFkZGVkJyk7XG4gICAgICAgICAgICAkYnV0dG9uLmNzcygnZGlzcGxheScsICdpbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICRidXR0b24uYXR0cignZGF0YS11cmwnLCByZW1vdmVVcmwpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCdkYXRhLWFjdGlvbicsICdSZW1vdmVJbnRlcm5hbCcpO1xuICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCd0aXRsZScsICgkYnV0dG9uLmF0dHIoJ2RhdGEtdGl0bGUtcmVtb3ZlJykgKyAnIC0gJyArIHNpemVUZXh0KSk7XG4gICAgICAgICAgICBpZiAoJGJ1dHRvbi5hdHRyKCdpZCcpID09ICd3aXNobGlzdC1idXR0b24nKSB7XG4gICAgICAgICAgICAgICAgJGJ1dHRvbi5maW5kKCdzcGFuJykuaHRtbCgkYnV0dG9uLmF0dHIoJ2RhdGEtcmVtb3ZlLW1lc3NhZ2UnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyQWxsV2lzaGxpc3RCdXR0b25zKCkge1xuICAgICQoJy53aXNobGlzdC1pdGVtLXN0YXR1cy1idXR0b24nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgJGJ1dHRvbiA9ICQodGhpcyk7XG4gICAgICAgIHZhciB3aXNobGlzdEl0ZW1JZCA9ICRidXR0b24uYXR0cignZGF0YS1waWQnKTtcbiAgICAgICAgaWYgKHdpc2hsaXN0SXRlbUlkICYmIHdpc2hsaXN0SXRlbUlkICE9ICcnKSB7XG4gICAgICAgICAgICB2YXIgaXNXaXNobGlzdEl0ZW0gPSBjaGVja1dpc2hsaXN0Rm9ySXRlbSh3aXNobGlzdEl0ZW1JZCk7XG4gICAgICAgICAgICBpZiAoaXNXaXNobGlzdEl0ZW0pIHsgXG4gICAgICAgICAgICAgICAgcHJlcGFyZVdpc2hsaXN0UmVtb3ZlVUkoJGJ1dHRvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByZXBhcmVXaXNobGlzdEFkZFVJKCRidXR0b24sIHdpc2hsaXN0SXRlbUlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUVtYWlsRm9ybSgkZW1haWwsICRtZXNzYWdlKSB7XHRcbiAgICAkKCcuc2hhcmUtd2lzaGxpc3QtbWVudS1wb3B1cCAuZXJyb3ItY29udGFpbmVyJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuXG4gICAgdmFyIHJlZ2V4RW1haWwgPSAvXlthLXpBLVowLTkuISMkJSYnKisvPT9eX2B7fH1+LV0rQFthLXpBLVowLTktXSsoPzpcXC5bYS16QS1aMC05LV0rKSokL2c7XHRcbiAgICB2YXIgcmVnZXhNZXNzYWdlID0gL15bQS1aYS16MC05IF8uLCFcIidcXC8oKSRdKi9nO1xuICAgIHZhciBlbWFpbCA9ICRlbWFpbC52YWwoKS50cmltKCk7XG4gICAgdmFyIG1lc3NhZ2UgPSAkbWVzc2FnZS52YWwoKS50cmltKCk7XG5cdHZhciBmb3JtVmFsaWRhdGlvbiA9IHRydWU7XG5cdFx0XHRcblx0aWYgKCghZW1haWwgfHwgZW1haWwubGVuZ3RoID09IDApIHx8IFN0cmluZyhlbWFpbCkubWF0Y2gocmVnZXhFbWFpbCkgPT0gbnVsbCkge1xuXHRcdGZvcm1WYWxpZGF0aW9uID0gZmFsc2U7XG4gICAgICAgICRlbWFpbC5hZGRDbGFzcygnZXJyb3InKTtcblx0ICAgICQoJyNzaGFyZS13aXNobGlzdC1lbWFpbC1wb3B1cCAuaW52YWxpZC1lbWFpbC1mb3JtYXQnKS5yZW1vdmVDbGFzcygnZC1ub25lJyk7XG5cdH1cbiAgICBpZiAoKCFtZXNzYWdlIHx8IG1lc3NhZ2UubGVuZ3RoID09IDApIHx8IFN0cmluZyhtZXNzYWdlKS5tYXRjaChyZWdleE1lc3NhZ2UpID09IG51bGwpIHtcbiAgICAgICAgZm9ybVZhbGlkYXRpb24gPSBmYWxzZTtcbiAgICAgICAgJG1lc3NhZ2UuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICQoJyNzaGFyZS13aXNobGlzdC1lbWFpbC1wb3B1cCAuaW52YWxpZC1lbWFpbC1tZXNzYWdlLWZvcm1hdCcpLnJlbW92ZUNsYXNzKCdkLW5vbmUnKTtcbiAgICB9XG5cdFx0XHRcblx0aWYgKCFmb3JtVmFsaWRhdGlvbikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpbml0ICgpIHtcbiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblxuICAgICAgICB1cGRhdGVDU1JGVG9rZW4oKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogT24gcGFnZSBsb2FkLCBtYWtlIEFKQVggY2FsbCB0byBnZXQgd2lzaGxpc3QgaXRlbXMgYW5kIHN0b3JlIGluIGxvY2FsU3RvcmFnZS4gRnJvbSBsb2NhbFN0b3JhZ2UsIGNvbXBhcmUgdGhlIGl0ZW1zIGJlaW5nIGxvYWRlZCBvbiBcbiAgICAgICAgICogcGFnZSB0byBzZWUgaWYgYW55IGFyZSBpbiB3aXNobGlzdCwgYW5kIG1hcmsgdGhlIGhlYXJ0IGljb25zIGFjY29yZGluZ2x5LiBcbiAgICAgICAgICovXG4gICAgICAgIGlmICgnbG9jYWxTdG9yYWdlJyBpbiB3aW5kb3cgJiYgd2luZG93Wydsb2NhbFN0b3JhZ2UnXSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gT25seSBtYWtlIEFKQVggY2FsbCB0byBnZXQgd2lzaGxpc3QgcHJvZHVjdCBJRHMgaWYgY3VzdG9tZXIgaXMgbG9nZ2VkIGluXG4gICAgICAgICAgICBpZiAoQ3VzdG9tZXIuYXV0aGVudGljYXRlZCkge1xuICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICB1cmw6IFVybHMud2lzaGxpc3RHZXRJdGVtcyxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLndpc2hsaXN0LWl0ZW0tc3RhdHVzLWJ1dHRvbicpLmNzcygnZGlzcGxheScsICdpbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlID09PSAnb2JqZWN0JyAmJiAnd2lzaGxpc3QnIGluIHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2UuV2lzaGxpc3RQcm9kdWN0SURzID0gSlNPTi5zdHJpbmdpZnkocmVzcG9uc2Uud2lzaGxpc3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJBbGxXaXNobGlzdEJ1dHRvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcud2lzaGxpc3QtaXRlbS1zdGF0dXMtYnV0dG9uJykuY3NzKCdkaXNwbGF5JywgJ2lubGluZS1ibG9jaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYWxTdG9yYWdlLldpc2hsaXN0UHJvZHVjdElEcyA9ICcnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pOyAgIFxuICAgICAgICAgICAgLy8gSWYgZ3Vlc3QgdXNlciwganVzdCByZW5kZXIgdGhlIHdpc2hsaXN0IGJ1dHRvbnMgYXMgZW1wdHlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5XaXNobGlzdFByb2R1Y3RJRHMgPSAnJztcbiAgICAgICAgICAgICAgICByZW5kZXJBbGxXaXNobGlzdEJ1dHRvbnMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBPbiBjbGljayBvZiBhIHdpc2hsaXN0IGhlYXJ0IGJ1dHRvbiwgb3BlbiBhIGxvZ2luIGRpYWxvZyAoaWYgZ3Vlc3QgdXNlcikgb3IgYWRkL3JlbW92ZSBpdGVtIGZyb20gd2lzaGxpc3QgKGlmIGxvZ2dlZC1pbiBjdXN0b21lcilcbiAgICAgICAgICovXG4gICAgICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnLndpc2hsaXN0LWl0ZW0tc3RhdHVzLWJ1dHRvbiwgLndpc2hsaXN0LWJ1dHRvbicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpO1xuICAgICAgICAgICAgdmFyIHdpc2hsaXN0VXJsID0gJGJ1dHRvbi5hdHRyKCdkYXRhLXVybCcpO1xuICAgICAgICAgICAgdmFyIHdpc2hsaXN0Q29udHJvbGxlciA9ICRidXR0b24uYXR0cignZGF0YS1jb250cm9sbGVyJyk7XG4gICAgICAgICAgICB2YXIgd2lzaGxpc3RBY3Rpb24gPSAkYnV0dG9uLmF0dHIoJ2RhdGEtYWN0aW9uJyk7XG4gICAgICAgICAgICB2YXIgcHJvZHVjdElEID0gJGJ1dHRvbi5hdHRyKCdkYXRhLXBpZCcpO1xuXG4gICAgICAgICAgICB2YXIgaXNQcm9kdWN0UGFnZSA9ICQoJy5wdF9wcm9kdWN0LWRldGFpbHMnKS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgY29udGludWVXaXNobGlzdCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChpc1Byb2R1Y3RQYWdlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNpemVTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLnNpemUuc2l6ZS1vcHRpb25zIGxpLnNlbGVjdGVkJyk7XG5cdFx0XHRcdHZhciBsZW5ndGhTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmxlbmd0aC5sZW5ndGgtb3B0aW9ucyBsaS5zZWxlY3RlZCcpLmxlbmd0aDtcblx0XHRcdFx0dmFyIHdpZHRoU2VsZWN0ZWQgPSAkKCdkaXYucHJvZHVjdC12YXJpYXRpb25zIC53aWR0aC53aWR0aC1vcHRpb25zIGxpLnNlbGVjdGVkJykubGVuZ3RoO1xuXHRcdFx0XHR2YXIgaXNTaXplU2VsZWN0ZWQgPSBzaXplU2VsZWN0ZWQubGVuZ3RoIHx8IChsZW5ndGhTZWxlY3RlZCAmJiB3aWR0aFNlbGVjdGVkKTtcblx0XHRcdFx0dmFyIGlzQ29sb3JTZWxlY3RlZCA9ICQoJ2Rpdi5wcm9kdWN0LXZhcmlhdGlvbnMgLmNvbG9yLmNvbG9yLW9wdGlvbnMgbGkuc2VsZWN0ZWQnKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaWYgKCFpc1NpemVTZWxlY3RlZCkge1xuICAgICAgICAgICAgICAgICAgICBhbGVydCgnUGxlYXNlIHNlbGVjdCBhIHNpemUnKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWVXaXNobGlzdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKGNvbnRpbnVlV2lzaGxpc3QpIHtcbiAgICAgICAgICAgIFx0Ly9Db3JkaWFsIHdpc2hsaXN0IGFkZC9yZW1vdmUgZXZlbnRzXG4gICAgICAgICAgICBcdGlmICgkYnV0dG9uLmhhc0NsYXNzKCd3aXNobGlzdC1pdGVtLWFkZGVkJykpIHtcbiAgICBcdFx0XHRcdGFkZFdpc2hsaXN0RXZlbnQoJ3JlbW92ZScsIHByb2R1Y3RJRCk7XG4gICAgXHRcdFx0fSBlbHNlIHtcbiAgICBcdFx0XHRcdGFkZFdpc2hsaXN0RXZlbnQoJ2FkZCcsIHByb2R1Y3RJRCk7XG4gICAgXHRcdFx0fVxuICAgICAgICAgICAgXHRcbiAgICAgICAgICAgICAgICAvLyBXSVNITElTVCBSRVBPUlRJTkc6IFRyYWNrIHdpc2hsaXN0LWl0ZW0tc3RhdHVzLWJ1dHRvbiBjbGlja3MgKGJvdGggZ3Vlc3QgYW5kIGxvZ2dlZC1pbiB1c2VycylcbiAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgIHVybDogVXJscy53aXNobGlzdFRyYWNrQWN0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiB3aXNobGlzdEFjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBpZDogcHJvZHVjdElEXG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24oanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2lzaGxpc3QtVHJhY2tBY3Rpb25zOiBFcnJvciBpbiBpbmNyZW1lbnRpbmcgd2lzaGxpc3QgYWN0aW9uIGNvdW50ZXJzLiBFUlJPUiBURVhUOiAnK3RleHRTdGF0dXMrJywgRVJST1IgVEhST1dOOiAnK2Vycm9yVGhyb3duKycuJyk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UpIHt9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIElmIGd1ZXN0IHVzZXIsIG9wZW4gYSBsb2dpbiBkaWFsb2dcbiAgICAgICAgICAgICAgICBpZiAoIUN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHdpc2hsaXN0VXJsLnN1YnN0cmluZyh3aXNobGlzdFVybC5pbmRleE9mKCc/JyksIHdpc2hsaXN0VXJsLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2luRGlhbG9nLnNob3coZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3IgcmVwb3J0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lciBbZGF0YS1sb2dpbi1zb3VyY2VdJykuYXR0cignZGF0YS1sb2dpbi1zb3VyY2UnLCAnd2lzaGxpc3QtbW9kYWwnKTsgXG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcubG9naW4tZGlhbG9nLWZvcm1zLWNvbnRhaW5lciBbZGF0YS1wYXNzd29yZGxlc3MtbG9naW4tc291cmNlXScpLmF0dHIoJ2RhdGEtcGFzc3dvcmRsZXNzLWxvZ2luLXNvdXJjZScsICd3aXNobGlzdC1tb2RhbCcpO1xuICAgICAgICAgICAgICAgICAgICB9LCB3aXNobGlzdENvbnRyb2xsZXIsIHdpc2hsaXN0QWN0aW9uLCBwcm9kdWN0SUQsIHBhcmFtcywgd2lzaGxpc3RVcmwpO1xuICAgICAgICAgICAgICAgIC8vIEVsc2UsIGlmIGxvZ2dlZC1pbiB1c2VyLCBhbGxvdyBjdXN0b21lciB0byBhZGQvcmVtb3ZlIHdpc2hsaXN0IGl0ZW1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IHdpc2hsaXN0VXJsLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsaW5nKGVycm9yVGhyb3duLCAnV2lzaGxpc3QgLSBFcnJvcicsICc8cCBzdHlsZT1cInBhZGRpbmc6IDEwcHg7XCI+VGhlcmUgd2FzIGEgcHJvYmxlbSBoYW5kbGluZyB5b3VyIHJlcXVlc3QuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlICYmIHJlc3BvbnNlLnJlc3VsdCAmJiByZXNwb25zZS5yZXN1bHQgPT0gJ3N1Y2Nlc3MnICYmIHJlc3BvbnNlLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlXaXNobGlzdEluU3RvcmFnZShyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5hY3Rpb24gPT0gJ3dpc2hsaXN0SXRlbVJlbW92ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvZHVjdElkUmVtb3ZlZCA9IHJlc3BvbnNlICYmIHJlc3BvbnNlLmZvcm1hdHRlZERhdGEgJiYgcmVzcG9uc2UuZm9ybWF0dGVkRGF0YS5wcm9kdWN0SUQgPyByZXNwb25zZS5mb3JtYXR0ZWREYXRhLnByb2R1Y3RJRCA6IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVwYXJlV2lzaGxpc3RBZGRVSSgkYnV0dG9uLCBwcm9kdWN0SWRSZW1vdmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXBhcmVXaXNobGlzdFJlbW92ZVVJKCRidXR0b24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRpYWxvZ0h0bWwgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPlVuYWJsZSB0byBtb2RpZnkgd2lzaGxpc3QgYXQgdGhpcyB0aW1lLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuYWN0aW9uID09ICd3aXNobGlzdEl0ZW1SZW1vdmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZ0h0bWwgPSAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPlVuYWJsZSB0byByZW1vdmUgaXRlbSBmcm9tIHdpc2hsaXN0LiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2dIdG1sID0gJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5VbmFibGUgdG8gYWRkIGl0ZW0gdG8gd2lzaGxpc3QuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhudWxsLCAnV2lzaGxpc3QgLSBFcnJvcicsIGRpYWxvZ0h0bWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQWRkIHByb2R1Y3QgdG8gY3VzdG9tZXIncyBjYXJ0IHdoZW4gXCJBZGQgdG8gQ2FydFwiIGJ1dHRvbiBpcyBjbGlja2VkIG9uIFdpc2hsaXN0IHBhZ2VcbiAgICAgICAgICovXG4gICAgICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnLndpc2hsaXN0LWFkZC10by1jYXJ0LWJ1dHRvbicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpO1xuICAgICAgICAgICAgdmFyIHByb2R1Y3RJZCA9ICRidXR0b24uYXR0cignZGF0YS1waWQnKTtcbiAgICAgICAgICAgICRidXR0b24uZmluZCgnc3BhbicpLmh0bWwoJycpO1xuICAgICAgICAgICAgcHJvZ3Jlc3Muc2hvdygkYnV0dG9uLmZpbmQoJ3NwYW4nKSwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIHVybDogVXJscy5hZGRQcm9kdWN0LFxuICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgIHBpZDogcHJvZHVjdElkLFxuICAgICAgICAgICAgICAgICAgICAgY3NyZl90b2tlbjogcGFnZUNvbnRleHQub3B0aW9ucy5Ub2tlblxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICRidXR0b24uZmluZCgnc3BhbicpLmh0bWwoJ0FkZCB0byBDYXJ0Jyk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcoZXJyb3JUaHJvd24sICdXaXNobGlzdCAtIEVycm9yJywgJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5VbmFibGUgdG8gYWRkIGl0ZW0gdG8gY2FydC4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+Jyk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgJG1pbmlDYXJ0RWxtID0gJCgnLm1pbmktY2FydCAubWluaWNhcnQtcXVhbnRpdHknKS5sZW5ndGggPiAwID8gJCgnLm1pbmktY2FydCAubWluaWNhcnQtcXVhbnRpdHknKSA6ICQoJy5taW5pLWNhcnQgLmJ0bi1taW5pY2FydCAuYnRuLW1pbmljYXJ0LXF0eScpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWluaUNhcnRUb3RhbDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRtaW5pQ2FydEVsbS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5pQ2FydFRvdGFsID0gcGFyc2VJbnQoJG1pbmlDYXJ0RWxtLmh0bWwoKS50cmltKCkpO1xuICAgICAgICAgICAgICAgICAgICB9ICBcbiAgICAgICAgICAgICAgICAgICAgbWluaUNhcnRUb3RhbCsrOyAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAkbWluaUNhcnRFbG0uaHRtbChtaW5pQ2FydFRvdGFsKTtcbiAgICAgICAgICAgICAgICAgICAgJGJ1dHRvbi5hdHRyKCdkaXNhYmxlZCcsIHRydWUpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAkYnV0dG9uLmZpbmQoJ3NwYW4nKS5odG1sKCc8aSBjbGFzcz1cImZhIGZhLWNoZWNrXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPiBJdGVtIEFkZGVkJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmaXJlIHRoaXMgQUpBWCBjYWxsIGlmIHRoZSBjdXN0b21lciBzdWNjZXNzZnVsbHkgYWRkZWQgdGhlIHByb2R1Y3QgdG8gdGhlaXIgY2FydC4gT24gZXJyb3Igb2YgYWRkUHJvZHVjdCwgZG8gbm90aGluZy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdJU0hMSVNUIFJFUE9SVElORzogVHJhY2sgJ0FkZCB0byBDYXJ0JyBjbGlja3MgZnJvbSB3aXNobGlzdCBwYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogVXJscy53aXNobGlzdFRyYWNrQWRkVG9DYXJ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2lzaGxpc3QtVHJhY2tBZGRUb0NhcnQ6IEVycm9yIGluIGluY3JlbWVudGluZyB3aXNobGlzdCBBZGQtdG8tQ2FydCBjb3VudGVyLiBFUlJPUiBURVhUOiAnK3RleHRTdGF0dXMrJywgRVJST1IgVEhST1dOOiAnK2Vycm9yVGhyb3duKycuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UpIHt9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJCgnYm9keScpLm9uKCdjbGljaycsICcjbW9iaWxlLXNoYXJlLXdpc2hsaXN0LWJ1dHRvbicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgJCgnLndpc2hsaXN0LXNoYXJlLW1vYmlsZS1jb250YWluZXInKS5zbGlkZVRvZ2dsZSgnc2xvdycpO1xuICAgICAgICB9KTtcbiAgICAgICAgJCgnYm9keScpLm9uKCdjaGFuZ2UnLCAnLnNoYXJlLXdpc2hsaXN0LXRvZ2dsZSBpbnB1dFtuYW1lPVwic2hhcmUtd2lzaGxpc3QtY2hlY2tib3hcIl0nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzdGF0dXMgPSAkKHRoaXMpLmlzKCc6Y2hlY2tlZCcpO1xuICAgICAgICAgICAgaWYgKHN0YXR1cykge1xuICAgICAgICAgICAgICAgICQoJyNzaGFyZS13aXNobGlzdC1tZW51Jykuc2xpZGVEb3duKCdzbG93JykuY3NzKCdkaXNwbGF5JywnZmxleCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKCcjc2hhcmUtd2lzaGxpc3QtbWVudScpLnNsaWRlVXAoJ3Nsb3cnKS5yZW1vdmVDbGFzcygnc2hvdy1zaGFyZS13aXNobGlzdC1tZW51JykuY3NzKCdkaXNwbGF5Jywnbm9uZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKEN1c3RvbWVyLmF1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgd2lzaGxpc3RJRCA9ICQoJ2lucHV0W25hbWU9XCJjdXJyZW50X3dpc2hsaXN0X2lkXCJdJykudmFsKCkudHJpbSgpO1xuICAgICAgICAgICAgICAgIGlmICh3aXNobGlzdElEKSB7XG4gICAgICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiBVcmxzLndpc2hsaXN0U2V0UHVibGljLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdpc2hsaXN0SUQ6IHdpc2hsaXN0SUQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgU2V0UHVibGljOiBzdGF0dXNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSkuZG9uZShmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLnJlc3VsdCA9PSAnZXJyb3InKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhudWxsLCAnJywgJ1dpc2hsaXN0IFNoYXJlIC0gRXJyb3InLCAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIGFuZCBjYW5ub3QgdXBkYXRlIHlvdXIgV2lzaGxpc3QgYXQgdGhpcyB0aW1lLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UucmVzdWx0ID09ICdzdWNjZXNzJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vIG9uLXNjcmVlbiB2aXN1YWxzIG5lZWQgdG8gb2NjdXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhudWxsLCAnJywgJ1dpc2hsaXN0IFNoYXJlIC0gRXJyb3InLCAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIGFuZCB3ZSBjb3VsZCBub3QgcmV0cmlldmUgeW91ciBXaXNobGlzdC4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci48L3A+Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IFVybHMuYWNjb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnLnNoYXJlLXdpc2hsaXN0LW1lbnUtcG9wdXAgLmNsb3NlLWJ1dHRvbicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgICAgICR0aGlzLnBhcmVudHMoJy5zaGFyZS13aXNobGlzdC1tZW51LXBvcHVwJykuYWRkQ2xhc3MoJ2Qtbm9uZScpO1xuICAgICAgICAgICAgdmFyIHNoYXJlTGluayA9ICR0aGlzLnBhcmVudHMoJy5zaGFyZS13aXNobGlzdC1tZW51LXBvcHVwJykuYXR0cignaWQnKS5pbmRleE9mKCdsaW5rLXBvcHVwJykgPiAtMTtcbiAgICAgICAgICAgIGlmIChzaGFyZUxpbmspIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zaWJsaW5ncygnLmZvcm0tcm93LWJ1dHRvbicpLmZpbmQoJ2J1dHRvbltuYW1lPVwic2hhcmUtd2lzaGxpc3QtbGluay1jb3B5XCJdJykucmVtb3ZlQ2xhc3MoJ2J0bi1jb21wbGV0ZSBkaXNhYmxlZCcpLmh0bWwoJ0NvcHknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnYnV0dG9uW25hbWU9XCJzaGFyZS13aXNobGlzdC1saW5rLWNvcHlcIl06bm90KC5kaXNhYmxlZCknLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgICAgIHZhciB3aXNobGlzdFVybCA9ICQoJyNzaGFyZS13aXNobGlzdC1saW5rLXBvcHVwIC5zaGFyZS13aXNobGlzdC11cmwgYScpLmh0bWwoKTtcbiAgICAgICAgICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHdpc2hsaXN0VXJsKTtcbiAgICAgICAgICAgICRidXR0b24uYWRkQ2xhc3MoJ2J0bi1jb21wbGV0ZSBkaXNhYmxlZCcpLmh0bWwoJzxpIGNsYXNzPVwiZmEgZmEtY2hlY2tcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+IENvcGllZCEnKTtcbiAgICAgICAgfSk7XG4gICAgICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnYnV0dG9uW25hbWU9XCJzaGFyZS13aXNobGlzdC1lbWFpbC1zZW5kXCJdOm5vdCguZGlzYWJsZWQpJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICAgICAgdmFyICRlbWFpbCA9ICQoJyN3aXNobGlzdC1zaGFyZS1lbWFpbC1pbnB1dCcpO1xuICAgICAgICAgICAgdmFyICRtZXNzYWdlID0gJCgnI3dpc2hsaXN0LXNoYXJlLWVtYWlsLW1lc3NhZ2UnKTtcbiAgICAgICAgICAgIHZhciBpc1ZhbGlkRW1haWxGb3JtID0gdmFsaWRhdGVFbWFpbEZvcm0oJGVtYWlsLCAkbWVzc2FnZSk7XG4gICAgICAgICAgICBpZiAoaXNWYWxpZEVtYWlsRm9ybSkge1xuICAgICAgICAgICAgICAgIGlmIChDdXN0b21lci5hdXRoZW50aWNhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3aXNobGlzdElEID0gJCgnaW5wdXRbbmFtZT1cImN1cnJlbnRfd2lzaGxpc3RfaWRcIl0nKS52YWwoKS50cmltKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aXNobGlzdElEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogVXJscy53aXNobGlzdFNoYXJlQnlFbWFpbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdpc2hsaXN0SUQ6IHdpc2hsaXN0SUQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRvRW1haWw6ICRlbWFpbC52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRW1haWxNZXNzYWdlOiAkbWVzc2FnZS52YWwoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmRvbmUoZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UucmVzdWx0ID09ICdlcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGluZyhudWxsLCAnJywgJ1dpc2hsaXN0IFNoYXJlIC0gRXJyb3InLCAnPHAgc3R5bGU9XCJwYWRkaW5nOiAxMHB4O1wiPk9vcHMsIHNvbWV0aGluZyB3ZW50IHdyb25nIGFuZCBjb3VsZCBub3Qgc2VuZCB5b3VyIFdpc2hsaXN0IGVtYWlsLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLjwvcD4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnJlc3VsdCA9PSAnc3VjY2VzcycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMucGFyZW50cygnI3NoYXJlLXdpc2hsaXN0LWVtYWlsLXBvcHVwJykuYWRkQ2xhc3MoJ3NoYXJlLXdpc2hsaXN0LWVtYWlsLXN1Y2Nlc3MnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxpbmcobnVsbCwgJycsICdXaXNobGlzdCBTaGFyZSAtIEVycm9yJywgJzxwIHN0eWxlPVwicGFkZGluZzogMTBweDtcIj5Pb3BzLCBzb21ldGhpbmcgd2VudCB3cm9uZyBhbmQgd2UgY291bGQgbm90IHJldHJpZXZlIHlvdXIgV2lzaGxpc3QgZm9yIHNoYXJpbmcuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuPC9wPicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBVcmxzLmFjY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCgnYm9keScpLm9uKCdjbGljaycsICcjc2hhcmUtd2lzaGxpc3QtbWVudSAuYnRuLW9wZW4nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJCh0aGlzKTtcbiAgICAgICAgICAgIHZhciAkc2hhcmVQb3B1cCA9ICRidXR0b24uc2libGluZ3MoJy5zaGFyZS13aXNobGlzdC1tZW51LXBvcHVwJyk7XG4gICAgICAgICAgICBpZiAoJHNoYXJlUG9wdXAubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJHNoYXJlUG9wdXAucmVtb3ZlQ2xhc3MoJ2Qtbm9uZSBzaGFyZS13aXNobGlzdC1lbWFpbC1zdWNjZXNzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLmNoZWNrV2lzaGxpc3RGb3JJdGVtID0gY2hlY2tXaXNobGlzdEZvckl0ZW07XG5leHBvcnRzLnByZXBhcmVXaXNobGlzdEFkZFVJID0gcHJlcGFyZVdpc2hsaXN0QWRkVUk7XG5leHBvcnRzLnByZXBhcmVXaXNobGlzdFJlbW92ZVVJID0gcHJlcGFyZVdpc2hsaXN0UmVtb3ZlVUk7XG5leHBvcnRzLnJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucyA9IHJlbmRlckFsbFdpc2hsaXN0QnV0dG9ucztcbmV4cG9ydHMuaW5pdCA9IGluaXQ7IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlNsaWNrU2xpZGVyID0ge1xuXHRPcHRpb25zOiB7XG5cdFx0U2luZ2xlOiB7XG5cdFx0XHRhY2Nlc3NpYmlsaXR5OiAgdHJ1ZSxcblx0XHRcdGluZmluaXRlOiBcdFx0dHJ1ZSxcblx0XHRcdGRvdHM6IFx0XHRcdGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBcdFx0ZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IFx0MSxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiAxLFxuXHRcdFx0cmVzcG9uc2l2ZTogXHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiA3NjcsXG5cdFx0XHRcdFx0c2V0dGluZ3M6IFx0e1xuXHRcdFx0XHRcdFx0ZG90czogdHJ1ZVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0sXG5cdFx0VGh1bWJuYWlsOiB7XG5cdFx0XHRhY2Nlc3NpYmlsaXR5OiAgdHJ1ZSxcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiBmYWxzZSxcblx0XHRcdGZvY3VzT25TZWxlY3Q6IFx0ZmFsc2UsXG5cdFx0XHRkb3RzOiBmYWxzZSxcblx0XHRcdGFycm93czogZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDcsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogN1xuXHRcdH0sXG5cdFx0Q2F0ZWdvcnlMYW5kaW5nOiB7XG5cdFx0XHRhY2Nlc3NpYmlsaXR5OiAgdHJ1ZSxcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiB0cnVlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiB0cnVlLFxuXHRcdFx0c2xpZGVzVG9TaG93OiA0LFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDQsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2N1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMCxcblx0XHRcdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRcdFx0c2xpZGVzVG9TaG93OiAzLFxuXHRcdFx0XHRcdFx0c2xpZGVzVG9TY3JvbGw6IDNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9XG5cdH1cbn0iLCJtb2R1bGUuZXhwb3J0cz17XCJOWVwiOntcIjAwNVwiOnRydWUsXCIwNjNcIjp0cnVlLFwiMTAwXCI6dHJ1ZSxcIjEwMVwiOnRydWUsXCIxMDJcIjp0cnVlLFwiMTAzXCI6dHJ1ZSxcIjEwNFwiOnRydWUsXCIxMDVcIjp0cnVlLFwiMTA2XCI6dHJ1ZSxcIjEwN1wiOnRydWUsXCIxMDhcIjp0cnVlLFwiMTA5XCI6dHJ1ZSxcIjExMFwiOnRydWUsXCIxMTFcIjp0cnVlLFwiMTEyXCI6dHJ1ZSxcIjExM1wiOnRydWUsXCIxMTRcIjp0cnVlLFwiMTE1XCI6dHJ1ZSxcIjExNlwiOnRydWUsXCIxMTdcIjp0cnVlLFwiMTE4XCI6dHJ1ZSxcIjExOVwiOnRydWUsXCIxMjBcIjp0cnVlLFwiMTIxXCI6dHJ1ZSxcIjEyMlwiOnRydWUsXCIxMjNcIjp0cnVlLFwiMTI0XCI6dHJ1ZSxcIjEyNVwiOnRydWUsXCIxMjZcIjp0cnVlLFwiMTI3XCI6dHJ1ZSxcIjEyOFwiOnRydWUsXCIxMjlcIjp0cnVlLFwiMTMwXCI6dHJ1ZSxcIjEzMVwiOnRydWUsXCIxMzJcIjp0cnVlLFwiMTMzXCI6dHJ1ZSxcIjEzNFwiOnRydWUsXCIxMzVcIjp0cnVlLFwiMTM2XCI6dHJ1ZSxcIjEzN1wiOnRydWUsXCIxMzhcIjp0cnVlLFwiMTM5XCI6dHJ1ZSxcIjE0MFwiOnRydWUsXCIxNDFcIjp0cnVlLFwiMTQyXCI6dHJ1ZSxcIjE0M1wiOnRydWUsXCIxNDRcIjp0cnVlLFwiMTQ1XCI6dHJ1ZSxcIjE0NlwiOnRydWUsXCIxNDdcIjp0cnVlLFwiMTQ4XCI6dHJ1ZSxcIjE0OVwiOnRydWV9LFwiUFJcIjp7XCIwMDZcIjp0cnVlLFwiMDA3XCI6dHJ1ZSxcIjAwOFwiOnRydWUsXCIwMDlcIjp0cnVlfSxcIlZJXCI6e1wiMDA2XCI6dHJ1ZSxcIjAwN1wiOnRydWUsXCIwMDhcIjp0cnVlLFwiMDA5XCI6dHJ1ZX0sXCJNQVwiOntcIjAxMFwiOnRydWUsXCIwMTFcIjp0cnVlLFwiMDEyXCI6dHJ1ZSxcIjAxM1wiOnRydWUsXCIwMTRcIjp0cnVlLFwiMDE1XCI6dHJ1ZSxcIjAxNlwiOnRydWUsXCIwMTdcIjp0cnVlLFwiMDE4XCI6dHJ1ZSxcIjAxOVwiOnRydWUsXCIwMjBcIjp0cnVlLFwiMDIxXCI6dHJ1ZSxcIjAyMlwiOnRydWUsXCIwMjNcIjp0cnVlLFwiMDI0XCI6dHJ1ZSxcIjAyNVwiOnRydWUsXCIwMjZcIjp0cnVlLFwiMDI3XCI6dHJ1ZSxcIjA1NVwiOnRydWV9LFwiUklcIjp7XCIwMjhcIjp0cnVlLFwiMDI5XCI6dHJ1ZX0sXCJOSFwiOntcIjAzMFwiOnRydWUsXCIwMzFcIjp0cnVlLFwiMDMyXCI6dHJ1ZSxcIjAzM1wiOnRydWUsXCIwMzRcIjp0cnVlLFwiMDM1XCI6dHJ1ZSxcIjAzNlwiOnRydWUsXCIwMzdcIjp0cnVlLFwiMDM4XCI6dHJ1ZSxcIjAzOVwiOnRydWV9LFwiVlRcIjp7XCIwMzVcIjp0cnVlLFwiMDM2XCI6dHJ1ZSxcIjAzN1wiOnRydWUsXCIwNTBcIjp0cnVlLFwiMDUxXCI6dHJ1ZSxcIjA1MlwiOnRydWUsXCIwNTNcIjp0cnVlLFwiMDU0XCI6dHJ1ZSxcIjA1NlwiOnRydWUsXCIwNTdcIjp0cnVlLFwiMDU4XCI6dHJ1ZSxcIjA1OVwiOnRydWV9LFwiTUVcIjp7XCIwMzlcIjp0cnVlLFwiMDQwXCI6dHJ1ZSxcIjA0MVwiOnRydWUsXCIwNDJcIjp0cnVlLFwiMDQzXCI6dHJ1ZSxcIjA0NFwiOnRydWUsXCIwNDVcIjp0cnVlLFwiMDQ2XCI6dHJ1ZSxcIjA0N1wiOnRydWUsXCIwNDhcIjp0cnVlLFwiMDQ5XCI6dHJ1ZX0sXCJDVFwiOntcIjA2MFwiOnRydWUsXCIwNjFcIjp0cnVlLFwiMDYyXCI6dHJ1ZSxcIjA2M1wiOnRydWUsXCIwNjRcIjp0cnVlLFwiMDY1XCI6dHJ1ZSxcIjA2NlwiOnRydWUsXCIwNjdcIjp0cnVlLFwiMDY4XCI6dHJ1ZSxcIjA2OVwiOnRydWV9LFwiTkpcIjp7XCIwNzBcIjp0cnVlLFwiMDcxXCI6dHJ1ZSxcIjA3MlwiOnRydWUsXCIwNzNcIjp0cnVlLFwiMDc0XCI6dHJ1ZSxcIjA3NVwiOnRydWUsXCIwNzZcIjp0cnVlLFwiMDc3XCI6dHJ1ZSxcIjA3OFwiOnRydWUsXCIwNzlcIjp0cnVlLFwiMDgwXCI6dHJ1ZSxcIjA4MVwiOnRydWUsXCIwODJcIjp0cnVlLFwiMDgzXCI6dHJ1ZSxcIjA4NFwiOnRydWUsXCIwODVcIjp0cnVlLFwiMDg2XCI6dHJ1ZSxcIjA4N1wiOnRydWUsXCIwODhcIjp0cnVlLFwiMDg5XCI6dHJ1ZX0sXCJBRVwiOntcIjA5MFwiOnRydWUsXCIwOTFcIjp0cnVlLFwiMDkyXCI6dHJ1ZSxcIjA5M1wiOnRydWUsXCIwOTRcIjp0cnVlLFwiMDk1XCI6dHJ1ZSxcIjA5NlwiOnRydWUsXCIwOTdcIjp0cnVlLFwiMDk4XCI6dHJ1ZSxcIjA5OVwiOnRydWV9LFwiUEFcIjp7XCIxNTBcIjp0cnVlLFwiMTUxXCI6dHJ1ZSxcIjE1MlwiOnRydWUsXCIxNTNcIjp0cnVlLFwiMTU0XCI6dHJ1ZSxcIjE1NVwiOnRydWUsXCIxNTZcIjp0cnVlLFwiMTU3XCI6dHJ1ZSxcIjE1OFwiOnRydWUsXCIxNTlcIjp0cnVlLFwiMTYwXCI6dHJ1ZSxcIjE2MVwiOnRydWUsXCIxNjJcIjp0cnVlLFwiMTYzXCI6dHJ1ZSxcIjE2NFwiOnRydWUsXCIxNjVcIjp0cnVlLFwiMTY2XCI6dHJ1ZSxcIjE2N1wiOnRydWUsXCIxNjhcIjp0cnVlLFwiMTY5XCI6dHJ1ZSxcIjE3MFwiOnRydWUsXCIxNzFcIjp0cnVlLFwiMTcyXCI6dHJ1ZSxcIjE3M1wiOnRydWUsXCIxNzRcIjp0cnVlLFwiMTc1XCI6dHJ1ZSxcIjE3NlwiOnRydWUsXCIxNzdcIjp0cnVlLFwiMTc4XCI6dHJ1ZSxcIjE3OVwiOnRydWUsXCIxODBcIjp0cnVlLFwiMTgxXCI6dHJ1ZSxcIjE4MlwiOnRydWUsXCIxODNcIjp0cnVlLFwiMTg0XCI6dHJ1ZSxcIjE4NVwiOnRydWUsXCIxODZcIjp0cnVlLFwiMTg3XCI6dHJ1ZSxcIjE4OFwiOnRydWUsXCIxODlcIjp0cnVlLFwiMTkwXCI6dHJ1ZSxcIjE5MVwiOnRydWUsXCIxOTJcIjp0cnVlLFwiMTkzXCI6dHJ1ZSxcIjE5NFwiOnRydWUsXCIxOTVcIjp0cnVlLFwiMTk2XCI6dHJ1ZSxcIjE5N1wiOnRydWV9LFwiREVcIjp7XCIxOTdcIjp0cnVlLFwiMTk4XCI6dHJ1ZSxcIjE5OVwiOnRydWV9LFwiRENcIjp7XCIyMDBcIjp0cnVlLFwiMjAyXCI6dHJ1ZSxcIjIwM1wiOnRydWUsXCIyMDRcIjp0cnVlLFwiMjA1XCI6dHJ1ZX0sXCJWQVwiOntcIjIwMVwiOnRydWUsXCIyMjBcIjp0cnVlLFwiMjIxXCI6dHJ1ZSxcIjIyMlwiOnRydWUsXCIyMjNcIjp0cnVlLFwiMjI0XCI6dHJ1ZSxcIjIyNVwiOnRydWUsXCIyMjZcIjp0cnVlLFwiMjI3XCI6dHJ1ZSxcIjIyOFwiOnRydWUsXCIyMjlcIjp0cnVlLFwiMjMwXCI6dHJ1ZSxcIjIzMVwiOnRydWUsXCIyMzJcIjp0cnVlLFwiMjMzXCI6dHJ1ZSxcIjIzNFwiOnRydWUsXCIyMzVcIjp0cnVlLFwiMjM2XCI6dHJ1ZSxcIjIzN1wiOnRydWUsXCIyMzhcIjp0cnVlLFwiMjM5XCI6dHJ1ZSxcIjI0MFwiOnRydWUsXCIyNDFcIjp0cnVlLFwiMjQyXCI6dHJ1ZSxcIjI0M1wiOnRydWUsXCIyNDRcIjp0cnVlLFwiMjQ1XCI6dHJ1ZSxcIjI0NlwiOnRydWV9LFwiTURcIjp7XCIyMDZcIjp0cnVlLFwiMjA3XCI6dHJ1ZSxcIjIwOFwiOnRydWUsXCIyMDlcIjp0cnVlLFwiMjEwXCI6dHJ1ZSxcIjIxMVwiOnRydWUsXCIyMTJcIjp0cnVlLFwiMjE0XCI6dHJ1ZSxcIjIxNVwiOnRydWUsXCIyMTZcIjp0cnVlLFwiMjE3XCI6dHJ1ZSxcIjIxOFwiOnRydWUsXCIyMTlcIjp0cnVlLFwiMjY3XCI6dHJ1ZX0sXCJXVlwiOntcIjI0NlwiOnRydWUsXCIyNDdcIjp0cnVlLFwiMjQ4XCI6dHJ1ZSxcIjI0OVwiOnRydWUsXCIyNTBcIjp0cnVlLFwiMjUxXCI6dHJ1ZSxcIjI1MlwiOnRydWUsXCIyNTNcIjp0cnVlLFwiMjU0XCI6dHJ1ZSxcIjI1NVwiOnRydWUsXCIyNTZcIjp0cnVlLFwiMjU3XCI6dHJ1ZSxcIjI1OFwiOnRydWUsXCIyNTlcIjp0cnVlLFwiMjYwXCI6dHJ1ZSxcIjI2MVwiOnRydWUsXCIyNjJcIjp0cnVlLFwiMjYzXCI6dHJ1ZSxcIjI2NFwiOnRydWUsXCIyNjVcIjp0cnVlLFwiMjY2XCI6dHJ1ZSxcIjI2N1wiOnRydWUsXCIyNjhcIjp0cnVlfSxcIk5DXCI6e1wiMjcwXCI6dHJ1ZSxcIjI3MVwiOnRydWUsXCIyNzJcIjp0cnVlLFwiMjczXCI6dHJ1ZSxcIjI3NFwiOnRydWUsXCIyNzVcIjp0cnVlLFwiMjc2XCI6dHJ1ZSxcIjI3N1wiOnRydWUsXCIyNzhcIjp0cnVlLFwiMjc5XCI6dHJ1ZSxcIjI4MFwiOnRydWUsXCIyODFcIjp0cnVlLFwiMjgyXCI6dHJ1ZSxcIjI4M1wiOnRydWUsXCIyODRcIjp0cnVlLFwiMjg1XCI6dHJ1ZSxcIjI4NlwiOnRydWUsXCIyODdcIjp0cnVlLFwiMjg4XCI6dHJ1ZSxcIjI4OVwiOnRydWUsXCIyOTdcIjp0cnVlfSxcIlNDXCI6e1wiMjkwXCI6dHJ1ZSxcIjI5MVwiOnRydWUsXCIyOTJcIjp0cnVlLFwiMjkzXCI6dHJ1ZSxcIjI5NFwiOnRydWUsXCIyOTVcIjp0cnVlLFwiMjk2XCI6dHJ1ZSxcIjI5N1wiOnRydWUsXCIyOThcIjp0cnVlLFwiMjk5XCI6dHJ1ZX0sXCJHQVwiOntcIjI5OFwiOnRydWUsXCIyOTlcIjp0cnVlLFwiMzAwXCI6dHJ1ZSxcIjMwMVwiOnRydWUsXCIzMDJcIjp0cnVlLFwiMzAzXCI6dHJ1ZSxcIjMwNFwiOnRydWUsXCIzMDVcIjp0cnVlLFwiMzA2XCI6dHJ1ZSxcIjMwN1wiOnRydWUsXCIzMDhcIjp0cnVlLFwiMzA5XCI6dHJ1ZSxcIjMxMFwiOnRydWUsXCIzMTFcIjp0cnVlLFwiMzEyXCI6dHJ1ZSxcIjMxM1wiOnRydWUsXCIzMTRcIjp0cnVlLFwiMzE1XCI6dHJ1ZSxcIjMxNlwiOnRydWUsXCIzMTdcIjp0cnVlLFwiMzE4XCI6dHJ1ZSxcIjMxOVwiOnRydWUsXCIzOThcIjp0cnVlLFwiMzk5XCI6dHJ1ZX0sXCJGTFwiOntcIjMyMFwiOnRydWUsXCIzMjFcIjp0cnVlLFwiMzIyXCI6dHJ1ZSxcIjMyM1wiOnRydWUsXCIzMjRcIjp0cnVlLFwiMzI1XCI6dHJ1ZSxcIjMyNlwiOnRydWUsXCIzMjdcIjp0cnVlLFwiMzI4XCI6dHJ1ZSxcIjMyOVwiOnRydWUsXCIzMzBcIjp0cnVlLFwiMzMxXCI6dHJ1ZSxcIjMzMlwiOnRydWUsXCIzMzNcIjp0cnVlLFwiMzM0XCI6dHJ1ZSxcIjMzNVwiOnRydWUsXCIzMzZcIjp0cnVlLFwiMzM3XCI6dHJ1ZSxcIjMzOFwiOnRydWUsXCIzMzlcIjp0cnVlLFwiMzQxXCI6dHJ1ZSxcIjM0MlwiOnRydWUsXCIzNDRcIjp0cnVlLFwiMzQ2XCI6dHJ1ZSxcIjM0N1wiOnRydWUsXCIzNDlcIjp0cnVlfSxcIkFBXCI6e1wiMzMxXCI6dHJ1ZSxcIjM0MFwiOnRydWV9LFwiQVBcIjp7XCIzNDBcIjp0cnVlLFwiOTYyXCI6dHJ1ZSxcIjk2M1wiOnRydWUsXCI5NjRcIjp0cnVlLFwiOTY1XCI6dHJ1ZSxcIjk2NlwiOnRydWV9LFwiQUxcIjp7XCIzNTBcIjp0cnVlLFwiMzUxXCI6dHJ1ZSxcIjM1MlwiOnRydWUsXCIzNTRcIjp0cnVlLFwiMzU1XCI6dHJ1ZSxcIjM1NlwiOnRydWUsXCIzNTdcIjp0cnVlLFwiMzU4XCI6dHJ1ZSxcIjM1OVwiOnRydWUsXCIzNjBcIjp0cnVlLFwiMzYxXCI6dHJ1ZSxcIjM2MlwiOnRydWUsXCIzNjNcIjp0cnVlLFwiMzY0XCI6dHJ1ZSxcIjM2NVwiOnRydWUsXCIzNjZcIjp0cnVlLFwiMzY3XCI6dHJ1ZSxcIjM2OFwiOnRydWUsXCIzNjlcIjp0cnVlfSxcIk1TXCI6e1wiMzY5XCI6dHJ1ZSxcIjM3MFwiOnRydWUsXCIzODZcIjp0cnVlLFwiMzg3XCI6dHJ1ZSxcIjM4OFwiOnRydWUsXCIzODlcIjp0cnVlLFwiMzkwXCI6dHJ1ZSxcIjM5MVwiOnRydWUsXCIzOTJcIjp0cnVlLFwiMzkzXCI6dHJ1ZSxcIjM5NFwiOnRydWUsXCIzOTVcIjp0cnVlLFwiMzk2XCI6dHJ1ZSxcIjM5N1wiOnRydWV9LFwiVE5cIjp7XCIzNzBcIjp0cnVlLFwiMzcxXCI6dHJ1ZSxcIjM3MlwiOnRydWUsXCIzNzNcIjp0cnVlLFwiMzc0XCI6dHJ1ZSxcIjM3NVwiOnRydWUsXCIzNzZcIjp0cnVlLFwiMzc3XCI6dHJ1ZSxcIjM3OFwiOnRydWUsXCIzNzlcIjp0cnVlLFwiMzgwXCI6dHJ1ZSxcIjM4MVwiOnRydWUsXCIzODJcIjp0cnVlLFwiMzgzXCI6dHJ1ZSxcIjM4NFwiOnRydWUsXCIzODVcIjp0cnVlLFwiMzg2XCI6dHJ1ZSxcIjcyM1wiOnRydWV9LFwiS1lcIjp7XCI0MDBcIjp0cnVlLFwiNDAxXCI6dHJ1ZSxcIjQwMlwiOnRydWUsXCI0MDNcIjp0cnVlLFwiNDA0XCI6dHJ1ZSxcIjQwNVwiOnRydWUsXCI0MDZcIjp0cnVlLFwiNDA3XCI6dHJ1ZSxcIjQwOFwiOnRydWUsXCI0MDlcIjp0cnVlLFwiNDEwXCI6dHJ1ZSxcIjQxMVwiOnRydWUsXCI0MTJcIjp0cnVlLFwiNDEzXCI6dHJ1ZSxcIjQxNFwiOnRydWUsXCI0MTVcIjp0cnVlLFwiNDE2XCI6dHJ1ZSxcIjQxN1wiOnRydWUsXCI0MThcIjp0cnVlLFwiNDIwXCI6dHJ1ZSxcIjQyMVwiOnRydWUsXCI0MjJcIjp0cnVlLFwiNDIzXCI6dHJ1ZSxcIjQyNFwiOnRydWUsXCI0MjVcIjp0cnVlLFwiNDI2XCI6dHJ1ZSxcIjQyN1wiOnRydWUsXCI0NzFcIjp0cnVlfSxcIk9IXCI6e1wiNDEwXCI6dHJ1ZSxcIjQzMFwiOnRydWUsXCI0MzFcIjp0cnVlLFwiNDMyXCI6dHJ1ZSxcIjQzM1wiOnRydWUsXCI0MzRcIjp0cnVlLFwiNDM1XCI6dHJ1ZSxcIjQzNlwiOnRydWUsXCI0MzdcIjp0cnVlLFwiNDM4XCI6dHJ1ZSxcIjQzOVwiOnRydWUsXCI0NDBcIjp0cnVlLFwiNDQxXCI6dHJ1ZSxcIjQ0MlwiOnRydWUsXCI0NDNcIjp0cnVlLFwiNDQ0XCI6dHJ1ZSxcIjQ0NVwiOnRydWUsXCI0NDZcIjp0cnVlLFwiNDQ3XCI6dHJ1ZSxcIjQ0OFwiOnRydWUsXCI0NDlcIjp0cnVlLFwiNDUwXCI6dHJ1ZSxcIjQ1MVwiOnRydWUsXCI0NTJcIjp0cnVlLFwiNDUzXCI6dHJ1ZSxcIjQ1NFwiOnRydWUsXCI0NTVcIjp0cnVlLFwiNDU2XCI6dHJ1ZSxcIjQ1N1wiOnRydWUsXCI0NThcIjp0cnVlLFwiNDU5XCI6dHJ1ZSxcIjQ3MFwiOnRydWUsXCI0NzJcIjp0cnVlfSxcIklOXCI6e1wiNDI0XCI6dHJ1ZSxcIjQ2MFwiOnRydWUsXCI0NjFcIjp0cnVlLFwiNDYyXCI6dHJ1ZSxcIjQ2M1wiOnRydWUsXCI0NjRcIjp0cnVlLFwiNDY1XCI6dHJ1ZSxcIjQ2NlwiOnRydWUsXCI0NjdcIjp0cnVlLFwiNDY4XCI6dHJ1ZSxcIjQ2OVwiOnRydWUsXCI0NzBcIjp0cnVlLFwiNDcxXCI6dHJ1ZSxcIjQ3MlwiOnRydWUsXCI0NzNcIjp0cnVlLFwiNDc0XCI6dHJ1ZSxcIjQ3NVwiOnRydWUsXCI0NzZcIjp0cnVlLFwiNDc3XCI6dHJ1ZSxcIjQ3OFwiOnRydWUsXCI0NzlcIjp0cnVlfSxcIk1JXCI6e1wiNDgwXCI6dHJ1ZSxcIjQ4MVwiOnRydWUsXCI0ODJcIjp0cnVlLFwiNDgzXCI6dHJ1ZSxcIjQ4NFwiOnRydWUsXCI0ODVcIjp0cnVlLFwiNDg2XCI6dHJ1ZSxcIjQ4N1wiOnRydWUsXCI0ODhcIjp0cnVlLFwiNDg5XCI6dHJ1ZSxcIjQ5MFwiOnRydWUsXCI0OTFcIjp0cnVlLFwiNDkyXCI6dHJ1ZSxcIjQ5M1wiOnRydWUsXCI0OTRcIjp0cnVlLFwiNDk1XCI6dHJ1ZSxcIjQ5NlwiOnRydWUsXCI0OTdcIjp0cnVlLFwiNDk4XCI6dHJ1ZSxcIjQ5OVwiOnRydWV9LFwiSUFcIjp7XCI1MDBcIjp0cnVlLFwiNTAxXCI6dHJ1ZSxcIjUwMlwiOnRydWUsXCI1MDNcIjp0cnVlLFwiNTA0XCI6dHJ1ZSxcIjUwNVwiOnRydWUsXCI1MDZcIjp0cnVlLFwiNTA3XCI6dHJ1ZSxcIjUwOFwiOnRydWUsXCI1MDlcIjp0cnVlLFwiNTEwXCI6dHJ1ZSxcIjUxMVwiOnRydWUsXCI1MTJcIjp0cnVlLFwiNTEzXCI6dHJ1ZSxcIjUxNFwiOnRydWUsXCI1MTVcIjp0cnVlLFwiNTE2XCI6dHJ1ZSxcIjUyMFwiOnRydWUsXCI1MjFcIjp0cnVlLFwiNTIyXCI6dHJ1ZSxcIjUyM1wiOnRydWUsXCI1MjRcIjp0cnVlLFwiNTI1XCI6dHJ1ZSxcIjUyNlwiOnRydWUsXCI1MjdcIjp0cnVlLFwiNTI4XCI6dHJ1ZX0sXCJORVwiOntcIjUxNVwiOnRydWUsXCI1MTZcIjp0cnVlLFwiNjgwXCI6dHJ1ZSxcIjY4MVwiOnRydWUsXCI2ODNcIjp0cnVlLFwiNjg0XCI6dHJ1ZSxcIjY4NVwiOnRydWUsXCI2ODZcIjp0cnVlLFwiNjg3XCI6dHJ1ZSxcIjY4OFwiOnRydWUsXCI2ODlcIjp0cnVlLFwiNjkwXCI6dHJ1ZSxcIjY5MVwiOnRydWUsXCI2OTJcIjp0cnVlLFwiNjkzXCI6dHJ1ZX0sXCJJTFwiOntcIjUyN1wiOnRydWUsXCI2MDBcIjp0cnVlLFwiNjAxXCI6dHJ1ZSxcIjYwMlwiOnRydWUsXCI2MDNcIjp0cnVlLFwiNjA0XCI6dHJ1ZSxcIjYwNVwiOnRydWUsXCI2MDZcIjp0cnVlLFwiNjA3XCI6dHJ1ZSxcIjYwOFwiOnRydWUsXCI2MDlcIjp0cnVlLFwiNjEwXCI6dHJ1ZSxcIjYxMVwiOnRydWUsXCI2MTJcIjp0cnVlLFwiNjEzXCI6dHJ1ZSxcIjYxNFwiOnRydWUsXCI2MTVcIjp0cnVlLFwiNjE2XCI6dHJ1ZSxcIjYxN1wiOnRydWUsXCI2MThcIjp0cnVlLFwiNjE5XCI6dHJ1ZSxcIjYyMFwiOnRydWUsXCI2MjJcIjp0cnVlLFwiNjIzXCI6dHJ1ZSxcIjYyNFwiOnRydWUsXCI2MjVcIjp0cnVlLFwiNjI2XCI6dHJ1ZSxcIjYyN1wiOnRydWUsXCI2MjhcIjp0cnVlLFwiNjI5XCI6dHJ1ZSxcIjYzNFwiOnRydWUsXCI2MzVcIjp0cnVlfSxcIldJXCI6e1wiNTMwXCI6dHJ1ZSxcIjUzMVwiOnRydWUsXCI1MzJcIjp0cnVlLFwiNTM0XCI6dHJ1ZSxcIjUzNVwiOnRydWUsXCI1MzdcIjp0cnVlLFwiNTM4XCI6dHJ1ZSxcIjUzOVwiOnRydWUsXCI1NDBcIjp0cnVlLFwiNTQxXCI6dHJ1ZSxcIjU0MlwiOnRydWUsXCI1NDNcIjp0cnVlLFwiNTQ0XCI6dHJ1ZSxcIjU0NVwiOnRydWUsXCI1NDZcIjp0cnVlLFwiNTQ3XCI6dHJ1ZSxcIjU0OFwiOnRydWUsXCI1NDlcIjp0cnVlfSxcIk1OXCI6e1wiNTQwXCI6dHJ1ZSxcIjU1MFwiOnRydWUsXCI1NTFcIjp0cnVlLFwiNTUzXCI6dHJ1ZSxcIjU1NFwiOnRydWUsXCI1NTZcIjp0cnVlLFwiNTU3XCI6dHJ1ZSxcIjU1OFwiOnRydWUsXCI1NTlcIjp0cnVlLFwiNTYwXCI6dHJ1ZSxcIjU2MVwiOnRydWUsXCI1NjJcIjp0cnVlLFwiNTYzXCI6dHJ1ZSxcIjU2NFwiOnRydWUsXCI1NjVcIjp0cnVlLFwiNTY2XCI6dHJ1ZSxcIjU2N1wiOnRydWV9LFwiTkRcIjp7XCI1NjdcIjp0cnVlLFwiNTgwXCI6dHJ1ZSxcIjU4MVwiOnRydWUsXCI1ODJcIjp0cnVlLFwiNTgzXCI6dHJ1ZSxcIjU4NFwiOnRydWUsXCI1ODVcIjp0cnVlLFwiNTg2XCI6dHJ1ZSxcIjU4N1wiOnRydWUsXCI1ODhcIjp0cnVlfSxcIlNEXCI6e1wiNTcwXCI6dHJ1ZSxcIjU3MVwiOnRydWUsXCI1NzJcIjp0cnVlLFwiNTczXCI6dHJ1ZSxcIjU3NFwiOnRydWUsXCI1NzVcIjp0cnVlLFwiNTc2XCI6dHJ1ZSxcIjU3N1wiOnRydWV9LFwiTVRcIjp7XCI1OTBcIjp0cnVlLFwiNTkxXCI6dHJ1ZSxcIjU5MlwiOnRydWUsXCI1OTNcIjp0cnVlLFwiNTk0XCI6dHJ1ZSxcIjU5NVwiOnRydWUsXCI1OTZcIjp0cnVlLFwiNTk3XCI6dHJ1ZSxcIjU5OFwiOnRydWUsXCI1OTlcIjp0cnVlfSxcIk1PXCI6e1wiNjIwXCI6dHJ1ZSxcIjYyMlwiOnRydWUsXCI2MzBcIjp0cnVlLFwiNjMxXCI6dHJ1ZSxcIjYzM1wiOnRydWUsXCI2MzRcIjp0cnVlLFwiNjM1XCI6dHJ1ZSxcIjYzNlwiOnRydWUsXCI2MzdcIjp0cnVlLFwiNjM4XCI6dHJ1ZSxcIjYzOVwiOnRydWUsXCI2NDBcIjp0cnVlLFwiNjQxXCI6dHJ1ZSxcIjY0NFwiOnRydWUsXCI2NDVcIjp0cnVlLFwiNjQ2XCI6dHJ1ZSxcIjY0N1wiOnRydWUsXCI2NDhcIjp0cnVlLFwiNjQ5XCI6dHJ1ZSxcIjY1MFwiOnRydWUsXCI2NTFcIjp0cnVlLFwiNjUyXCI6dHJ1ZSxcIjY1M1wiOnRydWUsXCI2NTRcIjp0cnVlLFwiNjU1XCI6dHJ1ZSxcIjY1NlwiOnRydWUsXCI2NTdcIjp0cnVlLFwiNjU4XCI6dHJ1ZX0sXCJLU1wiOntcIjY2MFwiOnRydWUsXCI2NjFcIjp0cnVlLFwiNjYyXCI6dHJ1ZSxcIjY2NFwiOnRydWUsXCI2NjVcIjp0cnVlLFwiNjY2XCI6dHJ1ZSxcIjY2N1wiOnRydWUsXCI2NjhcIjp0cnVlLFwiNjY5XCI6dHJ1ZSxcIjY3MFwiOnRydWUsXCI2NzFcIjp0cnVlLFwiNjcyXCI6dHJ1ZSxcIjY3M1wiOnRydWUsXCI2NzRcIjp0cnVlLFwiNjc1XCI6dHJ1ZSxcIjY3NlwiOnRydWUsXCI2NzdcIjp0cnVlLFwiNjc4XCI6dHJ1ZSxcIjY3OVwiOnRydWV9LFwiTEFcIjp7XCI3MDBcIjp0cnVlLFwiNzAxXCI6dHJ1ZSxcIjcwM1wiOnRydWUsXCI3MDRcIjp0cnVlLFwiNzA1XCI6dHJ1ZSxcIjcwNlwiOnRydWUsXCI3MDdcIjp0cnVlLFwiNzA4XCI6dHJ1ZSxcIjcxMFwiOnRydWUsXCI3MTFcIjp0cnVlLFwiNzEyXCI6dHJ1ZSxcIjcxM1wiOnRydWUsXCI3MTRcIjp0cnVlfSxcIkFSXCI6e1wiNzE2XCI6dHJ1ZSxcIjcxN1wiOnRydWUsXCI3MThcIjp0cnVlLFwiNzE5XCI6dHJ1ZSxcIjcyMFwiOnRydWUsXCI3MjFcIjp0cnVlLFwiNzIyXCI6dHJ1ZSxcIjcyM1wiOnRydWUsXCI3MjRcIjp0cnVlLFwiNzI1XCI6dHJ1ZSxcIjcyNlwiOnRydWUsXCI3MjdcIjp0cnVlLFwiNzI4XCI6dHJ1ZSxcIjcyOVwiOnRydWV9LFwiT0tcIjp7XCI3MzBcIjp0cnVlLFwiNzMxXCI6dHJ1ZSxcIjczNFwiOnRydWUsXCI3MzVcIjp0cnVlLFwiNzM2XCI6dHJ1ZSxcIjczN1wiOnRydWUsXCI3MzhcIjp0cnVlLFwiNzM5XCI6dHJ1ZSxcIjc0MFwiOnRydWUsXCI3NDFcIjp0cnVlLFwiNzQzXCI6dHJ1ZSxcIjc0NFwiOnRydWUsXCI3NDVcIjp0cnVlLFwiNzQ2XCI6dHJ1ZSxcIjc0N1wiOnRydWUsXCI3NDhcIjp0cnVlLFwiNzQ5XCI6dHJ1ZX0sXCJUWFwiOntcIjczM1wiOnRydWUsXCI3MzlcIjp0cnVlLFwiNzUwXCI6dHJ1ZSxcIjc1MVwiOnRydWUsXCI3NTJcIjp0cnVlLFwiNzUzXCI6dHJ1ZSxcIjc1NFwiOnRydWUsXCI3NTVcIjp0cnVlLFwiNzU2XCI6dHJ1ZSxcIjc1N1wiOnRydWUsXCI3NThcIjp0cnVlLFwiNzU5XCI6dHJ1ZSxcIjc2MFwiOnRydWUsXCI3NjFcIjp0cnVlLFwiNzYyXCI6dHJ1ZSxcIjc2M1wiOnRydWUsXCI3NjRcIjp0cnVlLFwiNzY1XCI6dHJ1ZSxcIjc2NlwiOnRydWUsXCI3NjdcIjp0cnVlLFwiNzY4XCI6dHJ1ZSxcIjc2OVwiOnRydWUsXCI3NzBcIjp0cnVlLFwiNzcxXCI6dHJ1ZSxcIjc3MlwiOnRydWUsXCI3NzNcIjp0cnVlLFwiNzc0XCI6dHJ1ZSxcIjc3NVwiOnRydWUsXCI3NzZcIjp0cnVlLFwiNzc3XCI6dHJ1ZSxcIjc3OFwiOnRydWUsXCI3NzlcIjp0cnVlLFwiNzgwXCI6dHJ1ZSxcIjc4MVwiOnRydWUsXCI3ODJcIjp0cnVlLFwiNzgzXCI6dHJ1ZSxcIjc4NFwiOnRydWUsXCI3ODVcIjp0cnVlLFwiNzg2XCI6dHJ1ZSxcIjc4N1wiOnRydWUsXCI3ODhcIjp0cnVlLFwiNzg5XCI6dHJ1ZSxcIjc5MFwiOnRydWUsXCI3OTFcIjp0cnVlLFwiNzkyXCI6dHJ1ZSxcIjc5M1wiOnRydWUsXCI3OTRcIjp0cnVlLFwiNzk1XCI6dHJ1ZSxcIjc5NlwiOnRydWUsXCI3OTdcIjp0cnVlLFwiNzk4XCI6dHJ1ZSxcIjc5OVwiOnRydWUsXCI4ODVcIjp0cnVlfSxcIkNPXCI6e1wiODAwXCI6dHJ1ZSxcIjgwMVwiOnRydWUsXCI4MDJcIjp0cnVlLFwiODAzXCI6dHJ1ZSxcIjgwNFwiOnRydWUsXCI4MDVcIjp0cnVlLFwiODA2XCI6dHJ1ZSxcIjgwN1wiOnRydWUsXCI4MDhcIjp0cnVlLFwiODA5XCI6dHJ1ZSxcIjgxMFwiOnRydWUsXCI4MTFcIjp0cnVlLFwiODEyXCI6dHJ1ZSxcIjgxM1wiOnRydWUsXCI4MTRcIjp0cnVlLFwiODE1XCI6dHJ1ZSxcIjgxNlwiOnRydWV9LFwiV1lcIjp7XCI4MjBcIjp0cnVlLFwiODIxXCI6dHJ1ZSxcIjgyMlwiOnRydWUsXCI4MjNcIjp0cnVlLFwiODI0XCI6dHJ1ZSxcIjgyNVwiOnRydWUsXCI4MjZcIjp0cnVlLFwiODI3XCI6dHJ1ZSxcIjgyOFwiOnRydWUsXCI4MjlcIjp0cnVlLFwiODMwXCI6dHJ1ZSxcIjgzMVwiOnRydWUsXCI4MzRcIjp0cnVlfSxcIklEXCI6e1wiODMyXCI6dHJ1ZSxcIjgzM1wiOnRydWUsXCI4MzRcIjp0cnVlLFwiODM1XCI6dHJ1ZSxcIjgzNlwiOnRydWUsXCI4MzdcIjp0cnVlLFwiODM4XCI6dHJ1ZSxcIjk3OVwiOnRydWUsXCI5OTRcIjp0cnVlfSxcIldBXCI6e1wiODM4XCI6dHJ1ZSxcIjk4MFwiOnRydWUsXCI5ODFcIjp0cnVlLFwiOTgyXCI6dHJ1ZSxcIjk4M1wiOnRydWUsXCI5ODRcIjp0cnVlLFwiOTg1XCI6dHJ1ZSxcIjk4NlwiOnRydWUsXCI5ODhcIjp0cnVlLFwiOTg5XCI6dHJ1ZSxcIjk5MFwiOnRydWUsXCI5OTFcIjp0cnVlLFwiOTkyXCI6dHJ1ZSxcIjk5M1wiOnRydWUsXCI5OTRcIjp0cnVlfSxcIlVUXCI6e1wiODQwXCI6dHJ1ZSxcIjg0MVwiOnRydWUsXCI4NDJcIjp0cnVlLFwiODQzXCI6dHJ1ZSxcIjg0NFwiOnRydWUsXCI4NDVcIjp0cnVlLFwiODQ2XCI6dHJ1ZSxcIjg0N1wiOnRydWV9LFwiQVpcIjp7XCI4NTBcIjp0cnVlLFwiODUxXCI6dHJ1ZSxcIjg1MlwiOnRydWUsXCI4NTNcIjp0cnVlLFwiODU1XCI6dHJ1ZSxcIjg1NlwiOnRydWUsXCI4NTdcIjp0cnVlLFwiODU5XCI6dHJ1ZSxcIjg2MFwiOnRydWUsXCI4NjNcIjp0cnVlLFwiODY0XCI6dHJ1ZSxcIjg2NVwiOnRydWV9LFwiTk1cIjp7XCI4NzBcIjp0cnVlLFwiODcxXCI6dHJ1ZSxcIjg3MlwiOnRydWUsXCI4NzNcIjp0cnVlLFwiODc0XCI6dHJ1ZSxcIjg3NVwiOnRydWUsXCI4NzdcIjp0cnVlLFwiODc4XCI6dHJ1ZSxcIjg3OVwiOnRydWUsXCI4ODBcIjp0cnVlLFwiODgxXCI6dHJ1ZSxcIjg4MlwiOnRydWUsXCI4ODNcIjp0cnVlLFwiODg0XCI6dHJ1ZX0sXCJOVlwiOntcIjg3N1wiOnRydWUsXCI4ODlcIjp0cnVlLFwiODkwXCI6dHJ1ZSxcIjg5MVwiOnRydWUsXCI4OTNcIjp0cnVlLFwiODk0XCI6dHJ1ZSxcIjg5NVwiOnRydWUsXCI4OTdcIjp0cnVlLFwiODk4XCI6dHJ1ZSxcIjk2MVwiOnRydWV9LFwiQ0FcIjp7XCI5MDBcIjp0cnVlLFwiOTAxXCI6dHJ1ZSxcIjkwMlwiOnRydWUsXCI5MDNcIjp0cnVlLFwiOTA0XCI6dHJ1ZSxcIjkwNVwiOnRydWUsXCI5MDZcIjp0cnVlLFwiOTA3XCI6dHJ1ZSxcIjkwOFwiOnRydWUsXCI5MTBcIjp0cnVlLFwiOTExXCI6dHJ1ZSxcIjkxMlwiOnRydWUsXCI5MTNcIjp0cnVlLFwiOTE0XCI6dHJ1ZSxcIjkxNVwiOnRydWUsXCI5MTZcIjp0cnVlLFwiOTE3XCI6dHJ1ZSxcIjkxOFwiOnRydWUsXCI5MTlcIjp0cnVlLFwiOTIwXCI6dHJ1ZSxcIjkyMVwiOnRydWUsXCI5MjJcIjp0cnVlLFwiOTIzXCI6dHJ1ZSxcIjkyNFwiOnRydWUsXCI5MjVcIjp0cnVlLFwiOTI2XCI6dHJ1ZSxcIjkyN1wiOnRydWUsXCI5MjhcIjp0cnVlLFwiOTMwXCI6dHJ1ZSxcIjkzMVwiOnRydWUsXCI5MzJcIjp0cnVlLFwiOTMzXCI6dHJ1ZSxcIjkzNFwiOnRydWUsXCI5MzVcIjp0cnVlLFwiOTM2XCI6dHJ1ZSxcIjkzN1wiOnRydWUsXCI5MzhcIjp0cnVlLFwiOTM5XCI6dHJ1ZSxcIjk0MFwiOnRydWUsXCI5NDFcIjp0cnVlLFwiOTQyXCI6dHJ1ZSxcIjk0M1wiOnRydWUsXCI5NDRcIjp0cnVlLFwiOTQ1XCI6dHJ1ZSxcIjk0NlwiOnRydWUsXCI5NDdcIjp0cnVlLFwiOTQ4XCI6dHJ1ZSxcIjk0OVwiOnRydWUsXCI5NTBcIjp0cnVlLFwiOTUxXCI6dHJ1ZSxcIjk1MlwiOnRydWUsXCI5NTNcIjp0cnVlLFwiOTU0XCI6dHJ1ZSxcIjk1NVwiOnRydWUsXCI5NTZcIjp0cnVlLFwiOTU3XCI6dHJ1ZSxcIjk1OFwiOnRydWUsXCI5NTlcIjp0cnVlLFwiOTYwXCI6dHJ1ZSxcIjk2MVwiOnRydWV9LFwiSElcIjp7XCI5NjdcIjp0cnVlLFwiOTY4XCI6dHJ1ZX0sXCJBU1wiOntcIjk2N1wiOnRydWV9LFwiR1VcIjp7XCI5NjlcIjp0cnVlfSxcIk1IXCI6e1wiOTY5XCI6dHJ1ZX0sXCJPUlwiOntcIjk3MFwiOnRydWUsXCI5NzFcIjp0cnVlLFwiOTcyXCI6dHJ1ZSxcIjk3M1wiOnRydWUsXCI5NzRcIjp0cnVlLFwiOTc1XCI6dHJ1ZSxcIjk3NlwiOnRydWUsXCI5NzdcIjp0cnVlLFwiOTc4XCI6dHJ1ZSxcIjk3OVwiOnRydWUsXCI5ODZcIjp0cnVlfSxcIkFLXCI6e1wiOTk1XCI6dHJ1ZSxcIjk5NlwiOnRydWUsXCI5OTdcIjp0cnVlLFwiOTk4XCI6dHJ1ZSxcIjk5OVwiOnRydWV9fSIsIm1vZHVsZS5leHBvcnRzPXtcIjEwMFwiOlwiTllcIixcIjEwMVwiOlwiTllcIixcIjEwMlwiOlwiTllcIixcIjEwM1wiOlwiTllcIixcIjEwNFwiOlwiTllcIixcIjEwNVwiOlwiTllcIixcIjEwNlwiOlwiTllcIixcIjEwN1wiOlwiTllcIixcIjEwOFwiOlwiTllcIixcIjEwOVwiOlwiTllcIixcIjExMFwiOlwiTllcIixcIjExMVwiOlwiTllcIixcIjExMlwiOlwiTllcIixcIjExM1wiOlwiTllcIixcIjExNFwiOlwiTllcIixcIjExNVwiOlwiTllcIixcIjExNlwiOlwiTllcIixcIjExN1wiOlwiTllcIixcIjExOFwiOlwiTllcIixcIjExOVwiOlwiTllcIixcIjEyMFwiOlwiTllcIixcIjEyMVwiOlwiTllcIixcIjEyMlwiOlwiTllcIixcIjEyM1wiOlwiTllcIixcIjEyNFwiOlwiTllcIixcIjEyNVwiOlwiTllcIixcIjEyNlwiOlwiTllcIixcIjEyN1wiOlwiTllcIixcIjEyOFwiOlwiTllcIixcIjEyOVwiOlwiTllcIixcIjEzMFwiOlwiTllcIixcIjEzMVwiOlwiTllcIixcIjEzMlwiOlwiTllcIixcIjEzM1wiOlwiTllcIixcIjEzNFwiOlwiTllcIixcIjEzNVwiOlwiTllcIixcIjEzNlwiOlwiTllcIixcIjEzN1wiOlwiTllcIixcIjEzOFwiOlwiTllcIixcIjEzOVwiOlwiTllcIixcIjE0MFwiOlwiTllcIixcIjE0MVwiOlwiTllcIixcIjE0MlwiOlwiTllcIixcIjE0M1wiOlwiTllcIixcIjE0NFwiOlwiTllcIixcIjE0NVwiOlwiTllcIixcIjE0NlwiOlwiTllcIixcIjE0N1wiOlwiTllcIixcIjE0OFwiOlwiTllcIixcIjE0OVwiOlwiTllcIixcIjE1MFwiOlwiUEFcIixcIjE1MVwiOlwiUEFcIixcIjE1MlwiOlwiUEFcIixcIjE1M1wiOlwiUEFcIixcIjE1NFwiOlwiUEFcIixcIjE1NVwiOlwiUEFcIixcIjE1NlwiOlwiUEFcIixcIjE1N1wiOlwiUEFcIixcIjE1OFwiOlwiUEFcIixcIjE1OVwiOlwiUEFcIixcIjE2MFwiOlwiUEFcIixcIjE2MVwiOlwiUEFcIixcIjE2MlwiOlwiUEFcIixcIjE2M1wiOlwiUEFcIixcIjE2NFwiOlwiUEFcIixcIjE2NVwiOlwiUEFcIixcIjE2NlwiOlwiUEFcIixcIjE2N1wiOlwiUEFcIixcIjE2OFwiOlwiUEFcIixcIjE2OVwiOlwiUEFcIixcIjE3MFwiOlwiUEFcIixcIjE3MVwiOlwiUEFcIixcIjE3MlwiOlwiUEFcIixcIjE3M1wiOlwiUEFcIixcIjE3NFwiOlwiUEFcIixcIjE3NVwiOlwiUEFcIixcIjE3NlwiOlwiUEFcIixcIjE3N1wiOlwiUEFcIixcIjE3OFwiOlwiUEFcIixcIjE3OVwiOlwiUEFcIixcIjE4MFwiOlwiUEFcIixcIjE4MVwiOlwiUEFcIixcIjE4MlwiOlwiUEFcIixcIjE4M1wiOlwiUEFcIixcIjE4NFwiOlwiUEFcIixcIjE4NVwiOlwiUEFcIixcIjE4NlwiOlwiUEFcIixcIjE4N1wiOlwiUEFcIixcIjE4OFwiOlwiUEFcIixcIjE4OVwiOlwiUEFcIixcIjE5MFwiOlwiUEFcIixcIjE5MVwiOlwiUEFcIixcIjE5MlwiOlwiUEFcIixcIjE5M1wiOlwiUEFcIixcIjE5NFwiOlwiUEFcIixcIjE5NVwiOlwiUEFcIixcIjE5NlwiOlwiUEFcIixcIjE5N1wiOlwiREVcIixcIjE5OFwiOlwiREVcIixcIjE5OVwiOlwiREVcIixcIjIwMFwiOlwiRENcIixcIjIwMVwiOlwiVkFcIixcIjIwMlwiOlwiRENcIixcIjIwM1wiOlwiRENcIixcIjIwNFwiOlwiRENcIixcIjIwNVwiOlwiRENcIixcIjIwNlwiOlwiTURcIixcIjIwN1wiOlwiTURcIixcIjIwOFwiOlwiTURcIixcIjIwOVwiOlwiTURcIixcIjIxMFwiOlwiTURcIixcIjIxMVwiOlwiTURcIixcIjIxMlwiOlwiTURcIixcIjIxNFwiOlwiTURcIixcIjIxNVwiOlwiTURcIixcIjIxNlwiOlwiTURcIixcIjIxN1wiOlwiTURcIixcIjIxOFwiOlwiTURcIixcIjIxOVwiOlwiTURcIixcIjIyMFwiOlwiVkFcIixcIjIyMVwiOlwiVkFcIixcIjIyMlwiOlwiVkFcIixcIjIyM1wiOlwiVkFcIixcIjIyNFwiOlwiVkFcIixcIjIyNVwiOlwiVkFcIixcIjIyNlwiOlwiVkFcIixcIjIyN1wiOlwiVkFcIixcIjIyOFwiOlwiVkFcIixcIjIyOVwiOlwiVkFcIixcIjIzMFwiOlwiVkFcIixcIjIzMVwiOlwiVkFcIixcIjIzMlwiOlwiVkFcIixcIjIzM1wiOlwiVkFcIixcIjIzNFwiOlwiVkFcIixcIjIzNVwiOlwiVkFcIixcIjIzNlwiOlwiVkFcIixcIjIzN1wiOlwiVkFcIixcIjIzOFwiOlwiVkFcIixcIjIzOVwiOlwiVkFcIixcIjI0MFwiOlwiVkFcIixcIjI0MVwiOlwiVkFcIixcIjI0MlwiOlwiVkFcIixcIjI0M1wiOlwiVkFcIixcIjI0NFwiOlwiVkFcIixcIjI0NVwiOlwiVkFcIixcIjI0NlwiOlwiV1ZcIixcIjI0N1wiOlwiV1ZcIixcIjI0OFwiOlwiV1ZcIixcIjI0OVwiOlwiV1ZcIixcIjI1MFwiOlwiV1ZcIixcIjI1MVwiOlwiV1ZcIixcIjI1MlwiOlwiV1ZcIixcIjI1M1wiOlwiV1ZcIixcIjI1NFwiOlwiV1ZcIixcIjI1NVwiOlwiV1ZcIixcIjI1NlwiOlwiV1ZcIixcIjI1N1wiOlwiV1ZcIixcIjI1OFwiOlwiV1ZcIixcIjI1OVwiOlwiV1ZcIixcIjI2MFwiOlwiV1ZcIixcIjI2MVwiOlwiV1ZcIixcIjI2MlwiOlwiV1ZcIixcIjI2M1wiOlwiV1ZcIixcIjI2NFwiOlwiV1ZcIixcIjI2NVwiOlwiV1ZcIixcIjI2NlwiOlwiV1ZcIixcIjI2N1wiOlwiV1ZcIixcIjI2OFwiOlwiV1ZcIixcIjI3MFwiOlwiTkNcIixcIjI3MVwiOlwiTkNcIixcIjI3MlwiOlwiTkNcIixcIjI3M1wiOlwiTkNcIixcIjI3NFwiOlwiTkNcIixcIjI3NVwiOlwiTkNcIixcIjI3NlwiOlwiTkNcIixcIjI3N1wiOlwiTkNcIixcIjI3OFwiOlwiTkNcIixcIjI3OVwiOlwiTkNcIixcIjI4MFwiOlwiTkNcIixcIjI4MVwiOlwiTkNcIixcIjI4MlwiOlwiTkNcIixcIjI4M1wiOlwiTkNcIixcIjI4NFwiOlwiTkNcIixcIjI4NVwiOlwiTkNcIixcIjI4NlwiOlwiTkNcIixcIjI4N1wiOlwiTkNcIixcIjI4OFwiOlwiTkNcIixcIjI4OVwiOlwiTkNcIixcIjI5MFwiOlwiU0NcIixcIjI5MVwiOlwiU0NcIixcIjI5MlwiOlwiU0NcIixcIjI5M1wiOlwiU0NcIixcIjI5NFwiOlwiU0NcIixcIjI5NVwiOlwiU0NcIixcIjI5NlwiOlwiU0NcIixcIjI5N1wiOlwiU0NcIixcIjI5OFwiOlwiR0FcIixcIjI5OVwiOlwiR0FcIixcIjMwMFwiOlwiR0FcIixcIjMwMVwiOlwiR0FcIixcIjMwMlwiOlwiR0FcIixcIjMwM1wiOlwiR0FcIixcIjMwNFwiOlwiR0FcIixcIjMwNVwiOlwiR0FcIixcIjMwNlwiOlwiR0FcIixcIjMwN1wiOlwiR0FcIixcIjMwOFwiOlwiR0FcIixcIjMwOVwiOlwiR0FcIixcIjMxMFwiOlwiR0FcIixcIjMxMVwiOlwiR0FcIixcIjMxMlwiOlwiR0FcIixcIjMxM1wiOlwiR0FcIixcIjMxNFwiOlwiR0FcIixcIjMxNVwiOlwiR0FcIixcIjMxNlwiOlwiR0FcIixcIjMxN1wiOlwiR0FcIixcIjMxOFwiOlwiR0FcIixcIjMxOVwiOlwiR0FcIixcIjMyMFwiOlwiRkxcIixcIjMyMVwiOlwiRkxcIixcIjMyMlwiOlwiRkxcIixcIjMyM1wiOlwiRkxcIixcIjMyNFwiOlwiRkxcIixcIjMyNVwiOlwiRkxcIixcIjMyNlwiOlwiRkxcIixcIjMyN1wiOlwiRkxcIixcIjMyOFwiOlwiRkxcIixcIjMyOVwiOlwiRkxcIixcIjMzMFwiOlwiRkxcIixcIjMzMVwiOlwiQUFcIixcIjMzMlwiOlwiRkxcIixcIjMzM1wiOlwiRkxcIixcIjMzNFwiOlwiRkxcIixcIjMzNVwiOlwiRkxcIixcIjMzNlwiOlwiRkxcIixcIjMzN1wiOlwiRkxcIixcIjMzOFwiOlwiRkxcIixcIjMzOVwiOlwiRkxcIixcIjM0MFwiOlwiQVBcIixcIjM0MVwiOlwiRkxcIixcIjM0MlwiOlwiRkxcIixcIjM0NFwiOlwiRkxcIixcIjM0NlwiOlwiRkxcIixcIjM0N1wiOlwiRkxcIixcIjM0OVwiOlwiRkxcIixcIjM1MFwiOlwiQUxcIixcIjM1MVwiOlwiQUxcIixcIjM1MlwiOlwiQUxcIixcIjM1NFwiOlwiQUxcIixcIjM1NVwiOlwiQUxcIixcIjM1NlwiOlwiQUxcIixcIjM1N1wiOlwiQUxcIixcIjM1OFwiOlwiQUxcIixcIjM1OVwiOlwiQUxcIixcIjM2MFwiOlwiQUxcIixcIjM2MVwiOlwiQUxcIixcIjM2MlwiOlwiQUxcIixcIjM2M1wiOlwiQUxcIixcIjM2NFwiOlwiQUxcIixcIjM2NVwiOlwiQUxcIixcIjM2NlwiOlwiQUxcIixcIjM2N1wiOlwiQUxcIixcIjM2OFwiOlwiQUxcIixcIjM2OVwiOlwiTVNcIixcIjM3MFwiOlwiVE5cIixcIjM3MVwiOlwiVE5cIixcIjM3MlwiOlwiVE5cIixcIjM3M1wiOlwiVE5cIixcIjM3NFwiOlwiVE5cIixcIjM3NVwiOlwiVE5cIixcIjM3NlwiOlwiVE5cIixcIjM3N1wiOlwiVE5cIixcIjM3OFwiOlwiVE5cIixcIjM3OVwiOlwiVE5cIixcIjM4MFwiOlwiVE5cIixcIjM4MVwiOlwiVE5cIixcIjM4MlwiOlwiVE5cIixcIjM4M1wiOlwiVE5cIixcIjM4NFwiOlwiVE5cIixcIjM4NVwiOlwiVE5cIixcIjM4NlwiOlwiVE5cIixcIjM4N1wiOlwiTVNcIixcIjM4OFwiOlwiTVNcIixcIjM4OVwiOlwiTVNcIixcIjM5MFwiOlwiTVNcIixcIjM5MVwiOlwiTVNcIixcIjM5MlwiOlwiTVNcIixcIjM5M1wiOlwiTVNcIixcIjM5NFwiOlwiTVNcIixcIjM5NVwiOlwiTVNcIixcIjM5NlwiOlwiTVNcIixcIjM5N1wiOlwiTVNcIixcIjM5OFwiOlwiR0FcIixcIjM5OVwiOlwiR0FcIixcIjQwMFwiOlwiS1lcIixcIjQwMVwiOlwiS1lcIixcIjQwMlwiOlwiS1lcIixcIjQwM1wiOlwiS1lcIixcIjQwNFwiOlwiS1lcIixcIjQwNVwiOlwiS1lcIixcIjQwNlwiOlwiS1lcIixcIjQwN1wiOlwiS1lcIixcIjQwOFwiOlwiS1lcIixcIjQwOVwiOlwiS1lcIixcIjQxMFwiOlwiT0hcIixcIjQxMVwiOlwiS1lcIixcIjQxMlwiOlwiS1lcIixcIjQxM1wiOlwiS1lcIixcIjQxNFwiOlwiS1lcIixcIjQxNVwiOlwiS1lcIixcIjQxNlwiOlwiS1lcIixcIjQxN1wiOlwiS1lcIixcIjQxOFwiOlwiS1lcIixcIjQyMFwiOlwiS1lcIixcIjQyMVwiOlwiS1lcIixcIjQyMlwiOlwiS1lcIixcIjQyM1wiOlwiS1lcIixcIjQyNFwiOlwiSU5cIixcIjQyNVwiOlwiS1lcIixcIjQyNlwiOlwiS1lcIixcIjQyN1wiOlwiS1lcIixcIjQzMFwiOlwiT0hcIixcIjQzMVwiOlwiT0hcIixcIjQzMlwiOlwiT0hcIixcIjQzM1wiOlwiT0hcIixcIjQzNFwiOlwiT0hcIixcIjQzNVwiOlwiT0hcIixcIjQzNlwiOlwiT0hcIixcIjQzN1wiOlwiT0hcIixcIjQzOFwiOlwiT0hcIixcIjQzOVwiOlwiT0hcIixcIjQ0MFwiOlwiT0hcIixcIjQ0MVwiOlwiT0hcIixcIjQ0MlwiOlwiT0hcIixcIjQ0M1wiOlwiT0hcIixcIjQ0NFwiOlwiT0hcIixcIjQ0NVwiOlwiT0hcIixcIjQ0NlwiOlwiT0hcIixcIjQ0N1wiOlwiT0hcIixcIjQ0OFwiOlwiT0hcIixcIjQ0OVwiOlwiT0hcIixcIjQ1MFwiOlwiT0hcIixcIjQ1MVwiOlwiT0hcIixcIjQ1MlwiOlwiT0hcIixcIjQ1M1wiOlwiT0hcIixcIjQ1NFwiOlwiT0hcIixcIjQ1NVwiOlwiT0hcIixcIjQ1NlwiOlwiT0hcIixcIjQ1N1wiOlwiT0hcIixcIjQ1OFwiOlwiT0hcIixcIjQ1OVwiOlwiT0hcIixcIjQ2MFwiOlwiSU5cIixcIjQ2MVwiOlwiSU5cIixcIjQ2MlwiOlwiSU5cIixcIjQ2M1wiOlwiSU5cIixcIjQ2NFwiOlwiSU5cIixcIjQ2NVwiOlwiSU5cIixcIjQ2NlwiOlwiSU5cIixcIjQ2N1wiOlwiSU5cIixcIjQ2OFwiOlwiSU5cIixcIjQ2OVwiOlwiSU5cIixcIjQ3MFwiOlwiSU5cIixcIjQ3MVwiOlwiSU5cIixcIjQ3MlwiOlwiSU5cIixcIjQ3M1wiOlwiSU5cIixcIjQ3NFwiOlwiSU5cIixcIjQ3NVwiOlwiSU5cIixcIjQ3NlwiOlwiSU5cIixcIjQ3N1wiOlwiSU5cIixcIjQ3OFwiOlwiSU5cIixcIjQ3OVwiOlwiSU5cIixcIjQ4MFwiOlwiTUlcIixcIjQ4MVwiOlwiTUlcIixcIjQ4MlwiOlwiTUlcIixcIjQ4M1wiOlwiTUlcIixcIjQ4NFwiOlwiTUlcIixcIjQ4NVwiOlwiTUlcIixcIjQ4NlwiOlwiTUlcIixcIjQ4N1wiOlwiTUlcIixcIjQ4OFwiOlwiTUlcIixcIjQ4OVwiOlwiTUlcIixcIjQ5MFwiOlwiTUlcIixcIjQ5MVwiOlwiTUlcIixcIjQ5MlwiOlwiTUlcIixcIjQ5M1wiOlwiTUlcIixcIjQ5NFwiOlwiTUlcIixcIjQ5NVwiOlwiTUlcIixcIjQ5NlwiOlwiTUlcIixcIjQ5N1wiOlwiTUlcIixcIjQ5OFwiOlwiTUlcIixcIjQ5OVwiOlwiTUlcIixcIjUwMFwiOlwiSUFcIixcIjUwMVwiOlwiSUFcIixcIjUwMlwiOlwiSUFcIixcIjUwM1wiOlwiSUFcIixcIjUwNFwiOlwiSUFcIixcIjUwNVwiOlwiSUFcIixcIjUwNlwiOlwiSUFcIixcIjUwN1wiOlwiSUFcIixcIjUwOFwiOlwiSUFcIixcIjUwOVwiOlwiSUFcIixcIjUxMFwiOlwiSUFcIixcIjUxMVwiOlwiSUFcIixcIjUxMlwiOlwiSUFcIixcIjUxM1wiOlwiSUFcIixcIjUxNFwiOlwiSUFcIixcIjUxNVwiOlwiTkVcIixcIjUxNlwiOlwiTkVcIixcIjUyMFwiOlwiSUFcIixcIjUyMVwiOlwiSUFcIixcIjUyMlwiOlwiSUFcIixcIjUyM1wiOlwiSUFcIixcIjUyNFwiOlwiSUFcIixcIjUyNVwiOlwiSUFcIixcIjUyNlwiOlwiSUFcIixcIjUyN1wiOlwiSUxcIixcIjUyOFwiOlwiSUFcIixcIjUzMFwiOlwiV0lcIixcIjUzMVwiOlwiV0lcIixcIjUzMlwiOlwiV0lcIixcIjUzNFwiOlwiV0lcIixcIjUzNVwiOlwiV0lcIixcIjUzN1wiOlwiV0lcIixcIjUzOFwiOlwiV0lcIixcIjUzOVwiOlwiV0lcIixcIjU0MFwiOlwiTU5cIixcIjU0MVwiOlwiV0lcIixcIjU0MlwiOlwiV0lcIixcIjU0M1wiOlwiV0lcIixcIjU0NFwiOlwiV0lcIixcIjU0NVwiOlwiV0lcIixcIjU0NlwiOlwiV0lcIixcIjU0N1wiOlwiV0lcIixcIjU0OFwiOlwiV0lcIixcIjU0OVwiOlwiV0lcIixcIjU1MFwiOlwiTU5cIixcIjU1MVwiOlwiTU5cIixcIjU1M1wiOlwiTU5cIixcIjU1NFwiOlwiTU5cIixcIjU1NlwiOlwiTU5cIixcIjU1N1wiOlwiTU5cIixcIjU1OFwiOlwiTU5cIixcIjU1OVwiOlwiTU5cIixcIjU2MFwiOlwiTU5cIixcIjU2MVwiOlwiTU5cIixcIjU2MlwiOlwiTU5cIixcIjU2M1wiOlwiTU5cIixcIjU2NFwiOlwiTU5cIixcIjU2NVwiOlwiTU5cIixcIjU2NlwiOlwiTU5cIixcIjU2N1wiOlwiTkRcIixcIjU3MFwiOlwiU0RcIixcIjU3MVwiOlwiU0RcIixcIjU3MlwiOlwiU0RcIixcIjU3M1wiOlwiU0RcIixcIjU3NFwiOlwiU0RcIixcIjU3NVwiOlwiU0RcIixcIjU3NlwiOlwiU0RcIixcIjU3N1wiOlwiU0RcIixcIjU4MFwiOlwiTkRcIixcIjU4MVwiOlwiTkRcIixcIjU4MlwiOlwiTkRcIixcIjU4M1wiOlwiTkRcIixcIjU4NFwiOlwiTkRcIixcIjU4NVwiOlwiTkRcIixcIjU4NlwiOlwiTkRcIixcIjU4N1wiOlwiTkRcIixcIjU4OFwiOlwiTkRcIixcIjU5MFwiOlwiTVRcIixcIjU5MVwiOlwiTVRcIixcIjU5MlwiOlwiTVRcIixcIjU5M1wiOlwiTVRcIixcIjU5NFwiOlwiTVRcIixcIjU5NVwiOlwiTVRcIixcIjU5NlwiOlwiTVRcIixcIjU5N1wiOlwiTVRcIixcIjU5OFwiOlwiTVRcIixcIjU5OVwiOlwiTVRcIixcIjYwMFwiOlwiSUxcIixcIjYwMVwiOlwiSUxcIixcIjYwMlwiOlwiSUxcIixcIjYwM1wiOlwiSUxcIixcIjYwNFwiOlwiSUxcIixcIjYwNVwiOlwiSUxcIixcIjYwNlwiOlwiSUxcIixcIjYwN1wiOlwiSUxcIixcIjYwOFwiOlwiSUxcIixcIjYwOVwiOlwiSUxcIixcIjYxMFwiOlwiSUxcIixcIjYxMVwiOlwiSUxcIixcIjYxMlwiOlwiSUxcIixcIjYxM1wiOlwiSUxcIixcIjYxNFwiOlwiSUxcIixcIjYxNVwiOlwiSUxcIixcIjYxNlwiOlwiSUxcIixcIjYxN1wiOlwiSUxcIixcIjYxOFwiOlwiSUxcIixcIjYxOVwiOlwiSUxcIixcIjYyMFwiOlwiTU9cIixcIjYyMlwiOlwiTU9cIixcIjYyM1wiOlwiSUxcIixcIjYyNFwiOlwiSUxcIixcIjYyNVwiOlwiSUxcIixcIjYyNlwiOlwiSUxcIixcIjYyN1wiOlwiSUxcIixcIjYyOFwiOlwiSUxcIixcIjYyOVwiOlwiSUxcIixcIjYzMFwiOlwiTU9cIixcIjYzMVwiOlwiTU9cIixcIjYzM1wiOlwiTU9cIixcIjYzNFwiOlwiTU9cIixcIjYzNVwiOlwiTU9cIixcIjYzNlwiOlwiTU9cIixcIjYzN1wiOlwiTU9cIixcIjYzOFwiOlwiTU9cIixcIjYzOVwiOlwiTU9cIixcIjY0MFwiOlwiTU9cIixcIjY0MVwiOlwiTU9cIixcIjY0NFwiOlwiTU9cIixcIjY0NVwiOlwiTU9cIixcIjY0NlwiOlwiTU9cIixcIjY0N1wiOlwiTU9cIixcIjY0OFwiOlwiTU9cIixcIjY0OVwiOlwiTU9cIixcIjY1MFwiOlwiTU9cIixcIjY1MVwiOlwiTU9cIixcIjY1MlwiOlwiTU9cIixcIjY1M1wiOlwiTU9cIixcIjY1NFwiOlwiTU9cIixcIjY1NVwiOlwiTU9cIixcIjY1NlwiOlwiTU9cIixcIjY1N1wiOlwiTU9cIixcIjY1OFwiOlwiTU9cIixcIjY2MFwiOlwiS1NcIixcIjY2MVwiOlwiS1NcIixcIjY2MlwiOlwiS1NcIixcIjY2NFwiOlwiS1NcIixcIjY2NVwiOlwiS1NcIixcIjY2NlwiOlwiS1NcIixcIjY2N1wiOlwiS1NcIixcIjY2OFwiOlwiS1NcIixcIjY2OVwiOlwiS1NcIixcIjY3MFwiOlwiS1NcIixcIjY3MVwiOlwiS1NcIixcIjY3MlwiOlwiS1NcIixcIjY3M1wiOlwiS1NcIixcIjY3NFwiOlwiS1NcIixcIjY3NVwiOlwiS1NcIixcIjY3NlwiOlwiS1NcIixcIjY3N1wiOlwiS1NcIixcIjY3OFwiOlwiS1NcIixcIjY3OVwiOlwiS1NcIixcIjY4MFwiOlwiTkVcIixcIjY4MVwiOlwiTkVcIixcIjY4M1wiOlwiTkVcIixcIjY4NFwiOlwiTkVcIixcIjY4NVwiOlwiTkVcIixcIjY4NlwiOlwiTkVcIixcIjY4N1wiOlwiTkVcIixcIjY4OFwiOlwiTkVcIixcIjY4OVwiOlwiTkVcIixcIjY5MFwiOlwiTkVcIixcIjY5MVwiOlwiTkVcIixcIjY5MlwiOlwiTkVcIixcIjY5M1wiOlwiTkVcIixcIjcwMFwiOlwiTEFcIixcIjcwMVwiOlwiTEFcIixcIjcwM1wiOlwiTEFcIixcIjcwNFwiOlwiTEFcIixcIjcwNVwiOlwiTEFcIixcIjcwNlwiOlwiTEFcIixcIjcwN1wiOlwiTEFcIixcIjcwOFwiOlwiTEFcIixcIjcxMFwiOlwiTEFcIixcIjcxMVwiOlwiTEFcIixcIjcxMlwiOlwiTEFcIixcIjcxM1wiOlwiTEFcIixcIjcxNFwiOlwiTEFcIixcIjcxNlwiOlwiQVJcIixcIjcxN1wiOlwiQVJcIixcIjcxOFwiOlwiQVJcIixcIjcxOVwiOlwiQVJcIixcIjcyMFwiOlwiQVJcIixcIjcyMVwiOlwiQVJcIixcIjcyMlwiOlwiQVJcIixcIjcyM1wiOlwiQVJcIixcIjcyNFwiOlwiQVJcIixcIjcyNVwiOlwiQVJcIixcIjcyNlwiOlwiQVJcIixcIjcyN1wiOlwiQVJcIixcIjcyOFwiOlwiQVJcIixcIjcyOVwiOlwiQVJcIixcIjczMFwiOlwiT0tcIixcIjczMVwiOlwiT0tcIixcIjczM1wiOlwiVFhcIixcIjczNFwiOlwiT0tcIixcIjczNVwiOlwiT0tcIixcIjczNlwiOlwiT0tcIixcIjczN1wiOlwiT0tcIixcIjczOFwiOlwiT0tcIixcIjczOVwiOlwiVFhcIixcIjc0MFwiOlwiT0tcIixcIjc0MVwiOlwiT0tcIixcIjc0M1wiOlwiT0tcIixcIjc0NFwiOlwiT0tcIixcIjc0NVwiOlwiT0tcIixcIjc0NlwiOlwiT0tcIixcIjc0N1wiOlwiT0tcIixcIjc0OFwiOlwiT0tcIixcIjc0OVwiOlwiT0tcIixcIjc1MFwiOlwiVFhcIixcIjc1MVwiOlwiVFhcIixcIjc1MlwiOlwiVFhcIixcIjc1M1wiOlwiVFhcIixcIjc1NFwiOlwiVFhcIixcIjc1NVwiOlwiVFhcIixcIjc1NlwiOlwiVFhcIixcIjc1N1wiOlwiVFhcIixcIjc1OFwiOlwiVFhcIixcIjc1OVwiOlwiVFhcIixcIjc2MFwiOlwiVFhcIixcIjc2MVwiOlwiVFhcIixcIjc2MlwiOlwiVFhcIixcIjc2M1wiOlwiVFhcIixcIjc2NFwiOlwiVFhcIixcIjc2NVwiOlwiVFhcIixcIjc2NlwiOlwiVFhcIixcIjc2N1wiOlwiVFhcIixcIjc2OFwiOlwiVFhcIixcIjc2OVwiOlwiVFhcIixcIjc3MFwiOlwiVFhcIixcIjc3MVwiOlwiVFhcIixcIjc3MlwiOlwiVFhcIixcIjc3M1wiOlwiVFhcIixcIjc3NFwiOlwiVFhcIixcIjc3NVwiOlwiVFhcIixcIjc3NlwiOlwiVFhcIixcIjc3N1wiOlwiVFhcIixcIjc3OFwiOlwiVFhcIixcIjc3OVwiOlwiVFhcIixcIjc4MFwiOlwiVFhcIixcIjc4MVwiOlwiVFhcIixcIjc4MlwiOlwiVFhcIixcIjc4M1wiOlwiVFhcIixcIjc4NFwiOlwiVFhcIixcIjc4NVwiOlwiVFhcIixcIjc4NlwiOlwiVFhcIixcIjc4N1wiOlwiVFhcIixcIjc4OFwiOlwiVFhcIixcIjc4OVwiOlwiVFhcIixcIjc5MFwiOlwiVFhcIixcIjc5MVwiOlwiVFhcIixcIjc5MlwiOlwiVFhcIixcIjc5M1wiOlwiVFhcIixcIjc5NFwiOlwiVFhcIixcIjc5NVwiOlwiVFhcIixcIjc5NlwiOlwiVFhcIixcIjc5N1wiOlwiVFhcIixcIjc5OFwiOlwiVFhcIixcIjc5OVwiOlwiVFhcIixcIjgwMFwiOlwiQ09cIixcIjgwMVwiOlwiQ09cIixcIjgwMlwiOlwiQ09cIixcIjgwM1wiOlwiQ09cIixcIjgwNFwiOlwiQ09cIixcIjgwNVwiOlwiQ09cIixcIjgwNlwiOlwiQ09cIixcIjgwN1wiOlwiQ09cIixcIjgwOFwiOlwiQ09cIixcIjgwOVwiOlwiQ09cIixcIjgxMFwiOlwiQ09cIixcIjgxMVwiOlwiQ09cIixcIjgxMlwiOlwiQ09cIixcIjgxM1wiOlwiQ09cIixcIjgxNFwiOlwiQ09cIixcIjgxNVwiOlwiQ09cIixcIjgxNlwiOlwiQ09cIixcIjgyMFwiOlwiV1lcIixcIjgyMVwiOlwiV1lcIixcIjgyMlwiOlwiV1lcIixcIjgyM1wiOlwiV1lcIixcIjgyNFwiOlwiV1lcIixcIjgyNVwiOlwiV1lcIixcIjgyNlwiOlwiV1lcIixcIjgyN1wiOlwiV1lcIixcIjgyOFwiOlwiV1lcIixcIjgyOVwiOlwiV1lcIixcIjgzMFwiOlwiV1lcIixcIjgzMVwiOlwiV1lcIixcIjgzMlwiOlwiSURcIixcIjgzM1wiOlwiSURcIixcIjgzNFwiOlwiSURcIixcIjgzNVwiOlwiSURcIixcIjgzNlwiOlwiSURcIixcIjgzN1wiOlwiSURcIixcIjgzOFwiOlwiV0FcIixcIjg0MFwiOlwiVVRcIixcIjg0MVwiOlwiVVRcIixcIjg0MlwiOlwiVVRcIixcIjg0M1wiOlwiVVRcIixcIjg0NFwiOlwiVVRcIixcIjg0NVwiOlwiVVRcIixcIjg0NlwiOlwiVVRcIixcIjg0N1wiOlwiVVRcIixcIjg1MFwiOlwiQVpcIixcIjg1MVwiOlwiQVpcIixcIjg1MlwiOlwiQVpcIixcIjg1M1wiOlwiQVpcIixcIjg1NVwiOlwiQVpcIixcIjg1NlwiOlwiQVpcIixcIjg1N1wiOlwiQVpcIixcIjg1OVwiOlwiQVpcIixcIjg2MFwiOlwiQVpcIixcIjg2M1wiOlwiQVpcIixcIjg2NFwiOlwiQVpcIixcIjg2NVwiOlwiQVpcIixcIjg3MFwiOlwiTk1cIixcIjg3MVwiOlwiTk1cIixcIjg3MlwiOlwiTk1cIixcIjg3M1wiOlwiTk1cIixcIjg3NFwiOlwiTk1cIixcIjg3NVwiOlwiTk1cIixcIjg3N1wiOlwiTlZcIixcIjg3OFwiOlwiTk1cIixcIjg3OVwiOlwiTk1cIixcIjg4MFwiOlwiTk1cIixcIjg4MVwiOlwiTk1cIixcIjg4MlwiOlwiTk1cIixcIjg4M1wiOlwiTk1cIixcIjg4NFwiOlwiTk1cIixcIjg4NVwiOlwiVFhcIixcIjg4OVwiOlwiTlZcIixcIjg5MFwiOlwiTlZcIixcIjg5MVwiOlwiTlZcIixcIjg5M1wiOlwiTlZcIixcIjg5NFwiOlwiTlZcIixcIjg5NVwiOlwiTlZcIixcIjg5N1wiOlwiTlZcIixcIjg5OFwiOlwiTlZcIixcIjkwMFwiOlwiQ0FcIixcIjkwMVwiOlwiQ0FcIixcIjkwMlwiOlwiQ0FcIixcIjkwM1wiOlwiQ0FcIixcIjkwNFwiOlwiQ0FcIixcIjkwNVwiOlwiQ0FcIixcIjkwNlwiOlwiQ0FcIixcIjkwN1wiOlwiQ0FcIixcIjkwOFwiOlwiQ0FcIixcIjkxMFwiOlwiQ0FcIixcIjkxMVwiOlwiQ0FcIixcIjkxMlwiOlwiQ0FcIixcIjkxM1wiOlwiQ0FcIixcIjkxNFwiOlwiQ0FcIixcIjkxNVwiOlwiQ0FcIixcIjkxNlwiOlwiQ0FcIixcIjkxN1wiOlwiQ0FcIixcIjkxOFwiOlwiQ0FcIixcIjkxOVwiOlwiQ0FcIixcIjkyMFwiOlwiQ0FcIixcIjkyMVwiOlwiQ0FcIixcIjkyMlwiOlwiQ0FcIixcIjkyM1wiOlwiQ0FcIixcIjkyNFwiOlwiQ0FcIixcIjkyNVwiOlwiQ0FcIixcIjkyNlwiOlwiQ0FcIixcIjkyN1wiOlwiQ0FcIixcIjkyOFwiOlwiQ0FcIixcIjkzMFwiOlwiQ0FcIixcIjkzMVwiOlwiQ0FcIixcIjkzMlwiOlwiQ0FcIixcIjkzM1wiOlwiQ0FcIixcIjkzNFwiOlwiQ0FcIixcIjkzNVwiOlwiQ0FcIixcIjkzNlwiOlwiQ0FcIixcIjkzN1wiOlwiQ0FcIixcIjkzOFwiOlwiQ0FcIixcIjkzOVwiOlwiQ0FcIixcIjk0MFwiOlwiQ0FcIixcIjk0MVwiOlwiQ0FcIixcIjk0MlwiOlwiQ0FcIixcIjk0M1wiOlwiQ0FcIixcIjk0NFwiOlwiQ0FcIixcIjk0NVwiOlwiQ0FcIixcIjk0NlwiOlwiQ0FcIixcIjk0N1wiOlwiQ0FcIixcIjk0OFwiOlwiQ0FcIixcIjk0OVwiOlwiQ0FcIixcIjk1MFwiOlwiQ0FcIixcIjk1MVwiOlwiQ0FcIixcIjk1MlwiOlwiQ0FcIixcIjk1M1wiOlwiQ0FcIixcIjk1NFwiOlwiQ0FcIixcIjk1NVwiOlwiQ0FcIixcIjk1NlwiOlwiQ0FcIixcIjk1N1wiOlwiQ0FcIixcIjk1OFwiOlwiQ0FcIixcIjk1OVwiOlwiQ0FcIixcIjk2MFwiOlwiQ0FcIixcIjk2MVwiOlwiQ0FcIixcIjk2MlwiOlwiQVBcIixcIjk2M1wiOlwiQVBcIixcIjk2NFwiOlwiQVBcIixcIjk2NVwiOlwiQVBcIixcIjk2NlwiOlwiQVBcIixcIjk2N1wiOlwiQVNcIixcIjk2OFwiOlwiSElcIixcIjk2OVwiOlwiTUhcIixcIjk3MFwiOlwiT1JcIixcIjk3MVwiOlwiT1JcIixcIjk3MlwiOlwiT1JcIixcIjk3M1wiOlwiT1JcIixcIjk3NFwiOlwiT1JcIixcIjk3NVwiOlwiT1JcIixcIjk3NlwiOlwiT1JcIixcIjk3N1wiOlwiT1JcIixcIjk3OFwiOlwiT1JcIixcIjk3OVwiOlwiT1JcIixcIjk4MFwiOlwiV0FcIixcIjk4MVwiOlwiV0FcIixcIjk4MlwiOlwiV0FcIixcIjk4M1wiOlwiV0FcIixcIjk4NFwiOlwiV0FcIixcIjk4NVwiOlwiV0FcIixcIjk4NlwiOlwiT1JcIixcIjk4OFwiOlwiV0FcIixcIjk4OVwiOlwiV0FcIixcIjk5MFwiOlwiV0FcIixcIjk5MVwiOlwiV0FcIixcIjk5MlwiOlwiV0FcIixcIjk5M1wiOlwiV0FcIixcIjk5NFwiOlwiV0FcIixcIjk5NVwiOlwiQUtcIixcIjk5NlwiOlwiQUtcIixcIjk5N1wiOlwiQUtcIixcIjk5OFwiOlwiQUtcIixcIjk5OVwiOlwiQUtcIixcIjAwNVwiOlwiTllcIixcIjA2M1wiOlwiQ1RcIixcIjAwNlwiOlwiVklcIixcIjAwN1wiOlwiVklcIixcIjAwOFwiOlwiVklcIixcIjAwOVwiOlwiVklcIixcIjAxMFwiOlwiTUFcIixcIjAxMVwiOlwiTUFcIixcIjAxMlwiOlwiTUFcIixcIjAxM1wiOlwiTUFcIixcIjAxNFwiOlwiTUFcIixcIjAxNVwiOlwiTUFcIixcIjAxNlwiOlwiTUFcIixcIjAxN1wiOlwiTUFcIixcIjAxOFwiOlwiTUFcIixcIjAxOVwiOlwiTUFcIixcIjAyMFwiOlwiTUFcIixcIjAyMVwiOlwiTUFcIixcIjAyMlwiOlwiTUFcIixcIjAyM1wiOlwiTUFcIixcIjAyNFwiOlwiTUFcIixcIjAyNVwiOlwiTUFcIixcIjAyNlwiOlwiTUFcIixcIjAyN1wiOlwiTUFcIixcIjA1NVwiOlwiTUFcIixcIjAyOFwiOlwiUklcIixcIjAyOVwiOlwiUklcIixcIjAzMFwiOlwiTkhcIixcIjAzMVwiOlwiTkhcIixcIjAzMlwiOlwiTkhcIixcIjAzM1wiOlwiTkhcIixcIjAzNFwiOlwiTkhcIixcIjAzNVwiOlwiVlRcIixcIjAzNlwiOlwiVlRcIixcIjAzN1wiOlwiVlRcIixcIjAzOFwiOlwiTkhcIixcIjAzOVwiOlwiTUVcIixcIjA1MFwiOlwiVlRcIixcIjA1MVwiOlwiVlRcIixcIjA1MlwiOlwiVlRcIixcIjA1M1wiOlwiVlRcIixcIjA1NFwiOlwiVlRcIixcIjA1NlwiOlwiVlRcIixcIjA1N1wiOlwiVlRcIixcIjA1OFwiOlwiVlRcIixcIjA1OVwiOlwiVlRcIixcIjA0MFwiOlwiTUVcIixcIjA0MVwiOlwiTUVcIixcIjA0MlwiOlwiTUVcIixcIjA0M1wiOlwiTUVcIixcIjA0NFwiOlwiTUVcIixcIjA0NVwiOlwiTUVcIixcIjA0NlwiOlwiTUVcIixcIjA0N1wiOlwiTUVcIixcIjA0OFwiOlwiTUVcIixcIjA0OVwiOlwiTUVcIixcIjA2MFwiOlwiQ1RcIixcIjA2MVwiOlwiQ1RcIixcIjA2MlwiOlwiQ1RcIixcIjA2NFwiOlwiQ1RcIixcIjA2NVwiOlwiQ1RcIixcIjA2NlwiOlwiQ1RcIixcIjA2N1wiOlwiQ1RcIixcIjA2OFwiOlwiQ1RcIixcIjA2OVwiOlwiQ1RcIixcIjA3MFwiOlwiTkpcIixcIjA3MVwiOlwiTkpcIixcIjA3MlwiOlwiTkpcIixcIjA3M1wiOlwiTkpcIixcIjA3NFwiOlwiTkpcIixcIjA3NVwiOlwiTkpcIixcIjA3NlwiOlwiTkpcIixcIjA3N1wiOlwiTkpcIixcIjA3OFwiOlwiTkpcIixcIjA3OVwiOlwiTkpcIixcIjA4MFwiOlwiTkpcIixcIjA4MVwiOlwiTkpcIixcIjA4MlwiOlwiTkpcIixcIjA4M1wiOlwiTkpcIixcIjA4NFwiOlwiTkpcIixcIjA4NVwiOlwiTkpcIixcIjA4NlwiOlwiTkpcIixcIjA4N1wiOlwiTkpcIixcIjA4OFwiOlwiTkpcIixcIjA4OVwiOlwiTkpcIixcIjA5MFwiOlwiQUVcIixcIjA5MVwiOlwiQUVcIixcIjA5MlwiOlwiQUVcIixcIjA5M1wiOlwiQUVcIixcIjA5NFwiOlwiQUVcIixcIjA5NVwiOlwiQUVcIixcIjA5NlwiOlwiQUVcIixcIjA5N1wiOlwiQUVcIixcIjA5OFwiOlwiQUVcIixcIjA5OVwiOlwiQUVcIn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuVmVyaWZ5QWRkcmVzcyA9IHZlcmlmeUFkZHJlc3M7XG5leHBvcnRzLkF1dG9jb21wbGV0ZUFkZHJlc3MgPSBhdXRvY29tcGxldGVBZGRyZXNzO1xuZXhwb3J0cy5TZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2cgPSBzZXRBZGRyZXNzRnJvbUFkZHJlc3NWZXJpZmljYXRpb25EaWFsb2c7XG5leHBvcnRzLkJ1aWxkQWRkcmVzc09iamVjdEZyb21DaGVja291dEZvcm0gPSBidWlsZEFkZHJlc3NPYmplY3RGcm9tQ2hlY2tvdXRGb3JtO1xuZXhwb3J0cy5CdWlsZEFkZHJlc3NPYmplY3RGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZVN1Z2dlc3Rpb24gPSBidWlsZEFkZHJlc3NPYmplY3RGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZVN1Z2dlc3Rpb247XG5leHBvcnRzLkJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzVmVyaWZ5UmVzcG9uc2UgPSBidWlsZEFkZHJlc3NPYmplY3RGcm9tQWRkcmVzc1ZlcmlmeVJlc3BvbnNlO1xuZXhwb3J0cy5Db21wYXJlQWRkcmVzc09iamVjdHMgPSBjb21wYXJlQWRkcmVzc09iamVjdHM7XG5cbnZhciBkYXRhQnVmZmVyID0ge307XG5cbmZ1bmN0aW9uIHZlcmlmeUFkZHJlc3MoJGZvcm0sIG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdHZhciBhZGRyZXNzVmVyaWZpY2F0aW9uUGF5bG9hZCA9IHtcblx0XHRcdHByaW1hcnlfbGluZTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczFcIl0nKS52YWwoKSB8fCAnJyxcblx0XHRcdHNlY29uZGFyeV9saW5lOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0Y2l0eTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0c3RhdGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0emlwX2NvZGU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwicG9zdGFsXCJdJykudmFsKCkgfHwgJydcblx0XHR9O1xuXHRcdGFkZHJlc3NWZXJpZmljYXRpb25QYXlsb2FkW29wdGlvbnMuQ1NSRlRva2VuLk5hbWVdID0gb3B0aW9ucy5DU1JGVG9rZW4uVG9rZW47XG5cblx0XHQkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuTG9iLkFkZHJlc3NWZXJpZnksXG5cdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoYWRkcmVzc1ZlcmlmaWNhdGlvblBheWxvYWQpLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0aWYgKCFkYXRhIHx8ICFkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQpIHtcblx0XHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGEuU3RhdHVzID0gJ2RlbGl2ZXJhYmxlJztcblx0XHRcdFx0XHRkYXRhLk1hdGNoID0gdHJ1ZTtcblx0XHRcdFx0XHRpZiAoZGF0YS5JbnF1aXJ5UmVzdWx0KSB7XG5cdFx0XHRcdFx0XHRkYXRhLkFkZHJlc3NPcmlnaW5hbCA9IGJ1aWxkQWRkcmVzc09iamVjdEZyb21DaGVja291dEZvcm0oJGZvcm0pO1xuXHRcdFx0XHRcdFx0ZGF0YS5BZGRyZXNzVmVyaWZpZWQgPSBidWlsZEFkZHJlc3NPYmplY3RGcm9tQWRkcmVzc1ZlcmlmeVJlc3BvbnNlKGRhdGEpO1xuXHRcdFx0XHRcdFx0ZGF0YS5BZGRyZXNzQ29tcGFyaXNvbiA9IGNvbXBhcmVBZGRyZXNzT2JqZWN0cyhkYXRhLkFkZHJlc3NPcmlnaW5hbCwgZGF0YS5BZGRyZXNzVmVyaWZpZWQpO1xuXHRcdFx0XHRcdFx0ZGF0YS5NYXRjaCA9IGRhdGEuQWRkcmVzc0NvbXBhcmlzb24uTWF0Y2g7XG5cdFx0XHRcdFx0XHRkYXRhLlN0YXR1cyA9IGRhdGEuSW5xdWlyeVJlc3VsdC5kZWxpdmVyYWJpbGl0eTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZGF0YS5TdGF0dXMgPT0gJ2RlbGl2ZXJhYmxlJyAmJiBkYXRhLk1hdGNoKSB7XG5cdFx0XHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRyZWplY3QoZGF0YSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0cmVzb2x2ZShkYXRhKTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBhdXRvY29tcGxldGVBZGRyZXNzKCRmb3JtLCAkZmllbGQsIG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdHZhciBhZGRyZXNzQXV0b2NvbXBsZXRlUGF5bG9hZCA9IHtcblx0XHRcdGFkZHJlc3NfcHJlZml4OiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0Y2l0eTogJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0c3RhdGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZVwiXScpLnZhbCgpIHx8ICcnLFxuXHRcdFx0emlwX2NvZGU6ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwicG9zdGFsXCJdJykudmFsKCkgfHwgJydcblx0XHR9O1xuXHRcdGFkZHJlc3NBdXRvY29tcGxldGVQYXlsb2FkW29wdGlvbnMuQ1NSRlRva2VuLk5hbWVdID0gb3B0aW9ucy5DU1JGVG9rZW4uVG9rZW47XG5cblx0XHRpZiAoZGF0YUJ1ZmZlciAmJiBkYXRhQnVmZmVyWydBdXRvY29tcGxldGVBZGRyZXNzQWpheCddICYmIGRhdGFCdWZmZXJbJ0F1dG9jb21wbGV0ZUFkZHJlc3NBamF4J10ucmVhZHlTdGF0ZSAhPT0gNCkge1xuXHRcdFx0ZGF0YUJ1ZmZlclsnQXV0b2NvbXBsZXRlQWRkcmVzc0FqYXgnXS5hYm9ydCgpO1xuXHRcdH1cblxuXHRcdGRhdGFCdWZmZXJbJ0F1dG9jb21wbGV0ZUFkZHJlc3NBamF4J10gPSAkLmFqYXgoe1xuXHRcdFx0bWV0aG9kOiAnUE9TVCcsXG5cdFx0XHR1cmw6IFVybHMuTG9iLkFkZHJlc3NBdXRvY29tcGxldGUsXG5cdFx0XHRjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRcdFx0ZGF0YTogSlNPTi5zdHJpbmdpZnkoYWRkcmVzc0F1dG9jb21wbGV0ZVBheWxvYWQpLFxuXHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0aWYgKCFkYXRhIHx8ICFkYXRhLlNlcnZpY2VTdWNjZXNzZnVsbHlDYWxsZWQpIHtcblx0XHRcdFx0XHRyZXNvbHZlKGRhdGEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGEuJGZvcm0gPSAkZm9ybTtcblx0XHRcdFx0XHRkYXRhLiRmaWVsZCA9ICRmaWVsZDtcblxuXHRcdFx0XHRcdHJlc29sdmUoZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gc2V0QWRkcmVzc0Zyb21BZGRyZXNzVmVyaWZpY2F0aW9uRGlhbG9nKCRmb3JtLCBhZGRyZXNzRGF0YSkge1xuXHRpZiAoYWRkcmVzc0RhdGEuRmlyc3ROYW1lKSB7XG5cdFx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykudmFsKGFkZHJlc3NEYXRhLkZpcnN0TmFtZSk7XG5cdH1cblx0aWYgKGFkZHJlc3NEYXRhLkxhc3ROYW1lKSB7XG5cdFx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoYWRkcmVzc0RhdGEuTGFzdE5hbWUpO1xuXHR9XG5cdCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKGFkZHJlc3NEYXRhLlByaW1hcnlMaW5lKTtcblx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoYWRkcmVzc0RhdGEuU2Vjb25kYXJ5TGluZSk7XG5cdCRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoYWRkcmVzc0RhdGEuQ2l0eSk7XG5cdCRmb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZVwiXScpLnZhbChhZGRyZXNzRGF0YS5TdGF0ZUNvZGUpO1xuXHQkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoYWRkcmVzc0RhdGEuUG9zdGFsQ29kZSk7XG5cdGlmIChhZGRyZXNzRGF0YS5Db3VudHJ5Q29kZSkge1xuXHRcdCRmb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9jb3VudHJ5Q29kZVwiXScpLnZhbChhZGRyZXNzRGF0YS5Db3VudHJ5Q29kZSk7XG5cdH1cblx0aWYgKGFkZHJlc3NEYXRhLlBob25lKSB7XG5cdFx0JGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJwaG9uZVwiXScpLnZhbChhZGRyZXNzRGF0YS5QaG9uZSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gYnVpbGRBZGRyZXNzT2JqZWN0RnJvbUNoZWNrb3V0Rm9ybSgkZm9ybSkge1xuXHR2YXIgYWRkcmVzc09iamVjdCA9IHt9O1xuXHRcblx0YWRkcmVzc09iamVjdC5QcmltYXJ5TGluZSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCk7XG5cdGFkZHJlc3NPYmplY3QuU2Vjb25kYXJ5TGluZSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCk7XG5cdGFkZHJlc3NPYmplY3QuQ2l0eSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2NpdHlcIl0nKS52YWwoKTtcblx0YWRkcmVzc09iamVjdC5TdGF0ZUNvZGUgPSAkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX3N0YXRlXCJdJykudmFsKCk7XG5cdGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgpO1xuXG5cdHJldHVybiBhZGRyZXNzT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBidWlsZEFkZHJlc3NPYmplY3RGcm9tQWRkcmVzc0F1dG9jb21wbGV0ZVN1Z2dlc3Rpb24oZGF0YSkge1xuXHR2YXIgYWRkcmVzc09iamVjdCA9IHt9O1xuXG5cdGlmIChkYXRhKSB7XG5cdFx0YWRkcmVzc09iamVjdC5QcmltYXJ5TGluZSA9IGRhdGEucHJpbWFyeV9saW5lIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuU2Vjb25kYXJ5TGluZSA9IGRhdGEuc2Vjb25kYXJ5X2xpbmUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5TdGF0ZUNvZGUgPSBkYXRhLnN0YXRlIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSA9IGRhdGEuemlwX2NvZGUgfHwgJyc7XG5cdFx0YWRkcmVzc09iamVjdC5DaXR5ID0gZGF0YS5jaXR5IHx8ICcnO1xuXHR9XG5cblx0cmV0dXJuIGFkZHJlc3NPYmplY3Q7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWRkcmVzc09iamVjdEZyb21BZGRyZXNzVmVyaWZ5UmVzcG9uc2UoZGF0YSkge1xuXHR2YXIgYWRkcmVzc09iamVjdCA9IHt9O1xuXG5cdGlmIChkYXRhICYmIGRhdGEuSW5xdWlyeVJlc3VsdCkge1xuXHRcdGFkZHJlc3NPYmplY3QuUHJpbWFyeUxpbmUgPSBkYXRhLklucXVpcnlSZXN1bHQucHJpbWFyeV9saW5lIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuU2Vjb25kYXJ5TGluZSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5zZWNvbmRhcnlfbGluZSB8fCAnJztcblx0XHRhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5jb21wb25lbnRzLnN0YXRlIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuUG9zdGFsQ29kZSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5jb21wb25lbnRzLnppcF9jb2RlIHx8ICcnO1xuXHRcdGFkZHJlc3NPYmplY3QuQ2l0eSA9IGRhdGEuSW5xdWlyeVJlc3VsdC5jb21wb25lbnRzLmNpdHkgfHwgJyc7XG5cdH1cblxuXHRyZXR1cm4gYWRkcmVzc09iamVjdDtcbn1cblxuZnVuY3Rpb24gY29tcGFyZUFkZHJlc3NPYmplY3RzKGFkZHJlc3NPcmlnaW5hbCwgYWRkcmVzc1ZlcmlmaWVkKSB7XG5cdHZhciBhZGRyZXNzT2JqZWN0ID0ge307XG5cblx0aWYgKGFkZHJlc3NPcmlnaW5hbCAmJiBhZGRyZXNzVmVyaWZpZWQpIHtcblx0XHRhZGRyZXNzT2JqZWN0LlByaW1hcnlMaW5lID0gY29tcGFyZUFkZHJlc3NFbGVtZW50KGFkZHJlc3NPcmlnaW5hbC5QcmltYXJ5TGluZSwgYWRkcmVzc1ZlcmlmaWVkLlByaW1hcnlMaW5lKTtcblx0XHRhZGRyZXNzT2JqZWN0LlNlY29uZGFyeUxpbmUgPSBjb21wYXJlQWRkcmVzc0VsZW1lbnQoYWRkcmVzc09yaWdpbmFsLlNlY29uZGFyeUxpbmUsIGFkZHJlc3NWZXJpZmllZC5TZWNvbmRhcnlMaW5lKTtcblx0XHRhZGRyZXNzT2JqZWN0LlN0YXRlQ29kZSA9IGNvbXBhcmVBZGRyZXNzRWxlbWVudChhZGRyZXNzT3JpZ2luYWwuU3RhdGVDb2RlLCBhZGRyZXNzVmVyaWZpZWQuU3RhdGVDb2RlKTtcblx0XHRhZGRyZXNzT2JqZWN0LlBvc3RhbENvZGUgPSBjb21wYXJlQWRkcmVzc0VsZW1lbnQoYWRkcmVzc09yaWdpbmFsLlBvc3RhbENvZGUsIGFkZHJlc3NWZXJpZmllZC5Qb3N0YWxDb2RlKTtcblx0XHRhZGRyZXNzT2JqZWN0LkNpdHkgPSBjb21wYXJlQWRkcmVzc0VsZW1lbnQoYWRkcmVzc09yaWdpbmFsLkNpdHksIGFkZHJlc3NWZXJpZmllZC5DaXR5KTtcblx0fVxuXG5cdHZhciBmaWVsZHNEaWZmZXJlbnQgPSBbXTtcblx0Zm9yICh2YXIgYWRkcmVzc0VsZW1lbnQgaW4gYWRkcmVzc09iamVjdCkge1xuXHRcdGlmICghYWRkcmVzc09iamVjdFthZGRyZXNzRWxlbWVudF0pIHtcblx0XHRcdGZpZWxkc0RpZmZlcmVudFtmaWVsZHNEaWZmZXJlbnQubGVuZ3RoXSA9IGFkZHJlc3NFbGVtZW50O1xuXHRcdH1cblx0fVxuXHRhZGRyZXNzT2JqZWN0LkZpZWxkc0RpZmZlcmVudCA9IGZpZWxkc0RpZmZlcmVudDtcblx0YWRkcmVzc09iamVjdC5NYXRjaCA9IGZpZWxkc0RpZmZlcmVudC5sZW5ndGggPT0gMDtcblxuXHRyZXR1cm4gYWRkcmVzc09iamVjdDtcbn1cblxuZnVuY3Rpb24gY29tcGFyZUFkZHJlc3NFbGVtZW50KGFkZHJlc3NFbGVtZW50T3JpZ2luYWwsIGFkZHJlc3NFbGVtZW50VmVyaWZpZWQpIHtcblx0YWRkcmVzc0VsZW1lbnRPcmlnaW5hbCA9IGFkZHJlc3NFbGVtZW50T3JpZ2luYWwgfHwgJyc7XG5cdGFkZHJlc3NFbGVtZW50VmVyaWZpZWQgPSBhZGRyZXNzRWxlbWVudFZlcmlmaWVkIHx8ICcnO1xuXG5cdHJldHVybiBhZGRyZXNzRWxlbWVudE9yaWdpbmFsLnRyaW0oKS50b0xvd2VyQ2FzZSgpID09IGFkZHJlc3NFbGVtZW50VmVyaWZpZWQudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlJlc3BvbnNlQ29kZXMgPSB7XG5cdEFscmVhZHlJbkJhc2tldDogJ0FMUkVBRFlfSU5fQkFTS0VUJ1xufVxuXG5leHBvcnRzLlVzZXIgPSB7XG5cdFNlbGVjdGVkQ3VzdG9tZXJTaGlwcGluZ01ldGhvZDogJ3NlbGVjdGVkQ3VzdG9tZXJTaGlwcGluZ01ldGhvZCcsXG5cdFNlbGVjdGVkU3RvcmVTaGlwcGluZ01ldGhvZDogJ3NlbGVjdGVkU3RvcmVTaGlwcGluZ01ldGhvZCdcbn1cblxuZXhwb3J0cy5TaGlwcGluZ01ldGhvZHMgPSB7XG5cdEJvcGlzOiAnQm9waXMnLFxuXHRMb2NhbERlbGl2ZXJ5OiAnTG9jYWxEZWxpdmVyeScsXG5cdFNoaXBUb1N0b3JlOiAnU2hpcC10by1TdG9yZScsXG5cdFNoaXBUb1N0b3JlUGlja3VwOiAnTXlfU3RvcmVfRnJlZV9TaGlwcGluZycsXG5cdFNoaXBUb1N0b3JlUGlja3VwRm9yV2hpcDogJ1dISVAgRlJFRSBTaGlwLXRvLXN0b3JlJyxcblx0VmlydHVhbDogJ1ZpcnR1YWwnXG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLkV2ZW50cyA9IHtcblx0Q2FydDoge1xuXHRcdEFkZFRvQ2FydDoge1xuXHRcdFx0TmFtZTogJ0FkZFRvQ2FydCdcblx0XHR9LFxuXHRcdFJlbW92ZUZyb21DYXJ0OiB7XG5cdFx0XHROYW1lOiAnUmVtb3ZlRnJvbUNhcnQnXG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydHMuRXZlbnRUeXBlcyA9IHtcblx0TWludXM6ICdtaW51cycsXG5cdFBsdXM6ICdwbHVzJ1xufSIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5HZXRQb3NpdGlvbiA9IGdldFBvc2l0aW9uO1xuXG5mdW5jdGlvbiBnZXRQb3NpdGlvbigpIHtcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcblx0XHRpZiAobmF2aWdhdG9yLmdlb2xvY2F0aW9uKSB7XG5cdFx0XHR2YXIgZ2VvbG9jYXRpb25TdWNjZXNzID0gZnVuY3Rpb24ocG9zaXRpb24pIHtcdFxuXHRcdFx0XHRyZXNvbHZlKHBvc2l0aW9uKTtcblx0XHRcdH07XG5cblx0XHRcdHZhciBnZW9sb2NhdGlvbkVycm9yID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdH07XG5cblx0XHRcdG5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24oZ2VvbG9jYXRpb25TdWNjZXNzLCBnZW9sb2NhdGlvbkVycm9yKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVzb2x2ZSgpO1xuXHRcdH1cblx0fSk7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlNsaWNrU2xpZGVyID0ge1xuXHRPcHRpb25zOiB7XG5cdFx0U2luZ2xlOiB7XG5cdFx0XHRhY2Nlc3NpYmlsaXR5OiAgdHJ1ZSxcblx0XHRcdGluZmluaXRlOiBcdFx0dHJ1ZSxcblx0XHRcdGRvdHM6IFx0XHRcdGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBcdFx0ZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IFx0MSxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiAxLFxuXHRcdFx0cmVzcG9uc2l2ZTogXHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiA3NjcsXG5cdFx0XHRcdFx0c2V0dGluZ3M6IFx0e1xuXHRcdFx0XHRcdFx0ZG90czogXHR0cnVlLFxuXHRcdFx0XHRcdFx0YXJyb3dzOiB0cnVlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMFxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSxcblx0XHRUaHVtYm5haWw6IHtcblx0XHRcdGFjY2Vzc2liaWxpdHk6ICB0cnVlLFxuXHRcdFx0ZHJhZ2dhYmxlOiBmYWxzZSxcblx0XHRcdGluZmluaXRlOiBmYWxzZSxcblx0XHRcdGZvY3VzT25TZWxlY3Q6IFx0ZmFsc2UsXG5cdFx0XHRkb3RzOiBmYWxzZSxcblx0XHRcdGFycm93czogZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDcsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogNyxcblx0XHRcdHJlc3BvbnNpdmU6IFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogNzY3XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwLFxuXHRcdFx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Nob3c6IDQsXG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Njcm9sbDogNFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0sXG5cdFx0Q2F0ZWdvcnlMYW5kaW5nOiB7XG5cdFx0XHRhY2Nlc3NpYmlsaXR5OiAgdHJ1ZSxcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiB0cnVlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiB0cnVlLFxuXHRcdFx0c2xpZGVzVG9TaG93OiA0LFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDQsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2N1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMCxcblx0XHRcdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRcdFx0c2xpZGVzVG9TaG93OiAzLFxuXHRcdFx0XHRcdFx0c2xpZGVzVG9TY3JvbGw6IDNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuUGF5bWVudE1ldGhvZHMgPSB7XG5cdEFsbGlhbmNlRGF0YTogJ0FsbGlhbmNlX0RhdGEnLFxuXHRBcHBsZVBheTogJ0RXX0FQUExFX1BBWScsXG5cdEJpbGxNZUxhdGVyOiAnQk1MJyxcblx0Q3JlZGl0Q2FyZDogJ0NSRURJVF9DQVJEJyxcblx0R2lmdENlcnRpZmljYXRlOiAnR0lGVF9DRVJUSUZJQ0FURScsXG5cdFBheVBhbDogJ1BheVBhbCcsXG5cdEdsb2JhbGU6ICdHTE9CQUxFJyxcblx0UmV3YXJkc0NyZWRpdDogJ1JFV0FSRFNfQ1JFRElUJyxcblx0TG95YWx0eUNyZWRpdDogJ0xPWUFMVFlfQ1JFRElUJyxcblx0U3RvcmVkVmFsdWVTb2x1dGlvbnM6ICdTVlNfR2lmdF9DYXJkJyxcblx0QWZmaXJtOiAnQWZmaXJtJyxcblx0UGF5bWVudFZvdWNoZXI6ICdCMkJfUGF5bWVudF9Wb3VjaGVyJyxcblx0U2hvcFBheTogJ1Nob3BQYXknXG59O1xuXG5leHBvcnRzLkNyZWRpdENhcmRzID0ge1xuXHRBbWVyaWNhbkV4cHJlc3M6ICdBbWV4Jyxcblx0Qm9vdEJhcm5DcmVkaXQ6ICdCb290IEJhcm4gQ3JlZGl0IENhcmQnLFxuXHREaXNjb3ZlcjogJ0Rpc2NvdmVyJyxcblx0SkNCOiAnSkNCJyxcblx0TWFlc3RybzogJ01hZXN0cm8nLFxuXHRNYXN0ZXJjYXJkOiAnTWFzdGVyJyxcblx0TWFzdGVyY2FyZFNlcmllczI6ICdNYXN0ZXIgU2VyaWVzIDInLFxuXHRWaXNhOiAnVmlzYSdcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlJlZmluZW1lbnRzVUlWZXJzaW9ucyA9IHtcblx0VXBkYXRlZDogJ1VwZGF0ZWQnLFxuXHRMZWdhY3k6ICdMZWdhY3knXG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0VmFsaWRhdGlvbjoge1xuXHRcdEVtYWlsOiAvXlthLXpBLVowLTkuISMkJSYnKitcXC89P15fYHt8fX4tXStAW2EtekEtWjAtOV0oPzpbYS16QS1aMC05LV17MCw2MX1bYS16QS1aMC05XSk/KD86XFwuW2EtekEtWjAtOV0oPzpbYS16QS1aMC05LV17MCw2MX1bYS16QS1aMC05XSk/KSokLyxcblx0XHRPcmRlck51bWJlcjogL15bYS16QS1aXXswLDZ9Wy0uX117MCwxfVswLTldezYsMTJ9JC8sXG5cdFx0UG9zdGFsQ29kZTogL15bYS16QS1aMC05XVthLXpBLVowLTlcXC0gXXswLDEwfVthLXpBLVowLTldJC8sXG5cdFx0UG9zdE9mZmljZUJveDogLygoKChwW1xcc1xcLl0/KVxccz9bb1xcc11bXFwuXT8pXFxzPyl8KHBvc3RcXHM/b2ZmaWNlXFxzPyl8KHBvc3RhbFxccz8pfChwb3N0XFxzPykpKChib3h8YmlufGJcXC4/KT9cXHM/KChudW18bnVtYmVyfG5vfCMpXFwuPyk/XFxzP1xcZCspL2ksXG5cdFx0WmlwQ29kZTogL15bMC05XXs1fSgtWzAtOV17NH0pKiQvLFxuXHRcdFJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb246IC9eWyNdKlteX1xcV10rLyxcblx0XHRHaWZ0Q2FyZE51bWJlckxlbmd0aDogLyhcXGQpL2csXG5cdFx0R2lmdENhcmROdW1iZXJWYWx1ZXM6IC9eWy1cXHMwLTldKiQvLFxuXHR9XG59XG5cbi8vIEVtYWlsIHBhdHRlcm4gaXMgZnJvbSBXM0Mgc3BlYywgc2FtZSB0aGF0IGpRdWVyeSBWYWxpZGF0ZSB1c2VzOiBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9pbnB1dC5odG1sI3ZhbGlkLWUtbWFpbC1hZGRyZXNzXG4vLyBQb3N0YWwgQ29kZSBwYXR0ZXJuIGlzIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTc4NDA2L3doYXQtaXMtdGhlLXVsdGltYXRlLXBvc3RhbC1jb2RlLWFuZC16aXAtcmVnZXhcbi8vIFBPIEJveCBwYXR0ZXJuIGlzIG1vZGlmaWVkIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTY4MDA1MC9wby1ib3gtcmVndWxhci1leHByZXNzaW9uLXZhbGlkYXRpb24iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuQWRkcmVzc1R5cGVzID0ge1xuXHRDdXN0b21lcjogJ0N1c3RvbWVyQWRkcmVzcycsXG5cdFN0b3JlOiAnU3RvcmVBZGRyZXNzJ1xufVxuXG5leHBvcnRzLkNvdW50cnlDb2RlcyA9IHtcblx0VW5pdGVkU3RhdGVzOiAnVVMnLFxuXHRDYW5hZGE6ICdDQSdcbn1cblxuZXhwb3J0cy5TdGF0ZUNvZGVzID0ge1xuXHROZXdZb3JrOiAnTlknXG59XG5cbmV4cG9ydHMuS2V5Q29kZXMgPSB7XG5cdEVudGVyOiAxMyxcblx0VGFiOiA5LFxuXHRBcnJvd0xlZnQ6IDM3LFxuXHRBcnJvd1VwOiAzOCxcblx0QXJyb3dSaWdodDogMzksXG5cdEFycm93RG93bjogNDBcbn1cblxuZXhwb3J0cy5SZXNwb25zaXZlID0ge1xuXHRXaWR0aHM6IHtcblx0XHRNb2JpbGU6IDc2Nyxcblx0XHRUYWJsZXQ6IDEwMjRcblx0fVxufVxuXG5leHBvcnRzLlNpdGVJZHMgPSB7XG5cdEJvb3RCYXJuVVM6ICdib290YmFybl91cycsXG5cdFNoZXBsZXJzVVM6ICdzaGVwbGVyc191cycsXG5cdENvdW50cnlPdXRmaXR0ZXJzVVM6ICdjb3VudHJ5X291dGZpdHRlcnNfdXMnLFxuXHRCb290QmFyblJzcFVTOiAnYm9vdGJhcm5fcnNwX3VzJyxcblx0Qm9vdEJhcm5QYXltZW50czogJ2Jvb3RiYXJuX3BheW1lbnRzJyxcblx0Qm9vdEJhcm5CMkJVUzogJ2Jvb3RiYXJuX2IyYl91cycsXG5cdFJhbmdlZmluZGVyOiAncmFuZ2VmaW5kZXInXG59XG5cbmV4cG9ydHMuUHJvZHVjdFJlY29tbWVuZGF0aW9uU3lzdGVtcyA9IHtcblx0RWluc3RlaW46ICdFaW5zdGVpbicsXG5cdFJlbGV2YW50OiAnUmVsZXZhbnQnXG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLkxvZGFzaCA9IHtcblx0U2V0dGluZ3M6IHtcblx0XHRpbnRlcnBvbGF0ZTogL3t7KFtcXHNcXFNdKz8pfX0vZ1xuXHR9XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLlNldHRpbmdzID0ge1xuXHRHbG9iYWw6IHtcblx0ICAgIGVycm9yQ2xhc3M6ICdlcnJvcicsXG5cdCAgICBlcnJvckVsZW1lbnQ6ICdzcGFuJyxcblx0ICAgIG9ua2V5dXA6IGZhbHNlLFxuXHQgICAgZXJyb3JQbGFjZW1lbnQ6IGZ1bmN0aW9uIChlcnJvciwgZWxlbWVudCkge1xuXHRcdFx0dmFyICR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIgPSBlbGVtZW50LmNsb3Nlc3QoJ2Zvcm0nKS5maW5kKCcudmFsaWRhdGlvbi1lcnJvci1jb250YWluZXInKTtcblx0XHRcdGlmICgkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0ZXJyb3IuYXBwZW5kVG8oJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lcik7XG5cdCAgICBcdH0gZWxzZSBpZiAoZWxlbWVudC5hdHRyKCdlcnJvci1jb250YWluZXInKSkge1xuXHQgICAgXHRcdGVycm9yLmFwcGVuZFRvKCQoZWxlbWVudC5hdHRyKCdlcnJvci1jb250YWluZXInKSkpO1xuXHQgICAgXHR9IGVsc2Uge1xuXHQgICAgXHRcdGVycm9yLmFwcGVuZFRvKGVsZW1lbnQucGFyZW50KCkpO1xuXHQgICAgXHR9XG5cdCAgICB9XG5cdH0sXG5cdENoZWNrb3V0OiB7XG5cdCAgICBlcnJvclBsYWNlbWVudDogZnVuY3Rpb24oZXJyb3IsIGVsZW1lbnQpIHtcblx0ICAgIFx0aWYgKGVsZW1lbnQuYXR0cignZXJyb3ItY29udGFpbmVyJykpIHtcblx0ICAgIFx0XHRlcnJvci5hcHBlbmRUbygkKGVsZW1lbnQuYXR0cignZXJyb3ItY29udGFpbmVyJykpKTtcblx0ICAgIFx0fSBlbHNlIHtcblx0ICAgIFx0XHRlcnJvci5hcHBlbmRUbyhlbGVtZW50LnBhcmVudCgpKTtcblx0ICAgIFx0fVxuXG5cdFx0XHR2YXIgJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lciA9IGVsZW1lbnQuY2xvc2VzdCgnZm9ybScpLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yLWNvbnRhaW5lcicpO1xuXHRcdFx0aWYgKCR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIubGVuZ3RoID4gMCkge1xuXHRcdFx0XHR2YXIgJGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXHRcdFx0XHR2YXIgJGVsZW1lbnRWYWxpZGF0aW9uRXJyb3IgPSAkdmFsaWRhdGlvbkVycm9yQ29udGFpbmVyLmZpbmQoJy52YWxpZGF0aW9uLWVycm9yW2ZpZWxkPVwiJyArICRlbGVtZW50LmF0dHIoJ2lkJykgKyAnXCJdJyk7XG5cdFx0XHRcdGlmICgkZWxlbWVudFZhbGlkYXRpb25FcnJvci5sZW5ndGggPD0gMCkge1xuXHRcdFx0XHRcdHZhciB2YWxpZGF0aW9uRXJyb3JUZXh0ID0gJCgnPHNwYW4gY2xhc3M9XCJ2YWxpZGF0aW9uLWVycm9yXCIgZmllbGQ9XCInICsgJGVsZW1lbnQuYXR0cignaWQnKSArICdcIiAvPicpLnRleHQoJGVsZW1lbnQuY2xvc2VzdCgnLmZvcm1maWVsZCcpLmZpbmQoJ2xhYmVsIHNwYW4nKS50ZXh0KCkgKyAnIGlzIHJlcXVpcmVkLicpO1xuXHRcdFx0XHRcdCR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIuYXBwZW5kKHZhbGlkYXRpb25FcnJvclRleHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdCAgICB9LFxuXHRcdG9uZm9jdXNvdXQ6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcblx0XHRcdGlmICghdGhpcy5jaGVja2FibGUoZWxlbWVudCkpIHtcblx0XHRcdFx0dmFyIGlzRWxlbWVudFZhbGlkID0gdGhpcy5lbGVtZW50KGVsZW1lbnQpO1xuXHRcdFx0XHR2YXIgJGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXHRcdFx0XHR2YXIgJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lciA9ICRlbGVtZW50LmNsb3Nlc3QoJ2Zvcm0nKS5maW5kKCcudmFsaWRhdGlvbi1lcnJvci1jb250YWluZXInKTtcblx0XHRcdFx0dmFyICRlbGVtZW50VmFsaWRhdGlvbkVycm9yID0gJHZhbGlkYXRpb25FcnJvckNvbnRhaW5lci5maW5kKCcudmFsaWRhdGlvbi1lcnJvcltmaWVsZD1cIicgKyAkZWxlbWVudC5hdHRyKCdpZCcpICsgJ1wiXScpO1xuXHRcdFx0XHRpZiAoaXNFbGVtZW50VmFsaWQgJiYgJGVsZW1lbnRWYWxpZGF0aW9uRXJyb3IubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdCRlbGVtZW50VmFsaWRhdGlvbkVycm9yLnJlbW92ZSgpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCFpc0VsZW1lbnRWYWxpZCAmJiAkZWxlbWVudFZhbGlkYXRpb25FcnJvci5sZW5ndGggPD0gMCkge1xuXHRcdFx0XHRcdHZhciB2YWxpZGF0aW9uRXJyb3JUZXh0ID0gJCgnPHNwYW4gY2xhc3M9XCJ2YWxpZGF0aW9uLWVycm9yXCIgZmllbGQ9XCInICsgJGVsZW1lbnQuYXR0cignaWQnKSArICdcIiAvPicpLnRleHQoJGVsZW1lbnQuY2xvc2VzdCgnLmZvcm1maWVsZCcpLmZpbmQoJ2xhYmVsIHNwYW4nKS50ZXh0KCkgKyAnIGlzIHJlcXVpcmVkLicpO1xuXHRcdFx0XHRcdCR2YWxpZGF0aW9uRXJyb3JDb250YWluZXIuYXBwZW5kKHZhbGlkYXRpb25FcnJvclRleHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydHMuUnVsZXMgPSB7XG5cdFJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb246IHtcblx0XHRyZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uOiB0cnVlXG5cdH0sXG5cdFZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3g6IHtcblx0XHRwb3N0T2ZmaWNlQm94OiB0cnVlXG5cdH0sXG5cdFZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5OiB7XG5cdFx0cG9zdE9mZmljZUJveE9ubHk6IHRydWVcblx0fSxcblx0RW1haWw6IHtcblx0XHRlbWFpbDogdHJ1ZSxcblx0XHRtaW5sZW5ndGg6IDFcblx0fSxcblx0T3JkZXJOdW1iZXI6IHtcblx0XHRvcmRlck51bWJlcjogdHJ1ZVxuXHR9LFxuXHRQb3N0YWxDb2RlOiB7XG5cdFx0cG9zdGFsQ29kZTogdHJ1ZVxuXHR9LFxuXHRQb3N0YWxDb2RlQW5kU3RhdGVDb2RlOiB7XG5cdFx0cG9zdGFsQ29kZTogdHJ1ZSxcblx0XHR6aXBDb2RlRm9yU3RhdGVDb2RlOiB0cnVlXG5cdH0sXG5cdFppcENvZGU6IHtcblx0XHR6aXBDb2RlOiB0cnVlXG5cdH0sXG5cdFppcENvZGVBbmRTdGF0ZUNvZGU6IHtcblx0XHR6aXBDb2RlOiB0cnVlLFxuXHRcdHppcENvZGVGb3JTdGF0ZUNvZGU6IHRydWVcblx0fSxcblx0U3RhdGVDb2RlRm9yQ2FsaWZvcm5pYVN0YXRlTGluZToge1xuXHRcdHN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmU6IHRydWVcblx0fSxcblx0R2lmdENhcmQ6IHtcblx0XHROdW1iZXI6IHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0Z2lmdENhcmROdW1iZXJMZW5ndGg6IHRydWUsXG5cdFx0XHRnaWZ0Q2FyZE51bWJlclZhbHVlczogdHJ1ZVxuXHRcdH0sXG5cdFx0UGluOiB7XG5cdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdGRpZ2l0czogdHJ1ZSxcblx0XHRcdG1pbmxlbmd0aDogNCxcblx0XHRcdG1heGxlbmd0aDogOCxcblx0XHRcdG1lc3NhZ2VzOiB7XG5cdFx0XHRcdG1pbmxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWluaW11bUxlbmd0aCksXG5cdFx0XHRcdG1heGxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWF4aW11bUxlbmd0aClcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdFJld2FyZHNDcmVkaXQ6IHtcblx0XHROdW1iZXI6IHtcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGlnaXRzOiB0cnVlLFxuXHRcdFx0bWlubGVuZ3RoOiAxNixcblx0XHRcdG1heGxlbmd0aDogMTYsXG5cdFx0XHRtZXNzYWdlczoge1xuXHRcdFx0XHRtaW5sZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5OdW1iZXJzLk1pbmltdW1MZW5ndGgpLFxuXHRcdFx0XHRtYXhsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5OdW1iZXJzLk1heGltdW1MZW5ndGgpXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRMb3lhbHR5Q3JlZGl0OiB7XG5cdFx0TnVtYmVyOiB7XG5cdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdGRpZ2l0czogdHJ1ZSxcblx0XHRcdG1pbmxlbmd0aDogMSxcblx0XHRcdG1heGxlbmd0aDogMTAsXG5cdFx0XHRtZXNzYWdlczoge1xuXHRcdFx0XHRtaW5sZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5OdW1iZXJzLk1pbmltdW1MZW5ndGgpLFxuXHRcdFx0XHRtYXhsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVmFsaWRhdGlvbi5NZXNzYWdlcy5OdW1iZXJzLk1heGltdW1MZW5ndGgpXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRQYXltZW50Vm91Y2hlcjoge1xuXHRcdE51bWJlcjoge1xuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRkaWdpdHM6IGZhbHNlLFxuXHRcdFx0bWlubGVuZ3RoOiAxLFxuXHRcdFx0bWF4bGVuZ3RoOiAyOCxcblx0XHRcdG1lc3NhZ2VzOiB7XG5cdFx0XHRcdG1pbmxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWluaW11bUxlbmd0aCksXG5cdFx0XHRcdG1heGxlbmd0aDogJC52YWxpZGF0b3IuZm9ybWF0KFJlc291cmNlcy5WYWxpZGF0aW9uLk1lc3NhZ2VzLk51bWJlcnMuTWF4aW11bUxlbmd0aClcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0iLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuUHVzaERhdGFMYXllckZvclBhZ2UgPSBwdXNoRGF0YUxheWVyRm9yUGFnZTtcbmV4cG9ydHMuUHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGUgPSBwdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZTtcbmV4cG9ydHMuUHVzaERhdGFMYXllckZvckV2ZW50ID0gcHVzaERhdGFMYXllckZvckV2ZW50O1xuXG5mdW5jdGlvbiBwdXNoRGF0YUxheWVyRm9yUGFnZShwYWdlKSB7XG5cdHdpbmRvdy5kYXRhTGF5ZXIgPSB3aW5kb3cuZGF0YUxheWVyIHx8IFtdO1xuXG5cdGlmIChwYWdlKSB7XG5cdFx0aWYgKHBhZ2Uub3B0aW9ucyAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlciAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5FbmFibGVHb29nbGVBbmFseXRpY3M0KSB7XG5cdFx0XHRwdXNoRGF0YUxheWVyRm9yUGFnZUZvckdvb2dsZUFuYWx5dGljczQocGFnZSk7XG5cdFx0fVxuXHRcdHB1c2hEYXRhTGF5ZXJGb3JQYWdlRm9yVW5pdmVyc2FsQW5hbHl0aWNzKHBhZ2UpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXJGb3JQYWdlRm9yR29vZ2xlQW5hbHl0aWNzNChwYWdlKSB7XG5cdHdpbmRvdy5kYXRhTGF5ZXIgPSB3aW5kb3cuZGF0YUxheWVyIHx8IFtdO1xuXG5cdGlmIChwYWdlKSB7XG5cdFx0aWYgKHBhZ2Uub3B0aW9ucyAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlciAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5EYXRhTGF5ZXJDYWNoZUZvckdvb2dsZUFuYWx5dGljczQpIHtcblx0XHRcdHZhciBkYXRhTGF5ZXI7XG5cdFx0XHRpZiAocGFnZS5ucyA9PSAnb3JkZXJjb25maXJtYXRpb24nKSB7XG5cdFx0XHRcdGRhdGFMYXllciA9IHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlRm9yR29vZ2xlQW5hbHl0aWNzNDtcblx0XHRcdFx0ZGF0YUxheWVyLml0ZW1zID0gZ2V0UHJvZHVjdERhdGFMYXllcignZGF0YS1wcm9kdWN0LWdhNC1qc29uJyk7XG5cdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKTtcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignRGF0YUxheWVyLk9yZGVyQ29tcGxldGUnLCBkYXRhTGF5ZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gVGhpcyBzaG91bGQgYmUgYWN0aXZhdGVkIHdoZW4gVUEgaXMgcmVtb3ZlZC5cblx0XHRcdFx0Ly8gJC5hamF4KHtcblx0XHRcdFx0Ly8gXHR1cmw6IFVybHMuR29vZ2xlVGFnTWFuYWdlci5HZXREYXRhTGF5ZXIsXG5cdFx0XHRcdC8vIFx0dHlwZTogJ1BPU1QnLFxuXHRcdFx0XHQvLyBcdGRhdGE6IHtcblx0XHRcdFx0Ly8gXHRcdERhdGFMYXllclR5cGU6ICdHZW5lcmFsJyxcblx0XHRcdFx0Ly8gXHRcdERhdGFMYXllclZlcnNpb246ICdHb29nbGVBbmFseXRpY3M0J1xuXHRcdFx0XHQvLyBcdH0sXG5cdFx0XHRcdC8vIFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0Ly8gXHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdC8vIFx0XHRkYXRhTGF5ZXIgPSAkLmV4dGVuZChwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5EYXRhTGF5ZXJDYWNoZUZvckdvb2dsZUFuYWx5dGljczQsIGRhdGEpO1xuXHRcdFx0XHQvLyBcdFx0d2luZG93LmRhdGFMYXllci5wdXNoKGRhdGFMYXllcik7XG5cdFx0XHRcdC8vIFx0fSxcblx0XHRcdFx0Ly8gXHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0Ly8gXHR9XG5cdFx0XHRcdC8vIH0pO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaGlzIHNob3VsZCBiZSBhY3RpdmF0ZWQgd2hlbiBVQSBpcyByZW1vdmVkLlxuXHRcdFx0Ly8gJChkb2N1bWVudCkudHJpZ2dlcignRGF0YUxheWVyLk9yZGVyQ29tcGxldGUnLCBkYXRhTGF5ZXIpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAocGFnZS5ucyAhPSAnb3JkZXJjb25maXJtYXRpb24nKSB7XG5cdFx0XHR2YXIgcGF5bG9hZCA9IHt9O1xuXG5cdFx0XHR2YXIgZGF0YUxheWVyUGFnZVR5cGU7XG5cdFx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLlBhZ2VUeXBlKSB7XG5cdFx0XHRcdGRhdGFMYXllclBhZ2VUeXBlID0gcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuUGFnZVR5cGU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkYXRhTGF5ZXJQYWdlVHlwZSA9IHBhZ2UubnM7XG5cdFx0XHR9XHRcdFxuXHRcdFx0cGF5bG9hZC5QYWdlID0gZGF0YUxheWVyUGFnZVR5cGU7XHRcblxuXHRcdFx0aWYgKHBhZ2Uub3B0aW9ucyAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlcikge1xuXHRcdFx0XHRwYXlsb2FkLk9wdGlvbnMgPSBKU09OLnN0cmluZ2lmeShwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlcik7XG5cdFx0XHRcdHBheWxvYWQuRGF0YUxheWVyVmVyc2lvbiA9ICdHb29nbGVBbmFseXRpY3M0Jztcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLkdvb2dsZVRhZ01hbmFnZXIuR2V0RGF0YUxheWVyLFxuXHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdGRhdGE6IHBheWxvYWQsXG5cdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRpZiAocGFnZS5vcHRpb25zICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyICYmIHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlRm9yR29vZ2xlQW5hbHl0aWNzNCkge1xuXHRcdFx0XHRcdFx0ZGF0YSA9ICQuZXh0ZW5kKHBhZ2Uub3B0aW9ucy5Hb29nbGVUYWdNYW5hZ2VyLkRhdGFMYXllckNhY2hlRm9yR29vZ2xlQW5hbHl0aWNzNCwgZGF0YSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChwYWdlLm5zID09ICdwcm9kdWN0Jykge1xuXHRcdFx0XHRcdFx0aWYgKCFkYXRhLnZhbHVlICYmIGRhdGEuaXRlbXMgJiYgZGF0YS5pdGVtcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdGRhdGEuY3VycmVuY3kgPSBkYXRhLml0ZW1zWzBdLmN1cnJlbmN5O1xuXHRcdFx0XHRcdFx0XHRkYXRhLnZhbHVlID0gZGF0YS5pdGVtc1swXS5wcmljZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYgKHBhZ2UubnMgPT0gJ3NlYXJjaCcpIHtcblx0XHRcdFx0XHRcdGRhdGEuaXRlbXMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKCdkYXRhLXByb2R1Y3QtZ2E0LWpzb24nLCB7IENvbnRhaW5lcjogJCgnLnNlYXJjaC1yZXN1bHQtY29udGVudCcpIH0pO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAocGFnZS5ucyA9PSAnY2FydCcgfHwgcGFnZS5ucyA9PSAnb25lcGNoZWNrb3V0JyB8fCBwYWdlLm5zID09ICdvbmVwY2hlY2tvdXRfZ3JvdXBzJykge1xuXHRcdFx0XHRcdFx0ZGF0YS5pdGVtcyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicpO1xuXHRcdFx0XHRcdFx0aWYgKCFkYXRhLnZhbHVlICYmIGRhdGEuaXRlbXMgJiYgZGF0YS5pdGVtcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRcdHZhciB2YWx1ZSA9IDA7XG5cdFx0XHRcdFx0XHRcdGZvciAodmFyIGl0ZW1LZXkgaW4gZGF0YS5pdGVtcykge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBpdGVtID0gZGF0YS5pdGVtc1tpdGVtS2V5XTtcblx0XHRcdFx0XHRcdFx0XHR2YWx1ZSArPSBpdGVtLnByaWNlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGRhdGEudmFsdWUgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cHVzaERhdGFMYXllcihkYXRhKTtcblx0XHRcdFx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGRhdGEpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBwdXNoRGF0YUxheWVyRm9yUGFnZUZvclVuaXZlcnNhbEFuYWx5dGljcyhwYWdlKSB7XG5cdHdpbmRvdy5kYXRhTGF5ZXIgPSB3aW5kb3cuZGF0YUxheWVyIHx8IFtdO1xuXG5cdGlmIChwYWdlKSB7XG5cdFx0aWYgKHBhZ2Uub3B0aW9ucyAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlciAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlci5EYXRhTGF5ZXJDYWNoZSkge1xuXHRcdFx0dmFyIGRhdGFMYXllcjtcblx0XHRcdGlmIChwYWdlLm5zID09ICdvcmRlcmNvbmZpcm1hdGlvbicpIHtcblx0XHRcdFx0ZGF0YUxheWVyID0gcGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuRGF0YUxheWVyQ2FjaGU7XG5cdFx0XHRcdGRhdGFMYXllci5lY29tbWVyY2UgPSBkYXRhTGF5ZXIuZWNvbW1lcmNlIHx8IHt9O1xuXHRcdFx0XHRkYXRhTGF5ZXIuZWNvbW1lcmNlLnB1cmNoYXNlID0gZGF0YUxheWVyLmVjb21tZXJjZS5wdXJjaGFzZSB8fCB7fTtcblx0XHRcdFx0ZGF0YUxheWVyLmVjb21tZXJjZS5wdXJjaGFzZS5wcm9kdWN0cyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoKTtcblx0XHRcdFx0cHVzaERhdGFMYXllcihkYXRhTGF5ZXIpO1xuXHRcdFx0XHQvLyAkKGRvY3VtZW50KS50cmlnZ2VyKCdEYXRhTGF5ZXIuT3JkZXJDb21wbGV0ZScsIGRhdGFMYXllcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHRcdHVybDogVXJscy5Hb29nbGVUYWdNYW5hZ2VyLkdldERhdGFMYXllcixcblx0XHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0RGF0YUxheWVyVHlwZTogJ0dlbmVyYWwnLFxuXHRcdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogJ1VuaXZlcnNhbEFuYWx5dGljcydcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdFx0ZGF0YUxheWVyID0gJC5leHRlbmQocGFnZS5vcHRpb25zLkdvb2dsZVRhZ01hbmFnZXIuRGF0YUxheWVyQ2FjaGUsIGRhdGEpO1xuXHRcdFx0XHRcdFx0cHVzaERhdGFMYXllcihkYXRhTGF5ZXIpO1xuXHRcdFx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlcignRGF0YUxheWVyLk9yZGVyQ29tcGxldGUnLCBkYXRhTGF5ZXIpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0aWYgKHBhZ2UubnMgIT0gJ29yZGVyY29uZmlybWF0aW9uJykge1xuXHRcdFx0dmFyIHBheWxvYWQgPSB7XG5cdFx0XHRcdFBhZ2U6IHBhZ2UubnNcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0aWYgKHBhZ2Uub3B0aW9ucyAmJiBwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlcikge1xuXHRcdFx0XHRwYXlsb2FkLk9wdGlvbnMgPSBKU09OLnN0cmluZ2lmeShwYWdlLm9wdGlvbnMuR29vZ2xlVGFnTWFuYWdlcik7XG5cdFx0XHRcdHBheWxvYWQuRGF0YUxheWVyVmVyc2lvbiA9ICdVbml2ZXJzYWxBbmFseXRpY3MnO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMuR29vZ2xlVGFnTWFuYWdlci5HZXREYXRhTGF5ZXIsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YTogcGF5bG9hZCxcblx0XHRcdFx0ZGF0YVR5cGU6ICdqc29uJyxcblx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuXHRcdFx0XHRcdGlmIChwYWdlLm5zID09ICdzZWFyY2gnKSB7XG5cdFx0XHRcdFx0XHRkYXRhLmVjb21tZXJjZSA9IGRhdGEuZWNvbW1lcmNlIHx8IHt9O1xuXHRcdFx0XHRcdFx0ZGF0YS5lY29tbWVyY2UuaW1wcmVzc2lvbnMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKG51bGwsIHsgQ29udGFpbmVyOiAkKCcuc2VhcmNoLXJlc3VsdC1jb250ZW50JykgfSk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwYWdlLm5zID09ICdwcm9kdWN0Jykge1xuXHRcdFx0XHRcdFx0ZGF0YS5lY29tbWVyY2UgPSBkYXRhLmVjb21tZXJjZSB8fCB7fTtcblx0XHRcdFx0XHRcdGRhdGEuZWNvbW1lcmNlLmRldGFpbCA9IGRhdGEuZWNvbW1lcmNlLmRldGFpbCB8fCB7fTtcblx0XHRcdFx0XHRcdGRhdGEuZWNvbW1lcmNlLmRldGFpbC5wcm9kdWN0cyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHBhZ2UubnMgPT0gJ2NhcnQnIHx8IHBhZ2UubnMgPT0gJ29uZXBjaGVja291dCcgfHwgcGFnZS5ucyA9PSAnb25lcGNoZWNrb3V0X2dyb3VwcycpIHtcblx0XHRcdFx0XHRcdGRhdGEuZWNvbW1lcmNlID0gZGF0YS5lY29tbWVyY2UgfHwge307XG5cdFx0XHRcdFx0XHRkYXRhLmVjb21tZXJjZS5jYXJ0Q29udGVudHMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YSk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXJGb3JEYXRhTGF5ZXJUeXBlKGRhdGFMYXllclR5cGUsIGRhdGFPYmplY3QsIG9wdGlvbnMpIHtcblx0dmFyIGRhdGFPYmplY3QgPSBkYXRhT2JqZWN0IHx8IHt9O1xuXG5cdHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcblx0XHR2YXIgYWpheENvbXBsZXRlU3RhdHVzID0ge1xuXHRcdFx0R29vZ2xlQW5hbHl0aWNzNDogJycsXG5cdFx0XHRVbml2ZXJzYWxBbmFseXRpY3M6ICcnXG5cdFx0fVxuXG5cdFx0dmFyIGFqYXhDb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKGFqYXhDb21wbGV0ZVN0YXR1cy5Vbml2ZXJzYWxBbmFseXRpY3MgPT0gJ3N1Y2Nlc3MnICYmIGFqYXhDb21wbGV0ZVN0YXR1cy5Hb29nbGVBbmFseXRpY3M0ID09ICdzdWNjZXNzJykge1xuXHRcdFx0XHRyZXNvbHZlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKGFqYXhDb21wbGV0ZVN0YXR1cy5Vbml2ZXJzYWxBbmFseXRpY3MgJiYgYWpheENvbXBsZXRlU3RhdHVzLkdvb2dsZUFuYWx5dGljczQgJiYgKGFqYXhDb21wbGV0ZVN0YXR1cy5Vbml2ZXJzYWxBbmFseXRpY3MgPT0gJ2Vycm9yJyB8fCBhamF4Q29tcGxldGVTdGF0dXMuR29vZ2xlQW5hbHl0aWNzNCA9PSAnZXJyb3InKSkge1xuXHRcdFx0XHRyZWplY3QoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRwdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZUZvckRhdGFMYXllclZlcnNpb24oZGF0YUxheWVyVHlwZSwgZGF0YU9iamVjdC5Vbml2ZXJzYWxBbmFseXRpY3MgfHwgT2JqZWN0LmFzc2lnbih7fSwgZGF0YU9iamVjdCksICdVbml2ZXJzYWxBbmFseXRpY3MnLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdFx0YWpheENvbXBsZXRlU3RhdHVzLlVuaXZlcnNhbEFuYWx5dGljcyA9ICdzdWNjZXNzJztcblx0XHRcdGFqYXhDb21wbGV0ZSgpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0YWpheENvbXBsZXRlU3RhdHVzLlVuaXZlcnNhbEFuYWx5dGljcyA9ICdlcnJvcic7XG5cdFx0XHRhamF4Q29tcGxldGUoKTtcblx0XHR9KTtcblx0XHRwdXNoRGF0YUxheWVyRm9yRGF0YUxheWVyVHlwZUZvckRhdGFMYXllclZlcnNpb24oZGF0YUxheWVyVHlwZSwgZGF0YU9iamVjdC5Hb29nbGVBbmFseXRpY3M0IHx8IE9iamVjdC5hc3NpZ24oe30sIGRhdGFPYmplY3QpLCAnR29vZ2xlQW5hbHl0aWNzNCcsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24oKSB7XG5cdFx0XHRhamF4Q29tcGxldGVTdGF0dXMuR29vZ2xlQW5hbHl0aWNzNCA9ICdzdWNjZXNzJztcblx0XHRcdGFqYXhDb21wbGV0ZSgpO1xuXHRcdH0pLmNhdGNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0YWpheENvbXBsZXRlU3RhdHVzLkdvb2dsZUFuYWx5dGljczQgPSAnZXJyb3InO1xuXHRcdFx0YWpheENvbXBsZXRlKCk7XG5cdFx0fSk7O1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcHVzaERhdGFMYXllckZvckRhdGFMYXllclR5cGVGb3JEYXRhTGF5ZXJWZXJzaW9uKGRhdGFMYXllclR5cGUsIGRhdGFPYmplY3QsIGRhdGFMYXllclZlcnNpb24sIG9wdGlvbnMpIHtcblx0dmFyIGRhdGFMYXllclR5cGUgPSBkYXRhTGF5ZXJUeXBlIHx8ICdHZW5lcmFsJztcblx0dmFyIGRhdGFMYXllclZlcnNpb24gPSBkYXRhTGF5ZXJWZXJzaW9uIHx8ICdVbml2ZXJzYWxBbmFseXRpY3MnO1xuXHR2YXIgZGF0YU9iamVjdCA9IGRhdGFPYmplY3QgfHwge307XG5cblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuXHRcdGlmIChkYXRhTGF5ZXJUeXBlKSB7XG5cdFx0XHQkLmFqYXgoe1xuXHRcdFx0XHR1cmw6IFVybHMuR29vZ2xlVGFnTWFuYWdlci5HZXREYXRhTGF5ZXIsXG5cdFx0XHRcdHR5cGU6ICdQT1NUJyxcblx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdERhdGFMYXllclR5cGU6IGRhdGFMYXllclR5cGUsXG5cdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvblxuXHRcdFx0XHR9LFxuXHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGFMYXllcjtcblx0XHRcdFx0XHRpZiAoZGF0YSAmJiAhJC5pc0VtcHR5T2JqZWN0KGRhdGEpKSB7XG5cdFx0XHRcdFx0XHRkYXRhTGF5ZXIgPSAkLmV4dGVuZChkYXRhLCBkYXRhT2JqZWN0KTtcblxuXHRcdFx0XHRcdFx0aWYgKGRhdGFMYXllclR5cGUgPT0gJ0FkZFBheW1lbnRJbmZvJykge1xuXHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdENvbnRhaW5lclNlbGVjdG9yOiBvcHRpb25zICYmIG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgPyBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yIDogJydcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGRhdGFMYXllclR5cGUgPT0gJ0FkZFNoaXBwaW5nSW5mbycpIHtcblx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvbixcblx0XHRcdFx0XHRcdFx0XHRDb250YWluZXJTZWxlY3Rvcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yID8gb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA6ICcnXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdBZGRUb0NhcnQnKSB7XG5cdFx0XHRcdFx0XHRcdGlmICgoZGF0YUxheWVyLmV2ZW50ID09ICdhZGRfdG9fY2FydCcgJiYgKCFkYXRhTGF5ZXIuaXRlbXMgfHwgZGF0YUxheWVyLml0ZW1zLmxlbmd0aCA9PSAwKSkgfHwgKGRhdGFMYXllci5ldmVudCA9PSAnYWRkVG9DYXJ0JyAmJiAoIWRhdGFMYXllci5lY29tbWVyY2UgfHwgIWRhdGFMYXllci5lY29tbWVyY2UgfHwgIWRhdGFMYXllci5lY29tbWVyY2UuYWRkIHx8ICFkYXRhTGF5ZXIuZWNvbW1lcmNlLmFkZC5wcm9kdWN0cyB8fCBkYXRhTGF5ZXIuZWNvbW1lcmNlLmFkZC5wcm9kdWN0cy5sZW5ndGggPT0gMCkpKSB7XG5cdFx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdFx0Q29udGFpbmVyU2VsZWN0b3I6IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA/IG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgOiAnJyxcblx0XHRcdFx0XHRcdFx0XHRcdEZpbHRlclNlbGVjdG9yOiAnLnBkcC1icm93c2UnLFxuXHRcdFx0XHRcdFx0XHRcdFx0VW5pdmVyc2FsQW5hbHl0aWNzS2V5OiAnYWRkJ1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmIChkYXRhTGF5ZXIuaXRlbXMgJiYgZGF0YUxheWVyLml0ZW1zLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIWRhdGFMYXllci5pdGVtc1swXS5xdWFudGl0eSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLml0ZW1zWzBdLnF1YW50aXR5ID0gMTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLmN1cnJlbmN5ID0gZGF0YUxheWVyLml0ZW1zWzBdLmN1cnJlbmN5O1xuXHRcdFx0XHRcdFx0XHRcdGRhdGFMYXllci52YWx1ZSA9IGRhdGFMYXllci5pdGVtc1swXS5wcmljZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdSZW1vdmVGcm9tQ2FydCcpIHtcblx0XHRcdFx0XHRcdFx0aWYgKGRhdGFMYXllci5pdGVtcyAmJiBkYXRhTGF5ZXIuaXRlbXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICghZGF0YUxheWVyLml0ZW1zWzBdLnF1YW50aXR5KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRkYXRhTGF5ZXIuaXRlbXNbMF0ucXVhbnRpdHkgPSAxO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRkYXRhTGF5ZXIuY3VycmVuY3kgPSBkYXRhTGF5ZXIuaXRlbXNbMF0uY3VycmVuY3k7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUxheWVyLnZhbHVlID0gZGF0YUxheWVyLml0ZW1zWzBdLnByaWNlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGRhdGFMYXllclR5cGUgPT0gJ1NlbGVjdFByb21vdGlvbicpIHtcblx0XHRcdFx0XHRcdFx0ZGVjb3JhdGVEYXRhTGF5ZXJXaXRoUHJvZHVjdERhdGEoZGF0YUxheWVyLCB7XG5cdFx0XHRcdFx0XHRcdFx0RGF0YUxheWVyVmVyc2lvbjogZGF0YUxheWVyVmVyc2lvbixcblx0XHRcdFx0XHRcdFx0XHRDb250YWluZXI6IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXIgPyBvcHRpb25zLkNvbnRhaW5lciA6ICcnXG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdWaWV3SXRlbScpIHtcblx0XHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHRcdERhdGFMYXllclZlcnNpb246IGRhdGFMYXllclZlcnNpb24sXG5cdFx0XHRcdFx0XHRcdFx0XHRDb250YWluZXJTZWxlY3Rvcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yID8gb3B0aW9ucy5Db250YWluZXJTZWxlY3RvciA6ICcnLFxuXHRcdFx0XHRcdFx0XHRcdFx0RmlsdGVyU2VsZWN0b3I6ICcucGRwLWJyb3dzZScsXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0VW5pdmVyc2FsQW5hbHl0aWNzS2V5OiAnZGV0YWlsJ1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChkYXRhTGF5ZXJUeXBlID09ICdWaWV3UHJvbW90aW9uJykge1xuXHRcdFx0XHRcdFx0XHRkZWNvcmF0ZURhdGFMYXllcldpdGhQcm9kdWN0RGF0YShkYXRhTGF5ZXIsIHtcblx0XHRcdFx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uLFxuXHRcdFx0XHRcdFx0XHRcdENvbnRhaW5lcjogb3B0aW9ucyAmJiBvcHRpb25zLkNvbnRhaW5lciA/IG9wdGlvbnMuQ29udGFpbmVyIDogJydcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmVzb2x2ZShkYXRhTGF5ZXIpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmVqZWN0KCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZWplY3QoKTtcblx0XHR9XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBwdXNoRGF0YUxheWVyRm9yRXZlbnQoZXZlbnROYW1lLCBkYXRhT2JqZWN0LCBkYXRhTGF5ZXJUeXBlLCBkYXRhTGF5ZXJWZXJzaW9uKSB7XG5cdHZhciBkYXRhT2JqZWN0ID0gZGF0YU9iamVjdCB8fCB7fTtcblxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG5cdFx0aWYgKGV2ZW50TmFtZSkge1xuXHRcdFx0JC5hamF4KHtcblx0XHRcdFx0dXJsOiBVcmxzLkdvb2dsZVRhZ01hbmFnZXIuR2V0RGF0YUxheWVyLFxuXHRcdFx0XHR0eXBlOiAnUE9TVCcsXG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHREYXRhTGF5ZXJUeXBlOiBkYXRhTGF5ZXJUeXBlIHx8ICdHZW5lcmFsJyxcblx0XHRcdFx0XHREYXRhTGF5ZXJWZXJzaW9uOiBkYXRhTGF5ZXJWZXJzaW9uIHx8ICdVbml2ZXJzYWxBbmFseXRpY3MnXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGRhdGFUeXBlOiAnanNvbicsXG5cdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHR2YXIgZGF0YUxheWVyID0gJC5leHRlbmQoZGF0YU9iamVjdCwgZGF0YSk7XG5cdFx0XHRcdFx0ZGF0YUxheWVyLmV2ZW50ID0gZXZlbnROYW1lO1xuXHRcdFx0XHRcdHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKTtcblx0XHRcdFx0XHRyZXNvbHZlKGRhdGFMYXllcik7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZWplY3QoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlamVjdCgpO1xuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIGRlY29yYXRlRGF0YUxheWVyV2l0aFByb2R1Y3REYXRhKGRhdGFMYXllciwgb3B0aW9ucykge1xuXHR2YXIgdW5pdmVyc2FsQW5hbHl0aWNzS2V5ID0gb3B0aW9ucyAmJiBvcHRpb25zLlVuaXZlcnNhbEFuYWx5dGljc0tleSA/IG9wdGlvbnMuVW5pdmVyc2FsQW5hbHl0aWNzS2V5IDogJyc7XG5cblx0aWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5EYXRhTGF5ZXJWZXJzaW9uID09ICdHb29nbGVBbmFseXRpY3M0Jykge1xuXHRcdGRhdGFMYXllci5pdGVtcyA9IGdldFByb2R1Y3REYXRhTGF5ZXIoJ2RhdGEtcHJvZHVjdC1nYTQtanNvbicsIG9wdGlvbnMpO1xuXHR9IGVsc2Uge1xuXHRcdGRhdGFMYXllci5lY29tbWVyY2UgPSBkYXRhTGF5ZXIuZWNvbW1lcmNlIHx8IHt9O1xuXHRcdGRhdGFMYXllci5lY29tbWVyY2VbdW5pdmVyc2FsQW5hbHl0aWNzS2V5XSA9IGRhdGFMYXllci5lY29tbWVyY2VbdW5pdmVyc2FsQW5hbHl0aWNzS2V5XSB8fCB7fTtcblx0XHRkYXRhTGF5ZXIuZWNvbW1lcmNlW3VuaXZlcnNhbEFuYWx5dGljc0tleV0ucHJvZHVjdHMgPSBnZXRQcm9kdWN0RGF0YUxheWVyKG51bGwsIG9wdGlvbnMpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGdldFByb2R1Y3REYXRhTGF5ZXIoYXR0cmlidXRlSWRQYXJhbWV0ZXIsIG9wdGlvbnMpIHtcblx0dmFyIGRhdGFMYXllclByb2R1Y3RzID0gd2luZG93LmRhdGFMYXllclByb2R1Y3RzIHx8IFtdO1xuXHR2YXIgYXR0cmlidXRlSWQgPSBhdHRyaWJ1dGVJZFBhcmFtZXRlciB8fCAnZGF0YS1wcm9kdWN0LWd0bS1qc29uJztcblx0dmFyIGNvbnRhaW5lciA9IG9wdGlvbnMgJiYgb3B0aW9ucy5Db250YWluZXIgPyBvcHRpb25zLkNvbnRhaW5lciA6ICcnO1xuXHR2YXIgY29udGFpbmVyU2VsZWN0b3IgPSBvcHRpb25zICYmIG9wdGlvbnMuQ29udGFpbmVyU2VsZWN0b3IgPyBvcHRpb25zLkNvbnRhaW5lclNlbGVjdG9yIDogJyc7XG5cdHZhciBmaWx0ZXJTZWxlY3RvciA9IG9wdGlvbnMgJiYgb3B0aW9ucy5GaWx0ZXJTZWxlY3RvciA/IG9wdGlvbnMuRmlsdGVyU2VsZWN0b3IgOiAnJztcblxuXHR2YXIgJHByb2R1Y3RDYXJkcztcblx0aWYgKGNvbnRhaW5lcikge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSBjb250YWluZXIuZmluZCgnWycgKyBhdHRyaWJ1dGVJZCArICddJyArIGZpbHRlclNlbGVjdG9yKTtcblx0fSBlbHNlIGlmIChjb250YWluZXJTZWxlY3Rvcikge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSAkKGNvbnRhaW5lclNlbGVjdG9yKS5maW5kKCdbJyArIGF0dHJpYnV0ZUlkICsgJ10nICsgZmlsdGVyU2VsZWN0b3IpO1xuXHR9IGVsc2Uge1xuXHRcdCRwcm9kdWN0Q2FyZHMgPSAkKCdbJyArIGF0dHJpYnV0ZUlkICsgJ10nICsgZmlsdGVyU2VsZWN0b3IpO1xuXHR9XG5cdCRwcm9kdWN0Q2FyZHMuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuXHRcdHZhciAkZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cblx0XHR2YXIgc2xpY2tJbmRleCA9IG51bGw7XG5cdFx0dmFyIGlzVmFsaWQgPSB0cnVlO1xuXHRcdGlmICgkZWxlbWVudC5jbG9zZXN0KCdbZGF0YS1zbGljay1pbmRleF0nKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRzbGlja0luZGV4ID0gcGFyc2VJbnQoJGVsZW1lbnQuY2xvc2VzdCgnW2RhdGEtc2xpY2staW5kZXhdJykuZGF0YSgnc2xpY2staW5kZXgnKSwgMTApICsgMTtcblx0XHRcdGlmIChzbGlja0luZGV4IDwgMSkge1xuXHRcdFx0XHRpc1ZhbGlkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGlzVmFsaWQpIHtcblx0XHRcdHZhciBqc29uT2JqZWN0ID0gSlNPTi5wYXJzZSgkZWxlbWVudC5hdHRyKGF0dHJpYnV0ZUlkKSk7XG5cdFx0XHRpZiAoYXR0cmlidXRlSWQgPT0gJ2RhdGEtcHJvZHVjdC1ndG0tanNvbicpIHtcblx0XHRcdFx0anNvbk9iamVjdC5wb3NpdGlvbiA9IGluZGV4O1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0anNvbk9iamVjdC5pbmRleCA9IGluZGV4O1xuXHRcdFx0fVxuXHRcdFx0ZGF0YUxheWVyUHJvZHVjdHMucHVzaChqc29uT2JqZWN0KTtcblx0XHR9XG5cdH0pO1xuXHRcdFxuXHRyZXR1cm4gZGF0YUxheWVyUHJvZHVjdHM7XG59XG5cbmZ1bmN0aW9uIHB1c2hEYXRhTGF5ZXIoZGF0YUxheWVyKSB7XG5cdHZhciBpc0NhcnRQYWdlID0gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucyAmJiBwYWdlQ29udGV4dC5vcHRpb25zLmlzQ2FydFBhZ2U7XG5cdHZhciBpc0NoZWNrb3V0UGFnZSA9IHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5pc0NoZWNrb3V0UGFnZTtcblx0dmFyIGlzQ29uZmlybWF0aW9uUGFnZSA9IHBhZ2VDb250ZXh0ICYmIHBhZ2VDb250ZXh0Lm9wdGlvbnMgJiYgcGFnZUNvbnRleHQub3B0aW9ucy5pc0NvbmZpcm1hdGlvblBhZ2U7XG5cdHZhciByZWFjdERhdGFMYXllclBhZ2VzID0gcGFnZUNvbnRleHQgJiYgcGFnZUNvbnRleHQub3B0aW9ucyAmJiBwYWdlQ29udGV4dC5vcHRpb25zLk1vYmlsZUFwcCAmJiBwYWdlQ29udGV4dC5vcHRpb25zLk1vYmlsZUFwcC5SZWFjdERhdGFMYXllclBhZ2VzID8gcGFnZUNvbnRleHQub3B0aW9ucy5Nb2JpbGVBcHAuUmVhY3REYXRhTGF5ZXJQYWdlcyA6IFtdO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDYXJ0ID0gaXNDYXJ0UGFnZSAmJiByZWFjdERhdGFMYXllclBhZ2VzLmluZGV4T2YoJ0NhcnQnKSA+IC0xO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDaGVja291dCA9IGlzQ2hlY2tvdXRQYWdlICYmIHJlYWN0RGF0YUxheWVyUGFnZXMuaW5kZXhPZignQ2hlY2tvdXQnKSA+IC0xO1xuXHR2YXIgc2VuZFJlYWN0RXZlbnRGb3JDb25maXJtYXRpb24gPSBpc0NvbmZpcm1hdGlvblBhZ2UgJiYgcmVhY3REYXRhTGF5ZXJQYWdlcy5pbmRleE9mKCdDb25maXJtYXRpb24nKSA+IC0xO1xuXG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cgJiYgKHNlbmRSZWFjdEV2ZW50Rm9yQ2FydCB8fCBzZW5kUmVhY3RFdmVudEZvckNoZWNrb3V0IHx8IHNlbmRSZWFjdEV2ZW50Rm9yQ29uZmlybWF0aW9uKSkge1xuXHRcdHRyaWdnZXJSZWFjdFdlYnZpZXdFdmVudChkYXRhTGF5ZXIuZXZlbnQsIGRhdGFMYXllcik7XG5cdH0gZWxzZSB7XG5cdFx0d2luZG93LmRhdGFMYXllci5wdXNoKGRhdGFMYXllcik7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJpZ2dlclJlYWN0V2Vidmlld0V2ZW50KGFjdGlvbiwgZGF0YUxheWVyKSB7XG5cdGlmICgnUmVhY3ROYXRpdmVXZWJWaWV3JyBpbiB3aW5kb3cpIHtcblx0XHR2YXIgbWVzc2FnZSA9ICB7XG5cdFx0XHRhY3Rpb246IGFjdGlvblxuXHRcdH1cblx0XHRpZiAoZGF0YUxheWVyKSB7XG5cdFx0XHRtZXNzYWdlLmRhdGFMYXllciA9IGRhdGFMYXllcjtcblx0XHR9XG5cblx0XHR3aW5kb3cuUmVhY3ROYXRpdmVXZWJWaWV3LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpKTtcblx0fVxufSIsIid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zID0gcmVxdWlyZSgnLi4vLi4vanMvUmVnZXhQYXR0ZXJucycpLlZhbGlkYXRpb247XG52YXIgU3RhdGVUb1ppcENvZGVNYXAgPSByZXF1aXJlKCcuLi8uLi9kYXRhL1N0YXRlVG9aaXBDb2RlTWFwLmpzb24nKTtcblxuZXhwb3J0cy5WYWxpZGF0ZVJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24gPSB2YWxpZGF0ZVJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb247XG5leHBvcnRzLlZhbGlkYXRlT3JkZXJOdW1iZXIgPSB2YWxpZGF0ZU9yZGVyTnVtYmVyO1xuZXhwb3J0cy5WYWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94ID0gdmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveDtcbmV4cG9ydHMuVmFsaWRhdGVBZGRyZXNzRm9yUG9zdE9mZmljZUJveE9ubHkgPSB2YWxpZGF0ZUFkZHJlc3NGb3JQb3N0T2ZmaWNlQm94T25seTtcbmV4cG9ydHMuVmFsaWRhdGVQb3N0YWxDb2RlID0gdmFsaWRhdGVQb3N0YWxDb2RlO1xuZXhwb3J0cy5WYWxpZGF0ZVppcENvZGUgPSB2YWxpZGF0ZVppcENvZGU7XG5leHBvcnRzLlZhbGlkYXRlWmlwQ29kZVByZWZpeEZvclN0YXRlQ29kZSA9IHZhbGlkYXRlWmlwQ29kZVByZWZpeEZvclN0YXRlQ29kZTtcbmV4cG9ydHMuVmFsaWRhdGVaaXBDb2RlUHJlZml4Rm9yU3RhdGVDb2RlVmFsdWVzID0gdmFsaWRhdGVaaXBDb2RlUHJlZml4Rm9yU3RhdGVDb2RlVmFsdWVzO1xuZXhwb3J0cy5WYWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUgPSB2YWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmU7XG5leHBvcnRzLlZhbGlkYXRlR2lmdENhcmROdW1iZXJMZW5ndGggPSB2YWxpZGF0ZUdpZnRDYXJkTnVtYmVyTGVuZ3RoO1xuZXhwb3J0cy5WYWxpZGF0ZUdpZnRDYXJkTnVtYmVyVmFsdWVzID0gdmFsaWRhdGVHaWZ0Q2FyZE51bWJlclZhbHVlcztcblxuZnVuY3Rpb24gdmFsaWRhdGVSZXF1aXJlZEV4Y2x1ZGluZ1B1bmN0dWF0aW9uKHZhbHVlLCBlbGVtZW50KSB7XG4gICAgcmV0dXJuIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zLlJlcXVpcmVkRXhjbHVkaW5nUHVuY3R1YXRpb24udGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3JkZXJOdW1iZXIodmFsdWUsIGVsZW1lbnQpIHtcbiAgICByZXR1cm4gUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuT3JkZXJOdW1iZXIudGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3godmFsdWUsIGVsZW1lbnQpIHtcblx0cmV0dXJuICFSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5Qb3N0T2ZmaWNlQm94LnRlc3QoKHZhbHVlICsgJycpLnRyaW0oKSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQWRkcmVzc0ZvclBvc3RPZmZpY2VCb3hPbmx5KHZhbHVlLCBlbGVtZW50KSB7XG5cdHZhciBhZGRyZXNzMSA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKCk7XG5cdHZhciBhZGRyZXNzMiA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCk7XG5cblx0cmV0dXJuICghUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuUG9zdE9mZmljZUJveC50ZXN0KChhZGRyZXNzMSArICcnKS50cmltKCkpICYmICFSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5Qb3N0T2ZmaWNlQm94LnRlc3QoKGFkZHJlc3MyICsgJycpLnRyaW0oKSkpIHx8ICghYWRkcmVzczEgfHwgIWFkZHJlc3MyKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVQb3N0YWxDb2RlKHZhbHVlLCBlbGVtZW50KSB7XG4gICAgcmV0dXJuIFJlZ2V4VmFsaWRhdGlvblBhdHRlcm5zLlBvc3RhbENvZGUudGVzdCgodmFsdWUgKyAnJykudHJpbSgpKTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlWmlwQ29kZSh2YWx1ZSwgZWxlbWVudCkge1xuICAgIHJldHVybiBSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5aaXBDb2RlLnRlc3QoKHZhbHVlICsgJycpLnRyaW0oKSk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVppcENvZGVQcmVmaXhGb3JTdGF0ZUNvZGUodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIHppcENvZGVQcmVmaXggPSB2YWx1ZS5zdWJzdHIoMCwzKTtcblx0dmFyIHN0YXRlQ29kZSA9ICQoZWxlbWVudCkuY2xvc2VzdCgnZm9ybScpLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZXNfc3RhdGVcIl0nKS52YWwoKS50b1VwcGVyQ2FzZSgpO1xuXHRpZiAoc3RhdGVDb2RlICYmIFN0YXRlVG9aaXBDb2RlTWFwICYmIFN0YXRlVG9aaXBDb2RlTWFwW3N0YXRlQ29kZV0pIHtcblx0XHRyZXR1cm4gU3RhdGVUb1ppcENvZGVNYXBbc3RhdGVDb2RlXVt6aXBDb2RlUHJlZml4XTtcblx0fVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVppcENvZGVQcmVmaXhGb3JTdGF0ZUNvZGVWYWx1ZXMoemlwQ29kZSwgc3RhdGVDb2RlKSB7XG5cdHZhciB6aXBDb2RlUHJlZml4ID0gemlwQ29kZS5zdWJzdHIoMCwzKTtcblx0aWYgKFN0YXRlVG9aaXBDb2RlTWFwICYmIFN0YXRlVG9aaXBDb2RlTWFwW3N0YXRlQ29kZV0pIHtcblx0XHRyZXR1cm4gU3RhdGVUb1ppcENvZGVNYXBbc3RhdGVDb2RlXVt6aXBDb2RlUHJlZml4XTtcblx0fVxuXG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVN0YXRlQ29kZUZvckNhbGlmb3JuaWFTdGF0ZUxpbmUodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIHN0YXRlQ29kZUZvclN0b3JlID0gJChlbGVtZW50KS5jbG9zZXN0KCdbc3RvcmUtc3RhdGVdJykuYXR0cignc3RvcmUtc3RhdGUnKTtcblxuXHRpZiAoKHZhbHVlICE9ICdDQScgJiYgc3RhdGVDb2RlRm9yU3RvcmUgIT0gJ0NBJykgfHwgdmFsdWUgPT0gc3RhdGVDb2RlRm9yU3RvcmUpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlR2lmdENhcmROdW1iZXJMZW5ndGgodmFsdWUsIGVsZW1lbnQpIHtcblx0dmFyIGRpZ2l0cyA9ICh2YWx1ZSArICcnKS50cmltKCkubWF0Y2goUmVnZXhWYWxpZGF0aW9uUGF0dGVybnMuR2lmdENhcmROdW1iZXJMZW5ndGgpO1xuXHRyZXR1cm4gZGlnaXRzICYmIGRpZ2l0cy5sZW5ndGggPT0gMTk7XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUdpZnRDYXJkTnVtYmVyVmFsdWVzKHZhbHVlLCBlbGVtZW50KSB7XG5cdHJldHVybiBSZWdleFZhbGlkYXRpb25QYXR0ZXJucy5HaWZ0Q2FyZE51bWJlclZhbHVlcy50ZXN0KCh2YWx1ZSArICcnKS50cmltKCkpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuU2xpY2tTbGlkZXIgPSB7XG5cdE9wdGlvbnM6IHtcblx0XHRTaW5nbGU6IHtcblx0XHRcdGluZmluaXRlOiBcdFx0dHJ1ZSxcblx0XHRcdGRvdHM6IFx0XHRcdGZhbHNlLFxuXHRcdFx0YXJyb3dzOiBcdFx0ZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IFx0MSxcblx0XHRcdHNsaWRlc1RvU2Nyb2xsOiAxLFxuXHRcdFx0cmVzcG9uc2l2ZTogXHRbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiA3NjcsXG5cdFx0XHRcdFx0c2V0dGluZ3M6IFx0e1xuXHRcdFx0XHRcdFx0ZG90czogXHR0cnVlLFxuXHRcdFx0XHRcdFx0YXJyb3dzOiB0cnVlXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMFxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSxcblx0XHRUaHVtYm5haWw6IHtcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiBmYWxzZSxcblx0XHRcdGZvY3VzT25TZWxlY3Q6IFx0ZmFsc2UsXG5cdFx0XHRkb3RzOiBmYWxzZSxcblx0XHRcdGFycm93czogZmFsc2UsXG5cdFx0XHRzbGlkZXNUb1Nob3c6IDcsXG5cdFx0XHRzbGlkZXNUb1Njcm9sbDogNyxcblx0XHRcdHJlc3BvbnNpdmU6IFx0W1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogNzY3XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRicmVha3BvaW50OiAxMjAwLFxuXHRcdFx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Nob3c6IDQsXG5cdFx0XHRcdFx0XHRzbGlkZXNUb1Njcm9sbDogNFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0vKixcblx0XHRDYXRlZ29yeUxhbmRpbmc6IHtcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcblx0XHRcdGluZmluaXRlOiB0cnVlLFxuXHRcdFx0Zm9jdXNPblNlbGVjdDogXHRmYWxzZSxcblx0XHRcdGRvdHM6IGZhbHNlLFxuXHRcdFx0YXJyb3dzOiB0cnVlLFxuXHRcdFx0c2xpZGVzVG9TaG93OiA0LFxuXHRcdFx0c2xpZGVzVG9TY3JvbGw6IDQsXG5cdFx0XHRyZXNwb25zaXZlOiBcdFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGJyZWFrcG9pbnQ6IDc2N1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YnJlYWtwb2ludDogMTIwMCxcblx0XHRcdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRcdFx0c2xpZGVzVG9TaG93OiAzLFxuXHRcdFx0XHRcdFx0c2xpZGVzVG9TY3JvbGw6IDNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9Ki9cblx0fVxufSIsIi8qIEdsb2JhbCBWYXJpYWJsZXMgKi9cbnZhciBoZWxwZXIgPSByZXF1aXJlKCcuLi9oZWxwZXJzL3Nob3BwYXlIZWxwZXInKTtcbnZhciBpc0J1eU5vdyA9IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcyA/IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cgOiBudWxsO1xudmFyIGlzQUFUZXN0ID0gd2luZG93LnNob3BwYXlDbGllbnRSZWZzICYmIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5QUFUZXN0ID8gd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlBQVRlc3QgOiBmYWxzZTtcbnZhciBzZXNzaW9uO1xuXG4kKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHdpbmRvdy5TaG9wUGF5KSB7XG4gICAgICAgIGluaXRTaG9wUGF5Q29uZmlnKCk7XG5cdFx0aWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5RW1haWxMaXN0ZW5lckVuYWJsZWQgJiYgJCgnLnNob3BpZnktZW1haWwtbGlzdGVuZXInKS5sZW5ndGgpIHtcblx0XHRcdGluaXRTaG9wUGF5RW1haWxSZWNvZ25pdGlvbigpO1xuXHRcdH1cblx0XHRpbml0U2hvcFBheUJ1dHRvbigpO1xuICAgICAgICB2YXIgcmVhZHlPblBhZ2VMb2FkID0gaGVscGVyLmlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCgpO1xuICAgICAgICBpZiAocmVhZHlPblBhZ2VMb2FkKSB7XG4gICAgICAgICAgICB2YXIgcGFnZUxvYWREYXRhID0gaGVscGVyLmdldEluaXRQcm9kdWN0RGF0YSgpO1xuICAgICAgICAgICAgaGVscGVyLnNldEluaXRQcm9kdWN0RGF0YShwYWdlTG9hZERhdGEpOyAvLyB1cGRhdGVzIGdsb2JhbCBwcm9kIGRhdGEuXG4gICAgICAgIH1cblxuICAgICAgICAvKiAgVGhlIGJlbG93IGNvZGUgdHJpZ2dlcnMgaWYgYSBwcm9kdWN0IGlzIGEgQnV5IE5vdyBpdGVtLCBidXQgaXMgbm90IHJlYWR5IHRvIG9yZGVyIG9uIHBhZ2UgbG9hZFxuICAgICAgICAgICAgKGV4OiByZXF1aXJlZCBwcm9kdWN0IGF0dHJpYnV0ZXMgbGlrZSBjb2xvciBvciBzaXplIGFyZSBub3QgeWV0IGNob3NlbikuIEhlcmUsIGEgd2F0Y2hlciBpcyBzZXRcbiAgICAgICAgICAgIHRvIGNhcHR1cmUgdXNlciBpbnRlcmFjdGlvbnMgd2hlbiBwcm9kdWN0IGF0dHJpYnV0ZXMgYXJlIHNlbGVjdGVkLiBIZWxwZXIgc2NyaXB0cyB3aWxsIGJlIHRyaWdnZXJlZFxuICAgICAgICAgICAgYnkgdGhlc2UgaW50ZXJhY3Rpb25zIHRvIGRldGVybWluZSBpZiB0aGUgaXRlbSBpcyByZWFkeSB0byBvcmRlciB3aGVuIGFsbCByZXF1aXJlZCBhdHRyaWJ1dGVzIGFyZVxuICAgICAgICAgICAgc2VsZWN0ZWQuXG4gICAgICAgICovXG4gICAgICAgIGlmIChpc0J1eU5vdyAmJiAhcmVhZHlPblBhZ2VMb2FkKSB7XG4gICAgICAgICAgICAkKCdib2R5Jykub24oJ3Byb2R1Y3Q6YWZ0ZXJBdHRyaWJ1dGVTZWxlY3QnLCBpbml0QnV5Tm93KTsgLy8gcmVjZWl2ZXMgdGhlIEV2ZW50ICYgUmVzcG9uc2VcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXHQkKGRvY3VtZW50KS5vbignQ2FydC5VcGRhdGVTdWNjZXNzJywgZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHdpbmRvdy5TaG9wUGF5ICYmICFpc0J1eU5vdykge1xuXHRcdFx0aWYgKCFzZXNzaW9uKSB7XG5cdFx0XHRcdHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlID0gaGVscGVyLmJ1aWxkUGF5bWVudFJlcXVlc3Qoc2Vzc2lvbik7XG5cdFx0XHRcdHZhciByZXNwb25zZUpTT04gPSAgcGF5bWVudFJlcXVlc3RSZXNwb25zZSA/IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UucmVzcG9uc2VKU09OIDogbnVsbDtcblx0XG5cdFx0XHRcdGlmIChyZXNwb25zZUpTT04pIHtcblx0XHRcdFx0XHRoZWxwZXIuc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzaG9wLXBheS1idXR0b24tY29udGFpbmVyXCIpKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0aWYgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCAhPT0gbnVsbCkge1xuXHRcdFx0XHRcdHNlc3Npb24uY2xvc2UoKTtcblx0XHRcdFx0XHRzZXNzaW9uID0gaW5pdFNob3BQYXlTZXNzaW9uKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufSk7XG5cbmZ1bmN0aW9uIGluaXRTaG9wUGF5Q29uZmlnKCkge1xuICAgIHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNvbmZpZ3VyZSh7XG4gICAgICAgIHNob3BJZDogd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlTdG9yZUlkLFxuICAgICAgICBjbGllbnRJZDogd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnByZWZlcmVuY2VzLnNob3BwYXlDbGllbnRJZCxcbiAgICAgICAgZGVidWc6IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5wcmVmZXJlbmNlcy5zaG9wcGF5TW9kYWxEZWJ1Z0VuYWJsZWRcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdFNob3BQYXlCdXR0b24oKSB7XG5cdHZhciBwYXltZW50U2VsZWN0b3JzID0gWycjc2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lcicsICcjc2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lci1tb2JpbGUnLCAnI3Nob3AtcGF5LWJ1dHRvbi1jb250YWluZXItZGVza3RvcCddXG5cdGZvciAodmFyIHBheW1lbnRTZWxlY3RvckluZGV4IGluIHBheW1lbnRTZWxlY3RvcnMpIHtcblx0XHR2YXIgcGF5bWVudFNlbGVjdG9yID0gcGF5bWVudFNlbGVjdG9yc1twYXltZW50U2VsZWN0b3JJbmRleF07XG5cdFx0aWYgKCQocGF5bWVudFNlbGVjdG9yKS5sZW5ndGggPiAwKSB7XG5cdFx0XHR3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5jcmVhdGVCdXR0b24oe2J1eVdpdGg6IGlzQnV5Tm93fSkucmVuZGVyKHBheW1lbnRTZWxlY3Rvcik7XG5cdFx0XHRoZWxwZXIuc2hvcHBheU11dGF0aW9uT2JzZXJ2ZXIocGF5bWVudFNlbGVjdG9yKTtcblx0XHR9XG5cdH1cbn1cblxuXG5mdW5jdGlvbiBpbml0QnV5Tm93KGUsIHJlc3BvbnNlKSB7XG4gICAgdmFyIHJlc3BvbnNlUHJvZHVjdCA9IHJlc3BvbnNlLmRhdGEucHJvZHVjdDtcbiAgICB2YXIgeyBidXlOb3csIHJlYWR5VG9PcmRlciwgaWQsIHNlbGVjdGVkUXVhbnRpdHksIG9wdGlvbnMsIGNoaWxkUHJvZHVjdHMgfSA9IHJlc3BvbnNlUHJvZHVjdDtcblxuICAgIGlmIChyZXNwb25zZVByb2R1Y3QgJiYgYnV5Tm93KSB7XG4gICAgICAgIGlmIChyZWFkeVRvT3JkZXIpIHtcbiAgICAgICAgICAgIGluaXRTaG9wUGF5U2Vzc2lvbihidXlOb3csIHJlYWR5VG9PcmRlcik7XG4gICAgICAgICAgICBoZWxwZXIuc2V0SW5pdFByb2R1Y3REYXRhKHtcbiAgICAgICAgICAgICAgICBwaWQ6IGlkLFxuICAgICAgICAgICAgICAgIHF1YW50aXR5OiBzZWxlY3RlZFF1YW50aXR5LFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGNoaWxkUHJvZHVjdHMpIHtcbiAgICAgICAgICAgICAgICBoZWxwZXIucHJvZHVjdERhdGEuY2hpbGRQcm9kdWN0cyA9IGNoaWxkUHJvZHVjdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGluaXRTaG9wUGF5RW1haWxSZWNvZ25pdGlvbigpIHtcbiAgICAvKiAgSWYgeW91ciBjaGVja291dCBpcyBub3QgYnVpbHQgd2l0aCBTRlJBIG9yIHlvdSBoYXZlIGN1c3RvbWl6ZWQgYW5kIHJlbW92ZWQgdGhlICdlbWFpbC1ndWVzdCdcbiAgICAgICAgaWQgb24gdGhlIGVtYWlsIGlucHV0IHlvdSB3aWxsIG5lZWQgdG8gdXBkYXRlIHRoZSBpZCB2YWx1ZSBmb3IgZW1haWxJbnB1dElkXG5cbiAgICAgICAgTm90ZTogQSAxLjUgc2Vjb25kIGRlbGF5IGhhcyBiZWVuIGFkZGVkIGJlZm9yZSBhdHRhY2hpbmcgdG8gdGhlIGVtYWlsIHRyaWdnZXIgdG8gdGhlIGVtYWlsIGZpZWxkIHRvXG4gICAgICAgIGFjY29tbW9kYXRlIHVzZXJzIHdobyBtYXkgaGF2ZSBpbmNvcnBvcmF0ZWQgYnJvd3NlciBhdXRvZmlsbHMuIFRoZSBwb3AtdXAgd2lsbCBhcHBlYXIgaWYgdGhlIGZpZWxkXG4gICAgICAgIGlzIGF1dG9maWxsZWQgd2l0aCBhIHJlY29nbml6ZWQgZW1haWwgYWRkcmVzc1xuICAgICovXG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHQkKCcuc2hvcGlmeS1lbWFpbC1saXN0ZW5lcjp2aXNpYmxlJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNyZWF0ZUxvZ2luKHtlbWFpbElucHV0SWQ6ICQodGhpcykuYXR0cignaWQnKX0pLnJlbmRlcignI3Nob3AtcGF5LWxvZ2luLWNvbnRhaW5lcicpO1xuXHRcdH0pO1xuICAgIH0sIDE1MDApO1xufVxuXG4kKCdib2R5Jykub24oJ2NhcnQ6dXBkYXRlIHByb2R1Y3Q6YWZ0ZXJBZGRUb0NhcnQgcHJvbW90aW9uOnN1Y2Nlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgLyogIE9ubHkgaW50ZXJlc3RlZCBpbiBjYXJ0IHVwZGF0ZXMgb24gQ2FydCBwYWdlIChjYXJ0IHVwZGF0ZXMgYXJlIG5vdCB0cmlnZ2VyZWQgaW4gY2hlY2tvdXQpLiBCdXkgTm93IGFscmVhZHlcbiAgICAgICAgaGFzIGEgc2VwYXJhdGUgZXZlbnQgaGFuZGxlciBmb3IgY2hhbmdlcyB0byBhdHRyaWJ1dGUgc2VsZWN0aW9uc1xuICAgICovXG4gICAgaWYgKHdpbmRvdy5TaG9wUGF5ICYmICFpc0J1eU5vdykge1xuICAgICAgICBpZiAoIXNlc3Npb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24gPSBpbml0U2hvcFBheVNlc3Npb24oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlID0gaGVscGVyLmJ1aWxkUGF5bWVudFJlcXVlc3Qoc2Vzc2lvbik7XG4gICAgICAgICAgICB2YXIgcmVzcG9uc2VKU09OID0gIHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPyBwYXltZW50UmVxdWVzdFJlc3BvbnNlLnJlc3BvbnNlSlNPTiA6IG51bGw7XG5cbiAgICAgICAgICAgIGlmIChyZXNwb25zZUpTT04pIHtcbiAgICAgICAgICAgICAgICBoZWxwZXIuc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzaG9wLXBheS1idXR0b24tY29udGFpbmVyXCIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uID0gaW5pdFNob3BQYXlTZXNzaW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxuXG5mdW5jdGlvbiBpbml0U2hvcFBheVNlc3Npb24ocGF5bWVudFJlcXVlc3RJbnB1dCwgcmVhZHlUb09yZGVyKSB7XG4gICAgdmFyIHBheW1lbnRSZXF1ZXN0O1xuICAgIHZhciBwYXltZW50UmVxdWVzdFJlc3BvbnNlO1xuICAgIHZhciByZXNwb25zZUpTT047XG5cbiAgICBpZiAoaXNCdXlOb3cgJiYgcGF5bWVudFJlcXVlc3RJbnB1dCkge1xuICAgICAgICBwYXltZW50UmVxdWVzdCA9IHBheW1lbnRSZXF1ZXN0SW5wdXQ7XG4gICAgfSBlbHNlIGlmIChpc0J1eU5vdyAmJiAhcGF5bWVudFJlcXVlc3RJbnB1dCkge1xuICAgICAgICB2YXIgcHJvZHVjdERhdGEgPSBoZWxwZXIuZ2V0SW5pdFByb2R1Y3REYXRhKCk7XG4gICAgICAgIGlmIChwcm9kdWN0RGF0YSkge1xuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3RSZXNwb25zZSA9IGhlbHBlci5jcmVhdGVSZXNwb25zZShwcm9kdWN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuQnV5Tm93RGF0YSk7XG4gICAgICAgICAgICBpZiAocGF5bWVudFJlcXVlc3RSZXNwb25zZS5leGNlcHRpb24gfHwgcGF5bWVudFJlcXVlc3RSZXNwb25zZS5lcnJvcil7XG4gICAgICAgICAgICAgICAgLyogIE5vIG5lZWQgdG8gY2xvc2UgYW55IHNlc3Npb24gYmVjYXVzZSBhIHNlc3Npb24gZG9lcyBub3QgZXhpc3QgYXQgdGhpcyBwb2ludCAoaGFzIG5vdCB5ZXQgYmVlblxuICAgICAgICAgICAgICAgICAgICBpbml0aWF0ZWQpLiBSZXR1cm4gdG8gZXhpdCBmdW5jdGlvbiAtIGRvbid0IHJlbG9hZCB0aGUgcGFnZSBpbiBjYXNlIHRoZXJlIGlzIGEgcGFnZSByZW5kZXJpbmdcbiAgICAgICAgICAgICAgICAgICAgaXNzdWUgKHdpbGwgcmVzdWx0IGluIGluZmluaXRlIHJlbG9hZCBsb29wKS5cbiAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0ID0gcGF5bWVudFJlcXVlc3RSZXNwb25zZS5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgICAgIHJlc3BvbnNlSlNPTiA9IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPyBwYXltZW50UmVxdWVzdFJlc3BvbnNlIDogbnVsbDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UgPSBoZWxwZXIuYnVpbGRQYXltZW50UmVxdWVzdChzZXNzaW9uKTtcbiAgICAgICAgcmVzcG9uc2VKU09OID0gcGF5bWVudFJlcXVlc3RSZXNwb25zZSA/IHBheW1lbnRSZXF1ZXN0UmVzcG9uc2UucmVzcG9uc2VKU09OIDogbnVsbDtcbiAgICB9XG5cbiAgICBpZiAocGF5bWVudFJlcXVlc3QgfHwgKHJlc3BvbnNlSlNPTiAmJiAhcmVzcG9uc2VKU09OLmVycm9yKSkge1xuICAgICAgICB2YXIgaW5pdGlhbFBheW1lbnRSZXF1ZXN0ID0gcmVzcG9uc2VKU09OICYmIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCA/IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCkgOiB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZChwYXltZW50UmVxdWVzdCk7XG4gICAgICAgIC8vIEVuYWJsZSBCdXlOb3cgQnV0dG9uIENsaWNrIG9uIFBEUCBpZiBQcm9kdWN0IGlzIFJlYWR5IFRvIE9yZGVyXG4gICAgICAgIGhlbHBlci5zaG9wcGF5QnRuRGlzYWJsZWRTdHlsZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNob3AtcGF5LWJ1dHRvbi1jb250YWluZXJcIiksIHJlYWR5VG9PcmRlcik7XG5cbiAgICAgICAgdmFyIHNob3BwYXlTZXNzaW9uID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuY3JlYXRlU2Vzc2lvbih7XG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogaW5pdGlhbFBheW1lbnRSZXF1ZXN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChzaG9wcGF5U2Vzc2lvbikge1xuICAgICAgICAgICAgaGVscGVyLnNldFNlc3Npb25MaXN0ZW5lcnMoc2hvcHBheVNlc3Npb24pO1xuICAgICAgICAgICAgJCgnYm9keScpLm9mZigncHJvZHVjdDphZnRlckF0dHJpYnV0ZVNlbGVjdCcsIGluaXRCdXlOb3cpO1xuXG4gICAgICAgICAgICAkKCdib2R5Jykub24oJ3Byb2R1Y3Q6YWZ0ZXJBdHRyaWJ1dGVTZWxlY3QnLCBmdW5jdGlvbihlLCByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIHZhciByZXNwb25zZVByb2R1Y3QgPSByZXNwb25zZS5kYXRhLnByb2R1Y3Q7XG4gICAgICAgICAgICAgICAgaWYgKGlzQnV5Tm93ICYmIHJlc3BvbnNlUHJvZHVjdC5idXlOb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVscGVyLnNldEluaXRQcm9kdWN0RGF0YSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwaWQ6IHJlc3BvbnNlUHJvZHVjdC5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1YW50aXR5OiByZXNwb25zZVByb2R1Y3Quc2VsZWN0ZWRRdWFudGl0eSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHJlc3BvbnNlUHJvZHVjdC5vcHRpb25zXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvcHBheVNlc3Npb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3BwYXlTZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQocmVzcG9uc2VQcm9kdWN0LmJ1eU5vdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG9wcGF5U2Vzc2lvbiA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmNyZWF0ZVNlc3Npb24oe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiB1cGRhdGVkUGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWxwZXIuc2V0U2Vzc2lvbkxpc3RlbmVycyhzaG9wcGF5U2Vzc2lvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IGhlbHBlci5nZXRVcmxXaXRoQ3NyZlRva2VuKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLkdldENhcnRTdW1tYXJ5KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzeW5jOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaG9wcGF5U2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvcHBheVNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF5bWVudFJlcXVlc3QgPSB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZChyZXNwb25zZS5wcm9kdWN0LmJ1eU5vdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3BwYXlTZXNzaW9uID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuY3JlYXRlU2Vzc2lvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50UmVxdWVzdDogcGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlbHBlci5zZXRTZXNzaW9uTGlzdGVuZXJzKHNob3BwYXlTZXNzaW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLnJlc3BvbnNlSlNPTiB8fCBlcnIuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2RhbCBoYXNuJ3Qgb3BlbmVkIHlldCBzbyBcIndpbmRvd2Nsb3NlZFwiIGxpc3RlbmVyIHdvbid0IGZpcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaG9wcGF5U2Vzc2lvbjtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGluaXRTaG9wUGF5U2Vzc2lvbjogaW5pdFNob3BQYXlTZXNzaW9uXG59OyIsIi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4vKiBHbG9iYWwgVmFyaWFibGVzICovXG5sZXQgY2hlY2tvdXRVcmwgPSBudWxsO1xubGV0IG9ic2VydmVyO1xubGV0IG9yZGVyQ29uZmlybWF0aW9uRGF0YTtcbmxldCBwcm9kdWN0RGF0YSA9IHt9O1xubGV0IHJlbG9hZE9uQ2xvc2UgPSB0cnVlO1xubGV0IHNvdXJjZUlkZW50aWZpZXIgPSBudWxsO1xuY29uc3QgdGVjaG5pY2FsRXJyb3JNc2cgPSB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMgPyB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLnRlY2huaWNhbEVycm9yIDogbnVsbDtcbmxldCB0b2tlbiA9IG51bGw7XG5cbi8qKlxuICogQWRkIGNzcmYgdG9rZW4gcGFyYW0gdG8gdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gc291cmNlIHVybFxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2tldElkIC0gVVVJRCBvZiB0aGUgdGVtcG9yYXJ5IGJhc2tldCBpbiB0aGUgc2Vzc2lvbiwgaWYgYXBwbGljYWJsZVxuICogQHJldHVybnMge3N0cmluZ30gLSB1cmwgd2l0aCBjc3JmX3Rva2VuIHBhcmFtXG4gKi9cbmZ1bmN0aW9uIGdldFVybFdpdGhDc3JmVG9rZW4odXJsLCBiYXNrZXRJZCkge1xuICAgIGNvbnN0IHVybEluc3RhbmNlID0gbmV3IFVSTCh1cmwsIGxvY2F0aW9uLm9yaWdpbik7XG5cbiAgICB1cmxJbnN0YW5jZS5zZWFyY2hQYXJhbXMuYXBwZW5kKCdjc3JmX3Rva2VuJywgZ2V0Q3NyZlRva2VuKCkpO1xuXG4gICAgaWYgKGJhc2tldElkKSB7XG4gICAgICAgIHVybEluc3RhbmNlLnNlYXJjaFBhcmFtcy5hcHBlbmQoJ2Jhc2tldElkJywgYmFza2V0SWQpO1xuICAgIH1cblxuICAgIHJldHVybiB1cmxJbnN0YW5jZS50b1N0cmluZygpO1xufVxuXG4vKipcbiAqIEdldCBDU1JGIFRva2VuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGNzcmYgdG9rZW4gdmFsdWVcbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKCkge1xuICAgIGxldCAkZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWNzcmYtdG9rZW5dJyk7XG5cbiAgICBpZiAoJGVsZW1lbnQgJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1jc3JmLXRva2VuJ10gJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1jc3JmLXRva2VuJ10udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtY3NyZi10b2tlbiddLnZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiAnJztcbn1cblxuLyoqXG4gKiBHZXQgSW5pdCBQcm9kdWN0IERhdGEgKHBhZ2UgbG9hZCBhbmQgY2FwdHVyZXMgZGF0YSBhdmFpbGFibGUgb24gcGFnZSBsb2FkKVxuICogQHJldHVybnMge09iamVjdH0gLSBwcm9kdWN0RGF0YSB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlOiB7IHBpZDogcHJvZElkLCBxdWFudGl0eTogc2VsZWN0ZWRRdWFudGl0eSwgb3B0aW9uczogc2VsZWN0ZWRPcHRpb25zIH1cbiAqL1xuZnVuY3Rpb24gZ2V0SW5pdFByb2R1Y3REYXRhKCkge1xuICAgIGxldCBwcm9kdWN0RGF0YSA9IG51bGw7XG4gICAgbGV0ICRlbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtYnV5LW5vdy1pbml0XScpO1xuICAgIGlmICgkZWxlbWVudCAmJiAkZWxlbWVudC5hdHRyaWJ1dGVzWydkYXRhLWJ1eS1ub3ctaW5pdCddICYmICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtYnV5LW5vdy1pbml0J10udmFsdWUpIHtcbiAgICAgICAgcHJvZHVjdERhdGEgPSBKU09OLnBhcnNlKCRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtYnV5LW5vdy1pbml0J10udmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvZHVjdERhdGE7XG59XG5cbi8qKlxuICogU2V0IEluaXQgUHJvZHVjdCBEYXRhXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSAtIGFjY2VwdHMgcHJvZHVjdCBkYXRhIG9iaiAmIHVwZGF0ZXMgZ2xvYmFsIHByb2R1Y3REYXRhIHZhcmlhYmxlOiB7IHBpZDogcHJvZElkLCBxdWFudGl0eTogc2VsZWN0ZWRRdWFudGl0eSwgb3B0aW9uczogc2VsZWN0ZWRPcHRpb25zIH1cbiAqL1xuZnVuY3Rpb24gc2V0SW5pdFByb2R1Y3REYXRhKGRhdGEpIHtcbiAgICBwcm9kdWN0RGF0YSA9IGRhdGE7XG59XG5cbi8qKlxuICogU2V0cyBVcCBTaG9wUGF5IGxpc3RlbmVyIEV2ZW50c1xuICogQHBhcmFtIHtPYmplY3R9IHNlc3Npb24gLSBBY2NlcHRzIHRoZSBTaG9wIFBheSBzZXNzaW9uIG9iamVjdCBhbmQgZXN0YWJsaXNoZXMgbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycyBvbiB0aGUgc2Vzc2lvbi5cbiAqL1xuZnVuY3Rpb24gc2V0U2Vzc2lvbkxpc3RlbmVycyhzZXNzaW9uKSB7XG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwic2Vzc2lvbnJlcXVlc3RlZFwiLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgbGV0IHNlc3Npb25QYXltZW50UmVxdWVzdDtcbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiBnZXRVcmxXaXRoQ3NyZlRva2VuKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlByZXBhcmVCYXNrZXQpLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGFzeW5jOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeShwcm9kdWN0RGF0YSksXG4gICAgICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb25QYXltZW50UmVxdWVzdCA9IGRhdGEucGF5bWVudFJlcXVlc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VJZGVudGlmaWVyID0gZGF0YS5iYXNrZXRJZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0IHJldHVyblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZCB1c2UgZGVmYXVsdCBtb2RhbCBlcnJvciBoYW5kbGluZy5cbiAgICAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95IHRoZSBzZXNzaW9uIGFuZCByZXR1cm4uXG4gICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2Vzc2lvblBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uUGF5bWVudFJlcXVlc3RcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4od2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuQmVnaW5TZXNzaW9uKSxcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgYXN5bmM6IGZhbHNlLFxuICAgICAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdERhdGEpLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRva2VuID0gZGF0YS50b2tlbjtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tvdXRVcmwgPSBkYXRhLmNoZWNrb3V0VXJsO1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2VJZGVudGlmaWVyID0gZGF0YS5zb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3Qoe3Rva2VuLCBjaGVja291dFVybCwgc291cmNlSWRlbnRpZmllcn0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNc2cgPSBkYXRhLmVycm9yTXNnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qICBzZXNzaW9uLmNvbXBsZXRlU2Vzc2lvblJlcXVlc3QoKSBkb2VzIG5vdCB0YWtlIGFuIGVycm9ycyBhcnJheSBhcyBpbnB1dCBzbyBqdXN0IHJldHVyblxuICAgICAgICAgICAgICAgICAgICAgICAgYW5kIHVzZSBkZWZhdWx0IG1vZGFsIGVycm9yIGhhbmRsaW5nLlxuICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgLyogIHNlc3Npb24uY29tcGxldGVTZXNzaW9uUmVxdWVzdCgpIGRvZXMgbm90IHRha2UgYW4gZXJyb3JzIGFycmF5IGFzIGlucHV0IHNvIGp1c3RcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveSB0aGUgc2Vzc2lvbiBhbmQgcmV0dXJuLlxuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcImRpc2NvdW50Y29kZWNoYW5nZWRcIiwgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgbGV0IHJlcXVlc3REYXRhID0ge1xuICAgICAgICAgICAgZGlzY291bnRDb2RlczogZXYuZGlzY291bnRDb2Rlc1xuICAgICAgICB9O1xuICAgICAgICBpZiAod2luZG93LnNob3BwYXlDbGllbnRSZWZzLmNvbnN0YW50cy5pc0J1eU5vdykge1xuICAgICAgICAgICAgcmVxdWVzdERhdGEuYmFza2V0SWQgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3BvbnNlSlNPTiA9IGNyZWF0ZVJlc3BvbnNlKHJlcXVlc3REYXRhLCB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMudXJscy5EaXNjb3VudENvZGVDaGFuZ2VkKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5leGNlcHRpb24pe1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiZGlzY291bnRDb2RlRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiZGlzY291bnRDb2RlRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGRlbGl2ZXJ5TWV0aG9kcywgZGlzY291bnRDb2RlcywgbGluZUl0ZW1zLCBzaGlwcGluZ0xpbmVzLCBzdWJ0b3RhbCwgZGlzY291bnRzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuXG5cdFx0dmFyIHBheW1lbnRSZXF1ZXN0T2JqZWN0ID0ge307XG5cdFx0Zm9yICh2YXIgcHJvcGVydHlLZXkgaW4gY3VycmVudFBheW1lbnRSZXF1ZXN0KSB7XG5cdFx0XHRwYXltZW50UmVxdWVzdE9iamVjdFtwcm9wZXJ0eUtleV0gPSBjdXJyZW50UGF5bWVudFJlcXVlc3RbcHJvcGVydHlLZXldO1xuXHRcdH1cblxuICAgICAgICBsZXQgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAvLyAuLi5jdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgICAgICBkaXNjb3VudENvZGVzOiBkaXNjb3VudENvZGVzLFxuICAgICAgICAgICAgbGluZUl0ZW1zOiBsaW5lSXRlbXMsXG4gICAgICAgICAgICBzaGlwcGluZ0xpbmVzOiBzaGlwcGluZ0xpbmVzLFxuICAgICAgICAgICAgZGVsaXZlcnlNZXRob2RzOiBkZWxpdmVyeU1ldGhvZHMsXG4gICAgICAgICAgICBzdWJ0b3RhbDogc3VidG90YWwsXG4gICAgICAgICAgICBkaXNjb3VudHM6IGRpc2NvdW50cyxcbiAgICAgICAgICAgIHRvdGFsVGF4OiB0b3RhbFRheCxcbiAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICB9KSk7XG4gICAgICAgIGlmICh0b3RhbFNoaXBwaW5nUHJpY2UpIHtcbiAgICAgICAgICAgIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKHVwZGF0ZWRQYXltZW50UmVxdWVzdCwge1xuICAgICAgICAgICAgICAgIC8vIC4uLnVwZGF0ZWRQYXltZW50UmVxdWVzdCxcbiAgICAgICAgICAgICAgICB0b3RhbFNoaXBwaW5nUHJpY2U6IHRvdGFsU2hpcHBpbmdQcmljZVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZURpc2NvdW50Q29kZUNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZGVsaXZlcnltZXRob2RjaGFuZ2VkXCIsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRQYXltZW50UmVxdWVzdCA9IHNlc3Npb24ucGF5bWVudFJlcXVlc3Q7XG4gICAgICAgIGxldCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIGRlbGl2ZXJ5TWV0aG9kOiBldi5kZWxpdmVyeU1ldGhvZCxcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuRGVsaXZlcnlNZXRob2RDaGFuZ2VkKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5leGNlcHRpb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24uY29tcGxldGVEZWxpdmVyeU1ldGhvZENoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeyBzaGlwcGluZ0xpbmVzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAgICAgLy8gLi4uY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICAgICAgICAgIHNoaXBwaW5nTGluZXM6IHNoaXBwaW5nTGluZXMsXG4gICAgICAgICAgICAgICAgdG90YWxTaGlwcGluZ1ByaWNlOiB0b3RhbFNoaXBwaW5nUHJpY2UsXG4gICAgICAgICAgICAgICAgdG90YWxUYXg6IHRvdGFsVGF4LFxuICAgICAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RDaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBzaGlwcGluZ0xpbmVzLCB0b3RhbFNoaXBwaW5nUHJpY2UsIHRvdGFsVGF4LCB0b3RhbCB9ID0gcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcGF5bWVudCByZXF1ZXN0IGJhc2VkIG9uIHRoZSBkZWxpdmVyeSBtZXRob2QgY2hhbmdlIGFuZCB1cGRhdGUgdGhlIHRvdGFsIGFjY29yZGluZ2x5XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwge1xuICAgICAgICAgICAgLy8gLi4uY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICAgICAgc2hpcHBpbmdMaW5lczogc2hpcHBpbmdMaW5lcyxcbiAgICAgICAgICAgIHRvdGFsU2hpcHBpbmdQcmljZTogdG90YWxTaGlwcGluZ1ByaWNlLFxuICAgICAgICAgICAgdG90YWxUYXg6IHRvdGFsVGF4LFxuICAgICAgICAgICAgdG90YWw6IHRvdGFsXG4gICAgICAgIH0pKTtcblxuICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RDaGFuZ2UoeyB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdCB9KTtcbiAgICB9KTtcblxuICAgIHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInNoaXBwaW5nYWRkcmVzc2NoYW5nZWRcIiwgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFBheW1lbnRSZXF1ZXN0ID0gc2Vzc2lvbi5wYXltZW50UmVxdWVzdDtcbiAgICAgICAgaWYgKCFldi5zaGlwcGluZ0FkZHJlc3MpIHtcbiAgICAgICAgICAgIC8qIFRoaXMgZXZlbnQgaXMgdHJpZ2dlcmVkIHdpdGggbm8gc2hpcHBpbmcgYWRkcmVzcyB3aGVuIGEgY3VzdG9tZXIgY2xpY2tzIFwiY2hhbmdlXCJcbiAgICAgICAgICAgICAgIHRvIGNob29zZSBhbiBhbHRlcm5hdGUgZW1haWwgYWRkcmVzcyBpbiB0aGUgbW9kYWxcbiAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlU2hpcHBpbmdBZGRyZXNzQ2hhbmdlKHsgdXBkYXRlZFBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJlcXVlc3REYXRhID0ge1xuICAgICAgICAgICAgc2hpcHBpbmdBZGRyZXNzOiBldi5zaGlwcGluZ0FkZHJlc3MsXG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlNoaXBwaW5nQWRkcmVzc0NoYW5nZWQpO1xuICAgICAgICBpZiAocmVzcG9uc2VKU09OLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRlY2huaWNhbEVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIC8vIEV2ZW50IGxpc3RlbmVycyBoYXZlIGxvYWRlZCBzbyB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCkgd2lsbCBiZSBjYWxsZWQgaW4gd2luZG93Y2xvc2VkXG4gICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZUpTT04uZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBlcnJvck1zZyA9IHRlY2huaWNhbEVycm9yTXNnO1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlSlNPTi5lcnJvck1zZykge1xuICAgICAgICAgICAgICAgIGVycm9yTXNnID0gcmVzcG9uc2VKU09OLmVycm9yTXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGRlbGl2ZXJ5TWV0aG9kcywgc2hpcHBpbmdMaW5lcywgdG90YWxTaGlwcGluZ1ByaWNlLCB0b3RhbFRheCwgdG90YWwgfSA9IHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdDtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHBheW1lbnQgcmVxdWVzdCBiYXNlZCBvbiB0aGUgc2hpcHBpbmcgYWRkcmVzcyBjaGFuZ2VcbiAgICAgICAgY29uc3QgdXBkYXRlZFBheW1lbnRSZXF1ZXN0ID0gd2luZG93LlNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoJC5leHRlbmQoY3VycmVudFBheW1lbnRSZXF1ZXN0LCB7XG4gICAgICAgICAgICAvLyAuLi5jdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgICAgICBkZWxpdmVyeU1ldGhvZHM6IGRlbGl2ZXJ5TWV0aG9kcyxcbiAgICAgICAgICAgIHNoaXBwaW5nTGluZXM6IHNoaXBwaW5nTGluZXMsXG4gICAgICAgICAgICB0b3RhbFNoaXBwaW5nUHJpY2U6IHRvdGFsU2hpcHBpbmdQcmljZSxcbiAgICAgICAgICAgIHRvdGFsVGF4OiB0b3RhbFRheCxcbiAgICAgICAgICAgIHRvdGFsOiB0b3RhbFxuICAgICAgICB9KSk7XG5cbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVNoaXBwaW5nQWRkcmVzc0NoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwicGF5bWVudGNvbmZpcm1hdGlvbnJlcXVlc3RlZFwiLCBmdW5jdGlvbihldikge1xuICAgICAgICBjb25zdCByZXF1ZXN0RGF0YSA9IHtcbiAgICAgICAgICAgIHRva2VuOiBzZXNzaW9uLnRva2VuLFxuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3Q6IHNlc3Npb24ucGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuU3VibWl0UGF5bWVudCk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGF5bWVudENvbmZpcm1hdGlvblJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImdlbmVyYWxFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgbGV0IGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGF5bWVudENvbmZpcm1hdGlvblJlcXVlc3Qoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImdlbmVyYWxFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgb3JkZXJDb25maXJtYXRpb25EYXRhID0ge1xuICAgICAgICAgICAgb3JkZXJJRDogcmVzcG9uc2VKU09OLm9yZGVySUQsXG4gICAgICAgICAgICBvcmRlclRva2VuOiByZXNwb25zZUpTT04ub3JkZXJUb2tlbixcbiAgICAgICAgICAgIGNvbnRpbnVlVXJsOiByZXNwb25zZUpTT04uY29udGludWVVcmxcbiAgICAgICAgfTtcbiAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVBheW1lbnRDb25maXJtYXRpb25SZXF1ZXN0KCk7XG4gICAgfSk7XG5cbiAgICBzZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJwYXltZW50Y29tcGxldGVcIiwgZnVuY3Rpb24oZXYpIHtcblx0XHR2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICB0b2tlbjogc2Vzc2lvbi50b2tlbixcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0LFxuXHRcdFx0ZXZlbnQ6IGV2XG4gICAgICAgIH07XG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblx0XHR2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlBheW1lbnRDb21wbGV0ZSk7XG5cdFx0aWYgKGV2LnByb2Nlc3NpbmdTdGF0dXMuc3RhdHVzID09PSBcImNvbXBsZXRlZFwiKSB7XG5cdFx0XHRyZWxvYWRPbkNsb3NlID0gZmFsc2U7XG5cdFx0XHRzZXNzaW9uLmNsb3NlKCk7XG5cdFx0XHR2YXIgZGF0YSA9IG9yZGVyQ29uZmlybWF0aW9uRGF0YTtcblx0XHRcdHZhciByZWRpcmVjdCA9ICQoJzxmb3JtPicpLmFwcGVuZFRvKGRvY3VtZW50LmJvZHkpLmF0dHIoe1xuXHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0YWN0aW9uOiBkYXRhLmNvbnRpbnVlVXJsXG5cdFx0XHR9KTtcblx0XHRcdCQoJzxpbnB1dD4nKS5hcHBlbmRUbyhyZWRpcmVjdCkuYXR0cih7XG5cdFx0XHRcdG5hbWU6ICdvcmRlcklEJyxcblx0XHRcdFx0dmFsdWU6IGRhdGEub3JkZXJJRFxuXHRcdFx0fSk7XG5cdFx0XHQkKCc8aW5wdXQ+JykuYXBwZW5kVG8ocmVkaXJlY3QpLmF0dHIoe1xuXHRcdFx0XHRuYW1lOiAnb3JkZXJUb2tlbicsXG5cdFx0XHRcdHZhbHVlOiBkYXRhLm9yZGVyVG9rZW5cblx0XHRcdH0pO1xuXHRcdFx0cmVkaXJlY3Quc3VibWl0KCk7XG5cdFx0fVxuICAgIH0pO1xuXG4gICAgc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwid2luZG93Y2xvc2VkXCIsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIC8vIFJlc2V0IGdsb2JhbCB2YWx1ZSB0byBkZWZhdWx0XG4gICAgICAgIC8vIGlmICghcmVsb2FkT25DbG9zZSkge1xuICAgICAgICAvLyAgICAgcmVsb2FkT25DbG9zZSA9IHRydWU7XG4gICAgICAgIC8vIH0gZWxzZSB7XG4gICAgICAgIC8vICAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG4gICAgICAgIC8vIH1cblx0XHR2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICB0b2tlbjogc2Vzc2lvbi50b2tlbixcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0LFxuXHRcdFx0ZXZlbnQ6IGV2XG4gICAgICAgIH07XG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblx0XHR2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLldpbmRvd0Nsb3NlZCk7XG4gICAgfSk7XG5cblx0c2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZGVsaXZlcnltZXRob2R0eXBlY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBkZWxpdmVyeU1ldGhvZFR5cGU6IGV2LmRlbGl2ZXJ5TWV0aG9kVHlwZSxcbiAgICAgICAgICAgIHBheW1lbnRSZXF1ZXN0OiBjdXJyZW50UGF5bWVudFJlcXVlc3QsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3cpIHtcbiAgICAgICAgICAgIHJlcXVlc3REYXRhLmJhc2tldElkID0gc291cmNlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXNwb25zZUpTT04gPSBjcmVhdGVSZXNwb25zZShyZXF1ZXN0RGF0YSwgd2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlZCk7XG5cdFx0dmFyIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwgcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0KSk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlRGVsaXZlcnlNZXRob2RUeXBlQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgdXBkYXRlZFBheW1lbnRSZXF1ZXN0OiB1cGRhdGVkUGF5bWVudFJlcXVlc3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cdFx0c2Vzc2lvbi5jb21wbGV0ZURlbGl2ZXJ5TWV0aG9kVHlwZUNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG5cdHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInBpY2t1cGxvY2F0aW9uY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBwaWNrdXBMb2NhdGlvbjogZXYucGlja3VwTG9jYXRpb24sXG4gICAgICAgICAgICBwYXltZW50UmVxdWVzdDogY3VycmVudFBheW1lbnRSZXF1ZXN0LFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMuY29uc3RhbnRzLmlzQnV5Tm93KSB7XG4gICAgICAgICAgICByZXF1ZXN0RGF0YS5iYXNrZXRJZCA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVzcG9uc2VKU09OID0gY3JlYXRlUmVzcG9uc2UocmVxdWVzdERhdGEsIHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy51cmxzLlBpY2t1cExvY2F0aW9uQ2hhbmdlZCk7XG5cdFx0dmFyIHVwZGF0ZWRQYXltZW50UmVxdWVzdCA9IHdpbmRvdy5TaG9wUGF5LlBheW1lbnRSZXF1ZXN0LmJ1aWxkKCQuZXh0ZW5kKGN1cnJlbnRQYXltZW50UmVxdWVzdCwgcmVzcG9uc2VKU09OLnBheW1lbnRSZXF1ZXN0KSk7XG4gICAgICAgIGlmIChyZXNwb25zZUpTT04uZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25DaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiB0ZWNobmljYWxFcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAvLyBFdmVudCBsaXN0ZW5lcnMgaGF2ZSBsb2FkZWQgc28gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpIHdpbGwgYmUgY2FsbGVkIGluIHdpbmRvd2Nsb3NlZFxuICAgICAgICAgICAgfSwgMjAwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2VKU09OLmVycm9yKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3JNc2cgPSB0ZWNobmljYWxFcnJvck1zZztcbiAgICAgICAgICAgIGlmIChyZXNwb25zZUpTT04uZXJyb3JNc2cpIHtcbiAgICAgICAgICAgICAgICBlcnJvck1zZyA9IHJlc3BvbnNlSlNPTi5lcnJvck1zZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlc3Npb24uY29tcGxldGVQaWNrdXBMb2NhdGlvbkNoYW5nZSh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2hpcHBpbmdBZGRyZXNzRXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTXNnXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXHRcdHNlc3Npb24uY29tcGxldGVQaWNrdXBMb2NhdGlvbkNoYW5nZSh7IHVwZGF0ZWRQYXltZW50UmVxdWVzdDogdXBkYXRlZFBheW1lbnRSZXF1ZXN0IH0pO1xuICAgIH0pO1xuXG5cdHNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcihcInBpY2t1cGxvY2F0aW9uZmlsdGVyY2hhbmdlZFwiLCBmdW5jdGlvbihldikge1xuXHRcdHZhciBjdXJyZW50UGF5bWVudFJlcXVlc3QgPSBzZXNzaW9uLnBheW1lbnRSZXF1ZXN0O1xuICAgICAgICB2YXIgcmVxdWVzdERhdGEgPSB7XG4gICAgICAgICAgICBidXllckxvY2F0aW9uOiBldi5idXllckxvY2F0aW9uLFxuICAgICAgICAgICAgcGF5bWVudFJlcXVlc3Q6IGN1cnJlbnRQYXltZW50UmVxdWVzdCxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAod2luZG93LnNob3BwYXlDbGllbnRSZWZzLmNvbnN0YW50cy5pc0J1eU5vdykge1xuICAgICAgICAgICAgcmVxdWVzdERhdGEuYmFza2V0SWQgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlc3BvbnNlSlNPTiA9IGNyZWF0ZVJlc3BvbnNlKHJlcXVlc3REYXRhLCB3aW5kb3cuc2hvcHBheUNsaWVudFJlZnMudXJscy5QaWNrdXBMb2NhdGlvbkZpbHRlckNoYW5nZWQpO1xuXHRcdHZhciB1cGRhdGVkUGF5bWVudFJlcXVlc3QgPSB3aW5kb3cuU2hvcFBheS5QYXltZW50UmVxdWVzdC5idWlsZCgkLmV4dGVuZChjdXJyZW50UGF5bWVudFJlcXVlc3QsIHJlc3BvbnNlSlNPTi5wYXltZW50UmVxdWVzdCkpO1xuICAgICAgICBpZiAocmVzcG9uc2VKU09OLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgc2Vzc2lvbi5jb21wbGV0ZVBpY2t1cExvY2F0aW9uRmlsdGVyQ2hhbmdlKHtcbiAgICAgICAgICAgICAgICBlcnJvcnM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzaGlwcGluZ0FkZHJlc3NFcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGVjaG5pY2FsRXJyb3JNc2dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgLy8gRXZlbnQgbGlzdGVuZXJzIGhhdmUgbG9hZGVkIHNvIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKSB3aWxsIGJlIGNhbGxlZCBpbiB3aW5kb3djbG9zZWRcbiAgICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlSlNPTi5lcnJvcikge1xuICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gdGVjaG5pY2FsRXJyb3JNc2c7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yTXNnKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNc2cgPSByZXNwb25zZUpTT04uZXJyb3JNc2c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25GaWx0ZXJDaGFuZ2Uoe1xuICAgICAgICAgICAgICAgIGVycm9yczogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInNoaXBwaW5nQWRkcmVzc0Vycm9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvck1zZ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblx0XHRzZXNzaW9uLmNvbXBsZXRlUGlja3VwTG9jYXRpb25GaWx0ZXJDaGFuZ2UoeyB1cGRhdGVkUGF5bWVudFJlcXVlc3Q6IHVwZGF0ZWRQYXltZW50UmVxdWVzdCB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBFbmFibGVzICYgRGlzYWJsZXMgU2hvcCBQYXkncyBCdXkgTm93IGJ1dHRvbiBjbGljayBiYXNlZCBvbiB3aGV0aGVyIHRoZSBwcm9kdWN0IGlzIHJlYWR5IHRvIG9yZGVyIG9uIHRoZSBQRFBcbiAqL1xuZnVuY3Rpb24gc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUoZWxlbSwgaXNSZWFkeVRvT3JkZXIsIGZvcmNlRGlzYWJsZSkge1xuICAgIGxldCByZWFkeVRvT3JkZXJQYWdlTG9hZCA9IGlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCgpO1xuICAgIGxldCBpc0J1eU5vdyA9IHdpbmRvdy5zaG9wcGF5Q2xpZW50UmVmcy5jb25zdGFudHMuaXNCdXlOb3c7XG5cbiAgICBpZiAoZWxlbSkge1xuICAgICAgICAvLyBBbiBlcnJvciBvY2N1cnJlZCwgZGlzYWJsZSB0aGUgYnV0dG9uXG4gICAgICAgIGlmICghaXNCdXlOb3cgJiYgZm9yY2VEaXNhYmxlKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgICAgICBpZiAob2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0J1eU5vdyB8fCAoaXNCdXlOb3cgJiYgKGlzUmVhZHlUb09yZGVyIHx8IHJlYWR5VG9PcmRlclBhZ2VMb2FkKSkpIHtcbiAgICAgICAgICAgIGVsZW0uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhdXRvJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVsZW0uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBXYXRjaGVzIGZvciB3aGVuIFNob3BQYXkgYnV0dG9uIGlzIGZpcnN0IHJlbmRlcmVkIHRvIHRoZSBwYWdlIHRvIHRoZW4gYXBwbHkgY29ycmVjdCBidXR0b24gc3R5bGluZyBkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgYmFza2V0IGlzIGVtcHR5IG9yIG5vdFxuICovXG5mdW5jdGlvbiBzaG9wcGF5TXV0YXRpb25PYnNlcnZlcihlbGVtU2VsZWN0b3IpIHtcbiAgICBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKChtdXRhdGlvbnNMaXN0LCBvYnNlcnZlcikgPT4ge1xuICAgICAgICBjb25zdCByZW5kZXJlZFNob3BQYXlFbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlbGVtU2VsZWN0b3IpO1xuICAgICAgICBpZiAocmVuZGVyZWRTaG9wUGF5RWxlbSkge1xuICAgICAgICAgICAgc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUocmVuZGVyZWRTaG9wUGF5RWxlbSk7XG4gICAgICAgICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIG9ic2VydmVyLm9ic2VydmUoZG9jdW1lbnQuYm9keSwgeyBjaGlsZExpc3Q6IHRydWUsIHN1YnRyZWU6IHRydWUgfSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBCdXkgTm93IHByb2R1Y3QgaXMgcmVhZHkgb24gcGFnZSBsb2FkIG9yIG5vdCAoZXg6IHNpbXBsZSBwcm9kdWN0cyB2cy4gdmFyaWFudHMgd2l0aCBtdWx0aXBsZSBvcHRpb25zIHRvIGNob29zZSBmcm9tLCBldGMuKVxuICovXG5mdW5jdGlvbiBpc1JlYWR5VG9PcmRlck9uUGFnZUxvYWQoKSB7XG4gICAgbGV0IHJlYWR5VG9PcmRlciA9IGZhbHNlO1xuICAgIGxldCAkZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLXJlYWR5LXRvLW9yZGVyXScpO1xuICAgIGlmICgkZWxlbWVudCAmJiAkZWxlbWVudC5hdHRyaWJ1dGVzWydkYXRhLXJlYWR5LXRvLW9yZGVyJ10gJiYgJGVsZW1lbnQuYXR0cmlidXRlc1snZGF0YS1yZWFkeS10by1vcmRlciddLnZhbHVlKSB7XG4gICAgICAgIHJlYWR5VG9PcmRlciA9ICRlbGVtZW50LmF0dHJpYnV0ZXNbJ2RhdGEtcmVhZHktdG8tb3JkZXInXS52YWx1ZSA9PT0gXCJ0cnVlXCI7XG4gICAgfVxuICAgIHJldHVybiByZWFkeVRvT3JkZXI7XG59XG5cbi8qKlxuICogSGFuZGxlcyBBSkFYIGNhbGwgdG8gY3JlYXRlIC8gdXBkYXRlIHRoZSBwYXltZW50IHJlc3BvbnNlIG5lZWRlZCBmb3IgdGhlIFNob3BQYXkuUGF5bWVudFJlcXVlc3QuYnVpbGQoKSBtZXRob2QuXG4gKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdE9iaiAtIGEgcmVxdWVzdCBvYmplY3QgdGhhdCBjb250YWlucyByZWxldmFudCBldmVudCBkYXRhICYgc2Vzc2lvbiBkYXRhLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRyb2xsZXJVUkwgLSBTdHJpbmcgdXJsIG9mIHRoZSB0YXJnZXRlZCBjb250cm9sbGVyIChiYXNlZCBvbiB0aGUgdXJscyBPYmogc2V0IGluIHNob3BwYXlHbG9iYWxSZWZzLmpzKVxuICogQHJldHVybnMge09iamVjdH0gcmVzcG9uc2VKU09OIC0gYW4gdXBkYXRlZCByZXNwb25zZSBvYmplY3QgdG8gYmUgdXNlZCBpbiB0aGUgYnVpbGQgJiBvbiB0aGUgU2hvcFBheS5QYXltZW50UmVxdWVzdCBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVJlc3BvbnNlIChyZXF1ZXN0T2JqLCBjb250cm9sbGVyVVJMKSB7XG4gICAgbGV0IHJlc3BvbnNlSlNPTjtcbiAgICAkLmFqYXgoe1xuICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4oY29udHJvbGxlclVSTCksXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBhc3luYzogZmFsc2UsXG4gICAgICAgIGRhdGE6IEpTT04uc3RyaW5naWZ5KHJlcXVlc3RPYmopLFxuICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICByZXNwb25zZUpTT04gPSBkYXRhO1xuICAgICAgICAgICAgcmVzcG9uc2VKU09OLmV4Y2VwdGlvbiA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgcmVzcG9uc2VKU09OID0gZXJyLnJlc3BvbnNlSlNPTiA/IGVyci5yZXNwb25zZUpTT04gOiB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlSlNPTi5leGNlcHRpb24gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzcG9uc2VKU09OO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgQUpBWCBjYWxsIHRvIGdldCB0aGUgcGF5bWVudCByZXNwb25zZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IHBheW1lbnRSZXNwb25zZSAtIGFuIHJlc3BvbnNlIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRQYXltZW50UmVxdWVzdChzZXNzaW9uKSB7XG4gICAgbGV0IHRva2VuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtY3NyZi10b2tlbl0nKTtcbiAgICBsZXQgcmVzcG9uc2U7XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICAgIGNvbnN0IHBheW1lbnRSZXNwb25zZSA9ICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IGdldFVybFdpdGhDc3JmVG9rZW4od2luZG93LnNob3BwYXlDbGllbnRSZWZzLnVybHMuR2V0Q2FydFN1bW1hcnkpLFxuICAgICAgICAgICAgdHlwZTogJ0dFVCcsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgYXN5bmM6IGZhbHNlLFxuICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghZGF0YS5lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlSlNPTjogZGF0YVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNob3BwYXlCdG5EaXNhYmxlZFN0eWxlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lclwiKSwgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAvKiAgUmV0dXJuIHRvIGV4aXQgZnVuY3Rpb24gLSBkb24ndCByZWxvYWQgdGhlIHBhZ2UgaW4gY2FzZSB0aGVyZSBpcyBhIHBhZ2UgcmVuZGVyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICBpc3N1ZSAod2lsbCByZXN1bHQgaW4gaW5maW5pdGUgcmVsb2FkIGxvb3ApLlxuICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNob3BwYXlCdG5EaXNhYmxlZFN0eWxlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2hvcC1wYXktYnV0dG9uLWNvbnRhaW5lclwiKSwgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLyogIFJldHVybiB0byBleGl0IGZ1bmN0aW9uIC0gZG9uJ3QgcmVsb2FkIHRoZSBwYWdlIGluIGNhc2UgdGhlcmUgaXMgYSBwYWdlIHJlbmRlcmluZ1xuICAgICAgICAgICAgaXNzdWUgKHdpbGwgcmVzdWx0IGluIGluZmluaXRlIHJlbG9hZCBsb29wKS5cbiAgICAgICAgKi9cbiAgICAgICAgaWYgKHNlc3Npb24pIHtcbiAgICAgICAgICAgIHNlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBzaG9wcGF5QnRuRGlzYWJsZWRTdHlsZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNob3AtcGF5LWJ1dHRvbi1jb250YWluZXJcIiksIG51bGwsIHRydWUpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYnVpbGRQYXltZW50UmVxdWVzdDogYnVpbGRQYXltZW50UmVxdWVzdCxcbiAgICBjcmVhdGVSZXNwb25zZTogY3JlYXRlUmVzcG9uc2UsXG4gICAgZ2V0Q3NyZlRva2VuOiBnZXRDc3JmVG9rZW4sXG4gICAgZ2V0SW5pdFByb2R1Y3REYXRhOiBnZXRJbml0UHJvZHVjdERhdGEsXG4gICAgZ2V0VXJsV2l0aENzcmZUb2tlbjogZ2V0VXJsV2l0aENzcmZUb2tlbixcbiAgICBpc1JlYWR5VG9PcmRlck9uUGFnZUxvYWQ6IGlzUmVhZHlUb09yZGVyT25QYWdlTG9hZCxcbiAgICBwcm9kdWN0RGF0YTogcHJvZHVjdERhdGEsXG4gICAgc2V0SW5pdFByb2R1Y3REYXRhOiBzZXRJbml0UHJvZHVjdERhdGEsXG4gICAgc2V0U2Vzc2lvbkxpc3RlbmVyczogc2V0U2Vzc2lvbkxpc3RlbmVycyxcbiAgICBzaG9wcGF5QnRuRGlzYWJsZWRTdHlsZTogc2hvcHBheUJ0bkRpc2FibGVkU3R5bGUsXG4gICAgc2hvcHBheU11dGF0aW9uT2JzZXJ2ZXI6IHNob3BwYXlNdXRhdGlvbk9ic2VydmVyLFxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5TZXJ2aWNlU3VmZml4ZXMgPSB7XG5cdFNlcnZpY2VTdWl0ZTogJy9lY29tbS8wLjEnLFxuXHRBdXRoZW50aWNhdGU6ICcvYXV0aGVudGljYXRlL3Jvb3QnLFxuXHRQdXJjaGFzZUdpZnRDYXJkOiAnL2Z1bGZpbGxtZW50LzAuMS9wdXJjaGFzZWVnaWZ0Lydcbn07XG5cbmV4cG9ydHMuTWVzc2FnZVByZWZpeGVzID0ge1xuXHROb25TdWNjZXNzOiAnU3RvcmVkIFZhbHVlIFNvbHV0aW9ucyByZXR1cm5lZCBhIHJlc3VsdCBvdGhlciB0aGFuIE9LIGFuZC9vciB3aXRob3V0IGRhdGEgJyxcblx0RXJyb3I6ICdTdG9yZWQgVmFsdWUgU29sdXRpb25zIGVuY291bnRlcmVkIGFuZCB1bmV4cGVjdGVkIGV4Y2VwdGlvbiAnXG59O1xuXG5leHBvcnRzLlRyYW5zYWN0aW9uSW5mb3JtYXRpb24gPSB7XG5cdFN1Y2Nlc3M6ICdTdWNjZXNzZnVsIFRyYW5zYWN0aW9uIC0gTm8gQWRkaXRpb25hbCBJbmZvcm1hdGlvbicsXG5cdEZhaWx1cmU6IHtcblx0XHRCYWxhbmNlRXhjZWVkZWQ6ICdPcmRlciBGYWlsdXJlIC0gUmVxdWVzdGVkIEFtb3VudCBFeGNlZWRlZCBHaWZ0IENhcmQgQmFsYW5jZScsXG5cdFx0SGVsZEFtb3VudFJlbGVhc2VkOiAnT3JkZXIgRmFpbHVyZSAtIFJlbGVhc2luZyBBbW91bnQgSGVsZCBieSBQcmUtQXV0aG9yaXphdGlvbidcblx0fVxufVxuXG5leHBvcnRzLlRyYW5zYWN0aW9uVHlwZXMgPSB7XG5cdEJhbGFuY2VJbnF1aXJ5OiAnQmFsYW5jZSBJbnF1aXJ5Jyxcblx0UHJlQXV0aG9yaXphdGlvbjogJ1ByZS1BdXRob3JpemF0aW9uJyxcblx0UHJlQXV0aG9yaXphdGlvbkNvbXBsZXRlOiAnUHJlLUF1dGhvcml6YXRpb24gQ29tcGxldGUnXG59XG5cbmV4cG9ydHMuUmVzcG9uc2VQYXJzZXJzID0ge1xuXHRiYWxhbmNlSW5xdWlyeVJlc3BvbnNlOiB7XG5cdFx0UGF0aDogJy9pbnRfc3ZzL2NhcnRyaWRnZS9zY3JpcHRzL0JhbGFuY2VJbnF1aXJ5UmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAnYmFsYW5jZUlucXVpcnlSZXR1cm4nXG5cdH0sXG5cdHByZUF1dGhSZXNwb25zZToge1xuXHRcdFBhdGg6ICcvaW50X3N2cy9jYXJ0cmlkZ2Uvc2NyaXB0cy9QcmVBdXRob3JpemF0aW9uUmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAncHJlQXV0aFJldHVybidcblx0fSxcblx0cHJlQXV0aENvbXBsZXRlUmVzcG9uc2U6IHtcblx0XHRQYXRoOiAnL2ludF9zdnMvY2FydHJpZGdlL3NjcmlwdHMvUHJlQXV0aG9yaXphdGlvbkNvbXBsZXRlUmVzcG9uc2VQYXJzZXInLFxuXHRcdEJvZHlOb2RlOiAncHJlQXV0aENvbXBsZXRlUmV0dXJuJ1xuXHR9XG59O1xuXG5leHBvcnRzLlJldHVybkNvZGVzID0ge1xuXHRBcHByb3ZhbDogJzAxJyxcblx0SW5hY3RpdmVDYXJkOiAnMDInLFxuXHRJbnZhbGlkQ2FyZE51bWJlcjogJzAzJyxcblx0SW52YWxpZFRyYW5zYWN0aW9uQ29kZTogJzA0Jyxcblx0SW5zdWZmaWNpZW50RnVuZHM6ICcwNScsXG5cdE5vUHJldmlvdXNBdXRob3JpemF0aW9uczogJzA2Jyxcblx0SW52YWxpZE1lc3NhZ2U6ICcwNycsXG5cdE5vQ2FyZEZvdW5kOiAnMDgnLFxuXHRJbnN1ZmZpY2VudEZ1bmRzRHVlVG9PdXRzdGFuZGluZ1ByZUF1dGhvcml6YXRpb246ICcwOScsXG5cdERlbmlhbE5vUHJldmlvdXNBdXRob3JpemF0aW9uOiAnMTAnLFxuXHROb0F1dGhvcml6YXRpb25OdW1iZXI6ICcxMScsXG5cdEludmFsaWRBdXRob3JpemF0aW9uTnVtYmVyOiAnMTInLFxuXHRNYXhpbXVtU2luZ2xlUmVjaGFyZ2VFeGNlZWRlZDogJzEzJyxcblx0TWF4aW11bVdPcmtpbmdCYWxhbmNlRXhjZWVkZWQ6ICcxNCcsXG5cdEhvc3RVbmF2YWlsYWJsZTogJzE1Jyxcblx0SW52YWxpZENhcmRTdGF0dXM6ICcxNicsXG5cdFVua25vd25EZWFsZXJTdG9yZUNvZGVTcGVjaWFsRWRpdDogJzE3Jyxcblx0TWF4aW11bU51bWJlck9mUmVjaGFyZ2VzRXhjZWVkZWQ6ICcxOCcsXG5cdEludmFsaWRDYXJkVmVyaWZpY2F0aW9uVmFsdWVPclNlY29uZGFyeVNlY3VyaXR5Q29kZTogJzE5Jyxcblx0SW52YWxpZFBpbk51bWJlck9yUGluTG9ja2VkOiAnMjAnLFxuXHRDYXJkQWxyZWFkeUlzc3VlZDogJzIxJyxcblx0Q2FyZE5vdElzc3VlZDogJzIyJyxcblx0Q2FyZEFscmVhZHlVc2VkOiAnMjMnLFxuXHRNYW51YWxUcmFuc2FjdGlvbk5vdEFsbG93ZWQ6ICcyNCcsXG5cdE1hZ1N0cmlwZVJlYWROb3RWYWxpZDogJzI1Jyxcblx0VHJhbnNhY3Rpb25UeXBlVW5rbm93bjogJzI2Jyxcblx0SW52YWxpZFRlbmRlclR5cGU6ICcyNycsXG5cdEludmFsaWRDdXN0b21lclR5cGU6ICcyOCcsXG5cdE1heE51bWJoZXJPZlJlZGVtcHRpb25FeGNlZWRlZDogJzMwJyxcblx0SW52YWxpZEN1cnJlbmN5Q29kZTogJzMxJyxcblx0SW52YWxpZFNlcnZlcklkOiAnMzInLFxuXHRGcm96ZW5DYXJkT3JVbmtub3duOiAnMzMnLFxuXHRJbnZhbGlkQW1vdW50OiAnMzQnLFxuXHRUcmFuc2FjdGlvblJlamVjdGVkSW52YWxpZFRyYW5zYWN0aW9uUHJvbW90aW9uV2lkZU9ySW52YWxpZEZvck9yaWdpbmF0aW5nTWVyY2hhbnRBbmRTdG9yZTogJzM2Jyxcblx0VHJhbnNhY3Rpb25SZWplY3RlZEludmFsaWRNZXJjaGFudEFuZFN0b3JlQ29tYmluYXRpb25Gb3JQcm9tb3Rpb246ICczNycsXG5cdFRyYW5zYWN0aW9uUmVqZWN0ZWRFeGNlZWRlZE1heGltdW1OdW1iZXJPZlByb21vdGlvbkNhcmRzOiAnMzgnLFxuXHRUcmFuc2FjdGlvbkRlY2xpbmVkQW1vdW50TGVzc1RoYW5NaW5pbXVtOiAnNDInLFxuXHRGYWlsdXJlSW5SZXRyaWV2aW5nRGF0YTogJzk5Jyxcblx0UmF0ZUxpbWl0RXhjZWVkZWQ6ICc5OTknXG59O1xuXG5leHBvcnRzLlJldHVybkRlc2NyaXB0aW9uTWVzc2FnZXNGb3JSZXR1cm5Db2RlcyA9IHtcblx0JzAzJzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJyxcblx0JzA4JzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJyxcblx0JzIwJzogJ0ludmFsaWQgQ2FyZCBvciBQSU4gTnVtYmVyJ1xufVxuXG5leHBvcnRzLkdpZnRDYXJkVHlwZXMgPSB7XG5cdGVHaWZ0OiAnZUdpZnQnLFxuXHRQaHlzaWNhbDogJ1BoeXNpY2FsJyxcblx0Tm90QXBwbGljYWJsZTogJ05vdEFwcGxpY2FibGUnXG59O1xuXG5leHBvcnRzLk9yZGVyVHlwZXMgPSB7XG5cdEludGVyYWN0aXZlOiAnSScsXG5cdFdlYjogJ1cnXG59OyJdfQ=="}