{"version":3,"sources":["node_modules/browser-pack/_prelude.js","cartridges/app_custom_giftshop/cartridge/js/ajax.js","cartridges/app_custom_giftshop/cartridge/js/app.js","cartridges/app_custom_giftshop/cartridge/js/bonus-products-view.js","cartridges/app_custom_giftshop/cartridge/js/captcha.js","cartridges/app_custom_giftshop/cartridge/js/compare-widget.js","cartridges/app_custom_giftshop/cartridge/js/components/accordion.js","cartridges/app_custom_giftshop/cartridge/js/components/quantitySwitcher.js","cartridges/app_custom_giftshop/cartridge/js/components/stickyComponent.js","cartridges/app_custom_giftshop/cartridge/js/configs/carousel.js","cartridges/app_custom_giftshop/cartridge/js/cookieprivacy.js","cartridges/app_custom_giftshop/cartridge/js/countries.js","cartridges/app_custom_giftshop/cartridge/js/dialog.js","cartridges/app_custom_giftshop/cartridge/js/fbevents.js","cartridges/app_custom_giftshop/cartridge/js/giftcard.js","cartridges/app_custom_giftshop/cartridge/js/giftcert.js","cartridges/app_custom_giftshop/cartridge/js/jquery-ext.js","cartridges/app_custom_giftshop/cartridge/js/login.js","cartridges/app_custom_giftshop/cartridge/js/minicart.js","cartridges/app_custom_giftshop/cartridge/js/page.js","cartridges/app_custom_giftshop/cartridge/js/pages/account.js","cartridges/app_custom_giftshop/cartridge/js/pages/cart.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/address.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/billing.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/formPrepare.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/index.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/multiship.js","cartridges/app_custom_giftshop/cartridge/js/pages/checkout/shipping.js","cartridges/app_custom_giftshop/cartridge/js/pages/compare.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/addToCart.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/availability.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/image.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/index.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/productNav.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/productSet.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/recommendations.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/sizeChart.js","cartridges/app_custom_giftshop/cartridge/js/pages/product/variant.js","cartridges/app_custom_giftshop/cartridge/js/pages/registry.js","cartridges/app_custom_giftshop/cartridge/js/pages/search.js","cartridges/app_custom_giftshop/cartridge/js/pages/storefront.js","cartridges/app_custom_giftshop/cartridge/js/pages/storelocator.js","cartridges/app_custom_giftshop/cartridge/js/pages/wishlist.js","cartridges/app_custom_giftshop/cartridge/js/product-tile.js","cartridges/app_custom_giftshop/cartridge/js/progress.js","cartridges/app_custom_giftshop/cartridge/js/quickview.js","cartridges/app_custom_giftshop/cartridge/js/rating.js","cartridges/app_custom_giftshop/cartridge/js/searchplaceholder.js","cartridges/app_custom_giftshop/cartridge/js/searchsuggest.js","cartridges/app_custom_giftshop/cartridge/js/sfchat.js","cartridges/app_custom_giftshop/cartridge/js/stickySearch.js","cartridges/app_custom_giftshop/cartridge/js/storeinventory/cart.js","cartridges/app_custom_giftshop/cartridge/js/storeinventory/index.js","cartridges/app_custom_giftshop/cartridge/js/storeinventory/product.js","cartridges/app_custom_giftshop/cartridge/js/tiktokevents.js","cartridges/app_custom_giftshop/cartridge/js/tls.js","cartridges/app_custom_giftshop/cartridge/js/tooltip.js","cartridges/app_custom_giftshop/cartridge/js/util.js","cartridges/app_custom_giftshop/cartridge/js/validator.js","node_modules/asap/browser-asap.js","node_modules/asap/browser-raw.js","node_modules/browser-resolve/empty.js","node_modules/call-bind/callBound.js","node_modules/call-bind/index.js","node_modules/ev-emitter/ev-emitter.js","node_modules/function-bind/implementation.js","node_modules/function-bind/index.js","node_modules/get-intrinsic/index.js","node_modules/has-symbols/index.js","node_modules/has-symbols/shams.js","node_modules/has/src/index.js","node_modules/imagesloaded/imagesloaded.js","node_modules/lodash/lodash.js","node_modules/object-inspect/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/punycode/punycode.js","node_modules/qs/lib/formats.js","node_modules/qs/lib/index.js","node_modules/qs/lib/parse.js","node_modules/qs/lib/stringify.js","node_modules/qs/lib/utils.js","node_modules/querystring-es3/decode.js","node_modules/querystring-es3/encode.js","node_modules/querystring-es3/index.js","node_modules/side-channel/index.js","node_modules/url/url.js","node_modules/url/util.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;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;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;;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;;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;;AC5CA;AACA;AACA;AACA;AACA;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;;AChJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxEA;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;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;;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;;ACxDA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;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;;ACvSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;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;;AC7JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;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;;AC9IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;AC/VA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;AC1KA;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;;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;;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;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACAA;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;;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;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1UA;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;;AC1CA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACzzhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvHA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AClhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5tBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"app.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()","'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';\r\n\r\nvar countries = require('./countries'),\r\n    dialog = require('./dialog'),\r\n    minicart = require('./minicart'),\r\n    page = require('./page'),\r\n    rating = require('./rating'),\r\n    searchplaceholder = require('./searchplaceholder'),\r\n    searchsuggest = require('./searchsuggest'),\r\n    tooltip = require('./tooltip'),\r\n    util = require('./util'),\r\n    validator = require('./validator'),\r\n    tls = require('./tls'),\r\n    fbevents = require('./fbevents'),\r\n    tiktok = require('./tiktokevents'),\r\n    sfchat = require('./sfchat'),\r\n    stickySearch = require('./stickySearch');\r\n\r\n\r\n// if jQuery has not been loaded, load from google cdn\r\nif (!window.jQuery) {\r\n    var s = document.createElement('script');\r\n    s.setAttribute('src', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js');\r\n    s.setAttribute('type', 'text/javascript');\r\n    document.getElementsByTagName('head')[0].appendChild(s);\r\n}\r\n\r\nrequire('./jquery-ext')();\r\nrequire('./cookieprivacy')();\r\nrequire('./captcha')();\r\n\r\nfunction initializeEvents() {\r\n    var controlKeys = ['8', '13', '46', '45', '36', '35', '38', '37', '40', '39'];\r\n\r\n    $('body')\r\n        .on('keydown', 'textarea[data-character-limit]', function (e) {\r\n            var text = $.trim($(this).val()),\r\n                charsLimit = $(this).data('character-limit'),\r\n                charsUsed = text.length;\r\n\r\n            if ((charsUsed >= charsLimit) && (controlKeys.indexOf(e.which.toString()) < 0)) {\r\n                e.preventDefault();\r\n            }\r\n        })\r\n        .on('change keyup mouseup', 'textarea[data-character-limit]', function () {\r\n            var text = $.trim($(this).val()),\r\n                charsLimit = $(this).data('character-limit'),\r\n                charsUsed = text.length,\r\n                charsRemain = charsLimit - charsUsed;\r\n\r\n            if (charsRemain < 0) {\r\n                $(this).val(text.slice(0, charsRemain));\r\n                charsRemain = 0;\r\n            }\r\n\r\n            $(this).next('div.char-count').find('.char-remain-count').html(charsRemain);\r\n        });\r\n\r\n    /**\r\n     * initialize search suggestions, pending the value of the site preference(enhancedSearchSuggestions)\r\n     * this will either init the legacy(false) or the beta versions(true) of the the search suggest feature.\r\n     * */\r\n    var $searchContainer = $('.header-search');\r\n    searchsuggest.init($searchContainer, Resources.SIMPLE_SEARCH);\r\n    \r\n    // Prevents the user from submitting the search when it's empty\r\n    $searchContainer.on(\"submit\", function(e) {\r\n    \t\tvar searchPhrase = $searchContainer.find('#q');\r\n    \t\tif (searchPhrase.val() == '' || searchPhrase.val() == searchPhrase.attr('placeholder')) {\r\n    \t\t\treturn false;\r\n    \t\t}\r\n    });\r\n\r\n    //this will change all the input to cater contextual keyboard\r\n    $(window).on('load resize', function(){\r\n    \tif($(window).width() < 768) {\r\n    \t\t$('.numberkey').prop('type', 'tel');\r\n    \t} else {\r\n    \t\t$('.numberkey').prop('type', 'text');\r\n    \t}\r\n    \t\r\n    });\r\n    \r\n    // add show/hide navigation elements\r\n    $('.secondary-navigation .toggle').click(function () {\r\n        $(this).toggleClass('expanded').next('ul').toggle();\r\n    });\r\n\r\n    // add show/hide search-icon\r\n    $(\".header-search-icon\").on(\"click\",function () {\r\n        $(\".header-search\").toggle();\r\n    });\r\n\r\n    // add generic toggle functionality\r\n    $('.toggle').next('.toggle-content').hide();\r\n    $('.toggle').click(function () {\r\n        $(this).toggleClass('expanded').next('.toggle-content').toggle();\r\n    });\r\n\r\n    // subscribe email box\r\n    var $subscribeEmail = $('.subscribe-email');\r\n    if ($subscribeEmail.length > 0)    {\r\n        $subscribeEmail.focus(function () {\r\n            var val = $(this.val());\r\n            if (val.length > 0 && val !== Resources.SUBSCRIBE_EMAIL_DEFAULT) {\r\n                return; // do not animate when contains non-default value\r\n            }\r\n\r\n            $(this).animate({color: '#999999'}, 500, 'linear', function () {\r\n                $(this).val('').css('color', '#333333');\r\n            });\r\n        }).blur(function () {\r\n            var val = $.trim($(this.val()));\r\n            if (val.length > 0) {\r\n                return; // do not animate when contains value\r\n            }\r\n            $(this).val(Resources.SUBSCRIBE_EMAIL_DEFAULT)\r\n                .css('color', '#999999')\r\n                .animate({color: '#333333'}, 500, 'linear');\r\n        });\r\n    }\r\n    window.setTimeout(function(){\r\n        if (window.ApplePaySession) {\r\n            $('body').addClass('applepay-browser');\r\n        }\r\n    }, 1000);\r\n    \r\n    $('.privacy-policy').on('click', function (e) {\r\n        e.preventDefault();\r\n        dialog.open({\r\n            url: $(e.target).attr('href'),\r\n            options: {\r\n                height: 600\r\n            }\r\n        });\r\n    });\r\n\r\n    // main menu toggle\r\n    $('.menu-toggle').on('click', function () {\r\n        $('#wrapper').toggleClass('menu-active');\r\n    });\r\n    $('.menu-category li .menu-item-toggle').on('click', function (e) {\r\n        e.preventDefault();\r\n        var $parentLi = $(e.target).closest('li');\r\n        $parentLi.siblings('li').removeClass('active').find('.menu-item-toggle').removeClass('fa-chevron-up active').addClass('fa-chevron-right');\r\n        $parentLi.toggleClass('active');\r\n        $(e.target).toggleClass('fa-chevron-right fa-chevron-up active');\r\n    });\r\n    $('.user-account').on('click', function (e) {\r\n        e.preventDefault();\r\n        $(this).parent('.user-info').toggleClass('active');\r\n    });\r\n    \r\n    /**\r\n     * Address State Selector\r\n     */\r\n    var $stateField = $(\"[name$=_state]\");\r\n    $('body').on('change', \"[name$=_state]\", function() { \r\n    \t$(\"[name$=_stateName]\").val($(this).find(\"option:selected\").text());\r\n    });\r\n    \r\n    if ($stateField.length > 0) {\r\n    \t$(\"[name$=_stateName]\").val($stateField.find(\"option:selected\").text());\r\n    }\r\n}\r\n/**\r\n * @private\r\n * @function\r\n * @description Adds class ('js') to html for css targeting and loads js specific styles.\r\n */\r\nfunction initializeDom() {\r\n    // add class to html for css targeting\r\n    $('html').addClass('js');\r\n    if (SitePreferences.LISTING_INFINITE_SCROLL) {\r\n        $('html').addClass('infinite-scroll');\r\n    }\r\n    // load js specific styles\r\n    util.limitCharacters();\r\n}\r\n\r\nvar pages = {\r\n    account: require('./pages/account'),\r\n    cart: require('./pages/cart'),\r\n    checkout: require('./pages/checkout'),\r\n    compare: require('./pages/compare'),\r\n    product: require('./pages/product'),\r\n    registry: require('./pages/registry'),\r\n    search: require('./pages/search'),\r\n    storefront: require('./pages/storefront'),\r\n    wishlist: require('./pages/wishlist'),\r\n    storelocator: require('./pages/storelocator')\r\n};\r\n\r\nvar app = {\r\n    init: function () {\r\n        if (document.cookie.length === 0) {\r\n            $('<div/>').addClass('browser-compatibility-alert').append($('<p/>').addClass('browser-error').html(Resources.COOKIES_DISABLED)).appendTo('#browser-check');\r\n        }\r\n        initializeDom();\r\n        initializeEvents();\r\n\r\n        // init specific global components\r\n        countries.init();\r\n        tooltip.init();\r\n        minicart.init();\r\n        validator.init();\r\n        rating.init();\r\n        searchplaceholder.init();\r\n        stickySearch.init();\r\n        \r\n\r\n        // execute page specific initializations\r\n        $.extend(page, window.pageContext);\r\n        var ns = page.ns;\r\n        if (ns && pages[ns] && pages[ns].init) {\r\n            pages[ns].init();\r\n        }\r\n\r\n        // Check TLS status if indicated by site preference\r\n        if (SitePreferences.CHECK_TLS === true) {\r\n            tls.getUserAgent();\r\n        }\r\n\r\n        window.setTimeout(function() {\r\n            if (SitePreferences.FB_PIXEL_ENABLED === true) {\r\n                try{\r\n                    fbevents.init();\r\n                } catch(err){\r\n                    console.error(err);\r\n                }\r\n            }\r\n    \r\n            if (SitePreferences.SF_CHAT_ENABLED === true) {\r\n                try{\r\n                    sfchat.init();\r\n                } catch(err){\r\n                    console.error(err);\r\n                }\r\n            }\r\n    \r\n            if (SitePreferences.TIKTOK_PIXEL_ENABLED === true && SitePreferences.TIKTOK_PIXEL_ID === true) {\r\n                try {\r\n                    tiktok.init();\r\n                } catch (err) {\r\n                    console.error(err);\r\n                }\r\n            }\r\n            console.log('TP- completed');\r\n        }, 1000);\r\n    }\r\n};\r\n\r\n// general extension functions\r\n(function () {\r\n    String.format = function () {\r\n        var s = arguments[0];\r\n        var i, len = arguments.length - 1;\r\n        for (i = 0; i < len; i++) {\r\n            var reg = new RegExp('\\\\{' + i + '\\\\}', 'gm');\r\n            s = s.replace(reg, arguments[i + 1]);\r\n        }\r\n        return s;\r\n    };\r\n})();\r\n\r\n// initialize app\r\n$(document).ready(function () {\r\n    app.init();\r\n});\r\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    var ulList = $bonusProductList.find('ul.selected-bonus-items').first();\n    // Disable select button if quantity is more than maxItems\n    var totquantitycount = 0;\n    for (let i = 0; i < selectedList.length; i++) {\n    let element = selectedList[i].qty;\n    totquantitycount += element;\n    if (totquantitycount >= maxItems) {\n        $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n    } else {\n        $bonusProductList.find('.select-bonus-item').removeAttr('disabled');\n    }\n    }\n    var totalQty = 0;\n    var itemsValid = [];\n    for (let i = 0; i < selectedList.length; i++) {\n        let element = selectedList[i].qty;\n        totalQty += element;\n        if (totalQty <= maxItems) {\n            itemsValid.push(selectedList[i]);\n        }else {\n            $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n        }\n    }\n    selectedList = itemsValid ? itemsValid: selectedList;\n    if (!selectedList.length) {\n        $bonusProductList.find('li.selected-bonus-item').remove();\n    } else {\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\n    var totquantitycount = 0;\n    for (let i = 0; i < selectedList.length; i++) {\n    let element = selectedList[i].qty;\n    totquantitycount += element;\n    if (totquantitycount >= maxItems) {\n        $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n    } else {\n        $bonusProductList.find('.select-bonus-item').removeAttr('disabled');\n    }\n    }\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    selectedList.length = 0;\n    cartItems.each(function () {\n        var ci = $(this);\n        var product = {\n            uuid: ci.data('uuid'),\n            pid: ''+ ci.data('pid'),\n            qty: eval(ci.find('.item-qty .display-value').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    var totquantitycount = 0;\n    for (let i = 0; i < selectedList.length; i++) {\n    let element = selectedList[i].qty;\n    totquantitycount += element;\n    if (totquantitycount >= maxItems) {\n        $bonusProductList.find('.select-bonus-item').attr('disabled', 'disabled');\n    }\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        var bonuscount = 0;\n        for (let i = 0; i < selectedList.length; i++) {\n        let element = selectedList[i].qty;\n        bonuscount += element;\n        }\n        if (bonuscount >= maxItems) {\n            selectedList = [];\n        }\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        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\n        var selectedfindproduct = selectedList.find((productlist) => productlist.pid === product.pid);\n\n        if (!selectedfindproduct) {\n            selectedList.push(product)\n        } else {\n            let tempselectedList = selectedList.map((sproduct)=>{\n                if (product.pid === sproduct.pid) {\n                    sproduct.qty += product.qty;\n                     if (sproduct.qty > maxItems) {\n                    \tselectedList = [];\n                     }\n                    product.qty = sproduct.qty;\n                }\n                return sproduct;\n            });\n            selectedList = tempselectedList;\n        }\n        let $bonusProductList = $('#bonus-product-list');\n        $bonusProductList.find('li.selected-bonus-item').remove();\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        let $bonusProductList = $('#bonus-product-list');\n        $bonusProductList.find('li.selected-bonus-item').remove();\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 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    /**\n     * if the session.privacy.ratelimited element is present then show the notification\n     * NOTE: You will probably want to replace this with a call to an actual CAPTCHA system to replace the simple one here\n     */\n    if (SessionAttributes.SHOW_CAPTCHA) {\n        dialog.open({\n            html: '<h1>' + Resources.ARE_YOU_HUMAN + '</h1>',\n            options: {\n                closeOnEscape: false,\n                dialogClass: 'no-close',\n                buttons: [{\n                    text: Resources.OK,\n                    click: function () {\n                        var url = util.appendParamsToUrl(Urls.rateLimiterReset, {format: 'ajax'});\n                        $.ajax({\n                            url: url\n                        });\n                        $(this).dialog('close');\n                    }\n                }]\n            }\n        });\n    }\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 accordion = function () {\n    var $container = $(this).closest('.accordion');\n    var $content = $container.find('.js-accordion-body');\n    \n    $container.toggleClass('m-opened');\n    $content.slideToggle(250);\n};\n\nmodule.exports = function () {\n    $('.js-accordion-switcher').on('click', accordion);\n};\n","'use strict';\n\nvar changeQuantity = function () {\n    var quantityCtas = ['button.js-quantity-decrease-button', 'button.js-quantity-increase-button'];\n    $(quantityCtas).each(function(idx, attr) {\n        $pdpMain.on('click', attr, function() {\n            var $quantityInput = $(attr).siblings('.js-product-quantity-input');\n            var quantityInputVal = parseInt($quantityInput.val());\n            var modificatedQuantity;\n\n            if ($(attr).hasClass('js-quantity-decrease-button')) {\n                modificatedQuantity = quantityInputVal > 1 ? quantityInputVal - 1 : 1;\n            } else if ($(attr).hasClass('js-quantity-increase-button')) {\n                modificatedQuantity = quantityInputVal + 1;\n            }\n\n            return $quantityInput.val(modificatedQuantity);\n        });\n    });\n}\n\nmodule.exports = function () {\n    $('.js-quantity-button').on('click', changeQuantity);\n}\n","'use strict';\n\nvar stickyComponent = {\n    init: function (params) {\n        this.isInit = false;\n\n        if(this.isExist(params)) {\n            var $triggerBlock = $(params.trigger);\n            var triggerBottomPoint = $triggerBlock.offset().top + $triggerBlock.height();\n            \n            var stickyContext = this;\n            $(window).on('scroll load', function () {\n                var initEvent;\n                clearTimeout(initEvent);\n            \n                initEvent = setTimeout(function() {\n                    if ($(window).scrollTop() > triggerBottomPoint && !stickyContext.isInit) {\n                        stickyContext.enable();\n                    } else if ($(window).scrollTop() < triggerBottomPoint && stickyContext.isInit) {\n                        stickyContext.disable();\n                    }\n                }, 300);\n            });\n        }\n    },\n    isExist: function (params) {\n        if (params && params.selector && $(params.selector).length) {\n            return this.$stickyBlock = $(params.selector);\n        } else if (this.$stickyBlock) {\n            return this.$stickyBlock;\n        } else {\n            return false;\n        }\n    },\n    enable: function(params) {\n        if(this.isExist(params)) {\n            this.$stickyBlock.addClass('m-sticky-enable').removeClass('m-sticky-disable');\n            this.isInit = true;\n        }\n    },\n    disable: function (params) {\n        if(this.isExist(params)) {\n            this.$stickyBlock.removeClass('m-sticky-enable').addClass('m-sticky-disable');\n            this.isInit = false;\n        }\n    }\n};\n\nmodule.exports = stickyComponent;\n","'use strict';\n\nvar settings = {\n    homePageSlider: {\n        infinite: true,\n        slidesToShow: 1,\n        slidesToScroll: 1,\n        autoplay: true,\n        dots: true,\n        arrows: false\n    },\n    pdpPrimaryCarousel: {\n        infinite: false,\n        slidesToShow: 1,\n        slidesToScroll: 1,\n        arrows: true,\n        asNavFor: '.pdp-thumbnails-slider',\n        responsive: [\n            {\n                breakpoint: 767,\n                settings: {\n                    dots: true\n                }\n            }\n        ]\n    },\n    pdpThumbCarousel: {\n        infinite: false,\n        slidesToShow: 4,\n        slidesToScroll: 1,\n        arrows: false,\n        vertical: true,\n        verticalSwiping: true,\n        asNavFor: '.pdp-primary-slider',\n        centerMode: false,\n        centerPadding: '0px',\n        focusOnSelect: true\n    },\n    pbThumbCarousel: {\n        infinite: false,\n        slidesToShow: 4,\n        slidesToScroll: 1,\n        arrows: false,\n        vertical: false,\n        verticalSwiping: false,\n        asNavFor: '.pdp-primary-slider',\n        centerMode: false,\n        centerPadding: '5px',\n        focusOnSelect: true\n    },\n    recommendationCarousel: {\n        infinite: false,\n        slidesToShow: 4,\n        slidesToScroll: 1,\n        responsive: [\n        {\n          breakpoint: 767,\n          settings: {\n            arrows: true,\n            slidesToShow: 2,\n            dots: false\n          }\n        }\n        ]\n    },\n    einsteinRecommendationCarousel: {\n        infinite: true,\n        slidesToShow: 4,\n        slidesToScroll: 1,\n        dots: false,\n        arrows: true,\n        responsive: [\n        {\n          breakpoint: 767,\n          settings: {\n            arrows: true,\n            slidesToShow: 2,\n            dots: false\n          }\n        }\n        ]\n    }\n};\n\nmodule.exports = settings;\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    $('.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 {\n            $target = $('#dialog-container');\n        }\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        // create the dialog\n        this.$container = $target;\n        this.$container.dialog(_.merge({}, this.settings, params.options || {}));\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    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: '800',\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\nfunction getCurrentData(){\n\tif(sjdata.page == 'shipping') {\n\t\t$(document).trigger('data:checkout', [sjdata]);\n\t} else if(sjdata.page == 'orderconfirmation' || sjdata.page == 'confirmation') {\n\t\t$(document).trigger('data:donate', [sjdata]);\n\t} else if(sjdata.page == 'product') {\n\t\t$(document).trigger('data:pdp', [sjdata]);\n\t} else if(sjdata.page == 'summary') {\n\t\t$(document).trigger('data:payment', [sjdata]);\n\t}\n\t\n}\n\nfunction customPararmeter(data) {\n    var array = data.pids;\n    var j = 0;\n    var contentIDS= [];\n    for (var i = 0; i < array.length; i++){\n    var testID = array[i];\n    if(testID.hasOwnProperty('id')){\n        contentIDS[j] = testID['id'];\n        j++;\n    }\n    }\n   return contentIDS;\n}\n\nmodule.exports = {\n\tinit: function () {\n\t    $(document).on(\"data:addtocart\", function(e, data){\n\t    \tfbq('track', 'AddToCart', {\n\t            content_ids: [data.content_ids],\n\t            content_type: 'product' \n\t        });\n\t    });\n\t    $(document).on(\"data:checkout\", function(e, data){\n\t    \tfbq('track', 'InitiateCheckout', {\n\t    \t\tvalue: data.cartTotal,\n\t    \t\tcurrency: data.currency,\n\t    \t\tnum_items : data.qty,\n\t    \t\tcontents : data.pids\n\t        });\n\t    });\n\t    $(document).on(\"data:donate\", function(e, data){\n\t    \tfbq('track', 'Donate', {\n\t    \t\tcurrency: data.currency,\n\t    \t\tvalue: data.cartTotal,\n\t    \t\tnum_items : data.qty,\n\t    \t\t// content_type: 'product',\n\t    \t\tcontents : data.pids,\n\t\t\t\tcontent_ids : customPararmeter(data)\n\t        });\n\t    });\n\t    $(document).on(\"data:pdp\", function(e, data){\n\t    \tfbq('track', 'ViewContent', {\n\t    \t\tcontent_ids: data.pids,\n\t    \t\tcontent_type: data.content_type,\n\t    \t\tcontent_name: data.content_name\n\t        });\n\t    });\n\t    $(document).on(\"data:payment\", function(e, data){\n\t    \tfbq('track', 'AddPaymentInfo', {\n\t    \t\tcontents: data.pids,\n\t    \t\tcurrency: data.currency,\n\t    \t\tvalue: data.cartTotal\n\t        });\n\t    });\n\t    \n\t\tgetCurrentData();\n\t}\n};","'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// 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        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","'use strict';\n\nvar dialog = require('./dialog'),\n    page = require('./page'),\n    validator = require('./validator');\n\nvar login = {\n    /**\n     * @private\n     * @function\n     * @description init events for the loginPage\n     */\n    init: function () {\n        //o-auth binding for which icon is clicked\n        $('.oAuthIcon').bind('click', function () {\n            $('#OAuthProvider').val(this.id);\n        });\n    \n\n        //toggle the value of the rememberme checkbox\n        $('#dwfrm_login_rememberme').bind('change', function () {\n            if ($('#dwfrm_login_rememberme').attr('checked')) {\n                $('#rememberme').val('true');\n            } else {\n                $('#rememberme').val('false');\n            }\n        });\n        \n        $('#password-reset').on('click', function (e) {\n            e.preventDefault();\n            dialog.open({\n                url: $(e.target).attr('href'),\n                options: {\n                    open: function () {\n                        validator.init();\n                        var $requestPasswordForm = $('[name$=\"_requestpassword\"]');\n                        var $submit = $requestPasswordForm.find('[name$=\"_requestpassword_send\"]');\n                        $($submit).on('click', function (e) {\n                            if (!$requestPasswordForm.valid()) {\n                                return;\n                            }\n                            e.preventDefault();\n                            var data = $requestPasswordForm.serialize();\n                            // add form action to data\n                            data += '&' + $submit.attr('name') + '=';\n                            // make sure the server knows this is an ajax request\n                            if (data.indexOf('ajax') === -1) {\n                                data += '&format=ajax';\n                            }\n                            $.ajax({\n                                type: 'POST',\n                                url: $requestPasswordForm.attr('action'),\n                                data: data,\n                                success: function (response) {\n                                    if (typeof response === 'object' &&\n                                            !response.success &&\n                                            response.error === 'CSRF Token Mismatch') {\n                                        page.redirect(Urls.csrffailed);\n                                    } else if (typeof response === 'string') {\n                                        dialog.$container.html(response);\n                                    }\n                                },\n                                failure: function () {\n                                    dialog.$container.html('<h1>' + Resources.SERVER_ERROR + '</h1>');\n                                }\n                            });\n                        });\n                    }\n                }\n            });\n        });\n        \n        // Based on Resource.ds session attributes\n        if(window.User && window.User.authenticated){\n            $(\".account-nav-registered\").show();\n            $(\".account-nav-unregistered\").hide();\n        } else {\n            $(\".account-nav-registered\").hide();\n            $(\".account-nav-unregistered\").show();\n        }\n    \n    }\n}\n\nmodule.exports = login;\n","'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 = $('.mini-cart-content')\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        timer.start(5000, this.close.bind(this));\n\t\tthis.$content.addClass('triggered');\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.removeClass('triggered');\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 giftcert = require('../giftcert'),\n    tooltip = require('../tooltip'),\n    util = require('../util'),\n    dialog = require('../dialog'),\n    page = require('../page'),\n    login = require('../login'),\n    validator = require('../validator');\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 $form = $('#edit-address-form');\n\n    $form.find('input[name=\"format\"]').remove();\n    tooltip.init();\n    //$(\"<input/>\").attr({type:\"hidden\", name:\"format\", value:\"ajax\"}).appendTo(form);\n\n    $form.on('click', '.apply-button', function (e) {\n        e.preventDefault();\n        if (!$form.valid()) {\n            return false;\n        }\n        var url = util.appendParamToURL($form.attr('action'), 'format', 'ajax');\n        var applyName = $form.find('.apply-button').attr('name');\n        var options = {\n            url: url,\n            data: $form.serialize() + '&' + applyName + '=x',\n            type: 'POST'\n        };\n        $.ajax(options).done(function (data) {\n            if (typeof(data) !== 'string') {\n                if (data.success) {\n                    dialog.close();\n                    page.refresh();\n                } else if (data.error) {\n                    page.redirect(Urls.csrffailed);\n                } else {\n                    window.alert(data.message);\n                    return false;\n                }\n            } else {\n                $('#dialog-container').html(data);\n                account.init();\n                tooltip.init();\n            }\n        });\n    })\n    .on('click', '.cancel-button, .close-button', function (e) {\n        e.preventDefault();\n        dialog.close();\n    })\n    .on('click', '.delete-button', function (e) {\n        e.preventDefault();\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                    page.refresh();\n                } else if (data.message.length > 0) {\n                    window.alert(data.message);\n                    return false;\n                } else {\n                    dialog.close();\n                    page.refresh();\n                }\n            });\n        }\n    });\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    var addresses = $('#addresses');\n    if (addresses.length === 0) { return; }\n\n    addresses.on('click', '.address-edit, .address-create', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: this.href,\n            options: {\n                open: initializeAddressForm \n            }\n        });\n    }).on('click', '.delete', function (e) {\n        e.preventDefault();\n        if (window.confirm(String.format(Resources.CONFIRM_DELETE, Resources.TITLE_ADDRESS))) {\n            $.ajax({\n                url: util.appendParamToURL($(this).attr('href'), 'format', 'ajax'),\n                dataType: 'json'\n            }).done(function (data) {\n                if (data.status.toLowerCase() === 'ok') {\n                    page.redirect(Urls.addressesList);\n                } else if (data.message.length > 0) {\n                    window.alert(data.message);\n                } else {\n                    page.refresh();\n                }\n            });\n        }\n    });\n}\n/**\n * @private\n * @function\n * @description Binds the events of the payment methods list (delete card)\n */\nfunction initPaymentEvents() {\n    $('.add-card').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href'),\n            options: {\n                open: initializePaymentForm\n            }\n        });\n    });\n\n    var paymentList = $('.payment-list');\n    if (paymentList.length === 0) { return; }\n\n    util.setDeleteConfirmation(paymentList, String.format(Resources.CONFIRM_DELETE, Resources.TITLE_CREDITCARD));\n\n    $('form[name=\"payment-remove\"]').on('submit', function (e) {\n        e.preventDefault();\n        // override form submission in order to prevent refresh issues\n        var button = $(this).find('.delete');\n        $('<input/>').attr({\n            type: 'hidden',\n            name: button.attr('name'),\n            value: button.attr('value') || 'delete card'\n        }).appendTo($(this));\n        var data = $(this).serialize();\n        $.ajax({\n            type: 'POST',\n            url: $(this).attr('action'),\n            data: data\n        })\n        .done(function () {\n            page.redirect(Urls.paymentsList);\n        });\n    });\n}\n\nfunction initializePaymentForm() {\n    $('#CreditCardForm').on('click', '.cancel-button', function (e) {\n        e.preventDefault();\n        dialog.close();\n    });\n    \n    validator.init();\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    login.init();\n}\n\nvar account = {\n    init: function () {\n        initializeEvents();\n        giftcert.init();\n    },\n    initCartLogin: function () {\n        login.init();\n    }\n};\n\nmodule.exports = account;\n","'use strict';\n\nvar account = require('./account'),\n    bonusProductsView = require('../bonus-products-view'),\n    quickview = require('../quickview'),\n    cartStoreInventory = require('../storeinventory/cart');\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() {\n    $('#cart-table').on('click', '.item-edit-details a', function (e) {\n        e.preventDefault();\n        quickview.show({\n            url: e.target.href,\n            source: 'cart'\n        });\n    })\n    .on('click', '.bonus-item-actions a, .item-details .bonusproducts a', function (e) {\n        e.preventDefault();\n        bonusProductsView.show(this.href);\n    });\n    \n    $('.update-item, .cart-update-msg').hide();\n    \n    $('form input[name$=\"_quantity\"]').change(function() {\n        $(this).closest('.cart-row').find('.item-quantity-details .item-user-actions .update-item').show();\n        $('.cart-update-msg').show();\n    });\n\n    // override enter key for coupon code entry\n    $('form input[name$=\"_couponCode\"]').on('keydown', function (e) {\n        if (e.which === 13 && $(this).val().length === 0) {\n        \t\treturn false;\n        \t} else if (e.which === 13) {\n        \t\te.preventDefault();\n        \t\t$('form button[name$=\"_cart_addCoupon\"]').trigger('click');\n        \t}\n    });\n    \n    //trigger update cart button\n    $('.updatecart-trigger, .update-item').on('click',function(e) {\n    \te.preventDefault();\n    \t$('#update-cart').trigger( \"click\" );\n    });\n\n    //to prevent multiple submissions of the form when removing a product from the cart\n    var removeItemEvent = false;\n    $('button[name$=\"deleteProduct\"]').on('click', function (e) {\n        if (removeItemEvent) {\n            e.preventDefault();\n        } else {\n            removeItemEvent = true;\n        }\n    });\n    $( window ).load(function() {\n    \tsetTimeout(function(){\n\t\t    $('.slick').each(function() {\n\t\t        var numberOfSlides = $(this).children().length;\n\t\t        if (numberOfSlides > 1) {\n\t\t            var slidesToShowDesktop = 3;\n\t\t            if (numberOfSlides < slidesToShowDesktop) {\n\t\t                slidesToShowDesktop = numberOfSlides;\n\t\t            }\n\t\t            $(this).slick({\n\t\t                infinite: false,\n\t\t                slidesToShow: slidesToShowDesktop,\n\t\t                slidesToScroll: 1,\n\t\t                responsive: [\n\t\t                {\n\t\t                  breakpoint: 959,\n\t\t                  settings: {\n\t\t                    slidesToShow: 2\n\t\t                  }\n\t\t                },\n\t\t                {\n\t\t                  breakpoint: 767,\n\t\t                  settings: {\n\t\t                    arrows:false,\n\t\t                    slidesToShow: 1,\n\t\t                    dots: true\n\t\t                  }\n\t\t                }\n\t\t                ]\n\t\t            }); \n\t\t        }\n\t\t    });\n    \t}, 2000);\n    });\n    \n    // Prevents the form from submitting if nothing has been entered\n    $('button[name$=\"_addDonation\"]').on('click', function (e) {\n    \t\tif (!$('input[name$=\"_donationAmount\"]').val()) {\n    \t\t\te.preventDefault();\n    \t\t}\n    });\n}\n\nexports.init = function () {\n    initializeEvents();\n    if (SitePreferences.STORE_PICKUP) {\n        cartStoreInventory.init();\n    }\n    account.initCartLogin();\n};\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        $('.checkout-billing input[name$=\"_useShippingAsBilling\"]').prop('checked', false);\n        // Briefly hide the payment section to avoid premature form validation on the payment section\n        $(\".checkout-billing-paymentmethods\").hide();\n    \t\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        $(\".checkout-billing-paymentmethods\").show();\n    });\n\n    $('[name$=\"_address1\"], [name$=\"_address2\"]').on('keypress keydown keyup change paste', function(e) {\n    \tvar max = 40;\n    \tif (this.value.length == max && e.keyCode !== 46 && e.keyCode !== 8 && e.keyCode !== 9 && !util.getSelectionText().length) {\n            e.preventDefault();\n        } else if (this.value.length > max) {\n            this.value = this.value.substring(0, max);\n        }\n    \t\n    \tif(this.value.length == max){\n    \t\t$(this).closest('.form-row').find('.form-caption').show().text('40 characters limit');\n    \t} else {\n    \t\t$(this).closest('.form-row').find('.form-caption').hide();\n    \t}\n    });\n};\n","'use strict';\n\nvar ajax = require('../../ajax'),\n    formPrepare = require('./formPrepare'),\n    giftcard = require('../../giftcard'),\n    util = require('../../util');\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=\"CREDIT_CARD\"]');\n    $creditCard.find('input[name$=\"creditCard_owner\"]').val(data.holder).trigger('change');\n    $creditCard.find('select[name$=\"_type\"]').val(data.type);\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('[name$=\"creditCard_selectedCardID\"]').val(data.selectedCardID).trigger('change');\n    if (!('CHECKOUT_AGENT' in SessionAttributes && SessionAttributes.CHECKOUT_AGENT == true)) {\n    \t\t$creditCard.find('input[name$=\"_cvn\"]').val('').trigger('change');\n    }\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/**\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 Populates the billing address fields with the values used for shipping\n */\nfunction initUseShippingAsBilling() {\n\tvar $checkoutForm = $('.checkout-billing');\n\t$('input[name$=\"_useShippingAsBilling\"]', $checkoutForm).on(\"change\", function () {\n\t\tif ($(this).is(':checked')) {\n            $('#billing_hide').hide();\n            $('#mini_address_show .billingAddressCard').show();\n\t\t\tif ('shippingAddress' in User && !$.isEmptyObject(User.shippingAddress)) {\n\t\t\t\t$checkoutForm.find('input[name$=\"_firstName\"]').val(User.shippingAddress.firstName);\n\t\t\t\t$checkoutForm.find('input[name$=\"_lastName\"]').val(User.shippingAddress.lastName);\n\t\t\t\t$checkoutForm.find('input[name$=\"_address1\"]').val(User.shippingAddress.address1);\n\t\t\t\t$checkoutForm.find('input[name$=\"_address2\"]').val(User.shippingAddress.address2);\n\t\t\t\t$checkoutForm.find('input[name$=\"_city\"]').val(User.shippingAddress.city);\n\t\t\t\t$checkoutForm.find('select[name$=\"_state\"]').val(User.shippingAddress.state);\n\t\t\t\t$checkoutForm.find('input[name$=\"_postal\"]').val(User.shippingAddress.postalCode);\n\t\t\t\t$checkoutForm.find('input[name$=\"_phone\"]').val(User.shippingAddress.phone);\n\t\t\t\t$checkoutForm.find('select[name$=\"_billing_addressList\"] option:first').prop('selected', true);\n\t\t\t}\n            $(this).closest('div.form-row').addClass('visually-hidden');\n\t\t} else {\n            $('#billing_hide').show();\n            $('#mini_address_show .billingAddressCard').hide();           \n\t\t\t$checkoutForm.find('input[name$=\"_firstName\"]').val('');\n\t\t\t$checkoutForm.find('input[name$=\"_lastName\"]').val('');\n\t\t\t$checkoutForm.find('input[name$=\"_address1\"]').val('');\n\t\t\t$checkoutForm.find('input[name$=\"_address2\"]').val('');\n\t\t\t$checkoutForm.find('input[name$=\"_city\"]').val('');\n\t\t\t$checkoutForm.find('select[name$=\"_state\"] option:first').prop('selected',true);\n\t\t\t$checkoutForm.find('input[name$=\"_postal\"]').val('');\n\t\t\t$checkoutForm.find('input[name$=\"_phone\"]').val('');\n\t\t}\n\t});\n\n    $('#btn_billing_edit').on('click', function () {\n        var $_useShippingAsBilling = $('input[name$=\"_useShippingAsBilling\"]');\n        $_useShippingAsBilling.prop(\"checked\", !$_useShippingAsBilling.prop(\"checked\"));\n        if (!$_useShippingAsBilling.prop(\"checked\")) {\n            $_useShippingAsBilling.closest('div.form-row').removeClass('visually-hidden');\n        } else {\n            $_useShippingAsBilling.closest('div.form-row').addClass('visually-hidden');\n        }\n        $('input[name$=\"_useShippingAsBilling\"]', $checkoutForm).trigger(\"change\");\n    });\n\t\n\t// If the user makes changes to the fields, we should uncheck the 'Use shipping as billing' box\n\t$('input', $checkoutForm).filter('[name$=\"_firstName\"],[name$=\"_lastName\"],[name$=\"_address1\"],[name$=\"_address2\"],[name$=\"_city\"],[name$=\"_postal\"],[name$=\"_phone\"]').keyup(function () {\n\t\t$('input[name$=\"_useShippingAsBilling\"]', $checkoutForm).prop('checked', false);\n\t});\n\n\t// The state drop-down doesn't have a keyup event, so we listen for it to be changed.\n\t$('select[name$=\"_state\"]', $checkoutForm).on('change', function () {\n\t\t$('input[name$=\"_useShippingAsBilling\"]', $checkoutForm).prop('checked', false);\n\t});\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    // This will reset the payment details on card type change to prevent functional issue\n    $(\"#dwfrm_billing_paymentMethods_creditCard_type\").on('change',function() {\n\t    \t$(\"input[id^='dwfrm_billing_paymentMethods_creditCard_number']\").val('');\n\t    \t$(\"#dwfrm_billing_paymentMethods_creditCard_expiration_month option:first\").prop('selected',true);\n\t    \t$(\"#dwfrm_billing_paymentMethods_creditCard_expiration_year option:first\").prop('selected',true);\n\t    \t$(\"input[id^='dwfrm_billing_paymentMethods_creditCard_cvn']\").val('');\n\t    \t$('.checkout-billing').find('input[name$=\"_selectedCardID\"]').val('');\n\t    \t$('#creditCardList option:first').prop('selected',true).trigger('change');\n    });\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 : 'CREDIT_CARD');\n    $selectPaymentMethod.on('click', 'input[type=\"radio\"]', function () {\n        updatePaymentMethod($(this).val());\n    });\n    \n    //this is make the whole expiration field container tag as error in billing page\n    if($('.expiration-container .form-row.month').hasClass('error')) {\n    \t\t$('.expiration-container').addClass('error');\n    }\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) {\n        \t\t$($checkoutForm).find('input[name$=\"_selectedCardID\"]').val(''); \n        \t\treturn;\n        \t}\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($('#paymentError').val() === 'false') {\n\t    if($creditCardList.length > 0){\n\t\t\t$creditCardList.find('option').eq(1).prop('selected', true);\n\t\t\t$creditCardList.trigger('change');\n\t\t}\n    }\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        \t\t$sucess = $checkoutForm.find('.coupon-success'),\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                $sucess.html('');\n                return;\n            }\n            \n            if(data.success) {\n            \t\t$sucess.html(data.message);\n            \t\twindow.location.assign(Urls.billing);\n            \t\treturn;\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    initUseShippingAsBilling();\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\n    return _(requiredValues).includes('');\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    \n    jQuery.validator.addMethod(\"checklen\", function (value) {\n        return value.length <= 40;\n    }, \"40 character limit\");\n\n    jQuery.validator.classRuleSettings.checklen = { checklen: true };\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    \t   onkeyup: true\n    });\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    $form.find('input[name$=\"_address2\"]').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\nfunction initRoundUpDonations() {\n\t$('input[name$=\"isRoundUpDonation\"').on('click', function () {\n\t\tvar previousSetting = $(this).data('checked') ? true : false,\n\t\t\toptions = {\n\t            url: Urls.SetCheckoutRoundUpDonations,\n\t            data: 'enableRoundUpDonation=' + !previousSetting,\n\t            type: 'POST'\n\t        };\n\t\t\n\t\t// Un-check the radio button\n\t\tif (previousSetting == true) {\n\t\t\t$(this).prop('checked', false);\n\t\t\t$(this).data('checked', false);\n\t\t} else {\n\t\t\t$(this).data('checked', true);\n\t\t}\n\t\t\n\t\t// The new setting is always the opposite of the previous\n\t\tif (!previousSetting) {\n\t\t\tupdateRoundUpTotalDisplay(true);\n\t\t} else {\n\t\t\tupdateRoundUpTotalDisplay(false);\n\t\t}\n\t});\n\t\n\t$('<span class=\"slider round\"></span>').insertAfter(\"#dwfrm_billing_donations_isRoundUpDonation\");\n\n}\n\nfunction updateRoundUpTotalDisplay(enabled) {\n\tvar $orderTotalElement = $(\".order-total .order-value\"),\n\t\t$donationTotalElement = $(\".donations-total .donations-value\"),\n\t\toriginalOrderTotal = $orderTotalElement.data('originalTotal'),\n\t\toriginalDonationTotal = $donationTotalElement.data('originalTotal'),\n\t\tnewDonationTotal;\n\t\n\t// If it's null, it hasn't been set before, so the original totals are still displaying\n\toriginalOrderTotal = getOrSetStoredValue(originalOrderTotal, $orderTotalElement);\n\toriginalDonationTotal = getOrSetStoredValue(originalDonationTotal, $donationTotalElement);\n\t\n\tif (enabled) {\n\t\t// Update the values to factor in round-up donation\n\t\tnewDonationTotal = originalDonationTotal + getRoundUpAmount(originalOrderTotal);\n\t\tif (Resources.CURRENCY_SYMBOL_PLACEMENT == 'before') {\n\t\t\t$donationTotalElement.html(Resources.CURRENCY_SYMBOL + newDonationTotal.toFixed(2));\n\t\t\t$orderTotalElement.html(Resources.CURRENCY_SYMBOL + Math.ceil(originalOrderTotal).toFixed(2));\t\n\t\t} else {\n\t\t\t$donationTotalElement.html(newDonationTotal.toFixed(2) + Resources.CURRENCY_SYMBOL);\n\t\t\t$orderTotalElement.html(Math.ceil(originalOrderTotal).toFixed(2) + Resources.CURRENCY_SYMBOL);\n\t\t}\n\t} else {\n\t\t// Grab the original total from the js data element\n\t\tif (Resources.CURRENCY_SYMBOL_PLACEMENT == 'before') {\n\t\t\t$donationTotalElement.html(Resources.CURRENCY_SYMBOL + $donationTotalElement.data('originalTotal').toFixed(2));\n\t\t\t$orderTotalElement.html(Resources.CURRENCY_SYMBOL + $orderTotalElement.data('originalTotal').toFixed(2));\n\t\t} else {\n\t\t\t$donationTotalElement.html($donationTotalElement.data('originalTotal').toFixed(2) + Resources.CURRENCY_SYMBOL);\n\t\t\t$orderTotalElement.html($orderTotalElement.data('originalTotal').toFixed(2) + Resources.CURRENCY_SYMBOL);\n\t\t}\n\t}\n}\n\nfunction getOrSetStoredValue(data, domElement) {\n\tif (data == null) {\n\t\tdata = Number(domElement.html().replace(/[^0-9\\.-]+/g,\"\"));\n\t\tdomElement.data('originalTotal', data);\n\t}\n\t\n\treturn data;\n}\n\nfunction getRoundUpAmount(OrderTotal) {\n\tconsole.log('Calculating round-up amount');\n\treturn Math.ceil(OrderTotal) - OrderTotal;\n}\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 disable 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    initRoundUpDonations();\n    \n    $('.js-submit-order').off('click.submit-order-ns').on('click.submit-order-ns', function(e) {\n        e.preventDefault()\n        $(this).prop('disabled', true);\n        $(this).closest('form.submit-order').submit();\n    });\n    \n    $('.js-submit-order').dblclick(false);\n};\n\n","'use strict';\n\nvar address = require('./address'),\n    formPrepare = require('./formPrepare'),\n    dialog = require('../../dialog'),\n    util = require('../../util'),\n    validator = require('../../validator');\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        originalUUID,\n        resetOptionValue = false,\n        selectedAddressUUID = $(target).parent().siblings('.select-address').val();\n\n    $addressDropdown.on('change', function (e) {\n        e.preventDefault();\n\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            resetOptionValue = false;\n            // proceed to fill the form with the selected address\n            util.fillAddressFields(selectedAddress, $addressForm);\n        } else if  (selectedAddress === 'newAddress') {\n            add = true;\n            resetOptionValue = true;\n            $addressForm.find('.input-text, .input-select').val('');\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        if (!$addressForm.valid()) {\n            return false;\n        }\n\n        $.getJSON(Urls.addEditAddress, $addressForm.serialize(), function (response) {\n            if (!response.success) {\n                $('#multiaddresserror').html(Resources.COULD_NOT_SAVE_ADDRESS);\n                return;\n            }\n            $('#multiaddresserror').toggleClass('hidden', response.success);\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\n            if (address.UUID !== originalUUID) {\n                resetOptionValue = true;\n            }\n\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() === '' || resetOptionValue) {\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        originalUUID = selectedAddressUUID;\n    }\n\n    validator.init();\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', 'span', function (e) {\n        dialog.open({url: this.attributes.href.value,  options: {open: function () {\n            address.init();\n            addEditAddress(e.target);\n        }}});\n    });\n};\n","'use strict';\r\n\r\nvar ajax = require('../../ajax'),\r\n    formPrepare = require('./formPrepare'),\r\n    progress = require('../../progress'),\r\n    tooltip = require('../../tooltip'),\r\n    util = require('../../util'),\r\n    dialog = require('../../dialog'),\r\n    _ = require('lodash');\r\nconst { title } = require('../../page');\r\n\r\nvar shippingMethods;\r\n/**\r\n * @function\r\n * @description Initializes gift message box, if shipment is gift\r\n */\r\nfunction giftMessageBox() {\r\n    // show gift message box, if shipment is gift\r\n    $('.gift-message-text').toggleClass('hidden', $('input[name$=\"_shippingAddress_isGift\"]:checked').val() !== 'true');\r\n}\r\n\r\n/**\r\n * @function\r\n * @description updates the order summary based on a possibly recalculated basket after a shipping promotion has been applied\r\n */\r\nfunction updateSummary() {\r\n    var $summary = $('#secondary.summary');\r\n    // indicate progress\r\n    progress.show($summary);\r\n\r\n    // load the updated summary area\r\n    $summary.load(Urls.summaryRefreshURL, function () {\r\n        // hide edit shipping method link\r\n        $summary.fadeIn('fast');\r\n        $summary.find('.checkout-mini-cart .minishipment .header a').hide();\r\n        $summary.find('.order-totals-table .order-shipping .label a').hide();\r\n    });\r\n}\r\n\r\n/**\r\n * @function\r\n * @description Helper method which constructs a URL for an AJAX request using the\r\n * entered address information as URL request parameters.\r\n */\r\nfunction getShippingMethodURL(url, extraParams) {\r\n    var $form = $('.address');\r\n    var params = {\r\n        address1: $form.find('input[name$=\"_address1\"]').val(),\r\n        address2: $form.find('input[name$=\"_address2\"]').val(),\r\n        countryCode: $form.find('select[id$=\"_country\"]').val(),\r\n        stateCode: $form.find('select[id$=\"_state\"]').val(),\r\n        postalCode: $form.find('input[name$=\"_postal\"]').val(),\r\n        city: $form.find('input[name$=\"_city\"]').val()\r\n    };\r\n    return util.appendParamsToUrl(url, $.extend(params, extraParams));\r\n}\r\n\r\n/**\r\n * @function\r\n * @description selects a shipping method for the default shipment and updates the summary section on the right hand side\r\n * @param\r\n */\r\nfunction selectShippingMethod(shippingMethodID) {\r\n    // nothing entered\r\n    if (!shippingMethodID) {\r\n        return;\r\n    }\r\n    // attempt to set shipping method\r\n    var url = getShippingMethodURL(Urls.selectShippingMethodsList, {shippingMethodID: shippingMethodID});\r\n    ajax.getJson({\r\n        url: url,\r\n        callback: function (data) {\r\n            updateSummary();\r\n            if (!data || !data.shippingMethodID) {\r\n                window.alert('Couldn\\'t select shipping method.');\r\n                return false;\r\n            }\r\n            // display promotion in UI and update the summary section,\r\n            // if some promotions were applied\r\n            $('.shippingpromotions').empty();\r\n\r\n            // TODO the for loop below isn't doing anything?\r\n            // if (data.shippingPriceAdjustments && data.shippingPriceAdjustments.length > 0) {\r\n            //     var len = data.shippingPriceAdjustments.length;\r\n            //     for (var i=0; i < len; i++) {\r\n            //         var spa = data.shippingPriceAdjustments[i];\r\n            //     }\r\n            // }\r\n        }\r\n    });\r\n}\r\n\r\n/**\r\n * @function\r\n * @description Make an AJAX request to the server to retrieve the list of applicable shipping methods\r\n * based on the merchandise in the cart and the currently entered shipping address\r\n * (the address may be only partially entered).  If the list of applicable shipping methods\r\n * has changed because new address information has been entered, then issue another AJAX\r\n * request which updates the currently selected shipping method (if needed) and also updates\r\n * the UI.\r\n */\r\nfunction updateShippingMethodList() {\r\n    var $shippingMethodList = $('#shipping-method-list');\r\n    if (!$shippingMethodList || $shippingMethodList.length === 0) { return; }\r\n    var url = getShippingMethodURL(Urls.shippingMethodsJSON);\r\n\r\n    ajax.getJson({\r\n        url: url,\r\n        callback: function (data) {\r\n            if (!data) {\r\n                window.alert('Couldn\\'t get list of applicable shipping methods.');\r\n                return false;\r\n            }\r\n            if (shippingMethods && shippingMethods.toString() === data.toString()) {\r\n                // No need to update the UI.  The list has not changed.\r\n                return true;\r\n            }\r\n\r\n            // We need to update the UI.  The list has changed.\r\n            // Cache the array of returned shipping methods.\r\n            shippingMethods = data;\r\n            // indicate progress\r\n            progress.show($shippingMethodList);\r\n\r\n            // load the shipping method form\r\n            var smlUrl = getShippingMethodURL(Urls.shippingMethodsList);\r\n            $shippingMethodList.load(smlUrl, function () {\r\n                $shippingMethodList.fadeIn('fast');\r\n                // rebind the radio buttons onclick function to a handler.\r\n                $shippingMethodList.find('[name$=\"_shippingMethodID\"]').click(function () {\r\n                    selectShippingMethod($(this).val());\r\n                });\r\n\r\n                // update the summary\r\n                updateSummary();\r\n                progress.hide();\r\n                tooltip.init();\r\n                //if nothing is selected in the shipping methods select the first one\r\n                if ($shippingMethodList.find('.input-radio:checked').length === 0) {\r\n                    $shippingMethodList.find('.input-radio:first').prop('checked', 'checked');\r\n                }\r\n            });\r\n        }\r\n    });\r\n}\r\n\r\nvar loqateHelper = {\r\n   \r\n    options : {\r\n        key: SitePreferences.LOQATE_KEY,\r\n        manualEntryItem: true, \r\n        setCountryByIP: false\r\n    },\r\n    \r\n    init : function() {\r\n        \r\n        var serviceAvailable = this.checkServiceAvailability();\r\n        \r\n        \r\n        return;\r\n        \r\n        if (!serviceAvailable) {\r\n            return;\r\n        }\r\n        var _this = this;\r\n        $('[name*=_billingAddress_addressFields_address1]').on('focus', function () {\r\n            _this.initOnBillingAddress();\r\n        });\r\n        \r\n        $('[name*=_shippingAddress_addressFields_address1]').on('focus', function () {\r\n            _this.initOnShippingAddress();\r\n        });\r\n        _this.initOnShippingAddress();\r\n    },\r\n    \r\n    initBillingAddressEvent : function () {\r\n        var serviceAvailable = this.checkServiceAvailability();\r\n        \r\n        if (!serviceAvailable) {\r\n            return;\r\n        }\r\n        var _this = this;\r\n        $('[name*=_billingAddress_addressFields_address1]').on('focus', function () {\r\n            _this.initOnBillingAddress();\r\n        });\r\n    },\r\n    \r\n    initOnBillingAddress : function () {\r\n        \r\n        var $billingCounty = $('[name*=_billingAddress_addressFields_countries]');\r\n        var serviceAvailable = this.checkServiceAvailability();\r\n        if (!serviceAvailable || !$billingCounty.length) {\r\n            return;\r\n        }\r\n        var stateElementSelector = '[name*=_billingAddress_addressFields_states]';\r\n        var billingState = $('[name*=_billingAddress_addressFields_states]');\r\n        \r\n        var billingCountry = $billingCounty.val();\r\n        var billingFields = [\r\n              {element: \"_billingAddress_addressFields_address1\", field: \"Line1\" },\r\n              {element: \"_billingAddress_addressFields_address2\", field: \"Line2\", mode: pca.fieldMode.POPULATE },\r\n              {element: \"_billingAddress_addressFields_city\", field: \"City\", mode: pca.fieldMode.POPULATE },\r\n              {element: \"_billingAddress_addressFields_postal\", field: \"PostalCode\", mode: pca.fieldMode.POPULATE}\r\n        ];\r\n        if (billingState.length) {\r\n            billingFields.push({element: billingState.attr('name'), field: \"ProvinceName\", mode: pca.fieldMode.POPULATE });\r\n        }\r\n        \r\n        var billingOptions = this.options;\r\n        billingOptions.search = {countries: billingCountry.toUpperCase()};\r\n        \r\n        this.billingControl = new pca.Address(billingFields, billingOptions);\r\n        \r\n        this._addCustomEvents(\r\n            this.billingControl,\r\n            {\r\n                'country' : billingCountry,\r\n                'stateElementSelector' : stateElementSelector,\r\n                'postalElementSelector' : \"[name$='_billingAddress_addressFields_postal']\",\r\n                'billing' : true\r\n            }\r\n        );\r\n    },\r\n    \r\n    initOnShippingAddress : function () {\r\n        var $shippingCountry =  $(\"[name$='_shippingAddress_addressFields_country']\");\r\n        var serviceAvailable = this.checkServiceAvailability();\r\n        if (!serviceAvailable) {\r\n            return;\r\n        }\r\n        var stateElementSelector = \"[name$='_shippingAddress_addressFields_states_state']\";\r\n        var shippingState = $(stateElementSelector);\r\n        \r\n        var shippingCountry = $shippingCountry.val();\r\n        var shippingFields = [\r\n              {element: \"_shippingAddress_addressFields_address1\", field: \"Line1\" },\r\n              {element: \"_shippingAddress_addressFields_address2\", field: \"Line2\"/*, mode: pca.fieldMode.POPULATE */},\r\n              {element: \"_shippingAddress_addressFields_city\", field: \"City\"/*, mode: pca.fieldMode.POPULATE */},\r\n              {element: \"_shippingAddress_addressFields_postal\", field: \"PostalCode\"/*, mode: pca.fieldMode.POPULATE*/}\r\n        ];\r\n        \r\n        if (shippingState.length) {\r\n            shippingFields.push({element: \"_shippingAddress_addressFields_states_state\", field: \"ProvinceCode\"/*, mode: pca.fieldMode.POPULATE */});\r\n        }\r\n\r\n        var shippingOptions = this.options;\r\n        shippingOptions.search = {countries: shippingCountry.toUpperCase()};\r\n        this.shippingControl = new pca.Address(shippingFields, shippingOptions);\r\n        \r\n        this._addCustomEvents(\r\n                this.shippingControl,\r\n                {\r\n                    'country' : shippingCountry,\r\n                    'stateElementSelector' : stateElementSelector,\r\n                    'postalElementSelector' : \"[name$='_shippingAddress_addressFields_postal']\",\r\n                    'shipping' : true\r\n                }\r\n            );\r\n        \r\n    },\r\n    \r\n    initOnProfileAddress : function () {\r\n        var $profileCountry =  $(\"[name*=_profile_address_countries]\");\r\n        var serviceAvailable = this.checkServiceAvailability();\r\n        if (!serviceAvailable || !$profileCountry.length) {\r\n            return;\r\n        }\r\n        var stateElementSelector = '[name*=_profile_address_states]';\r\n        var $profileState = $(stateElementSelector);\r\n        \r\n        var profileCountry = $profileCountry.val();\r\n        var profileFields = [\r\n              {element: \"_profile_address_address1\", field: \"Line1\" },\r\n              {element: \"_profile_address_address2\", field: \"Line2\", mode: pca.fieldMode.POPULATE },\r\n              {element: \"_profile_address_city\", field: \"City\", mode: pca.fieldMode.POPULATE },\r\n              {element: \"_profile_address_postal\", field: \"PostalCode\", mode: pca.fieldMode.POPULATE}\r\n        ];\r\n        \r\n        if ($profileState.length) {\r\n            profileFields.push({element: $profileState.attr('name'), field: \"ProvinceName\", mode: pca.fieldMode.POPULATE });\r\n        }\r\n\r\n        var profileOptions = this.options;\r\n        profileOptions.search = {countries: profileCountry.toUpperCase()};\r\n       \r\n        this.profileControl = new pca.Address(profileFields, profileOptions);\r\n        \r\n        this._addCustomEvents(\r\n                this.profileControl,\r\n                {\r\n                    'country' : profileCountry,\r\n                    'stateElementSelector' : stateElementSelector,\r\n                    'postalElementSelector' : \"[name$='_profile_address_postal']\",\r\n                    'profile' : true\r\n                }\r\n            );\r\n        \r\n    },\r\n    \r\n    checkServiceAvailability : function () {\r\n        if (typeof pca === 'undefined' || !pca) {\r\n            return false;\r\n        }\r\n        return true;\r\n    },\r\n   \r\n    _addCustomEvents : function (control, config) {\r\n       if (!control) {\r\n           return;\r\n       }\r\n       \r\n       control.listen(\"populate\", function(address) {\r\n           // populate GB county with AdminAreaName data if it is not populated yet \r\n           if (config.country.toLowerCase() === 'gb') {\r\n               var $province = $(config.stateElementSelector);\r\n               var province = address.Province;\r\n               var adminAreaName = address.AdminAreaName;\r\n\r\n               var proviceNameOptionVal = getOptionWithTextValue(config.stateElementSelector, province);\r\n               var adminAreaNameOptionVal = getOptionWithTextValue(config.stateElementSelector, adminAreaName);\r\n               if (proviceNameOptionVal) {\r\n                   $province.val(proviceNameOptionVal);\r\n               } else if (adminAreaNameOptionVal) {\r\n                   $province.val(adminAreaNameOptionVal);\r\n               } else if ($(config.stateElementSelector + ' option[value=\"' +province+ '\"]').length) {\r\n                   $province.val(province);\r\n               }\r\n           }\r\n           // auto populate Postal code for the Hong Kong \r\n           if (config.country.toLowerCase() === 'hk') {\r\n               var $postal = $(config.postalElementSelector);\r\n               if ($postal.length) {\r\n                   $postal.val(SitePreferences.HONG_KONG_DEFAULT_POSTAL);\r\n               }\r\n           }\r\n\r\n           if (config.shipping) {\r\n               $(\"[name$='_shippingAddress_addressFields_address1']\").trigger('shipping-address-populated');\r\n           }\r\n           \r\n           if (config.billing) {\r\n               $(\"[name$='_billingAddress_addressFields_address1']\").trigger('billing-address-populated');\r\n           }\r\n           \r\n           if (config.profile) {\r\n               $(\"[name$='_profile_address_address1']\").trigger('profile-address-populated');\r\n           }\r\n       });\r\n       \r\n       function getOptionWithTextValue(selectSelector, text) {\r\n           var value = '';\r\n           $(selectSelector + ' option').each(function() {    \r\n               if($(this).text().toString() === text) {\r\n                   value = $(this).val();\r\n                   return false;\r\n               }\r\n           });\r\n           return value;\r\n       }\r\n    }\r\n}\r\n\r\n/**\r\n * @function\r\n * @description filter emoji symbols\r\n * @param String\r\n * @return String\r\n */\r\nfunction filterEmoji (str) {\r\n    var regex = /(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\u0023-\\u0039]\\ufe0f?\\u20e3|\\u3299|\\u3297|\\u303d|\\u3030|\\u24c2|\\ud83c[\\udd70-\\udd71]|\\ud83c[\\udd7e-\\udd7f]|\\ud83c\\udd8e|\\ud83c[\\udd91-\\udd9a]|\\ud83c[\\udde6-\\uddff]|\\ud83c[\\ude01-\\ude02]|\\ud83c\\ude1a|\\ud83c\\ude2f|\\ud83c[\\ude32-\\ude3a]|\\ud83c[\\ude50-\\ude51]|\\u203c|\\u2049|[\\u25aa-\\u25ab]|\\u25b6|\\u25c0|[\\u25fb-\\u25fe]|\\u00a9|\\u00ae|\\u2122|\\u2139|\\ud83c\\udc04|[\\u2600-\\u26FF]|\\u2b05|\\u2b06|\\u2b07|\\u2b1b|\\u2b1c|\\u2b50|\\u2b55|\\u231a|\\u231b|\\u2328|\\u23cf|[\\u23e9-\\u23f3]|[\\u23f8-\\u23fa]|\\ud83c\\udccf|\\u2934|\\u2935|[\\u2190-\\u21ff])/g;\r\n    return str.replace(regex, '');\r\n}\r\n\r\nfunction populateAdrr() {\r\n\r\n    var $shippinForm = $('form.checkout-shipping');\r\n    var url = $shippinForm.data('avs-url');\r\n    \r\n    if(!url){\r\n        return;\r\n    }\r\n\r\n    $.ajax({\r\n        type: \"POST\",\r\n        url: url,\r\n        data: $shippinForm.serialize(),\r\n        success: function (response) {\r\n            if (response) {\r\n                dialog.open({\r\n                    html: response,\r\n                    options: {\r\n                        modal:true,\r\n                        width: 570,\r\n                        open: function () {\r\n                            $('.ui-dialog-titlebar').hide();\r\n                            $(document).on('click','#recom_address, #btn_recomended', function (e) {\r\n                                e.preventDefault();\r\n                                var addrData = JSON.parse($('input[type=radio][id=recom_address]').val());\r\n                                $(\"input[name$='_singleshipping_shippingAddress_addressFields_city']\").val(addrData.Locality);\r\n                                $(\"input[name$='_singleshipping_shippingAddress_addressFields_postal']\").val(addrData.PostalCodePrimary);\r\n                                $(\"select[name$='_singleshipping_shippingAddress_addressFields_states_state']\").val(addrData.AdministrativeArea);\r\n                                $(\"input[name$='_shippingAddress_addressFields_address1']\").val(addrData.DeliveryAddress1);\r\n                                $(\"input[name$='_shippingAddress_addressFields_address2']\").val(addrData.Address2);\r\n                                dialog.close();\r\n                                $('#dwfrm_singleshipping_shippingAddress').data('avs-confirmed',1);\r\n                                $(\"button[name='dwfrm_singleshipping_shippingAddress_save']\").first().trigger('click');\r\n                                \r\n                            });\r\n\r\n                            $(document).on('click','#btn_entered, #entered_address', function (e) {\r\n                                e.preventDefault();\r\n                                dialog.close();\r\n                                $('#dwfrm_singleshipping_shippingAddress').data('avs-confirmed',1);\r\n                                $(\"button[name='dwfrm_singleshipping_shippingAddress_save']\").first().trigger('click');\r\n                            });\r\n                        }\r\n        \r\n                    }\r\n                });\r\n            }\r\n        },\r\n        error: function(error){\r\n            console.log('Error AVS request'); // never expose public error  messages\r\n        }\r\n    });\r\n\r\n    \r\n}\r\n\r\nexports.init = function () {\r\n    formPrepare.init({\r\n        continueSelector: '[name$=\"shippingAddress_save\"]',\r\n        formSelector:'[id$=\"singleshipping_shippingAddress\"]'\r\n    });\r\n    $('input[name$=\"_shippingAddress_isGift\"]').on('click', giftMessageBox);\r\n\r\n    $('.address').on('change',\r\n        'input[name$=\"_addressFields_address1\"], input[name$=\"_addressFields_address2\"], select[name$=\"_addressFields_states_state\"], input[name$=\"_addressFields_city\"], input[name$=\"_addressFields_zip\"]',\r\n        updateShippingMethodList\r\n    );\r\n\r\n    $('#dwfrm_singleshipping_shippingAddress').on('submit', function(e){\r\n        var avsUrl = $('#dwfrm_singleshipping_shippingAddress').data('avs-url');\r\n        if(avsUrl){\r\n            let confirmed = $('#dwfrm_singleshipping_shippingAddress').data('avs-confirmed');\r\n            if(!confirmed){\r\n                e.preventDefault();\r\n                populateAdrr();\r\n            }\r\n        }\r\n    });\r\n\r\n    \r\n\r\n    giftMessageBox();\r\n    updateShippingMethodList();\r\n};\r\n\r\nexports.updateShippingMethodList = updateShippingMethodList;\r\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 dialog = require('../../dialog'),\n    minicart = require('../../minicart'),\n    page = require('../../page'),\n    util = require('../../util'),\n    Promise = require('promise'),\n    _ = require('lodash');\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        $pid = $form.find('input[name=\"pid\"]').val();\n    if ($qty.length === 0 || isNaN($qty.val()) || parseInt($qty.val(), 10) === 0) {\n        $qty.val('1');\n    }\n    return Promise.resolve($.ajax({\n        type: 'POST',\n        url: util.ajaxUrl(Urls.addProduct),\n        data: $form.serialize(),\n        async: false\n    })).then(function (response) {\n        // handle error in the response\n        if (response.error) {\n            throw new Error(response.error);\n        } else {\n            try {\n                if (SitePreferences.FB_PIXEL_ENABLED === true || (SitePreferences.TIKTOK_PIXEL_ENABLED === true && SitePreferences.TIKTOK_PIXEL_ID === true)) {\n                    $(document).trigger('data:addtocart', {'content_ids' : $pid});\n                }\n                return response;\n            } catch (error) {\n                console.error(error);\n            }\n        }\n    });\n};\n\n/**\n * @description Handler to handle the add to cart event\n */\nvar addToCart = function (e) {\n    e.preventDefault();\n    var $form = $(this).closest('form');\n\n    addItemToCart($form).then(function (response) {\n        var $uuid = $form.find('input[name=\"uuid\"]');\n        if ($uuid.length > 0 && $uuid.val().length > 0) {\n            page.refresh();\n        } else {\n            // do not close quickview if adding individual item that is part of product set\n            // @TODO should notify the user some other way that the add action has completed successfully\n            if (!$(this).hasClass('sub-product-item')) {\n                dialog.close();\n            }\n            minicart.show(response);\n        }\n    }.bind(this));\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    Promise.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', addToCart);\n    $('.producttile-addtocart').on('click', '.add-to-cart', addToCart);\n    $('#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 util = require('../../util');\nvar carouselConfig = require('../../configs/carousel');\nvar qs = require('qs');\nvar url = require('url');\nvar _ = require('lodash');\n\nvar zoomMediaQuery = matchMedia('(min-width: 960px)');\n\n\n/* @module image\n * @description this module handles the primary image viewer on PDP\n **/\n\n/**\n * @description Enables the zoom viewer on the product detail page\n * @param zmq {Media Query List}\n */\nfunction loadZoom (zmq) {\n    var $imgZoom = $('#pdpMain .main-image .zoom-img'),\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\n    $imgZoom.each(function(ind, item) {\n        hiresUrl = $(item).data('href');\n\n        if (hiresUrl && hiresUrl !== 'null' && hiresUrl.indexOf('noimagelarge') === -1 && zoomMediaQuery.matches) {\n            $(item).trigger('zoom.destroy');\n            $(item).zoom({\n                url: hiresUrl\n            });\n        }\n    });\n}\n\nzoomMediaQuery.addListener(loadZoom);\n\n/**\n * Sliders initialization handler. Monitors the loading of images inside the slider container\n * @param {jQuery object} $sliderContainer - slider container jQuery object\n * @param {JSON} settings - json with slider settings\n */\nfunction initSliderHandler($sliderContainer, settings) {\n    var $images = $sliderContainer.find('.js-slider-image').filter((ind, image) => {\n        return image.complete === false;\n    });\n    var i = 0;    \n    if (!$images.length) {\n        $sliderContainer.slick(settings);\n    } else {\n        $images.on('load', function() {\n            i++;\n            if(i === $images.length) {\n                setTimeout(function(){\n                    $sliderContainer.slick(settings).data('slick',settings);\n                },0)\n            }\n        });\n    }\n}\n\n/**\n * @description initialize mobile slider for images\n */\nfunction initProductSlider() {     \n    initSliderHandler(\n        $('.pdp-primary-slider'),\n        carouselConfig.pdpPrimaryCarousel\n    );\n    let isPBThumbCarousel = $('.pb-thumbnails-slider').length > 0;\n    initSliderHandler(\n        $('.pdp-thumbnails-slider'),\n        !isPBThumbCarousel ? carouselConfig.pdpThumbCarousel: carouselConfig.pbThumbCarousel\n    );\n}\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 */\nfunction setMainImage (attr) {\n    var atts =  typeof attr === 'string' ? JSON.parse(attr) : attr;\n\n    $('#pdpMain .main-image.slick-current .primary-image').attr({\n        src: atts.url,\n        alt: atts.alt,\n        title: atts.title\n    });\n    updatePinButton(atts.url);\n    if (!dialog.isActive() && !util.isMobile() && $('#pdpMain .main-image').length < 2) {\n        $('#pdpMain .main-image.slick-current .primary-image').attr('href', atts.hires);\n    }\n}\n\nfunction updatePinButton (imageUrl) {\n    var pinButton = document.querySelector('.share-icon[data-share=pinterest]');\n    if (!pinButton) {\n        return;\n    }\n    var newUrl = imageUrl;\n    if (!imageUrl) {\n        newUrl = document.querySelector('#pdpMain .primary-image').getAttribute('src');\n    }\n    var href = url.parse(pinButton.href);\n    var query = qs.parse(href.query);\n    query.media = url.resolve(window.location.href, newUrl);\n    query.url = window.location.href;\n    var newHref = url.format(_.extend({}, href, {\n        query: query, // query is only used if search is absent\n        search: qs.stringify(query)\n    }));\n    pinButton.href = newHref;\n}\n\n/**\n * @description Replaces the images in the image container, for eg. when a different color was clicked.\n */\nfunction replaceImages () {\n    var $newImages = $('#update-images'),\n        $imageContainer = $('#pdpMain .product-primary-image-carousel');\n    if ($newImages.length === 0) { return; }\n\n    $imageContainer.html($newImages.html());\n    $newImages.remove();\n    loadZoom();\n    initProductSlider();\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    updatePinButton();\n    loadZoom();\n\n    initProductSlider();\n\n    $('#pdpMain').on('click', '.main-image', function() { \n        return false; \n    });\n};\nmodule.exports.loadZoom = loadZoom;\nmodule.exports.setMainImage = setMainImage;\nmodule.exports.replaceImages = replaceImages;\nmodule.exports.initProductSlider = initProductSlider;\nmodule.exports.initSliderHandler = initSliderHandler;\n","'use strict';\n\nvar dialog = require('../../dialog'),\n    productStoreInventory = require('../../storeinventory/product'),\n    tooltip = require('../../tooltip'),\n    util = require('../../util'),\n    addToCart = require('./addToCart'),\n    availability = require('./availability'),\n    image = require('./image'),\n    productNav = require('./productNav'),\n    productSet = require('./productSet'),\n    recommendations = require('./recommendations'),\n    variant = require('./variant'),\n    quantitySwitcher = require('../../components/quantitySwitcher'),\n    accordion = require('../../components/accordion'),\n    sizeChart = require('./sizeChart');\n\n/**\n * @description Initialize product detail page with reviews, recommendation and product navigation.\n */\nfunction initializeDom() {\n    productNav();\n    tooltip.init();\n}\n\n/**\n * @description Initialize event handlers on product detail page\n */\nfunction initializeEvents() {\n    var $pdpMain = $('#pdpMain');\n\n    addToCart();\n    availability();\n    variant();\n    image();\n    recommendations();\n    productSet();\n    quantitySwitcher();\n    accordion();\n    sizeChart();\n\n    if (SitePreferences.STORE_PICKUP) {\n        productStoreInventory.init();\n    }\n\n    // Add to Wishlist and Add to Gift Registry links behaviors\n    $pdpMain.on('click', '[data-action=\"wishlist\"], [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    $('.size-chart-link a').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href')\n        });\n    });\n    \n    // Sanitizes data entered by the user into the quantity field\n    $('.pdpForm input[name=\"Quantity\"]').keyup(function () {\n\t\tvar numbers = $(this).val();\n\t\t$(this).val(numbers.replace(/\\D+/, ''));\n\t\tif ($(this).val() == '' || $(this).val() == '0') {\n\t\t\t$(this).val(1);\n\t\t}\n\t});\n    \n    $( window ).load(function() {\n    \tsetTimeout(function(){\n\t\t    $('.product-listing.pdppage .slick').slick({\n\t\t        infinite: false,\n\t\t        slidesToShow: 3,\n\t\t        slidesToScroll: 1,\n\t\t        dots: false\n\t\t    });\n    \t}, 2000);\n    });\n}\n\nvar product = {\n    initializeEvents: initializeEvents,\n    init: function () {\n        initializeDom();\n        initializeEvents();\n    }\n};\n\nmodule.exports = product;\n","'use strict';\n\nvar ajax = require('../../ajax'),\n    util = require('../../util');\n\n/**\n * @description loads product's navigation\n **/\nmodule.exports = function () {\n    var $pidInput = $('.pdpForm input[name=\"pid\"]').last(),\n        $navContainer = $('#product-nav-container');\n    // if no hash exists, or no pid exists, or nav container does not exist, return\n    if (window.location.hash.length <= 1 || $pidInput.length === 0 || $navContainer.length === 0) {\n        return;\n    }\n\n    var pid = $pidInput.val(),\n        hash = encodeURIComponent(window.location.hash.substr(1)),       \n        url = util.appendParamToURL(Urls.productNav + '?' + hash, 'pid', pid);\n\n    ajax.load({\n        url: url,\n        target: $navContainer\n    });\n};\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';\nvar carouselConfig = require('../../configs/carousel');\n\n/**\n * Carousel initialization function\n * @param {Object} $carousel - jQuery object\n * @param {Object} config - carousel settings\n */\nfunction initCarousel($carousel, config) {\n    $carousel.each(function(ind, item) {\n        // var config = carouselConfig.einsteinRecommendationCarousel;\n        var numberOfSlides = $(item).children().length;\n        // numberOfSlides > config.slidesToShow && \n        if (!$(item).hasClass('slick-initialized')) {\n            $(item).slick(config).data('carousel', config);\n        }\n    });\n}\n\n/**\n * Init Product Recommendation Carousel\n */\nfunction initProductRecommendationCarousel() {\n    var $carousel = $('#carousel-recommendations .slick');\n    var config = carouselConfig.recommendationCarousel;\n    initCarousel($carousel, config)\n}\n\n/**\n * Init Einstein Recommendation Carousel\n */\nfunction initEinsteinRecommendationCarousel() {\n    var $carousel = $('.einstein-recommendation .slick');\n    var config = carouselConfig.einsteinRecommendationCarousel;\n    \n    $(document).on('einstein:loaded', function () {\n        $carousel = $('.einstein-recommendation .slick');\n        initCarousel($carousel, config);\n    });\n\n    if ($carousel.length) {\n        initCarousel($carousel, config);\n    }\n}\n\n/**\n * @description Creates product recommendation carousels\n **/\nmodule.exports = function () {\n    initProductRecommendationCarousel()\n    initEinsteinRecommendationCarousel();\n};\n","'use strict';\n\nvar dialog = require('../../dialog');\nvar util = require('../../util');\n\nvar maxHeight = function() {\n    var isMob = util.isMobile() || matchMedia('(max-width: 550px)').matches;\n    var height;\n    var windowHeight = $(window).height();\n    if (isMob) {\n        height = windowHeight * 0.7;\n    } else {\n        height = windowHeight * 0.9;\n    }\n    return height;\n}\n\nvar sizeChart = function () {\n    var $content = $('#size-chart-content');\n\n    $('body').on('click', '.js-size-chart-btn', function() {\n        dialog.open({\n            html: $content.html(),\n            options: {\n                dialogClass: \"size-chart-modal\",\n                maxHeight: maxHeight(),\n                open: function(event, ui) {\n                   \n                    $(event.target).scrollTop(0);\n                }\n            }\n        })\n    });\n}\n\nmodule.exports = sizeChart;\n","'use strict';\n\nvar ajax = require('../../ajax'),\n    image = require('./image'),\n    progress = require('../../progress'),\n    productStoreInventory = require('../../storeinventory/product'),\n    tooltip = require('../../tooltip'),\n    util = require('../../util'),\n    _ = require('lodash');\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    var $pdpForm = $('.pdpForm');\n    var qty = $pdpForm.find('input[name=\"Quantity\"]').first().val();\n    var params = {\n        Quantity: isNaN(qty) ? '1' : qty,\n        format: 'ajax',\n        productlistid: $pdpForm.find('input[name=\"productlistid\"]').first().val()\n    };\n\n    progress.show($('#pdpMain'));\n\n    ajax.load({\n        url: util.appendParamsToUrl(href, params),\n        target: $('#product-content'),\n        callback: function () {\n            if (SitePreferences.STORE_PICKUP) {\n                productStoreInventory.init();\n            }\n            image.replaceImages();\n            tooltip.init();\n        }\n    });\n};\n\nvar colorSwatchesHover = function ($this) {\n    var $pdpMain = $('#pdpMain'),\n        largeImg = $this.data('lgimg'),\n        $imgZoom = $pdpMain.find('.main-image.slick-current .zoom-img'),\n        $mainImage = $pdpMain.find('.slick-current .primary-image');\n\n    if (!largeImg) { return; }\n    // store the old data from main image for mouseleave handler\n    $this.data('lgimg', {\n        hires: $imgZoom.data('href'),\n        url: $mainImage.attr('src'),\n        alt: $mainImage.attr('alt'),\n        title: $mainImage.attr('title')\n    });\n    // set the main image\n    image.setMainImage(largeImg);\n};\n\n/**\n * @description update product tile 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 updatePTContent = function (productTile) {\n    var $ptForm = $(productTile);\n    var $addToCart = $(productTile).closest('.product-variations').parent();\n    var params = {\n        Quantity: '1',\n        format: 'ajaxJSON',\n        productlistid: $ptForm.find('input[name=\"productlistid\"]').first().val()\n    };\n\n    progress.show($('#search-result-items'));\n    ajax.getJson({\n        url: util.appendParamsToUrl(productTile.href, params),\n        callback: function (response) {\n            let context = response.context;\n            let selectedAttr = context.selectedAttrs ? JSON.parse(context.selectedAttrs) : '{}';\n            let keys = Object.entries(selectedAttr);\n            let attr = keys && keys.length > 0 ? context.attrs.filter((attr) => attr.attributeId === keys[0][0]) : null;\n            if (attr) {\n                let attrSelected = attr[0].values.filter((attr) => attr.isSelected);\n                let paramAttr = keys[0][0]+\"=\"+attrSelected[0].value;\n                let paramIndex = productTile.href.indexOf(paramAttr);\n                if(attrSelected && paramIndex != -1){\n                    // Selected value\n                    $ptForm.closest('.swatches').find('li').removeClass('selected');\n                    $ptForm.closest('li').first().addClass('selected');\n                    //Update pid attribute\n                    $addToCart.find('input[name=\"pid\"]').first().val(response.productID);\n                }\n            }\n            progress.hide();\n        }\n    });\n};\n\nmodule.exports = function () {\n    var $pdpMain = $('#pdpMain');\n    // hover on swatch - should update main image with swatch image\n    $pdpMain.on('mouseenter mouseleave', '.swatches.color .swatchanchor', function() {\n        var timer;\n        clearTimeout(timer);\n        timer = setTimeout(colorSwatchesHover($(this)), 100);\n    });\n\n    // click on swatch - should replace product content with new variant\n    $pdpMain.on('click', '.product-detail .swatchanchor', function (e) {\n        e.preventDefault();\n        if ($(this).parents('li').hasClass('unselectable')) { return; }\n        updateContent(this.href);\n    });\n\n    // change drop down variation attribute - should replace product content with new variant\n    $pdpMain.on('change', '.variation-select', function () {\n        if ($(this).val().length === 0) { return; }\n        updateContent($(this).val());\n    });\n    /*var $plpMain = $('#search-result-items');\n    // click on swatch - should replace product content with new variant\n    $plpMain.on('click', '.product-variations .swatchanchor', function (e) {\n        e.preventDefault();\n        if ($(this).parents('li').hasClass('unselectable')) { return; }\n        updatePTContent(this);\n        return false;\n    });*/\n\n    var quantityCtas = ['button.js-quantity-decrease-button', 'button.js-quantity-increase-button'];\n    $(quantityCtas).each(function(idx, attr) {\n        $pdpMain.on('click', attr, function() {\n            var $quantityInput = $(attr).siblings('.js-product-quantity-input');\n            var quantityInputVal = parseInt($quantityInput.val());\n            var modificatedQuantity;\n\n            if ($(attr).hasClass('js-quantity-decrease-button')) {\n                modificatedQuantity = quantityInputVal > 1 ? quantityInputVal - 1 : 1;\n            } else if ($(attr).hasClass('js-quantity-increase-button')) {\n                modificatedQuantity = quantityInputVal + 1;\n            }\n\n            return $quantityInput.val(modificatedQuantity);\n        });\n    });\n};\n","'use strict';\n\nvar addProductToCart = require('./product/addToCart'),\n    ajax = require('../ajax'),\n    login = require('../login'),\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    $('.item-list').on('click', '.item-edit-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\nexports.init = function () {\n    initializeEvents();\n    addProductToCart();\n    login.init();\n    util.setDeleteConfirmation('.item-list', String.format(Resources.CONFIRM_DELETE, Resources.TITLE_GIFTREGISTRY));\n};\n","'use strict';\n\nvar compareWidget = require('../compare-widget'),\n    productTile = require('../product-tile'),\n    progress = require('../progress'),\n    addToCart = require('./product/addToCart'),\n    variant = require('./product/variant'),\n    util = require('../util');\n\nfunction infiniteScroll() {\n    // getting the hidden div, which is the placeholder for the next page\n    var loadingPlaceHolder = $('.infinite-scroll-placeholder[data-loading-state=\"unloaded\"]');\n    // get url hidden in DOM\n    var gridUrl = loadingPlaceHolder.attr('data-grid-url');\n\n    if (loadingPlaceHolder.length === 1 && util.elementInViewport(loadingPlaceHolder.get(0), 250)) {\n        // switch state to 'loading'\n        // - switches state, so the above selector is only matching once\n        // - shows loading indicator\n        loadingPlaceHolder.attr('data-loading-state', 'loading');\n        loadingPlaceHolder.addClass('infinite-scroll-loading');\n\n\n        // named wrapper function, which can either be called, if cache is hit, or ajax repsonse is received\n        var fillEndlessScrollChunk = function (html) {\n            loadingPlaceHolder.removeClass('infinite-scroll-loading');\n            loadingPlaceHolder.attr('data-loading-state', 'loaded');\n            $('div.search-result-content').append(html);\n        };\n\n        // old condition for caching was `'sessionStorage' in window && sessionStorage[\"scroll-cache_\" + gridUrl]`\n        // it was removed to temporarily address RAP-2649\n\n        $.ajax({\n            type: 'GET',\n            dataType: 'html',\n            url: gridUrl,\n            success: function (response) {\n                // put response into cache\n                try {\n                    sessionStorage['scroll-cache_' + gridUrl] = response;\n                } catch (e) {\n                    // nothing to catch in case of out of memory of session storage\n                    // it will fall back to load via ajax\n                }\n                // update UI\n                fillEndlessScrollChunk(response);\n                productTile.init();\n            }\n        });\n    }\n}\n\nfunction filterMultiSelection() {\n\n    $('#secondary.hideContent').on('click', '.refinement-link, [id*=\"swatch-\"],[id*=\"simple-attr-\"]', function (e) {\n        //e.stopImmediatePropagation();\n        try {\n            let selectedItem = $(this);\n            let urlParam = selectedItem.data(\"param\");\n            if(!urlParam){\n                return true\n            }\n            let isSelected = selectedItem.closest('li').hasClass('selected');\n            \n            let urlFilters = $('#secondary').data('urlFilters');\n            let urlObj = new URL(urlParam);\n            let baseUrl = new URL(urlObj.href.replace(urlObj.search,''));            \n            let tmpURL  = new URL(urlFilters ? urlFilters : baseUrl);\n            \n            let isGroup = false;\n            let groupClass = '.ref-def-' + selectedItem.data('refinementid');\n            let refDefGroup = {\n                refinementid: selectedItem.data('refinementid'),\n                refinementvalue: selectedItem.data('refinementvalue'),\n                prefNo:selectedItem.data('loopstateindex') ?  Number(selectedItem.data('loopstateindex')) : 1,\n                selectedValues:[]\n            }\n            if (groupClass) {\n                isGroup = true;\n                $(groupClass).each(function() {\n                    let rdItem = $(this);\n                    console.log(rdItem);\n                    if (rdItem.closest('li').hasClass('selected')) {\n                        if(selectedItem.data('refinementid') !== rdItem.data('refinementvalue')){\n                            refDefGroup.selectedValues.push(rdItem.data('refinementvalue'));\n                        }\n                    }\n                });\n            }\n            \n            if (urlObj) {\n                if (isSelected) { // isSelected  then remove from searchParams\n                    // Filter params to delete\n                    urlObj.searchParams.forEach((valueRA, keyRA) => {\n                        let value = valueRA;\n                        let key = keyRA;\n                        if(refDefGroup.refinementid === value){\n                            if(keyRA.indexOf('prefn') != -1){\n                                key = 'prefn' + refDefGroup.prefNo;\n                            }\n                        }\n                        if(keyRA.indexOf('prefv') != -1){\n                            value = refDefGroup.refinementvalue;\n                            key = 'prefv' + refDefGroup.prefNo;\n                            if(refDefGroup.refinementid !== value && refDefGroup.selectedValues.includes(value)){\n                                refDefGroup.selectedValues= refDefGroup.selectedValues.filter(item => item !== value);\n                            }\n                            \n                            value = refDefGroup.selectedValues.join('|');\n                        }\n                        if(!baseUrl.searchParams.has(key,value) || !value){\n                            if(!value){\n                                tmpURL.searchParams.delete(key);    \n                            } else {\n                                tmpURL.searchParams.set(key,value);\n                            }\n                        }\n                    });\n                    // UX unselect\n                    selectedItem.closest('li').removeClass('selected');\n                    selectedItem.find('i').attr('class','fa fa-square-o fa-lg');\n                    \n                } else { // append to querystring\n                    urlObj.searchParams.forEach((valueRA, keyRA) => {\n                        let value = valueRA;\n                        let key = keyRA;\n                        if(refDefGroup.refinementid === value){\n                            if(keyRA.indexOf('prefn') != -1){\n                                key = 'prefn' + refDefGroup.prefNo;\n                            }\n                        }\n                        if(keyRA.indexOf('prefv') != -1){\n                            value = refDefGroup.refinementvalue;\n                            if(refDefGroup.refinementid !== value && !refDefGroup.selectedValues.includes(value)){\n                                key = 'prefv' + refDefGroup.prefNo;\n                                refDefGroup.selectedValues.push(value);\n                            }\n                            value = refDefGroup.selectedValues.join('|');\n                        }\n                        tmpURL.searchParams.set(key, value);\n                    });\n                    // UX select\n                    selectedItem.closest('li').addClass('selected');\n                    selectedItem.find('i').attr('class','fa fa-check-square-o fa-lg');\n                    \n                }\n                $('#secondary').data('urlFilters', tmpURL.href);\n            }\n        } catch (ferror) {\n            console.error('Debugging: ', ferror);\n        }\n        \n        return false;\n    });\n}\n\n\nfunction closeThickInit(){\n    var $main = $('#main');\n    //$('#secondary').append(\"<div id='closethick' class='applyfilters'></div>\");\n    $('.applyfilters').on('click',function () {\n        let urlFilters = $('#secondary').data('urlFilters');\n        if(urlFilters) {\n            let tmpURL  = new URL(urlFilters);\n            updateProductListing(tmpURL.href);\n        }\n        $(\"#secondary\").removeClass('hideContent');\n        //$(\".c-overlay\").hide();\n    });\n    // handle toggle refinement section\n    /*$main.on('keydown', function (event) {\n        if (event.key == \"Escape\") {\n            $(\"#secondary\").removeClass('hideContent');\n            $(\".c-overlay\").hide();\n        }\n    });*/\n}\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) {\n    if (!url || url === window.location.href) {\n        return;\n    }\n    progress.show($('.search-result-content'));\n    //util.scrollBrowser(0);// send to the bottom\n    $('#main').load(util.appendParamToURL(url, 'format', 'ajax'), function () {\n        compareWidget.init();\n        productTile.init();\n        progress.hide();\n        closeThickInit();\n        history.pushState(undefined, '', url);\n        var $tiles = $('.tiles-container .product-tile');\n        if ($tiles.length > 0) {\n            $tiles.syncHeight().each(function (idx) {\n                $(this).data('idx', idx);\n            });\n        }\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    var $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    $( window ).load(function() {\n    \tsetTimeout(function(){ \n\t\t    $('.product-listing.nohit .slick').slick({\n\t\t        infinite: false,\n\t\t        slidesToShow: 3,\n\t\t        slidesToScroll: 1,\n\t\t        dots: false\n\t\t    });\n    \t}, 2000);\n        var $tiles = $('.tiles-container .product-tile');\n        if ($tiles.length > 0) {\n            $tiles.syncHeight().each(function (idx) {\n                $(this).data('idx', idx);\n            });\n        }\n    });\n    \n\n    // handle toggle refinement blocks\n    $main.on('click', '.refinement h3', function () {\n        $(this).toggleClass('expanded')\n        .siblings('ul').toggle();\n    });\n\n    // handle events for updating grid\n    $main.on('click', '.refinements a, .pagination a, .breadcrumb-refinement-value a', function (e) {\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        updateProductListing(this.href);\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        updateProductListing($(this).find('option:selected').val());\n    })\n    .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    });\n    /** new enhancements */\n    // handle toggle refinement section\n    $main.on('click', '.filtersbtn', function () {\n        let $secondary =  $(\"#secondary\");\n        let $primary = $(\"#primary\");\n        let display = !$secondary.hasClass('hideContent');\n        if(display){\n            $secondary.addClass('hideContent');    \n            $primary.addClass('full-width');\n            $('.filtersbtn .filterbuttonhide').hide();\n            $('.filtersbtn .filterbutton').show();\n            filterMultiSelection();\n        } else {\n            $secondary.removeClass('hideContent');\n            $primary.removeClass('full-width'); \n            $('.filtersbtn .filterbuttonhide').show();\n            $('.filtersbtn .filterbutton').hide();\n        }\n        \n        console.log(\"display\",display);\n        \n    });\n\n    closeThickInit();\n    \n    // $(\".totalproductnumber\").detach().appendTo('#primary .slot-grid-header .html-slot-container');\n    \n    $main.on('click','.buttonloadmore', function() {\n        let loadPagesUrls = $(this).data(\"loadpages\");\n        if (loadPagesUrls && loadPagesUrls.length > 0) { // Check if loadPagesUrls is defined\n                updateProductListing(loadPagesUrls[0]);\n        } else {\n                $('.buttonloadmore').hide();\n                //TODO: Show message with no more results. \n        }\n    });\n    addToCart();\n    variant();\n}\n\nexports.init = function () {\n    compareWidget.init();\n    if (SitePreferences.LISTING_INFINITE_SCROLL) {\n        $(window).on('scroll', infiniteScroll);\n    }\n    productTile.init();\n    initializeEvents();\n};\n","'use strict';\nvar carouselConfig = require('../configs/carousel');\nvar util = require('../util');\n\nexports.init = function () {\n    $('#homepage-slider .slick').slick({\n        infinite: true,\n        slidesToShow: 1,\n        slidesToScroll: 1,\n        autoplay: true,\n        dots: true,\n        arrows: false\n    });\n\n    $('#vertical-carousel .slick').slick({\n        infinite: false,\n        slidesToShow: 1,\n        slidesToScroll: 1,\n        dots: true\n    });\n    \n    $( window ).load(function() {\n    \tsetTimeout(function(){ \n\t\t    $('.product-listing.homepage .slick').slick({\n\t\t        infinite: false,\n\t\t        slidesToShow: 3,\n\t\t        slidesToScroll: 1,\n\t\t        dots: false\n\t\t    });\n            var isMob = util.isMobile() || matchMedia('(max-width: 550px)').matches;\n            $('.carousel-hp .product-listing .slick').slick({\n\t\t        infinite: false,\n\t\t        slidesToShow: isMob ? 2 : 4,\n\t\t        slidesToScroll: 1,\n\t\t        dots: false\n\t\t    });\n    \t}, 2000);\n    });\n    \n    \n};\n","'use strict';\nvar dialog = require('../dialog');\n\nexports.init = function () {\n    $('.store-details-link').on('click', function (e) {\n        e.preventDefault();\n        dialog.open({\n            url: $(e.target).attr('href')\n        });\n    });\n};\n","'use strict';\n\nvar addProductToCart = require('./product/addToCart'),\n    page = require('../page'),\n    login = require('../login'),\n    util = require('../util');\n\nexports.init = function () {\n    addProductToCart();\n    $('#editAddress').on('change', function () {\n        page.redirect(util.appendParamToURL(Urls.wishlistAddress, 'AddressID', $(this).val()));\n    });\n\n    //add js logic to remove the , from the qty feild to pass regex expression on client side\n    $('.option-quantity-desired input').on('focusout', function () {\n        $(this).val($(this).val().replace(',', ''));\n    });\n\n    login.init();\n\n};\n","'use strict';\n\nvar imagesLoaded = require('imagesloaded'),\n    quickview = require('./quickview');\n\nfunction initQuickViewButtons() {\n    $('.tiles-container .product-image').on('mouseenter', function () {\n        var $qvButton = $(this).find('.js-quickviewbutton');\n        if ($qvButton.length === 0) {\n            $qvButton = $('<a class=\"quickview button small quickviewbutton js-quickviewbutton\"><i class=\"fa fa-arrows-alt\"></i> ' + Resources.QUICK_VIEW + '</a>');\n        }\n        var $link = $(this).find('.thumb-link');\n        $qvButton.attr({\n            'href': $link.attr('href'),\n            'title': $link.attr('title')\n        }).appendTo(this);\n    });\n\n    $('body').on('click', '.js-quickviewbutton', function (e) {\n        e.preventDefault();\n        quickview.show({\n            url: $(this).attr('href'),\n            source: 'quickview'\n        });\n    });\n}\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 Initializes events on the product-tile for the following elements:\n * - swatches\n * - thumbnails\n */\nfunction initializeEvents() {\n    initQuickViewButtons();\n    gridViewToggle();\n    $('.swatch-list').on('mouseleave', function () {\n        // Restore current thumb image\n        var $tile = $(this).closest('.product-tile'),\n            $thumb = $tile.find('.product-image .thumb-link img').eq(0),\n            data = $thumb.data('current');\n\n        $thumb.attr({\n            src: data.src,\n            alt: data.alt,\n            title: data.title\n        });\n    });\n    $('.swatch-list .swatch').on('click', function (e) {\n        e.preventDefault();\n        if ($(this).hasClass('selected')) { return; }\n\n        var $tile = $(this).closest('.product-tile');\n        $(this).closest('.swatch-list').find('.swatch.selected').removeClass('selected');\n        $(this).addClass('selected');\n        $tile.find('.thumb-link').attr('href', $(this).attr('href'));\n        $tile.find('name-link').attr('href', $(this).attr('href'));\n\n        var data = $(this).children('img').filter(':first').data('thumb');\n        var $thumb = $tile.find('.product-image .thumb-link img').eq(0);\n        var currentAttrs = {\n            src: data.src,\n            alt: data.alt,\n            title: data.title\n        };\n        $thumb.attr(currentAttrs);\n        $thumb.data('current', currentAttrs);\n    }).on('mouseenter', function () {\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('img').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        $thumb.attr({\n            src: data.src,\n            alt: data.alt,\n            title: data.title\n        });\n    });\n}\n\nexports.init = function () {\n    var $tiles = $('.tiles-container .product-tile');\n    if ($tiles.length === 0) { return; }\n    imagesLoaded('.tiles-container').on('done', function () {\n        $tiles.syncHeight()\n            .each(function (idx) {\n                $(this).data('idx', idx);\n            });\n    });\n    initializeEvents();\n};\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) {\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    return $loader.appendTo(target).show();\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 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        var $btnNext = $('.quickview-next'),\n            $btnPrev = $('.quickview-prev');\n\n        product.initializeEvents();\n\n        this.productLinkIndex = _(this.productLinks).findIndex(function (url) {\n            return removeParam(url) === removeParam(qvUrl);\n        });\n\n        // hide the buttons on the compare page or when there are no other products\n        if (this.productLinks.length <= 1 || $('.compareremovecell').length > 0) {\n            $btnNext.hide();\n            $btnPrev.hide();\n            return;\n        }\n\n        if (this.productLinkIndex === this.productLinks.length - 1) {\n            $btnNext.attr('disabled', 'disabled');\n        }\n        if (this.productLinkIndex === 0) {\n            $btnPrev.attr('disabled', 'disabled');\n        }\n\n        $btnNext.on('click', function (e) {\n            e.preventDefault();\n            this.navigateQuickview(1);\n        }.bind(this));\n        $btnPrev.on('click', function (e) {\n            e.preventDefault();\n            this.navigateQuickview(-1);\n        }.bind(this));\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: 920,\n                title: Resources.QUICK_VIEW_POPUP,\n                open: function () {\n                    this.setup(url);\n                    \n                    // Omniture quickview tracking\n\t            \t\tif (SitePreferences.OMNITURE_ENABLED && typeof _satellite != 'undefined') {\n\t            \t\t\t_satellite.track(\"productModalView\");\n\t            \t\t}\n\t            \t\t\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        $('.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 * @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 util = require('./util');\n\nvar currentQuery = null,\n    lastQuery = null,\n    runningQuery = null,\n    listTotal = -1,\n    listCurrent = -1,\n    delay = 30,\n    $resultsContainer;\n/**\n * @function\n * @description Handles keyboard's arrow keys\n * @param keyCode Code of an arrow key to be handled\n */\nfunction handleArrowKeys(keyCode) {\n    switch (keyCode) {\n        case 38:\n            // keyUp\n            listCurrent = (listCurrent <= 0) ? (listTotal - 1) : (listCurrent - 1);\n            break;\n        case 40:\n            // keyDown\n            listCurrent = (listCurrent >= listTotal - 1) ? 0 : listCurrent + 1;\n            break;\n        default:\n            // reset\n            listCurrent = -1;\n            return false;\n    }\n\n    $resultsContainer.children().removeClass('selected').eq(listCurrent).addClass('selected');\n    $('input[name=\"q\"]').val($resultsContainer.find('.selected .suggestionterm').first().text());\n    return true;\n}\n\nvar searchsuggest = {\n    /**\n     * @function\n     * @description Configures parameters and required object instances\n     */\n    init: function (container, defaultValue) {\n        var $searchContainer = $(container);\n        var $searchForm = $searchContainer.find('form[name=\"simpleSearch\"]');\n        var $searchField = $searchForm.find('input[name=\"q\"]');\n\n        // disable browser auto complete\n        $searchField.attr('autocomplete', 'off');\n\n        // on focus listener (clear default value)\n        $searchField.focus(function () {\n            if (!$resultsContainer) {\n                // create results container if needed\n                $resultsContainer = $('<div/>').attr('id', 'search-suggestions').appendTo($searchContainer);\n            }\n            if ($searchField.val() === defaultValue) {\n                $searchField.val('');\n            }\n        });\n\n        $(document).on('click', function (e) {\n            if (!$searchContainer.is(e.target)) {\n                setTimeout(this.clearResults, 200);\n            }\n        }.bind(this));\n        // on key up listener\n        $searchField.keyup(function (e) {\n\n            // get keyCode (window.event is for IE)\n            var keyCode = e.keyCode || window.event.keyCode;\n\n            // check and treat up and down arrows\n            if (handleArrowKeys(keyCode)) {\n                return;\n            }\n            // check for an ENTER or ESC\n            if (keyCode === 13 || keyCode === 27) {\n                this.clearResults();\n                return;\n            }\n\n            currentQuery = $searchField.val().trim();\n\n            // no query currently running, init an update\n            if (!runningQuery) {\n                runningQuery = currentQuery;\n                setTimeout(this.suggest.bind(this), delay);\n            }\n        }.bind(this));\n    },\n\n    /**\n     * @function\n     * @description trigger suggest action\n     */\n    suggest: function () {\n        // check whether query to execute (runningQuery) is still up to date and had not changed in the meanwhile\n        // (we had a little delay)\n        if (runningQuery !== currentQuery) {\n            // update running query to the most recent search phrase\n            runningQuery = currentQuery;\n        }\n\n        // if it's empty clear the results box and return\n        if (runningQuery.length === 0) {\n            this.clearResults();\n            runningQuery = null;\n            return;\n        }\n\n        // if the current search phrase is the same as for the last suggestion call, just return\n        if (lastQuery === runningQuery) {\n            runningQuery = null;\n            return;\n        }\n\n        // build the request url\n        var reqUrl = util.appendParamToURL(Urls.searchsuggest, 'q', runningQuery);\n\n        // execute server call\n        $.get(reqUrl, function (data) {\n            var suggestionHTML = data,\n                ansLength = suggestionHTML.trim().length;\n\n            // if there are results populate the results div\n            if (ansLength === 0) {\n                this.clearResults();\n            } else {\n                // update the results div\n                $resultsContainer.html(suggestionHTML).fadeIn(200);\n            }\n\n            // record the query that has been executed\n            lastQuery = runningQuery;\n            // reset currently running query\n            runningQuery = null;\n\n            // check for another required update (if current search phrase is different from just executed call)\n            if (currentQuery !== lastQuery) {\n                // ... and execute immediately if search has changed while this server call was in transit\n                runningQuery = currentQuery;\n                setTimeout(this.suggest.bind(this), delay);\n            }\n            this.hideLeftPanel();\n        }.bind(this));\n    },\n    /**\n     * @function\n     * @description\n     */\n    clearResults: function () {\n        if (!$resultsContainer) { return; }\n        $resultsContainer.fadeOut(200, function () {$resultsContainer.empty();});\n    },\n    /**\n     * @function\n     * @description\n     */\n    hideLeftPanel: function () {\n        //hide left panel if there is only a matching suggested custom phrase\n        if ($('.search-suggestion-left-panel-hit').length === 1 && $('.search-phrase-suggestion a').text().replace(/(^[\\s]+|[\\s]+$)/g, '').toUpperCase() === $('.search-suggestion-left-panel-hit a').text().toUpperCase()) {\n            $('.search-suggestion-left-panel').css('display', 'none');\n            $('.search-suggestion-wrapper-full').addClass('search-suggestion-wrapper');\n            $('.search-suggestion-wrapper').removeClass('search-suggestion-wrapper-full');\n        }\n    }\n};\n\nmodule.exports = searchsuggest;\n","'use strict';\n\nmodule.exports = {\n\tinit: function () {\n\t    $('#liveagent_button_online').on(\"click\", function(e){\n\t    \te.preventDefault();\n\t    \tliveagent.startChat(SitePreferences.SF_BUTTON_ID); //button id\n\t    });\n\n\t\tliveagent.init(SitePreferences.SF_INIT_CHAT_URL, SitePreferences.SF_DEPLOYMENT_ID, SitePreferences.SF_ORG_ID); //url, deployment, org\n\t\n\t\tif (!window._laq)\n\t\t{ window._laq = []; }\n\n\t\twindow._laq.push(function() {\n\t\t    liveagent.showWhenOnline(SitePreferences.SF_BUTTON_ID, document.getElementById('liveagent_button_online'));\n\t\t    liveagent.showWhenOffline(SitePreferences.SF_BUTTON_ID, document.getElementById('liveagent_button_offline'));\n\t\t});\n\t}\n}\n","'use strict';\n\nvar stickyComponent = require('./components/stickyComponent');\n\nfunction getPageMapping() {\n    var obj = SitePreferences.MAPPING_FOR_STICKY_COMP;\n    if (!obj.length) {\n        return {\n            home: '.pt_storefront',\n            plp: '.pt_product-search-result',\n            pdp: '.pt_product-details',\n            search: '.pt_product-search-noresult'\n        }\n    }\n    return JSON.parse(obj);\n}\n\nvar stickySearch = {\n    init: function () {\n        var pageString = SitePreferences.STICKY_SEARCH_BAR_LIST.toLowerCase();\n        if(!pageString.length) {\n            return;\n        }\n        var pageList = pageString.split(',');\n\n        var pageMapping = getPageMapping();\n\n        var isEnabled = pageList.some(item => pageMapping.hasOwnProperty(item.trim()) && $(pageMapping[item.trim()]).length);\n\n        if (isEnabled) {\n            stickyComponent.init({\n                selector: '.header-search',\n                trigger: '.top-banner'\n            });\n\n            if ($('body').find('.pt_product-details').length) {\n                $('#wrapper').addClass('m-pdp-with-sticky-search');\n            }\n        };\n    }\n}\n\nmodule.exports = stickySearch;\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        $.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\nconst { values } = require(\"lodash\");\n\nfunction getCurrentData(){\n\tif(sjdata.page == 'shipping') {\n\t\t$(document).trigger('data:checkout', [sjdata]);\n\t} else if(sjdata.page == 'orderconfirmation' || sjdata.page == 'confirmation') {\n\t\t$(document).trigger('data:purchase', [sjdata]);\n\t} else if(sjdata.page == 'product') {\n\t\t$(document).trigger('data:pdp', [sjdata]);\n\t} else if(sjdata.page == 'summary') {\n\t\t$(document).trigger('data:payment', [sjdata]);\n\t}\n\n}\n\nmodule.exports = {\n\tinit: function () {\n\t    $(document).on(\"data:addtocart\", function(e, data){\n\t\t\tttq.track('AddToCart', {\n\t\t\t\tcontent_type: data.content_type,\n\t\t\t\tquantity: data.qty,\n\t    \t\tcontent_name: data.content_name,\n\t\t\t\tcontent_id: data.content_ids,\n\t\t\t\tcurrency: 'USD',\n\t\t\t\tvalue: data.cartTotal\n\t\t\t});\n\t    });\n\n\t\t$(document).on(\"data:checkout\", function(e, data){\n\t    \tttq.track('InitiateCheckout', {\n\t    \t\tvalue: data.cartTotal,\n\t    \t\tcurrency: data.currency,\n\t    \t\tquantity : data.qty,\n\t    \t\tcontents : [data.pids]\n\t        });\n\t    });\n\n\t    $(document).on(\"data:purchase\", function(e, data){\n\t    \tttq.track('Purchase', {\n\t    \t\tcontents: [data.pids],\n\t    \t\tcurrency: data.currency,\n\t    \t\tvalue: data.cartTotal,\n\t\t\t\tquantity : data.qty\n\t        });\n\t    });\n\t\t\n\t    $(document).on(\"data:pdp\", function(e, data){\n\t    \tttq.track('ViewContent', {\n\t\t\t\tquantity : data.qty,\n\t\t\t\tcurrency: data.currency,\n\t\t\t\tvalue: data.value,\n\t\t\t\tcontents : data.pids,\n\t    \t\tcontent_type: data.content_type,\n\t    \t\tcontent_name: data.content_name\n\t        });\n\t    });\n\n\t    $(document).on(\"data:payment\", function(e, data){\n\t    \tttq.track('AddPaymentInfo',  {\n\t    \t\tcontents: [data.pids],\n\t    \t\tcurrency: data.currency,\n\t    \t\tvalue: data.cartTotal\n\t        });\n\t    });\n\n\t\tgetCurrentData();\n\t}\n};","'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 () {\n    $(document).tooltip({\n        items: '.tooltip',\n        track: true,\n        content: function () {\n            return $(this).find('.tooltip-content').html();\n        }\n    });\n\n    $('.share-link').on('click', function (e) {\n        e.preventDefault();\n        var target = $(this).data('target');\n        if (!target) {\n            return;\n        }\n        $(target).toggleClass('active');\n    });\n    \n    $(document).on('click','.tooltip:not(\".click-through\")',function(e) {\n        e.preventDefault();\n    });\n};\n","'use strict';\n\nvar _ = require('lodash');\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        return url + separator + name + '=' + encodeURIComponent(value);\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 = decodeURIComponent(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 === 'ID' || field === 'UUID' || field === 'key' || field === 'type') {\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            $form.find('[name$=\"' + field.replace('Code', '') + '\"]').val(address[field]).trigger('change');\n            // update the state fields\n            if (field === 'countryCode') {\n                $form.find('[name$=\"country\"]').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                $form.find('[name$=\"state\"]').val(address.stateCode).trigger('change');\n                $(\"[name$=_stateName]\").val($('[name$=\"state\"]').find(\"option:selected\").text());\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    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 Returns selected text in input or text area\n     */\n    getSelectionText: function () {\n        var text = \"\";\n        var activeEl = document.activeElement;\n        var activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;\n        if (\n          (activeElTagName == \"textarea\") || (activeElTagName == \"input\" &&\n          /^(?:text|search|password|tel|url)$/i.test(activeEl.type)) &&\n          (typeof activeEl.selectionStart == \"number\")\n        ) {\n            text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);\n        } else if (window.getSelection) {\n            text = window.getSelection().toString();\n        }\n        return text;\n    }\n};\n\nmodule.exports = util;\n","'use strict';\n\nvar naPhone = /^\\(?([2-9][0-8][0-9])\\)?[\\-\\. ]?([2-9][0-9]{2})[\\-\\. ]?([0-9]{4})(\\s*x[0-9]+)?$/;\nvar regex = {\n    phone: {\n        us: naPhone,\n        ca: naPhone,\n        fr: /^0[1-6]{1}(([0-9]{2}){4})|((\\s[0-9]{2}){4})|((-[0-9]{2}){4})$/,\n        it: /^(([0-9]{2,4})([-\\s\\/]{0,1})([0-9]{4,8}))?$/,\n        jp: /^(0\\d{1,4}- ?)?\\d{1,4}-\\d{4}$/,\n        cn: /.*/,\n        gb: /^((\\(?0\\d{4}\\)?\\s?\\d{3}\\s?\\d{3})|(\\(?0\\d{3}\\)?\\s?\\d{3}\\s?\\d{4})|(\\(?0\\d{2}\\)?\\s?\\d{4}\\s?\\d{4}))(\\s?\\#(\\d{4}|\\d{3}))?$/\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}$/,\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)$/\n    },\n    notCC: /^(?!(([0-9 -]){13,19})).*$/,\n    validPostal: /(^\\d{5}(-\\d{4})?$)|(^[abceghjklmnprstvxyABCEGHJKLMNPRSTVXY]{1}\\d{1}[A-Za-z]{1} *\\d{1}[A-Za-z]{1}\\d{1}$)/,\n    validateEmail: /^(([^<>()\\[\\]\\\\.,;:\\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    nospecialchars: /^[a-zA-Z0-9. ,~!&()-_@]+$/,\n    noemojichar: /(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\u0023-\\u0039]\\ufe0f?\\u20e3|\\u3299|\\u3297|\\u303d|\\u3030|\\u24c2|\\ud83c[\\udd70-\\udd71]|\\ud83c[\\udd7e-\\udd7f]|\\ud83c\\udd8e|\\ud83c[\\udd91-\\udd9a]|\\ud83c[\\udde6-\\uddff]|[\\ud83c[\\ude01-\\ude02]|\\ud83c\\ude1a|\\ud83c\\ude2f|[\\ud83c[\\ude32-\\ude3a]|[\\ud83c[\\ude50-\\ude51]|\\u203c|\\u2049|[\\u25aa-\\u25ab]|\\u25b6|\\u25c0|[\\u25fb-\\u25fe]|\\u00a9|\\u00ae|\\u2122|\\u2139|\\ud83c\\udc04|[\\u2600-\\u26FF]|\\u2b05|\\u2b06|\\u2b07|\\u2b1b|\\u2b1c|\\u2b50|\\u2b55|\\u231a|\\u231b|\\u2328|\\u23cf|[\\u23e9-\\u23f3]|[\\u23f8-\\u23fa]|\\ud83c\\udccf|\\u2934|\\u2935|[\\u2190-\\u21ff])/,\n    onlyAlpha: /^([a-zA-Z]|-|\\ )+$/\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};\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    if (country.length === 0 || country.val().length === 0 || !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\n\n$.validator.addMethod('pw-validation', function (value, el) {\n\tif (value.length >= 8 && value.length <= 255) {\n        return true;\n    }else{\n    \t\treturn false;\n    }\n}, Resources.VALIDATE_PW_MINMAX);\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\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}, ''); // '' should be replaced with error message if needed\n\n\nvar $emojichar = function (emochar) {  \n\tvar isEmoji = regex.noemojichar.test($.trim(emochar));   \n    var witherror = false;\n    if(isEmoji){\n    \twitherror = false;     \n    }else{\n    \twitherror = true;\n    }\n    \n    if($.trim(emochar) == '') {\n    \twitherror = true;\n    }\n    return witherror;\n};\n\n$.validator.addMethod('noemojichar', $emojichar, Resources.VALIDATE_EMOJI_CHAR); \n\nvar validateSpecialChars = function (value) { \n    var isValid = regex.nospecialchars.test($.trim(value));\n    if($.trim(value) == '') {\n    \treturn true\n    }\n   return isValid;\n};\n\n$.validator.addMethod('validateSpecialChars', validateSpecialChars, Resources.VALIDATE_SPECIAL_CHAR);\n\nvar validateValidPostal = function (value) {\n\tvar isValid = regex.validPostal.test($.trim(value));\n    if($.trim(value) == '') {\n    \treturn true\n    }\n    return isValid;\n}\n\n$.validator.addMethod('validatePostalCode', validateValidPostal, Resources.VALIDATE_POSTALCODE);\n\n\nvar validateEmail = function (value) { \n    var isValid = regex.validateEmail.test($.trim(value));\n    if($.trim(value) == '') {\n    \treturn true\n    }\n   return isValid;\n};\n\n$.validator.addMethod('validateEmail', validateEmail, Resources.VALIDATE_EMAIL);\n\nvar validateOnlyAlphabet = function (value) {\n\tvar isValid = regex.onlyAlpha.test($.trim(value));\n\tif ($.trim(value) == '') {\n\t\treturn true;\n\t}\n\t\n\treturn isValid;\n}\n\n$.validator.addMethod('validateOnlyAlphabet', validateOnlyAlphabet, Resources.VALIDATE_ONLYALPHA);\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","\"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 GetIntrinsic = require('get-intrinsic');\n\nvar callBind = require('./');\n\nvar $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));\n\nmodule.exports = function callBoundIntrinsic(name, allowMissing) {\n\tvar intrinsic = GetIntrinsic(name, !!allowMissing);\n\tif (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {\n\t\treturn callBind(intrinsic);\n\t}\n\treturn intrinsic;\n};\n","'use strict';\n\nvar bind = require('function-bind');\nvar GetIntrinsic = require('get-intrinsic');\n\nvar $apply = GetIntrinsic('%Function.prototype.apply%');\nvar $call = GetIntrinsic('%Function.prototype.call%');\nvar $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);\n\nvar $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);\nvar $defineProperty = GetIntrinsic('%Object.defineProperty%', true);\nvar $max = GetIntrinsic('%Math.max%');\n\nif ($defineProperty) {\n\ttry {\n\t\t$defineProperty({}, 'a', { value: 1 });\n\t} catch (e) {\n\t\t// IE 8 has a broken defineProperty\n\t\t$defineProperty = null;\n\t}\n}\n\nmodule.exports = function callBind(originalFunction) {\n\tvar func = $reflectApply(bind, $call, arguments);\n\tif ($gOPD && $defineProperty) {\n\t\tvar desc = $gOPD(func, 'length');\n\t\tif (desc.configurable) {\n\t\t\t// original length, plus the receiver, minus any additional arguments (after the receiver)\n\t\t\t$defineProperty(\n\t\t\t\tfunc,\n\t\t\t\t'length',\n\t\t\t\t{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }\n\t\t\t);\n\t\t}\n\t}\n\treturn func;\n};\n\nvar applyBind = function applyBind() {\n\treturn $reflectApply(bind, $apply, arguments);\n};\n\nif ($defineProperty) {\n\t$defineProperty(module.exports, 'apply', { value: applyBind });\n} else {\n\tmodule.exports.apply = applyBind;\n}\n","/**\n * EvEmitter v1.1.0\n * Lil' event emitter\n * MIT License\n */\n\n/* jshint unused: true, undef: true, strict: true */\n\n( function( global, factory ) {\n  // universal module definition\n  /* jshint strict: false */ /* globals define, module, window */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD - RequireJS\n    define( factory );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS - Browserify, Webpack\n    module.exports = factory();\n  } else {\n    // Browser globals\n    global.EvEmitter = factory();\n  }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\n\"use strict\";\n\nfunction EvEmitter() {}\n\nvar proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n  if ( !eventName || !listener ) {\n    return;\n  }\n  // set events hash\n  var events = this._events = this._events || {};\n  // set listeners array\n  var listeners = events[ eventName ] = events[ eventName ] || [];\n  // only add once\n  if ( listeners.indexOf( listener ) == -1 ) {\n    listeners.push( listener );\n  }\n\n  return this;\n};\n\nproto.once = function( eventName, listener ) {\n  if ( !eventName || !listener ) {\n    return;\n  }\n  // add event\n  this.on( eventName, listener );\n  // set once flag\n  // set onceEvents hash\n  var onceEvents = this._onceEvents = this._onceEvents || {};\n  // set onceListeners object\n  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n  // set flag\n  onceListeners[ listener ] = true;\n\n  return this;\n};\n\nproto.off = function( eventName, listener ) {\n  var listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) {\n    return;\n  }\n  var index = listeners.indexOf( listener );\n  if ( index != -1 ) {\n    listeners.splice( index, 1 );\n  }\n\n  return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n  var listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) {\n    return;\n  }\n  // copy over to avoid interference if .off() in listener\n  listeners = listeners.slice(0);\n  args = args || [];\n  // once stuff\n  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n  for ( var i=0; i < listeners.length; i++ ) {\n    var listener = listeners[i]\n    var isOnce = onceListeners && onceListeners[ listener ];\n    if ( isOnce ) {\n      // remove listener\n      // remove before trigger to prevent recursion\n      this.off( eventName, listener );\n      // unset once flag\n      delete onceListeners[ listener ];\n    }\n    // trigger listener\n    listener.apply( this, args );\n  }\n\n  return this;\n};\n\nproto.allOff = function() {\n  delete this._events;\n  delete this._onceEvents;\n};\n\nreturn EvEmitter;\n\n}));\n","'use strict';\n\n/* eslint no-invalid-this: 1 */\n\nvar ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';\nvar slice = Array.prototype.slice;\nvar toStr = Object.prototype.toString;\nvar funcType = '[object Function]';\n\nmodule.exports = function bind(that) {\n    var target = this;\n    if (typeof target !== 'function' || toStr.call(target) !== funcType) {\n        throw new TypeError(ERROR_MESSAGE + target);\n    }\n    var args = slice.call(arguments, 1);\n\n    var bound;\n    var binder = function () {\n        if (this instanceof bound) {\n            var result = target.apply(\n                this,\n                args.concat(slice.call(arguments))\n            );\n            if (Object(result) === result) {\n                return result;\n            }\n            return this;\n        } else {\n            return target.apply(\n                that,\n                args.concat(slice.call(arguments))\n            );\n        }\n    };\n\n    var boundLength = Math.max(0, target.length - args.length);\n    var boundArgs = [];\n    for (var i = 0; i < boundLength; i++) {\n        boundArgs.push('$' + i);\n    }\n\n    bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);\n\n    if (target.prototype) {\n        var Empty = function Empty() {};\n        Empty.prototype = target.prototype;\n        bound.prototype = new Empty();\n        Empty.prototype = null;\n    }\n\n    return bound;\n};\n","'use strict';\n\nvar implementation = require('./implementation');\n\nmodule.exports = Function.prototype.bind || implementation;\n","'use strict';\n\nvar undefined;\n\nvar $SyntaxError = SyntaxError;\nvar $Function = Function;\nvar $TypeError = TypeError;\n\n// eslint-disable-next-line consistent-return\nvar getEvalledConstructor = function (expressionSyntax) {\n\ttry {\n\t\treturn $Function('\"use strict\"; return (' + expressionSyntax + ').constructor;')();\n\t} catch (e) {}\n};\n\nvar $gOPD = Object.getOwnPropertyDescriptor;\nif ($gOPD) {\n\ttry {\n\t\t$gOPD({}, '');\n\t} catch (e) {\n\t\t$gOPD = null; // this is IE 8, which has a broken gOPD\n\t}\n}\n\nvar throwTypeError = function () {\n\tthrow new $TypeError();\n};\nvar ThrowTypeError = $gOPD\n\t? (function () {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties\n\t\t\targuments.callee; // IE 8 does not throw here\n\t\t\treturn throwTypeError;\n\t\t} catch (calleeThrows) {\n\t\t\ttry {\n\t\t\t\t// IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '')\n\t\t\t\treturn $gOPD(arguments, 'callee').get;\n\t\t\t} catch (gOPDthrows) {\n\t\t\t\treturn throwTypeError;\n\t\t\t}\n\t\t}\n\t}())\n\t: throwTypeError;\n\nvar hasSymbols = require('has-symbols')();\n\nvar getProto = Object.getPrototypeOf || function (x) { return x.__proto__; }; // eslint-disable-line no-proto\n\nvar needsEval = {};\n\nvar TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array);\n\nvar INTRINSICS = {\n\t'%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,\n\t'%Array%': Array,\n\t'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,\n\t'%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined,\n\t'%AsyncFromSyncIteratorPrototype%': undefined,\n\t'%AsyncFunction%': needsEval,\n\t'%AsyncGenerator%': needsEval,\n\t'%AsyncGeneratorFunction%': needsEval,\n\t'%AsyncIteratorPrototype%': needsEval,\n\t'%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,\n\t'%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,\n\t'%Boolean%': Boolean,\n\t'%DataView%': typeof DataView === 'undefined' ? undefined : DataView,\n\t'%Date%': Date,\n\t'%decodeURI%': decodeURI,\n\t'%decodeURIComponent%': decodeURIComponent,\n\t'%encodeURI%': encodeURI,\n\t'%encodeURIComponent%': encodeURIComponent,\n\t'%Error%': Error,\n\t'%eval%': eval, // eslint-disable-line no-eval\n\t'%EvalError%': EvalError,\n\t'%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array,\n\t'%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array,\n\t'%FinalizationRegistry%': typeof FinalizationRegistry === 'undefined' ? undefined : FinalizationRegistry,\n\t'%Function%': $Function,\n\t'%GeneratorFunction%': needsEval,\n\t'%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array,\n\t'%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array,\n\t'%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,\n\t'%isFinite%': isFinite,\n\t'%isNaN%': isNaN,\n\t'%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined,\n\t'%JSON%': typeof JSON === 'object' ? JSON : undefined,\n\t'%Map%': typeof Map === 'undefined' ? undefined : Map,\n\t'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()),\n\t'%Math%': Math,\n\t'%Number%': Number,\n\t'%Object%': Object,\n\t'%parseFloat%': parseFloat,\n\t'%parseInt%': parseInt,\n\t'%Promise%': typeof Promise === 'undefined' ? undefined : Promise,\n\t'%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy,\n\t'%RangeError%': RangeError,\n\t'%ReferenceError%': ReferenceError,\n\t'%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,\n\t'%RegExp%': RegExp,\n\t'%Set%': typeof Set === 'undefined' ? undefined : Set,\n\t'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()),\n\t'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,\n\t'%String%': String,\n\t'%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined,\n\t'%Symbol%': hasSymbols ? Symbol : undefined,\n\t'%SyntaxError%': $SyntaxError,\n\t'%ThrowTypeError%': ThrowTypeError,\n\t'%TypedArray%': TypedArray,\n\t'%TypeError%': $TypeError,\n\t'%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array,\n\t'%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray,\n\t'%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array,\n\t'%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array,\n\t'%URIError%': URIError,\n\t'%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap,\n\t'%WeakRef%': typeof WeakRef === 'undefined' ? undefined : WeakRef,\n\t'%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet\n};\n\nvar doEval = function doEval(name) {\n\tvar value;\n\tif (name === '%AsyncFunction%') {\n\t\tvalue = getEvalledConstructor('async function () {}');\n\t} else if (name === '%GeneratorFunction%') {\n\t\tvalue = getEvalledConstructor('function* () {}');\n\t} else if (name === '%AsyncGeneratorFunction%') {\n\t\tvalue = getEvalledConstructor('async function* () {}');\n\t} else if (name === '%AsyncGenerator%') {\n\t\tvar fn = doEval('%AsyncGeneratorFunction%');\n\t\tif (fn) {\n\t\t\tvalue = fn.prototype;\n\t\t}\n\t} else if (name === '%AsyncIteratorPrototype%') {\n\t\tvar gen = doEval('%AsyncGenerator%');\n\t\tif (gen) {\n\t\t\tvalue = getProto(gen.prototype);\n\t\t}\n\t}\n\n\tINTRINSICS[name] = value;\n\n\treturn value;\n};\n\nvar LEGACY_ALIASES = {\n\t'%ArrayBufferPrototype%': ['ArrayBuffer', 'prototype'],\n\t'%ArrayPrototype%': ['Array', 'prototype'],\n\t'%ArrayProto_entries%': ['Array', 'prototype', 'entries'],\n\t'%ArrayProto_forEach%': ['Array', 'prototype', 'forEach'],\n\t'%ArrayProto_keys%': ['Array', 'prototype', 'keys'],\n\t'%ArrayProto_values%': ['Array', 'prototype', 'values'],\n\t'%AsyncFunctionPrototype%': ['AsyncFunction', 'prototype'],\n\t'%AsyncGenerator%': ['AsyncGeneratorFunction', 'prototype'],\n\t'%AsyncGeneratorPrototype%': ['AsyncGeneratorFunction', 'prototype', 'prototype'],\n\t'%BooleanPrototype%': ['Boolean', 'prototype'],\n\t'%DataViewPrototype%': ['DataView', 'prototype'],\n\t'%DatePrototype%': ['Date', 'prototype'],\n\t'%ErrorPrototype%': ['Error', 'prototype'],\n\t'%EvalErrorPrototype%': ['EvalError', 'prototype'],\n\t'%Float32ArrayPrototype%': ['Float32Array', 'prototype'],\n\t'%Float64ArrayPrototype%': ['Float64Array', 'prototype'],\n\t'%FunctionPrototype%': ['Function', 'prototype'],\n\t'%Generator%': ['GeneratorFunction', 'prototype'],\n\t'%GeneratorPrototype%': ['GeneratorFunction', 'prototype', 'prototype'],\n\t'%Int8ArrayPrototype%': ['Int8Array', 'prototype'],\n\t'%Int16ArrayPrototype%': ['Int16Array', 'prototype'],\n\t'%Int32ArrayPrototype%': ['Int32Array', 'prototype'],\n\t'%JSONParse%': ['JSON', 'parse'],\n\t'%JSONStringify%': ['JSON', 'stringify'],\n\t'%MapPrototype%': ['Map', 'prototype'],\n\t'%NumberPrototype%': ['Number', 'prototype'],\n\t'%ObjectPrototype%': ['Object', 'prototype'],\n\t'%ObjProto_toString%': ['Object', 'prototype', 'toString'],\n\t'%ObjProto_valueOf%': ['Object', 'prototype', 'valueOf'],\n\t'%PromisePrototype%': ['Promise', 'prototype'],\n\t'%PromiseProto_then%': ['Promise', 'prototype', 'then'],\n\t'%Promise_all%': ['Promise', 'all'],\n\t'%Promise_reject%': ['Promise', 'reject'],\n\t'%Promise_resolve%': ['Promise', 'resolve'],\n\t'%RangeErrorPrototype%': ['RangeError', 'prototype'],\n\t'%ReferenceErrorPrototype%': ['ReferenceError', 'prototype'],\n\t'%RegExpPrototype%': ['RegExp', 'prototype'],\n\t'%SetPrototype%': ['Set', 'prototype'],\n\t'%SharedArrayBufferPrototype%': ['SharedArrayBuffer', 'prototype'],\n\t'%StringPrototype%': ['String', 'prototype'],\n\t'%SymbolPrototype%': ['Symbol', 'prototype'],\n\t'%SyntaxErrorPrototype%': ['SyntaxError', 'prototype'],\n\t'%TypedArrayPrototype%': ['TypedArray', 'prototype'],\n\t'%TypeErrorPrototype%': ['TypeError', 'prototype'],\n\t'%Uint8ArrayPrototype%': ['Uint8Array', 'prototype'],\n\t'%Uint8ClampedArrayPrototype%': ['Uint8ClampedArray', 'prototype'],\n\t'%Uint16ArrayPrototype%': ['Uint16Array', 'prototype'],\n\t'%Uint32ArrayPrototype%': ['Uint32Array', 'prototype'],\n\t'%URIErrorPrototype%': ['URIError', 'prototype'],\n\t'%WeakMapPrototype%': ['WeakMap', 'prototype'],\n\t'%WeakSetPrototype%': ['WeakSet', 'prototype']\n};\n\nvar bind = require('function-bind');\nvar hasOwn = require('has');\nvar $concat = bind.call(Function.call, Array.prototype.concat);\nvar $spliceApply = bind.call(Function.apply, Array.prototype.splice);\nvar $replace = bind.call(Function.call, String.prototype.replace);\nvar $strSlice = bind.call(Function.call, String.prototype.slice);\n\n/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */\nvar rePropName = /[^%.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|%$))/g;\nvar reEscapeChar = /\\\\(\\\\)?/g; /** Used to match backslashes in property paths. */\nvar stringToPath = function stringToPath(string) {\n\tvar first = $strSlice(string, 0, 1);\n\tvar last = $strSlice(string, -1);\n\tif (first === '%' && last !== '%') {\n\t\tthrow new $SyntaxError('invalid intrinsic syntax, expected closing `%`');\n\t} else if (last === '%' && first !== '%') {\n\t\tthrow new $SyntaxError('invalid intrinsic syntax, expected opening `%`');\n\t}\n\tvar result = [];\n\t$replace(string, rePropName, function (match, number, quote, subString) {\n\t\tresult[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : number || match;\n\t});\n\treturn result;\n};\n/* end adaptation */\n\nvar getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {\n\tvar intrinsicName = name;\n\tvar alias;\n\tif (hasOwn(LEGACY_ALIASES, intrinsicName)) {\n\t\talias = LEGACY_ALIASES[intrinsicName];\n\t\tintrinsicName = '%' + alias[0] + '%';\n\t}\n\n\tif (hasOwn(INTRINSICS, intrinsicName)) {\n\t\tvar value = INTRINSICS[intrinsicName];\n\t\tif (value === needsEval) {\n\t\t\tvalue = doEval(intrinsicName);\n\t\t}\n\t\tif (typeof value === 'undefined' && !allowMissing) {\n\t\t\tthrow new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!');\n\t\t}\n\n\t\treturn {\n\t\t\talias: alias,\n\t\t\tname: intrinsicName,\n\t\t\tvalue: value\n\t\t};\n\t}\n\n\tthrow new $SyntaxError('intrinsic ' + name + ' does not exist!');\n};\n\nmodule.exports = function GetIntrinsic(name, allowMissing) {\n\tif (typeof name !== 'string' || name.length === 0) {\n\t\tthrow new $TypeError('intrinsic name must be a non-empty string');\n\t}\n\tif (arguments.length > 1 && typeof allowMissing !== 'boolean') {\n\t\tthrow new $TypeError('\"allowMissing\" argument must be a boolean');\n\t}\n\n\tvar parts = stringToPath(name);\n\tvar intrinsicBaseName = parts.length > 0 ? parts[0] : '';\n\n\tvar intrinsic = getBaseIntrinsic('%' + intrinsicBaseName + '%', allowMissing);\n\tvar intrinsicRealName = intrinsic.name;\n\tvar value = intrinsic.value;\n\tvar skipFurtherCaching = false;\n\n\tvar alias = intrinsic.alias;\n\tif (alias) {\n\t\tintrinsicBaseName = alias[0];\n\t\t$spliceApply(parts, $concat([0, 1], alias));\n\t}\n\n\tfor (var i = 1, isOwn = true; i < parts.length; i += 1) {\n\t\tvar part = parts[i];\n\t\tvar first = $strSlice(part, 0, 1);\n\t\tvar last = $strSlice(part, -1);\n\t\tif (\n\t\t\t(\n\t\t\t\t(first === '\"' || first === \"'\" || first === '`')\n\t\t\t\t|| (last === '\"' || last === \"'\" || last === '`')\n\t\t\t)\n\t\t\t&& first !== last\n\t\t) {\n\t\t\tthrow new $SyntaxError('property names with quotes must have matching quotes');\n\t\t}\n\t\tif (part === 'constructor' || !isOwn) {\n\t\t\tskipFurtherCaching = true;\n\t\t}\n\n\t\tintrinsicBaseName += '.' + part;\n\t\tintrinsicRealName = '%' + intrinsicBaseName + '%';\n\n\t\tif (hasOwn(INTRINSICS, intrinsicRealName)) {\n\t\t\tvalue = INTRINSICS[intrinsicRealName];\n\t\t} else if (value != null) {\n\t\t\tif (!(part in value)) {\n\t\t\t\tif (!allowMissing) {\n\t\t\t\t\tthrow new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.');\n\t\t\t\t}\n\t\t\t\treturn void undefined;\n\t\t\t}\n\t\t\tif ($gOPD && (i + 1) >= parts.length) {\n\t\t\t\tvar desc = $gOPD(value, part);\n\t\t\t\tisOwn = !!desc;\n\n\t\t\t\t// By convention, when a data property is converted to an accessor\n\t\t\t\t// property to emulate a data property that does not suffer from\n\t\t\t\t// the override mistake, that accessor's getter is marked with\n\t\t\t\t// an `originalValue` property. Here, when we detect this, we\n\t\t\t\t// uphold the illusion by pretending to see that original data\n\t\t\t\t// property, i.e., returning the value rather than the getter\n\t\t\t\t// itself.\n\t\t\t\tif (isOwn && 'get' in desc && !('originalValue' in desc.get)) {\n\t\t\t\t\tvalue = desc.get;\n\t\t\t\t} else {\n\t\t\t\t\tvalue = value[part];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tisOwn = hasOwn(value, part);\n\t\t\t\tvalue = value[part];\n\t\t\t}\n\n\t\t\tif (isOwn && !skipFurtherCaching) {\n\t\t\t\tINTRINSICS[intrinsicRealName] = value;\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n","'use strict';\n\nvar origSymbol = typeof Symbol !== 'undefined' && Symbol;\nvar hasSymbolSham = require('./shams');\n\nmodule.exports = function hasNativeSymbols() {\n\tif (typeof origSymbol !== 'function') { return false; }\n\tif (typeof Symbol !== 'function') { return false; }\n\tif (typeof origSymbol('foo') !== 'symbol') { return false; }\n\tif (typeof Symbol('bar') !== 'symbol') { return false; }\n\n\treturn hasSymbolSham();\n};\n","'use strict';\n\n/* eslint complexity: [2, 18], max-statements: [2, 33] */\nmodule.exports = function hasSymbols() {\n\tif (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }\n\tif (typeof Symbol.iterator === 'symbol') { return true; }\n\n\tvar obj = {};\n\tvar sym = Symbol('test');\n\tvar symObj = Object(sym);\n\tif (typeof sym === 'string') { return false; }\n\n\tif (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; }\n\tif (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; }\n\n\t// temp disabled per https://github.com/ljharb/object.assign/issues/17\n\t// if (sym instanceof Symbol) { return false; }\n\t// temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4\n\t// if (!(symObj instanceof Symbol)) { return false; }\n\n\t// if (typeof Symbol.prototype.toString !== 'function') { return false; }\n\t// if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }\n\n\tvar symVal = 42;\n\tobj[sym] = symVal;\n\tfor (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop\n\tif (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }\n\n\tif (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }\n\n\tvar syms = Object.getOwnPropertySymbols(obj);\n\tif (syms.length !== 1 || syms[0] !== sym) { return false; }\n\n\tif (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }\n\n\tif (typeof Object.getOwnPropertyDescriptor === 'function') {\n\t\tvar descriptor = Object.getOwnPropertyDescriptor(obj, sym);\n\t\tif (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }\n\t}\n\n\treturn true;\n};\n","'use strict';\n\nvar bind = require('function-bind');\n\nmodule.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);\n","/*!\n * imagesLoaded v4.1.4\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      'ev-emitter/ev-emitter'\n    ], function( EvEmitter ) {\n      return factory( window, EvEmitter );\n    });\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory(\n      window,\n      require('ev-emitter')\n    );\n  } else {\n    // browser global\n    window.imagesLoaded = factory(\n      window,\n      window.EvEmitter\n    );\n  }\n\n})( typeof window !== 'undefined' ? window : this,\n\n// --------------------------  factory -------------------------- //\n\nfunction factory( window, EvEmitter ) {\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 arraySlice = Array.prototype.slice;\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n  if ( Array.isArray( obj ) ) {\n    // use object if already an array\n    return obj;\n  }\n\n  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n  if ( isArrayLike ) {\n    // convert nodeList to array\n    return arraySlice.call( obj );\n  }\n\n  // array of single index\n  return [ obj ];\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 */\nfunction 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  var queryElem = elem;\n  if ( typeof elem == 'string' ) {\n    queryElem = document.querySelectorAll( elem );\n  }\n  // bail if bad element\n  if ( !queryElem ) {\n    console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) );\n    return;\n  }\n\n  this.elements = makeArray( queryElem );\n  this.options = extend( {}, this.options );\n  // shift arguments if no options set\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  setTimeout( this.check.bind( this ) );\n}\n\nImagesLoaded.prototype = Object.create( EvEmitter.prototype );\n\nImagesLoaded.prototype.options = {};\n\nImagesLoaded.prototype.getImages = function() {\n  this.images = [];\n\n  // filter & find items if we have an item selector\n  this.elements.forEach( this.addElementImages, this );\n};\n\n/**\n * @param {Node} element\n */\nImagesLoaded.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\nvar elementNodeTypes = {\n  1: true,\n  9: true,\n  11: true\n};\n\nImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n  var style = getComputedStyle( elem );\n  if ( !style ) {\n    // Firefox returns null if in a hidden iframe https://bugzil.la/548397\n    return;\n  }\n  // get url inside url(\"...\")\n  var reURL = /url\\((['\"])?(.*?)\\1\\)/gi;\n  var matches = reURL.exec( style.backgroundImage );\n  while ( matches !== null ) {\n    var url = matches && matches[2];\n    if ( url ) {\n      this.addBackground( url, elem );\n    }\n    matches = reURL.exec( style.backgroundImage );\n  }\n};\n\n/**\n * @param {Image} img\n */\nImagesLoaded.prototype.addImage = function( img ) {\n  var loadingImage = new LoadingImage( img );\n  this.images.push( loadingImage );\n};\n\nImagesLoaded.prototype.addBackground = function( url, elem ) {\n  var background = new Background( url, elem );\n  this.images.push( background );\n};\n\nImagesLoaded.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  this.images.forEach( function( loadingImage ) {\n    loadingImage.once( 'progress', onProgress );\n    loadingImage.check();\n  });\n};\n\nImagesLoaded.prototype.progress = function( image, elem, message ) {\n  this.progressedCount++;\n  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;\n  // progress event\n  this.emitEvent( '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\nImagesLoaded.prototype.complete = function() {\n  var eventName = this.hasAnyBroken ? 'fail' : 'done';\n  this.isComplete = true;\n  this.emitEvent( eventName, [ this ] );\n  this.emitEvent( 'always', [ this ] );\n  if ( this.jqDeferred ) {\n    var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';\n    this.jqDeferred[ jqMethod ]( this );\n  }\n};\n\n// --------------------------  -------------------------- //\n\nfunction LoadingImage( img ) {\n  this.img = img;\n}\n\nLoadingImage.prototype = Object.create( EvEmitter.prototype );\n\nLoadingImage.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  this.proxyImage.addEventListener( 'load', this );\n  this.proxyImage.addEventListener( 'error', this );\n  // bind to image as well for Firefox. #191\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( 'error', this );\n  this.proxyImage.src = this.img.src;\n};\n\nLoadingImage.prototype.getIsImageComplete = function() {\n  // check for non-zero, non-undefined naturalWidth\n  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671\n  return this.img.complete && this.img.naturalWidth;\n};\n\nLoadingImage.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  this.emitEvent( 'progress', [ this, this.img, message ] );\n};\n\n// ----- events ----- //\n\n// trigger specified handler for event type\nLoadingImage.prototype.handleEvent = function( event ) {\n  var method = 'on' + event.type;\n  if ( this[ method ] ) {\n    this[ method ]( event );\n  }\n};\n\nLoadingImage.prototype.onload = function() {\n  this.confirm( true, 'onload' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.onerror = function() {\n  this.confirm( false, 'onerror' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.unbindEvents = function() {\n  this.proxyImage.removeEventListener( 'load', this );\n  this.proxyImage.removeEventListener( 'error', this );\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\n// -------------------------- Background -------------------------- //\n\nfunction Background( url, element ) {\n  this.url = url;\n  this.element = element;\n  this.img = new Image();\n}\n\n// inherit LoadingImage prototype\nBackground.prototype = Object.create( LoadingImage.prototype );\n\nBackground.prototype.check = function() {\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( '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\nBackground.prototype.unbindEvents = function() {\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\nBackground.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  this.emitEvent( 'progress', [ this, this.element, message ] );\n};\n\n// -------------------------- jQuery -------------------------- //\n\nImagesLoaded.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\nImagesLoaded.makeJQueryPlugin();\n\n// --------------------------  -------------------------- //\n\nreturn ImagesLoaded;\n\n});\n","/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\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 = '4.17.21';\n\n  /** Used as the size to enable large array optimizations. */\n  var LARGE_ARRAY_SIZE = 200;\n\n  /** Error message constants. */\n  var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',\n      FUNC_ERROR_TEXT = 'Expected a function',\n      INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';\n\n  /** Used to stand-in for `undefined` hash values. */\n  var HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n  /** Used as the maximum memoize cache size. */\n  var MAX_MEMOIZE_SIZE = 500;\n\n  /** Used as the internal argument placeholder. */\n  var PLACEHOLDER = '__lodash_placeholder__';\n\n  /** Used to compose bitmasks for cloning. */\n  var CLONE_DEEP_FLAG = 1,\n      CLONE_FLAT_FLAG = 2,\n      CLONE_SYMBOLS_FLAG = 4;\n\n  /** Used to compose bitmasks for value comparisons. */\n  var COMPARE_PARTIAL_FLAG = 1,\n      COMPARE_UNORDERED_FLAG = 2;\n\n  /** Used to compose bitmasks for function metadata. */\n  var WRAP_BIND_FLAG = 1,\n      WRAP_BIND_KEY_FLAG = 2,\n      WRAP_CURRY_BOUND_FLAG = 4,\n      WRAP_CURRY_FLAG = 8,\n      WRAP_CURRY_RIGHT_FLAG = 16,\n      WRAP_PARTIAL_FLAG = 32,\n      WRAP_PARTIAL_RIGHT_FLAG = 64,\n      WRAP_ARY_FLAG = 128,\n      WRAP_REARG_FLAG = 256,\n      WRAP_FLIP_FLAG = 512;\n\n  /** Used as default options for `_.truncate`. */\n  var DEFAULT_TRUNC_LENGTH = 30,\n      DEFAULT_TRUNC_OMISSION = '...';\n\n  /** Used to detect hot functions by number of calls within a span of milliseconds. */\n  var HOT_COUNT = 800,\n      HOT_SPAN = 16;\n\n  /** Used to indicate the type of lazy iteratees. */\n  var LAZY_FILTER_FLAG = 1,\n      LAZY_MAP_FLAG = 2,\n      LAZY_WHILE_FLAG = 3;\n\n  /** Used as references for various `Number` constants. */\n  var INFINITY = 1 / 0,\n      MAX_SAFE_INTEGER = 9007199254740991,\n      MAX_INTEGER = 1.7976931348623157e+308,\n      NAN = 0 / 0;\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  /** Used to associate wrap methods with their bit flags. */\n  var wrapFlags = [\n    ['ary', WRAP_ARY_FLAG],\n    ['bind', WRAP_BIND_FLAG],\n    ['bindKey', WRAP_BIND_KEY_FLAG],\n    ['curry', WRAP_CURRY_FLAG],\n    ['curryRight', WRAP_CURRY_RIGHT_FLAG],\n    ['flip', WRAP_FLIP_FLAG],\n    ['partial', WRAP_PARTIAL_FLAG],\n    ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],\n    ['rearg', WRAP_REARG_FLAG]\n  ];\n\n  /** `Object#toString` result references. */\n  var argsTag = '[object Arguments]',\n      arrayTag = '[object Array]',\n      asyncTag = '[object AsyncFunction]',\n      boolTag = '[object Boolean]',\n      dateTag = '[object Date]',\n      domExcTag = '[object DOMException]',\n      errorTag = '[object Error]',\n      funcTag = '[object Function]',\n      genTag = '[object GeneratorFunction]',\n      mapTag = '[object Map]',\n      numberTag = '[object Number]',\n      nullTag = '[object Null]',\n      objectTag = '[object Object]',\n      promiseTag = '[object Promise]',\n      proxyTag = '[object Proxy]',\n      regexpTag = '[object RegExp]',\n      setTag = '[object Set]',\n      stringTag = '[object String]',\n      symbolTag = '[object Symbol]',\n      undefinedTag = '[object Undefined]',\n      weakMapTag = '[object WeakMap]',\n      weakSetTag = '[object WeakSet]';\n\n  var arrayBufferTag = '[object ArrayBuffer]',\n      dataViewTag = '[object DataView]',\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);/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)[^\\\\]|\\\\.)*?\\1)\\]/,\n      reIsPlainProp = /^\\w*$/,\n      rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n  /**\n   * Used to match `RegExp`\n   * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n   */\n  var reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g,\n      reHasRegExpChar = RegExp(reRegExpChar.source);\n\n  /** Used to match leading whitespace. */\n  var reTrimStart = /^\\s+/;\n\n  /** Used to match a single whitespace character. */\n  var reWhitespace = /\\s/;\n\n  /** Used to match wrap detail comments. */\n  var reWrapComment = /\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,\n      reWrapDetails = /\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,\n      reSplitDetails = /,? & /;\n\n  /** Used to match words composed of alphanumeric characters. */\n  var reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n  /**\n   * Used to validate the `validate` option in `_.template` variable.\n   *\n   * Forbids characters which could potentially change the meaning of the function argument definition:\n   * - \"(),\" (modification of function parameters)\n   * - \"=\" (default value)\n   * - \"[]{}\" (destructuring of function parameters)\n   * - \"/\" (beginning of a comment)\n   * - whitespace\n   */\n  var reForbiddenIdentifierChars = /[()=,{}\\[\\]\\/\\s]/;\n\n  /** Used to match backslashes in property paths. */\n  var reEscapeChar = /\\\\(\\\\)?/g;\n\n  /**\n   * Used to match\n   * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).\n   */\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 bad signed hexadecimal string values. */\n  var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n  /** Used to detect binary string values. */\n  var reIsBinary = /^0b[01]+$/i;\n\n  /** Used to detect host constructors (Safari). */\n  var reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n  /** Used to detect octal string values. */\n  var reIsOctal = /^0o[0-7]+$/i;\n\n  /** Used to detect unsigned integer values. */\n  var reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n  /** Used to match Latin Unicode letters (excluding mathematical operators). */\n  var reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/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 compose unicode character classes. */\n  var rsAstralRange = '\\\\ud800-\\\\udfff',\n      rsComboMarksRange = '\\\\u0300-\\\\u036f',\n      reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n      rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n      rsDingbatRange = '\\\\u2700-\\\\u27bf',\n      rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n      rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n      rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n      rsPunctuationRange = '\\\\u2000-\\\\u206f',\n      rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n      rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n      rsVarRange = '\\\\ufe0e\\\\ufe0f',\n      rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n  /** Used to compose unicode capture groups. */\n  var rsApos = \"['\\u2019]\",\n      rsAstral = '[' + rsAstralRange + ']',\n      rsBreak = '[' + rsBreakRange + ']',\n      rsCombo = '[' + rsComboRange + ']',\n      rsDigits = '\\\\d+',\n      rsDingbat = '[' + rsDingbatRange + ']',\n      rsLower = '[' + rsLowerRange + ']',\n      rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n      rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n      rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n      rsNonAstral = '[^' + rsAstralRange + ']',\n      rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n      rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n      rsUpper = '[' + rsUpperRange + ']',\n      rsZWJ = '\\\\u200d';\n\n  /** Used to compose unicode regexes. */\n  var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n      rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n      rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n      rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n      reOptMod = rsModifier + '?',\n      rsOptVar = '[' + rsVarRange + ']?',\n      rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n      rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])',\n      rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])',\n      rsSeq = rsOptVar + reOptMod + rsOptJoin,\n      rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,\n      rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n  /** Used to match apostrophes. */\n  var reApos = RegExp(rsApos, 'g');\n\n  /**\n   * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n   * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n   */\n  var reComboMark = RegExp(rsCombo, 'g');\n\n  /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\n  var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n  /** Used to match complex or compound words. */\n  var reUnicodeWord = RegExp([\n    rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n    rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n    rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n    rsUpper + '+' + rsOptContrUpper,\n    rsOrdUpper,\n    rsOrdLower,\n    rsDigits,\n    rsEmoji\n  ].join('|'), 'g');\n\n  /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\n  var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');\n\n  /** Used to detect strings that need a more robust regexp to match words. */\n  var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n  /** Used to assign default `context` object properties. */\n  var contextProps = [\n    'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',\n    'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',\n    'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',\n    'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',\n    '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'\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[dataViewTag] = typedArrayTags[dateTag] =\n  typedArrayTags[errorTag] = typedArrayTags[funcTag] =\n  typedArrayTags[mapTag] = typedArrayTags[numberTag] =\n  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =\n  typedArrayTags[setTag] = typedArrayTags[stringTag] =\n  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[dataViewTag] =\n  cloneableTags[boolTag] = cloneableTags[dateTag] =\n  cloneableTags[float32Tag] = cloneableTags[float64Tag] =\n  cloneableTags[int8Tag] = cloneableTags[int16Tag] =\n  cloneableTags[int32Tag] = cloneableTags[mapTag] =\n  cloneableTags[numberTag] = cloneableTags[objectTag] =\n  cloneableTags[regexpTag] = cloneableTags[setTag] =\n  cloneableTags[stringTag] = cloneableTags[symbolTag] =\n  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\n  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\n  cloneableTags[errorTag] = cloneableTags[funcTag] =\n  cloneableTags[weakMapTag] = false;\n\n  /** Used to map Latin Unicode letters to basic Latin letters. */\n  var deburredLetters = {\n    // Latin-1 Supplement block.\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    // Latin Extended-A block.\n    '\\u0100': 'A',  '\\u0102': 'A', '\\u0104': 'A',\n    '\\u0101': 'a',  '\\u0103': 'a', '\\u0105': 'a',\n    '\\u0106': 'C',  '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n    '\\u0107': 'c',  '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n    '\\u010e': 'D',  '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n    '\\u0112': 'E',  '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n    '\\u0113': 'e',  '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n    '\\u011c': 'G',  '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n    '\\u011d': 'g',  '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n    '\\u0124': 'H',  '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n    '\\u0128': 'I',  '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n    '\\u0129': 'i',  '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n    '\\u0134': 'J',  '\\u0135': 'j',\n    '\\u0136': 'K',  '\\u0137': 'k', '\\u0138': 'k',\n    '\\u0139': 'L',  '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n    '\\u013a': 'l',  '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n    '\\u0143': 'N',  '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n    '\\u0144': 'n',  '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n    '\\u014c': 'O',  '\\u014e': 'O', '\\u0150': 'O',\n    '\\u014d': 'o',  '\\u014f': 'o', '\\u0151': 'o',\n    '\\u0154': 'R',  '\\u0156': 'R', '\\u0158': 'R',\n    '\\u0155': 'r',  '\\u0157': 'r', '\\u0159': 'r',\n    '\\u015a': 'S',  '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n    '\\u015b': 's',  '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n    '\\u0162': 'T',  '\\u0164': 'T', '\\u0166': 'T',\n    '\\u0163': 't',  '\\u0165': 't', '\\u0167': 't',\n    '\\u0168': 'U',  '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n    '\\u0169': 'u',  '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n    '\\u0174': 'W',  '\\u0175': 'w',\n    '\\u0176': 'Y',  '\\u0177': 'y', '\\u0178': 'Y',\n    '\\u0179': 'Z',  '\\u017b': 'Z', '\\u017d': 'Z',\n    '\\u017a': 'z',  '\\u017c': 'z', '\\u017e': 'z',\n    '\\u0132': 'IJ', '\\u0133': 'ij',\n    '\\u0152': 'Oe', '\\u0153': 'oe',\n    '\\u0149': \"'n\", '\\u017f': 's'\n  };\n\n  /** Used to map characters to HTML entities. */\n  var htmlEscapes = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#39;'\n  };\n\n  /** Used to map HTML entities to characters. */\n  var htmlUnescapes = {\n    '&amp;': '&',\n    '&lt;': '<',\n    '&gt;': '>',\n    '&quot;': '\"',\n    '&#39;': \"'\"\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  /** Built-in method references without a dependency on `root`. */\n  var freeParseFloat = parseFloat,\n      freeParseInt = parseInt;\n\n  /** Detect free variable `global` from Node.js. */\n  var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n  /** Detect free variable `self`. */\n  var freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n  /** Used as a reference to the global object. */\n  var root = freeGlobal || freeSelf || Function('return this')();\n\n  /** Detect free variable `exports`. */\n  var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n  /** Detect free variable `module`. */\n  var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n  /** Detect the popular CommonJS extension `module.exports`. */\n  var moduleExports = freeModule && freeModule.exports === freeExports;\n\n  /** Detect free variable `process` from Node.js. */\n  var freeProcess = moduleExports && freeGlobal.process;\n\n  /** Used to access faster Node.js helpers. */\n  var nodeUtil = (function() {\n    try {\n      // Use `util.types` for Node.js 10+.\n      var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n      if (types) {\n        return types;\n      }\n\n      // Legacy `process.binding('util')` for Node.js < 10.\n      return freeProcess && freeProcess.binding && freeProcess.binding('util');\n    } catch (e) {}\n  }());\n\n  /* Node.js helper references. */\n  var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,\n      nodeIsDate = nodeUtil && nodeUtil.isDate,\n      nodeIsMap = nodeUtil && nodeUtil.isMap,\n      nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,\n      nodeIsSet = nodeUtil && nodeUtil.isSet,\n      nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * A faster alternative to `Function#apply`, this function invokes `func`\n   * with the `this` binding of `thisArg` and the arguments of `args`.\n   *\n   * @private\n   * @param {Function} func The function to invoke.\n   * @param {*} thisArg The `this` binding of `func`.\n   * @param {Array} args The arguments to invoke `func` with.\n   * @returns {*} Returns the result of `func`.\n   */\n  function apply(func, thisArg, args) {\n    switch (args.length) {\n      case 0: return func.call(thisArg);\n      case 1: return func.call(thisArg, args[0]);\n      case 2: return func.call(thisArg, args[0], args[1]);\n      case 3: return func.call(thisArg, args[0], args[1], args[2]);\n    }\n    return func.apply(thisArg, args);\n  }\n\n  /**\n   * A specialized version of `baseAggregator` for arrays.\n   *\n   * @private\n   * @param {Array} [array] The array to iterate over.\n   * @param {Function} setter The function to set `accumulator` values.\n   * @param {Function} iteratee The iteratee to transform keys.\n   * @param {Object} accumulator The initial aggregated object.\n   * @returns {Function} Returns `accumulator`.\n   */\n  function arrayAggregator(array, setter, iteratee, accumulator) {\n    var index = -1,\n        length = array == null ? 0 : array.length;\n\n    while (++index < length) {\n      var value = array[index];\n      setter(accumulator, value, iteratee(value), array);\n    }\n    return accumulator;\n  }\n\n  /**\n   * A specialized version of `_.forEach` for arrays without support for\n   * iteratee shorthands.\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 == null ? 0 : 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   * iteratee shorthands.\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 == null ? 0 : 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\n   * iteratee shorthands.\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 == null ? 0 : 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 `_.filter` for arrays without support for\n   * iteratee shorthands.\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 == null ? 0 : array.length,\n        resIndex = 0,\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 `_.includes` for arrays without support for\n   * specifying an index to search from.\n   *\n   * @private\n   * @param {Array} [array] The array to inspect.\n   * @param {*} target The value to search for.\n   * @returns {boolean} Returns `true` if `target` is found, else `false`.\n   */\n  function arrayIncludes(array, value) {\n    var length = array == null ? 0 : array.length;\n    return !!length && baseIndexOf(array, value, 0) > -1;\n  }\n\n  /**\n   * This function is like `arrayIncludes` except that it accepts a comparator.\n   *\n   * @private\n   * @param {Array} [array] The array to inspect.\n   * @param {*} target The value to search for.\n   * @param {Function} comparator The comparator invoked per element.\n   * @returns {boolean} Returns `true` if `target` is found, else `false`.\n   */\n  function arrayIncludesWith(array, value, comparator) {\n    var index = -1,\n        length = array == null ? 0 : array.length;\n\n    while (++index < length) {\n      if (comparator(value, array[index])) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * A specialized version of `_.map` for arrays without support for iteratee\n   * shorthands.\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 == null ? 0 : 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\n   * iteratee shorthands.\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} [initAccum] Specify using the first element of `array` as\n   *  the initial value.\n   * @returns {*} Returns the accumulated value.\n   */\n  function arrayReduce(array, iteratee, accumulator, initAccum) {\n    var index = -1,\n        length = array == null ? 0 : array.length;\n\n    if (initAccum && 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   * iteratee shorthands.\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} [initAccum] Specify using the last element of `array` as\n   *  the initial value.\n   * @returns {*} Returns the accumulated value.\n   */\n  function arrayReduceRight(array, iteratee, accumulator, initAccum) {\n    var length = array == null ? 0 : array.length;\n    if (initAccum && 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 iteratee\n   * shorthands.\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 == null ? 0 : 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   * Gets the size of an ASCII `string`.\n   *\n   * @private\n   * @param {string} string The string inspect.\n   * @returns {number} Returns the string size.\n   */\n  var asciiSize = baseProperty('length');\n\n  /**\n   * Converts an ASCII `string` to an array.\n   *\n   * @private\n   * @param {string} string The string to convert.\n   * @returns {Array} Returns the converted array.\n   */\n  function asciiToArray(string) {\n    return string.split('');\n  }\n\n  /**\n   * Splits an ASCII `string` into an array of its words.\n   *\n   * @private\n   * @param {string} The string to inspect.\n   * @returns {Array} Returns the words of `string`.\n   */\n  function asciiWords(string) {\n    return string.match(reAsciiWord) || [];\n  }\n\n  /**\n   * The base implementation of methods like `_.findKey` and `_.findLastKey`,\n   * without support for iteratee shorthands, which iterates over `collection`\n   * using `eachFunc`.\n   *\n   * @private\n   * @param {Array|Object} collection The collection to inspect.\n   * @param {Function} predicate The function invoked per iteration.\n   * @param {Function} eachFunc The function to iterate over `collection`.\n   * @returns {*} Returns the found element or its key, else `undefined`.\n   */\n  function baseFindKey(collection, predicate, eachFunc) {\n    var result;\n    eachFunc(collection, function(value, key, collection) {\n      if (predicate(value, key, collection)) {\n        result = key;\n        return false;\n      }\n    });\n    return result;\n  }\n\n  /**\n   * The base implementation of `_.findIndex` and `_.findLastIndex` without\n   * support for iteratee shorthands.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\n   * @param {Function} predicate The function invoked per iteration.\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 value, else `-1`.\n   */\n  function baseFindIndex(array, predicate, fromIndex, fromRight) {\n    var length = array.length,\n        index = fromIndex + (fromRight ? 1 : -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 `fromIndex` bounds checks.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\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    return value === value\n      ? strictIndexOf(array, value, fromIndex)\n      : baseFindIndex(array, baseIsNaN, fromIndex);\n  }\n\n  /**\n   * This function is like `baseIndexOf` except that it accepts a comparator.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\n   * @param {*} value The value to search for.\n   * @param {number} fromIndex The index to search from.\n   * @param {Function} comparator The comparator invoked per element.\n   * @returns {number} Returns the index of the matched value, else `-1`.\n   */\n  function baseIndexOfWith(array, value, fromIndex, comparator) {\n    var index = fromIndex - 1,\n        length = array.length;\n\n    while (++index < length) {\n      if (comparator(array[index], value)) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  /**\n   * The base implementation of `_.isNaN` without support for number objects.\n   *\n   * @private\n   * @param {*} value The value to check.\n   * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n   */\n  function baseIsNaN(value) {\n    return value !== value;\n  }\n\n  /**\n   * The base implementation of `_.mean` and `_.meanBy` without support for\n   * iteratee shorthands.\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 mean.\n   */\n  function baseMean(array, iteratee) {\n    var length = array == null ? 0 : array.length;\n    return length ? (baseSum(array, iteratee) / length) : NAN;\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 accessor function.\n   */\n  function baseProperty(key) {\n    return function(object) {\n      return object == null ? undefined : object[key];\n    };\n  }\n\n  /**\n   * The base implementation of `_.propertyOf` without support for deep paths.\n   *\n   * @private\n   * @param {Object} object The object to query.\n   * @returns {Function} Returns the new accessor function.\n   */\n  function basePropertyOf(object) {\n    return function(key) {\n      return object == null ? undefined : object[key];\n    };\n  }\n\n  /**\n   * The base implementation of `_.reduce` and `_.reduceRight`, without support\n   * for iteratee shorthands, which iterates over `collection` using `eachFunc`.\n   *\n   * @private\n   * @param {Array|Object} collection The collection to iterate over.\n   * @param {Function} iteratee The function invoked per iteration.\n   * @param {*} accumulator The initial value.\n   * @param {boolean} initAccum Specify using the first or last element of\n   *  `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, initAccum, eachFunc) {\n    eachFunc(collection, function(value, index, collection) {\n      accumulator = initAccum\n        ? (initAccum = false, value)\n        : iteratee(accumulator, value, index, collection);\n    });\n    return accumulator;\n  }\n\n  /**\n   * The base implementation of `_.sortBy` which uses `comparer` to define the\n   * sort order of `array` and replaces criteria objects with their corresponding\n   * 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 `_.sum` and `_.sumBy` without support for\n   * iteratee shorthands.\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 baseSum(array, iteratee) {\n    var result,\n        index = -1,\n        length = array.length;\n\n    while (++index < length) {\n      var current = iteratee(array[index]);\n      if (current !== undefined) {\n        result = result === undefined ? current : (result + current);\n      }\n    }\n    return result;\n  }\n\n  /**\n   * The base implementation of `_.times` without support for iteratee shorthands\n   * or max array length checks.\n   *\n   * @private\n   * @param {number} n The number of times to invoke `iteratee`.\n   * @param {Function} iteratee The function invoked per iteration.\n   * @returns {Array} Returns the array of results.\n   */\n  function baseTimes(n, iteratee) {\n    var index = -1,\n        result = Array(n);\n\n    while (++index < n) {\n      result[index] = iteratee(index);\n    }\n    return result;\n  }\n\n  /**\n   * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array\n   * of key-value pairs for `object` corresponding to the property names 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 key-value pairs.\n   */\n  function baseToPairs(object, props) {\n    return arrayMap(props, function(key) {\n      return [key, object[key]];\n    });\n  }\n\n  /**\n   * The base implementation of `_.trim`.\n   *\n   * @private\n   * @param {string} string The string to trim.\n   * @returns {string} Returns the trimmed string.\n   */\n  function baseTrim(string) {\n    return string\n      ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n      : string;\n  }\n\n  /**\n   * The base implementation of `_.unary` without support for storing metadata.\n   *\n   * @private\n   * @param {Function} func The function to cap arguments for.\n   * @returns {Function} Returns the new capped function.\n   */\n  function baseUnary(func) {\n    return function(value) {\n      return func(value);\n    };\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    return arrayMap(props, function(key) {\n      return object[key];\n    });\n  }\n\n  /**\n   * Checks if a `cache` value for `key` exists.\n   *\n   * @private\n   * @param {Object} cache The cache to query.\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 cacheHas(cache, key) {\n    return cache.has(key);\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol\n   * that is not found in the character symbols.\n   *\n   * @private\n   * @param {Array} strSymbols The string symbols to inspect.\n   * @param {Array} chrSymbols The character symbols to find.\n   * @returns {number} Returns the index of the first unmatched string symbol.\n   */\n  function charsStartIndex(strSymbols, chrSymbols) {\n    var index = -1,\n        length = strSymbols.length;\n\n    while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n    return index;\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol\n   * that is not found in the character symbols.\n   *\n   * @private\n   * @param {Array} strSymbols The string symbols to inspect.\n   * @param {Array} chrSymbols The character symbols to find.\n   * @returns {number} Returns the index of the last unmatched string symbol.\n   */\n  function charsEndIndex(strSymbols, chrSymbols) {\n    var index = strSymbols.length;\n\n    while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n    return index;\n  }\n\n  /**\n   * Gets the number of `placeholder` occurrences in `array`.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\n   * @param {*} placeholder The placeholder to search for.\n   * @returns {number} Returns the placeholder count.\n   */\n  function countHolders(array, placeholder) {\n    var length = array.length,\n        result = 0;\n\n    while (length--) {\n      if (array[length] === placeholder) {\n        ++result;\n      }\n    }\n    return result;\n  }\n\n  /**\n   * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n   * 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  var deburrLetter = basePropertyOf(deburredLetters);\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  var escapeHtmlChar = basePropertyOf(htmlEscapes);\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 value at `key` of `object`.\n   *\n   * @private\n   * @param {Object} [object] The object to query.\n   * @param {string} key The key of the property to get.\n   * @returns {*} Returns the property value.\n   */\n  function getValue(object, key) {\n    return object == null ? undefined : object[key];\n  }\n\n  /**\n   * Checks if `string` contains Unicode symbols.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n   */\n  function hasUnicode(string) {\n    return reHasUnicode.test(string);\n  }\n\n  /**\n   * Checks if `string` contains a word composed of Unicode symbols.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @returns {boolean} Returns `true` if a word is found, else `false`.\n   */\n  function hasUnicodeWord(string) {\n    return reHasUnicodeWord.test(string);\n  }\n\n  /**\n   * Converts `iterator` to an array.\n   *\n   * @private\n   * @param {Object} iterator The iterator to convert.\n   * @returns {Array} Returns the converted array.\n   */\n  function iteratorToArray(iterator) {\n    var data,\n        result = [];\n\n    while (!(data = iterator.next()).done) {\n      result.push(data.value);\n    }\n    return result;\n  }\n\n  /**\n   * Converts `map` to its key-value pairs.\n   *\n   * @private\n   * @param {Object} map The map to convert.\n   * @returns {Array} Returns the key-value pairs.\n   */\n  function mapToArray(map) {\n    var index = -1,\n        result = Array(map.size);\n\n    map.forEach(function(value, key) {\n      result[++index] = [key, value];\n    });\n    return result;\n  }\n\n  /**\n   * Creates a unary function that invokes `func` with its argument transformed.\n   *\n   * @private\n   * @param {Function} func The function to wrap.\n   * @param {Function} transform The argument transform.\n   * @returns {Function} Returns the new function.\n   */\n  function overArg(func, transform) {\n    return function(arg) {\n      return func(transform(arg));\n    };\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 = 0,\n        result = [];\n\n    while (++index < length) {\n      var value = array[index];\n      if (value === placeholder || value === PLACEHOLDER) {\n        array[index] = PLACEHOLDER;\n        result[resIndex++] = index;\n      }\n    }\n    return result;\n  }\n\n  /**\n   * Converts `set` to an array of its values.\n   *\n   * @private\n   * @param {Object} set The set to convert.\n   * @returns {Array} Returns the values.\n   */\n  function setToArray(set) {\n    var index = -1,\n        result = Array(set.size);\n\n    set.forEach(function(value) {\n      result[++index] = value;\n    });\n    return result;\n  }\n\n  /**\n   * Converts `set` to its value-value pairs.\n   *\n   * @private\n   * @param {Object} set The set to convert.\n   * @returns {Array} Returns the value-value pairs.\n   */\n  function setToPairs(set) {\n    var index = -1,\n        result = Array(set.size);\n\n    set.forEach(function(value) {\n      result[++index] = [value, value];\n    });\n    return result;\n  }\n\n  /**\n   * A specialized version of `_.indexOf` which performs strict equality\n   * comparisons of values, i.e. `===`.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\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 strictIndexOf(array, value, fromIndex) {\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   * A specialized version of `_.lastIndexOf` which performs strict equality\n   * comparisons of values, i.e. `===`.\n   *\n   * @private\n   * @param {Array} array The array to inspect.\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 strictLastIndexOf(array, value, fromIndex) {\n    var index = fromIndex + 1;\n    while (index--) {\n      if (array[index] === value) {\n        return index;\n      }\n    }\n    return index;\n  }\n\n  /**\n   * Gets the number of symbols in `string`.\n   *\n   * @private\n   * @param {string} string The string to inspect.\n   * @returns {number} Returns the string size.\n   */\n  function stringSize(string) {\n    return hasUnicode(string)\n      ? unicodeSize(string)\n      : asciiSize(string);\n  }\n\n  /**\n   * Converts `string` to an array.\n   *\n   * @private\n   * @param {string} string The string to convert.\n   * @returns {Array} Returns the converted array.\n   */\n  function stringToArray(string) {\n    return hasUnicode(string)\n      ? unicodeToArray(string)\n      : asciiToArray(string);\n  }\n\n  /**\n   * Used by `_.trim` and `_.trimEnd` 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 trimmedEndIndex(string) {\n    var index = string.length;\n\n    while (index-- && reWhitespace.test(string.charAt(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  var unescapeHtmlChar = basePropertyOf(htmlUnescapes);\n\n  /**\n   * Gets the size of a Unicode `string`.\n   *\n   * @private\n   * @param {string} string The string inspect.\n   * @returns {number} Returns the string size.\n   */\n  function unicodeSize(string) {\n    var result = reUnicode.lastIndex = 0;\n    while (reUnicode.test(string)) {\n      ++result;\n    }\n    return result;\n  }\n\n  /**\n   * Converts a Unicode `string` to an array.\n   *\n   * @private\n   * @param {string} string The string to convert.\n   * @returns {Array} Returns the converted array.\n   */\n  function unicodeToArray(string) {\n    return string.match(reUnicode) || [];\n  }\n\n  /**\n   * Splits a Unicode `string` into an array of its words.\n   *\n   * @private\n   * @param {string} The string to inspect.\n   * @returns {Array} Returns the words of `string`.\n   */\n  function unicodeWords(string) {\n    return string.match(reUnicodeWord) || [];\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Create a new pristine `lodash` function using the `context` object.\n   *\n   * @static\n   * @memberOf _\n   * @since 1.1.0\n   * @category Util\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   * // Create a suped-up `defer` in Node.js.\n   * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;\n   */\n  var runInContext = (function runInContext(context) {\n    context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));\n\n    /** Built-in constructor references. */\n    var Array = context.Array,\n        Date = context.Date,\n        Error = context.Error,\n        Function = context.Function,\n        Math = context.Math,\n        Object = context.Object,\n        RegExp = context.RegExp,\n        String = context.String,\n        TypeError = context.TypeError;\n\n    /** Used for built-in method references. */\n    var arrayProto = Array.prototype,\n        funcProto = Function.prototype,\n        objectProto = Object.prototype;\n\n    /** Used to detect overreaching core-js shims. */\n    var coreJsData = context['__core-js_shared__'];\n\n    /** Used to resolve the decompiled source of functions. */\n    var funcToString = funcProto.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    /** Used to detect methods masquerading as native. */\n    var maskSrcKey = (function() {\n      var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n      return uid ? ('Symbol(src)_1.' + uid) : '';\n    }());\n\n    /**\n     * Used to resolve the\n     * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n     * of values.\n     */\n    var nativeObjectToString = objectProto.toString;\n\n    /** Used to infer the `Object` constructor. */\n    var objectCtorString = funcToString.call(Object);\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      funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n      .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n    );\n\n    /** Built-in value references. */\n    var Buffer = moduleExports ? context.Buffer : undefined,\n        Symbol = context.Symbol,\n        Uint8Array = context.Uint8Array,\n        allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,\n        getPrototype = overArg(Object.getPrototypeOf, Object),\n        objectCreate = Object.create,\n        propertyIsEnumerable = objectProto.propertyIsEnumerable,\n        splice = arrayProto.splice,\n        spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,\n        symIterator = Symbol ? Symbol.iterator : undefined,\n        symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n    var defineProperty = (function() {\n      try {\n        var func = getNative(Object, 'defineProperty');\n        func({}, '', {});\n        return func;\n      } catch (e) {}\n    }());\n\n    /** Mocked built-ins. */\n    var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,\n        ctxNow = Date && Date.now !== root.Date.now && Date.now,\n        ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;\n\n    /* Built-in method references for those with the same name as other `lodash` methods. */\n    var nativeCeil = Math.ceil,\n        nativeFloor = Math.floor,\n        nativeGetSymbols = Object.getOwnPropertySymbols,\n        nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,\n        nativeIsFinite = context.isFinite,\n        nativeJoin = arrayProto.join,\n        nativeKeys = overArg(Object.keys, Object),\n        nativeMax = Math.max,\n        nativeMin = Math.min,\n        nativeNow = Date.now,\n        nativeParseInt = context.parseInt,\n        nativeRandom = Math.random,\n        nativeReverse = arrayProto.reverse;\n\n    /* Built-in method references that are verified to be native. */\n    var DataView = getNative(context, 'DataView'),\n        Map = getNative(context, 'Map'),\n        Promise = getNative(context, 'Promise'),\n        Set = getNative(context, 'Set'),\n        WeakMap = getNative(context, 'WeakMap'),\n        nativeCreate = getNative(Object, 'create');\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    /** Used to detect maps, sets, and weakmaps. */\n    var dataViewCtorString = toSource(DataView),\n        mapCtorString = toSource(Map),\n        promiseCtorString = toSource(Promise),\n        setCtorString = toSource(Set),\n        weakMapCtorString = toSource(WeakMap);\n\n    /** Used to convert symbols to primitives and strings. */\n    var symbolProto = Symbol ? Symbol.prototype : undefined,\n        symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,\n        symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a `lodash` object which wraps `value` to enable implicit method\n     * chain sequences. Methods that operate on and return arrays, collections,\n     * and functions can be chained together. Methods that retrieve a single value\n     * or may return a primitive value will automatically end the chain sequence\n     * and return the unwrapped value. Otherwise, the value must be unwrapped\n     * with `_#value`.\n     *\n     * Explicit chain sequences, which must be unwrapped with `_#value`, may be\n     * enabled using `_.chain`.\n     *\n     * The execution of chained methods is lazy, that is, it's deferred until\n     * `_#value` is implicitly or explicitly called.\n     *\n     * Lazy evaluation allows several methods to support shortcut fusion.\n     * Shortcut fusion is an optimization to merge iteratee calls; this avoids\n     * the creation of intermediate arrays and can greatly reduce the number of\n     * iteratee executions. Sections of a chain sequence qualify for shortcut\n     * fusion if the section is applied to an array and iteratees accept only\n     * one argument. The heuristic for whether a section qualifies for shortcut\n     * fusion is subject to change.\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`, `shift`, `sort`, `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     * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,\n     * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,\n     * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`\n     *\n     * The chainable wrapper methods are:\n     * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,\n     * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,\n     * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,\n     * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,\n     * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,\n     * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,\n     * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,\n     * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,\n     * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,\n     * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,\n     * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,\n     * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,\n     * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,\n     * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,\n     * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,\n     * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,\n     * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,\n     * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,\n     * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,\n     * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,\n     * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,\n     * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,\n     * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,\n     * `zipObject`, `zipObjectDeep`, and `zipWith`\n     *\n     * The wrapper methods that are **not** chainable by default are:\n     * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,\n     * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,\n     * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,\n     * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,\n     * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,\n     * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,\n     * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,\n     * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,\n     * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,\n     * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,\n     * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,\n     * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,\n     * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,\n     * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,\n     * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,\n     * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,\n     * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,\n     * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,\n     * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,\n     * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,\n     * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,\n     * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,\n     * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,\n     * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,\n     * `upperFirst`, `value`, and `words`\n     *\n     * @name _\n     * @constructor\n     * @category Seq\n     * @param {*} value The value to wrap in a `lodash` instance.\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * var wrapped = _([1, 2, 3]);\n     *\n     * // Returns an unwrapped value.\n     * wrapped.reduce(_.add);\n     * // => 6\n     *\n     * // Returns a wrapped value.\n     * var squares = wrapped.map(square);\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, '__wrapped__')) {\n          return wrapperClone(value);\n        }\n      }\n      return new LodashWrapper(value);\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} proto The object to inherit from.\n     * @returns {Object} Returns the new object.\n     */\n    var baseCreate = (function() {\n      function object() {}\n      return function(proto) {\n        if (!isObject(proto)) {\n          return {};\n        }\n        if (objectCreate) {\n          return objectCreate(proto);\n        }\n        object.prototype = proto;\n        var result = new object;\n        object.prototype = undefined;\n        return result;\n      };\n    }());\n\n    /**\n     * The function whose prototype chain sequence 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 explicit method chain sequences.\n     */\n    function LodashWrapper(value, chainAll) {\n      this.__wrapped__ = value;\n      this.__actions__ = [];\n      this.__chain__ = !!chainAll;\n      this.__index__ = 0;\n      this.__values__ = undefined;\n    }\n\n    /**\n     * By default, the template delimiters used by lodash are like those in\n     * embedded Ruby (ERB) as well as ES2015 template strings. Change the\n     * following template settings to use 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    // Ensure wrappers are instances of `baseLodash`.\n    lodash.prototype = baseLodash.prototype;\n    lodash.prototype.constructor = lodash;\n\n    LodashWrapper.prototype = baseCreate(baseLodash.prototype);\n    LodashWrapper.prototype.constructor = LodashWrapper;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.\n     *\n     * @private\n     * @constructor\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__ = MAX_ARRAY_LENGTH;\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__ = copyArray(this.__actions__);\n      result.__dir__ = this.__dir__;\n      result.__filtered__ = this.__filtered__;\n      result.__iteratees__ = copyArray(this.__iteratees__);\n      result.__takeCount__ = this.__takeCount__;\n      result.__views__ = copyArray(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 || (!isRight && arrLength == length && takeCount == length)) {\n        return baseWrapperValue(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    // Ensure `LazyWrapper` is an instance of `baseLodash`.\n    LazyWrapper.prototype = baseCreate(baseLodash.prototype);\n    LazyWrapper.prototype.constructor = LazyWrapper;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a hash object.\n     *\n     * @private\n     * @constructor\n     * @param {Array} [entries] The key-value pairs to cache.\n     */\n    function Hash(entries) {\n      var index = -1,\n          length = entries == null ? 0 : entries.length;\n\n      this.clear();\n      while (++index < length) {\n        var entry = entries[index];\n        this.set(entry[0], entry[1]);\n      }\n    }\n\n    /**\n     * Removes all key-value entries from the hash.\n     *\n     * @private\n     * @name clear\n     * @memberOf Hash\n     */\n    function hashClear() {\n      this.__data__ = nativeCreate ? nativeCreate(null) : {};\n      this.size = 0;\n    }\n\n    /**\n     * Removes `key` and its value from the hash.\n     *\n     * @private\n     * @name delete\n     * @memberOf Hash\n     * @param {Object} hash The hash to modify.\n     * @param {string} key The key of the value to remove.\n     * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n     */\n    function hashDelete(key) {\n      var result = this.has(key) && delete this.__data__[key];\n      this.size -= result ? 1 : 0;\n      return result;\n    }\n\n    /**\n     * Gets the hash value for `key`.\n     *\n     * @private\n     * @name get\n     * @memberOf Hash\n     * @param {string} key The key of the value to get.\n     * @returns {*} Returns the entry value.\n     */\n    function hashGet(key) {\n      var data = this.__data__;\n      if (nativeCreate) {\n        var result = data[key];\n        return result === HASH_UNDEFINED ? undefined : result;\n      }\n      return hasOwnProperty.call(data, key) ? data[key] : undefined;\n    }\n\n    /**\n     * Checks if a hash value for `key` exists.\n     *\n     * @private\n     * @name has\n     * @memberOf Hash\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 hashHas(key) {\n      var data = this.__data__;\n      return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n    }\n\n    /**\n     * Sets the hash `key` to `value`.\n     *\n     * @private\n     * @name set\n     * @memberOf Hash\n     * @param {string} key The key of the value to set.\n     * @param {*} value The value to set.\n     * @returns {Object} Returns the hash instance.\n     */\n    function hashSet(key, value) {\n      var data = this.__data__;\n      this.size += this.has(key) ? 0 : 1;\n      data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n      return this;\n    }\n\n    // Add methods to `Hash`.\n    Hash.prototype.clear = hashClear;\n    Hash.prototype['delete'] = hashDelete;\n    Hash.prototype.get = hashGet;\n    Hash.prototype.has = hashHas;\n    Hash.prototype.set = hashSet;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates an list cache object.\n     *\n     * @private\n     * @constructor\n     * @param {Array} [entries] The key-value pairs to cache.\n     */\n    function ListCache(entries) {\n      var index = -1,\n          length = entries == null ? 0 : entries.length;\n\n      this.clear();\n      while (++index < length) {\n        var entry = entries[index];\n        this.set(entry[0], entry[1]);\n      }\n    }\n\n    /**\n     * Removes all key-value entries from the list cache.\n     *\n     * @private\n     * @name clear\n     * @memberOf ListCache\n     */\n    function listCacheClear() {\n      this.__data__ = [];\n      this.size = 0;\n    }\n\n    /**\n     * Removes `key` and its value from the list cache.\n     *\n     * @private\n     * @name delete\n     * @memberOf ListCache\n     * @param {string} key The key of the value to remove.\n     * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n     */\n    function listCacheDelete(key) {\n      var data = this.__data__,\n          index = assocIndexOf(data, key);\n\n      if (index < 0) {\n        return false;\n      }\n      var lastIndex = data.length - 1;\n      if (index == lastIndex) {\n        data.pop();\n      } else {\n        splice.call(data, index, 1);\n      }\n      --this.size;\n      return true;\n    }\n\n    /**\n     * Gets the list cache value for `key`.\n     *\n     * @private\n     * @name get\n     * @memberOf ListCache\n     * @param {string} key The key of the value to get.\n     * @returns {*} Returns the entry value.\n     */\n    function listCacheGet(key) {\n      var data = this.__data__,\n          index = assocIndexOf(data, key);\n\n      return index < 0 ? undefined : data[index][1];\n    }\n\n    /**\n     * Checks if a list cache value for `key` exists.\n     *\n     * @private\n     * @name has\n     * @memberOf ListCache\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 listCacheHas(key) {\n      return assocIndexOf(this.__data__, key) > -1;\n    }\n\n    /**\n     * Sets the list cache `key` to `value`.\n     *\n     * @private\n     * @name set\n     * @memberOf ListCache\n     * @param {string} key The key of the value to set.\n     * @param {*} value The value to set.\n     * @returns {Object} Returns the list cache instance.\n     */\n    function listCacheSet(key, value) {\n      var data = this.__data__,\n          index = assocIndexOf(data, key);\n\n      if (index < 0) {\n        ++this.size;\n        data.push([key, value]);\n      } else {\n        data[index][1] = value;\n      }\n      return this;\n    }\n\n    // Add methods to `ListCache`.\n    ListCache.prototype.clear = listCacheClear;\n    ListCache.prototype['delete'] = listCacheDelete;\n    ListCache.prototype.get = listCacheGet;\n    ListCache.prototype.has = listCacheHas;\n    ListCache.prototype.set = listCacheSet;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a map cache object to store key-value pairs.\n     *\n     * @private\n     * @constructor\n     * @param {Array} [entries] The key-value pairs to cache.\n     */\n    function MapCache(entries) {\n      var index = -1,\n          length = entries == null ? 0 : entries.length;\n\n      this.clear();\n      while (++index < length) {\n        var entry = entries[index];\n        this.set(entry[0], entry[1]);\n      }\n    }\n\n    /**\n     * Removes all key-value entries from the map.\n     *\n     * @private\n     * @name clear\n     * @memberOf MapCache\n     */\n    function mapCacheClear() {\n      this.size = 0;\n      this.__data__ = {\n        'hash': new Hash,\n        'map': new (Map || ListCache),\n        'string': new Hash\n      };\n    }\n\n    /**\n     * Removes `key` and its value from the map.\n     *\n     * @private\n     * @name delete\n     * @memberOf MapCache\n     * @param {string} key The key of the value to remove.\n     * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n     */\n    function mapCacheDelete(key) {\n      var result = getMapData(this, key)['delete'](key);\n      this.size -= result ? 1 : 0;\n      return result;\n    }\n\n    /**\n     * Gets the map value for `key`.\n     *\n     * @private\n     * @name get\n     * @memberOf MapCache\n     * @param {string} key The key of the value to get.\n     * @returns {*} Returns the entry value.\n     */\n    function mapCacheGet(key) {\n      return getMapData(this, key).get(key);\n    }\n\n    /**\n     * Checks if a map value for `key` exists.\n     *\n     * @private\n     * @name has\n     * @memberOf MapCache\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 mapCacheHas(key) {\n      return getMapData(this, key).has(key);\n    }\n\n    /**\n     * Sets the map `key` to `value`.\n     *\n     * @private\n     * @name set\n     * @memberOf MapCache\n     * @param {string} key The key of the value to set.\n     * @param {*} value The value to set.\n     * @returns {Object} Returns the map cache instance.\n     */\n    function mapCacheSet(key, value) {\n      var data = getMapData(this, key),\n          size = data.size;\n\n      data.set(key, value);\n      this.size += data.size == size ? 0 : 1;\n      return this;\n    }\n\n    // Add methods to `MapCache`.\n    MapCache.prototype.clear = mapCacheClear;\n    MapCache.prototype['delete'] = mapCacheDelete;\n    MapCache.prototype.get = mapCacheGet;\n    MapCache.prototype.has = mapCacheHas;\n    MapCache.prototype.set = mapCacheSet;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     *\n     * Creates an array cache object to store unique values.\n     *\n     * @private\n     * @constructor\n     * @param {Array} [values] The values to cache.\n     */\n    function SetCache(values) {\n      var index = -1,\n          length = values == null ? 0 : values.length;\n\n      this.__data__ = new MapCache;\n      while (++index < length) {\n        this.add(values[index]);\n      }\n    }\n\n    /**\n     * Adds `value` to the array cache.\n     *\n     * @private\n     * @name add\n     * @memberOf SetCache\n     * @alias push\n     * @param {*} value The value to cache.\n     * @returns {Object} Returns the cache instance.\n     */\n    function setCacheAdd(value) {\n      this.__data__.set(value, HASH_UNDEFINED);\n      return this;\n    }\n\n    /**\n     * Checks if `value` is in the array cache.\n     *\n     * @private\n     * @name has\n     * @memberOf SetCache\n     * @param {*} value The value to search for.\n     * @returns {number} Returns `true` if `value` is found, else `false`.\n     */\n    function setCacheHas(value) {\n      return this.__data__.has(value);\n    }\n\n    // Add methods to `SetCache`.\n    SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\n    SetCache.prototype.has = setCacheHas;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a stack cache object to store key-value pairs.\n     *\n     * @private\n     * @constructor\n     * @param {Array} [entries] The key-value pairs to cache.\n     */\n    function Stack(entries) {\n      var data = this.__data__ = new ListCache(entries);\n      this.size = data.size;\n    }\n\n    /**\n     * Removes all key-value entries from the stack.\n     *\n     * @private\n     * @name clear\n     * @memberOf Stack\n     */\n    function stackClear() {\n      this.__data__ = new ListCache;\n      this.size = 0;\n    }\n\n    /**\n     * Removes `key` and its value from the stack.\n     *\n     * @private\n     * @name delete\n     * @memberOf Stack\n     * @param {string} key The key of the value to remove.\n     * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n     */\n    function stackDelete(key) {\n      var data = this.__data__,\n          result = data['delete'](key);\n\n      this.size = data.size;\n      return result;\n    }\n\n    /**\n     * Gets the stack value for `key`.\n     *\n     * @private\n     * @name get\n     * @memberOf Stack\n     * @param {string} key The key of the value to get.\n     * @returns {*} Returns the entry value.\n     */\n    function stackGet(key) {\n      return this.__data__.get(key);\n    }\n\n    /**\n     * Checks if a stack value for `key` exists.\n     *\n     * @private\n     * @name has\n     * @memberOf Stack\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 stackHas(key) {\n      return this.__data__.has(key);\n    }\n\n    /**\n     * Sets the stack `key` to `value`.\n     *\n     * @private\n     * @name set\n     * @memberOf Stack\n     * @param {string} key The key of the value to set.\n     * @param {*} value The value to set.\n     * @returns {Object} Returns the stack cache instance.\n     */\n    function stackSet(key, value) {\n      var data = this.__data__;\n      if (data instanceof ListCache) {\n        var pairs = data.__data__;\n        if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n          pairs.push([key, value]);\n          this.size = ++data.size;\n          return this;\n        }\n        data = this.__data__ = new MapCache(pairs);\n      }\n      data.set(key, value);\n      this.size = data.size;\n      return this;\n    }\n\n    // Add methods to `Stack`.\n    Stack.prototype.clear = stackClear;\n    Stack.prototype['delete'] = stackDelete;\n    Stack.prototype.get = stackGet;\n    Stack.prototype.has = stackHas;\n    Stack.prototype.set = stackSet;\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array of the enumerable property names of the array-like `value`.\n     *\n     * @private\n     * @param {*} value The value to query.\n     * @param {boolean} inherited Specify returning inherited property names.\n     * @returns {Array} Returns the array of property names.\n     */\n    function arrayLikeKeys(value, inherited) {\n      var isArr = isArray(value),\n          isArg = !isArr && isArguments(value),\n          isBuff = !isArr && !isArg && isBuffer(value),\n          isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n          skipIndexes = isArr || isArg || isBuff || isType,\n          result = skipIndexes ? baseTimes(value.length, String) : [],\n          length = result.length;\n\n      for (var key in value) {\n        if ((inherited || hasOwnProperty.call(value, key)) &&\n            !(skipIndexes && (\n               // Safari 9 has enumerable `arguments.length` in strict mode.\n               key == 'length' ||\n               // Node.js 0.10 has enumerable non-index properties on buffers.\n               (isBuff && (key == 'offset' || key == 'parent')) ||\n               // PhantomJS 2 has enumerable non-index properties on typed arrays.\n               (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n               // Skip index properties.\n               isIndex(key, length)\n            ))) {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * A specialized version of `_.sample` for arrays.\n     *\n     * @private\n     * @param {Array} array The array to sample.\n     * @returns {*} Returns the random element.\n     */\n    function arraySample(array) {\n      var length = array.length;\n      return length ? array[baseRandom(0, length - 1)] : undefined;\n    }\n\n    /**\n     * A specialized version of `_.sampleSize` for arrays.\n     *\n     * @private\n     * @param {Array} array The array to sample.\n     * @param {number} n The number of elements to sample.\n     * @returns {Array} Returns the random elements.\n     */\n    function arraySampleSize(array, n) {\n      return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));\n    }\n\n    /**\n     * A specialized version of `_.shuffle` for arrays.\n     *\n     * @private\n     * @param {Array} array The array to shuffle.\n     * @returns {Array} Returns the new shuffled array.\n     */\n    function arrayShuffle(array) {\n      return shuffleSelf(copyArray(array));\n    }\n\n    /**\n     * This function is like `assignValue` except that it doesn't assign\n     * `undefined` values.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {string} key The key of the property to assign.\n     * @param {*} value The value to assign.\n     */\n    function assignMergeValue(object, key, value) {\n      if ((value !== undefined && !eq(object[key], value)) ||\n          (value === undefined && !(key in object))) {\n        baseAssignValue(object, key, value);\n      }\n    }\n\n    /**\n     * Assigns `value` to `key` of `object` if the existing value is not equivalent\n     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {string} key The key of the property to assign.\n     * @param {*} value The value to assign.\n     */\n    function assignValue(object, key, value) {\n      var objValue = object[key];\n      if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n          (value === undefined && !(key in object))) {\n        baseAssignValue(object, key, value);\n      }\n    }\n\n    /**\n     * Gets the index at which the `key` is found in `array` of key-value pairs.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {*} key The key to search for.\n     * @returns {number} Returns the index of the matched value, else `-1`.\n     */\n    function assocIndexOf(array, key) {\n      var length = array.length;\n      while (length--) {\n        if (eq(array[length][0], key)) {\n          return length;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * Aggregates elements of `collection` on `accumulator` with keys transformed\n     * by `iteratee` and values set by `setter`.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} setter The function to set `accumulator` values.\n     * @param {Function} iteratee The iteratee to transform keys.\n     * @param {Object} accumulator The initial aggregated object.\n     * @returns {Function} Returns `accumulator`.\n     */\n    function baseAggregator(collection, setter, iteratee, accumulator) {\n      baseEach(collection, function(value, key, collection) {\n        setter(accumulator, value, iteratee(value), collection);\n      });\n      return accumulator;\n    }\n\n    /**\n     * The base implementation of `_.assign` without support for multiple sources\n     * or `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 object && copyObject(source, keys(source), object);\n    }\n\n    /**\n     * The base implementation of `_.assignIn` without support for multiple sources\n     * or `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 baseAssignIn(object, source) {\n      return object && copyObject(source, keysIn(source), object);\n    }\n\n    /**\n     * The base implementation of `assignValue` and `assignMergeValue` without\n     * value checks.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {string} key The key of the property to assign.\n     * @param {*} value The value to assign.\n     */\n    function baseAssignValue(object, key, value) {\n      if (key == '__proto__' && defineProperty) {\n        defineProperty(object, key, {\n          'configurable': true,\n          'enumerable': true,\n          'value': value,\n          'writable': true\n        });\n      } else {\n        object[key] = value;\n      }\n    }\n\n    /**\n     * The base implementation of `_.at` without support for individual paths.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {string[]} paths The property paths to pick.\n     * @returns {Array} Returns the picked elements.\n     */\n    function baseAt(object, paths) {\n      var index = -1,\n          length = paths.length,\n          result = Array(length),\n          skip = object == null;\n\n      while (++index < length) {\n        result[index] = skip ? undefined : get(object, paths[index]);\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.clamp` which doesn't coerce arguments.\n     *\n     * @private\n     * @param {number} number The number to clamp.\n     * @param {number} [lower] The lower bound.\n     * @param {number} upper The upper bound.\n     * @returns {number} Returns the clamped number.\n     */\n    function baseClamp(number, lower, upper) {\n      if (number === number) {\n        if (upper !== undefined) {\n          number = number <= upper ? number : upper;\n        }\n        if (lower !== undefined) {\n          number = number >= lower ? number : lower;\n        }\n      }\n      return number;\n    }\n\n    /**\n     * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n     * traversed objects.\n     *\n     * @private\n     * @param {*} value The value to clone.\n     * @param {boolean} bitmask The bitmask flags.\n     *  1 - Deep clone\n     *  2 - Flatten inherited properties\n     *  4 - Clone symbols\n     * @param {Function} [customizer] The function to customize cloning.\n     * @param {string} [key] The key of `value`.\n     * @param {Object} [object] The parent object of `value`.\n     * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n     * @returns {*} Returns the cloned value.\n     */\n    function baseClone(value, bitmask, customizer, key, object, stack) {\n      var result,\n          isDeep = bitmask & CLONE_DEEP_FLAG,\n          isFlat = bitmask & CLONE_FLAT_FLAG,\n          isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n      if (customizer) {\n        result = object ? customizer(value, key, object, stack) : 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 copyArray(value, result);\n        }\n      } else {\n        var tag = getTag(value),\n            isFunc = tag == funcTag || tag == genTag;\n\n        if (isBuffer(value)) {\n          return cloneBuffer(value, isDeep);\n        }\n        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n          result = (isFlat || isFunc) ? {} : initCloneObject(value);\n          if (!isDeep) {\n            return isFlat\n              ? copySymbolsIn(value, baseAssignIn(result, value))\n              : copySymbols(value, baseAssign(result, value));\n          }\n        } else {\n          if (!cloneableTags[tag]) {\n            return object ? value : {};\n          }\n          result = initCloneByTag(value, tag, isDeep);\n        }\n      }\n      // Check for circular references and return its corresponding clone.\n      stack || (stack = new Stack);\n      var stacked = stack.get(value);\n      if (stacked) {\n        return stacked;\n      }\n      stack.set(value, result);\n\n      if (isSet(value)) {\n        value.forEach(function(subValue) {\n          result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n        });\n      } else if (isMap(value)) {\n        value.forEach(function(subValue, key) {\n          result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n        });\n      }\n\n      var keysFunc = isFull\n        ? (isFlat ? getAllKeysIn : getAllKeys)\n        : (isFlat ? keysIn : keys);\n\n      var props = isArr ? undefined : keysFunc(value);\n      arrayEach(props || value, function(subValue, key) {\n        if (props) {\n          key = subValue;\n          subValue = value[key];\n        }\n        // Recursively populate clone (susceptible to call stack limits).\n        assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n      });\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.conforms` which doesn't clone `source`.\n     *\n     * @private\n     * @param {Object} source The object of property predicates to conform to.\n     * @returns {Function} Returns the new spec function.\n     */\n    function baseConforms(source) {\n      var props = keys(source);\n      return function(object) {\n        return baseConformsTo(object, source, props);\n      };\n    }\n\n    /**\n     * The base implementation of `_.conformsTo` which accepts `props` to check.\n     *\n     * @private\n     * @param {Object} object The object to inspect.\n     * @param {Object} source The object of property predicates to conform to.\n     * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n     */\n    function baseConformsTo(object, source, props) {\n      var length = props.length;\n      if (object == null) {\n        return !length;\n      }\n      object = Object(object);\n      while (length--) {\n        var key = props[length],\n            predicate = source[key],\n            value = object[key];\n\n        if ((value === undefined && !(key in object)) || !predicate(value)) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n    /**\n     * The base implementation of `_.delay` and `_.defer` which accepts `args`\n     * 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 {Array} args The arguments to provide to `func`.\n     * @returns {number|Object} Returns the timer id or timeout object.\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 methods like `_.difference` without support\n     * for excluding multiple arrays or iteratee shorthands.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {Array} values The values to exclude.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of filtered values.\n     */\n    function baseDifference(array, values, iteratee, comparator) {\n      var index = -1,\n          includes = arrayIncludes,\n          isCommon = true,\n          length = array.length,\n          result = [],\n          valuesLength = values.length;\n\n      if (!length) {\n        return result;\n      }\n      if (iteratee) {\n        values = arrayMap(values, baseUnary(iteratee));\n      }\n      if (comparator) {\n        includes = arrayIncludesWith;\n        isCommon = false;\n      }\n      else if (values.length >= LARGE_ARRAY_SIZE) {\n        includes = cacheHas;\n        isCommon = false;\n        values = new SetCache(values);\n      }\n      outer:\n      while (++index < length) {\n        var value = array[index],\n            computed = iteratee == null ? value : iteratee(value);\n\n        value = (comparator || value !== 0) ? value : 0;\n        if (isCommon && computed === computed) {\n          var valuesIndex = valuesLength;\n          while (valuesIndex--) {\n            if (values[valuesIndex] === computed) {\n              continue outer;\n            }\n          }\n          result.push(value);\n        }\n        else if (!includes(values, computed, comparator)) {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.forEach` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array|Object} Returns `collection`.\n     */\n    var baseEach = createBaseEach(baseForOwn);\n\n    /**\n     * The base implementation of `_.forEachRight` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} iteratee The function invoked per iteration.\n     * @returns {Array|Object} Returns `collection`.\n     */\n    var baseEachRight = createBaseEach(baseForOwnRight, true);\n\n    /**\n     * The base implementation of `_.every` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} 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     * The base implementation of methods like `_.max` and `_.min` which accepts a\n     * `comparator` to determine the extremum value.\n     *\n     * @private\n     * @param {Array} array The array to iterate over.\n     * @param {Function} iteratee The iteratee invoked per iteration.\n     * @param {Function} comparator The comparator used to compare values.\n     * @returns {*} Returns the extremum value.\n     */\n    function baseExtremum(array, iteratee, comparator) {\n      var index = -1,\n          length = array.length;\n\n      while (++index < length) {\n        var value = array[index],\n            current = iteratee(value);\n\n        if (current != null && (computed === undefined\n              ? (current === current && !isSymbol(current))\n              : comparator(current, computed)\n            )) {\n          var 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 = toInteger(start);\n      if (start < 0) {\n        start = -start > length ? 0 : (length + start);\n      }\n      end = (end === undefined || end > length) ? length : toInteger(end);\n      if (end < 0) {\n        end += length;\n      }\n      end = start > end ? 0 : toLength(end);\n      while (start < end) {\n        array[start++] = value;\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.filter` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} 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 `_.flatten` with support for restricting flattening.\n     *\n     * @private\n     * @param {Array} array The array to flatten.\n     * @param {number} depth The maximum recursion depth.\n     * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n     * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n     * @param {Array} [result=[]] The initial result value.\n     * @returns {Array} Returns the new flattened array.\n     */\n    function baseFlatten(array, depth, predicate, isStrict, result) {\n      var index = -1,\n          length = array.length;\n\n      predicate || (predicate = isFlattenable);\n      result || (result = []);\n\n      while (++index < length) {\n        var value = array[index];\n        if (depth > 0 && predicate(value)) {\n          if (depth > 1) {\n            // Recursively flatten arrays (susceptible to call stack limits).\n            baseFlatten(value, depth - 1, predicate, 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 `baseForOwn` which iterates over `object`\n     * properties returned by `keysFunc` and invokes `iteratee` for each property.\n     * Iteratee functions may exit iteration early by explicitly 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 `_.forOwn` without support for iteratee shorthands.\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 object && baseFor(object, iteratee, keys);\n    }\n\n    /**\n     * The base implementation of `_.forOwnRight` without support for iteratee shorthands.\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 object && 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 `props`.\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 function names.\n     */\n    function baseFunctions(object, props) {\n      return arrayFilter(props, function(key) {\n        return isFunction(object[key]);\n      });\n    }\n\n    /**\n     * The base implementation of `_.get` without support for default values.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path of the property to get.\n     * @returns {*} Returns the resolved value.\n     */\n    function baseGet(object, path) {\n      path = castPath(path, object);\n\n      var index = 0,\n          length = path.length;\n\n      while (object != null && index < length) {\n        object = object[toKey(path[index++])];\n      }\n      return (index && index == length) ? object : undefined;\n    }\n\n    /**\n     * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n     * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n     * symbols of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Function} keysFunc The function to get the keys of `object`.\n     * @param {Function} symbolsFunc The function to get the symbols of `object`.\n     * @returns {Array} Returns the array of property names and symbols.\n     */\n    function baseGetAllKeys(object, keysFunc, symbolsFunc) {\n      var result = keysFunc(object);\n      return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n    }\n\n    /**\n     * The base implementation of `getTag` without fallbacks for buggy environments.\n     *\n     * @private\n     * @param {*} value The value to query.\n     * @returns {string} Returns the `toStringTag`.\n     */\n    function baseGetTag(value) {\n      if (value == null) {\n        return value === undefined ? undefinedTag : nullTag;\n      }\n      return (symToStringTag && symToStringTag in Object(value))\n        ? getRawTag(value)\n        : objectToString(value);\n    }\n\n    /**\n     * The base implementation of `_.gt` which doesn't coerce arguments.\n     *\n     * @private\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`,\n     *  else `false`.\n     */\n    function baseGt(value, other) {\n      return value > other;\n    }\n\n    /**\n     * The base implementation of `_.has` without support for deep paths.\n     *\n     * @private\n     * @param {Object} [object] The object to query.\n     * @param {Array|string} key The key to check.\n     * @returns {boolean} Returns `true` if `key` exists, else `false`.\n     */\n    function baseHas(object, key) {\n      return object != null && hasOwnProperty.call(object, key);\n    }\n\n    /**\n     * The base implementation of `_.hasIn` without support for deep paths.\n     *\n     * @private\n     * @param {Object} [object] The object to query.\n     * @param {Array|string} key The key to check.\n     * @returns {boolean} Returns `true` if `key` exists, else `false`.\n     */\n    function baseHasIn(object, key) {\n      return object != null && key in Object(object);\n    }\n\n    /**\n     * The base implementation of `_.inRange` which doesn't coerce arguments.\n     *\n     * @private\n     * @param {number} number The number to check.\n     * @param {number} start The start of the range.\n     * @param {number} end The end of the range.\n     * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n     */\n    function baseInRange(number, start, end) {\n      return number >= nativeMin(start, end) && number < nativeMax(start, end);\n    }\n\n    /**\n     * The base implementation of methods like `_.intersection`, without support\n     * for iteratee shorthands, that accepts an array of arrays to inspect.\n     *\n     * @private\n     * @param {Array} arrays The arrays to inspect.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of shared values.\n     */\n    function baseIntersection(arrays, iteratee, comparator) {\n      var includes = comparator ? arrayIncludesWith : arrayIncludes,\n          length = arrays[0].length,\n          othLength = arrays.length,\n          othIndex = othLength,\n          caches = Array(othLength),\n          maxLength = Infinity,\n          result = [];\n\n      while (othIndex--) {\n        var array = arrays[othIndex];\n        if (othIndex && iteratee) {\n          array = arrayMap(array, baseUnary(iteratee));\n        }\n        maxLength = nativeMin(array.length, maxLength);\n        caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))\n          ? new SetCache(othIndex && array)\n          : undefined;\n      }\n      array = arrays[0];\n\n      var index = -1,\n          seen = caches[0];\n\n      outer:\n      while (++index < length && result.length < maxLength) {\n        var value = array[index],\n            computed = iteratee ? iteratee(value) : value;\n\n        value = (comparator || value !== 0) ? value : 0;\n        if (!(seen\n              ? cacheHas(seen, computed)\n              : includes(result, computed, comparator)\n            )) {\n          othIndex = othLength;\n          while (--othIndex) {\n            var cache = caches[othIndex];\n            if (!(cache\n                  ? cacheHas(cache, computed)\n                  : includes(arrays[othIndex], computed, comparator))\n                ) {\n              continue outer;\n            }\n          }\n          if (seen) {\n            seen.push(computed);\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.invert` and `_.invertBy` which inverts\n     * `object` with values transformed by `iteratee` and set by `setter`.\n     *\n     * @private\n     * @param {Object} object The object to iterate over.\n     * @param {Function} setter The function to set `accumulator` values.\n     * @param {Function} iteratee The iteratee to transform values.\n     * @param {Object} accumulator The initial inverted object.\n     * @returns {Function} Returns `accumulator`.\n     */\n    function baseInverter(object, setter, iteratee, accumulator) {\n      baseForOwn(object, function(value, key, object) {\n        setter(accumulator, iteratee(value), key, object);\n      });\n      return accumulator;\n    }\n\n    /**\n     * The base implementation of `_.invoke` without support for individual\n     * method arguments.\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 baseInvoke(object, path, args) {\n      path = castPath(path, object);\n      object = parent(object, path);\n      var func = object == null ? object : object[toKey(last(path))];\n      return func == null ? undefined : apply(func, object, args);\n    }\n\n    /**\n     * The base implementation of `_.isArguments`.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n     */\n    function baseIsArguments(value) {\n      return isObjectLike(value) && baseGetTag(value) == argsTag;\n    }\n\n    /**\n     * The base implementation of `_.isArrayBuffer` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n     */\n    function baseIsArrayBuffer(value) {\n      return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;\n    }\n\n    /**\n     * The base implementation of `_.isDate` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n     */\n    function baseIsDate(value) {\n      return isObjectLike(value) && baseGetTag(value) == dateTag;\n    }\n\n    /**\n     * The base implementation of `_.isEqual` which supports partial comparisons\n     * and tracks traversed objects.\n     *\n     * @private\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @param {boolean} bitmask The bitmask flags.\n     *  1 - Unordered comparison\n     *  2 - Partial comparison\n     * @param {Function} [customizer] The function to customize comparisons.\n     * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     */\n    function baseIsEqual(value, other, bitmask, customizer, stack) {\n      if (value === other) {\n        return true;\n      }\n      if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n        return value !== value && other !== other;\n      }\n      return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n     * @param {Function} customizer The function to customize comparisons.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n      var objIsArr = isArray(object),\n          othIsArr = isArray(other),\n          objTag = objIsArr ? arrayTag : getTag(object),\n          othTag = othIsArr ? arrayTag : getTag(other);\n\n      objTag = objTag == argsTag ? objectTag : objTag;\n      othTag = othTag == argsTag ? objectTag : othTag;\n\n      var objIsObj = objTag == objectTag,\n          othIsObj = othTag == objectTag,\n          isSameTag = objTag == othTag;\n\n      if (isSameTag && isBuffer(object)) {\n        if (!isBuffer(other)) {\n          return false;\n        }\n        objIsArr = true;\n        objIsObj = false;\n      }\n      if (isSameTag && !objIsObj) {\n        stack || (stack = new Stack);\n        return (objIsArr || isTypedArray(object))\n          ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n          : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n      }\n      if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n        var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n            othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n        if (objIsWrapped || othIsWrapped) {\n          var objUnwrapped = objIsWrapped ? object.value() : object,\n              othUnwrapped = othIsWrapped ? other.value() : other;\n\n          stack || (stack = new Stack);\n          return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n        }\n      }\n      if (!isSameTag) {\n        return false;\n      }\n      stack || (stack = new Stack);\n      return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n    }\n\n    /**\n     * The base implementation of `_.isMap` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n     */\n    function baseIsMap(value) {\n      return isObjectLike(value) && getTag(value) == mapTag;\n    }\n\n    /**\n     * The base implementation of `_.isMatch` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Object} object The object to inspect.\n     * @param {Object} source The object of property values to match.\n     * @param {Array} matchData The property names, values, and compare flags to match.\n     * @param {Function} [customizer] The function to customize comparisons.\n     * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n     */\n    function baseIsMatch(object, source, matchData, customizer) {\n      var index = matchData.length,\n          length = index,\n          noCustomizer = !customizer;\n\n      if (object == null) {\n        return !length;\n      }\n      object = Object(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 stack = new Stack;\n          if (customizer) {\n            var result = customizer(objValue, srcValue, key, object, source, stack);\n          }\n          if (!(result === undefined\n                ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)\n                : result\n              )) {\n            return false;\n          }\n        }\n      }\n      return true;\n    }\n\n    /**\n     * The base implementation of `_.isNative` without bad shim checks.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a native function,\n     *  else `false`.\n     */\n    function baseIsNative(value) {\n      if (!isObject(value) || isMasked(value)) {\n        return false;\n      }\n      var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n      return pattern.test(toSource(value));\n    }\n\n    /**\n     * The base implementation of `_.isRegExp` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n     */\n    function baseIsRegExp(value) {\n      return isObjectLike(value) && baseGetTag(value) == regexpTag;\n    }\n\n    /**\n     * The base implementation of `_.isSet` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n     */\n    function baseIsSet(value) {\n      return isObjectLike(value) && getTag(value) == setTag;\n    }\n\n    /**\n     * The base implementation of `_.isTypedArray` without Node.js optimizations.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n     */\n    function baseIsTypedArray(value) {\n      return isObjectLike(value) &&\n        isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n    }\n\n    /**\n     * The base implementation of `_.iteratee`.\n     *\n     * @private\n     * @param {*} [value=_.identity] The value to convert to an iteratee.\n     * @returns {Function} Returns the iteratee.\n     */\n    function baseIteratee(value) {\n      // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.\n      // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.\n      if (typeof value == 'function') {\n        return value;\n      }\n      if (value == null) {\n        return identity;\n      }\n      if (typeof value == 'object') {\n        return isArray(value)\n          ? baseMatchesProperty(value[0], value[1])\n          : baseMatches(value);\n      }\n      return property(value);\n    }\n\n    /**\n     * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     */\n    function baseKeys(object) {\n      if (!isPrototype(object)) {\n        return nativeKeys(object);\n      }\n      var result = [];\n      for (var key in Object(object)) {\n        if (hasOwnProperty.call(object, key) && key != 'constructor') {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     */\n    function baseKeysIn(object) {\n      if (!isObject(object)) {\n        return nativeKeysIn(object);\n      }\n      var isProto = isPrototype(object),\n          result = [];\n\n      for (var key in object) {\n        if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.lt` which doesn't coerce arguments.\n     *\n     * @private\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`,\n     *  else `false`.\n     */\n    function baseLt(value, other) {\n      return value < other;\n    }\n\n    /**\n     * The base implementation of `_.map` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} 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 doesn't clone `source`.\n     *\n     * @private\n     * @param {Object} source The object of property values to match.\n     * @returns {Function} Returns the new spec function.\n     */\n    function baseMatches(source) {\n      var matchData = getMatchData(source);\n      if (matchData.length == 1 && matchData[0][2]) {\n        return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n      }\n      return function(object) {\n        return object === source || baseIsMatch(object, source, matchData);\n      };\n    }\n\n    /**\n     * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.\n     *\n     * @private\n     * @param {string} path The path of the property to get.\n     * @param {*} srcValue The value to match.\n     * @returns {Function} Returns the new spec function.\n     */\n    function baseMatchesProperty(path, srcValue) {\n      if (isKey(path) && isStrictComparable(srcValue)) {\n        return matchesStrictComparable(toKey(path), srcValue);\n      }\n      return function(object) {\n        var objValue = get(object, path);\n        return (objValue === undefined && objValue === srcValue)\n          ? hasIn(object, path)\n          : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);\n      };\n    }\n\n    /**\n     * The base implementation of `_.merge` without support for multiple sources.\n     *\n     * @private\n     * @param {Object} object The destination object.\n     * @param {Object} source The source object.\n     * @param {number} srcIndex The index of `source`.\n     * @param {Function} [customizer] The function to customize merged values.\n     * @param {Object} [stack] Tracks traversed source values and their merged\n     *  counterparts.\n     */\n    function baseMerge(object, source, srcIndex, customizer, stack) {\n      if (object === source) {\n        return;\n      }\n      baseFor(source, function(srcValue, key) {\n        stack || (stack = new Stack);\n        if (isObject(srcValue)) {\n          baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n        }\n        else {\n          var newValue = customizer\n            ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n            : undefined;\n\n          if (newValue === undefined) {\n            newValue = srcValue;\n          }\n          assignMergeValue(object, key, newValue);\n        }\n      }, keysIn);\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 {number} srcIndex The index of `source`.\n     * @param {Function} mergeFunc The function to merge values.\n     * @param {Function} [customizer] The function to customize assigned values.\n     * @param {Object} [stack] Tracks traversed source values and their merged\n     *  counterparts.\n     */\n    function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n      var objValue = safeGet(object, key),\n          srcValue = safeGet(source, key),\n          stacked = stack.get(srcValue);\n\n      if (stacked) {\n        assignMergeValue(object, key, stacked);\n        return;\n      }\n      var newValue = customizer\n        ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n        : undefined;\n\n      var isCommon = newValue === undefined;\n\n      if (isCommon) {\n        var isArr = isArray(srcValue),\n            isBuff = !isArr && isBuffer(srcValue),\n            isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n        newValue = srcValue;\n        if (isArr || isBuff || isTyped) {\n          if (isArray(objValue)) {\n            newValue = objValue;\n          }\n          else if (isArrayLikeObject(objValue)) {\n            newValue = copyArray(objValue);\n          }\n          else if (isBuff) {\n            isCommon = false;\n            newValue = cloneBuffer(srcValue, true);\n          }\n          else if (isTyped) {\n            isCommon = false;\n            newValue = cloneTypedArray(srcValue, true);\n          }\n          else {\n            newValue = [];\n          }\n        }\n        else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n          newValue = objValue;\n          if (isArguments(objValue)) {\n            newValue = toPlainObject(objValue);\n          }\n          else if (!isObject(objValue) || isFunction(objValue)) {\n            newValue = initCloneObject(srcValue);\n          }\n        }\n        else {\n          isCommon = false;\n        }\n      }\n      if (isCommon) {\n        // Recursively merge objects and arrays (susceptible to call stack limits).\n        stack.set(srcValue, newValue);\n        mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n        stack['delete'](srcValue);\n      }\n      assignMergeValue(object, key, newValue);\n    }\n\n    /**\n     * The base implementation of `_.nth` which doesn't coerce arguments.\n     *\n     * @private\n     * @param {Array} array The array to query.\n     * @param {number} n The index of the element to return.\n     * @returns {*} Returns the nth element of `array`.\n     */\n    function baseNth(array, n) {\n      var length = array.length;\n      if (!length) {\n        return;\n      }\n      n += n < 0 ? length : 0;\n      return isIndex(n, length) ? array[n] : undefined;\n    }\n\n    /**\n     * The base implementation of `_.orderBy` without param guards.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n     * @param {string[]} orders The sort orders of `iteratees`.\n     * @returns {Array} Returns the new sorted array.\n     */\n    function baseOrderBy(collection, iteratees, orders) {\n      if (iteratees.length) {\n        iteratees = arrayMap(iteratees, function(iteratee) {\n          if (isArray(iteratee)) {\n            return function(value) {\n              return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n            }\n          }\n          return iteratee;\n        });\n      } else {\n        iteratees = [identity];\n      }\n\n      var index = -1;\n      iteratees = arrayMap(iteratees, baseUnary(getIteratee()));\n\n      var result = baseMap(collection, function(value, key, collection) {\n        var criteria = arrayMap(iteratees, function(iteratee) {\n          return iteratee(value);\n        });\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 `_.pick` without support for individual\n     * property identifiers.\n     *\n     * @private\n     * @param {Object} object The source object.\n     * @param {string[]} paths The property paths to pick.\n     * @returns {Object} Returns the new object.\n     */\n    function basePick(object, paths) {\n      return basePickBy(object, paths, function(value, path) {\n        return hasIn(object, path);\n      });\n    }\n\n    /**\n     * The base implementation of  `_.pickBy` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Object} object The source object.\n     * @param {string[]} paths The property paths to pick.\n     * @param {Function} predicate The function invoked per property.\n     * @returns {Object} Returns the new object.\n     */\n    function basePickBy(object, paths, predicate) {\n      var index = -1,\n          length = paths.length,\n          result = {};\n\n      while (++index < length) {\n        var path = paths[index],\n            value = baseGet(object, path);\n\n        if (predicate(value, path)) {\n          baseSet(result, castPath(path, object), value);\n        }\n      }\n      return result;\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 accessor function.\n     */\n    function basePropertyDeep(path) {\n      return function(object) {\n        return baseGet(object, path);\n      };\n    }\n\n    /**\n     * The base implementation of `_.pullAllBy` without support for iteratee\n     * shorthands.\n     *\n     * @private\n     * @param {Array} array The array to modify.\n     * @param {Array} values The values to remove.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns `array`.\n     */\n    function basePullAll(array, values, iteratee, comparator) {\n      var indexOf = comparator ? baseIndexOfWith : baseIndexOf,\n          index = -1,\n          length = values.length,\n          seen = array;\n\n      if (array === values) {\n        values = copyArray(values);\n      }\n      if (iteratee) {\n        seen = arrayMap(array, baseUnary(iteratee));\n      }\n      while (++index < length) {\n        var fromIndex = 0,\n            value = values[index],\n            computed = iteratee ? iteratee(value) : value;\n\n        while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {\n          if (seen !== array) {\n            splice.call(seen, fromIndex, 1);\n          }\n          splice.call(array, fromIndex, 1);\n        }\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.pullAt` without support for individual\n     * indexes or 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          lastIndex = length - 1;\n\n      while (length--) {\n        var index = indexes[length];\n        if (length == lastIndex || index !== previous) {\n          var previous = index;\n          if (isIndex(index)) {\n            splice.call(array, index, 1);\n          } else {\n            baseUnset(array, index);\n          }\n        }\n      }\n      return array;\n    }\n\n    /**\n     * The base implementation of `_.random` without support for returning\n     * floating-point numbers.\n     *\n     * @private\n     * @param {number} lower The lower bound.\n     * @param {number} upper The upper bound.\n     * @returns {number} Returns the random number.\n     */\n    function baseRandom(lower, upper) {\n      return lower + nativeFloor(nativeRandom() * (upper - lower + 1));\n    }\n\n    /**\n     * The base implementation of `_.range` and `_.rangeRight` which doesn't\n     * coerce arguments.\n     *\n     * @private\n     * @param {number} start The start of the range.\n     * @param {number} end The end of the range.\n     * @param {number} step The value to increment or decrement by.\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Array} Returns the range of numbers.\n     */\n    function baseRange(start, end, step, fromRight) {\n      var index = -1,\n          length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),\n          result = Array(length);\n\n      while (length--) {\n        result[fromRight ? length : ++index] = start;\n        start += step;\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.repeat` which doesn't coerce arguments.\n     *\n     * @private\n     * @param {string} string The string to repeat.\n     * @param {number} n The number of times to repeat the string.\n     * @returns {string} Returns the repeated string.\n     */\n    function baseRepeat(string, n) {\n      var result = '';\n      if (!string || n < 1 || n > MAX_SAFE_INTEGER) {\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        if (n) {\n          string += string;\n        }\n      } while (n);\n\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n     *\n     * @private\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     */\n    function baseRest(func, start) {\n      return setToString(overRest(func, start, identity), func + '');\n    }\n\n    /**\n     * The base implementation of `_.sample`.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to sample.\n     * @returns {*} Returns the random element.\n     */\n    function baseSample(collection) {\n      return arraySample(values(collection));\n    }\n\n    /**\n     * The base implementation of `_.sampleSize` without param guards.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to sample.\n     * @param {number} n The number of elements to sample.\n     * @returns {Array} Returns the random elements.\n     */\n    function baseSampleSize(collection, n) {\n      var array = values(collection);\n      return shuffleSelf(array, baseClamp(n, 0, array.length));\n    }\n\n    /**\n     * The base implementation of `_.set`.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to set.\n     * @param {*} value The value to set.\n     * @param {Function} [customizer] The function to customize path creation.\n     * @returns {Object} Returns `object`.\n     */\n    function baseSet(object, path, value, customizer) {\n      if (!isObject(object)) {\n        return object;\n      }\n      path = castPath(path, object);\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 = toKey(path[index]),\n            newValue = value;\n\n        if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n          return object;\n        }\n\n        if (index != lastIndex) {\n          var objValue = nested[key];\n          newValue = customizer ? customizer(objValue, key, nested) : undefined;\n          if (newValue === undefined) {\n            newValue = isObject(objValue)\n              ? objValue\n              : (isIndex(path[index + 1]) ? [] : {});\n          }\n        }\n        assignValue(nested, key, newValue);\n        nested = nested[key];\n      }\n      return object;\n    }\n\n    /**\n     * The base implementation of `setData` without support for hot loop shorting.\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 `setToString` without support for hot loop shorting.\n     *\n     * @private\n     * @param {Function} func The function to modify.\n     * @param {Function} string The `toString` result.\n     * @returns {Function} Returns `func`.\n     */\n    var baseSetToString = !defineProperty ? identity : function(func, string) {\n      return defineProperty(func, 'toString', {\n        'configurable': true,\n        'enumerable': false,\n        'value': constant(string),\n        'writable': true\n      });\n    };\n\n    /**\n     * The base implementation of `_.shuffle`.\n     *\n     * @private\n     * @param {Array|Object} collection The collection to shuffle.\n     * @returns {Array} Returns the new shuffled array.\n     */\n    function baseShuffle(collection) {\n      return shuffleSelf(values(collection));\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      if (start < 0) {\n        start = -start > length ? 0 : (length + start);\n      }\n      end = end > length ? length : end;\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 iteratee shorthands.\n     *\n     * @private\n     * @param {Array|Object} 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 `_.sortedIndex` and `_.sortedLastIndex` which\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 baseSortedIndex(array, value, retHighest) {\n      var low = 0,\n          high = array == null ? low : array.length;\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 (computed !== null && !isSymbol(computed) &&\n              (retHighest ? (computed <= value) : (computed < value))) {\n            low = mid + 1;\n          } else {\n            high = mid;\n          }\n        }\n        return high;\n      }\n      return baseSortedIndexBy(array, value, identity, retHighest);\n    }\n\n    /**\n     * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`\n     * which invokes `iteratee` for `value` and each element of `array` to compute\n     * their sort ranking. The 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 iteratee invoked per element.\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 baseSortedIndexBy(array, value, iteratee, retHighest) {\n      var low = 0,\n          high = array == null ? 0 : array.length;\n      if (high === 0) {\n        return 0;\n      }\n\n      value = iteratee(value);\n      var valIsNaN = value !== value,\n          valIsNull = value === null,\n          valIsSymbol = isSymbol(value),\n          valIsUndefined = value === undefined;\n\n      while (low < high) {\n        var mid = nativeFloor((low + high) / 2),\n            computed = iteratee(array[mid]),\n            othIsDefined = computed !== undefined,\n            othIsNull = computed === null,\n            othIsReflexive = computed === computed,\n            othIsSymbol = isSymbol(computed);\n\n        if (valIsNaN) {\n          var setLow = retHighest || othIsReflexive;\n        } else if (valIsUndefined) {\n          setLow = othIsReflexive && (retHighest || othIsDefined);\n        } else if (valIsNull) {\n          setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);\n        } else if (valIsSymbol) {\n          setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);\n        } else if (othIsNull || othIsSymbol) {\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     * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without\n     * support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @returns {Array} Returns the new duplicate free array.\n     */\n    function baseSortedUniq(array, iteratee) {\n      var index = -1,\n          length = array.length,\n          resIndex = 0,\n          result = [];\n\n      while (++index < length) {\n        var value = array[index],\n            computed = iteratee ? iteratee(value) : value;\n\n        if (!index || !eq(computed, seen)) {\n          var seen = computed;\n          result[resIndex++] = value === 0 ? 0 : value;\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.toNumber` which doesn't ensure correct\n     * conversions of binary, hexadecimal, or octal string values.\n     *\n     * @private\n     * @param {*} value The value to process.\n     * @returns {number} Returns the number.\n     */\n    function baseToNumber(value) {\n      if (typeof value == 'number') {\n        return value;\n      }\n      if (isSymbol(value)) {\n        return NAN;\n      }\n      return +value;\n    }\n\n    /**\n     * The base implementation of `_.toString` which doesn't convert nullish\n     * values to empty strings.\n     *\n     * @private\n     * @param {*} value The value to process.\n     * @returns {string} Returns the string.\n     */\n    function baseToString(value) {\n      // Exit early for strings to avoid a performance hit in some environments.\n      if (typeof value == 'string') {\n        return value;\n      }\n      if (isArray(value)) {\n        // Recursively convert values (susceptible to call stack limits).\n        return arrayMap(value, baseToString) + '';\n      }\n      if (isSymbol(value)) {\n        return symbolToString ? symbolToString.call(value) : '';\n      }\n      var result = (value + '');\n      return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n    }\n\n    /**\n     * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new duplicate free array.\n     */\n    function baseUniq(array, iteratee, comparator) {\n      var index = -1,\n          includes = arrayIncludes,\n          length = array.length,\n          isCommon = true,\n          result = [],\n          seen = result;\n\n      if (comparator) {\n        isCommon = false;\n        includes = arrayIncludesWith;\n      }\n      else if (length >= LARGE_ARRAY_SIZE) {\n        var set = iteratee ? null : createSet(array);\n        if (set) {\n          return setToArray(set);\n        }\n        isCommon = false;\n        includes = cacheHas;\n        seen = new SetCache;\n      }\n      else {\n        seen = iteratee ? [] : result;\n      }\n      outer:\n      while (++index < length) {\n        var value = array[index],\n            computed = iteratee ? iteratee(value) : value;\n\n        value = (comparator || value !== 0) ? value : 0;\n        if (isCommon && computed === computed) {\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 (!includes(seen, computed, comparator)) {\n          if (seen !== result) {\n            seen.push(computed);\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * The base implementation of `_.unset`.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The property path to unset.\n     * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n     */\n    function baseUnset(object, path) {\n      path = castPath(path, object);\n      object = parent(object, path);\n      return object == null || delete object[toKey(last(path))];\n    }\n\n    /**\n     * The base implementation of `_.update`.\n     *\n     * @private\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to update.\n     * @param {Function} updater The function to produce the updated value.\n     * @param {Function} [customizer] The function to customize path creation.\n     * @returns {Object} Returns `object`.\n     */\n    function baseUpdate(object, path, updater, customizer) {\n      return baseSet(object, path, updater(baseGet(object, path)), customizer);\n    }\n\n    /**\n     * The base implementation of methods like `_.dropWhile` and `_.takeWhile`\n     * without support for iteratee shorthands.\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) &&\n        predicate(array[index], index, array)) {}\n\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 perform 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      return arrayReduce(actions, function(result, action) {\n        return action.func.apply(action.thisArg, arrayPush([result], action.args));\n      }, result);\n    }\n\n    /**\n     * The base implementation of methods like `_.xor`, without support for\n     * iteratee shorthands, that accepts an array of arrays to inspect.\n     *\n     * @private\n     * @param {Array} arrays The arrays to inspect.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of values.\n     */\n    function baseXor(arrays, iteratee, comparator) {\n      var length = arrays.length;\n      if (length < 2) {\n        return length ? baseUniq(arrays[0]) : [];\n      }\n      var index = -1,\n          result = Array(length);\n\n      while (++index < length) {\n        var array = arrays[index],\n            othIndex = -1;\n\n        while (++othIndex < length) {\n          if (othIndex != index) {\n            result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);\n          }\n        }\n      }\n      return baseUniq(baseFlatten(result, 1), iteratee, comparator);\n    }\n\n    /**\n     * This base implementation of `_.zipObject` which assigns values using `assignFunc`.\n     *\n     * @private\n     * @param {Array} props The property identifiers.\n     * @param {Array} values The property values.\n     * @param {Function} assignFunc The function to assign values.\n     * @returns {Object} Returns the new object.\n     */\n    function baseZipObject(props, values, assignFunc) {\n      var index = -1,\n          length = props.length,\n          valsLength = values.length,\n          result = {};\n\n      while (++index < length) {\n        var value = index < valsLength ? values[index] : undefined;\n        assignFunc(result, props[index], value);\n      }\n      return result;\n    }\n\n    /**\n     * Casts `value` to an empty array if it's not an array like object.\n     *\n     * @private\n     * @param {*} value The value to inspect.\n     * @returns {Array|Object} Returns the cast array-like object.\n     */\n    function castArrayLikeObject(value) {\n      return isArrayLikeObject(value) ? value : [];\n    }\n\n    /**\n     * Casts `value` to `identity` if it's not a function.\n     *\n     * @private\n     * @param {*} value The value to inspect.\n     * @returns {Function} Returns cast function.\n     */\n    function castFunction(value) {\n      return typeof value == 'function' ? value : identity;\n    }\n\n    /**\n     * Casts `value` to a path array if it's not one.\n     *\n     * @private\n     * @param {*} value The value to inspect.\n     * @param {Object} [object] The object to query keys on.\n     * @returns {Array} Returns the cast property path array.\n     */\n    function castPath(value, object) {\n      if (isArray(value)) {\n        return value;\n      }\n      return isKey(value, object) ? [value] : stringToPath(toString(value));\n    }\n\n    /**\n     * A `baseRest` alias which can be replaced with `identity` by module\n     * replacement plugins.\n     *\n     * @private\n     * @type {Function}\n     * @param {Function} func The function to apply a rest parameter to.\n     * @returns {Function} Returns the new function.\n     */\n    var castRest = baseRest;\n\n    /**\n     * Casts `array` to a slice if it's needed.\n     *\n     * @private\n     * @param {Array} array The array to inspect.\n     * @param {number} start The start position.\n     * @param {number} [end=array.length] The end position.\n     * @returns {Array} Returns the cast slice.\n     */\n    function castSlice(array, start, end) {\n      var length = array.length;\n      end = end === undefined ? length : end;\n      return (!start && end >= length) ? array : baseSlice(array, start, end);\n    }\n\n    /**\n     * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).\n     *\n     * @private\n     * @param {number|Object} id The timer id or timeout object of the timer to clear.\n     */\n    var clearTimeout = ctxClearTimeout || function(id) {\n      return root.clearTimeout(id);\n    };\n\n    /**\n     * Creates a clone of  `buffer`.\n     *\n     * @private\n     * @param {Buffer} buffer The buffer to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @returns {Buffer} Returns the cloned buffer.\n     */\n    function cloneBuffer(buffer, isDeep) {\n      if (isDeep) {\n        return buffer.slice();\n      }\n      var length = buffer.length,\n          result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n      buffer.copy(result);\n      return result;\n    }\n\n    /**\n     * Creates a clone of `arrayBuffer`.\n     *\n     * @private\n     * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n     * @returns {ArrayBuffer} Returns the cloned array buffer.\n     */\n    function cloneArrayBuffer(arrayBuffer) {\n      var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n      new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n      return result;\n    }\n\n    /**\n     * Creates a clone of `dataView`.\n     *\n     * @private\n     * @param {Object} dataView The data view to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @returns {Object} Returns the cloned data view.\n     */\n    function cloneDataView(dataView, isDeep) {\n      var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n      return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n    }\n\n    /**\n     * Creates a clone of `regexp`.\n     *\n     * @private\n     * @param {Object} regexp The regexp to clone.\n     * @returns {Object} Returns the cloned regexp.\n     */\n    function cloneRegExp(regexp) {\n      var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n      result.lastIndex = regexp.lastIndex;\n      return result;\n    }\n\n    /**\n     * Creates a clone of the `symbol` object.\n     *\n     * @private\n     * @param {Object} symbol The symbol object to clone.\n     * @returns {Object} Returns the cloned symbol object.\n     */\n    function cloneSymbol(symbol) {\n      return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n    }\n\n    /**\n     * Creates a clone of `typedArray`.\n     *\n     * @private\n     * @param {Object} typedArray The typed array to clone.\n     * @param {boolean} [isDeep] Specify a deep clone.\n     * @returns {Object} Returns the cloned typed array.\n     */\n    function cloneTypedArray(typedArray, isDeep) {\n      var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n      return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n    }\n\n    /**\n     * Compares values to sort them in ascending order.\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 compareAscending(value, other) {\n      if (value !== other) {\n        var valIsDefined = value !== undefined,\n            valIsNull = value === null,\n            valIsReflexive = value === value,\n            valIsSymbol = isSymbol(value);\n\n        var othIsDefined = other !== undefined,\n            othIsNull = other === null,\n            othIsReflexive = other === other,\n            othIsSymbol = isSymbol(other);\n\n        if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n            (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n            (valIsNull && othIsDefined && othIsReflexive) ||\n            (!valIsDefined && othIsReflexive) ||\n            !valIsReflexive) {\n          return 1;\n        }\n        if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n            (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n            (othIsNull && valIsDefined && valIsReflexive) ||\n            (!othIsDefined && valIsReflexive) ||\n            !othIsReflexive) {\n          return -1;\n        }\n      }\n      return 0;\n    }\n\n    /**\n     * Used by `_.orderBy` to compare multiple properties of a value to another\n     * and stable sort them.\n     *\n     * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n     * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n     * of corresponding values.\n     *\n     * @private\n     * @param {Object} object The object to compare.\n     * @param {Object} other The other object to compare.\n     * @param {boolean[]|string[]} 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 = compareAscending(objCriteria[index], othCriteria[index]);\n        if (result) {\n          if (index >= ordersLength) {\n            return result;\n          }\n          var order = orders[index];\n          return result * (order == 'desc' ? -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://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n      return object.index - other.index;\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} args The provided arguments.\n     * @param {Array} partials The arguments to prepend to those provided.\n     * @param {Array} holders The `partials` placeholder indexes.\n     * @params {boolean} [isCurried] Specify composing for a curried function.\n     * @returns {Array} Returns the new array of composed arguments.\n     */\n    function composeArgs(args, partials, holders, isCurried) {\n      var argsIndex = -1,\n          argsLength = args.length,\n          holdersLength = holders.length,\n          leftIndex = -1,\n          leftLength = partials.length,\n          rangeLength = nativeMax(argsLength - holdersLength, 0),\n          result = Array(leftLength + rangeLength),\n          isUncurried = !isCurried;\n\n      while (++leftIndex < leftLength) {\n        result[leftIndex] = partials[leftIndex];\n      }\n      while (++argsIndex < holdersLength) {\n        if (isUncurried || argsIndex < argsLength) {\n          result[holders[argsIndex]] = args[argsIndex];\n        }\n      }\n      while (rangeLength--) {\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} args The provided arguments.\n     * @param {Array} partials The arguments to append to those provided.\n     * @param {Array} holders The `partials` placeholder indexes.\n     * @params {boolean} [isCurried] Specify composing for a curried function.\n     * @returns {Array} Returns the new array of composed arguments.\n     */\n    function composeArgsRight(args, partials, holders, isCurried) {\n      var argsIndex = -1,\n          argsLength = args.length,\n          holdersIndex = -1,\n          holdersLength = holders.length,\n          rightIndex = -1,\n          rightLength = partials.length,\n          rangeLength = nativeMax(argsLength - holdersLength, 0),\n          result = Array(rangeLength + rightLength),\n          isUncurried = !isCurried;\n\n      while (++argsIndex < rangeLength) {\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        if (isUncurried || argsIndex < argsLength) {\n          result[offset + holders[holdersIndex]] = args[argsIndex++];\n        }\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 copyArray(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     * 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 identifiers to copy.\n     * @param {Object} [object={}] The object to copy properties to.\n     * @param {Function} [customizer] The function to customize copied values.\n     * @returns {Object} Returns `object`.\n     */\n    function copyObject(source, props, object, customizer) {\n      var isNew = !object;\n      object || (object = {});\n\n      var index = -1,\n          length = props.length;\n\n      while (++index < length) {\n        var key = props[index];\n\n        var newValue = customizer\n          ? customizer(object[key], source[key], key, object, source)\n          : undefined;\n\n        if (newValue === undefined) {\n          newValue = source[key];\n        }\n        if (isNew) {\n          baseAssignValue(object, key, newValue);\n        } else {\n          assignValue(object, key, newValue);\n        }\n      }\n      return object;\n    }\n\n    /**\n     * Copies own symbols of `source` to `object`.\n     *\n     * @private\n     * @param {Object} source The object to copy symbols from.\n     * @param {Object} [object={}] The object to copy symbols to.\n     * @returns {Object} Returns `object`.\n     */\n    function copySymbols(source, object) {\n      return copyObject(source, getSymbols(source), object);\n    }\n\n    /**\n     * Copies own and inherited symbols of `source` to `object`.\n     *\n     * @private\n     * @param {Object} source The object to copy symbols from.\n     * @param {Object} [object={}] The object to copy symbols to.\n     * @returns {Object} Returns `object`.\n     */\n    function copySymbolsIn(source, object) {\n      return copyObject(source, getSymbolsIn(source), object);\n    }\n\n    /**\n     * Creates a function like `_.groupBy`.\n     *\n     * @private\n     * @param {Function} setter The function to set accumulator values.\n     * @param {Function} [initializer] The accumulator object initializer.\n     * @returns {Function} Returns the new aggregator function.\n     */\n    function createAggregator(setter, initializer) {\n      return function(collection, iteratee) {\n        var func = isArray(collection) ? arrayAggregator : baseAggregator,\n            accumulator = initializer ? initializer() : {};\n\n        return func(collection, setter, getIteratee(iteratee, 2), accumulator);\n      };\n    }\n\n    /**\n     * Creates a function like `_.assign`.\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 baseRest(function(object, sources) {\n        var index = -1,\n            length = sources.length,\n            customizer = length > 1 ? sources[length - 1] : undefined,\n            guard = length > 2 ? sources[2] : undefined;\n\n        customizer = (assigner.length > 3 && typeof customizer == 'function')\n          ? (length--, customizer)\n          : undefined;\n\n        if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n          customizer = length < 3 ? undefined : customizer;\n          length = 1;\n        }\n        object = Object(object);\n        while (++index < length) {\n          var source = sources[index];\n          if (source) {\n            assigner(object, source, index, 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        if (collection == null) {\n          return collection;\n        }\n        if (!isArrayLike(collection)) {\n          return eachFunc(collection, iteratee);\n        }\n        var length = collection.length,\n            index = fromRight ? length : -1,\n            iterable = Object(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 methods like `_.forIn` and `_.forOwn`.\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 index = -1,\n            iterable = Object(object),\n            props = keysFunc(object),\n            length = props.length;\n\n        while (length--) {\n          var key = props[fromRight ? length : ++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` to invoke it with the optional `this`\n     * binding of `thisArg`.\n     *\n     * @private\n     * @param {Function} func The function to wrap.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createBind(func, bitmask, thisArg) {\n      var isBind = bitmask & WRAP_BIND_FLAG,\n          Ctor = createCtor(func);\n\n      function wrapper() {\n        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n        return fn.apply(isBind ? thisArg : this, arguments);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a function like `_.lowerFirst`.\n     *\n     * @private\n     * @param {string} methodName The name of the `String` case method to use.\n     * @returns {Function} Returns the new case function.\n     */\n    function createCaseFirst(methodName) {\n      return function(string) {\n        string = toString(string);\n\n        var strSymbols = hasUnicode(string)\n          ? stringToArray(string)\n          : undefined;\n\n        var chr = strSymbols\n          ? strSymbols[0]\n          : string.charAt(0);\n\n        var trailing = strSymbols\n          ? castSlice(strSymbols, 1).join('')\n          : string.slice(1);\n\n        return chr[methodName]() + trailing;\n      };\n    }\n\n    /**\n     * Creates a function like `_.camelCase`.\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        return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\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 createCtor(Ctor) {\n      return function() {\n        // Use a `switch` statement to work with class constructors. See\n        // http://ecma-international.org/ecma-262/7.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 function that wraps `func` to enable currying.\n     *\n     * @private\n     * @param {Function} func The function to wrap.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @param {number} arity The arity of `func`.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createCurry(func, bitmask, arity) {\n      var Ctor = createCtor(func);\n\n      function wrapper() {\n        var length = arguments.length,\n            args = Array(length),\n            index = length,\n            placeholder = getHolder(wrapper);\n\n        while (index--) {\n          args[index] = arguments[index];\n        }\n        var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)\n          ? []\n          : replaceHolders(args, placeholder);\n\n        length -= holders.length;\n        if (length < arity) {\n          return createRecurry(\n            func, bitmask, createHybrid, wrapper.placeholder, undefined,\n            args, holders, undefined, undefined, arity - length);\n        }\n        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n        return apply(fn, this, args);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a `_.find` or `_.findLast` function.\n     *\n     * @private\n     * @param {Function} findIndexFunc The function to find the collection index.\n     * @returns {Function} Returns the new find function.\n     */\n    function createFind(findIndexFunc) {\n      return function(collection, predicate, fromIndex) {\n        var iterable = Object(collection);\n        if (!isArrayLike(collection)) {\n          var iteratee = getIteratee(predicate, 3);\n          collection = keys(collection);\n          predicate = function(key) { return iteratee(iterable[key], key, iterable); };\n        }\n        var index = findIndexFunc(collection, predicate, fromIndex);\n        return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;\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 flatRest(function(funcs) {\n        var length = funcs.length,\n            index = length,\n            prereq = LodashWrapper.prototype.thru;\n\n        if (fromRight) {\n          funcs.reverse();\n        }\n        while (index--) {\n          var func = funcs[index];\n          if (typeof func != 'function') {\n            throw new TypeError(FUNC_ERROR_TEXT);\n          }\n          if (prereq && !wrapper && getFuncName(func) == 'wrapper') {\n            var wrapper = new LodashWrapper([], true);\n          }\n        }\n        index = wrapper ? index : 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]) &&\n                data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&\n                !data[4].length && data[9] == 1\n              ) {\n            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);\n          } else {\n            wrapper = (func.length == 1 && isLaziable(func))\n              ? wrapper[funcName]()\n              : 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)) {\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 that wraps `func` to invoke it with optional `this`\n     * binding of `thisArg`, partial application, and currying.\n     *\n     * @private\n     * @param {Function|string} func The function or method name to wrap.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param {Array} [partials] The arguments to prepend to those provided to\n     *  the new function.\n     * @param {Array} [holders] The `partials` placeholder indexes.\n     * @param {Array} [partialsRight] The arguments to append to those provided\n     *  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 createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {\n      var isAry = bitmask & WRAP_ARY_FLAG,\n          isBind = bitmask & WRAP_BIND_FLAG,\n          isBindKey = bitmask & WRAP_BIND_KEY_FLAG,\n          isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),\n          isFlip = bitmask & WRAP_FLIP_FLAG,\n          Ctor = isBindKey ? undefined : createCtor(func);\n\n      function wrapper() {\n        var length = arguments.length,\n            args = Array(length),\n            index = length;\n\n        while (index--) {\n          args[index] = arguments[index];\n        }\n        if (isCurried) {\n          var placeholder = getHolder(wrapper),\n              holdersCount = countHolders(args, placeholder);\n        }\n        if (partials) {\n          args = composeArgs(args, partials, holders, isCurried);\n        }\n        if (partialsRight) {\n          args = composeArgsRight(args, partialsRight, holdersRight, isCurried);\n        }\n        length -= holdersCount;\n        if (isCurried && length < arity) {\n          var newHolders = replaceHolders(args, placeholder);\n          return createRecurry(\n            func, bitmask, createHybrid, wrapper.placeholder, thisArg,\n            args, newHolders, argPos, ary, arity - length\n          );\n        }\n        var thisBinding = isBind ? thisArg : this,\n            fn = isBindKey ? thisBinding[func] : func;\n\n        length = args.length;\n        if (argPos) {\n          args = reorder(args, argPos);\n        } else if (isFlip && length > 1) {\n          args.reverse();\n        }\n        if (isAry && ary < length) {\n          args.length = ary;\n        }\n        if (this && this !== root && this instanceof wrapper) {\n          fn = Ctor || createCtor(fn);\n        }\n        return fn.apply(thisBinding, args);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a function like `_.invertBy`.\n     *\n     * @private\n     * @param {Function} setter The function to set accumulator values.\n     * @param {Function} toIteratee The function to resolve iteratees.\n     * @returns {Function} Returns the new inverter function.\n     */\n    function createInverter(setter, toIteratee) {\n      return function(object, iteratee) {\n        return baseInverter(object, setter, toIteratee(iteratee), {});\n      };\n    }\n\n    /**\n     * Creates a function that performs a mathematical operation on two values.\n     *\n     * @private\n     * @param {Function} operator The function to perform the operation.\n     * @param {number} [defaultValue] The value used for `undefined` arguments.\n     * @returns {Function} Returns the new mathematical operation function.\n     */\n    function createMathOperation(operator, defaultValue) {\n      return function(value, other) {\n        var result;\n        if (value === undefined && other === undefined) {\n          return defaultValue;\n        }\n        if (value !== undefined) {\n          result = value;\n        }\n        if (other !== undefined) {\n          if (result === undefined) {\n            return other;\n          }\n          if (typeof value == 'string' || typeof other == 'string') {\n            value = baseToString(value);\n            other = baseToString(other);\n          } else {\n            value = baseToNumber(value);\n            other = baseToNumber(other);\n          }\n          result = operator(value, other);\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function like `_.over`.\n     *\n     * @private\n     * @param {Function} arrayFunc The function to iterate over iteratees.\n     * @returns {Function} Returns the new over function.\n     */\n    function createOver(arrayFunc) {\n      return flatRest(function(iteratees) {\n        iteratees = arrayMap(iteratees, baseUnary(getIteratee()));\n        return baseRest(function(args) {\n          var thisArg = this;\n          return arrayFunc(iteratees, function(iteratee) {\n            return apply(iteratee, thisArg, args);\n          });\n        });\n      });\n    }\n\n    /**\n     * Creates the padding for `string` based on `length`. The `chars` string\n     * is truncated if the number of characters exceeds `length`.\n     *\n     * @private\n     * @param {number} length The padding length.\n     * @param {string} [chars=' '] The string used as padding.\n     * @returns {string} Returns the padding for `string`.\n     */\n    function createPadding(length, chars) {\n      chars = chars === undefined ? ' ' : baseToString(chars);\n\n      var charsLength = chars.length;\n      if (charsLength < 2) {\n        return charsLength ? baseRepeat(chars, length) : chars;\n      }\n      var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));\n      return hasUnicode(chars)\n        ? castSlice(stringToArray(result), 0, length).join('')\n        : result.slice(0, length);\n    }\n\n    /**\n     * Creates a function that wraps `func` to invoke it with the `this` binding\n     * of `thisArg` and `partials` prepended to the arguments it receives.\n     *\n     * @private\n     * @param {Function} func The function to wrap.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @param {*} thisArg The `this` binding of `func`.\n     * @param {Array} partials The arguments to prepend to those provided to\n     *  the new function.\n     * @returns {Function} Returns the new wrapped function.\n     */\n    function createPartial(func, bitmask, thisArg, partials) {\n      var isBind = bitmask & WRAP_BIND_FLAG,\n          Ctor = createCtor(func);\n\n      function wrapper() {\n        var argsIndex = -1,\n            argsLength = arguments.length,\n            leftIndex = -1,\n            leftLength = partials.length,\n            args = Array(leftLength + argsLength),\n            fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n\n        while (++leftIndex < leftLength) {\n          args[leftIndex] = partials[leftIndex];\n        }\n        while (argsLength--) {\n          args[leftIndex++] = arguments[++argsIndex];\n        }\n        return apply(fn, isBind ? thisArg : this, args);\n      }\n      return wrapper;\n    }\n\n    /**\n     * Creates a `_.range` or `_.rangeRight` function.\n     *\n     * @private\n     * @param {boolean} [fromRight] Specify iterating from right to left.\n     * @returns {Function} Returns the new range function.\n     */\n    function createRange(fromRight) {\n      return function(start, end, step) {\n        if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {\n          end = step = undefined;\n        }\n        // Ensure the sign of `-0` is preserved.\n        start = toFinite(start);\n        if (end === undefined) {\n          end = start;\n          start = 0;\n        } else {\n          end = toFinite(end);\n        }\n        step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);\n        return baseRange(start, end, step, fromRight);\n      };\n    }\n\n    /**\n     * Creates a function that performs a relational operation on two values.\n     *\n     * @private\n     * @param {Function} operator The function to perform the operation.\n     * @returns {Function} Returns the new relational operation function.\n     */\n    function createRelationalOperation(operator) {\n      return function(value, other) {\n        if (!(typeof value == 'string' && typeof other == 'string')) {\n          value = toNumber(value);\n          other = toNumber(other);\n        }\n        return operator(value, other);\n      };\n    }\n\n    /**\n     * Creates a function that wraps `func` to continue currying.\n     *\n     * @private\n     * @param {Function} func The function to wrap.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @param {Function} wrapFunc The function to create the `func` wrapper.\n     * @param {*} placeholder The placeholder value.\n     * @param {*} [thisArg] The `this` binding of `func`.\n     * @param {Array} [partials] The arguments to prepend to those provided to\n     *  the new function.\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 createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {\n      var isCurry = bitmask & WRAP_CURRY_FLAG,\n          newHolders = isCurry ? holders : undefined,\n          newHoldersRight = isCurry ? undefined : holders,\n          newPartials = isCurry ? partials : undefined,\n          newPartialsRight = isCurry ? undefined : partials;\n\n      bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);\n      bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);\n\n      if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {\n        bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);\n      }\n      var newData = [\n        func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,\n        newHoldersRight, argPos, ary, arity\n      ];\n\n      var result = wrapFunc.apply(undefined, newData);\n      if (isLaziable(func)) {\n        setData(result, newData);\n      }\n      result.placeholder = placeholder;\n      return setWrapToString(result, func, bitmask);\n    }\n\n    /**\n     * Creates a function like `_.round`.\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        number = toNumber(number);\n        precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);\n        if (precision && nativeIsFinite(number)) {\n          // Shift with exponential notation to avoid floating-point issues.\n          // See [MDN](https://mdn.io/round#Examples) for more details.\n          var pair = (toString(number) + 'e').split('e'),\n              value = func(pair[0] + 'e' + (+pair[1] + precision));\n\n          pair = (toString(value) + 'e').split('e');\n          return +(pair[0] + 'e' + (+pair[1] - precision));\n        }\n        return func(number);\n      };\n    }\n\n    /**\n     * Creates a set object of `values`.\n     *\n     * @private\n     * @param {Array} values The values to add to the set.\n     * @returns {Object} Returns the new set.\n     */\n    var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n      return new Set(values);\n    };\n\n    /**\n     * Creates a `_.toPairs` or `_.toPairsIn` function.\n     *\n     * @private\n     * @param {Function} keysFunc The function to get the keys of a given object.\n     * @returns {Function} Returns the new pairs function.\n     */\n    function createToPairs(keysFunc) {\n      return function(object) {\n        var tag = getTag(object);\n        if (tag == mapTag) {\n          return mapToArray(object);\n        }\n        if (tag == setTag) {\n          return setToPairs(object);\n        }\n        return baseToPairs(object, keysFunc(object));\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 wrap.\n     * @param {number} bitmask The bitmask 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     *  512 - `_.flip`\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 createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {\n      var isBindKey = bitmask & WRAP_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 &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);\n        partials = holders = undefined;\n      }\n      ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);\n      arity = arity === undefined ? arity : toInteger(arity);\n      length -= holders ? holders.length : 0;\n\n      if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {\n        var partialsRight = partials,\n            holdersRight = holders;\n\n        partials = holders = undefined;\n      }\n      var data = isBindKey ? undefined : getData(func);\n\n      var newData = [\n        func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,\n        argPos, ary, arity\n      ];\n\n      if (data) {\n        mergeData(newData, data);\n      }\n      func = newData[0];\n      bitmask = newData[1];\n      thisArg = newData[2];\n      partials = newData[3];\n      holders = newData[4];\n      arity = newData[9] = newData[9] === undefined\n        ? (isBindKey ? 0 : func.length)\n        : nativeMax(newData[9] - length, 0);\n\n      if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {\n        bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);\n      }\n      if (!bitmask || bitmask == WRAP_BIND_FLAG) {\n        var result = createBind(func, bitmask, thisArg);\n      } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {\n        result = createCurry(func, bitmask, arity);\n      } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {\n        result = createPartial(func, bitmask, thisArg, partials);\n      } else {\n        result = createHybrid.apply(undefined, newData);\n      }\n      var setter = data ? baseSetData : setData;\n      return setWrapToString(setter(result, newData), func, bitmask);\n    }\n\n    /**\n     * Used by `_.defaults` to customize its `_.assignIn` use to assign properties\n     * of source objects to the destination object for all destination properties\n     * that resolve to `undefined`.\n     *\n     * @private\n     * @param {*} objValue The destination value.\n     * @param {*} srcValue The source value.\n     * @param {string} key The key of the property to assign.\n     * @param {Object} object The parent object of `objValue`.\n     * @returns {*} Returns the value to assign.\n     */\n    function customDefaultsAssignIn(objValue, srcValue, key, object) {\n      if (objValue === undefined ||\n          (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n        return srcValue;\n      }\n      return objValue;\n    }\n\n    /**\n     * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source\n     * objects into destination objects that are passed thru.\n     *\n     * @private\n     * @param {*} objValue The destination value.\n     * @param {*} srcValue The source value.\n     * @param {string} key The key of the property to merge.\n     * @param {Object} object The parent object of `objValue`.\n     * @param {Object} source The parent object of `srcValue`.\n     * @param {Object} [stack] Tracks traversed source values and their merged\n     *  counterparts.\n     * @returns {*} Returns the value to assign.\n     */\n    function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n      if (isObject(objValue) && isObject(srcValue)) {\n        // Recursively merge objects and arrays (susceptible to call stack limits).\n        stack.set(srcValue, objValue);\n        baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n        stack['delete'](srcValue);\n      }\n      return objValue;\n    }\n\n    /**\n     * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain\n     * objects.\n     *\n     * @private\n     * @param {*} value The value to inspect.\n     * @param {string} key The key of the property to inspect.\n     * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.\n     */\n    function customOmitClone(value) {\n      return isPlainObject(value) ? undefined : value;\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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n     * @param {Function} customizer The function to customize comparisons.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Object} stack Tracks traversed `array` and `other` objects.\n     * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n     */\n    function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n      var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n          arrLength = array.length,\n          othLength = other.length;\n\n      if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n        return false;\n      }\n      // Check that cyclic values are equal.\n      var arrStacked = stack.get(array);\n      var othStacked = stack.get(other);\n      if (arrStacked && othStacked) {\n        return arrStacked == other && othStacked == array;\n      }\n      var index = -1,\n          result = true,\n          seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n      stack.set(array, other);\n      stack.set(other, array);\n\n      // Ignore non-index properties.\n      while (++index < arrLength) {\n        var arrValue = array[index],\n            othValue = other[index];\n\n        if (customizer) {\n          var compared = isPartial\n            ? customizer(othValue, arrValue, index, other, array, stack)\n            : customizer(arrValue, othValue, index, array, other, stack);\n        }\n        if (compared !== undefined) {\n          if (compared) {\n            continue;\n          }\n          result = false;\n          break;\n        }\n        // Recursively compare arrays (susceptible to call stack limits).\n        if (seen) {\n          if (!arraySome(other, function(othValue, othIndex) {\n                if (!cacheHas(seen, othIndex) &&\n                    (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n                  return seen.push(othIndex);\n                }\n              })) {\n            result = false;\n            break;\n          }\n        } else if (!(\n              arrValue === othValue ||\n                equalFunc(arrValue, othValue, bitmask, customizer, stack)\n            )) {\n          result = false;\n          break;\n        }\n      }\n      stack['delete'](array);\n      stack['delete'](other);\n      return result;\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     * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n     * @param {Function} customizer The function to customize comparisons.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Object} stack Tracks traversed `object` and `other` objects.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n      switch (tag) {\n        case dataViewTag:\n          if ((object.byteLength != other.byteLength) ||\n              (object.byteOffset != other.byteOffset)) {\n            return false;\n          }\n          object = object.buffer;\n          other = other.buffer;\n\n        case arrayBufferTag:\n          if ((object.byteLength != other.byteLength) ||\n              !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n            return false;\n          }\n          return true;\n\n        case boolTag:\n        case dateTag:\n        case numberTag:\n          // Coerce booleans to `1` or `0` and dates to milliseconds.\n          // Invalid dates are coerced to `NaN`.\n          return eq(+object, +other);\n\n        case errorTag:\n          return object.name == other.name && object.message == other.message;\n\n        case regexpTag:\n        case stringTag:\n          // Coerce regexes to strings and treat strings, primitives and objects,\n          // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n          // for more details.\n          return object == (other + '');\n\n        case mapTag:\n          var convert = mapToArray;\n\n        case setTag:\n          var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n          convert || (convert = setToArray);\n\n          if (object.size != other.size && !isPartial) {\n            return false;\n          }\n          // Assume cyclic values are equal.\n          var stacked = stack.get(object);\n          if (stacked) {\n            return stacked == other;\n          }\n          bitmask |= COMPARE_UNORDERED_FLAG;\n\n          // Recursively compare objects (susceptible to call stack limits).\n          stack.set(object, other);\n          var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n          stack['delete'](object);\n          return result;\n\n        case symbolTag:\n          if (symbolValueOf) {\n            return symbolValueOf.call(object) == symbolValueOf.call(other);\n          }\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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n     * @param {Function} customizer The function to customize comparisons.\n     * @param {Function} equalFunc The function to determine equivalents of values.\n     * @param {Object} stack Tracks traversed `object` and `other` objects.\n     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n     */\n    function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n      var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n          objProps = getAllKeys(object),\n          objLength = objProps.length,\n          othProps = getAllKeys(other),\n          othLength = othProps.length;\n\n      if (objLength != othLength && !isPartial) {\n        return false;\n      }\n      var index = objLength;\n      while (index--) {\n        var key = objProps[index];\n        if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n          return false;\n        }\n      }\n      // Check that cyclic values are equal.\n      var objStacked = stack.get(object);\n      var othStacked = stack.get(other);\n      if (objStacked && othStacked) {\n        return objStacked == other && othStacked == object;\n      }\n      var result = true;\n      stack.set(object, other);\n      stack.set(other, object);\n\n      var skipCtor = isPartial;\n      while (++index < objLength) {\n        key = objProps[index];\n        var objValue = object[key],\n            othValue = other[key];\n\n        if (customizer) {\n          var compared = isPartial\n            ? customizer(othValue, objValue, key, other, object, stack)\n            : customizer(objValue, othValue, key, object, other, stack);\n        }\n        // Recursively compare objects (susceptible to call stack limits).\n        if (!(compared === undefined\n              ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n              : compared\n            )) {\n          result = false;\n          break;\n        }\n        skipCtor || (skipCtor = key == 'constructor');\n      }\n      if (result && !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          result = false;\n        }\n      }\n      stack['delete'](object);\n      stack['delete'](other);\n      return result;\n    }\n\n    /**\n     * A specialized version of `baseRest` which flattens the rest array.\n     *\n     * @private\n     * @param {Function} func The function to apply a rest parameter to.\n     * @returns {Function} Returns the new function.\n     */\n    function flatRest(func) {\n      return setToString(overRest(func, undefined, flatten), func + '');\n    }\n\n    /**\n     * Creates an array of own enumerable property names and symbols of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names and symbols.\n     */\n    function getAllKeys(object) {\n      return baseGetAllKeys(object, keys, getSymbols);\n    }\n\n    /**\n     * Creates an array of own and inherited enumerable property names and\n     * symbols of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names and symbols.\n     */\n    function getAllKeysIn(object) {\n      return baseGetAllKeys(object, keysIn, getSymbolsIn);\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 = hasOwnProperty.call(realNames, result) ? 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 argument placeholder value for `func`.\n     *\n     * @private\n     * @param {Function} func The function to inspect.\n     * @returns {*} Returns the placeholder value.\n     */\n    function getHolder(func) {\n      var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;\n      return object.placeholder;\n    }\n\n    /**\n     * Gets the appropriate \"iteratee\" function. If `_.iteratee` is customized,\n     * this function returns the custom method, otherwise it returns `baseIteratee`.\n     * If arguments are provided, the chosen function is invoked with them and\n     * its result is returned.\n     *\n     * @private\n     * @param {*} [value] The value to convert to an iteratee.\n     * @param {number} [arity] The arity of the created iteratee.\n     * @returns {Function} Returns the chosen function or its result.\n     */\n    function getIteratee() {\n      var result = lodash.iteratee || iteratee;\n      result = result === iteratee ? baseIteratee : result;\n      return arguments.length ? result(arguments[0], arguments[1]) : result;\n    }\n\n    /**\n     * Gets the data for `map`.\n     *\n     * @private\n     * @param {Object} map The map to query.\n     * @param {string} key The reference key.\n     * @returns {*} Returns the map data.\n     */\n    function getMapData(map, key) {\n      var data = map.__data__;\n      return isKeyable(key)\n        ? data[typeof key == 'string' ? 'string' : 'hash']\n        : data.map;\n    }\n\n    /**\n     * Gets the property 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 = keys(object),\n          length = result.length;\n\n      while (length--) {\n        var key = result[length],\n            value = object[key];\n\n        result[length] = [key, value, isStrictComparable(value)];\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 = getValue(object, key);\n      return baseIsNative(value) ? value : undefined;\n    }\n\n    /**\n     * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n     *\n     * @private\n     * @param {*} value The value to query.\n     * @returns {string} Returns the raw `toStringTag`.\n     */\n    function getRawTag(value) {\n      var isOwn = hasOwnProperty.call(value, symToStringTag),\n          tag = value[symToStringTag];\n\n      try {\n        value[symToStringTag] = undefined;\n        var unmasked = true;\n      } catch (e) {}\n\n      var result = nativeObjectToString.call(value);\n      if (unmasked) {\n        if (isOwn) {\n          value[symToStringTag] = tag;\n        } else {\n          delete value[symToStringTag];\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array of the own enumerable symbols of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of symbols.\n     */\n    var getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n      if (object == null) {\n        return [];\n      }\n      object = Object(object);\n      return arrayFilter(nativeGetSymbols(object), function(symbol) {\n        return propertyIsEnumerable.call(object, symbol);\n      });\n    };\n\n    /**\n     * Creates an array of the own and inherited enumerable symbols of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of symbols.\n     */\n    var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n      var result = [];\n      while (object) {\n        arrayPush(result, getSymbols(object));\n        object = getPrototype(object);\n      }\n      return result;\n    };\n\n    /**\n     * Gets the `toStringTag` of `value`.\n     *\n     * @private\n     * @param {*} value The value to query.\n     * @returns {string} Returns the `toStringTag`.\n     */\n    var getTag = baseGetTag;\n\n    // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\n    if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n        (Map && getTag(new Map) != mapTag) ||\n        (Promise && getTag(Promise.resolve()) != promiseTag) ||\n        (Set && getTag(new Set) != setTag) ||\n        (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n      getTag = function(value) {\n        var result = baseGetTag(value),\n            Ctor = result == objectTag ? value.constructor : undefined,\n            ctorString = Ctor ? toSource(Ctor) : '';\n\n        if (ctorString) {\n          switch (ctorString) {\n            case dataViewCtorString: return dataViewTag;\n            case mapCtorString: return mapTag;\n            case promiseCtorString: return promiseTag;\n            case setCtorString: return setTag;\n            case weakMapCtorString: return weakMapTag;\n          }\n        }\n        return result;\n      };\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     * Extracts wrapper details from the `source` body comment.\n     *\n     * @private\n     * @param {string} source The source to inspect.\n     * @returns {Array} Returns the wrapper details.\n     */\n    function getWrapDetails(source) {\n      var match = source.match(reWrapDetails);\n      return match ? match[1].split(reSplitDetails) : [];\n    }\n\n    /**\n     * Checks if `path` exists on `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path to check.\n     * @param {Function} hasFunc The function to check properties.\n     * @returns {boolean} Returns `true` if `path` exists, else `false`.\n     */\n    function hasPath(object, path, hasFunc) {\n      path = castPath(path, object);\n\n      var index = -1,\n          length = path.length,\n          result = false;\n\n      while (++index < length) {\n        var key = toKey(path[index]);\n        if (!(result = object != null && hasFunc(object, key))) {\n          break;\n        }\n        object = object[key];\n      }\n      if (result || ++index != length) {\n        return result;\n      }\n      length = object == null ? 0 : object.length;\n      return !!length && isLength(length) && isIndex(key, length) &&\n        (isArray(object) || isArguments(object));\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 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      return (typeof object.constructor == 'function' && !isPrototype(object))\n        ? baseCreate(getPrototype(object))\n        : {};\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`, `Map`, `Number`, `RegExp`, `Set`, 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 cloneArrayBuffer(object);\n\n        case boolTag:\n        case dateTag:\n          return new Ctor(+object);\n\n        case dataViewTag:\n          return cloneDataView(object, isDeep);\n\n        case float32Tag: case float64Tag:\n        case int8Tag: case int16Tag: case int32Tag:\n        case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n          return cloneTypedArray(object, isDeep);\n\n        case mapTag:\n          return new Ctor;\n\n        case numberTag:\n        case stringTag:\n          return new Ctor(object);\n\n        case regexpTag:\n          return cloneRegExp(object);\n\n        case setTag:\n          return new Ctor;\n\n        case symbolTag:\n          return cloneSymbol(object);\n      }\n    }\n\n    /**\n     * Inserts wrapper `details` in a comment at the top of the `source` body.\n     *\n     * @private\n     * @param {string} source The source to modify.\n     * @returns {Array} details The details to insert.\n     * @returns {string} Returns the modified source.\n     */\n    function insertWrapDetails(source, details) {\n      var length = details.length;\n      if (!length) {\n        return source;\n      }\n      var lastIndex = length - 1;\n      details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];\n      details = details.join(length > 2 ? ', ' : ' ');\n      return source.replace(reWrapComment, '{\\n/* [wrapped with ' + details + '] */\\n');\n    }\n\n    /**\n     * Checks if `value` is a flattenable `arguments` object or array.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n     */\n    function isFlattenable(value) {\n      return isArray(value) || isArguments(value) ||\n        !!(spreadableSymbol && value && value[spreadableSymbol]);\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      var type = typeof value;\n      length = length == null ? MAX_SAFE_INTEGER : length;\n\n      return !!length &&\n        (type == 'number' ||\n          (type != 'symbol' && reIsUint.test(value))) &&\n            (value > -1 && value % 1 == 0 && value < length);\n    }\n\n    /**\n     * Checks if the given 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,\n     *  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          ) {\n        return eq(object[index], value);\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      if (isArray(value)) {\n        return false;\n      }\n      var type = typeof value;\n      if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n          value == null || isSymbol(value)) {\n        return true;\n      }\n      return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n        (object != null && value in Object(object));\n    }\n\n    /**\n     * Checks if `value` is suitable for use as unique object key.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n     */\n    function isKeyable(value) {\n      var type = typeof value;\n      return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n        ? (value !== '__proto__')\n        : (value === null);\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,\n     *  else `false`.\n     */\n    function isLaziable(func) {\n      var funcName = getFuncName(func),\n          other = lodash[funcName];\n\n      if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {\n        return false;\n      }\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 `func` has its source masked.\n     *\n     * @private\n     * @param {Function} func The function to check.\n     * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n     */\n    function isMasked(func) {\n      return !!maskSrcKey && (maskSrcKey in func);\n    }\n\n    /**\n     * Checks if `func` is capable of being masked.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `func` is maskable, else `false`.\n     */\n    var isMaskable = coreJsData ? isFunction : stubFalse;\n\n    /**\n     * Checks if `value` is likely a prototype object.\n     *\n     * @private\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n     */\n    function isPrototype(value) {\n      var Ctor = value && value.constructor,\n          proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n      return value === proto;\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     * A specialized version of `matchesProperty` for source values suitable\n     * for strict equality comparisons, i.e. `===`.\n     *\n     * @private\n     * @param {string} key The key of the property to get.\n     * @param {*} srcValue The value to match.\n     * @returns {Function} Returns the new spec function.\n     */\n    function matchesStrictComparable(key, srcValue) {\n      return function(object) {\n        if (object == null) {\n          return false;\n        }\n        return object[key] === srcValue &&\n          (srcValue !== undefined || (key in Object(object)));\n      };\n    }\n\n    /**\n     * A specialized version of `_.memoize` which clears the memoized function's\n     * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n     *\n     * @private\n     * @param {Function} func The function to have its output memoized.\n     * @returns {Function} Returns the new memoized function.\n     */\n    function memoizeCapped(func) {\n      var result = memoize(func, function(key) {\n        if (cache.size === MAX_MEMOIZE_SIZE) {\n          cache.clear();\n        }\n        return key;\n      });\n\n      var cache = result.cache;\n      return result;\n    }\n\n    /**\n     * Merges the function metadata of `source` into `data`.\n     *\n     * Merging metadata reduces the number of wrappers used 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\n     * `_.rearg` modify function arguments, making the order in which they are\n     * executed important, preventing the merging of metadata. However, we make\n     * an exception for a safe combined case where curried functions have `_.ary`\n     * 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 < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);\n\n      var isCombo =\n        ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||\n        ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||\n        ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_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 & WRAP_BIND_FLAG) {\n        data[2] = source[2];\n        // Set when currying a bound function.\n        newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_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]) : value;\n        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : 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]) : value;\n        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];\n      }\n      // Use source `argPos` if available.\n      value = source[7];\n      if (value) {\n        data[7] = value;\n      }\n      // Use source `ary` if it's smaller.\n      if (srcBitmask & WRAP_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     * This function is like\n     * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n     * except that it includes inherited enumerable properties.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the array of property names.\n     */\n    function nativeKeysIn(object) {\n      var result = [];\n      if (object != null) {\n        for (var key in Object(object)) {\n          result.push(key);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Converts `value` to a string using `Object.prototype.toString`.\n     *\n     * @private\n     * @param {*} value The value to convert.\n     * @returns {string} Returns the converted string.\n     */\n    function objectToString(value) {\n      return nativeObjectToString.call(value);\n    }\n\n    /**\n     * A specialized version of `baseRest` which transforms the rest array.\n     *\n     * @private\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     * @param {Function} transform The rest array transform.\n     * @returns {Function} Returns the new function.\n     */\n    function overRest(func, start, transform) {\n      start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n      return function() {\n        var args = arguments,\n            index = -1,\n            length = nativeMax(args.length - start, 0),\n            array = Array(length);\n\n        while (++index < length) {\n          array[index] = args[start + index];\n        }\n        index = -1;\n        var otherArgs = Array(start + 1);\n        while (++index < start) {\n          otherArgs[index] = args[index];\n        }\n        otherArgs[start] = transform(array);\n        return apply(func, this, otherArgs);\n      };\n    }\n\n    /**\n     * Gets the parent value at `path` of `object`.\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {Array} path The path to get the parent value of.\n     * @returns {*} Returns the parent value.\n     */\n    function parent(object, path) {\n      return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));\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 = copyArray(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     * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n     *\n     * @private\n     * @param {Object} object The object to query.\n     * @param {string} key The key of the property to get.\n     * @returns {*} Returns the property value.\n     */\n    function safeGet(object, key) {\n      if (key === 'constructor' && typeof object[key] === 'function') {\n        return;\n      }\n\n      if (key == '__proto__') {\n        return;\n      }\n\n      return object[key];\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\n     * function to avoid garbage collection pauses in V8. See\n     * [V8 issue 2070](https://bugs.chromium.org/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 = shortOut(baseSetData);\n\n    /**\n     * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).\n     *\n     * @private\n     * @param {Function} func The function to delay.\n     * @param {number} wait The number of milliseconds to delay invocation.\n     * @returns {number|Object} Returns the timer id or timeout object.\n     */\n    var setTimeout = ctxSetTimeout || function(func, wait) {\n      return root.setTimeout(func, wait);\n    };\n\n    /**\n     * Sets the `toString` method of `func` to return `string`.\n     *\n     * @private\n     * @param {Function} func The function to modify.\n     * @param {Function} string The `toString` result.\n     * @returns {Function} Returns `func`.\n     */\n    var setToString = shortOut(baseSetToString);\n\n    /**\n     * Sets the `toString` method of `wrapper` to mimic the source of `reference`\n     * with wrapper details in a comment at the top of the source body.\n     *\n     * @private\n     * @param {Function} wrapper The function to modify.\n     * @param {Function} reference The reference function.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @returns {Function} Returns `wrapper`.\n     */\n    function setWrapToString(wrapper, reference, bitmask) {\n      var source = (reference + '');\n      return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));\n    }\n\n    /**\n     * Creates a function that'll short out and invoke `identity` instead\n     * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n     * milliseconds.\n     *\n     * @private\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new shortable function.\n     */\n    function shortOut(func) {\n      var count = 0,\n          lastCalled = 0;\n\n      return function() {\n        var stamp = nativeNow(),\n            remaining = HOT_SPAN - (stamp - lastCalled);\n\n        lastCalled = stamp;\n        if (remaining > 0) {\n          if (++count >= HOT_COUNT) {\n            return arguments[0];\n          }\n        } else {\n          count = 0;\n        }\n        return func.apply(undefined, arguments);\n      };\n    }\n\n    /**\n     * A specialized version of `_.shuffle` which mutates and sets the size of `array`.\n     *\n     * @private\n     * @param {Array} array The array to shuffle.\n     * @param {number} [size=array.length] The size of `array`.\n     * @returns {Array} Returns `array`.\n     */\n    function shuffleSelf(array, size) {\n      var index = -1,\n          length = array.length,\n          lastIndex = length - 1;\n\n      size = size === undefined ? length : size;\n      while (++index < size) {\n        var rand = baseRandom(index, lastIndex),\n            value = array[rand];\n\n        array[rand] = array[index];\n        array[index] = value;\n      }\n      array.length = size;\n      return array;\n    }\n\n    /**\n     * Converts `string` to a property path array.\n     *\n     * @private\n     * @param {string} string The string to convert.\n     * @returns {Array} Returns the property path array.\n     */\n    var stringToPath = memoizeCapped(function(string) {\n      var result = [];\n      if (string.charCodeAt(0) === 46 /* . */) {\n        result.push('');\n      }\n      string.replace(rePropName, function(match, number, quote, subString) {\n        result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n      });\n      return result;\n    });\n\n    /**\n     * Converts `value` to a string key if it's not a string or symbol.\n     *\n     * @private\n     * @param {*} value The value to inspect.\n     * @returns {string|symbol} Returns the key.\n     */\n    function toKey(value) {\n      if (typeof value == 'string' || isSymbol(value)) {\n        return value;\n      }\n      var result = (value + '');\n      return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n    }\n\n    /**\n     * Converts `func` to its source code.\n     *\n     * @private\n     * @param {Function} func The function to convert.\n     * @returns {string} Returns the source code.\n     */\n    function toSource(func) {\n      if (func != null) {\n        try {\n          return funcToString.call(func);\n        } catch (e) {}\n        try {\n          return (func + '');\n        } catch (e) {}\n      }\n      return '';\n    }\n\n    /**\n     * Updates wrapper `details` based on `bitmask` flags.\n     *\n     * @private\n     * @returns {Array} details The details to modify.\n     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n     * @returns {Array} Returns `details`.\n     */\n    function updateWrapDetails(details, bitmask) {\n      arrayEach(wrapFlags, function(pair) {\n        var value = '_.' + pair[0];\n        if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {\n          details.push(value);\n        }\n      });\n      return details.sort();\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      if (wrapper instanceof LazyWrapper) {\n        return wrapper.clone();\n      }\n      var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);\n      result.__actions__ = copyArray(wrapper.__actions__);\n      result.__index__  = wrapper.__index__;\n      result.__values__ = wrapper.__values__;\n      return result;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array of elements split into groups the length of `size`.\n     * If `array` can't be split evenly, the final chunk will be the remaining\n     * elements.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods like `_.map`.\n     * @returns {Array} Returns the new array of 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 === undefined)) {\n        size = 1;\n      } else {\n        size = nativeMax(toInteger(size), 0);\n      }\n      var length = array == null ? 0 : array.length;\n      if (!length || size < 1) {\n        return [];\n      }\n      var index = 0,\n          resIndex = 0,\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     * @since 0.1.0\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 == null ? 0 : array.length,\n          resIndex = 0,\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 a new array concatenating `array` with any additional arrays\n     * and/or values.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to concatenate.\n     * @param {...*} [values] The values to concatenate.\n     * @returns {Array} Returns the new concatenated array.\n     * @example\n     *\n     * var array = [1];\n     * var other = _.concat(array, 2, [3], [[4]]);\n     *\n     * console.log(other);\n     * // => [1, 2, 3, [4]]\n     *\n     * console.log(array);\n     * // => [1]\n     */\n    function concat() {\n      var length = arguments.length;\n      if (!length) {\n        return [];\n      }\n      var args = Array(length - 1),\n          array = arguments[0],\n          index = length;\n\n      while (index--) {\n        args[index - 1] = arguments[index];\n      }\n      return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));\n    }\n\n    /**\n     * Creates an array of `array` values not included in the other given arrays\n     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons. The order and references of result values are\n     * determined by the first array.\n     *\n     * **Note:** Unlike `_.pullAll`, this method returns a new array.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\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     * @see _.without, _.xor\n     * @example\n     *\n     * _.difference([2, 1], [2, 3]);\n     * // => [1]\n     */\n    var difference = baseRest(function(array, values) {\n      return isArrayLikeObject(array)\n        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))\n        : [];\n    });\n\n    /**\n     * This method is like `_.difference` except that it accepts `iteratee` which\n     * is invoked for each element of `array` and `values` to generate the criterion\n     * by which they're compared. The order and references of result values are\n     * determined by the first array. The iteratee is invoked with one argument:\n     * (value).\n     *\n     * **Note:** Unlike `_.pullAllBy`, this method returns a new array.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {...Array} [values] The values to exclude.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n     * // => [1.2]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');\n     * // => [{ 'x': 2 }]\n     */\n    var differenceBy = baseRest(function(array, values) {\n      var iteratee = last(values);\n      if (isArrayLikeObject(iteratee)) {\n        iteratee = undefined;\n      }\n      return isArrayLikeObject(array)\n        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))\n        : [];\n    });\n\n    /**\n     * This method is like `_.difference` except that it accepts `comparator`\n     * which is invoked to compare elements of `array` to `values`. The order and\n     * references of result values are determined by the first array. The comparator\n     * is invoked with two arguments: (arrVal, othVal).\n     *\n     * **Note:** Unlike `_.pullAllWith`, this method returns a new array.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {...Array} [values] The values to exclude.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n     *\n     * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);\n     * // => [{ 'x': 2, 'y': 1 }]\n     */\n    var differenceWith = baseRest(function(array, values) {\n      var comparator = last(values);\n      if (isArrayLikeObject(comparator)) {\n        comparator = undefined;\n      }\n      return isArrayLikeObject(array)\n        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)\n        : [];\n    });\n\n    /**\n     * Creates a slice of `array` with `n` elements dropped from the beginning.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.5.0\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 an iteratee for methods 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 == null ? 0 : array.length;\n      if (!length) {\n        return [];\n      }\n      n = (guard || n === undefined) ? 1 : toInteger(n);\n      return baseSlice(array, n < 0 ? 0 : n, length);\n    }\n\n    /**\n     * Creates a slice of `array` with `n` elements dropped from the end.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods 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 == null ? 0 : array.length;\n      if (!length) {\n        return [];\n      }\n      n = (guard || n === undefined) ? 1 : toInteger(n);\n      n = length - n;\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     * invoked with three arguments: (value, index, array).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': true },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': false }\n     * ];\n     *\n     * _.dropRightWhile(users, function(o) { return !o.active; });\n     * // => objects for ['barney']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });\n     * // => objects for ['barney', 'fred']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.dropRightWhile(users, ['active', false]);\n     * // => objects for ['barney']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.dropRightWhile(users, 'active');\n     * // => objects for ['barney', 'fred', 'pebbles']\n     */\n    function dropRightWhile(array, predicate) {\n      return (array && array.length)\n        ? baseWhile(array, getIteratee(predicate, 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     * invoked with three arguments: (value, index, array).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': false },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': true }\n     * ];\n     *\n     * _.dropWhile(users, function(o) { return !o.active; });\n     * // => objects for ['pebbles']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.dropWhile(users, { 'user': 'barney', 'active': false });\n     * // => objects for ['fred', 'pebbles']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.dropWhile(users, ['active', false]);\n     * // => objects for ['pebbles']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.dropWhile(users, 'active');\n     * // => objects for ['barney', 'fred', 'pebbles']\n     */\n    function dropWhile(array, predicate) {\n      return (array && array.length)\n        ? baseWhile(array, getIteratee(predicate, 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     * @since 3.2.0\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, 10], '*', 1, 3);\n     * // => [4, '*', '*', 10]\n     */\n    function fill(array, value, start, end) {\n      var length = array == null ? 0 : array.length;\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     * @static\n     * @memberOf _\n     * @since 1.1.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param {number} [fromIndex=0] The index to search from.\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(o) { return o.user == 'barney'; });\n     * // => 0\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.findIndex(users, { 'user': 'fred', 'active': false });\n     * // => 1\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.findIndex(users, ['active', false]);\n     * // => 0\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.findIndex(users, 'active');\n     * // => 2\n     */\n    function findIndex(array, predicate, fromIndex) {\n      var length = array == null ? 0 : array.length;\n      if (!length) {\n        return -1;\n      }\n      var index = fromIndex == null ? 0 : toInteger(fromIndex);\n      if (index < 0) {\n        index = nativeMax(length + index, 0);\n      }\n      return baseFindIndex(array, getIteratee(predicate, 3), index);\n    }\n\n    /**\n     * This method is like `_.findIndex` except that it iterates over elements\n     * of `collection` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param {number} [fromIndex=array.length-1] The index to search from.\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(o) { return o.user == 'pebbles'; });\n     * // => 2\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.findLastIndex(users, { 'user': 'barney', 'active': true });\n     * // => 0\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.findLastIndex(users, ['active', false]);\n     * // => 2\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.findLastIndex(users, 'active');\n     * // => 0\n     */\n    function findLastIndex(array, predicate, fromIndex) {\n      var length = array == null ? 0 : array.length;\n      if (!length) {\n        return -1;\n      }\n      var index = length - 1;\n      if (fromIndex !== undefined) {\n        index = toInteger(fromIndex);\n        index = fromIndex < 0\n          ? nativeMax(length + index, 0)\n          : nativeMin(index, length - 1);\n      }\n      return baseFindIndex(array, getIteratee(predicate, 3), index, true);\n    }\n\n    /**\n     * Flattens `array` a single level deep.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The array to flatten.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * _.flatten([1, [2, [3, [4]], 5]]);\n     * // => [1, 2, [3, [4]], 5]\n     */\n    function flatten(array) {\n      var length = array == null ? 0 : array.length;\n      return length ? baseFlatten(array, 1) : [];\n    }\n\n    /**\n     * Recursively flattens `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to flatten.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * _.flattenDeep([1, [2, [3, [4]], 5]]);\n     * // => [1, 2, 3, 4, 5]\n     */\n    function flattenDeep(array) {\n      var length = array == null ? 0 : array.length;\n      return length ? baseFlatten(array, INFINITY) : [];\n    }\n\n    /**\n     * Recursively flatten `array` up to `depth` times.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.4.0\n     * @category Array\n     * @param {Array} array The array to flatten.\n     * @param {number} [depth=1] The maximum recursion depth.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * var array = [1, [2, [3, [4]], 5]];\n     *\n     * _.flattenDepth(array, 1);\n     * // => [1, 2, [3, [4]], 5]\n     *\n     * _.flattenDepth(array, 2);\n     * // => [1, 2, 3, [4], 5]\n     */\n    function flattenDepth(array, depth) {\n      var length = array == null ? 0 : array.length;\n      if (!length) {\n        return [];\n      }\n      depth = depth === undefined ? 1 : toInteger(depth);\n      return baseFlatten(array, depth);\n    }\n\n    /**\n     * The inverse of `_.toPairs`; this method returns an object composed\n     * from key-value `pairs`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} pairs The key-value pairs.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * _.fromPairs([['a', 1], ['b', 2]]);\n     * // => { 'a': 1, 'b': 2 }\n     */\n    function fromPairs(pairs) {\n      var index = -1,\n          length = pairs == null ? 0 : pairs.length,\n          result = {};\n\n      while (++index < length) {\n        var pair = pairs[index];\n        result[pair[0]] = pair[1];\n      }\n      return result;\n    }\n\n    /**\n     * Gets the first element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @alias first\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {*} Returns the first element of `array`.\n     * @example\n     *\n     * _.head([1, 2, 3]);\n     * // => 1\n     *\n     * _.head([]);\n     * // => undefined\n     */\n    function head(array) {\n      return (array && array.length) ? array[0] : undefined;\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/7.0/#sec-samevaluezero)\n     * for equality comparisons. If `fromIndex` is negative, it's used as the\n     * offset from the end of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {*} value The value to search for.\n     * @param {number} [fromIndex=0] The index to search from.\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     * // Search from the `fromIndex`.\n     * _.indexOf([1, 2, 1, 2], 2, 2);\n     * // => 3\n     */\n    function indexOf(array, value, fromIndex) {\n      var length = array == null ? 0 : array.length;\n      if (!length) {\n        return -1;\n      }\n      var index = fromIndex == null ? 0 : toInteger(fromIndex);\n      if (index < 0) {\n        index = nativeMax(length + index, 0);\n      }\n      return baseIndexOf(array, value, index);\n    }\n\n    /**\n     * Gets all but the last element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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      var length = array == null ? 0 : array.length;\n      return length ? baseSlice(array, 0, -1) : [];\n    }\n\n    /**\n     * Creates an array of unique values that are included in all given arrays\n     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons. The order and references of result values are\n     * determined by the first array.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @returns {Array} Returns the new array of intersecting values.\n     * @example\n     *\n     * _.intersection([2, 1], [2, 3]);\n     * // => [2]\n     */\n    var intersection = baseRest(function(arrays) {\n      var mapped = arrayMap(arrays, castArrayLikeObject);\n      return (mapped.length && mapped[0] === arrays[0])\n        ? baseIntersection(mapped)\n        : [];\n    });\n\n    /**\n     * This method is like `_.intersection` except that it accepts `iteratee`\n     * which is invoked for each element of each `arrays` to generate the criterion\n     * by which they're compared. The order and references of result values are\n     * determined by the first array. The iteratee is invoked with one argument:\n     * (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns the new array of intersecting values.\n     * @example\n     *\n     * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n     * // => [2.1]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 1 }]\n     */\n    var intersectionBy = baseRest(function(arrays) {\n      var iteratee = last(arrays),\n          mapped = arrayMap(arrays, castArrayLikeObject);\n\n      if (iteratee === last(mapped)) {\n        iteratee = undefined;\n      } else {\n        mapped.pop();\n      }\n      return (mapped.length && mapped[0] === arrays[0])\n        ? baseIntersection(mapped, getIteratee(iteratee, 2))\n        : [];\n    });\n\n    /**\n     * This method is like `_.intersection` except that it accepts `comparator`\n     * which is invoked to compare elements of `arrays`. The order and references\n     * of result values are determined by the first array. The comparator is\n     * invoked with two arguments: (arrVal, othVal).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of intersecting values.\n     * @example\n     *\n     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n     *\n     * _.intersectionWith(objects, others, _.isEqual);\n     * // => [{ 'x': 1, 'y': 2 }]\n     */\n    var intersectionWith = baseRest(function(arrays) {\n      var comparator = last(arrays),\n          mapped = arrayMap(arrays, castArrayLikeObject);\n\n      comparator = typeof comparator == 'function' ? comparator : undefined;\n      if (comparator) {\n        mapped.pop();\n      }\n      return (mapped.length && mapped[0] === arrays[0])\n        ? baseIntersection(mapped, undefined, comparator)\n        : [];\n    });\n\n    /**\n     * Converts all elements in `array` into a string separated by `separator`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to convert.\n     * @param {string} [separator=','] The element separator.\n     * @returns {string} Returns the joined string.\n     * @example\n     *\n     * _.join(['a', 'b', 'c'], '~');\n     * // => 'a~b~c'\n     */\n    function join(array, separator) {\n      return array == null ? '' : nativeJoin.call(array, separator);\n    }\n\n    /**\n     * Gets the last element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 == null ? 0 : array.length;\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     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {*} value The value to search for.\n     * @param {number} [fromIndex=array.length-1] The index to search from.\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     * // Search from the `fromIndex`.\n     * _.lastIndexOf([1, 2, 1, 2], 2, 2);\n     * // => 1\n     */\n    function lastIndexOf(array, value, fromIndex) {\n      var length = array == null ? 0 : array.length;\n      if (!length) {\n        return -1;\n      }\n      var index = length;\n      if (fromIndex !== undefined) {\n        index = toInteger(fromIndex);\n        index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);\n      }\n      return value === value\n        ? strictLastIndexOf(array, value, index)\n        : baseFindIndex(array, baseIsNaN, index, true);\n    }\n\n    /**\n     * Gets the element at index `n` of `array`. If `n` is negative, the nth\n     * element from the end is returned.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.11.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {number} [n=0] The index of the element to return.\n     * @returns {*} Returns the nth element of `array`.\n     * @example\n     *\n     * var array = ['a', 'b', 'c', 'd'];\n     *\n     * _.nth(array, 1);\n     * // => 'b'\n     *\n     * _.nth(array, -2);\n     * // => 'c';\n     */\n    function nth(array, n) {\n      return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;\n    }\n\n    /**\n     * Removes all given values from `array` using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`\n     * to remove elements from an array by predicate.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\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 = ['a', 'b', 'c', 'a', 'b', 'c'];\n     *\n     * _.pull(array, 'a', 'c');\n     * console.log(array);\n     * // => ['b', 'b']\n     */\n    var pull = baseRest(pullAll);\n\n    /**\n     * This method is like `_.pull` except that it accepts an array of values to remove.\n     *\n     * **Note:** Unlike `_.difference`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {Array} values The values to remove.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n     *\n     * _.pullAll(array, ['a', 'c']);\n     * console.log(array);\n     * // => ['b', 'b']\n     */\n    function pullAll(array, values) {\n      return (array && array.length && values && values.length)\n        ? basePullAll(array, values)\n        : array;\n    }\n\n    /**\n     * This method is like `_.pullAll` except that it accepts `iteratee` which is\n     * invoked for each element of `array` and `values` to generate the criterion\n     * by which they're compared. The iteratee is invoked with one argument: (value).\n     *\n     * **Note:** Unlike `_.differenceBy`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {Array} values The values to remove.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];\n     *\n     * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');\n     * console.log(array);\n     * // => [{ 'x': 2 }]\n     */\n    function pullAllBy(array, values, iteratee) {\n      return (array && array.length && values && values.length)\n        ? basePullAll(array, values, getIteratee(iteratee, 2))\n        : array;\n    }\n\n    /**\n     * This method is like `_.pullAll` except that it accepts `comparator` which\n     * is invoked to compare elements of `array` to `values`. The comparator is\n     * invoked with two arguments: (arrVal, othVal).\n     *\n     * **Note:** Unlike `_.differenceWith`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.6.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {Array} values The values to remove.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];\n     *\n     * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);\n     * console.log(array);\n     * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]\n     */\n    function pullAllWith(array, values, comparator) {\n      return (array && array.length && values && values.length)\n        ? basePullAll(array, values, undefined, comparator)\n        : array;\n    }\n\n    /**\n     * Removes elements from `array` corresponding to `indexes` and returns an\n     * array of removed elements.\n     *\n     * **Note:** Unlike `_.at`, this method mutates `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {...(number|number[])} [indexes] The indexes of elements to remove.\n     * @returns {Array} Returns the new array of removed elements.\n     * @example\n     *\n     * var array = ['a', 'b', 'c', 'd'];\n     * var pulled = _.pullAt(array, [1, 3]);\n     *\n     * console.log(array);\n     * // => ['a', 'c']\n     *\n     * console.log(pulled);\n     * // => ['b', 'd']\n     */\n    var pullAt = flatRest(function(array, indexes) {\n      var length = array == null ? 0 : array.length,\n          result = baseAt(array, indexes);\n\n      basePullAt(array, arrayMap(indexes, function(index) {\n        return isIndex(index, length) ? +index : index;\n      }).sort(compareAscending));\n\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 invoked\n     * with three arguments: (value, index, array).\n     *\n     * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`\n     * to pull elements from an array by value.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\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) {\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 = getIteratee(predicate, 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     * Reverses `array` so that the first element becomes the last, the second\n     * element becomes the second to last, and so on.\n     *\n     * **Note:** This method mutates `array` and is based on\n     * [`Array#reverse`](https://mdn.io/Array/reverse).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to modify.\n     * @returns {Array} Returns `array`.\n     * @example\n     *\n     * var array = [1, 2, 3];\n     *\n     * _.reverse(array);\n     * // => [3, 2, 1]\n     *\n     * console.log(array);\n     * // => [3, 2, 1]\n     */\n    function reverse(array) {\n      return array == null ? array : nativeReverse.call(array);\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\n     * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are\n     * returned.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 == null ? 0 : array.length;\n      if (!length) {\n        return [];\n      }\n      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {\n        start = 0;\n        end = length;\n      }\n      else {\n        start = start == null ? 0 : toInteger(start);\n        end = end === undefined ? length : toInteger(end);\n      }\n      return baseSlice(array, start, end);\n    }\n\n    /**\n     * Uses a binary search to determine the lowest index at which `value`\n     * should be inserted into `array` in order to maintain its sort order.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\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    function sortedIndex(array, value) {\n      return baseSortedIndex(array, value);\n    }\n\n    /**\n     * This method is like `_.sortedIndex` except that it accepts `iteratee`\n     * which is invoked for `value` and each element of `array` to compute their\n     * sort ranking. The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     * @example\n     *\n     * var objects = [{ 'x': 4 }, { 'x': 5 }];\n     *\n     * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n     * // => 0\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.sortedIndexBy(objects, { 'x': 4 }, 'x');\n     * // => 0\n     */\n    function sortedIndexBy(array, value, iteratee) {\n      return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));\n    }\n\n    /**\n     * This method is like `_.indexOf` except that it performs a binary\n     * search on a sorted `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {*} value The value to search for.\n     * @returns {number} Returns the index of the matched value, else `-1`.\n     * @example\n     *\n     * _.sortedIndexOf([4, 5, 5, 5, 6], 5);\n     * // => 1\n     */\n    function sortedIndexOf(array, value) {\n      var length = array == null ? 0 : array.length;\n      if (length) {\n        var index = baseSortedIndex(array, value);\n        if (index < length && eq(array[index], value)) {\n          return index;\n        }\n      }\n      return -1;\n    }\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     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     * @example\n     *\n     * _.sortedLastIndex([4, 5, 5, 5, 6], 5);\n     * // => 4\n     */\n    function sortedLastIndex(array, value) {\n      return baseSortedIndex(array, value, true);\n    }\n\n    /**\n     * This method is like `_.sortedLastIndex` except that it accepts `iteratee`\n     * which is invoked for `value` and each element of `array` to compute their\n     * sort ranking. The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The sorted array to inspect.\n     * @param {*} value The value to evaluate.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {number} Returns the index at which `value` should be inserted\n     *  into `array`.\n     * @example\n     *\n     * var objects = [{ 'x': 4 }, { 'x': 5 }];\n     *\n     * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n     * // => 1\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');\n     * // => 1\n     */\n    function sortedLastIndexBy(array, value, iteratee) {\n      return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);\n    }\n\n    /**\n     * This method is like `_.lastIndexOf` except that it performs a binary\n     * search on a sorted `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {*} value The value to search for.\n     * @returns {number} Returns the index of the matched value, else `-1`.\n     * @example\n     *\n     * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);\n     * // => 3\n     */\n    function sortedLastIndexOf(array, value) {\n      var length = array == null ? 0 : array.length;\n      if (length) {\n        var index = baseSortedIndex(array, value, true) - 1;\n        if (eq(array[index], value)) {\n          return index;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * This method is like `_.uniq` except that it's designed and optimized\n     * for sorted arrays.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @returns {Array} Returns the new duplicate free array.\n     * @example\n     *\n     * _.sortedUniq([1, 1, 2]);\n     * // => [1, 2]\n     */\n    function sortedUniq(array) {\n      return (array && array.length)\n        ? baseSortedUniq(array)\n        : [];\n    }\n\n    /**\n     * This method is like `_.uniqBy` except that it's designed and optimized\n     * for sorted arrays.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {Function} [iteratee] The iteratee invoked per element.\n     * @returns {Array} Returns the new duplicate free array.\n     * @example\n     *\n     * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);\n     * // => [1.1, 2.3]\n     */\n    function sortedUniqBy(array, iteratee) {\n      return (array && array.length)\n        ? baseSortedUniq(array, getIteratee(iteratee, 2))\n        : [];\n    }\n\n    /**\n     * Gets all but the first element of `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * _.tail([1, 2, 3]);\n     * // => [2, 3]\n     */\n    function tail(array) {\n      var length = array == null ? 0 : array.length;\n      return length ? baseSlice(array, 1, length) : [];\n    }\n\n    /**\n     * Creates a slice of `array` with `n` elements taken from the beginning.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 an iteratee for methods 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      if (!(array && array.length)) {\n        return [];\n      }\n      n = (guard || n === undefined) ? 1 : toInteger(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     * @since 3.0.0\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 an iteratee for methods 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 == null ? 0 : array.length;\n      if (!length) {\n        return [];\n      }\n      n = (guard || n === undefined) ? 1 : toInteger(n);\n      n = length - n;\n      return baseSlice(array, n < 0 ? 0 : n, length);\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 invoked with\n     * three arguments: (value, index, array).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': true },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': false }\n     * ];\n     *\n     * _.takeRightWhile(users, function(o) { return !o.active; });\n     * // => objects for ['fred', 'pebbles']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });\n     * // => objects for ['pebbles']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.takeRightWhile(users, ['active', false]);\n     * // => objects for ['fred', 'pebbles']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.takeRightWhile(users, 'active');\n     * // => []\n     */\n    function takeRightWhile(array, predicate) {\n      return (array && array.length)\n        ? baseWhile(array, getIteratee(predicate, 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 invoked with\n     * three arguments: (value, index, array).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Array\n     * @param {Array} array The array to query.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the slice of `array`.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney',  'active': false },\n     *   { 'user': 'fred',    'active': false },\n     *   { 'user': 'pebbles', 'active': true }\n     * ];\n     *\n     * _.takeWhile(users, function(o) { return !o.active; });\n     * // => objects for ['barney', 'fred']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.takeWhile(users, { 'user': 'barney', 'active': false });\n     * // => objects for ['barney']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.takeWhile(users, ['active', false]);\n     * // => objects for ['barney', 'fred']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.takeWhile(users, 'active');\n     * // => []\n     */\n    function takeWhile(array, predicate) {\n      return (array && array.length)\n        ? baseWhile(array, getIteratee(predicate, 3))\n        : [];\n    }\n\n    /**\n     * Creates an array of unique values, in order, from all given arrays using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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([2], [1, 2]);\n     * // => [2, 1]\n     */\n    var union = baseRest(function(arrays) {\n      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));\n    });\n\n    /**\n     * This method is like `_.union` except that it accepts `iteratee` which is\n     * invoked for each element of each `arrays` to generate the criterion by\n     * which uniqueness is computed. Result values are chosen from the first\n     * array in which the value occurs. The iteratee is invoked with one argument:\n     * (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns the new array of combined values.\n     * @example\n     *\n     * _.unionBy([2.1], [1.2, 2.3], Math.floor);\n     * // => [2.1, 1.2]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 1 }, { 'x': 2 }]\n     */\n    var unionBy = baseRest(function(arrays) {\n      var iteratee = last(arrays);\n      if (isArrayLikeObject(iteratee)) {\n        iteratee = undefined;\n      }\n      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));\n    });\n\n    /**\n     * This method is like `_.union` except that it accepts `comparator` which\n     * is invoked to compare elements of `arrays`. Result values are chosen from\n     * the first array in which the value occurs. The comparator is invoked\n     * with two arguments: (arrVal, othVal).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of combined values.\n     * @example\n     *\n     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n     *\n     * _.unionWith(objects, others, _.isEqual);\n     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n     */\n    var unionWith = baseRest(function(arrays) {\n      var comparator = last(arrays);\n      comparator = typeof comparator == 'function' ? comparator : undefined;\n      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);\n    });\n\n    /**\n     * Creates a duplicate-free version of an array, using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons, in which only the first occurrence of each element\n     * is kept. The order of result values is determined by the order they occur\n     * in the array.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @returns {Array} Returns the new duplicate free array.\n     * @example\n     *\n     * _.uniq([2, 1, 2]);\n     * // => [2, 1]\n     */\n    function uniq(array) {\n      return (array && array.length) ? baseUniq(array) : [];\n    }\n\n    /**\n     * This method is like `_.uniq` except that it accepts `iteratee` which is\n     * invoked for each element in `array` to generate the criterion by which\n     * uniqueness is computed. The order of result values is determined by the\n     * order they occur in the array. The iteratee is invoked with one argument:\n     * (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns the new duplicate free array.\n     * @example\n     *\n     * _.uniqBy([2.1, 1.2, 2.3], Math.floor);\n     * // => [2.1, 1.2]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 1 }, { 'x': 2 }]\n     */\n    function uniqBy(array, iteratee) {\n      return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];\n    }\n\n    /**\n     * This method is like `_.uniq` except that it accepts `comparator` which\n     * is invoked to compare elements of `array`. The order of result values is\n     * determined by the order they occur in the array.The comparator is invoked\n     * with two arguments: (arrVal, othVal).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new duplicate free array.\n     * @example\n     *\n     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n     *\n     * _.uniqWith(objects, _.isEqual);\n     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n     */\n    function uniqWith(array, comparator) {\n      comparator = typeof comparator == 'function' ? comparator : undefined;\n      return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\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     * @since 1.2.0\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(['a', 'b'], [1, 2], [true, false]);\n     * // => [['a', 1, true], ['b', 2, false]]\n     *\n     * _.unzip(zipped);\n     * // => [['a', 'b'], [1, 2], [true, false]]\n     */\n    function unzip(array) {\n      if (!(array && array.length)) {\n        return [];\n      }\n      var length = 0;\n      array = arrayFilter(array, function(group) {\n        if (isArrayLikeObject(group)) {\n          length = nativeMax(group.length, length);\n          return true;\n        }\n      });\n      return baseTimes(length, function(index) {\n        return arrayMap(array, baseProperty(index));\n      });\n    }\n\n    /**\n     * This method is like `_.unzip` except that it accepts `iteratee` to specify\n     * how regrouped values should be combined. The iteratee is invoked with the\n     * elements of each group: (...group).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.8.0\n     * @category Array\n     * @param {Array} array The array of grouped elements to process.\n     * @param {Function} [iteratee=_.identity] The function to combine\n     *  regrouped values.\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) {\n      if (!(array && array.length)) {\n        return [];\n      }\n      var result = unzip(array);\n      if (iteratee == null) {\n        return result;\n      }\n      return arrayMap(result, function(group) {\n        return apply(iteratee, undefined, group);\n      });\n    }\n\n    /**\n     * Creates an array excluding all given values using\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * for equality comparisons.\n     *\n     * **Note:** Unlike `_.pull`, this method returns a new array.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Array\n     * @param {Array} array The array to inspect.\n     * @param {...*} [values] The values to exclude.\n     * @returns {Array} Returns the new array of filtered values.\n     * @see _.difference, _.xor\n     * @example\n     *\n     * _.without([2, 1, 2, 3], 1, 2);\n     * // => [3]\n     */\n    var without = baseRest(function(array, values) {\n      return isArrayLikeObject(array)\n        ? baseDifference(array, values)\n        : [];\n    });\n\n    /**\n     * Creates an array of unique values that is the\n     * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)\n     * of the given arrays. The order of result values is determined by the order\n     * they occur in the arrays.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.4.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @returns {Array} Returns the new array of filtered values.\n     * @see _.difference, _.without\n     * @example\n     *\n     * _.xor([2, 1], [2, 3]);\n     * // => [1, 3]\n     */\n    var xor = baseRest(function(arrays) {\n      return baseXor(arrayFilter(arrays, isArrayLikeObject));\n    });\n\n    /**\n     * This method is like `_.xor` except that it accepts `iteratee` which is\n     * invoked for each element of each `arrays` to generate the criterion by\n     * which by which they're compared. The order of result values is determined\n     * by the order they occur in the arrays. The iteratee is invoked with one\n     * argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n     * // => [1.2, 3.4]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 2 }]\n     */\n    var xorBy = baseRest(function(arrays) {\n      var iteratee = last(arrays);\n      if (isArrayLikeObject(iteratee)) {\n        iteratee = undefined;\n      }\n      return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));\n    });\n\n    /**\n     * This method is like `_.xor` except that it accepts `comparator` which is\n     * invoked to compare elements of `arrays`. The order of result values is\n     * determined by the order they occur in the arrays. The comparator is invoked\n     * with two arguments: (arrVal, othVal).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to inspect.\n     * @param {Function} [comparator] The comparator invoked per element.\n     * @returns {Array} Returns the new array of filtered values.\n     * @example\n     *\n     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n     *\n     * _.xorWith(objects, others, _.isEqual);\n     * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n     */\n    var xorWith = baseRest(function(arrays) {\n      var comparator = last(arrays);\n      comparator = typeof comparator == 'function' ? comparator : undefined;\n      return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);\n    });\n\n    /**\n     * Creates an array of grouped elements, the first of which contains the\n     * first elements of the given arrays, the second of which contains the\n     * second elements of the given arrays, and so on.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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(['a', 'b'], [1, 2], [true, false]);\n     * // => [['a', 1, true], ['b', 2, false]]\n     */\n    var zip = baseRest(unzip);\n\n    /**\n     * This method is like `_.fromPairs` except that it accepts two arrays,\n     * one of property identifiers and one of corresponding values.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.4.0\n     * @category Array\n     * @param {Array} [props=[]] The property identifiers.\n     * @param {Array} [values=[]] The property values.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * _.zipObject(['a', 'b'], [1, 2]);\n     * // => { 'a': 1, 'b': 2 }\n     */\n    function zipObject(props, values) {\n      return baseZipObject(props || [], values || [], assignValue);\n    }\n\n    /**\n     * This method is like `_.zipObject` except that it supports property paths.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.1.0\n     * @category Array\n     * @param {Array} [props=[]] The property identifiers.\n     * @param {Array} [values=[]] The property values.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);\n     * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }\n     */\n    function zipObjectDeep(props, values) {\n      return baseZipObject(props || [], values || [], baseSet);\n    }\n\n    /**\n     * This method is like `_.zip` except that it accepts `iteratee` to specify\n     * how grouped values should be combined. The iteratee is invoked with the\n     * elements of each group: (...group).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.8.0\n     * @category Array\n     * @param {...Array} [arrays] The arrays to process.\n     * @param {Function} [iteratee=_.identity] The function to combine\n     *  grouped values.\n     * @returns {Array} Returns the new array of grouped elements.\n     * @example\n     *\n     * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {\n     *   return a + b + c;\n     * });\n     * // => [111, 222]\n     */\n    var zipWith = baseRest(function(arrays) {\n      var length = arrays.length,\n          iteratee = length > 1 ? arrays[length - 1] : undefined;\n\n      iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;\n      return unzipWith(arrays, iteratee);\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Creates a `lodash` wrapper instance that wraps `value` with explicit method\n     * chain sequences enabled. The result of such sequences must be unwrapped\n     * with `_#value`.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.3.0\n     * @category Seq\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 = _\n     *   .chain(users)\n     *   .sortBy('age')\n     *   .map(function(o) {\n     *     return o.user + ' is ' + o.age;\n     *   })\n     *   .head()\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\n     * is invoked with one argument; (value). The purpose of this method is to\n     * \"tap into\" a method chain sequence in order to modify intermediate results.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Seq\n     * @param {*} value The value to provide to `interceptor`.\n     * @param {Function} interceptor The function to invoke.\n     * @returns {*} Returns `value`.\n     * @example\n     *\n     * _([1, 2, 3])\n     *  .tap(function(array) {\n     *    // Mutate input array.\n     *    array.pop();\n     *  })\n     *  .reverse()\n     *  .value();\n     * // => [2, 1]\n     */\n    function tap(value, interceptor) {\n      interceptor(value);\n      return value;\n    }\n\n    /**\n     * This method is like `_.tap` except that it returns the result of `interceptor`.\n     * The purpose of this method is to \"pass thru\" values replacing intermediate\n     * results in a method chain sequence.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Seq\n     * @param {*} value The value to provide to `interceptor`.\n     * @param {Function} interceptor The function to invoke.\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) {\n      return interceptor(value);\n    }\n\n    /**\n     * This method is the wrapper version of `_.at`.\n     *\n     * @name at\n     * @memberOf _\n     * @since 1.0.0\n     * @category Seq\n     * @param {...(string|string[])} [paths] The property paths to pick.\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n     *\n     * _(object).at(['a[0].b.c', 'a[1]']).value();\n     * // => [3, 4]\n     */\n    var wrapperAt = flatRest(function(paths) {\n      var length = paths.length,\n          start = length ? paths[0] : 0,\n          value = this.__wrapped__,\n          interceptor = function(object) { return baseAt(object, paths); };\n\n      if (length > 1 || this.__actions__.length ||\n          !(value instanceof LazyWrapper) || !isIndex(start)) {\n        return this.thru(interceptor);\n      }\n      value = value.slice(start, +start + (length ? 1 : 0));\n      value.__actions__.push({\n        'func': thru,\n        'args': [interceptor],\n        'thisArg': undefined\n      });\n      return new LodashWrapper(value, this.__chain__).thru(function(array) {\n        if (length && !array.length) {\n          array.push(undefined);\n        }\n        return array;\n      });\n    });\n\n    /**\n     * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.\n     *\n     * @name chain\n     * @memberOf _\n     * @since 0.1.0\n     * @category Seq\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     * // A sequence without explicit chaining.\n     * _(users).head();\n     * // => { 'user': 'barney', 'age': 36 }\n     *\n     * // A sequence with explicit chaining.\n     * _(users)\n     *   .chain()\n     *   .head()\n     *   .pick('user')\n     *   .value();\n     * // => { 'user': 'barney' }\n     */\n    function wrapperChain() {\n      return chain(this);\n    }\n\n    /**\n     * Executes the chain sequence and returns the wrapped result.\n     *\n     * @name commit\n     * @memberOf _\n     * @since 3.2.0\n     * @category Seq\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     * Gets the next value on a wrapped object following the\n     * [iterator protocol](https://mdn.io/iteration_protocols#iterator).\n     *\n     * @name next\n     * @memberOf _\n     * @since 4.0.0\n     * @category Seq\n     * @returns {Object} Returns the next iterator value.\n     * @example\n     *\n     * var wrapped = _([1, 2]);\n     *\n     * wrapped.next();\n     * // => { 'done': false, 'value': 1 }\n     *\n     * wrapped.next();\n     * // => { 'done': false, 'value': 2 }\n     *\n     * wrapped.next();\n     * // => { 'done': true, 'value': undefined }\n     */\n    function wrapperNext() {\n      if (this.__values__ === undefined) {\n        this.__values__ = toArray(this.value());\n      }\n      var done = this.__index__ >= this.__values__.length,\n          value = done ? undefined : this.__values__[this.__index__++];\n\n      return { 'done': done, 'value': value };\n    }\n\n    /**\n     * Enables the wrapper to be iterable.\n     *\n     * @name Symbol.iterator\n     * @memberOf _\n     * @since 4.0.0\n     * @category Seq\n     * @returns {Object} Returns the wrapper object.\n     * @example\n     *\n     * var wrapped = _([1, 2]);\n     *\n     * wrapped[Symbol.iterator]() === wrapped;\n     * // => true\n     *\n     * Array.from(wrapped);\n     * // => [1, 2]\n     */\n    function wrapperToIterator() {\n      return this;\n    }\n\n    /**\n     * Creates a clone of the chain sequence planting `value` as the wrapped value.\n     *\n     * @name plant\n     * @memberOf _\n     * @since 3.2.0\n     * @category Seq\n     * @param {*} value The value to plant.\n     * @returns {Object} Returns the new `lodash` wrapper instance.\n     * @example\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * var wrapped = _([1, 2]).map(square);\n     * var other = wrapped.plant([3, 4]);\n     *\n     * other.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        clone.__index__ = 0;\n        clone.__values__ = undefined;\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     * This method is the wrapper version of `_.reverse`.\n     *\n     * **Note:** This method mutates the wrapped array.\n     *\n     * @name reverse\n     * @memberOf _\n     * @since 0.1.0\n     * @category Seq\n     * @returns {Object} Returns the new `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      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({\n          'func': thru,\n          'args': [reverse],\n          'thisArg': undefined\n        });\n        return new LodashWrapper(wrapped, this.__chain__);\n      }\n      return this.thru(reverse);\n    }\n\n    /**\n     * Executes the chain sequence to resolve the unwrapped value.\n     *\n     * @name value\n     * @memberOf _\n     * @since 0.1.0\n     * @alias toJSON, valueOf\n     * @category Seq\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 object composed of keys generated from the results of running\n     * each element of `collection` thru `iteratee`. The corresponding value of\n     * each key is the number of times the key was returned by `iteratee`. The\n     * iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.5.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.countBy([6.1, 4.2, 6.3], Math.floor);\n     * // => { '4': 1, '6': 2 }\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.countBy(['one', 'two', 'three'], 'length');\n     * // => { '3': 2, '5': 1 }\n     */\n    var countBy = createAggregator(function(result, value, key) {\n      if (hasOwnProperty.call(result, key)) {\n        ++result[key];\n      } else {\n        baseAssignValue(result, key, 1);\n      }\n    });\n\n    /**\n     * Checks if `predicate` returns truthy for **all** elements of `collection`.\n     * Iteration is stopped once `predicate` returns falsey. The predicate is\n     * invoked with three arguments: (value, index|key, collection).\n     *\n     * **Note:** This method returns `true` for\n     * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because\n     * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of\n     * elements of empty collections.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\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', 'age': 36, 'active': false },\n     *   { 'user': 'fred',   'age': 40, 'active': false }\n     * ];\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.every(users, { 'user': 'barney', 'active': false });\n     * // => false\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.every(users, ['active', false]);\n     * // => true\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.every(users, 'active');\n     * // => false\n     */\n    function every(collection, predicate, guard) {\n      var func = isArray(collection) ? arrayEvery : baseEvery;\n      if (guard && isIterateeCall(collection, predicate, guard)) {\n        predicate = undefined;\n      }\n      return func(collection, getIteratee(predicate, 3));\n    }\n\n    /**\n     * Iterates over elements of `collection`, returning an array of all elements\n     * `predicate` returns truthy for. The predicate is invoked with three\n     * arguments: (value, index|key, collection).\n     *\n     * **Note:** Unlike `_.remove`, this method returns a new array.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the new filtered array.\n     * @see _.reject\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, function(o) { return !o.active; });\n     * // => objects for ['fred']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.filter(users, { 'age': 36, 'active': true });\n     * // => objects for ['barney']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.filter(users, ['active', false]);\n     * // => objects for ['fred']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.filter(users, 'active');\n     * // => objects for ['barney']\n     *\n     * // Combining several predicates using `_.overEvery` or `_.overSome`.\n     * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));\n     * // => objects for ['fred', 'barney']\n     */\n    function filter(collection, predicate) {\n      var func = isArray(collection) ? arrayFilter : baseFilter;\n      return func(collection, getIteratee(predicate, 3));\n    }\n\n    /**\n     * Iterates over elements of `collection`, returning the first element\n     * `predicate` returns truthy for. The predicate is invoked with three\n     * arguments: (value, index|key, collection).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param {number} [fromIndex=0] The index to search from.\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     * _.find(users, function(o) { return o.age < 40; });\n     * // => object for 'barney'\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.find(users, { 'age': 1, 'active': true });\n     * // => object for 'pebbles'\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.find(users, ['active', false]);\n     * // => object for 'fred'\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.find(users, 'active');\n     * // => object for 'barney'\n     */\n    var find = createFind(findIndex);\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     * @since 2.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param {number} [fromIndex=collection.length-1] The index to search from.\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(findLastIndex);\n\n    /**\n     * Creates a flattened array of values by running each element in `collection`\n     * thru `iteratee` and flattening the mapped results. The iteratee is invoked\n     * with three arguments: (value, index|key, collection).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * function duplicate(n) {\n     *   return [n, n];\n     * }\n     *\n     * _.flatMap([1, 2], duplicate);\n     * // => [1, 1, 2, 2]\n     */\n    function flatMap(collection, iteratee) {\n      return baseFlatten(map(collection, iteratee), 1);\n    }\n\n    /**\n     * This method is like `_.flatMap` except that it recursively flattens the\n     * mapped results.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.7.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * function duplicate(n) {\n     *   return [[[n, n]]];\n     * }\n     *\n     * _.flatMapDeep([1, 2], duplicate);\n     * // => [1, 1, 2, 2]\n     */\n    function flatMapDeep(collection, iteratee) {\n      return baseFlatten(map(collection, iteratee), INFINITY);\n    }\n\n    /**\n     * This method is like `_.flatMap` except that it recursively flattens the\n     * mapped results up to `depth` times.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.7.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {number} [depth=1] The maximum recursion depth.\n     * @returns {Array} Returns the new flattened array.\n     * @example\n     *\n     * function duplicate(n) {\n     *   return [[[n, n]]];\n     * }\n     *\n     * _.flatMapDepth([1, 2], duplicate, 2);\n     * // => [[1, 1], [2, 2]]\n     */\n    function flatMapDepth(collection, iteratee, depth) {\n      depth = depth === undefined ? 1 : toInteger(depth);\n      return baseFlatten(map(collection, iteratee), depth);\n    }\n\n    /**\n     * Iterates over elements of `collection` and invokes `iteratee` for each element.\n     * The iteratee is invoked with three arguments: (value, index|key, collection).\n     * Iteratee functions may exit iteration early by explicitly returning `false`.\n     *\n     * **Note:** As with other \"Collections\" methods, objects with a \"length\"\n     * property are iterated like arrays. To avoid this behavior use `_.forIn`\n     * or `_.forOwn` for object iteration.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @alias each\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array|Object} Returns `collection`.\n     * @see _.forEachRight\n     * @example\n     *\n     * _.forEach([1, 2], function(value) {\n     *   console.log(value);\n     * });\n     * // => Logs `1` then `2`.\n     *\n     * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {\n     *   console.log(key);\n     * });\n     * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n     */\n    function forEach(collection, iteratee) {\n      var func = isArray(collection) ? arrayEach : baseEach;\n      return func(collection, getIteratee(iteratee, 3));\n    }\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     * @since 2.0.0\n     * @alias eachRight\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array|Object} Returns `collection`.\n     * @see _.forEach\n     * @example\n     *\n     * _.forEachRight([1, 2], function(value) {\n     *   console.log(value);\n     * });\n     * // => Logs `2` then `1`.\n     */\n    function forEachRight(collection, iteratee) {\n      var func = isArray(collection) ? arrayEachRight : baseEachRight;\n      return func(collection, getIteratee(iteratee, 3));\n    }\n\n    /**\n     * Creates an object composed of keys generated from the results of running\n     * each element of `collection` thru `iteratee`. The order of grouped values\n     * is determined by the order they occur in `collection`. The corresponding\n     * value of each key is an array of elements responsible for generating the\n     * key. The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.groupBy([6.1, 4.2, 6.3], Math.floor);\n     * // => { '4': [4.2], '6': [6.1, 6.3] }\n     *\n     * // The `_.property` iteratee 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        baseAssignValue(result, key, [value]);\n      }\n    });\n\n    /**\n     * Checks if `value` is in `collection`. If `collection` is a string, it's\n     * checked for a substring of `value`, otherwise\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * is used for equality comparisons. If `fromIndex` is negative, it's used as\n     * the offset from the end of `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to inspect.\n     * @param {*} value The value to search for.\n     * @param {number} [fromIndex=0] The index to search from.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.\n     * @returns {boolean} Returns `true` if `value` 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({ 'a': 1, 'b': 2 }, 1);\n     * // => true\n     *\n     * _.includes('abcd', 'bc');\n     * // => true\n     */\n    function includes(collection, value, fromIndex, guard) {\n      collection = isArrayLike(collection) ? collection : values(collection);\n      fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;\n\n      var length = collection.length;\n      if (fromIndex < 0) {\n        fromIndex = nativeMax(length + fromIndex, 0);\n      }\n      return isString(collection)\n        ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)\n        : (!!length && baseIndexOf(collection, value, fromIndex) > -1);\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 `path` is a function, it's invoked\n     * for, and `this` bound to, each element in `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Collection\n     * @param {Array|Object} 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 each method with.\n     * @returns {Array} Returns the array of results.\n     * @example\n     *\n     * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');\n     * // => [[1, 5, 7], [1, 2, 3]]\n     *\n     * _.invokeMap([123, 456], String.prototype.split, '');\n     * // => [['1', '2', '3'], ['4', '5', '6']]\n     */\n    var invokeMap = baseRest(function(collection, path, args) {\n      var index = -1,\n          isFunc = typeof path == 'function',\n          result = isArrayLike(collection) ? Array(collection.length) : [];\n\n      baseEach(collection, function(value) {\n        result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);\n      });\n      return result;\n    });\n\n    /**\n     * Creates an object composed of keys generated from the results of running\n     * each element of `collection` thru `iteratee`. The corresponding value of\n     * each key is the last element responsible for generating the key. The\n     * iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * var array = [\n     *   { 'dir': 'left', 'code': 97 },\n     *   { 'dir': 'right', 'code': 100 }\n     * ];\n     *\n     * _.keyBy(array, function(o) {\n     *   return String.fromCharCode(o.code);\n     * });\n     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }\n     *\n     * _.keyBy(array, 'dir');\n     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }\n     */\n    var keyBy = createAggregator(function(result, value, key) {\n      baseAssignValue(result, key, value);\n    });\n\n    /**\n     * Creates an array of values by running each element in `collection` thru\n     * `iteratee`. The iteratee is invoked with three arguments:\n     * (value, index|key, collection).\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`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,\n     * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,\n     * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,\n     * `template`, `trim`, `trimEnd`, `trimStart`, and `words`\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the new mapped array.\n     * @example\n     *\n     * function square(n) {\n     *   return n * n;\n     * }\n     *\n     * _.map([4, 8], square);\n     * // => [16, 64]\n     *\n     * _.map({ 'a': 4, 'b': 8 }, square);\n     * // => [16, 64] (iteration order is not guaranteed)\n     *\n     * var users = [\n     *   { 'user': 'barney' },\n     *   { 'user': 'fred' }\n     * ];\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.map(users, 'user');\n     * // => ['barney', 'fred']\n     */\n    function map(collection, iteratee) {\n      var func = isArray(collection) ? arrayMap : baseMap;\n      return func(collection, getIteratee(iteratee, 3));\n    }\n\n    /**\n     * This method is like `_.sortBy` except that it allows specifying the sort\n     * orders of the iteratees to sort by. If `orders` is unspecified, all values\n     * are sorted in ascending order. Otherwise, specify an order of \"desc\" for\n     * descending or \"asc\" for ascending sort order of corresponding values.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]\n     *  The iteratees to sort by.\n     * @param {string[]} [orders] The sort orders of `iteratees`.\n     * @param- {Object} [guard] Enables use as an iteratee for methods 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': 40 },\n     *   { 'user': 'barney', 'age': 36 }\n     * ];\n     *\n     * // Sort by `user` in ascending order and by `age` in descending order.\n     * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);\n     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]\n     */\n    function orderBy(collection, iteratees, orders, guard) {\n      if (collection == null) {\n        return [];\n      }\n      if (!isArray(iteratees)) {\n        iteratees = iteratees == null ? [] : [iteratees];\n      }\n      orders = guard ? undefined : orders;\n      if (!isArray(orders)) {\n        orders = orders == null ? [] : [orders];\n      }\n      return baseOrderBy(collection, iteratees, orders);\n    }\n\n    /**\n     * Creates an array of elements split into two groups, the first of which\n     * contains elements `predicate` returns truthy for, the second of which\n     * contains elements `predicate` returns falsey for. The predicate is\n     * invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the array of grouped elements.\n     * @example\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     * _.partition(users, function(o) { return o.active; });\n     * // => objects for [['fred'], ['barney', 'pebbles']]\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.partition(users, { 'age': 1, 'active': false });\n     * // => objects for [['pebbles'], ['barney', 'fred']]\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.partition(users, ['active', false]);\n     * // => objects for [['barney', 'pebbles'], ['fred']]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.partition(users, 'active');\n     * // => objects for [['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     * Reduces `collection` to a value which is the accumulated result of running\n     * each element in `collection` thru `iteratee`, where each successive\n     * invocation is supplied the return value of the previous. If `accumulator`\n     * is not given, the first element of `collection` is used as the initial\n     * value. The iteratee is 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`, `orderBy`,\n     * and `sortBy`\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @returns {*} Returns the accumulated value.\n     * @see _.reduceRight\n     * @example\n     *\n     * _.reduce([1, 2], function(sum, n) {\n     *   return sum + n;\n     * }, 0);\n     * // => 3\n     *\n     * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n     *   (result[value] || (result[value] = [])).push(key);\n     *   return result;\n     * }, {});\n     * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)\n     */\n    function reduce(collection, iteratee, accumulator) {\n      var func = isArray(collection) ? arrayReduce : baseReduce,\n          initAccum = arguments.length < 3;\n\n      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);\n    }\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     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @param {*} [accumulator] The initial value.\n     * @returns {*} Returns the accumulated value.\n     * @see _.reduce\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    function reduceRight(collection, iteratee, accumulator) {\n      var func = isArray(collection) ? arrayReduceRight : baseReduce,\n          initAccum = arguments.length < 3;\n\n      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);\n    }\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     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the new filtered array.\n     * @see _.filter\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': false },\n     *   { 'user': 'fred',   'age': 40, 'active': true }\n     * ];\n     *\n     * _.reject(users, function(o) { return !o.active; });\n     * // => objects for ['fred']\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.reject(users, { 'age': 40, 'active': true });\n     * // => objects for ['barney']\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.reject(users, ['active', false]);\n     * // => objects for ['fred']\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.reject(users, 'active');\n     * // => objects for ['barney']\n     */\n    function reject(collection, predicate) {\n      var func = isArray(collection) ? arrayFilter : baseFilter;\n      return func(collection, negate(getIteratee(predicate, 3)));\n    }\n\n    /**\n     * Gets a random element from `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to sample.\n     * @returns {*} Returns the random element.\n     * @example\n     *\n     * _.sample([1, 2, 3, 4]);\n     * // => 2\n     */\n    function sample(collection) {\n      var func = isArray(collection) ? arraySample : baseSample;\n      return func(collection);\n    }\n\n    /**\n     * Gets `n` random elements at unique keys from `collection` up to the\n     * size of `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to sample.\n     * @param {number} [n=1] The number of elements to sample.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n     * @returns {Array} Returns the random elements.\n     * @example\n     *\n     * _.sampleSize([1, 2, 3], 2);\n     * // => [3, 1]\n     *\n     * _.sampleSize([1, 2, 3], 4);\n     * // => [2, 3, 1]\n     */\n    function sampleSize(collection, n, guard) {\n      if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {\n        n = 1;\n      } else {\n        n = toInteger(n);\n      }\n      var func = isArray(collection) ? arraySampleSize : baseSampleSize;\n      return func(collection, n);\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     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} 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      var func = isArray(collection) ? arrayShuffle : baseShuffle;\n      return func(collection);\n    }\n\n    /**\n     * Gets the size of `collection` by returning its length for array-like\n     * values or the number of own enumerable string keyed properties for objects.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object|string} collection The collection to inspect.\n     * @returns {number} Returns the collection size.\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      if (collection == null) {\n        return 0;\n      }\n      if (isArrayLike(collection)) {\n        return isString(collection) ? stringSize(collection) : collection.length;\n      }\n      var tag = getTag(collection);\n      if (tag == mapTag || tag == setTag) {\n        return collection.size;\n      }\n      return baseKeys(collection).length;\n    }\n\n    /**\n     * Checks if `predicate` returns truthy for **any** element of `collection`.\n     * Iteration is stopped once `predicate` returns truthy. The predicate is\n     * invoked with three arguments: (value, index|key, collection).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\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     * // The `_.matches` iteratee shorthand.\n     * _.some(users, { 'user': 'barney', 'active': false });\n     * // => false\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.some(users, ['active', false]);\n     * // => true\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.some(users, 'active');\n     * // => true\n     */\n    function some(collection, predicate, guard) {\n      var func = isArray(collection) ? arraySome : baseSome;\n      if (guard && isIterateeCall(collection, predicate, guard)) {\n        predicate = undefined;\n      }\n      return func(collection, getIteratee(predicate, 3));\n    }\n\n    /**\n     * Creates an array of elements, sorted in ascending order by the results of\n     * running each element in a collection thru each iteratee. This method\n     * performs a stable sort, that is, it preserves the original sort order of\n     * equal elements. The iteratees are invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Collection\n     * @param {Array|Object} collection The collection to iterate over.\n     * @param {...(Function|Function[])} [iteratees=[_.identity]]\n     *  The iteratees to sort by.\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': 30 },\n     *   { 'user': 'barney', 'age': 34 }\n     * ];\n     *\n     * _.sortBy(users, [function(o) { return o.user; }]);\n     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n     *\n     * _.sortBy(users, ['user', 'age']);\n     * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n     */\n    var sortBy = baseRest(function(collection, iteratees) {\n      if (collection == null) {\n        return [];\n      }\n      var length = iteratees.length;\n      if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n        iteratees = [];\n      } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n        iteratees = [iteratees[0]];\n      }\n      return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Gets the timestamp of the number of milliseconds that have elapsed since\n     * the Unix epoch (1 January 1970 00:00:00 UTC).\n     *\n     * @static\n     * @memberOf _\n     * @since 2.4.0\n     * @category Date\n     * @returns {number} Returns the timestamp.\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 invocation.\n     */\n    var now = ctxNow || function() {\n      return root.Date.now();\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The opposite of `_.before`; this method creates a function that invokes\n     * `func` once it's called `n` or more times.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      n = toInteger(n);\n      return function() {\n        if (--n < 1) {\n          return func.apply(this, arguments);\n        }\n      };\n    }\n\n    /**\n     * Creates a function that invokes `func`, with up to `n` arguments,\n     * ignoring any additional arguments.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods like `_.map`.\n     * @returns {Function} Returns the new capped function.\n     * @example\n     *\n     * _.map(['6', '8', '10'], _.ary(parseInt, 1));\n     * // => [6, 8, 10]\n     */\n    function ary(func, n, guard) {\n      n = guard ? undefined : n;\n      n = (func && n == null) ? func.length : n;\n      return createWrap(func, WRAP_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's 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     * @since 3.0.0\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(element).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        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      n = toInteger(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 `partials` prepended to the arguments it receives.\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 doesn't set the \"length\"\n     * property of bound functions.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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     * function greet(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     * // Bound with placeholders.\n     * var bound = _.bind(greet, object, _, '!');\n     * bound('hi');\n     * // => 'hi fred!'\n     */\n    var bind = baseRest(function(func, thisArg, partials) {\n      var bitmask = WRAP_BIND_FLAG;\n      if (partials.length) {\n        var holders = replaceHolders(partials, getHolder(bind));\n        bitmask |= WRAP_PARTIAL_FLAG;\n      }\n      return createWrap(func, bitmask, thisArg, partials, holders);\n    });\n\n    /**\n     * Creates a function that invokes the method at `object[key]` with `partials`\n     * prepended to the arguments it receives.\n     *\n     * This method differs from `_.bind` by allowing bound functions to reference\n     * methods that may be redefined or don't yet exist. See\n     * [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     * @since 0.10.0\n     * @category Function\n     * @param {Object} object The object to invoke the method on.\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     * // Bound with placeholders.\n     * var bound = _.bindKey(object, 'greet', _, '!');\n     * bound('hi');\n     * // => 'hiya fred!'\n     */\n    var bindKey = baseRest(function(object, key, partials) {\n      var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;\n      if (partials.length) {\n        var holders = replaceHolders(partials, getHolder(bindKey));\n        bitmask |= WRAP_PARTIAL_FLAG;\n      }\n      return createWrap(key, bitmask, object, partials, holders);\n    });\n\n    /**\n     * Creates a function that accepts arguments of `func` and either invokes\n     * `func` returning its result, if at least `arity` number of arguments have\n     * been provided, or returns a function that accepts the remaining `func`\n     * arguments, and so on. The arity of `func` may be specified if `func.length`\n     * 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 doesn't set the \"length\" property of curried functions.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\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 an iteratee for methods 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     * // Curried with placeholders.\n     * curried(1)(_, 3)(2);\n     * // => [1, 2, 3]\n     */\n    function curry(func, arity, guard) {\n      arity = guard ? undefined : arity;\n      var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n      result.placeholder = curry.placeholder;\n      return result;\n    }\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 doesn't set the \"length\" property of curried functions.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods 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     * // Curried with placeholders.\n     * curried(3)(1, _)(2);\n     * // => [1, 2, 3]\n     */\n    function curryRight(func, arity, guard) {\n      arity = guard ? undefined : arity;\n      var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n      result.placeholder = curryRight.placeholder;\n      return result;\n    }\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 `func` invocations and a `flush` method to immediately invoke them.\n     * Provide `options` to indicate whether `func` should be invoked on the\n     * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n     * with the last arguments provided to the debounced function. Subsequent\n     * calls to the debounced function return the result of the last `func`\n     * invocation.\n     *\n     * **Note:** If `leading` and `trailing` options are `true`, `func` is\n     * invoked on the trailing edge of the timeout only if the debounced function\n     * is invoked more than once during the `wait` timeout.\n     *\n     * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n     * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n     *\n     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n     * for details over the differences between `_.debounce` and `_.throttle`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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]\n     *  Specify invoking on the leading edge of the timeout.\n     * @param {number} [options.maxWait]\n     *  The maximum time `func` is allowed to be delayed before it's invoked.\n     * @param {boolean} [options.trailing=true]\n     *  Specify invoking on the trailing 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 clicked, debouncing subsequent calls.\n     * jQuery(element).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 debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n     * var source = new EventSource('/stream');\n     * jQuery(source).on('message', debounced);\n     *\n     * // Cancel the trailing debounced invocation.\n     * jQuery(window).on('popstate', debounced.cancel);\n     */\n    function debounce(func, wait, options) {\n      var lastArgs,\n          lastThis,\n          maxWait,\n          result,\n          timerId,\n          lastCallTime,\n          lastInvokeTime = 0,\n          leading = false,\n          maxing = false,\n          trailing = true;\n\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      wait = toNumber(wait) || 0;\n      if (isObject(options)) {\n        leading = !!options.leading;\n        maxing = 'maxWait' in options;\n        maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n        trailing = 'trailing' in options ? !!options.trailing : trailing;\n      }\n\n      function invokeFunc(time) {\n        var args = lastArgs,\n            thisArg = lastThis;\n\n        lastArgs = lastThis = undefined;\n        lastInvokeTime = time;\n        result = func.apply(thisArg, args);\n        return result;\n      }\n\n      function leadingEdge(time) {\n        // Reset any `maxWait` timer.\n        lastInvokeTime = time;\n        // Start the timer for the trailing edge.\n        timerId = setTimeout(timerExpired, wait);\n        // Invoke the leading edge.\n        return leading ? invokeFunc(time) : result;\n      }\n\n      function remainingWait(time) {\n        var timeSinceLastCall = time - lastCallTime,\n            timeSinceLastInvoke = time - lastInvokeTime,\n            timeWaiting = wait - timeSinceLastCall;\n\n        return maxing\n          ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)\n          : timeWaiting;\n      }\n\n      function shouldInvoke(time) {\n        var timeSinceLastCall = time - lastCallTime,\n            timeSinceLastInvoke = time - lastInvokeTime;\n\n        // Either this is the first call, activity has stopped and we're at the\n        // trailing edge, the system time has gone backwards and we're treating\n        // it as the trailing edge, or we've hit the `maxWait` limit.\n        return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n          (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n      }\n\n      function timerExpired() {\n        var time = now();\n        if (shouldInvoke(time)) {\n          return trailingEdge(time);\n        }\n        // Restart the timer.\n        timerId = setTimeout(timerExpired, remainingWait(time));\n      }\n\n      function trailingEdge(time) {\n        timerId = undefined;\n\n        // Only invoke if we have `lastArgs` which means `func` has been\n        // debounced at least once.\n        if (trailing && lastArgs) {\n          return invokeFunc(time);\n        }\n        lastArgs = lastThis = undefined;\n        return result;\n      }\n\n      function cancel() {\n        if (timerId !== undefined) {\n          clearTimeout(timerId);\n        }\n        lastInvokeTime = 0;\n        lastArgs = lastCallTime = lastThis = timerId = undefined;\n      }\n\n      function flush() {\n        return timerId === undefined ? result : trailingEdge(now());\n      }\n\n      function debounced() {\n        var time = now(),\n            isInvoking = shouldInvoke(time);\n\n        lastArgs = arguments;\n        lastThis = this;\n        lastCallTime = time;\n\n        if (isInvoking) {\n          if (timerId === undefined) {\n            return leadingEdge(lastCallTime);\n          }\n          if (maxing) {\n            // Handle invocations in a tight loop.\n            clearTimeout(timerId);\n            timerId = setTimeout(timerExpired, wait);\n            return invokeFunc(lastCallTime);\n          }\n        }\n        if (timerId === undefined) {\n          timerId = setTimeout(timerExpired, wait);\n        }\n        return result;\n      }\n      debounced.cancel = cancel;\n      debounced.flush = flush;\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's invoked.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Function\n     * @param {Function} func The function to defer.\n     * @param {...*} [args] The arguments to invoke `func` 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 millisecond.\n     */\n    var defer = baseRest(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's invoked.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 `func` 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 = baseRest(function(func, wait, args) {\n      return baseDelay(func, toNumber(wait) || 0, args);\n    });\n\n    /**\n     * Creates a function that invokes `func` with arguments reversed.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Function\n     * @param {Function} func The function to flip arguments for.\n     * @returns {Function} Returns the new flipped function.\n     * @example\n     *\n     * var flipped = _.flip(function() {\n     *   return _.toArray(arguments);\n     * });\n     *\n     * flipped('a', 'b', 'c', 'd');\n     * // => ['d', 'c', 'b', 'a']\n     */\n    function flip(func) {\n      return createWrap(func, WRAP_FLIP_FLAG);\n    }\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 used as the map cache key. The `func`\n     * is invoked with the `this` binding of the memoized 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\n     * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n     * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 memoized function.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': 2 };\n     * var other = { 'c': 3, 'd': 4 };\n     *\n     * var values = _.memoize(_.values);\n     * values(object);\n     * // => [1, 2]\n     *\n     * values(other);\n     * // => [3, 4]\n     *\n     * object.a = 2;\n     * values(object);\n     * // => [1, 2]\n     *\n     * // Modify the result cache.\n     * values.cache.set(object, ['a', 'b']);\n     * values(object);\n     * // => ['a', 'b']\n     *\n     * // Replace `_.memoize.Cache`.\n     * _.memoize.Cache = WeakMap;\n     */\n    function memoize(func, resolver) {\n      if (typeof func != 'function' || (resolver != null && 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) || cache;\n        return result;\n      };\n      memoized.cache = new (memoize.Cache || MapCache);\n      return memoized;\n    }\n\n    // Expose `MapCache`.\n    memoize.Cache = MapCache;\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     * @since 3.0.0\n     * @category Function\n     * @param {Function} predicate The predicate to negate.\n     * @returns {Function} Returns the new negated 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        var args = arguments;\n        switch (args.length) {\n          case 0: return !predicate.call(this);\n          case 1: return !predicate.call(this, args[0]);\n          case 2: return !predicate.call(this, args[0], args[1]);\n          case 3: return !predicate.call(this, args[0], args[1], args[2]);\n        }\n        return !predicate.apply(this, args);\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 invocation. The `func` is\n     * invoked with the `this` binding and arguments of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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     * // => `createApplication` is invoked once\n     */\n    function once(func) {\n      return before(2, func);\n    }\n\n    /**\n     * Creates a function that invokes `func` with its arguments transformed.\n     *\n     * @static\n     * @since 4.0.0\n     * @memberOf _\n     * @category Function\n     * @param {Function} func The function to wrap.\n     * @param {...(Function|Function[])} [transforms=[_.identity]]\n     *  The argument transforms.\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 func = _.overArgs(function(x, y) {\n     *   return [x, y];\n     * }, [square, doubled]);\n     *\n     * func(9, 3);\n     * // => [81, 6]\n     *\n     * func(10, 5);\n     * // => [100, 10]\n     */\n    var overArgs = castRest(function(func, transforms) {\n      transforms = (transforms.length == 1 && isArray(transforms[0]))\n        ? arrayMap(transforms[0], baseUnary(getIteratee()))\n        : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));\n\n      var funcsLength = transforms.length;\n      return baseRest(function(args) {\n        var index = -1,\n            length = nativeMin(args.length, funcsLength);\n\n        while (++index < length) {\n          args[index] = transforms[index].call(this, args[index]);\n        }\n        return apply(func, this, args);\n      });\n    });\n\n    /**\n     * Creates a function that invokes `func` with `partials` prepended to the\n     * arguments it receives. This method is like `_.bind` except it does **not**\n     * 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 doesn't set the \"length\" property of partially\n     * applied functions.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.2.0\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     * function greet(greeting, name) {\n     *   return greeting + ' ' + name;\n     * }\n     *\n     * var sayHelloTo = _.partial(greet, 'hello');\n     * sayHelloTo('fred');\n     * // => 'hello fred'\n     *\n     * // Partially applied with placeholders.\n     * var greetFred = _.partial(greet, _, 'fred');\n     * greetFred('hi');\n     * // => 'hi fred'\n     */\n    var partial = baseRest(function(func, partials) {\n      var holders = replaceHolders(partials, getHolder(partial));\n      return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);\n    });\n\n    /**\n     * This method is like `_.partial` except that partially applied arguments\n     * are appended to the arguments it receives.\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 doesn't set the \"length\" property of partially\n     * applied functions.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.0.0\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     * function greet(greeting, name) {\n     *   return greeting + ' ' + name;\n     * }\n     *\n     * var greetFred = _.partialRight(greet, 'fred');\n     * greetFred('hi');\n     * // => 'hi fred'\n     *\n     * // Partially applied with placeholders.\n     * var sayHelloTo = _.partialRight(greet, 'hello', _);\n     * sayHelloTo('fred');\n     * // => 'hello fred'\n     */\n    var partialRight = baseRest(function(func, partials) {\n      var holders = replaceHolders(partials, getHolder(partialRight));\n      return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);\n    });\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     * @since 3.0.0\n     * @category Function\n     * @param {Function} func The function to rearrange arguments for.\n     * @param {...(number|number[])} indexes The arranged argument 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 rearg = flatRest(function(func, indexes) {\n      return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, 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\n     * an array.\n     *\n     * **Note:** This method is based on the\n     * [rest parameter](https://mdn.io/rest_parameters).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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 = _.rest(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 rest(func, start) {\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      start = start === undefined ? start : toInteger(start);\n      return baseRest(func, start);\n    }\n\n    /**\n     * Creates a function that invokes `func` with the `this` binding of the\n     * create function and an array of arguments much like\n     * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).\n     *\n     * **Note:** This method is based on the\n     * [spread operator](https://mdn.io/spread_operator).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.2.0\n     * @category Function\n     * @param {Function} func The function to spread arguments over.\n     * @param {number} [start=0] The start position of the spread.\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     * 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, start) {\n      if (typeof func != 'function') {\n        throw new TypeError(FUNC_ERROR_TEXT);\n      }\n      start = start == null ? 0 : nativeMax(toInteger(start), 0);\n      return baseRest(function(args) {\n        var array = args[start],\n            otherArgs = castSlice(args, 0, start);\n\n        if (array) {\n          arrayPush(otherArgs, array);\n        }\n        return apply(func, this, otherArgs);\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 `func` invocations and a `flush` method to\n     * immediately invoke them. Provide `options` to indicate whether `func`\n     * should be invoked on the leading and/or trailing edge of the `wait`\n     * timeout. The `func` is invoked with the last arguments provided to the\n     * throttled function. Subsequent calls to the throttled function return the\n     * result of the last `func` invocation.\n     *\n     * **Note:** If `leading` and `trailing` options are `true`, `func` is\n     * invoked on the trailing edge of the timeout only if the throttled function\n     * is invoked more than once during the `wait` timeout.\n     *\n     * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n     * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n     *\n     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n     * for details over the differences between `_.throttle` and `_.debounce`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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]\n     *  Specify invoking on the leading edge of the timeout.\n     * @param {boolean} [options.trailing=true]\n     *  Specify invoking on the trailing 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     * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });\n     * jQuery(element).on('click', throttled);\n     *\n     * // Cancel the trailing throttled invocation.\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 (isObject(options)) {\n        leading = 'leading' in options ? !!options.leading : leading;\n        trailing = 'trailing' in options ? !!options.trailing : trailing;\n      }\n      return debounce(func, wait, {\n        'leading': leading,\n        'maxWait': wait,\n        'trailing': trailing\n      });\n    }\n\n    /**\n     * Creates a function that accepts up to one argument, ignoring any\n     * additional arguments.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Function\n     * @param {Function} func The function to cap arguments for.\n     * @returns {Function} Returns the new capped function.\n     * @example\n     *\n     * _.map(['6', '8', '10'], _.unary(parseInt));\n     * // => [6, 8, 10]\n     */\n    function unary(func) {\n      return ary(func, 1);\n    }\n\n    /**\n     * Creates a function that provides `value` to `wrapper` as its first\n     * argument. Any additional arguments provided to the function are appended\n     * to those provided to the `wrapper`. The wrapper is invoked with the `this`\n     * binding of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Function\n     * @param {*} value The value to wrap.\n     * @param {Function} [wrapper=identity] 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      return partial(castFunction(wrapper), value);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Casts `value` as an array if it's not one.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.4.0\n     * @category Lang\n     * @param {*} value The value to inspect.\n     * @returns {Array} Returns the cast array.\n     * @example\n     *\n     * _.castArray(1);\n     * // => [1]\n     *\n     * _.castArray({ 'a': 1 });\n     * // => [{ 'a': 1 }]\n     *\n     * _.castArray('abc');\n     * // => ['abc']\n     *\n     * _.castArray(null);\n     * // => [null]\n     *\n     * _.castArray(undefined);\n     * // => [undefined]\n     *\n     * _.castArray();\n     * // => []\n     *\n     * var array = [1, 2, 3];\n     * console.log(_.castArray(array) === array);\n     * // => true\n     */\n    function castArray() {\n      if (!arguments.length) {\n        return [];\n      }\n      var value = arguments[0];\n      return isArray(value) ? value : [value];\n    }\n\n    /**\n     * Creates a shallow clone of `value`.\n     *\n     * **Note:** This method is loosely based on the\n     * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n     * and supports cloning arrays, array buffers, booleans, date objects, maps,\n     * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n     * arrays. The own enumerable properties of `arguments` objects are cloned\n     * as plain objects. An empty object is returned for uncloneable values such\n     * as error objects, functions, DOM nodes, and WeakMaps.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to clone.\n     * @returns {*} Returns the cloned value.\n     * @see _.cloneDeep\n     * @example\n     *\n     * var objects = [{ 'a': 1 }, { 'b': 2 }];\n     *\n     * var shallow = _.clone(objects);\n     * console.log(shallow[0] === objects[0]);\n     * // => true\n     */\n    function clone(value) {\n      return baseClone(value, CLONE_SYMBOLS_FLAG);\n    }\n\n    /**\n     * This method is like `_.clone` except that it accepts `customizer` which\n     * is invoked to produce the cloned value. If `customizer` returns `undefined`,\n     * cloning is handled by the method instead. The `customizer` is invoked with\n     * up to four arguments; (value [, index|key, object, stack]).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to clone.\n     * @param {Function} [customizer] The function to customize cloning.\n     * @returns {*} Returns the cloned value.\n     * @see _.cloneDeepWith\n     * @example\n     *\n     * function customizer(value) {\n     *   if (_.isElement(value)) {\n     *     return value.cloneNode(false);\n     *   }\n     * }\n     *\n     * var el = _.cloneWith(document.body, customizer);\n     *\n     * console.log(el === document.body);\n     * // => false\n     * console.log(el.nodeName);\n     * // => 'BODY'\n     * console.log(el.childNodes.length);\n     * // => 0\n     */\n    function cloneWith(value, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);\n    }\n\n    /**\n     * This method is like `_.clone` except that it recursively clones `value`.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.0.0\n     * @category Lang\n     * @param {*} value The value to recursively clone.\n     * @returns {*} Returns the deep cloned value.\n     * @see _.clone\n     * @example\n     *\n     * var objects = [{ 'a': 1 }, { 'b': 2 }];\n     *\n     * var deep = _.cloneDeep(objects);\n     * console.log(deep[0] === objects[0]);\n     * // => false\n     */\n    function cloneDeep(value) {\n      return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n    }\n\n    /**\n     * This method is like `_.cloneWith` except that it recursively clones `value`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to recursively clone.\n     * @param {Function} [customizer] The function to customize cloning.\n     * @returns {*} Returns the deep cloned value.\n     * @see _.cloneWith\n     * @example\n     *\n     * function customizer(value) {\n     *   if (_.isElement(value)) {\n     *     return value.cloneNode(true);\n     *   }\n     * }\n     *\n     * var el = _.cloneDeepWith(document.body, customizer);\n     *\n     * console.log(el === document.body);\n     * // => false\n     * console.log(el.nodeName);\n     * // => 'BODY'\n     * console.log(el.childNodes.length);\n     * // => 20\n     */\n    function cloneDeepWith(value, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);\n    }\n\n    /**\n     * Checks if `object` conforms to `source` by invoking the predicate\n     * properties of `source` with the corresponding property values of `object`.\n     *\n     * **Note:** This method is equivalent to `_.conforms` when `source` is\n     * partially applied.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.14.0\n     * @category Lang\n     * @param {Object} object The object to inspect.\n     * @param {Object} source The object of property predicates to conform to.\n     * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': 2 };\n     *\n     * _.conformsTo(object, { 'b': function(n) { return n > 1; } });\n     * // => true\n     *\n     * _.conformsTo(object, { 'b': function(n) { return n > 2; } });\n     * // => false\n     */\n    function conformsTo(object, source) {\n      return source == null || baseConformsTo(object, source, keys(source));\n    }\n\n    /**\n     * Performs a\n     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n     * comparison between two values to determine if they are equivalent.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     * @example\n     *\n     * var object = { 'a': 1 };\n     * var other = { 'a': 1 };\n     *\n     * _.eq(object, object);\n     * // => true\n     *\n     * _.eq(object, other);\n     * // => false\n     *\n     * _.eq('a', 'a');\n     * // => true\n     *\n     * _.eq('a', Object('a'));\n     * // => false\n     *\n     * _.eq(NaN, NaN);\n     * // => true\n     */\n    function eq(value, other) {\n      return value === other || (value !== value && other !== other);\n    }\n\n    /**\n     * Checks if `value` is greater than `other`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.9.0\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`,\n     *  else `false`.\n     * @see _.lt\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    var gt = createRelationalOperation(baseGt);\n\n    /**\n     * Checks if `value` is greater than or equal to `other`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.9.0\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\n     *  `other`, else `false`.\n     * @see _.lte\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    var gte = createRelationalOperation(function(value, other) {\n      return value >= other;\n    });\n\n    /**\n     * Checks if `value` is likely an `arguments` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n     *  else `false`.\n     * @example\n     *\n     * _.isArguments(function() { return arguments; }());\n     * // => true\n     *\n     * _.isArguments([1, 2, 3]);\n     * // => false\n     */\n    var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n      return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n        !propertyIsEnumerable.call(value, 'callee');\n    };\n\n    /**\n     * Checks if `value` is classified as an `Array` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n     * @example\n     *\n     * _.isArray([1, 2, 3]);\n     * // => true\n     *\n     * _.isArray(document.body.children);\n     * // => false\n     *\n     * _.isArray('abc');\n     * // => false\n     *\n     * _.isArray(_.noop);\n     * // => false\n     */\n    var isArray = Array.isArray;\n\n    /**\n     * Checks if `value` is classified as an `ArrayBuffer` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n     * @example\n     *\n     * _.isArrayBuffer(new ArrayBuffer(2));\n     * // => true\n     *\n     * _.isArrayBuffer(new Array(2));\n     * // => false\n     */\n    var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;\n\n    /**\n     * Checks if `value` is array-like. A value is considered array-like if it's\n     * not a function and has a `value.length` that's an integer greater than or\n     * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n     * @example\n     *\n     * _.isArrayLike([1, 2, 3]);\n     * // => true\n     *\n     * _.isArrayLike(document.body.children);\n     * // => true\n     *\n     * _.isArrayLike('abc');\n     * // => true\n     *\n     * _.isArrayLike(_.noop);\n     * // => false\n     */\n    function isArrayLike(value) {\n      return value != null && isLength(value.length) && !isFunction(value);\n    }\n\n    /**\n     * This method is like `_.isArrayLike` except that it also checks if `value`\n     * is an object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an array-like object,\n     *  else `false`.\n     * @example\n     *\n     * _.isArrayLikeObject([1, 2, 3]);\n     * // => true\n     *\n     * _.isArrayLikeObject(document.body.children);\n     * // => true\n     *\n     * _.isArrayLikeObject('abc');\n     * // => false\n     *\n     * _.isArrayLikeObject(_.noop);\n     * // => false\n     */\n    function isArrayLikeObject(value) {\n      return isObjectLike(value) && isArrayLike(value);\n    }\n\n    /**\n     * Checks if `value` is classified as a boolean primitive or object.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a boolean, 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 ||\n        (isObjectLike(value) && baseGetTag(value) == boolTag);\n    }\n\n    /**\n     * Checks if `value` is a buffer.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n     * @example\n     *\n     * _.isBuffer(new Buffer(2));\n     * // => true\n     *\n     * _.isBuffer(new Uint8Array(2));\n     * // => false\n     */\n    var isBuffer = nativeIsBuffer || stubFalse;\n\n    /**\n     * Checks if `value` is classified as a `Date` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n     * @example\n     *\n     * _.isDate(new Date);\n     * // => true\n     *\n     * _.isDate('Mon April 23 2012');\n     * // => false\n     */\n    var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;\n\n    /**\n     * Checks if `value` is likely a DOM element.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);\n    }\n\n    /**\n     * Checks if `value` is an empty object, collection, map, or set.\n     *\n     * Objects are considered empty if they have no own enumerable string keyed\n     * properties.\n     *\n     * Array-like values such as `arguments` objects, arrays, buffers, strings, or\n     * jQuery-like collections are considered empty if they have a `length` of `0`.\n     * Similarly, maps and sets are considered empty if they have a `size` of `0`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\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) &&\n          (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||\n            isBuffer(value) || isTypedArray(value) || isArguments(value))) {\n        return !value.length;\n      }\n      var tag = getTag(value);\n      if (tag == mapTag || tag == setTag) {\n        return !value.size;\n      }\n      if (isPrototype(value)) {\n        return !baseKeys(value).length;\n      }\n      for (var key in value) {\n        if (hasOwnProperty.call(value, key)) {\n          return false;\n        }\n      }\n      return true;\n    }\n\n    /**\n     * Performs a deep comparison between two values to determine if they are\n     * equivalent.\n     *\n     * **Note:** This method supports comparing arrays, array buffers, booleans,\n     * date objects, error objects, maps, numbers, `Object` objects, regexes,\n     * sets, strings, symbols, and typed arrays. `Object` objects are compared\n     * by their own, not inherited, enumerable properties. Functions and DOM\n     * nodes are compared by strict equality, i.e. `===`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to compare.\n     * @param {*} other The other value to compare.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     * @example\n     *\n     * var object = { 'a': 1 };\n     * var other = { 'a': 1 };\n     *\n     * _.isEqual(object, other);\n     * // => true\n     *\n     * object === other;\n     * // => false\n     */\n    function isEqual(value, other) {\n      return baseIsEqual(value, other);\n    }\n\n    /**\n     * This method is like `_.isEqual` except that it accepts `customizer` which\n     * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n     * are handled by the method instead. The `customizer` is invoked with up to\n     * six arguments: (objValue, othValue [, index|key, object, other, stack]).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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 comparisons.\n     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n     * @example\n     *\n     * function isGreeting(value) {\n     *   return /^h(?:i|ello)$/.test(value);\n     * }\n     *\n     * function customizer(objValue, othValue) {\n     *   if (isGreeting(objValue) && isGreeting(othValue)) {\n     *     return true;\n     *   }\n     * }\n     *\n     * var array = ['hello', 'goodbye'];\n     * var other = ['hi', 'goodbye'];\n     *\n     * _.isEqualWith(array, other, customizer);\n     * // => true\n     */\n    function isEqualWith(value, other, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      var result = customizer ? customizer(value, other) : undefined;\n      return result === undefined ? baseIsEqual(value, other, undefined, 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     * @since 3.0.0\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      if (!isObjectLike(value)) {\n        return false;\n      }\n      var tag = baseGetTag(value);\n      return tag == errorTag || tag == domExcTag ||\n        (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));\n    }\n\n    /**\n     * Checks if `value` is a finite primitive number.\n     *\n     * **Note:** This method is based on\n     * [`Number.isFinite`](https://mdn.io/Number/isFinite).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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(3);\n     * // => true\n     *\n     * _.isFinite(Number.MIN_VALUE);\n     * // => true\n     *\n     * _.isFinite(Infinity);\n     * // => false\n     *\n     * _.isFinite('3');\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     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n     * @example\n     *\n     * _.isFunction(_);\n     * // => true\n     *\n     * _.isFunction(/abc/);\n     * // => false\n     */\n    function isFunction(value) {\n      if (!isObject(value)) {\n        return false;\n      }\n      // The use of `Object#toString` avoids issues with the `typeof` operator\n      // in Safari 9 which returns 'object' for typed arrays and other constructors.\n      var tag = baseGetTag(value);\n      return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n    }\n\n    /**\n     * Checks if `value` is an integer.\n     *\n     * **Note:** This method is based on\n     * [`Number.isInteger`](https://mdn.io/Number/isInteger).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is an integer, else `false`.\n     * @example\n     *\n     * _.isInteger(3);\n     * // => true\n     *\n     * _.isInteger(Number.MIN_VALUE);\n     * // => false\n     *\n     * _.isInteger(Infinity);\n     * // => false\n     *\n     * _.isInteger('3');\n     * // => false\n     */\n    function isInteger(value) {\n      return typeof value == 'number' && value == toInteger(value);\n    }\n\n    /**\n     * Checks if `value` is a valid array-like length.\n     *\n     * **Note:** This method is loosely based on\n     * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n     * @example\n     *\n     * _.isLength(3);\n     * // => true\n     *\n     * _.isLength(Number.MIN_VALUE);\n     * // => false\n     *\n     * _.isLength(Infinity);\n     * // => false\n     *\n     * _.isLength('3');\n     * // => false\n     */\n    function isLength(value) {\n      return typeof value == 'number' &&\n        value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n    }\n\n    /**\n     * Checks if `value` is the\n     * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n     * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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(_.noop);\n     * // => true\n     *\n     * _.isObject(null);\n     * // => false\n     */\n    function isObject(value) {\n      var type = typeof value;\n      return value != null && (type == 'object' || type == 'function');\n    }\n\n    /**\n     * Checks if `value` is object-like. A value is object-like if it's not `null`\n     * and has a `typeof` result of \"object\".\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n     * @example\n     *\n     * _.isObjectLike({});\n     * // => true\n     *\n     * _.isObjectLike([1, 2, 3]);\n     * // => true\n     *\n     * _.isObjectLike(_.noop);\n     * // => false\n     *\n     * _.isObjectLike(null);\n     * // => false\n     */\n    function isObjectLike(value) {\n      return value != null && typeof value == 'object';\n    }\n\n    /**\n     * Checks if `value` is classified as a `Map` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n     * @example\n     *\n     * _.isMap(new Map);\n     * // => true\n     *\n     * _.isMap(new WeakMap);\n     * // => false\n     */\n    var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\n    /**\n     * Performs a partial deep comparison between `object` and `source` to\n     * determine if `object` contains equivalent property values.\n     *\n     * **Note:** This method is equivalent to `_.matches` when `source` is\n     * partially applied.\n     *\n     * Partial comparisons will match empty array and empty object `source`\n     * values against any array or object value, respectively. See `_.isEqual`\n     * for a list of supported value comparisons.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Lang\n     * @param {Object} object The object to inspect.\n     * @param {Object} source The object of property values to match.\n     * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': 2 };\n     *\n     * _.isMatch(object, { 'b': 2 });\n     * // => true\n     *\n     * _.isMatch(object, { 'b': 1 });\n     * // => false\n     */\n    function isMatch(object, source) {\n      return object === source || baseIsMatch(object, source, getMatchData(source));\n    }\n\n    /**\n     * This method is like `_.isMatch` except that it accepts `customizer` which\n     * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n     * are handled by the method instead. The `customizer` is invoked with five\n     * arguments: (objValue, srcValue, index|key, object, source).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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 comparisons.\n     * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n     * @example\n     *\n     * function isGreeting(value) {\n     *   return /^h(?:i|ello)$/.test(value);\n     * }\n     *\n     * function customizer(objValue, srcValue) {\n     *   if (isGreeting(objValue) && isGreeting(srcValue)) {\n     *     return true;\n     *   }\n     * }\n     *\n     * var object = { 'greeting': 'hello' };\n     * var source = { 'greeting': 'hi' };\n     *\n     * _.isMatchWith(object, source, customizer);\n     * // => true\n     */\n    function isMatchWith(object, source, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      return baseIsMatch(object, source, getMatchData(source), customizer);\n    }\n\n    /**\n     * Checks if `value` is `NaN`.\n     *\n     * **Note:** This method is based on\n     * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as\n     * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for\n     * `undefined` and other non-number values.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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\n      // ActiveX objects in IE.\n      return isNumber(value) && value != +value;\n    }\n\n    /**\n     * Checks if `value` is a pristine native function.\n     *\n     * **Note:** This method can't reliably detect native functions in the presence\n     * of the core-js package because core-js circumvents this kind of detection.\n     * Despite multiple requests, the core-js maintainer has made it clear: any\n     * attempt to fix the detection will be obstructed. As a result, we're left\n     * with little choice but to throw an error. Unfortunately, this also affects\n     * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),\n     * which rely on core-js.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a native function,\n     *  else `false`.\n     * @example\n     *\n     * _.isNative(Array.prototype.push);\n     * // => true\n     *\n     * _.isNative(_);\n     * // => false\n     */\n    function isNative(value) {\n      if (isMaskable(value)) {\n        throw new Error(CORE_ERROR_TEXT);\n      }\n      return baseIsNative(value);\n    }\n\n    /**\n     * Checks if `value` is `null`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\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 `null` or `undefined`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is nullish, else `false`.\n     * @example\n     *\n     * _.isNil(null);\n     * // => true\n     *\n     * _.isNil(void 0);\n     * // => true\n     *\n     * _.isNil(NaN);\n     * // => false\n     */\n    function isNil(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\n     * classified as numbers, use the `_.isFinite` method.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a number, else `false`.\n     * @example\n     *\n     * _.isNumber(3);\n     * // => true\n     *\n     * _.isNumber(Number.MIN_VALUE);\n     * // => true\n     *\n     * _.isNumber(Infinity);\n     * // => true\n     *\n     * _.isNumber('3');\n     * // => false\n     */\n    function isNumber(value) {\n      return typeof value == 'number' ||\n        (isObjectLike(value) && baseGetTag(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     * @static\n     * @memberOf _\n     * @since 0.8.0\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      if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n        return false;\n      }\n      var proto = getPrototype(value);\n      if (proto === null) {\n        return true;\n      }\n      var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n      return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n        funcToString.call(Ctor) == objectCtorString;\n    }\n\n    /**\n     * Checks if `value` is classified as a `RegExp` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.1.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n     * @example\n     *\n     * _.isRegExp(/abc/);\n     * // => true\n     *\n     * _.isRegExp('/abc/');\n     * // => false\n     */\n    var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;\n\n    /**\n     * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754\n     * double precision number which isn't the result of a rounded unsafe integer.\n     *\n     * **Note:** This method is based on\n     * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.\n     * @example\n     *\n     * _.isSafeInteger(3);\n     * // => true\n     *\n     * _.isSafeInteger(Number.MIN_VALUE);\n     * // => false\n     *\n     * _.isSafeInteger(Infinity);\n     * // => false\n     *\n     * _.isSafeInteger('3');\n     * // => false\n     */\n    function isSafeInteger(value) {\n      return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;\n    }\n\n    /**\n     * Checks if `value` is classified as a `Set` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n     * @example\n     *\n     * _.isSet(new Set);\n     * // => true\n     *\n     * _.isSet(new WeakSet);\n     * // => false\n     */\n    var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\n    /**\n     * Checks if `value` is classified as a `String` primitive or object.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a string, 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' ||\n        (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);\n    }\n\n    /**\n     * Checks if `value` is classified as a `Symbol` primitive or object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n     * @example\n     *\n     * _.isSymbol(Symbol.iterator);\n     * // => true\n     *\n     * _.isSymbol('abc');\n     * // => false\n     */\n    function isSymbol(value) {\n      return typeof value == 'symbol' ||\n        (isObjectLike(value) && baseGetTag(value) == symbolTag);\n    }\n\n    /**\n     * Checks if `value` is classified as a typed array.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n     * @example\n     *\n     * _.isTypedArray(new Uint8Array);\n     * // => true\n     *\n     * _.isTypedArray([]);\n     * // => false\n     */\n    var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\n    /**\n     * Checks if `value` is `undefined`.\n     *\n     * @static\n     * @since 0.1.0\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 classified as a `WeakMap` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.\n     * @example\n     *\n     * _.isWeakMap(new WeakMap);\n     * // => true\n     *\n     * _.isWeakMap(new Map);\n     * // => false\n     */\n    function isWeakMap(value) {\n      return isObjectLike(value) && getTag(value) == weakMapTag;\n    }\n\n    /**\n     * Checks if `value` is classified as a `WeakSet` object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.3.0\n     * @category Lang\n     * @param {*} value The value to check.\n     * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.\n     * @example\n     *\n     * _.isWeakSet(new WeakSet);\n     * // => true\n     *\n     * _.isWeakSet(new Set);\n     * // => false\n     */\n    function isWeakSet(value) {\n      return isObjectLike(value) && baseGetTag(value) == weakSetTag;\n    }\n\n    /**\n     * Checks if `value` is less than `other`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.9.0\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`,\n     *  else `false`.\n     * @see _.gt\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    var lt = createRelationalOperation(baseLt);\n\n    /**\n     * Checks if `value` is less than or equal to `other`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.9.0\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\n     *  `other`, else `false`.\n     * @see _.gte\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    var lte = createRelationalOperation(function(value, other) {\n      return value <= other;\n    });\n\n    /**\n     * Converts `value` to an array.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {Array} Returns the converted array.\n     * @example\n     *\n     * _.toArray({ 'a': 1, 'b': 2 });\n     * // => [1, 2]\n     *\n     * _.toArray('abc');\n     * // => ['a', 'b', 'c']\n     *\n     * _.toArray(1);\n     * // => []\n     *\n     * _.toArray(null);\n     * // => []\n     */\n    function toArray(value) {\n      if (!value) {\n        return [];\n      }\n      if (isArrayLike(value)) {\n        return isString(value) ? stringToArray(value) : copyArray(value);\n      }\n      if (symIterator && value[symIterator]) {\n        return iteratorToArray(value[symIterator]());\n      }\n      var tag = getTag(value),\n          func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);\n\n      return func(value);\n    }\n\n    /**\n     * Converts `value` to a finite number.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.12.0\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {number} Returns the converted number.\n     * @example\n     *\n     * _.toFinite(3.2);\n     * // => 3.2\n     *\n     * _.toFinite(Number.MIN_VALUE);\n     * // => 5e-324\n     *\n     * _.toFinite(Infinity);\n     * // => 1.7976931348623157e+308\n     *\n     * _.toFinite('3.2');\n     * // => 3.2\n     */\n    function toFinite(value) {\n      if (!value) {\n        return value === 0 ? value : 0;\n      }\n      value = toNumber(value);\n      if (value === INFINITY || value === -INFINITY) {\n        var sign = (value < 0 ? -1 : 1);\n        return sign * MAX_INTEGER;\n      }\n      return value === value ? value : 0;\n    }\n\n    /**\n     * Converts `value` to an integer.\n     *\n     * **Note:** This method is loosely based on\n     * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {number} Returns the converted integer.\n     * @example\n     *\n     * _.toInteger(3.2);\n     * // => 3\n     *\n     * _.toInteger(Number.MIN_VALUE);\n     * // => 0\n     *\n     * _.toInteger(Infinity);\n     * // => 1.7976931348623157e+308\n     *\n     * _.toInteger('3.2');\n     * // => 3\n     */\n    function toInteger(value) {\n      var result = toFinite(value),\n          remainder = result % 1;\n\n      return result === result ? (remainder ? result - remainder : result) : 0;\n    }\n\n    /**\n     * Converts `value` to an integer suitable for use as the length of an\n     * array-like object.\n     *\n     * **Note:** This method is based on\n     * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {number} Returns the converted integer.\n     * @example\n     *\n     * _.toLength(3.2);\n     * // => 3\n     *\n     * _.toLength(Number.MIN_VALUE);\n     * // => 0\n     *\n     * _.toLength(Infinity);\n     * // => 4294967295\n     *\n     * _.toLength('3.2');\n     * // => 3\n     */\n    function toLength(value) {\n      return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;\n    }\n\n    /**\n     * Converts `value` to a number.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to process.\n     * @returns {number} Returns the number.\n     * @example\n     *\n     * _.toNumber(3.2);\n     * // => 3.2\n     *\n     * _.toNumber(Number.MIN_VALUE);\n     * // => 5e-324\n     *\n     * _.toNumber(Infinity);\n     * // => Infinity\n     *\n     * _.toNumber('3.2');\n     * // => 3.2\n     */\n    function toNumber(value) {\n      if (typeof value == 'number') {\n        return value;\n      }\n      if (isSymbol(value)) {\n        return NAN;\n      }\n      if (isObject(value)) {\n        var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n        value = isObject(other) ? (other + '') : other;\n      }\n      if (typeof value != 'string') {\n        return value === 0 ? value : +value;\n      }\n      value = baseTrim(value);\n      var isBinary = reIsBinary.test(value);\n      return (isBinary || reIsOctal.test(value))\n        ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n        : (reIsBadHex.test(value) ? NAN : +value);\n    }\n\n    /**\n     * Converts `value` to a plain object flattening inherited enumerable string\n     * keyed properties of `value` to own properties of the plain object.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 copyObject(value, keysIn(value));\n    }\n\n    /**\n     * Converts `value` to a safe integer. A safe integer can be compared and\n     * represented correctly.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {number} Returns the converted integer.\n     * @example\n     *\n     * _.toSafeInteger(3.2);\n     * // => 3\n     *\n     * _.toSafeInteger(Number.MIN_VALUE);\n     * // => 0\n     *\n     * _.toSafeInteger(Infinity);\n     * // => 9007199254740991\n     *\n     * _.toSafeInteger('3.2');\n     * // => 3\n     */\n    function toSafeInteger(value) {\n      return value\n        ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)\n        : (value === 0 ? value : 0);\n    }\n\n    /**\n     * Converts `value` to a string. An empty string is returned for `null`\n     * and `undefined` values. The sign of `-0` is preserved.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Lang\n     * @param {*} value The value to convert.\n     * @returns {string} Returns the converted string.\n     * @example\n     *\n     * _.toString(null);\n     * // => ''\n     *\n     * _.toString(-0);\n     * // => '-0'\n     *\n     * _.toString([1, 2, 3]);\n     * // => '1,2,3'\n     */\n    function toString(value) {\n      return value == null ? '' : baseToString(value);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Assigns own enumerable string keyed properties of source objects to the\n     * destination object. Source objects are applied from left to right.\n     * Subsequent sources overwrite property assignments of previous sources.\n     *\n     * **Note:** This method mutates `object` and is loosely based on\n     * [`Object.assign`](https://mdn.io/Object/assign).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.10.0\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @returns {Object} Returns `object`.\n     * @see _.assignIn\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     * }\n     *\n     * function Bar() {\n     *   this.c = 3;\n     * }\n     *\n     * Foo.prototype.b = 2;\n     * Bar.prototype.d = 4;\n     *\n     * _.assign({ 'a': 0 }, new Foo, new Bar);\n     * // => { 'a': 1, 'c': 3 }\n     */\n    var assign = createAssigner(function(object, source) {\n      if (isPrototype(source) || isArrayLike(source)) {\n        copyObject(source, keys(source), object);\n        return;\n      }\n      for (var key in source) {\n        if (hasOwnProperty.call(source, key)) {\n          assignValue(object, key, source[key]);\n        }\n      }\n    });\n\n    /**\n     * This method is like `_.assign` except that it iterates over own and\n     * inherited source properties.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @alias extend\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @returns {Object} Returns `object`.\n     * @see _.assign\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     * }\n     *\n     * function Bar() {\n     *   this.c = 3;\n     * }\n     *\n     * Foo.prototype.b = 2;\n     * Bar.prototype.d = 4;\n     *\n     * _.assignIn({ 'a': 0 }, new Foo, new Bar);\n     * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }\n     */\n    var assignIn = createAssigner(function(object, source) {\n      copyObject(source, keysIn(source), object);\n    });\n\n    /**\n     * This method is like `_.assignIn` except that it accepts `customizer`\n     * which is invoked to produce the assigned values. If `customizer` returns\n     * `undefined`, assignment is handled by the method instead. The `customizer`\n     * is invoked with five arguments: (objValue, srcValue, key, object, source).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @alias extendWith\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     * @returns {Object} Returns `object`.\n     * @see _.assignWith\n     * @example\n     *\n     * function customizer(objValue, srcValue) {\n     *   return _.isUndefined(objValue) ? srcValue : objValue;\n     * }\n     *\n     * var defaults = _.partialRight(_.assignInWith, customizer);\n     *\n     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n     * // => { 'a': 1, 'b': 2 }\n     */\n    var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n      copyObject(source, keysIn(source), object, customizer);\n    });\n\n    /**\n     * This method is like `_.assign` except that it accepts `customizer`\n     * which is invoked to produce the assigned values. If `customizer` returns\n     * `undefined`, assignment is handled by the method instead. The `customizer`\n     * is invoked with five arguments: (objValue, srcValue, key, object, source).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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     * @returns {Object} Returns `object`.\n     * @see _.assignInWith\n     * @example\n     *\n     * function customizer(objValue, srcValue) {\n     *   return _.isUndefined(objValue) ? srcValue : objValue;\n     * }\n     *\n     * var defaults = _.partialRight(_.assignWith, customizer);\n     *\n     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n     * // => { 'a': 1, 'b': 2 }\n     */\n    var assignWith = createAssigner(function(object, source, srcIndex, customizer) {\n      copyObject(source, keys(source), object, customizer);\n    });\n\n    /**\n     * Creates an array of values corresponding to `paths` of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.0.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {...(string|string[])} [paths] The property paths to pick.\n     * @returns {Array} Returns the picked values.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n     *\n     * _.at(object, ['a[0].b.c', 'a[1]']);\n     * // => [3, 4]\n     */\n    var at = flatRest(baseAt);\n\n    /**\n     * Creates an object that inherits from the `prototype` object. If a\n     * `properties` object is given, its own enumerable string keyed properties\n     * are assigned to the created object.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.3.0\n     * @category Object\n     * @param {Object} prototype The object to inherit from.\n     * @param {Object} [properties] The properties to assign to the object.\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) {\n      var result = baseCreate(prototype);\n      return properties == null ? result : baseAssign(result, properties);\n    }\n\n    /**\n     * Assigns own and inherited enumerable string keyed properties of source\n     * objects to the destination object for all destination properties that\n     * resolve to `undefined`. Source objects are applied from left to right.\n     * Once a property is set, additional values of the same property are ignored.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @since 0.1.0\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     * @see _.defaultsDeep\n     * @example\n     *\n     * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n     * // => { 'a': 1, 'b': 2 }\n     */\n    var defaults = baseRest(function(object, sources) {\n      object = Object(object);\n\n      var index = -1;\n      var length = sources.length;\n      var guard = length > 2 ? sources[2] : undefined;\n\n      if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n        length = 1;\n      }\n\n      while (++index < length) {\n        var source = sources[index];\n        var props = keysIn(source);\n        var propsIndex = -1;\n        var propsLength = props.length;\n\n        while (++propsIndex < propsLength) {\n          var key = props[propsIndex];\n          var value = object[key];\n\n          if (value === undefined ||\n              (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n            object[key] = source[key];\n          }\n        }\n      }\n\n      return object;\n    });\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     * @since 3.10.0\n     * @category Object\n     * @param {Object} object The destination object.\n     * @param {...Object} [sources] The source objects.\n     * @returns {Object} Returns `object`.\n     * @see _.defaults\n     * @example\n     *\n     * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n     * // => { 'a': { 'b': 2, 'c': 3 } }\n     */\n    var defaultsDeep = baseRest(function(args) {\n      args.push(undefined, customDefaultsMerge);\n      return apply(mergeWith, undefined, args);\n    });\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     * @static\n     * @memberOf _\n     * @since 1.1.0\n     * @category Object\n     * @param {Object} object The object to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {string|undefined} Returns the key of the matched element,\n     *  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(o) { return o.age < 40; });\n     * // => 'barney' (iteration order is not guaranteed)\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.findKey(users, { 'age': 1, 'active': true });\n     * // => 'pebbles'\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.findKey(users, ['active', false]);\n     * // => 'fred'\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.findKey(users, 'active');\n     * // => 'barney'\n     */\n    function findKey(object, predicate) {\n      return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);\n    }\n\n    /**\n     * This method is like `_.findKey` except that it iterates over elements of\n     * a collection in the opposite order.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.0.0\n     * @category Object\n     * @param {Object} object The object to inspect.\n     * @param {Function} [predicate=_.identity] The function invoked per iteration.\n     * @returns {string|undefined} Returns the key of the matched element,\n     *  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(o) { return o.age < 40; });\n     * // => returns 'pebbles' assuming `_.findKey` returns 'barney'\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.findLastKey(users, { 'age': 36, 'active': true });\n     * // => 'barney'\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.findLastKey(users, ['active', false]);\n     * // => 'fred'\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.findLastKey(users, 'active');\n     * // => 'pebbles'\n     */\n    function findLastKey(object, predicate) {\n      return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);\n    }\n\n    /**\n     * Iterates over own and inherited enumerable string keyed properties of an\n     * object and invokes `iteratee` for each property. The iteratee is 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     * @since 0.3.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     * @see _.forInRight\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', then 'c' (iteration order is not guaranteed).\n     */\n    function forIn(object, iteratee) {\n      return object == null\n        ? object\n        : baseFor(object, getIteratee(iteratee, 3), keysIn);\n    }\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     * @since 2.0.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     * @see _.forIn\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', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.\n     */\n    function forInRight(object, iteratee) {\n      return object == null\n        ? object\n        : baseForRight(object, getIteratee(iteratee, 3), keysIn);\n    }\n\n    /**\n     * Iterates over own enumerable string keyed properties of an object and\n     * invokes `iteratee` for each property. The iteratee is invoked with three\n     * arguments: (value, key, object). Iteratee functions may exit iteration\n     * early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.3.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     * @see _.forOwnRight\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' then 'b' (iteration order is not guaranteed).\n     */\n    function forOwn(object, iteratee) {\n      return object && baseForOwn(object, getIteratee(iteratee, 3));\n    }\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     * @since 2.0.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns `object`.\n     * @see _.forOwn\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' then 'a' assuming `_.forOwn` logs 'a' then 'b'.\n     */\n    function forOwnRight(object, iteratee) {\n      return object && baseForOwnRight(object, getIteratee(iteratee, 3));\n    }\n\n    /**\n     * Creates an array of function property names from own enumerable properties\n     * of `object`.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns the function names.\n     * @see _.functionsIn\n     * @example\n     *\n     * function Foo() {\n     *   this.a = _.constant('a');\n     *   this.b = _.constant('b');\n     * }\n     *\n     * Foo.prototype.c = _.constant('c');\n     *\n     * _.functions(new Foo);\n     * // => ['a', 'b']\n     */\n    function functions(object) {\n      return object == null ? [] : baseFunctions(object, keys(object));\n    }\n\n    /**\n     * Creates an array of function property names from own and inherited\n     * enumerable properties of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns the function names.\n     * @see _.functions\n     * @example\n     *\n     * function Foo() {\n     *   this.a = _.constant('a');\n     *   this.b = _.constant('b');\n     * }\n     *\n     * Foo.prototype.c = _.constant('c');\n     *\n     * _.functionsIn(new Foo);\n     * // => ['a', 'b', 'c']\n     */\n    function functionsIn(object) {\n      return object == null ? [] : baseFunctions(object, keysIn(object));\n    }\n\n    /**\n     * Gets the value at `path` of `object`. If the resolved value is\n     * `undefined`, the `defaultValue` is returned in its place.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.7.0\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 for `undefined` resolved values.\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, path);\n      return result === undefined ? defaultValue : result;\n    }\n\n    /**\n     * Checks if `path` is a direct property of `object`.\n     *\n     * @static\n     * @since 0.1.0\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` exists, else `false`.\n     * @example\n     *\n     * var object = { 'a': { 'b': 2 } };\n     * var other = _.create({ 'a': _.create({ 'b': 2 }) });\n     *\n     * _.has(object, 'a');\n     * // => true\n     *\n     * _.has(object, 'a.b');\n     * // => true\n     *\n     * _.has(object, ['a', 'b']);\n     * // => true\n     *\n     * _.has(other, 'a');\n     * // => false\n     */\n    function has(object, path) {\n      return object != null && hasPath(object, path, baseHas);\n    }\n\n    /**\n     * Checks if `path` is a direct or inherited property of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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` exists, else `false`.\n     * @example\n     *\n     * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n     *\n     * _.hasIn(object, 'a');\n     * // => true\n     *\n     * _.hasIn(object, 'a.b');\n     * // => true\n     *\n     * _.hasIn(object, ['a', 'b']);\n     * // => true\n     *\n     * _.hasIn(object, 'b');\n     * // => false\n     */\n    function hasIn(object, path) {\n      return object != null && hasPath(object, path, baseHasIn);\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\n     * property assignments of previous values.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.7.0\n     * @category Object\n     * @param {Object} object The object to invert.\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    var invert = createInverter(function(result, value, key) {\n      if (value != null &&\n          typeof value.toString != 'function') {\n        value = nativeObjectToString.call(value);\n      }\n\n      result[value] = key;\n    }, constant(identity));\n\n    /**\n     * This method is like `_.invert` except that the inverted object is generated\n     * from the results of running each element of `object` thru `iteratee`. The\n     * corresponding inverted value of each inverted key is an array of keys\n     * responsible for generating the inverted value. The iteratee is invoked\n     * with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.1.0\n     * @category Object\n     * @param {Object} object The object to invert.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {Object} Returns the new inverted object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': 2, 'c': 1 };\n     *\n     * _.invertBy(object);\n     * // => { '1': ['a', 'c'], '2': ['b'] }\n     *\n     * _.invertBy(object, function(value) {\n     *   return 'group' + value;\n     * });\n     * // => { 'group1': ['a', 'c'], 'group2': ['b'] }\n     */\n    var invertBy = createInverter(function(result, value, key) {\n      if (value != null &&\n          typeof value.toString != 'function') {\n        value = nativeObjectToString.call(value);\n      }\n\n      if (hasOwnProperty.call(result, value)) {\n        result[value].push(key);\n      } else {\n        result[value] = [key];\n      }\n    }, getIteratee);\n\n    /**\n     * Invokes the method at `path` of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The object to query.\n     * @param {Array|string} path The path of the method to invoke.\n     * @param {...*} [args] The arguments to invoke the method with.\n     * @returns {*} Returns the result of the invoked method.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };\n     *\n     * _.invoke(object, 'a[0].b.c.slice', 1, 3);\n     * // => [2, 3]\n     */\n    var invoke = baseRest(baseInvoke);\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/7.0/#sec-object.keys)\n     * for more details.\n     *\n     * @static\n     * @since 0.1.0\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    function keys(object) {\n      return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(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     * @since 3.0.0\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      return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\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     * string keyed property of `object` thru `iteratee`. The iteratee is invoked\n     * with three arguments: (value, key, object).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.8.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns the new mapped object.\n     * @see _.mapValues\n     * @example\n     *\n     * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {\n     *   return key + value;\n     * });\n     * // => { 'a1': 1, 'b2': 2 }\n     */\n    function mapKeys(object, iteratee) {\n      var result = {};\n      iteratee = getIteratee(iteratee, 3);\n\n      baseForOwn(object, function(value, key, object) {\n        baseAssignValue(result, iteratee(value, key, object), value);\n      });\n      return result;\n    }\n\n    /**\n     * Creates an object with the same keys as `object` and values generated\n     * by running each own enumerable string keyed property of `object` thru\n     * `iteratee`. The iteratee is invoked with three arguments:\n     * (value, key, object).\n     *\n     * @static\n     * @memberOf _\n     * @since 2.4.0\n     * @category Object\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Object} Returns the new mapped object.\n     * @see _.mapKeys\n     * @example\n     *\n     * var users = {\n     *   'fred':    { 'user': 'fred',    'age': 40 },\n     *   'pebbles': { 'user': 'pebbles', 'age': 1 }\n     * };\n     *\n     * _.mapValues(users, function(o) { return o.age; });\n     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.mapValues(users, 'age');\n     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n     */\n    function mapValues(object, iteratee) {\n      var result = {};\n      iteratee = getIteratee(iteratee, 3);\n\n      baseForOwn(object, function(value, key, object) {\n        baseAssignValue(result, key, iteratee(value, key, object));\n      });\n      return result;\n    }\n\n    /**\n     * This method is like `_.assign` except that it recursively merges own and\n     * inherited enumerable string keyed properties of source objects into the\n     * destination object. Source properties that resolve to `undefined` are\n     * skipped if a destination value exists. Array and plain object properties\n     * are merged recursively. Other objects and value types are overridden by\n     * assignment. Source objects are applied from left to right. Subsequent\n     * sources overwrite property assignments of previous sources.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.5.0\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     * var object = {\n     *   'a': [{ 'b': 2 }, { 'd': 4 }]\n     * };\n     *\n     * var other = {\n     *   'a': [{ 'c': 3 }, { 'e': 5 }]\n     * };\n     *\n     * _.merge(object, other);\n     * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n     */\n    var merge = createAssigner(function(object, source, srcIndex) {\n      baseMerge(object, source, srcIndex);\n    });\n\n    /**\n     * This method is like `_.merge` except that it accepts `customizer` which\n     * is invoked to produce the merged values of the destination and source\n     * properties. If `customizer` returns `undefined`, merging is handled by the\n     * method instead. The `customizer` is invoked with six arguments:\n     * (objValue, srcValue, key, object, source, stack).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function customizer(objValue, srcValue) {\n     *   if (_.isArray(objValue)) {\n     *     return objValue.concat(srcValue);\n     *   }\n     * }\n     *\n     * var object = { 'a': [1], 'b': [2] };\n     * var other = { 'a': [3], 'b': [4] };\n     *\n     * _.mergeWith(object, other, customizer);\n     * // => { 'a': [1, 3], 'b': [2, 4] }\n     */\n    var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n      baseMerge(object, source, srcIndex, customizer);\n    });\n\n    /**\n     * The opposite of `_.pick`; this method creates an object composed of the\n     * own and inherited enumerable property paths of `object` that are not omitted.\n     *\n     * **Note:** This method is considerably slower than `_.pick`.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {...(string|string[])} [paths] The property paths to omit.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': '2', 'c': 3 };\n     *\n     * _.omit(object, ['a', 'c']);\n     * // => { 'b': '2' }\n     */\n    var omit = flatRest(function(object, paths) {\n      var result = {};\n      if (object == null) {\n        return result;\n      }\n      var isDeep = false;\n      paths = arrayMap(paths, function(path) {\n        path = castPath(path, object);\n        isDeep || (isDeep = path.length > 1);\n        return path;\n      });\n      copyObject(object, getAllKeysIn(object), result);\n      if (isDeep) {\n        result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);\n      }\n      var length = paths.length;\n      while (length--) {\n        baseUnset(result, paths[length]);\n      }\n      return result;\n    });\n\n    /**\n     * The opposite of `_.pickBy`; this method creates an object composed of\n     * the own and inherited enumerable string keyed properties of `object` that\n     * `predicate` doesn't return truthy for. The predicate is invoked with two\n     * arguments: (value, key).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {Function} [predicate=_.identity] The function invoked per property.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': '2', 'c': 3 };\n     *\n     * _.omitBy(object, _.isNumber);\n     * // => { 'b': '2' }\n     */\n    function omitBy(object, predicate) {\n      return pickBy(object, negate(getIteratee(predicate)));\n    }\n\n    /**\n     * Creates an object composed of the picked `object` properties.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {...(string|string[])} [paths] The property paths to pick.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': '2', 'c': 3 };\n     *\n     * _.pick(object, ['a', 'c']);\n     * // => { 'a': 1, 'c': 3 }\n     */\n    var pick = flatRest(function(object, paths) {\n      return object == null ? {} : basePick(object, paths);\n    });\n\n    /**\n     * Creates an object composed of the `object` properties `predicate` returns\n     * truthy for. The predicate is invoked with two arguments: (value, key).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The source object.\n     * @param {Function} [predicate=_.identity] The function invoked per property.\n     * @returns {Object} Returns the new object.\n     * @example\n     *\n     * var object = { 'a': 1, 'b': '2', 'c': 3 };\n     *\n     * _.pickBy(object, _.isNumber);\n     * // => { 'a': 1, 'c': 3 }\n     */\n    function pickBy(object, predicate) {\n      if (object == null) {\n        return {};\n      }\n      var props = arrayMap(getAllKeysIn(object), function(prop) {\n        return [prop];\n      });\n      predicate = getIteratee(predicate);\n      return basePickBy(object, props, function(value, path) {\n        return predicate(value, path[0]);\n      });\n    }\n\n    /**\n     * This method is like `_.get` except that if the resolved value is a\n     * function it's invoked with the `this` binding of its parent object and\n     * its result is returned.\n     *\n     * @static\n     * @since 0.1.0\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 for `undefined` resolved values.\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[0].b.c3', 'default');\n     * // => 'default'\n     *\n     * _.result(object, 'a[0].b.c3', _.constant('default'));\n     * // => 'default'\n     */\n    function result(object, path, defaultValue) {\n      path = castPath(path, object);\n\n      var index = -1,\n          length = path.length;\n\n      // Ensure the loop is entered when path is empty.\n      if (!length) {\n        length = 1;\n        object = undefined;\n      }\n      while (++index < length) {\n        var value = object == null ? undefined : object[toKey(path[index])];\n        if (value === undefined) {\n          index = length;\n          value = defaultValue;\n        }\n        object = isFunction(value) ? value.call(object) : value;\n      }\n      return object;\n    }\n\n    /**\n     * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,\n     * it's created. Arrays are created for missing index properties while objects\n     * are created for all other missing properties. Use `_.setWith` to customize\n     * `path` creation.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.7.0\n     * @category Object\n     * @param {Object} object The object to modify.\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      return object == null ? object : baseSet(object, path, value);\n    }\n\n    /**\n     * This method is like `_.set` except that it accepts `customizer` which is\n     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`\n     * path creation is handled by the method instead. The `customizer` is invoked\n     * with three arguments: (nsValue, key, nsObject).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to set.\n     * @param {*} value The value to set.\n     * @param {Function} [customizer] The function to customize assigned values.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var object = {};\n     *\n     * _.setWith(object, '[0][1]', 'a', Object);\n     * // => { '0': { '1': 'a' } }\n     */\n    function setWith(object, path, value, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      return object == null ? object : baseSet(object, path, value, customizer);\n    }\n\n    /**\n     * Creates an array of own enumerable string keyed-value pairs for `object`\n     * which can be consumed by `_.fromPairs`. If `object` is a map or set, its\n     * entries are returned.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @alias entries\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the key-value pairs.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.toPairs(new Foo);\n     * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)\n     */\n    var toPairs = createToPairs(keys);\n\n    /**\n     * Creates an array of own and inherited enumerable string keyed-value pairs\n     * for `object` which can be consumed by `_.fromPairs`. If `object` is a map\n     * or set, its entries are returned.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @alias entriesIn\n     * @category Object\n     * @param {Object} object The object to query.\n     * @returns {Array} Returns the key-value pairs.\n     * @example\n     *\n     * function Foo() {\n     *   this.a = 1;\n     *   this.b = 2;\n     * }\n     *\n     * Foo.prototype.c = 3;\n     *\n     * _.toPairsIn(new Foo);\n     * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)\n     */\n    var toPairsIn = createToPairs(keysIn);\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\n     * enumerable string keyed properties thru `iteratee`, with each invocation\n     * potentially mutating the `accumulator` object. If `accumulator` is not\n     * provided, a new object with the same `[[Prototype]]` will be used. The\n     * iteratee is invoked with four arguments: (accumulator, value, key, object).\n     * Iteratee functions may exit iteration early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.3.0\n     * @category Object\n     * @param {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     * @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, 'c': 1 }, function(result, value, key) {\n     *   (result[value] || (result[value] = [])).push(key);\n     * }, {});\n     * // => { '1': ['a', 'c'], '2': ['b'] }\n     */\n    function transform(object, iteratee, accumulator) {\n      var isArr = isArray(object),\n          isArrLike = isArr || isBuffer(object) || isTypedArray(object);\n\n      iteratee = getIteratee(iteratee, 4);\n      if (accumulator == null) {\n        var Ctor = object && object.constructor;\n        if (isArrLike) {\n          accumulator = isArr ? new Ctor : [];\n        }\n        else if (isObject(object)) {\n          accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};\n        }\n        else {\n          accumulator = {};\n        }\n      }\n      (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {\n        return iteratee(accumulator, value, index, object);\n      });\n      return accumulator;\n    }\n\n    /**\n     * Removes the property at `path` of `object`.\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Object\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to unset.\n     * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 7 } }] };\n     * _.unset(object, 'a[0].b.c');\n     * // => true\n     *\n     * console.log(object);\n     * // => { 'a': [{ 'b': {} }] };\n     *\n     * _.unset(object, ['a', '0', 'b', 'c']);\n     * // => true\n     *\n     * console.log(object);\n     * // => { 'a': [{ 'b': {} }] };\n     */\n    function unset(object, path) {\n      return object == null ? true : baseUnset(object, path);\n    }\n\n    /**\n     * This method is like `_.set` except that accepts `updater` to produce the\n     * value to set. Use `_.updateWith` to customize `path` creation. The `updater`\n     * is invoked with one argument: (value).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.6.0\n     * @category Object\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to set.\n     * @param {Function} updater The function to produce the updated value.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n     *\n     * _.update(object, 'a[0].b.c', function(n) { return n * n; });\n     * console.log(object.a[0].b.c);\n     * // => 9\n     *\n     * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });\n     * console.log(object.x[0].y.z);\n     * // => 0\n     */\n    function update(object, path, updater) {\n      return object == null ? object : baseUpdate(object, path, castFunction(updater));\n    }\n\n    /**\n     * This method is like `_.update` except that it accepts `customizer` which is\n     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`\n     * path creation is handled by the method instead. The `customizer` is invoked\n     * with three arguments: (nsValue, key, nsObject).\n     *\n     * **Note:** This method mutates `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.6.0\n     * @category Object\n     * @param {Object} object The object to modify.\n     * @param {Array|string} path The path of the property to set.\n     * @param {Function} updater The function to produce the updated value.\n     * @param {Function} [customizer] The function to customize assigned values.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var object = {};\n     *\n     * _.updateWith(object, '[0][1]', _.constant('a'), Object);\n     * // => { '0': { '1': 'a' } }\n     */\n    function updateWith(object, path, updater, customizer) {\n      customizer = typeof customizer == 'function' ? customizer : undefined;\n      return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);\n    }\n\n    /**\n     * Creates an array of the own enumerable string keyed property values of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects.\n     *\n     * @static\n     * @since 0.1.0\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 object == null ? [] : baseValues(object, keys(object));\n    }\n\n    /**\n     * Creates an array of the own and inherited enumerable string keyed property\n     * values of `object`.\n     *\n     * **Note:** Non-object values are coerced to objects.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 object == null ? [] : baseValues(object, keysIn(object));\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Clamps `number` within the inclusive `lower` and `upper` bounds.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Number\n     * @param {number} number The number to clamp.\n     * @param {number} [lower] The lower bound.\n     * @param {number} upper The upper bound.\n     * @returns {number} Returns the clamped number.\n     * @example\n     *\n     * _.clamp(-10, -5, 5);\n     * // => -5\n     *\n     * _.clamp(10, -5, 5);\n     * // => 5\n     */\n    function clamp(number, lower, upper) {\n      if (upper === undefined) {\n        upper = lower;\n        lower = undefined;\n      }\n      if (upper !== undefined) {\n        upper = toNumber(upper);\n        upper = upper === upper ? upper : 0;\n      }\n      if (lower !== undefined) {\n        lower = toNumber(lower);\n        lower = lower === lower ? lower : 0;\n      }\n      return baseClamp(toNumber(number), lower, upper);\n    }\n\n    /**\n     * Checks if `n` is between `start` and up to, but not including, `end`. If\n     * `end` is not specified, it's set to `start` with `start` then set to `0`.\n     * If `start` is greater than `end` the params are swapped to support\n     * negative ranges.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.3.0\n     * @category Number\n     * @param {number} number 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 `number` is in the range, else `false`.\n     * @see _.range, _.rangeRight\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     * _.inRange(-3, -2, -6);\n     * // => true\n     */\n    function inRange(number, start, end) {\n      start = toFinite(start);\n      if (end === undefined) {\n        end = start;\n        start = 0;\n      } else {\n        end = toFinite(end);\n      }\n      number = toNumber(number);\n      return baseInRange(number, start, end);\n    }\n\n    /**\n     * Produces a random number between the inclusive `lower` and `upper` bounds.\n     * If only one argument is provided a number between `0` and the given number\n     * is returned. If `floating` is `true`, or either `lower` or `upper` are\n     * floats, a floating-point number is returned instead of an integer.\n     *\n     * **Note:** JavaScript follows the IEEE-754 standard for resolving\n     * floating-point values which can produce unexpected results.\n     *\n     * @static\n     * @memberOf _\n     * @since 0.7.0\n     * @category Number\n     * @param {number} [lower=0] The lower bound.\n     * @param {number} [upper=1] The upper bound.\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(lower, upper, floating) {\n      if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {\n        upper = floating = undefined;\n      }\n      if (floating === undefined) {\n        if (typeof upper == 'boolean') {\n          floating = upper;\n          upper = undefined;\n        }\n        else if (typeof lower == 'boolean') {\n          floating = lower;\n          lower = undefined;\n        }\n      }\n      if (lower === undefined && upper === undefined) {\n        lower = 0;\n        upper = 1;\n      }\n      else {\n        lower = toFinite(lower);\n        if (upper === undefined) {\n          upper = lower;\n          lower = 0;\n        } else {\n          upper = toFinite(upper);\n        }\n      }\n      if (lower > upper) {\n        var temp = lower;\n        lower = upper;\n        upper = temp;\n      }\n      if (floating || lower % 1 || upper % 1) {\n        var rand = nativeRandom();\n        return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);\n      }\n      return baseRandom(lower, upper);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 ? capitalize(word) : word);\n    });\n\n    /**\n     * Converts the first character of `string` to upper case and the remaining\n     * to lower case.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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      return upperFirst(toString(string).toLowerCase());\n    }\n\n    /**\n     * Deburrs `string` by converting\n     * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n     * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n     * letters to basic Latin letters and removing\n     * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 = toString(string);\n      return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n    }\n\n    /**\n     * Checks if `string` ends with the given target string.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category String\n     * @param {string} [string=''] The string to inspect.\n     * @param {string} [target] The string to search for.\n     * @param {number} [position=string.length] The position to search up to.\n     * @returns {boolean} Returns `true` if `string` ends with `target`,\n     *  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 = toString(string);\n      target = baseToString(target);\n\n      var length = string.length;\n      position = position === undefined\n        ? length\n        : baseClamp(toInteger(position), 0, length);\n\n      var end = position;\n      position -= target.length;\n      return position >= 0 && string.slice(position, end) == target;\n    }\n\n    /**\n     * Converts the characters \"&\", \"<\", \">\", '\"', and \"'\" in `string` to their\n     * corresponding HTML entities.\n     *\n     * **Note:** No other characters are escaped. To escape additional\n     * characters 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. See\n     * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)\n     * (under \"semi-related fun fact\") for more details.\n     *\n     * When working with HTML you should always\n     * [quote attribute values](http://wonko.com/post/html-escaping) to reduce\n     * XSS vectors.\n     *\n     * @static\n     * @since 0.1.0\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      string = toString(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     * @since 3.0.0\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 = toString(string);\n      return (string && reHasRegExpChar.test(string))\n        ? string.replace(reRegExpChar, '\\\\$&')\n        : string;\n    }\n\n    /**\n     * Converts `string` to\n     * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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     * Converts `string`, as space separated words, to lower case.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the lower cased string.\n     * @example\n     *\n     * _.lowerCase('--Foo-Bar--');\n     * // => 'foo bar'\n     *\n     * _.lowerCase('fooBar');\n     * // => 'foo bar'\n     *\n     * _.lowerCase('__FOO_BAR__');\n     * // => 'foo bar'\n     */\n    var lowerCase = createCompounder(function(result, word, index) {\n      return result + (index ? ' ' : '') + word.toLowerCase();\n    });\n\n    /**\n     * Converts the first character of `string` to lower case.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the converted string.\n     * @example\n     *\n     * _.lowerFirst('Fred');\n     * // => 'fred'\n     *\n     * _.lowerFirst('FRED');\n     * // => 'fRED'\n     */\n    var lowerFirst = createCaseFirst('toLowerCase');\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     * @since 3.0.0\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 = toString(string);\n      length = toInteger(length);\n\n      var strLength = length ? stringSize(string) : 0;\n      if (!length || strLength >= length) {\n        return string;\n      }\n      var mid = (length - strLength) / 2;\n      return (\n        createPadding(nativeFloor(mid), chars) +\n        string +\n        createPadding(nativeCeil(mid), chars)\n      );\n    }\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     * @since 4.0.0\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     * _.padEnd('abc', 6);\n     * // => 'abc   '\n     *\n     * _.padEnd('abc', 6, '_-');\n     * // => 'abc_-_'\n     *\n     * _.padEnd('abc', 3);\n     * // => 'abc'\n     */\n    function padEnd(string, length, chars) {\n      string = toString(string);\n      length = toInteger(length);\n\n      var strLength = length ? stringSize(string) : 0;\n      return (length && strLength < length)\n        ? (string + createPadding(length - strLength, chars))\n        : string;\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     * @since 4.0.0\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     * _.padStart('abc', 6);\n     * // => '   abc'\n     *\n     * _.padStart('abc', 6, '_-');\n     * // => '_-_abc'\n     *\n     * _.padStart('abc', 3);\n     * // => 'abc'\n     */\n    function padStart(string, length, chars) {\n      string = toString(string);\n      length = toInteger(length);\n\n      var strLength = length ? stringSize(string) : 0;\n      return (length && strLength < length)\n        ? (createPadding(length - strLength, chars) + string)\n        : string;\n    }\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\n     * hexadecimal, in which case a `radix` of `16` is used.\n     *\n     * **Note:** This method aligns with the\n     * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.\n     *\n     * @static\n     * @memberOf _\n     * @since 1.1.0\n     * @category String\n     * @param {string} string The string to convert.\n     * @param {number} [radix=10] The radix to interpret `value` by.\n     * @param- {Object} [guard] Enables use as an iteratee for methods 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      if (guard || radix == null) {\n        radix = 0;\n      } else if (radix) {\n        radix = +radix;\n      }\n      return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);\n    }\n\n    /**\n     * Repeats the given string `n` times.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category String\n     * @param {string} [string=''] The string to repeat.\n     * @param {number} [n=1] The number of times to repeat the string.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\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, guard) {\n      if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {\n        n = 1;\n      } else {\n        n = toInteger(n);\n      }\n      return baseRepeat(toString(string), n);\n    }\n\n    /**\n     * Replaces matches for `pattern` in `string` with `replacement`.\n     *\n     * **Note:** This method is based on\n     * [`String#replace`](https://mdn.io/String/replace).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to modify.\n     * @param {RegExp|string} pattern The pattern to replace.\n     * @param {Function|string} replacement The match replacement.\n     * @returns {string} Returns the modified string.\n     * @example\n     *\n     * _.replace('Hi Fred', 'Fred', 'Barney');\n     * // => 'Hi Barney'\n     */\n    function replace() {\n      var args = arguments,\n          string = toString(args[0]);\n\n      return args.length < 3 ? string : string.replace(args[1], args[2]);\n    }\n\n    /**\n     * Converts `string` to\n     * [snake case](https://en.wikipedia.org/wiki/Snake_case).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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     * Splits `string` by `separator`.\n     *\n     * **Note:** This method is based on\n     * [`String#split`](https://mdn.io/String/split).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to split.\n     * @param {RegExp|string} separator The separator pattern to split by.\n     * @param {number} [limit] The length to truncate results to.\n     * @returns {Array} Returns the string segments.\n     * @example\n     *\n     * _.split('a-b-c', '-', 2);\n     * // => ['a', 'b']\n     */\n    function split(string, separator, limit) {\n      if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {\n        separator = limit = undefined;\n      }\n      limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;\n      if (!limit) {\n        return [];\n      }\n      string = toString(string);\n      if (string && (\n            typeof separator == 'string' ||\n            (separator != null && !isRegExp(separator))\n          )) {\n        separator = baseToString(separator);\n        if (!separator && hasUnicode(string)) {\n          return castSlice(stringToArray(string), 0, limit);\n        }\n      }\n      return string.split(separator, limit);\n    }\n\n    /**\n     * Converts `string` to\n     * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n     *\n     * @static\n     * @memberOf _\n     * @since 3.1.0\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 ? ' ' : '') + upperFirst(word);\n    });\n\n    /**\n     * Checks if `string` starts with the given target string.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category String\n     * @param {string} [string=''] The string to inspect.\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`,\n     *  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 = toString(string);\n      position = position == null\n        ? 0\n        : baseClamp(toInteger(position), 0, string.length);\n\n      target = baseToString(target);\n      return string.slice(position, position + target.length) == target;\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 given, 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     * @since 0.1.0\n     * @memberOf _\n     * @category String\n     * @param {string} [string=''] The template string.\n     * @param {Object} [options={}] The options object.\n     * @param {RegExp} [options.escape=_.templateSettings.escape]\n     *  The HTML \"escape\" delimiter.\n     * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]\n     *  The \"evaluate\" delimiter.\n     * @param {Object} [options.imports=_.templateSettings.imports]\n     *  An object to import into the template as free variables.\n     * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]\n     *  The \"interpolate\" delimiter.\n     * @param {string} [options.sourceURL='lodash.templateSources[n]']\n     *  The sourceURL of the compiled template.\n     * @param {string} [options.variable='obj']\n     *  The data object variable name.\n     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n     * @returns {Function} Returns the compiled template function.\n     * @example\n     *\n     * // Use the \"interpolate\" delimiter to create a compiled template.\n     * var compiled = _.template('hello <%= user %>!');\n     * compiled({ 'user': 'fred' });\n     * // => 'hello fred!'\n     *\n     * // Use 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     * // Use 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     * // Use the internal `print` function in \"evaluate\" delimiters.\n     * var compiled = _.template('<% print(\"hello \" + user); %>!');\n     * compiled({ 'user': 'barney' });\n     * // => 'hello barney!'\n     *\n     * // Use the ES template literal delimiter as an \"interpolate\" delimiter.\n     * // Disable support by replacing the \"interpolate\" delimiter.\n     * var compiled = _.template('hello ${ user }!');\n     * compiled({ 'user': 'pebbles' });\n     * // => 'hello pebbles!'\n     *\n     * // Use backslashes to treat delimiters as plain text.\n     * var compiled = _.template('<%= \"\\\\<%- value %\\\\>\" %>');\n     * compiled({ 'value': 'ignored' });\n     * // => '<%- value %>'\n     *\n     * // Use 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     * // Use 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     * // Use 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     * // Use custom template delimiters.\n     * _.templateSettings.interpolate = /{{([\\s\\S]+?)}}/g;\n     * var compiled = _.template('hello {{ user }}!');\n     * compiled({ 'user': 'mustache' });\n     * // => 'hello mustache!'\n     *\n     * // Use the `source` property to inline compiled templates for meaningful\n     * // line numbers in error messages and stack traces.\n     * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\\\n     *   var JST = {\\\n     *     \"main\": ' + _.template(mainText).source + '\\\n     *   };\\\n     * ');\n     */\n    function template(string, options, guard) {\n      // Based on John Resig's `tmpl` implementation\n      // (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 (guard && isIterateeCall(string, options, guard)) {\n        options = undefined;\n      }\n      string = toString(string);\n      options = assignInWith({}, options, settings, customDefaultsAssignIn);\n\n      var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),\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      // The sourceURL gets injected into the source that's eval-ed, so be careful\n      // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in\n      // and escape the comment, thus injecting code that gets evaled.\n      var sourceURL = '//# sourceURL=' +\n        (hasOwnProperty.call(options, 'sourceURL')\n          ? (options.sourceURL + '').replace(/\\s/g, ' ')\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 needs `match` returned in\n        // 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 = hasOwnProperty.call(options, 'variable') && options.variable;\n      if (!variable) {\n        source = 'with (obj) {\\n' + source + '\\n}\\n';\n      }\n      // Throw an error if a forbidden character was found in `variable`, to prevent\n      // potential command injection attacks.\n      else if (reForbiddenIdentifierChars.test(variable)) {\n        throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);\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)\n          .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     * Converts `string`, as a whole, to lower case just like\n     * [String#toLowerCase](https://mdn.io/toLowerCase).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the lower cased string.\n     * @example\n     *\n     * _.toLower('--Foo-Bar--');\n     * // => '--foo-bar--'\n     *\n     * _.toLower('fooBar');\n     * // => 'foobar'\n     *\n     * _.toLower('__FOO_BAR__');\n     * // => '__foo_bar__'\n     */\n    function toLower(value) {\n      return toString(value).toLowerCase();\n    }\n\n    /**\n     * Converts `string`, as a whole, to upper case just like\n     * [String#toUpperCase](https://mdn.io/toUpperCase).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the upper cased string.\n     * @example\n     *\n     * _.toUpper('--foo-bar--');\n     * // => '--FOO-BAR--'\n     *\n     * _.toUpper('fooBar');\n     * // => 'FOOBAR'\n     *\n     * _.toUpper('__foo_bar__');\n     * // => '__FOO_BAR__'\n     */\n    function toUpper(value) {\n      return toString(value).toUpperCase();\n    }\n\n    /**\n     * Removes leading and trailing whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods 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      string = toString(string);\n      if (string && (guard || chars === undefined)) {\n        return baseTrim(string);\n      }\n      if (!string || !(chars = baseToString(chars))) {\n        return string;\n      }\n      var strSymbols = stringToArray(string),\n          chrSymbols = stringToArray(chars),\n          start = charsStartIndex(strSymbols, chrSymbols),\n          end = charsEndIndex(strSymbols, chrSymbols) + 1;\n\n      return castSlice(strSymbols, start, end).join('');\n    }\n\n    /**\n     * Removes trailing whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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 an iteratee for methods like `_.map`.\n     * @returns {string} Returns the trimmed string.\n     * @example\n     *\n     * _.trimEnd('  abc  ');\n     * // => '  abc'\n     *\n     * _.trimEnd('-_-abc-_-', '_-');\n     * // => '-_-abc'\n     */\n    function trimEnd(string, chars, guard) {\n      string = toString(string);\n      if (string && (guard || chars === undefined)) {\n        return string.slice(0, trimmedEndIndex(string) + 1);\n      }\n      if (!string || !(chars = baseToString(chars))) {\n        return string;\n      }\n      var strSymbols = stringToArray(string),\n          end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;\n\n      return castSlice(strSymbols, 0, end).join('');\n    }\n\n    /**\n     * Removes leading whitespace or specified characters from `string`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\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 an iteratee for methods like `_.map`.\n     * @returns {string} Returns the trimmed string.\n     * @example\n     *\n     * _.trimStart('  abc  ');\n     * // => 'abc  '\n     *\n     * _.trimStart('-_-abc-_-', '_-');\n     * // => 'abc-_-'\n     */\n    function trimStart(string, chars, guard) {\n      string = toString(string);\n      if (string && (guard || chars === undefined)) {\n        return string.replace(reTrimStart, '');\n      }\n      if (!string || !(chars = baseToString(chars))) {\n        return string;\n      }\n      var strSymbols = stringToArray(string),\n          start = charsStartIndex(strSymbols, stringToArray(chars));\n\n      return castSlice(strSymbols, start).join('');\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     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to truncate.\n     * @param {Object} [options={}] The options object.\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     * @returns {string} Returns the truncated string.\n     * @example\n     *\n     * _.truncate('hi-diddly-ho there, neighborino');\n     * // => 'hi-diddly-ho there, neighbo...'\n     *\n     * _.truncate('hi-diddly-ho there, neighborino', {\n     *   'length': 24,\n     *   'separator': ' '\n     * });\n     * // => 'hi-diddly-ho there,...'\n     *\n     * _.truncate('hi-diddly-ho there, neighborino', {\n     *   'length': 24,\n     *   'separator': /,? +/\n     * });\n     * // => 'hi-diddly-ho there...'\n     *\n     * _.truncate('hi-diddly-ho there, neighborino', {\n     *   'omission': ' [...]'\n     * });\n     * // => 'hi-diddly-ho there, neig [...]'\n     */\n    function truncate(string, options) {\n      var length = DEFAULT_TRUNC_LENGTH,\n          omission = DEFAULT_TRUNC_OMISSION;\n\n      if (isObject(options)) {\n        var separator = 'separator' in options ? options.separator : separator;\n        length = 'length' in options ? toInteger(options.length) : length;\n        omission = 'omission' in options ? baseToString(options.omission) : omission;\n      }\n      string = toString(string);\n\n      var strLength = string.length;\n      if (hasUnicode(string)) {\n        var strSymbols = stringToArray(string);\n        strLength = strSymbols.length;\n      }\n      if (length >= strLength) {\n        return string;\n      }\n      var end = length - stringSize(omission);\n      if (end < 1) {\n        return omission;\n      }\n      var result = strSymbols\n        ? castSlice(strSymbols, 0, end).join('')\n        : string.slice(0, end);\n\n      if (separator === undefined) {\n        return result + omission;\n      }\n      if (strSymbols) {\n        end += (result.length - end);\n      }\n      if (isRegExp(separator)) {\n        if (string.slice(end).search(separator)) {\n          var match,\n              substring = result;\n\n          if (!separator.global) {\n            separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');\n          }\n          separator.lastIndex = 0;\n          while ((match = separator.exec(substring))) {\n            var newEnd = match.index;\n          }\n          result = result.slice(0, newEnd === undefined ? end : newEnd);\n        }\n      } else if (string.indexOf(baseToString(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;`, and `&#39;` in `string` to\n     * their corresponding characters.\n     *\n     * **Note:** No other HTML entities are unescaped. To unescape additional\n     * HTML entities use a third-party library like [_he_](https://mths.be/he).\n     *\n     * @static\n     * @memberOf _\n     * @since 0.6.0\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 = toString(string);\n      return (string && reHasEscapedHtml.test(string))\n        ? string.replace(reEscapedHtml, unescapeHtmlChar)\n        : string;\n    }\n\n    /**\n     * Converts `string`, as space separated words, to upper case.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the upper cased string.\n     * @example\n     *\n     * _.upperCase('--foo-bar');\n     * // => 'FOO BAR'\n     *\n     * _.upperCase('fooBar');\n     * // => 'FOO BAR'\n     *\n     * _.upperCase('__foo_bar__');\n     * // => 'FOO BAR'\n     */\n    var upperCase = createCompounder(function(result, word, index) {\n      return result + (index ? ' ' : '') + word.toUpperCase();\n    });\n\n    /**\n     * Converts the first character of `string` to upper case.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category String\n     * @param {string} [string=''] The string to convert.\n     * @returns {string} Returns the converted string.\n     * @example\n     *\n     * _.upperFirst('fred');\n     * // => 'Fred'\n     *\n     * _.upperFirst('FRED');\n     * // => 'FRED'\n     */\n    var upperFirst = createCaseFirst('toUpperCase');\n\n    /**\n     * Splits `string` into an array of its words.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\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 an iteratee for methods 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      string = toString(string);\n      pattern = guard ? undefined : pattern;\n\n      if (pattern === undefined) {\n        return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n      }\n      return string.match(pattern) || [];\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's invoked.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Util\n     * @param {Function} func The function to attempt.\n     * @param {...*} [args] The arguments to invoke `func` with.\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 = baseRest(function(func, args) {\n      try {\n        return apply(func, undefined, args);\n      } catch (e) {\n        return isError(e) ? e : new Error(e);\n      }\n    });\n\n    /**\n     * Binds methods of an object to the object itself, overwriting the existing\n     * method.\n     *\n     * **Note:** This method doesn't set the \"length\" property of bound functions.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Util\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     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var view = {\n     *   'label': 'docs',\n     *   'click': function() {\n     *     console.log('clicked ' + this.label);\n     *   }\n     * };\n     *\n     * _.bindAll(view, ['click']);\n     * jQuery(element).on('click', view.click);\n     * // => Logs 'clicked docs' when clicked.\n     */\n    var bindAll = flatRest(function(object, methodNames) {\n      arrayEach(methodNames, function(key) {\n        key = toKey(key);\n        baseAssignValue(object, key, bind(object[key], object));\n      });\n      return object;\n    });\n\n    /**\n     * Creates a function that iterates over `pairs` and invokes the corresponding\n     * function of the first predicate to return truthy. The predicate-function\n     * pairs are invoked with the `this` binding and arguments of the created\n     * function.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {Array} pairs The predicate-function pairs.\n     * @returns {Function} Returns the new composite function.\n     * @example\n     *\n     * var func = _.cond([\n     *   [_.matches({ 'a': 1 }),           _.constant('matches A')],\n     *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],\n     *   [_.stubTrue,                      _.constant('no match')]\n     * ]);\n     *\n     * func({ 'a': 1, 'b': 2 });\n     * // => 'matches A'\n     *\n     * func({ 'a': 0, 'b': 1 });\n     * // => 'matches B'\n     *\n     * func({ 'a': '1', 'b': '2' });\n     * // => 'no match'\n     */\n    function cond(pairs) {\n      var length = pairs == null ? 0 : pairs.length,\n          toIteratee = getIteratee();\n\n      pairs = !length ? [] : arrayMap(pairs, function(pair) {\n        if (typeof pair[1] != 'function') {\n          throw new TypeError(FUNC_ERROR_TEXT);\n        }\n        return [toIteratee(pair[0]), pair[1]];\n      });\n\n      return baseRest(function(args) {\n        var index = -1;\n        while (++index < length) {\n          var pair = pairs[index];\n          if (apply(pair[0], this, args)) {\n            return apply(pair[1], this, args);\n          }\n        }\n      });\n    }\n\n    /**\n     * Creates a function that invokes the predicate properties of `source` with\n     * the corresponding property values of a given object, returning `true` if\n     * all predicates return truthy, else `false`.\n     *\n     * **Note:** The created function is equivalent to `_.conformsTo` with\n     * `source` partially applied.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {Object} source The object of property predicates to conform to.\n     * @returns {Function} Returns the new spec function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': 2, 'b': 1 },\n     *   { 'a': 1, 'b': 2 }\n     * ];\n     *\n     * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));\n     * // => [{ 'a': 1, 'b': 2 }]\n     */\n    function conforms(source) {\n      return baseConforms(baseClone(source, CLONE_DEEP_FLAG));\n    }\n\n    /**\n     * Creates a function that returns `value`.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.4.0\n     * @category Util\n     * @param {*} value The value to return from the new function.\n     * @returns {Function} Returns the new constant function.\n     * @example\n     *\n     * var objects = _.times(2, _.constant({ 'a': 1 }));\n     *\n     * console.log(objects);\n     * // => [{ 'a': 1 }, { 'a': 1 }]\n     *\n     * console.log(objects[0] === objects[1]);\n     * // => true\n     */\n    function constant(value) {\n      return function() {\n        return value;\n      };\n    }\n\n    /**\n     * Checks `value` to determine whether a default value should be returned in\n     * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,\n     * or `undefined`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.14.0\n     * @category Util\n     * @param {*} value The value to check.\n     * @param {*} defaultValue The default value.\n     * @returns {*} Returns the resolved value.\n     * @example\n     *\n     * _.defaultTo(1, 10);\n     * // => 1\n     *\n     * _.defaultTo(undefined, 10);\n     * // => 10\n     */\n    function defaultTo(value, defaultValue) {\n      return (value == null || value !== value) ? defaultValue : value;\n    }\n\n    /**\n     * Creates a function that returns the result of invoking the given functions\n     * with the `this` binding of the created function, where each successive\n     * invocation is supplied the return value of the previous.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Util\n     * @param {...(Function|Function[])} [funcs] The functions to invoke.\n     * @returns {Function} Returns the new composite function.\n     * @see _.flowRight\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 given functions from right to left.\n     *\n     * @static\n     * @since 3.0.0\n     * @memberOf _\n     * @category Util\n     * @param {...(Function|Function[])} [funcs] The functions to invoke.\n     * @returns {Function} Returns the new composite function.\n     * @see _.flow\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     * This method returns the first argument it receives.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Util\n     * @param {*} value Any value.\n     * @returns {*} Returns `value`.\n     * @example\n     *\n     * var object = { 'a': 1 };\n     *\n     * console.log(_.identity(object) === object);\n     * // => true\n     */\n    function identity(value) {\n      return value;\n    }\n\n    /**\n     * Creates a function that invokes `func` with the arguments of the created\n     * function. If `func` is a property name, the created function returns the\n     * property value for a given element. If `func` is an array or object, the\n     * created function returns `true` for elements that contain the equivalent\n     * source properties, otherwise it returns `false`.\n     *\n     * @static\n     * @since 4.0.0\n     * @memberOf _\n     * @category Util\n     * @param {*} [func=_.identity] The value to convert to a callback.\n     * @returns {Function} Returns the callback.\n     * @example\n     *\n     * var users = [\n     *   { 'user': 'barney', 'age': 36, 'active': true },\n     *   { 'user': 'fred',   'age': 40, 'active': false }\n     * ];\n     *\n     * // The `_.matches` iteratee shorthand.\n     * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));\n     * // => [{ 'user': 'barney', 'age': 36, 'active': true }]\n     *\n     * // The `_.matchesProperty` iteratee shorthand.\n     * _.filter(users, _.iteratee(['user', 'fred']));\n     * // => [{ 'user': 'fred', 'age': 40 }]\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.map(users, _.iteratee('user'));\n     * // => ['barney', 'fred']\n     *\n     * // Create custom iteratee shorthands.\n     * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {\n     *   return !_.isRegExp(func) ? iteratee(func) : function(string) {\n     *     return func.test(string);\n     *   };\n     * });\n     *\n     * _.filter(['abc', 'def'], /ef/);\n     * // => ['def']\n     */\n    function iteratee(func) {\n      return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));\n    }\n\n    /**\n     * Creates a function that performs a partial deep comparison between a given\n     * object and `source`, returning `true` if the given object has equivalent\n     * property values, else `false`.\n     *\n     * **Note:** The created function is equivalent to `_.isMatch` with `source`\n     * partially applied.\n     *\n     * Partial comparisons will match empty array and empty object `source`\n     * values against any array or object value, respectively. See `_.isEqual`\n     * for a list of supported value comparisons.\n     *\n     * **Note:** Multiple values can be checked by combining several matchers\n     * using `_.overSome`\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Util\n     * @param {Object} source The object of property values to match.\n     * @returns {Function} Returns the new spec function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': 1, 'b': 2, 'c': 3 },\n     *   { 'a': 4, 'b': 5, 'c': 6 }\n     * ];\n     *\n     * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));\n     * // => [{ 'a': 4, 'b': 5, 'c': 6 }]\n     *\n     * // Checking for several possible values\n     * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));\n     * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]\n     */\n    function matches(source) {\n      return baseMatches(baseClone(source, CLONE_DEEP_FLAG));\n    }\n\n    /**\n     * Creates a function that performs a partial deep comparison between the\n     * value at `path` of a given object to `srcValue`, returning `true` if the\n     * object value is equivalent, else `false`.\n     *\n     * **Note:** Partial comparisons will match empty array and empty object\n     * `srcValue` values against any array or object value, respectively. See\n     * `_.isEqual` for a list of supported value comparisons.\n     *\n     * **Note:** Multiple values can be checked by combining several matchers\n     * using `_.overSome`\n     *\n     * @static\n     * @memberOf _\n     * @since 3.2.0\n     * @category Util\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 spec function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': 1, 'b': 2, 'c': 3 },\n     *   { 'a': 4, 'b': 5, 'c': 6 }\n     * ];\n     *\n     * _.find(objects, _.matchesProperty('a', 4));\n     * // => { 'a': 4, 'b': 5, 'c': 6 }\n     *\n     * // Checking for several possible values\n     * _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));\n     * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]\n     */\n    function matchesProperty(path, srcValue) {\n      return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));\n    }\n\n    /**\n     * Creates a function that invokes the method at `path` of a given object.\n     * Any additional arguments are provided to the invoked method.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.7.0\n     * @category Util\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 invoker function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': { 'b': _.constant(2) } },\n     *   { 'a': { 'b': _.constant(1) } }\n     * ];\n     *\n     * _.map(objects, _.method('a.b'));\n     * // => [2, 1]\n     *\n     * _.map(objects, _.method(['a', 'b']));\n     * // => [2, 1]\n     */\n    var method = baseRest(function(path, args) {\n      return function(object) {\n        return baseInvoke(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 of `object`. Any additional arguments are\n     * provided to the invoked method.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.7.0\n     * @category Util\n     * @param {Object} object The object to query.\n     * @param {...*} [args] The arguments to invoke the method with.\n     * @returns {Function} Returns the new invoker 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 = baseRest(function(object, args) {\n      return function(path) {\n        return baseInvoke(object, path, args);\n      };\n    });\n\n    /**\n     * Adds all own enumerable string keyed function properties of a source\n     * object to the destination object. If `object` is a function, then methods\n     * are added to 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     * @since 0.1.0\n     * @memberOf _\n     * @category Util\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 mixins 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      var props = keys(source),\n          methodNames = baseFunctions(source, props);\n\n      if (options == null &&\n          !(isObject(source) && (methodNames.length || !props.length))) {\n        options = source;\n        source = object;\n        object = this;\n        methodNames = baseFunctions(source, keys(source));\n      }\n      var chain = !(isObject(options) && 'chain' in options) || !!options.chain,\n          isFunc = isFunction(object);\n\n      arrayEach(methodNames, function(methodName) {\n        var func = source[methodName];\n        object[methodName] = func;\n        if (isFunc) {\n          object.prototype[methodName] = function() {\n            var chainAll = this.__chain__;\n            if (chain || chainAll) {\n              var result = object(this.__wrapped__),\n                  actions = result.__actions__ = copyArray(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        }\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     * @since 0.1.0\n     * @memberOf _\n     * @category Util\n     * @returns {Function} Returns the `lodash` function.\n     * @example\n     *\n     * var lodash = _.noConflict();\n     */\n    function noConflict() {\n      if (root._ === this) {\n        root._ = oldDash;\n      }\n      return this;\n    }\n\n    /**\n     * This method returns `undefined`.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.3.0\n     * @category Util\n     * @example\n     *\n     * _.times(2, _.noop);\n     * // => [undefined, undefined]\n     */\n    function noop() {\n      // No operation performed.\n    }\n\n    /**\n     * Creates a function that gets the argument at index `n`. If `n` is negative,\n     * the nth argument from the end is returned.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {number} [n=0] The index of the argument to return.\n     * @returns {Function} Returns the new pass-thru function.\n     * @example\n     *\n     * var func = _.nthArg(1);\n     * func('a', 'b', 'c', 'd');\n     * // => 'b'\n     *\n     * var func = _.nthArg(-2);\n     * func('a', 'b', 'c', 'd');\n     * // => 'c'\n     */\n    function nthArg(n) {\n      n = toInteger(n);\n      return baseRest(function(args) {\n        return baseNth(args, n);\n      });\n    }\n\n    /**\n     * Creates a function that invokes `iteratees` with the arguments it receives\n     * and returns their results.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {...(Function|Function[])} [iteratees=[_.identity]]\n     *  The iteratees to invoke.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var func = _.over([Math.max, Math.min]);\n     *\n     * func(1, 2, 3, 4);\n     * // => [4, 1]\n     */\n    var over = createOver(arrayMap);\n\n    /**\n     * Creates a function that checks if **all** of the `predicates` return\n     * truthy when invoked with the arguments it receives.\n     *\n     * Following shorthands are possible for providing predicates.\n     * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.\n     * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {...(Function|Function[])} [predicates=[_.identity]]\n     *  The predicates to check.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var func = _.overEvery([Boolean, isFinite]);\n     *\n     * func('1');\n     * // => true\n     *\n     * func(null);\n     * // => false\n     *\n     * func(NaN);\n     * // => false\n     */\n    var overEvery = createOver(arrayEvery);\n\n    /**\n     * Creates a function that checks if **any** of the `predicates` return\n     * truthy when invoked with the arguments it receives.\n     *\n     * Following shorthands are possible for providing predicates.\n     * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.\n     * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {...(Function|Function[])} [predicates=[_.identity]]\n     *  The predicates to check.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var func = _.overSome([Boolean, isFinite]);\n     *\n     * func('1');\n     * // => true\n     *\n     * func(null);\n     * // => true\n     *\n     * func(NaN);\n     * // => false\n     *\n     * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])\n     * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])\n     */\n    var overSome = createOver(arraySome);\n\n    /**\n     * Creates a function that returns the value at `path` of a given object.\n     *\n     * @static\n     * @memberOf _\n     * @since 2.4.0\n     * @category Util\n     * @param {Array|string} path The path of the property to get.\n     * @returns {Function} Returns the new accessor function.\n     * @example\n     *\n     * var objects = [\n     *   { 'a': { 'b': 2 } },\n     *   { 'a': { 'b': 1 } }\n     * ];\n     *\n     * _.map(objects, _.property('a.b'));\n     * // => [2, 1]\n     *\n     * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');\n     * // => [1, 2]\n     */\n    function property(path) {\n      return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n    }\n\n    /**\n     * The opposite of `_.property`; this method creates a function that returns\n     * the value at a given path of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.0.0\n     * @category Util\n     * @param {Object} object The object to query.\n     * @returns {Function} Returns the new accessor 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 object == null ? undefined : baseGet(object, 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`. A step of `-1` is used if a negative\n     * `start` is specified without an `end` or `step`. If `end` is not specified,\n     * it's set to `start` with `start` then set to `0`.\n     *\n     * **Note:** JavaScript follows the IEEE-754 standard for resolving\n     * floating-point values which can produce unexpected results.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Util\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 range of numbers.\n     * @see _.inRange, _.rangeRight\n     * @example\n     *\n     * _.range(4);\n     * // => [0, 1, 2, 3]\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    var range = createRange();\n\n    /**\n     * This method is like `_.range` except that it populates values in\n     * descending order.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\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 range of numbers.\n     * @see _.inRange, _.range\n     * @example\n     *\n     * _.rangeRight(4);\n     * // => [3, 2, 1, 0]\n     *\n     * _.rangeRight(-4);\n     * // => [-3, -2, -1, 0]\n     *\n     * _.rangeRight(1, 5);\n     * // => [4, 3, 2, 1]\n     *\n     * _.rangeRight(0, 20, 5);\n     * // => [15, 10, 5, 0]\n     *\n     * _.rangeRight(0, -4, -1);\n     * // => [-3, -2, -1, 0]\n     *\n     * _.rangeRight(1, 4, 0);\n     * // => [1, 1, 1]\n     *\n     * _.rangeRight(0);\n     * // => []\n     */\n    var rangeRight = createRange(true);\n\n    /**\n     * This method returns a new empty array.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.13.0\n     * @category Util\n     * @returns {Array} Returns the new empty array.\n     * @example\n     *\n     * var arrays = _.times(2, _.stubArray);\n     *\n     * console.log(arrays);\n     * // => [[], []]\n     *\n     * console.log(arrays[0] === arrays[1]);\n     * // => false\n     */\n    function stubArray() {\n      return [];\n    }\n\n    /**\n     * This method returns `false`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.13.0\n     * @category Util\n     * @returns {boolean} Returns `false`.\n     * @example\n     *\n     * _.times(2, _.stubFalse);\n     * // => [false, false]\n     */\n    function stubFalse() {\n      return false;\n    }\n\n    /**\n     * This method returns a new empty object.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.13.0\n     * @category Util\n     * @returns {Object} Returns the new empty object.\n     * @example\n     *\n     * var objects = _.times(2, _.stubObject);\n     *\n     * console.log(objects);\n     * // => [{}, {}]\n     *\n     * console.log(objects[0] === objects[1]);\n     * // => false\n     */\n    function stubObject() {\n      return {};\n    }\n\n    /**\n     * This method returns an empty string.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.13.0\n     * @category Util\n     * @returns {string} Returns the empty string.\n     * @example\n     *\n     * _.times(2, _.stubString);\n     * // => ['', '']\n     */\n    function stubString() {\n      return '';\n    }\n\n    /**\n     * This method returns `true`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.13.0\n     * @category Util\n     * @returns {boolean} Returns `true`.\n     * @example\n     *\n     * _.times(2, _.stubTrue);\n     * // => [true, true]\n     */\n    function stubTrue() {\n      return true;\n    }\n\n    /**\n     * Invokes the iteratee `n` times, returning an array of the results of\n     * each invocation. The iteratee is invoked with one argument; (index).\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Util\n     * @param {number} n The number of times to invoke `iteratee`.\n     * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n     * @returns {Array} Returns the array of results.\n     * @example\n     *\n     * _.times(3, String);\n     * // => ['0', '1', '2']\n     *\n     *  _.times(4, _.constant(0));\n     * // => [0, 0, 0, 0]\n     */\n    function times(n, iteratee) {\n      n = toInteger(n);\n      if (n < 1 || n > MAX_SAFE_INTEGER) {\n        return [];\n      }\n      var index = MAX_ARRAY_LENGTH,\n          length = nativeMin(n, MAX_ARRAY_LENGTH);\n\n      iteratee = getIteratee(iteratee);\n      n -= MAX_ARRAY_LENGTH;\n\n      var result = baseTimes(length, iteratee);\n      while (++index < n) {\n        iteratee(index);\n      }\n      return result;\n    }\n\n    /**\n     * Converts `value` to a property path array.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Util\n     * @param {*} value The value to convert.\n     * @returns {Array} Returns the new property path array.\n     * @example\n     *\n     * _.toPath('a.b.c');\n     * // => ['a', 'b', 'c']\n     *\n     * _.toPath('a[0].b.c');\n     * // => ['a', '0', 'b', 'c']\n     */\n    function toPath(value) {\n      if (isArray(value)) {\n        return arrayMap(value, toKey);\n      }\n      return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));\n    }\n\n    /**\n     * Generates a unique ID. If `prefix` is given, the ID is appended to it.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Util\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 toString(prefix) + id;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Adds two numbers.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.4.0\n     * @category Math\n     * @param {number} augend The first number in an addition.\n     * @param {number} addend The second number in an addition.\n     * @returns {number} Returns the total.\n     * @example\n     *\n     * _.add(6, 4);\n     * // => 10\n     */\n    var add = createMathOperation(function(augend, addend) {\n      return augend + addend;\n    }, 0);\n\n    /**\n     * Computes `number` rounded up to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.10.0\n     * @category Math\n     * @param {number} number 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     * Divide two numbers.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.7.0\n     * @category Math\n     * @param {number} dividend The first number in a division.\n     * @param {number} divisor The second number in a division.\n     * @returns {number} Returns the quotient.\n     * @example\n     *\n     * _.divide(6, 4);\n     * // => 1.5\n     */\n    var divide = createMathOperation(function(dividend, divisor) {\n      return dividend / divisor;\n    }, 1);\n\n    /**\n     * Computes `number` rounded down to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.10.0\n     * @category Math\n     * @param {number} number 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     * Computes the maximum value of `array`. If `array` is empty or falsey,\n     * `undefined` is returned.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @returns {*} Returns the maximum value.\n     * @example\n     *\n     * _.max([4, 2, 8, 6]);\n     * // => 8\n     *\n     * _.max([]);\n     * // => undefined\n     */\n    function max(array) {\n      return (array && array.length)\n        ? baseExtremum(array, identity, baseGt)\n        : undefined;\n    }\n\n    /**\n     * This method is like `_.max` except that it accepts `iteratee` which is\n     * invoked for each element in `array` to generate the criterion by which\n     * the value is ranked. The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {*} Returns the maximum value.\n     * @example\n     *\n     * var objects = [{ 'n': 1 }, { 'n': 2 }];\n     *\n     * _.maxBy(objects, function(o) { return o.n; });\n     * // => { 'n': 2 }\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.maxBy(objects, 'n');\n     * // => { 'n': 2 }\n     */\n    function maxBy(array, iteratee) {\n      return (array && array.length)\n        ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)\n        : undefined;\n    }\n\n    /**\n     * Computes the mean of the values in `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @returns {number} Returns the mean.\n     * @example\n     *\n     * _.mean([4, 2, 8, 6]);\n     * // => 5\n     */\n    function mean(array) {\n      return baseMean(array, identity);\n    }\n\n    /**\n     * This method is like `_.mean` except that it accepts `iteratee` which is\n     * invoked for each element in `array` to generate the value to be averaged.\n     * The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.7.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {number} Returns the mean.\n     * @example\n     *\n     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n     *\n     * _.meanBy(objects, function(o) { return o.n; });\n     * // => 5\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.meanBy(objects, 'n');\n     * // => 5\n     */\n    function meanBy(array, iteratee) {\n      return baseMean(array, getIteratee(iteratee, 2));\n    }\n\n    /**\n     * Computes the minimum value of `array`. If `array` is empty or falsey,\n     * `undefined` is returned.\n     *\n     * @static\n     * @since 0.1.0\n     * @memberOf _\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @returns {*} Returns the minimum value.\n     * @example\n     *\n     * _.min([4, 2, 8, 6]);\n     * // => 2\n     *\n     * _.min([]);\n     * // => undefined\n     */\n    function min(array) {\n      return (array && array.length)\n        ? baseExtremum(array, identity, baseLt)\n        : undefined;\n    }\n\n    /**\n     * This method is like `_.min` except that it accepts `iteratee` which is\n     * invoked for each element in `array` to generate the criterion by which\n     * the value is ranked. The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {*} Returns the minimum value.\n     * @example\n     *\n     * var objects = [{ 'n': 1 }, { 'n': 2 }];\n     *\n     * _.minBy(objects, function(o) { return o.n; });\n     * // => { 'n': 1 }\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.minBy(objects, 'n');\n     * // => { 'n': 1 }\n     */\n    function minBy(array, iteratee) {\n      return (array && array.length)\n        ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)\n        : undefined;\n    }\n\n    /**\n     * Multiply two numbers.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.7.0\n     * @category Math\n     * @param {number} multiplier The first number in a multiplication.\n     * @param {number} multiplicand The second number in a multiplication.\n     * @returns {number} Returns the product.\n     * @example\n     *\n     * _.multiply(6, 4);\n     * // => 24\n     */\n    var multiply = createMathOperation(function(multiplier, multiplicand) {\n      return multiplier * multiplicand;\n    }, 1);\n\n    /**\n     * Computes `number` rounded to `precision`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.10.0\n     * @category Math\n     * @param {number} number 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     * Subtract two numbers.\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Math\n     * @param {number} minuend The first number in a subtraction.\n     * @param {number} subtrahend The second number in a subtraction.\n     * @returns {number} Returns the difference.\n     * @example\n     *\n     * _.subtract(6, 4);\n     * // => 2\n     */\n    var subtract = createMathOperation(function(minuend, subtrahend) {\n      return minuend - subtrahend;\n    }, 0);\n\n    /**\n     * Computes the sum of the values in `array`.\n     *\n     * @static\n     * @memberOf _\n     * @since 3.4.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @returns {number} Returns the sum.\n     * @example\n     *\n     * _.sum([4, 2, 8, 6]);\n     * // => 20\n     */\n    function sum(array) {\n      return (array && array.length)\n        ? baseSum(array, identity)\n        : 0;\n    }\n\n    /**\n     * This method is like `_.sum` except that it accepts `iteratee` which is\n     * invoked for each element in `array` to generate the value to be summed.\n     * The iteratee is invoked with one argument: (value).\n     *\n     * @static\n     * @memberOf _\n     * @since 4.0.0\n     * @category Math\n     * @param {Array} array The array to iterate over.\n     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n     * @returns {number} Returns the sum.\n     * @example\n     *\n     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n     *\n     * _.sumBy(objects, function(o) { return o.n; });\n     * // => 20\n     *\n     * // The `_.property` iteratee shorthand.\n     * _.sumBy(objects, 'n');\n     * // => 20\n     */\n    function sumBy(array, iteratee) {\n      return (array && array.length)\n        ? baseSum(array, getIteratee(iteratee, 2))\n        : 0;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // Add methods that return wrapped values in chain sequences.\n    lodash.after = after;\n    lodash.ary = ary;\n    lodash.assign = assign;\n    lodash.assignIn = assignIn;\n    lodash.assignInWith = assignInWith;\n    lodash.assignWith = assignWith;\n    lodash.at = at;\n    lodash.before = before;\n    lodash.bind = bind;\n    lodash.bindAll = bindAll;\n    lodash.bindKey = bindKey;\n    lodash.castArray = castArray;\n    lodash.chain = chain;\n    lodash.chunk = chunk;\n    lodash.compact = compact;\n    lodash.concat = concat;\n    lodash.cond = cond;\n    lodash.conforms = conforms;\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.differenceBy = differenceBy;\n    lodash.differenceWith = differenceWith;\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.flatMap = flatMap;\n    lodash.flatMapDeep = flatMapDeep;\n    lodash.flatMapDepth = flatMapDepth;\n    lodash.flatten = flatten;\n    lodash.flattenDeep = flattenDeep;\n    lodash.flattenDepth = flattenDepth;\n    lodash.flip = flip;\n    lodash.flow = flow;\n    lodash.flowRight = flowRight;\n    lodash.fromPairs = fromPairs;\n    lodash.functions = functions;\n    lodash.functionsIn = functionsIn;\n    lodash.groupBy = groupBy;\n    lodash.initial = initial;\n    lodash.intersection = intersection;\n    lodash.intersectionBy = intersectionBy;\n    lodash.intersectionWith = intersectionWith;\n    lodash.invert = invert;\n    lodash.invertBy = invertBy;\n    lodash.invokeMap = invokeMap;\n    lodash.iteratee = iteratee;\n    lodash.keyBy = keyBy;\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.mergeWith = mergeWith;\n    lodash.method = method;\n    lodash.methodOf = methodOf;\n    lodash.mixin = mixin;\n    lodash.negate = negate;\n    lodash.nthArg = nthArg;\n    lodash.omit = omit;\n    lodash.omitBy = omitBy;\n    lodash.once = once;\n    lodash.orderBy = orderBy;\n    lodash.over = over;\n    lodash.overArgs = overArgs;\n    lodash.overEvery = overEvery;\n    lodash.overSome = overSome;\n    lodash.partial = partial;\n    lodash.partialRight = partialRight;\n    lodash.partition = partition;\n    lodash.pick = pick;\n    lodash.pickBy = pickBy;\n    lodash.property = property;\n    lodash.propertyOf = propertyOf;\n    lodash.pull = pull;\n    lodash.pullAll = pullAll;\n    lodash.pullAllBy = pullAllBy;\n    lodash.pullAllWith = pullAllWith;\n    lodash.pullAt = pullAt;\n    lodash.range = range;\n    lodash.rangeRight = rangeRight;\n    lodash.rearg = rearg;\n    lodash.reject = reject;\n    lodash.remove = remove;\n    lodash.rest = rest;\n    lodash.reverse = reverse;\n    lodash.sampleSize = sampleSize;\n    lodash.set = set;\n    lodash.setWith = setWith;\n    lodash.shuffle = shuffle;\n    lodash.slice = slice;\n    lodash.sortBy = sortBy;\n    lodash.sortedUniq = sortedUniq;\n    lodash.sortedUniqBy = sortedUniqBy;\n    lodash.split = split;\n    lodash.spread = spread;\n    lodash.tail = tail;\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.toArray = toArray;\n    lodash.toPairs = toPairs;\n    lodash.toPairsIn = toPairsIn;\n    lodash.toPath = toPath;\n    lodash.toPlainObject = toPlainObject;\n    lodash.transform = transform;\n    lodash.unary = unary;\n    lodash.union = union;\n    lodash.unionBy = unionBy;\n    lodash.unionWith = unionWith;\n    lodash.uniq = uniq;\n    lodash.uniqBy = uniqBy;\n    lodash.uniqWith = uniqWith;\n    lodash.unset = unset;\n    lodash.unzip = unzip;\n    lodash.unzipWith = unzipWith;\n    lodash.update = update;\n    lodash.updateWith = updateWith;\n    lodash.values = values;\n    lodash.valuesIn = valuesIn;\n    lodash.without = without;\n    lodash.words = words;\n    lodash.wrap = wrap;\n    lodash.xor = xor;\n    lodash.xorBy = xorBy;\n    lodash.xorWith = xorWith;\n    lodash.zip = zip;\n    lodash.zipObject = zipObject;\n    lodash.zipObjectDeep = zipObjectDeep;\n    lodash.zipWith = zipWith;\n\n    // Add aliases.\n    lodash.entries = toPairs;\n    lodash.entriesIn = toPairsIn;\n    lodash.extend = assignIn;\n    lodash.extendWith = assignInWith;\n\n    // Add methods to `lodash.prototype`.\n    mixin(lodash, lodash);\n\n    /*------------------------------------------------------------------------*/\n\n    // Add methods that return unwrapped values in chain sequences.\n    lodash.add = add;\n    lodash.attempt = attempt;\n    lodash.camelCase = camelCase;\n    lodash.capitalize = capitalize;\n    lodash.ceil = ceil;\n    lodash.clamp = clamp;\n    lodash.clone = clone;\n    lodash.cloneDeep = cloneDeep;\n    lodash.cloneDeepWith = cloneDeepWith;\n    lodash.cloneWith = cloneWith;\n    lodash.conformsTo = conformsTo;\n    lodash.deburr = deburr;\n    lodash.defaultTo = defaultTo;\n    lodash.divide = divide;\n    lodash.endsWith = endsWith;\n    lodash.eq = eq;\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.floor = floor;\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.get = get;\n    lodash.gt = gt;\n    lodash.gte = gte;\n    lodash.has = has;\n    lodash.hasIn = hasIn;\n    lodash.head = head;\n    lodash.identity = identity;\n    lodash.includes = includes;\n    lodash.indexOf = indexOf;\n    lodash.inRange = inRange;\n    lodash.invoke = invoke;\n    lodash.isArguments = isArguments;\n    lodash.isArray = isArray;\n    lodash.isArrayBuffer = isArrayBuffer;\n    lodash.isArrayLike = isArrayLike;\n    lodash.isArrayLikeObject = isArrayLikeObject;\n    lodash.isBoolean = isBoolean;\n    lodash.isBuffer = isBuffer;\n    lodash.isDate = isDate;\n    lodash.isElement = isElement;\n    lodash.isEmpty = isEmpty;\n    lodash.isEqual = isEqual;\n    lodash.isEqualWith = isEqualWith;\n    lodash.isError = isError;\n    lodash.isFinite = isFinite;\n    lodash.isFunction = isFunction;\n    lodash.isInteger = isInteger;\n    lodash.isLength = isLength;\n    lodash.isMap = isMap;\n    lodash.isMatch = isMatch;\n    lodash.isMatchWith = isMatchWith;\n    lodash.isNaN = isNaN;\n    lodash.isNative = isNative;\n    lodash.isNil = isNil;\n    lodash.isNull = isNull;\n    lodash.isNumber = isNumber;\n    lodash.isObject = isObject;\n    lodash.isObjectLike = isObjectLike;\n    lodash.isPlainObject = isPlainObject;\n    lodash.isRegExp = isRegExp;\n    lodash.isSafeInteger = isSafeInteger;\n    lodash.isSet = isSet;\n    lodash.isString = isString;\n    lodash.isSymbol = isSymbol;\n    lodash.isTypedArray = isTypedArray;\n    lodash.isUndefined = isUndefined;\n    lodash.isWeakMap = isWeakMap;\n    lodash.isWeakSet = isWeakSet;\n    lodash.join = join;\n    lodash.kebabCase = kebabCase;\n    lodash.last = last;\n    lodash.lastIndexOf = lastIndexOf;\n    lodash.lowerCase = lowerCase;\n    lodash.lowerFirst = lowerFirst;\n    lodash.lt = lt;\n    lodash.lte = lte;\n    lodash.max = max;\n    lodash.maxBy = maxBy;\n    lodash.mean = mean;\n    lodash.meanBy = meanBy;\n    lodash.min = min;\n    lodash.minBy = minBy;\n    lodash.stubArray = stubArray;\n    lodash.stubFalse = stubFalse;\n    lodash.stubObject = stubObject;\n    lodash.stubString = stubString;\n    lodash.stubTrue = stubTrue;\n    lodash.multiply = multiply;\n    lodash.nth = nth;\n    lodash.noConflict = noConflict;\n    lodash.noop = noop;\n    lodash.now = now;\n    lodash.pad = pad;\n    lodash.padEnd = padEnd;\n    lodash.padStart = padStart;\n    lodash.parseInt = parseInt;\n    lodash.random = random;\n    lodash.reduce = reduce;\n    lodash.reduceRight = reduceRight;\n    lodash.repeat = repeat;\n    lodash.replace = replace;\n    lodash.result = result;\n    lodash.round = round;\n    lodash.runInContext = runInContext;\n    lodash.sample = sample;\n    lodash.size = size;\n    lodash.snakeCase = snakeCase;\n    lodash.some = some;\n    lodash.sortedIndex = sortedIndex;\n    lodash.sortedIndexBy = sortedIndexBy;\n    lodash.sortedIndexOf = sortedIndexOf;\n    lodash.sortedLastIndex = sortedLastIndex;\n    lodash.sortedLastIndexBy = sortedLastIndexBy;\n    lodash.sortedLastIndexOf = sortedLastIndexOf;\n    lodash.startCase = startCase;\n    lodash.startsWith = startsWith;\n    lodash.subtract = subtract;\n    lodash.sum = sum;\n    lodash.sumBy = sumBy;\n    lodash.template = template;\n    lodash.times = times;\n    lodash.toFinite = toFinite;\n    lodash.toInteger = toInteger;\n    lodash.toLength = toLength;\n    lodash.toLower = toLower;\n    lodash.toNumber = toNumber;\n    lodash.toSafeInteger = toSafeInteger;\n    lodash.toString = toString;\n    lodash.toUpper = toUpper;\n    lodash.trim = trim;\n    lodash.trimEnd = trimEnd;\n    lodash.trimStart = trimStart;\n    lodash.truncate = truncate;\n    lodash.unescape = unescape;\n    lodash.uniqueId = uniqueId;\n    lodash.upperCase = upperCase;\n    lodash.upperFirst = upperFirst;\n\n    // Add aliases.\n    lodash.each = forEach;\n    lodash.eachRight = forEachRight;\n    lodash.first = head;\n\n    mixin(lodash, (function() {\n      var source = {};\n      baseForOwn(lodash, function(func, methodName) {\n        if (!hasOwnProperty.call(lodash.prototype, methodName)) {\n          source[methodName] = func;\n        }\n      });\n      return source;\n    }()), { 'chain': false });\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        n = n === undefined ? 1 : nativeMax(toInteger(n), 0);\n\n        var result = (this.__filtered__ && !index)\n          ? new LazyWrapper(this)\n          : this.clone();\n\n        if (result.__filtered__) {\n          result.__takeCount__ = nativeMin(n, result.__takeCount__);\n        } else {\n          result.__views__.push({\n            'size': nativeMin(n, MAX_ARRAY_LENGTH),\n            'type': methodName + (result.__dir__ < 0 ? 'Right' : '')\n          });\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_FILTER_FLAG || type == LAZY_WHILE_FLAG;\n\n      LazyWrapper.prototype[methodName] = function(iteratee) {\n        var result = this.clone();\n        result.__iteratees__.push({\n          'iteratee': getIteratee(iteratee, 3),\n          'type': type\n        });\n        result.__filtered__ = result.__filtered__ || isFilter;\n        return result;\n      };\n    });\n\n    // Add `LazyWrapper` methods for `_.head` and `_.last`.\n    arrayEach(['head', '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 `_.tail`.\n    arrayEach(['initial', 'tail'], 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    LazyWrapper.prototype.compact = function() {\n      return this.filter(identity);\n    };\n\n    LazyWrapper.prototype.find = function(predicate) {\n      return this.filter(predicate).head();\n    };\n\n    LazyWrapper.prototype.findLast = function(predicate) {\n      return this.reverse().find(predicate);\n    };\n\n    LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {\n      if (typeof path == 'function') {\n        return new LazyWrapper(this);\n      }\n      return this.map(function(value) {\n        return baseInvoke(value, path, args);\n      });\n    });\n\n    LazyWrapper.prototype.reject = function(predicate) {\n      return this.filter(negate(getIteratee(predicate)));\n    };\n\n    LazyWrapper.prototype.slice = function(start, end) {\n      start = toInteger(start);\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 = toInteger(end);\n        result = end < 0 ? result.dropRight(-end) : result.take(end - start);\n      }\n      return result;\n    };\n\n    LazyWrapper.prototype.takeRightWhile = function(predicate) {\n      return this.reverse().takeWhile(predicate).reverse();\n    };\n\n    LazyWrapper.prototype.toArray = function() {\n      return this.take(MAX_ARRAY_LENGTH);\n    };\n\n    // Add `LazyWrapper` methods to `lodash.prototype`.\n    baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n      var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),\n          isTaker = /^(?:head|last)$/.test(methodName),\n          lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],\n          retUnwrapped = isTaker || /^find/.test(methodName);\n\n      if (!lodashFunc) {\n        return;\n      }\n      lodash.prototype[methodName] = function() {\n        var value = this.__wrapped__,\n            args = isTaker ? [1] : arguments,\n            isLazy = value instanceof LazyWrapper,\n            iteratee = args[0],\n            useLazy = isLazy || isArray(value);\n\n        var interceptor = function(value) {\n          var result = lodashFunc.apply(lodash, arrayPush([value], args));\n          return (isTaker && chainAll) ? result[0] : result;\n        };\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 chainAll = this.__chain__,\n            isHybrid = !!this.__actions__.length,\n            isUnwrapped = retUnwrapped && !chainAll,\n            onlyLazy = isLazy && !isHybrid;\n\n        if (!retUnwrapped && useLazy) {\n          value = onlyLazy ? value : new LazyWrapper(this);\n          var result = func.apply(value, args);\n          result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });\n          return new LodashWrapper(result, chainAll);\n        }\n        if (isUnwrapped && onlyLazy) {\n          return func.apply(this, args);\n        }\n        result = this.thru(interceptor);\n        return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;\n      };\n    });\n\n    // Add `Array` methods to `lodash.prototype`.\n    arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {\n      var func = arrayProto[methodName],\n          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',\n          retUnwrapped = /^(?:pop|shift)$/.test(methodName);\n\n      lodash.prototype[methodName] = function() {\n        var args = arguments;\n        if (retUnwrapped && !this.__chain__) {\n          var value = this.value();\n          return func.apply(isArray(value) ? value : [], args);\n        }\n        return this[chainName](function(value) {\n          return func.apply(isArray(value) ? value : [], args);\n        });\n      };\n    });\n\n    // Map minified method 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        if (!hasOwnProperty.call(realNames, key)) {\n          realNames[key] = [];\n        }\n        realNames[key].push({ 'name': methodName, 'func': lodashFunc });\n      }\n    });\n\n    realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{\n      'name': 'wrapper',\n      'func': undefined\n    }];\n\n    // Add methods to `LazyWrapper`.\n    LazyWrapper.prototype.clone = lazyClone;\n    LazyWrapper.prototype.reverse = lazyReverse;\n    LazyWrapper.prototype.value = lazyValue;\n\n    // Add chain sequence methods to the `lodash` wrapper.\n    lodash.prototype.at = wrapperAt;\n    lodash.prototype.chain = wrapperChain;\n    lodash.prototype.commit = wrapperCommit;\n    lodash.prototype.next = wrapperNext;\n    lodash.prototype.plant = wrapperPlant;\n    lodash.prototype.reverse = wrapperReverse;\n    lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;\n\n    // Add lazy aliases.\n    lodash.prototype.first = lodash.prototype.head;\n\n    if (symIterator) {\n      lodash.prototype[symIterator] = wrapperToIterator;\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:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // Expose Lodash on the global object to prevent errors when Lodash is\n    // loaded by a script tag in the presence of an AMD loader.\n    // See http://requirejs.org/docs/errors.html#mismatch for more details.\n    // Use `_.noConflict` to remove Lodash from the global object.\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 it.\n  else if (freeModule) {\n    // Export for Node.js.\n    (freeModule.exports = _)._ = _;\n    // Export for CommonJS support.\n    freeExports._ = _;\n  }\n  else {\n    // Export to the global object.\n    root._ = _;\n  }\n}.call(this));\n","var hasMap = typeof Map === 'function' && Map.prototype;\nvar mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null;\nvar mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null;\nvar mapForEach = hasMap && Map.prototype.forEach;\nvar hasSet = typeof Set === 'function' && Set.prototype;\nvar setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null;\nvar setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null;\nvar setForEach = hasSet && Set.prototype.forEach;\nvar hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype;\nvar weakMapHas = hasWeakMap ? WeakMap.prototype.has : null;\nvar hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype;\nvar weakSetHas = hasWeakSet ? WeakSet.prototype.has : null;\nvar hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype;\nvar weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null;\nvar booleanValueOf = Boolean.prototype.valueOf;\nvar objectToString = Object.prototype.toString;\nvar functionToString = Function.prototype.toString;\nvar match = String.prototype.match;\nvar bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null;\nvar gOPS = Object.getOwnPropertySymbols;\nvar symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null;\nvar hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object';\nvar isEnumerable = Object.prototype.propertyIsEnumerable;\n\nvar gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || (\n    [].__proto__ === Array.prototype // eslint-disable-line no-proto\n        ? function (O) {\n            return O.__proto__; // eslint-disable-line no-proto\n        }\n        : null\n);\n\nvar inspectCustom = require('./util.inspect').custom;\nvar inspectSymbol = inspectCustom && isSymbol(inspectCustom) ? inspectCustom : null;\nvar toStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag !== 'undefined' ? Symbol.toStringTag : null;\n\nmodule.exports = function inspect_(obj, options, depth, seen) {\n    var opts = options || {};\n\n    if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) {\n        throw new TypeError('option \"quoteStyle\" must be \"single\" or \"double\"');\n    }\n    if (\n        has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number'\n            ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity\n            : opts.maxStringLength !== null\n        )\n    ) {\n        throw new TypeError('option \"maxStringLength\", if provided, must be a positive integer, Infinity, or `null`');\n    }\n    var customInspect = has(opts, 'customInspect') ? opts.customInspect : true;\n    if (typeof customInspect !== 'boolean') {\n        throw new TypeError('option \"customInspect\", if provided, must be `true` or `false`');\n    }\n\n    if (\n        has(opts, 'indent')\n        && opts.indent !== null\n        && opts.indent !== '\\t'\n        && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0)\n    ) {\n        throw new TypeError('options \"indent\" must be \"\\\\t\", an integer > 0, or `null`');\n    }\n\n    if (typeof obj === 'undefined') {\n        return 'undefined';\n    }\n    if (obj === null) {\n        return 'null';\n    }\n    if (typeof obj === 'boolean') {\n        return obj ? 'true' : 'false';\n    }\n\n    if (typeof obj === 'string') {\n        return inspectString(obj, opts);\n    }\n    if (typeof obj === 'number') {\n        if (obj === 0) {\n            return Infinity / obj > 0 ? '0' : '-0';\n        }\n        return String(obj);\n    }\n    if (typeof obj === 'bigint') {\n        return String(obj) + 'n';\n    }\n\n    var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth;\n    if (typeof depth === 'undefined') { depth = 0; }\n    if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') {\n        return isArray(obj) ? '[Array]' : '[Object]';\n    }\n\n    var indent = getIndent(opts, depth);\n\n    if (typeof seen === 'undefined') {\n        seen = [];\n    } else if (indexOf(seen, obj) >= 0) {\n        return '[Circular]';\n    }\n\n    function inspect(value, from, noIndent) {\n        if (from) {\n            seen = seen.slice();\n            seen.push(from);\n        }\n        if (noIndent) {\n            var newOpts = {\n                depth: opts.depth\n            };\n            if (has(opts, 'quoteStyle')) {\n                newOpts.quoteStyle = opts.quoteStyle;\n            }\n            return inspect_(value, newOpts, depth + 1, seen);\n        }\n        return inspect_(value, opts, depth + 1, seen);\n    }\n\n    if (typeof obj === 'function') {\n        var name = nameOf(obj);\n        var keys = arrObjKeys(obj, inspect);\n        return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + keys.join(', ') + ' }' : '');\n    }\n    if (isSymbol(obj)) {\n        var symString = hasShammedSymbols ? String(obj).replace(/^(Symbol\\(.*\\))_[^)]*$/, '$1') : symToString.call(obj);\n        return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString;\n    }\n    if (isElement(obj)) {\n        var s = '<' + String(obj.nodeName).toLowerCase();\n        var attrs = obj.attributes || [];\n        for (var i = 0; i < attrs.length; i++) {\n            s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts);\n        }\n        s += '>';\n        if (obj.childNodes && obj.childNodes.length) { s += '...'; }\n        s += '</' + String(obj.nodeName).toLowerCase() + '>';\n        return s;\n    }\n    if (isArray(obj)) {\n        if (obj.length === 0) { return '[]'; }\n        var xs = arrObjKeys(obj, inspect);\n        if (indent && !singleLineValues(xs)) {\n            return '[' + indentedJoin(xs, indent) + ']';\n        }\n        return '[ ' + xs.join(', ') + ' ]';\n    }\n    if (isError(obj)) {\n        var parts = arrObjKeys(obj, inspect);\n        if (parts.length === 0) { return '[' + String(obj) + ']'; }\n        return '{ [' + String(obj) + '] ' + parts.join(', ') + ' }';\n    }\n    if (typeof obj === 'object' && customInspect) {\n        if (inspectSymbol && typeof obj[inspectSymbol] === 'function') {\n            return obj[inspectSymbol]();\n        } else if (typeof obj.inspect === 'function') {\n            return obj.inspect();\n        }\n    }\n    if (isMap(obj)) {\n        var mapParts = [];\n        mapForEach.call(obj, function (value, key) {\n            mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj));\n        });\n        return collectionOf('Map', mapSize.call(obj), mapParts, indent);\n    }\n    if (isSet(obj)) {\n        var setParts = [];\n        setForEach.call(obj, function (value) {\n            setParts.push(inspect(value, obj));\n        });\n        return collectionOf('Set', setSize.call(obj), setParts, indent);\n    }\n    if (isWeakMap(obj)) {\n        return weakCollectionOf('WeakMap');\n    }\n    if (isWeakSet(obj)) {\n        return weakCollectionOf('WeakSet');\n    }\n    if (isWeakRef(obj)) {\n        return weakCollectionOf('WeakRef');\n    }\n    if (isNumber(obj)) {\n        return markBoxed(inspect(Number(obj)));\n    }\n    if (isBigInt(obj)) {\n        return markBoxed(inspect(bigIntValueOf.call(obj)));\n    }\n    if (isBoolean(obj)) {\n        return markBoxed(booleanValueOf.call(obj));\n    }\n    if (isString(obj)) {\n        return markBoxed(inspect(String(obj)));\n    }\n    if (!isDate(obj) && !isRegExp(obj)) {\n        var ys = arrObjKeys(obj, inspect);\n        var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;\n        var protoTag = obj instanceof Object ? '' : 'null prototype';\n        var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? toStr(obj).slice(8, -1) : protoTag ? 'Object' : '';\n        var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : '';\n        var tag = constructorTag + (stringTag || protoTag ? '[' + [].concat(stringTag || [], protoTag || []).join(': ') + '] ' : '');\n        if (ys.length === 0) { return tag + '{}'; }\n        if (indent) {\n            return tag + '{' + indentedJoin(ys, indent) + '}';\n        }\n        return tag + '{ ' + ys.join(', ') + ' }';\n    }\n    return String(obj);\n};\n\nfunction wrapQuotes(s, defaultStyle, opts) {\n    var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '\"' : \"'\";\n    return quoteChar + s + quoteChar;\n}\n\nfunction quote(s) {\n    return String(s).replace(/\"/g, '&quot;');\n}\n\nfunction isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\nfunction isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }\n\n// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives\nfunction isSymbol(obj) {\n    if (hasShammedSymbols) {\n        return obj && typeof obj === 'object' && obj instanceof Symbol;\n    }\n    if (typeof obj === 'symbol') {\n        return true;\n    }\n    if (!obj || typeof obj !== 'object' || !symToString) {\n        return false;\n    }\n    try {\n        symToString.call(obj);\n        return true;\n    } catch (e) {}\n    return false;\n}\n\nfunction isBigInt(obj) {\n    if (!obj || typeof obj !== 'object' || !bigIntValueOf) {\n        return false;\n    }\n    try {\n        bigIntValueOf.call(obj);\n        return true;\n    } catch (e) {}\n    return false;\n}\n\nvar hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };\nfunction has(obj, key) {\n    return hasOwn.call(obj, key);\n}\n\nfunction toStr(obj) {\n    return objectToString.call(obj);\n}\n\nfunction nameOf(f) {\n    if (f.name) { return f.name; }\n    var m = match.call(functionToString.call(f), /^function\\s*([\\w$]+)/);\n    if (m) { return m[1]; }\n    return null;\n}\n\nfunction indexOf(xs, x) {\n    if (xs.indexOf) { return xs.indexOf(x); }\n    for (var i = 0, l = xs.length; i < l; i++) {\n        if (xs[i] === x) { return i; }\n    }\n    return -1;\n}\n\nfunction isMap(x) {\n    if (!mapSize || !x || typeof x !== 'object') {\n        return false;\n    }\n    try {\n        mapSize.call(x);\n        try {\n            setSize.call(x);\n        } catch (s) {\n            return true;\n        }\n        return x instanceof Map; // core-js workaround, pre-v2.5.0\n    } catch (e) {}\n    return false;\n}\n\nfunction isWeakMap(x) {\n    if (!weakMapHas || !x || typeof x !== 'object') {\n        return false;\n    }\n    try {\n        weakMapHas.call(x, weakMapHas);\n        try {\n            weakSetHas.call(x, weakSetHas);\n        } catch (s) {\n            return true;\n        }\n        return x instanceof WeakMap; // core-js workaround, pre-v2.5.0\n    } catch (e) {}\n    return false;\n}\n\nfunction isWeakRef(x) {\n    if (!weakRefDeref || !x || typeof x !== 'object') {\n        return false;\n    }\n    try {\n        weakRefDeref.call(x);\n        return true;\n    } catch (e) {}\n    return false;\n}\n\nfunction isSet(x) {\n    if (!setSize || !x || typeof x !== 'object') {\n        return false;\n    }\n    try {\n        setSize.call(x);\n        try {\n            mapSize.call(x);\n        } catch (m) {\n            return true;\n        }\n        return x instanceof Set; // core-js workaround, pre-v2.5.0\n    } catch (e) {}\n    return false;\n}\n\nfunction isWeakSet(x) {\n    if (!weakSetHas || !x || typeof x !== 'object') {\n        return false;\n    }\n    try {\n        weakSetHas.call(x, weakSetHas);\n        try {\n            weakMapHas.call(x, weakMapHas);\n        } catch (s) {\n            return true;\n        }\n        return x instanceof WeakSet; // core-js workaround, pre-v2.5.0\n    } catch (e) {}\n    return false;\n}\n\nfunction isElement(x) {\n    if (!x || typeof x !== 'object') { return false; }\n    if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) {\n        return true;\n    }\n    return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function';\n}\n\nfunction inspectString(str, opts) {\n    if (str.length > opts.maxStringLength) {\n        var remaining = str.length - opts.maxStringLength;\n        var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : '');\n        return inspectString(str.slice(0, opts.maxStringLength), opts) + trailer;\n    }\n    // eslint-disable-next-line no-control-regex\n    var s = str.replace(/(['\\\\])/g, '\\\\$1').replace(/[\\x00-\\x1f]/g, lowbyte);\n    return wrapQuotes(s, 'single', opts);\n}\n\nfunction lowbyte(c) {\n    var n = c.charCodeAt(0);\n    var x = {\n        8: 'b',\n        9: 't',\n        10: 'n',\n        12: 'f',\n        13: 'r'\n    }[n];\n    if (x) { return '\\\\' + x; }\n    return '\\\\x' + (n < 0x10 ? '0' : '') + n.toString(16).toUpperCase();\n}\n\nfunction markBoxed(str) {\n    return 'Object(' + str + ')';\n}\n\nfunction weakCollectionOf(type) {\n    return type + ' { ? }';\n}\n\nfunction collectionOf(type, size, entries, indent) {\n    var joinedEntries = indent ? indentedJoin(entries, indent) : entries.join(', ');\n    return type + ' (' + size + ') {' + joinedEntries + '}';\n}\n\nfunction singleLineValues(xs) {\n    for (var i = 0; i < xs.length; i++) {\n        if (indexOf(xs[i], '\\n') >= 0) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction getIndent(opts, depth) {\n    var baseIndent;\n    if (opts.indent === '\\t') {\n        baseIndent = '\\t';\n    } else if (typeof opts.indent === 'number' && opts.indent > 0) {\n        baseIndent = Array(opts.indent + 1).join(' ');\n    } else {\n        return null;\n    }\n    return {\n        base: baseIndent,\n        prev: Array(depth + 1).join(baseIndent)\n    };\n}\n\nfunction indentedJoin(xs, indent) {\n    if (xs.length === 0) { return ''; }\n    var lineJoiner = '\\n' + indent.prev + indent.base;\n    return lineJoiner + xs.join(',' + lineJoiner) + '\\n' + indent.prev;\n}\n\nfunction arrObjKeys(obj, inspect) {\n    var isArr = isArray(obj);\n    var xs = [];\n    if (isArr) {\n        xs.length = obj.length;\n        for (var i = 0; i < obj.length; i++) {\n            xs[i] = has(obj, i) ? inspect(obj[i], obj) : '';\n        }\n    }\n    var syms = typeof gOPS === 'function' ? gOPS(obj) : [];\n    var symMap;\n    if (hasShammedSymbols) {\n        symMap = {};\n        for (var k = 0; k < syms.length; k++) {\n            symMap['$' + syms[k]] = syms[k];\n        }\n    }\n\n    for (var key in obj) { // eslint-disable-line no-restricted-syntax\n        if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue\n        if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue\n        if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) {\n            // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section\n            continue; // eslint-disable-line no-restricted-syntax, no-continue\n        } else if ((/[^\\w$]/).test(key)) {\n            xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj));\n        } else {\n            xs.push(key + ': ' + inspect(obj[key], obj));\n        }\n    }\n    if (typeof gOPS === 'function') {\n        for (var j = 0; j < syms.length; j++) {\n            if (isEnumerable.call(obj, syms[j])) {\n                xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj));\n            }\n        }\n    }\n    return xs;\n}\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._U = 0;\n  this._V = 0;\n  this._W = null;\n  this._X = null;\n  if (fn === noop) return;\n  doResolve(fn, this);\n}\nPromise._Y = null;\nPromise._Z = null;\nPromise._0 = 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._V === 3) {\n    self = self._W;\n  }\n  if (Promise._Y) {\n    Promise._Y(self);\n  }\n  if (self._V === 0) {\n    if (self._U === 0) {\n      self._U = 1;\n      self._X = deferred;\n      return;\n    }\n    if (self._U === 1) {\n      self._U = 2;\n      self._X = [self._X, deferred];\n      return;\n    }\n    self._X.push(deferred);\n    return;\n  }\n  handleResolved(self, deferred);\n}\n\nfunction handleResolved(self, deferred) {\n  asap(function() {\n    var cb = self._V === 1 ? deferred.onFulfilled : deferred.onRejected;\n    if (cb === null) {\n      if (self._V === 1) {\n        resolve(deferred.promise, self._W);\n      } else {\n        reject(deferred.promise, self._W);\n      }\n      return;\n    }\n    var ret = tryCallOne(cb, self._W);\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._V = 3;\n      self._W = newValue;\n      finale(self);\n      return;\n    } else if (typeof then === 'function') {\n      doResolve(then.bind(newValue), self);\n      return;\n    }\n  }\n  self._V = 1;\n  self._W = newValue;\n  finale(self);\n}\n\nfunction reject(self, newValue) {\n  self._V = 2;\n  self._W = newValue;\n  if (Promise._Z) {\n    Promise._Z(self, newValue);\n  }\n  finale(self);\n}\nfunction finale(self) {\n  if (self._U === 1) {\n    handle(self, self._X);\n    self._X = null;\n  }\n  if (self._U === 2) {\n    for (var i = 0; i < self._X.length; i++) {\n      handle(self, self._X[i]);\n    }\n    self._X = 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._0);\n  p._V = 1;\n  p._W = 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\nvar iterableToArray = function (iterable) {\n  if (typeof Array.from === 'function') {\n    // ES2015+, iterables exist\n    iterableToArray = Array.from;\n    return Array.from(iterable);\n  }\n\n  // ES5, only arrays and array-likes exist\n  iterableToArray = function (x) { return Array.prototype.slice.call(x); };\n  return Array.prototype.slice.call(iterable);\n}\n\nPromise.all = function (arr) {\n  var args = iterableToArray(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._V === 3) {\n            val = val._W;\n          }\n          if (val._V === 1) return res(i, val._W);\n          if (val._V === 2) reject(val._W);\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    iterableToArray(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._V === 3) {\n      return this._W.getValue();\n    }\n\n    if (!this.isFulfilled()) {\n      throw new Error('Cannot get a value of an unfulfilled promise.');\n    }\n\n    return this._W;\n  };\n\n  Promise.prototype.getReason = function () {\n    if (this._V === 3) {\n      return this._W.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._W;\n  };\n\n  Promise.prototype.getState = function () {\n    if (this._V === 3) {\n      return this._W.getState();\n    }\n    if (this._V === -1 || this._V === -2) {\n      return 0;\n    }\n\n    return this._V;\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","/*! https://mths.be/punycode v1.3.2 by @mathias */\n;(function(root) {\n\n\t/** Detect free variables */\n\tvar freeExports = typeof exports == 'object' && exports &&\n\t\t!exports.nodeType && exports;\n\tvar freeModule = typeof module == 'object' && module &&\n\t\t!module.nodeType && module;\n\tvar freeGlobal = typeof global == 'object' && global;\n\tif (\n\t\tfreeGlobal.global === freeGlobal ||\n\t\tfreeGlobal.window === freeGlobal ||\n\t\tfreeGlobal.self === freeGlobal\n\t) {\n\t\troot = freeGlobal;\n\t}\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexPunycode = /^xn--/,\n\tregexNonASCII = /[^\\x20-\\x7E]/, // unprintable ASCII chars + non-ASCII chars\n\tregexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g, // RFC 3490 separators\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\tvar result = [];\n\t\twhile (length--) {\n\t\t\tresult[length] = fn(array[length]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings or email\n\t * addresses.\n\t * @private\n\t * @param {String} domain The domain name or email address.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar parts = string.split('@');\n\t\tvar result = '';\n\t\tif (parts.length > 1) {\n\t\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t\t// the local part (i.e. everything up to `@`) intact.\n\t\t\tresult = parts[0] + '@';\n\t\t\tstring = parts[1];\n\t\t}\n\t\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\t\tstring = string.replace(regexSeparators, '\\x2E');\n\t\tvar labels = string.split('.');\n\t\tvar encoded = map(labels, fn).join('.');\n\t\treturn result + encoded;\n\t}\n\n\t/**\n\t * Creates an array containing the numeric code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see <https://mathiasbynens.be/notes/javascript-encoding>\n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t    counter = 0,\n\t\t    length = string.length,\n\t\t    value,\n\t\t    extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t\t// high surrogate, and there is a next character\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((extra & 0xFC00) == 0xDC00) { // low surrogate\n\t\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t\t} else {\n\t\t\t\t\t// unmatched surrogate; only append this code unit, in case the next\n\t\t\t\t\t// code unit is the high surrogate of a surrogate pair\n\t\t\t\t\toutput.push(value);\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toutput.push(value);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of numeric code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of numeric code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic numeric code point value.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\tif (codePoint - 48 < 10) {\n\t\t\treturn codePoint - 22;\n\t\t}\n\t\tif (codePoint - 65 < 26) {\n\t\t\treturn codePoint - 65;\n\t\t}\n\t\tif (codePoint - 97 < 26) {\n\t\t\treturn codePoint - 97;\n\t\t}\n\t\treturn base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if `flag` is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t//  0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * http://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n\t * symbols.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII-only symbols.\n\t * @returns {String} The resulting string of Unicode symbols.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t    inputLength = input.length,\n\t\t    out,\n\t\t    i = 0,\n\t\t    n = initialN,\n\t\t    bias = initialBias,\n\t\t    basic,\n\t\t    j,\n\t\t    index,\n\t\t    oldi,\n\t\t    w,\n\t\t    k,\n\t\t    digit,\n\t\t    t,\n\t\t    /** Cached calculation results */\n\t\t    baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode symbols (e.g. a domain name label) to a\n\t * Punycode string of ASCII-only symbols.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode symbols.\n\t * @returns {String} The resulting Punycode string of ASCII-only symbols.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t    delta,\n\t\t    handledCPCount,\n\t\t    basicLength,\n\t\t    bias,\n\t\t    j,\n\t\t    m,\n\t\t    q,\n\t\t    k,\n\t\t    t,\n\t\t    currentValue,\n\t\t    output = [],\n\t\t    /** `inputLength` will hold the number of code points in `input`. */\n\t\t    inputLength,\n\t\t    /** Cached calculation results */\n\t\t    handledCPCountPlusOne,\n\t\t    baseMinusT,\n\t\t    qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name or an email address\n\t * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n\t * it doesn't matter if you call it on a string that has already been\n\t * converted to Unicode.\n\t * @memberOf punycode\n\t * @param {String} input The Punycoded domain name or email address to\n\t * convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name or an email address to\n\t * Punycode. Only the non-ASCII parts of the domain name will be converted,\n\t * i.e. it doesn't matter if you call it with a domain that's already in\n\t * ASCII.\n\t * @memberOf punycode\n\t * @param {String} input The domain name or email address to convert, as a\n\t * Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name or\n\t * email address.\n\t */\n\tfunction toASCII(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.3.2',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to Unicode code points, and back.\n\t\t * @see <https://mathiasbynens.be/notes/javascript-encoding>\n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\t// Some AMD build optimizers, like r.js, check for specific condition patterns\n\t// like the following:\n\tif (\n\t\ttypeof define == 'function' &&\n\t\ttypeof define.amd == 'object' &&\n\t\tdefine.amd\n\t) {\n\t\tdefine('punycode', function() {\n\t\t\treturn punycode;\n\t\t});\n\t} else if (freeExports && freeModule) {\n\t\tif (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else { // in Narwhal or RingoJS v0.7.0-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else { // in Rhino or a web browser\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n","'use strict';\n\nvar replace = String.prototype.replace;\nvar percentTwenties = /%20/g;\n\nvar Format = {\n    RFC1738: 'RFC1738',\n    RFC3986: 'RFC3986'\n};\n\nmodule.exports = {\n    'default': Format.RFC3986,\n    formatters: {\n        RFC1738: function (value) {\n            return replace.call(value, percentTwenties, '+');\n        },\n        RFC3986: function (value) {\n            return String(value);\n        }\n    },\n    RFC1738: Format.RFC1738,\n    RFC3986: Format.RFC3986\n};\n","'use strict';\n\nvar stringify = require('./stringify');\nvar parse = require('./parse');\nvar formats = require('./formats');\n\nmodule.exports = {\n    formats: formats,\n    parse: parse,\n    stringify: stringify\n};\n","'use strict';\n\nvar utils = require('./utils');\n\nvar has = Object.prototype.hasOwnProperty;\nvar isArray = Array.isArray;\n\nvar defaults = {\n    allowDots: false,\n    allowPrototypes: false,\n    allowSparse: false,\n    arrayLimit: 20,\n    charset: 'utf-8',\n    charsetSentinel: false,\n    comma: false,\n    decoder: utils.decode,\n    delimiter: '&',\n    depth: 5,\n    ignoreQueryPrefix: false,\n    interpretNumericEntities: false,\n    parameterLimit: 1000,\n    parseArrays: true,\n    plainObjects: false,\n    strictNullHandling: false\n};\n\nvar interpretNumericEntities = function (str) {\n    return str.replace(/&#(\\d+);/g, function ($0, numberStr) {\n        return String.fromCharCode(parseInt(numberStr, 10));\n    });\n};\n\nvar parseArrayValue = function (val, options) {\n    if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {\n        return val.split(',');\n    }\n\n    return val;\n};\n\n// This is what browsers will submit when the ✓ character occurs in an\n// application/x-www-form-urlencoded body and the encoding of the page containing\n// the form is iso-8859-1, or when the submitted form has an accept-charset\n// attribute of iso-8859-1. Presumably also with other charsets that do not contain\n// the ✓ character, such as us-ascii.\nvar isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('&#10003;')\n\n// These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.\nvar charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')\n\nvar parseValues = function parseQueryStringValues(str, options) {\n    var obj = {};\n    var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\\?/, '') : str;\n    var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;\n    var parts = cleanStr.split(options.delimiter, limit);\n    var skipIndex = -1; // Keep track of where the utf8 sentinel was found\n    var i;\n\n    var charset = options.charset;\n    if (options.charsetSentinel) {\n        for (i = 0; i < parts.length; ++i) {\n            if (parts[i].indexOf('utf8=') === 0) {\n                if (parts[i] === charsetSentinel) {\n                    charset = 'utf-8';\n                } else if (parts[i] === isoSentinel) {\n                    charset = 'iso-8859-1';\n                }\n                skipIndex = i;\n                i = parts.length; // The eslint settings do not allow break;\n            }\n        }\n    }\n\n    for (i = 0; i < parts.length; ++i) {\n        if (i === skipIndex) {\n            continue;\n        }\n        var part = parts[i];\n\n        var bracketEqualsPos = part.indexOf(']=');\n        var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1;\n\n        var key, val;\n        if (pos === -1) {\n            key = options.decoder(part, defaults.decoder, charset, 'key');\n            val = options.strictNullHandling ? null : '';\n        } else {\n            key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');\n            val = utils.maybeMap(\n                parseArrayValue(part.slice(pos + 1), options),\n                function (encodedVal) {\n                    return options.decoder(encodedVal, defaults.decoder, charset, 'value');\n                }\n            );\n        }\n\n        if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {\n            val = interpretNumericEntities(val);\n        }\n\n        if (part.indexOf('[]=') > -1) {\n            val = isArray(val) ? [val] : val;\n        }\n\n        if (has.call(obj, key)) {\n            obj[key] = utils.combine(obj[key], val);\n        } else {\n            obj[key] = val;\n        }\n    }\n\n    return obj;\n};\n\nvar parseObject = function (chain, val, options, valuesParsed) {\n    var leaf = valuesParsed ? val : parseArrayValue(val, options);\n\n    for (var i = chain.length - 1; i >= 0; --i) {\n        var obj;\n        var root = chain[i];\n\n        if (root === '[]' && options.parseArrays) {\n            obj = [].concat(leaf);\n        } else {\n            obj = options.plainObjects ? Object.create(null) : {};\n            var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;\n            var index = parseInt(cleanRoot, 10);\n            if (!options.parseArrays && cleanRoot === '') {\n                obj = { 0: leaf };\n            } else if (\n                !isNaN(index)\n                && root !== cleanRoot\n                && String(index) === cleanRoot\n                && index >= 0\n                && (options.parseArrays && index <= options.arrayLimit)\n            ) {\n                obj = [];\n                obj[index] = leaf;\n            } else {\n                obj[cleanRoot] = leaf;\n            }\n        }\n\n        leaf = obj;\n    }\n\n    return leaf;\n};\n\nvar parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {\n    if (!givenKey) {\n        return;\n    }\n\n    // Transform dot notation to bracket notation\n    var key = options.allowDots ? givenKey.replace(/\\.([^.[]+)/g, '[$1]') : givenKey;\n\n    // The regex chunks\n\n    var brackets = /(\\[[^[\\]]*])/;\n    var child = /(\\[[^[\\]]*])/g;\n\n    // Get the parent\n\n    var segment = options.depth > 0 && brackets.exec(key);\n    var parent = segment ? key.slice(0, segment.index) : key;\n\n    // Stash the parent if it exists\n\n    var keys = [];\n    if (parent) {\n        // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties\n        if (!options.plainObjects && has.call(Object.prototype, parent)) {\n            if (!options.allowPrototypes) {\n                return;\n            }\n        }\n\n        keys.push(parent);\n    }\n\n    // Loop through children appending to the array until we hit depth\n\n    var i = 0;\n    while (options.depth > 0 && (segment = child.exec(key)) !== null && i < options.depth) {\n        i += 1;\n        if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) {\n            if (!options.allowPrototypes) {\n                return;\n            }\n        }\n        keys.push(segment[1]);\n    }\n\n    // If there's a remainder, just add whatever is left\n\n    if (segment) {\n        keys.push('[' + key.slice(segment.index) + ']');\n    }\n\n    return parseObject(keys, val, options, valuesParsed);\n};\n\nvar normalizeParseOptions = function normalizeParseOptions(opts) {\n    if (!opts) {\n        return defaults;\n    }\n\n    if (opts.decoder !== null && opts.decoder !== undefined && typeof opts.decoder !== 'function') {\n        throw new TypeError('Decoder has to be a function.');\n    }\n\n    if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {\n        throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');\n    }\n    var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;\n\n    return {\n        allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,\n        allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes,\n        allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse,\n        arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit,\n        charset: charset,\n        charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,\n        comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma,\n        decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder,\n        delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter,\n        // eslint-disable-next-line no-implicit-coercion, no-extra-parens\n        depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth,\n        ignoreQueryPrefix: opts.ignoreQueryPrefix === true,\n        interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities,\n        parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit,\n        parseArrays: opts.parseArrays !== false,\n        plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,\n        strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling\n    };\n};\n\nmodule.exports = function (str, opts) {\n    var options = normalizeParseOptions(opts);\n\n    if (str === '' || str === null || typeof str === 'undefined') {\n        return options.plainObjects ? Object.create(null) : {};\n    }\n\n    var tempObj = typeof str === 'string' ? parseValues(str, options) : str;\n    var obj = options.plainObjects ? Object.create(null) : {};\n\n    // Iterate over the keys and setup the new object\n\n    var keys = Object.keys(tempObj);\n    for (var i = 0; i < keys.length; ++i) {\n        var key = keys[i];\n        var newObj = parseKeys(key, tempObj[key], options, typeof str === 'string');\n        obj = utils.merge(obj, newObj, options);\n    }\n\n    if (options.allowSparse === true) {\n        return obj;\n    }\n\n    return utils.compact(obj);\n};\n","'use strict';\n\nvar getSideChannel = require('side-channel');\nvar utils = require('./utils');\nvar formats = require('./formats');\nvar has = Object.prototype.hasOwnProperty;\n\nvar arrayPrefixGenerators = {\n    brackets: function brackets(prefix) {\n        return prefix + '[]';\n    },\n    comma: 'comma',\n    indices: function indices(prefix, key) {\n        return prefix + '[' + key + ']';\n    },\n    repeat: function repeat(prefix) {\n        return prefix;\n    }\n};\n\nvar isArray = Array.isArray;\nvar push = Array.prototype.push;\nvar pushToArray = function (arr, valueOrArray) {\n    push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);\n};\n\nvar toISO = Date.prototype.toISOString;\n\nvar defaultFormat = formats['default'];\nvar defaults = {\n    addQueryPrefix: false,\n    allowDots: false,\n    charset: 'utf-8',\n    charsetSentinel: false,\n    delimiter: '&',\n    encode: true,\n    encoder: utils.encode,\n    encodeValuesOnly: false,\n    format: defaultFormat,\n    formatter: formats.formatters[defaultFormat],\n    // deprecated\n    indices: false,\n    serializeDate: function serializeDate(date) {\n        return toISO.call(date);\n    },\n    skipNulls: false,\n    strictNullHandling: false\n};\n\nvar isNonNullishPrimitive = function isNonNullishPrimitive(v) {\n    return typeof v === 'string'\n        || typeof v === 'number'\n        || typeof v === 'boolean'\n        || typeof v === 'symbol'\n        || typeof v === 'bigint';\n};\n\nvar stringify = function stringify(\n    object,\n    prefix,\n    generateArrayPrefix,\n    strictNullHandling,\n    skipNulls,\n    encoder,\n    filter,\n    sort,\n    allowDots,\n    serializeDate,\n    format,\n    formatter,\n    encodeValuesOnly,\n    charset,\n    sideChannel\n) {\n    var obj = object;\n\n    if (sideChannel.has(object)) {\n        throw new RangeError('Cyclic object value');\n    }\n\n    if (typeof filter === 'function') {\n        obj = filter(prefix, obj);\n    } else if (obj instanceof Date) {\n        obj = serializeDate(obj);\n    } else if (generateArrayPrefix === 'comma' && isArray(obj)) {\n        obj = utils.maybeMap(obj, function (value) {\n            if (value instanceof Date) {\n                return serializeDate(value);\n            }\n            return value;\n        });\n    }\n\n    if (obj === null) {\n        if (strictNullHandling) {\n            return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix;\n        }\n\n        obj = '';\n    }\n\n    if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {\n        if (encoder) {\n            var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);\n            return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];\n        }\n        return [formatter(prefix) + '=' + formatter(String(obj))];\n    }\n\n    var values = [];\n\n    if (typeof obj === 'undefined') {\n        return values;\n    }\n\n    var objKeys;\n    if (generateArrayPrefix === 'comma' && isArray(obj)) {\n        // we need to join elements in\n        objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : undefined }];\n    } else if (isArray(filter)) {\n        objKeys = filter;\n    } else {\n        var keys = Object.keys(obj);\n        objKeys = sort ? keys.sort(sort) : keys;\n    }\n\n    for (var i = 0; i < objKeys.length; ++i) {\n        var key = objKeys[i];\n        var value = typeof key === 'object' && key.value !== undefined ? key.value : obj[key];\n\n        if (skipNulls && value === null) {\n            continue;\n        }\n\n        var keyPrefix = isArray(obj)\n            ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix\n            : prefix + (allowDots ? '.' + key : '[' + key + ']');\n\n        sideChannel.set(object, true);\n        var valueSideChannel = getSideChannel();\n        pushToArray(values, stringify(\n            value,\n            keyPrefix,\n            generateArrayPrefix,\n            strictNullHandling,\n            skipNulls,\n            encoder,\n            filter,\n            sort,\n            allowDots,\n            serializeDate,\n            format,\n            formatter,\n            encodeValuesOnly,\n            charset,\n            valueSideChannel\n        ));\n    }\n\n    return values;\n};\n\nvar normalizeStringifyOptions = function normalizeStringifyOptions(opts) {\n    if (!opts) {\n        return defaults;\n    }\n\n    if (opts.encoder !== null && opts.encoder !== undefined && typeof opts.encoder !== 'function') {\n        throw new TypeError('Encoder has to be a function.');\n    }\n\n    var charset = opts.charset || defaults.charset;\n    if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {\n        throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');\n    }\n\n    var format = formats['default'];\n    if (typeof opts.format !== 'undefined') {\n        if (!has.call(formats.formatters, opts.format)) {\n            throw new TypeError('Unknown format option provided.');\n        }\n        format = opts.format;\n    }\n    var formatter = formats.formatters[format];\n\n    var filter = defaults.filter;\n    if (typeof opts.filter === 'function' || isArray(opts.filter)) {\n        filter = opts.filter;\n    }\n\n    return {\n        addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,\n        allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,\n        charset: charset,\n        charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,\n        delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,\n        encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,\n        encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,\n        encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,\n        filter: filter,\n        format: format,\n        formatter: formatter,\n        serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,\n        skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,\n        sort: typeof opts.sort === 'function' ? opts.sort : null,\n        strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling\n    };\n};\n\nmodule.exports = function (object, opts) {\n    var obj = object;\n    var options = normalizeStringifyOptions(opts);\n\n    var objKeys;\n    var filter;\n\n    if (typeof options.filter === 'function') {\n        filter = options.filter;\n        obj = filter('', obj);\n    } else if (isArray(options.filter)) {\n        filter = options.filter;\n        objKeys = filter;\n    }\n\n    var keys = [];\n\n    if (typeof obj !== 'object' || obj === null) {\n        return '';\n    }\n\n    var arrayFormat;\n    if (opts && opts.arrayFormat in arrayPrefixGenerators) {\n        arrayFormat = opts.arrayFormat;\n    } else if (opts && 'indices' in opts) {\n        arrayFormat = opts.indices ? 'indices' : 'repeat';\n    } else {\n        arrayFormat = 'indices';\n    }\n\n    var generateArrayPrefix = arrayPrefixGenerators[arrayFormat];\n\n    if (!objKeys) {\n        objKeys = Object.keys(obj);\n    }\n\n    if (options.sort) {\n        objKeys.sort(options.sort);\n    }\n\n    var sideChannel = getSideChannel();\n    for (var i = 0; i < objKeys.length; ++i) {\n        var key = objKeys[i];\n\n        if (options.skipNulls && obj[key] === null) {\n            continue;\n        }\n        pushToArray(keys, stringify(\n            obj[key],\n            key,\n            generateArrayPrefix,\n            options.strictNullHandling,\n            options.skipNulls,\n            options.encode ? options.encoder : null,\n            options.filter,\n            options.sort,\n            options.allowDots,\n            options.serializeDate,\n            options.format,\n            options.formatter,\n            options.encodeValuesOnly,\n            options.charset,\n            sideChannel\n        ));\n    }\n\n    var joined = keys.join(options.delimiter);\n    var prefix = options.addQueryPrefix === true ? '?' : '';\n\n    if (options.charsetSentinel) {\n        if (options.charset === 'iso-8859-1') {\n            // encodeURIComponent('&#10003;'), the \"numeric entity\" representation of a checkmark\n            prefix += 'utf8=%26%2310003%3B&';\n        } else {\n            // encodeURIComponent('✓')\n            prefix += 'utf8=%E2%9C%93&';\n        }\n    }\n\n    return joined.length > 0 ? prefix + joined : '';\n};\n","'use strict';\n\nvar formats = require('./formats');\n\nvar has = Object.prototype.hasOwnProperty;\nvar isArray = Array.isArray;\n\nvar hexTable = (function () {\n    var array = [];\n    for (var i = 0; i < 256; ++i) {\n        array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());\n    }\n\n    return array;\n}());\n\nvar compactQueue = function compactQueue(queue) {\n    while (queue.length > 1) {\n        var item = queue.pop();\n        var obj = item.obj[item.prop];\n\n        if (isArray(obj)) {\n            var compacted = [];\n\n            for (var j = 0; j < obj.length; ++j) {\n                if (typeof obj[j] !== 'undefined') {\n                    compacted.push(obj[j]);\n                }\n            }\n\n            item.obj[item.prop] = compacted;\n        }\n    }\n};\n\nvar arrayToObject = function arrayToObject(source, options) {\n    var obj = options && options.plainObjects ? Object.create(null) : {};\n    for (var i = 0; i < source.length; ++i) {\n        if (typeof source[i] !== 'undefined') {\n            obj[i] = source[i];\n        }\n    }\n\n    return obj;\n};\n\nvar merge = function merge(target, source, options) {\n    /* eslint no-param-reassign: 0 */\n    if (!source) {\n        return target;\n    }\n\n    if (typeof source !== 'object') {\n        if (isArray(target)) {\n            target.push(source);\n        } else if (target && typeof target === 'object') {\n            if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {\n                target[source] = true;\n            }\n        } else {\n            return [target, source];\n        }\n\n        return target;\n    }\n\n    if (!target || typeof target !== 'object') {\n        return [target].concat(source);\n    }\n\n    var mergeTarget = target;\n    if (isArray(target) && !isArray(source)) {\n        mergeTarget = arrayToObject(target, options);\n    }\n\n    if (isArray(target) && isArray(source)) {\n        source.forEach(function (item, i) {\n            if (has.call(target, i)) {\n                var targetItem = target[i];\n                if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {\n                    target[i] = merge(targetItem, item, options);\n                } else {\n                    target.push(item);\n                }\n            } else {\n                target[i] = item;\n            }\n        });\n        return target;\n    }\n\n    return Object.keys(source).reduce(function (acc, key) {\n        var value = source[key];\n\n        if (has.call(acc, key)) {\n            acc[key] = merge(acc[key], value, options);\n        } else {\n            acc[key] = value;\n        }\n        return acc;\n    }, mergeTarget);\n};\n\nvar assign = function assignSingleSource(target, source) {\n    return Object.keys(source).reduce(function (acc, key) {\n        acc[key] = source[key];\n        return acc;\n    }, target);\n};\n\nvar decode = function (str, decoder, charset) {\n    var strWithoutPlus = str.replace(/\\+/g, ' ');\n    if (charset === 'iso-8859-1') {\n        // unescape never throws, no try...catch needed:\n        return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);\n    }\n    // utf-8\n    try {\n        return decodeURIComponent(strWithoutPlus);\n    } catch (e) {\n        return strWithoutPlus;\n    }\n};\n\nvar encode = function encode(str, defaultEncoder, charset, kind, format) {\n    // This code was originally written by Brian White (mscdex) for the io.js core querystring library.\n    // It has been adapted here for stricter adherence to RFC 3986\n    if (str.length === 0) {\n        return str;\n    }\n\n    var string = str;\n    if (typeof str === 'symbol') {\n        string = Symbol.prototype.toString.call(str);\n    } else if (typeof str !== 'string') {\n        string = String(str);\n    }\n\n    if (charset === 'iso-8859-1') {\n        return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {\n            return '%26%23' + parseInt($0.slice(2), 16) + '%3B';\n        });\n    }\n\n    var out = '';\n    for (var i = 0; i < string.length; ++i) {\n        var c = string.charCodeAt(i);\n\n        if (\n            c === 0x2D // -\n            || c === 0x2E // .\n            || c === 0x5F // _\n            || c === 0x7E // ~\n            || (c >= 0x30 && c <= 0x39) // 0-9\n            || (c >= 0x41 && c <= 0x5A) // a-z\n            || (c >= 0x61 && c <= 0x7A) // A-Z\n            || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( )\n        ) {\n            out += string.charAt(i);\n            continue;\n        }\n\n        if (c < 0x80) {\n            out = out + hexTable[c];\n            continue;\n        }\n\n        if (c < 0x800) {\n            out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]);\n            continue;\n        }\n\n        if (c < 0xD800 || c >= 0xE000) {\n            out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]);\n            continue;\n        }\n\n        i += 1;\n        c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));\n        out += hexTable[0xF0 | (c >> 18)]\n            + hexTable[0x80 | ((c >> 12) & 0x3F)]\n            + hexTable[0x80 | ((c >> 6) & 0x3F)]\n            + hexTable[0x80 | (c & 0x3F)];\n    }\n\n    return out;\n};\n\nvar compact = function compact(value) {\n    var queue = [{ obj: { o: value }, prop: 'o' }];\n    var refs = [];\n\n    for (var i = 0; i < queue.length; ++i) {\n        var item = queue[i];\n        var obj = item.obj[item.prop];\n\n        var keys = Object.keys(obj);\n        for (var j = 0; j < keys.length; ++j) {\n            var key = keys[j];\n            var val = obj[key];\n            if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {\n                queue.push({ obj: obj, prop: key });\n                refs.push(val);\n            }\n        }\n    }\n\n    compactQueue(queue);\n\n    return value;\n};\n\nvar isRegExp = function isRegExp(obj) {\n    return Object.prototype.toString.call(obj) === '[object RegExp]';\n};\n\nvar isBuffer = function isBuffer(obj) {\n    if (!obj || typeof obj !== 'object') {\n        return false;\n    }\n\n    return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));\n};\n\nvar combine = function combine(a, b) {\n    return [].concat(a, b);\n};\n\nvar maybeMap = function maybeMap(val, fn) {\n    if (isArray(val)) {\n        var mapped = [];\n        for (var i = 0; i < val.length; i += 1) {\n            mapped.push(fn(val[i]));\n        }\n        return mapped;\n    }\n    return fn(val);\n};\n\nmodule.exports = {\n    arrayToObject: arrayToObject,\n    assign: assign,\n    combine: combine,\n    compact: compact,\n    decode: decode,\n    encode: encode,\n    isBuffer: isBuffer,\n    isRegExp: isRegExp,\n    maybeMap: maybeMap,\n    merge: merge\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\n// If obj.hasOwnProperty has been overridden, then calling\n// obj.hasOwnProperty(prop) will break.\n// See: https://github.com/joyent/node/issues/1707\nfunction hasOwnProperty(obj, prop) {\n  return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nmodule.exports = function(qs, sep, eq, options) {\n  sep = sep || '&';\n  eq = eq || '=';\n  var obj = {};\n\n  if (typeof qs !== 'string' || qs.length === 0) {\n    return obj;\n  }\n\n  var regexp = /\\+/g;\n  qs = qs.split(sep);\n\n  var maxKeys = 1000;\n  if (options && typeof options.maxKeys === 'number') {\n    maxKeys = options.maxKeys;\n  }\n\n  var len = qs.length;\n  // maxKeys <= 0 means that we should not limit keys count\n  if (maxKeys > 0 && len > maxKeys) {\n    len = maxKeys;\n  }\n\n  for (var i = 0; i < len; ++i) {\n    var x = qs[i].replace(regexp, '%20'),\n        idx = x.indexOf(eq),\n        kstr, vstr, k, v;\n\n    if (idx >= 0) {\n      kstr = x.substr(0, idx);\n      vstr = x.substr(idx + 1);\n    } else {\n      kstr = x;\n      vstr = '';\n    }\n\n    k = decodeURIComponent(kstr);\n    v = decodeURIComponent(vstr);\n\n    if (!hasOwnProperty(obj, k)) {\n      obj[k] = v;\n    } else if (isArray(obj[k])) {\n      obj[k].push(v);\n    } else {\n      obj[k] = [obj[k], v];\n    }\n  }\n\n  return obj;\n};\n\nvar isArray = Array.isArray || function (xs) {\n  return Object.prototype.toString.call(xs) === '[object Array]';\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar stringifyPrimitive = function(v) {\n  switch (typeof v) {\n    case 'string':\n      return v;\n\n    case 'boolean':\n      return v ? 'true' : 'false';\n\n    case 'number':\n      return isFinite(v) ? v : '';\n\n    default:\n      return '';\n  }\n};\n\nmodule.exports = function(obj, sep, eq, name) {\n  sep = sep || '&';\n  eq = eq || '=';\n  if (obj === null) {\n    obj = undefined;\n  }\n\n  if (typeof obj === 'object') {\n    return map(objectKeys(obj), function(k) {\n      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;\n      if (isArray(obj[k])) {\n        return map(obj[k], function(v) {\n          return ks + encodeURIComponent(stringifyPrimitive(v));\n        }).join(sep);\n      } else {\n        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));\n      }\n    }).join(sep);\n\n  }\n\n  if (!name) return '';\n  return encodeURIComponent(stringifyPrimitive(name)) + eq +\n         encodeURIComponent(stringifyPrimitive(obj));\n};\n\nvar isArray = Array.isArray || function (xs) {\n  return Object.prototype.toString.call(xs) === '[object Array]';\n};\n\nfunction map (xs, f) {\n  if (xs.map) return xs.map(f);\n  var res = [];\n  for (var i = 0; i < xs.length; i++) {\n    res.push(f(xs[i], i));\n  }\n  return res;\n}\n\nvar objectKeys = Object.keys || function (obj) {\n  var res = [];\n  for (var key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);\n  }\n  return res;\n};\n","'use strict';\n\nexports.decode = exports.parse = require('./decode');\nexports.encode = exports.stringify = require('./encode');\n","'use strict';\n\nvar GetIntrinsic = require('get-intrinsic');\nvar callBound = require('call-bind/callBound');\nvar inspect = require('object-inspect');\n\nvar $TypeError = GetIntrinsic('%TypeError%');\nvar $WeakMap = GetIntrinsic('%WeakMap%', true);\nvar $Map = GetIntrinsic('%Map%', true);\n\nvar $weakMapGet = callBound('WeakMap.prototype.get', true);\nvar $weakMapSet = callBound('WeakMap.prototype.set', true);\nvar $weakMapHas = callBound('WeakMap.prototype.has', true);\nvar $mapGet = callBound('Map.prototype.get', true);\nvar $mapSet = callBound('Map.prototype.set', true);\nvar $mapHas = callBound('Map.prototype.has', true);\n\n/*\n * This function traverses the list returning the node corresponding to the\n * given key.\n *\n * That node is also moved to the head of the list, so that if it's accessed\n * again we don't need to traverse the whole list. By doing so, all the recently\n * used nodes can be accessed relatively quickly.\n */\nvar listGetNode = function (list, key) { // eslint-disable-line consistent-return\n\tfor (var prev = list, curr; (curr = prev.next) !== null; prev = curr) {\n\t\tif (curr.key === key) {\n\t\t\tprev.next = curr.next;\n\t\t\tcurr.next = list.next;\n\t\t\tlist.next = curr; // eslint-disable-line no-param-reassign\n\t\t\treturn curr;\n\t\t}\n\t}\n};\n\nvar listGet = function (objects, key) {\n\tvar node = listGetNode(objects, key);\n\treturn node && node.value;\n};\nvar listSet = function (objects, key, value) {\n\tvar node = listGetNode(objects, key);\n\tif (node) {\n\t\tnode.value = value;\n\t} else {\n\t\t// Prepend the new node to the beginning of the list\n\t\tobjects.next = { // eslint-disable-line no-param-reassign\n\t\t\tkey: key,\n\t\t\tnext: objects.next,\n\t\t\tvalue: value\n\t\t};\n\t}\n};\nvar listHas = function (objects, key) {\n\treturn !!listGetNode(objects, key);\n};\n\nmodule.exports = function getSideChannel() {\n\tvar $wm;\n\tvar $m;\n\tvar $o;\n\tvar channel = {\n\t\tassert: function (key) {\n\t\t\tif (!channel.has(key)) {\n\t\t\t\tthrow new $TypeError('Side channel does not contain ' + inspect(key));\n\t\t\t}\n\t\t},\n\t\tget: function (key) { // eslint-disable-line consistent-return\n\t\t\tif ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {\n\t\t\t\tif ($wm) {\n\t\t\t\t\treturn $weakMapGet($wm, key);\n\t\t\t\t}\n\t\t\t} else if ($Map) {\n\t\t\t\tif ($m) {\n\t\t\t\t\treturn $mapGet($m, key);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ($o) { // eslint-disable-line no-lonely-if\n\t\t\t\t\treturn listGet($o, key);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thas: function (key) {\n\t\t\tif ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {\n\t\t\t\tif ($wm) {\n\t\t\t\t\treturn $weakMapHas($wm, key);\n\t\t\t\t}\n\t\t\t} else if ($Map) {\n\t\t\t\tif ($m) {\n\t\t\t\t\treturn $mapHas($m, key);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ($o) { // eslint-disable-line no-lonely-if\n\t\t\t\t\treturn listHas($o, key);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tset: function (key, value) {\n\t\t\tif ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {\n\t\t\t\tif (!$wm) {\n\t\t\t\t\t$wm = new $WeakMap();\n\t\t\t\t}\n\t\t\t\t$weakMapSet($wm, key, value);\n\t\t\t} else if ($Map) {\n\t\t\t\tif (!$m) {\n\t\t\t\t\t$m = new $Map();\n\t\t\t\t}\n\t\t\t\t$mapSet($m, key, value);\n\t\t\t} else {\n\t\t\t\tif (!$o) {\n\t\t\t\t\t/*\n\t\t\t\t\t * Initialize the linked list as an empty node, so that we don't have\n\t\t\t\t\t * to special-case handling of the first node: we can always refer to\n\t\t\t\t\t * it as (previous node).next, instead of something like (list).head\n\t\t\t\t\t */\n\t\t\t\t\t$o = { key: {}, next: null };\n\t\t\t\t}\n\t\t\t\tlistSet($o, key, value);\n\t\t\t}\n\t\t}\n\t};\n\treturn channel;\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar punycode = require('punycode');\nvar util = require('./util');\n\nexports.parse = urlParse;\nexports.resolve = urlResolve;\nexports.resolveObject = urlResolveObject;\nexports.format = urlFormat;\n\nexports.Url = Url;\n\nfunction Url() {\n  this.protocol = null;\n  this.slashes = null;\n  this.auth = null;\n  this.host = null;\n  this.port = null;\n  this.hostname = null;\n  this.hash = null;\n  this.search = null;\n  this.query = null;\n  this.pathname = null;\n  this.path = null;\n  this.href = null;\n}\n\n// Reference: RFC 3986, RFC 1808, RFC 2396\n\n// define these here so at least they only have to be\n// compiled once on the first module load.\nvar protocolPattern = /^([a-z0-9.+-]+:)/i,\n    portPattern = /:[0-9]*$/,\n\n    // Special case for a simple path URL\n    simplePathPattern = /^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,\n\n    // RFC 2396: characters reserved for delimiting URLs.\n    // We actually just auto-escape these.\n    delims = ['<', '>', '\"', '`', ' ', '\\r', '\\n', '\\t'],\n\n    // RFC 2396: characters not allowed for various reasons.\n    unwise = ['{', '}', '|', '\\\\', '^', '`'].concat(delims),\n\n    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.\n    autoEscape = ['\\''].concat(unwise),\n    // Characters that are never ever allowed in a hostname.\n    // Note that any invalid chars are also handled, but these\n    // are the ones that are *expected* to be seen, so we fast-path\n    // them.\n    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),\n    hostEndingChars = ['/', '?', '#'],\n    hostnameMaxLen = 255,\n    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,\n    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,\n    // protocols that can allow \"unsafe\" and \"unwise\" chars.\n    unsafeProtocol = {\n      'javascript': true,\n      'javascript:': true\n    },\n    // protocols that never have a hostname.\n    hostlessProtocol = {\n      'javascript': true,\n      'javascript:': true\n    },\n    // protocols that always contain a // bit.\n    slashedProtocol = {\n      'http': true,\n      'https': true,\n      'ftp': true,\n      'gopher': true,\n      'file': true,\n      'http:': true,\n      'https:': true,\n      'ftp:': true,\n      'gopher:': true,\n      'file:': true\n    },\n    querystring = require('querystring');\n\nfunction urlParse(url, parseQueryString, slashesDenoteHost) {\n  if (url && util.isObject(url) && url instanceof Url) return url;\n\n  var u = new Url;\n  u.parse(url, parseQueryString, slashesDenoteHost);\n  return u;\n}\n\nUrl.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {\n  if (!util.isString(url)) {\n    throw new TypeError(\"Parameter 'url' must be a string, not \" + typeof url);\n  }\n\n  // Copy chrome, IE, opera backslash-handling behavior.\n  // Back slashes before the query string get converted to forward slashes\n  // See: https://code.google.com/p/chromium/issues/detail?id=25916\n  var queryIndex = url.indexOf('?'),\n      splitter =\n          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',\n      uSplit = url.split(splitter),\n      slashRegex = /\\\\/g;\n  uSplit[0] = uSplit[0].replace(slashRegex, '/');\n  url = uSplit.join(splitter);\n\n  var rest = url;\n\n  // trim before proceeding.\n  // This is to support parse stuff like \"  http://foo.com  \\n\"\n  rest = rest.trim();\n\n  if (!slashesDenoteHost && url.split('#').length === 1) {\n    // Try fast path regexp\n    var simplePath = simplePathPattern.exec(rest);\n    if (simplePath) {\n      this.path = rest;\n      this.href = rest;\n      this.pathname = simplePath[1];\n      if (simplePath[2]) {\n        this.search = simplePath[2];\n        if (parseQueryString) {\n          this.query = querystring.parse(this.search.substr(1));\n        } else {\n          this.query = this.search.substr(1);\n        }\n      } else if (parseQueryString) {\n        this.search = '';\n        this.query = {};\n      }\n      return this;\n    }\n  }\n\n  var proto = protocolPattern.exec(rest);\n  if (proto) {\n    proto = proto[0];\n    var lowerProto = proto.toLowerCase();\n    this.protocol = lowerProto;\n    rest = rest.substr(proto.length);\n  }\n\n  // figure out if it's got a host\n  // user@server is *always* interpreted as a hostname, and url\n  // resolution will treat //foo/bar as host=foo,path=bar because that's\n  // how the browser resolves relative URLs.\n  if (slashesDenoteHost || proto || rest.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)) {\n    var slashes = rest.substr(0, 2) === '//';\n    if (slashes && !(proto && hostlessProtocol[proto])) {\n      rest = rest.substr(2);\n      this.slashes = true;\n    }\n  }\n\n  if (!hostlessProtocol[proto] &&\n      (slashes || (proto && !slashedProtocol[proto]))) {\n\n    // there's a hostname.\n    // the first instance of /, ?, ;, or # ends the host.\n    //\n    // If there is an @ in the hostname, then non-host chars *are* allowed\n    // to the left of the last @ sign, unless some host-ending character\n    // comes *before* the @-sign.\n    // URLs are obnoxious.\n    //\n    // ex:\n    // http://a@b@c/ => user:a@b host:c\n    // http://a@b?@c => user:a host:c path:/?@c\n\n    // v0.12 TODO(isaacs): This is not quite how Chrome does things.\n    // Review our test case against browsers more comprehensively.\n\n    // find the first instance of any hostEndingChars\n    var hostEnd = -1;\n    for (var i = 0; i < hostEndingChars.length; i++) {\n      var hec = rest.indexOf(hostEndingChars[i]);\n      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))\n        hostEnd = hec;\n    }\n\n    // at this point, either we have an explicit point where the\n    // auth portion cannot go past, or the last @ char is the decider.\n    var auth, atSign;\n    if (hostEnd === -1) {\n      // atSign can be anywhere.\n      atSign = rest.lastIndexOf('@');\n    } else {\n      // atSign must be in auth portion.\n      // http://a@b/c@d => host:b auth:a path:/c@d\n      atSign = rest.lastIndexOf('@', hostEnd);\n    }\n\n    // Now we have a portion which is definitely the auth.\n    // Pull that off.\n    if (atSign !== -1) {\n      auth = rest.slice(0, atSign);\n      rest = rest.slice(atSign + 1);\n      this.auth = decodeURIComponent(auth);\n    }\n\n    // the host is the remaining to the left of the first non-host char\n    hostEnd = -1;\n    for (var i = 0; i < nonHostChars.length; i++) {\n      var hec = rest.indexOf(nonHostChars[i]);\n      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))\n        hostEnd = hec;\n    }\n    // if we still have not hit it, then the entire thing is a host.\n    if (hostEnd === -1)\n      hostEnd = rest.length;\n\n    this.host = rest.slice(0, hostEnd);\n    rest = rest.slice(hostEnd);\n\n    // pull out port.\n    this.parseHost();\n\n    // we've indicated that there is a hostname,\n    // so even if it's empty, it has to be present.\n    this.hostname = this.hostname || '';\n\n    // if hostname begins with [ and ends with ]\n    // assume that it's an IPv6 address.\n    var ipv6Hostname = this.hostname[0] === '[' &&\n        this.hostname[this.hostname.length - 1] === ']';\n\n    // validate a little.\n    if (!ipv6Hostname) {\n      var hostparts = this.hostname.split(/\\./);\n      for (var i = 0, l = hostparts.length; i < l; i++) {\n        var part = hostparts[i];\n        if (!part) continue;\n        if (!part.match(hostnamePartPattern)) {\n          var newpart = '';\n          for (var j = 0, k = part.length; j < k; j++) {\n            if (part.charCodeAt(j) > 127) {\n              // we replace non-ASCII char with a temporary placeholder\n              // we need this to make sure size of hostname is not\n              // broken by replacing non-ASCII by nothing\n              newpart += 'x';\n            } else {\n              newpart += part[j];\n            }\n          }\n          // we test again with ASCII char only\n          if (!newpart.match(hostnamePartPattern)) {\n            var validParts = hostparts.slice(0, i);\n            var notHost = hostparts.slice(i + 1);\n            var bit = part.match(hostnamePartStart);\n            if (bit) {\n              validParts.push(bit[1]);\n              notHost.unshift(bit[2]);\n            }\n            if (notHost.length) {\n              rest = '/' + notHost.join('.') + rest;\n            }\n            this.hostname = validParts.join('.');\n            break;\n          }\n        }\n      }\n    }\n\n    if (this.hostname.length > hostnameMaxLen) {\n      this.hostname = '';\n    } else {\n      // hostnames are always lower case.\n      this.hostname = this.hostname.toLowerCase();\n    }\n\n    if (!ipv6Hostname) {\n      // IDNA Support: Returns a punycoded representation of \"domain\".\n      // It only converts parts of the domain name that\n      // have non-ASCII characters, i.e. it doesn't matter if\n      // you call it with a domain that already is ASCII-only.\n      this.hostname = punycode.toASCII(this.hostname);\n    }\n\n    var p = this.port ? ':' + this.port : '';\n    var h = this.hostname || '';\n    this.host = h + p;\n    this.href += this.host;\n\n    // strip [ and ] from the hostname\n    // the host field still retains them, though\n    if (ipv6Hostname) {\n      this.hostname = this.hostname.substr(1, this.hostname.length - 2);\n      if (rest[0] !== '/') {\n        rest = '/' + rest;\n      }\n    }\n  }\n\n  // now rest is set to the post-host stuff.\n  // chop off any delim chars.\n  if (!unsafeProtocol[lowerProto]) {\n\n    // First, make 100% sure that any \"autoEscape\" chars get\n    // escaped, even if encodeURIComponent doesn't think they\n    // need to be.\n    for (var i = 0, l = autoEscape.length; i < l; i++) {\n      var ae = autoEscape[i];\n      if (rest.indexOf(ae) === -1)\n        continue;\n      var esc = encodeURIComponent(ae);\n      if (esc === ae) {\n        esc = escape(ae);\n      }\n      rest = rest.split(ae).join(esc);\n    }\n  }\n\n\n  // chop off from the tail first.\n  var hash = rest.indexOf('#');\n  if (hash !== -1) {\n    // got a fragment string.\n    this.hash = rest.substr(hash);\n    rest = rest.slice(0, hash);\n  }\n  var qm = rest.indexOf('?');\n  if (qm !== -1) {\n    this.search = rest.substr(qm);\n    this.query = rest.substr(qm + 1);\n    if (parseQueryString) {\n      this.query = querystring.parse(this.query);\n    }\n    rest = rest.slice(0, qm);\n  } else if (parseQueryString) {\n    // no query string, but parseQueryString still requested\n    this.search = '';\n    this.query = {};\n  }\n  if (rest) this.pathname = rest;\n  if (slashedProtocol[lowerProto] &&\n      this.hostname && !this.pathname) {\n    this.pathname = '/';\n  }\n\n  //to support http.request\n  if (this.pathname || this.search) {\n    var p = this.pathname || '';\n    var s = this.search || '';\n    this.path = p + s;\n  }\n\n  // finally, reconstruct the href based on what has been validated.\n  this.href = this.format();\n  return this;\n};\n\n// format a parsed object into a url string\nfunction urlFormat(obj) {\n  // ensure it's an object, and not a string url.\n  // If it's an obj, this is a no-op.\n  // this way, you can call url_format() on strings\n  // to clean up potentially wonky urls.\n  if (util.isString(obj)) obj = urlParse(obj);\n  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);\n  return obj.format();\n}\n\nUrl.prototype.format = function() {\n  var auth = this.auth || '';\n  if (auth) {\n    auth = encodeURIComponent(auth);\n    auth = auth.replace(/%3A/i, ':');\n    auth += '@';\n  }\n\n  var protocol = this.protocol || '',\n      pathname = this.pathname || '',\n      hash = this.hash || '',\n      host = false,\n      query = '';\n\n  if (this.host) {\n    host = auth + this.host;\n  } else if (this.hostname) {\n    host = auth + (this.hostname.indexOf(':') === -1 ?\n        this.hostname :\n        '[' + this.hostname + ']');\n    if (this.port) {\n      host += ':' + this.port;\n    }\n  }\n\n  if (this.query &&\n      util.isObject(this.query) &&\n      Object.keys(this.query).length) {\n    query = querystring.stringify(this.query);\n  }\n\n  var search = this.search || (query && ('?' + query)) || '';\n\n  if (protocol && protocol.substr(-1) !== ':') protocol += ':';\n\n  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.\n  // unless they had them to begin with.\n  if (this.slashes ||\n      (!protocol || slashedProtocol[protocol]) && host !== false) {\n    host = '//' + (host || '');\n    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;\n  } else if (!host) {\n    host = '';\n  }\n\n  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;\n  if (search && search.charAt(0) !== '?') search = '?' + search;\n\n  pathname = pathname.replace(/[?#]/g, function(match) {\n    return encodeURIComponent(match);\n  });\n  search = search.replace('#', '%23');\n\n  return protocol + host + pathname + search + hash;\n};\n\nfunction urlResolve(source, relative) {\n  return urlParse(source, false, true).resolve(relative);\n}\n\nUrl.prototype.resolve = function(relative) {\n  return this.resolveObject(urlParse(relative, false, true)).format();\n};\n\nfunction urlResolveObject(source, relative) {\n  if (!source) return relative;\n  return urlParse(source, false, true).resolveObject(relative);\n}\n\nUrl.prototype.resolveObject = function(relative) {\n  if (util.isString(relative)) {\n    var rel = new Url();\n    rel.parse(relative, false, true);\n    relative = rel;\n  }\n\n  var result = new Url();\n  var tkeys = Object.keys(this);\n  for (var tk = 0; tk < tkeys.length; tk++) {\n    var tkey = tkeys[tk];\n    result[tkey] = this[tkey];\n  }\n\n  // hash is always overridden, no matter what.\n  // even href=\"\" will remove it.\n  result.hash = relative.hash;\n\n  // if the relative url is empty, then there's nothing left to do here.\n  if (relative.href === '') {\n    result.href = result.format();\n    return result;\n  }\n\n  // hrefs like //foo/bar always cut to the protocol.\n  if (relative.slashes && !relative.protocol) {\n    // take everything except the protocol from relative\n    var rkeys = Object.keys(relative);\n    for (var rk = 0; rk < rkeys.length; rk++) {\n      var rkey = rkeys[rk];\n      if (rkey !== 'protocol')\n        result[rkey] = relative[rkey];\n    }\n\n    //urlParse appends trailing / to urls like http://www.example.com\n    if (slashedProtocol[result.protocol] &&\n        result.hostname && !result.pathname) {\n      result.path = result.pathname = '/';\n    }\n\n    result.href = result.format();\n    return result;\n  }\n\n  if (relative.protocol && relative.protocol !== result.protocol) {\n    // if it's a known url protocol, then changing\n    // the protocol does weird things\n    // first, if it's not file:, then we MUST have a host,\n    // and if there was a path\n    // to begin with, then we MUST have a path.\n    // if it is file:, then the host is dropped,\n    // because that's known to be hostless.\n    // anything else is assumed to be absolute.\n    if (!slashedProtocol[relative.protocol]) {\n      var keys = Object.keys(relative);\n      for (var v = 0; v < keys.length; v++) {\n        var k = keys[v];\n        result[k] = relative[k];\n      }\n      result.href = result.format();\n      return result;\n    }\n\n    result.protocol = relative.protocol;\n    if (!relative.host && !hostlessProtocol[relative.protocol]) {\n      var relPath = (relative.pathname || '').split('/');\n      while (relPath.length && !(relative.host = relPath.shift()));\n      if (!relative.host) relative.host = '';\n      if (!relative.hostname) relative.hostname = '';\n      if (relPath[0] !== '') relPath.unshift('');\n      if (relPath.length < 2) relPath.unshift('');\n      result.pathname = relPath.join('/');\n    } else {\n      result.pathname = relative.pathname;\n    }\n    result.search = relative.search;\n    result.query = relative.query;\n    result.host = relative.host || '';\n    result.auth = relative.auth;\n    result.hostname = relative.hostname || relative.host;\n    result.port = relative.port;\n    // to support http.request\n    if (result.pathname || result.search) {\n      var p = result.pathname || '';\n      var s = result.search || '';\n      result.path = p + s;\n    }\n    result.slashes = result.slashes || relative.slashes;\n    result.href = result.format();\n    return result;\n  }\n\n  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),\n      isRelAbs = (\n          relative.host ||\n          relative.pathname && relative.pathname.charAt(0) === '/'\n      ),\n      mustEndAbs = (isRelAbs || isSourceAbs ||\n                    (result.host && relative.pathname)),\n      removeAllDots = mustEndAbs,\n      srcPath = result.pathname && result.pathname.split('/') || [],\n      relPath = relative.pathname && relative.pathname.split('/') || [],\n      psychotic = result.protocol && !slashedProtocol[result.protocol];\n\n  // if the url is a non-slashed url, then relative\n  // links like ../.. should be able\n  // to crawl up to the hostname, as well.  This is strange.\n  // result.protocol has already been set by now.\n  // Later on, put the first path part into the host field.\n  if (psychotic) {\n    result.hostname = '';\n    result.port = null;\n    if (result.host) {\n      if (srcPath[0] === '') srcPath[0] = result.host;\n      else srcPath.unshift(result.host);\n    }\n    result.host = '';\n    if (relative.protocol) {\n      relative.hostname = null;\n      relative.port = null;\n      if (relative.host) {\n        if (relPath[0] === '') relPath[0] = relative.host;\n        else relPath.unshift(relative.host);\n      }\n      relative.host = null;\n    }\n    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');\n  }\n\n  if (isRelAbs) {\n    // it's absolute.\n    result.host = (relative.host || relative.host === '') ?\n                  relative.host : result.host;\n    result.hostname = (relative.hostname || relative.hostname === '') ?\n                      relative.hostname : result.hostname;\n    result.search = relative.search;\n    result.query = relative.query;\n    srcPath = relPath;\n    // fall through to the dot-handling below.\n  } else if (relPath.length) {\n    // it's relative\n    // throw away the existing file, and take the new path instead.\n    if (!srcPath) srcPath = [];\n    srcPath.pop();\n    srcPath = srcPath.concat(relPath);\n    result.search = relative.search;\n    result.query = relative.query;\n  } else if (!util.isNullOrUndefined(relative.search)) {\n    // just pull out the search.\n    // like href='?foo'.\n    // Put this after the other two cases because it simplifies the booleans\n    if (psychotic) {\n      result.hostname = result.host = srcPath.shift();\n      //occationaly the auth can get stuck only in host\n      //this especially happens in cases like\n      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n      var authInHost = result.host && result.host.indexOf('@') > 0 ?\n                       result.host.split('@') : false;\n      if (authInHost) {\n        result.auth = authInHost.shift();\n        result.host = result.hostname = authInHost.shift();\n      }\n    }\n    result.search = relative.search;\n    result.query = relative.query;\n    //to support http.request\n    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {\n      result.path = (result.pathname ? result.pathname : '') +\n                    (result.search ? result.search : '');\n    }\n    result.href = result.format();\n    return result;\n  }\n\n  if (!srcPath.length) {\n    // no path at all.  easy.\n    // we've already handled the other stuff above.\n    result.pathname = null;\n    //to support http.request\n    if (result.search) {\n      result.path = '/' + result.search;\n    } else {\n      result.path = null;\n    }\n    result.href = result.format();\n    return result;\n  }\n\n  // if a url ENDs in . or .., then it must get a trailing slash.\n  // however, if it ends in anything else non-slashy,\n  // then it must NOT get a trailing slash.\n  var last = srcPath.slice(-1)[0];\n  var hasTrailingSlash = (\n      (result.host || relative.host || srcPath.length > 1) &&\n      (last === '.' || last === '..') || last === '');\n\n  // strip single dots, resolve double dots to parent dir\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = srcPath.length; i >= 0; i--) {\n    last = srcPath[i];\n    if (last === '.') {\n      srcPath.splice(i, 1);\n    } else if (last === '..') {\n      srcPath.splice(i, 1);\n      up++;\n    } else if (up) {\n      srcPath.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (!mustEndAbs && !removeAllDots) {\n    for (; up--; up) {\n      srcPath.unshift('..');\n    }\n  }\n\n  if (mustEndAbs && srcPath[0] !== '' &&\n      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {\n    srcPath.unshift('');\n  }\n\n  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {\n    srcPath.push('');\n  }\n\n  var isAbsolute = srcPath[0] === '' ||\n      (srcPath[0] && srcPath[0].charAt(0) === '/');\n\n  // put the host back\n  if (psychotic) {\n    result.hostname = result.host = isAbsolute ? '' :\n                                    srcPath.length ? srcPath.shift() : '';\n    //occationaly the auth can get stuck only in host\n    //this especially happens in cases like\n    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')\n    var authInHost = result.host && result.host.indexOf('@') > 0 ?\n                     result.host.split('@') : false;\n    if (authInHost) {\n      result.auth = authInHost.shift();\n      result.host = result.hostname = authInHost.shift();\n    }\n  }\n\n  mustEndAbs = mustEndAbs || (result.host && srcPath.length);\n\n  if (mustEndAbs && !isAbsolute) {\n    srcPath.unshift('');\n  }\n\n  if (!srcPath.length) {\n    result.pathname = null;\n    result.path = null;\n  } else {\n    result.pathname = srcPath.join('/');\n  }\n\n  //to support request.http\n  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {\n    result.path = (result.pathname ? result.pathname : '') +\n                  (result.search ? result.search : '');\n  }\n  result.auth = relative.auth || result.auth;\n  result.slashes = result.slashes || relative.slashes;\n  result.href = result.format();\n  return result;\n};\n\nUrl.prototype.parseHost = function() {\n  var host = this.host;\n  var port = portPattern.exec(host);\n  if (port) {\n    port = port[0];\n    if (port !== ':') {\n      this.port = port.substr(1);\n    }\n    host = host.substr(0, host.length - port.length);\n  }\n  if (host) this.hostname = host;\n};\n","'use strict';\n\nmodule.exports = {\n  isString: function(arg) {\n    return typeof(arg) === 'string';\n  },\n  isObject: function(arg) {\n    return typeof(arg) === 'object' && arg !== null;\n  },\n  isNull: function(arg) {\n    return arg === null;\n  },\n  isNullOrUndefined: function(arg) {\n    return arg == null;\n  }\n};\n"],"preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2FqYXguanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2FwcC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvYm9udXMtcHJvZHVjdHMtdmlldy5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvY2FwdGNoYS5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvY29tcGFyZS13aWRnZXQuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvYWNjb3JkaW9uLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9jb21wb25lbnRzL3F1YW50aXR5U3dpdGNoZXIuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2NvbXBvbmVudHMvc3RpY2t5Q29tcG9uZW50LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9jb25maWdzL2Nhcm91c2VsLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9jb29raWVwcml2YWN5LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9jb3VudHJpZXMuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2RpYWxvZy5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvZmJldmVudHMuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL2dpZnRjYXJkLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9naWZ0Y2VydC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvanF1ZXJ5LWV4dC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvbG9naW4uanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL21pbmljYXJ0LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9hY2NvdW50LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9jYXJ0LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9hZGRyZXNzLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9iaWxsaW5nLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9jaGVja291dC9mb3JtUHJlcGFyZS5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvaW5kZXguanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3BhZ2VzL2NoZWNrb3V0L211bHRpc2hpcC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvY2hlY2tvdXQvc2hpcHBpbmcuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3BhZ2VzL2NvbXBhcmUuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvYWRkVG9DYXJ0LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L2F2YWlsYWJpbGl0eS5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC9pbWFnZS5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC9pbmRleC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC9wcm9kdWN0TmF2LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L3Byb2R1Y3RTZXQuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3BhZ2VzL3Byb2R1Y3QvcmVjb21tZW5kYXRpb25zLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9wcm9kdWN0L3NpemVDaGFydC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvcHJvZHVjdC92YXJpYW50LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9yZWdpc3RyeS5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvcGFnZXMvc2VhcmNoLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9zdG9yZWZyb250LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wYWdlcy9zdG9yZWxvY2F0b3IuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3BhZ2VzL3dpc2hsaXN0LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9wcm9kdWN0LXRpbGUuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3Byb2dyZXNzLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9xdWlja3ZpZXcuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3JhdGluZy5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvc2VhcmNocGxhY2Vob2xkZXIuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3NlYXJjaHN1Z2dlc3QuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3NmY2hhdC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvc3RpY2t5U2VhcmNoLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9jYXJ0LmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy9zdG9yZWludmVudG9yeS9pbmRleC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvc3RvcmVpbnZlbnRvcnkvcHJvZHVjdC5qcyIsImNhcnRyaWRnZXMvYXBwX2N1c3RvbV9naWZ0c2hvcC9jYXJ0cmlkZ2UvanMvdGlrdG9rZXZlbnRzLmpzIiwiY2FydHJpZGdlcy9hcHBfY3VzdG9tX2dpZnRzaG9wL2NhcnRyaWRnZS9qcy90bHMuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3Rvb2x0aXAuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3V0aWwuanMiLCJjYXJ0cmlkZ2VzL2FwcF9jdXN0b21fZ2lmdHNob3AvY2FydHJpZGdlL2pzL3ZhbGlkYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9hc2FwL2Jyb3dzZXItYXNhcC5qcyIsIm5vZGVfbW9kdWxlcy9hc2FwL2Jyb3dzZXItcmF3LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXItcmVzb2x2ZS9lbXB0eS5qcyIsIm5vZGVfbW9kdWxlcy9jYWxsLWJpbmQvY2FsbEJvdW5kLmpzIiwibm9kZV9tb2R1bGVzL2NhbGwtYmluZC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9ldi1lbWl0dGVyL2V2LWVtaXR0ZXIuanMiLCJub2RlX21vZHVsZXMvZnVuY3Rpb24tYmluZC9pbXBsZW1lbnRhdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9mdW5jdGlvbi1iaW5kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2dldC1pbnRyaW5zaWMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaGFzLXN5bWJvbHMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaGFzLXN5bWJvbHMvc2hhbXMuanMiLCJub2RlX21vZHVsZXMvaGFzL3NyYy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvaW1hZ2VzbG9hZGVkLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC9sb2Rhc2guanMiLCJub2RlX21vZHVsZXMvb2JqZWN0LWluc3BlY3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL3Byb21pc2UvbGliL2RvbmUuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZXM2LWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvZmluYWxseS5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9taXNlL2xpYi9ub2RlLWV4dGVuc2lvbnMuanMiLCJub2RlX21vZHVsZXMvcHJvbWlzZS9saWIvc3luY2hyb25vdXMuanMiLCJub2RlX21vZHVsZXMvcHVueWNvZGUvcHVueWNvZGUuanMiLCJub2RlX21vZHVsZXMvcXMvbGliL2Zvcm1hdHMuanMiLCJub2RlX21vZHVsZXMvcXMvbGliL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3FzL2xpYi9wYXJzZS5qcyIsIm5vZGVfbW9kdWxlcy9xcy9saWIvc3RyaW5naWZ5LmpzIiwibm9kZV9tb2R1bGVzL3FzL2xpYi91dGlscy5qcyIsIm5vZGVfbW9kdWxlcy9xdWVyeXN0cmluZy1lczMvZGVjb2RlLmpzIiwibm9kZV9tb2R1bGVzL3F1ZXJ5c3RyaW5nLWVzMy9lbmNvZGUuanMiLCJub2RlX21vZHVsZXMvcXVlcnlzdHJpbmctZXMzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NpZGUtY2hhbm5lbC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy91cmwvdXJsLmpzIiwibm9kZV9tb2R1bGVzL3VybC91dGlsLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN1FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDak5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2U0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9WQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDL05BOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN6WEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3p6aEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BkQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNsaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzV0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIid1c2Ugc3RyaWN0JztcblxudmFyIHByb2dyZXNzID0gcmVxdWlyZSgnLi9wcm9ncmVzcycpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxudmFyIGN1cnJlbnRSZXF1ZXN0cyA9IFtdO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEFqYXggcmVxdWVzdCB0byBnZXQganNvbiByZXNwb25zZVxuICogQHBhcmFtIHtCb29sZWFufSBhc3luYyAgQXN5bmNocm9ub3VzIG9yIG5vdFxuICogQHBhcmFtIHtTdHJpbmd9IHVybCBVUkkgZm9yIHRoZSByZXF1ZXN0XG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YSBOYW1lL1ZhbHVlIHBhaXIgZGF0YSByZXF1ZXN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAgQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkXG4gKi9cbnZhciBnZXRKc29uID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zLnVybCA9IHV0aWwudG9BYnNvbHV0ZVVybChvcHRpb25zLnVybCk7XG4gICAgLy8gcmV0dXJuIGlmIG5vIHVybCBleGlzdHMgb3IgdXJsIG1hdGNoZXMgYSBjdXJyZW50IHJlcXVlc3RcbiAgICBpZiAoIW9wdGlvbnMudXJsIHx8IGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF0gPSB0cnVlO1xuXG4gICAgLy8gbWFrZSB0aGUgc2VydmVyIGNhbGxcbiAgICAkLmFqYXgoe1xuICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICB1cmw6IG9wdGlvbnMudXJsLFxuICAgICAgICBhc3luYzogKHR5cGVvZiBvcHRpb25zLmFzeW5jID09PSAndW5kZWZpbmVkJyB8fCBvcHRpb25zLmFzeW5jID09PSBudWxsKSA/IHRydWUgOiBvcHRpb25zLmFzeW5jLFxuICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEgfHwge31cbiAgICB9KVxuICAgIC8vIHN1Y2Nlc3NcbiAgICAuZG9uZShmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2spIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2socmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAvLyBmYWlsZWRcbiAgICAuZmFpbChmdW5jdGlvbiAoeGhyLCB0ZXh0U3RhdHVzKSB7XG4gICAgICAgIGlmICh0ZXh0U3RhdHVzID09PSAncGFyc2VyZXJyb3InKSB7XG4gICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkJBRF9SRVNQT05TRSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2spIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sobnVsbCk7XG4gICAgICAgIH1cbiAgICB9KVxuICAgIC8vIGV4ZWN1dGVkIG9uIHN1Y2Nlc3Mgb3IgZmFpbFxuICAgIC5hbHdheXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyByZW1vdmUgY3VycmVudCByZXF1ZXN0IGZyb20gaGFzaFxuICAgICAgICBpZiAoY3VycmVudFJlcXVlc3RzW29wdGlvbnMudXJsXSkge1xuICAgICAgICAgICAgZGVsZXRlIGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF07XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGFqYXggcmVxdWVzdCB0byBsb2FkIGh0bWwgcmVzcG9uc2UgaW4gYSBnaXZlbiBjb250YWluZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgVVJJIGZvciB0aGUgcmVxdWVzdFxuICogQHBhcmFtIHtPYmplY3R9IGRhdGEgTmFtZS9WYWx1ZSBwYWlyIGRhdGEgcmVxdWVzdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuICogQHBhcmFtIHtPYmplY3R9IHRhcmdldCBTZWxlY3RvciBvciBlbGVtZW50IHRoYXQgd2lsbCByZWNlaXZlIGNvbnRlbnRcbiAqL1xudmFyIGxvYWQgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIG9wdGlvbnMudXJsID0gdXRpbC50b0Fic29sdXRlVXJsKG9wdGlvbnMudXJsKTtcbiAgICAvLyByZXR1cm4gaWYgbm8gdXJsIGV4aXN0cyBvciB1cmwgbWF0Y2hlcyBhIGN1cnJlbnQgcmVxdWVzdFxuICAgIGlmICghb3B0aW9ucy51cmwgfHwgY3VycmVudFJlcXVlc3RzW29wdGlvbnMudXJsXSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY3VycmVudFJlcXVlc3RzW29wdGlvbnMudXJsXSA9IHRydWU7XG5cbiAgICAvLyBtYWtlIHRoZSBzZXJ2ZXIgY2FsbFxuICAgICQuYWpheCh7XG4gICAgICAgIGRhdGFUeXBlOiAnaHRtbCcsXG4gICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbVRvVVJMKG9wdGlvbnMudXJsLCAnZm9ybWF0JywgJ2FqYXgnKSxcbiAgICAgICAgZGF0YTogb3B0aW9ucy5kYXRhLFxuICAgICAgICB4aHJGaWVsZHM6IHtcbiAgICAgICAgICAgIHdpdGhDcmVkZW50aWFsczogdHJ1ZVxuICAgICAgICB9XG4gICAgfSlcbiAgICAuZG9uZShmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgLy8gc3VjY2Vzc1xuICAgICAgICBpZiAob3B0aW9ucy50YXJnZXQpIHtcbiAgICAgICAgICAgICQob3B0aW9ucy50YXJnZXQpLmVtcHR5KCkuaHRtbChyZXNwb25zZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2spIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2socmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAuZmFpbChmdW5jdGlvbiAoeGhyLCB0ZXh0U3RhdHVzKSB7XG4gICAgICAgIC8vIGZhaWxlZFxuICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgICB9XG4gICAgICAgIG9wdGlvbnMuY2FsbGJhY2sobnVsbCwgdGV4dFN0YXR1cyk7XG4gICAgfSlcbiAgICAuYWx3YXlzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xuICAgICAgICAvLyByZW1vdmUgY3VycmVudCByZXF1ZXN0IGZyb20gaGFzaFxuICAgICAgICBpZiAoY3VycmVudFJlcXVlc3RzW29wdGlvbnMudXJsXSkge1xuICAgICAgICAgICAgZGVsZXRlIGN1cnJlbnRSZXF1ZXN0c1tvcHRpb25zLnVybF07XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbmV4cG9ydHMuZ2V0SnNvbiA9IGdldEpzb247XG5leHBvcnRzLmxvYWQgPSBsb2FkO1xuIiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxudmFyIGNvdW50cmllcyA9IHJlcXVpcmUoJy4vY291bnRyaWVzJyksXHJcbiAgICBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpLFxyXG4gICAgbWluaWNhcnQgPSByZXF1aXJlKCcuL21pbmljYXJ0JyksXHJcbiAgICBwYWdlID0gcmVxdWlyZSgnLi9wYWdlJyksXHJcbiAgICByYXRpbmcgPSByZXF1aXJlKCcuL3JhdGluZycpLFxyXG4gICAgc2VhcmNocGxhY2Vob2xkZXIgPSByZXF1aXJlKCcuL3NlYXJjaHBsYWNlaG9sZGVyJyksXHJcbiAgICBzZWFyY2hzdWdnZXN0ID0gcmVxdWlyZSgnLi9zZWFyY2hzdWdnZXN0JyksXHJcbiAgICB0b29sdGlwID0gcmVxdWlyZSgnLi90b29sdGlwJyksXHJcbiAgICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyksXHJcbiAgICB2YWxpZGF0b3IgPSByZXF1aXJlKCcuL3ZhbGlkYXRvcicpLFxyXG4gICAgdGxzID0gcmVxdWlyZSgnLi90bHMnKSxcclxuICAgIGZiZXZlbnRzID0gcmVxdWlyZSgnLi9mYmV2ZW50cycpLFxyXG4gICAgdGlrdG9rID0gcmVxdWlyZSgnLi90aWt0b2tldmVudHMnKSxcclxuICAgIHNmY2hhdCA9IHJlcXVpcmUoJy4vc2ZjaGF0JyksXHJcbiAgICBzdGlja3lTZWFyY2ggPSByZXF1aXJlKCcuL3N0aWNreVNlYXJjaCcpO1xyXG5cclxuXHJcbi8vIGlmIGpRdWVyeSBoYXMgbm90IGJlZW4gbG9hZGVkLCBsb2FkIGZyb20gZ29vZ2xlIGNkblxyXG5pZiAoIXdpbmRvdy5qUXVlcnkpIHtcclxuICAgIHZhciBzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XHJcbiAgICBzLnNldEF0dHJpYnV0ZSgnc3JjJywgJ2h0dHBzOi8vYWpheC5nb29nbGVhcGlzLmNvbS9hamF4L2xpYnMvanF1ZXJ5LzEuNy4xL2pxdWVyeS5taW4uanMnKTtcclxuICAgIHMuc2V0QXR0cmlidXRlKCd0eXBlJywgJ3RleHQvamF2YXNjcmlwdCcpO1xyXG4gICAgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2hlYWQnKVswXS5hcHBlbmRDaGlsZChzKTtcclxufVxyXG5cclxucmVxdWlyZSgnLi9qcXVlcnktZXh0JykoKTtcclxucmVxdWlyZSgnLi9jb29raWVwcml2YWN5JykoKTtcclxucmVxdWlyZSgnLi9jYXB0Y2hhJykoKTtcclxuXHJcbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XHJcbiAgICB2YXIgY29udHJvbEtleXMgPSBbJzgnLCAnMTMnLCAnNDYnLCAnNDUnLCAnMzYnLCAnMzUnLCAnMzgnLCAnMzcnLCAnNDAnLCAnMzknXTtcclxuXHJcbiAgICAkKCdib2R5JylcclxuICAgICAgICAub24oJ2tleWRvd24nLCAndGV4dGFyZWFbZGF0YS1jaGFyYWN0ZXItbGltaXRdJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgdmFyIHRleHQgPSAkLnRyaW0oJCh0aGlzKS52YWwoKSksXHJcbiAgICAgICAgICAgICAgICBjaGFyc0xpbWl0ID0gJCh0aGlzKS5kYXRhKCdjaGFyYWN0ZXItbGltaXQnKSxcclxuICAgICAgICAgICAgICAgIGNoYXJzVXNlZCA9IHRleHQubGVuZ3RoO1xyXG5cclxuICAgICAgICAgICAgaWYgKChjaGFyc1VzZWQgPj0gY2hhcnNMaW1pdCkgJiYgKGNvbnRyb2xLZXlzLmluZGV4T2YoZS53aGljaC50b1N0cmluZygpKSA8IDApKSB7XHJcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgICAgIC5vbignY2hhbmdlIGtleXVwIG1vdXNldXAnLCAndGV4dGFyZWFbZGF0YS1jaGFyYWN0ZXItbGltaXRdJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgdGV4dCA9ICQudHJpbSgkKHRoaXMpLnZhbCgpKSxcclxuICAgICAgICAgICAgICAgIGNoYXJzTGltaXQgPSAkKHRoaXMpLmRhdGEoJ2NoYXJhY3Rlci1saW1pdCcpLFxyXG4gICAgICAgICAgICAgICAgY2hhcnNVc2VkID0gdGV4dC5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICBjaGFyc1JlbWFpbiA9IGNoYXJzTGltaXQgLSBjaGFyc1VzZWQ7XHJcblxyXG4gICAgICAgICAgICBpZiAoY2hhcnNSZW1haW4gPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAkKHRoaXMpLnZhbCh0ZXh0LnNsaWNlKDAsIGNoYXJzUmVtYWluKSk7XHJcbiAgICAgICAgICAgICAgICBjaGFyc1JlbWFpbiA9IDA7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICQodGhpcykubmV4dCgnZGl2LmNoYXItY291bnQnKS5maW5kKCcuY2hhci1yZW1haW4tY291bnQnKS5odG1sKGNoYXJzUmVtYWluKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIGluaXRpYWxpemUgc2VhcmNoIHN1Z2dlc3Rpb25zLCBwZW5kaW5nIHRoZSB2YWx1ZSBvZiB0aGUgc2l0ZSBwcmVmZXJlbmNlKGVuaGFuY2VkU2VhcmNoU3VnZ2VzdGlvbnMpXHJcbiAgICAgKiB0aGlzIHdpbGwgZWl0aGVyIGluaXQgdGhlIGxlZ2FjeShmYWxzZSkgb3IgdGhlIGJldGEgdmVyc2lvbnModHJ1ZSkgb2YgdGhlIHRoZSBzZWFyY2ggc3VnZ2VzdCBmZWF0dXJlLlxyXG4gICAgICogKi9cclxuICAgIHZhciAkc2VhcmNoQ29udGFpbmVyID0gJCgnLmhlYWRlci1zZWFyY2gnKTtcclxuICAgIHNlYXJjaHN1Z2dlc3QuaW5pdCgkc2VhcmNoQ29udGFpbmVyLCBSZXNvdXJjZXMuU0lNUExFX1NFQVJDSCk7XHJcbiAgICBcclxuICAgIC8vIFByZXZlbnRzIHRoZSB1c2VyIGZyb20gc3VibWl0dGluZyB0aGUgc2VhcmNoIHdoZW4gaXQncyBlbXB0eVxyXG4gICAgJHNlYXJjaENvbnRhaW5lci5vbihcInN1Ym1pdFwiLCBmdW5jdGlvbihlKSB7XHJcbiAgICBcdFx0dmFyIHNlYXJjaFBocmFzZSA9ICRzZWFyY2hDb250YWluZXIuZmluZCgnI3EnKTtcclxuICAgIFx0XHRpZiAoc2VhcmNoUGhyYXNlLnZhbCgpID09ICcnIHx8IHNlYXJjaFBocmFzZS52YWwoKSA9PSBzZWFyY2hQaHJhc2UuYXR0cigncGxhY2Vob2xkZXInKSkge1xyXG4gICAgXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG4gICAgXHRcdH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vdGhpcyB3aWxsIGNoYW5nZSBhbGwgdGhlIGlucHV0IHRvIGNhdGVyIGNvbnRleHR1YWwga2V5Ym9hcmRcclxuICAgICQod2luZG93KS5vbignbG9hZCByZXNpemUnLCBmdW5jdGlvbigpe1xyXG4gICAgXHRpZigkKHdpbmRvdykud2lkdGgoKSA8IDc2OCkge1xyXG4gICAgXHRcdCQoJy5udW1iZXJrZXknKS5wcm9wKCd0eXBlJywgJ3RlbCcpO1xyXG4gICAgXHR9IGVsc2Uge1xyXG4gICAgXHRcdCQoJy5udW1iZXJrZXknKS5wcm9wKCd0eXBlJywgJ3RleHQnKTtcclxuICAgIFx0fVxyXG4gICAgXHRcclxuICAgIH0pO1xyXG4gICAgXHJcbiAgICAvLyBhZGQgc2hvdy9oaWRlIG5hdmlnYXRpb24gZWxlbWVudHNcclxuICAgICQoJy5zZWNvbmRhcnktbmF2aWdhdGlvbiAudG9nZ2xlJykuY2xpY2soZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICQodGhpcykudG9nZ2xlQ2xhc3MoJ2V4cGFuZGVkJykubmV4dCgndWwnKS50b2dnbGUoKTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIGFkZCBzaG93L2hpZGUgc2VhcmNoLWljb25cclxuICAgICQoXCIuaGVhZGVyLXNlYXJjaC1pY29uXCIpLm9uKFwiY2xpY2tcIixmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgJChcIi5oZWFkZXItc2VhcmNoXCIpLnRvZ2dsZSgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gYWRkIGdlbmVyaWMgdG9nZ2xlIGZ1bmN0aW9uYWxpdHlcclxuICAgICQoJy50b2dnbGUnKS5uZXh0KCcudG9nZ2xlLWNvbnRlbnQnKS5oaWRlKCk7XHJcbiAgICAkKCcudG9nZ2xlJykuY2xpY2soZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICQodGhpcykudG9nZ2xlQ2xhc3MoJ2V4cGFuZGVkJykubmV4dCgnLnRvZ2dsZS1jb250ZW50JykudG9nZ2xlKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBzdWJzY3JpYmUgZW1haWwgYm94XHJcbiAgICB2YXIgJHN1YnNjcmliZUVtYWlsID0gJCgnLnN1YnNjcmliZS1lbWFpbCcpO1xyXG4gICAgaWYgKCRzdWJzY3JpYmVFbWFpbC5sZW5ndGggPiAwKSAgICB7XHJcbiAgICAgICAgJHN1YnNjcmliZUVtYWlsLmZvY3VzKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHZhbCA9ICQodGhpcy52YWwoKSk7XHJcbiAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID4gMCAmJiB2YWwgIT09IFJlc291cmNlcy5TVUJTQ1JJQkVfRU1BSUxfREVGQVVMVCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBkbyBub3QgYW5pbWF0ZSB3aGVuIGNvbnRhaW5zIG5vbi1kZWZhdWx0IHZhbHVlXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICQodGhpcykuYW5pbWF0ZSh7Y29sb3I6ICcjOTk5OTk5J30sIDUwMCwgJ2xpbmVhcicsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICQodGhpcykudmFsKCcnKS5jc3MoJ2NvbG9yJywgJyMzMzMzMzMnKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSkuYmx1cihmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciB2YWwgPSAkLnRyaW0oJCh0aGlzLnZhbCgpKSk7XHJcbiAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBkbyBub3QgYW5pbWF0ZSB3aGVuIGNvbnRhaW5zIHZhbHVlXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgJCh0aGlzKS52YWwoUmVzb3VyY2VzLlNVQlNDUklCRV9FTUFJTF9ERUZBVUxUKVxyXG4gICAgICAgICAgICAgICAgLmNzcygnY29sb3InLCAnIzk5OTk5OScpXHJcbiAgICAgICAgICAgICAgICAuYW5pbWF0ZSh7Y29sb3I6ICcjMzMzMzMzJ30sIDUwMCwgJ2xpbmVhcicpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKXtcclxuICAgICAgICBpZiAod2luZG93LkFwcGxlUGF5U2Vzc2lvbikge1xyXG4gICAgICAgICAgICAkKCdib2R5JykuYWRkQ2xhc3MoJ2FwcGxlcGF5LWJyb3dzZXInKTtcclxuICAgICAgICB9XHJcbiAgICB9LCAxMDAwKTtcclxuICAgIFxyXG4gICAgJCgnLnByaXZhY3ktcG9saWN5Jykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xyXG4gICAgICAgICAgICB1cmw6ICQoZS50YXJnZXQpLmF0dHIoJ2hyZWYnKSxcclxuICAgICAgICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiA2MDBcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gbWFpbiBtZW51IHRvZ2dsZVxyXG4gICAgJCgnLm1lbnUtdG9nZ2xlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICQoJyN3cmFwcGVyJykudG9nZ2xlQ2xhc3MoJ21lbnUtYWN0aXZlJyk7XHJcbiAgICB9KTtcclxuICAgICQoJy5tZW51LWNhdGVnb3J5IGxpIC5tZW51LWl0ZW0tdG9nZ2xlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgdmFyICRwYXJlbnRMaSA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJ2xpJyk7XHJcbiAgICAgICAgJHBhcmVudExpLnNpYmxpbmdzKCdsaScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5maW5kKCcubWVudS1pdGVtLXRvZ2dsZScpLnJlbW92ZUNsYXNzKCdmYS1jaGV2cm9uLXVwIGFjdGl2ZScpLmFkZENsYXNzKCdmYS1jaGV2cm9uLXJpZ2h0Jyk7XHJcbiAgICAgICAgJHBhcmVudExpLnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAkKGUudGFyZ2V0KS50b2dnbGVDbGFzcygnZmEtY2hldnJvbi1yaWdodCBmYS1jaGV2cm9uLXVwIGFjdGl2ZScpO1xyXG4gICAgfSk7XHJcbiAgICAkKCcudXNlci1hY2NvdW50Jykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgJCh0aGlzKS5wYXJlbnQoJy51c2VyLWluZm8nKS50b2dnbGVDbGFzcygnYWN0aXZlJyk7XHJcbiAgICB9KTtcclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBBZGRyZXNzIFN0YXRlIFNlbGVjdG9yXHJcbiAgICAgKi9cclxuICAgIHZhciAkc3RhdGVGaWVsZCA9ICQoXCJbbmFtZSQ9X3N0YXRlXVwiKTtcclxuICAgICQoJ2JvZHknKS5vbignY2hhbmdlJywgXCJbbmFtZSQ9X3N0YXRlXVwiLCBmdW5jdGlvbigpIHsgXHJcbiAgICBcdCQoXCJbbmFtZSQ9X3N0YXRlTmFtZV1cIikudmFsKCQodGhpcykuZmluZChcIm9wdGlvbjpzZWxlY3RlZFwiKS50ZXh0KCkpO1xyXG4gICAgfSk7XHJcbiAgICBcclxuICAgIGlmICgkc3RhdGVGaWVsZC5sZW5ndGggPiAwKSB7XHJcbiAgICBcdCQoXCJbbmFtZSQ9X3N0YXRlTmFtZV1cIikudmFsKCRzdGF0ZUZpZWxkLmZpbmQoXCJvcHRpb246c2VsZWN0ZWRcIikudGV4dCgpKTtcclxuICAgIH1cclxufVxyXG4vKipcclxuICogQHByaXZhdGVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBkZXNjcmlwdGlvbiBBZGRzIGNsYXNzICgnanMnKSB0byBodG1sIGZvciBjc3MgdGFyZ2V0aW5nIGFuZCBsb2FkcyBqcyBzcGVjaWZpYyBzdHlsZXMuXHJcbiAqL1xyXG5mdW5jdGlvbiBpbml0aWFsaXplRG9tKCkge1xyXG4gICAgLy8gYWRkIGNsYXNzIHRvIGh0bWwgZm9yIGNzcyB0YXJnZXRpbmdcclxuICAgICQoJ2h0bWwnKS5hZGRDbGFzcygnanMnKTtcclxuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuTElTVElOR19JTkZJTklURV9TQ1JPTEwpIHtcclxuICAgICAgICAkKCdodG1sJykuYWRkQ2xhc3MoJ2luZmluaXRlLXNjcm9sbCcpO1xyXG4gICAgfVxyXG4gICAgLy8gbG9hZCBqcyBzcGVjaWZpYyBzdHlsZXNcclxuICAgIHV0aWwubGltaXRDaGFyYWN0ZXJzKCk7XHJcbn1cclxuXHJcbnZhciBwYWdlcyA9IHtcclxuICAgIGFjY291bnQ6IHJlcXVpcmUoJy4vcGFnZXMvYWNjb3VudCcpLFxyXG4gICAgY2FydDogcmVxdWlyZSgnLi9wYWdlcy9jYXJ0JyksXHJcbiAgICBjaGVja291dDogcmVxdWlyZSgnLi9wYWdlcy9jaGVja291dCcpLFxyXG4gICAgY29tcGFyZTogcmVxdWlyZSgnLi9wYWdlcy9jb21wYXJlJyksXHJcbiAgICBwcm9kdWN0OiByZXF1aXJlKCcuL3BhZ2VzL3Byb2R1Y3QnKSxcclxuICAgIHJlZ2lzdHJ5OiByZXF1aXJlKCcuL3BhZ2VzL3JlZ2lzdHJ5JyksXHJcbiAgICBzZWFyY2g6IHJlcXVpcmUoJy4vcGFnZXMvc2VhcmNoJyksXHJcbiAgICBzdG9yZWZyb250OiByZXF1aXJlKCcuL3BhZ2VzL3N0b3JlZnJvbnQnKSxcclxuICAgIHdpc2hsaXN0OiByZXF1aXJlKCcuL3BhZ2VzL3dpc2hsaXN0JyksXHJcbiAgICBzdG9yZWxvY2F0b3I6IHJlcXVpcmUoJy4vcGFnZXMvc3RvcmVsb2NhdG9yJylcclxufTtcclxuXHJcbnZhciBhcHAgPSB7XHJcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKGRvY3VtZW50LmNvb2tpZS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgJCgnPGRpdi8+JykuYWRkQ2xhc3MoJ2Jyb3dzZXItY29tcGF0aWJpbGl0eS1hbGVydCcpLmFwcGVuZCgkKCc8cC8+JykuYWRkQ2xhc3MoJ2Jyb3dzZXItZXJyb3InKS5odG1sKFJlc291cmNlcy5DT09LSUVTX0RJU0FCTEVEKSkuYXBwZW5kVG8oJyNicm93c2VyLWNoZWNrJyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGluaXRpYWxpemVEb20oKTtcclxuICAgICAgICBpbml0aWFsaXplRXZlbnRzKCk7XHJcblxyXG4gICAgICAgIC8vIGluaXQgc3BlY2lmaWMgZ2xvYmFsIGNvbXBvbmVudHNcclxuICAgICAgICBjb3VudHJpZXMuaW5pdCgpO1xyXG4gICAgICAgIHRvb2x0aXAuaW5pdCgpO1xyXG4gICAgICAgIG1pbmljYXJ0LmluaXQoKTtcclxuICAgICAgICB2YWxpZGF0b3IuaW5pdCgpO1xyXG4gICAgICAgIHJhdGluZy5pbml0KCk7XHJcbiAgICAgICAgc2VhcmNocGxhY2Vob2xkZXIuaW5pdCgpO1xyXG4gICAgICAgIHN0aWNreVNlYXJjaC5pbml0KCk7XHJcbiAgICAgICAgXHJcblxyXG4gICAgICAgIC8vIGV4ZWN1dGUgcGFnZSBzcGVjaWZpYyBpbml0aWFsaXphdGlvbnNcclxuICAgICAgICAkLmV4dGVuZChwYWdlLCB3aW5kb3cucGFnZUNvbnRleHQpO1xyXG4gICAgICAgIHZhciBucyA9IHBhZ2UubnM7XHJcbiAgICAgICAgaWYgKG5zICYmIHBhZ2VzW25zXSAmJiBwYWdlc1tuc10uaW5pdCkge1xyXG4gICAgICAgICAgICBwYWdlc1tuc10uaW5pdCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ2hlY2sgVExTIHN0YXR1cyBpZiBpbmRpY2F0ZWQgYnkgc2l0ZSBwcmVmZXJlbmNlXHJcbiAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5DSEVDS19UTFMgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgdGxzLmdldFVzZXJBZ2VudCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuRkJfUElYRUxfRU5BQkxFRCA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgdHJ5e1xyXG4gICAgICAgICAgICAgICAgICAgIGZiZXZlbnRzLmluaXQoKTtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2goZXJyKXtcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgIFxyXG4gICAgICAgICAgICBpZiAoU2l0ZVByZWZlcmVuY2VzLlNGX0NIQVRfRU5BQkxFRCA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgdHJ5e1xyXG4gICAgICAgICAgICAgICAgICAgIHNmY2hhdC5pbml0KCk7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoKGVycil7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICBcclxuICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5USUtUT0tfUElYRUxfRU5BQkxFRCA9PT0gdHJ1ZSAmJiBTaXRlUHJlZmVyZW5jZXMuVElLVE9LX1BJWEVMX0lEID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRpa3Rvay5pbml0KCk7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29uc29sZS5sb2coJ1RQLSBjb21wbGV0ZWQnKTtcclxuICAgICAgICB9LCAxMDAwKTtcclxuICAgIH1cclxufTtcclxuXHJcbi8vIGdlbmVyYWwgZXh0ZW5zaW9uIGZ1bmN0aW9uc1xyXG4oZnVuY3Rpb24gKCkge1xyXG4gICAgU3RyaW5nLmZvcm1hdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgcyA9IGFyZ3VtZW50c1swXTtcclxuICAgICAgICB2YXIgaSwgbGVuID0gYXJndW1lbnRzLmxlbmd0aCAtIDE7XHJcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHZhciByZWcgPSBuZXcgUmVnRXhwKCdcXFxceycgKyBpICsgJ1xcXFx9JywgJ2dtJyk7XHJcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UocmVnLCBhcmd1bWVudHNbaSArIDFdKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHM7XHJcbiAgICB9O1xyXG59KSgpO1xyXG5cclxuLy8gaW5pdGlhbGl6ZSBhcHBcclxuJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCkge1xyXG4gICAgYXBwLmluaXQoKTtcclxufSk7XHJcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyksXG4gICAgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxudmFyIHNlbGVjdGVkTGlzdCA9IFtdO1xudmFyIG1heEl0ZW1zID0gMTtcbnZhciBibGlVVUlEID0gJyc7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogZGVzY3JpcHRpb24gR2V0cyBhIGxpc3Qgb2YgYm9udXMgcHJvZHVjdHMgcmVsYXRlZCB0byBhIHByb21vdGVkIHByb2R1Y3RcbiAqL1xuZnVuY3Rpb24gZ2V0Qm9udXNQcm9kdWN0cygpIHtcbiAgICB2YXIgYm9udXNwcm9kdWN0cyA9IFtdO1xuXG4gICAgdmFyIGksIGxlbjtcbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBzZWxlY3RlZExpc3QubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHAgPSB7XG4gICAgICAgICAgICBwaWQ6IHNlbGVjdGVkTGlzdFtpXS5waWQsXG4gICAgICAgICAgICBxdHk6IHNlbGVjdGVkTGlzdFtpXS5xdHksXG4gICAgICAgICAgICBvcHRpb25zOiB7fVxuICAgICAgICB9O1xuICAgICAgICB2YXIgYSwgYWxlbiwgYnAgPSBzZWxlY3RlZExpc3RbaV07XG4gICAgICAgIGlmIChicC5vcHRpb25zKSB7XG4gICAgICAgICAgICBmb3IgKGEgPSAwLCBhbGVuID0gYnAub3B0aW9ucy5sZW5ndGg7IGEgPCBhbGVuOyBhKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgb3B0ID0gYnAub3B0aW9uc1thXTtcbiAgICAgICAgICAgICAgICBwLm9wdGlvbnMgPSB7b3B0aW9uTmFtZTpvcHQubmFtZSwgb3B0aW9uVmFsdWU6b3B0LnZhbHVlfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBib251c3Byb2R1Y3RzLnB1c2goe3Byb2R1Y3Q6cH0pO1xuICAgIH1cbiAgICByZXR1cm4ge2JvbnVzcHJvZHVjdHM6IGJvbnVzcHJvZHVjdHN9O1xufVxuXG52YXIgc2VsZWN0ZWRJdGVtVGVtcGxhdGUgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0gJyc7XG4gICAgLy8gZm9yICh2YXIgYXR0cklEIGluIGRhdGEuYXR0cmlidXRlcykge1xuICAgIC8vICAgICB2YXIgYXR0ciA9IGRhdGEuYXR0cmlidXRlc1thdHRySURdO1xuICAgIC8vICAgICBhdHRyaWJ1dGVzICs9ICc8bGkgZGF0YS1hdHRyaWJ1dGUtaWQ9XCInICsgYXR0cklEICsgJ1wiPlxcbic7XG4gICAgLy8gICAgIGF0dHJpYnV0ZXMgKz0gJzxzcGFuIGNsYXNzPVwiZGlzcGxheS1uYW1lXCI+JyArIGF0dHIuZGlzcGxheU5hbWUgKyAnPC9zcGFuPjogJztcbiAgICAvLyAgICAgYXR0cmlidXRlcyArPSAnPHNwYW4gY2xhc3M9XCJkaXNwbGF5LXZhbHVlXCI+JyArIGF0dHIuZGlzcGxheVZhbHVlICsgJzwvc3Bhbj5cXG4nO1xuICAgIC8vICAgICBhdHRyaWJ1dGVzICs9ICc8L2xpPic7XG4gICAgLy8gfVxuICAgIGF0dHJpYnV0ZXMgKz0gJzxsaSBjbGFzcz1cIml0ZW0tcXR5XCI+XFxuJztcbiAgICBhdHRyaWJ1dGVzICs9ICc8c3BhbiBjbGFzcz1cImRpc3BsYXktbmFtZVwiPlF0eTwvc3Bhbj46ICc7XG4gICAgYXR0cmlidXRlcyArPSAnPHNwYW4gY2xhc3M9XCJkaXNwbGF5LXZhbHVlXCI+JyArIGRhdGEucXR5ICsgJzwvc3Bhbj4nO1xuICAgIHJldHVybiBbXG4gICAgICAgICc8bGkgY2xhc3M9XCJzZWxlY3RlZC1ib251cy1pdGVtXCIgZGF0YS11dWlkPVwiJyArIGRhdGEudXVpZCArICdcIiBkYXRhLXBpZD1cIicgKyBkYXRhLnBpZCArICdcIj4nLFxuICAgICAgICAnPGkgY2xhc3M9XCJyZW1vdmUtbGluayBmYSBmYS1yZW1vdmVcIiB0aXRsZT1cIlJlbW92ZSB0aGlzIHByb2R1Y3RcIiBocmVmPVwiI1wiPjwvaT4nLFxuICAgICAgICAnPGRpdiBjbGFzcz1cIml0ZW0tbmFtZVwiPicgKyBkYXRhLm5hbWUgKyAnPC9kaXY+JyxcbiAgICAgICAgJzx1bCBjbGFzcz1cIml0ZW0tYXR0cmlidXRlc1wiPicsXG4gICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICc8dWw+JyxcbiAgICAgICAgJzxsaT4nXG4gICAgXS5qb2luKCdcXG4nKTtcbn07XG5cbi8vIGhpZGUgc3dhdGNoZXMgdGhhdCBhcmUgbm90IHNlbGVjdGVkIG9yIG5vdCBwYXJ0IG9mIGEgUHJvZHVjdCBWYXJpYXRpb24gR3JvdXBcbnZhciBoaWRlU3dhdGNoZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCgnLmJvbnVzLXByb2R1Y3QtaXRlbTpub3QoW2RhdGEtcHJvZHVjdHR5cGU9XCJtYXN0ZXJcIl0pIC5zd2F0Y2hlcyBsaScpLm5vdCgnLnNlbGVjdGVkJykubm90KCcudmFyaWF0aW9uLWdyb3VwLXZhbHVlJykuaGlkZSgpO1xuICAgIC8vIHByZXZlbnQgdW5zZWxlY3RpbmcgdGhlIHNlbGVjdGVkIHZhcmlhbnRcbiAgICAkKCcuYm9udXMtcHJvZHVjdC1pdGVtIC5zd2F0Y2hlcyAuc2VsZWN0ZWQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIHN1bW1hcnkgcGFnZSB3aXRoIHRoZSBzZWxlY3RlZCBib251cyBwcm9kdWN0XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVN1bW1hcnkoKSB7XG4gICAgdmFyICRib251c1Byb2R1Y3RMaXN0ID0gJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpO1xuICAgIHZhciB1bExpc3QgPSAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCd1bC5zZWxlY3RlZC1ib251cy1pdGVtcycpLmZpcnN0KCk7XG4gICAgLy8gRGlzYWJsZSBzZWxlY3QgYnV0dG9uIGlmIHF1YW50aXR5IGlzIG1vcmUgdGhhbiBtYXhJdGVtc1xuICAgIHZhciB0b3RxdWFudGl0eWNvdW50ID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGVkTGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGxldCBlbGVtZW50ID0gc2VsZWN0ZWRMaXN0W2ldLnF0eTtcbiAgICB0b3RxdWFudGl0eWNvdW50ICs9IGVsZW1lbnQ7XG4gICAgaWYgKHRvdHF1YW50aXR5Y291bnQgPj0gbWF4SXRlbXMpIHtcbiAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgIH1cbiAgICB9XG4gICAgdmFyIHRvdGFsUXR5ID0gMDtcbiAgICB2YXIgaXRlbXNWYWxpZCA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0ZWRMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBlbGVtZW50ID0gc2VsZWN0ZWRMaXN0W2ldLnF0eTtcbiAgICAgICAgdG90YWxRdHkgKz0gZWxlbWVudDtcbiAgICAgICAgaWYgKHRvdGFsUXR5IDw9IG1heEl0ZW1zKSB7XG4gICAgICAgICAgICBpdGVtc1ZhbGlkLnB1c2goc2VsZWN0ZWRMaXN0W2ldKTtcbiAgICAgICAgfWVsc2Uge1xuICAgICAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZWxlY3RlZExpc3QgPSBpdGVtc1ZhbGlkID8gaXRlbXNWYWxpZDogc2VsZWN0ZWRMaXN0O1xuICAgIGlmICghc2VsZWN0ZWRMaXN0Lmxlbmd0aCkge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCdsaS5zZWxlY3RlZC1ib251cy1pdGVtJykucmVtb3ZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGksIGxlbjtcbiAgICAgICAgZm9yIChpID0gMCwgbGVuID0gc2VsZWN0ZWRMaXN0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IHNlbGVjdGVkTGlzdFtpXTtcbiAgICAgICAgICAgIHZhciBsaSA9IHNlbGVjdGVkSXRlbVRlbXBsYXRlKGl0ZW0pO1xuICAgICAgICAgICAgJChsaSkuYXBwZW5kVG8odWxMaXN0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGdldCByZW1haW5pbmcgaXRlbSBjb3VudFxuICAgIHZhciByZW1haW4gPSBtYXhJdGVtcyAtIHNlbGVjdGVkTGlzdC5sZW5ndGg7XG4gICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLmJvbnVzLWl0ZW1zLWF2YWlsYWJsZScpLnRleHQocmVtYWluKTtcbiAgICBpZiAocmVtYWluIDw9IDApIHtcbiAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgIH1cblxuICAgIHZhciB0b3RxdWFudGl0eWNvdW50ID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGVkTGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGxldCBlbGVtZW50ID0gc2VsZWN0ZWRMaXN0W2ldLnF0eTtcbiAgICB0b3RxdWFudGl0eWNvdW50ICs9IGVsZW1lbnQ7XG4gICAgaWYgKHRvdHF1YW50aXR5Y291bnQgPj0gbWF4SXRlbXMpIHtcbiAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVHcmlkICgpIHtcbiAgICB2YXIgJGJvbnVzUHJvZHVjdCA9ICQoJyNib251cy1wcm9kdWN0LWRpYWxvZycpLFxuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdCA9ICQoJyNib251cy1wcm9kdWN0LWxpc3QnKSxcbiAgICAgICAgYmxpRGF0YSA9ICRib251c1Byb2R1Y3RMaXN0LmRhdGEoJ2xpbmUtaXRlbS1kZXRhaWwnKTtcbiAgICBtYXhJdGVtcyA9IGJsaURhdGEubWF4SXRlbXM7XG4gICAgYmxpVVVJRCA9IGJsaURhdGEudXVpZDtcblxuICAgIGlmIChibGlEYXRhLml0ZW1Db3VudCA+PSBtYXhJdGVtcykge1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0LWJvbnVzLWl0ZW0nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH1cblxuICAgIHZhciBjYXJ0SXRlbXMgPSAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuc2VsZWN0ZWQtYm9udXMtaXRlbScpO1xuICAgIHNlbGVjdGVkTGlzdC5sZW5ndGggPSAwO1xuICAgIGNhcnRJdGVtcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNpID0gJCh0aGlzKTtcbiAgICAgICAgdmFyIHByb2R1Y3QgPSB7XG4gICAgICAgICAgICB1dWlkOiBjaS5kYXRhKCd1dWlkJyksXG4gICAgICAgICAgICBwaWQ6ICcnKyBjaS5kYXRhKCdwaWQnKSxcbiAgICAgICAgICAgIHF0eTogZXZhbChjaS5maW5kKCcuaXRlbS1xdHkgLmRpc3BsYXktdmFsdWUnKS50ZXh0KCkpLFxuICAgICAgICAgICAgbmFtZTogY2kuZmluZCgnLml0ZW0tbmFtZScpLmh0bWwoKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHt9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBhdHRyaWJ1dGVzID0gY2kuZmluZCgndWwuaXRlbS1hdHRyaWJ1dGVzIGxpJyk7XG4gICAgICAgIGF0dHJpYnV0ZXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGkgPSAkKHRoaXMpO1xuICAgICAgICAgICAgcHJvZHVjdC5hdHRyaWJ1dGVzW2xpLmRhdGEoJ2F0dHJpYnV0ZUlkJyldID0ge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOmxpLmNoaWxkcmVuKCcuZGlzcGxheS1uYW1lJykuaHRtbCgpLFxuICAgICAgICAgICAgICAgIGRpc3BsYXlWYWx1ZTpsaS5jaGlsZHJlbignLmRpc3BsYXktdmFsdWUnKS5odG1sKClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICBzZWxlY3RlZExpc3QucHVzaChwcm9kdWN0KTtcbiAgICB9KTtcbiAgICB2YXIgdG90cXVhbnRpdHljb3VudCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3RlZExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgZWxlbWVudCA9IHNlbGVjdGVkTGlzdFtpXS5xdHk7XG4gICAgdG90cXVhbnRpdHljb3VudCArPSBlbGVtZW50O1xuICAgIGlmICh0b3RxdWFudGl0eWNvdW50ID49IG1heEl0ZW1zKSB7XG4gICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJy5zZWxlY3QtYm9udXMtaXRlbScpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgfVxuICAgIH1cblxuICAgICRib251c1Byb2R1Y3RMaXN0Lm9uKCdjbGljaycsICcuYm9udXMtcHJvZHVjdC1pdGVtIGFbaHJlZl0uc3dhdGNoYW5jaG9yJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdXJsID0gdGhpcy5ocmVmLFxuICAgICAgICAgICAgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKHVybCwge1xuICAgICAgICAgICAgJ3NvdXJjZSc6ICdib251cycsXG4gICAgICAgICAgICAnZm9ybWF0JzogJ2FqYXgnXG4gICAgICAgIH0pO1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5jbG9zZXN0KCcuYm9udXMtcHJvZHVjdC1pdGVtJykuZW1wdHkoKS5odG1sKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBoaWRlU3dhdGNoZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSlcbiAgICAub24oJ2NoYW5nZScsICcuaW5wdXQtdGV4dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgJCh0aGlzKS5jbG9zZXN0KCcuYm9udXMtcHJvZHVjdC1mb3JtJykuZmluZCgnLnF1YW50aXR5LWVycm9yJykudGV4dCgnJyk7XG4gICAgICAgIHZhciBib251c2NvdW50ID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3RlZExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGVsZW1lbnQgPSBzZWxlY3RlZExpc3RbaV0ucXR5O1xuICAgICAgICBib251c2NvdW50ICs9IGVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJvbnVzY291bnQgPj0gbWF4SXRlbXMpIHtcbiAgICAgICAgICAgIHNlbGVjdGVkTGlzdCA9IFtdO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAub24oJ2NsaWNrJywgJy5zZWxlY3QtYm9udXMtaXRlbScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkTGlzdC5sZW5ndGggPj0gbWF4SXRlbXMpIHtcbiAgICAgICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJy5zZWxlY3QtYm9udXMtaXRlbScpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCcuYm9udXMtaXRlbXMtYXZhaWxhYmxlJykudGV4dCgnMCcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZvcm0gPSAkKHRoaXMpLmNsb3Nlc3QoJy5ib251cy1wcm9kdWN0LWZvcm0nKSxcbiAgICAgICAgICAgIGRldGFpbCA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3QtZGV0YWlsJyksXG4gICAgICAgICAgICB1dWlkID0gZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwicHJvZHVjdFVVSURcIl0nKS52YWwoKSxcbiAgICAgICAgICAgIHF0eVZhbCA9IGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIlF1YW50aXR5XCJdJykudmFsKCksXG4gICAgICAgICAgICBxdHkgPSAoaXNOYU4ocXR5VmFsKSkgPyAxIDogKCtxdHlWYWwpO1xuXG4gICAgICAgIGlmIChxdHkgPiBtYXhJdGVtcykge1xuICAgICAgICAgICAgJGJvbnVzUHJvZHVjdExpc3QuZmluZCgnLnNlbGVjdC1ib251cy1pdGVtJykuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIGZvcm0uZmluZCgnLnF1YW50aXR5LWVycm9yJykudGV4dChSZXNvdXJjZXMuQk9OVVNfUFJPRFVDVF9UT09NQU5ZKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcm9kdWN0ID0ge1xuICAgICAgICAgICAgdXVpZDogdXVpZCxcbiAgICAgICAgICAgIHBpZDogZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwicGlkXCJdJykudmFsKCksXG4gICAgICAgICAgICBxdHk6IHF0eSxcbiAgICAgICAgICAgIG5hbWU6IGRldGFpbC5maW5kKCcucHJvZHVjdC1uYW1lJykudGV4dCgpLFxuICAgICAgICAgICAgYXR0cmlidXRlczogZGV0YWlsLmZpbmQoJy5wcm9kdWN0LXZhcmlhdGlvbnMnKS5kYXRhKCdhdHRyaWJ1dGVzJyksXG4gICAgICAgICAgICBvcHRpb25zOiBbXVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBvcHRpb25TZWxlY3RzID0gZm9ybS5maW5kKCcucHJvZHVjdC1vcHRpb24nKTtcbiAgICAgICAgb3B0aW9uU2VsZWN0cy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHByb2R1Y3Qub3B0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICAgICAgICAgICAgdmFsdWU6ICQodGhpcykudmFsKCksXG4gICAgICAgICAgICAgICAgZGlzcGxheTogJCh0aGlzKS5jaGlsZHJlbignOnNlbGVjdGVkJykuZmlyc3QoKS5odG1sKClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgc2VsZWN0ZWRmaW5kcHJvZHVjdCA9IHNlbGVjdGVkTGlzdC5maW5kKChwcm9kdWN0bGlzdCkgPT4gcHJvZHVjdGxpc3QucGlkID09PSBwcm9kdWN0LnBpZCk7XG5cbiAgICAgICAgaWYgKCFzZWxlY3RlZGZpbmRwcm9kdWN0KSB7XG4gICAgICAgICAgICBzZWxlY3RlZExpc3QucHVzaChwcm9kdWN0KVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IHRlbXBzZWxlY3RlZExpc3QgPSBzZWxlY3RlZExpc3QubWFwKChzcHJvZHVjdCk9PntcbiAgICAgICAgICAgICAgICBpZiAocHJvZHVjdC5waWQgPT09IHNwcm9kdWN0LnBpZCkge1xuICAgICAgICAgICAgICAgICAgICBzcHJvZHVjdC5xdHkgKz0gcHJvZHVjdC5xdHk7XG4gICAgICAgICAgICAgICAgICAgICBpZiAoc3Byb2R1Y3QucXR5ID4gbWF4SXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgXHRzZWxlY3RlZExpc3QgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHJvZHVjdC5xdHkgPSBzcHJvZHVjdC5xdHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzcHJvZHVjdDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZWN0ZWRMaXN0ID0gdGVtcHNlbGVjdGVkTGlzdDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgJGJvbnVzUHJvZHVjdExpc3QgPSAkKCcjYm9udXMtcHJvZHVjdC1saXN0Jyk7XG4gICAgICAgICRib251c1Byb2R1Y3RMaXN0LmZpbmQoJ2xpLnNlbGVjdGVkLWJvbnVzLWl0ZW0nKS5yZW1vdmUoKTtcbiAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xuICAgIH0pXG4gICAgLm9uKCdjbGljaycsICcucmVtb3ZlLWxpbmsnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBjb250YWluZXIgPSAkKHRoaXMpLmNsb3Nlc3QoJy5zZWxlY3RlZC1ib251cy1pdGVtJyk7XG4gICAgICAgIGlmICghY29udGFpbmVyLmRhdGEoJ3V1aWQnKSkgeyByZXR1cm47IH1cblxuICAgICAgICB2YXIgdXVpZCA9IGNvbnRhaW5lci5kYXRhKCd1dWlkJyk7XG4gICAgICAgIHZhciBpLCBsZW4gPSBzZWxlY3RlZExpc3QubGVuZ3RoO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3RlZExpc3RbaV0udXVpZCA9PT0gdXVpZCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkTGlzdC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0ICRib251c1Byb2R1Y3RMaXN0ID0gJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpO1xuICAgICAgICAkYm9udXNQcm9kdWN0TGlzdC5maW5kKCdsaS5zZWxlY3RlZC1ib251cy1pdGVtJykucmVtb3ZlKCk7XG4gICAgICAgIHVwZGF0ZVN1bW1hcnkoKTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnLmFkZC10by1jYXJ0LWJvbnVzJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmFkZEJvbnVzUHJvZHVjdCwge2JvbnVzRGlzY291bnRMaW5lSXRlbVVVSUQ6IGJsaVVVSUR9KTtcbiAgICAgICAgdmFyIGJvbnVzUHJvZHVjdHMgPSBnZXRCb251c1Byb2R1Y3RzKCk7XG4gICAgICAgIGlmIChib251c1Byb2R1Y3RzLmJvbnVzcHJvZHVjdHNbMF0ucHJvZHVjdC5xdHkgPiBtYXhJdGVtcykge1xuICAgICAgICAgICAgYm9udXNQcm9kdWN0cy5ib251c3Byb2R1Y3RzWzBdLnByb2R1Y3QucXR5ID0gbWF4SXRlbXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbWFrZSB0aGUgc2VydmVyIGNhbGxcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeShib251c1Byb2R1Y3RzKVxuICAgICAgICB9KVxuICAgICAgICAuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBzdWNjZXNzXG4gICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmZhaWwoZnVuY3Rpb24gKHhociwgdGV4dFN0YXR1cykge1xuICAgICAgICAgICAgLy8gZmFpbGVkXG4gICAgICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQkFEX1JFU1BPTlNFKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5TRVJWRVJfQ09OTkVDVElPTl9FUlJPUik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5hbHdheXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJGJvbnVzUHJvZHVjdC5kaWFsb2coJ2Nsb3NlJyk7XG4gICAgICAgIH0pO1xuICAgIH0pXG4gICAgLm9uKCdjbGljaycsICcjbW9yZS1ib251cy1wcm9kdWN0cycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHV1aWQgPSAkKCcjYm9udXMtcHJvZHVjdC1saXN0JykuZGF0YSgpLmxpbmVJdGVtRGV0YWlsLnV1aWQ7XG5cbiAgICAgICAgLy9nZXQgdGhlIG5leHQgcGFnZSBvZiBjaG9pY2Ugb2YgYm9udXMgcHJvZHVjdHNcbiAgICAgICAgdmFyIGxpbmVJdGVtRGV0YWlsID0gSlNPTi5wYXJzZSgkKCcjYm9udXMtcHJvZHVjdC1saXN0JykuYXR0cignZGF0YS1saW5lLWl0ZW0tZGV0YWlsJykpO1xuICAgICAgICBsaW5lSXRlbURldGFpbC5wYWdlU3RhcnQgPSBsaW5lSXRlbURldGFpbC5wYWdlU3RhcnQgKyBsaW5lSXRlbURldGFpbC5wYWdlU2l6ZTtcbiAgICAgICAgJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmF0dHIoJ2RhdGEtbGluZS1pdGVtLWRldGFpbCcsIEpTT04uc3RyaW5naWZ5KGxpbmVJdGVtRGV0YWlsKSk7XG5cbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5nZXRCb251c1Byb2R1Y3RzLCB7XG4gICAgICAgICAgICBib251c0Rpc2NvdW50TGluZUl0ZW1VVUlEOiB1dWlkLFxuICAgICAgICAgICAgZm9ybWF0OiAnYWpheCcsXG4gICAgICAgICAgICBsYXp5TG9hZDogJ3RydWUnLFxuICAgICAgICAgICAgcGFnZVN0YXJ0OiBsaW5lSXRlbURldGFpbC5wYWdlU3RhcnQsXG4gICAgICAgICAgICBwYWdlU2l6ZTogJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmRhdGEoKS5saW5lSXRlbURldGFpbC5wYWdlU2l6ZSxcbiAgICAgICAgICAgIGJvbnVzUHJvZHVjdHNUb3RhbDogJCgnI2JvbnVzLXByb2R1Y3QtbGlzdCcpLmRhdGEoKS5saW5lSXRlbURldGFpbC5icFRvdGFsXG4gICAgICAgIH0pO1xuXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB0eXBlOiAnR0VUJyxcbiAgICAgICAgICAgIGNhY2hlOiBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICB1cmw6IHVybFxuICAgICAgICB9KVxuICAgICAgICAuZG9uZShmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgLy9hZGQgdGhlIG5ldyBwYWdlIHRvIERPTSBhbmQgcmVtb3ZlICdNb3JlJyBsaW5rIGlmIGl0IGlzIHRoZSBsYXN0IHBhZ2Ugb2YgcmVzdWx0c1xuICAgICAgICAgICAgJCgnI21vcmUtYm9udXMtcHJvZHVjdHMnKS5iZWZvcmUoZGF0YSk7XG4gICAgICAgICAgICBpZiAoKGxpbmVJdGVtRGV0YWlsLnBhZ2VTdGFydCArIGxpbmVJdGVtRGV0YWlsLnBhZ2VTaXplKSA+PSAkKCcjYm9udXMtcHJvZHVjdC1saXN0JykuZGF0YSgpLmxpbmVJdGVtRGV0YWlsLmJwVG90YWwpIHtcbiAgICAgICAgICAgICAgICAkKCcjbW9yZS1ib251cy1wcm9kdWN0cycpLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuZmFpbChmdW5jdGlvbiAoeGhyLCB0ZXh0U3RhdHVzKSB7XG4gICAgICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChSZXNvdXJjZXMuQkFEX1JFU1BPTlNFKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5TRVJWRVJfQ09OTkVDVElPTl9FUlJPUik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG52YXIgYm9udXNQcm9kdWN0c1ZpZXcgPSB7XG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIE9wZW4gdGhlIGxpc3Qgb2YgYm9udXMgcHJvZHVjdHMgc2VsZWN0aW9uIGRpYWxvZ1xuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uICh1cmwpIHtcbiAgICAgICAgdmFyICRib251c1Byb2R1Y3QgPSAkKCcjYm9udXMtcHJvZHVjdC1kaWFsb2cnKTtcbiAgICAgICAgLy8gY3JlYXRlIHRoZSBkaWFsb2dcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdGFyZ2V0OiAkYm9udXNQcm9kdWN0LFxuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IDc5NSxcbiAgICAgICAgICAgICAgICB0aXRsZTogUmVzb3VyY2VzLkJPTlVTX1BST0RVQ1RTXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpbml0aWFsaXplR3JpZCgpO1xuICAgICAgICAgICAgICAgIGhpZGVTd2F0Y2hlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBPcGVuIGJvbnVzIHByb2R1Y3QgcHJvbW8gcHJvbXB0IGRpYWxvZ1xuICAgICAqL1xuICAgIGxvYWRCb251c09wdGlvbjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgICAgc2VsZiA9IHRoaXMsXG4gICAgICAgICAgICBib251c0Rpc2NvdW50Q29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmJvbnVzLWRpc2NvdW50LWNvbnRhaW5lcicpO1xuICAgICAgICBpZiAoIWJvbnVzRGlzY291bnRDb250YWluZXIpIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgLy8gZ2V0IHRoZSBodG1sIGZyb20gbWluaWNhcnQsIHRoZW4gdHJhc2ggaXRcbiAgICAgICAgdmFyIGJvbnVzRGlzY291bnRDb250YWluZXJIdG1sID0gYm9udXNEaXNjb3VudENvbnRhaW5lci5vdXRlckhUTUw7XG4gICAgICAgIGJvbnVzRGlzY291bnRDb250YWluZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChib251c0Rpc2NvdW50Q29udGFpbmVyKTtcblxuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICBodG1sOiBib251c0Rpc2NvdW50Q29udGFpbmVySHRtbCxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogNDAwLFxuICAgICAgICAgICAgICAgIHRpdGxlOiBSZXNvdXJjZXMuQk9OVVNfUFJPRFVDVCxcbiAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuU0VMRUNUX0JPTlVTX1BST0RVQ1RTLFxuICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHV1aWQgPSAkKCcuYm9udXMtcHJvZHVjdC1wcm9tbycpLmRhdGEoJ2xpbmVpdGVtaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKFVybHMuZ2V0Qm9udXNQcm9kdWN0cywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib251c0Rpc2NvdW50TGluZUl0ZW1VVUlEOiB1dWlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICdib251cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdDogJ2FqYXgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXp5TG9hZDogJ2ZhbHNlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVN0YXJ0OiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlU2l6ZTogMTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvbnVzUHJvZHVjdHNUb3RhbDogLTFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zaG93KHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IFJlc291cmNlcy5OT19USEFOS1MsXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmRpYWxvZygnY2xvc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1dXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBzaG93IGhpZGUgcHJvbW8gZGV0YWlsc1xuICAgICAgICAgICAgICAgICQoJy5zaG93LXByb21vLWRldGFpbHMnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJy5wcm9tby1kZXRhaWxzJykudG9nZ2xlQ2xhc3MoJ3Zpc2libGUnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBib251c1Byb2R1Y3RzVmlldztcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIFNlc3Npb25BdHRyaWJ1dGVzID0gd2luZG93LlNlc3Npb25BdHRyaWJ1dGVzO1xuXG4vKipcbiAqIEBmdW5jdGlvbiBjYXB0Y2hhICAgIFVzZWQgdG8gZGlzcGxheS9jb250cm9sIHRoZSBzY3JpbSBjb250YWluaW5nIHRoZSBzaW11bGF0ZWQgY2FwdGNoYSBjb2RlXG4gKiovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAvKipcbiAgICAgKiBpZiB0aGUgc2Vzc2lvbi5wcml2YWN5LnJhdGVsaW1pdGVkIGVsZW1lbnQgaXMgcHJlc2VudCB0aGVuIHNob3cgdGhlIG5vdGlmaWNhdGlvblxuICAgICAqIE5PVEU6IFlvdSB3aWxsIHByb2JhYmx5IHdhbnQgdG8gcmVwbGFjZSB0aGlzIHdpdGggYSBjYWxsIHRvIGFuIGFjdHVhbCBDQVBUQ0hBIHN5c3RlbSB0byByZXBsYWNlIHRoZSBzaW1wbGUgb25lIGhlcmVcbiAgICAgKi9cbiAgICBpZiAoU2Vzc2lvbkF0dHJpYnV0ZXMuU0hPV19DQVBUQ0hBKSB7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIGh0bWw6ICc8aDE+JyArIFJlc291cmNlcy5BUkVfWU9VX0hVTUFOICsgJzwvaDE+JyxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBjbG9zZU9uRXNjYXBlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkaWFsb2dDbGFzczogJ25vLWNsb3NlJyxcbiAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBSZXNvdXJjZXMuT0ssXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLnJhdGVMaW1pdGVyUmVzZXQsIHtmb3JtYXQ6ICdhamF4J30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6IHVybFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmRpYWxvZygnY2xvc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1dXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBwYWdlID0gcmVxdWlyZSgnLi9wYWdlJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIFRQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpO1xuXG52YXIgX2N1cnJlbnRDYXRlZ29yeSA9ICcnLFxuICAgIE1BWF9BQ1RJVkUgPSA2O1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBWZXJpZmllcyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBjb21wYXJlIGNvbnRhaW5lciBhbmQgdXBkYXRlcyBpdCB3aXRoIHNlcXVlbnRpYWwgY2xhc3NlcyBmb3IgdWkgdGFyZ2V0aW5nXG4gKi9cbmZ1bmN0aW9uIHJlZnJlc2hDb250YWluZXIoKSB7XG4gICAgdmFyICRjb21wYXJlQ29udGFpbmVyID0gJCgnLmNvbXBhcmUtaXRlbXMnKTtcbiAgICB2YXIgJGNvbXBhcmVJdGVtcyA9ICRjb21wYXJlQ29udGFpbmVyLmZpbmQoJy5jb21wYXJlLWl0ZW0nKTtcbiAgICB2YXIgbnVtQWN0aXZlID0gJGNvbXBhcmVJdGVtcy5maWx0ZXIoJy5hY3RpdmUnKS5sZW5ndGg7XG5cbiAgICBpZiAobnVtQWN0aXZlIDwgMikge1xuICAgICAgICAkKCcjY29tcGFyZS1pdGVtcy1idXR0b24nKS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICQoJyNjb21wYXJlLWl0ZW1zLWJ1dHRvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgfVxuXG4gICAgJGNvbXBhcmVDb250YWluZXIudG9nZ2xlKG51bUFjdGl2ZSA+IDApO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQWRkcyBhbiBpdGVtIHRvIHRoZSBjb21wYXJlIGNvbnRhaW5lciBhbmQgcmVmcmVzaGVzIGl0XG4gKi9cbmZ1bmN0aW9uIGFkZFRvTGlzdChkYXRhKSB7XG4gICAgLy8gZ2V0IHRoZSBmaXJzdCBjb21wYXJlLWl0ZW0gbm90IGN1cnJlbnRseSBhY3RpdmVcbiAgICB2YXIgJGl0ZW0gPSAkKCcuY29tcGFyZS1pdGVtcyAuY29tcGFyZS1pdGVtJykubm90KCcuYWN0aXZlJykuZmlyc3QoKSxcbiAgICAgICAgJHByb2R1Y3RUaWxlID0gJCgnIycgKyBkYXRhLnV1aWQpO1xuXG4gICAgaWYgKCRpdGVtLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZiAoJHByb2R1Y3RUaWxlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRwcm9kdWN0VGlsZS5maW5kKCcuY29tcGFyZS1jaGVjaycpWzBdLmNoZWNrZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkNPTVBBUkVfQUREX0ZBSUwpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gaWYgYWxyZWFkeSBhZGRlZCBzb21laG93LCByZXR1cm5cbiAgICBpZiAoJCgnW2RhdGEtdXVpZD1cIicgKyBkYXRhLnV1aWQgKyAnXCJdJykubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIHNldCBhcyBhY3RpdmUgaXRlbVxuICAgICRpdGVtLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAuYXR0cignZGF0YS11dWlkJywgZGF0YS51dWlkKVxuICAgICAgICAuYXR0cignZGF0YS1pdGVtaWQnLCBkYXRhLml0ZW1pZClcbiAgICAgICAgLmRhdGEoJ3V1aWQnLCBkYXRhLnV1aWQpXG4gICAgICAgIC5kYXRhKCdpdGVtaWQnLCBkYXRhLml0ZW1pZClcbiAgICAgICAgLmFwcGVuZCgkKGRhdGEuaW1nKS5jbG9uZSgpLmFkZENsYXNzKCdjb21wYXJlLWl0ZW0taW1hZ2UnKSk7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIGRlc2NyaXB0aW9uIFJlbW92ZXMgYW4gaXRlbSBmcm9tIHRoZSBjb21wYXJlIGNvbnRhaW5lciBhbmQgcmVmcmVzaGVzIGl0XG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUZyb21MaXN0KCRpdGVtKSB7XG4gICAgaWYgKCRpdGVtLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAvLyByZW1vdmUgY2xhc3MsIGRhdGEgYW5kIGlkIGZyb20gaXRlbVxuICAgICRpdGVtLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuICAgICAgICAucmVtb3ZlQXR0cignZGF0YS11dWlkJylcbiAgICAgICAgLnJlbW92ZUF0dHIoJ2RhdGEtaXRlbWlkJylcbiAgICAgICAgLmRhdGEoJ3V1aWQnLCAnJylcbiAgICAgICAgLmRhdGEoJ2l0ZW1pZCcsICcnKVxuICAgICAgICAvLyByZW1vdmUgdGhlIGltYWdlXG4gICAgICAgIC5maW5kKCcuY29tcGFyZS1pdGVtLWltYWdlJykucmVtb3ZlKCk7XG59XG5cbmZ1bmN0aW9uIGFkZFByb2R1Y3RBamF4KGFyZ3MpIHtcbiAgICB2YXIgcHJvbWlzZSA9IG5ldyBUUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IFVybHMuY29tcGFyZUFkZCxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBwaWQ6IGFyZ3MuaXRlbWlkLFxuICAgICAgICAgICAgICAgIGNhdGVnb3J5OiBfY3VycmVudENhdGVnb3J5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJ1xuICAgICAgICB9KS5kb25lKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZSB8fCAhcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoUmVzb3VyY2VzLkNPTVBBUkVfQUREX0ZBSUwpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmZhaWwoZnVuY3Rpb24gKGpxeGhyLCBzdGF0dXMsIGVycikge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihlcnIpKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHByb21pc2U7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZVByb2R1Y3RBamF4KGFyZ3MpIHtcbiAgICB2YXIgcHJvbWlzZSA9IG5ldyBUUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IFVybHMuY29tcGFyZVJlbW92ZSxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBwaWQ6IGFyZ3MuaXRlbWlkLFxuICAgICAgICAgICAgICAgIGNhdGVnb3J5OiBfY3VycmVudENhdGVnb3J5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJ1xuICAgICAgICB9KS5kb25lKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZSB8fCAhcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoUmVzb3VyY2VzLkNPTVBBUkVfUkVNT1ZFX0ZBSUwpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmZhaWwoZnVuY3Rpb24gKGpxeGhyLCBzdGF0dXMsIGVycikge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihlcnIpKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHByb21pc2U7XG59XG5cbmZ1bmN0aW9uIHNoaWZ0SW1hZ2VzKCkge1xuICAgIHJldHVybiBuZXcgVFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICAgICAgdmFyICRpdGVtcyA9ICQoJy5jb21wYXJlLWl0ZW1zIC5jb21wYXJlLWl0ZW0nKTtcbiAgICAgICAgJGl0ZW1zLmVhY2goZnVuY3Rpb24gKGksIGl0ZW0pIHtcbiAgICAgICAgICAgIHZhciAkaXRlbSA9ICQoaXRlbSk7XG4gICAgICAgICAgICAvLyBsYXN0IGl0ZW1cbiAgICAgICAgICAgIGlmIChpID09PSAkaXRlbXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVGcm9tTGlzdCgkaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgJG5leHQgPSAkaXRlbXMuZXEoaSArIDEpO1xuICAgICAgICAgICAgaWYgKCRuZXh0Lmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdHMgb3duIGltYWdlXG4gICAgICAgICAgICAgICAgJG5leHQuZmluZCgnLmNvbXBhcmUtaXRlbS1pbWFnZScpLmRldGFjaCgpLmFwcGVuZFRvKCRpdGVtKTtcbiAgICAgICAgICAgICAgICAkaXRlbS5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2RhdGEtdXVpZCcsICRuZXh0LmRhdGEoJ3V1aWQnKSlcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2RhdGEtaXRlbWlkJywgJG5leHQuZGF0YSgnaXRlbWlkJykpXG4gICAgICAgICAgICAgICAgICAgIC5kYXRhKCd1dWlkJywgJG5leHQuZGF0YSgndXVpZCcpKVxuICAgICAgICAgICAgICAgICAgICAuZGF0YSgnaXRlbWlkJywgJG5leHQuZGF0YSgnaXRlbWlkJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEFkZHMgcHJvZHVjdCB0byB0aGUgY29tcGFyZSB0YWJsZVxuICovXG5mdW5jdGlvbiBhZGRQcm9kdWN0KGFyZ3MpIHtcbiAgICB2YXIgcHJvbWlzZTtcbiAgICB2YXIgJGl0ZW1zID0gJCgnLmNvbXBhcmUtaXRlbXMgLmNvbXBhcmUtaXRlbScpO1xuICAgIHZhciAkY2IgPSAkKGFyZ3MuY2IpO1xuICAgIHZhciBudW1BY3RpdmUgPSAkaXRlbXMuZmlsdGVyKCcuYWN0aXZlJykubGVuZ3RoO1xuICAgIGlmIChudW1BY3RpdmUgPT09IE1BWF9BQ1RJVkUpIHtcbiAgICAgICAgaWYgKCF3aW5kb3cuY29uZmlybShSZXNvdXJjZXMuQ09NUEFSRV9DT05GSVJNQVRJT04pKSB7XG4gICAgICAgICAgICAkY2JbMF0uY2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVtb3ZlIHByb2R1Y3QgdXNpbmcgaWRcbiAgICAgICAgdmFyICRmaXJzdEl0ZW0gPSAkaXRlbXMuZmlyc3QoKTtcbiAgICAgICAgcHJvbWlzZSA9IHJlbW92ZUl0ZW0oJGZpcnN0SXRlbSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2hpZnRJbWFnZXMoKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcHJvbWlzZSA9IFRQcm9taXNlLnJlc29sdmUoMCk7XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gYWRkUHJvZHVjdEFqYXgoYXJncykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhZGRUb0xpc3QoYXJncyk7XG4gICAgICAgICAgICBpZiAoJGNiICYmICRjYi5sZW5ndGggPiAwKSB7ICRjYlswXS5jaGVja2VkID0gdHJ1ZTsgfVxuICAgICAgICAgICAgcmVmcmVzaENvbnRhaW5lcigpO1xuICAgICAgICB9KTtcbiAgICB9KS50aGVuKG51bGwsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCRjYiAmJiAkY2IubGVuZ3RoID4gMCkgeyAkY2JbMF0uY2hlY2tlZCA9IGZhbHNlOyB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyBwcm9kdWN0IGZyb20gdGhlIGNvbXBhcmUgdGFibGVcbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gdGhlIGFyZ3VtZW50cyBvYmplY3Qgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOiBpdGVtaWQsIHV1aWQgYW5kIGNiIChjaGVja2JveClcbiAqL1xuZnVuY3Rpb24gcmVtb3ZlUHJvZHVjdChhcmdzKSB7XG4gICAgdmFyICRjYiA9IGFyZ3MuY2IgPyAkKGFyZ3MuY2IpIDogbnVsbDtcbiAgICByZXR1cm4gcmVtb3ZlUHJvZHVjdEFqYXgoYXJncykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkaXRlbSA9ICQoJ1tkYXRhLXV1aWQ9XCInICsgYXJncy51dWlkICsgJ1wiXScpO1xuICAgICAgICByZW1vdmVGcm9tTGlzdCgkaXRlbSk7XG4gICAgICAgIGlmICgkY2IgJiYgJGNiLmxlbmd0aCA+IDApIHsgJGNiWzBdLmNoZWNrZWQgPSBmYWxzZTsgfVxuICAgICAgICByZWZyZXNoQ29udGFpbmVyKCk7XG4gICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoJGNiICYmICRjYi5sZW5ndGggPiAwKSB7ICRjYlswXS5jaGVja2VkID0gdHJ1ZTsgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiByZW1vdmVJdGVtKCRpdGVtKSB7XG4gICAgdmFyIHV1aWQgPSAkaXRlbS5kYXRhKCd1dWlkJyksXG4gICAgICAgICRwcm9kdWN0VGlsZSA9ICQoJyMnICsgdXVpZCk7XG4gICAgcmV0dXJuIHJlbW92ZVByb2R1Y3Qoe1xuICAgICAgICBpdGVtaWQ6ICRpdGVtLmRhdGEoJ2l0ZW1pZCcpLFxuICAgICAgICB1dWlkOiB1dWlkLFxuICAgICAgICBjYjogKCRwcm9kdWN0VGlsZS5sZW5ndGggPT09IDApID8gbnVsbCA6ICRwcm9kdWN0VGlsZS5maW5kKCcuY29tcGFyZS1jaGVjaycpXG4gICAgfSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBET00tT2JqZWN0IG9mIHRoZSBjb21wYXJlIGNvbnRhaW5lclxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRG9tKCkge1xuICAgIHZhciAkY29tcGFyZUNvbnRhaW5lciA9ICQoJy5jb21wYXJlLWl0ZW1zJyk7XG4gICAgX2N1cnJlbnRDYXRlZ29yeSA9ICRjb21wYXJlQ29udGFpbmVyLmRhdGEoJ2NhdGVnb3J5JykgfHwgJyc7XG4gICAgdmFyICRhY3RpdmUgPSAkY29tcGFyZUNvbnRhaW5lci5maW5kKCcuY29tcGFyZS1pdGVtJykuZmlsdGVyKCcuYWN0aXZlJyk7XG4gICAgJGFjdGl2ZS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRwcm9kdWN0VGlsZSA9ICQoJyMnICsgICQodGhpcykuZGF0YSgndXVpZCcpKTtcbiAgICAgICAgaWYgKCRwcm9kdWN0VGlsZS5sZW5ndGggPT09IDApIHtyZXR1cm47fVxuICAgICAgICAkcHJvZHVjdFRpbGUuZmluZCgnLmNvbXBhcmUtY2hlY2snKVswXS5jaGVja2VkID0gdHJ1ZTtcbiAgICB9KTtcbiAgICAvLyBzZXQgY29udGFpbmVyIHN0YXRlXG4gICAgcmVmcmVzaENvbnRhaW5lcigpO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgZXZlbnRzIG9uIHRoZSBjb21wYXJlIGNvbnRhaW5lclxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgIC8vIGFkZCBldmVudCB0byBidXR0b25zIHRvIHJlbW92ZSBwcm9kdWN0c1xuICAgICQoJy5jb21wYXJlLWl0ZW0nKS5vbignY2xpY2snLCAnLmNvbXBhcmUtaXRlbS1yZW1vdmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlbW92ZUl0ZW0oJCh0aGlzKS5jbG9zZXN0KCcuY29tcGFyZS1pdGVtJykpO1xuICAgIH0pO1xuXG4gICAgLy8gQnV0dG9uIHRvIGdvIHRvIGNvbXBhcmUgcGFnZVxuICAgICQoJyNjb21wYXJlLWl0ZW1zLWJ1dHRvbicpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcGFnZS5yZWRpcmVjdCh1dGlsLmFwcGVuZFBhcmFtVG9VUkwoVXJscy5jb21wYXJlU2hvdywgJ2NhdGVnb3J5JywgX2N1cnJlbnRDYXRlZ29yeSkpO1xuICAgIH0pO1xuXG4gICAgLy8gQnV0dG9uIHRvIGNsZWFyIGFsbCBjb21wYXJlZCBpdGVtc1xuICAgIC8vIHJlbHkgb24gcmVmcmVzaENvbnRhaW5lciB0byB0YWtlIGNhcmUgb2YgaGlkaW5nIHRoZSBjb250YWluZXJcbiAgICAkKCcjY2xlYXItY29tcGFyZWQtaXRlbXMnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJy5jb21wYXJlLWl0ZW1zIC5hY3RpdmUnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJlbW92ZUl0ZW0oJCh0aGlzKSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaW5pdGlhbGl6ZURvbSgpO1xuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbn07XG5cbmV4cG9ydHMuYWRkUHJvZHVjdCA9IGFkZFByb2R1Y3Q7XG5leHBvcnRzLnJlbW92ZVByb2R1Y3QgPSByZW1vdmVQcm9kdWN0O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWNjb3JkaW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkY29udGFpbmVyID0gJCh0aGlzKS5jbG9zZXN0KCcuYWNjb3JkaW9uJyk7XG4gICAgdmFyICRjb250ZW50ID0gJGNvbnRhaW5lci5maW5kKCcuanMtYWNjb3JkaW9uLWJvZHknKTtcbiAgICBcbiAgICAkY29udGFpbmVyLnRvZ2dsZUNsYXNzKCdtLW9wZW5lZCcpO1xuICAgICRjb250ZW50LnNsaWRlVG9nZ2xlKDI1MCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcuanMtYWNjb3JkaW9uLXN3aXRjaGVyJykub24oJ2NsaWNrJywgYWNjb3JkaW9uKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBjaGFuZ2VRdWFudGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcXVhbnRpdHlDdGFzID0gWydidXR0b24uanMtcXVhbnRpdHktZGVjcmVhc2UtYnV0dG9uJywgJ2J1dHRvbi5qcy1xdWFudGl0eS1pbmNyZWFzZS1idXR0b24nXTtcbiAgICAkKHF1YW50aXR5Q3RhcykuZWFjaChmdW5jdGlvbihpZHgsIGF0dHIpIHtcbiAgICAgICAgJHBkcE1haW4ub24oJ2NsaWNrJywgYXR0ciwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgJHF1YW50aXR5SW5wdXQgPSAkKGF0dHIpLnNpYmxpbmdzKCcuanMtcHJvZHVjdC1xdWFudGl0eS1pbnB1dCcpO1xuICAgICAgICAgICAgdmFyIHF1YW50aXR5SW5wdXRWYWwgPSBwYXJzZUludCgkcXVhbnRpdHlJbnB1dC52YWwoKSk7XG4gICAgICAgICAgICB2YXIgbW9kaWZpY2F0ZWRRdWFudGl0eTtcblxuICAgICAgICAgICAgaWYgKCQoYXR0cikuaGFzQ2xhc3MoJ2pzLXF1YW50aXR5LWRlY3JlYXNlLWJ1dHRvbicpKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZpY2F0ZWRRdWFudGl0eSA9IHF1YW50aXR5SW5wdXRWYWwgPiAxID8gcXVhbnRpdHlJbnB1dFZhbCAtIDEgOiAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgkKGF0dHIpLmhhc0NsYXNzKCdqcy1xdWFudGl0eS1pbmNyZWFzZS1idXR0b24nKSkge1xuICAgICAgICAgICAgICAgIG1vZGlmaWNhdGVkUXVhbnRpdHkgPSBxdWFudGl0eUlucHV0VmFsICsgMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuICRxdWFudGl0eUlucHV0LnZhbChtb2RpZmljYXRlZFF1YW50aXR5KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICQoJy5qcy1xdWFudGl0eS1idXR0b24nKS5vbignY2xpY2snLCBjaGFuZ2VRdWFudGl0eSk7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBzdGlja3lDb21wb25lbnQgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB0aGlzLmlzSW5pdCA9IGZhbHNlO1xuXG4gICAgICAgIGlmKHRoaXMuaXNFeGlzdChwYXJhbXMpKSB7XG4gICAgICAgICAgICB2YXIgJHRyaWdnZXJCbG9jayA9ICQocGFyYW1zLnRyaWdnZXIpO1xuICAgICAgICAgICAgdmFyIHRyaWdnZXJCb3R0b21Qb2ludCA9ICR0cmlnZ2VyQmxvY2sub2Zmc2V0KCkudG9wICsgJHRyaWdnZXJCbG9jay5oZWlnaHQoKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgdmFyIHN0aWNreUNvbnRleHQgPSB0aGlzO1xuICAgICAgICAgICAgJCh3aW5kb3cpLm9uKCdzY3JvbGwgbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5pdEV2ZW50O1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChpbml0RXZlbnQpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgaW5pdEV2ZW50ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQod2luZG93KS5zY3JvbGxUb3AoKSA+IHRyaWdnZXJCb3R0b21Qb2ludCAmJiAhc3RpY2t5Q29udGV4dC5pc0luaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0aWNreUNvbnRleHQuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJCh3aW5kb3cpLnNjcm9sbFRvcCgpIDwgdHJpZ2dlckJvdHRvbVBvaW50ICYmIHN0aWNreUNvbnRleHQuaXNJbml0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGlja3lDb250ZXh0LmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIDMwMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaXNFeGlzdDogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zICYmIHBhcmFtcy5zZWxlY3RvciAmJiAkKHBhcmFtcy5zZWxlY3RvcikubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kc3RpY2t5QmxvY2sgPSAkKHBhcmFtcy5zZWxlY3Rvcik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy4kc3RpY2t5QmxvY2spIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRzdGlja3lCbG9jaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZW5hYmxlOiBmdW5jdGlvbihwYXJhbXMpIHtcbiAgICAgICAgaWYodGhpcy5pc0V4aXN0KHBhcmFtcykpIHtcbiAgICAgICAgICAgIHRoaXMuJHN0aWNreUJsb2NrLmFkZENsYXNzKCdtLXN0aWNreS1lbmFibGUnKS5yZW1vdmVDbGFzcygnbS1zdGlja3ktZGlzYWJsZScpO1xuICAgICAgICAgICAgdGhpcy5pc0luaXQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkaXNhYmxlOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmKHRoaXMuaXNFeGlzdChwYXJhbXMpKSB7XG4gICAgICAgICAgICB0aGlzLiRzdGlja3lCbG9jay5yZW1vdmVDbGFzcygnbS1zdGlja3ktZW5hYmxlJykuYWRkQ2xhc3MoJ20tc3RpY2t5LWRpc2FibGUnKTtcbiAgICAgICAgICAgIHRoaXMuaXNJbml0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHN0aWNreUNvbXBvbmVudDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHNldHRpbmdzID0ge1xuICAgIGhvbWVQYWdlU2xpZGVyOiB7XG4gICAgICAgIGluZmluaXRlOiB0cnVlLFxuICAgICAgICBzbGlkZXNUb1Nob3c6IDEsXG4gICAgICAgIHNsaWRlc1RvU2Nyb2xsOiAxLFxuICAgICAgICBhdXRvcGxheTogdHJ1ZSxcbiAgICAgICAgZG90czogdHJ1ZSxcbiAgICAgICAgYXJyb3dzOiBmYWxzZVxuICAgIH0sXG4gICAgcGRwUHJpbWFyeUNhcm91c2VsOiB7XG4gICAgICAgIGluZmluaXRlOiBmYWxzZSxcbiAgICAgICAgc2xpZGVzVG9TaG93OiAxLFxuICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcbiAgICAgICAgYXJyb3dzOiB0cnVlLFxuICAgICAgICBhc05hdkZvcjogJy5wZHAtdGh1bWJuYWlscy1zbGlkZXInLFxuICAgICAgICByZXNwb25zaXZlOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYnJlYWtwb2ludDogNzY3LFxuICAgICAgICAgICAgICAgIHNldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGRvdHM6IHRydWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICB9LFxuICAgIHBkcFRodW1iQ2Fyb3VzZWw6IHtcbiAgICAgICAgaW5maW5pdGU6IGZhbHNlLFxuICAgICAgICBzbGlkZXNUb1Nob3c6IDQsXG4gICAgICAgIHNsaWRlc1RvU2Nyb2xsOiAxLFxuICAgICAgICBhcnJvd3M6IGZhbHNlLFxuICAgICAgICB2ZXJ0aWNhbDogdHJ1ZSxcbiAgICAgICAgdmVydGljYWxTd2lwaW5nOiB0cnVlLFxuICAgICAgICBhc05hdkZvcjogJy5wZHAtcHJpbWFyeS1zbGlkZXInLFxuICAgICAgICBjZW50ZXJNb2RlOiBmYWxzZSxcbiAgICAgICAgY2VudGVyUGFkZGluZzogJzBweCcsXG4gICAgICAgIGZvY3VzT25TZWxlY3Q6IHRydWVcbiAgICB9LFxuICAgIHBiVGh1bWJDYXJvdXNlbDoge1xuICAgICAgICBpbmZpbml0ZTogZmFsc2UsXG4gICAgICAgIHNsaWRlc1RvU2hvdzogNCxcbiAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG4gICAgICAgIGFycm93czogZmFsc2UsXG4gICAgICAgIHZlcnRpY2FsOiBmYWxzZSxcbiAgICAgICAgdmVydGljYWxTd2lwaW5nOiBmYWxzZSxcbiAgICAgICAgYXNOYXZGb3I6ICcucGRwLXByaW1hcnktc2xpZGVyJyxcbiAgICAgICAgY2VudGVyTW9kZTogZmFsc2UsXG4gICAgICAgIGNlbnRlclBhZGRpbmc6ICc1cHgnLFxuICAgICAgICBmb2N1c09uU2VsZWN0OiB0cnVlXG4gICAgfSxcbiAgICByZWNvbW1lbmRhdGlvbkNhcm91c2VsOiB7XG4gICAgICAgIGluZmluaXRlOiBmYWxzZSxcbiAgICAgICAgc2xpZGVzVG9TaG93OiA0LFxuICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcbiAgICAgICAgcmVzcG9uc2l2ZTogW1xuICAgICAgICB7XG4gICAgICAgICAgYnJlYWtwb2ludDogNzY3LFxuICAgICAgICAgIHNldHRpbmdzOiB7XG4gICAgICAgICAgICBhcnJvd3M6IHRydWUsXG4gICAgICAgICAgICBzbGlkZXNUb1Nob3c6IDIsXG4gICAgICAgICAgICBkb3RzOiBmYWxzZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBdXG4gICAgfSxcbiAgICBlaW5zdGVpblJlY29tbWVuZGF0aW9uQ2Fyb3VzZWw6IHtcbiAgICAgICAgaW5maW5pdGU6IHRydWUsXG4gICAgICAgIHNsaWRlc1RvU2hvdzogNCxcbiAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG4gICAgICAgIGRvdHM6IGZhbHNlLFxuICAgICAgICBhcnJvd3M6IHRydWUsXG4gICAgICAgIHJlc3BvbnNpdmU6IFtcbiAgICAgICAge1xuICAgICAgICAgIGJyZWFrcG9pbnQ6IDc2NyxcbiAgICAgICAgICBzZXR0aW5nczoge1xuICAgICAgICAgICAgYXJyb3dzOiB0cnVlLFxuICAgICAgICAgICAgc2xpZGVzVG9TaG93OiAyLFxuICAgICAgICAgICAgZG90czogZmFsc2VcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXVxuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2V0dGluZ3M7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuL2RpYWxvZycpO1xuXG4vKipcbiAqIEBmdW5jdGlvbiBjb29raWVwcml2YWN5ICAgIFVzZWQgdG8gZGlzcGxheS9jb250cm9sIHRoZSBzY3JpbSBjb250YWluaW5nIHRoZSBjb29raWUgcHJpdmFjeSBjb2RlXG4gKiovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAvKipcbiAgICAgKiBJZiB3ZSBoYXZlIG5vdCBhY2NlcHRlZCBjb29raWVzIEFORCB3ZSdyZSBub3Qgb24gdGhlIFByaXZhY3kgUG9saWN5IHBhZ2UsIHRoZW4gc2hvdyB0aGUgbm90aWZpY2F0aW9uXG4gICAgICogTk9URTogWW91IHdpbGwgcHJvYmFibHkgd2FudCB0byBhZGp1c3QgdGhlIFByaXZhY3kgUGFnZSB0ZXN0IHRvIG1hdGNoIHlvdXIgc2l0ZSdzIHNwZWNpZmljIHByaXZhY3kgLyBjb29raWUgcGFnZVxuICAgICAqL1xuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuQ09PS0lFX0hJTlQgPT09IHRydWUgJiYgZG9jdW1lbnQuY29va2llLmluZGV4T2YoJ2R3X2Nvb2tpZXNfYWNjZXB0ZWQnKSA8IDApIHtcbiAgICAgICAgLy8gY2hlY2sgZm9yIHByaXZhY3kgcG9saWN5IHBhZ2VcbiAgICAgICAgaWYgKCQoJy5wcml2YWN5LXBvbGljeScpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgIHVybDogVXJscy5jb29raWVIaW50LFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgY2xvc2VPbkVzY2FwZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiAnbm8tY2xvc2UnLFxuICAgICAgICAgICAgICAgICAgICBidXR0b25zOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogUmVzb3VyY2VzLklfQUdSRUUsXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZUNvb2tpZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE90aGVyd2lzZSwgd2UgZG9uJ3QgbmVlZCB0byBzaG93IHRoZSBhc3NldCwganVzdCBlbmFibGUgdGhlIGNvb2tpZXNcbiAgICAgICAgZW5hYmxlQ29va2llcygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVuYWJsZUNvb2tpZXMoKSB7XG4gICAgICAgIGlmIChkb2N1bWVudC5jb29raWUuaW5kZXhPZignZHc9MScpIDwgMCkge1xuICAgICAgICAgICAgZG9jdW1lbnQuY29va2llID0gJ2R3PTE7IHBhdGg9Lyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRvY3VtZW50LmNvb2tpZS5pbmRleE9mKCdkd19jb29raWVzX2FjY2VwdGVkJykgPCAwKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSAnZHdfY29va2llc19hY2NlcHRlZD0xOyBwYXRoPS8nO1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gaW5pdCAoKSB7XG4gICAgJCgnLmNvdW50cnktc2VsZWN0b3IgLmN1cnJlbnQtY291bnRyeScpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnLmNvdW50cnktc2VsZWN0b3IgLnNlbGVjdG9yJykudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAkKHRoaXMpLnRvZ2dsZUNsYXNzKCdzZWxlY3Rvci1hY3RpdmUnKTtcbiAgICB9KTtcbiAgICAvLyBzZXQgY3VycmVuY3kgZmlyc3QgYmVmb3JlIHJlbG9hZFxuICAgICQoJy5jb3VudHJ5LXNlbGVjdG9yIC5zZWxlY3RvciAubG9jYWxlJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdXJsID0gdGhpcy5ocmVmO1xuICAgICAgICB2YXIgY3VycmVuY3kgPSB0aGlzLmdldEF0dHJpYnV0ZSgnZGF0YS1jdXJyZW5jeScpO1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgIHVybDogVXJscy5zZXRTZXNzaW9uQ3VycmVuY3ksXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgZm9ybWF0OiAnYWpheCcsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lNbmVtb25pYzogY3VycmVuY3lcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmRvbmUoZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBzZXQgY3VycmVuY3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi9hamF4JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcbiAgICBpbWFnZXNMb2FkZWQgPSByZXF1aXJlKCdpbWFnZXNsb2FkZWQnKTtcblxudmFyIGRpYWxvZyA9IHtcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQXBwZW5kcyBhIGRpYWxvZyB0byBhIGdpdmVuIGNvbnRhaW5lciAodGFyZ2V0KVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgIHBhcmFtcy50YXJnZXQgY2FuIGJlIGFuIGlkIHNlbGVjdG9yIG9yIGFuIGpxdWVyeSBvYmplY3RcbiAgICAgKi9cbiAgICBjcmVhdGU6IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyICR0YXJnZXQsIGlkO1xuXG4gICAgICAgIGlmIChfLmlzU3RyaW5nKHBhcmFtcy50YXJnZXQpKSB7XG4gICAgICAgICAgICBpZiAocGFyYW1zLnRhcmdldC5jaGFyQXQoMCkgPT09ICcjJykge1xuICAgICAgICAgICAgICAgICR0YXJnZXQgPSAkKHBhcmFtcy50YXJnZXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkdGFyZ2V0ID0gJCgnIycgKyBwYXJhbXMudGFyZ2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMudGFyZ2V0IGluc3RhbmNlb2YgalF1ZXJ5KSB7XG4gICAgICAgICAgICAkdGFyZ2V0ID0gcGFyYW1zLnRhcmdldDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICR0YXJnZXQgPSAkKCcjZGlhbG9nLWNvbnRhaW5lcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgbm8gZWxlbWVudCBmb3VuZCwgY3JlYXRlIG9uZVxuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGlmICgkdGFyZ2V0LnNlbGVjdG9yICYmICR0YXJnZXQuc2VsZWN0b3IuY2hhckF0KDApID09PSAnIycpIHtcbiAgICAgICAgICAgICAgICBpZCA9ICR0YXJnZXQuc2VsZWN0b3Iuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICR0YXJnZXQgPSAkKCc8ZGl2PicpLmF0dHIoJ2lkJywgaWQpLmFkZENsYXNzKCdkaWFsb2ctY29udGVudCcpLmFwcGVuZFRvKCdib2R5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgdGhlIGRpYWxvZ1xuICAgICAgICB0aGlzLiRjb250YWluZXIgPSAkdGFyZ2V0O1xuICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKF8ubWVyZ2Uoe30sIHRoaXMuc2V0dGluZ3MsIHBhcmFtcy5vcHRpb25zIHx8IHt9KSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gT3BlbnMgYSBkaWFsb2cgdXNpbmcgdGhlIGdpdmVuIHVybCAocGFyYW1zLnVybCkgb3IgaHRtbCAocGFyYW1zLmh0bWwpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMudXJsIHNob3VsZCBjb250YWluIHRoZSB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLmh0bWwgY29udGFpbnMgdGhlIGh0bWwgb2YgdGhlIGRpYWxvZyBjb250ZW50XG4gICAgICovXG4gICAgb3BlbjogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAvLyBjbG9zZSBhbnkgb3BlbiBkaWFsb2dcbiAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICB0aGlzLmNyZWF0ZShwYXJhbXMpO1xuICAgICAgICB0aGlzLnJlcGxhY2UocGFyYW1zKTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBwb3B1bGF0ZSB0aGUgZGlhbG9nIHdpdGggaHRtbCBjb250ZW50LCB0aGVuIG9wZW4gaXRcbiAgICAgKiovXG4gICAgb3BlbldpdGhDb250ZW50OiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBjb250ZW50LCBwb3NpdGlvbiwgY2FsbGJhY2s7XG5cbiAgICAgICAgaWYgKCF0aGlzLiRjb250YWluZXIpIHsgcmV0dXJuOyB9XG4gICAgICAgIGNvbnRlbnQgPSBwYXJhbXMuY29udGVudCB8fCBwYXJhbXMuaHRtbDtcbiAgICAgICAgaWYgKCFjb250ZW50KSB7IHJldHVybjsgfVxuICAgICAgICB0aGlzLiRjb250YWluZXIuZW1wdHkoKS5odG1sKGNvbnRlbnQpO1xuICAgICAgICBpZiAoIXRoaXMuJGNvbnRhaW5lci5kaWFsb2coJ2lzT3BlbicpKSB7XG4gICAgICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKCdvcGVuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLm9wdGlvbnMpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gcGFyYW1zLm9wdGlvbnMucG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFwb3NpdGlvbikge1xuICAgICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnNldHRpbmdzLnBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlc0xvYWRlZCh0aGlzLiRjb250YWluZXIpLm9uKCdkb25lJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyLmRpYWxvZygnb3B0aW9uJywgJ3Bvc2l0aW9uJywgcG9zaXRpb24pO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgICAgIGNhbGxiYWNrID0gKHR5cGVvZiBwYXJhbXMuY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpID8gcGFyYW1zLmNhbGxiYWNrIDogZnVuY3Rpb24gKCkge307XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gUmVwbGFjZSB0aGUgY29udGVudCBvZiBjdXJyZW50IGRpYWxvZ1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwYXJhbXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1zLnVybCAtIElmIHRoZSB1cmwgcHJvcGVydHkgaXMgcHJvdmlkZWQsIGFuIGFqYXggY2FsbCBpcyBwZXJmb3JtZWQgdG8gZ2V0IHRoZSBjb250ZW50IHRvIHJlcGxhY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyYW1zLmh0bWwgLSBJZiBubyB1cmwgcHJvcGVydHkgaXMgcHJvdmlkZWQsIHVzZSBodG1sIHByb3ZpZGVkIHRvIHJlcGxhY2VcbiAgICAgKi9cbiAgICByZXBsYWNlOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmICghdGhpcy4kY29udGFpbmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy51cmwpIHtcbiAgICAgICAgICAgIHBhcmFtcy51cmwgPSB1dGlsLmFwcGVuZFBhcmFtVG9VUkwocGFyYW1zLnVybCwgJ2Zvcm1hdCcsICdhamF4Jyk7XG4gICAgICAgICAgICBhamF4LmxvYWQoe1xuICAgICAgICAgICAgICAgIHVybDogcGFyYW1zLnVybCxcbiAgICAgICAgICAgICAgICBkYXRhOiBwYXJhbXMuZGF0YSxcbiAgICAgICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtcy5jb250ZW50ID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbldpdGhDb250ZW50KHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuaHRtbCkge1xuICAgICAgICAgICAgdGhpcy5vcGVuV2l0aENvbnRlbnQocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgZGlhbG9nXG4gICAgICovXG4gICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLiRjb250YWluZXIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLiRjb250YWluZXIuZGlhbG9nKCdjbG9zZScpO1xuICAgIH0sXG4gICAgZXhpc3RzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRjb250YWluZXIgJiYgKHRoaXMuJGNvbnRhaW5lci5sZW5ndGggPiAwKTtcbiAgICB9LFxuICAgIGlzQWN0aXZlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmV4aXN0cygpICYmICh0aGlzLiRjb250YWluZXIuY2hpbGRyZW4ubGVuZ3RoID4gMCk7XG4gICAgfSxcbiAgICBzZXR0aW5nczoge1xuICAgICAgICBhdXRvT3BlbjogZmFsc2UsXG4gICAgICAgIGhlaWdodDogJ2F1dG8nLFxuICAgICAgICBtb2RhbDogdHJ1ZSxcbiAgICAgICAgb3ZlcmxheToge1xuICAgICAgICAgICAgb3BhY2l0eTogMC41LFxuICAgICAgICAgICAgYmFja2dyb3VuZDogJ2JsYWNrJ1xuICAgICAgICB9LFxuICAgICAgICByZXNpemFibGU6IGZhbHNlLFxuICAgICAgICB0aXRsZTogJycsXG4gICAgICAgIHdpZHRoOiAnODAwJyxcbiAgICAgICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuICAgICAgICB9LFxuICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgbXk6ICdjZW50ZXInLFxuICAgICAgICAgICAgYXQ6ICdjZW50ZXInLFxuICAgICAgICAgICAgb2Y6IHdpbmRvdyxcbiAgICAgICAgICAgIGNvbGxpc2lvbjogJ2ZsaXBmaXQnXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRpYWxvZztcbiIsIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gZ2V0Q3VycmVudERhdGEoKXtcblx0aWYoc2pkYXRhLnBhZ2UgPT0gJ3NoaXBwaW5nJykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2RhdGE6Y2hlY2tvdXQnLCBbc2pkYXRhXSk7XG5cdH0gZWxzZSBpZihzamRhdGEucGFnZSA9PSAnb3JkZXJjb25maXJtYXRpb24nIHx8IHNqZGF0YS5wYWdlID09ICdjb25maXJtYXRpb24nKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignZGF0YTpkb25hdGUnLCBbc2pkYXRhXSk7XG5cdH0gZWxzZSBpZihzamRhdGEucGFnZSA9PSAncHJvZHVjdCcpIHtcblx0XHQkKGRvY3VtZW50KS50cmlnZ2VyKCdkYXRhOnBkcCcsIFtzamRhdGFdKTtcblx0fSBlbHNlIGlmKHNqZGF0YS5wYWdlID09ICdzdW1tYXJ5Jykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2RhdGE6cGF5bWVudCcsIFtzamRhdGFdKTtcblx0fVxuXHRcbn1cblxuZnVuY3Rpb24gY3VzdG9tUGFyYXJtZXRlcihkYXRhKSB7XG4gICAgdmFyIGFycmF5ID0gZGF0YS5waWRzO1xuICAgIHZhciBqID0gMDtcbiAgICB2YXIgY29udGVudElEUz0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKyl7XG4gICAgdmFyIHRlc3RJRCA9IGFycmF5W2ldO1xuICAgIGlmKHRlc3RJRC5oYXNPd25Qcm9wZXJ0eSgnaWQnKSl7XG4gICAgICAgIGNvbnRlbnRJRFNbal0gPSB0ZXN0SURbJ2lkJ107XG4gICAgICAgIGorKztcbiAgICB9XG4gICAgfVxuICAgcmV0dXJuIGNvbnRlbnRJRFM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAkKGRvY3VtZW50KS5vbihcImRhdGE6YWRkdG9jYXJ0XCIsIGZ1bmN0aW9uKGUsIGRhdGEpe1xuXHQgICAgXHRmYnEoJ3RyYWNrJywgJ0FkZFRvQ2FydCcsIHtcblx0ICAgICAgICAgICAgY29udGVudF9pZHM6IFtkYXRhLmNvbnRlbnRfaWRzXSxcblx0ICAgICAgICAgICAgY29udGVudF90eXBlOiAncHJvZHVjdCcgXG5cdCAgICAgICAgfSk7XG5cdCAgICB9KTtcblx0ICAgICQoZG9jdW1lbnQpLm9uKFwiZGF0YTpjaGVja291dFwiLCBmdW5jdGlvbihlLCBkYXRhKXtcblx0ICAgIFx0ZmJxKCd0cmFjaycsICdJbml0aWF0ZUNoZWNrb3V0Jywge1xuXHQgICAgXHRcdHZhbHVlOiBkYXRhLmNhcnRUb3RhbCxcblx0ICAgIFx0XHRjdXJyZW5jeTogZGF0YS5jdXJyZW5jeSxcblx0ICAgIFx0XHRudW1faXRlbXMgOiBkYXRhLnF0eSxcblx0ICAgIFx0XHRjb250ZW50cyA6IGRhdGEucGlkc1xuXHQgICAgICAgIH0pO1xuXHQgICAgfSk7XG5cdCAgICAkKGRvY3VtZW50KS5vbihcImRhdGE6ZG9uYXRlXCIsIGZ1bmN0aW9uKGUsIGRhdGEpe1xuXHQgICAgXHRmYnEoJ3RyYWNrJywgJ0RvbmF0ZScsIHtcblx0ICAgIFx0XHRjdXJyZW5jeTogZGF0YS5jdXJyZW5jeSxcblx0ICAgIFx0XHR2YWx1ZTogZGF0YS5jYXJ0VG90YWwsXG5cdCAgICBcdFx0bnVtX2l0ZW1zIDogZGF0YS5xdHksXG5cdCAgICBcdFx0Ly8gY29udGVudF90eXBlOiAncHJvZHVjdCcsXG5cdCAgICBcdFx0Y29udGVudHMgOiBkYXRhLnBpZHMsXG5cdFx0XHRcdGNvbnRlbnRfaWRzIDogY3VzdG9tUGFyYXJtZXRlcihkYXRhKVxuXHQgICAgICAgIH0pO1xuXHQgICAgfSk7XG5cdCAgICAkKGRvY3VtZW50KS5vbihcImRhdGE6cGRwXCIsIGZ1bmN0aW9uKGUsIGRhdGEpe1xuXHQgICAgXHRmYnEoJ3RyYWNrJywgJ1ZpZXdDb250ZW50Jywge1xuXHQgICAgXHRcdGNvbnRlbnRfaWRzOiBkYXRhLnBpZHMsXG5cdCAgICBcdFx0Y29udGVudF90eXBlOiBkYXRhLmNvbnRlbnRfdHlwZSxcblx0ICAgIFx0XHRjb250ZW50X25hbWU6IGRhdGEuY29udGVudF9uYW1lXG5cdCAgICAgICAgfSk7XG5cdCAgICB9KTtcblx0ICAgICQoZG9jdW1lbnQpLm9uKFwiZGF0YTpwYXltZW50XCIsIGZ1bmN0aW9uKGUsIGRhdGEpe1xuXHQgICAgXHRmYnEoJ3RyYWNrJywgJ0FkZFBheW1lbnRJbmZvJywge1xuXHQgICAgXHRcdGNvbnRlbnRzOiBkYXRhLnBpZHMsXG5cdCAgICBcdFx0Y3VycmVuY3k6IGRhdGEuY3VycmVuY3ksXG5cdCAgICBcdFx0dmFsdWU6IGRhdGEuY2FydFRvdGFsXG5cdCAgICAgICAgfSk7XG5cdCAgICB9KTtcblx0ICAgIFxuXHRcdGdldEN1cnJlbnREYXRhKCk7XG5cdH1cbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4vYWpheCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gTG9hZCBkZXRhaWxzIHRvIGEgZ2l2ZW4gZ2lmdCBjZXJ0aWZpY2F0ZVxuICogQHBhcmFtIHtTdHJpbmd9IGlkIFRoZSBJRCBvZiB0aGUgZ2lmdCBjZXJ0aWZpY2F0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgQSBmdW5jdGlvbiB0byBjYWxsZWRcbiAqL1xuZXhwb3J0cy5jaGVja0JhbGFuY2UgPSBmdW5jdGlvbiAoaWQsIGNhbGxiYWNrKSB7XG4gICAgLy8gbG9hZCBnaWZ0IGNlcnRpZmljYXRlIGRldGFpbHNcbiAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMuZ2lmdENhcmRDaGVja0JhbGFuY2UsICdnaWZ0Q2VydGlmaWNhdGVJRCcsIGlkKTtcblxuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogY2FsbGJhY2tcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi9hamF4JyksXG4gICAgbWluaWNhcnQgPSByZXF1aXJlKCcuL21pbmljYXJ0JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG52YXIgc2V0QWRkVG9DYXJ0SGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciBmb3JtID0gJCh0aGlzKS5jbG9zZXN0KCdmb3JtJyk7XG5cbiAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgICAgdXJsOiB1dGlsLmFqYXhVcmwoZm9ybS5hdHRyKCdhY3Rpb24nKSksXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgIGRhdGE6IGZvcm0uc2VyaWFsaXplKClcbiAgICB9O1xuICAgICQuYWpheChvcHRpb25zKS5kb25lKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICBpZiAocmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgYWpheC5sb2FkKHtcbiAgICAgICAgICAgICAgICB1cmw6IFVybHMubWluaWNhcnRHQyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7bGluZUl0ZW1JZDogcmVzcG9uc2UucmVzdWx0LmxpbmVJdGVtSWR9LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluaWNhcnQuc2hvdyhyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgICAgIGZvcm0uZmluZCgnaW5wdXQsdGV4dGFyZWEnKS52YWwoJycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9ybS5maW5kKCdzcGFuLmVycm9yJykuaGlkZSgpO1xuICAgICAgICAgICAgZm9yICh2YXIgaWQgaW4gcmVzcG9uc2UuZXJyb3JzLkZvcm1FcnJvcnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVycm9yRWwgPSAkKCcjJyArIGlkKS5hZGRDbGFzcygnZXJyb3InKS5yZW1vdmVDbGFzcygndmFsaWQnKS5uZXh0KCcuZXJyb3InKTtcbiAgICAgICAgICAgICAgICBpZiAoISRlcnJvckVsIHx8ICRlcnJvckVsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAkZXJyb3JFbCA9ICQoJzxzcGFuIGZvcj1cIicgKyBpZCArICdcIiBnZW5lcmF0ZWQ9XCJ0cnVlXCIgY2xhc3M9XCJlcnJvclwiIHN0eWxlPVwiXCI+PC9zcGFuPicpO1xuICAgICAgICAgICAgICAgICAgICAkKCcjJyArIGlkKS5hZnRlcigkZXJyb3JFbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRlcnJvckVsLnRleHQocmVzcG9uc2UuZXJyb3JzLkZvcm1FcnJvcnNbaWRdLnJlcGxhY2UoL1xcXFwnL2csICdcXCcnKSkuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSkuZmFpbChmdW5jdGlvbiAoeGhyLCB0ZXh0U3RhdHVzKSB7XG4gICAgICAgIC8vIGZhaWxlZFxuICAgICAgICBpZiAodGV4dFN0YXR1cyA9PT0gJ3BhcnNlcmVycm9yJykge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5CQURfUkVTUE9OU0UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5TRVJWRVJfQ09OTkVDVElPTl9FUlJPUik7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcjQWRkVG9CYXNrZXRCdXR0b24nKS5vbignY2xpY2snLCBzZXRBZGRUb0NhcnRIYW5kbGVyKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG4vLyBqUXVlcnkgZXh0ZW5zaW9uc1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBwYXJhbXNcbiAgICAvLyB0b2dnbGVDbGFzcyAtIHJlcXVpcmVkXG4gICAgLy8gdHJpZ2dlclNlbGVjdG9yIC0gb3B0aW9uYWwuIHRoZSBzZWxlY3RvciBmb3IgdGhlIGVsZW1lbnQgdGhhdCB0cmlnZ2VycyB0aGUgZXZlbnQgaGFuZGxlci4gZGVmYXVsdHMgdG8gdGhlIGNoaWxkIGVsZW1lbnRzIG9mIHRoZSBsaXN0LlxuICAgIC8vIGV2ZW50TmFtZSAtIG9wdGlvbmFsLiBkZWZhdWx0cyB0byAnY2xpY2snXG4gICAgJC5mbi50b2dnbGVkTGlzdCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIGlmICghb3B0aW9ucy50b2dnbGVDbGFzcykgeyByZXR1cm4gdGhpczsgfVxuICAgICAgICB2YXIgbGlzdCA9IHRoaXM7XG4gICAgICAgIHJldHVybiBsaXN0Lm9uKG9wdGlvbnMuZXZlbnROYW1lIHx8ICdjbGljaycsIG9wdGlvbnMudHJpZ2dlclNlbGVjdG9yIHx8IGxpc3QuY2hpbGRyZW4oKSwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHZhciBjbGFzc1RhcmdldCA9IG9wdGlvbnMudHJpZ2dlclNlbGVjdG9yID8gJCh0aGlzKS5wYXJlbnQoKSA6ICQodGhpcyk7XG4gICAgICAgICAgICBjbGFzc1RhcmdldC50b2dnbGVDbGFzcyhvcHRpb25zLnRvZ2dsZUNsYXNzKTtcbiAgICAgICAgICAgIC8vIGV4ZWN1dGUgY2FsbGJhY2sgaWYgZXhpc3RzXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5jYWxsYmFjaykge29wdGlvbnMuY2FsbGJhY2soKTt9XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAkLmZuLnN5bmNIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhcnIgPSAkLm1ha2VBcnJheSh0aGlzKTtcbiAgICAgICAgYXJyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAkKGEpLmhlaWdodCgpIC0gJChiKS5oZWlnaHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmhlaWdodCgkKGFyclthcnIubGVuZ3RoIC0gMV0pLmhlaWdodCgpKTtcbiAgICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4vZGlhbG9nJyksXG4gICAgcGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpLFxuICAgIHZhbGlkYXRvciA9IHJlcXVpcmUoJy4vdmFsaWRhdG9yJyk7XG5cbnZhciBsb2dpbiA9IHtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBpbml0IGV2ZW50cyBmb3IgdGhlIGxvZ2luUGFnZVxuICAgICAqL1xuICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy9vLWF1dGggYmluZGluZyBmb3Igd2hpY2ggaWNvbiBpcyBjbGlja2VkXG4gICAgICAgICQoJy5vQXV0aEljb24nKS5iaW5kKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQoJyNPQXV0aFByb3ZpZGVyJykudmFsKHRoaXMuaWQpO1xuICAgICAgICB9KTtcbiAgICBcblxuICAgICAgICAvL3RvZ2dsZSB0aGUgdmFsdWUgb2YgdGhlIHJlbWVtYmVybWUgY2hlY2tib3hcbiAgICAgICAgJCgnI2R3ZnJtX2xvZ2luX3JlbWVtYmVybWUnKS5iaW5kKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoJCgnI2R3ZnJtX2xvZ2luX3JlbWVtYmVybWUnKS5hdHRyKCdjaGVja2VkJykpIHtcbiAgICAgICAgICAgICAgICAkKCcjcmVtZW1iZXJtZScpLnZhbCgndHJ1ZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKCcjcmVtZW1iZXJtZScpLnZhbCgnZmFsc2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIFxuICAgICAgICAkKCcjcGFzc3dvcmQtcmVzZXQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgICAgIHVybDogJChlLnRhcmdldCkuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yLmluaXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkcmVxdWVzdFBhc3N3b3JkRm9ybSA9ICQoJ1tuYW1lJD1cIl9yZXF1ZXN0cGFzc3dvcmRcIl0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkc3VibWl0ID0gJHJlcXVlc3RQYXNzd29yZEZvcm0uZmluZCgnW25hbWUkPVwiX3JlcXVlc3RwYXNzd29yZF9zZW5kXCJdJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKCRzdWJtaXQpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkcmVxdWVzdFBhc3N3b3JkRm9ybS52YWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gJHJlcXVlc3RQYXNzd29yZEZvcm0uc2VyaWFsaXplKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGZvcm0gYWN0aW9uIHRvIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhICs9ICcmJyArICRzdWJtaXQuYXR0cignbmFtZScpICsgJz0nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSB0aGUgc2VydmVyIGtub3dzIHRoaXMgaXMgYW4gYWpheCByZXF1ZXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuaW5kZXhPZignYWpheCcpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhICs9ICcmZm9ybWF0PWFqYXgnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJHJlcXVlc3RQYXNzd29yZEZvcm0uYXR0cignYWN0aW9uJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIXJlc3BvbnNlLnN1Y2Nlc3MgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuZXJyb3IgPT09ICdDU1JGIFRva2VuIE1pc21hdGNoJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2UucmVkaXJlY3QoVXJscy5jc3JmZmFpbGVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlc3BvbnNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy4kY29udGFpbmVyLmh0bWwocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsdXJlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2cuJGNvbnRhaW5lci5odG1sKCc8aDE+JyArIFJlc291cmNlcy5TRVJWRVJfRVJST1IgKyAnPC9oMT4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIFxuICAgICAgICAvLyBCYXNlZCBvbiBSZXNvdXJjZS5kcyBzZXNzaW9uIGF0dHJpYnV0ZXNcbiAgICAgICAgaWYod2luZG93LlVzZXIgJiYgd2luZG93LlVzZXIuYXV0aGVudGljYXRlZCl7XG4gICAgICAgICAgICAkKFwiLmFjY291bnQtbmF2LXJlZ2lzdGVyZWRcIikuc2hvdygpO1xuICAgICAgICAgICAgJChcIi5hY2NvdW50LW5hdi11bnJlZ2lzdGVyZWRcIikuaGlkZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJChcIi5hY2NvdW50LW5hdi1yZWdpc3RlcmVkXCIpLmhpZGUoKTtcbiAgICAgICAgICAgICQoXCIuYWNjb3VudC1uYXYtdW5yZWdpc3RlcmVkXCIpLnNob3coKTtcbiAgICAgICAgfVxuICAgIFxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsb2dpbjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKSxcbiAgICBib251c1Byb2R1Y3RzVmlldyA9IHJlcXVpcmUoJy4vYm9udXMtcHJvZHVjdHMtdmlldycpO1xuXG52YXIgdGltZXIgPSB7XG4gICAgaWQ6IG51bGwsXG4gICAgY2xlYXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5pZCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5pZDtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgc3RhcnQ6IGZ1bmN0aW9uIChkdXJhdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5pZCA9IHNldFRpbWVvdXQoY2FsbGJhY2ssIGR1cmF0aW9uKTtcbiAgICB9XG59O1xuXG52YXIgbWluaWNhcnQgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRlbCA9ICQoJyNtaW5pLWNhcnQnKTtcbiAgICAgICAgdGhpcy4kY29udGVudCA9ICQoJy5taW5pLWNhcnQtY29udGVudCcpXG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gU2hvd3MgdGhlIGdpdmVuIGNvbnRlbnQgaW4gdGhlIG1pbmkgY2FydFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBBIEhUTUwgc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgd2hpY2ggd2lsbCBiZSBzaG93blxuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uIChodG1sKSB7XG4gICAgICAgIHRoaXMuJGVsLmh0bWwoaHRtbCk7XG4gICAgICAgIHV0aWwuc2Nyb2xsQnJvd3NlcigwKTtcbiAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgIHRoaXMuc2xpZGUoKTtcbiAgICAgICAgYm9udXNQcm9kdWN0c1ZpZXcubG9hZEJvbnVzT3B0aW9uKCk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gU2xpZGVzIGRvd24gYW5kIHNob3cgdGhlIGNvbnRlbnRzIG9mIHRoZSBtaW5pIGNhcnRcbiAgICAgKi9cbiAgICBzbGlkZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aW1lci5jbGVhcigpO1xuICAgICAgICB0aW1lci5zdGFydCg1MDAwLCB0aGlzLmNsb3NlLmJpbmQodGhpcykpO1xuXHRcdHRoaXMuJGNvbnRlbnQuYWRkQ2xhc3MoJ3RyaWdnZXJlZCcpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIENsb3NlcyB0aGUgbWluaSBjYXJ0IHdpdGggZ2l2ZW4gZGVsYXlcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gZGVsYXkgVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kc1xuICAgICAqL1xuICAgIGNsb3NlOiBmdW5jdGlvbiAoZGVsYXkpIHtcbiAgICAgICAgdGltZXIuY2xlYXIoKTtcbiAgICAgICAgdGhpcy4kY29udGVudC5yZW1vdmVDbGFzcygndHJpZ2dlcmVkJyk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBtaW5pY2FydDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxudmFyIHBhZ2UgPSB7XG4gICAgdGl0bGU6ICcnLFxuICAgIHR5cGU6ICcnLFxuICAgIHBhcmFtczogdXRpbC5nZXRRdWVyeVN0cmluZ1BhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoLnN1YnN0cigxKSksXG4gICAgcmVkaXJlY3Q6IGZ1bmN0aW9uIChuZXdVUkwpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IG5ld1VSTDtcbiAgICAgICAgfSwgMCk7XG4gICAgfSxcbiAgICByZWZyZXNoOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmFzc2lnbih3aW5kb3cubG9jYXRpb24uaHJlZik7XG4gICAgICAgIH0sIDUwMCk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBwYWdlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2lmdGNlcnQgPSByZXF1aXJlKCcuLi9naWZ0Y2VydCcpLFxuICAgIHRvb2x0aXAgPSByZXF1aXJlKCcuLi90b29sdGlwJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgICBkaWFsb2cgPSByZXF1aXJlKCcuLi9kaWFsb2cnKSxcbiAgICBwYWdlID0gcmVxdWlyZSgnLi4vcGFnZScpLFxuICAgIGxvZ2luID0gcmVxdWlyZSgnLi4vbG9naW4nKSxcbiAgICB2YWxpZGF0b3IgPSByZXF1aXJlKCcuLi92YWxpZGF0b3InKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgZXZlbnRzIG9uIHRoZSBhZGRyZXNzIGZvcm0gKGFwcGx5LCBjYW5jZWwsIGRlbGV0ZSlcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSB3aGljaCB3aWxsIGJlIGluaXRpYWxpemVkXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVBZGRyZXNzRm9ybSgpIHtcbiAgICB2YXIgJGZvcm0gPSAkKCcjZWRpdC1hZGRyZXNzLWZvcm0nKTtcblxuICAgICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJmb3JtYXRcIl0nKS5yZW1vdmUoKTtcbiAgICB0b29sdGlwLmluaXQoKTtcbiAgICAvLyQoXCI8aW5wdXQvPlwiKS5hdHRyKHt0eXBlOlwiaGlkZGVuXCIsIG5hbWU6XCJmb3JtYXRcIiwgdmFsdWU6XCJhamF4XCJ9KS5hcHBlbmRUbyhmb3JtKTtcblxuICAgICRmb3JtLm9uKCdjbGljaycsICcuYXBwbHktYnV0dG9uJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoISRmb3JtLnZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKCRmb3JtLmF0dHIoJ2FjdGlvbicpLCAnZm9ybWF0JywgJ2FqYXgnKTtcbiAgICAgICAgdmFyIGFwcGx5TmFtZSA9ICRmb3JtLmZpbmQoJy5hcHBseS1idXR0b24nKS5hdHRyKCduYW1lJyk7XG4gICAgICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBkYXRhOiAkZm9ybS5zZXJpYWxpemUoKSArICcmJyArIGFwcGx5TmFtZSArICc9eCcsXG4gICAgICAgICAgICB0eXBlOiAnUE9TVCdcbiAgICAgICAgfTtcbiAgICAgICAgJC5hamF4KG9wdGlvbnMpLmRvbmUoZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YoZGF0YSkgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcGFnZS5yZWZyZXNoKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2UucmVkaXJlY3QoVXJscy5jc3JmZmFpbGVkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJCgnI2RpYWxvZy1jb250YWluZXInKS5odG1sKGRhdGEpO1xuICAgICAgICAgICAgICAgIGFjY291bnQuaW5pdCgpO1xuICAgICAgICAgICAgICAgIHRvb2x0aXAuaW5pdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnLmNhbmNlbC1idXR0b24sIC5jbG9zZS1idXR0b24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgIH0pXG4gICAgLm9uKCdjbGljaycsICcuZGVsZXRlLWJ1dHRvbicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfQUREUkVTUykpKSB7XG4gICAgICAgICAgICB2YXIgdXJsID0gdXRpbC5hcHBlbmRQYXJhbXNUb1VybChVcmxzLmRlbGV0ZUFkZHJlc3MsIHtcbiAgICAgICAgICAgICAgICBBZGRyZXNzSUQ6ICRmb3JtLmZpbmQoJyNhZGRyZXNzaWQnKS52YWwoKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQ6ICdhamF4J1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbidcbiAgICAgICAgICAgIH0pLmRvbmUoZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdGF0dXMudG9Mb3dlckNhc2UoKSA9PT0gJ29rJykge1xuICAgICAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcGFnZS5yZWZyZXNoKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLm1lc3NhZ2UubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFsaWRhdG9yLmluaXQoKTtcbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFRvZ2dsZXMgdGhlIGxpc3Qgb2YgT3JkZXJzXG4gKi9cbmZ1bmN0aW9uIHRvZ2dsZUZ1bGxPcmRlciAoKSB7XG4gICAgJCgnLm9yZGVyLWl0ZW1zJylcbiAgICAgICAgLmZpbmQoJ2xpLmhpZGRlbjpmaXJzdCcpXG4gICAgICAgIC5wcmV2KCdsaScpXG4gICAgICAgIC5hcHBlbmQoJzxhIGNsYXNzPVwidG9nZ2xlXCI+VmlldyBBbGw8L2E+JylcbiAgICAgICAgLmNoaWxkcmVuKCcudG9nZ2xlJylcbiAgICAgICAgLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQodGhpcykucGFyZW50KCkuc2libGluZ3MoJ2xpLmhpZGRlbicpLnNob3coKTtcbiAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGV2ZW50cyBvbiB0aGUgYWRkcmVzcyBmb3JtIChlZGl0LCBjcmVhdGUsIGRlbGV0ZSlcbiAqL1xuZnVuY3Rpb24gaW5pdEFkZHJlc3NFdmVudHMoKSB7XG4gICAgdmFyIGFkZHJlc3NlcyA9ICQoJyNhZGRyZXNzZXMnKTtcbiAgICBpZiAoYWRkcmVzc2VzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblxuICAgIGFkZHJlc3Nlcy5vbignY2xpY2snLCAnLmFkZHJlc3MtZWRpdCwgLmFkZHJlc3MtY3JlYXRlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBkaWFsb2cub3Blbih7XG4gICAgICAgICAgICB1cmw6IHRoaXMuaHJlZixcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBvcGVuOiBpbml0aWFsaXplQWRkcmVzc0Zvcm0gXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pLm9uKCdjbGljaycsICcuZGVsZXRlJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAod2luZG93LmNvbmZpcm0oU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ09ORklSTV9ERUxFVEUsIFJlc291cmNlcy5USVRMRV9BRERSRVNTKSkpIHtcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiB1dGlsLmFwcGVuZFBhcmFtVG9VUkwoJCh0aGlzKS5hdHRyKCdocmVmJyksICdmb3JtYXQnLCAnYWpheCcpLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbidcbiAgICAgICAgICAgIH0pLmRvbmUoZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdGF0dXMudG9Mb3dlckNhc2UoKSA9PT0gJ29rJykge1xuICAgICAgICAgICAgICAgICAgICBwYWdlLnJlZGlyZWN0KFVybHMuYWRkcmVzc2VzTGlzdCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLm1lc3NhZ2UubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGV2ZW50cyBvZiB0aGUgcGF5bWVudCBtZXRob2RzIGxpc3QgKGRlbGV0ZSBjYXJkKVxuICovXG5mdW5jdGlvbiBpbml0UGF5bWVudEV2ZW50cygpIHtcbiAgICAkKCcuYWRkLWNhcmQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIHVybDogJChlLnRhcmdldCkuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIG9wZW46IGluaXRpYWxpemVQYXltZW50Rm9ybVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHZhciBwYXltZW50TGlzdCA9ICQoJy5wYXltZW50LWxpc3QnKTtcbiAgICBpZiAocGF5bWVudExpc3QubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuXG4gICAgdXRpbC5zZXREZWxldGVDb25maXJtYXRpb24ocGF5bWVudExpc3QsIFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfQ1JFRElUQ0FSRCkpO1xuXG4gICAgJCgnZm9ybVtuYW1lPVwicGF5bWVudC1yZW1vdmVcIl0nKS5vbignc3VibWl0JywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAvLyBvdmVycmlkZSBmb3JtIHN1Ym1pc3Npb24gaW4gb3JkZXIgdG8gcHJldmVudCByZWZyZXNoIGlzc3Vlc1xuICAgICAgICB2YXIgYnV0dG9uID0gJCh0aGlzKS5maW5kKCcuZGVsZXRlJyk7XG4gICAgICAgICQoJzxpbnB1dC8+JykuYXR0cih7XG4gICAgICAgICAgICB0eXBlOiAnaGlkZGVuJyxcbiAgICAgICAgICAgIG5hbWU6IGJ1dHRvbi5hdHRyKCduYW1lJyksXG4gICAgICAgICAgICB2YWx1ZTogYnV0dG9uLmF0dHIoJ3ZhbHVlJykgfHwgJ2RlbGV0ZSBjYXJkJ1xuICAgICAgICB9KS5hcHBlbmRUbygkKHRoaXMpKTtcbiAgICAgICAgdmFyIGRhdGEgPSAkKHRoaXMpLnNlcmlhbGl6ZSgpO1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgdXJsOiAkKHRoaXMpLmF0dHIoJ2FjdGlvbicpLFxuICAgICAgICAgICAgZGF0YTogZGF0YVxuICAgICAgICB9KVxuICAgICAgICAuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwYWdlLnJlZGlyZWN0KFVybHMucGF5bWVudHNMaXN0KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQYXltZW50Rm9ybSgpIHtcbiAgICAkKCcjQ3JlZGl0Q2FyZEZvcm0nKS5vbignY2xpY2snLCAnLmNhbmNlbC1idXR0b24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgIH0pO1xuICAgIFxuICAgIHZhbGlkYXRvci5pbml0KCk7XG5cbn1cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBldmVudHMgb2YgdGhlIG9yZGVyLCBhZGRyZXNzIGFuZCBwYXltZW50IHBhZ2VzXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgdG9nZ2xlRnVsbE9yZGVyKCk7XG4gICAgaW5pdEFkZHJlc3NFdmVudHMoKTtcbiAgICBpbml0UGF5bWVudEV2ZW50cygpO1xuICAgIGxvZ2luLmluaXQoKTtcbn1cblxudmFyIGFjY291bnQgPSB7XG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgICAgIGdpZnRjZXJ0LmluaXQoKTtcbiAgICB9LFxuICAgIGluaXRDYXJ0TG9naW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbG9naW4uaW5pdCgpO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gYWNjb3VudDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFjY291bnQgPSByZXF1aXJlKCcuL2FjY291bnQnKSxcbiAgICBib251c1Byb2R1Y3RzVmlldyA9IHJlcXVpcmUoJy4uL2JvbnVzLXByb2R1Y3RzLXZpZXcnKSxcbiAgICBxdWlja3ZpZXcgPSByZXF1aXJlKCcuLi9xdWlja3ZpZXcnKSxcbiAgICBjYXJ0U3RvcmVJbnZlbnRvcnkgPSByZXF1aXJlKCcuLi9zdG9yZWludmVudG9yeS9jYXJ0Jyk7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIGV2ZW50cyB0byB0aGUgY2FydCBwYWdlIChlZGl0IGl0ZW0ncyBkZXRhaWxzLCBib251cyBpdGVtJ3MgYWN0aW9ucywgY291cG9uIGNvZGUgZW50cnkpXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgJCgnI2NhcnQtdGFibGUnKS5vbignY2xpY2snLCAnLml0ZW0tZWRpdC1kZXRhaWxzIGEnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHF1aWNrdmlldy5zaG93KHtcbiAgICAgICAgICAgIHVybDogZS50YXJnZXQuaHJlZixcbiAgICAgICAgICAgIHNvdXJjZTogJ2NhcnQnXG4gICAgICAgIH0pO1xuICAgIH0pXG4gICAgLm9uKCdjbGljaycsICcuYm9udXMtaXRlbS1hY3Rpb25zIGEsIC5pdGVtLWRldGFpbHMgLmJvbnVzcHJvZHVjdHMgYScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgYm9udXNQcm9kdWN0c1ZpZXcuc2hvdyh0aGlzLmhyZWYpO1xuICAgIH0pO1xuICAgIFxuICAgICQoJy51cGRhdGUtaXRlbSwgLmNhcnQtdXBkYXRlLW1zZycpLmhpZGUoKTtcbiAgICBcbiAgICAkKCdmb3JtIGlucHV0W25hbWUkPVwiX3F1YW50aXR5XCJdJykuY2hhbmdlKGZ1bmN0aW9uKCkge1xuICAgICAgICAkKHRoaXMpLmNsb3Nlc3QoJy5jYXJ0LXJvdycpLmZpbmQoJy5pdGVtLXF1YW50aXR5LWRldGFpbHMgLml0ZW0tdXNlci1hY3Rpb25zIC51cGRhdGUtaXRlbScpLnNob3coKTtcbiAgICAgICAgJCgnLmNhcnQtdXBkYXRlLW1zZycpLnNob3coKTtcbiAgICB9KTtcblxuICAgIC8vIG92ZXJyaWRlIGVudGVyIGtleSBmb3IgY291cG9uIGNvZGUgZW50cnlcbiAgICAkKCdmb3JtIGlucHV0W25hbWUkPVwiX2NvdXBvbkNvZGVcIl0nKS5vbigna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmIChlLndoaWNoID09PSAxMyAmJiAkKHRoaXMpLnZhbCgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBcdFx0cmV0dXJuIGZhbHNlO1xuICAgICAgICBcdH0gZWxzZSBpZiAoZS53aGljaCA9PT0gMTMpIHtcbiAgICAgICAgXHRcdGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgXHRcdCQoJ2Zvcm0gYnV0dG9uW25hbWUkPVwiX2NhcnRfYWRkQ291cG9uXCJdJykudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgXHR9XG4gICAgfSk7XG4gICAgXG4gICAgLy90cmlnZ2VyIHVwZGF0ZSBjYXJ0IGJ1dHRvblxuICAgICQoJy51cGRhdGVjYXJ0LXRyaWdnZXIsIC51cGRhdGUtaXRlbScpLm9uKCdjbGljaycsZnVuY3Rpb24oZSkge1xuICAgIFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0JCgnI3VwZGF0ZS1jYXJ0JykudHJpZ2dlciggXCJjbGlja1wiICk7XG4gICAgfSk7XG5cbiAgICAvL3RvIHByZXZlbnQgbXVsdGlwbGUgc3VibWlzc2lvbnMgb2YgdGhlIGZvcm0gd2hlbiByZW1vdmluZyBhIHByb2R1Y3QgZnJvbSB0aGUgY2FydFxuICAgIHZhciByZW1vdmVJdGVtRXZlbnQgPSBmYWxzZTtcbiAgICAkKCdidXR0b25bbmFtZSQ9XCJkZWxldGVQcm9kdWN0XCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHJlbW92ZUl0ZW1FdmVudCkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVtb3ZlSXRlbUV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgICQoIHdpbmRvdyApLmxvYWQoZnVuY3Rpb24oKSB7XG4gICAgXHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG5cdFx0ICAgICQoJy5zbGljaycpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0ICAgICAgICB2YXIgbnVtYmVyT2ZTbGlkZXMgPSAkKHRoaXMpLmNoaWxkcmVuKCkubGVuZ3RoO1xuXHRcdCAgICAgICAgaWYgKG51bWJlck9mU2xpZGVzID4gMSkge1xuXHRcdCAgICAgICAgICAgIHZhciBzbGlkZXNUb1Nob3dEZXNrdG9wID0gMztcblx0XHQgICAgICAgICAgICBpZiAobnVtYmVyT2ZTbGlkZXMgPCBzbGlkZXNUb1Nob3dEZXNrdG9wKSB7XG5cdFx0ICAgICAgICAgICAgICAgIHNsaWRlc1RvU2hvd0Rlc2t0b3AgPSBudW1iZXJPZlNsaWRlcztcblx0XHQgICAgICAgICAgICB9XG5cdFx0ICAgICAgICAgICAgJCh0aGlzKS5zbGljayh7XG5cdFx0ICAgICAgICAgICAgICAgIGluZmluaXRlOiBmYWxzZSxcblx0XHQgICAgICAgICAgICAgICAgc2xpZGVzVG9TaG93OiBzbGlkZXNUb1Nob3dEZXNrdG9wLFxuXHRcdCAgICAgICAgICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcblx0XHQgICAgICAgICAgICAgICAgcmVzcG9uc2l2ZTogW1xuXHRcdCAgICAgICAgICAgICAgICB7XG5cdFx0ICAgICAgICAgICAgICAgICAgYnJlYWtwb2ludDogOTU5LFxuXHRcdCAgICAgICAgICAgICAgICAgIHNldHRpbmdzOiB7XG5cdFx0ICAgICAgICAgICAgICAgICAgICBzbGlkZXNUb1Nob3c6IDJcblx0XHQgICAgICAgICAgICAgICAgICB9XG5cdFx0ICAgICAgICAgICAgICAgIH0sXG5cdFx0ICAgICAgICAgICAgICAgIHtcblx0XHQgICAgICAgICAgICAgICAgICBicmVha3BvaW50OiA3NjcsXG5cdFx0ICAgICAgICAgICAgICAgICAgc2V0dGluZ3M6IHtcblx0XHQgICAgICAgICAgICAgICAgICAgIGFycm93czpmYWxzZSxcblx0XHQgICAgICAgICAgICAgICAgICAgIHNsaWRlc1RvU2hvdzogMSxcblx0XHQgICAgICAgICAgICAgICAgICAgIGRvdHM6IHRydWVcblx0XHQgICAgICAgICAgICAgICAgICB9XG5cdFx0ICAgICAgICAgICAgICAgIH1cblx0XHQgICAgICAgICAgICAgICAgXVxuXHRcdCAgICAgICAgICAgIH0pOyBcblx0XHQgICAgICAgIH1cblx0XHQgICAgfSk7XG4gICAgXHR9LCAyMDAwKTtcbiAgICB9KTtcbiAgICBcbiAgICAvLyBQcmV2ZW50cyB0aGUgZm9ybSBmcm9tIHN1Ym1pdHRpbmcgaWYgbm90aGluZyBoYXMgYmVlbiBlbnRlcmVkXG4gICAgJCgnYnV0dG9uW25hbWUkPVwiX2FkZERvbmF0aW9uXCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICBcdFx0aWYgKCEkKCdpbnB1dFtuYW1lJD1cIl9kb25hdGlvbkFtb3VudFwiXScpLnZhbCgpKSB7XG4gICAgXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIFx0XHR9XG4gICAgfSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgY2FydFN0b3JlSW52ZW50b3J5LmluaXQoKTtcbiAgICB9XG4gICAgYWNjb3VudC5pbml0Q2FydExvZ2luKCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcbnZhciBzaGlwcGluZyA9IHJlcXVpcmUoJy4vc2hpcHBpbmcnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBTZWxlY3RzIHRoZSBmaXJzdCBhZGRyZXNzIGZyb20gdGhlIGxpc3Qgb2YgYWRkcmVzc2VzXG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGZvcm0gPSAkKCcuYWRkcmVzcycpO1xuICAgIC8vIHNlbGVjdCBhZGRyZXNzIGZyb20gbGlzdFxuICAgICQoJ3NlbGVjdFtuYW1lJD1cIl9hZGRyZXNzTGlzdFwiXScsICRmb3JtKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKCcuY2hlY2tvdXQtYmlsbGluZyBpbnB1dFtuYW1lJD1cIl91c2VTaGlwcGluZ0FzQmlsbGluZ1wiXScpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG4gICAgICAgIC8vIEJyaWVmbHkgaGlkZSB0aGUgcGF5bWVudCBzZWN0aW9uIHRvIGF2b2lkIHByZW1hdHVyZSBmb3JtIHZhbGlkYXRpb24gb24gdGhlIHBheW1lbnQgc2VjdGlvblxuICAgICAgICAkKFwiLmNoZWNrb3V0LWJpbGxpbmctcGF5bWVudG1ldGhvZHNcIikuaGlkZSgpO1xuICAgIFx0XG4gICAgICAgIHZhciBzZWxlY3RlZCA9ICQodGhpcykuY2hpbGRyZW4oJzpzZWxlY3RlZCcpLmZpcnN0KCk7XG4gICAgICAgIHZhciBzZWxlY3RlZEFkZHJlc3MgPSAkKHNlbGVjdGVkKS5kYXRhKCdhZGRyZXNzJyk7XG4gICAgICAgIGlmICghc2VsZWN0ZWRBZGRyZXNzKSB7IHJldHVybjsgfVxuICAgICAgICB1dGlsLmZpbGxBZGRyZXNzRmllbGRzKHNlbGVjdGVkQWRkcmVzcywgJGZvcm0pO1xuICAgICAgICBzaGlwcGluZy51cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoKTtcbiAgICAgICAgLy8gcmUtdmFsaWRhdGUgdGhlIGZvcm1cbiAgICAgICAgJGZvcm0udmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgICAgIFxuICAgICAgICAkKFwiLmNoZWNrb3V0LWJpbGxpbmctcGF5bWVudG1ldGhvZHNcIikuc2hvdygpO1xuICAgIH0pO1xuXG4gICAgJCgnW25hbWUkPVwiX2FkZHJlc3MxXCJdLCBbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS5vbigna2V5cHJlc3Mga2V5ZG93biBrZXl1cCBjaGFuZ2UgcGFzdGUnLCBmdW5jdGlvbihlKSB7XG4gICAgXHR2YXIgbWF4ID0gNDA7XG4gICAgXHRpZiAodGhpcy52YWx1ZS5sZW5ndGggPT0gbWF4ICYmIGUua2V5Q29kZSAhPT0gNDYgJiYgZS5rZXlDb2RlICE9PSA4ICYmIGUua2V5Q29kZSAhPT0gOSAmJiAhdXRpbC5nZXRTZWxlY3Rpb25UZXh0KCkubGVuZ3RoKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy52YWx1ZS5sZW5ndGggPiBtYXgpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlLnN1YnN0cmluZygwLCBtYXgpO1xuICAgICAgICB9XG4gICAgXHRcbiAgICBcdGlmKHRoaXMudmFsdWUubGVuZ3RoID09IG1heCl7XG4gICAgXHRcdCQodGhpcykuY2xvc2VzdCgnLmZvcm0tcm93JykuZmluZCgnLmZvcm0tY2FwdGlvbicpLnNob3coKS50ZXh0KCc0MCBjaGFyYWN0ZXJzIGxpbWl0Jyk7XG4gICAgXHR9IGVsc2Uge1xuICAgIFx0XHQkKHRoaXMpLmNsb3Nlc3QoJy5mb3JtLXJvdycpLmZpbmQoJy5mb3JtLWNhcHRpb24nKS5oaWRlKCk7XG4gICAgXHR9XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9IHJlcXVpcmUoJy4uLy4uL2FqYXgnKSxcbiAgICBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vZm9ybVByZXBhcmUnKSxcbiAgICBnaWZ0Y2FyZCA9IHJlcXVpcmUoJy4uLy4uL2dpZnRjYXJkJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBGaWxscyB0aGUgQ3JlZGl0IENhcmQgZm9ybSB3aXRoIHRoZSBwYXNzZWQgZGF0YS1wYXJhbWV0ZXIgYW5kIGNsZWFycyB0aGUgZm9ybWVyIGN2biBpbnB1dFxuICogQHBhcmFtIHtPYmplY3R9IGRhdGEgVGhlIENyZWRpdCBDYXJkIGRhdGEgKGhvbGRlciwgdHlwZSwgbWFza2VkIG51bWJlciwgZXhwaXJhdGlvbiBtb250aC95ZWFyKVxuICovXG5mdW5jdGlvbiBzZXRDQ0ZpZWxkcyhkYXRhKSB7XG4gICAgdmFyICRjcmVkaXRDYXJkID0gJCgnW2RhdGEtbWV0aG9kPVwiQ1JFRElUX0NBUkRcIl0nKTtcbiAgICAkY3JlZGl0Q2FyZC5maW5kKCdpbnB1dFtuYW1lJD1cImNyZWRpdENhcmRfb3duZXJcIl0nKS52YWwoZGF0YS5ob2xkZXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICRjcmVkaXRDYXJkLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl90eXBlXCJdJykudmFsKGRhdGEudHlwZSk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnaW5wdXRbbmFtZSo9XCJfY3JlZGl0Q2FyZF9udW1iZXJcIl0nKS52YWwoZGF0YS5tYXNrZWROdW1iZXIpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICRjcmVkaXRDYXJkLmZpbmQoJ1tuYW1lJD1cIl9tb250aFwiXScpLnZhbChkYXRhLmV4cGlyYXRpb25Nb250aCkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnW25hbWUkPVwiX3llYXJcIl0nKS52YWwoZGF0YS5leHBpcmF0aW9uWWVhcikudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgJGNyZWRpdENhcmQuZmluZCgnW25hbWUkPVwiY3JlZGl0Q2FyZF9zZWxlY3RlZENhcmRJRFwiXScpLnZhbChkYXRhLnNlbGVjdGVkQ2FyZElEKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICBpZiAoISgnQ0hFQ0tPVVRfQUdFTlQnIGluIFNlc3Npb25BdHRyaWJ1dGVzICYmIFNlc3Npb25BdHRyaWJ1dGVzLkNIRUNLT1VUX0FHRU5UID09IHRydWUpKSB7XG4gICAgXHRcdCRjcmVkaXRDYXJkLmZpbmQoJ2lucHV0W25hbWUkPVwiX2N2blwiXScpLnZhbCgnJykudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIGNyZWRpdCBjYXJkIGZvcm0gd2l0aCB0aGUgYXR0cmlidXRlcyBvZiBhIGdpdmVuIGNhcmRcbiAqIEBwYXJhbSB7U3RyaW5nfSBjYXJkSUQgdGhlIGNyZWRpdCBjYXJkIElEIG9mIGEgZ2l2ZW4gY2FyZFxuICovXG5mdW5jdGlvbiBwb3B1bGF0ZUNyZWRpdENhcmRGb3JtKGNhcmRJRCkge1xuICAgIC8vIGxvYWQgY2FyZCBkZXRhaWxzXG4gICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChVcmxzLmJpbGxpbmdTZWxlY3RDQywgJ2NyZWRpdENhcmRVVUlEJywgY2FyZElEKTtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoUmVzb3VyY2VzLkNDX0xPQURfRVJST1IpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldENDRmllbGRzKGRhdGEpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQ2hhbmdlcyB0aGUgcGF5bWVudCBtZXRob2QgZm9ybSBkZXBlbmRpbmcgb24gdGhlIHBhc3NlZCBwYXltZW50TWV0aG9kSURcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXltZW50TWV0aG9kSUQgdGhlIElEIG9mIHRoZSBwYXltZW50IG1ldGhvZCwgdG8gd2hpY2ggdGhlIHBheW1lbnQgbWV0aG9kIGZvcm0gc2hvdWxkIGJlIGNoYW5nZWQgdG9cbiAqL1xuZnVuY3Rpb24gdXBkYXRlUGF5bWVudE1ldGhvZChwYXltZW50TWV0aG9kSUQpIHtcbiAgICB2YXIgJHBheW1lbnRNZXRob2RzID0gJCgnLnBheW1lbnQtbWV0aG9kJyk7XG4gICAgJHBheW1lbnRNZXRob2RzLnJlbW92ZUNsYXNzKCdwYXltZW50LW1ldGhvZC1leHBhbmRlZCcpO1xuXG4gICAgdmFyICRzZWxlY3RlZFBheW1lbnRNZXRob2QgPSAkcGF5bWVudE1ldGhvZHMuZmlsdGVyKCdbZGF0YS1tZXRob2Q9XCInICsgcGF5bWVudE1ldGhvZElEICsgJ1wiXScpO1xuICAgIGlmICgkc2VsZWN0ZWRQYXltZW50TWV0aG9kLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAkc2VsZWN0ZWRQYXltZW50TWV0aG9kID0gJCgnW2RhdGEtbWV0aG9kPVwiQ3VzdG9tXCJdJyk7XG4gICAgfVxuICAgICRzZWxlY3RlZFBheW1lbnRNZXRob2QuYWRkQ2xhc3MoJ3BheW1lbnQtbWV0aG9kLWV4cGFuZGVkJyk7XG5cbiAgICAvLyBlbnN1cmUgY2hlY2tib3ggb2YgcGF5bWVudCBtZXRob2QgaXMgY2hlY2tlZFxuICAgICQoJ2lucHV0W25hbWUkPVwiX3NlbGVjdGVkUGF5bWVudE1ldGhvZElEXCJdJykucmVtb3ZlQXR0cignY2hlY2tlZCcpO1xuICAgICQoJ2lucHV0W3ZhbHVlPScgKyBwYXltZW50TWV0aG9kSUQgKyAnXScpLnByb3AoJ2NoZWNrZWQnLCAnY2hlY2tlZCcpO1xuXG4gICAgZm9ybVByZXBhcmUudmFsaWRhdGVGb3JtKCk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gUG9wdWxhdGVzIHRoZSBiaWxsaW5nIGFkZHJlc3MgZmllbGRzIHdpdGggdGhlIHZhbHVlcyB1c2VkIGZvciBzaGlwcGluZ1xuICovXG5mdW5jdGlvbiBpbml0VXNlU2hpcHBpbmdBc0JpbGxpbmcoKSB7XG5cdHZhciAkY2hlY2tvdXRGb3JtID0gJCgnLmNoZWNrb3V0LWJpbGxpbmcnKTtcblx0JCgnaW5wdXRbbmFtZSQ9XCJfdXNlU2hpcHBpbmdBc0JpbGxpbmdcIl0nLCAkY2hlY2tvdXRGb3JtKS5vbihcImNoYW5nZVwiLCBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCQodGhpcykuaXMoJzpjaGVja2VkJykpIHtcbiAgICAgICAgICAgICQoJyNiaWxsaW5nX2hpZGUnKS5oaWRlKCk7XG4gICAgICAgICAgICAkKCcjbWluaV9hZGRyZXNzX3Nob3cgLmJpbGxpbmdBZGRyZXNzQ2FyZCcpLnNob3coKTtcblx0XHRcdGlmICgnc2hpcHBpbmdBZGRyZXNzJyBpbiBVc2VyICYmICEkLmlzRW1wdHlPYmplY3QoVXNlci5zaGlwcGluZ0FkZHJlc3MpKSB7XG5cdFx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykudmFsKFVzZXIuc2hpcHBpbmdBZGRyZXNzLmZpcnN0TmFtZSk7XG5cdFx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoVXNlci5zaGlwcGluZ0FkZHJlc3MubGFzdE5hbWUpO1xuXHRcdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKFVzZXIuc2hpcHBpbmdBZGRyZXNzLmFkZHJlc3MxKTtcblx0XHRcdFx0JGNoZWNrb3V0Rm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbChVc2VyLnNoaXBwaW5nQWRkcmVzcy5hZGRyZXNzMik7XG5cdFx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbChVc2VyLnNoaXBwaW5nQWRkcmVzcy5jaXR5KTtcblx0XHRcdFx0JGNoZWNrb3V0Rm9ybS5maW5kKCdzZWxlY3RbbmFtZSQ9XCJfc3RhdGVcIl0nKS52YWwoVXNlci5zaGlwcGluZ0FkZHJlc3Muc3RhdGUpO1xuXHRcdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbChVc2VyLnNoaXBwaW5nQWRkcmVzcy5wb3N0YWxDb2RlKTtcblx0XHRcdFx0JGNoZWNrb3V0Rm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9waG9uZVwiXScpLnZhbChVc2VyLnNoaXBwaW5nQWRkcmVzcy5waG9uZSk7XG5cdFx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnc2VsZWN0W25hbWUkPVwiX2JpbGxpbmdfYWRkcmVzc0xpc3RcIl0gb3B0aW9uOmZpcnN0JykucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHRcdH1cbiAgICAgICAgICAgICQodGhpcykuY2xvc2VzdCgnZGl2LmZvcm0tcm93JykuYWRkQ2xhc3MoJ3Zpc3VhbGx5LWhpZGRlbicpO1xuXHRcdH0gZWxzZSB7XG4gICAgICAgICAgICAkKCcjYmlsbGluZ19oaWRlJykuc2hvdygpO1xuICAgICAgICAgICAgJCgnI21pbmlfYWRkcmVzc19zaG93IC5iaWxsaW5nQWRkcmVzc0NhcmQnKS5oaWRlKCk7ICAgICAgICAgICBcblx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfZmlyc3ROYW1lXCJdJykudmFsKCcnKTtcblx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfbGFzdE5hbWVcIl0nKS52YWwoJycpO1xuXHRcdFx0JGNoZWNrb3V0Rm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgnJyk7XG5cdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX2FkZHJlc3MyXCJdJykudmFsKCcnKTtcblx0XHRcdCRjaGVja291dEZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfY2l0eVwiXScpLnZhbCgnJyk7XG5cdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1cIl9zdGF0ZVwiXSBvcHRpb246Zmlyc3QnKS5wcm9wKCdzZWxlY3RlZCcsdHJ1ZSk7XG5cdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bvc3RhbFwiXScpLnZhbCgnJyk7XG5cdFx0XHQkY2hlY2tvdXRGb3JtLmZpbmQoJ2lucHV0W25hbWUkPVwiX3Bob25lXCJdJykudmFsKCcnKTtcblx0XHR9XG5cdH0pO1xuXG4gICAgJCgnI2J0bl9iaWxsaW5nX2VkaXQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkX3VzZVNoaXBwaW5nQXNCaWxsaW5nID0gJCgnaW5wdXRbbmFtZSQ9XCJfdXNlU2hpcHBpbmdBc0JpbGxpbmdcIl0nKTtcbiAgICAgICAgJF91c2VTaGlwcGluZ0FzQmlsbGluZy5wcm9wKFwiY2hlY2tlZFwiLCAhJF91c2VTaGlwcGluZ0FzQmlsbGluZy5wcm9wKFwiY2hlY2tlZFwiKSk7XG4gICAgICAgIGlmICghJF91c2VTaGlwcGluZ0FzQmlsbGluZy5wcm9wKFwiY2hlY2tlZFwiKSkge1xuICAgICAgICAgICAgJF91c2VTaGlwcGluZ0FzQmlsbGluZy5jbG9zZXN0KCdkaXYuZm9ybS1yb3cnKS5yZW1vdmVDbGFzcygndmlzdWFsbHktaGlkZGVuJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkX3VzZVNoaXBwaW5nQXNCaWxsaW5nLmNsb3Nlc3QoJ2Rpdi5mb3JtLXJvdycpLmFkZENsYXNzKCd2aXN1YWxseS1oaWRkZW4nKTtcbiAgICAgICAgfVxuICAgICAgICAkKCdpbnB1dFtuYW1lJD1cIl91c2VTaGlwcGluZ0FzQmlsbGluZ1wiXScsICRjaGVja291dEZvcm0pLnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgfSk7XG5cdFxuXHQvLyBJZiB0aGUgdXNlciBtYWtlcyBjaGFuZ2VzIHRvIHRoZSBmaWVsZHMsIHdlIHNob3VsZCB1bmNoZWNrIHRoZSAnVXNlIHNoaXBwaW5nIGFzIGJpbGxpbmcnIGJveFxuXHQkKCdpbnB1dCcsICRjaGVja291dEZvcm0pLmZpbHRlcignW25hbWUkPVwiX2ZpcnN0TmFtZVwiXSxbbmFtZSQ9XCJfbGFzdE5hbWVcIl0sW25hbWUkPVwiX2FkZHJlc3MxXCJdLFtuYW1lJD1cIl9hZGRyZXNzMlwiXSxbbmFtZSQ9XCJfY2l0eVwiXSxbbmFtZSQ9XCJfcG9zdGFsXCJdLFtuYW1lJD1cIl9waG9uZVwiXScpLmtleXVwKGZ1bmN0aW9uICgpIHtcblx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VTaGlwcGluZ0FzQmlsbGluZ1wiXScsICRjaGVja291dEZvcm0pLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdH0pO1xuXG5cdC8vIFRoZSBzdGF0ZSBkcm9wLWRvd24gZG9lc24ndCBoYXZlIGEga2V5dXAgZXZlbnQsIHNvIHdlIGxpc3RlbiBmb3IgaXQgdG8gYmUgY2hhbmdlZC5cblx0JCgnc2VsZWN0W25hbWUkPVwiX3N0YXRlXCJdJywgJGNoZWNrb3V0Rm9ybSkub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcblx0XHQkKCdpbnB1dFtuYW1lJD1cIl91c2VTaGlwcGluZ0FzQmlsbGluZ1wiXScsICRjaGVja291dEZvcm0pLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG5cdH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIGxvYWRzIGJpbGxpbmcgYWRkcmVzcywgR2lmdCBDZXJ0aWZpY2F0ZXMsIENvdXBvbiBhbmQgUGF5bWVudCBtZXRob2RzXG4gKi9cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGNoZWNrb3V0Rm9ybSA9ICQoJy5jaGVja291dC1iaWxsaW5nJyk7XG4gICAgdmFyICRhZGRHaWZ0Q2VydCA9ICQoJyNhZGQtZ2lmdGNlcnQnKTtcbiAgICB2YXIgJGdpZnRDZXJ0Q29kZSA9ICQoJ2lucHV0W25hbWUkPVwiX2dpZnRDZXJ0Q29kZVwiXScpO1xuICAgIHZhciAkYWRkQ291cG9uID0gJCgnI2FkZC1jb3Vwb24nKTtcbiAgICB2YXIgJGNvdXBvbkNvZGUgPSAkKCdpbnB1dFtuYW1lJD1cIl9jb3Vwb25Db2RlXCJdJyk7XG4gICAgdmFyICRzZWxlY3RQYXltZW50TWV0aG9kID0gJCgnLnBheW1lbnQtbWV0aG9kLW9wdGlvbnMnKTtcbiAgICB2YXIgc2VsZWN0ZWRQYXltZW50TWV0aG9kID0gJHNlbGVjdFBheW1lbnRNZXRob2QuZmluZCgnOmNoZWNrZWQnKS52YWwoKTtcblxuICAgIC8vIFRoaXMgd2lsbCByZXNldCB0aGUgcGF5bWVudCBkZXRhaWxzIG9uIGNhcmQgdHlwZSBjaGFuZ2UgdG8gcHJldmVudCBmdW5jdGlvbmFsIGlzc3VlXG4gICAgJChcIiNkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfdHlwZVwiKS5vbignY2hhbmdlJyxmdW5jdGlvbigpIHtcblx0ICAgIFx0JChcImlucHV0W2lkXj0nZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX251bWJlciddXCIpLnZhbCgnJyk7XG5cdCAgICBcdCQoXCIjZHdmcm1fYmlsbGluZ19wYXltZW50TWV0aG9kc19jcmVkaXRDYXJkX2V4cGlyYXRpb25fbW9udGggb3B0aW9uOmZpcnN0XCIpLnByb3AoJ3NlbGVjdGVkJyx0cnVlKTtcblx0ICAgIFx0JChcIiNkd2ZybV9iaWxsaW5nX3BheW1lbnRNZXRob2RzX2NyZWRpdENhcmRfZXhwaXJhdGlvbl95ZWFyIG9wdGlvbjpmaXJzdFwiKS5wcm9wKCdzZWxlY3RlZCcsdHJ1ZSk7XG5cdCAgICBcdCQoXCJpbnB1dFtpZF49J2R3ZnJtX2JpbGxpbmdfcGF5bWVudE1ldGhvZHNfY3JlZGl0Q2FyZF9jdm4nXVwiKS52YWwoJycpO1xuXHQgICAgXHQkKCcuY2hlY2tvdXQtYmlsbGluZycpLmZpbmQoJ2lucHV0W25hbWUkPVwiX3NlbGVjdGVkQ2FyZElEXCJdJykudmFsKCcnKTtcblx0ICAgIFx0JCgnI2NyZWRpdENhcmRMaXN0IG9wdGlvbjpmaXJzdCcpLnByb3AoJ3NlbGVjdGVkJyx0cnVlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICB9KTtcbiAgICBcbiAgICBmb3JtUHJlcGFyZS5pbml0KHtcbiAgICAgICAgZm9ybVNlbGVjdG9yOiAnZm9ybVtpZCQ9XCJiaWxsaW5nXCJdJyxcbiAgICAgICAgY29udGludWVTZWxlY3RvcjogJ1tuYW1lJD1cImJpbGxpbmdfc2F2ZVwiXSdcbiAgICB9KTtcblxuICAgIC8vIGRlZmF1bHQgcGF5bWVudCBtZXRob2QgdG8gJ0NSRURJVF9DQVJEJ1xuICAgIHVwZGF0ZVBheW1lbnRNZXRob2QoKHNlbGVjdGVkUGF5bWVudE1ldGhvZCkgPyBzZWxlY3RlZFBheW1lbnRNZXRob2QgOiAnQ1JFRElUX0NBUkQnKTtcbiAgICAkc2VsZWN0UGF5bWVudE1ldGhvZC5vbignY2xpY2snLCAnaW5wdXRbdHlwZT1cInJhZGlvXCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB1cGRhdGVQYXltZW50TWV0aG9kKCQodGhpcykudmFsKCkpO1xuICAgIH0pO1xuICAgIFxuICAgIC8vdGhpcyBpcyBtYWtlIHRoZSB3aG9sZSBleHBpcmF0aW9uIGZpZWxkIGNvbnRhaW5lciB0YWcgYXMgZXJyb3IgaW4gYmlsbGluZyBwYWdlXG4gICAgaWYoJCgnLmV4cGlyYXRpb24tY29udGFpbmVyIC5mb3JtLXJvdy5tb250aCcpLmhhc0NsYXNzKCdlcnJvcicpKSB7XG4gICAgXHRcdCQoJy5leHBpcmF0aW9uLWNvbnRhaW5lcicpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgIH1cblxuXG4gICAgLy8gc2VsZWN0IGNyZWRpdCBjYXJkIGZyb20gbGlzdFxuICAgIHZhciAkY3JlZGl0Q2FyZExpc3QgPSAkKCcjY3JlZGl0Q2FyZExpc3QnKTtcbiAgICAkY3JlZGl0Q2FyZExpc3Qub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhcmRVVUlEID0gJCh0aGlzKS52YWwoKTtcbiAgICAgICAgaWYgKCFjYXJkVVVJRCkge1xuICAgICAgICBcdFx0JCgkY2hlY2tvdXRGb3JtKS5maW5kKCdpbnB1dFtuYW1lJD1cIl9zZWxlY3RlZENhcmRJRFwiXScpLnZhbCgnJyk7IFxuICAgICAgICBcdFx0cmV0dXJuO1xuICAgICAgICBcdH1cbiAgICAgICAgcG9wdWxhdGVDcmVkaXRDYXJkRm9ybShjYXJkVVVJRCk7XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNlcnZlciBzaWRlIGVycm9yXG4gICAgICAgICQoJy5yZXF1aXJlZC5lcnJvcicpLnJlbW92ZUNsYXNzKCdlcnJvcicpO1xuICAgICAgICAkKCcuZXJyb3ItbWVzc2FnZScpLnJlbW92ZSgpO1xuICAgIH0pO1xuICAgIFxuICAgIC8vcHJlc2VsZWN0IGRlZmF1bHQgY3JlZGl0IGNhcmRcbiAgICBpZigkKCcjcGF5bWVudEVycm9yJykudmFsKCkgPT09ICdmYWxzZScpIHtcblx0ICAgIGlmKCRjcmVkaXRDYXJkTGlzdC5sZW5ndGggPiAwKXtcblx0XHRcdCRjcmVkaXRDYXJkTGlzdC5maW5kKCdvcHRpb24nKS5lcSgxKS5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xuXHRcdFx0JGNyZWRpdENhcmRMaXN0LnRyaWdnZXIoJ2NoYW5nZScpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAkKCcjY2hlY2stZ2lmdGNlcnQnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciAkYmFsYW5jZSA9ICQoJy5iYWxhbmNlJyk7XG4gICAgICAgIGlmICgkZ2lmdENlcnRDb2RlLmxlbmd0aCA9PT0gMCB8fCAkZ2lmdENlcnRDb2RlLnZhbCgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdmFyIGVycm9yID0gJGJhbGFuY2UuZmluZCgnc3Bhbi5lcnJvcicpO1xuICAgICAgICAgICAgaWYgKGVycm9yLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGVycm9yID0gJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ2Vycm9yJykuYXBwZW5kVG8oJGJhbGFuY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXJyb3IuaHRtbChSZXNvdXJjZXMuR0lGVF9DRVJUX01JU1NJTkcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2lmdGNhcmQuY2hlY2tCYWxhbmNlKCRnaWZ0Q2VydENvZGUudmFsKCksIGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuZ2lmdENlcnRpZmljYXRlKSB7XG4gICAgICAgICAgICAgICAgJGJhbGFuY2UuaHRtbChSZXNvdXJjZXMuR0lGVF9DRVJUX0lOVkFMSUQpLnJlbW92ZUNsYXNzKCdzdWNjZXNzJykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGJhbGFuY2UuaHRtbChSZXNvdXJjZXMuR0lGVF9DRVJUX0JBTEFOQ0UgKyAnICcgKyBkYXRhLmdpZnRDZXJ0aWZpY2F0ZS5iYWxhbmNlKS5yZW1vdmVDbGFzcygnZXJyb3InKS5hZGRDbGFzcygnc3VjY2VzcycpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgICRhZGRHaWZ0Q2VydC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZhciBjb2RlID0gJGdpZnRDZXJ0Q29kZS52YWwoKSxcbiAgICAgICAgICAgICRlcnJvciA9ICRjaGVja291dEZvcm0uZmluZCgnLmdpZnRjZXJ0LWVycm9yJyk7XG4gICAgICAgIGlmIChjb2RlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgJGVycm9yLmh0bWwoUmVzb3VyY2VzLkdJRlRfQ0VSVF9NSVNTSU5HKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKFVybHMucmVkZWVtR2lmdENlcnQsIHtnaWZ0Q2VydENvZGU6IGNvZGUsIGZvcm1hdDogJ2FqYXgnfSk7XG4gICAgICAgICQuZ2V0SlNPTih1cmwsIGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICB2YXIgZmFpbCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIG1zZyA9ICcnO1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gUmVzb3VyY2VzLkJBRF9SRVNQT05TRTtcbiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIG1zZyA9IGRhdGEubWVzc2FnZS5zcGxpdCgnPCcpLmpvaW4oJyZsdDsnKS5zcGxpdCgnPicpLmpvaW4oJyZndDsnKTtcbiAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmYWlsKSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmh0bWwobXNnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5hc3NpZ24oVXJscy5iaWxsaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAkYWRkQ291cG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyICRlcnJvciA9ICRjaGVja291dEZvcm0uZmluZCgnLmNvdXBvbi1lcnJvcicpLFxuICAgICAgICBcdFx0JHN1Y2VzcyA9ICRjaGVja291dEZvcm0uZmluZCgnLmNvdXBvbi1zdWNjZXNzJyksXG4gICAgICAgICAgICBjb2RlID0gJGNvdXBvbkNvZGUudmFsKCk7XG4gICAgICAgIGlmIChjb2RlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgJGVycm9yLmh0bWwoUmVzb3VyY2VzLkNPVVBPTl9DT0RFX01JU1NJTkcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5hZGRDb3Vwb24sIHtjb3Vwb25Db2RlOiBjb2RlLCBmb3JtYXQ6ICdhamF4J30pO1xuICAgICAgICAkLmdldEpTT04odXJsLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgdmFyIGZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBtc2cgPSAnJztcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIG1zZyA9IFJlc291cmNlcy5CQURfUkVTUE9OU0U7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSBkYXRhLm1lc3NhZ2Uuc3BsaXQoJzwnKS5qb2luKCcmbHQ7Jykuc3BsaXQoJz4nKS5qb2luKCcmZ3Q7Jyk7XG4gICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmFpbCkge1xuICAgICAgICAgICAgICAgICRlcnJvci5odG1sKG1zZyk7XG4gICAgICAgICAgICAgICAgJHN1Y2Vzcy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKGRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgXHRcdCRzdWNlc3MuaHRtbChkYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgXHRcdHdpbmRvdy5sb2NhdGlvbi5hc3NpZ24oVXJscy5iaWxsaW5nKTtcbiAgICAgICAgICAgIFx0XHRyZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vYmFza2V0IGNoZWNrIGZvciBkaXNwbGF5aW5nIHRoZSBwYXltZW50IHNlY3Rpb24sIGlmIHRoZSBhZGp1c3RlZCB0b3RhbCBvZiB0aGUgYmFza2V0IGlzIDAgYWZ0ZXIgYXBwbHlpbmcgdGhlIGNvdXBvblxuICAgICAgICAgICAgLy90aGlzIHdpbGwgZm9yY2UgYSBwYWdlIHJlZnJlc2ggdG8gZGlzcGxheSB0aGUgY291cG9uIG1lc3NhZ2UgYmFzZWQgb24gYSBwYXJhbWV0ZXIgbWVzc2FnZVxuICAgICAgICAgICAgaWYgKGRhdGEuc3VjY2VzcyAmJiBkYXRhLmJhc2tldHRvdGFsID09PSAwKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmFzc2lnbihVcmxzLmJpbGxpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIHRyaWdnZXIgZXZlbnRzIG9uIGVudGVyXG4gICAgJGNvdXBvbkNvZGUub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS53aGljaCA9PT0gMTMpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICRhZGRDb3Vwb24uY2xpY2soKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgICRnaWZ0Q2VydENvZGUub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS53aGljaCA9PT0gMTMpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICRhZGRHaWZ0Q2VydC5jbGljaygpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgaW5pdFVzZVNoaXBwaW5nQXNCaWxsaW5nKCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpO1xuXG52YXIgJGZvcm0sICRjb250aW51ZSwgJHJlcXVpcmVkSW5wdXRzLCB2YWxpZGF0b3I7XG5cbnZhciBoYXNFbXB0eVJlcXVpcmVkID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIGZpbHRlciBvdXQgb25seSB0aGUgdmlzaWJsZSBmaWVsZHNcbiAgICB2YXIgcmVxdWlyZWRWYWx1ZXMgPSAkcmVxdWlyZWRJbnB1dHMuZmlsdGVyKCc6dmlzaWJsZScpLm1hcChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAkKHRoaXMpLnZhbCgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIF8ocmVxdWlyZWRWYWx1ZXMpLmluY2x1ZGVzKCcnKTtcbn07XG5cbnZhciB2YWxpZGF0ZUZvcm0gPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gb25seSB2YWxpZGF0ZSBmb3JtIHdoZW4gYWxsIHJlcXVpcmVkIGZpZWxkcyBhcmUgZmlsbGVkIHRvIGF2b2lkXG4gICAgLy8gdGhyb3dpbmcgZXJyb3JzIG9uIGVtcHR5IGZvcm1cbiAgICBpZiAoIXZhbGlkYXRvcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIGpRdWVyeS52YWxpZGF0b3IuYWRkTWV0aG9kKFwiY2hlY2tsZW5cIiwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZS5sZW5ndGggPD0gNDA7XG4gICAgfSwgXCI0MCBjaGFyYWN0ZXIgbGltaXRcIik7XG5cbiAgICBqUXVlcnkudmFsaWRhdG9yLmNsYXNzUnVsZVNldHRpbmdzLmNoZWNrbGVuID0geyBjaGVja2xlbjogdHJ1ZSB9O1xuICAgIFxuICAgIGlmICghaGFzRW1wdHlSZXF1aXJlZCgpKSB7XG4gICAgICAgIGlmICh2YWxpZGF0b3IuZm9ybSgpKSB7XG4gICAgICAgICAgICAkY29udGludWUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgICRjb250aW51ZS5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH1cbn07XG5cbnZhciB2YWxpZGF0ZUVsID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICgkKHRoaXMpLnZhbCgpID09PSAnJykge1xuICAgICAgICAkY29udGludWUuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBlbmFibGUgY29udGludWUgYnV0dG9uIG9uIGxhc3QgcmVxdWlyZWQgZmllbGQgdGhhdCBpcyB2YWxpZFxuICAgICAgICAvLyBvbmx5IHZhbGlkYXRlIHNpbmdsZSBmaWVsZFxuICAgICAgICBpZiAodmFsaWRhdG9yLmVsZW1lbnQodGhpcykgJiYgIWhhc0VtcHR5UmVxdWlyZWQoKSkge1xuICAgICAgICAgICAgJGNvbnRpbnVlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkY29udGludWUuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbnZhciBpbml0ID0gZnVuY3Rpb24gKG9wdHMpIHtcbiAgICBpZiAoIW9wdHMuZm9ybVNlbGVjdG9yIHx8ICFvcHRzLmNvbnRpbnVlU2VsZWN0b3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGZvcm0gYW5kIGNvbnRpbnVlIGFjdGlvbiBzZWxlY3RvcnMuJyk7XG4gICAgfVxuICAgICRmb3JtID0gJChvcHRzLmZvcm1TZWxlY3Rvcik7XG4gICAgJGNvbnRpbnVlID0gJChvcHRzLmNvbnRpbnVlU2VsZWN0b3IpO1xuICAgIHZhbGlkYXRvciA9ICRmb3JtLnZhbGlkYXRlKHtcbiAgICBcdCAgIG9ua2V5dXA6IHRydWVcbiAgICB9KTtcbiAgICAkcmVxdWlyZWRJbnB1dHMgPSAkKCcucmVxdWlyZWQnLCAkZm9ybSkuZmluZCgnOmlucHV0Jyk7XG4gICAgdmFsaWRhdGVGb3JtKCk7XG4gICAgLy8gc3RhcnQgbGlzdGVuaW5nXG4gICAgJHJlcXVpcmVkSW5wdXRzLm9uKCdjaGFuZ2UnLCB2YWxpZGF0ZUVsKTtcbiAgICAkcmVxdWlyZWRJbnB1dHMuZmlsdGVyKCdpbnB1dCcpLm9uKCdrZXl1cCcsIF8uZGVib3VuY2UodmFsaWRhdGVFbCwgMjAwKSk7XG4gICAgJGZvcm0uZmluZCgnaW5wdXRbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS5vbigna2V5dXAnLCBfLmRlYm91bmNlKHZhbGlkYXRlRWwsIDIwMCkpO1xufTtcblxuZXhwb3J0cy5pbml0ID0gaW5pdDtcbmV4cG9ydHMudmFsaWRhdGVGb3JtID0gdmFsaWRhdGVGb3JtO1xuZXhwb3J0cy52YWxpZGF0ZUVsID0gdmFsaWRhdGVFbDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZHJlc3MgPSByZXF1aXJlKCcuL2FkZHJlc3MnKSxcbiAgICBiaWxsaW5nID0gcmVxdWlyZSgnLi9iaWxsaW5nJyksXG4gICAgbXVsdGlzaGlwID0gcmVxdWlyZSgnLi9tdWx0aXNoaXAnKSxcbiAgICBzaGlwcGluZyA9IHJlcXVpcmUoJy4vc2hpcHBpbmcnKTtcblxuZnVuY3Rpb24gaW5pdFJvdW5kVXBEb25hdGlvbnMoKSB7XG5cdCQoJ2lucHV0W25hbWUkPVwiaXNSb3VuZFVwRG9uYXRpb25cIicpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgcHJldmlvdXNTZXR0aW5nID0gJCh0aGlzKS5kYXRhKCdjaGVja2VkJykgPyB0cnVlIDogZmFsc2UsXG5cdFx0XHRvcHRpb25zID0ge1xuXHQgICAgICAgICAgICB1cmw6IFVybHMuU2V0Q2hlY2tvdXRSb3VuZFVwRG9uYXRpb25zLFxuXHQgICAgICAgICAgICBkYXRhOiAnZW5hYmxlUm91bmRVcERvbmF0aW9uPScgKyAhcHJldmlvdXNTZXR0aW5nLFxuXHQgICAgICAgICAgICB0eXBlOiAnUE9TVCdcblx0ICAgICAgICB9O1xuXHRcdFxuXHRcdC8vIFVuLWNoZWNrIHRoZSByYWRpbyBidXR0b25cblx0XHRpZiAocHJldmlvdXNTZXR0aW5nID09IHRydWUpIHtcblx0XHRcdCQodGhpcykucHJvcCgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHRcdCQodGhpcykuZGF0YSgnY2hlY2tlZCcsIGZhbHNlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JCh0aGlzKS5kYXRhKCdjaGVja2VkJywgdHJ1ZSk7XG5cdFx0fVxuXHRcdFxuXHRcdC8vIFRoZSBuZXcgc2V0dGluZyBpcyBhbHdheXMgdGhlIG9wcG9zaXRlIG9mIHRoZSBwcmV2aW91c1xuXHRcdGlmICghcHJldmlvdXNTZXR0aW5nKSB7XG5cdFx0XHR1cGRhdGVSb3VuZFVwVG90YWxEaXNwbGF5KHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR1cGRhdGVSb3VuZFVwVG90YWxEaXNwbGF5KGZhbHNlKTtcblx0XHR9XG5cdH0pO1xuXHRcblx0JCgnPHNwYW4gY2xhc3M9XCJzbGlkZXIgcm91bmRcIj48L3NwYW4+JykuaW5zZXJ0QWZ0ZXIoXCIjZHdmcm1fYmlsbGluZ19kb25hdGlvbnNfaXNSb3VuZFVwRG9uYXRpb25cIik7XG5cbn1cblxuZnVuY3Rpb24gdXBkYXRlUm91bmRVcFRvdGFsRGlzcGxheShlbmFibGVkKSB7XG5cdHZhciAkb3JkZXJUb3RhbEVsZW1lbnQgPSAkKFwiLm9yZGVyLXRvdGFsIC5vcmRlci12YWx1ZVwiKSxcblx0XHQkZG9uYXRpb25Ub3RhbEVsZW1lbnQgPSAkKFwiLmRvbmF0aW9ucy10b3RhbCAuZG9uYXRpb25zLXZhbHVlXCIpLFxuXHRcdG9yaWdpbmFsT3JkZXJUb3RhbCA9ICRvcmRlclRvdGFsRWxlbWVudC5kYXRhKCdvcmlnaW5hbFRvdGFsJyksXG5cdFx0b3JpZ2luYWxEb25hdGlvblRvdGFsID0gJGRvbmF0aW9uVG90YWxFbGVtZW50LmRhdGEoJ29yaWdpbmFsVG90YWwnKSxcblx0XHRuZXdEb25hdGlvblRvdGFsO1xuXHRcblx0Ly8gSWYgaXQncyBudWxsLCBpdCBoYXNuJ3QgYmVlbiBzZXQgYmVmb3JlLCBzbyB0aGUgb3JpZ2luYWwgdG90YWxzIGFyZSBzdGlsbCBkaXNwbGF5aW5nXG5cdG9yaWdpbmFsT3JkZXJUb3RhbCA9IGdldE9yU2V0U3RvcmVkVmFsdWUob3JpZ2luYWxPcmRlclRvdGFsLCAkb3JkZXJUb3RhbEVsZW1lbnQpO1xuXHRvcmlnaW5hbERvbmF0aW9uVG90YWwgPSBnZXRPclNldFN0b3JlZFZhbHVlKG9yaWdpbmFsRG9uYXRpb25Ub3RhbCwgJGRvbmF0aW9uVG90YWxFbGVtZW50KTtcblx0XG5cdGlmIChlbmFibGVkKSB7XG5cdFx0Ly8gVXBkYXRlIHRoZSB2YWx1ZXMgdG8gZmFjdG9yIGluIHJvdW5kLXVwIGRvbmF0aW9uXG5cdFx0bmV3RG9uYXRpb25Ub3RhbCA9IG9yaWdpbmFsRG9uYXRpb25Ub3RhbCArIGdldFJvdW5kVXBBbW91bnQob3JpZ2luYWxPcmRlclRvdGFsKTtcblx0XHRpZiAoUmVzb3VyY2VzLkNVUlJFTkNZX1NZTUJPTF9QTEFDRU1FTlQgPT0gJ2JlZm9yZScpIHtcblx0XHRcdCRkb25hdGlvblRvdGFsRWxlbWVudC5odG1sKFJlc291cmNlcy5DVVJSRU5DWV9TWU1CT0wgKyBuZXdEb25hdGlvblRvdGFsLnRvRml4ZWQoMikpO1xuXHRcdFx0JG9yZGVyVG90YWxFbGVtZW50Lmh0bWwoUmVzb3VyY2VzLkNVUlJFTkNZX1NZTUJPTCArIE1hdGguY2VpbChvcmlnaW5hbE9yZGVyVG90YWwpLnRvRml4ZWQoMikpO1x0XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRkb25hdGlvblRvdGFsRWxlbWVudC5odG1sKG5ld0RvbmF0aW9uVG90YWwudG9GaXhlZCgyKSArIFJlc291cmNlcy5DVVJSRU5DWV9TWU1CT0wpO1xuXHRcdFx0JG9yZGVyVG90YWxFbGVtZW50Lmh0bWwoTWF0aC5jZWlsKG9yaWdpbmFsT3JkZXJUb3RhbCkudG9GaXhlZCgyKSArIFJlc291cmNlcy5DVVJSRU5DWV9TWU1CT0wpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHQvLyBHcmFiIHRoZSBvcmlnaW5hbCB0b3RhbCBmcm9tIHRoZSBqcyBkYXRhIGVsZW1lbnRcblx0XHRpZiAoUmVzb3VyY2VzLkNVUlJFTkNZX1NZTUJPTF9QTEFDRU1FTlQgPT0gJ2JlZm9yZScpIHtcblx0XHRcdCRkb25hdGlvblRvdGFsRWxlbWVudC5odG1sKFJlc291cmNlcy5DVVJSRU5DWV9TWU1CT0wgKyAkZG9uYXRpb25Ub3RhbEVsZW1lbnQuZGF0YSgnb3JpZ2luYWxUb3RhbCcpLnRvRml4ZWQoMikpO1xuXHRcdFx0JG9yZGVyVG90YWxFbGVtZW50Lmh0bWwoUmVzb3VyY2VzLkNVUlJFTkNZX1NZTUJPTCArICRvcmRlclRvdGFsRWxlbWVudC5kYXRhKCdvcmlnaW5hbFRvdGFsJykudG9GaXhlZCgyKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCRkb25hdGlvblRvdGFsRWxlbWVudC5odG1sKCRkb25hdGlvblRvdGFsRWxlbWVudC5kYXRhKCdvcmlnaW5hbFRvdGFsJykudG9GaXhlZCgyKSArIFJlc291cmNlcy5DVVJSRU5DWV9TWU1CT0wpO1xuXHRcdFx0JG9yZGVyVG90YWxFbGVtZW50Lmh0bWwoJG9yZGVyVG90YWxFbGVtZW50LmRhdGEoJ29yaWdpbmFsVG90YWwnKS50b0ZpeGVkKDIpICsgUmVzb3VyY2VzLkNVUlJFTkNZX1NZTUJPTCk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGdldE9yU2V0U3RvcmVkVmFsdWUoZGF0YSwgZG9tRWxlbWVudCkge1xuXHRpZiAoZGF0YSA9PSBudWxsKSB7XG5cdFx0ZGF0YSA9IE51bWJlcihkb21FbGVtZW50Lmh0bWwoKS5yZXBsYWNlKC9bXjAtOVxcLi1dKy9nLFwiXCIpKTtcblx0XHRkb21FbGVtZW50LmRhdGEoJ29yaWdpbmFsVG90YWwnLCBkYXRhKTtcblx0fVxuXHRcblx0cmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIGdldFJvdW5kVXBBbW91bnQoT3JkZXJUb3RhbCkge1xuXHRjb25zb2xlLmxvZygnQ2FsY3VsYXRpbmcgcm91bmQtdXAgYW1vdW50Jyk7XG5cdHJldHVybiBNYXRoLmNlaWwoT3JkZXJUb3RhbCkgLSBPcmRlclRvdGFsO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBJbml0aWFsaXplcyB0aGUgcGFnZSBldmVudHMgZGVwZW5kaW5nIG9uIHRoZSBjaGVja291dCBzdGFnZSAoc2hpcHBpbmcvYmlsbGluZylcbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGFkZHJlc3MuaW5pdCgpO1xuICAgIGlmICgkKCcuY2hlY2tvdXQtc2hpcHBpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHNoaXBwaW5nLmluaXQoKTtcbiAgICB9IGVsc2UgaWYgKCQoJy5jaGVja291dC1tdWx0aS1zaGlwcGluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbXVsdGlzaGlwLmluaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBiaWxsaW5nLmluaXQoKTtcbiAgICB9XG5cbiAgICAvL2lmIG9uIHRoZSBvcmRlciByZXZpZXcgcGFnZSBhbmQgdGhlcmUgYXJlIHByb2R1Y3RzIHRoYXQgYXJlIG5vdCBhdmFpbGFibGUgZGlzYWJsZSB0aGUgc3VibWl0IG9yZGVyIGJ1dHRvblxuICAgIGlmICgkKCcub3JkZXItc3VtbWFyeS1mb290ZXInKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGlmICgkKCcubm90YXZhaWxhYmxlJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJCgnLm9yZGVyLXN1bW1hcnktZm9vdGVyIC5zdWJtaXQtb3JkZXIgLmJ1dHRvbi1mYW5jeS1sYXJnZScpLmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaW5pdFJvdW5kVXBEb25hdGlvbnMoKTtcbiAgICBcbiAgICAkKCcuanMtc3VibWl0LW9yZGVyJykub2ZmKCdjbGljay5zdWJtaXQtb3JkZXItbnMnKS5vbignY2xpY2suc3VibWl0LW9yZGVyLW5zJywgZnVuY3Rpb24oZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgJCh0aGlzKS5wcm9wKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAkKHRoaXMpLmNsb3Nlc3QoJ2Zvcm0uc3VibWl0LW9yZGVyJykuc3VibWl0KCk7XG4gICAgfSk7XG4gICAgXG4gICAgJCgnLmpzLXN1Ym1pdC1vcmRlcicpLmRibGNsaWNrKGZhbHNlKTtcbn07XG5cbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZHJlc3MgPSByZXF1aXJlKCcuL2FkZHJlc3MnKSxcbiAgICBmb3JtUHJlcGFyZSA9IHJlcXVpcmUoJy4vZm9ybVByZXBhcmUnKSxcbiAgICBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpLFxuICAgIHZhbGlkYXRvciA9IHJlcXVpcmUoJy4uLy4uL3ZhbGlkYXRvcicpO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIGdpZnQgbWVzc2FnZSBib3ggZm9yIG11bHRpc2hpcCBzaGlwcGluZywgdGhlIG1lc3NhZ2UgYm94IHN0YXJ0cyBvZmYgYXMgaGlkZGVuIGFuZCB0aGlzIHdpbGwgZGlzcGxheSBpdCBpZiB0aGUgcmFkaW8gYnV0dG9uIGlzIGNoZWNrZWQgdG8geWVzLCBhbHNvIGFkZGVkIGV2ZW50IGhhbmRsZXIgdG8gbGlzdGVuIGZvciB3aGVuIGEgcmFkaW8gYnV0dG9uIGlzIHByZXNzZWQgdG8gZGlzcGxheSB0aGUgbWVzc2FnZSBib3hcbiAqL1xuZnVuY3Rpb24gaW5pdE11bHRpR2lmdE1lc3NhZ2VCb3goKSB7XG4gICAgJC5lYWNoKCQoJy5pdGVtLWxpc3QnKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICB2YXIgJGdpZnRNZXNzYWdlID0gJHRoaXMuZmluZCgnLmdpZnQtbWVzc2FnZS10ZXh0Jyk7XG5cbiAgICAgICAgLy9oYW5kbGUgaW5pdGlhbCBsb2FkXG4gICAgICAgICRnaWZ0TWVzc2FnZS50b2dnbGVDbGFzcygnaGlkZGVuJywgJCgnaW5wdXRbbmFtZSQ9XCJfaXNHaWZ0XCJdOmNoZWNrZWQnLCB0aGlzKS52YWwoKSAhPT0gJ3RydWUnKTtcblxuICAgICAgICAvL3NldCBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgJHRoaXMub24oJ2NoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRnaWZ0TWVzc2FnZS50b2dnbGVDbGFzcygnaGlkZGVuJywgJCgnaW5wdXRbbmFtZSQ9XCJfaXNHaWZ0XCJdOmNoZWNrZWQnLCB0aGlzKS52YWwoKSAhPT0gJ3RydWUnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBjYXB0dXJlIGFkZCBlZGl0IGFkZGRyZXNzIGZvcm0gZXZlbnRzXG4gKi9cbmZ1bmN0aW9uIGFkZEVkaXRBZGRyZXNzKHRhcmdldCkge1xuICAgIHZhciAkYWRkcmVzc0Zvcm0gPSAkKCdmb3JtW25hbWUkPVwibXVsdGlzaGlwcGluZ19lZGl0QWRkcmVzc1wiXScpLFxuICAgICAgICAkYWRkcmVzc0Ryb3Bkb3duID0gJGFkZHJlc3NGb3JtLmZpbmQoJ3NlbGVjdFtuYW1lJD1fYWRkcmVzc0xpc3RdJyksXG4gICAgICAgICRhZGRyZXNzTGlzdCA9ICRhZGRyZXNzRm9ybS5maW5kKCcuYWRkcmVzcy1saXN0JyksXG4gICAgICAgIGFkZCA9IHRydWUsXG4gICAgICAgIG9yaWdpbmFsVVVJRCxcbiAgICAgICAgcmVzZXRPcHRpb25WYWx1ZSA9IGZhbHNlLFxuICAgICAgICBzZWxlY3RlZEFkZHJlc3NVVUlEID0gJCh0YXJnZXQpLnBhcmVudCgpLnNpYmxpbmdzKCcuc2VsZWN0LWFkZHJlc3MnKS52YWwoKTtcblxuICAgICRhZGRyZXNzRHJvcGRvd24ub24oJ2NoYW5nZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB2YXIgc2VsZWN0ZWRBZGRyZXNzID0gJGFkZHJlc3NMaXN0LmZpbmQoJ3NlbGVjdCcpLnZhbCgpO1xuICAgICAgICBpZiAoc2VsZWN0ZWRBZGRyZXNzICE9PSAnbmV3QWRkcmVzcycpIHtcbiAgICAgICAgICAgIHNlbGVjdGVkQWRkcmVzcyA9ICQuZ3JlcCgkYWRkcmVzc0xpc3QuZGF0YSgnYWRkcmVzc2VzJyksIGZ1bmN0aW9uIChhZGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWRkLlVVSUQgPT09IHNlbGVjdGVkQWRkcmVzcztcbiAgICAgICAgICAgIH0pWzBdO1xuICAgICAgICAgICAgYWRkID0gZmFsc2U7XG4gICAgICAgICAgICByZXNldE9wdGlvblZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBwcm9jZWVkIHRvIGZpbGwgdGhlIGZvcm0gd2l0aCB0aGUgc2VsZWN0ZWQgYWRkcmVzc1xuICAgICAgICAgICAgdXRpbC5maWxsQWRkcmVzc0ZpZWxkcyhzZWxlY3RlZEFkZHJlc3MsICRhZGRyZXNzRm9ybSk7XG4gICAgICAgIH0gZWxzZSBpZiAgKHNlbGVjdGVkQWRkcmVzcyA9PT0gJ25ld0FkZHJlc3MnKSB7XG4gICAgICAgICAgICBhZGQgPSB0cnVlO1xuICAgICAgICAgICAgcmVzZXRPcHRpb25WYWx1ZSA9IHRydWU7XG4gICAgICAgICAgICAkYWRkcmVzc0Zvcm0uZmluZCgnLmlucHV0LXRleHQsIC5pbnB1dC1zZWxlY3QnKS52YWwoJycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9yZXNldCB0aGUgZm9ybSBpZiB0aGUgdmFsdWUgb2YgdGhlIG9wdGlvbiBpcyBub3QgYSBVVUlEXG4gICAgICAgICAgICAkYWRkcmVzc0Zvcm0uZmluZCgnLmlucHV0LXRleHQsIC5pbnB1dC1zZWxlY3QnKS52YWwoJycpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAkYWRkcmVzc0Zvcm0ub24oJ2NsaWNrJywgJy5jYW5jZWwnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgJGFkZHJlc3NGb3JtLm9uKCdzdWJtaXQnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmICghJGFkZHJlc3NGb3JtLnZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgICQuZ2V0SlNPTihVcmxzLmFkZEVkaXRBZGRyZXNzLCAkYWRkcmVzc0Zvcm0uc2VyaWFsaXplKCksIGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgJCgnI211bHRpYWRkcmVzc2Vycm9yJykuaHRtbChSZXNvdXJjZXMuQ09VTERfTk9UX1NBVkVfQUREUkVTUyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJCgnI211bHRpYWRkcmVzc2Vycm9yJykudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsIHJlc3BvbnNlLnN1Y2Nlc3MpO1xuXG4gICAgICAgICAgICB2YXIgYWRkcmVzcyA9IHJlc3BvbnNlLmFkZHJlc3MsXG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nQWRkcmVzcyA9ICQodGFyZ2V0KS5jbG9zZXN0KCcuc2hpcHBpbmdhZGRyZXNzJyksXG4gICAgICAgICAgICAgICAgJHNlbGVjdCA9ICRzaGlwcGluZ0FkZHJlc3MuZmluZCgnLnNlbGVjdC1hZGRyZXNzJyksXG4gICAgICAgICAgICAgICAgJHNlbGVjdGVkID0gJHNlbGVjdC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKSxcbiAgICAgICAgICAgICAgICBuZXdPcHRpb24gPSAnPG9wdGlvbiB2YWx1ZT1cIicgKyBhZGRyZXNzLlVVSUQgKyAnXCI+JyArXG4gICAgICAgICAgICAgICAgICAgICgoYWRkcmVzcy5JRCkgPyAnKCcgKyBhZGRyZXNzLklEICsgJyknIDogYWRkcmVzcy5maXJzdE5hbWUgKyAnICcgKyBhZGRyZXNzLmxhc3ROYW1lKSArICcsICcgK1xuICAgICAgICAgICAgICAgICAgICBhZGRyZXNzLmFkZHJlc3MxICsgJywgJyArIGFkZHJlc3MuY2l0eSArICcsICcgKyBhZGRyZXNzLnN0YXRlQ29kZSArICcsICcgKyBhZGRyZXNzLnBvc3RhbENvZGUgK1xuICAgICAgICAgICAgICAgICAgICAnPC9vcHRpb24+JztcbiAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuXG4gICAgICAgICAgICBpZiAoYWRkcmVzcy5VVUlEICE9PSBvcmlnaW5hbFVVSUQpIHtcbiAgICAgICAgICAgICAgICByZXNldE9wdGlvblZhbHVlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFkZCkge1xuICAgICAgICAgICAgICAgICQoJy5zaGlwcGluZ2FkZHJlc3Mgc2VsZWN0JykucmVtb3ZlQ2xhc3MoJ25vLW9wdGlvbicpLmFwcGVuZChuZXdPcHRpb24pO1xuICAgICAgICAgICAgICAgICQoJy5uby1hZGRyZXNzJykuaGlkZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKCcuc2hpcHBpbmdhZGRyZXNzIHNlbGVjdCcpLmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBhZGRyZXNzLlVVSUQgKyAnXCJdJykuaHRtbChuZXdPcHRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgdGhlcmUncyBubyBwcmV2aW91c2x5IHNlbGVjdGVkIG9wdGlvbiwgc2VsZWN0IGl0XG4gICAgICAgICAgICBpZiAoJHNlbGVjdGVkLmxlbmd0aCA9PT0gMCB8fCAkc2VsZWN0ZWQudmFsKCkgPT09ICcnIHx8IHJlc2V0T3B0aW9uVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAkc2VsZWN0LmZpbmQoJ29wdGlvblt2YWx1ZT1cIicgKyBhZGRyZXNzLlVVSUQgKyAnXCJdJykucHJvcCgnc2VsZWN0ZWQnLCAnc2VsZWN0ZWQnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvL3ByZXNlcnZlIHRoZSB1dWlkIG9mIHRoZSBvcHRpb24gZm9yIHRoZSBob3AgdXAgZm9ybVxuICAgIGlmIChzZWxlY3RlZEFkZHJlc3NVVUlEKSB7XG4gICAgICAgIC8vdXBkYXRlIHRoZSBmb3JtIHdpdGggc2VsZWN0ZWQgYWRkcmVzc1xuICAgICAgICAkYWRkcmVzc0xpc3QuZmluZCgnb3B0aW9uJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvL2NoZWNrIHRoZSB2YWx1ZXMgb2YgdGhlIG9wdGlvbnNcbiAgICAgICAgICAgIGlmICgkKHRoaXMpLmF0dHIoJ3ZhbHVlJykgPT09IHNlbGVjdGVkQWRkcmVzc1VVSUQpIHtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLnByb3AoJ3NlbGVjdGVkJywgJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICAgICAgJGFkZHJlc3NEcm9wZG93bi50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIG9yaWdpbmFsVVVJRCA9IHNlbGVjdGVkQWRkcmVzc1VVSUQ7XG4gICAgfVxuXG4gICAgdmFsaWRhdG9yLmluaXQoKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBzaG93cyBnaWZ0IG1lc3NhZ2UgYm94IGluIG11bHRpc2hpcCwgYW5kIGlmIHRoZSBwYWdlIGlzIHRoZSBtdWx0aSBzaGlwcGluZyBhZGRyZXNzIHBhZ2UgaXQgd2lsbCBjYWxsIGluaXRtdWx0aXNoaXBzaGlwYWRkcmVzcygpIHRvIGluaXRpYWxpemUgdGhlIGZvcm1cbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRNdWx0aUdpZnRNZXNzYWdlQm94KCk7XG4gICAgaWYgKCQoJy5jYXJ0LXJvdyAuc2hpcHBpbmdhZGRyZXNzIC5zZWxlY3QtYWRkcmVzcycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZm9ybVByZXBhcmUuaW5pdCh7XG4gICAgICAgICAgICBjb250aW51ZVNlbGVjdG9yOiAnW25hbWUkPVwiYWRkcmVzc1NlbGVjdGlvbl9zYXZlXCJdJyxcbiAgICAgICAgICAgIGZvcm1TZWxlY3RvcjogJ1tpZCQ9XCJtdWx0aXNoaXBwaW5nX2FkZHJlc3NTZWxlY3Rpb25cIl0nXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAkKCcuZWRpdC1hZGRyZXNzJykub24oJ2NsaWNrJywgJ3NwYW4nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBkaWFsb2cub3Blbih7dXJsOiB0aGlzLmF0dHJpYnV0ZXMuaHJlZi52YWx1ZSwgIG9wdGlvbnM6IHtvcGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhZGRyZXNzLmluaXQoKTtcbiAgICAgICAgICAgIGFkZEVkaXRBZGRyZXNzKGUudGFyZ2V0KTtcbiAgICAgICAgfX19KTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XHJcblxyXG52YXIgYWpheCA9IHJlcXVpcmUoJy4uLy4uL2FqYXgnKSxcclxuICAgIGZvcm1QcmVwYXJlID0gcmVxdWlyZSgnLi9mb3JtUHJlcGFyZScpLFxyXG4gICAgcHJvZ3Jlc3MgPSByZXF1aXJlKCcuLi8uLi9wcm9ncmVzcycpLFxyXG4gICAgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKSxcclxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyksXHJcbiAgICBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKSxcclxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcclxuY29uc3QgeyB0aXRsZSB9ID0gcmVxdWlyZSgnLi4vLi4vcGFnZScpO1xyXG5cclxudmFyIHNoaXBwaW5nTWV0aG9kcztcclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZ2lmdCBtZXNzYWdlIGJveCwgaWYgc2hpcG1lbnQgaXMgZ2lmdFxyXG4gKi9cclxuZnVuY3Rpb24gZ2lmdE1lc3NhZ2VCb3goKSB7XHJcbiAgICAvLyBzaG93IGdpZnQgbWVzc2FnZSBib3gsIGlmIHNoaXBtZW50IGlzIGdpZnRcclxuICAgICQoJy5naWZ0LW1lc3NhZ2UtdGV4dCcpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nLCAkKCdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdOmNoZWNrZWQnKS52YWwoKSAhPT0gJ3RydWUnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAZGVzY3JpcHRpb24gdXBkYXRlcyB0aGUgb3JkZXIgc3VtbWFyeSBiYXNlZCBvbiBhIHBvc3NpYmx5IHJlY2FsY3VsYXRlZCBiYXNrZXQgYWZ0ZXIgYSBzaGlwcGluZyBwcm9tb3Rpb24gaGFzIGJlZW4gYXBwbGllZFxyXG4gKi9cclxuZnVuY3Rpb24gdXBkYXRlU3VtbWFyeSgpIHtcclxuICAgIHZhciAkc3VtbWFyeSA9ICQoJyNzZWNvbmRhcnkuc3VtbWFyeScpO1xyXG4gICAgLy8gaW5kaWNhdGUgcHJvZ3Jlc3NcclxuICAgIHByb2dyZXNzLnNob3coJHN1bW1hcnkpO1xyXG5cclxuICAgIC8vIGxvYWQgdGhlIHVwZGF0ZWQgc3VtbWFyeSBhcmVhXHJcbiAgICAkc3VtbWFyeS5sb2FkKFVybHMuc3VtbWFyeVJlZnJlc2hVUkwsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBoaWRlIGVkaXQgc2hpcHBpbmcgbWV0aG9kIGxpbmtcclxuICAgICAgICAkc3VtbWFyeS5mYWRlSW4oJ2Zhc3QnKTtcclxuICAgICAgICAkc3VtbWFyeS5maW5kKCcuY2hlY2tvdXQtbWluaS1jYXJ0IC5taW5pc2hpcG1lbnQgLmhlYWRlciBhJykuaGlkZSgpO1xyXG4gICAgICAgICRzdW1tYXJ5LmZpbmQoJy5vcmRlci10b3RhbHMtdGFibGUgLm9yZGVyLXNoaXBwaW5nIC5sYWJlbCBhJykuaGlkZSgpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAZnVuY3Rpb25cclxuICogQGRlc2NyaXB0aW9uIEhlbHBlciBtZXRob2Qgd2hpY2ggY29uc3RydWN0cyBhIFVSTCBmb3IgYW4gQUpBWCByZXF1ZXN0IHVzaW5nIHRoZVxyXG4gKiBlbnRlcmVkIGFkZHJlc3MgaW5mb3JtYXRpb24gYXMgVVJMIHJlcXVlc3QgcGFyYW1ldGVycy5cclxuICovXHJcbmZ1bmN0aW9uIGdldFNoaXBwaW5nTWV0aG9kVVJMKHVybCwgZXh0cmFQYXJhbXMpIHtcclxuICAgIHZhciAkZm9ybSA9ICQoJy5hZGRyZXNzJyk7XHJcbiAgICB2YXIgcGFyYW1zID0ge1xyXG4gICAgICAgIGFkZHJlc3MxOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMVwiXScpLnZhbCgpLFxyXG4gICAgICAgIGFkZHJlc3MyOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9hZGRyZXNzMlwiXScpLnZhbCgpLFxyXG4gICAgICAgIGNvdW50cnlDb2RlOiAkZm9ybS5maW5kKCdzZWxlY3RbaWQkPVwiX2NvdW50cnlcIl0nKS52YWwoKSxcclxuICAgICAgICBzdGF0ZUNvZGU6ICRmb3JtLmZpbmQoJ3NlbGVjdFtpZCQ9XCJfc3RhdGVcIl0nKS52YWwoKSxcclxuICAgICAgICBwb3N0YWxDb2RlOiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9wb3N0YWxcIl0nKS52YWwoKSxcclxuICAgICAgICBjaXR5OiAkZm9ybS5maW5kKCdpbnB1dFtuYW1lJD1cIl9jaXR5XCJdJykudmFsKClcclxuICAgIH07XHJcbiAgICByZXR1cm4gdXRpbC5hcHBlbmRQYXJhbXNUb1VybCh1cmwsICQuZXh0ZW5kKHBhcmFtcywgZXh0cmFQYXJhbXMpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAZGVzY3JpcHRpb24gc2VsZWN0cyBhIHNoaXBwaW5nIG1ldGhvZCBmb3IgdGhlIGRlZmF1bHQgc2hpcG1lbnQgYW5kIHVwZGF0ZXMgdGhlIHN1bW1hcnkgc2VjdGlvbiBvbiB0aGUgcmlnaHQgaGFuZCBzaWRlXHJcbiAqIEBwYXJhbVxyXG4gKi9cclxuZnVuY3Rpb24gc2VsZWN0U2hpcHBpbmdNZXRob2Qoc2hpcHBpbmdNZXRob2RJRCkge1xyXG4gICAgLy8gbm90aGluZyBlbnRlcmVkXHJcbiAgICBpZiAoIXNoaXBwaW5nTWV0aG9kSUQpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICAvLyBhdHRlbXB0IHRvIHNldCBzaGlwcGluZyBtZXRob2RcclxuICAgIHZhciB1cmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChVcmxzLnNlbGVjdFNoaXBwaW5nTWV0aG9kc0xpc3QsIHtzaGlwcGluZ01ldGhvZElEOiBzaGlwcGluZ01ldGhvZElEfSk7XHJcbiAgICBhamF4LmdldEpzb24oe1xyXG4gICAgICAgIHVybDogdXJsLFxyXG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoZGF0YSkge1xyXG4gICAgICAgICAgICB1cGRhdGVTdW1tYXJ5KCk7XHJcbiAgICAgICAgICAgIGlmICghZGF0YSB8fCAhZGF0YS5zaGlwcGluZ01ldGhvZElEKSB7XHJcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3Qgc2VsZWN0IHNoaXBwaW5nIG1ldGhvZC4nKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBkaXNwbGF5IHByb21vdGlvbiBpbiBVSSBhbmQgdXBkYXRlIHRoZSBzdW1tYXJ5IHNlY3Rpb24sXHJcbiAgICAgICAgICAgIC8vIGlmIHNvbWUgcHJvbW90aW9ucyB3ZXJlIGFwcGxpZWRcclxuICAgICAgICAgICAgJCgnLnNoaXBwaW5ncHJvbW90aW9ucycpLmVtcHR5KCk7XHJcblxyXG4gICAgICAgICAgICAvLyBUT0RPIHRoZSBmb3IgbG9vcCBiZWxvdyBpc24ndCBkb2luZyBhbnl0aGluZz9cclxuICAgICAgICAgICAgLy8gaWYgKGRhdGEuc2hpcHBpbmdQcmljZUFkanVzdG1lbnRzICYmIGRhdGEuc2hpcHBpbmdQcmljZUFkanVzdG1lbnRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgLy8gICAgIHZhciBsZW4gPSBkYXRhLnNoaXBwaW5nUHJpY2VBZGp1c3RtZW50cy5sZW5ndGg7XHJcbiAgICAgICAgICAgIC8vICAgICBmb3IgKHZhciBpPTA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIHZhciBzcGEgPSBkYXRhLnNoaXBwaW5nUHJpY2VBZGp1c3RtZW50c1tpXTtcclxuICAgICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgICAgLy8gfVxyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBkZXNjcmlwdGlvbiBNYWtlIGFuIEFKQVggcmVxdWVzdCB0byB0aGUgc2VydmVyIHRvIHJldHJpZXZlIHRoZSBsaXN0IG9mIGFwcGxpY2FibGUgc2hpcHBpbmcgbWV0aG9kc1xyXG4gKiBiYXNlZCBvbiB0aGUgbWVyY2hhbmRpc2UgaW4gdGhlIGNhcnQgYW5kIHRoZSBjdXJyZW50bHkgZW50ZXJlZCBzaGlwcGluZyBhZGRyZXNzXHJcbiAqICh0aGUgYWRkcmVzcyBtYXkgYmUgb25seSBwYXJ0aWFsbHkgZW50ZXJlZCkuICBJZiB0aGUgbGlzdCBvZiBhcHBsaWNhYmxlIHNoaXBwaW5nIG1ldGhvZHNcclxuICogaGFzIGNoYW5nZWQgYmVjYXVzZSBuZXcgYWRkcmVzcyBpbmZvcm1hdGlvbiBoYXMgYmVlbiBlbnRlcmVkLCB0aGVuIGlzc3VlIGFub3RoZXIgQUpBWFxyXG4gKiByZXF1ZXN0IHdoaWNoIHVwZGF0ZXMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzaGlwcGluZyBtZXRob2QgKGlmIG5lZWRlZCkgYW5kIGFsc28gdXBkYXRlc1xyXG4gKiB0aGUgVUkuXHJcbiAqL1xyXG5mdW5jdGlvbiB1cGRhdGVTaGlwcGluZ01ldGhvZExpc3QoKSB7XHJcbiAgICB2YXIgJHNoaXBwaW5nTWV0aG9kTGlzdCA9ICQoJyNzaGlwcGluZy1tZXRob2QtbGlzdCcpO1xyXG4gICAgaWYgKCEkc2hpcHBpbmdNZXRob2RMaXN0IHx8ICRzaGlwcGluZ01ldGhvZExpc3QubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxyXG4gICAgdmFyIHVybCA9IGdldFNoaXBwaW5nTWV0aG9kVVJMKFVybHMuc2hpcHBpbmdNZXRob2RzSlNPTik7XHJcblxyXG4gICAgYWpheC5nZXRKc29uKHtcclxuICAgICAgICB1cmw6IHVybCxcclxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XHJcbiAgICAgICAgICAgICAgICB3aW5kb3cuYWxlcnQoJ0NvdWxkblxcJ3QgZ2V0IGxpc3Qgb2YgYXBwbGljYWJsZSBzaGlwcGluZyBtZXRob2RzLicpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChzaGlwcGluZ01ldGhvZHMgJiYgc2hpcHBpbmdNZXRob2RzLnRvU3RyaW5nKCkgPT09IGRhdGEudG9TdHJpbmcoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gTm8gbmVlZCB0byB1cGRhdGUgdGhlIFVJLiAgVGhlIGxpc3QgaGFzIG5vdCBjaGFuZ2VkLlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gdXBkYXRlIHRoZSBVSS4gIFRoZSBsaXN0IGhhcyBjaGFuZ2VkLlxyXG4gICAgICAgICAgICAvLyBDYWNoZSB0aGUgYXJyYXkgb2YgcmV0dXJuZWQgc2hpcHBpbmcgbWV0aG9kcy5cclxuICAgICAgICAgICAgc2hpcHBpbmdNZXRob2RzID0gZGF0YTtcclxuICAgICAgICAgICAgLy8gaW5kaWNhdGUgcHJvZ3Jlc3NcclxuICAgICAgICAgICAgcHJvZ3Jlc3Muc2hvdygkc2hpcHBpbmdNZXRob2RMaXN0KTtcclxuXHJcbiAgICAgICAgICAgIC8vIGxvYWQgdGhlIHNoaXBwaW5nIG1ldGhvZCBmb3JtXHJcbiAgICAgICAgICAgIHZhciBzbWxVcmwgPSBnZXRTaGlwcGluZ01ldGhvZFVSTChVcmxzLnNoaXBwaW5nTWV0aG9kc0xpc3QpO1xyXG4gICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmxvYWQoc21sVXJsLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAkc2hpcHBpbmdNZXRob2RMaXN0LmZhZGVJbignZmFzdCcpO1xyXG4gICAgICAgICAgICAgICAgLy8gcmViaW5kIHRoZSByYWRpbyBidXR0b25zIG9uY2xpY2sgZnVuY3Rpb24gdG8gYSBoYW5kbGVyLlxyXG4gICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCdbbmFtZSQ9XCJfc2hpcHBpbmdNZXRob2RJRFwiXScpLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RTaGlwcGluZ01ldGhvZCgkKHRoaXMpLnZhbCgpKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgc3VtbWFyeVxyXG4gICAgICAgICAgICAgICAgdXBkYXRlU3VtbWFyeSgpO1xyXG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgdG9vbHRpcC5pbml0KCk7XHJcbiAgICAgICAgICAgICAgICAvL2lmIG5vdGhpbmcgaXMgc2VsZWN0ZWQgaW4gdGhlIHNoaXBwaW5nIG1ldGhvZHMgc2VsZWN0IHRoZSBmaXJzdCBvbmVcclxuICAgICAgICAgICAgICAgIGlmICgkc2hpcHBpbmdNZXRob2RMaXN0LmZpbmQoJy5pbnB1dC1yYWRpbzpjaGVja2VkJykubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJHNoaXBwaW5nTWV0aG9kTGlzdC5maW5kKCcuaW5wdXQtcmFkaW86Zmlyc3QnKS5wcm9wKCdjaGVja2VkJywgJ2NoZWNrZWQnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbn1cclxuXHJcbnZhciBsb3FhdGVIZWxwZXIgPSB7XHJcbiAgIFxyXG4gICAgb3B0aW9ucyA6IHtcclxuICAgICAgICBrZXk6IFNpdGVQcmVmZXJlbmNlcy5MT1FBVEVfS0VZLFxyXG4gICAgICAgIG1hbnVhbEVudHJ5SXRlbTogdHJ1ZSwgXHJcbiAgICAgICAgc2V0Q291bnRyeUJ5SVA6IGZhbHNlXHJcbiAgICB9LFxyXG4gICAgXHJcbiAgICBpbml0IDogZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgdmFyIHNlcnZpY2VBdmFpbGFibGUgPSB0aGlzLmNoZWNrU2VydmljZUF2YWlsYWJpbGl0eSgpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgICBcclxuICAgICAgICBpZiAoIXNlcnZpY2VBdmFpbGFibGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xyXG4gICAgICAgICQoJ1tuYW1lKj1fYmlsbGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMV0nKS5vbignZm9jdXMnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIF90aGlzLmluaXRPbkJpbGxpbmdBZGRyZXNzKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgJCgnW25hbWUqPV9zaGlwcGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMV0nKS5vbignZm9jdXMnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIF90aGlzLmluaXRPblNoaXBwaW5nQWRkcmVzcygpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIF90aGlzLmluaXRPblNoaXBwaW5nQWRkcmVzcygpO1xyXG4gICAgfSxcclxuICAgIFxyXG4gICAgaW5pdEJpbGxpbmdBZGRyZXNzRXZlbnQgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIHNlcnZpY2VBdmFpbGFibGUgPSB0aGlzLmNoZWNrU2VydmljZUF2YWlsYWJpbGl0eSgpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmICghc2VydmljZUF2YWlsYWJsZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XHJcbiAgICAgICAgJCgnW25hbWUqPV9iaWxsaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MxXScpLm9uKCdmb2N1cycsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgX3RoaXMuaW5pdE9uQmlsbGluZ0FkZHJlc3MoKTtcclxuICAgICAgICB9KTtcclxuICAgIH0sXHJcbiAgICBcclxuICAgIGluaXRPbkJpbGxpbmdBZGRyZXNzIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIFxyXG4gICAgICAgIHZhciAkYmlsbGluZ0NvdW50eSA9ICQoJ1tuYW1lKj1fYmlsbGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19jb3VudHJpZXNdJyk7XHJcbiAgICAgICAgdmFyIHNlcnZpY2VBdmFpbGFibGUgPSB0aGlzLmNoZWNrU2VydmljZUF2YWlsYWJpbGl0eSgpO1xyXG4gICAgICAgIGlmICghc2VydmljZUF2YWlsYWJsZSB8fCAhJGJpbGxpbmdDb3VudHkubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXRlRWxlbWVudFNlbGVjdG9yID0gJ1tuYW1lKj1fYmlsbGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19zdGF0ZXNdJztcclxuICAgICAgICB2YXIgYmlsbGluZ1N0YXRlID0gJCgnW25hbWUqPV9iaWxsaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX3N0YXRlc10nKTtcclxuICAgICAgICBcclxuICAgICAgICB2YXIgYmlsbGluZ0NvdW50cnkgPSAkYmlsbGluZ0NvdW50eS52YWwoKTtcclxuICAgICAgICB2YXIgYmlsbGluZ0ZpZWxkcyA9IFtcclxuICAgICAgICAgICAgICB7ZWxlbWVudDogXCJfYmlsbGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMVwiLCBmaWVsZDogXCJMaW5lMVwiIH0sXHJcbiAgICAgICAgICAgICAge2VsZW1lbnQ6IFwiX2JpbGxpbmdBZGRyZXNzX2FkZHJlc3NGaWVsZHNfYWRkcmVzczJcIiwgZmllbGQ6IFwiTGluZTJcIiwgbW9kZTogcGNhLmZpZWxkTW9kZS5QT1BVTEFURSB9LFxyXG4gICAgICAgICAgICAgIHtlbGVtZW50OiBcIl9iaWxsaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2NpdHlcIiwgZmllbGQ6IFwiQ2l0eVwiLCBtb2RlOiBwY2EuZmllbGRNb2RlLlBPUFVMQVRFIH0sXHJcbiAgICAgICAgICAgICAge2VsZW1lbnQ6IFwiX2JpbGxpbmdBZGRyZXNzX2FkZHJlc3NGaWVsZHNfcG9zdGFsXCIsIGZpZWxkOiBcIlBvc3RhbENvZGVcIiwgbW9kZTogcGNhLmZpZWxkTW9kZS5QT1BVTEFURX1cclxuICAgICAgICBdO1xyXG4gICAgICAgIGlmIChiaWxsaW5nU3RhdGUubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIGJpbGxpbmdGaWVsZHMucHVzaCh7ZWxlbWVudDogYmlsbGluZ1N0YXRlLmF0dHIoJ25hbWUnKSwgZmllbGQ6IFwiUHJvdmluY2VOYW1lXCIsIG1vZGU6IHBjYS5maWVsZE1vZGUuUE9QVUxBVEUgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIHZhciBiaWxsaW5nT3B0aW9ucyA9IHRoaXMub3B0aW9ucztcclxuICAgICAgICBiaWxsaW5nT3B0aW9ucy5zZWFyY2ggPSB7Y291bnRyaWVzOiBiaWxsaW5nQ291bnRyeS50b1VwcGVyQ2FzZSgpfTtcclxuICAgICAgICBcclxuICAgICAgICB0aGlzLmJpbGxpbmdDb250cm9sID0gbmV3IHBjYS5BZGRyZXNzKGJpbGxpbmdGaWVsZHMsIGJpbGxpbmdPcHRpb25zKTtcclxuICAgICAgICBcclxuICAgICAgICB0aGlzLl9hZGRDdXN0b21FdmVudHMoXHJcbiAgICAgICAgICAgIHRoaXMuYmlsbGluZ0NvbnRyb2wsXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICdjb3VudHJ5JyA6IGJpbGxpbmdDb3VudHJ5LFxyXG4gICAgICAgICAgICAgICAgJ3N0YXRlRWxlbWVudFNlbGVjdG9yJyA6IHN0YXRlRWxlbWVudFNlbGVjdG9yLFxyXG4gICAgICAgICAgICAgICAgJ3Bvc3RhbEVsZW1lbnRTZWxlY3RvcicgOiBcIltuYW1lJD0nX2JpbGxpbmdBZGRyZXNzX2FkZHJlc3NGaWVsZHNfcG9zdGFsJ11cIixcclxuICAgICAgICAgICAgICAgICdiaWxsaW5nJyA6IHRydWVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICB9LFxyXG4gICAgXHJcbiAgICBpbml0T25TaGlwcGluZ0FkZHJlc3MgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyICRzaGlwcGluZ0NvdW50cnkgPSAgJChcIltuYW1lJD0nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2NvdW50cnknXVwiKTtcclxuICAgICAgICB2YXIgc2VydmljZUF2YWlsYWJsZSA9IHRoaXMuY2hlY2tTZXJ2aWNlQXZhaWxhYmlsaXR5KCk7XHJcbiAgICAgICAgaWYgKCFzZXJ2aWNlQXZhaWxhYmxlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXRlRWxlbWVudFNlbGVjdG9yID0gXCJbbmFtZSQ9J19zaGlwcGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19zdGF0ZXNfc3RhdGUnXVwiO1xyXG4gICAgICAgIHZhciBzaGlwcGluZ1N0YXRlID0gJChzdGF0ZUVsZW1lbnRTZWxlY3Rvcik7XHJcbiAgICAgICAgXHJcbiAgICAgICAgdmFyIHNoaXBwaW5nQ291bnRyeSA9ICRzaGlwcGluZ0NvdW50cnkudmFsKCk7XHJcbiAgICAgICAgdmFyIHNoaXBwaW5nRmllbGRzID0gW1xyXG4gICAgICAgICAgICAgIHtlbGVtZW50OiBcIl9zaGlwcGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19hZGRyZXNzMVwiLCBmaWVsZDogXCJMaW5lMVwiIH0sXHJcbiAgICAgICAgICAgICAge2VsZW1lbnQ6IFwiX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MyXCIsIGZpZWxkOiBcIkxpbmUyXCIvKiwgbW9kZTogcGNhLmZpZWxkTW9kZS5QT1BVTEFURSAqL30sXHJcbiAgICAgICAgICAgICAge2VsZW1lbnQ6IFwiX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2NpdHlcIiwgZmllbGQ6IFwiQ2l0eVwiLyosIG1vZGU6IHBjYS5maWVsZE1vZGUuUE9QVUxBVEUgKi99LFxyXG4gICAgICAgICAgICAgIHtlbGVtZW50OiBcIl9zaGlwcGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19wb3N0YWxcIiwgZmllbGQ6IFwiUG9zdGFsQ29kZVwiLyosIG1vZGU6IHBjYS5maWVsZE1vZGUuUE9QVUxBVEUqL31cclxuICAgICAgICBdO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmIChzaGlwcGluZ1N0YXRlLmxlbmd0aCkge1xyXG4gICAgICAgICAgICBzaGlwcGluZ0ZpZWxkcy5wdXNoKHtlbGVtZW50OiBcIl9zaGlwcGluZ0FkZHJlc3NfYWRkcmVzc0ZpZWxkc19zdGF0ZXNfc3RhdGVcIiwgZmllbGQ6IFwiUHJvdmluY2VDb2RlXCIvKiwgbW9kZTogcGNhLmZpZWxkTW9kZS5QT1BVTEFURSAqL30pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIHNoaXBwaW5nT3B0aW9ucyA9IHRoaXMub3B0aW9ucztcclxuICAgICAgICBzaGlwcGluZ09wdGlvbnMuc2VhcmNoID0ge2NvdW50cmllczogc2hpcHBpbmdDb3VudHJ5LnRvVXBwZXJDYXNlKCl9O1xyXG4gICAgICAgIHRoaXMuc2hpcHBpbmdDb250cm9sID0gbmV3IHBjYS5BZGRyZXNzKHNoaXBwaW5nRmllbGRzLCBzaGlwcGluZ09wdGlvbnMpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHRoaXMuX2FkZEN1c3RvbUV2ZW50cyhcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hpcHBpbmdDb250cm9sLFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgICdjb3VudHJ5JyA6IHNoaXBwaW5nQ291bnRyeSxcclxuICAgICAgICAgICAgICAgICAgICAnc3RhdGVFbGVtZW50U2VsZWN0b3InIDogc3RhdGVFbGVtZW50U2VsZWN0b3IsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3Bvc3RhbEVsZW1lbnRTZWxlY3RvcicgOiBcIltuYW1lJD0nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX3Bvc3RhbCddXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3NoaXBwaW5nJyA6IHRydWVcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICBcclxuICAgIH0sXHJcbiAgICBcclxuICAgIGluaXRPblByb2ZpbGVBZGRyZXNzIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciAkcHJvZmlsZUNvdW50cnkgPSAgJChcIltuYW1lKj1fcHJvZmlsZV9hZGRyZXNzX2NvdW50cmllc11cIik7XHJcbiAgICAgICAgdmFyIHNlcnZpY2VBdmFpbGFibGUgPSB0aGlzLmNoZWNrU2VydmljZUF2YWlsYWJpbGl0eSgpO1xyXG4gICAgICAgIGlmICghc2VydmljZUF2YWlsYWJsZSB8fCAhJHByb2ZpbGVDb3VudHJ5Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdGF0ZUVsZW1lbnRTZWxlY3RvciA9ICdbbmFtZSo9X3Byb2ZpbGVfYWRkcmVzc19zdGF0ZXNdJztcclxuICAgICAgICB2YXIgJHByb2ZpbGVTdGF0ZSA9ICQoc3RhdGVFbGVtZW50U2VsZWN0b3IpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHZhciBwcm9maWxlQ291bnRyeSA9ICRwcm9maWxlQ291bnRyeS52YWwoKTtcclxuICAgICAgICB2YXIgcHJvZmlsZUZpZWxkcyA9IFtcclxuICAgICAgICAgICAgICB7ZWxlbWVudDogXCJfcHJvZmlsZV9hZGRyZXNzX2FkZHJlc3MxXCIsIGZpZWxkOiBcIkxpbmUxXCIgfSxcclxuICAgICAgICAgICAgICB7ZWxlbWVudDogXCJfcHJvZmlsZV9hZGRyZXNzX2FkZHJlc3MyXCIsIGZpZWxkOiBcIkxpbmUyXCIsIG1vZGU6IHBjYS5maWVsZE1vZGUuUE9QVUxBVEUgfSxcclxuICAgICAgICAgICAgICB7ZWxlbWVudDogXCJfcHJvZmlsZV9hZGRyZXNzX2NpdHlcIiwgZmllbGQ6IFwiQ2l0eVwiLCBtb2RlOiBwY2EuZmllbGRNb2RlLlBPUFVMQVRFIH0sXHJcbiAgICAgICAgICAgICAge2VsZW1lbnQ6IFwiX3Byb2ZpbGVfYWRkcmVzc19wb3N0YWxcIiwgZmllbGQ6IFwiUG9zdGFsQ29kZVwiLCBtb2RlOiBwY2EuZmllbGRNb2RlLlBPUFVMQVRFfVxyXG4gICAgICAgIF07XHJcbiAgICAgICAgXHJcbiAgICAgICAgaWYgKCRwcm9maWxlU3RhdGUubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHByb2ZpbGVGaWVsZHMucHVzaCh7ZWxlbWVudDogJHByb2ZpbGVTdGF0ZS5hdHRyKCduYW1lJyksIGZpZWxkOiBcIlByb3ZpbmNlTmFtZVwiLCBtb2RlOiBwY2EuZmllbGRNb2RlLlBPUFVMQVRFIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIHByb2ZpbGVPcHRpb25zID0gdGhpcy5vcHRpb25zO1xyXG4gICAgICAgIHByb2ZpbGVPcHRpb25zLnNlYXJjaCA9IHtjb3VudHJpZXM6IHByb2ZpbGVDb3VudHJ5LnRvVXBwZXJDYXNlKCl9O1xyXG4gICAgICAgXHJcbiAgICAgICAgdGhpcy5wcm9maWxlQ29udHJvbCA9IG5ldyBwY2EuQWRkcmVzcyhwcm9maWxlRmllbGRzLCBwcm9maWxlT3B0aW9ucyk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgdGhpcy5fYWRkQ3VzdG9tRXZlbnRzKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5wcm9maWxlQ29udHJvbCxcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICAnY291bnRyeScgOiBwcm9maWxlQ291bnRyeSxcclxuICAgICAgICAgICAgICAgICAgICAnc3RhdGVFbGVtZW50U2VsZWN0b3InIDogc3RhdGVFbGVtZW50U2VsZWN0b3IsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3Bvc3RhbEVsZW1lbnRTZWxlY3RvcicgOiBcIltuYW1lJD0nX3Byb2ZpbGVfYWRkcmVzc19wb3N0YWwnXVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICdwcm9maWxlJyA6IHRydWVcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICBcclxuICAgIH0sXHJcbiAgICBcclxuICAgIGNoZWNrU2VydmljZUF2YWlsYWJpbGl0eSA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBpZiAodHlwZW9mIHBjYSA9PT0gJ3VuZGVmaW5lZCcgfHwgIXBjYSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSxcclxuICAgXHJcbiAgICBfYWRkQ3VzdG9tRXZlbnRzIDogZnVuY3Rpb24gKGNvbnRyb2wsIGNvbmZpZykge1xyXG4gICAgICAgaWYgKCFjb250cm9sKSB7XHJcbiAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgfVxyXG4gICAgICAgXHJcbiAgICAgICBjb250cm9sLmxpc3RlbihcInBvcHVsYXRlXCIsIGZ1bmN0aW9uKGFkZHJlc3MpIHtcclxuICAgICAgICAgICAvLyBwb3B1bGF0ZSBHQiBjb3VudHkgd2l0aCBBZG1pbkFyZWFOYW1lIGRhdGEgaWYgaXQgaXMgbm90IHBvcHVsYXRlZCB5ZXQgXHJcbiAgICAgICAgICAgaWYgKGNvbmZpZy5jb3VudHJ5LnRvTG93ZXJDYXNlKCkgPT09ICdnYicpIHtcclxuICAgICAgICAgICAgICAgdmFyICRwcm92aW5jZSA9ICQoY29uZmlnLnN0YXRlRWxlbWVudFNlbGVjdG9yKTtcclxuICAgICAgICAgICAgICAgdmFyIHByb3ZpbmNlID0gYWRkcmVzcy5Qcm92aW5jZTtcclxuICAgICAgICAgICAgICAgdmFyIGFkbWluQXJlYU5hbWUgPSBhZGRyZXNzLkFkbWluQXJlYU5hbWU7XHJcblxyXG4gICAgICAgICAgICAgICB2YXIgcHJvdmljZU5hbWVPcHRpb25WYWwgPSBnZXRPcHRpb25XaXRoVGV4dFZhbHVlKGNvbmZpZy5zdGF0ZUVsZW1lbnRTZWxlY3RvciwgcHJvdmluY2UpO1xyXG4gICAgICAgICAgICAgICB2YXIgYWRtaW5BcmVhTmFtZU9wdGlvblZhbCA9IGdldE9wdGlvbldpdGhUZXh0VmFsdWUoY29uZmlnLnN0YXRlRWxlbWVudFNlbGVjdG9yLCBhZG1pbkFyZWFOYW1lKTtcclxuICAgICAgICAgICAgICAgaWYgKHByb3ZpY2VOYW1lT3B0aW9uVmFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAkcHJvdmluY2UudmFsKHByb3ZpY2VOYW1lT3B0aW9uVmFsKTtcclxuICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhZG1pbkFyZWFOYW1lT3B0aW9uVmFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAkcHJvdmluY2UudmFsKGFkbWluQXJlYU5hbWVPcHRpb25WYWwpO1xyXG4gICAgICAgICAgICAgICB9IGVsc2UgaWYgKCQoY29uZmlnLnN0YXRlRWxlbWVudFNlbGVjdG9yICsgJyBvcHRpb25bdmFsdWU9XCInICtwcm92aW5jZSsgJ1wiXScpLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgJHByb3ZpbmNlLnZhbChwcm92aW5jZSk7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICB9XHJcbiAgICAgICAgICAgLy8gYXV0byBwb3B1bGF0ZSBQb3N0YWwgY29kZSBmb3IgdGhlIEhvbmcgS29uZyBcclxuICAgICAgICAgICBpZiAoY29uZmlnLmNvdW50cnkudG9Mb3dlckNhc2UoKSA9PT0gJ2hrJykge1xyXG4gICAgICAgICAgICAgICB2YXIgJHBvc3RhbCA9ICQoY29uZmlnLnBvc3RhbEVsZW1lbnRTZWxlY3Rvcik7XHJcbiAgICAgICAgICAgICAgIGlmICgkcG9zdGFsLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgJHBvc3RhbC52YWwoU2l0ZVByZWZlcmVuY2VzLkhPTkdfS09OR19ERUZBVUxUX1BPU1RBTCk7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgIGlmIChjb25maWcuc2hpcHBpbmcpIHtcclxuICAgICAgICAgICAgICAgJChcIltuYW1lJD0nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MxJ11cIikudHJpZ2dlcignc2hpcHBpbmctYWRkcmVzcy1wb3B1bGF0ZWQnKTtcclxuICAgICAgICAgICB9XHJcbiAgICAgICAgICAgXHJcbiAgICAgICAgICAgaWYgKGNvbmZpZy5iaWxsaW5nKSB7XHJcbiAgICAgICAgICAgICAgICQoXCJbbmFtZSQ9J19iaWxsaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MxJ11cIikudHJpZ2dlcignYmlsbGluZy1hZGRyZXNzLXBvcHVsYXRlZCcpO1xyXG4gICAgICAgICAgIH1cclxuICAgICAgICAgICBcclxuICAgICAgICAgICBpZiAoY29uZmlnLnByb2ZpbGUpIHtcclxuICAgICAgICAgICAgICAgJChcIltuYW1lJD0nX3Byb2ZpbGVfYWRkcmVzc19hZGRyZXNzMSddXCIpLnRyaWdnZXIoJ3Byb2ZpbGUtYWRkcmVzcy1wb3B1bGF0ZWQnKTtcclxuICAgICAgICAgICB9XHJcbiAgICAgICB9KTtcclxuICAgICAgIFxyXG4gICAgICAgZnVuY3Rpb24gZ2V0T3B0aW9uV2l0aFRleHRWYWx1ZShzZWxlY3RTZWxlY3RvciwgdGV4dCkge1xyXG4gICAgICAgICAgIHZhciB2YWx1ZSA9ICcnO1xyXG4gICAgICAgICAgICQoc2VsZWN0U2VsZWN0b3IgKyAnIG9wdGlvbicpLmVhY2goZnVuY3Rpb24oKSB7ICAgIFxyXG4gICAgICAgICAgICAgICBpZigkKHRoaXMpLnRleHQoKS50b1N0cmluZygpID09PSB0ZXh0KSB7XHJcbiAgICAgICAgICAgICAgICAgICB2YWx1ZSA9ICQodGhpcykudmFsKCk7XHJcbiAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICB9KTtcclxuICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAZnVuY3Rpb25cclxuICogQGRlc2NyaXB0aW9uIGZpbHRlciBlbW9qaSBzeW1ib2xzXHJcbiAqIEBwYXJhbSBTdHJpbmdcclxuICogQHJldHVybiBTdHJpbmdcclxuICovXHJcbmZ1bmN0aW9uIGZpbHRlckVtb2ppIChzdHIpIHtcclxuICAgIHZhciByZWdleCA9IC8oPzpbXFx1MjcwMC1cXHUyN2JmXXwoPzpcXHVkODNjW1xcdWRkZTYtXFx1ZGRmZl0pezJ9fFtcXHVkODAwLVxcdWRiZmZdW1xcdWRjMDAtXFx1ZGZmZl18W1xcdTAwMjMtXFx1MDAzOV1cXHVmZTBmP1xcdTIwZTN8XFx1MzI5OXxcXHUzMjk3fFxcdTMwM2R8XFx1MzAzMHxcXHUyNGMyfFxcdWQ4M2NbXFx1ZGQ3MC1cXHVkZDcxXXxcXHVkODNjW1xcdWRkN2UtXFx1ZGQ3Zl18XFx1ZDgzY1xcdWRkOGV8XFx1ZDgzY1tcXHVkZDkxLVxcdWRkOWFdfFxcdWQ4M2NbXFx1ZGRlNi1cXHVkZGZmXXxcXHVkODNjW1xcdWRlMDEtXFx1ZGUwMl18XFx1ZDgzY1xcdWRlMWF8XFx1ZDgzY1xcdWRlMmZ8XFx1ZDgzY1tcXHVkZTMyLVxcdWRlM2FdfFxcdWQ4M2NbXFx1ZGU1MC1cXHVkZTUxXXxcXHUyMDNjfFxcdTIwNDl8W1xcdTI1YWEtXFx1MjVhYl18XFx1MjViNnxcXHUyNWMwfFtcXHUyNWZiLVxcdTI1ZmVdfFxcdTAwYTl8XFx1MDBhZXxcXHUyMTIyfFxcdTIxMzl8XFx1ZDgzY1xcdWRjMDR8W1xcdTI2MDAtXFx1MjZGRl18XFx1MmIwNXxcXHUyYjA2fFxcdTJiMDd8XFx1MmIxYnxcXHUyYjFjfFxcdTJiNTB8XFx1MmI1NXxcXHUyMzFhfFxcdTIzMWJ8XFx1MjMyOHxcXHUyM2NmfFtcXHUyM2U5LVxcdTIzZjNdfFtcXHUyM2Y4LVxcdTIzZmFdfFxcdWQ4M2NcXHVkY2NmfFxcdTI5MzR8XFx1MjkzNXxbXFx1MjE5MC1cXHUyMWZmXSkvZztcclxuICAgIHJldHVybiBzdHIucmVwbGFjZShyZWdleCwgJycpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwb3B1bGF0ZUFkcnIoKSB7XHJcblxyXG4gICAgdmFyICRzaGlwcGluRm9ybSA9ICQoJ2Zvcm0uY2hlY2tvdXQtc2hpcHBpbmcnKTtcclxuICAgIHZhciB1cmwgPSAkc2hpcHBpbkZvcm0uZGF0YSgnYXZzLXVybCcpO1xyXG4gICAgXHJcbiAgICBpZighdXJsKXtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgJC5hamF4KHtcclxuICAgICAgICB0eXBlOiBcIlBPU1RcIixcclxuICAgICAgICB1cmw6IHVybCxcclxuICAgICAgICBkYXRhOiAkc2hpcHBpbkZvcm0uc2VyaWFsaXplKCksXHJcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXNwb25zZSkge1xyXG4gICAgICAgICAgICAgICAgZGlhbG9nLm9wZW4oe1xyXG4gICAgICAgICAgICAgICAgICAgIGh0bWw6IHJlc3BvbnNlLFxyXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbW9kYWw6dHJ1ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IDU3MCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnVpLWRpYWxvZy10aXRsZWJhcicpLmhpZGUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsJyNyZWNvbV9hZGRyZXNzLCAjYnRuX3JlY29tZW5kZWQnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWRkckRhdGEgPSBKU09OLnBhcnNlKCQoJ2lucHV0W3R5cGU9cmFkaW9dW2lkPXJlY29tX2FkZHJlc3NdJykudmFsKCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoXCJpbnB1dFtuYW1lJD0nX3NpbmdsZXNoaXBwaW5nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2NpdHknXVwiKS52YWwoYWRkckRhdGEuTG9jYWxpdHkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoXCJpbnB1dFtuYW1lJD0nX3NpbmdsZXNoaXBwaW5nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX3Bvc3RhbCddXCIpLnZhbChhZGRyRGF0YS5Qb3N0YWxDb2RlUHJpbWFyeSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChcInNlbGVjdFtuYW1lJD0nX3NpbmdsZXNoaXBwaW5nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX3N0YXRlc19zdGF0ZSddXCIpLnZhbChhZGRyRGF0YS5BZG1pbmlzdHJhdGl2ZUFyZWEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoXCJpbnB1dFtuYW1lJD0nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MxJ11cIikudmFsKGFkZHJEYXRhLkRlbGl2ZXJ5QWRkcmVzczEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoXCJpbnB1dFtuYW1lJD0nX3NoaXBwaW5nQWRkcmVzc19hZGRyZXNzRmllbGRzX2FkZHJlc3MyJ11cIikudmFsKGFkZHJEYXRhLkFkZHJlc3MyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKCcjZHdmcm1fc2luZ2xlc2hpcHBpbmdfc2hpcHBpbmdBZGRyZXNzJykuZGF0YSgnYXZzLWNvbmZpcm1lZCcsMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChcImJ1dHRvbltuYW1lPSdkd2ZybV9zaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3Nfc2F2ZSddXCIpLmZpcnN0KCkudHJpZ2dlcignY2xpY2snKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsJyNidG5fZW50ZXJlZCwgI2VudGVyZWRfYWRkcmVzcycsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3MnKS5kYXRhKCdhdnMtY29uZmlybWVkJywxKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKFwiYnV0dG9uW25hbWU9J2R3ZnJtX3NpbmdsZXNoaXBwaW5nX3NoaXBwaW5nQWRkcmVzc19zYXZlJ11cIikuZmlyc3QoKS50cmlnZ2VyKCdjbGljaycpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKGVycm9yKXtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coJ0Vycm9yIEFWUyByZXF1ZXN0Jyk7IC8vIG5ldmVyIGV4cG9zZSBwdWJsaWMgZXJyb3IgIG1lc3NhZ2VzXHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgXHJcbn1cclxuXHJcbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgIGZvcm1QcmVwYXJlLmluaXQoe1xyXG4gICAgICAgIGNvbnRpbnVlU2VsZWN0b3I6ICdbbmFtZSQ9XCJzaGlwcGluZ0FkZHJlc3Nfc2F2ZVwiXScsXHJcbiAgICAgICAgZm9ybVNlbGVjdG9yOidbaWQkPVwic2luZ2xlc2hpcHBpbmdfc2hpcHBpbmdBZGRyZXNzXCJdJ1xyXG4gICAgfSk7XHJcbiAgICAkKCdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdJykub24oJ2NsaWNrJywgZ2lmdE1lc3NhZ2VCb3gpO1xyXG5cclxuICAgICQoJy5hZGRyZXNzJykub24oJ2NoYW5nZScsXHJcbiAgICAgICAgJ2lucHV0W25hbWUkPVwiX2FkZHJlc3NGaWVsZHNfYWRkcmVzczFcIl0sIGlucHV0W25hbWUkPVwiX2FkZHJlc3NGaWVsZHNfYWRkcmVzczJcIl0sIHNlbGVjdFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX3N0YXRlc19zdGF0ZVwiXSwgaW5wdXRbbmFtZSQ9XCJfYWRkcmVzc0ZpZWxkc19jaXR5XCJdLCBpbnB1dFtuYW1lJD1cIl9hZGRyZXNzRmllbGRzX3ppcFwiXScsXHJcbiAgICAgICAgdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0XHJcbiAgICApO1xyXG5cclxuICAgICQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3MnKS5vbignc3VibWl0JywgZnVuY3Rpb24oZSl7XHJcbiAgICAgICAgdmFyIGF2c1VybCA9ICQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3MnKS5kYXRhKCdhdnMtdXJsJyk7XHJcbiAgICAgICAgaWYoYXZzVXJsKXtcclxuICAgICAgICAgICAgbGV0IGNvbmZpcm1lZCA9ICQoJyNkd2ZybV9zaW5nbGVzaGlwcGluZ19zaGlwcGluZ0FkZHJlc3MnKS5kYXRhKCdhdnMtY29uZmlybWVkJyk7XHJcbiAgICAgICAgICAgIGlmKCFjb25maXJtZWQpe1xyXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAgICAgcG9wdWxhdGVBZHJyKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBcclxuXHJcbiAgICBnaWZ0TWVzc2FnZUJveCgpO1xyXG4gICAgdXBkYXRlU2hpcHBpbmdNZXRob2RMaXN0KCk7XHJcbn07XHJcblxyXG5leHBvcnRzLnVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdCA9IHVwZGF0ZVNoaXBwaW5nTWV0aG9kTGlzdDtcclxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRkUHJvZHVjdFRvQ2FydCA9IHJlcXVpcmUoJy4vcHJvZHVjdC9hZGRUb0NhcnQnKSxcbiAgICBhamF4ID0gcmVxdWlyZSgnLi4vYWpheCcpLFxuICAgIHBhZ2UgPSByZXF1aXJlKCcuLi9wYWdlJyksXG4gICAgcHJvZHVjdFRpbGUgPSByZXF1aXJlKCcuLi9wcm9kdWN0LXRpbGUnKSxcbiAgICBxdWlja3ZpZXcgPSByZXF1aXJlKCcuLi9xdWlja3ZpZXcnKTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgdGhlIGNsaWNrIGV2ZW50cyB0byB0aGUgcmVtb3ZlLWxpbmsgYW5kIHF1aWNrLXZpZXcgYnV0dG9uXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgJCgnI2NvbXBhcmUtdGFibGUnKS5vbignY2xpY2snLCAnLnJlbW92ZS1saW5rJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBhamF4LmdldEpzb24oe1xuICAgICAgICAgICAgdXJsOiB0aGlzLmhyZWYsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHBhZ2UucmVmcmVzaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KVxuICAgIC5vbignY2xpY2snLCAnLm9wZW4tcXVpY2stdmlldycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHVybCA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3QnKS5maW5kKCcudGh1bWItbGluaycpLmF0dHIoJ2hyZWYnKTtcbiAgICAgICAgcXVpY2t2aWV3LnNob3coe1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBzb3VyY2U6ICdxdWlja3ZpZXcnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJCgnI2NvbXBhcmUtY2F0ZWdvcnktbGlzdCcpLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQodGhpcykuY2xvc2VzdCgnZm9ybScpLnN1Ym1pdCgpO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcHJvZHVjdFRpbGUuaW5pdCgpO1xuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbiAgICBhZGRQcm9kdWN0VG9DYXJ0KCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi4vLi4vZGlhbG9nJyksXG4gICAgbWluaWNhcnQgPSByZXF1aXJlKCcuLi8uLi9taW5pY2FydCcpLFxuICAgIHBhZ2UgPSByZXF1aXJlKCcuLi8uLi9wYWdlJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKSxcbiAgICBQcm9taXNlID0gcmVxdWlyZSgncHJvbWlzZScpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFrZSB0aGUgQUpBWCByZXF1ZXN0IHRvIGFkZCBhbiBpdGVtIHRvIGNhcnRcbiAqIEBwYXJhbSB7RWxlbWVudH0gZm9ybSBUaGUgZm9ybSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGl0ZW0gcXVhbnRpdHkgYW5kIElEIGRhdGFcbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG52YXIgYWRkSXRlbVRvQ2FydCA9IGZ1bmN0aW9uIChmb3JtKSB7XG4gICAgdmFyICRmb3JtID0gJChmb3JtKSxcbiAgICAgICAgJHF0eSA9ICRmb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJRdWFudGl0eVwiXScpLFxuICAgICAgICAkcGlkID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInBpZFwiXScpLnZhbCgpO1xuICAgIGlmICgkcXR5Lmxlbmd0aCA9PT0gMCB8fCBpc05hTigkcXR5LnZhbCgpKSB8fCBwYXJzZUludCgkcXR5LnZhbCgpLCAxMCkgPT09IDApIHtcbiAgICAgICAgJHF0eS52YWwoJzEnKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgkLmFqYXgoe1xuICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgIHVybDogdXRpbC5hamF4VXJsKFVybHMuYWRkUHJvZHVjdCksXG4gICAgICAgIGRhdGE6ICRmb3JtLnNlcmlhbGl6ZSgpLFxuICAgICAgICBhc3luYzogZmFsc2VcbiAgICB9KSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgLy8gaGFuZGxlIGVycm9yIGluIHRoZSByZXNwb25zZVxuICAgICAgICBpZiAocmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihyZXNwb25zZS5lcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuRkJfUElYRUxfRU5BQkxFRCA9PT0gdHJ1ZSB8fCAoU2l0ZVByZWZlcmVuY2VzLlRJS1RPS19QSVhFTF9FTkFCTEVEID09PSB0cnVlICYmIFNpdGVQcmVmZXJlbmNlcy5USUtUT0tfUElYRUxfSUQgPT09IHRydWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ2RhdGE6YWRkdG9jYXJ0Jywgeydjb250ZW50X2lkcycgOiAkcGlkfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgdG8gaGFuZGxlIHRoZSBhZGQgdG8gY2FydCBldmVudFxuICovXG52YXIgYWRkVG9DYXJ0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgdmFyICRmb3JtID0gJCh0aGlzKS5jbG9zZXN0KCdmb3JtJyk7XG5cbiAgICBhZGRJdGVtVG9DYXJ0KCRmb3JtKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICB2YXIgJHV1aWQgPSAkZm9ybS5maW5kKCdpbnB1dFtuYW1lPVwidXVpZFwiXScpO1xuICAgICAgICBpZiAoJHV1aWQubGVuZ3RoID4gMCAmJiAkdXVpZC52YWwoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBwYWdlLnJlZnJlc2goKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdCBjbG9zZSBxdWlja3ZpZXcgaWYgYWRkaW5nIGluZGl2aWR1YWwgaXRlbSB0aGF0IGlzIHBhcnQgb2YgcHJvZHVjdCBzZXRcbiAgICAgICAgICAgIC8vIEBUT0RPIHNob3VsZCBub3RpZnkgdGhlIHVzZXIgc29tZSBvdGhlciB3YXkgdGhhdCB0aGUgYWRkIGFjdGlvbiBoYXMgY29tcGxldGVkIHN1Y2Nlc3NmdWxseVxuICAgICAgICAgICAgaWYgKCEkKHRoaXMpLmhhc0NsYXNzKCdzdWItcHJvZHVjdC1pdGVtJykpIHtcbiAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pbmljYXJ0LnNob3cocmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgfS5iaW5kKHRoaXMpKTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgdG8gaGFuZGxlIHRoZSBhZGQgYWxsIGl0ZW1zIHRvIGNhcnQgZXZlbnRcbiAqL1xudmFyIGFkZEFsbFRvQ2FydCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciAkcHJvZHVjdEZvcm1zID0gJCgnI3Byb2R1Y3Qtc2V0LWxpc3QnKS5maW5kKCdmb3JtJykudG9BcnJheSgpO1xuICAgIFByb21pc2UuYWxsKF8ubWFwKCRwcm9kdWN0Rm9ybXMsIGFkZEl0ZW1Ub0NhcnQpKVxuICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzcG9uc2VzKSB7XG4gICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgIC8vIHNob3cgdGhlIGZpbmFsIHJlc3BvbnNlIG9ubHksIHdoaWNoIHdvdWxkIGluY2x1ZGUgYWxsIHRoZSBvdGhlciBpdGVtc1xuICAgICAgICAgICAgbWluaWNhcnQuc2hvdyhyZXNwb25zZXNbcmVzcG9uc2VzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgfSk7XG59O1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBjbGljayBldmVudCB0byBhIGdpdmVuIHRhcmdldCBmb3IgdGhlIGFkZC10by1jYXJ0IGhhbmRsaW5nXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICQoJy5hZGQtdG8tY2FydFtkaXNhYmxlZF0nKS5hdHRyKCd0aXRsZScsICQoJy5hdmFpbGFiaWxpdHktbXNnJykudGV4dCgpKTtcbiAgICAkKCcucHJvZHVjdC1kZXRhaWwnKS5vbignY2xpY2snLCAnLmFkZC10by1jYXJ0JywgYWRkVG9DYXJ0KTtcbiAgICAkKCcucHJvZHVjdHRpbGUtYWRkdG9jYXJ0Jykub24oJ2NsaWNrJywgJy5hZGQtdG8tY2FydCcsIGFkZFRvQ2FydCk7XG4gICAgJCgnI2FkZC1hbGwtdG8tY2FydCcpLm9uKCdjbGljaycsIGFkZEFsbFRvQ2FydCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWpheCA9ICByZXF1aXJlKCcuLi8uLi9hamF4JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxudmFyIHVwZGF0ZUNvbnRhaW5lciA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyICRhdmFpbGFiaWxpdHlNc2cgPSAkKCcjcGRwTWFpbiAuYXZhaWxhYmlsaXR5IC5hdmFpbGFiaWxpdHktbXNnJyk7XG4gICAgdmFyIG1lc3NhZ2U7IC8vIHRoaXMgc2hvdWxkIGJlIGxleGljYWxseSBzY29wZWQsIHdoZW4gYGxldGAgaXMgc3VwcG9ydGVkIChFUzYpXG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuaHRtbChSZXNvdXJjZXMuSVRFTV9TVEFUVVNfTk9UQVZBSUxBQkxFKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAkYXZhaWxhYmlsaXR5TXNnLmVtcHR5KCk7XG4gICAgLy8gTG9vayB0aHJvdWdoIGxldmVscyAuLi4gaWYgbXNnIGlzIG5vdCBlbXB0eSwgdGhlbiBjcmVhdGUgc3BhbiBlbFxuICAgIGlmIChkYXRhLmxldmVscy5JTl9TVE9DSyA+IDApIHtcbiAgICAgICAgaWYgKGRhdGEubGV2ZWxzLlBSRU9SREVSID09PSAwICYmIGRhdGEubGV2ZWxzLkJBQ0tPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5OT1RfQVZBSUxBQkxFID09PSAwKSB7XG4gICAgICAgICAgICAvLyBKdXN0IGluIHN0b2NrXG4gICAgICAgICAgICBtZXNzYWdlID0gUmVzb3VyY2VzLklOX1NUT0NLO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSW4gc3RvY2sgd2l0aCBjb25kaXRpb25zIC4uLlxuICAgICAgICAgICAgbWVzc2FnZSA9IGRhdGEuaW5TdG9ja01zZztcbiAgICAgICAgfVxuICAgICAgICAkYXZhaWxhYmlsaXR5TXNnLmFwcGVuZCgnPHAgY2xhc3M9XCJpbi1zdG9jay1tc2dcIj4nICsgbWVzc2FnZSArICc8L3A+Jyk7XG4gICAgfVxuICAgIGlmIChkYXRhLmxldmVscy5QUkVPUkRFUiA+IDApIHtcbiAgICAgICAgaWYgKGRhdGEubGV2ZWxzLklOX1NUT0NLID09PSAwICYmIGRhdGEubGV2ZWxzLkJBQ0tPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5OT1RfQVZBSUxBQkxFID09PSAwKSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gUmVzb3VyY2VzLlBSRU9SREVSO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWVzc2FnZSA9IGRhdGEucHJlT3JkZXJNc2c7XG4gICAgICAgIH1cbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5hcHBlbmQoJzxwIGNsYXNzPVwicHJlb3JkZXItbXNnXCI+JyArIG1lc3NhZ2UgKyAnPC9wPicpO1xuICAgIH1cbiAgICBpZiAoZGF0YS5sZXZlbHMuQkFDS09SREVSID4gMCkge1xuICAgICAgICBpZiAoZGF0YS5sZXZlbHMuSU5fU1RPQ0sgPT09IDAgJiYgZGF0YS5sZXZlbHMuUFJFT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuTk9UX0FWQUlMQUJMRSA9PT0gMCkge1xuICAgICAgICAgICAgbWVzc2FnZSA9IFJlc291cmNlcy5CQUNLT1JERVI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gZGF0YS5iYWNrT3JkZXJNc2c7XG4gICAgICAgIH1cbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5hcHBlbmQoJzxwIGNsYXNzPVwiYmFja29yZGVyLW1zZ1wiPicgKyBtZXNzYWdlICsgJzwvcD4nKTtcbiAgICB9XG4gICAgaWYgKGRhdGEuaW5TdG9ja0RhdGUgIT09ICcnKSB7XG4gICAgICAgICRhdmFpbGFiaWxpdHlNc2cuYXBwZW5kKCc8cCBjbGFzcz1cImluLXN0b2NrLWRhdGUtbXNnXCI+JyArIFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLklOX1NUT0NLX0RBVEUsIGRhdGEuaW5TdG9ja0RhdGUpICsgJzwvcD4nKTtcbiAgICB9XG4gICAgaWYgKGRhdGEubGV2ZWxzLk5PVF9BVkFJTEFCTEUgPiAwKSB7XG4gICAgICAgIGlmIChkYXRhLmxldmVscy5QUkVPUkRFUiA9PT0gMCAmJiBkYXRhLmxldmVscy5CQUNLT1JERVIgPT09IDAgJiYgZGF0YS5sZXZlbHMuSU5fU1RPQ0sgPT09IDApIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBSZXNvdXJjZXMuTk9UX0FWQUlMQUJMRTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBSZXNvdXJjZXMuUkVNQUlOX05PVF9BVkFJTEFCTEU7XG4gICAgICAgIH1cbiAgICAgICAgJGF2YWlsYWJpbGl0eU1zZy5hcHBlbmQoJzxwIGNsYXNzPVwibm90LWF2YWlsYWJsZS1tc2dcIj4nICsgbWVzc2FnZSArICc8L3A+Jyk7XG4gICAgfVxufTtcblxudmFyIGdldEF2YWlsYWJpbGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5nZXRBdmFpbGFiaWxpdHksIHtcbiAgICAgICAgICAgIHBpZDogJCgnI3BpZCcpLnZhbCgpLFxuICAgICAgICAgICAgUXVhbnRpdHk6ICQodGhpcykudmFsKClcbiAgICAgICAgfSksXG4gICAgICAgIGNhbGxiYWNrOiB1cGRhdGVDb250YWluZXJcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICQoJyNwZHBNYWluJykub24oJ2NoYW5nZScsICcucGRwRm9ybSBpbnB1dFtuYW1lPVwiUXVhbnRpdHlcIl0nLCBnZXRBdmFpbGFiaWxpdHkpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBkaWFsb2cgPSByZXF1aXJlKCcuLi8uLi9kaWFsb2cnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xudmFyIGNhcm91c2VsQ29uZmlnID0gcmVxdWlyZSgnLi4vLi4vY29uZmlncy9jYXJvdXNlbCcpO1xudmFyIHFzID0gcmVxdWlyZSgncXMnKTtcbnZhciB1cmwgPSByZXF1aXJlKCd1cmwnKTtcbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG5cbnZhciB6b29tTWVkaWFRdWVyeSA9IG1hdGNoTWVkaWEoJyhtaW4td2lkdGg6IDk2MHB4KScpO1xuXG5cbi8qIEBtb2R1bGUgaW1hZ2VcbiAqIEBkZXNjcmlwdGlvbiB0aGlzIG1vZHVsZSBoYW5kbGVzIHRoZSBwcmltYXJ5IGltYWdlIHZpZXdlciBvbiBQRFBcbiAqKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRW5hYmxlcyB0aGUgem9vbSB2aWV3ZXIgb24gdGhlIHByb2R1Y3QgZGV0YWlsIHBhZ2VcbiAqIEBwYXJhbSB6bXEge01lZGlhIFF1ZXJ5IExpc3R9XG4gKi9cbmZ1bmN0aW9uIGxvYWRab29tICh6bXEpIHtcbiAgICB2YXIgJGltZ1pvb20gPSAkKCcjcGRwTWFpbiAubWFpbi1pbWFnZSAuem9vbS1pbWcnKSxcbiAgICAgICAgaGlyZXNVcmw7XG4gICAgaWYgKCF6bXEpIHtcbiAgICAgICAgem1xID0gem9vbU1lZGlhUXVlcnk7XG4gICAgfVxuICAgIGlmICgkaW1nWm9vbS5sZW5ndGggPT09IDAgfHwgZGlhbG9nLmlzQWN0aXZlKCkgfHwgdXRpbC5pc01vYmlsZSgpIHx8ICF6b29tTWVkaWFRdWVyeS5tYXRjaGVzKSB7XG4gICAgICAgIC8vIHJlbW92ZSB6b29tXG4gICAgICAgICRpbWdab29tLnRyaWdnZXIoJ3pvb20uZGVzdHJveScpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgJGltZ1pvb20uZWFjaChmdW5jdGlvbihpbmQsIGl0ZW0pIHtcbiAgICAgICAgaGlyZXNVcmwgPSAkKGl0ZW0pLmRhdGEoJ2hyZWYnKTtcblxuICAgICAgICBpZiAoaGlyZXNVcmwgJiYgaGlyZXNVcmwgIT09ICdudWxsJyAmJiBoaXJlc1VybC5pbmRleE9mKCdub2ltYWdlbGFyZ2UnKSA9PT0gLTEgJiYgem9vbU1lZGlhUXVlcnkubWF0Y2hlcykge1xuICAgICAgICAgICAgJChpdGVtKS50cmlnZ2VyKCd6b29tLmRlc3Ryb3knKTtcbiAgICAgICAgICAgICQoaXRlbSkuem9vbSh7XG4gICAgICAgICAgICAgICAgdXJsOiBoaXJlc1VybFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuem9vbU1lZGlhUXVlcnkuYWRkTGlzdGVuZXIobG9hZFpvb20pO1xuXG4vKipcbiAqIFNsaWRlcnMgaW5pdGlhbGl6YXRpb24gaGFuZGxlci4gTW9uaXRvcnMgdGhlIGxvYWRpbmcgb2YgaW1hZ2VzIGluc2lkZSB0aGUgc2xpZGVyIGNvbnRhaW5lclxuICogQHBhcmFtIHtqUXVlcnkgb2JqZWN0fSAkc2xpZGVyQ29udGFpbmVyIC0gc2xpZGVyIGNvbnRhaW5lciBqUXVlcnkgb2JqZWN0XG4gKiBAcGFyYW0ge0pTT059IHNldHRpbmdzIC0ganNvbiB3aXRoIHNsaWRlciBzZXR0aW5nc1xuICovXG5mdW5jdGlvbiBpbml0U2xpZGVySGFuZGxlcigkc2xpZGVyQ29udGFpbmVyLCBzZXR0aW5ncykge1xuICAgIHZhciAkaW1hZ2VzID0gJHNsaWRlckNvbnRhaW5lci5maW5kKCcuanMtc2xpZGVyLWltYWdlJykuZmlsdGVyKChpbmQsIGltYWdlKSA9PiB7XG4gICAgICAgIHJldHVybiBpbWFnZS5jb21wbGV0ZSA9PT0gZmFsc2U7XG4gICAgfSk7XG4gICAgdmFyIGkgPSAwOyAgICBcbiAgICBpZiAoISRpbWFnZXMubGVuZ3RoKSB7XG4gICAgICAgICRzbGlkZXJDb250YWluZXIuc2xpY2soc2V0dGluZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgICRpbWFnZXMub24oJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIGlmKGkgPT09ICRpbWFnZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAkc2xpZGVyQ29udGFpbmVyLnNsaWNrKHNldHRpbmdzKS5kYXRhKCdzbGljaycsc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIH0sMClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBpbml0aWFsaXplIG1vYmlsZSBzbGlkZXIgZm9yIGltYWdlc1xuICovXG5mdW5jdGlvbiBpbml0UHJvZHVjdFNsaWRlcigpIHsgICAgIFxuICAgIGluaXRTbGlkZXJIYW5kbGVyKFxuICAgICAgICAkKCcucGRwLXByaW1hcnktc2xpZGVyJyksXG4gICAgICAgIGNhcm91c2VsQ29uZmlnLnBkcFByaW1hcnlDYXJvdXNlbFxuICAgICk7XG4gICAgbGV0IGlzUEJUaHVtYkNhcm91c2VsID0gJCgnLnBiLXRodW1ibmFpbHMtc2xpZGVyJykubGVuZ3RoID4gMDtcbiAgICBpbml0U2xpZGVySGFuZGxlcihcbiAgICAgICAgJCgnLnBkcC10aHVtYm5haWxzLXNsaWRlcicpLFxuICAgICAgICAhaXNQQlRodW1iQ2Fyb3VzZWwgPyBjYXJvdXNlbENvbmZpZy5wZHBUaHVtYkNhcm91c2VsOiBjYXJvdXNlbENvbmZpZy5wYlRodW1iQ2Fyb3VzZWxcbiAgICApO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtYWluIGltYWdlIGF0dHJpYnV0ZXMgYW5kIHRoZSBocmVmIGZvciB0aGUgc3Vycm91bmRpbmcgPGE+IHRhZ1xuICogQHBhcmFtIHtPYmplY3R9IGF0dHMgT2JqZWN0IHdpdGggdXJsLCBhbHQsIHRpdGxlIGFuZCBoaXJlcyBwcm9wZXJ0aWVzXG4gKi9cbmZ1bmN0aW9uIHNldE1haW5JbWFnZSAoYXR0cikge1xuICAgIHZhciBhdHRzID0gIHR5cGVvZiBhdHRyID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoYXR0cikgOiBhdHRyO1xuXG4gICAgJCgnI3BkcE1haW4gLm1haW4taW1hZ2Uuc2xpY2stY3VycmVudCAucHJpbWFyeS1pbWFnZScpLmF0dHIoe1xuICAgICAgICBzcmM6IGF0dHMudXJsLFxuICAgICAgICBhbHQ6IGF0dHMuYWx0LFxuICAgICAgICB0aXRsZTogYXR0cy50aXRsZVxuICAgIH0pO1xuICAgIHVwZGF0ZVBpbkJ1dHRvbihhdHRzLnVybCk7XG4gICAgaWYgKCFkaWFsb2cuaXNBY3RpdmUoKSAmJiAhdXRpbC5pc01vYmlsZSgpICYmICQoJyNwZHBNYWluIC5tYWluLWltYWdlJykubGVuZ3RoIDwgMikge1xuICAgICAgICAkKCcjcGRwTWFpbiAubWFpbi1pbWFnZS5zbGljay1jdXJyZW50IC5wcmltYXJ5LWltYWdlJykuYXR0cignaHJlZicsIGF0dHMuaGlyZXMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlUGluQnV0dG9uIChpbWFnZVVybCkge1xuICAgIHZhciBwaW5CdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuc2hhcmUtaWNvbltkYXRhLXNoYXJlPXBpbnRlcmVzdF0nKTtcbiAgICBpZiAoIXBpbkJ1dHRvbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBuZXdVcmwgPSBpbWFnZVVybDtcbiAgICBpZiAoIWltYWdlVXJsKSB7XG4gICAgICAgIG5ld1VybCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwZHBNYWluIC5wcmltYXJ5LWltYWdlJykuZ2V0QXR0cmlidXRlKCdzcmMnKTtcbiAgICB9XG4gICAgdmFyIGhyZWYgPSB1cmwucGFyc2UocGluQnV0dG9uLmhyZWYpO1xuICAgIHZhciBxdWVyeSA9IHFzLnBhcnNlKGhyZWYucXVlcnkpO1xuICAgIHF1ZXJ5Lm1lZGlhID0gdXJsLnJlc29sdmUod2luZG93LmxvY2F0aW9uLmhyZWYsIG5ld1VybCk7XG4gICAgcXVlcnkudXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWY7XG4gICAgdmFyIG5ld0hyZWYgPSB1cmwuZm9ybWF0KF8uZXh0ZW5kKHt9LCBocmVmLCB7XG4gICAgICAgIHF1ZXJ5OiBxdWVyeSwgLy8gcXVlcnkgaXMgb25seSB1c2VkIGlmIHNlYXJjaCBpcyBhYnNlbnRcbiAgICAgICAgc2VhcmNoOiBxcy5zdHJpbmdpZnkocXVlcnkpXG4gICAgfSkpO1xuICAgIHBpbkJ1dHRvbi5ocmVmID0gbmV3SHJlZjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwbGFjZXMgdGhlIGltYWdlcyBpbiB0aGUgaW1hZ2UgY29udGFpbmVyLCBmb3IgZWcuIHdoZW4gYSBkaWZmZXJlbnQgY29sb3Igd2FzIGNsaWNrZWQuXG4gKi9cbmZ1bmN0aW9uIHJlcGxhY2VJbWFnZXMgKCkge1xuICAgIHZhciAkbmV3SW1hZ2VzID0gJCgnI3VwZGF0ZS1pbWFnZXMnKSxcbiAgICAgICAgJGltYWdlQ29udGFpbmVyID0gJCgnI3BkcE1haW4gLnByb2R1Y3QtcHJpbWFyeS1pbWFnZS1jYXJvdXNlbCcpO1xuICAgIGlmICgkbmV3SW1hZ2VzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblxuICAgICRpbWFnZUNvbnRhaW5lci5odG1sKCRuZXdJbWFnZXMuaHRtbCgpKTtcbiAgICAkbmV3SW1hZ2VzLnJlbW92ZSgpO1xuICAgIGxvYWRab29tKCk7XG4gICAgaW5pdFByb2R1Y3RTbGlkZXIoKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gYnkgZGVmYXVsdCwgdGhpcyBmdW5jdGlvbiBzZXRzIHVwIHpvb20gYW5kIGV2ZW50IGhhbmRsZXIgZm9yIHRodW1ibmFpbCBjbGlja1xuICoqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGRpYWxvZy5pc0FjdGl2ZSgpIHx8IHV0aWwuaXNNb2JpbGUoKSkge1xuICAgICAgICAkKCcjcGRwTWFpbiAubWFpbi1pbWFnZScpLnJlbW92ZUF0dHIoJ2hyZWYnKTtcbiAgICB9XG4gICAgdXBkYXRlUGluQnV0dG9uKCk7XG4gICAgbG9hZFpvb20oKTtcblxuICAgIGluaXRQcm9kdWN0U2xpZGVyKCk7XG5cbiAgICAkKCcjcGRwTWFpbicpLm9uKCdjbGljaycsICcubWFpbi1pbWFnZScsIGZ1bmN0aW9uKCkgeyBcbiAgICAgICAgcmV0dXJuIGZhbHNlOyBcbiAgICB9KTtcbn07XG5tb2R1bGUuZXhwb3J0cy5sb2FkWm9vbSA9IGxvYWRab29tO1xubW9kdWxlLmV4cG9ydHMuc2V0TWFpbkltYWdlID0gc2V0TWFpbkltYWdlO1xubW9kdWxlLmV4cG9ydHMucmVwbGFjZUltYWdlcyA9IHJlcGxhY2VJbWFnZXM7XG5tb2R1bGUuZXhwb3J0cy5pbml0UHJvZHVjdFNsaWRlciA9IGluaXRQcm9kdWN0U2xpZGVyO1xubW9kdWxlLmV4cG9ydHMuaW5pdFNsaWRlckhhbmRsZXIgPSBpbml0U2xpZGVySGFuZGxlcjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpLFxuICAgIHByb2R1Y3RTdG9yZUludmVudG9yeSA9IHJlcXVpcmUoJy4uLy4uL3N0b3JlaW52ZW50b3J5L3Byb2R1Y3QnKSxcbiAgICB0b29sdGlwID0gcmVxdWlyZSgnLi4vLi4vdG9vbHRpcCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyksXG4gICAgYWRkVG9DYXJ0ID0gcmVxdWlyZSgnLi9hZGRUb0NhcnQnKSxcbiAgICBhdmFpbGFiaWxpdHkgPSByZXF1aXJlKCcuL2F2YWlsYWJpbGl0eScpLFxuICAgIGltYWdlID0gcmVxdWlyZSgnLi9pbWFnZScpLFxuICAgIHByb2R1Y3ROYXYgPSByZXF1aXJlKCcuL3Byb2R1Y3ROYXYnKSxcbiAgICBwcm9kdWN0U2V0ID0gcmVxdWlyZSgnLi9wcm9kdWN0U2V0JyksXG4gICAgcmVjb21tZW5kYXRpb25zID0gcmVxdWlyZSgnLi9yZWNvbW1lbmRhdGlvbnMnKSxcbiAgICB2YXJpYW50ID0gcmVxdWlyZSgnLi92YXJpYW50JyksXG4gICAgcXVhbnRpdHlTd2l0Y2hlciA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvcXVhbnRpdHlTd2l0Y2hlcicpLFxuICAgIGFjY29yZGlvbiA9IHJlcXVpcmUoJy4uLy4uL2NvbXBvbmVudHMvYWNjb3JkaW9uJyksXG4gICAgc2l6ZUNoYXJ0ID0gcmVxdWlyZSgnLi9zaXplQ2hhcnQnKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZSBwcm9kdWN0IGRldGFpbCBwYWdlIHdpdGggcmV2aWV3cywgcmVjb21tZW5kYXRpb24gYW5kIHByb2R1Y3QgbmF2aWdhdGlvbi5cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZURvbSgpIHtcbiAgICBwcm9kdWN0TmF2KCk7XG4gICAgdG9vbHRpcC5pbml0KCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemUgZXZlbnQgaGFuZGxlcnMgb24gcHJvZHVjdCBkZXRhaWwgcGFnZVxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgIHZhciAkcGRwTWFpbiA9ICQoJyNwZHBNYWluJyk7XG5cbiAgICBhZGRUb0NhcnQoKTtcbiAgICBhdmFpbGFiaWxpdHkoKTtcbiAgICB2YXJpYW50KCk7XG4gICAgaW1hZ2UoKTtcbiAgICByZWNvbW1lbmRhdGlvbnMoKTtcbiAgICBwcm9kdWN0U2V0KCk7XG4gICAgcXVhbnRpdHlTd2l0Y2hlcigpO1xuICAgIGFjY29yZGlvbigpO1xuICAgIHNpemVDaGFydCgpO1xuXG4gICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgcHJvZHVjdFN0b3JlSW52ZW50b3J5LmluaXQoKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgdG8gV2lzaGxpc3QgYW5kIEFkZCB0byBHaWZ0IFJlZ2lzdHJ5IGxpbmtzIGJlaGF2aW9yc1xuICAgICRwZHBNYWluLm9uKCdjbGljaycsICdbZGF0YS1hY3Rpb249XCJ3aXNobGlzdFwiXSwgW2RhdGEtYWN0aW9uPVwiZ2lmdC1yZWdpc3RyeVwiXScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKCQoJy5wZHBGb3JtJykuc2VyaWFsaXplKCkpO1xuICAgICAgICBpZiAoZGF0YS5jYXJ0QWN0aW9uKSB7XG4gICAgICAgICAgICBkZWxldGUgZGF0YS5jYXJ0QWN0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1cmwgPSB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKHRoaXMuaHJlZiwgZGF0YSk7XG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdocmVmJywgdXJsKTtcbiAgICB9KTtcblxuICAgIC8vIHByb2R1Y3Qgb3B0aW9uc1xuICAgICRwZHBNYWluLm9uKCdjaGFuZ2UnLCAnLnByb2R1Y3Qtb3B0aW9ucyBzZWxlY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzYWxlc1ByaWNlID0gJHBkcE1haW4uZmluZCgnLnByb2R1Y3QtYWRkLXRvLWNhcnQgLnByaWNlLXNhbGVzJyk7XG4gICAgICAgIHZhciBzZWxlY3RlZEl0ZW0gPSAkKHRoaXMpLmNoaWxkcmVuKCkuZmlsdGVyKCc6c2VsZWN0ZWQnKS5maXJzdCgpO1xuICAgICAgICBzYWxlc1ByaWNlLnRleHQoc2VsZWN0ZWRJdGVtLmRhdGEoJ2NvbWJpbmVkJykpO1xuICAgIH0pO1xuXG4gICAgLy8gcHJldmVudCBkZWZhdWx0IGJlaGF2aW9yIG9mIHRodW1ibmFpbCBsaW5rIGFuZCBhZGQgdGhpcyBCdXR0b25cbiAgICAkcGRwTWFpbi5vbignY2xpY2snLCAnLnRodW1ibmFpbC1saW5rLCAudW5zZWxlY3RhYmxlIGEnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSk7XG5cbiAgICAkKCcuc2l6ZS1jaGFydC1saW5rIGEnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIHVybDogJChlLnRhcmdldCkuYXR0cignaHJlZicpXG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgIFxuICAgIC8vIFNhbml0aXplcyBkYXRhIGVudGVyZWQgYnkgdGhlIHVzZXIgaW50byB0aGUgcXVhbnRpdHkgZmllbGRcbiAgICAkKCcucGRwRm9ybSBpbnB1dFtuYW1lPVwiUXVhbnRpdHlcIl0nKS5rZXl1cChmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG51bWJlcnMgPSAkKHRoaXMpLnZhbCgpO1xuXHRcdCQodGhpcykudmFsKG51bWJlcnMucmVwbGFjZSgvXFxEKy8sICcnKSk7XG5cdFx0aWYgKCQodGhpcykudmFsKCkgPT0gJycgfHwgJCh0aGlzKS52YWwoKSA9PSAnMCcpIHtcblx0XHRcdCQodGhpcykudmFsKDEpO1xuXHRcdH1cblx0fSk7XG4gICAgXG4gICAgJCggd2luZG93ICkubG9hZChmdW5jdGlvbigpIHtcbiAgICBcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHQgICAgJCgnLnByb2R1Y3QtbGlzdGluZy5wZHBwYWdlIC5zbGljaycpLnNsaWNrKHtcblx0XHQgICAgICAgIGluZmluaXRlOiBmYWxzZSxcblx0XHQgICAgICAgIHNsaWRlc1RvU2hvdzogMyxcblx0XHQgICAgICAgIHNsaWRlc1RvU2Nyb2xsOiAxLFxuXHRcdCAgICAgICAgZG90czogZmFsc2Vcblx0XHQgICAgfSk7XG4gICAgXHR9LCAyMDAwKTtcbiAgICB9KTtcbn1cblxudmFyIHByb2R1Y3QgPSB7XG4gICAgaW5pdGlhbGl6ZUV2ZW50czogaW5pdGlhbGl6ZUV2ZW50cyxcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGluaXRpYWxpemVEb20oKTtcbiAgICAgICAgaW5pdGlhbGl6ZUV2ZW50cygpO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvZHVjdDtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gbG9hZHMgcHJvZHVjdCdzIG5hdmlnYXRpb25cbiAqKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkcGlkSW5wdXQgPSAkKCcucGRwRm9ybSBpbnB1dFtuYW1lPVwicGlkXCJdJykubGFzdCgpLFxuICAgICAgICAkbmF2Q29udGFpbmVyID0gJCgnI3Byb2R1Y3QtbmF2LWNvbnRhaW5lcicpO1xuICAgIC8vIGlmIG5vIGhhc2ggZXhpc3RzLCBvciBubyBwaWQgZXhpc3RzLCBvciBuYXYgY29udGFpbmVyIGRvZXMgbm90IGV4aXN0LCByZXR1cm5cbiAgICBpZiAod2luZG93LmxvY2F0aW9uLmhhc2gubGVuZ3RoIDw9IDEgfHwgJHBpZElucHV0Lmxlbmd0aCA9PT0gMCB8fCAkbmF2Q29udGFpbmVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHBpZCA9ICRwaWRJbnB1dC52YWwoKSxcbiAgICAgICAgaGFzaCA9IGVuY29kZVVSSUNvbXBvbmVudCh3aW5kb3cubG9jYXRpb24uaGFzaC5zdWJzdHIoMSkpLCAgICAgICBcbiAgICAgICAgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMucHJvZHVjdE5hdiArICc/JyArIGhhc2gsICdwaWQnLCBwaWQpO1xuXG4gICAgYWpheC5sb2FkKHtcbiAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgIHRhcmdldDogJG5hdkNvbnRhaW5lclxuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFqYXggPSByZXF1aXJlKCcuLi8uLi9hamF4JyksXG4gICAgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJGFkZFRvQ2FydCA9ICQoJyNhZGQtdG8tY2FydCcpLFxuICAgICAgICAkYWRkQWxsVG9DYXJ0ID0gJCgnI2FkZC1hbGwtdG8tY2FydCcpLFxuICAgICAgICAkcHJvZHVjdFNldExpc3QgPSAkKCcjcHJvZHVjdC1zZXQtbGlzdCcpO1xuXG4gICAgdmFyIHVwZGF0ZUFkZFRvQ2FydEJ1dHRvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICgkcHJvZHVjdFNldExpc3QuZmluZCgnLmFkZC10by1jYXJ0W2Rpc2FibGVkXScpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICRhZGRBbGxUb0NhcnQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIC8vIHByb2R1Y3Qgc2V0IGRvZXMgbm90IGhhdmUgYW4gYWRkLXRvLWNhcnQgYnV0dG9uLCBidXQgcHJvZHVjdCBidW5kbGUgZG9lc1xuICAgICAgICAgICAgJGFkZFRvQ2FydC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGFkZEFsbFRvQ2FydC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgJGFkZFRvQ2FydC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICgkcHJvZHVjdFNldExpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICB1cGRhdGVBZGRUb0NhcnRCdXR0b25zKCk7XG4gICAgfVxuICAgIC8vIGNsaWNrIG9uIHN3YXRjaCBmb3IgcHJvZHVjdCBzZXRcbiAgICAkcHJvZHVjdFNldExpc3Qub24oJ2NsaWNrJywgJy5wcm9kdWN0LXNldC1pdGVtIC5zd2F0Y2hhbmNob3InLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7IHJldHVybjsgfVxuICAgICAgICB2YXIgdXJsID0gVXJscy5nZXRTZXRJdGVtICsgdGhpcy5zZWFyY2g7XG4gICAgICAgIHZhciAkY29udGFpbmVyID0gJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC1zZXQtaXRlbScpO1xuICAgICAgICB2YXIgcXR5ID0gJGNvbnRhaW5lci5maW5kKCdmb3JtIGlucHV0W25hbWU9XCJRdWFudGl0eVwiXScpLmZpcnN0KCkudmFsKCk7XG5cbiAgICAgICAgYWpheC5sb2FkKHtcbiAgICAgICAgICAgIHVybDogdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ1F1YW50aXR5JywgaXNOYU4ocXR5KSA/ICcxJyA6IHF0eSksXG4gICAgICAgICAgICB0YXJnZXQ6ICRjb250YWluZXIsXG4gICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZUFkZFRvQ2FydEJ1dHRvbnMoKTtcbiAgICAgICAgICAgICAgICB0b29sdGlwLmluaXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNhcm91c2VsQ29uZmlnID0gcmVxdWlyZSgnLi4vLi4vY29uZmlncy9jYXJvdXNlbCcpO1xuXG4vKipcbiAqIENhcm91c2VsIGluaXRpYWxpemF0aW9uIGZ1bmN0aW9uXG4gKiBAcGFyYW0ge09iamVjdH0gJGNhcm91c2VsIC0galF1ZXJ5IG9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIGNhcm91c2VsIHNldHRpbmdzXG4gKi9cbmZ1bmN0aW9uIGluaXRDYXJvdXNlbCgkY2Fyb3VzZWwsIGNvbmZpZykge1xuICAgICRjYXJvdXNlbC5lYWNoKGZ1bmN0aW9uKGluZCwgaXRlbSkge1xuICAgICAgICAvLyB2YXIgY29uZmlnID0gY2Fyb3VzZWxDb25maWcuZWluc3RlaW5SZWNvbW1lbmRhdGlvbkNhcm91c2VsO1xuICAgICAgICB2YXIgbnVtYmVyT2ZTbGlkZXMgPSAkKGl0ZW0pLmNoaWxkcmVuKCkubGVuZ3RoO1xuICAgICAgICAvLyBudW1iZXJPZlNsaWRlcyA+IGNvbmZpZy5zbGlkZXNUb1Nob3cgJiYgXG4gICAgICAgIGlmICghJChpdGVtKS5oYXNDbGFzcygnc2xpY2staW5pdGlhbGl6ZWQnKSkge1xuICAgICAgICAgICAgJChpdGVtKS5zbGljayhjb25maWcpLmRhdGEoJ2Nhcm91c2VsJywgY29uZmlnKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEluaXQgUHJvZHVjdCBSZWNvbW1lbmRhdGlvbiBDYXJvdXNlbFxuICovXG5mdW5jdGlvbiBpbml0UHJvZHVjdFJlY29tbWVuZGF0aW9uQ2Fyb3VzZWwoKSB7XG4gICAgdmFyICRjYXJvdXNlbCA9ICQoJyNjYXJvdXNlbC1yZWNvbW1lbmRhdGlvbnMgLnNsaWNrJyk7XG4gICAgdmFyIGNvbmZpZyA9IGNhcm91c2VsQ29uZmlnLnJlY29tbWVuZGF0aW9uQ2Fyb3VzZWw7XG4gICAgaW5pdENhcm91c2VsKCRjYXJvdXNlbCwgY29uZmlnKVxufVxuXG4vKipcbiAqIEluaXQgRWluc3RlaW4gUmVjb21tZW5kYXRpb24gQ2Fyb3VzZWxcbiAqL1xuZnVuY3Rpb24gaW5pdEVpbnN0ZWluUmVjb21tZW5kYXRpb25DYXJvdXNlbCgpIHtcbiAgICB2YXIgJGNhcm91c2VsID0gJCgnLmVpbnN0ZWluLXJlY29tbWVuZGF0aW9uIC5zbGljaycpO1xuICAgIHZhciBjb25maWcgPSBjYXJvdXNlbENvbmZpZy5laW5zdGVpblJlY29tbWVuZGF0aW9uQ2Fyb3VzZWw7XG4gICAgXG4gICAgJChkb2N1bWVudCkub24oJ2VpbnN0ZWluOmxvYWRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJGNhcm91c2VsID0gJCgnLmVpbnN0ZWluLXJlY29tbWVuZGF0aW9uIC5zbGljaycpO1xuICAgICAgICBpbml0Q2Fyb3VzZWwoJGNhcm91c2VsLCBjb25maWcpO1xuICAgIH0pO1xuXG4gICAgaWYgKCRjYXJvdXNlbC5sZW5ndGgpIHtcbiAgICAgICAgaW5pdENhcm91c2VsKCRjYXJvdXNlbCwgY29uZmlnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgcHJvZHVjdCByZWNvbW1lbmRhdGlvbiBjYXJvdXNlbHNcbiAqKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgIGluaXRQcm9kdWN0UmVjb21tZW5kYXRpb25DYXJvdXNlbCgpXG4gICAgaW5pdEVpbnN0ZWluUmVjb21tZW5kYXRpb25DYXJvdXNlbCgpO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uLy4uL2RpYWxvZycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbnZhciBtYXhIZWlnaHQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaXNNb2IgPSB1dGlsLmlzTW9iaWxlKCkgfHwgbWF0Y2hNZWRpYSgnKG1heC13aWR0aDogNTUwcHgpJykubWF0Y2hlcztcbiAgICB2YXIgaGVpZ2h0O1xuICAgIHZhciB3aW5kb3dIZWlnaHQgPSAkKHdpbmRvdykuaGVpZ2h0KCk7XG4gICAgaWYgKGlzTW9iKSB7XG4gICAgICAgIGhlaWdodCA9IHdpbmRvd0hlaWdodCAqIDAuNztcbiAgICB9IGVsc2Uge1xuICAgICAgICBoZWlnaHQgPSB3aW5kb3dIZWlnaHQgKiAwLjk7XG4gICAgfVxuICAgIHJldHVybiBoZWlnaHQ7XG59XG5cbnZhciBzaXplQ2hhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRjb250ZW50ID0gJCgnI3NpemUtY2hhcnQtY29udGVudCcpO1xuXG4gICAgJCgnYm9keScpLm9uKCdjbGljaycsICcuanMtc2l6ZS1jaGFydC1idG4nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgaHRtbDogJGNvbnRlbnQuaHRtbCgpLFxuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIGRpYWxvZ0NsYXNzOiBcInNpemUtY2hhcnQtbW9kYWxcIixcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IG1heEhlaWdodCgpLFxuICAgICAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uKGV2ZW50LCB1aSkge1xuICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAkKGV2ZW50LnRhcmdldCkuc2Nyb2xsVG9wKDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzaXplQ2hhcnQ7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBhamF4ID0gcmVxdWlyZSgnLi4vLi4vYWpheCcpLFxuICAgIGltYWdlID0gcmVxdWlyZSgnLi9pbWFnZScpLFxuICAgIHByb2dyZXNzID0gcmVxdWlyZSgnLi4vLi4vcHJvZ3Jlc3MnKSxcbiAgICBwcm9kdWN0U3RvcmVJbnZlbnRvcnkgPSByZXF1aXJlKCcuLi8uLi9zdG9yZWludmVudG9yeS9wcm9kdWN0JyksXG4gICAgdG9vbHRpcCA9IHJlcXVpcmUoJy4uLy4uL3Rvb2x0aXAnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGUgcHJvZHVjdCBjb250ZW50IHdpdGggbmV3IHZhcmlhbnQgZnJvbSBocmVmLCBsb2FkIG5ldyBjb250ZW50IHRvICNwcm9kdWN0LWNvbnRlbnQgcGFuZWxcbiAqIEBwYXJhbSB7U3RyaW5nfSBocmVmIC0gdXJsIG9mIHRoZSBuZXcgcHJvZHVjdCB2YXJpYW50XG4gKiovXG52YXIgdXBkYXRlQ29udGVudCA9IGZ1bmN0aW9uIChocmVmKSB7XG4gICAgdmFyICRwZHBGb3JtID0gJCgnLnBkcEZvcm0nKTtcbiAgICB2YXIgcXR5ID0gJHBkcEZvcm0uZmluZCgnaW5wdXRbbmFtZT1cIlF1YW50aXR5XCJdJykuZmlyc3QoKS52YWwoKTtcbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBRdWFudGl0eTogaXNOYU4ocXR5KSA/ICcxJyA6IHF0eSxcbiAgICAgICAgZm9ybWF0OiAnYWpheCcsXG4gICAgICAgIHByb2R1Y3RsaXN0aWQ6ICRwZHBGb3JtLmZpbmQoJ2lucHV0W25hbWU9XCJwcm9kdWN0bGlzdGlkXCJdJykuZmlyc3QoKS52YWwoKVxuICAgIH07XG5cbiAgICBwcm9ncmVzcy5zaG93KCQoJyNwZHBNYWluJykpO1xuXG4gICAgYWpheC5sb2FkKHtcbiAgICAgICAgdXJsOiB1dGlsLmFwcGVuZFBhcmFtc1RvVXJsKGhyZWYsIHBhcmFtcyksXG4gICAgICAgIHRhcmdldDogJCgnI3Byb2R1Y3QtY29udGVudCcpLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKFNpdGVQcmVmZXJlbmNlcy5TVE9SRV9QSUNLVVApIHtcbiAgICAgICAgICAgICAgICBwcm9kdWN0U3RvcmVJbnZlbnRvcnkuaW5pdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW1hZ2UucmVwbGFjZUltYWdlcygpO1xuICAgICAgICAgICAgdG9vbHRpcC5pbml0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbnZhciBjb2xvclN3YXRjaGVzSG92ZXIgPSBmdW5jdGlvbiAoJHRoaXMpIHtcbiAgICB2YXIgJHBkcE1haW4gPSAkKCcjcGRwTWFpbicpLFxuICAgICAgICBsYXJnZUltZyA9ICR0aGlzLmRhdGEoJ2xnaW1nJyksXG4gICAgICAgICRpbWdab29tID0gJHBkcE1haW4uZmluZCgnLm1haW4taW1hZ2Uuc2xpY2stY3VycmVudCAuem9vbS1pbWcnKSxcbiAgICAgICAgJG1haW5JbWFnZSA9ICRwZHBNYWluLmZpbmQoJy5zbGljay1jdXJyZW50IC5wcmltYXJ5LWltYWdlJyk7XG5cbiAgICBpZiAoIWxhcmdlSW1nKSB7IHJldHVybjsgfVxuICAgIC8vIHN0b3JlIHRoZSBvbGQgZGF0YSBmcm9tIG1haW4gaW1hZ2UgZm9yIG1vdXNlbGVhdmUgaGFuZGxlclxuICAgICR0aGlzLmRhdGEoJ2xnaW1nJywge1xuICAgICAgICBoaXJlczogJGltZ1pvb20uZGF0YSgnaHJlZicpLFxuICAgICAgICB1cmw6ICRtYWluSW1hZ2UuYXR0cignc3JjJyksXG4gICAgICAgIGFsdDogJG1haW5JbWFnZS5hdHRyKCdhbHQnKSxcbiAgICAgICAgdGl0bGU6ICRtYWluSW1hZ2UuYXR0cigndGl0bGUnKVxuICAgIH0pO1xuICAgIC8vIHNldCB0aGUgbWFpbiBpbWFnZVxuICAgIGltYWdlLnNldE1haW5JbWFnZShsYXJnZUltZyk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB1cGRhdGUgcHJvZHVjdCB0aWxlIGNvbnRlbnQgd2l0aCBuZXcgdmFyaWFudCBmcm9tIGhyZWYsIGxvYWQgbmV3IGNvbnRlbnQgdG8gI3Byb2R1Y3QtY29udGVudCBwYW5lbFxuICogQHBhcmFtIHtTdHJpbmd9IGhyZWYgLSB1cmwgb2YgdGhlIG5ldyBwcm9kdWN0IHZhcmlhbnRcbiAqKi9cbnZhciB1cGRhdGVQVENvbnRlbnQgPSBmdW5jdGlvbiAocHJvZHVjdFRpbGUpIHtcbiAgICB2YXIgJHB0Rm9ybSA9ICQocHJvZHVjdFRpbGUpO1xuICAgIHZhciAkYWRkVG9DYXJ0ID0gJChwcm9kdWN0VGlsZSkuY2xvc2VzdCgnLnByb2R1Y3QtdmFyaWF0aW9ucycpLnBhcmVudCgpO1xuICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgIFF1YW50aXR5OiAnMScsXG4gICAgICAgIGZvcm1hdDogJ2FqYXhKU09OJyxcbiAgICAgICAgcHJvZHVjdGxpc3RpZDogJHB0Rm9ybS5maW5kKCdpbnB1dFtuYW1lPVwicHJvZHVjdGxpc3RpZFwiXScpLmZpcnN0KCkudmFsKClcbiAgICB9O1xuXG4gICAgcHJvZ3Jlc3Muc2hvdygkKCcjc2VhcmNoLXJlc3VsdC1pdGVtcycpKTtcbiAgICBhamF4LmdldEpzb24oe1xuICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwocHJvZHVjdFRpbGUuaHJlZiwgcGFyYW1zKSxcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgbGV0IGNvbnRleHQgPSByZXNwb25zZS5jb250ZXh0O1xuICAgICAgICAgICAgbGV0IHNlbGVjdGVkQXR0ciA9IGNvbnRleHQuc2VsZWN0ZWRBdHRycyA/IEpTT04ucGFyc2UoY29udGV4dC5zZWxlY3RlZEF0dHJzKSA6ICd7fSc7XG4gICAgICAgICAgICBsZXQga2V5cyA9IE9iamVjdC5lbnRyaWVzKHNlbGVjdGVkQXR0cik7XG4gICAgICAgICAgICBsZXQgYXR0ciA9IGtleXMgJiYga2V5cy5sZW5ndGggPiAwID8gY29udGV4dC5hdHRycy5maWx0ZXIoKGF0dHIpID0+IGF0dHIuYXR0cmlidXRlSWQgPT09IGtleXNbMF1bMF0pIDogbnVsbDtcbiAgICAgICAgICAgIGlmIChhdHRyKSB7XG4gICAgICAgICAgICAgICAgbGV0IGF0dHJTZWxlY3RlZCA9IGF0dHJbMF0udmFsdWVzLmZpbHRlcigoYXR0cikgPT4gYXR0ci5pc1NlbGVjdGVkKTtcbiAgICAgICAgICAgICAgICBsZXQgcGFyYW1BdHRyID0ga2V5c1swXVswXStcIj1cIithdHRyU2VsZWN0ZWRbMF0udmFsdWU7XG4gICAgICAgICAgICAgICAgbGV0IHBhcmFtSW5kZXggPSBwcm9kdWN0VGlsZS5ocmVmLmluZGV4T2YocGFyYW1BdHRyKTtcbiAgICAgICAgICAgICAgICBpZihhdHRyU2VsZWN0ZWQgJiYgcGFyYW1JbmRleCAhPSAtMSl7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNlbGVjdGVkIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgICRwdEZvcm0uY2xvc2VzdCgnLnN3YXRjaGVzJykuZmluZCgnbGknKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgJHB0Rm9ybS5jbG9zZXN0KCdsaScpLmZpcnN0KCkuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIC8vVXBkYXRlIHBpZCBhdHRyaWJ1dGVcbiAgICAgICAgICAgICAgICAgICAgJGFkZFRvQ2FydC5maW5kKCdpbnB1dFtuYW1lPVwicGlkXCJdJykuZmlyc3QoKS52YWwocmVzcG9uc2UucHJvZHVjdElEKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcm9ncmVzcy5oaWRlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkcGRwTWFpbiA9ICQoJyNwZHBNYWluJyk7XG4gICAgLy8gaG92ZXIgb24gc3dhdGNoIC0gc2hvdWxkIHVwZGF0ZSBtYWluIGltYWdlIHdpdGggc3dhdGNoIGltYWdlXG4gICAgJHBkcE1haW4ub24oJ21vdXNlZW50ZXIgbW91c2VsZWF2ZScsICcuc3dhdGNoZXMuY29sb3IgLnN3YXRjaGFuY2hvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGltZXI7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIHRpbWVyID0gc2V0VGltZW91dChjb2xvclN3YXRjaGVzSG92ZXIoJCh0aGlzKSksIDEwMCk7XG4gICAgfSk7XG5cbiAgICAvLyBjbGljayBvbiBzd2F0Y2ggLSBzaG91bGQgcmVwbGFjZSBwcm9kdWN0IGNvbnRlbnQgd2l0aCBuZXcgdmFyaWFudFxuICAgICRwZHBNYWluLm9uKCdjbGljaycsICcucHJvZHVjdC1kZXRhaWwgLnN3YXRjaGFuY2hvcicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKCQodGhpcykucGFyZW50cygnbGknKS5oYXNDbGFzcygndW5zZWxlY3RhYmxlJykpIHsgcmV0dXJuOyB9XG4gICAgICAgIHVwZGF0ZUNvbnRlbnQodGhpcy5ocmVmKTtcbiAgICB9KTtcblxuICAgIC8vIGNoYW5nZSBkcm9wIGRvd24gdmFyaWF0aW9uIGF0dHJpYnV0ZSAtIHNob3VsZCByZXBsYWNlIHByb2R1Y3QgY29udGVudCB3aXRoIG5ldyB2YXJpYW50XG4gICAgJHBkcE1haW4ub24oJ2NoYW5nZScsICcudmFyaWF0aW9uLXNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCQodGhpcykudmFsKCkubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuICAgICAgICB1cGRhdGVDb250ZW50KCQodGhpcykudmFsKCkpO1xuICAgIH0pO1xuICAgIC8qdmFyICRwbHBNYWluID0gJCgnI3NlYXJjaC1yZXN1bHQtaXRlbXMnKTtcbiAgICAvLyBjbGljayBvbiBzd2F0Y2ggLSBzaG91bGQgcmVwbGFjZSBwcm9kdWN0IGNvbnRlbnQgd2l0aCBuZXcgdmFyaWFudFxuICAgICRwbHBNYWluLm9uKCdjbGljaycsICcucHJvZHVjdC12YXJpYXRpb25zIC5zd2F0Y2hhbmNob3InLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJ2xpJykuaGFzQ2xhc3MoJ3Vuc2VsZWN0YWJsZScpKSB7IHJldHVybjsgfVxuICAgICAgICB1cGRhdGVQVENvbnRlbnQodGhpcyk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTsqL1xuXG4gICAgdmFyIHF1YW50aXR5Q3RhcyA9IFsnYnV0dG9uLmpzLXF1YW50aXR5LWRlY3JlYXNlLWJ1dHRvbicsICdidXR0b24uanMtcXVhbnRpdHktaW5jcmVhc2UtYnV0dG9uJ107XG4gICAgJChxdWFudGl0eUN0YXMpLmVhY2goZnVuY3Rpb24oaWR4LCBhdHRyKSB7XG4gICAgICAgICRwZHBNYWluLm9uKCdjbGljaycsIGF0dHIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRxdWFudGl0eUlucHV0ID0gJChhdHRyKS5zaWJsaW5ncygnLmpzLXByb2R1Y3QtcXVhbnRpdHktaW5wdXQnKTtcbiAgICAgICAgICAgIHZhciBxdWFudGl0eUlucHV0VmFsID0gcGFyc2VJbnQoJHF1YW50aXR5SW5wdXQudmFsKCkpO1xuICAgICAgICAgICAgdmFyIG1vZGlmaWNhdGVkUXVhbnRpdHk7XG5cbiAgICAgICAgICAgIGlmICgkKGF0dHIpLmhhc0NsYXNzKCdqcy1xdWFudGl0eS1kZWNyZWFzZS1idXR0b24nKSkge1xuICAgICAgICAgICAgICAgIG1vZGlmaWNhdGVkUXVhbnRpdHkgPSBxdWFudGl0eUlucHV0VmFsID4gMSA/IHF1YW50aXR5SW5wdXRWYWwgLSAxIDogMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoJChhdHRyKS5oYXNDbGFzcygnanMtcXVhbnRpdHktaW5jcmVhc2UtYnV0dG9uJykpIHtcbiAgICAgICAgICAgICAgICBtb2RpZmljYXRlZFF1YW50aXR5ID0gcXVhbnRpdHlJbnB1dFZhbCArIDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAkcXVhbnRpdHlJbnB1dC52YWwobW9kaWZpY2F0ZWRRdWFudGl0eSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFkZFByb2R1Y3RUb0NhcnQgPSByZXF1aXJlKCcuL3Byb2R1Y3QvYWRkVG9DYXJ0JyksXG4gICAgYWpheCA9IHJlcXVpcmUoJy4uL2FqYXgnKSxcbiAgICBsb2dpbiA9IHJlcXVpcmUoJy4uL2xvZ2luJyksXG4gICAgcXVpY2t2aWV3ID0gcmVxdWlyZSgnLi4vcXVpY2t2aWV3JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBMb2FkcyBhZGRyZXNzIGRldGFpbHMgdG8gYSBnaXZlbiBhZGRyZXNzIGFuZCBmaWxscyB0aGUgYWRkcmVzcyBmb3JtXG4gKiBAcGFyYW0ge1N0cmluZ30gYWRkcmVzc0lEIFRoZSBJRCBvZiB0aGUgYWRkcmVzcyB0byB3aGljaCBkYXRhIHdpbGwgYmUgbG9hZGVkXG4gKi9cbmZ1bmN0aW9uIHBvcHVsYXRlRm9ybShhZGRyZXNzSUQsICRmb3JtKSB7XG4gICAgLy8gbG9hZCBhZGRyZXNzIGRldGFpbHNcbiAgICB2YXIgdXJsID0gVXJscy5naWZ0UmVnQWRkICsgYWRkcmVzc0lEO1xuICAgIGFqYXguZ2V0SnNvbih7XG4gICAgICAgIHVybDogdXJsLFxuICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YSB8fCAhZGF0YS5hZGRyZXNzKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KFJlc291cmNlcy5SRUdfQUREUl9FUlJPUik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZmlsbCB0aGUgZm9ybVxuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2FkZHJlc3NpZFwiXScpLnZhbChkYXRhLmFkZHJlc3MuSUQpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2ZpcnN0bmFtZVwiXScpLnZhbChkYXRhLmFkZHJlc3MuZmlyc3ROYW1lKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9sYXN0bmFtZVwiXScpLnZhbChkYXRhLmFkZHJlc3MubGFzdE5hbWUpO1xuICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiX2FkZHJlc3MxXCJdJykudmFsKGRhdGEuYWRkcmVzcy5hZGRyZXNzMSk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfYWRkcmVzczJcIl0nKS52YWwoZGF0YS5hZGRyZXNzLmFkZHJlc3MyKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9jaXR5XCJdJykudmFsKGRhdGEuYWRkcmVzcy5jaXR5KTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9jb3VudHJ5XCJdJykudmFsKGRhdGEuYWRkcmVzcy5jb3VudHJ5Q29kZSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAkZm9ybS5maW5kKCdbbmFtZSQ9XCJfcG9zdGFsXCJdJykudmFsKGRhdGEuYWRkcmVzcy5wb3N0YWxDb2RlKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9zdGF0ZVwiXScpLnZhbChkYXRhLmFkZHJlc3Muc3RhdGVDb2RlKTtcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIl9waG9uZVwiXScpLnZhbChkYXRhLmFkZHJlc3MucGhvbmUpO1xuICAgICAgICAgICAgLy8gJGZvcm0ucGFyZW50KCdmb3JtJykudmFsaWRhdGUoKS5mb3JtKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgZXZlbnRzIGZvciB0aGUgZ2lmdCByZWdpc3RyYXRpb25cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUV2ZW50cygpIHtcbiAgICB2YXIgJGV2ZW50QWRkcmVzc0Zvcm0gPSAkKCdmb3JtW25hbWUkPVwiX2dpZnRyZWdpc3RyeVwiXScpLFxuICAgICAgICAkYmVmb3JlQWRkcmVzcyA9ICRldmVudEFkZHJlc3NGb3JtLmZpbmQoJ2ZpZWxkc2V0W25hbWU9XCJhZGRyZXNzLWJlZm9yZVwiXScpLFxuICAgICAgICAkYWZ0ZXJBZGRyZXNzID0gJGV2ZW50QWRkcmVzc0Zvcm0uZmluZCgnZmllbGRzZXRbbmFtZT1cImFkZHJlc3MtYWZ0ZXJcIl0nKTtcblxuICAgICQoJy51c2VwcmVldmVudCcpLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZmlsdGVyIG91dCBzdG9yZWZyb250IHRvb2xraXRcbiAgICAgICAgJCgnOmlucHV0JywgJGJlZm9yZUFkZHJlc3MpLm5vdCgnW2lkXj1cImV4dFwiXScpLm5vdCgnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NCZWZvcmVMaXN0XCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZmllbGROYW1lID0gJCh0aGlzKS5hdHRyKCduYW1lJyksXG4gICAgICAgICAgICAgICAgJGFmdGVyRmllbGQgPSAkYWZ0ZXJBZGRyZXNzLmZpbmQoJ1tuYW1lPVwiJyArIGZpZWxkTmFtZS5yZXBsYWNlKCdCZWZvcmUnLCAnQWZ0ZXInKSArICdcIl0nKTtcbiAgICAgICAgICAgICRhZnRlckZpZWxkLnZhbCgkKHRoaXMpLnZhbCgpKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgJGV2ZW50QWRkcmVzc0Zvcm0ub24oJ2NoYW5nZScsICdzZWxlY3RbbmFtZSQ9XCJfYWRkcmVzc0JlZm9yZUxpc3RcIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhZGRyZXNzSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoYWRkcmVzc0lELmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAgICAgcG9wdWxhdGVGb3JtKGFkZHJlc3NJRCwgJGJlZm9yZUFkZHJlc3MpO1xuICAgIH0pXG4gICAgLm9uKCdjaGFuZ2UnLCAnc2VsZWN0W25hbWUkPVwiX2FkZHJlc3NBZnRlckxpc3RcIl0nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhZGRyZXNzSUQgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICBpZiAoYWRkcmVzc0lELmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICAgICAgcG9wdWxhdGVGb3JtKGFkZHJlc3NJRCwgJGFmdGVyQWRkcmVzcyk7XG4gICAgfSk7XG5cbiAgICAkKCcuaXRlbS1saXN0Jykub24oJ2NsaWNrJywgJy5pdGVtLWVkaXQtZGV0YWlscyBhJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgcHJvZHVjdExpc3RJRCA9ICQoJ2lucHV0W25hbWU9cHJvZHVjdExpc3RJRF0nKS52YWwoKTtcbiAgICAgICAgcXVpY2t2aWV3LnNob3coe1xuICAgICAgICAgICAgdXJsOiBlLnRhcmdldC5ocmVmLFxuICAgICAgICAgICAgc291cmNlOiAnZ2lmdHJlZ2lzdHJ5JyxcbiAgICAgICAgICAgIHByb2R1Y3RsaXN0aWQ6IHByb2R1Y3RMaXN0SURcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG4gICAgYWRkUHJvZHVjdFRvQ2FydCgpO1xuICAgIGxvZ2luLmluaXQoKTtcbiAgICB1dGlsLnNldERlbGV0ZUNvbmZpcm1hdGlvbignLml0ZW0tbGlzdCcsIFN0cmluZy5mb3JtYXQoUmVzb3VyY2VzLkNPTkZJUk1fREVMRVRFLCBSZXNvdXJjZXMuVElUTEVfR0lGVFJFR0lTVFJZKSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29tcGFyZVdpZGdldCA9IHJlcXVpcmUoJy4uL2NvbXBhcmUtd2lkZ2V0JyksXG4gICAgcHJvZHVjdFRpbGUgPSByZXF1aXJlKCcuLi9wcm9kdWN0LXRpbGUnKSxcbiAgICBwcm9ncmVzcyA9IHJlcXVpcmUoJy4uL3Byb2dyZXNzJyksXG4gICAgYWRkVG9DYXJ0ID0gcmVxdWlyZSgnLi9wcm9kdWN0L2FkZFRvQ2FydCcpLFxuICAgIHZhcmlhbnQgPSByZXF1aXJlKCcuL3Byb2R1Y3QvdmFyaWFudCcpLFxuICAgIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbmZ1bmN0aW9uIGluZmluaXRlU2Nyb2xsKCkge1xuICAgIC8vIGdldHRpbmcgdGhlIGhpZGRlbiBkaXYsIHdoaWNoIGlzIHRoZSBwbGFjZWhvbGRlciBmb3IgdGhlIG5leHQgcGFnZVxuICAgIHZhciBsb2FkaW5nUGxhY2VIb2xkZXIgPSAkKCcuaW5maW5pdGUtc2Nyb2xsLXBsYWNlaG9sZGVyW2RhdGEtbG9hZGluZy1zdGF0ZT1cInVubG9hZGVkXCJdJyk7XG4gICAgLy8gZ2V0IHVybCBoaWRkZW4gaW4gRE9NXG4gICAgdmFyIGdyaWRVcmwgPSBsb2FkaW5nUGxhY2VIb2xkZXIuYXR0cignZGF0YS1ncmlkLXVybCcpO1xuXG4gICAgaWYgKGxvYWRpbmdQbGFjZUhvbGRlci5sZW5ndGggPT09IDEgJiYgdXRpbC5lbGVtZW50SW5WaWV3cG9ydChsb2FkaW5nUGxhY2VIb2xkZXIuZ2V0KDApLCAyNTApKSB7XG4gICAgICAgIC8vIHN3aXRjaCBzdGF0ZSB0byAnbG9hZGluZydcbiAgICAgICAgLy8gLSBzd2l0Y2hlcyBzdGF0ZSwgc28gdGhlIGFib3ZlIHNlbGVjdG9yIGlzIG9ubHkgbWF0Y2hpbmcgb25jZVxuICAgICAgICAvLyAtIHNob3dzIGxvYWRpbmcgaW5kaWNhdG9yXG4gICAgICAgIGxvYWRpbmdQbGFjZUhvbGRlci5hdHRyKCdkYXRhLWxvYWRpbmctc3RhdGUnLCAnbG9hZGluZycpO1xuICAgICAgICBsb2FkaW5nUGxhY2VIb2xkZXIuYWRkQ2xhc3MoJ2luZmluaXRlLXNjcm9sbC1sb2FkaW5nJyk7XG5cblxuICAgICAgICAvLyBuYW1lZCB3cmFwcGVyIGZ1bmN0aW9uLCB3aGljaCBjYW4gZWl0aGVyIGJlIGNhbGxlZCwgaWYgY2FjaGUgaXMgaGl0LCBvciBhamF4IHJlcHNvbnNlIGlzIHJlY2VpdmVkXG4gICAgICAgIHZhciBmaWxsRW5kbGVzc1Njcm9sbENodW5rID0gZnVuY3Rpb24gKGh0bWwpIHtcbiAgICAgICAgICAgIGxvYWRpbmdQbGFjZUhvbGRlci5yZW1vdmVDbGFzcygnaW5maW5pdGUtc2Nyb2xsLWxvYWRpbmcnKTtcbiAgICAgICAgICAgIGxvYWRpbmdQbGFjZUhvbGRlci5hdHRyKCdkYXRhLWxvYWRpbmctc3RhdGUnLCAnbG9hZGVkJyk7XG4gICAgICAgICAgICAkKCdkaXYuc2VhcmNoLXJlc3VsdC1jb250ZW50JykuYXBwZW5kKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIG9sZCBjb25kaXRpb24gZm9yIGNhY2hpbmcgd2FzIGAnc2Vzc2lvblN0b3JhZ2UnIGluIHdpbmRvdyAmJiBzZXNzaW9uU3RvcmFnZVtcInNjcm9sbC1jYWNoZV9cIiArIGdyaWRVcmxdYFxuICAgICAgICAvLyBpdCB3YXMgcmVtb3ZlZCB0byB0ZW1wb3JhcmlseSBhZGRyZXNzIFJBUC0yNjQ5XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdodG1sJyxcbiAgICAgICAgICAgIHVybDogZ3JpZFVybCxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIC8vIHB1dCByZXNwb25zZSBpbnRvIGNhY2hlXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2VbJ3Njcm9sbC1jYWNoZV8nICsgZ3JpZFVybF0gPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG5vdGhpbmcgdG8gY2F0Y2ggaW4gY2FzZSBvZiBvdXQgb2YgbWVtb3J5IG9mIHNlc3Npb24gc3RvcmFnZVxuICAgICAgICAgICAgICAgICAgICAvLyBpdCB3aWxsIGZhbGwgYmFjayB0byBsb2FkIHZpYSBhamF4XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSBVSVxuICAgICAgICAgICAgICAgIGZpbGxFbmRsZXNzU2Nyb2xsQ2h1bmsocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHByb2R1Y3RUaWxlLmluaXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmaWx0ZXJNdWx0aVNlbGVjdGlvbigpIHtcblxuICAgICQoJyNzZWNvbmRhcnkuaGlkZUNvbnRlbnQnKS5vbignY2xpY2snLCAnLnJlZmluZW1lbnQtbGluaywgW2lkKj1cInN3YXRjaC1cIl0sW2lkKj1cInNpbXBsZS1hdHRyLVwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIC8vZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGxldCBzZWxlY3RlZEl0ZW0gPSAkKHRoaXMpO1xuICAgICAgICAgICAgbGV0IHVybFBhcmFtID0gc2VsZWN0ZWRJdGVtLmRhdGEoXCJwYXJhbVwiKTtcbiAgICAgICAgICAgIGlmKCF1cmxQYXJhbSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpc1NlbGVjdGVkID0gc2VsZWN0ZWRJdGVtLmNsb3Nlc3QoJ2xpJykuaGFzQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGxldCB1cmxGaWx0ZXJzID0gJCgnI3NlY29uZGFyeScpLmRhdGEoJ3VybEZpbHRlcnMnKTtcbiAgICAgICAgICAgIGxldCB1cmxPYmogPSBuZXcgVVJMKHVybFBhcmFtKTtcbiAgICAgICAgICAgIGxldCBiYXNlVXJsID0gbmV3IFVSTCh1cmxPYmouaHJlZi5yZXBsYWNlKHVybE9iai5zZWFyY2gsJycpKTsgICAgICAgICAgICBcbiAgICAgICAgICAgIGxldCB0bXBVUkwgID0gbmV3IFVSTCh1cmxGaWx0ZXJzID8gdXJsRmlsdGVycyA6IGJhc2VVcmwpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgaXNHcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGdyb3VwQ2xhc3MgPSAnLnJlZi1kZWYtJyArIHNlbGVjdGVkSXRlbS5kYXRhKCdyZWZpbmVtZW50aWQnKTtcbiAgICAgICAgICAgIGxldCByZWZEZWZHcm91cCA9IHtcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50aWQ6IHNlbGVjdGVkSXRlbS5kYXRhKCdyZWZpbmVtZW50aWQnKSxcbiAgICAgICAgICAgICAgICByZWZpbmVtZW50dmFsdWU6IHNlbGVjdGVkSXRlbS5kYXRhKCdyZWZpbmVtZW50dmFsdWUnKSxcbiAgICAgICAgICAgICAgICBwcmVmTm86c2VsZWN0ZWRJdGVtLmRhdGEoJ2xvb3BzdGF0ZWluZGV4JykgPyAgTnVtYmVyKHNlbGVjdGVkSXRlbS5kYXRhKCdsb29wc3RhdGVpbmRleCcpKSA6IDEsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRWYWx1ZXM6W11cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChncm91cENsYXNzKSB7XG4gICAgICAgICAgICAgICAgaXNHcm91cCA9IHRydWU7XG4gICAgICAgICAgICAgICAgJChncm91cENsYXNzKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcmRJdGVtID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmRJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJkSXRlbS5jbG9zZXN0KCdsaScpLmhhc0NsYXNzKCdzZWxlY3RlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihzZWxlY3RlZEl0ZW0uZGF0YSgncmVmaW5lbWVudGlkJykgIT09IHJkSXRlbS5kYXRhKCdyZWZpbmVtZW50dmFsdWUnKSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmRGVmR3JvdXAuc2VsZWN0ZWRWYWx1ZXMucHVzaChyZEl0ZW0uZGF0YSgncmVmaW5lbWVudHZhbHVlJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmICh1cmxPYmopIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNTZWxlY3RlZCkgeyAvLyBpc1NlbGVjdGVkICB0aGVuIHJlbW92ZSBmcm9tIHNlYXJjaFBhcmFtc1xuICAgICAgICAgICAgICAgICAgICAvLyBGaWx0ZXIgcGFyYW1zIHRvIGRlbGV0ZVxuICAgICAgICAgICAgICAgICAgICB1cmxPYmouc2VhcmNoUGFyYW1zLmZvckVhY2goKHZhbHVlUkEsIGtleVJBKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSB2YWx1ZVJBO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGtleSA9IGtleVJBO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVmRGVmR3JvdXAucmVmaW5lbWVudGlkID09PSB2YWx1ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5UkEuaW5kZXhPZigncHJlZm4nKSAhPSAtMSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICdwcmVmbicgKyByZWZEZWZHcm91cC5wcmVmTm87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5UkEuaW5kZXhPZigncHJlZnYnKSAhPSAtMSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSByZWZEZWZHcm91cC5yZWZpbmVtZW50dmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0gJ3ByZWZ2JyArIHJlZkRlZkdyb3VwLnByZWZObztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihyZWZEZWZHcm91cC5yZWZpbmVtZW50aWQgIT09IHZhbHVlICYmIHJlZkRlZkdyb3VwLnNlbGVjdGVkVmFsdWVzLmluY2x1ZGVzKHZhbHVlKSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZkRlZkdyb3VwLnNlbGVjdGVkVmFsdWVzPSByZWZEZWZHcm91cC5zZWxlY3RlZFZhbHVlcy5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gcmVmRGVmR3JvdXAuc2VsZWN0ZWRWYWx1ZXMuam9pbignfCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIWJhc2VVcmwuc2VhcmNoUGFyYW1zLmhhcyhrZXksdmFsdWUpIHx8ICF2YWx1ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXZhbHVlKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wVVJMLnNlYXJjaFBhcmFtcy5kZWxldGUoa2V5KTsgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wVVJMLnNlYXJjaFBhcmFtcy5zZXQoa2V5LHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAvLyBVWCB1bnNlbGVjdFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEl0ZW0uY2xvc2VzdCgnbGknKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRJdGVtLmZpbmQoJ2knKS5hdHRyKCdjbGFzcycsJ2ZhIGZhLXNxdWFyZS1vIGZhLWxnJyk7XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIGFwcGVuZCB0byBxdWVyeXN0cmluZ1xuICAgICAgICAgICAgICAgICAgICB1cmxPYmouc2VhcmNoUGFyYW1zLmZvckVhY2goKHZhbHVlUkEsIGtleVJBKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSB2YWx1ZVJBO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGtleSA9IGtleVJBO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVmRGVmR3JvdXAucmVmaW5lbWVudGlkID09PSB2YWx1ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5UkEuaW5kZXhPZigncHJlZm4nKSAhPSAtMSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICdwcmVmbicgKyByZWZEZWZHcm91cC5wcmVmTm87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5UkEuaW5kZXhPZigncHJlZnYnKSAhPSAtMSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSByZWZEZWZHcm91cC5yZWZpbmVtZW50dmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVmRGVmR3JvdXAucmVmaW5lbWVudGlkICE9PSB2YWx1ZSAmJiAhcmVmRGVmR3JvdXAuc2VsZWN0ZWRWYWx1ZXMuaW5jbHVkZXModmFsdWUpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0gJ3ByZWZ2JyArIHJlZkRlZkdyb3VwLnByZWZObztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmRGVmR3JvdXAuc2VsZWN0ZWRWYWx1ZXMucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gcmVmRGVmR3JvdXAuc2VsZWN0ZWRWYWx1ZXMuam9pbignfCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdG1wVVJMLnNlYXJjaFBhcmFtcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAvLyBVWCBzZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRJdGVtLmNsb3Nlc3QoJ2xpJykuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkSXRlbS5maW5kKCdpJykuYXR0cignY2xhc3MnLCdmYSBmYS1jaGVjay1zcXVhcmUtbyBmYS1sZycpO1xuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJCgnI3NlY29uZGFyeScpLmRhdGEoJ3VybEZpbHRlcnMnLCB0bXBVUkwuaHJlZik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGZlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRGVidWdnaW5nOiAnLCBmZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG59XG5cblxuZnVuY3Rpb24gY2xvc2VUaGlja0luaXQoKXtcbiAgICB2YXIgJG1haW4gPSAkKCcjbWFpbicpO1xuICAgIC8vJCgnI3NlY29uZGFyeScpLmFwcGVuZChcIjxkaXYgaWQ9J2Nsb3NldGhpY2snIGNsYXNzPSdhcHBseWZpbHRlcnMnPjwvZGl2PlwiKTtcbiAgICAkKCcuYXBwbHlmaWx0ZXJzJykub24oJ2NsaWNrJyxmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCB1cmxGaWx0ZXJzID0gJCgnI3NlY29uZGFyeScpLmRhdGEoJ3VybEZpbHRlcnMnKTtcbiAgICAgICAgaWYodXJsRmlsdGVycykge1xuICAgICAgICAgICAgbGV0IHRtcFVSTCAgPSBuZXcgVVJMKHVybEZpbHRlcnMpO1xuICAgICAgICAgICAgdXBkYXRlUHJvZHVjdExpc3RpbmcodG1wVVJMLmhyZWYpO1xuICAgICAgICB9XG4gICAgICAgICQoXCIjc2Vjb25kYXJ5XCIpLnJlbW92ZUNsYXNzKCdoaWRlQ29udGVudCcpO1xuICAgICAgICAvLyQoXCIuYy1vdmVybGF5XCIpLmhpZGUoKTtcbiAgICB9KTtcbiAgICAvLyBoYW5kbGUgdG9nZ2xlIHJlZmluZW1lbnQgc2VjdGlvblxuICAgIC8qJG1haW4ub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PSBcIkVzY2FwZVwiKSB7XG4gICAgICAgICAgICAkKFwiI3NlY29uZGFyeVwiKS5yZW1vdmVDbGFzcygnaGlkZUNvbnRlbnQnKTtcbiAgICAgICAgICAgICQoXCIuYy1vdmVybGF5XCIpLmhpZGUoKTtcbiAgICAgICAgfVxuICAgIH0pOyovXG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIHJlcGxhY2VzIGJyZWFkY3J1bWJzLCBsZWZ0aGFuZCBuYXYgYW5kIHByb2R1Y3QgbGlzdGluZyB3aXRoIGFqYXggYW5kIHB1dHMgYSBsb2FkaW5nIGluZGljYXRvciBvdmVyIHRoZSBwcm9kdWN0IGxpc3RpbmdcbiAqL1xuZnVuY3Rpb24gdXBkYXRlUHJvZHVjdExpc3RpbmcodXJsKSB7XG4gICAgaWYgKCF1cmwgfHwgdXJsID09PSB3aW5kb3cubG9jYXRpb24uaHJlZikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHByb2dyZXNzLnNob3coJCgnLnNlYXJjaC1yZXN1bHQtY29udGVudCcpKTtcbiAgICAvL3V0aWwuc2Nyb2xsQnJvd3NlcigwKTsvLyBzZW5kIHRvIHRoZSBib3R0b21cbiAgICAkKCcjbWFpbicpLmxvYWQodXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ2Zvcm1hdCcsICdhamF4JyksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29tcGFyZVdpZGdldC5pbml0KCk7XG4gICAgICAgIHByb2R1Y3RUaWxlLmluaXQoKTtcbiAgICAgICAgcHJvZ3Jlc3MuaGlkZSgpO1xuICAgICAgICBjbG9zZVRoaWNrSW5pdCgpO1xuICAgICAgICBoaXN0b3J5LnB1c2hTdGF0ZSh1bmRlZmluZWQsICcnLCB1cmwpO1xuICAgICAgICB2YXIgJHRpbGVzID0gJCgnLnRpbGVzLWNvbnRhaW5lciAucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIGlmICgkdGlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJHRpbGVzLnN5bmNIZWlnaHQoKS5lYWNoKGZ1bmN0aW9uIChpZHgpIHtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLmRhdGEoJ2lkeCcsIGlkeCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBldmVudHMgZm9yIHRoZSBmb2xsb3dpbmcgZWxlbWVudHM6PGJyLz5cbiAqIDxwPnJlZmluZW1lbnQgYmxvY2tzPC9wPlxuICogPHA+dXBkYXRpbmcgZ3JpZDogcmVmaW5lbWVudHMsIHBhZ2luYXRpb24sIGJyZWFkY3J1bWI8L3A+XG4gKiA8cD5pdGVtIGNsaWNrPC9wPlxuICogPHA+c29ydGluZyBjaGFuZ2VzPC9wPlxuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgIHZhciAkbWFpbiA9ICQoJyNtYWluJyk7XG4gICAgLy8gY29tcGFyZSBjaGVja2VkXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJ2lucHV0W3R5cGU9XCJjaGVja2JveFwiXS5jb21wYXJlLWNoZWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2IgPSAkKHRoaXMpO1xuICAgICAgICB2YXIgdGlsZSA9IGNiLmNsb3Nlc3QoJy5wcm9kdWN0LXRpbGUnKTtcblxuICAgICAgICB2YXIgZnVuYyA9IHRoaXMuY2hlY2tlZCA/IGNvbXBhcmVXaWRnZXQuYWRkUHJvZHVjdCA6IGNvbXBhcmVXaWRnZXQucmVtb3ZlUHJvZHVjdDtcbiAgICAgICAgdmFyIGl0ZW1JbWcgPSB0aWxlLmZpbmQoJy5wcm9kdWN0LWltYWdlIGEgaW1nJykuZmlyc3QoKTtcbiAgICAgICAgZnVuYyh7XG4gICAgICAgICAgICBpdGVtaWQ6IHRpbGUuZGF0YSgnaXRlbWlkJyksXG4gICAgICAgICAgICB1dWlkOiB0aWxlWzBdLmlkLFxuICAgICAgICAgICAgaW1nOiBpdGVtSW1nLFxuICAgICAgICAgICAgY2I6IGNiXG4gICAgICAgIH0pO1xuXG4gICAgfSk7XG4gICAgJCggd2luZG93ICkubG9hZChmdW5jdGlvbigpIHtcbiAgICBcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgXG5cdFx0ICAgICQoJy5wcm9kdWN0LWxpc3Rpbmcubm9oaXQgLnNsaWNrJykuc2xpY2soe1xuXHRcdCAgICAgICAgaW5maW5pdGU6IGZhbHNlLFxuXHRcdCAgICAgICAgc2xpZGVzVG9TaG93OiAzLFxuXHRcdCAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG5cdFx0ICAgICAgICBkb3RzOiBmYWxzZVxuXHRcdCAgICB9KTtcbiAgICBcdH0sIDIwMDApO1xuICAgICAgICB2YXIgJHRpbGVzID0gJCgnLnRpbGVzLWNvbnRhaW5lciAucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIGlmICgkdGlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJHRpbGVzLnN5bmNIZWlnaHQoKS5lYWNoKGZ1bmN0aW9uIChpZHgpIHtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLmRhdGEoJ2lkeCcsIGlkeCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIFxuXG4gICAgLy8gaGFuZGxlIHRvZ2dsZSByZWZpbmVtZW50IGJsb2Nrc1xuICAgICRtYWluLm9uKCdjbGljaycsICcucmVmaW5lbWVudCBoMycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnZXhwYW5kZWQnKVxuICAgICAgICAuc2libGluZ3MoJ3VsJykudG9nZ2xlKCk7XG4gICAgfSk7XG5cbiAgICAvLyBoYW5kbGUgZXZlbnRzIGZvciB1cGRhdGluZyBncmlkXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5yZWZpbmVtZW50cyBhLCAucGFnaW5hdGlvbiBhLCAuYnJlYWRjcnVtYi1yZWZpbmVtZW50LXZhbHVlIGEnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAvLyBkb24ndCBpbnRlcmNlcHQgZm9yIGNhdGVnb3J5IGFuZCBmb2xkZXIgcmVmaW5lbWVudHMsIGFzIHdlbGwgYXMgdW5zZWxlY3RhYmxlXG4gICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJy5jYXRlZ29yeS1yZWZpbmVtZW50JykubGVuZ3RoID4gMCB8fCAkKHRoaXMpLnBhcmVudHMoJy5mb2xkZXItcmVmaW5lbWVudCcpLmxlbmd0aCA+IDAgfHwgJCh0aGlzKS5wYXJlbnQoKS5oYXNDbGFzcygndW5zZWxlY3RhYmxlJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHRoaXMuaHJlZik7XG4gICAgfSk7XG5cbiAgICAvLyBoYW5kbGUgZXZlbnRzIGl0ZW0gY2xpY2suIGFwcGVuZCBwYXJhbXMuXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5wcm9kdWN0LXRpbGUgYTpub3QoXCIucXVpY2t2aWV3YnV0dG9uXCIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYSA9ICQodGhpcyk7XG4gICAgICAgIC8vIGdldCBjdXJyZW50IHBhZ2UgcmVmaW5lbWVudCB2YWx1ZXNcbiAgICAgICAgdmFyIHdsID0gd2luZG93LmxvY2F0aW9uO1xuXG4gICAgICAgIHZhciBxc1BhcmFtcyA9ICh3bC5zZWFyY2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLnNlYXJjaC5zdWJzdHIoMSkpIDoge307XG4gICAgICAgIHZhciBoYXNoUGFyYW1zID0gKHdsLmhhc2gubGVuZ3RoID4gMSkgPyB1dGlsLmdldFF1ZXJ5U3RyaW5nUGFyYW1zKHdsLmhhc2guc3Vic3RyKDEpKSA6IHt9O1xuXG4gICAgICAgIC8vIG1lcmdlIGhhc2ggcGFyYW1zIHdpdGggcXVlcnlzdHJpbmcgcGFyYW1zXG4gICAgICAgIHZhciBwYXJhbXMgPSAkLmV4dGVuZChoYXNoUGFyYW1zLCBxc1BhcmFtcyk7XG4gICAgICAgIGlmICghcGFyYW1zLnN0YXJ0KSB7XG4gICAgICAgICAgICBwYXJhbXMuc3RhcnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIGdldCB0aGUgaW5kZXggb2YgdGhlIHNlbGVjdGVkIGl0ZW0gYW5kIHNhdmUgYXMgc3RhcnQgcGFyYW1ldGVyXG4gICAgICAgIHZhciB0aWxlID0gYS5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyk7XG4gICAgICAgIHZhciBpZHggPSB0aWxlLmRhdGEoJ2lkeCcpID8gKyB0aWxlLmRhdGEoJ2lkeCcpIDogMDtcblxuICAgICAgICAvLyBjb252ZXJ0IHBhcmFtcy5zdGFydCB0byBpbnRlZ2VyIGFuZCBhZGQgaW5kZXhcbiAgICAgICAgcGFyYW1zLnN0YXJ0ID0gKCtwYXJhbXMuc3RhcnQpICsgKGlkeCArIDEpO1xuICAgICAgICAvLyBzZXQgdGhlIGhhc2ggYW5kIGFsbG93IG5vcm1hbCBhY3Rpb24gdG8gY29udGludWVcbiAgICAgICAgYVswXS5oYXNoID0gJC5wYXJhbShwYXJhbXMpO1xuICAgIH0pO1xuXG4gICAgLy8gaGFuZGxlIHNvcnRpbmcgY2hhbmdlXG4gICAgJG1haW4ub24oJ2NoYW5nZScsICcuc29ydC1ieSBzZWxlY3QnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKCQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCkpO1xuICAgIH0pXG4gICAgLm9uKCdjaGFuZ2UnLCAnLml0ZW1zLXBlci1wYWdlIHNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlZmluZVVybCA9ICQodGhpcykuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykudmFsKCk7XG4gICAgICAgIGlmIChyZWZpbmVVcmwgPT09ICdJTkZJTklURV9TQ1JPTEwnKSB7XG4gICAgICAgICAgICAkKCdodG1sJykuYWRkQ2xhc3MoJ2luZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJCgnaHRtbCcpLmFkZENsYXNzKCdkaXNhYmxlLWluZmluaXRlLXNjcm9sbCcpLnJlbW92ZUNsYXNzKCdpbmZpbml0ZS1zY3JvbGwnKTtcbiAgICAgICAgICAgIHVwZGF0ZVByb2R1Y3RMaXN0aW5nKHJlZmluZVVybCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICAvKiogbmV3IGVuaGFuY2VtZW50cyAqL1xuICAgIC8vIGhhbmRsZSB0b2dnbGUgcmVmaW5lbWVudCBzZWN0aW9uXG4gICAgJG1haW4ub24oJ2NsaWNrJywgJy5maWx0ZXJzYnRuJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgJHNlY29uZGFyeSA9ICAkKFwiI3NlY29uZGFyeVwiKTtcbiAgICAgICAgbGV0ICRwcmltYXJ5ID0gJChcIiNwcmltYXJ5XCIpO1xuICAgICAgICBsZXQgZGlzcGxheSA9ICEkc2Vjb25kYXJ5Lmhhc0NsYXNzKCdoaWRlQ29udGVudCcpO1xuICAgICAgICBpZihkaXNwbGF5KXtcbiAgICAgICAgICAgICRzZWNvbmRhcnkuYWRkQ2xhc3MoJ2hpZGVDb250ZW50Jyk7ICAgIFxuICAgICAgICAgICAgJHByaW1hcnkuYWRkQ2xhc3MoJ2Z1bGwtd2lkdGgnKTtcbiAgICAgICAgICAgICQoJy5maWx0ZXJzYnRuIC5maWx0ZXJidXR0b25oaWRlJykuaGlkZSgpO1xuICAgICAgICAgICAgJCgnLmZpbHRlcnNidG4gLmZpbHRlcmJ1dHRvbicpLnNob3coKTtcbiAgICAgICAgICAgIGZpbHRlck11bHRpU2VsZWN0aW9uKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkc2Vjb25kYXJ5LnJlbW92ZUNsYXNzKCdoaWRlQ29udGVudCcpO1xuICAgICAgICAgICAgJHByaW1hcnkucmVtb3ZlQ2xhc3MoJ2Z1bGwtd2lkdGgnKTsgXG4gICAgICAgICAgICAkKCcuZmlsdGVyc2J0biAuZmlsdGVyYnV0dG9uaGlkZScpLnNob3coKTtcbiAgICAgICAgICAgICQoJy5maWx0ZXJzYnRuIC5maWx0ZXJidXR0b24nKS5oaWRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGNvbnNvbGUubG9nKFwiZGlzcGxheVwiLGRpc3BsYXkpO1xuICAgICAgICBcbiAgICB9KTtcblxuICAgIGNsb3NlVGhpY2tJbml0KCk7XG4gICAgXG4gICAgLy8gJChcIi50b3RhbHByb2R1Y3RudW1iZXJcIikuZGV0YWNoKCkuYXBwZW5kVG8oJyNwcmltYXJ5IC5zbG90LWdyaWQtaGVhZGVyIC5odG1sLXNsb3QtY29udGFpbmVyJyk7XG4gICAgXG4gICAgJG1haW4ub24oJ2NsaWNrJywnLmJ1dHRvbmxvYWRtb3JlJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGxldCBsb2FkUGFnZXNVcmxzID0gJCh0aGlzKS5kYXRhKFwibG9hZHBhZ2VzXCIpO1xuICAgICAgICBpZiAobG9hZFBhZ2VzVXJscyAmJiBsb2FkUGFnZXNVcmxzLmxlbmd0aCA+IDApIHsgLy8gQ2hlY2sgaWYgbG9hZFBhZ2VzVXJscyBpcyBkZWZpbmVkXG4gICAgICAgICAgICAgICAgdXBkYXRlUHJvZHVjdExpc3RpbmcobG9hZFBhZ2VzVXJsc1swXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJCgnLmJ1dHRvbmxvYWRtb3JlJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgIC8vVE9ETzogU2hvdyBtZXNzYWdlIHdpdGggbm8gbW9yZSByZXN1bHRzLiBcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGFkZFRvQ2FydCgpO1xuICAgIHZhcmlhbnQoKTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIGNvbXBhcmVXaWRnZXQuaW5pdCgpO1xuICAgIGlmIChTaXRlUHJlZmVyZW5jZXMuTElTVElOR19JTkZJTklURV9TQ1JPTEwpIHtcbiAgICAgICAgJCh3aW5kb3cpLm9uKCdzY3JvbGwnLCBpbmZpbml0ZVNjcm9sbCk7XG4gICAgfVxuICAgIHByb2R1Y3RUaWxlLmluaXQoKTtcbiAgICBpbml0aWFsaXplRXZlbnRzKCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNhcm91c2VsQ29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlncy9jYXJvdXNlbCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbmV4cG9ydHMuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKCcjaG9tZXBhZ2Utc2xpZGVyIC5zbGljaycpLnNsaWNrKHtcbiAgICAgICAgaW5maW5pdGU6IHRydWUsXG4gICAgICAgIHNsaWRlc1RvU2hvdzogMSxcbiAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG4gICAgICAgIGF1dG9wbGF5OiB0cnVlLFxuICAgICAgICBkb3RzOiB0cnVlLFxuICAgICAgICBhcnJvd3M6IGZhbHNlXG4gICAgfSk7XG5cbiAgICAkKCcjdmVydGljYWwtY2Fyb3VzZWwgLnNsaWNrJykuc2xpY2soe1xuICAgICAgICBpbmZpbml0ZTogZmFsc2UsXG4gICAgICAgIHNsaWRlc1RvU2hvdzogMSxcbiAgICAgICAgc2xpZGVzVG9TY3JvbGw6IDEsXG4gICAgICAgIGRvdHM6IHRydWVcbiAgICB9KTtcbiAgICBcbiAgICAkKCB3aW5kb3cgKS5sb2FkKGZ1bmN0aW9uKCkge1xuICAgIFx0c2V0VGltZW91dChmdW5jdGlvbigpeyBcblx0XHQgICAgJCgnLnByb2R1Y3QtbGlzdGluZy5ob21lcGFnZSAuc2xpY2snKS5zbGljayh7XG5cdFx0ICAgICAgICBpbmZpbml0ZTogZmFsc2UsXG5cdFx0ICAgICAgICBzbGlkZXNUb1Nob3c6IDMsXG5cdFx0ICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcblx0XHQgICAgICAgIGRvdHM6IGZhbHNlXG5cdFx0ICAgIH0pO1xuICAgICAgICAgICAgdmFyIGlzTW9iID0gdXRpbC5pc01vYmlsZSgpIHx8IG1hdGNoTWVkaWEoJyhtYXgtd2lkdGg6IDU1MHB4KScpLm1hdGNoZXM7XG4gICAgICAgICAgICAkKCcuY2Fyb3VzZWwtaHAgLnByb2R1Y3QtbGlzdGluZyAuc2xpY2snKS5zbGljayh7XG5cdFx0ICAgICAgICBpbmZpbml0ZTogZmFsc2UsXG5cdFx0ICAgICAgICBzbGlkZXNUb1Nob3c6IGlzTW9iID8gMiA6IDQsXG5cdFx0ICAgICAgICBzbGlkZXNUb1Njcm9sbDogMSxcblx0XHQgICAgICAgIGRvdHM6IGZhbHNlXG5cdFx0ICAgIH0pO1xuICAgIFx0fSwgMjAwMCk7XG4gICAgfSk7XG4gICAgXG4gICAgXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGRpYWxvZyA9IHJlcXVpcmUoJy4uL2RpYWxvZycpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCgnLnN0b3JlLWRldGFpbHMtbGluaycpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdXJsOiAkKGUudGFyZ2V0KS5hdHRyKCdocmVmJylcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRkUHJvZHVjdFRvQ2FydCA9IHJlcXVpcmUoJy4vcHJvZHVjdC9hZGRUb0NhcnQnKSxcbiAgICBwYWdlID0gcmVxdWlyZSgnLi4vcGFnZScpLFxuICAgIGxvZ2luID0gcmVxdWlyZSgnLi4vbG9naW4nKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG5leHBvcnRzLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgYWRkUHJvZHVjdFRvQ2FydCgpO1xuICAgICQoJyNlZGl0QWRkcmVzcycpLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHBhZ2UucmVkaXJlY3QodXRpbC5hcHBlbmRQYXJhbVRvVVJMKFVybHMud2lzaGxpc3RBZGRyZXNzLCAnQWRkcmVzc0lEJywgJCh0aGlzKS52YWwoKSkpO1xuICAgIH0pO1xuXG4gICAgLy9hZGQganMgbG9naWMgdG8gcmVtb3ZlIHRoZSAsIGZyb20gdGhlIHF0eSBmZWlsZCB0byBwYXNzIHJlZ2V4IGV4cHJlc3Npb24gb24gY2xpZW50IHNpZGVcbiAgICAkKCcub3B0aW9uLXF1YW50aXR5LWRlc2lyZWQgaW5wdXQnKS5vbignZm9jdXNvdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQodGhpcykudmFsKCQodGhpcykudmFsKCkucmVwbGFjZSgnLCcsICcnKSk7XG4gICAgfSk7XG5cbiAgICBsb2dpbi5pbml0KCk7XG5cbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBpbWFnZXNMb2FkZWQgPSByZXF1aXJlKCdpbWFnZXNsb2FkZWQnKSxcbiAgICBxdWlja3ZpZXcgPSByZXF1aXJlKCcuL3F1aWNrdmlldycpO1xuXG5mdW5jdGlvbiBpbml0UXVpY2tWaWV3QnV0dG9ucygpIHtcbiAgICAkKCcudGlsZXMtY29udGFpbmVyIC5wcm9kdWN0LWltYWdlJykub24oJ21vdXNlZW50ZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkcXZCdXR0b24gPSAkKHRoaXMpLmZpbmQoJy5qcy1xdWlja3ZpZXdidXR0b24nKTtcbiAgICAgICAgaWYgKCRxdkJ1dHRvbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICRxdkJ1dHRvbiA9ICQoJzxhIGNsYXNzPVwicXVpY2t2aWV3IGJ1dHRvbiBzbWFsbCBxdWlja3ZpZXdidXR0b24ganMtcXVpY2t2aWV3YnV0dG9uXCI+PGkgY2xhc3M9XCJmYSBmYS1hcnJvd3MtYWx0XCI+PC9pPiAnICsgUmVzb3VyY2VzLlFVSUNLX1ZJRVcgKyAnPC9hPicpO1xuICAgICAgICB9XG4gICAgICAgIHZhciAkbGluayA9ICQodGhpcykuZmluZCgnLnRodW1iLWxpbmsnKTtcbiAgICAgICAgJHF2QnV0dG9uLmF0dHIoe1xuICAgICAgICAgICAgJ2hyZWYnOiAkbGluay5hdHRyKCdocmVmJyksXG4gICAgICAgICAgICAndGl0bGUnOiAkbGluay5hdHRyKCd0aXRsZScpXG4gICAgICAgIH0pLmFwcGVuZFRvKHRoaXMpO1xuICAgIH0pO1xuXG4gICAgJCgnYm9keScpLm9uKCdjbGljaycsICcuanMtcXVpY2t2aWV3YnV0dG9uJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBxdWlja3ZpZXcuc2hvdyh7XG4gICAgICAgICAgICB1cmw6ICQodGhpcykuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgc291cmNlOiAncXVpY2t2aWV3J1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZ3JpZFZpZXdUb2dnbGUoKSB7XG4gICAgJCgnLnRvZ2dsZS1ncmlkJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkKCcuc2VhcmNoLXJlc3VsdC1jb250ZW50JykudG9nZ2xlQ2xhc3MoJ3dpZGUtdGlsZXMnKTtcbiAgICAgICAgJCh0aGlzKS50b2dnbGVDbGFzcygnd2lkZScpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBldmVudHMgb24gdGhlIHByb2R1Y3QtdGlsZSBmb3IgdGhlIGZvbGxvd2luZyBlbGVtZW50czpcbiAqIC0gc3dhdGNoZXNcbiAqIC0gdGh1bWJuYWlsc1xuICovXG5mdW5jdGlvbiBpbml0aWFsaXplRXZlbnRzKCkge1xuICAgIGluaXRRdWlja1ZpZXdCdXR0b25zKCk7XG4gICAgZ3JpZFZpZXdUb2dnbGUoKTtcbiAgICAkKCcuc3dhdGNoLWxpc3QnKS5vbignbW91c2VsZWF2ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gUmVzdG9yZSBjdXJyZW50IHRodW1iIGltYWdlXG4gICAgICAgIHZhciAkdGlsZSA9ICQodGhpcykuY2xvc2VzdCgnLnByb2R1Y3QtdGlsZScpLFxuICAgICAgICAgICAgJHRodW1iID0gJHRpbGUuZmluZCgnLnByb2R1Y3QtaW1hZ2UgLnRodW1iLWxpbmsgaW1nJykuZXEoMCksXG4gICAgICAgICAgICBkYXRhID0gJHRodW1iLmRhdGEoJ2N1cnJlbnQnKTtcblxuICAgICAgICAkdGh1bWIuYXR0cih7XG4gICAgICAgICAgICBzcmM6IGRhdGEuc3JjLFxuICAgICAgICAgICAgYWx0OiBkYXRhLmFsdCxcbiAgICAgICAgICAgIHRpdGxlOiBkYXRhLnRpdGxlXG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgICQoJy5zd2F0Y2gtbGlzdCAuc3dhdGNoJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcygnc2VsZWN0ZWQnKSkgeyByZXR1cm47IH1cblxuICAgICAgICB2YXIgJHRpbGUgPSAkKHRoaXMpLmNsb3Nlc3QoJy5wcm9kdWN0LXRpbGUnKTtcbiAgICAgICAgJCh0aGlzKS5jbG9zZXN0KCcuc3dhdGNoLWxpc3QnKS5maW5kKCcuc3dhdGNoLnNlbGVjdGVkJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICR0aWxlLmZpbmQoJy50aHVtYi1saW5rJykuYXR0cignaHJlZicsICQodGhpcykuYXR0cignaHJlZicpKTtcbiAgICAgICAgJHRpbGUuZmluZCgnbmFtZS1saW5rJykuYXR0cignaHJlZicsICQodGhpcykuYXR0cignaHJlZicpKTtcblxuICAgICAgICB2YXIgZGF0YSA9ICQodGhpcykuY2hpbGRyZW4oJ2ltZycpLmZpbHRlcignOmZpcnN0JykuZGF0YSgndGh1bWInKTtcbiAgICAgICAgdmFyICR0aHVtYiA9ICR0aWxlLmZpbmQoJy5wcm9kdWN0LWltYWdlIC50aHVtYi1saW5rIGltZycpLmVxKDApO1xuICAgICAgICB2YXIgY3VycmVudEF0dHJzID0ge1xuICAgICAgICAgICAgc3JjOiBkYXRhLnNyYyxcbiAgICAgICAgICAgIGFsdDogZGF0YS5hbHQsXG4gICAgICAgICAgICB0aXRsZTogZGF0YS50aXRsZVxuICAgICAgICB9O1xuICAgICAgICAkdGh1bWIuYXR0cihjdXJyZW50QXR0cnMpO1xuICAgICAgICAkdGh1bWIuZGF0YSgnY3VycmVudCcsIGN1cnJlbnRBdHRycyk7XG4gICAgfSkub24oJ21vdXNlZW50ZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGdldCBjdXJyZW50IHRodW1iIGRldGFpbHNcbiAgICAgICAgdmFyICR0aWxlID0gJCh0aGlzKS5jbG9zZXN0KCcucHJvZHVjdC10aWxlJyksXG4gICAgICAgICAgICAkdGh1bWIgPSAkdGlsZS5maW5kKCcucHJvZHVjdC1pbWFnZSAudGh1bWItbGluayBpbWcnKS5lcSgwKSxcbiAgICAgICAgICAgIGRhdGEgPSAkKHRoaXMpLmNoaWxkcmVuKCdpbWcnKS5maWx0ZXIoJzpmaXJzdCcpLmRhdGEoJ3RodW1iJyksXG4gICAgICAgICAgICBjdXJyZW50ID0gJHRodW1iLmRhdGEoJ2N1cnJlbnQnKTtcblxuICAgICAgICAvLyBJZiB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lLCB0aGVuIHJlY29yZCB0aGUgY3VycmVudCBpbWdcbiAgICAgICAgaWYgKCFjdXJyZW50KSB7XG4gICAgICAgICAgICAkdGh1bWIuZGF0YSgnY3VycmVudCcsIHtcbiAgICAgICAgICAgICAgICBzcmM6ICR0aHVtYlswXS5zcmMsXG4gICAgICAgICAgICAgICAgYWx0OiAkdGh1bWJbMF0uYWx0LFxuICAgICAgICAgICAgICAgIHRpdGxlOiAkdGh1bWJbMF0udGl0bGVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0IHRoZSB0aWxlIGltYWdlIHRvIHRoZSB2YWx1ZXMgcHJvdmlkZWQgb24gdGhlIHN3YXRjaCBkYXRhIGF0dHJpYnV0ZXNcbiAgICAgICAgJHRodW1iLmF0dHIoe1xuICAgICAgICAgICAgc3JjOiBkYXRhLnNyYyxcbiAgICAgICAgICAgIGFsdDogZGF0YS5hbHQsXG4gICAgICAgICAgICB0aXRsZTogZGF0YS50aXRsZVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkdGlsZXMgPSAkKCcudGlsZXMtY29udGFpbmVyIC5wcm9kdWN0LXRpbGUnKTtcbiAgICBpZiAoJHRpbGVzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cbiAgICBpbWFnZXNMb2FkZWQoJy50aWxlcy1jb250YWluZXInKS5vbignZG9uZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJHRpbGVzLnN5bmNIZWlnaHQoKVxuICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24gKGlkeCkge1xuICAgICAgICAgICAgICAgICQodGhpcykuZGF0YSgnaWR4JywgaWR4KTtcbiAgICAgICAgICAgIH0pO1xuICAgIH0pO1xuICAgIGluaXRpYWxpemVFdmVudHMoKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciAkbG9hZGVyO1xuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIFNob3dzIGFuIEFKQVgtbG9hZGVyIG9uIHRvcCBvZiBhIGdpdmVuIGNvbnRhaW5lclxuICogQHBhcmFtIHtFbGVtZW50fSBjb250YWluZXIgVGhlIEVsZW1lbnQgb24gdG9wIG9mIHdoaWNoIHRoZSBBSkFYLUxvYWRlciB3aWxsIGJlIHNob3duXG4gKi9cbnZhciBzaG93ID0gZnVuY3Rpb24gKGNvbnRhaW5lcikge1xuICAgIHZhciB0YXJnZXQgPSAoIWNvbnRhaW5lciB8fCAkKGNvbnRhaW5lcikubGVuZ3RoID09PSAwKSA/ICQoJ2JvZHknKSA6ICQoY29udGFpbmVyKTtcbiAgICAkbG9hZGVyID0gJGxvYWRlciB8fCAkKCcubG9hZGVyJyk7XG5cbiAgICBpZiAoJGxvYWRlci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgJGxvYWRlciA9ICQoJzxkaXYvPicpLmFkZENsYXNzKCdsb2FkZXInKVxuICAgICAgICAgICAgLmFwcGVuZCgkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnbG9hZGVyLWluZGljYXRvcicpLCAkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnbG9hZGVyLWJnJykpO1xuICAgIH1cbiAgICByZXR1cm4gJGxvYWRlci5hcHBlbmRUbyh0YXJnZXQpLnNob3coKTtcbn07XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEhpZGVzIGFuIEFKQVgtbG9hZGVyXG4gKi9cbnZhciBoaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICgkbG9hZGVyKSB7XG4gICAgICAgICRsb2FkZXIuaGlkZSgpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuc2hvdyA9IHNob3c7XG5leHBvcnRzLmhpZGUgPSBoaWRlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZGlhbG9nID0gcmVxdWlyZSgnLi9kaWFsb2cnKSxcbiAgICBwcm9kdWN0ID0gcmVxdWlyZSgnLi9wYWdlcy9wcm9kdWN0JyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxuXG52YXIgbWFrZVVybCA9IGZ1bmN0aW9uICh1cmwsIHNvdXJjZSwgcHJvZHVjdExpc3RJRCkge1xuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgICAgdXJsID0gdXRpbC5hcHBlbmRQYXJhbVRvVVJMKHVybCwgJ3NvdXJjZScsIHNvdXJjZSk7XG4gICAgfVxuICAgIGlmIChwcm9kdWN0TGlzdElEKSB7XG4gICAgICAgIHVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTCh1cmwsICdwcm9kdWN0bGlzdGlkJywgcHJvZHVjdExpc3RJRCk7XG4gICAgfVxuICAgIHJldHVybiB1cmw7XG59O1xuXG52YXIgcmVtb3ZlUGFyYW0gPSBmdW5jdGlvbiAodXJsKSB7XG4gICAgaWYgKHVybC5pbmRleE9mKCc/JykgIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB1cmwuc3Vic3RyaW5nKDAsIHVybC5pbmRleE9mKCc/JykpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfVxufTtcblxudmFyIHF1aWNrdmlldyA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5leGlzdHMoKSkge1xuICAgICAgICAgICAgdGhpcy4kY29udGFpbmVyID0gJCgnPGRpdi8+JykuYXR0cignaWQnLCAnUXVpY2tWaWV3RGlhbG9nJykuYXBwZW5kVG8oZG9jdW1lbnQuYm9keSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcm9kdWN0TGlua3MgPSAkKCcjc2VhcmNoLXJlc3VsdC1pdGVtcyAudGh1bWItbGluaycpLm1hcChmdW5jdGlvbiAoaW5kZXgsIHRodW1iTGluaykge1xuICAgICAgICAgICAgcmV0dXJuICQodGh1bWJMaW5rKS5hdHRyKCdocmVmJyk7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBzZXR1cDogZnVuY3Rpb24gKHF2VXJsKSB7XG4gICAgICAgIHZhciAkYnRuTmV4dCA9ICQoJy5xdWlja3ZpZXctbmV4dCcpLFxuICAgICAgICAgICAgJGJ0blByZXYgPSAkKCcucXVpY2t2aWV3LXByZXYnKTtcblxuICAgICAgICBwcm9kdWN0LmluaXRpYWxpemVFdmVudHMoKTtcblxuICAgICAgICB0aGlzLnByb2R1Y3RMaW5rSW5kZXggPSBfKHRoaXMucHJvZHVjdExpbmtzKS5maW5kSW5kZXgoZnVuY3Rpb24gKHVybCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZVBhcmFtKHVybCkgPT09IHJlbW92ZVBhcmFtKHF2VXJsKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gaGlkZSB0aGUgYnV0dG9ucyBvbiB0aGUgY29tcGFyZSBwYWdlIG9yIHdoZW4gdGhlcmUgYXJlIG5vIG90aGVyIHByb2R1Y3RzXG4gICAgICAgIGlmICh0aGlzLnByb2R1Y3RMaW5rcy5sZW5ndGggPD0gMSB8fCAkKCcuY29tcGFyZXJlbW92ZWNlbGwnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkYnRuTmV4dC5oaWRlKCk7XG4gICAgICAgICAgICAkYnRuUHJldi5oaWRlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5wcm9kdWN0TGlua0luZGV4ID09PSB0aGlzLnByb2R1Y3RMaW5rcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAkYnRuTmV4dC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnByb2R1Y3RMaW5rSW5kZXggPT09IDApIHtcbiAgICAgICAgICAgICRidG5QcmV2LmF0dHIoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cblxuICAgICAgICAkYnRuTmV4dC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVF1aWNrdmlldygxKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgJGJ0blByZXYub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMubmF2aWdhdGVRdWlja3ZpZXcoLTEpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gc3RlcCAtIEhvdyBtYW55IHByb2R1Y3RzIGF3YXkgZnJvbSBjdXJyZW50IHByb2R1Y3QgdG8gbmF2aWdhdGUgdG8uIE5lZ2F0aXZlIG51bWJlciBtZWFucyBuYXZpZ2F0ZSBiYWNrd2FyZFxuICAgICAqL1xuICAgIG5hdmlnYXRlUXVpY2t2aWV3OiBmdW5jdGlvbiAoc3RlcCkge1xuICAgICAgICAvLyBkZWZhdWx0IHN0ZXAgdG8gMFxuICAgICAgICB0aGlzLnByb2R1Y3RMaW5rSW5kZXggKz0gKHN0ZXAgPyBzdGVwIDogMCk7XG4gICAgICAgIHZhciB1cmwgPSBtYWtlVXJsKHRoaXMucHJvZHVjdExpbmtzW3RoaXMucHJvZHVjdExpbmtJbmRleF0sICdxdWlja3ZpZXcnKTtcbiAgICAgICAgZGlhbG9nLnJlcGxhY2Uoe1xuICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICBjYWxsYmFjazogdGhpcy5zZXR1cC5iaW5kKHRoaXMsIHVybClcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBzaG93IHF1aWNrIHZpZXcgZGlhbG9nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy51cmwgLSB1cmwgb2YgdGhlIHByb2R1Y3QgZGV0YWlsc1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnNvdXJjZSAtIHNvdXJjZSBvZiB0aGUgZGlhbG9nIHRvIGJlIGFwcGVuZGVkIHRvIFVSTFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnByb2R1Y3RsaXN0aWQgLSB0byBiZSBhcHBlbmRlZCB0byBVUkxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcHRpb25zLmNhbGxiYWNrIC0gY2FsbGJhY2sgb25jZSB0aGUgZGlhbG9nIGlzIG9wZW5lZFxuICAgICAqL1xuICAgIHNob3c6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciB1cmw7XG4gICAgICAgIGlmICghdGhpcy5leGlzdHMoKSkge1xuICAgICAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgIH1cbiAgICAgICAgdXJsID0gbWFrZVVybChvcHRpb25zLnVybCwgb3B0aW9ucy5zb3VyY2UsIG9wdGlvbnMucHJvZHVjdGxpc3RpZCk7XG5cbiAgICAgICAgZGlhbG9nLm9wZW4oe1xuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLiRjb250YWluZXIsXG4gICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogOTIwLFxuICAgICAgICAgICAgICAgIHRpdGxlOiBSZXNvdXJjZXMuUVVJQ0tfVklFV19QT1BVUCxcbiAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dXAodXJsKTtcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIC8vIE9tbml0dXJlIHF1aWNrdmlldyB0cmFja2luZ1xuXHQgICAgICAgICAgICBcdFx0aWYgKFNpdGVQcmVmZXJlbmNlcy5PTU5JVFVSRV9FTkFCTEVEICYmIHR5cGVvZiBfc2F0ZWxsaXRlICE9ICd1bmRlZmluZWQnKSB7XG5cdCAgICAgICAgICAgIFx0XHRcdF9zYXRlbGxpdGUudHJhY2soXCJwcm9kdWN0TW9kYWxWaWV3XCIpO1xuXHQgICAgICAgICAgICBcdFx0fVxuXHQgICAgICAgICAgICBcdFx0XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgeyBvcHRpb25zLmNhbGxiYWNrKCk7IH1cbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBleGlzdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuJGNvbnRhaW5lciAmJiAodGhpcy4kY29udGFpbmVyLmxlbmd0aCA+IDApO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcXVpY2t2aWV3O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIGNvcGllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9kYXJrc2t5YXBwL3N0cmluZy1oYXNoXG4gKi9cbmZ1bmN0aW9uIGhhc2hGbihzdHIpIHtcbiAgICB2YXIgaGFzaCA9IDUzODEsXG4gICAgICAgIGkgPSBzdHIubGVuZ3RoO1xuXG4gICAgd2hpbGUgKGkpIHtcbiAgICAgICAgaGFzaCA9IChoYXNoICogMzMpIF4gc3RyLmNoYXJDb2RlQXQoLS1pKTtcbiAgICB9XG4gICAgLyogSmF2YVNjcmlwdCBkb2VzIGJpdHdpc2Ugb3BlcmF0aW9ucyAobGlrZSBYT1IsIGFib3ZlKSBvbiAzMi1iaXQgc2lnbmVkXG4gICAgKiBpbnRlZ2Vycy4gU2luY2Ugd2Ugd2FudCB0aGUgcmVzdWx0cyB0byBiZSBhbHdheXMgcG9zaXRpdmUsIGNvbnZlcnQgdGhlXG4gICAgKiBzaWduZWQgaW50IHRvIGFuIHVuc2lnbmVkIGJ5IGRvaW5nIGFuIHVuc2lnbmVkIGJpdHNoaWZ0LiAqL1xuICAgIHJldHVybiBoYXNoID4+PiAwO1xufVxuXG4vKipcbiAqIENyZWF0ZSByYXRpbmcgYmFzZWQgb24gaGFzaCByYW5naW5nIGZyb20gMi01XG4gKiBAcGFyYW0gcGlkXG4gKi9cbmZ1bmN0aW9uIGdldFJhdGluZyhwaWQpIHtcbiAgICByZXR1cm4gaGFzaEZuKHBpZC50b1N0cmluZygpKSAlIDMwIC8gMTAgKyAyO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQoJy5wcm9kdWN0LXJldmlldycpLmVhY2goZnVuY3Rpb24gKGluZGV4LCByZXZpZXcpIHtcbiAgICAgICAgICAgIHZhciBwaWQgPSAkKHJldmlldykuZGF0YSgncGlkJyk7XG4gICAgICAgICAgICBpZiAoIXBpZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJhdGluZyByYW5nZSBmcm9tIDIgLSA1XG4gICAgICAgICAgICB2YXIgcmF0aW5nID0gZ2V0UmF0aW5nKHBpZCk7XG4gICAgICAgICAgICB2YXIgYmFzZVJhdGluZyA9IE1hdGguZmxvb3IocmF0aW5nKTtcbiAgICAgICAgICAgIHZhciBzdGFyc0NvdW50ID0gMDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmFzZVJhdGluZzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgJCgnLnJhdGluZycsIHJldmlldykuYXBwZW5kKCc8aSBjbGFzcz1cImZhIGZhLXN0YXJcIj48L2k+Jyk7XG4gICAgICAgICAgICAgICAgc3RhcnNDb3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZ2l2ZSBoYWxmIHN0YXIgZm9yIGFueXRoaW5nIGluIGJldHdlZW5cbiAgICAgICAgICAgIGlmIChyYXRpbmcgPiBiYXNlUmF0aW5nKSB7XG4gICAgICAgICAgICAgICAgJCgnLnJhdGluZycsIHJldmlldykuYXBwZW5kKCc8aSBjbGFzcz1cImZhIGZhLXN0YXItaGFsZi1vXCI+PC9pPicpO1xuICAgICAgICAgICAgICAgIHN0YXJzQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGFyc0NvdW50IDwgNSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgNSAtIHN0YXJzQ291bnQ7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAkKCcucmF0aW5nJywgcmV2aWV3KS5hcHBlbmQoJzxpIGNsYXNzPVwiZmEgZmEtc3Rhci1vXCI+PC9pPicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gQmluZHMgZXZlbnQgdG8gdGhlIHBsYWNlIGhvbGRlciAoLmJsdXIpXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVFdmVudHMoKSB7XG4gICAgJCgnI3EnKS5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpbnB1dCA9ICQodGhpcyk7XG4gICAgICAgIGlmIChpbnB1dC52YWwoKSA9PT0gaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSkge1xuICAgICAgICAgICAgaW5wdXQudmFsKCcnKTtcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLmJsdXIoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICBpZiAoaW5wdXQudmFsKCkgPT09ICcnIHx8IGlucHV0LnZhbCgpID09PSBpbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpKSB7XG4gICAgICAgICAgICBpbnB1dC52YWwoaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSk7XG4gICAgICAgIH1cbiAgICB9KVxuICAgIC5ibHVyKCk7XG59XG5cbmV4cG9ydHMuaW5pdCA9IGluaXRpYWxpemVFdmVudHM7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbnZhciBjdXJyZW50UXVlcnkgPSBudWxsLFxuICAgIGxhc3RRdWVyeSA9IG51bGwsXG4gICAgcnVubmluZ1F1ZXJ5ID0gbnVsbCxcbiAgICBsaXN0VG90YWwgPSAtMSxcbiAgICBsaXN0Q3VycmVudCA9IC0xLFxuICAgIGRlbGF5ID0gMzAsXG4gICAgJHJlc3VsdHNDb250YWluZXI7XG4vKipcbiAqIEBmdW5jdGlvblxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXMga2V5Ym9hcmQncyBhcnJvdyBrZXlzXG4gKiBAcGFyYW0ga2V5Q29kZSBDb2RlIG9mIGFuIGFycm93IGtleSB0byBiZSBoYW5kbGVkXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUFycm93S2V5cyhrZXlDb2RlKSB7XG4gICAgc3dpdGNoIChrZXlDb2RlKSB7XG4gICAgICAgIGNhc2UgMzg6XG4gICAgICAgICAgICAvLyBrZXlVcFxuICAgICAgICAgICAgbGlzdEN1cnJlbnQgPSAobGlzdEN1cnJlbnQgPD0gMCkgPyAobGlzdFRvdGFsIC0gMSkgOiAobGlzdEN1cnJlbnQgLSAxKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDQwOlxuICAgICAgICAgICAgLy8ga2V5RG93blxuICAgICAgICAgICAgbGlzdEN1cnJlbnQgPSAobGlzdEN1cnJlbnQgPj0gbGlzdFRvdGFsIC0gMSkgPyAwIDogbGlzdEN1cnJlbnQgKyAxO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAvLyByZXNldFxuICAgICAgICAgICAgbGlzdEN1cnJlbnQgPSAtMTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAkcmVzdWx0c0NvbnRhaW5lci5jaGlsZHJlbigpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpLmVxKGxpc3RDdXJyZW50KS5hZGRDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAkKCdpbnB1dFtuYW1lPVwicVwiXScpLnZhbCgkcmVzdWx0c0NvbnRhaW5lci5maW5kKCcuc2VsZWN0ZWQgLnN1Z2dlc3Rpb250ZXJtJykuZmlyc3QoKS50ZXh0KCkpO1xuICAgIHJldHVybiB0cnVlO1xufVxuXG52YXIgc2VhcmNoc3VnZ2VzdCA9IHtcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQ29uZmlndXJlcyBwYXJhbWV0ZXJzIGFuZCByZXF1aXJlZCBvYmplY3QgaW5zdGFuY2VzXG4gICAgICovXG4gICAgaW5pdDogZnVuY3Rpb24gKGNvbnRhaW5lciwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgIHZhciAkc2VhcmNoQ29udGFpbmVyID0gJChjb250YWluZXIpO1xuICAgICAgICB2YXIgJHNlYXJjaEZvcm0gPSAkc2VhcmNoQ29udGFpbmVyLmZpbmQoJ2Zvcm1bbmFtZT1cInNpbXBsZVNlYXJjaFwiXScpO1xuICAgICAgICB2YXIgJHNlYXJjaEZpZWxkID0gJHNlYXJjaEZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInFcIl0nKTtcblxuICAgICAgICAvLyBkaXNhYmxlIGJyb3dzZXIgYXV0byBjb21wbGV0ZVxuICAgICAgICAkc2VhcmNoRmllbGQuYXR0cignYXV0b2NvbXBsZXRlJywgJ29mZicpO1xuXG4gICAgICAgIC8vIG9uIGZvY3VzIGxpc3RlbmVyIChjbGVhciBkZWZhdWx0IHZhbHVlKVxuICAgICAgICAkc2VhcmNoRmllbGQuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCEkcmVzdWx0c0NvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSByZXN1bHRzIGNvbnRhaW5lciBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAkcmVzdWx0c0NvbnRhaW5lciA9ICQoJzxkaXYvPicpLmF0dHIoJ2lkJywgJ3NlYXJjaC1zdWdnZXN0aW9ucycpLmFwcGVuZFRvKCRzZWFyY2hDb250YWluZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRzZWFyY2hGaWVsZC52YWwoKSA9PT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgJHNlYXJjaEZpZWxkLnZhbCgnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoISRzZWFyY2hDb250YWluZXIuaXMoZS50YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCh0aGlzLmNsZWFyUmVzdWx0cywgMjAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgLy8gb24ga2V5IHVwIGxpc3RlbmVyXG4gICAgICAgICRzZWFyY2hGaWVsZC5rZXl1cChmdW5jdGlvbiAoZSkge1xuXG4gICAgICAgICAgICAvLyBnZXQga2V5Q29kZSAod2luZG93LmV2ZW50IGlzIGZvciBJRSlcbiAgICAgICAgICAgIHZhciBrZXlDb2RlID0gZS5rZXlDb2RlIHx8IHdpbmRvdy5ldmVudC5rZXlDb2RlO1xuXG4gICAgICAgICAgICAvLyBjaGVjayBhbmQgdHJlYXQgdXAgYW5kIGRvd24gYXJyb3dzXG4gICAgICAgICAgICBpZiAoaGFuZGxlQXJyb3dLZXlzKGtleUNvZGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIGFuIEVOVEVSIG9yIEVTQ1xuICAgICAgICAgICAgaWYgKGtleUNvZGUgPT09IDEzIHx8IGtleUNvZGUgPT09IDI3KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclJlc3VsdHMoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGN1cnJlbnRRdWVyeSA9ICRzZWFyY2hGaWVsZC52YWwoKS50cmltKCk7XG5cbiAgICAgICAgICAgIC8vIG5vIHF1ZXJ5IGN1cnJlbnRseSBydW5uaW5nLCBpbml0IGFuIHVwZGF0ZVxuICAgICAgICAgICAgaWYgKCFydW5uaW5nUXVlcnkpIHtcbiAgICAgICAgICAgICAgICBydW5uaW5nUXVlcnkgPSBjdXJyZW50UXVlcnk7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCh0aGlzLnN1Z2dlc3QuYmluZCh0aGlzKSwgZGVsYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gdHJpZ2dlciBzdWdnZXN0IGFjdGlvblxuICAgICAqL1xuICAgIHN1Z2dlc3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gY2hlY2sgd2hldGhlciBxdWVyeSB0byBleGVjdXRlIChydW5uaW5nUXVlcnkpIGlzIHN0aWxsIHVwIHRvIGRhdGUgYW5kIGhhZCBub3QgY2hhbmdlZCBpbiB0aGUgbWVhbndoaWxlXG4gICAgICAgIC8vICh3ZSBoYWQgYSBsaXR0bGUgZGVsYXkpXG4gICAgICAgIGlmIChydW5uaW5nUXVlcnkgIT09IGN1cnJlbnRRdWVyeSkge1xuICAgICAgICAgICAgLy8gdXBkYXRlIHJ1bm5pbmcgcXVlcnkgdG8gdGhlIG1vc3QgcmVjZW50IHNlYXJjaCBwaHJhc2VcbiAgICAgICAgICAgIHJ1bm5pbmdRdWVyeSA9IGN1cnJlbnRRdWVyeTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIGl0J3MgZW1wdHkgY2xlYXIgdGhlIHJlc3VsdHMgYm94IGFuZCByZXR1cm5cbiAgICAgICAgaWYgKHJ1bm5pbmdRdWVyeS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJSZXN1bHRzKCk7XG4gICAgICAgICAgICBydW5uaW5nUXVlcnkgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgdGhlIGN1cnJlbnQgc2VhcmNoIHBocmFzZSBpcyB0aGUgc2FtZSBhcyBmb3IgdGhlIGxhc3Qgc3VnZ2VzdGlvbiBjYWxsLCBqdXN0IHJldHVyblxuICAgICAgICBpZiAobGFzdFF1ZXJ5ID09PSBydW5uaW5nUXVlcnkpIHtcbiAgICAgICAgICAgIHJ1bm5pbmdRdWVyeSA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBidWlsZCB0aGUgcmVxdWVzdCB1cmxcbiAgICAgICAgdmFyIHJlcVVybCA9IHV0aWwuYXBwZW5kUGFyYW1Ub1VSTChVcmxzLnNlYXJjaHN1Z2dlc3QsICdxJywgcnVubmluZ1F1ZXJ5KTtcblxuICAgICAgICAvLyBleGVjdXRlIHNlcnZlciBjYWxsXG4gICAgICAgICQuZ2V0KHJlcVVybCwgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIHZhciBzdWdnZXN0aW9uSFRNTCA9IGRhdGEsXG4gICAgICAgICAgICAgICAgYW5zTGVuZ3RoID0gc3VnZ2VzdGlvbkhUTUwudHJpbSgpLmxlbmd0aDtcblxuICAgICAgICAgICAgLy8gaWYgdGhlcmUgYXJlIHJlc3VsdHMgcG9wdWxhdGUgdGhlIHJlc3VsdHMgZGl2XG4gICAgICAgICAgICBpZiAoYW5zTGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclJlc3VsdHMoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSByZXN1bHRzIGRpdlxuICAgICAgICAgICAgICAgICRyZXN1bHRzQ29udGFpbmVyLmh0bWwoc3VnZ2VzdGlvbkhUTUwpLmZhZGVJbigyMDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyByZWNvcmQgdGhlIHF1ZXJ5IHRoYXQgaGFzIGJlZW4gZXhlY3V0ZWRcbiAgICAgICAgICAgIGxhc3RRdWVyeSA9IHJ1bm5pbmdRdWVyeTtcbiAgICAgICAgICAgIC8vIHJlc2V0IGN1cnJlbnRseSBydW5uaW5nIHF1ZXJ5XG4gICAgICAgICAgICBydW5uaW5nUXVlcnkgPSBudWxsO1xuXG4gICAgICAgICAgICAvLyBjaGVjayBmb3IgYW5vdGhlciByZXF1aXJlZCB1cGRhdGUgKGlmIGN1cnJlbnQgc2VhcmNoIHBocmFzZSBpcyBkaWZmZXJlbnQgZnJvbSBqdXN0IGV4ZWN1dGVkIGNhbGwpXG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXJ5ICE9PSBsYXN0UXVlcnkpIHtcbiAgICAgICAgICAgICAgICAvLyAuLi4gYW5kIGV4ZWN1dGUgaW1tZWRpYXRlbHkgaWYgc2VhcmNoIGhhcyBjaGFuZ2VkIHdoaWxlIHRoaXMgc2VydmVyIGNhbGwgd2FzIGluIHRyYW5zaXRcbiAgICAgICAgICAgICAgICBydW5uaW5nUXVlcnkgPSBjdXJyZW50UXVlcnk7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCh0aGlzLnN1Z2dlc3QuYmluZCh0aGlzKSwgZGVsYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oaWRlTGVmdFBhbmVsKCk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBjbGVhclJlc3VsdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCEkcmVzdWx0c0NvbnRhaW5lcikgeyByZXR1cm47IH1cbiAgICAgICAgJHJlc3VsdHNDb250YWluZXIuZmFkZU91dCgyMDAsIGZ1bmN0aW9uICgpIHskcmVzdWx0c0NvbnRhaW5lci5lbXB0eSgpO30pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICovXG4gICAgaGlkZUxlZnRQYW5lbDogZnVuY3Rpb24gKCkge1xuICAgICAgICAvL2hpZGUgbGVmdCBwYW5lbCBpZiB0aGVyZSBpcyBvbmx5IGEgbWF0Y2hpbmcgc3VnZ2VzdGVkIGN1c3RvbSBwaHJhc2VcbiAgICAgICAgaWYgKCQoJy5zZWFyY2gtc3VnZ2VzdGlvbi1sZWZ0LXBhbmVsLWhpdCcpLmxlbmd0aCA9PT0gMSAmJiAkKCcuc2VhcmNoLXBocmFzZS1zdWdnZXN0aW9uIGEnKS50ZXh0KCkucmVwbGFjZSgvKF5bXFxzXSt8W1xcc10rJCkvZywgJycpLnRvVXBwZXJDYXNlKCkgPT09ICQoJy5zZWFyY2gtc3VnZ2VzdGlvbi1sZWZ0LXBhbmVsLWhpdCBhJykudGV4dCgpLnRvVXBwZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICQoJy5zZWFyY2gtc3VnZ2VzdGlvbi1sZWZ0LXBhbmVsJykuY3NzKCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICAgICAgICAgICQoJy5zZWFyY2gtc3VnZ2VzdGlvbi13cmFwcGVyLWZ1bGwnKS5hZGRDbGFzcygnc2VhcmNoLXN1Z2dlc3Rpb24td3JhcHBlcicpO1xuICAgICAgICAgICAgJCgnLnNlYXJjaC1zdWdnZXN0aW9uLXdyYXBwZXInKS5yZW1vdmVDbGFzcygnc2VhcmNoLXN1Z2dlc3Rpb24td3JhcHBlci1mdWxsJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHNlYXJjaHN1Z2dlc3Q7XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAkKCcjbGl2ZWFnZW50X2J1dHRvbl9vbmxpbmUnKS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKGUpe1xuXHQgICAgXHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdCAgICBcdGxpdmVhZ2VudC5zdGFydENoYXQoU2l0ZVByZWZlcmVuY2VzLlNGX0JVVFRPTl9JRCk7IC8vYnV0dG9uIGlkXG5cdCAgICB9KTtcblxuXHRcdGxpdmVhZ2VudC5pbml0KFNpdGVQcmVmZXJlbmNlcy5TRl9JTklUX0NIQVRfVVJMLCBTaXRlUHJlZmVyZW5jZXMuU0ZfREVQTE9ZTUVOVF9JRCwgU2l0ZVByZWZlcmVuY2VzLlNGX09SR19JRCk7IC8vdXJsLCBkZXBsb3ltZW50LCBvcmdcblx0XG5cdFx0aWYgKCF3aW5kb3cuX2xhcSlcblx0XHR7IHdpbmRvdy5fbGFxID0gW107IH1cblxuXHRcdHdpbmRvdy5fbGFxLnB1c2goZnVuY3Rpb24oKSB7XG5cdFx0ICAgIGxpdmVhZ2VudC5zaG93V2hlbk9ubGluZShTaXRlUHJlZmVyZW5jZXMuU0ZfQlVUVE9OX0lELCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGl2ZWFnZW50X2J1dHRvbl9vbmxpbmUnKSk7XG5cdFx0ICAgIGxpdmVhZ2VudC5zaG93V2hlbk9mZmxpbmUoU2l0ZVByZWZlcmVuY2VzLlNGX0JVVFRPTl9JRCwgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xpdmVhZ2VudF9idXR0b25fb2ZmbGluZScpKTtcblx0XHR9KTtcblx0fVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3RpY2t5Q29tcG9uZW50ID0gcmVxdWlyZSgnLi9jb21wb25lbnRzL3N0aWNreUNvbXBvbmVudCcpO1xuXG5mdW5jdGlvbiBnZXRQYWdlTWFwcGluZygpIHtcbiAgICB2YXIgb2JqID0gU2l0ZVByZWZlcmVuY2VzLk1BUFBJTkdfRk9SX1NUSUNLWV9DT01QO1xuICAgIGlmICghb2JqLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaG9tZTogJy5wdF9zdG9yZWZyb250JyxcbiAgICAgICAgICAgIHBscDogJy5wdF9wcm9kdWN0LXNlYXJjaC1yZXN1bHQnLFxuICAgICAgICAgICAgcGRwOiAnLnB0X3Byb2R1Y3QtZGV0YWlscycsXG4gICAgICAgICAgICBzZWFyY2g6ICcucHRfcHJvZHVjdC1zZWFyY2gtbm9yZXN1bHQnXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uob2JqKTtcbn1cblxudmFyIHN0aWNreVNlYXJjaCA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwYWdlU3RyaW5nID0gU2l0ZVByZWZlcmVuY2VzLlNUSUNLWV9TRUFSQ0hfQkFSX0xJU1QudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYoIXBhZ2VTdHJpbmcubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhZ2VMaXN0ID0gcGFnZVN0cmluZy5zcGxpdCgnLCcpO1xuXG4gICAgICAgIHZhciBwYWdlTWFwcGluZyA9IGdldFBhZ2VNYXBwaW5nKCk7XG5cbiAgICAgICAgdmFyIGlzRW5hYmxlZCA9IHBhZ2VMaXN0LnNvbWUoaXRlbSA9PiBwYWdlTWFwcGluZy5oYXNPd25Qcm9wZXJ0eShpdGVtLnRyaW0oKSkgJiYgJChwYWdlTWFwcGluZ1tpdGVtLnRyaW0oKV0pLmxlbmd0aCk7XG5cbiAgICAgICAgaWYgKGlzRW5hYmxlZCkge1xuICAgICAgICAgICAgc3RpY2t5Q29tcG9uZW50LmluaXQoe1xuICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnLmhlYWRlci1zZWFyY2gnLFxuICAgICAgICAgICAgICAgIHRyaWdnZXI6ICcudG9wLWJhbm5lcidcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoJCgnYm9keScpLmZpbmQoJy5wdF9wcm9kdWN0LWRldGFpbHMnKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkKCcjd3JhcHBlcicpLmFkZENsYXNzKCdtLXBkcC13aXRoLXN0aWNreS1zZWFyY2gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RpY2t5U2VhcmNoO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW52ZW50b3J5ID0gcmVxdWlyZSgnLi8nKTtcblxudmFyIGNhcnRJbnZlbnRvcnkgPSB7XG4gICAgc2V0U2VsZWN0ZWRTdG9yZTogZnVuY3Rpb24gKHN0b3JlSWQpIHtcbiAgICAgICAgdmFyICRzZWxlY3RlZFN0b3JlID0gJCgnLnN0b3JlLXRpbGUuJyArIHN0b3JlSWQpLFxuICAgICAgICAgICAgJGxpbmVJdGVtID0gJCgnLmNhcnQtcm93W2RhdGEtdXVpZD1cIicgKyB0aGlzLnV1aWQgKyAnXCJdJyksXG4gICAgICAgICAgICBzdG9yZUFkZHJlc3MgPSAkc2VsZWN0ZWRTdG9yZS5maW5kKCcuc3RvcmUtYWRkcmVzcycpLmh0bWwoKSxcbiAgICAgICAgICAgIHN0b3JlU3RhdHVzID0gJHNlbGVjdGVkU3RvcmUuZmluZCgnLnN0b3JlLXN0YXR1cycpLmRhdGEoJ3N0YXR1cycpLFxuICAgICAgICAgICAgc3RvcmVTdGF0dXNUZXh0ID0gJHNlbGVjdGVkU3RvcmUuZmluZCgnLnN0b3JlLXN0YXR1cycpLnRleHQoKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFN0b3JlID0gc3RvcmVJZDtcblxuICAgICAgICAkbGluZUl0ZW0uZmluZCgnLmluc3RvcmUtZGVsaXZlcnkgLnNlbGVjdGVkLXN0b3JlLWFkZHJlc3MnKVxuICAgICAgICAgICAgLmRhdGEoJ3N0b3JlSWQnLCBzdG9yZUlkKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtc3RvcmUtaWQnLCBzdG9yZUlkKVxuICAgICAgICAgICAgLmh0bWwoc3RvcmVBZGRyZXNzKTtcbiAgICAgICAgJGxpbmVJdGVtLmZpbmQoJy5pbnN0b3JlLWRlbGl2ZXJ5IC5zZWxlY3RlZC1zdG9yZS1hdmFpbGFiaWxpdHknKVxuICAgICAgICAgICAgLmRhdGEoJ3N0YXR1cycsIHN0b3JlU3RhdHVzKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtc3RhdHVzJywgc3RvcmVTdGF0dXMpXG4gICAgICAgICAgICAudGV4dChzdG9yZVN0YXR1c1RleHQpO1xuICAgICAgICAkbGluZUl0ZW0uZmluZCgnLmluc3RvcmUtZGVsaXZlcnkgLmRlbGl2ZXJ5LW9wdGlvbicpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJykudHJpZ2dlcignY2xpY2snKTtcbiAgICB9LFxuICAgIGNhcnRTZWxlY3RTdG9yZTogZnVuY3Rpb24gKHNlbGVjdGVkU3RvcmUpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMudXVpZCkudGhlbihmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgICAgICAgICBpbnZlbnRvcnkuc2VsZWN0U3RvcmVEaWFsb2coe1xuICAgICAgICAgICAgICAgIHN0b3Jlczogc3RvcmVzLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVJZDogc2VsZWN0ZWRTdG9yZSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZFN0b3JlVGV4dDogUmVzb3VyY2VzLlNFTEVDVEVEX1NUT1JFLFxuICAgICAgICAgICAgICAgIGNvbnRpbnVlQ2FsbGJhY2s6IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgICAgICAgICAgIHNlbGVjdFN0b3JlQ2FsbGJhY2s6IHNlbGYuc2V0U2VsZWN0ZWRTdG9yZS5iaW5kKHNlbGYpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuZG9uZSgpO1xuICAgIH0sXG4gICAgc2V0RGVsaXZlcnlPcHRpb246IGZ1bmN0aW9uICh2YWx1ZSwgc3RvcmVJZCkge1xuICAgICAgICAvLyBzZXQgbG9hZGluZyBzdGF0ZVxuICAgICAgICAkKCcuaXRlbS1kZWxpdmVyeS1vcHRpb25zJylcbiAgICAgICAgICAgIC5hZGRDbGFzcygnbG9hZGluZycpXG4gICAgICAgICAgICAuY2hpbGRyZW4oKS5oaWRlKCk7XG5cbiAgICAgICAgdmFyIGRhdGEgPSB7XG4gICAgICAgICAgICBwbGlkOiB0aGlzLnV1aWQsXG4gICAgICAgICAgICBzdG9yZXBpY2t1cDogKHZhbHVlID09PSAnc3RvcmUnID8gdHJ1ZSA6IGZhbHNlKVxuICAgICAgICB9O1xuICAgICAgICBpZiAodmFsdWUgPT09ICdzdG9yZScpIHtcbiAgICAgICAgICAgIGRhdGEuc3RvcmVwaWNrdXAgPSB0cnVlO1xuICAgICAgICAgICAgZGF0YS5zdG9yZWlkID0gc3RvcmVJZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEuc3RvcmVwaWNrdXAgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBVcmxzLnNldFN0b3JlUGlja3VwLFxuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgbG9hZGluZyBzdGF0ZVxuICAgICAgICAgICAgICAgICQoJy5pdGVtLWRlbGl2ZXJ5LW9wdGlvbnMnKVxuICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcnKVxuICAgICAgICAgICAgICAgICAgICAuY2hpbGRyZW4oKS5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICQoJy5pdGVtLWRlbGl2ZXJ5LW9wdGlvbnMgLnNldC1wcmVmZXJyZWQtc3RvcmUnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgc2VsZi51dWlkID0gJCh0aGlzKS5kYXRhKCd1dWlkJyk7XG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRTdG9yZSA9ICQodGhpcykuY2xvc2VzdCgnLmluc3RvcmUtZGVsaXZlcnknKS5maW5kKCcuc2VsZWN0ZWQtc3RvcmUtYWRkcmVzcycpLmRhdGEoJ3N0b3JlSWQnKTtcbiAgICAgICAgICAgIGlmICghVXNlci56aXApIHtcbiAgICAgICAgICAgICAgICBpbnZlbnRvcnkuemlwUHJvbXB0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYXJ0U2VsZWN0U3RvcmUoc2VsZWN0ZWRTdG9yZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuY2FydFNlbGVjdFN0b3JlKHNlbGVjdGVkU3RvcmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCgnLml0ZW0tZGVsaXZlcnktb3B0aW9ucyAuZGVsaXZlcnktb3B0aW9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gcmVzZXQgdGhlIHV1aWRcbiAgICAgICAgICAgIHZhciBzZWxlY3RlZFN0b3JlID0gJCh0aGlzKS5jbG9zZXN0KCcuaW5zdG9yZS1kZWxpdmVyeScpLmZpbmQoJy5zZWxlY3RlZC1zdG9yZS1hZGRyZXNzJykuZGF0YSgnc3RvcmVJZCcpO1xuICAgICAgICAgICAgc2VsZi51dWlkID0gJCh0aGlzKS5jbG9zZXN0KCcuY2FydC1yb3cnKS5kYXRhKCd1dWlkJyk7XG4gICAgICAgICAgICBzZWxmLnNldERlbGl2ZXJ5T3B0aW9uKCQodGhpcykudmFsKCksIHNlbGVjdGVkU3RvcmUpO1xuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNhcnRJbnZlbnRvcnk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gICAgZGlhbG9nID0gcmVxdWlyZSgnLi4vZGlhbG9nJyksXG4gICAgVFByb21pc2UgPSByZXF1aXJlKCdwcm9taXNlJyksXG4gICAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxudmFyIG5ld0xpbmUgPSAnXFxuJztcbnZhciBzdG9yZVRlbXBsYXRlID0gZnVuY3Rpb24gKHN0b3JlLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgJzxsaSBjbGFzcz1cInN0b3JlLXRpbGUgJyArIHN0b3JlLnN0b3JlSWQgKyAoc3RvcmUuc3RvcmVJZCA9PT0gc2VsZWN0ZWRTdG9yZUlkID8gJyBzZWxlY3RlZCcgOiAnJykgKyAnXCI+JyxcbiAgICAgICAgJyAgICA8cCBjbGFzcz1cInN0b3JlLWFkZHJlc3NcIj4nLFxuICAgICAgICAnICAgICAgICAnICsgc3RvcmUuYWRkcmVzczEgKyAnPGJyLz4nLFxuICAgICAgICAnICAgICAgICAnICsgc3RvcmUuY2l0eSArICcsICcgKyBzdG9yZS5zdGF0ZUNvZGUgKyAnICcgKyBzdG9yZS5wb3N0YWxDb2RlLFxuICAgICAgICAnICAgIDwvcD4nLFxuICAgICAgICAnICAgIDxwIGNsYXNzPVwic3RvcmUtc3RhdHVzXCIgZGF0YS1zdGF0dXM9XCInICsgc3RvcmUuc3RhdHVzY2xhc3MgKyAnXCI+JyArIHN0b3JlLnN0YXR1cyArICc8L3A+JyxcbiAgICAgICAgJyAgICA8YnV0dG9uIGNsYXNzPVwic2VsZWN0LXN0b3JlLWJ1dHRvblwiIGRhdGEtc3RvcmUtaWQ9XCInICsgc3RvcmUuc3RvcmVJZCArICdcIicgK1xuICAgICAgICAoc3RvcmUuc3RhdHVzY2xhc3MgIT09ICdzdG9yZS1pbi1zdG9jaycgPyAnZGlzYWJsZWQ9XCJkaXNhYmxlZFwiJyA6ICcnKSArICc+JyxcbiAgICAgICAgJyAgICAgICAgJyArIChzdG9yZS5zdG9yZUlkID09PSBzZWxlY3RlZFN0b3JlSWQgPyBzZWxlY3RlZFN0b3JlVGV4dCA6IFJlc291cmNlcy5TRUxFQ1RfU1RPUkUpLFxuICAgICAgICAnICAgIDwvYnV0dG9uPicsXG4gICAgICAgICc8L2xpPidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xuXG52YXIgc3RvcmVMaXN0VGVtcGxhdGUgPSBmdW5jdGlvbiAoc3RvcmVzLCBzZWxlY3RlZFN0b3JlSWQsIHNlbGVjdGVkU3RvcmVUZXh0KSB7XG4gICAgaWYgKHN0b3JlcyAmJiBzdG9yZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cInN0b3JlLWxpc3QtY29udGFpbmVyXCI+JyxcbiAgICAgICAgICAgICc8dWwgY2xhc3M9XCJzdG9yZS1saXN0XCI+JyxcbiAgICAgICAgICAgIF8ubWFwKHN0b3JlcywgZnVuY3Rpb24gKHN0b3JlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0b3JlVGVtcGxhdGUoc3RvcmUsIHNlbGVjdGVkU3RvcmVJZCwgc2VsZWN0ZWRTdG9yZVRleHQpO1xuICAgICAgICAgICAgfSkuam9pbihuZXdMaW5lKSxcbiAgICAgICAgICAgICc8L3VsPicsXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwic3RvcmUtbGlzdC1wYWdpbmF0aW9uXCI+JyxcbiAgICAgICAgICAgICc8L2Rpdj4nXG4gICAgICAgIF0uam9pbihuZXdMaW5lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJzxkaXYgY2xhc3M9XCJuby1yZXN1bHRzXCI+JyArIFJlc291cmNlcy5JTlZBTElEX1pJUCArICc8L2Rpdj4nO1xuICAgIH1cbn07XG5cbnZhciB6aXBQcm9tcHRUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAnPGRpdiBpZD1cInByZWZlcnJlZC1zdG9yZS1wYW5lbFwiPicsXG4gICAgICAgICcgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWQ9XCJ1c2VyLXppcFwiIHBsYWNlaG9sZGVyPVwiJyArIFJlc291cmNlcy5FTlRFUl9aSVAgKyAnXCIgbmFtZT1cInppcENvZGVcIi8+JyxcbiAgICAgICAgJzwvZGl2PidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiB0ZXN0IHdoZXRoZXIgemlwY29kZSBpcyB2YWxpZCBmb3IgZWl0aGVyIFVTIG9yIENhbmFkYVxuICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB0aGUgemlwY29kZSBpcyB2YWxpZCBmb3IgZWl0aGVyIGNvdW50cnksIGZhbHNlIGlmIGl0J3MgaW52YWxpZCBmb3IgYm90aFxuICoqL1xudmFyIHZhbGlkYXRlWmlwQ29kZSA9IGZ1bmN0aW9uICh6aXBDb2RlKSB7XG4gICAgdmFyIHJlZ2V4ZXMgPSB7XG4gICAgICAgICAgICBjYW5hZGE6IC9eW0FCQ0VHSEpLTE1OUFJTVFZYWV1cXGRbQUJDRUdISktMTU5QUlNUVldYWVpdKCApP1xcZFtBQkNFR0hKS0xNTlBSU1RWV1hZWl1cXGQkL2ksXG4gICAgICAgICAgICB1c2E6IC9eXFxkezV9KC1cXGR7NH0pPyQvXG4gICAgICAgIH0sXG4gICAgICAgIHZhbGlkID0gZmFsc2U7XG4gICAgaWYgKCF6aXBDb2RlKSB7IHJldHVybjsgfVxuICAgIF8uZWFjaChyZWdleGVzLCBmdW5jdGlvbiAocmUpIHtcbiAgICAgICAgdmFyIHJlZ2V4cCA9IG5ldyBSZWdFeHAocmUpO1xuICAgICAgICB2YWxpZCA9IHJlZ2V4cC50ZXN0KHppcENvZGUpO1xuICAgIH0pO1xuICAgIHJldHVybiB2YWxpZDtcbn07XG5cbnZhciBzdG9yZWludmVudG9yeSA9IHtcbiAgICB6aXBQcm9tcHQ6IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIGh0bWw6IHppcFByb21wdFRlbXBsYXRlKCksXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFJlc291cmNlcy5TVE9SRV9ORUFSX1lPVSxcbiAgICAgICAgICAgICAgICB3aWR0aDogNTAwLFxuICAgICAgICAgICAgICAgIGJ1dHRvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IFJlc291cmNlcy5TRUFSQ0gsXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgemlwQ29kZSA9ICQoJyN1c2VyLXppcCcpLnZhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkYXRlWmlwQ29kZSh6aXBDb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc2V0VXNlclppcCh6aXBDb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soemlwQ29kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcjdXNlci16aXAnKS5vbigna2V5cHJlc3MnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT09IDEzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciB0aGUgc2VhcmNoIGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoJy51aS1kaWFsb2ctYnV0dG9uc2V0IC51aS1idXR0b24nKS50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZ2V0U3RvcmVzSW52ZW50b3J5OiBmdW5jdGlvbiAocGlkKSB7XG4gICAgICAgIHJldHVybiBUUHJvbWlzZS5yZXNvbHZlKCQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IHV0aWwuYXBwZW5kUGFyYW1zVG9VcmwoVXJscy5zdG9yZXNJbnZlbnRvcnksIHtcbiAgICAgICAgICAgICAgICBwaWQ6IHBpZCxcbiAgICAgICAgICAgICAgICB6aXBDb2RlOiBVc2VyLnppcFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nXG4gICAgICAgIH0pKTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBvcGVuIHRoZSBkaWFsb2cgdG8gc2VsZWN0IHN0b3JlXG4gICAgICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5zdG9yZXNcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5zZWxlY3RlZFN0b3JlSWRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5zZWxlY3RlZFN0b3JlVGV4dFxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdGlvbnMuY29udGludWVDYWxsYmFja1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdGlvbnMuc2VsZWN0U3RvcmVDYWxsYmFja1xuICAgICAqKi9cbiAgICBzZWxlY3RTdG9yZURpYWxvZzogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgICAgc3RvcmVzID0gb3B0aW9ucy5zdG9yZXMsXG4gICAgICAgICAgICBzZWxlY3RlZFN0b3JlSWQgPSBvcHRpb25zLnNlbGVjdGVkU3RvcmVJZCxcbiAgICAgICAgICAgIHNlbGVjdGVkU3RvcmVUZXh0ID0gb3B0aW9ucy5zZWxlY3RlZFN0b3JlVGV4dCxcbiAgICAgICAgICAgIHN0b3JlTGlzdCA9IHN0b3JlTGlzdFRlbXBsYXRlKHN0b3Jlcywgc2VsZWN0ZWRTdG9yZUlkLCBzZWxlY3RlZFN0b3JlVGV4dCk7XG4gICAgICAgIGRpYWxvZy5vcGVuKHtcbiAgICAgICAgICAgIGh0bWw6IHN0b3JlTGlzdCxcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICB0aXRsZTogUmVzb3VyY2VzLlNFTEVDVF9TVE9SRSArICcgLSAnICsgVXNlci56aXAsXG4gICAgICAgICAgICAgICAgYnV0dG9uczogW3tcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogUmVzb3VyY2VzLkNIQU5HRV9MT0NBVElPTixcbiAgICAgICAgICAgICAgICAgICAgY2xpY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc2V0VXNlclppcChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyaWdnZXIgdGhlIGV2ZW50IHRvIHN0YXJ0IHRoZSBwcm9jZXNzIGFsbCBvdmVyIGFnYWluXG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcuc2V0LXByZWZlcnJlZC1zdG9yZScpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogUmVzb3VyY2VzLkNPTlRJTlVFLFxuICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuY29udGludWVDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuY29udGludWVDYWxsYmFjayhzdG9yZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGlhbG9nLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICBvcGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICQoJy5zZWxlY3Qtc3RvcmUtYnV0dG9uJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdG9yZUlkID0gJCh0aGlzKS5kYXRhKCdzdG9yZUlkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgc3RvcmUgaXMgYWxyZWFkeSBzZWxlY3RlZCwgZG9uJ3Qgc2VsZWN0IGFnYWluXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcmVJZCA9PT0gc2VsZWN0ZWRTdG9yZUlkKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJCgnLnN0b3JlLWxpc3QgLnN0b3JlLXRpbGUuc2VsZWN0ZWQnKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5maW5kKCcuc2VsZWN0LXN0b3JlLWJ1dHRvbicpLnRleHQoUmVzb3VyY2VzLlNFTEVDVF9TVE9SRSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRleHQoc2VsZWN0ZWRTdG9yZVRleHQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNsb3Nlc3QoJy5zdG9yZS10aWxlJykuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zZWxlY3RTdG9yZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zZWxlY3RTdG9yZUNhbGxiYWNrKHN0b3JlSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgc2V0VXNlclppcDogZnVuY3Rpb24gKHppcCkge1xuICAgICAgICBVc2VyLnppcCA9IHppcDtcbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgIHVybDogVXJscy5zZXRaaXBDb2RlLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHppcENvZGU6IHppcFxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHNoaXBwaW5nTG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGNoZWNrb3V0Rm9ybSA9ICQoJy5hZGRyZXNzJyk7XG4gICAgICAgICRjaGVja291dEZvcm0ub2ZmKCdjbGljaycpO1xuICAgICAgICAkY2hlY2tvdXRGb3JtLm9uKCdjbGljaycsICdpbnB1dFtuYW1lJD1cIl9zaGlwcGluZ0FkZHJlc3NfaXNHaWZ0XCJdJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS5wYXJlbnQoKS5zaWJsaW5ncygnLmdpZnQtbWVzc2FnZS10ZXh0JykudG9nZ2xlQ2xhc3MoJ2hpZGRlbicsICQoJ2lucHV0W25hbWUkPVwiX3NoaXBwaW5nQWRkcmVzc19pc0dpZnRcIl06Y2hlY2tlZCcpLnZhbCgpKTtcbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzdG9yZWludmVudG9yeTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcbiAgICBpbnZlbnRvcnkgPSByZXF1aXJlKCcuLycpO1xuXG52YXIgbmV3TGluZSA9ICdcXG4nO1xudmFyIHBkcFN0b3JlVGVtcGxhdGUgPSBmdW5jdGlvbiAoc3RvcmUpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAnPGxpIGNsYXNzPVwic3RvcmUtbGlzdC1pdGVtICcgKyAoc3RvcmUuc3RvcmVJZCA9PT0gVXNlci5zdG9yZUlkID8gJyBzZWxlY3RlZCcgOiAnJykgKyAnXCI+JyxcbiAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwic3RvcmUtYWRkcmVzc1wiPicgKyBzdG9yZS5hZGRyZXNzMSArICcsICcgKyBzdG9yZS5jaXR5ICsgJyAnICsgc3RvcmUuc3RhdGVDb2RlICtcbiAgICAgICAgJyAnICsgc3RvcmUucG9zdGFsQ29kZSArICc8L2Rpdj4nLFxuICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJzdG9yZS1zdGF0dXNcIiBkYXRhLXN0YXR1cz1cIicgKyBzdG9yZS5zdGF0dXNjbGFzcyArICdcIj4nICsgc3RvcmUuc3RhdHVzICsgJzwvZGl2PicsXG4gICAgICAgICc8L2xpPidcbiAgICBdLmpvaW4obmV3TGluZSk7XG59O1xudmFyIHBkcFN0b3Jlc0xpc3RpbmdUZW1wbGF0ZSA9IGZ1bmN0aW9uIChzdG9yZXMpIHtcbiAgICBpZiAoc3RvcmVzICYmIHN0b3Jlcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwic3RvcmUtbGlzdC1wZHAtY29udGFpbmVyXCI+JyxcbiAgICAgICAgICAgIChzdG9yZXMubGVuZ3RoID4gMSA/ICcgICAgPGEgY2xhc3M9XCJzdG9yZXMtdG9nZ2xlIGNvbGxhcHNlZFwiIGhyZWY9XCIjXCI+JyArIFJlc291cmNlcy5TRUVfTU9SRSArICc8L2E+JyA6ICcnKSxcbiAgICAgICAgICAgICcgICAgPHVsIGNsYXNzPVwic3RvcmUtbGlzdC1wZHBcIj4nLFxuICAgICAgICAgICAgXy5tYXAoc3RvcmVzLCBwZHBTdG9yZVRlbXBsYXRlKS5qb2luKG5ld0xpbmUpLFxuICAgICAgICAgICAgJyAgICA8L3VsPicsXG4gICAgICAgICAgICAnPC9kaXY+J1xuICAgICAgICBdLmpvaW4obmV3TGluZSk7XG4gICAgfVxufTtcblxudmFyIHN0b3Jlc0xpc3RpbmcgPSBmdW5jdGlvbiAoc3RvcmVzKSB7XG4gICAgLy8gbGlzdCBhbGwgc3RvcmVzIG9uIFBEUCBwYWdlXG4gICAgaWYgKCQoJy5zdG9yZS1saXN0LXBkcC1jb250YWluZXInKS5sZW5ndGgpIHtcbiAgICAgICAgJCgnLnN0b3JlLWxpc3QtcGRwLWNvbnRhaW5lcicpLnJlbW92ZSgpO1xuICAgIH1cbiAgICAkKCcuYXZhaWxhYmlsaXR5LXJlc3VsdHMnKS5hcHBlbmQocGRwU3RvcmVzTGlzdGluZ1RlbXBsYXRlKHN0b3JlcykpO1xufTtcblxudmFyIHByb2R1Y3RJbnZlbnRvcnkgPSB7XG4gICAgc2V0UHJlZmVycmVkU3RvcmU6IGZ1bmN0aW9uIChzdG9yZUlkKSB7XG4gICAgICAgIFVzZXIuc3RvcmVJZCA9IHN0b3JlSWQ7XG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IFVybHMuc2V0UHJlZmVycmVkU3RvcmUsXG4gICAgICAgICAgICB0eXBlOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhOiB7c3RvcmVJZDogc3RvcmVJZH1cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwcm9kdWN0U2VsZWN0U3RvcmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMucGlkKS50aGVuKGZ1bmN0aW9uIChzdG9yZXMpIHtcbiAgICAgICAgICAgIGludmVudG9yeS5zZWxlY3RTdG9yZURpYWxvZyh7XG4gICAgICAgICAgICAgICAgc3RvcmVzOiBzdG9yZXMsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZUlkOiBVc2VyLnN0b3JlSWQsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTdG9yZVRleHQ6IFJlc291cmNlcy5QUkVGRVJSRURfU1RPUkUsXG4gICAgICAgICAgICAgICAgY29udGludWVDYWxsYmFjazogc3RvcmVzTGlzdGluZyxcbiAgICAgICAgICAgICAgICBzZWxlY3RTdG9yZUNhbGxiYWNrOiBzZWxmLnNldFByZWZlcnJlZFN0b3JlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuZG9uZSgpO1xuICAgIH0sXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGF2YWlsYWJpbGl0eUNvbnRhaW5lciA9ICQoJy5hdmFpbGFiaWxpdHktcmVzdWx0cycpLFxuICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG4gICAgICAgIHRoaXMucGlkID0gJCgnaW5wdXRbbmFtZT1cInBpZFwiXScpLnZhbCgpO1xuXG4gICAgICAgICQoJyNwcm9kdWN0LWNvbnRlbnQgLnNldC1wcmVmZXJyZWQtc3RvcmUnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgaWYgKCFVc2VyLnppcCkge1xuICAgICAgICAgICAgICAgIGludmVudG9yeS56aXBQcm9tcHQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByb2R1Y3RTZWxlY3RTdG9yZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLnByb2R1Y3RTZWxlY3RTdG9yZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoJGF2YWlsYWJpbGl0eUNvbnRhaW5lci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChVc2VyLnN0b3JlSWQpIHtcbiAgICAgICAgICAgICAgICBpbnZlbnRvcnkuZ2V0U3RvcmVzSW52ZW50b3J5KHRoaXMucGlkKS50aGVuKHN0b3Jlc0xpc3RpbmcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZWUgbW9yZSBvciBsZXNzIHN0b3JlcyBpbiB0aGUgbGlzdGluZ1xuICAgICAgICAgICAgJGF2YWlsYWJpbGl0eUNvbnRhaW5lci5vbignY2xpY2snLCAnLnN0b3Jlcy10b2dnbGUnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAkKCcuc3RvcmUtbGlzdC1wZHAgLnN0b3JlLWxpc3QtaXRlbScpLnRvZ2dsZUNsYXNzKCd2aXNpYmxlJyk7XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykuaGFzQ2xhc3MoJ2NvbGxhcHNlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudGV4dChSZXNvdXJjZXMuU0VFX0xFU1MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudGV4dChSZXNvdXJjZXMuU0VFX01PUkUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkKHRoaXMpLnRvZ2dsZUNsYXNzKCdjb2xsYXBzZWQnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBwcm9kdWN0SW52ZW50b3J5O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5jb25zdCB7IHZhbHVlcyB9ID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxuZnVuY3Rpb24gZ2V0Q3VycmVudERhdGEoKXtcblx0aWYoc2pkYXRhLnBhZ2UgPT0gJ3NoaXBwaW5nJykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2RhdGE6Y2hlY2tvdXQnLCBbc2pkYXRhXSk7XG5cdH0gZWxzZSBpZihzamRhdGEucGFnZSA9PSAnb3JkZXJjb25maXJtYXRpb24nIHx8IHNqZGF0YS5wYWdlID09ICdjb25maXJtYXRpb24nKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignZGF0YTpwdXJjaGFzZScsIFtzamRhdGFdKTtcblx0fSBlbHNlIGlmKHNqZGF0YS5wYWdlID09ICdwcm9kdWN0Jykge1xuXHRcdCQoZG9jdW1lbnQpLnRyaWdnZXIoJ2RhdGE6cGRwJywgW3NqZGF0YV0pO1xuXHR9IGVsc2UgaWYoc2pkYXRhLnBhZ2UgPT0gJ3N1bW1hcnknKSB7XG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcignZGF0YTpwYXltZW50JywgW3NqZGF0YV0pO1xuXHR9XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdGluaXQ6IGZ1bmN0aW9uICgpIHtcblx0ICAgICQoZG9jdW1lbnQpLm9uKFwiZGF0YTphZGR0b2NhcnRcIiwgZnVuY3Rpb24oZSwgZGF0YSl7XG5cdFx0XHR0dHEudHJhY2soJ0FkZFRvQ2FydCcsIHtcblx0XHRcdFx0Y29udGVudF90eXBlOiBkYXRhLmNvbnRlbnRfdHlwZSxcblx0XHRcdFx0cXVhbnRpdHk6IGRhdGEucXR5LFxuXHQgICAgXHRcdGNvbnRlbnRfbmFtZTogZGF0YS5jb250ZW50X25hbWUsXG5cdFx0XHRcdGNvbnRlbnRfaWQ6IGRhdGEuY29udGVudF9pZHMsXG5cdFx0XHRcdGN1cnJlbmN5OiAnVVNEJyxcblx0XHRcdFx0dmFsdWU6IGRhdGEuY2FydFRvdGFsXG5cdFx0XHR9KTtcblx0ICAgIH0pO1xuXG5cdFx0JChkb2N1bWVudCkub24oXCJkYXRhOmNoZWNrb3V0XCIsIGZ1bmN0aW9uKGUsIGRhdGEpe1xuXHQgICAgXHR0dHEudHJhY2soJ0luaXRpYXRlQ2hlY2tvdXQnLCB7XG5cdCAgICBcdFx0dmFsdWU6IGRhdGEuY2FydFRvdGFsLFxuXHQgICAgXHRcdGN1cnJlbmN5OiBkYXRhLmN1cnJlbmN5LFxuXHQgICAgXHRcdHF1YW50aXR5IDogZGF0YS5xdHksXG5cdCAgICBcdFx0Y29udGVudHMgOiBbZGF0YS5waWRzXVxuXHQgICAgICAgIH0pO1xuXHQgICAgfSk7XG5cblx0ICAgICQoZG9jdW1lbnQpLm9uKFwiZGF0YTpwdXJjaGFzZVwiLCBmdW5jdGlvbihlLCBkYXRhKXtcblx0ICAgIFx0dHRxLnRyYWNrKCdQdXJjaGFzZScsIHtcblx0ICAgIFx0XHRjb250ZW50czogW2RhdGEucGlkc10sXG5cdCAgICBcdFx0Y3VycmVuY3k6IGRhdGEuY3VycmVuY3ksXG5cdCAgICBcdFx0dmFsdWU6IGRhdGEuY2FydFRvdGFsLFxuXHRcdFx0XHRxdWFudGl0eSA6IGRhdGEucXR5XG5cdCAgICAgICAgfSk7XG5cdCAgICB9KTtcblx0XHRcblx0ICAgICQoZG9jdW1lbnQpLm9uKFwiZGF0YTpwZHBcIiwgZnVuY3Rpb24oZSwgZGF0YSl7XG5cdCAgICBcdHR0cS50cmFjaygnVmlld0NvbnRlbnQnLCB7XG5cdFx0XHRcdHF1YW50aXR5IDogZGF0YS5xdHksXG5cdFx0XHRcdGN1cnJlbmN5OiBkYXRhLmN1cnJlbmN5LFxuXHRcdFx0XHR2YWx1ZTogZGF0YS52YWx1ZSxcblx0XHRcdFx0Y29udGVudHMgOiBkYXRhLnBpZHMsXG5cdCAgICBcdFx0Y29udGVudF90eXBlOiBkYXRhLmNvbnRlbnRfdHlwZSxcblx0ICAgIFx0XHRjb250ZW50X25hbWU6IGRhdGEuY29udGVudF9uYW1lXG5cdCAgICAgICAgfSk7XG5cdCAgICB9KTtcblxuXHQgICAgJChkb2N1bWVudCkub24oXCJkYXRhOnBheW1lbnRcIiwgZnVuY3Rpb24oZSwgZGF0YSl7XG5cdCAgICBcdHR0cS50cmFjaygnQWRkUGF5bWVudEluZm8nLCAge1xuXHQgICAgXHRcdGNvbnRlbnRzOiBbZGF0YS5waWRzXSxcblx0ICAgIFx0XHRjdXJyZW5jeTogZGF0YS5jdXJyZW5jeSxcblx0ICAgIFx0XHR2YWx1ZTogZGF0YS5jYXJ0VG90YWxcblx0ICAgICAgICB9KTtcblx0ICAgIH0pO1xuXG5cdFx0Z2V0Q3VycmVudERhdGEoKTtcblx0fVxufTsiLCIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBUTFMgYW5kIGRpc3BsYXlzIGEgd2FybmluZyBpZiBhcHByb3ByaWF0ZVxuICogQGZ1bmN0aW9uIGdldFVzZXJBZ2VudCBDaGVja3MgdGhlIFRMUyBhbmQgZGlzcGxheXMgYSB3YXJuaW5nIGlmIGFwcHJvcHJpYXRlXG4gKiovXG5mdW5jdGlvbiBnZXRVc2VyQWdlbnQoKSB7XG4gICAgLy8gVXNlIGFuIGV4dGVybmFsIHNlcnZpY2UgdG8gY2hlY2sgdGhlIFRMUyBvZiB0aGUgYnJvd3NlclxuICAgIC8vIE5PVEU6IHRoaXMgaW1wbGVtZW50YXRpb24gdXNlcyBodHRwczovL3d3dy5ob3dzbXlzc2wuY29tXG4gICAgLy8gICAgIHlvdSBtYXkgYWxzbyB3aXNoIHRvIGNvbnNpZGVyIHRoZSBBUEkgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3LnNzbGxhYnMuY29tL3Byb2plY3RzL3NzbGxhYnMtYXBpcy9pbmRleC5odG1sXG4gICAgdmFyIHVybCA9ICdodHRwczovL3d3dy5ob3dzbXlzc2wuY29tL2EvY2hlY2snO1xuICAgIHZhciBjb29raWVOYW1lID0gJ2R3X1RMU1dhcm5pbmcnO1xuICAgIHZhciBjb29raWVWYWx1ZSA9IGdldENvb2tpZShjb29raWVOYW1lKTtcblxuICAgIC8vIFRlc3QgdG8gc2VlIGlmIHRoaXMgYnJvd3NlciBoYXMgYWxyZWFkeSBiZWVuIGZsYWdnZWQgYnkgbG9va2luZyBhdCBpdHMgY29va2llc1xuICAgIGlmICghY29va2llVmFsdWUpIHtcbiAgICAgICAgZ2V0VExTKHVybCwgZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzaG93V2FybmluZyhtZXNzYWdlWzBdKTtcblxuICAgICAgICAgICAgICAgIC8vIHRoZSBicm93c2VyIGlzIGJhZCAtIHNldCB0aGUgY29va2llIHRvIHRydWUgKGZvciAxNSBtaW51dGVzKVxuICAgICAgICAgICAgICAgIHNldENvb2tpZShjb29raWVOYW1lLCAndHJ1ZScsIDE1KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZWxzZSB0aGUgYnJvd3NlciBpcyBnb29kLCBzZXQgdGhlIGNvb2tpZSB0byBmYWxzZSAoZm9yIDMwIGRheXMpIHNvIHdlIGRvbid0IGNoZWNrIGFnYWluXG4gICAgICAgICAgICAgICAgc2V0Q29va2llKGNvb2tpZU5hbWUsICdmYWxzZScsIDYwICogMjQgKiAzMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoY29va2llVmFsdWUgPT09ICd0cnVlJykge1xuICAgICAgICAvLyBpZiB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGlzIGlzIGFuIGludmFsaWQgYnJvd3Nlciwgc2hvdyB0aGUgd2FybmluZ1xuICAgICAgICBzaG93V2FybmluZyhSZXNvdXJjZXMuVExTX1dBUk5JTkcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxscyBvdXQgdG8gdGhlIFRMUyBzZXJ2aWNlIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgd2l0aCBhIG1lc3NhZ2UgKGlmIG5lY2Vzc2FyeSlcbiAqIEBmdW5jdGlvbiBnZXRUTFNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gVVJMIG9mIGV4dGVybmFsIFRMUy1jaGVja2luZyBBUElcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gZnVuY3Rpb24gdG8gY2FsbCB3aXRoIHJlc3BvbnNlXG4gKiovXG5mdW5jdGlvbiBnZXRUTFModXJsLCBjYWxsYmFjaykge1xuICAgIHZhciBtZXNzYWdlID0gW107XG5cbiAgICAvLyBGaXJzdCwgc2VlIGlmIHRoZSBicm93c2VyIGlzIGFtb25nIHRoZSBzdXNwZWN0IGJyb3dzZXJzIHRvIHNlZSBpZiBhIFRMUyBjaGVjayBpcyBuZWNlc3NhcnlcbiAgICB2YXIgdXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGlzIGxpc3QgZGVyaXZlZCBmcm9tIGh0dHBzOi8vd3d3LnNzbGxhYnMuY29tL3NzbHRlc3QvY2xpZW50cy5odG1sICoqL1xuICAgIHZhciBiYWRCcm93c2VycyA9IFsnTVNJRSA2LjAnLCdNU0lFIDcuMCcsJ01TSUUgOC4wJywnTVNJRSA5LjAnLCdNU0lFIDEwLjAnLFxuICAgICAgICAgICAgICAgICAgICAgICAnQW5kcm9pZCAyLjMuNycsICdBbmRyb2lkIDQuMC40JywgJ0FuZHJvaWQgNC4xLjEnLCAnQW5kcm9pZCA0LjIuMicsICdBbmRyb2lkIDQuMycsXG4gICAgICAgICAgICAgICAgICAgICAgICdTYWZhcmkgNS4xLjkgLyBPUyBYIDEwLjYuOCcsICdTYWZhcmkgNi4wLjQgLyBPUyBYIDEwLjguNCAnXTtcbiAgICBmdW5jdGlvbiBjaGVja1RMU0xldmVsKGRhdGEpIHtcbiAgICAgICAgLy8gSWYgd2UgY2FuIGRldGVybWluZSB0aGUgVExTIGxldmVsLCBjaGVjayB0byBzZWUgaWYgaXQncyBsZXNzIHRoYW4gMS4yXG4gICAgICAgIGlmIChwYXJzZUZsb2F0KGRhdGEudGxzX3ZlcnNpb24uc3BsaXQoJyAnKVsxXSkgPCAxLjEpIHtcbiAgICAgICAgICAgIG1lc3NhZ2UucHVzaChSZXNvdXJjZXMuVExTX1dBUk5JTkcpO1xuICAgICAgICAgICAgY2FsbGJhY2sobWVzc2FnZSk7XG5cbiAgICAgICAgICAgIC8vSWYgeW91IHdhbnQgdG8gdHJhY2sgc3RhdGlzdGljcyBvbiBiYWQgVExTIGhpdHMsIGluY2x1ZGUgdGhpcyBjYWxsXG4gICAgICAgICAgICAkLmFqYXgoe3VybDogVXJscy5UTFNCYWRUTFN9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlcG9ydEJhZEJyb3dzZXIgKCkge1xuICAgICAgICAvLyBJZiB0aGUgVExTIGxldmVsIGNhbm5vdCBiZSBkZXRlcm1pbmVkIGp1c3QgcmVwb3J0IHRoYXQgdGhpcyBicm93c2VyIGlzIHN1c3BlY3RcbiAgICAgICAgbWVzc2FnZS5wdXNoKFJlc291cmNlcy5UTFNfV0FSTklORyk7XG4gICAgICAgIGNhbGxiYWNrKG1lc3NhZ2UpO1xuXG4gICAgICAgIC8vSWYgeW91IHdhbnQgdG8gdHJhY2sgc3RhdGlzdGljcyBvbiBkZXByZWNhdGVkIGJyb3dzZXJzLCBpbmNsdWRlIHRoaXMgY2FsbFxuICAgICAgICAkLmFqYXgoe3VybDogVXJscy5UTFNCYWRCcm93c2VyfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiYWRCcm93c2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodXNlckFnZW50Lm1hdGNoKGJhZEJyb3dzZXJzW2ldKSkge1xuICAgICAgICAgICAgLy8gSXQncyBhIHN1c3BlY3QgYnJvd3NlciwgbGV0J3Mgc2VlIHdoYXQgaXQncyBUTFMgbGV2ZWwgaXNcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiB1cmxcbiAgICAgICAgICAgIH0pLmRvbmUoY2hlY2tUTFNMZXZlbCkuZmFpbChyZXBvcnRCYWRCcm93c2VyKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEZvciB0ZXN0aW5nIHB1cnBvc2VzLCB1bmNvbW1lbnQgdGhpcyBibG9ja1xuICAgICAgICBtZXNzYWdlLnB1c2goUmVzb3VyY2VzLlRMU19XQVJOSU5HKTtcbiAgICAqKi9cbiAgICBjYWxsYmFjayhtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb24gc2hvd1dhcm5pbmcgdHVybnMgb24gdGhlIGJyb3dzZXItY29tcGF0aWJpbGl0eS1hbGVydCBhbmQgc2V0cyB0aGUgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gdGhlIG1lc3NhZ2UgdGhhdCB3aWxsIGJlIHNob3duIHVwb24gZGV0ZWN0aW9uIG9mIGEgYmFkIGJyb3dzZXJcbiAqKi9cbmZ1bmN0aW9uIHNob3dXYXJuaW5nKG1lc3NhZ2UpIHtcbiAgICAkKCc8ZGl2Lz4nKS5hZGRDbGFzcygnYnJvd3Nlci1jb21wYXRpYmlsaXR5LWFsZXJ0JykuYXBwZW5kKCQoJzxwLz4nKS5hZGRDbGFzcygnYnJvd3Nlci1lcnJvcicpLmh0bWwobWVzc2FnZSkpLmFwcGVuZFRvKCcjYnJvd3Nlci1jaGVjaycpO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBnZXRDb29raWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGNvb2tpZSBuYW1lXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB2YWx1ZSAtIHRoZSB2YWx1ZSBvZiB0aGUgY29va2llIGlmIGZvdW5kLCBudWxsIG90aGVyd2lzZVxuICoqL1xuZnVuY3Rpb24gZ2V0Q29va2llKGtleSkge1xuICAgIHZhciBjb29raWVzID0gZG9jdW1lbnQuY29va2llLnNwbGl0KCc7Jyk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb29raWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0b2tlbnMgPSBjb29raWVzW2ldLnNwbGl0KCc9Jyk7XG4gICAgICAgIHZhciBjb29raWVLZXkgPSB0b2tlbnNbMF0udHJpbSgpO1xuICAgICAgICBpZiAoY29va2llS2V5ID09PSBrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiB0b2tlbnNbMV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvbiBzZXRDb29raWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGNvb2tpZSBuYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgY29va2llIHZhbHVlXG4gKiBAcGFyYW0ge2ludGVnZXJ9IG1pbnV0ZXMgLSBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgdG8gZXhwaXJlIHRoZSBjb29raWVcbiAqKi9cbmZ1bmN0aW9uIHNldENvb2tpZSAoa2V5LCB2YWx1ZSwgbWludXRlcykge1xuICAgIHZhciBkYXRlID0gbmV3IERhdGUoKTtcbiAgICBkYXRlLnNldFRpbWUoZGF0ZSArIChtaW51dGVzICogNjAgKiAxMDAwKSk7XG5cbiAgICBkb2N1bWVudC5jb29raWUgPSBrZXkgKyAnPScgKyB2YWx1ZSArICc7IGV4cGlyZXM9JyArIGRhdGUudG9HTVRTdHJpbmcoKSArICc7IHBhdGg9Lyc7XG59XG5cbi8qKlxuICogRXhwb3J0IHRoZSBnZXRVc2VyQWdlbnQgZnVuY3Rpb25cbiAqL1xuXG5leHBvcnRzLmdldFVzZXJBZ2VudCA9IGdldFVzZXJBZ2VudDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgdG9vbHRpcC1jb250ZW50IGFuZCBsYXlvdXRcbiAqL1xuZXhwb3J0cy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICQoZG9jdW1lbnQpLnRvb2x0aXAoe1xuICAgICAgICBpdGVtczogJy50b29sdGlwJyxcbiAgICAgICAgdHJhY2s6IHRydWUsXG4gICAgICAgIGNvbnRlbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAkKHRoaXMpLmZpbmQoJy50b29sdGlwLWNvbnRlbnQnKS5odG1sKCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgICQoJy5zaGFyZS1saW5rJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2YXIgdGFyZ2V0ID0gJCh0aGlzKS5kYXRhKCd0YXJnZXQnKTtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAkKHRhcmdldCkudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgIH0pO1xuICAgIFxuICAgICQoZG9jdW1lbnQpLm9uKCdjbGljaycsJy50b29sdGlwOm5vdChcIi5jbGljay10aHJvdWdoXCIpJyxmdW5jdGlvbihlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG5cbnZhciB1dGlsID0ge1xuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBhcHBlbmRzIHRoZSBwYXJhbWV0ZXIgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgdmFsdWUgdG8gdGhlIGdpdmVuIHVybCBhbmQgcmV0dXJucyB0aGUgY2hhbmdlZCB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIHRoZSB1cmwgdG8gd2hpY2ggdGhlIHBhcmFtZXRlciB3aWxsIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHBhcmFtZXRlclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSB0aGUgdmFsdWUgb2YgdGhlIHBhcmFtZXRlclxuICAgICAqL1xuICAgIGFwcGVuZFBhcmFtVG9VUkw6IGZ1bmN0aW9uICh1cmwsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIC8vIHF1aXQgaWYgdGhlIHBhcmFtIGFscmVhZHkgZXhpc3RzXG4gICAgICAgIGlmICh1cmwuaW5kZXhPZihuYW1lICsgJz0nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNlcGFyYXRvciA9IHVybC5pbmRleE9mKCc/JykgIT09IC0xID8gJyYnIDogJz8nO1xuICAgICAgICByZXR1cm4gdXJsICsgc2VwYXJhdG9yICsgbmFtZSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiByZW1vdmUgdGhlIHBhcmFtZXRlciBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGdpdmVuIHVybCBhbmQgcmV0dXJucyB0aGUgY2hhbmdlZCB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIHRoZSB1cmwgZnJvbSB3aGljaCB0aGUgcGFyYW1ldGVyIHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHBhcmFtZXRlciB0aGF0IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHVybFxuICAgICAqL1xuICAgIHJlbW92ZVBhcmFtRnJvbVVSTDogZnVuY3Rpb24gKHVybCwgbmFtZSkge1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoJz8nKSA9PT0gLTEgfHwgdXJsLmluZGV4T2YobmFtZSArICc9JykgPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoYXNoO1xuICAgICAgICB2YXIgcGFyYW1zO1xuICAgICAgICB2YXIgZG9tYWluID0gdXJsLnNwbGl0KCc/JylbMF07XG4gICAgICAgIHZhciBwYXJhbVVybCA9IHVybC5zcGxpdCgnPycpWzFdO1xuICAgICAgICB2YXIgbmV3UGFyYW1zID0gW107XG4gICAgICAgIC8vIGlmIHRoZXJlIGlzIGEgaGFzaCBhdCB0aGUgZW5kLCBzdG9yZSB0aGUgaGFzaFxuICAgICAgICBpZiAocGFyYW1VcmwuaW5kZXhPZignIycpID4gLTEpIHtcbiAgICAgICAgICAgIGhhc2ggPSBwYXJhbVVybC5zcGxpdCgnIycpWzFdIHx8ICcnO1xuICAgICAgICAgICAgcGFyYW1VcmwgPSBwYXJhbVVybC5zcGxpdCgnIycpWzBdO1xuICAgICAgICB9XG4gICAgICAgIHBhcmFtcyA9IHBhcmFtVXJsLnNwbGl0KCcmJyk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAvLyBwdXQgYmFjayBwYXJhbSB0byBuZXdQYXJhbXMgYXJyYXkgaWYgaXQgaXMgbm90IHRoZSBvbmUgdG8gYmUgcmVtb3ZlZFxuICAgICAgICAgICAgaWYgKHBhcmFtc1tpXS5zcGxpdCgnPScpWzBdICE9PSBuYW1lKSB7XG4gICAgICAgICAgICAgICAgbmV3UGFyYW1zLnB1c2gocGFyYW1zW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZG9tYWluICsgJz8nICsgbmV3UGFyYW1zLmpvaW4oJyYnKSArIChoYXNoID8gJyMnICsgaGFzaCA6ICcnKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIGFwcGVuZHMgdGhlIHBhcmFtZXRlcnMgdG8gdGhlIGdpdmVuIHVybCBhbmQgcmV0dXJucyB0aGUgY2hhbmdlZCB1cmxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIHRoZSB1cmwgdG8gd2hpY2ggdGhlIHBhcmFtZXRlcnMgd2lsbCBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXNcbiAgICAgKi9cbiAgICBhcHBlbmRQYXJhbXNUb1VybDogZnVuY3Rpb24gKHVybCwgcGFyYW1zKSB7XG4gICAgICAgIHZhciBfdXJsID0gdXJsO1xuICAgICAgICBfLmVhY2gocGFyYW1zLCBmdW5jdGlvbiAodmFsdWUsIG5hbWUpIHtcbiAgICAgICAgICAgIF91cmwgPSB0aGlzLmFwcGVuZFBhcmFtVG9VUkwoX3VybCwgbmFtZSwgdmFsdWUpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICByZXR1cm4gX3VybDtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBleHRyYWN0IHRoZSBxdWVyeSBzdHJpbmcgZnJvbSBVUkxcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIHRoZSB1cmwgdG8gZXh0cmEgcXVlcnkgc3RyaW5nIGZyb21cbiAgICAgKiovXG4gICAgZ2V0UXVlcnlTdHJpbmc6IGZ1bmN0aW9uICh1cmwpIHtcbiAgICAgICAgdmFyIHFzO1xuICAgICAgICBpZiAoIV8uaXNTdHJpbmcodXJsKSkgeyByZXR1cm47IH1cbiAgICAgICAgdmFyIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgaWYgKGEuc2VhcmNoKSB7XG4gICAgICAgICAgICBxcyA9IGEuc2VhcmNoLnN1YnN0cigxKTsgLy8gcmVtb3ZlIHRoZSBsZWFkaW5nID9cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcXM7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiBAcGFyYW0ge1N0cmluZ31cbiAgICAgKiBAcGFyYW0ge1N0cmluZ31cbiAgICAgKi9cbiAgICBlbGVtZW50SW5WaWV3cG9ydDogZnVuY3Rpb24gKGVsLCBvZmZzZXRUb1RvcCkge1xuICAgICAgICB2YXIgdG9wID0gZWwub2Zmc2V0VG9wLFxuICAgICAgICAgICAgbGVmdCA9IGVsLm9mZnNldExlZnQsXG4gICAgICAgICAgICB3aWR0aCA9IGVsLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0ID0gZWwub2Zmc2V0SGVpZ2h0O1xuXG4gICAgICAgIHdoaWxlIChlbC5vZmZzZXRQYXJlbnQpIHtcbiAgICAgICAgICAgIGVsID0gZWwub2Zmc2V0UGFyZW50O1xuICAgICAgICAgICAgdG9wICs9IGVsLm9mZnNldFRvcDtcbiAgICAgICAgICAgIGxlZnQgKz0gZWwub2Zmc2V0TGVmdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2Yob2Zmc2V0VG9Ub3ApICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdG9wIC09IG9mZnNldFRvVG9wO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHdpbmRvdy5wYWdlWE9mZnNldCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB0b3AgPCAod2luZG93LnBhZ2VZT2Zmc2V0ICsgd2luZG93LmlubmVySGVpZ2h0KSAmJlxuICAgICAgICAgICAgICAgIGxlZnQgPCAod2luZG93LnBhZ2VYT2Zmc2V0ICsgd2luZG93LmlubmVyV2lkdGgpICYmXG4gICAgICAgICAgICAgICAgKHRvcCArIGhlaWdodCkgPiB3aW5kb3cucGFnZVlPZmZzZXQgJiZcbiAgICAgICAgICAgICAgICAobGVmdCArIHdpZHRoKSA+IHdpbmRvdy5wYWdlWE9mZnNldFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkb2N1bWVudC5jb21wYXRNb2RlID09PSAnQ1NTMUNvbXBhdCcpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdG9wIDwgKHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wICsgd2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpICYmXG4gICAgICAgICAgICAgICAgbGVmdCA8ICh3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgKyB3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoKSAmJlxuICAgICAgICAgICAgICAgICh0b3AgKyBoZWlnaHQpID4gd2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgJiZcbiAgICAgICAgICAgICAgICAobGVmdCArIHdpZHRoKSA+IHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb24gQXBwZW5kcyB0aGUgcGFyYW1ldGVyICdmb3JtYXQ9YWpheCcgdG8gYSBnaXZlbiBwYXRoXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHBhdGggdGhlIHJlbGF0aXZlIHBhdGhcbiAgICAgKi9cbiAgICBhamF4VXJsOiBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hcHBlbmRQYXJhbVRvVVJMKHBhdGgsICdmb3JtYXQnLCAnYWpheCcpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gICAgICovXG4gICAgdG9BYnNvbHV0ZVVybDogZnVuY3Rpb24gKHVybCkge1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoJ2h0dHAnKSAhPT0gMCAmJiB1cmwuY2hhckF0KDApICE9PSAnLycpIHtcbiAgICAgICAgICAgIHVybCA9ICcvJyArIHVybDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXJsO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIExvYWRzIGNzcyBkeW5hbWljYWxseSBmcm9tIGdpdmVuIHVybHNcbiAgICAgKiBAcGFyYW0ge0FycmF5fSB1cmxzIEFycmF5IG9mIHVybHMgZnJvbSB3aGljaCBjc3Mgd2lsbCBiZSBkeW5hbWljYWxseSBsb2FkZWQuXG4gICAgICovXG4gICAgbG9hZER5bmFtaWNDc3M6IGZ1bmN0aW9uICh1cmxzKSB7XG4gICAgICAgIHZhciBpLCBsZW4gPSB1cmxzLmxlbmd0aDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmxvYWRlZENzc0ZpbGVzLnB1c2godGhpcy5sb2FkQ3NzRmlsZSh1cmxzW2ldKSk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIExvYWRzIGNzcyBmaWxlIGR5bmFtaWNhbGx5IGZyb20gZ2l2ZW4gdXJsXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHVybCBUaGUgdXJsIGZyb20gd2hpY2ggY3NzIGZpbGUgd2lsbCBiZSBkeW5hbWljYWxseSBsb2FkZWQuXG4gICAgICovXG4gICAgbG9hZENzc0ZpbGU6IGZ1bmN0aW9uICh1cmwpIHtcbiAgICAgICAgcmV0dXJuICQoJzxsaW5rLz4nKS5hcHBlbmRUbygkKCdoZWFkJykpLmF0dHIoe1xuICAgICAgICAgICAgdHlwZTogJ3RleHQvY3NzJyxcbiAgICAgICAgICAgIHJlbDogJ3N0eWxlc2hlZXQnXG4gICAgICAgIH0pLmF0dHIoJ2hyZWYnLCB1cmwpOyAvLyBmb3IgaS5lLiA8OSwgaHJlZiBtdXN0IGJlIGFkZGVkIGFmdGVyIGxpbmsgaGFzIGJlZW4gYXBwZW5kZWQgdG8gaGVhZFxuICAgIH0sXG4gICAgLy8gYXJyYXkgdG8ga2VlcCB0cmFjayBvZiB0aGUgZHluYW1pY2FsbHkgbG9hZGVkIENTUyBmaWxlc1xuICAgIGxvYWRlZENzc0ZpbGVzOiBbXSxcblxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBSZW1vdmVzIGFsbCBjc3MgZmlsZXMgd2hpY2ggd2VyZSBkeW5hbWljYWxseSBsb2FkZWRcbiAgICAgKi9cbiAgICBjbGVhckR5bmFtaWNDc3M6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGkgPSB0aGlzLmxvYWRlZENzc0ZpbGVzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKDAgPiBpLS0pIHtcbiAgICAgICAgICAgICQodGhpcy5sb2FkZWRDc3NGaWxlc1tpXSkucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2FkZWRDc3NGaWxlcyA9IFtdO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEV4dHJhY3RzIGFsbCBwYXJhbWV0ZXJzIGZyb20gYSBnaXZlbiBxdWVyeSBzdHJpbmcgaW50byBhbiBvYmplY3RcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcXMgVGhlIHF1ZXJ5IHN0cmluZyBmcm9tIHdoaWNoIHRoZSBwYXJhbWV0ZXJzIHdpbGwgYmUgZXh0cmFjdGVkXG4gICAgICovXG4gICAgZ2V0UXVlcnlTdHJpbmdQYXJhbXM6IGZ1bmN0aW9uIChxcykge1xuICAgICAgICBpZiAoIXFzIHx8IHFzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4ge307IH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHt9LFxuICAgICAgICAgICAgdW5lc2NhcGVkUVMgPSBkZWNvZGVVUklDb21wb25lbnQocXMpO1xuICAgICAgICAvLyBVc2UgdGhlIFN0cmluZzo6cmVwbGFjZSBtZXRob2QgdG8gaXRlcmF0ZSBvdmVyIGVhY2hcbiAgICAgICAgLy8gbmFtZS12YWx1ZSBwYWlyIGluIHRoZSBzdHJpbmcuXG4gICAgICAgIHVuZXNjYXBlZFFTLnJlcGxhY2UobmV3IFJlZ0V4cCgnKFtePz0mXSspKD0oW14mXSopKT8nLCAnZycpLFxuICAgICAgICAgICAgZnVuY3Rpb24gKCQwLCAkMSwgJDIsICQzKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zWyQxXSA9ICQzO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH0sXG5cbiAgICBmaWxsQWRkcmVzc0ZpZWxkczogZnVuY3Rpb24gKGFkZHJlc3MsICRmb3JtKSB7XG4gICAgICAgIGZvciAodmFyIGZpZWxkIGluIGFkZHJlc3MpIHtcbiAgICAgICAgICAgIGlmIChmaWVsZCA9PT0gJ0lEJyB8fCBmaWVsZCA9PT0gJ1VVSUQnIHx8IGZpZWxkID09PSAna2V5JyB8fCBmaWVsZCA9PT0gJ3R5cGUnKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiB0aGUga2V5IGluIGFkZHJlc3Mgb2JqZWN0IGVuZHMgd2l0aCAnQ29kZScsIHJlbW92ZSB0aGF0IHN1ZmZpeFxuICAgICAgICAgICAgLy8ga2V5cyB0aGF0IGVuZHMgd2l0aCAnQ29kZScgYXJlIHBvc3RhbENvZGUsIHN0YXRlQ29kZSBhbmQgY291bnRyeUNvZGVcbiAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cIicgKyBmaWVsZC5yZXBsYWNlKCdDb2RlJywgJycpICsgJ1wiXScpLnZhbChhZGRyZXNzW2ZpZWxkXSkudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHN0YXRlIGZpZWxkc1xuICAgICAgICAgICAgaWYgKGZpZWxkID09PSAnY291bnRyeUNvZGUnKSB7XG4gICAgICAgICAgICAgICAgJGZvcm0uZmluZCgnW25hbWUkPVwiY291bnRyeVwiXScpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgICAgIC8vIHJldHJpZ2dlciBzdGF0ZSBzZWxlY3Rpb24gYWZ0ZXIgY291bnRyeSBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgICAgIC8vIHRoaXMgcmVzdWx0cyBpbiBkdXBsaWNhdGlvbiBvZiB0aGUgc3RhdGUgY29kZSwgYnV0IGlzIGEgbmVjZXNzYXJ5IGV2aWxcbiAgICAgICAgICAgICAgICAvLyBmb3Igbm93IGJlY2F1c2Ugc29tZXRpbWVzIGNvdW50cnlDb2RlIGNvbWVzIGFmdGVyIHN0YXRlQ29kZVxuICAgICAgICAgICAgICAgICRmb3JtLmZpbmQoJ1tuYW1lJD1cInN0YXRlXCJdJykudmFsKGFkZHJlc3Muc3RhdGVDb2RlKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgICAgICAkKFwiW25hbWUkPV9zdGF0ZU5hbWVdXCIpLnZhbCgkKCdbbmFtZSQ9XCJzdGF0ZVwiXScpLmZpbmQoXCJvcHRpb246c2VsZWN0ZWRcIikudGV4dCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIG51bWJlciBvZiB0aGUgcmVtYWluaW5nIGNoYXJhY3RlclxuICAgICAqIGJhc2VkIG9uIHRoZSBjaGFyYWN0ZXIgbGltaXQgaW4gYSB0ZXh0IGFyZWFcbiAgICAgKi9cbiAgICBsaW1pdENoYXJhY3RlcnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJCgnZm9ybScpLmZpbmQoJ3RleHRhcmVhW2RhdGEtY2hhcmFjdGVyLWxpbWl0XScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNoYXJhY3RlckxpbWl0ID0gJCh0aGlzKS5kYXRhKCdjaGFyYWN0ZXItbGltaXQnKTtcbiAgICAgICAgICAgIHZhciBjaGFyQ291bnRIdG1sID0gU3RyaW5nLmZvcm1hdChSZXNvdXJjZXMuQ0hBUl9MSU1JVF9NU0csXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiY2hhci1yZW1haW4tY291bnRcIj4nICsgY2hhcmFjdGVyTGltaXQgKyAnPC9zcGFuPicsXG4gICAgICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiY2hhci1hbGxvd2VkLWNvdW50XCI+JyArIGNoYXJhY3RlckxpbWl0ICsgJzwvc3Bhbj4nKTtcbiAgICAgICAgICAgIHZhciBjaGFyQ291bnRDb250YWluZXIgPSAkKHRoaXMpLm5leHQoJ2Rpdi5jaGFyLWNvdW50Jyk7XG4gICAgICAgICAgICBpZiAoY2hhckNvdW50Q29udGFpbmVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNoYXJDb3VudENvbnRhaW5lciA9ICQoJzxkaXYgY2xhc3M9XCJjaGFyLWNvdW50XCIvPicpLmluc2VydEFmdGVyKCQodGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hhckNvdW50Q29udGFpbmVyLmh0bWwoY2hhckNvdW50SHRtbCk7XG4gICAgICAgICAgICAvLyB0cmlnZ2VyIHRoZSBrZXlkb3duIGV2ZW50IHNvIHRoYXQgYW55IGV4aXN0aW5nIGNoYXJhY3RlciBkYXRhIGlzIGNhbGN1bGF0ZWRcbiAgICAgICAgICAgICQodGhpcykuY2hhbmdlKCk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIEJpbmRzIHRoZSBvbmNsaWNrLWV2ZW50IHRvIGEgZGVsZXRlIGJ1dHRvbiBvbiBhIGdpdmVuIGNvbnRhaW5lcixcbiAgICAgKiB3aGljaCBvcGVucyBhIGNvbmZpcm1hdGlvbiBib3ggd2l0aCBhIGdpdmVuIG1lc3NhZ2VcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gY29udGFpbmVyIFRoZSBuYW1lIG9mIGVsZW1lbnQgdG8gd2hpY2ggdGhlIGZ1bmN0aW9uIHdpbGwgYmUgYmluZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRoZSB3aWxsIGJlIHNob3duIHVwb24gYSBjbGlja1xuICAgICAqL1xuICAgIHNldERlbGV0ZUNvbmZpcm1hdGlvbjogZnVuY3Rpb24gKGNvbnRhaW5lciwgbWVzc2FnZSkge1xuICAgICAgICAkKGNvbnRhaW5lcikub24oJ2NsaWNrJywgJy5kZWxldGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmNvbmZpcm0obWVzc2FnZSk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQGZ1bmN0aW9uXG4gICAgICogQGRlc2NyaXB0aW9uIFNjcm9sbHMgYSBicm93c2VyIHdpbmRvdyB0byBhIGdpdmVuIHggcG9pbnRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gVGhlIHggY29vcmRpbmF0ZVxuICAgICAqL1xuICAgIHNjcm9sbEJyb3dzZXI6IGZ1bmN0aW9uICh4TG9jYXRpb24pIHtcbiAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoe3Njcm9sbFRvcDogeExvY2F0aW9ufSwgNTAwKTtcbiAgICB9LFxuXG4gICAgaXNNb2JpbGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1vYmlsZUFnZW50SGFzaCA9IFsnbW9iaWxlJywgJ3RhYmxldCcsICdwaG9uZScsICdpcGFkJywgJ2lwb2QnLCAnYW5kcm9pZCcsICdibGFja2JlcnJ5JywgJ3dpbmRvd3MgY2UnLCAnb3BlcmEgbWluaScsICdwYWxtJ107XG4gICAgICAgIHZhciAgICBpZHggPSAwO1xuICAgICAgICB2YXIgaXNNb2JpbGUgPSBmYWxzZTtcbiAgICAgICAgdmFyIHVzZXJBZ2VudCA9IChuYXZpZ2F0b3IudXNlckFnZW50KS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIHdoaWxlIChtb2JpbGVBZ2VudEhhc2hbaWR4XSAmJiAhaXNNb2JpbGUpIHtcbiAgICAgICAgICAgIGlzTW9iaWxlID0gKHVzZXJBZ2VudC5pbmRleE9mKG1vYmlsZUFnZW50SGFzaFtpZHhdKSA+PSAwKTtcbiAgICAgICAgICAgIGlkeCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc01vYmlsZTtcbiAgICB9LFxuICAgIFxuICAgIC8qKlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIHNlbGVjdGVkIHRleHQgaW4gaW5wdXQgb3IgdGV4dCBhcmVhXG4gICAgICovXG4gICAgZ2V0U2VsZWN0aW9uVGV4dDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdGV4dCA9IFwiXCI7XG4gICAgICAgIHZhciBhY3RpdmVFbCA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgICAgIHZhciBhY3RpdmVFbFRhZ05hbWUgPSBhY3RpdmVFbCA/IGFjdGl2ZUVsLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA6IG51bGw7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAoYWN0aXZlRWxUYWdOYW1lID09IFwidGV4dGFyZWFcIikgfHwgKGFjdGl2ZUVsVGFnTmFtZSA9PSBcImlucHV0XCIgJiZcbiAgICAgICAgICAvXig/OnRleHR8c2VhcmNofHBhc3N3b3JkfHRlbHx1cmwpJC9pLnRlc3QoYWN0aXZlRWwudHlwZSkpICYmXG4gICAgICAgICAgKHR5cGVvZiBhY3RpdmVFbC5zZWxlY3Rpb25TdGFydCA9PSBcIm51bWJlclwiKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRleHQgPSBhY3RpdmVFbC52YWx1ZS5zbGljZShhY3RpdmVFbC5zZWxlY3Rpb25TdGFydCwgYWN0aXZlRWwuc2VsZWN0aW9uRW5kKTtcbiAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XG4gICAgICAgICAgICB0ZXh0ID0gd2luZG93LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB1dGlsO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbmFQaG9uZSA9IC9eXFwoPyhbMi05XVswLThdWzAtOV0pXFwpP1tcXC1cXC4gXT8oWzItOV1bMC05XXsyfSlbXFwtXFwuIF0/KFswLTldezR9KShcXHMqeFswLTldKyk/JC87XG52YXIgcmVnZXggPSB7XG4gICAgcGhvbmU6IHtcbiAgICAgICAgdXM6IG5hUGhvbmUsXG4gICAgICAgIGNhOiBuYVBob25lLFxuICAgICAgICBmcjogL14wWzEtNl17MX0oKFswLTldezJ9KXs0fSl8KChcXHNbMC05XXsyfSl7NH0pfCgoLVswLTldezJ9KXs0fSkkLyxcbiAgICAgICAgaXQ6IC9eKChbMC05XXsyLDR9KShbLVxcc1xcL117MCwxfSkoWzAtOV17NCw4fSkpPyQvLFxuICAgICAgICBqcDogL14oMFxcZHsxLDR9LSA/KT9cXGR7MSw0fS1cXGR7NH0kLyxcbiAgICAgICAgY246IC8uKi8sXG4gICAgICAgIGdiOiAvXigoXFwoPzBcXGR7NH1cXCk/XFxzP1xcZHszfVxccz9cXGR7M30pfChcXCg/MFxcZHszfVxcKT9cXHM/XFxkezN9XFxzP1xcZHs0fSl8KFxcKD8wXFxkezJ9XFwpP1xccz9cXGR7NH1cXHM/XFxkezR9KSkoXFxzP1xcIyhcXGR7NH18XFxkezN9KSk/JC9cbiAgICB9LFxuICAgIHBvc3RhbDoge1xuICAgICAgICB1czogL15cXGR7NX0oLVxcZHs0fSk/JC8sXG4gICAgICAgIGNhOiAvXltBQkNFR0hKS0xNTlBSU1RWWFldezF9XFxkezF9W0EtWl17MX0gKlxcZHsxfVtBLVpdezF9XFxkezF9JC8sXG4gICAgICAgIGZyOiAvXihGLSk/KCgyW0F8Ql0pfFswLTldezJ9KVswLTldezN9JC8sXG4gICAgICAgIGl0OiAvXihbMC05XSl7NX0kLyxcbiAgICAgICAganA6IC9eKFswLTldKXszfVstXShbMC05XSl7NH0kLyxcbiAgICAgICAgY246IC9eKFswLTldKXs2fSQvLFxuICAgICAgICBnYjogL14oW0EtUFItVVdZWjAtOV1bQS1ISy1ZMC05XVtBRUhNTlBSVFZYWTAtOV0/W0FCRUhNTlBSVldYWTAtOV0/IHsxLDJ9WzAtOV1bQUJELUhKTE4tVVctWl17Mn18R0lSIDBBQSkkL1xuICAgIH0sXG4gICAgbm90Q0M6IC9eKD8hKChbMC05IC1dKXsxMywxOX0pKS4qJC8sXG4gICAgdmFsaWRQb3N0YWw6IC8oXlxcZHs1fSgtXFxkezR9KT8kKXwoXlthYmNlZ2hqa2xtbnByc3R2eHlBQkNFR0hKS0xNTlBSU1RWWFldezF9XFxkezF9W0EtWmEtel17MX0gKlxcZHsxfVtBLVphLXpdezF9XFxkezF9JCkvLFxuICAgIHZhbGlkYXRlRW1haWw6IC9eKChbXjw+KClcXFtcXF1cXFxcLiw7Olxcc0BcIl0rKFxcLltePD4oKVxcW1xcXVxcXFwuLDs6XFxzQFwiXSspKil8KFwiLitcIikpQCgoXFxbWzAtOV17MSwzfVxcLlswLTldezEsM31cXC5bMC05XXsxLDN9XFwuWzAtOV17MSwzfV0pfCgoW2EtekEtWlxcLTAtOV0rXFwuKStbYS16QS1aXXsyLH0pKSQvLFxuICAgIG5vc3BlY2lhbGNoYXJzOiAvXlthLXpBLVowLTkuICx+ISYoKS1fQF0rJC8sXG4gICAgbm9lbW9qaWNoYXI6IC8oPzpbXFx1MjcwMC1cXHUyN2JmXXwoPzpcXHVkODNjW1xcdWRkZTYtXFx1ZGRmZl0pezJ9fFtcXHVkODAwLVxcdWRiZmZdW1xcdWRjMDAtXFx1ZGZmZl18W1xcdTAwMjMtXFx1MDAzOV1cXHVmZTBmP1xcdTIwZTN8XFx1MzI5OXxcXHUzMjk3fFxcdTMwM2R8XFx1MzAzMHxcXHUyNGMyfFxcdWQ4M2NbXFx1ZGQ3MC1cXHVkZDcxXXxcXHVkODNjW1xcdWRkN2UtXFx1ZGQ3Zl18XFx1ZDgzY1xcdWRkOGV8XFx1ZDgzY1tcXHVkZDkxLVxcdWRkOWFdfFxcdWQ4M2NbXFx1ZGRlNi1cXHVkZGZmXXxbXFx1ZDgzY1tcXHVkZTAxLVxcdWRlMDJdfFxcdWQ4M2NcXHVkZTFhfFxcdWQ4M2NcXHVkZTJmfFtcXHVkODNjW1xcdWRlMzItXFx1ZGUzYV18W1xcdWQ4M2NbXFx1ZGU1MC1cXHVkZTUxXXxcXHUyMDNjfFxcdTIwNDl8W1xcdTI1YWEtXFx1MjVhYl18XFx1MjViNnxcXHUyNWMwfFtcXHUyNWZiLVxcdTI1ZmVdfFxcdTAwYTl8XFx1MDBhZXxcXHUyMTIyfFxcdTIxMzl8XFx1ZDgzY1xcdWRjMDR8W1xcdTI2MDAtXFx1MjZGRl18XFx1MmIwNXxcXHUyYjA2fFxcdTJiMDd8XFx1MmIxYnxcXHUyYjFjfFxcdTJiNTB8XFx1MmI1NXxcXHUyMzFhfFxcdTIzMWJ8XFx1MjMyOHxcXHUyM2NmfFtcXHUyM2U5LVxcdTIzZjNdfFtcXHUyM2Y4LVxcdTIzZmFdfFxcdWQ4M2NcXHVkY2NmfFxcdTI5MzR8XFx1MjkzNXxbXFx1MjE5MC1cXHUyMWZmXSkvLFxuICAgIG9ubHlBbHBoYTogL14oW2EtekEtWl18LXxcXCApKyQvXG59O1xuLy8gZ2xvYmFsIGZvcm0gdmFsaWRhdG9yIHNldHRpbmdzXG52YXIgc2V0dGluZ3MgPSB7XG4gICAgZXJyb3JDbGFzczogJ2Vycm9yJyxcbiAgICBlcnJvckVsZW1lbnQ6ICdzcGFuJyxcbiAgICBvbmtleXVwOiBmYWxzZSxcbiAgICBvbmZvY3Vzb3V0OiBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICBpZiAoIXRoaXMuY2hlY2thYmxlKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgYSBnaXZlbiBwaG9uZSBudW1iZXIgYWdhaW5zdCB0aGUgY291bnRyaWVzIHBob25lIHJlZ2V4XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgVGhlIHBob25lIG51bWJlciB3aGljaCB3aWxsIGJlIHZhbGlkYXRlZFxuICogQHBhcmFtIHtTdHJpbmd9IGVsIFRoZSBpbnB1dCBmaWVsZFxuICovXG52YXIgdmFsaWRhdGVQaG9uZSA9IGZ1bmN0aW9uICh2YWx1ZSwgZWwpIHtcbiAgICB2YXIgY291bnRyeSA9ICQoZWwpLmNsb3Nlc3QoJ2Zvcm0nKS5maW5kKCcuY291bnRyeScpO1xuICAgIGlmIChjb3VudHJ5Lmxlbmd0aCA9PT0gMCB8fCBjb3VudHJ5LnZhbCgpLmxlbmd0aCA9PT0gMCB8fCAhcmVnZXgucGhvbmVbY291bnRyeS52YWwoKS50b0xvd2VyQ2FzZSgpXSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgcmd4ID0gcmVnZXgucGhvbmVbY291bnRyeS52YWwoKS50b0xvd2VyQ2FzZSgpXTtcbiAgICB2YXIgaXNPcHRpb25hbCA9IHRoaXMub3B0aW9uYWwoZWwpO1xuICAgIHZhciBpc1ZhbGlkID0gcmd4LnRlc3QoJC50cmltKHZhbHVlKSk7XG5cbiAgICByZXR1cm4gaXNPcHRpb25hbCB8fCBpc1ZhbGlkO1xufTtcblxuXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3B3LXZhbGlkYXRpb24nLCBmdW5jdGlvbiAodmFsdWUsIGVsKSB7XG5cdGlmICh2YWx1ZS5sZW5ndGggPj0gOCAmJiB2YWx1ZS5sZW5ndGggPD0gMjU1KSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1lbHNle1xuICAgIFx0XHRyZXR1cm4gZmFsc2U7XG4gICAgfVxufSwgUmVzb3VyY2VzLlZBTElEQVRFX1BXX01JTk1BWCk7XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdGVzIHRoYXQgYSBjcmVkaXQgY2FyZCBvd25lciBpcyBub3QgYSBDcmVkaXQgY2FyZCBudW1iZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSBUaGUgb3duZXIgZmllbGQgd2hpY2ggd2lsbCBiZSB2YWxpZGF0ZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBlbCBUaGUgaW5wdXQgZmllbGRcbiAqL1xudmFyIHZhbGlkYXRlT3duZXIgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICB2YXIgaXNWYWxpZCA9IHJlZ2V4Lm5vdENDLnRlc3QoJC50cmltKHZhbHVlKSk7XG4gICAgcmV0dXJuIGlzVmFsaWQ7XG59O1xuXG4vKipcbiAqIEFkZCBwaG9uZSB2YWxpZGF0aW9uIG1ldGhvZCB0byBqUXVlcnkgdmFsaWRhdGlvbiBwbHVnaW4uXG4gKiBUZXh0IGZpZWxkcyBtdXN0IGhhdmUgJ3Bob25lJyBjc3MgY2xhc3MgdG8gYmUgdmFsaWRhdGVkIGFzIHBob25lXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgncGhvbmUnLCB2YWxpZGF0ZVBob25lLCBSZXNvdXJjZXMuSU5WQUxJRF9QSE9ORSk7XG5cbi8qKlxuICogQWRkIENDT3duZXIgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdvd25lcicgY3NzIGNsYXNzIHRvIGJlIHZhbGlkYXRlZCBhcyBub3QgYSBjcmVkaXQgY2FyZFxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ293bmVyJywgdmFsaWRhdGVPd25lciwgUmVzb3VyY2VzLklOVkFMSURfT1dORVIpO1xuXG4vKipcbiAqIEFkZCBnaWZ0IGNlcnQgYW1vdW50IHZhbGlkYXRpb24gbWV0aG9kIHRvIGpRdWVyeSB2YWxpZGF0aW9uIHBsdWdpbi5cbiAqIFRleHQgZmllbGRzIG11c3QgaGF2ZSAnZ2lmdC1jZXJ0LWFtb250JyBjc3MgY2xhc3MgdG8gYmUgdmFsaWRhdGVkXG4gKi9cbiQudmFsaWRhdG9yLmFkZE1ldGhvZCgnZ2lmdC1jZXJ0LWFtb3VudCcsIGZ1bmN0aW9uICh2YWx1ZSwgZWwpIHtcbiAgICB2YXIgaXNPcHRpb25hbCA9IHRoaXMub3B0aW9uYWwoZWwpO1xuICAgIHZhciBpc1ZhbGlkID0gKCFpc05hTih2YWx1ZSkpICYmIChwYXJzZUZsb2F0KHZhbHVlKSA+PSA1KSAmJiAocGFyc2VGbG9hdCh2YWx1ZSkgPD0gNTAwMCk7XG4gICAgcmV0dXJuIGlzT3B0aW9uYWwgfHwgaXNWYWxpZDtcbn0sIFJlc291cmNlcy5HSUZUX0NFUlRfQU1PVU5UX0lOVkFMSUQpO1xuXG4vKipcbiAqIEFkZCBwb3NpdGl2ZSBudW1iZXIgdmFsaWRhdGlvbiBtZXRob2QgdG8galF1ZXJ5IHZhbGlkYXRpb24gcGx1Z2luLlxuICogVGV4dCBmaWVsZHMgbXVzdCBoYXZlICdwb3NpdGl2ZW51bWJlcicgY3NzIGNsYXNzIHRvIGJlIHZhbGlkYXRlZCBhcyBwb3NpdGl2ZW51bWJlclxuICovXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3Bvc2l0aXZlbnVtYmVyJywgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgaWYgKCQudHJpbSh2YWx1ZSkubGVuZ3RoID09PSAwKSB7IHJldHVybiB0cnVlOyB9XG4gICAgcmV0dXJuICghaXNOYU4odmFsdWUpICYmIE51bWJlcih2YWx1ZSkgPj0gMCk7XG59LCAnJyk7IC8vICcnIHNob3VsZCBiZSByZXBsYWNlZCB3aXRoIGVycm9yIG1lc3NhZ2UgaWYgbmVlZGVkXG5cblxudmFyICRlbW9qaWNoYXIgPSBmdW5jdGlvbiAoZW1vY2hhcikgeyAgXG5cdHZhciBpc0Vtb2ppID0gcmVnZXgubm9lbW9qaWNoYXIudGVzdCgkLnRyaW0oZW1vY2hhcikpOyAgIFxuICAgIHZhciB3aXRoZXJyb3IgPSBmYWxzZTtcbiAgICBpZihpc0Vtb2ppKXtcbiAgICBcdHdpdGhlcnJvciA9IGZhbHNlOyAgICAgXG4gICAgfWVsc2V7XG4gICAgXHR3aXRoZXJyb3IgPSB0cnVlO1xuICAgIH1cbiAgICBcbiAgICBpZigkLnRyaW0oZW1vY2hhcikgPT0gJycpIHtcbiAgICBcdHdpdGhlcnJvciA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiB3aXRoZXJyb3I7XG59O1xuXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ25vZW1vamljaGFyJywgJGVtb2ppY2hhciwgUmVzb3VyY2VzLlZBTElEQVRFX0VNT0pJX0NIQVIpOyBcblxudmFyIHZhbGlkYXRlU3BlY2lhbENoYXJzID0gZnVuY3Rpb24gKHZhbHVlKSB7IFxuICAgIHZhciBpc1ZhbGlkID0gcmVnZXgubm9zcGVjaWFsY2hhcnMudGVzdCgkLnRyaW0odmFsdWUpKTtcbiAgICBpZigkLnRyaW0odmFsdWUpID09ICcnKSB7XG4gICAgXHRyZXR1cm4gdHJ1ZVxuICAgIH1cbiAgIHJldHVybiBpc1ZhbGlkO1xufTtcblxuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCd2YWxpZGF0ZVNwZWNpYWxDaGFycycsIHZhbGlkYXRlU3BlY2lhbENoYXJzLCBSZXNvdXJjZXMuVkFMSURBVEVfU1BFQ0lBTF9DSEFSKTtcblxudmFyIHZhbGlkYXRlVmFsaWRQb3N0YWwgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0dmFyIGlzVmFsaWQgPSByZWdleC52YWxpZFBvc3RhbC50ZXN0KCQudHJpbSh2YWx1ZSkpO1xuICAgIGlmKCQudHJpbSh2YWx1ZSkgPT0gJycpIHtcbiAgICBcdHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBpc1ZhbGlkO1xufVxuXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ZhbGlkYXRlUG9zdGFsQ29kZScsIHZhbGlkYXRlVmFsaWRQb3N0YWwsIFJlc291cmNlcy5WQUxJREFURV9QT1NUQUxDT0RFKTtcblxuXG52YXIgdmFsaWRhdGVFbWFpbCA9IGZ1bmN0aW9uICh2YWx1ZSkgeyBcbiAgICB2YXIgaXNWYWxpZCA9IHJlZ2V4LnZhbGlkYXRlRW1haWwudGVzdCgkLnRyaW0odmFsdWUpKTtcbiAgICBpZigkLnRyaW0odmFsdWUpID09ICcnKSB7XG4gICAgXHRyZXR1cm4gdHJ1ZVxuICAgIH1cbiAgIHJldHVybiBpc1ZhbGlkO1xufTtcblxuJC52YWxpZGF0b3IuYWRkTWV0aG9kKCd2YWxpZGF0ZUVtYWlsJywgdmFsaWRhdGVFbWFpbCwgUmVzb3VyY2VzLlZBTElEQVRFX0VNQUlMKTtcblxudmFyIHZhbGlkYXRlT25seUFscGhhYmV0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdHZhciBpc1ZhbGlkID0gcmVnZXgub25seUFscGhhLnRlc3QoJC50cmltKHZhbHVlKSk7XG5cdGlmICgkLnRyaW0odmFsdWUpID09ICcnKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0XG5cdHJldHVybiBpc1ZhbGlkO1xufVxuXG4kLnZhbGlkYXRvci5hZGRNZXRob2QoJ3ZhbGlkYXRlT25seUFscGhhYmV0JywgdmFsaWRhdGVPbmx5QWxwaGFiZXQsIFJlc291cmNlcy5WQUxJREFURV9PTkxZQUxQSEEpO1xuXG4kLmV4dGVuZCgkLnZhbGlkYXRvci5tZXNzYWdlcywge1xuICAgIHJlcXVpcmVkOiBSZXNvdXJjZXMuVkFMSURBVEVfUkVRVUlSRUQsXG4gICAgcmVtb3RlOiBSZXNvdXJjZXMuVkFMSURBVEVfUkVNT1RFLFxuICAgIGVtYWlsOiBSZXNvdXJjZXMuVkFMSURBVEVfRU1BSUwsXG4gICAgdXJsOiBSZXNvdXJjZXMuVkFMSURBVEVfVVJMLFxuICAgIGRhdGU6IFJlc291cmNlcy5WQUxJREFURV9EQVRFLFxuICAgIGRhdGVJU086IFJlc291cmNlcy5WQUxJREFURV9EQVRFSVNPLFxuICAgIG51bWJlcjogUmVzb3VyY2VzLlZBTElEQVRFX05VTUJFUixcbiAgICBkaWdpdHM6IFJlc291cmNlcy5WQUxJREFURV9ESUdJVFMsXG4gICAgY3JlZGl0Y2FyZDogUmVzb3VyY2VzLlZBTElEQVRFX0NSRURJVENBUkQsXG4gICAgZXF1YWxUbzogUmVzb3VyY2VzLlZBTElEQVRFX0VRVUFMVE8sXG4gICAgbWF4bGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX01BWExFTkdUSCksXG4gICAgbWlubGVuZ3RoOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX01JTkxFTkdUSCksXG4gICAgcmFuZ2VsZW5ndGg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfUkFOR0VMRU5HVEgpLFxuICAgIHJhbmdlOiAkLnZhbGlkYXRvci5mb3JtYXQoUmVzb3VyY2VzLlZBTElEQVRFX1JBTkdFKSxcbiAgICBtYXg6ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUFYKSxcbiAgICBtaW46ICQudmFsaWRhdG9yLmZvcm1hdChSZXNvdXJjZXMuVkFMSURBVEVfTUlOKVxufSk7XG5cbnZhciB2YWxpZGF0b3IgPSB7XG4gICAgcmVnZXg6IHJlZ2V4LFxuICAgIHNldHRpbmdzOiBzZXR0aW5ncyxcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgJCgnZm9ybTpub3QoLnN1cHByZXNzKScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCh0aGlzKS52YWxpZGF0ZShzZWxmLnNldHRpbmdzKTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBpbml0Rm9ybTogZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgJChmKS52YWxpZGF0ZSh0aGlzLnNldHRpbmdzKTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHZhbGlkYXRvcjtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vLyByYXdBc2FwIHByb3ZpZGVzIGV2ZXJ5dGhpbmcgd2UgbmVlZCBleGNlcHQgZXhjZXB0aW9uIG1hbmFnZW1lbnQuXG52YXIgcmF3QXNhcCA9IHJlcXVpcmUoXCIuL3Jhd1wiKTtcbi8vIFJhd1Rhc2tzIGFyZSByZWN5Y2xlZCB0byByZWR1Y2UgR0MgY2h1cm4uXG52YXIgZnJlZVRhc2tzID0gW107XG4vLyBXZSBxdWV1ZSBlcnJvcnMgdG8gZW5zdXJlIHRoZXkgYXJlIHRocm93biBpbiByaWdodCBvcmRlciAoRklGTykuXG4vLyBBcnJheS1hcy1xdWV1ZSBpcyBnb29kIGVub3VnaCBoZXJlLCBzaW5jZSB3ZSBhcmUganVzdCBkZWFsaW5nIHdpdGggZXhjZXB0aW9ucy5cbnZhciBwZW5kaW5nRXJyb3JzID0gW107XG52YXIgcmVxdWVzdEVycm9yVGhyb3cgPSByYXdBc2FwLm1ha2VSZXF1ZXN0Q2FsbEZyb21UaW1lcih0aHJvd0ZpcnN0RXJyb3IpO1xuXG5mdW5jdGlvbiB0aHJvd0ZpcnN0RXJyb3IoKSB7XG4gICAgaWYgKHBlbmRpbmdFcnJvcnMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IHBlbmRpbmdFcnJvcnMuc2hpZnQoKTtcbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbHMgYSB0YXNrIGFzIHNvb24gYXMgcG9zc2libGUgYWZ0ZXIgcmV0dXJuaW5nLCBpbiBpdHMgb3duIGV2ZW50LCB3aXRoIHByaW9yaXR5XG4gKiBvdmVyIG90aGVyIGV2ZW50cyBsaWtlIGFuaW1hdGlvbiwgcmVmbG93LCBhbmQgcmVwYWludC4gQW4gZXJyb3IgdGhyb3duIGZyb20gYW5cbiAqIGV2ZW50IHdpbGwgbm90IGludGVycnVwdCwgbm9yIGV2ZW4gc3Vic3RhbnRpYWxseSBzbG93IGRvd24gdGhlIHByb2Nlc3Npbmcgb2ZcbiAqIG90aGVyIGV2ZW50cywgYnV0IHdpbGwgYmUgcmF0aGVyIHBvc3Rwb25lZCB0byBhIGxvd2VyIHByaW9yaXR5IGV2ZW50LlxuICogQHBhcmFtIHt7Y2FsbH19IHRhc2sgQSBjYWxsYWJsZSBvYmplY3QsIHR5cGljYWxseSBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgbm9cbiAqIGFyZ3VtZW50cy5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBhc2FwO1xuZnVuY3Rpb24gYXNhcCh0YXNrKSB7XG4gICAgdmFyIHJhd1Rhc2s7XG4gICAgaWYgKGZyZWVUYXNrcy5sZW5ndGgpIHtcbiAgICAgICAgcmF3VGFzayA9IGZyZWVUYXNrcy5wb3AoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByYXdUYXNrID0gbmV3IFJhd1Rhc2soKTtcbiAgICB9XG4gICAgcmF3VGFzay50YXNrID0gdGFzaztcbiAgICByYXdBc2FwKHJhd1Rhc2spO1xufVxuXG4vLyBXZSB3cmFwIHRhc2tzIHdpdGggcmVjeWNsYWJsZSB0YXNrIG9iamVjdHMuICBBIHRhc2sgb2JqZWN0IGltcGxlbWVudHNcbi8vIGBjYWxsYCwganVzdCBsaWtlIGEgZnVuY3Rpb24uXG5mdW5jdGlvbiBSYXdUYXNrKCkge1xuICAgIHRoaXMudGFzayA9IG51bGw7XG59XG5cbi8vIFRoZSBzb2xlIHB1cnBvc2Ugb2Ygd3JhcHBpbmcgdGhlIHRhc2sgaXMgdG8gY2F0Y2ggdGhlIGV4Y2VwdGlvbiBhbmQgcmVjeWNsZVxuLy8gdGhlIHRhc2sgb2JqZWN0IGFmdGVyIGl0cyBzaW5nbGUgdXNlLlxuUmF3VGFzay5wcm90b3R5cGUuY2FsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICB0aGlzLnRhc2suY2FsbCgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChhc2FwLm9uZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaG9vayBleGlzdHMgcHVyZWx5IGZvciB0ZXN0aW5nIHB1cnBvc2VzLlxuICAgICAgICAgICAgLy8gSXRzIG5hbWUgd2lsbCBiZSBwZXJpb2RpY2FsbHkgcmFuZG9taXplZCB0byBicmVhayBhbnkgY29kZSB0aGF0XG4gICAgICAgICAgICAvLyBkZXBlbmRzIG9uIGl0cyBleGlzdGVuY2UuXG4gICAgICAgICAgICBhc2FwLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSW4gYSB3ZWIgYnJvd3NlciwgZXhjZXB0aW9ucyBhcmUgbm90IGZhdGFsLiBIb3dldmVyLCB0byBhdm9pZFxuICAgICAgICAgICAgLy8gc2xvd2luZyBkb3duIHRoZSBxdWV1ZSBvZiBwZW5kaW5nIHRhc2tzLCB3ZSByZXRocm93IHRoZSBlcnJvciBpbiBhXG4gICAgICAgICAgICAvLyBsb3dlciBwcmlvcml0eSB0dXJuLlxuICAgICAgICAgICAgcGVuZGluZ0Vycm9ycy5wdXNoKGVycm9yKTtcbiAgICAgICAgICAgIHJlcXVlc3RFcnJvclRocm93KCk7XG4gICAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLnRhc2sgPSBudWxsO1xuICAgICAgICBmcmVlVGFza3NbZnJlZVRhc2tzLmxlbmd0aF0gPSB0aGlzO1xuICAgIH1cbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLy8gVXNlIHRoZSBmYXN0ZXN0IG1lYW5zIHBvc3NpYmxlIHRvIGV4ZWN1dGUgYSB0YXNrIGluIGl0cyBvd24gdHVybiwgd2l0aFxuLy8gcHJpb3JpdHkgb3ZlciBvdGhlciBldmVudHMgaW5jbHVkaW5nIElPLCBhbmltYXRpb24sIHJlZmxvdywgYW5kIHJlZHJhd1xuLy8gZXZlbnRzIGluIGJyb3dzZXJzLlxuLy9cbi8vIEFuIGV4Y2VwdGlvbiB0aHJvd24gYnkgYSB0YXNrIHdpbGwgcGVybWFuZW50bHkgaW50ZXJydXB0IHRoZSBwcm9jZXNzaW5nIG9mXG4vLyBzdWJzZXF1ZW50IHRhc2tzLiBUaGUgaGlnaGVyIGxldmVsIGBhc2FwYCBmdW5jdGlvbiBlbnN1cmVzIHRoYXQgaWYgYW5cbi8vIGV4Y2VwdGlvbiBpcyB0aHJvd24gYnkgYSB0YXNrLCB0aGF0IHRoZSB0YXNrIHF1ZXVlIHdpbGwgY29udGludWUgZmx1c2hpbmcgYXNcbi8vIHNvb24gYXMgcG9zc2libGUsIGJ1dCBpZiB5b3UgdXNlIGByYXdBc2FwYCBkaXJlY3RseSwgeW91IGFyZSByZXNwb25zaWJsZSB0b1xuLy8gZWl0aGVyIGVuc3VyZSB0aGF0IG5vIGV4Y2VwdGlvbnMgYXJlIHRocm93biBmcm9tIHlvdXIgdGFzaywgb3IgdG8gbWFudWFsbHlcbi8vIGNhbGwgYHJhd0FzYXAucmVxdWVzdEZsdXNoYCBpZiBhbiBleGNlcHRpb24gaXMgdGhyb3duLlxubW9kdWxlLmV4cG9ydHMgPSByYXdBc2FwO1xuZnVuY3Rpb24gcmF3QXNhcCh0YXNrKSB7XG4gICAgaWYgKCFxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgcmVxdWVzdEZsdXNoKCk7XG4gICAgICAgIGZsdXNoaW5nID0gdHJ1ZTtcbiAgICB9XG4gICAgLy8gRXF1aXZhbGVudCB0byBwdXNoLCBidXQgYXZvaWRzIGEgZnVuY3Rpb24gY2FsbC5cbiAgICBxdWV1ZVtxdWV1ZS5sZW5ndGhdID0gdGFzaztcbn1cblxudmFyIHF1ZXVlID0gW107XG4vLyBPbmNlIGEgZmx1c2ggaGFzIGJlZW4gcmVxdWVzdGVkLCBubyBmdXJ0aGVyIGNhbGxzIHRvIGByZXF1ZXN0Rmx1c2hgIGFyZVxuLy8gbmVjZXNzYXJ5IHVudGlsIHRoZSBuZXh0IGBmbHVzaGAgY29tcGxldGVzLlxudmFyIGZsdXNoaW5nID0gZmFsc2U7XG4vLyBgcmVxdWVzdEZsdXNoYCBpcyBhbiBpbXBsZW1lbnRhdGlvbi1zcGVjaWZpYyBtZXRob2QgdGhhdCBhdHRlbXB0cyB0byBraWNrXG4vLyBvZmYgYSBgZmx1c2hgIGV2ZW50IGFzIHF1aWNrbHkgYXMgcG9zc2libGUuIGBmbHVzaGAgd2lsbCBhdHRlbXB0IHRvIGV4aGF1c3Rcbi8vIHRoZSBldmVudCBxdWV1ZSBiZWZvcmUgeWllbGRpbmcgdG8gdGhlIGJyb3dzZXIncyBvd24gZXZlbnQgbG9vcC5cbnZhciByZXF1ZXN0Rmx1c2g7XG4vLyBUaGUgcG9zaXRpb24gb2YgdGhlIG5leHQgdGFzayB0byBleGVjdXRlIGluIHRoZSB0YXNrIHF1ZXVlLiBUaGlzIGlzXG4vLyBwcmVzZXJ2ZWQgYmV0d2VlbiBjYWxscyB0byBgZmx1c2hgIHNvIHRoYXQgaXQgY2FuIGJlIHJlc3VtZWQgaWZcbi8vIGEgdGFzayB0aHJvd3MgYW4gZXhjZXB0aW9uLlxudmFyIGluZGV4ID0gMDtcbi8vIElmIGEgdGFzayBzY2hlZHVsZXMgYWRkaXRpb25hbCB0YXNrcyByZWN1cnNpdmVseSwgdGhlIHRhc2sgcXVldWUgY2FuIGdyb3dcbi8vIHVuYm91bmRlZC4gVG8gcHJldmVudCBtZW1vcnkgZXhoYXVzdGlvbiwgdGhlIHRhc2sgcXVldWUgd2lsbCBwZXJpb2RpY2FsbHlcbi8vIHRydW5jYXRlIGFscmVhZHktY29tcGxldGVkIHRhc2tzLlxudmFyIGNhcGFjaXR5ID0gMTAyNDtcblxuLy8gVGhlIGZsdXNoIGZ1bmN0aW9uIHByb2Nlc3NlcyBhbGwgdGFza3MgdGhhdCBoYXZlIGJlZW4gc2NoZWR1bGVkIHdpdGhcbi8vIGByYXdBc2FwYCB1bmxlc3MgYW5kIHVudGlsIG9uZSBvZiB0aG9zZSB0YXNrcyB0aHJvd3MgYW4gZXhjZXB0aW9uLlxuLy8gSWYgYSB0YXNrIHRocm93cyBhbiBleGNlcHRpb24sIGBmbHVzaGAgZW5zdXJlcyB0aGF0IGl0cyBzdGF0ZSB3aWxsIHJlbWFpblxuLy8gY29uc2lzdGVudCBhbmQgd2lsbCByZXN1bWUgd2hlcmUgaXQgbGVmdCBvZmYgd2hlbiBjYWxsZWQgYWdhaW4uXG4vLyBIb3dldmVyLCBgZmx1c2hgIGRvZXMgbm90IG1ha2UgYW55IGFycmFuZ2VtZW50cyB0byBiZSBjYWxsZWQgYWdhaW4gaWYgYW5cbi8vIGV4Y2VwdGlvbiBpcyB0aHJvd24uXG5mdW5jdGlvbiBmbHVzaCgpIHtcbiAgICB3aGlsZSAoaW5kZXggPCBxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGN1cnJlbnRJbmRleCA9IGluZGV4O1xuICAgICAgICAvLyBBZHZhbmNlIHRoZSBpbmRleCBiZWZvcmUgY2FsbGluZyB0aGUgdGFzay4gVGhpcyBlbnN1cmVzIHRoYXQgd2Ugd2lsbFxuICAgICAgICAvLyBiZWdpbiBmbHVzaGluZyBvbiB0aGUgbmV4dCB0YXNrIHRoZSB0YXNrIHRocm93cyBhbiBlcnJvci5cbiAgICAgICAgaW5kZXggPSBpbmRleCArIDE7XG4gICAgICAgIHF1ZXVlW2N1cnJlbnRJbmRleF0uY2FsbCgpO1xuICAgICAgICAvLyBQcmV2ZW50IGxlYWtpbmcgbWVtb3J5IGZvciBsb25nIGNoYWlucyBvZiByZWN1cnNpdmUgY2FsbHMgdG8gYGFzYXBgLlxuICAgICAgICAvLyBJZiB3ZSBjYWxsIGBhc2FwYCB3aXRoaW4gdGFza3Mgc2NoZWR1bGVkIGJ5IGBhc2FwYCwgdGhlIHF1ZXVlIHdpbGxcbiAgICAgICAgLy8gZ3JvdywgYnV0IHRvIGF2b2lkIGFuIE8obikgd2FsayBmb3IgZXZlcnkgdGFzayB3ZSBleGVjdXRlLCB3ZSBkb24ndFxuICAgICAgICAvLyBzaGlmdCB0YXNrcyBvZmYgdGhlIHF1ZXVlIGFmdGVyIHRoZXkgaGF2ZSBiZWVuIGV4ZWN1dGVkLlxuICAgICAgICAvLyBJbnN0ZWFkLCB3ZSBwZXJpb2RpY2FsbHkgc2hpZnQgMTAyNCB0YXNrcyBvZmYgdGhlIHF1ZXVlLlxuICAgICAgICBpZiAoaW5kZXggPiBjYXBhY2l0eSkge1xuICAgICAgICAgICAgLy8gTWFudWFsbHkgc2hpZnQgYWxsIHZhbHVlcyBzdGFydGluZyBhdCB0aGUgaW5kZXggYmFjayB0byB0aGVcbiAgICAgICAgICAgIC8vIGJlZ2lubmluZyBvZiB0aGUgcXVldWUuXG4gICAgICAgICAgICBmb3IgKHZhciBzY2FuID0gMCwgbmV3TGVuZ3RoID0gcXVldWUubGVuZ3RoIC0gaW5kZXg7IHNjYW4gPCBuZXdMZW5ndGg7IHNjYW4rKykge1xuICAgICAgICAgICAgICAgIHF1ZXVlW3NjYW5dID0gcXVldWVbc2NhbiArIGluZGV4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHF1ZXVlLmxlbmd0aCAtPSBpbmRleDtcbiAgICAgICAgICAgIGluZGV4ID0gMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5sZW5ndGggPSAwO1xuICAgIGluZGV4ID0gMDtcbiAgICBmbHVzaGluZyA9IGZhbHNlO1xufVxuXG4vLyBgcmVxdWVzdEZsdXNoYCBpcyBpbXBsZW1lbnRlZCB1c2luZyBhIHN0cmF0ZWd5IGJhc2VkIG9uIGRhdGEgY29sbGVjdGVkIGZyb21cbi8vIGV2ZXJ5IGF2YWlsYWJsZSBTYXVjZUxhYnMgU2VsZW5pdW0gd2ViIGRyaXZlciB3b3JrZXIgYXQgdGltZSBvZiB3cml0aW5nLlxuLy8gaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMW1HLTVVWUd1cDVxeEdkRU1Xa2hQNkJXQ3owNTNOVWIyRTFRb1VUVTE2dUEvZWRpdCNnaWQ9NzgzNzI0NTkzXG5cbi8vIFNhZmFyaSA2IGFuZCA2LjEgZm9yIGRlc2t0b3AsIGlQYWQsIGFuZCBpUGhvbmUgYXJlIHRoZSBvbmx5IGJyb3dzZXJzIHRoYXRcbi8vIGhhdmUgV2ViS2l0TXV0YXRpb25PYnNlcnZlciBidXQgbm90IHVuLXByZWZpeGVkIE11dGF0aW9uT2JzZXJ2ZXIuXG4vLyBNdXN0IHVzZSBgZ2xvYmFsYCBvciBgc2VsZmAgaW5zdGVhZCBvZiBgd2luZG93YCB0byB3b3JrIGluIGJvdGggZnJhbWVzIGFuZCB3ZWJcbi8vIHdvcmtlcnMuIGBnbG9iYWxgIGlzIGEgcHJvdmlzaW9uIG9mIEJyb3dzZXJpZnksIE1yLCBNcnMsIG9yIE1vcC5cblxuLyogZ2xvYmFscyBzZWxmICovXG52YXIgc2NvcGUgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogc2VsZjtcbnZhciBCcm93c2VyTXV0YXRpb25PYnNlcnZlciA9IHNjb3BlLk11dGF0aW9uT2JzZXJ2ZXIgfHwgc2NvcGUuV2ViS2l0TXV0YXRpb25PYnNlcnZlcjtcblxuLy8gTXV0YXRpb25PYnNlcnZlcnMgYXJlIGRlc2lyYWJsZSBiZWNhdXNlIHRoZXkgaGF2ZSBoaWdoIHByaW9yaXR5IGFuZCB3b3JrXG4vLyByZWxpYWJseSBldmVyeXdoZXJlIHRoZXkgYXJlIGltcGxlbWVudGVkLlxuLy8gVGhleSBhcmUgaW1wbGVtZW50ZWQgaW4gYWxsIG1vZGVybiBicm93c2Vycy5cbi8vXG4vLyAtIEFuZHJvaWQgNC00LjNcbi8vIC0gQ2hyb21lIDI2LTM0XG4vLyAtIEZpcmVmb3ggMTQtMjlcbi8vIC0gSW50ZXJuZXQgRXhwbG9yZXIgMTFcbi8vIC0gaVBhZCBTYWZhcmkgNi03LjFcbi8vIC0gaVBob25lIFNhZmFyaSA3LTcuMVxuLy8gLSBTYWZhcmkgNi03XG5pZiAodHlwZW9mIEJyb3dzZXJNdXRhdGlvbk9ic2VydmVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICByZXF1ZXN0Rmx1c2ggPSBtYWtlUmVxdWVzdENhbGxGcm9tTXV0YXRpb25PYnNlcnZlcihmbHVzaCk7XG5cbi8vIE1lc3NhZ2VDaGFubmVscyBhcmUgZGVzaXJhYmxlIGJlY2F1c2UgdGhleSBnaXZlIGRpcmVjdCBhY2Nlc3MgdG8gdGhlIEhUTUxcbi8vIHRhc2sgcXVldWUsIGFyZSBpbXBsZW1lbnRlZCBpbiBJbnRlcm5ldCBFeHBsb3JlciAxMCwgU2FmYXJpIDUuMC0xLCBhbmQgT3BlcmFcbi8vIDExLTEyLCBhbmQgaW4gd2ViIHdvcmtlcnMgaW4gbWFueSBlbmdpbmVzLlxuLy8gQWx0aG91Z2ggbWVzc2FnZSBjaGFubmVscyB5aWVsZCB0byBhbnkgcXVldWVkIHJlbmRlcmluZyBhbmQgSU8gdGFza3MsIHRoZXlcbi8vIHdvdWxkIGJlIGJldHRlciB0aGFuIGltcG9zaW5nIHRoZSA0bXMgZGVsYXkgb2YgdGltZXJzLlxuLy8gSG93ZXZlciwgdGhleSBkbyBub3Qgd29yayByZWxpYWJseSBpbiBJbnRlcm5ldCBFeHBsb3JlciBvciBTYWZhcmkuXG5cbi8vIEludGVybmV0IEV4cGxvcmVyIDEwIGlzIHRoZSBvbmx5IGJyb3dzZXIgdGhhdCBoYXMgc2V0SW1tZWRpYXRlIGJ1dCBkb2VzXG4vLyBub3QgaGF2ZSBNdXRhdGlvbk9ic2VydmVycy5cbi8vIEFsdGhvdWdoIHNldEltbWVkaWF0ZSB5aWVsZHMgdG8gdGhlIGJyb3dzZXIncyByZW5kZXJlciwgaXQgd291bGQgYmVcbi8vIHByZWZlcnJhYmxlIHRvIGZhbGxpbmcgYmFjayB0byBzZXRUaW1lb3V0IHNpbmNlIGl0IGRvZXMgbm90IGhhdmVcbi8vIHRoZSBtaW5pbXVtIDRtcyBwZW5hbHR5LlxuLy8gVW5mb3J0dW5hdGVseSB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgYnVnIGluIEludGVybmV0IEV4cGxvcmVyIDEwIE1vYmlsZSAoYW5kXG4vLyBEZXNrdG9wIHRvIGEgbGVzc2VyIGV4dGVudCkgdGhhdCByZW5kZXJzIGJvdGggc2V0SW1tZWRpYXRlIGFuZFxuLy8gTWVzc2FnZUNoYW5uZWwgdXNlbGVzcyBmb3IgdGhlIHB1cnBvc2VzIG9mIEFTQVAuXG4vLyBodHRwczovL2dpdGh1Yi5jb20va3Jpc2tvd2FsL3EvaXNzdWVzLzM5NlxuXG4vLyBUaW1lcnMgYXJlIGltcGxlbWVudGVkIHVuaXZlcnNhbGx5LlxuLy8gV2UgZmFsbCBiYWNrIHRvIHRpbWVycyBpbiB3b3JrZXJzIGluIG1vc3QgZW5naW5lcywgYW5kIGluIGZvcmVncm91bmRcbi8vIGNvbnRleHRzIGluIHRoZSBmb2xsb3dpbmcgYnJvd3NlcnMuXG4vLyBIb3dldmVyLCBub3RlIHRoYXQgZXZlbiB0aGlzIHNpbXBsZSBjYXNlIHJlcXVpcmVzIG51YW5jZXMgdG8gb3BlcmF0ZSBpbiBhXG4vLyBicm9hZCBzcGVjdHJ1bSBvZiBicm93c2Vycy5cbi8vXG4vLyAtIEZpcmVmb3ggMy0xM1xuLy8gLSBJbnRlcm5ldCBFeHBsb3JlciA2LTlcbi8vIC0gaVBhZCBTYWZhcmkgNC4zXG4vLyAtIEx5bnggMi44Ljdcbn0gZWxzZSB7XG4gICAgcmVxdWVzdEZsdXNoID0gbWFrZVJlcXVlc3RDYWxsRnJvbVRpbWVyKGZsdXNoKTtcbn1cblxuLy8gYHJlcXVlc3RGbHVzaGAgcmVxdWVzdHMgdGhhdCB0aGUgaGlnaCBwcmlvcml0eSBldmVudCBxdWV1ZSBiZSBmbHVzaGVkIGFzXG4vLyBzb29uIGFzIHBvc3NpYmxlLlxuLy8gVGhpcyBpcyB1c2VmdWwgdG8gcHJldmVudCBhbiBlcnJvciB0aHJvd24gaW4gYSB0YXNrIGZyb20gc3RhbGxpbmcgdGhlIGV2ZW50XG4vLyBxdWV1ZSBpZiB0aGUgZXhjZXB0aW9uIGhhbmRsZWQgYnkgTm9kZS5qc+KAmXNcbi8vIGBwcm9jZXNzLm9uKFwidW5jYXVnaHRFeGNlcHRpb25cIilgIG9yIGJ5IGEgZG9tYWluLlxucmF3QXNhcC5yZXF1ZXN0Rmx1c2ggPSByZXF1ZXN0Rmx1c2g7XG5cbi8vIFRvIHJlcXVlc3QgYSBoaWdoIHByaW9yaXR5IGV2ZW50LCB3ZSBpbmR1Y2UgYSBtdXRhdGlvbiBvYnNlcnZlciBieSB0b2dnbGluZ1xuLy8gdGhlIHRleHQgb2YgYSB0ZXh0IG5vZGUgYmV0d2VlbiBcIjFcIiBhbmQgXCItMVwiLlxuZnVuY3Rpb24gbWFrZVJlcXVlc3RDYWxsRnJvbU11dGF0aW9uT2JzZXJ2ZXIoY2FsbGJhY2spIHtcbiAgICB2YXIgdG9nZ2xlID0gMTtcbiAgICB2YXIgb2JzZXJ2ZXIgPSBuZXcgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIoY2FsbGJhY2spO1xuICAgIHZhciBub2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJcIik7XG4gICAgb2JzZXJ2ZXIub2JzZXJ2ZShub2RlLCB7Y2hhcmFjdGVyRGF0YTogdHJ1ZX0pO1xuICAgIHJldHVybiBmdW5jdGlvbiByZXF1ZXN0Q2FsbCgpIHtcbiAgICAgICAgdG9nZ2xlID0gLXRvZ2dsZTtcbiAgICAgICAgbm9kZS5kYXRhID0gdG9nZ2xlO1xuICAgIH07XG59XG5cbi8vIFRoZSBtZXNzYWdlIGNoYW5uZWwgdGVjaG5pcXVlIHdhcyBkaXNjb3ZlcmVkIGJ5IE1hbHRlIFVibCBhbmQgd2FzIHRoZVxuLy8gb3JpZ2luYWwgZm91bmRhdGlvbiBmb3IgdGhpcyBsaWJyYXJ5LlxuLy8gaHR0cDovL3d3dy5ub25ibG9ja2luZy5pby8yMDExLzA2L3dpbmRvd25leHR0aWNrLmh0bWxcblxuLy8gU2FmYXJpIDYuMC41IChhdCBsZWFzdCkgaW50ZXJtaXR0ZW50bHkgZmFpbHMgdG8gY3JlYXRlIG1lc3NhZ2UgcG9ydHMgb24gYVxuLy8gcGFnZSdzIGZpcnN0IGxvYWQuIFRoYW5rZnVsbHksIHRoaXMgdmVyc2lvbiBvZiBTYWZhcmkgc3VwcG9ydHNcbi8vIE11dGF0aW9uT2JzZXJ2ZXJzLCBzbyB3ZSBkb24ndCBuZWVkIHRvIGZhbGwgYmFjayBpbiB0aGF0IGNhc2UuXG5cbi8vIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0Q2FsbEZyb21NZXNzYWdlQ2hhbm5lbChjYWxsYmFjaykge1xuLy8gICAgIHZhciBjaGFubmVsID0gbmV3IE1lc3NhZ2VDaGFubmVsKCk7XG4vLyAgICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBjYWxsYmFjaztcbi8vICAgICByZXR1cm4gZnVuY3Rpb24gcmVxdWVzdENhbGwoKSB7XG4vLyAgICAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG4vLyAgICAgfTtcbi8vIH1cblxuLy8gRm9yIHJlYXNvbnMgZXhwbGFpbmVkIGFib3ZlLCB3ZSBhcmUgYWxzbyB1bmFibGUgdG8gdXNlIGBzZXRJbW1lZGlhdGVgXG4vLyB1bmRlciBhbnkgY2lyY3Vtc3RhbmNlcy5cbi8vIEV2ZW4gaWYgd2Ugd2VyZSwgdGhlcmUgaXMgYW5vdGhlciBidWcgaW4gSW50ZXJuZXQgRXhwbG9yZXIgMTAuXG4vLyBJdCBpcyBub3Qgc3VmZmljaWVudCB0byBhc3NpZ24gYHNldEltbWVkaWF0ZWAgdG8gYHJlcXVlc3RGbHVzaGAgYmVjYXVzZVxuLy8gYHNldEltbWVkaWF0ZWAgbXVzdCBiZSBjYWxsZWQgKmJ5IG5hbWUqIGFuZCB0aGVyZWZvcmUgbXVzdCBiZSB3cmFwcGVkIGluIGFcbi8vIGNsb3N1cmUuXG4vLyBOZXZlciBmb3JnZXQuXG5cbi8vIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0Q2FsbEZyb21TZXRJbW1lZGlhdGUoY2FsbGJhY2spIHtcbi8vICAgICByZXR1cm4gZnVuY3Rpb24gcmVxdWVzdENhbGwoKSB7XG4vLyAgICAgICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4vLyAgICAgfTtcbi8vIH1cblxuLy8gU2FmYXJpIDYuMCBoYXMgYSBwcm9ibGVtIHdoZXJlIHRpbWVycyB3aWxsIGdldCBsb3N0IHdoaWxlIHRoZSB1c2VyIGlzXG4vLyBzY3JvbGxpbmcuIFRoaXMgcHJvYmxlbSBkb2VzIG5vdCBpbXBhY3QgQVNBUCBiZWNhdXNlIFNhZmFyaSA2LjAgc3VwcG9ydHNcbi8vIG11dGF0aW9uIG9ic2VydmVycywgc28gdGhhdCBpbXBsZW1lbnRhdGlvbiBpcyB1c2VkIGluc3RlYWQuXG4vLyBIb3dldmVyLCBpZiB3ZSBldmVyIGVsZWN0IHRvIHVzZSB0aW1lcnMgaW4gU2FmYXJpLCB0aGUgcHJldmFsZW50IHdvcmstYXJvdW5kXG4vLyBpcyB0byBhZGQgYSBzY3JvbGwgZXZlbnQgbGlzdGVuZXIgdGhhdCBjYWxscyBmb3IgYSBmbHVzaC5cblxuLy8gYHNldFRpbWVvdXRgIGRvZXMgbm90IGNhbGwgdGhlIHBhc3NlZCBjYWxsYmFjayBpZiB0aGUgZGVsYXkgaXMgbGVzcyB0aGFuXG4vLyBhcHByb3hpbWF0ZWx5IDcgaW4gd2ViIHdvcmtlcnMgaW4gRmlyZWZveCA4IHRocm91Z2ggMTgsIGFuZCBzb21ldGltZXMgbm90XG4vLyBldmVuIHRoZW4uXG5cbmZ1bmN0aW9uIG1ha2VSZXF1ZXN0Q2FsbEZyb21UaW1lcihjYWxsYmFjaykge1xuICAgIHJldHVybiBmdW5jdGlvbiByZXF1ZXN0Q2FsbCgpIHtcbiAgICAgICAgLy8gV2UgZGlzcGF0Y2ggYSB0aW1lb3V0IHdpdGggYSBzcGVjaWZpZWQgZGVsYXkgb2YgMCBmb3IgZW5naW5lcyB0aGF0XG4gICAgICAgIC8vIGNhbiByZWxpYWJseSBhY2NvbW1vZGF0ZSB0aGF0IHJlcXVlc3QuIFRoaXMgd2lsbCB1c3VhbGx5IGJlIHNuYXBwZWRcbiAgICAgICAgLy8gdG8gYSA0IG1pbGlzZWNvbmQgZGVsYXksIGJ1dCBvbmNlIHdlJ3JlIGZsdXNoaW5nLCB0aGVyZSdzIG5vIGRlbGF5XG4gICAgICAgIC8vIGJldHdlZW4gZXZlbnRzLlxuICAgICAgICB2YXIgdGltZW91dEhhbmRsZSA9IHNldFRpbWVvdXQoaGFuZGxlVGltZXIsIDApO1xuICAgICAgICAvLyBIb3dldmVyLCBzaW5jZSB0aGlzIHRpbWVyIGdldHMgZnJlcXVlbnRseSBkcm9wcGVkIGluIEZpcmVmb3hcbiAgICAgICAgLy8gd29ya2Vycywgd2UgZW5saXN0IGFuIGludGVydmFsIGhhbmRsZSB0aGF0IHdpbGwgdHJ5IHRvIGZpcmVcbiAgICAgICAgLy8gYW4gZXZlbnQgMjAgdGltZXMgcGVyIHNlY29uZCB1bnRpbCBpdCBzdWNjZWVkcy5cbiAgICAgICAgdmFyIGludGVydmFsSGFuZGxlID0gc2V0SW50ZXJ2YWwoaGFuZGxlVGltZXIsIDUwKTtcblxuICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaW1lcigpIHtcbiAgICAgICAgICAgIC8vIFdoaWNoZXZlciB0aW1lciBzdWNjZWVkcyB3aWxsIGNhbmNlbCBib3RoIHRpbWVycyBhbmRcbiAgICAgICAgICAgIC8vIGV4ZWN1dGUgdGhlIGNhbGxiYWNrLlxuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRIYW5kbGUpO1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbEhhbmRsZSk7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuLy8gVGhpcyBpcyBmb3IgYGFzYXAuanNgIG9ubHkuXG4vLyBJdHMgbmFtZSB3aWxsIGJlIHBlcmlvZGljYWxseSByYW5kb21pemVkIHRvIGJyZWFrIGFueSBjb2RlIHRoYXQgZGVwZW5kcyBvblxuLy8gaXRzIGV4aXN0ZW5jZS5cbnJhd0FzYXAubWFrZVJlcXVlc3RDYWxsRnJvbVRpbWVyID0gbWFrZVJlcXVlc3RDYWxsRnJvbVRpbWVyO1xuXG4vLyBBU0FQIHdhcyBvcmlnaW5hbGx5IGEgbmV4dFRpY2sgc2hpbSBpbmNsdWRlZCBpbiBRLiBUaGlzIHdhcyBmYWN0b3JlZCBvdXRcbi8vIGludG8gdGhpcyBBU0FQIHBhY2thZ2UuIEl0IHdhcyBsYXRlciBhZGFwdGVkIHRvIFJTVlAgd2hpY2ggbWFkZSBmdXJ0aGVyXG4vLyBhbWVuZG1lbnRzLiBUaGVzZSBkZWNpc2lvbnMsIHBhcnRpY3VsYXJseSB0byBtYXJnaW5hbGl6ZSBNZXNzYWdlQ2hhbm5lbCBhbmRcbi8vIHRvIGNhcHR1cmUgdGhlIE11dGF0aW9uT2JzZXJ2ZXIgaW1wbGVtZW50YXRpb24gaW4gYSBjbG9zdXJlLCB3ZXJlIGludGVncmF0ZWRcbi8vIGJhY2sgaW50byBBU0FQIHByb3Blci5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90aWxkZWlvL3JzdnAuanMvYmxvYi9jZGRmNzIzMjU0NmE5Y2Y4NTg1MjRiNzVjZGU2ZjllZGY3MjYyMGE3L2xpYi9yc3ZwL2FzYXAuanNcbiIsIiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEdldEludHJpbnNpYyA9IHJlcXVpcmUoJ2dldC1pbnRyaW5zaWMnKTtcblxudmFyIGNhbGxCaW5kID0gcmVxdWlyZSgnLi8nKTtcblxudmFyICRpbmRleE9mID0gY2FsbEJpbmQoR2V0SW50cmluc2ljKCdTdHJpbmcucHJvdG90eXBlLmluZGV4T2YnKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsbEJvdW5kSW50cmluc2ljKG5hbWUsIGFsbG93TWlzc2luZykge1xuXHR2YXIgaW50cmluc2ljID0gR2V0SW50cmluc2ljKG5hbWUsICEhYWxsb3dNaXNzaW5nKTtcblx0aWYgKHR5cGVvZiBpbnRyaW5zaWMgPT09ICdmdW5jdGlvbicgJiYgJGluZGV4T2YobmFtZSwgJy5wcm90b3R5cGUuJykgPiAtMSkge1xuXHRcdHJldHVybiBjYWxsQmluZChpbnRyaW5zaWMpO1xuXHR9XG5cdHJldHVybiBpbnRyaW5zaWM7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYmluZCA9IHJlcXVpcmUoJ2Z1bmN0aW9uLWJpbmQnKTtcbnZhciBHZXRJbnRyaW5zaWMgPSByZXF1aXJlKCdnZXQtaW50cmluc2ljJyk7XG5cbnZhciAkYXBwbHkgPSBHZXRJbnRyaW5zaWMoJyVGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHklJyk7XG52YXIgJGNhbGwgPSBHZXRJbnRyaW5zaWMoJyVGdW5jdGlvbi5wcm90b3R5cGUuY2FsbCUnKTtcbnZhciAkcmVmbGVjdEFwcGx5ID0gR2V0SW50cmluc2ljKCclUmVmbGVjdC5hcHBseSUnLCB0cnVlKSB8fCBiaW5kLmNhbGwoJGNhbGwsICRhcHBseSk7XG5cbnZhciAkZ09QRCA9IEdldEludHJpbnNpYygnJU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IlJywgdHJ1ZSk7XG52YXIgJGRlZmluZVByb3BlcnR5ID0gR2V0SW50cmluc2ljKCclT2JqZWN0LmRlZmluZVByb3BlcnR5JScsIHRydWUpO1xudmFyICRtYXggPSBHZXRJbnRyaW5zaWMoJyVNYXRoLm1heCUnKTtcblxuaWYgKCRkZWZpbmVQcm9wZXJ0eSkge1xuXHR0cnkge1xuXHRcdCRkZWZpbmVQcm9wZXJ0eSh7fSwgJ2EnLCB7IHZhbHVlOiAxIH0pO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Ly8gSUUgOCBoYXMgYSBicm9rZW4gZGVmaW5lUHJvcGVydHlcblx0XHQkZGVmaW5lUHJvcGVydHkgPSBudWxsO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsbEJpbmQob3JpZ2luYWxGdW5jdGlvbikge1xuXHR2YXIgZnVuYyA9ICRyZWZsZWN0QXBwbHkoYmluZCwgJGNhbGwsIGFyZ3VtZW50cyk7XG5cdGlmICgkZ09QRCAmJiAkZGVmaW5lUHJvcGVydHkpIHtcblx0XHR2YXIgZGVzYyA9ICRnT1BEKGZ1bmMsICdsZW5ndGgnKTtcblx0XHRpZiAoZGVzYy5jb25maWd1cmFibGUpIHtcblx0XHRcdC8vIG9yaWdpbmFsIGxlbmd0aCwgcGx1cyB0aGUgcmVjZWl2ZXIsIG1pbnVzIGFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyAoYWZ0ZXIgdGhlIHJlY2VpdmVyKVxuXHRcdFx0JGRlZmluZVByb3BlcnR5KFxuXHRcdFx0XHRmdW5jLFxuXHRcdFx0XHQnbGVuZ3RoJyxcblx0XHRcdFx0eyB2YWx1ZTogMSArICRtYXgoMCwgb3JpZ2luYWxGdW5jdGlvbi5sZW5ndGggLSAoYXJndW1lbnRzLmxlbmd0aCAtIDEpKSB9XG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gZnVuYztcbn07XG5cbnZhciBhcHBseUJpbmQgPSBmdW5jdGlvbiBhcHBseUJpbmQoKSB7XG5cdHJldHVybiAkcmVmbGVjdEFwcGx5KGJpbmQsICRhcHBseSwgYXJndW1lbnRzKTtcbn07XG5cbmlmICgkZGVmaW5lUHJvcGVydHkpIHtcblx0JGRlZmluZVByb3BlcnR5KG1vZHVsZS5leHBvcnRzLCAnYXBwbHknLCB7IHZhbHVlOiBhcHBseUJpbmQgfSk7XG59IGVsc2Uge1xuXHRtb2R1bGUuZXhwb3J0cy5hcHBseSA9IGFwcGx5QmluZDtcbn1cbiIsIi8qKlxuICogRXZFbWl0dGVyIHYxLjEuMFxuICogTGlsJyBldmVudCBlbWl0dGVyXG4gKiBNSVQgTGljZW5zZVxuICovXG5cbi8qIGpzaGludCB1bnVzZWQ6IHRydWUsIHVuZGVmOiB0cnVlLCBzdHJpY3Q6IHRydWUgKi9cblxuKCBmdW5jdGlvbiggZ2xvYmFsLCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgLyoganNoaW50IHN0cmljdDogZmFsc2UgKi8gLyogZ2xvYmFscyBkZWZpbmUsIG1vZHVsZSwgd2luZG93ICovXG4gIGlmICggdHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG4gICAgLy8gQU1EIC0gUmVxdWlyZUpTXG4gICAgZGVmaW5lKCBmYWN0b3J5ICk7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlMgLSBCcm93c2VyaWZ5LCBXZWJwYWNrXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgZ2xvYmFsLkV2RW1pdHRlciA9IGZhY3RvcnkoKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oKSB7XG5cblwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBFdkVtaXR0ZXIoKSB7fVxuXG52YXIgcHJvdG8gPSBFdkVtaXR0ZXIucHJvdG90eXBlO1xuXG5wcm90by5vbiA9IGZ1bmN0aW9uKCBldmVudE5hbWUsIGxpc3RlbmVyICkge1xuICBpZiAoICFldmVudE5hbWUgfHwgIWxpc3RlbmVyICkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBzZXQgZXZlbnRzIGhhc2hcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgLy8gc2V0IGxpc3RlbmVycyBhcnJheVxuICB2YXIgbGlzdGVuZXJzID0gZXZlbnRzWyBldmVudE5hbWUgXSA9IGV2ZW50c1sgZXZlbnROYW1lIF0gfHwgW107XG4gIC8vIG9ubHkgYWRkIG9uY2VcbiAgaWYgKCBsaXN0ZW5lcnMuaW5kZXhPZiggbGlzdGVuZXIgKSA9PSAtMSApIHtcbiAgICBsaXN0ZW5lcnMucHVzaCggbGlzdGVuZXIgKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxucHJvdG8ub25jZSA9IGZ1bmN0aW9uKCBldmVudE5hbWUsIGxpc3RlbmVyICkge1xuICBpZiAoICFldmVudE5hbWUgfHwgIWxpc3RlbmVyICkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBhZGQgZXZlbnRcbiAgdGhpcy5vbiggZXZlbnROYW1lLCBsaXN0ZW5lciApO1xuICAvLyBzZXQgb25jZSBmbGFnXG4gIC8vIHNldCBvbmNlRXZlbnRzIGhhc2hcbiAgdmFyIG9uY2VFdmVudHMgPSB0aGlzLl9vbmNlRXZlbnRzID0gdGhpcy5fb25jZUV2ZW50cyB8fCB7fTtcbiAgLy8gc2V0IG9uY2VMaXN0ZW5lcnMgb2JqZWN0XG4gIHZhciBvbmNlTGlzdGVuZXJzID0gb25jZUV2ZW50c1sgZXZlbnROYW1lIF0gPSBvbmNlRXZlbnRzWyBldmVudE5hbWUgXSB8fCB7fTtcbiAgLy8gc2V0IGZsYWdcbiAgb25jZUxpc3RlbmVyc1sgbGlzdGVuZXIgXSA9IHRydWU7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5vZmYgPSBmdW5jdGlvbiggZXZlbnROYW1lLCBsaXN0ZW5lciApIHtcbiAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbIGV2ZW50TmFtZSBdO1xuICBpZiAoICFsaXN0ZW5lcnMgfHwgIWxpc3RlbmVycy5sZW5ndGggKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBpbmRleCA9IGxpc3RlbmVycy5pbmRleE9mKCBsaXN0ZW5lciApO1xuICBpZiAoIGluZGV4ICE9IC0xICkge1xuICAgIGxpc3RlbmVycy5zcGxpY2UoIGluZGV4LCAxICk7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbnByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uKCBldmVudE5hbWUsIGFyZ3MgKSB7XG4gIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHMgJiYgdGhpcy5fZXZlbnRzWyBldmVudE5hbWUgXTtcbiAgaWYgKCAhbGlzdGVuZXJzIHx8ICFsaXN0ZW5lcnMubGVuZ3RoICkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBjb3B5IG92ZXIgdG8gYXZvaWQgaW50ZXJmZXJlbmNlIGlmIC5vZmYoKSBpbiBsaXN0ZW5lclxuICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuc2xpY2UoMCk7XG4gIGFyZ3MgPSBhcmdzIHx8IFtdO1xuICAvLyBvbmNlIHN0dWZmXG4gIHZhciBvbmNlTGlzdGVuZXJzID0gdGhpcy5fb25jZUV2ZW50cyAmJiB0aGlzLl9vbmNlRXZlbnRzWyBldmVudE5hbWUgXTtcblxuICBmb3IgKCB2YXIgaT0wOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrICkge1xuICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXVxuICAgIHZhciBpc09uY2UgPSBvbmNlTGlzdGVuZXJzICYmIG9uY2VMaXN0ZW5lcnNbIGxpc3RlbmVyIF07XG4gICAgaWYgKCBpc09uY2UgKSB7XG4gICAgICAvLyByZW1vdmUgbGlzdGVuZXJcbiAgICAgIC8vIHJlbW92ZSBiZWZvcmUgdHJpZ2dlciB0byBwcmV2ZW50IHJlY3Vyc2lvblxuICAgICAgdGhpcy5vZmYoIGV2ZW50TmFtZSwgbGlzdGVuZXIgKTtcbiAgICAgIC8vIHVuc2V0IG9uY2UgZmxhZ1xuICAgICAgZGVsZXRlIG9uY2VMaXN0ZW5lcnNbIGxpc3RlbmVyIF07XG4gICAgfVxuICAgIC8vIHRyaWdnZXIgbGlzdGVuZXJcbiAgICBsaXN0ZW5lci5hcHBseSggdGhpcywgYXJncyApO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5hbGxPZmYgPSBmdW5jdGlvbigpIHtcbiAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgZGVsZXRlIHRoaXMuX29uY2VFdmVudHM7XG59O1xuXG5yZXR1cm4gRXZFbWl0dGVyO1xuXG59KSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qIGVzbGludCBuby1pbnZhbGlkLXRoaXM6IDEgKi9cblxudmFyIEVSUk9SX01FU1NBR0UgPSAnRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgY2FsbGVkIG9uIGluY29tcGF0aWJsZSAnO1xudmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xudmFyIHRvU3RyID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcbnZhciBmdW5jVHlwZSA9ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYmluZCh0aGF0KSB7XG4gICAgdmFyIHRhcmdldCA9IHRoaXM7XG4gICAgaWYgKHR5cGVvZiB0YXJnZXQgIT09ICdmdW5jdGlvbicgfHwgdG9TdHIuY2FsbCh0YXJnZXQpICE9PSBmdW5jVHlwZSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEVSUk9SX01FU1NBR0UgKyB0YXJnZXQpO1xuICAgIH1cbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcblxuICAgIHZhciBib3VuZDtcbiAgICB2YXIgYmluZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGFyZ2V0LmFwcGx5KFxuICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChPYmplY3QocmVzdWx0KSA9PT0gcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5hcHBseShcbiAgICAgICAgICAgICAgICB0aGF0LFxuICAgICAgICAgICAgICAgIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFyIGJvdW5kTGVuZ3RoID0gTWF0aC5tYXgoMCwgdGFyZ2V0Lmxlbmd0aCAtIGFyZ3MubGVuZ3RoKTtcbiAgICB2YXIgYm91bmRBcmdzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBib3VuZExlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJvdW5kQXJncy5wdXNoKCckJyArIGkpO1xuICAgIH1cblxuICAgIGJvdW5kID0gRnVuY3Rpb24oJ2JpbmRlcicsICdyZXR1cm4gZnVuY3Rpb24gKCcgKyBib3VuZEFyZ3Muam9pbignLCcpICsgJyl7IHJldHVybiBiaW5kZXIuYXBwbHkodGhpcyxhcmd1bWVudHMpOyB9JykoYmluZGVyKTtcblxuICAgIGlmICh0YXJnZXQucHJvdG90eXBlKSB7XG4gICAgICAgIHZhciBFbXB0eSA9IGZ1bmN0aW9uIEVtcHR5KCkge307XG4gICAgICAgIEVtcHR5LnByb3RvdHlwZSA9IHRhcmdldC5wcm90b3R5cGU7XG4gICAgICAgIGJvdW5kLnByb3RvdHlwZSA9IG5ldyBFbXB0eSgpO1xuICAgICAgICBFbXB0eS5wcm90b3R5cGUgPSBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBib3VuZDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBpbXBsZW1lbnRhdGlvbiA9IHJlcXVpcmUoJy4vaW1wbGVtZW50YXRpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCB8fCBpbXBsZW1lbnRhdGlvbjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHVuZGVmaW5lZDtcblxudmFyICRTeW50YXhFcnJvciA9IFN5bnRheEVycm9yO1xudmFyICRGdW5jdGlvbiA9IEZ1bmN0aW9uO1xudmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb25zaXN0ZW50LXJldHVyblxudmFyIGdldEV2YWxsZWRDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChleHByZXNzaW9uU3ludGF4KSB7XG5cdHRyeSB7XG5cdFx0cmV0dXJuICRGdW5jdGlvbignXCJ1c2Ugc3RyaWN0XCI7IHJldHVybiAoJyArIGV4cHJlc3Npb25TeW50YXggKyAnKS5jb25zdHJ1Y3RvcjsnKSgpO1xuXHR9IGNhdGNoIChlKSB7fVxufTtcblxudmFyICRnT1BEID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcbmlmICgkZ09QRCkge1xuXHR0cnkge1xuXHRcdCRnT1BEKHt9LCAnJyk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHQkZ09QRCA9IG51bGw7IC8vIHRoaXMgaXMgSUUgOCwgd2hpY2ggaGFzIGEgYnJva2VuIGdPUERcblx0fVxufVxuXG52YXIgdGhyb3dUeXBlRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG5cdHRocm93IG5ldyAkVHlwZUVycm9yKCk7XG59O1xudmFyIFRocm93VHlwZUVycm9yID0gJGdPUERcblx0PyAoZnVuY3Rpb24gKCkge1xuXHRcdHRyeSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLWV4cHJlc3Npb25zLCBuby1jYWxsZXIsIG5vLXJlc3RyaWN0ZWQtcHJvcGVydGllc1xuXHRcdFx0YXJndW1lbnRzLmNhbGxlZTsgLy8gSUUgOCBkb2VzIG5vdCB0aHJvdyBoZXJlXG5cdFx0XHRyZXR1cm4gdGhyb3dUeXBlRXJyb3I7XG5cdFx0fSBjYXRjaCAoY2FsbGVlVGhyb3dzKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHQvLyBJRSA4IHRocm93cyBvbiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGFyZ3VtZW50cywgJycpXG5cdFx0XHRcdHJldHVybiAkZ09QRChhcmd1bWVudHMsICdjYWxsZWUnKS5nZXQ7XG5cdFx0XHR9IGNhdGNoIChnT1BEdGhyb3dzKSB7XG5cdFx0XHRcdHJldHVybiB0aHJvd1R5cGVFcnJvcjtcblx0XHRcdH1cblx0XHR9XG5cdH0oKSlcblx0OiB0aHJvd1R5cGVFcnJvcjtcblxudmFyIGhhc1N5bWJvbHMgPSByZXF1aXJlKCdoYXMtc3ltYm9scycpKCk7XG5cbnZhciBnZXRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiB8fCBmdW5jdGlvbiAoeCkgeyByZXR1cm4geC5fX3Byb3RvX187IH07IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tcHJvdG9cblxudmFyIG5lZWRzRXZhbCA9IHt9O1xuXG52YXIgVHlwZWRBcnJheSA9IHR5cGVvZiBVaW50OEFycmF5ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IGdldFByb3RvKFVpbnQ4QXJyYXkpO1xuXG52YXIgSU5UUklOU0lDUyA9IHtcblx0JyVBZ2dyZWdhdGVFcnJvciUnOiB0eXBlb2YgQWdncmVnYXRlRXJyb3IgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogQWdncmVnYXRlRXJyb3IsXG5cdCclQXJyYXklJzogQXJyYXksXG5cdCclQXJyYXlCdWZmZXIlJzogdHlwZW9mIEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IEFycmF5QnVmZmVyLFxuXHQnJUFycmF5SXRlcmF0b3JQcm90b3R5cGUlJzogaGFzU3ltYm9scyA/IGdldFByb3RvKFtdW1N5bWJvbC5pdGVyYXRvcl0oKSkgOiB1bmRlZmluZWQsXG5cdCclQXN5bmNGcm9tU3luY0l0ZXJhdG9yUHJvdG90eXBlJSc6IHVuZGVmaW5lZCxcblx0JyVBc3luY0Z1bmN0aW9uJSc6IG5lZWRzRXZhbCxcblx0JyVBc3luY0dlbmVyYXRvciUnOiBuZWVkc0V2YWwsXG5cdCclQXN5bmNHZW5lcmF0b3JGdW5jdGlvbiUnOiBuZWVkc0V2YWwsXG5cdCclQXN5bmNJdGVyYXRvclByb3RvdHlwZSUnOiBuZWVkc0V2YWwsXG5cdCclQXRvbWljcyUnOiB0eXBlb2YgQXRvbWljcyA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBBdG9taWNzLFxuXHQnJUJpZ0ludCUnOiB0eXBlb2YgQmlnSW50ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IEJpZ0ludCxcblx0JyVCb29sZWFuJSc6IEJvb2xlYW4sXG5cdCclRGF0YVZpZXclJzogdHlwZW9mIERhdGFWaWV3ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IERhdGFWaWV3LFxuXHQnJURhdGUlJzogRGF0ZSxcblx0JyVkZWNvZGVVUkklJzogZGVjb2RlVVJJLFxuXHQnJWRlY29kZVVSSUNvbXBvbmVudCUnOiBkZWNvZGVVUklDb21wb25lbnQsXG5cdCclZW5jb2RlVVJJJSc6IGVuY29kZVVSSSxcblx0JyVlbmNvZGVVUklDb21wb25lbnQlJzogZW5jb2RlVVJJQ29tcG9uZW50LFxuXHQnJUVycm9yJSc6IEVycm9yLFxuXHQnJWV2YWwlJzogZXZhbCwgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1ldmFsXG5cdCclRXZhbEVycm9yJSc6IEV2YWxFcnJvcixcblx0JyVGbG9hdDMyQXJyYXklJzogdHlwZW9mIEZsb2F0MzJBcnJheSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBGbG9hdDMyQXJyYXksXG5cdCclRmxvYXQ2NEFycmF5JSc6IHR5cGVvZiBGbG9hdDY0QXJyYXkgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogRmxvYXQ2NEFycmF5LFxuXHQnJUZpbmFsaXphdGlvblJlZ2lzdHJ5JSc6IHR5cGVvZiBGaW5hbGl6YXRpb25SZWdpc3RyeSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBGaW5hbGl6YXRpb25SZWdpc3RyeSxcblx0JyVGdW5jdGlvbiUnOiAkRnVuY3Rpb24sXG5cdCclR2VuZXJhdG9yRnVuY3Rpb24lJzogbmVlZHNFdmFsLFxuXHQnJUludDhBcnJheSUnOiB0eXBlb2YgSW50OEFycmF5ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IEludDhBcnJheSxcblx0JyVJbnQxNkFycmF5JSc6IHR5cGVvZiBJbnQxNkFycmF5ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IEludDE2QXJyYXksXG5cdCclSW50MzJBcnJheSUnOiB0eXBlb2YgSW50MzJBcnJheSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBJbnQzMkFycmF5LFxuXHQnJWlzRmluaXRlJSc6IGlzRmluaXRlLFxuXHQnJWlzTmFOJSc6IGlzTmFOLFxuXHQnJUl0ZXJhdG9yUHJvdG90eXBlJSc6IGhhc1N5bWJvbHMgPyBnZXRQcm90byhnZXRQcm90byhbXVtTeW1ib2wuaXRlcmF0b3JdKCkpKSA6IHVuZGVmaW5lZCxcblx0JyVKU09OJSc6IHR5cGVvZiBKU09OID09PSAnb2JqZWN0JyA/IEpTT04gOiB1bmRlZmluZWQsXG5cdCclTWFwJSc6IHR5cGVvZiBNYXAgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogTWFwLFxuXHQnJU1hcEl0ZXJhdG9yUHJvdG90eXBlJSc6IHR5cGVvZiBNYXAgPT09ICd1bmRlZmluZWQnIHx8ICFoYXNTeW1ib2xzID8gdW5kZWZpbmVkIDogZ2V0UHJvdG8obmV3IE1hcCgpW1N5bWJvbC5pdGVyYXRvcl0oKSksXG5cdCclTWF0aCUnOiBNYXRoLFxuXHQnJU51bWJlciUnOiBOdW1iZXIsXG5cdCclT2JqZWN0JSc6IE9iamVjdCxcblx0JyVwYXJzZUZsb2F0JSc6IHBhcnNlRmxvYXQsXG5cdCclcGFyc2VJbnQlJzogcGFyc2VJbnQsXG5cdCclUHJvbWlzZSUnOiB0eXBlb2YgUHJvbWlzZSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBQcm9taXNlLFxuXHQnJVByb3h5JSc6IHR5cGVvZiBQcm94eSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBQcm94eSxcblx0JyVSYW5nZUVycm9yJSc6IFJhbmdlRXJyb3IsXG5cdCclUmVmZXJlbmNlRXJyb3IlJzogUmVmZXJlbmNlRXJyb3IsXG5cdCclUmVmbGVjdCUnOiB0eXBlb2YgUmVmbGVjdCA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBSZWZsZWN0LFxuXHQnJVJlZ0V4cCUnOiBSZWdFeHAsXG5cdCclU2V0JSc6IHR5cGVvZiBTZXQgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogU2V0LFxuXHQnJVNldEl0ZXJhdG9yUHJvdG90eXBlJSc6IHR5cGVvZiBTZXQgPT09ICd1bmRlZmluZWQnIHx8ICFoYXNTeW1ib2xzID8gdW5kZWZpbmVkIDogZ2V0UHJvdG8obmV3IFNldCgpW1N5bWJvbC5pdGVyYXRvcl0oKSksXG5cdCclU2hhcmVkQXJyYXlCdWZmZXIlJzogdHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IFNoYXJlZEFycmF5QnVmZmVyLFxuXHQnJVN0cmluZyUnOiBTdHJpbmcsXG5cdCclU3RyaW5nSXRlcmF0b3JQcm90b3R5cGUlJzogaGFzU3ltYm9scyA/IGdldFByb3RvKCcnW1N5bWJvbC5pdGVyYXRvcl0oKSkgOiB1bmRlZmluZWQsXG5cdCclU3ltYm9sJSc6IGhhc1N5bWJvbHMgPyBTeW1ib2wgOiB1bmRlZmluZWQsXG5cdCclU3ludGF4RXJyb3IlJzogJFN5bnRheEVycm9yLFxuXHQnJVRocm93VHlwZUVycm9yJSc6IFRocm93VHlwZUVycm9yLFxuXHQnJVR5cGVkQXJyYXklJzogVHlwZWRBcnJheSxcblx0JyVUeXBlRXJyb3IlJzogJFR5cGVFcnJvcixcblx0JyVVaW50OEFycmF5JSc6IHR5cGVvZiBVaW50OEFycmF5ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IFVpbnQ4QXJyYXksXG5cdCclVWludDhDbGFtcGVkQXJyYXklJzogdHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IFVpbnQ4Q2xhbXBlZEFycmF5LFxuXHQnJVVpbnQxNkFycmF5JSc6IHR5cGVvZiBVaW50MTZBcnJheSA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBVaW50MTZBcnJheSxcblx0JyVVaW50MzJBcnJheSUnOiB0eXBlb2YgVWludDMyQXJyYXkgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogVWludDMyQXJyYXksXG5cdCclVVJJRXJyb3IlJzogVVJJRXJyb3IsXG5cdCclV2Vha01hcCUnOiB0eXBlb2YgV2Vha01hcCA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBXZWFrTWFwLFxuXHQnJVdlYWtSZWYlJzogdHlwZW9mIFdlYWtSZWYgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogV2Vha1JlZixcblx0JyVXZWFrU2V0JSc6IHR5cGVvZiBXZWFrU2V0ID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IFdlYWtTZXRcbn07XG5cbnZhciBkb0V2YWwgPSBmdW5jdGlvbiBkb0V2YWwobmFtZSkge1xuXHR2YXIgdmFsdWU7XG5cdGlmIChuYW1lID09PSAnJUFzeW5jRnVuY3Rpb24lJykge1xuXHRcdHZhbHVlID0gZ2V0RXZhbGxlZENvbnN0cnVjdG9yKCdhc3luYyBmdW5jdGlvbiAoKSB7fScpO1xuXHR9IGVsc2UgaWYgKG5hbWUgPT09ICclR2VuZXJhdG9yRnVuY3Rpb24lJykge1xuXHRcdHZhbHVlID0gZ2V0RXZhbGxlZENvbnN0cnVjdG9yKCdmdW5jdGlvbiogKCkge30nKTtcblx0fSBlbHNlIGlmIChuYW1lID09PSAnJUFzeW5jR2VuZXJhdG9yRnVuY3Rpb24lJykge1xuXHRcdHZhbHVlID0gZ2V0RXZhbGxlZENvbnN0cnVjdG9yKCdhc3luYyBmdW5jdGlvbiogKCkge30nKTtcblx0fSBlbHNlIGlmIChuYW1lID09PSAnJUFzeW5jR2VuZXJhdG9yJScpIHtcblx0XHR2YXIgZm4gPSBkb0V2YWwoJyVBc3luY0dlbmVyYXRvckZ1bmN0aW9uJScpO1xuXHRcdGlmIChmbikge1xuXHRcdFx0dmFsdWUgPSBmbi5wcm90b3R5cGU7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKG5hbWUgPT09ICclQXN5bmNJdGVyYXRvclByb3RvdHlwZSUnKSB7XG5cdFx0dmFyIGdlbiA9IGRvRXZhbCgnJUFzeW5jR2VuZXJhdG9yJScpO1xuXHRcdGlmIChnZW4pIHtcblx0XHRcdHZhbHVlID0gZ2V0UHJvdG8oZ2VuLnByb3RvdHlwZSk7XG5cdFx0fVxuXHR9XG5cblx0SU5UUklOU0lDU1tuYW1lXSA9IHZhbHVlO1xuXG5cdHJldHVybiB2YWx1ZTtcbn07XG5cbnZhciBMRUdBQ1lfQUxJQVNFUyA9IHtcblx0JyVBcnJheUJ1ZmZlclByb3RvdHlwZSUnOiBbJ0FycmF5QnVmZmVyJywgJ3Byb3RvdHlwZSddLFxuXHQnJUFycmF5UHJvdG90eXBlJSc6IFsnQXJyYXknLCAncHJvdG90eXBlJ10sXG5cdCclQXJyYXlQcm90b19lbnRyaWVzJSc6IFsnQXJyYXknLCAncHJvdG90eXBlJywgJ2VudHJpZXMnXSxcblx0JyVBcnJheVByb3RvX2ZvckVhY2glJzogWydBcnJheScsICdwcm90b3R5cGUnLCAnZm9yRWFjaCddLFxuXHQnJUFycmF5UHJvdG9fa2V5cyUnOiBbJ0FycmF5JywgJ3Byb3RvdHlwZScsICdrZXlzJ10sXG5cdCclQXJyYXlQcm90b192YWx1ZXMlJzogWydBcnJheScsICdwcm90b3R5cGUnLCAndmFsdWVzJ10sXG5cdCclQXN5bmNGdW5jdGlvblByb3RvdHlwZSUnOiBbJ0FzeW5jRnVuY3Rpb24nLCAncHJvdG90eXBlJ10sXG5cdCclQXN5bmNHZW5lcmF0b3IlJzogWydBc3luY0dlbmVyYXRvckZ1bmN0aW9uJywgJ3Byb3RvdHlwZSddLFxuXHQnJUFzeW5jR2VuZXJhdG9yUHJvdG90eXBlJSc6IFsnQXN5bmNHZW5lcmF0b3JGdW5jdGlvbicsICdwcm90b3R5cGUnLCAncHJvdG90eXBlJ10sXG5cdCclQm9vbGVhblByb3RvdHlwZSUnOiBbJ0Jvb2xlYW4nLCAncHJvdG90eXBlJ10sXG5cdCclRGF0YVZpZXdQcm90b3R5cGUlJzogWydEYXRhVmlldycsICdwcm90b3R5cGUnXSxcblx0JyVEYXRlUHJvdG90eXBlJSc6IFsnRGF0ZScsICdwcm90b3R5cGUnXSxcblx0JyVFcnJvclByb3RvdHlwZSUnOiBbJ0Vycm9yJywgJ3Byb3RvdHlwZSddLFxuXHQnJUV2YWxFcnJvclByb3RvdHlwZSUnOiBbJ0V2YWxFcnJvcicsICdwcm90b3R5cGUnXSxcblx0JyVGbG9hdDMyQXJyYXlQcm90b3R5cGUlJzogWydGbG9hdDMyQXJyYXknLCAncHJvdG90eXBlJ10sXG5cdCclRmxvYXQ2NEFycmF5UHJvdG90eXBlJSc6IFsnRmxvYXQ2NEFycmF5JywgJ3Byb3RvdHlwZSddLFxuXHQnJUZ1bmN0aW9uUHJvdG90eXBlJSc6IFsnRnVuY3Rpb24nLCAncHJvdG90eXBlJ10sXG5cdCclR2VuZXJhdG9yJSc6IFsnR2VuZXJhdG9yRnVuY3Rpb24nLCAncHJvdG90eXBlJ10sXG5cdCclR2VuZXJhdG9yUHJvdG90eXBlJSc6IFsnR2VuZXJhdG9yRnVuY3Rpb24nLCAncHJvdG90eXBlJywgJ3Byb3RvdHlwZSddLFxuXHQnJUludDhBcnJheVByb3RvdHlwZSUnOiBbJ0ludDhBcnJheScsICdwcm90b3R5cGUnXSxcblx0JyVJbnQxNkFycmF5UHJvdG90eXBlJSc6IFsnSW50MTZBcnJheScsICdwcm90b3R5cGUnXSxcblx0JyVJbnQzMkFycmF5UHJvdG90eXBlJSc6IFsnSW50MzJBcnJheScsICdwcm90b3R5cGUnXSxcblx0JyVKU09OUGFyc2UlJzogWydKU09OJywgJ3BhcnNlJ10sXG5cdCclSlNPTlN0cmluZ2lmeSUnOiBbJ0pTT04nLCAnc3RyaW5naWZ5J10sXG5cdCclTWFwUHJvdG90eXBlJSc6IFsnTWFwJywgJ3Byb3RvdHlwZSddLFxuXHQnJU51bWJlclByb3RvdHlwZSUnOiBbJ051bWJlcicsICdwcm90b3R5cGUnXSxcblx0JyVPYmplY3RQcm90b3R5cGUlJzogWydPYmplY3QnLCAncHJvdG90eXBlJ10sXG5cdCclT2JqUHJvdG9fdG9TdHJpbmclJzogWydPYmplY3QnLCAncHJvdG90eXBlJywgJ3RvU3RyaW5nJ10sXG5cdCclT2JqUHJvdG9fdmFsdWVPZiUnOiBbJ09iamVjdCcsICdwcm90b3R5cGUnLCAndmFsdWVPZiddLFxuXHQnJVByb21pc2VQcm90b3R5cGUlJzogWydQcm9taXNlJywgJ3Byb3RvdHlwZSddLFxuXHQnJVByb21pc2VQcm90b190aGVuJSc6IFsnUHJvbWlzZScsICdwcm90b3R5cGUnLCAndGhlbiddLFxuXHQnJVByb21pc2VfYWxsJSc6IFsnUHJvbWlzZScsICdhbGwnXSxcblx0JyVQcm9taXNlX3JlamVjdCUnOiBbJ1Byb21pc2UnLCAncmVqZWN0J10sXG5cdCclUHJvbWlzZV9yZXNvbHZlJSc6IFsnUHJvbWlzZScsICdyZXNvbHZlJ10sXG5cdCclUmFuZ2VFcnJvclByb3RvdHlwZSUnOiBbJ1JhbmdlRXJyb3InLCAncHJvdG90eXBlJ10sXG5cdCclUmVmZXJlbmNlRXJyb3JQcm90b3R5cGUlJzogWydSZWZlcmVuY2VFcnJvcicsICdwcm90b3R5cGUnXSxcblx0JyVSZWdFeHBQcm90b3R5cGUlJzogWydSZWdFeHAnLCAncHJvdG90eXBlJ10sXG5cdCclU2V0UHJvdG90eXBlJSc6IFsnU2V0JywgJ3Byb3RvdHlwZSddLFxuXHQnJVNoYXJlZEFycmF5QnVmZmVyUHJvdG90eXBlJSc6IFsnU2hhcmVkQXJyYXlCdWZmZXInLCAncHJvdG90eXBlJ10sXG5cdCclU3RyaW5nUHJvdG90eXBlJSc6IFsnU3RyaW5nJywgJ3Byb3RvdHlwZSddLFxuXHQnJVN5bWJvbFByb3RvdHlwZSUnOiBbJ1N5bWJvbCcsICdwcm90b3R5cGUnXSxcblx0JyVTeW50YXhFcnJvclByb3RvdHlwZSUnOiBbJ1N5bnRheEVycm9yJywgJ3Byb3RvdHlwZSddLFxuXHQnJVR5cGVkQXJyYXlQcm90b3R5cGUlJzogWydUeXBlZEFycmF5JywgJ3Byb3RvdHlwZSddLFxuXHQnJVR5cGVFcnJvclByb3RvdHlwZSUnOiBbJ1R5cGVFcnJvcicsICdwcm90b3R5cGUnXSxcblx0JyVVaW50OEFycmF5UHJvdG90eXBlJSc6IFsnVWludDhBcnJheScsICdwcm90b3R5cGUnXSxcblx0JyVVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSUnOiBbJ1VpbnQ4Q2xhbXBlZEFycmF5JywgJ3Byb3RvdHlwZSddLFxuXHQnJVVpbnQxNkFycmF5UHJvdG90eXBlJSc6IFsnVWludDE2QXJyYXknLCAncHJvdG90eXBlJ10sXG5cdCclVWludDMyQXJyYXlQcm90b3R5cGUlJzogWydVaW50MzJBcnJheScsICdwcm90b3R5cGUnXSxcblx0JyVVUklFcnJvclByb3RvdHlwZSUnOiBbJ1VSSUVycm9yJywgJ3Byb3RvdHlwZSddLFxuXHQnJVdlYWtNYXBQcm90b3R5cGUlJzogWydXZWFrTWFwJywgJ3Byb3RvdHlwZSddLFxuXHQnJVdlYWtTZXRQcm90b3R5cGUlJzogWydXZWFrU2V0JywgJ3Byb3RvdHlwZSddXG59O1xuXG52YXIgYmluZCA9IHJlcXVpcmUoJ2Z1bmN0aW9uLWJpbmQnKTtcbnZhciBoYXNPd24gPSByZXF1aXJlKCdoYXMnKTtcbnZhciAkY29uY2F0ID0gYmluZC5jYWxsKEZ1bmN0aW9uLmNhbGwsIEFycmF5LnByb3RvdHlwZS5jb25jYXQpO1xudmFyICRzcGxpY2VBcHBseSA9IGJpbmQuY2FsbChGdW5jdGlvbi5hcHBseSwgQXJyYXkucHJvdG90eXBlLnNwbGljZSk7XG52YXIgJHJlcGxhY2UgPSBiaW5kLmNhbGwoRnVuY3Rpb24uY2FsbCwgU3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlKTtcbnZhciAkc3RyU2xpY2UgPSBiaW5kLmNhbGwoRnVuY3Rpb24uY2FsbCwgU3RyaW5nLnByb3RvdHlwZS5zbGljZSk7XG5cbi8qIGFkYXB0ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbG9kYXNoL2xvZGFzaC9ibG9iLzQuMTcuMTUvZGlzdC9sb2Rhc2guanMjTDY3MzUtTDY3NDQgKi9cbnZhciByZVByb3BOYW1lID0gL1teJS5bXFxdXSt8XFxbKD86KC0/XFxkKyg/OlxcLlxcZCspPyl8KFtcIiddKSgoPzooPyFcXDIpW15cXFxcXXxcXFxcLikqPylcXDIpXFxdfCg/PSg/OlxcLnxcXFtcXF0pKD86XFwufFxcW1xcXXwlJCkpL2c7XG52YXIgcmVFc2NhcGVDaGFyID0gL1xcXFwoXFxcXCk/L2c7IC8qKiBVc2VkIHRvIG1hdGNoIGJhY2tzbGFzaGVzIGluIHByb3BlcnR5IHBhdGhzLiAqL1xudmFyIHN0cmluZ1RvUGF0aCA9IGZ1bmN0aW9uIHN0cmluZ1RvUGF0aChzdHJpbmcpIHtcblx0dmFyIGZpcnN0ID0gJHN0clNsaWNlKHN0cmluZywgMCwgMSk7XG5cdHZhciBsYXN0ID0gJHN0clNsaWNlKHN0cmluZywgLTEpO1xuXHRpZiAoZmlyc3QgPT09ICclJyAmJiBsYXN0ICE9PSAnJScpIHtcblx0XHR0aHJvdyBuZXcgJFN5bnRheEVycm9yKCdpbnZhbGlkIGludHJpbnNpYyBzeW50YXgsIGV4cGVjdGVkIGNsb3NpbmcgYCVgJyk7XG5cdH0gZWxzZSBpZiAobGFzdCA9PT0gJyUnICYmIGZpcnN0ICE9PSAnJScpIHtcblx0XHR0aHJvdyBuZXcgJFN5bnRheEVycm9yKCdpbnZhbGlkIGludHJpbnNpYyBzeW50YXgsIGV4cGVjdGVkIG9wZW5pbmcgYCVgJyk7XG5cdH1cblx0dmFyIHJlc3VsdCA9IFtdO1xuXHQkcmVwbGFjZShzdHJpbmcsIHJlUHJvcE5hbWUsIGZ1bmN0aW9uIChtYXRjaCwgbnVtYmVyLCBxdW90ZSwgc3ViU3RyaW5nKSB7XG5cdFx0cmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gcXVvdGUgPyAkcmVwbGFjZShzdWJTdHJpbmcsIHJlRXNjYXBlQ2hhciwgJyQxJykgOiBudW1iZXIgfHwgbWF0Y2g7XG5cdH0pO1xuXHRyZXR1cm4gcmVzdWx0O1xufTtcbi8qIGVuZCBhZGFwdGF0aW9uICovXG5cbnZhciBnZXRCYXNlSW50cmluc2ljID0gZnVuY3Rpb24gZ2V0QmFzZUludHJpbnNpYyhuYW1lLCBhbGxvd01pc3NpbmcpIHtcblx0dmFyIGludHJpbnNpY05hbWUgPSBuYW1lO1xuXHR2YXIgYWxpYXM7XG5cdGlmIChoYXNPd24oTEVHQUNZX0FMSUFTRVMsIGludHJpbnNpY05hbWUpKSB7XG5cdFx0YWxpYXMgPSBMRUdBQ1lfQUxJQVNFU1tpbnRyaW5zaWNOYW1lXTtcblx0XHRpbnRyaW5zaWNOYW1lID0gJyUnICsgYWxpYXNbMF0gKyAnJSc7XG5cdH1cblxuXHRpZiAoaGFzT3duKElOVFJJTlNJQ1MsIGludHJpbnNpY05hbWUpKSB7XG5cdFx0dmFyIHZhbHVlID0gSU5UUklOU0lDU1tpbnRyaW5zaWNOYW1lXTtcblx0XHRpZiAodmFsdWUgPT09IG5lZWRzRXZhbCkge1xuXHRcdFx0dmFsdWUgPSBkb0V2YWwoaW50cmluc2ljTmFtZSk7XG5cdFx0fVxuXHRcdGlmICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnICYmICFhbGxvd01pc3NpbmcpIHtcblx0XHRcdHRocm93IG5ldyAkVHlwZUVycm9yKCdpbnRyaW5zaWMgJyArIG5hbWUgKyAnIGV4aXN0cywgYnV0IGlzIG5vdCBhdmFpbGFibGUuIFBsZWFzZSBmaWxlIGFuIGlzc3VlIScpO1xuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRhbGlhczogYWxpYXMsXG5cdFx0XHRuYW1lOiBpbnRyaW5zaWNOYW1lLFxuXHRcdFx0dmFsdWU6IHZhbHVlXG5cdFx0fTtcblx0fVxuXG5cdHRocm93IG5ldyAkU3ludGF4RXJyb3IoJ2ludHJpbnNpYyAnICsgbmFtZSArICcgZG9lcyBub3QgZXhpc3QhJyk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIEdldEludHJpbnNpYyhuYW1lLCBhbGxvd01pc3NpbmcpIHtcblx0aWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJyB8fCBuYW1lLmxlbmd0aCA9PT0gMCkge1xuXHRcdHRocm93IG5ldyAkVHlwZUVycm9yKCdpbnRyaW5zaWMgbmFtZSBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZycpO1xuXHR9XG5cdGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSAmJiB0eXBlb2YgYWxsb3dNaXNzaW5nICE9PSAnYm9vbGVhbicpIHtcblx0XHR0aHJvdyBuZXcgJFR5cGVFcnJvcignXCJhbGxvd01pc3NpbmdcIiBhcmd1bWVudCBtdXN0IGJlIGEgYm9vbGVhbicpO1xuXHR9XG5cblx0dmFyIHBhcnRzID0gc3RyaW5nVG9QYXRoKG5hbWUpO1xuXHR2YXIgaW50cmluc2ljQmFzZU5hbWUgPSBwYXJ0cy5sZW5ndGggPiAwID8gcGFydHNbMF0gOiAnJztcblxuXHR2YXIgaW50cmluc2ljID0gZ2V0QmFzZUludHJpbnNpYygnJScgKyBpbnRyaW5zaWNCYXNlTmFtZSArICclJywgYWxsb3dNaXNzaW5nKTtcblx0dmFyIGludHJpbnNpY1JlYWxOYW1lID0gaW50cmluc2ljLm5hbWU7XG5cdHZhciB2YWx1ZSA9IGludHJpbnNpYy52YWx1ZTtcblx0dmFyIHNraXBGdXJ0aGVyQ2FjaGluZyA9IGZhbHNlO1xuXG5cdHZhciBhbGlhcyA9IGludHJpbnNpYy5hbGlhcztcblx0aWYgKGFsaWFzKSB7XG5cdFx0aW50cmluc2ljQmFzZU5hbWUgPSBhbGlhc1swXTtcblx0XHQkc3BsaWNlQXBwbHkocGFydHMsICRjb25jYXQoWzAsIDFdLCBhbGlhcykpO1xuXHR9XG5cblx0Zm9yICh2YXIgaSA9IDEsIGlzT3duID0gdHJ1ZTsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAxKSB7XG5cdFx0dmFyIHBhcnQgPSBwYXJ0c1tpXTtcblx0XHR2YXIgZmlyc3QgPSAkc3RyU2xpY2UocGFydCwgMCwgMSk7XG5cdFx0dmFyIGxhc3QgPSAkc3RyU2xpY2UocGFydCwgLTEpO1xuXHRcdGlmIChcblx0XHRcdChcblx0XHRcdFx0KGZpcnN0ID09PSAnXCInIHx8IGZpcnN0ID09PSBcIidcIiB8fCBmaXJzdCA9PT0gJ2AnKVxuXHRcdFx0XHR8fCAobGFzdCA9PT0gJ1wiJyB8fCBsYXN0ID09PSBcIidcIiB8fCBsYXN0ID09PSAnYCcpXG5cdFx0XHQpXG5cdFx0XHQmJiBmaXJzdCAhPT0gbGFzdFxuXHRcdCkge1xuXHRcdFx0dGhyb3cgbmV3ICRTeW50YXhFcnJvcigncHJvcGVydHkgbmFtZXMgd2l0aCBxdW90ZXMgbXVzdCBoYXZlIG1hdGNoaW5nIHF1b3RlcycpO1xuXHRcdH1cblx0XHRpZiAocGFydCA9PT0gJ2NvbnN0cnVjdG9yJyB8fCAhaXNPd24pIHtcblx0XHRcdHNraXBGdXJ0aGVyQ2FjaGluZyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aW50cmluc2ljQmFzZU5hbWUgKz0gJy4nICsgcGFydDtcblx0XHRpbnRyaW5zaWNSZWFsTmFtZSA9ICclJyArIGludHJpbnNpY0Jhc2VOYW1lICsgJyUnO1xuXG5cdFx0aWYgKGhhc093bihJTlRSSU5TSUNTLCBpbnRyaW5zaWNSZWFsTmFtZSkpIHtcblx0XHRcdHZhbHVlID0gSU5UUklOU0lDU1tpbnRyaW5zaWNSZWFsTmFtZV07XG5cdFx0fSBlbHNlIGlmICh2YWx1ZSAhPSBudWxsKSB7XG5cdFx0XHRpZiAoIShwYXJ0IGluIHZhbHVlKSkge1xuXHRcdFx0XHRpZiAoIWFsbG93TWlzc2luZykge1xuXHRcdFx0XHRcdHRocm93IG5ldyAkVHlwZUVycm9yKCdiYXNlIGludHJpbnNpYyBmb3IgJyArIG5hbWUgKyAnIGV4aXN0cywgYnV0IHRoZSBwcm9wZXJ0eSBpcyBub3QgYXZhaWxhYmxlLicpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB2b2lkIHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHRcdGlmICgkZ09QRCAmJiAoaSArIDEpID49IHBhcnRzLmxlbmd0aCkge1xuXHRcdFx0XHR2YXIgZGVzYyA9ICRnT1BEKHZhbHVlLCBwYXJ0KTtcblx0XHRcdFx0aXNPd24gPSAhIWRlc2M7XG5cblx0XHRcdFx0Ly8gQnkgY29udmVudGlvbiwgd2hlbiBhIGRhdGEgcHJvcGVydHkgaXMgY29udmVydGVkIHRvIGFuIGFjY2Vzc29yXG5cdFx0XHRcdC8vIHByb3BlcnR5IHRvIGVtdWxhdGUgYSBkYXRhIHByb3BlcnR5IHRoYXQgZG9lcyBub3Qgc3VmZmVyIGZyb21cblx0XHRcdFx0Ly8gdGhlIG92ZXJyaWRlIG1pc3Rha2UsIHRoYXQgYWNjZXNzb3IncyBnZXR0ZXIgaXMgbWFya2VkIHdpdGhcblx0XHRcdFx0Ly8gYW4gYG9yaWdpbmFsVmFsdWVgIHByb3BlcnR5LiBIZXJlLCB3aGVuIHdlIGRldGVjdCB0aGlzLCB3ZVxuXHRcdFx0XHQvLyB1cGhvbGQgdGhlIGlsbHVzaW9uIGJ5IHByZXRlbmRpbmcgdG8gc2VlIHRoYXQgb3JpZ2luYWwgZGF0YVxuXHRcdFx0XHQvLyBwcm9wZXJ0eSwgaS5lLiwgcmV0dXJuaW5nIHRoZSB2YWx1ZSByYXRoZXIgdGhhbiB0aGUgZ2V0dGVyXG5cdFx0XHRcdC8vIGl0c2VsZi5cblx0XHRcdFx0aWYgKGlzT3duICYmICdnZXQnIGluIGRlc2MgJiYgISgnb3JpZ2luYWxWYWx1ZScgaW4gZGVzYy5nZXQpKSB7XG5cdFx0XHRcdFx0dmFsdWUgPSBkZXNjLmdldDtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR2YWx1ZSA9IHZhbHVlW3BhcnRdO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpc093biA9IGhhc093bih2YWx1ZSwgcGFydCk7XG5cdFx0XHRcdHZhbHVlID0gdmFsdWVbcGFydF07XG5cdFx0XHR9XG5cblx0XHRcdGlmIChpc093biAmJiAhc2tpcEZ1cnRoZXJDYWNoaW5nKSB7XG5cdFx0XHRcdElOVFJJTlNJQ1NbaW50cmluc2ljUmVhbE5hbWVdID0gdmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHJldHVybiB2YWx1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBvcmlnU3ltYm9sID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sO1xudmFyIGhhc1N5bWJvbFNoYW0gPSByZXF1aXJlKCcuL3NoYW1zJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFzTmF0aXZlU3ltYm9scygpIHtcblx0aWYgKHR5cGVvZiBvcmlnU3ltYm9sICE9PSAnZnVuY3Rpb24nKSB7IHJldHVybiBmYWxzZTsgfVxuXHRpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ2Z1bmN0aW9uJykgeyByZXR1cm4gZmFsc2U7IH1cblx0aWYgKHR5cGVvZiBvcmlnU3ltYm9sKCdmb28nKSAhPT0gJ3N5bWJvbCcpIHsgcmV0dXJuIGZhbHNlOyB9XG5cdGlmICh0eXBlb2YgU3ltYm9sKCdiYXInKSAhPT0gJ3N5bWJvbCcpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0cmV0dXJuIGhhc1N5bWJvbFNoYW0oKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qIGVzbGludCBjb21wbGV4aXR5OiBbMiwgMThdLCBtYXgtc3RhdGVtZW50czogWzIsIDMzXSAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYXNTeW1ib2xzKCkge1xuXHRpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAhPT0gJ2Z1bmN0aW9uJykgeyByZXR1cm4gZmFsc2U7IH1cblx0aWYgKHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09ICdzeW1ib2wnKSB7IHJldHVybiB0cnVlOyB9XG5cblx0dmFyIG9iaiA9IHt9O1xuXHR2YXIgc3ltID0gU3ltYm9sKCd0ZXN0Jyk7XG5cdHZhciBzeW1PYmogPSBPYmplY3Qoc3ltKTtcblx0aWYgKHR5cGVvZiBzeW0gPT09ICdzdHJpbmcnKSB7IHJldHVybiBmYWxzZTsgfVxuXG5cdGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc3ltKSAhPT0gJ1tvYmplY3QgU3ltYm9sXScpIHsgcmV0dXJuIGZhbHNlOyB9XG5cdGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc3ltT2JqKSAhPT0gJ1tvYmplY3QgU3ltYm9sXScpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0Ly8gdGVtcCBkaXNhYmxlZCBwZXIgaHR0cHM6Ly9naXRodWIuY29tL2xqaGFyYi9vYmplY3QuYXNzaWduL2lzc3Vlcy8xN1xuXHQvLyBpZiAoc3ltIGluc3RhbmNlb2YgU3ltYm9sKSB7IHJldHVybiBmYWxzZTsgfVxuXHQvLyB0ZW1wIGRpc2FibGVkIHBlciBodHRwczovL2dpdGh1Yi5jb20vV2ViUmVmbGVjdGlvbi9nZXQtb3duLXByb3BlcnR5LXN5bWJvbHMvaXNzdWVzLzRcblx0Ly8gaWYgKCEoc3ltT2JqIGluc3RhbmNlb2YgU3ltYm9sKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHQvLyBpZiAodHlwZW9mIFN5bWJvbC5wcm90b3R5cGUudG9TdHJpbmcgIT09ICdmdW5jdGlvbicpIHsgcmV0dXJuIGZhbHNlOyB9XG5cdC8vIGlmIChTdHJpbmcoc3ltKSAhPT0gU3ltYm9sLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHN5bSkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0dmFyIHN5bVZhbCA9IDQyO1xuXHRvYmpbc3ltXSA9IHN5bVZhbDtcblx0Zm9yIChzeW0gaW4gb2JqKSB7IHJldHVybiBmYWxzZTsgfSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXJlc3RyaWN0ZWQtc3ludGF4LCBuby11bnJlYWNoYWJsZS1sb29wXG5cdGlmICh0eXBlb2YgT2JqZWN0LmtleXMgPT09ICdmdW5jdGlvbicgJiYgT2JqZWN0LmtleXMob2JqKS5sZW5ndGggIT09IDApIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0aWYgKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyA9PT0gJ2Z1bmN0aW9uJyAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopLmxlbmd0aCAhPT0gMCkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHR2YXIgc3ltcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqKTtcblx0aWYgKHN5bXMubGVuZ3RoICE9PSAxIHx8IHN5bXNbMF0gIT09IHN5bSkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHRpZiAoIU9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIHN5bSkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0aWYgKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0dmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iaiwgc3ltKTtcblx0XHRpZiAoZGVzY3JpcHRvci52YWx1ZSAhPT0gc3ltVmFsIHx8IGRlc2NyaXB0b3IuZW51bWVyYWJsZSAhPT0gdHJ1ZSkgeyByZXR1cm4gZmFsc2U7IH1cblx0fVxuXG5cdHJldHVybiB0cnVlO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGJpbmQgPSByZXF1aXJlKCdmdW5jdGlvbi1iaW5kJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gYmluZC5jYWxsKEZ1bmN0aW9uLmNhbGwsIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkpO1xuIiwiLyohXG4gKiBpbWFnZXNMb2FkZWQgdjQuMS40XG4gKiBKYXZhU2NyaXB0IGlzIGFsbCBsaWtlIFwiWW91IGltYWdlcyBhcmUgZG9uZSB5ZXQgb3Igd2hhdD9cIlxuICogTUlUIExpY2Vuc2VcbiAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7ICd1c2Ugc3RyaWN0JztcbiAgLy8gdW5pdmVyc2FsIG1vZHVsZSBkZWZpbml0aW9uXG5cbiAgLypnbG9iYWwgZGVmaW5lOiBmYWxzZSwgbW9kdWxlOiBmYWxzZSwgcmVxdWlyZTogZmFsc2UgKi9cblxuICBpZiAoIHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kICkge1xuICAgIC8vIEFNRFxuICAgIGRlZmluZSggW1xuICAgICAgJ2V2LWVtaXR0ZXIvZXYtZW1pdHRlcidcbiAgICBdLCBmdW5jdGlvbiggRXZFbWl0dGVyICkge1xuICAgICAgcmV0dXJuIGZhY3RvcnkoIHdpbmRvdywgRXZFbWl0dGVyICk7XG4gICAgfSk7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICByZXF1aXJlKCdldi1lbWl0dGVyJylcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmltYWdlc0xvYWRlZCA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICB3aW5kb3cuRXZFbWl0dGVyXG4gICAgKTtcbiAgfVxuXG59KSggdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLFxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgZmFjdG9yeSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5mdW5jdGlvbiBmYWN0b3J5KCB3aW5kb3csIEV2RW1pdHRlciApIHtcblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgJCA9IHdpbmRvdy5qUXVlcnk7XG52YXIgY29uc29sZSA9IHdpbmRvdy5jb25zb2xlO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBoZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8vIGV4dGVuZCBvYmplY3RzXG5mdW5jdGlvbiBleHRlbmQoIGEsIGIgKSB7XG4gIGZvciAoIHZhciBwcm9wIGluIGIgKSB7XG4gICAgYVsgcHJvcCBdID0gYlsgcHJvcCBdO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG52YXIgYXJyYXlTbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuLy8gdHVybiBlbGVtZW50IG9yIG5vZGVMaXN0IGludG8gYW4gYXJyYXlcbmZ1bmN0aW9uIG1ha2VBcnJheSggb2JqICkge1xuICBpZiAoIEFycmF5LmlzQXJyYXkoIG9iaiApICkge1xuICAgIC8vIHVzZSBvYmplY3QgaWYgYWxyZWFkeSBhbiBhcnJheVxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICB2YXIgaXNBcnJheUxpa2UgPSB0eXBlb2Ygb2JqID09ICdvYmplY3QnICYmIHR5cGVvZiBvYmoubGVuZ3RoID09ICdudW1iZXInO1xuICBpZiAoIGlzQXJyYXlMaWtlICkge1xuICAgIC8vIGNvbnZlcnQgbm9kZUxpc3QgdG8gYXJyYXlcbiAgICByZXR1cm4gYXJyYXlTbGljZS5jYWxsKCBvYmogKTtcbiAgfVxuXG4gIC8vIGFycmF5IG9mIHNpbmdsZSBpbmRleFxuICByZXR1cm4gWyBvYmogXTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaW1hZ2VzTG9hZGVkIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8qKlxuICogQHBhcmFtIHtBcnJheSwgRWxlbWVudCwgTm9kZUxpc3QsIFN0cmluZ30gZWxlbVxuICogQHBhcmFtIHtPYmplY3Qgb3IgRnVuY3Rpb259IG9wdGlvbnMgLSBpZiBmdW5jdGlvbiwgdXNlIGFzIGNhbGxiYWNrXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBvbkFsd2F5cyAtIGNhbGxiYWNrIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIEltYWdlc0xvYWRlZCggZWxlbSwgb3B0aW9ucywgb25BbHdheXMgKSB7XG4gIC8vIGNvZXJjZSBJbWFnZXNMb2FkZWQoKSB3aXRob3V0IG5ldywgdG8gYmUgbmV3IEltYWdlc0xvYWRlZCgpXG4gIGlmICggISggdGhpcyBpbnN0YW5jZW9mIEltYWdlc0xvYWRlZCApICkge1xuICAgIHJldHVybiBuZXcgSW1hZ2VzTG9hZGVkKCBlbGVtLCBvcHRpb25zLCBvbkFsd2F5cyApO1xuICB9XG4gIC8vIHVzZSBlbGVtIGFzIHNlbGVjdG9yIHN0cmluZ1xuICB2YXIgcXVlcnlFbGVtID0gZWxlbTtcbiAgaWYgKCB0eXBlb2YgZWxlbSA9PSAnc3RyaW5nJyApIHtcbiAgICBxdWVyeUVsZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCBlbGVtICk7XG4gIH1cbiAgLy8gYmFpbCBpZiBiYWQgZWxlbWVudFxuICBpZiAoICFxdWVyeUVsZW0gKSB7XG4gICAgY29uc29sZS5lcnJvciggJ0JhZCBlbGVtZW50IGZvciBpbWFnZXNMb2FkZWQgJyArICggcXVlcnlFbGVtIHx8IGVsZW0gKSApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRoaXMuZWxlbWVudHMgPSBtYWtlQXJyYXkoIHF1ZXJ5RWxlbSApO1xuICB0aGlzLm9wdGlvbnMgPSBleHRlbmQoIHt9LCB0aGlzLm9wdGlvbnMgKTtcbiAgLy8gc2hpZnQgYXJndW1lbnRzIGlmIG5vIG9wdGlvbnMgc2V0XG4gIGlmICggdHlwZW9mIG9wdGlvbnMgPT0gJ2Z1bmN0aW9uJyApIHtcbiAgICBvbkFsd2F5cyA9IG9wdGlvbnM7XG4gIH0gZWxzZSB7XG4gICAgZXh0ZW5kKCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMgKTtcbiAgfVxuXG4gIGlmICggb25BbHdheXMgKSB7XG4gICAgdGhpcy5vbiggJ2Fsd2F5cycsIG9uQWx3YXlzICk7XG4gIH1cblxuICB0aGlzLmdldEltYWdlcygpO1xuXG4gIGlmICggJCApIHtcbiAgICAvLyBhZGQgalF1ZXJ5IERlZmVycmVkIG9iamVjdFxuICAgIHRoaXMuanFEZWZlcnJlZCA9IG5ldyAkLkRlZmVycmVkKCk7XG4gIH1cblxuICAvLyBIQUNLIGNoZWNrIGFzeW5jIHRvIGFsbG93IHRpbWUgdG8gYmluZCBsaXN0ZW5lcnNcbiAgc2V0VGltZW91dCggdGhpcy5jaGVjay5iaW5kKCB0aGlzICkgKTtcbn1cblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoIEV2RW1pdHRlci5wcm90b3R5cGUgKTtcblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5vcHRpb25zID0ge307XG5cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuZ2V0SW1hZ2VzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuaW1hZ2VzID0gW107XG5cbiAgLy8gZmlsdGVyICYgZmluZCBpdGVtcyBpZiB3ZSBoYXZlIGFuIGl0ZW0gc2VsZWN0b3JcbiAgdGhpcy5lbGVtZW50cy5mb3JFYWNoKCB0aGlzLmFkZEVsZW1lbnRJbWFnZXMsIHRoaXMgKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlfSBlbGVtZW50XG4gKi9cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkRWxlbWVudEltYWdlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuICAvLyBmaWx0ZXIgc2libGluZ3NcbiAgaWYgKCBlbGVtLm5vZGVOYW1lID09ICdJTUcnICkge1xuICAgIHRoaXMuYWRkSW1hZ2UoIGVsZW0gKTtcbiAgfVxuICAvLyBnZXQgYmFja2dyb3VuZCBpbWFnZSBvbiBlbGVtZW50XG4gIGlmICggdGhpcy5vcHRpb25zLmJhY2tncm91bmQgPT09IHRydWUgKSB7XG4gICAgdGhpcy5hZGRFbGVtZW50QmFja2dyb3VuZEltYWdlcyggZWxlbSApO1xuICB9XG5cbiAgLy8gZmluZCBjaGlsZHJlblxuICAvLyBubyBub24tZWxlbWVudCBub2RlcywgIzE0M1xuICB2YXIgbm9kZVR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuICBpZiAoICFub2RlVHlwZSB8fCAhZWxlbWVudE5vZGVUeXBlc1sgbm9kZVR5cGUgXSApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGNoaWxkSW1ncyA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCgnaW1nJyk7XG4gIC8vIGNvbmNhdCBjaGlsZEVsZW1zIHRvIGZpbHRlckZvdW5kIGFycmF5XG4gIGZvciAoIHZhciBpPTA7IGkgPCBjaGlsZEltZ3MubGVuZ3RoOyBpKysgKSB7XG4gICAgdmFyIGltZyA9IGNoaWxkSW1nc1tpXTtcbiAgICB0aGlzLmFkZEltYWdlKCBpbWcgKTtcbiAgfVxuXG4gIC8vIGdldCBjaGlsZCBiYWNrZ3JvdW5kIGltYWdlc1xuICBpZiAoIHR5cGVvZiB0aGlzLm9wdGlvbnMuYmFja2dyb3VuZCA9PSAnc3RyaW5nJyApIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoIHRoaXMub3B0aW9ucy5iYWNrZ3JvdW5kICk7XG4gICAgZm9yICggaT0wOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKysgKSB7XG4gICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgIHRoaXMuYWRkRWxlbWVudEJhY2tncm91bmRJbWFnZXMoIGNoaWxkICk7XG4gICAgfVxuICB9XG59O1xuXG52YXIgZWxlbWVudE5vZGVUeXBlcyA9IHtcbiAgMTogdHJ1ZSxcbiAgOTogdHJ1ZSxcbiAgMTE6IHRydWVcbn07XG5cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkRWxlbWVudEJhY2tncm91bmRJbWFnZXMgPSBmdW5jdGlvbiggZWxlbSApIHtcbiAgdmFyIHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZSggZWxlbSApO1xuICBpZiAoICFzdHlsZSApIHtcbiAgICAvLyBGaXJlZm94IHJldHVybnMgbnVsbCBpZiBpbiBhIGhpZGRlbiBpZnJhbWUgaHR0cHM6Ly9idWd6aWwubGEvNTQ4Mzk3XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIGdldCB1cmwgaW5zaWRlIHVybChcIi4uLlwiKVxuICB2YXIgcmVVUkwgPSAvdXJsXFwoKFsnXCJdKT8oLio/KVxcMVxcKS9naTtcbiAgdmFyIG1hdGNoZXMgPSByZVVSTC5leGVjKCBzdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgKTtcbiAgd2hpbGUgKCBtYXRjaGVzICE9PSBudWxsICkge1xuICAgIHZhciB1cmwgPSBtYXRjaGVzICYmIG1hdGNoZXNbMl07XG4gICAgaWYgKCB1cmwgKSB7XG4gICAgICB0aGlzLmFkZEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICAgIH1cbiAgICBtYXRjaGVzID0gcmVVUkwuZXhlYyggc3R5bGUuYmFja2dyb3VuZEltYWdlICk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtJbWFnZX0gaW1nXG4gKi9cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkSW1hZ2UgPSBmdW5jdGlvbiggaW1nICkge1xuICB2YXIgbG9hZGluZ0ltYWdlID0gbmV3IExvYWRpbmdJbWFnZSggaW1nICk7XG4gIHRoaXMuaW1hZ2VzLnB1c2goIGxvYWRpbmdJbWFnZSApO1xufTtcblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5hZGRCYWNrZ3JvdW5kID0gZnVuY3Rpb24oIHVybCwgZWxlbSApIHtcbiAgdmFyIGJhY2tncm91bmQgPSBuZXcgQmFja2dyb3VuZCggdXJsLCBlbGVtICk7XG4gIHRoaXMuaW1hZ2VzLnB1c2goIGJhY2tncm91bmQgKTtcbn07XG5cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuY2hlY2sgPSBmdW5jdGlvbigpIHtcbiAgdmFyIF90aGlzID0gdGhpcztcbiAgdGhpcy5wcm9ncmVzc2VkQ291bnQgPSAwO1xuICB0aGlzLmhhc0FueUJyb2tlbiA9IGZhbHNlO1xuICAvLyBjb21wbGV0ZSBpZiBubyBpbWFnZXNcbiAgaWYgKCAhdGhpcy5pbWFnZXMubGVuZ3RoICkge1xuICAgIHRoaXMuY29tcGxldGUoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBmdW5jdGlvbiBvblByb2dyZXNzKCBpbWFnZSwgZWxlbSwgbWVzc2FnZSApIHtcbiAgICAvLyBIQUNLIC0gQ2hyb21lIHRyaWdnZXJzIGV2ZW50IGJlZm9yZSBvYmplY3QgcHJvcGVydGllcyBoYXZlIGNoYW5nZWQuICM4M1xuICAgIHNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuICAgICAgX3RoaXMucHJvZ3Jlc3MoIGltYWdlLCBlbGVtLCBtZXNzYWdlICk7XG4gICAgfSk7XG4gIH1cblxuICB0aGlzLmltYWdlcy5mb3JFYWNoKCBmdW5jdGlvbiggbG9hZGluZ0ltYWdlICkge1xuICAgIGxvYWRpbmdJbWFnZS5vbmNlKCAncHJvZ3Jlc3MnLCBvblByb2dyZXNzICk7XG4gICAgbG9hZGluZ0ltYWdlLmNoZWNrKCk7XG4gIH0pO1xufTtcblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5wcm9ncmVzcyA9IGZ1bmN0aW9uKCBpbWFnZSwgZWxlbSwgbWVzc2FnZSApIHtcbiAgdGhpcy5wcm9ncmVzc2VkQ291bnQrKztcbiAgdGhpcy5oYXNBbnlCcm9rZW4gPSB0aGlzLmhhc0FueUJyb2tlbiB8fCAhaW1hZ2UuaXNMb2FkZWQ7XG4gIC8vIHByb2dyZXNzIGV2ZW50XG4gIHRoaXMuZW1pdEV2ZW50KCAncHJvZ3Jlc3MnLCBbIHRoaXMsIGltYWdlLCBlbGVtIF0gKTtcbiAgaWYgKCB0aGlzLmpxRGVmZXJyZWQgJiYgdGhpcy5qcURlZmVycmVkLm5vdGlmeSApIHtcbiAgICB0aGlzLmpxRGVmZXJyZWQubm90aWZ5KCB0aGlzLCBpbWFnZSApO1xuICB9XG4gIC8vIGNoZWNrIGlmIGNvbXBsZXRlZFxuICBpZiAoIHRoaXMucHJvZ3Jlc3NlZENvdW50ID09IHRoaXMuaW1hZ2VzLmxlbmd0aCApIHtcbiAgICB0aGlzLmNvbXBsZXRlKCk7XG4gIH1cblxuICBpZiAoIHRoaXMub3B0aW9ucy5kZWJ1ZyAmJiBjb25zb2xlICkge1xuICAgIGNvbnNvbGUubG9nKCAncHJvZ3Jlc3M6ICcgKyBtZXNzYWdlLCBpbWFnZSwgZWxlbSApO1xuICB9XG59O1xuXG5JbWFnZXNMb2FkZWQucHJvdG90eXBlLmNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gIHZhciBldmVudE5hbWUgPSB0aGlzLmhhc0FueUJyb2tlbiA/ICdmYWlsJyA6ICdkb25lJztcbiAgdGhpcy5pc0NvbXBsZXRlID0gdHJ1ZTtcbiAgdGhpcy5lbWl0RXZlbnQoIGV2ZW50TmFtZSwgWyB0aGlzIF0gKTtcbiAgdGhpcy5lbWl0RXZlbnQoICdhbHdheXMnLCBbIHRoaXMgXSApO1xuICBpZiAoIHRoaXMuanFEZWZlcnJlZCApIHtcbiAgICB2YXIganFNZXRob2QgPSB0aGlzLmhhc0FueUJyb2tlbiA/ICdyZWplY3QnIDogJ3Jlc29sdmUnO1xuICAgIHRoaXMuanFEZWZlcnJlZFsganFNZXRob2QgXSggdGhpcyApO1xuICB9XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuZnVuY3Rpb24gTG9hZGluZ0ltYWdlKCBpbWcgKSB7XG4gIHRoaXMuaW1nID0gaW1nO1xufVxuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSggRXZFbWl0dGVyLnByb3RvdHlwZSApO1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gIC8vIElmIGNvbXBsZXRlIGlzIHRydWUgYW5kIGJyb3dzZXIgc3VwcG9ydHMgbmF0dXJhbCBzaXplcyxcbiAgLy8gdHJ5IHRvIGNoZWNrIGZvciBpbWFnZSBzdGF0dXMgbWFudWFsbHkuXG4gIHZhciBpc0NvbXBsZXRlID0gdGhpcy5nZXRJc0ltYWdlQ29tcGxldGUoKTtcbiAgaWYgKCBpc0NvbXBsZXRlICkge1xuICAgIC8vIHJlcG9ydCBiYXNlZCBvbiBuYXR1cmFsV2lkdGhcbiAgICB0aGlzLmNvbmZpcm0oIHRoaXMuaW1nLm5hdHVyYWxXaWR0aCAhPT0gMCwgJ25hdHVyYWxXaWR0aCcgKTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJZiBub25lIG9mIHRoZSBjaGVja3MgYWJvdmUgbWF0Y2hlZCwgc2ltdWxhdGUgbG9hZGluZyBvbiBkZXRhY2hlZCBlbGVtZW50LlxuICB0aGlzLnByb3h5SW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgdGhpcy5wcm94eUltYWdlLmFkZEV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLnByb3h5SW1hZ2UuYWRkRXZlbnRMaXN0ZW5lciggJ2Vycm9yJywgdGhpcyApO1xuICAvLyBiaW5kIHRvIGltYWdlIGFzIHdlbGwgZm9yIEZpcmVmb3guICMxOTFcbiAgdGhpcy5pbWcuYWRkRXZlbnRMaXN0ZW5lciggJ2xvYWQnLCB0aGlzICk7XG4gIHRoaXMuaW1nLmFkZEV2ZW50TGlzdGVuZXIoICdlcnJvcicsIHRoaXMgKTtcbiAgdGhpcy5wcm94eUltYWdlLnNyYyA9IHRoaXMuaW1nLnNyYztcbn07XG5cbkxvYWRpbmdJbWFnZS5wcm90b3R5cGUuZ2V0SXNJbWFnZUNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gIC8vIGNoZWNrIGZvciBub24temVybywgbm9uLXVuZGVmaW5lZCBuYXR1cmFsV2lkdGhcbiAgLy8gZml4ZXMgU2FmYXJpK0luZmluaXRlU2Nyb2xsK01hc29ucnkgYnVnIGluZmluaXRlLXNjcm9sbCM2NzFcbiAgcmV0dXJuIHRoaXMuaW1nLmNvbXBsZXRlICYmIHRoaXMuaW1nLm5hdHVyYWxXaWR0aDtcbn07XG5cbkxvYWRpbmdJbWFnZS5wcm90b3R5cGUuY29uZmlybSA9IGZ1bmN0aW9uKCBpc0xvYWRlZCwgbWVzc2FnZSApIHtcbiAgdGhpcy5pc0xvYWRlZCA9IGlzTG9hZGVkO1xuICB0aGlzLmVtaXRFdmVudCggJ3Byb2dyZXNzJywgWyB0aGlzLCB0aGlzLmltZywgbWVzc2FnZSBdICk7XG59O1xuXG4vLyAtLS0tLSBldmVudHMgLS0tLS0gLy9cblxuLy8gdHJpZ2dlciBzcGVjaWZpZWQgaGFuZGxlciBmb3IgZXZlbnQgdHlwZVxuTG9hZGluZ0ltYWdlLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdmFyIG1ldGhvZCA9ICdvbicgKyBldmVudC50eXBlO1xuICBpZiAoIHRoaXNbIG1ldGhvZCBdICkge1xuICAgIHRoaXNbIG1ldGhvZCBdKCBldmVudCApO1xuICB9XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmNvbmZpcm0oIHRydWUsICdvbmxvYWQnICk7XG4gIHRoaXMudW5iaW5kRXZlbnRzKCk7XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5jb25maXJtKCBmYWxzZSwgJ29uZXJyb3InICk7XG4gIHRoaXMudW5iaW5kRXZlbnRzKCk7XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLnVuYmluZEV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnByb3h5SW1hZ2UucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2xvYWQnLCB0aGlzICk7XG4gIHRoaXMucHJveHlJbWFnZS5yZW1vdmVFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG4gIHRoaXMuaW1nLnJlbW92ZUV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLmltZy5yZW1vdmVFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBCYWNrZ3JvdW5kIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIEJhY2tncm91bmQoIHVybCwgZWxlbWVudCApIHtcbiAgdGhpcy51cmwgPSB1cmw7XG4gIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gIHRoaXMuaW1nID0gbmV3IEltYWdlKCk7XG59XG5cbi8vIGluaGVyaXQgTG9hZGluZ0ltYWdlIHByb3RvdHlwZVxuQmFja2dyb3VuZC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKCBMb2FkaW5nSW1hZ2UucHJvdG90eXBlICk7XG5cbkJhY2tncm91bmQucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuaW1nLmFkZEV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLmltZy5hZGRFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG4gIHRoaXMuaW1nLnNyYyA9IHRoaXMudXJsO1xuICAvLyBjaGVjayBpZiBpbWFnZSBpcyBhbHJlYWR5IGNvbXBsZXRlXG4gIHZhciBpc0NvbXBsZXRlID0gdGhpcy5nZXRJc0ltYWdlQ29tcGxldGUoKTtcbiAgaWYgKCBpc0NvbXBsZXRlICkge1xuICAgIHRoaXMuY29uZmlybSggdGhpcy5pbWcubmF0dXJhbFdpZHRoICE9PSAwLCAnbmF0dXJhbFdpZHRoJyApO1xuICAgIHRoaXMudW5iaW5kRXZlbnRzKCk7XG4gIH1cbn07XG5cbkJhY2tncm91bmQucHJvdG90eXBlLnVuYmluZEV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmltZy5yZW1vdmVFdmVudExpc3RlbmVyKCAnbG9hZCcsIHRoaXMgKTtcbiAgdGhpcy5pbWcucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2Vycm9yJywgdGhpcyApO1xufTtcblxuQmFja2dyb3VuZC5wcm90b3R5cGUuY29uZmlybSA9IGZ1bmN0aW9uKCBpc0xvYWRlZCwgbWVzc2FnZSApIHtcbiAgdGhpcy5pc0xvYWRlZCA9IGlzTG9hZGVkO1xuICB0aGlzLmVtaXRFdmVudCggJ3Byb2dyZXNzJywgWyB0aGlzLCB0aGlzLmVsZW1lbnQsIG1lc3NhZ2UgXSApO1xufTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0galF1ZXJ5IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbkltYWdlc0xvYWRlZC5tYWtlSlF1ZXJ5UGx1Z2luID0gZnVuY3Rpb24oIGpRdWVyeSApIHtcbiAgalF1ZXJ5ID0galF1ZXJ5IHx8IHdpbmRvdy5qUXVlcnk7XG4gIGlmICggIWpRdWVyeSApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gc2V0IGxvY2FsIHZhcmlhYmxlXG4gICQgPSBqUXVlcnk7XG4gIC8vICQoKS5pbWFnZXNMb2FkZWQoKVxuICAkLmZuLmltYWdlc0xvYWRlZCA9IGZ1bmN0aW9uKCBvcHRpb25zLCBjYWxsYmFjayApIHtcbiAgICB2YXIgaW5zdGFuY2UgPSBuZXcgSW1hZ2VzTG9hZGVkKCB0aGlzLCBvcHRpb25zLCBjYWxsYmFjayApO1xuICAgIHJldHVybiBpbnN0YW5jZS5qcURlZmVycmVkLnByb21pc2UoICQodGhpcykgKTtcbiAgfTtcbn07XG4vLyB0cnkgbWFraW5nIHBsdWdpblxuSW1hZ2VzTG9hZGVkLm1ha2VKUXVlcnlQbHVnaW4oKTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbnJldHVybiBJbWFnZXNMb2FkZWQ7XG5cbn0pO1xuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogTG9kYXNoIDxodHRwczovL2xvZGFzaC5jb20vPlxuICogQ29weXJpZ2h0IE9wZW5KUyBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnMgPGh0dHBzOi8vb3BlbmpzZi5vcmcvPlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICogQmFzZWQgb24gVW5kZXJzY29yZS5qcyAxLjguMyA8aHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvTElDRU5TRT5cbiAqIENvcHlyaWdodCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICovXG47KGZ1bmN0aW9uKCkge1xuXG4gIC8qKiBVc2VkIGFzIGEgc2FmZSByZWZlcmVuY2UgZm9yIGB1bmRlZmluZWRgIGluIHByZS1FUzUgZW52aXJvbm1lbnRzLiAqL1xuICB2YXIgdW5kZWZpbmVkO1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlci4gKi9cbiAgdmFyIFZFUlNJT04gPSAnNC4xNy4yMSc7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIHNpemUgdG8gZW5hYmxlIGxhcmdlIGFycmF5IG9wdGltaXphdGlvbnMuICovXG4gIHZhciBMQVJHRV9BUlJBWV9TSVpFID0gMjAwO1xuXG4gIC8qKiBFcnJvciBtZXNzYWdlIGNvbnN0YW50cy4gKi9cbiAgdmFyIENPUkVfRVJST1JfVEVYVCA9ICdVbnN1cHBvcnRlZCBjb3JlLWpzIHVzZS4gVHJ5IGh0dHBzOi8vbnBtcy5pby9zZWFyY2g/cT1wb255ZmlsbC4nLFxuICAgICAgRlVOQ19FUlJPUl9URVhUID0gJ0V4cGVjdGVkIGEgZnVuY3Rpb24nLFxuICAgICAgSU5WQUxJRF9URU1QTF9WQVJfRVJST1JfVEVYVCA9ICdJbnZhbGlkIGB2YXJpYWJsZWAgb3B0aW9uIHBhc3NlZCBpbnRvIGBfLnRlbXBsYXRlYCc7XG5cbiAgLyoqIFVzZWQgdG8gc3RhbmQtaW4gZm9yIGB1bmRlZmluZWRgIGhhc2ggdmFsdWVzLiAqL1xuICB2YXIgSEFTSF9VTkRFRklORUQgPSAnX19sb2Rhc2hfaGFzaF91bmRlZmluZWRfXyc7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIG1heGltdW0gbWVtb2l6ZSBjYWNoZSBzaXplLiAqL1xuICB2YXIgTUFYX01FTU9JWkVfU0laRSA9IDUwMDtcblxuICAvKiogVXNlZCBhcyB0aGUgaW50ZXJuYWwgYXJndW1lbnQgcGxhY2Vob2xkZXIuICovXG4gIHZhciBQTEFDRUhPTERFUiA9ICdfX2xvZGFzaF9wbGFjZWhvbGRlcl9fJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciBjbG9uaW5nLiAqL1xuICB2YXIgQ0xPTkVfREVFUF9GTEFHID0gMSxcbiAgICAgIENMT05FX0ZMQVRfRkxBRyA9IDIsXG4gICAgICBDTE9ORV9TWU1CT0xTX0ZMQUcgPSA0O1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHZhbHVlIGNvbXBhcmlzb25zLiAqL1xuICB2YXIgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgPSAxLFxuICAgICAgQ09NUEFSRV9VTk9SREVSRURfRkxBRyA9IDI7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgZnVuY3Rpb24gbWV0YWRhdGEuICovXG4gIHZhciBXUkFQX0JJTkRfRkxBRyA9IDEsXG4gICAgICBXUkFQX0JJTkRfS0VZX0ZMQUcgPSAyLFxuICAgICAgV1JBUF9DVVJSWV9CT1VORF9GTEFHID0gNCxcbiAgICAgIFdSQVBfQ1VSUllfRkxBRyA9IDgsXG4gICAgICBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcgPSAxNixcbiAgICAgIFdSQVBfUEFSVElBTF9GTEFHID0gMzIsXG4gICAgICBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyA9IDY0LFxuICAgICAgV1JBUF9BUllfRkxBRyA9IDEyOCxcbiAgICAgIFdSQVBfUkVBUkdfRkxBRyA9IDI1NixcbiAgICAgIFdSQVBfRkxJUF9GTEFHID0gNTEyO1xuXG4gIC8qKiBVc2VkIGFzIGRlZmF1bHQgb3B0aW9ucyBmb3IgYF8udHJ1bmNhdGVgLiAqL1xuICB2YXIgREVGQVVMVF9UUlVOQ19MRU5HVEggPSAzMCxcbiAgICAgIERFRkFVTFRfVFJVTkNfT01JU1NJT04gPSAnLi4uJztcblxuICAvKiogVXNlZCB0byBkZXRlY3QgaG90IGZ1bmN0aW9ucyBieSBudW1iZXIgb2YgY2FsbHMgd2l0aGluIGEgc3BhbiBvZiBtaWxsaXNlY29uZHMuICovXG4gIHZhciBIT1RfQ09VTlQgPSA4MDAsXG4gICAgICBIT1RfU1BBTiA9IDE2O1xuXG4gIC8qKiBVc2VkIHRvIGluZGljYXRlIHRoZSB0eXBlIG9mIGxhenkgaXRlcmF0ZWVzLiAqL1xuICB2YXIgTEFaWV9GSUxURVJfRkxBRyA9IDEsXG4gICAgICBMQVpZX01BUF9GTEFHID0gMixcbiAgICAgIExBWllfV0hJTEVfRkxBRyA9IDM7XG5cbiAgLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG4gIHZhciBJTkZJTklUWSA9IDEgLyAwLFxuICAgICAgTUFYX1NBRkVfSU5URUdFUiA9IDkwMDcxOTkyNTQ3NDA5OTEsXG4gICAgICBNQVhfSU5URUdFUiA9IDEuNzk3NjkzMTM0ODYyMzE1N2UrMzA4LFxuICAgICAgTkFOID0gMCAvIDA7XG5cbiAgLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdGhlIG1heGltdW0gbGVuZ3RoIGFuZCBpbmRleCBvZiBhbiBhcnJheS4gKi9cbiAgdmFyIE1BWF9BUlJBWV9MRU5HVEggPSA0Mjk0OTY3Mjk1LFxuICAgICAgTUFYX0FSUkFZX0lOREVYID0gTUFYX0FSUkFZX0xFTkdUSCAtIDEsXG4gICAgICBIQUxGX01BWF9BUlJBWV9MRU5HVEggPSBNQVhfQVJSQVlfTEVOR1RIID4+PiAxO1xuXG4gIC8qKiBVc2VkIHRvIGFzc29jaWF0ZSB3cmFwIG1ldGhvZHMgd2l0aCB0aGVpciBiaXQgZmxhZ3MuICovXG4gIHZhciB3cmFwRmxhZ3MgPSBbXG4gICAgWydhcnknLCBXUkFQX0FSWV9GTEFHXSxcbiAgICBbJ2JpbmQnLCBXUkFQX0JJTkRfRkxBR10sXG4gICAgWydiaW5kS2V5JywgV1JBUF9CSU5EX0tFWV9GTEFHXSxcbiAgICBbJ2N1cnJ5JywgV1JBUF9DVVJSWV9GTEFHXSxcbiAgICBbJ2N1cnJ5UmlnaHQnLCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUddLFxuICAgIFsnZmxpcCcsIFdSQVBfRkxJUF9GTEFHXSxcbiAgICBbJ3BhcnRpYWwnLCBXUkFQX1BBUlRJQUxfRkxBR10sXG4gICAgWydwYXJ0aWFsUmlnaHQnLCBXUkFQX1BBUlRJQUxfUklHSFRfRkxBR10sXG4gICAgWydyZWFyZycsIFdSQVBfUkVBUkdfRkxBR11cbiAgXTtcblxuICAvKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG4gIHZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgICBhc3luY1RhZyA9ICdbb2JqZWN0IEFzeW5jRnVuY3Rpb25dJyxcbiAgICAgIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgICBkYXRlVGFnID0gJ1tvYmplY3QgRGF0ZV0nLFxuICAgICAgZG9tRXhjVGFnID0gJ1tvYmplY3QgRE9NRXhjZXB0aW9uXScsXG4gICAgICBlcnJvclRhZyA9ICdbb2JqZWN0IEVycm9yXScsXG4gICAgICBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICAgIGdlblRhZyA9ICdbb2JqZWN0IEdlbmVyYXRvckZ1bmN0aW9uXScsXG4gICAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgICAgbnVsbFRhZyA9ICdbb2JqZWN0IE51bGxdJyxcbiAgICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgICAgcHJvbWlzZVRhZyA9ICdbb2JqZWN0IFByb21pc2VdJyxcbiAgICAgIHByb3h5VGFnID0gJ1tvYmplY3QgUHJveHldJyxcbiAgICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICAgIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nLFxuICAgICAgdW5kZWZpbmVkVGFnID0gJ1tvYmplY3QgVW5kZWZpbmVkXScsXG4gICAgICB3ZWFrTWFwVGFnID0gJ1tvYmplY3QgV2Vha01hcF0nLFxuICAgICAgd2Vha1NldFRhZyA9ICdbb2JqZWN0IFdlYWtTZXRdJztcblxuICB2YXIgYXJyYXlCdWZmZXJUYWcgPSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nLFxuICAgICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nLFxuICAgICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGVtcHR5IHN0cmluZyBsaXRlcmFscyBpbiBjb21waWxlZCB0ZW1wbGF0ZSBzb3VyY2UuICovXG4gIHZhciByZUVtcHR5U3RyaW5nTGVhZGluZyA9IC9cXGJfX3AgXFwrPSAnJzsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdNaWRkbGUgPSAvXFxiKF9fcCBcXCs9KSAnJyBcXCsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdUcmFpbGluZyA9IC8oX19lXFwoLio/XFwpfFxcYl9fdFxcKSkgXFwrXFxuJyc7L2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggSFRNTCBlbnRpdGllcyBhbmQgSFRNTCBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgcmVFc2NhcGVkSHRtbCA9IC8mKD86YW1wfGx0fGd0fHF1b3R8IzM5KTsvZyxcbiAgICAgIHJlVW5lc2NhcGVkSHRtbCA9IC9bJjw+XCInXS9nLFxuICAgICAgcmVIYXNFc2NhcGVkSHRtbCA9IFJlZ0V4cChyZUVzY2FwZWRIdG1sLnNvdXJjZSksXG4gICAgICByZUhhc1VuZXNjYXBlZEh0bWwgPSBSZWdFeHAocmVVbmVzY2FwZWRIdG1sLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdGVtcGxhdGUgZGVsaW1pdGVycy4gKi9cbiAgdmFyIHJlRXNjYXBlID0gLzwlLShbXFxzXFxTXSs/KSU+L2csXG4gICAgICByZUV2YWx1YXRlID0gLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICAgIHJlSW50ZXJwb2xhdGUgPSAvPCU9KFtcXHNcXFNdKz8pJT4vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBwcm9wZXJ0eSBuYW1lcyB3aXRoaW4gcHJvcGVydHkgcGF0aHMuICovXG4gIHZhciByZUlzRGVlcFByb3AgPSAvXFwufFxcWyg/OlteW1xcXV0qfChbXCInXSkoPzooPyFcXDEpW15cXFxcXXxcXFxcLikqP1xcMSlcXF0vLFxuICAgICAgcmVJc1BsYWluUHJvcCA9IC9eXFx3KiQvLFxuICAgICAgcmVQcm9wTmFtZSA9IC9bXi5bXFxdXSt8XFxbKD86KC0/XFxkKyg/OlxcLlxcZCspPyl8KFtcIiddKSgoPzooPyFcXDIpW15cXFxcXXxcXFxcLikqPylcXDIpXFxdfCg/PSg/OlxcLnxcXFtcXF0pKD86XFwufFxcW1xcXXwkKSkvZztcblxuICAvKipcbiAgICogVXNlZCB0byBtYXRjaCBgUmVnRXhwYFxuICAgKiBbc3ludGF4IGNoYXJhY3RlcnNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXBhdHRlcm5zKS5cbiAgICovXG4gIHZhciByZVJlZ0V4cENoYXIgPSAvW1xcXFxeJC4qKz8oKVtcXF17fXxdL2csXG4gICAgICByZUhhc1JlZ0V4cENoYXIgPSBSZWdFeHAocmVSZWdFeHBDaGFyLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyB3aGl0ZXNwYWNlLiAqL1xuICB2YXIgcmVUcmltU3RhcnQgPSAvXlxccysvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGEgc2luZ2xlIHdoaXRlc3BhY2UgY2hhcmFjdGVyLiAqL1xuICB2YXIgcmVXaGl0ZXNwYWNlID0gL1xccy87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggd3JhcCBkZXRhaWwgY29tbWVudHMuICovXG4gIHZhciByZVdyYXBDb21tZW50ID0gL1xceyg/OlxcblxcL1xcKiBcXFt3cmFwcGVkIHdpdGggLitcXF0gXFwqXFwvKT9cXG4/LyxcbiAgICAgIHJlV3JhcERldGFpbHMgPSAvXFx7XFxuXFwvXFwqIFxcW3dyYXBwZWQgd2l0aCAoLispXFxdIFxcKi8sXG4gICAgICByZVNwbGl0RGV0YWlscyA9IC8sPyAmIC87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggd29yZHMgY29tcG9zZWQgb2YgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMuICovXG4gIHZhciByZUFzY2lpV29yZCA9IC9bXlxceDAwLVxceDJmXFx4M2EtXFx4NDBcXHg1Yi1cXHg2MFxceDdiLVxceDdmXSsvZztcblxuICAvKipcbiAgICogVXNlZCB0byB2YWxpZGF0ZSB0aGUgYHZhbGlkYXRlYCBvcHRpb24gaW4gYF8udGVtcGxhdGVgIHZhcmlhYmxlLlxuICAgKlxuICAgKiBGb3JiaWRzIGNoYXJhY3RlcnMgd2hpY2ggY291bGQgcG90ZW50aWFsbHkgY2hhbmdlIHRoZSBtZWFuaW5nIG9mIHRoZSBmdW5jdGlvbiBhcmd1bWVudCBkZWZpbml0aW9uOlxuICAgKiAtIFwiKCksXCIgKG1vZGlmaWNhdGlvbiBvZiBmdW5jdGlvbiBwYXJhbWV0ZXJzKVxuICAgKiAtIFwiPVwiIChkZWZhdWx0IHZhbHVlKVxuICAgKiAtIFwiW117fVwiIChkZXN0cnVjdHVyaW5nIG9mIGZ1bmN0aW9uIHBhcmFtZXRlcnMpXG4gICAqIC0gXCIvXCIgKGJlZ2lubmluZyBvZiBhIGNvbW1lbnQpXG4gICAqIC0gd2hpdGVzcGFjZVxuICAgKi9cbiAgdmFyIHJlRm9yYmlkZGVuSWRlbnRpZmllckNoYXJzID0gL1soKT0se31cXFtcXF1cXC9cXHNdLztcblxuICAvKiogVXNlZCB0byBtYXRjaCBiYWNrc2xhc2hlcyBpbiBwcm9wZXJ0eSBwYXRocy4gKi9cbiAgdmFyIHJlRXNjYXBlQ2hhciA9IC9cXFxcKFxcXFwpPy9nO1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIG1hdGNoXG4gICAqIFtFUyB0ZW1wbGF0ZSBkZWxpbWl0ZXJzXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy10ZW1wbGF0ZS1saXRlcmFsLWxleGljYWwtY29tcG9uZW50cykuXG4gICAqL1xuICB2YXIgcmVFc1RlbXBsYXRlID0gL1xcJFxceyhbXlxcXFx9XSooPzpcXFxcLlteXFxcXH1dKikqKVxcfS9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgIGZsYWdzIGZyb20gdGhlaXIgY29lcmNlZCBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVGbGFncyA9IC9cXHcqJC87XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGJhZCBzaWduZWQgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNCYWRIZXggPSAvXlstK10weFswLTlhLWZdKyQvaTtcblxuICAvKiogVXNlZCB0byBkZXRlY3QgYmluYXJ5IHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUlzQmluYXJ5ID0gL14wYlswMV0rJC9pO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBob3N0IGNvbnN0cnVjdG9ycyAoU2FmYXJpKS4gKi9cbiAgdmFyIHJlSXNIb3N0Q3RvciA9IC9eXFxbb2JqZWN0IC4rP0NvbnN0cnVjdG9yXFxdJC87XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IG9jdGFsIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUlzT2N0YWwgPSAvXjBvWzAtN10rJC9pO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCB1bnNpZ25lZCBpbnRlZ2VyIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNVaW50ID0gL14oPzowfFsxLTldXFxkKikkLztcblxuICAvKiogVXNlZCB0byBtYXRjaCBMYXRpbiBVbmljb2RlIGxldHRlcnMgKGV4Y2x1ZGluZyBtYXRoZW1hdGljYWwgb3BlcmF0b3JzKS4gKi9cbiAgdmFyIHJlTGF0aW4gPSAvW1xceGMwLVxceGQ2XFx4ZDgtXFx4ZjZcXHhmOC1cXHhmZlxcdTAxMDAtXFx1MDE3Zl0vZztcblxuICAvKiogVXNlZCB0byBlbnN1cmUgY2FwdHVyaW5nIG9yZGVyIG9mIHRlbXBsYXRlIGRlbGltaXRlcnMuICovXG4gIHZhciByZU5vTWF0Y2ggPSAvKCReKS87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdW5lc2NhcGVkIGNoYXJhY3RlcnMgaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzLiAqL1xuICB2YXIgcmVVbmVzY2FwZWRTdHJpbmcgPSAvWydcXG5cXHJcXHUyMDI4XFx1MjAyOVxcXFxdL2c7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSB1bmljb2RlIGNoYXJhY3RlciBjbGFzc2VzLiAqL1xuICB2YXIgcnNBc3RyYWxSYW5nZSA9ICdcXFxcdWQ4MDAtXFxcXHVkZmZmJyxcbiAgICAgIHJzQ29tYm9NYXJrc1JhbmdlID0gJ1xcXFx1MDMwMC1cXFxcdTAzNmYnLFxuICAgICAgcmVDb21ib0hhbGZNYXJrc1JhbmdlID0gJ1xcXFx1ZmUyMC1cXFxcdWZlMmYnLFxuICAgICAgcnNDb21ib1N5bWJvbHNSYW5nZSA9ICdcXFxcdTIwZDAtXFxcXHUyMGZmJyxcbiAgICAgIHJzQ29tYm9SYW5nZSA9IHJzQ29tYm9NYXJrc1JhbmdlICsgcmVDb21ib0hhbGZNYXJrc1JhbmdlICsgcnNDb21ib1N5bWJvbHNSYW5nZSxcbiAgICAgIHJzRGluZ2JhdFJhbmdlID0gJ1xcXFx1MjcwMC1cXFxcdTI3YmYnLFxuICAgICAgcnNMb3dlclJhbmdlID0gJ2EtelxcXFx4ZGYtXFxcXHhmNlxcXFx4ZjgtXFxcXHhmZicsXG4gICAgICByc01hdGhPcFJhbmdlID0gJ1xcXFx4YWNcXFxceGIxXFxcXHhkN1xcXFx4ZjcnLFxuICAgICAgcnNOb25DaGFyUmFuZ2UgPSAnXFxcXHgwMC1cXFxceDJmXFxcXHgzYS1cXFxceDQwXFxcXHg1Yi1cXFxceDYwXFxcXHg3Yi1cXFxceGJmJyxcbiAgICAgIHJzUHVuY3R1YXRpb25SYW5nZSA9ICdcXFxcdTIwMDAtXFxcXHUyMDZmJyxcbiAgICAgIHJzU3BhY2VSYW5nZSA9ICcgXFxcXHRcXFxceDBiXFxcXGZcXFxceGEwXFxcXHVmZWZmXFxcXG5cXFxcclxcXFx1MjAyOFxcXFx1MjAyOVxcXFx1MTY4MFxcXFx1MTgwZVxcXFx1MjAwMFxcXFx1MjAwMVxcXFx1MjAwMlxcXFx1MjAwM1xcXFx1MjAwNFxcXFx1MjAwNVxcXFx1MjAwNlxcXFx1MjAwN1xcXFx1MjAwOFxcXFx1MjAwOVxcXFx1MjAwYVxcXFx1MjAyZlxcXFx1MjA1ZlxcXFx1MzAwMCcsXG4gICAgICByc1VwcGVyUmFuZ2UgPSAnQS1aXFxcXHhjMC1cXFxceGQ2XFxcXHhkOC1cXFxceGRlJyxcbiAgICAgIHJzVmFyUmFuZ2UgPSAnXFxcXHVmZTBlXFxcXHVmZTBmJyxcbiAgICAgIHJzQnJlYWtSYW5nZSA9IHJzTWF0aE9wUmFuZ2UgKyByc05vbkNoYXJSYW5nZSArIHJzUHVuY3R1YXRpb25SYW5nZSArIHJzU3BhY2VSYW5nZTtcblxuICAvKiogVXNlZCB0byBjb21wb3NlIHVuaWNvZGUgY2FwdHVyZSBncm91cHMuICovXG4gIHZhciByc0Fwb3MgPSBcIlsnXFx1MjAxOV1cIixcbiAgICAgIHJzQXN0cmFsID0gJ1snICsgcnNBc3RyYWxSYW5nZSArICddJyxcbiAgICAgIHJzQnJlYWsgPSAnWycgKyByc0JyZWFrUmFuZ2UgKyAnXScsXG4gICAgICByc0NvbWJvID0gJ1snICsgcnNDb21ib1JhbmdlICsgJ10nLFxuICAgICAgcnNEaWdpdHMgPSAnXFxcXGQrJyxcbiAgICAgIHJzRGluZ2JhdCA9ICdbJyArIHJzRGluZ2JhdFJhbmdlICsgJ10nLFxuICAgICAgcnNMb3dlciA9ICdbJyArIHJzTG93ZXJSYW5nZSArICddJyxcbiAgICAgIHJzTWlzYyA9ICdbXicgKyByc0FzdHJhbFJhbmdlICsgcnNCcmVha1JhbmdlICsgcnNEaWdpdHMgKyByc0RpbmdiYXRSYW5nZSArIHJzTG93ZXJSYW5nZSArIHJzVXBwZXJSYW5nZSArICddJyxcbiAgICAgIHJzRml0eiA9ICdcXFxcdWQ4M2NbXFxcXHVkZmZiLVxcXFx1ZGZmZl0nLFxuICAgICAgcnNNb2RpZmllciA9ICcoPzonICsgcnNDb21ibyArICd8JyArIHJzRml0eiArICcpJyxcbiAgICAgIHJzTm9uQXN0cmFsID0gJ1teJyArIHJzQXN0cmFsUmFuZ2UgKyAnXScsXG4gICAgICByc1JlZ2lvbmFsID0gJyg/OlxcXFx1ZDgzY1tcXFxcdWRkZTYtXFxcXHVkZGZmXSl7Mn0nLFxuICAgICAgcnNTdXJyUGFpciA9ICdbXFxcXHVkODAwLVxcXFx1ZGJmZl1bXFxcXHVkYzAwLVxcXFx1ZGZmZl0nLFxuICAgICAgcnNVcHBlciA9ICdbJyArIHJzVXBwZXJSYW5nZSArICddJyxcbiAgICAgIHJzWldKID0gJ1xcXFx1MjAwZCc7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSB1bmljb2RlIHJlZ2V4ZXMuICovXG4gIHZhciByc01pc2NMb3dlciA9ICcoPzonICsgcnNMb3dlciArICd8JyArIHJzTWlzYyArICcpJyxcbiAgICAgIHJzTWlzY1VwcGVyID0gJyg/OicgKyByc1VwcGVyICsgJ3wnICsgcnNNaXNjICsgJyknLFxuICAgICAgcnNPcHRDb250ckxvd2VyID0gJyg/OicgKyByc0Fwb3MgKyAnKD86ZHxsbHxtfHJlfHN8dHx2ZSkpPycsXG4gICAgICByc09wdENvbnRyVXBwZXIgPSAnKD86JyArIHJzQXBvcyArICcoPzpEfExMfE18UkV8U3xUfFZFKSk/JyxcbiAgICAgIHJlT3B0TW9kID0gcnNNb2RpZmllciArICc/JyxcbiAgICAgIHJzT3B0VmFyID0gJ1snICsgcnNWYXJSYW5nZSArICddPycsXG4gICAgICByc09wdEpvaW4gPSAnKD86JyArIHJzWldKICsgJyg/OicgKyBbcnNOb25Bc3RyYWwsIHJzUmVnaW9uYWwsIHJzU3VyclBhaXJdLmpvaW4oJ3wnKSArICcpJyArIHJzT3B0VmFyICsgcmVPcHRNb2QgKyAnKSonLFxuICAgICAgcnNPcmRMb3dlciA9ICdcXFxcZCooPzoxc3R8Mm5kfDNyZHwoPyFbMTIzXSlcXFxcZHRoKSg/PVxcXFxifFtBLVpfXSknLFxuICAgICAgcnNPcmRVcHBlciA9ICdcXFxcZCooPzoxU1R8Mk5EfDNSRHwoPyFbMTIzXSlcXFxcZFRIKSg/PVxcXFxifFthLXpfXSknLFxuICAgICAgcnNTZXEgPSByc09wdFZhciArIHJlT3B0TW9kICsgcnNPcHRKb2luLFxuICAgICAgcnNFbW9qaSA9ICcoPzonICsgW3JzRGluZ2JhdCwgcnNSZWdpb25hbCwgcnNTdXJyUGFpcl0uam9pbignfCcpICsgJyknICsgcnNTZXEsXG4gICAgICByc1N5bWJvbCA9ICcoPzonICsgW3JzTm9uQXN0cmFsICsgcnNDb21ibyArICc/JywgcnNDb21ibywgcnNSZWdpb25hbCwgcnNTdXJyUGFpciwgcnNBc3RyYWxdLmpvaW4oJ3wnKSArICcpJztcblxuICAvKiogVXNlZCB0byBtYXRjaCBhcG9zdHJvcGhlcy4gKi9cbiAgdmFyIHJlQXBvcyA9IFJlZ0V4cChyc0Fwb3MsICdnJyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gbWF0Y2ggW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKSBhbmRcbiAgICogW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrcyBmb3Igc3ltYm9sc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzX2Zvcl9TeW1ib2xzKS5cbiAgICovXG4gIHZhciByZUNvbWJvTWFyayA9IFJlZ0V4cChyc0NvbWJvLCAnZycpO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIFtzdHJpbmcgc3ltYm9sc10oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtdW5pY29kZSkuICovXG4gIHZhciByZVVuaWNvZGUgPSBSZWdFeHAocnNGaXR6ICsgJyg/PScgKyByc0ZpdHogKyAnKXwnICsgcnNTeW1ib2wgKyByc1NlcSwgJ2cnKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCBjb21wbGV4IG9yIGNvbXBvdW5kIHdvcmRzLiAqL1xuICB2YXIgcmVVbmljb2RlV29yZCA9IFJlZ0V4cChbXG4gICAgcnNVcHBlciArICc/JyArIHJzTG93ZXIgKyAnKycgKyByc09wdENvbnRyTG93ZXIgKyAnKD89JyArIFtyc0JyZWFrLCByc1VwcGVyLCAnJCddLmpvaW4oJ3wnKSArICcpJyxcbiAgICByc01pc2NVcHBlciArICcrJyArIHJzT3B0Q29udHJVcHBlciArICcoPz0nICsgW3JzQnJlYWssIHJzVXBwZXIgKyByc01pc2NMb3dlciwgJyQnXS5qb2luKCd8JykgKyAnKScsXG4gICAgcnNVcHBlciArICc/JyArIHJzTWlzY0xvd2VyICsgJysnICsgcnNPcHRDb250ckxvd2VyLFxuICAgIHJzVXBwZXIgKyAnKycgKyByc09wdENvbnRyVXBwZXIsXG4gICAgcnNPcmRVcHBlcixcbiAgICByc09yZExvd2VyLFxuICAgIHJzRGlnaXRzLFxuICAgIHJzRW1vamlcbiAgXS5qb2luKCd8JyksICdnJyk7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IHN0cmluZ3Mgd2l0aCBbemVyby13aWR0aCBqb2luZXJzIG9yIGNvZGUgcG9pbnRzIGZyb20gdGhlIGFzdHJhbCBwbGFuZXNdKGh0dHA6Ly9lZXYuZWUvYmxvZy8yMDE1LzA5LzEyL2RhcmstY29ybmVycy1vZi11bmljb2RlLykuICovXG4gIHZhciByZUhhc1VuaWNvZGUgPSBSZWdFeHAoJ1snICsgcnNaV0ogKyByc0FzdHJhbFJhbmdlICArIHJzQ29tYm9SYW5nZSArIHJzVmFyUmFuZ2UgKyAnXScpO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBzdHJpbmdzIHRoYXQgbmVlZCBhIG1vcmUgcm9idXN0IHJlZ2V4cCB0byBtYXRjaCB3b3Jkcy4gKi9cbiAgdmFyIHJlSGFzVW5pY29kZVdvcmQgPSAvW2Etel1bQS1aXXxbQS1aXXsyfVthLXpdfFswLTldW2EtekEtWl18W2EtekEtWl1bMC05XXxbXmEtekEtWjAtOSBdLztcblxuICAvKiogVXNlZCB0byBhc3NpZ24gZGVmYXVsdCBgY29udGV4dGAgb2JqZWN0IHByb3BlcnRpZXMuICovXG4gIHZhciBjb250ZXh0UHJvcHMgPSBbXG4gICAgJ0FycmF5JywgJ0J1ZmZlcicsICdEYXRhVmlldycsICdEYXRlJywgJ0Vycm9yJywgJ0Zsb2F0MzJBcnJheScsICdGbG9hdDY0QXJyYXknLFxuICAgICdGdW5jdGlvbicsICdJbnQ4QXJyYXknLCAnSW50MTZBcnJheScsICdJbnQzMkFycmF5JywgJ01hcCcsICdNYXRoJywgJ09iamVjdCcsXG4gICAgJ1Byb21pc2UnLCAnUmVnRXhwJywgJ1NldCcsICdTdHJpbmcnLCAnU3ltYm9sJywgJ1R5cGVFcnJvcicsICdVaW50OEFycmF5JyxcbiAgICAnVWludDhDbGFtcGVkQXJyYXknLCAnVWludDE2QXJyYXknLCAnVWludDMyQXJyYXknLCAnV2Vha01hcCcsXG4gICAgJ18nLCAnY2xlYXJUaW1lb3V0JywgJ2lzRmluaXRlJywgJ3BhcnNlSW50JywgJ3NldFRpbWVvdXQnXG4gIF07XG5cbiAgLyoqIFVzZWQgdG8gbWFrZSB0ZW1wbGF0ZSBzb3VyY2VVUkxzIGVhc2llciB0byBpZGVudGlmeS4gKi9cbiAgdmFyIHRlbXBsYXRlQ291bnRlciA9IC0xO1xuXG4gIC8qKiBVc2VkIHRvIGlkZW50aWZ5IGB0b1N0cmluZ1RhZ2AgdmFsdWVzIG9mIHR5cGVkIGFycmF5cy4gKi9cbiAgdmFyIHR5cGVkQXJyYXlUYWdzID0ge307XG4gIHR5cGVkQXJyYXlUYWdzW2Zsb2F0MzJUYWddID0gdHlwZWRBcnJheVRhZ3NbZmxvYXQ2NFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tpbnQ4VGFnXSA9IHR5cGVkQXJyYXlUYWdzW2ludDE2VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2ludDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW3VpbnQ4VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPSB0eXBlZEFycmF5VGFnc1t1aW50MTZUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbdWludDMyVGFnXSA9IHRydWU7XG4gIHR5cGVkQXJyYXlUYWdzW2FyZ3NUYWddID0gdHlwZWRBcnJheVRhZ3NbYXJyYXlUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbYXJyYXlCdWZmZXJUYWddID0gdHlwZWRBcnJheVRhZ3NbYm9vbFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tkYXRhVmlld1RhZ10gPSB0eXBlZEFycmF5VGFnc1tkYXRlVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2Vycm9yVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Z1bmNUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbbWFwVGFnXSA9IHR5cGVkQXJyYXlUYWdzW251bWJlclRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tvYmplY3RUYWddID0gdHlwZWRBcnJheVRhZ3NbcmVnZXhwVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3NldFRhZ10gPSB0eXBlZEFycmF5VGFnc1tzdHJpbmdUYWddID1cbiAgdHlwZWRBcnJheVRhZ3Nbd2Vha01hcFRhZ10gPSBmYWxzZTtcblxuICAvKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBzdXBwb3J0ZWQgYnkgYF8uY2xvbmVgLiAqL1xuICB2YXIgY2xvbmVhYmxlVGFncyA9IHt9O1xuICBjbG9uZWFibGVUYWdzW2FyZ3NUYWddID0gY2xvbmVhYmxlVGFnc1thcnJheVRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2FycmF5QnVmZmVyVGFnXSA9IGNsb25lYWJsZVRhZ3NbZGF0YVZpZXdUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tib29sVGFnXSA9IGNsb25lYWJsZVRhZ3NbZGF0ZVRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2Zsb2F0MzJUYWddID0gY2xvbmVhYmxlVGFnc1tmbG9hdDY0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbaW50OFRhZ10gPSBjbG9uZWFibGVUYWdzW2ludDE2VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbaW50MzJUYWddID0gY2xvbmVhYmxlVGFnc1ttYXBUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tudW1iZXJUYWddID0gY2xvbmVhYmxlVGFnc1tvYmplY3RUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tyZWdleHBUYWddID0gY2xvbmVhYmxlVGFnc1tzZXRUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tzdHJpbmdUYWddID0gY2xvbmVhYmxlVGFnc1tzeW1ib2xUYWddID1cbiAgY2xvbmVhYmxlVGFnc1t1aW50OFRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW3VpbnQxNlRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuICBjbG9uZWFibGVUYWdzW2Vycm9yVGFnXSA9IGNsb25lYWJsZVRhZ3NbZnVuY1RhZ10gPVxuICBjbG9uZWFibGVUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbiAgLyoqIFVzZWQgdG8gbWFwIExhdGluIFVuaWNvZGUgbGV0dGVycyB0byBiYXNpYyBMYXRpbiBsZXR0ZXJzLiAqL1xuICB2YXIgZGVidXJyZWRMZXR0ZXJzID0ge1xuICAgIC8vIExhdGluLTEgU3VwcGxlbWVudCBibG9jay5cbiAgICAnXFx4YzAnOiAnQScsICAnXFx4YzEnOiAnQScsICdcXHhjMic6ICdBJywgJ1xceGMzJzogJ0EnLCAnXFx4YzQnOiAnQScsICdcXHhjNSc6ICdBJyxcbiAgICAnXFx4ZTAnOiAnYScsICAnXFx4ZTEnOiAnYScsICdcXHhlMic6ICdhJywgJ1xceGUzJzogJ2EnLCAnXFx4ZTQnOiAnYScsICdcXHhlNSc6ICdhJyxcbiAgICAnXFx4YzcnOiAnQycsICAnXFx4ZTcnOiAnYycsXG4gICAgJ1xceGQwJzogJ0QnLCAgJ1xceGYwJzogJ2QnLFxuICAgICdcXHhjOCc6ICdFJywgICdcXHhjOSc6ICdFJywgJ1xceGNhJzogJ0UnLCAnXFx4Y2InOiAnRScsXG4gICAgJ1xceGU4JzogJ2UnLCAgJ1xceGU5JzogJ2UnLCAnXFx4ZWEnOiAnZScsICdcXHhlYic6ICdlJyxcbiAgICAnXFx4Y2MnOiAnSScsICAnXFx4Y2QnOiAnSScsICdcXHhjZSc6ICdJJywgJ1xceGNmJzogJ0knLFxuICAgICdcXHhlYyc6ICdpJywgICdcXHhlZCc6ICdpJywgJ1xceGVlJzogJ2knLCAnXFx4ZWYnOiAnaScsXG4gICAgJ1xceGQxJzogJ04nLCAgJ1xceGYxJzogJ24nLFxuICAgICdcXHhkMic6ICdPJywgICdcXHhkMyc6ICdPJywgJ1xceGQ0JzogJ08nLCAnXFx4ZDUnOiAnTycsICdcXHhkNic6ICdPJywgJ1xceGQ4JzogJ08nLFxuICAgICdcXHhmMic6ICdvJywgICdcXHhmMyc6ICdvJywgJ1xceGY0JzogJ28nLCAnXFx4ZjUnOiAnbycsICdcXHhmNic6ICdvJywgJ1xceGY4JzogJ28nLFxuICAgICdcXHhkOSc6ICdVJywgICdcXHhkYSc6ICdVJywgJ1xceGRiJzogJ1UnLCAnXFx4ZGMnOiAnVScsXG4gICAgJ1xceGY5JzogJ3UnLCAgJ1xceGZhJzogJ3UnLCAnXFx4ZmInOiAndScsICdcXHhmYyc6ICd1JyxcbiAgICAnXFx4ZGQnOiAnWScsICAnXFx4ZmQnOiAneScsICdcXHhmZic6ICd5JyxcbiAgICAnXFx4YzYnOiAnQWUnLCAnXFx4ZTYnOiAnYWUnLFxuICAgICdcXHhkZSc6ICdUaCcsICdcXHhmZSc6ICd0aCcsXG4gICAgJ1xceGRmJzogJ3NzJyxcbiAgICAvLyBMYXRpbiBFeHRlbmRlZC1BIGJsb2NrLlxuICAgICdcXHUwMTAwJzogJ0EnLCAgJ1xcdTAxMDInOiAnQScsICdcXHUwMTA0JzogJ0EnLFxuICAgICdcXHUwMTAxJzogJ2EnLCAgJ1xcdTAxMDMnOiAnYScsICdcXHUwMTA1JzogJ2EnLFxuICAgICdcXHUwMTA2JzogJ0MnLCAgJ1xcdTAxMDgnOiAnQycsICdcXHUwMTBhJzogJ0MnLCAnXFx1MDEwYyc6ICdDJyxcbiAgICAnXFx1MDEwNyc6ICdjJywgICdcXHUwMTA5JzogJ2MnLCAnXFx1MDEwYic6ICdjJywgJ1xcdTAxMGQnOiAnYycsXG4gICAgJ1xcdTAxMGUnOiAnRCcsICAnXFx1MDExMCc6ICdEJywgJ1xcdTAxMGYnOiAnZCcsICdcXHUwMTExJzogJ2QnLFxuICAgICdcXHUwMTEyJzogJ0UnLCAgJ1xcdTAxMTQnOiAnRScsICdcXHUwMTE2JzogJ0UnLCAnXFx1MDExOCc6ICdFJywgJ1xcdTAxMWEnOiAnRScsXG4gICAgJ1xcdTAxMTMnOiAnZScsICAnXFx1MDExNSc6ICdlJywgJ1xcdTAxMTcnOiAnZScsICdcXHUwMTE5JzogJ2UnLCAnXFx1MDExYic6ICdlJyxcbiAgICAnXFx1MDExYyc6ICdHJywgICdcXHUwMTFlJzogJ0cnLCAnXFx1MDEyMCc6ICdHJywgJ1xcdTAxMjInOiAnRycsXG4gICAgJ1xcdTAxMWQnOiAnZycsICAnXFx1MDExZic6ICdnJywgJ1xcdTAxMjEnOiAnZycsICdcXHUwMTIzJzogJ2cnLFxuICAgICdcXHUwMTI0JzogJ0gnLCAgJ1xcdTAxMjYnOiAnSCcsICdcXHUwMTI1JzogJ2gnLCAnXFx1MDEyNyc6ICdoJyxcbiAgICAnXFx1MDEyOCc6ICdJJywgICdcXHUwMTJhJzogJ0knLCAnXFx1MDEyYyc6ICdJJywgJ1xcdTAxMmUnOiAnSScsICdcXHUwMTMwJzogJ0knLFxuICAgICdcXHUwMTI5JzogJ2knLCAgJ1xcdTAxMmInOiAnaScsICdcXHUwMTJkJzogJ2knLCAnXFx1MDEyZic6ICdpJywgJ1xcdTAxMzEnOiAnaScsXG4gICAgJ1xcdTAxMzQnOiAnSicsICAnXFx1MDEzNSc6ICdqJyxcbiAgICAnXFx1MDEzNic6ICdLJywgICdcXHUwMTM3JzogJ2snLCAnXFx1MDEzOCc6ICdrJyxcbiAgICAnXFx1MDEzOSc6ICdMJywgICdcXHUwMTNiJzogJ0wnLCAnXFx1MDEzZCc6ICdMJywgJ1xcdTAxM2YnOiAnTCcsICdcXHUwMTQxJzogJ0wnLFxuICAgICdcXHUwMTNhJzogJ2wnLCAgJ1xcdTAxM2MnOiAnbCcsICdcXHUwMTNlJzogJ2wnLCAnXFx1MDE0MCc6ICdsJywgJ1xcdTAxNDInOiAnbCcsXG4gICAgJ1xcdTAxNDMnOiAnTicsICAnXFx1MDE0NSc6ICdOJywgJ1xcdTAxNDcnOiAnTicsICdcXHUwMTRhJzogJ04nLFxuICAgICdcXHUwMTQ0JzogJ24nLCAgJ1xcdTAxNDYnOiAnbicsICdcXHUwMTQ4JzogJ24nLCAnXFx1MDE0Yic6ICduJyxcbiAgICAnXFx1MDE0Yyc6ICdPJywgICdcXHUwMTRlJzogJ08nLCAnXFx1MDE1MCc6ICdPJyxcbiAgICAnXFx1MDE0ZCc6ICdvJywgICdcXHUwMTRmJzogJ28nLCAnXFx1MDE1MSc6ICdvJyxcbiAgICAnXFx1MDE1NCc6ICdSJywgICdcXHUwMTU2JzogJ1InLCAnXFx1MDE1OCc6ICdSJyxcbiAgICAnXFx1MDE1NSc6ICdyJywgICdcXHUwMTU3JzogJ3InLCAnXFx1MDE1OSc6ICdyJyxcbiAgICAnXFx1MDE1YSc6ICdTJywgICdcXHUwMTVjJzogJ1MnLCAnXFx1MDE1ZSc6ICdTJywgJ1xcdTAxNjAnOiAnUycsXG4gICAgJ1xcdTAxNWInOiAncycsICAnXFx1MDE1ZCc6ICdzJywgJ1xcdTAxNWYnOiAncycsICdcXHUwMTYxJzogJ3MnLFxuICAgICdcXHUwMTYyJzogJ1QnLCAgJ1xcdTAxNjQnOiAnVCcsICdcXHUwMTY2JzogJ1QnLFxuICAgICdcXHUwMTYzJzogJ3QnLCAgJ1xcdTAxNjUnOiAndCcsICdcXHUwMTY3JzogJ3QnLFxuICAgICdcXHUwMTY4JzogJ1UnLCAgJ1xcdTAxNmEnOiAnVScsICdcXHUwMTZjJzogJ1UnLCAnXFx1MDE2ZSc6ICdVJywgJ1xcdTAxNzAnOiAnVScsICdcXHUwMTcyJzogJ1UnLFxuICAgICdcXHUwMTY5JzogJ3UnLCAgJ1xcdTAxNmInOiAndScsICdcXHUwMTZkJzogJ3UnLCAnXFx1MDE2Zic6ICd1JywgJ1xcdTAxNzEnOiAndScsICdcXHUwMTczJzogJ3UnLFxuICAgICdcXHUwMTc0JzogJ1cnLCAgJ1xcdTAxNzUnOiAndycsXG4gICAgJ1xcdTAxNzYnOiAnWScsICAnXFx1MDE3Nyc6ICd5JywgJ1xcdTAxNzgnOiAnWScsXG4gICAgJ1xcdTAxNzknOiAnWicsICAnXFx1MDE3Yic6ICdaJywgJ1xcdTAxN2QnOiAnWicsXG4gICAgJ1xcdTAxN2EnOiAneicsICAnXFx1MDE3Yyc6ICd6JywgJ1xcdTAxN2UnOiAneicsXG4gICAgJ1xcdTAxMzInOiAnSUonLCAnXFx1MDEzMyc6ICdpaicsXG4gICAgJ1xcdTAxNTInOiAnT2UnLCAnXFx1MDE1Myc6ICdvZScsXG4gICAgJ1xcdTAxNDknOiBcIiduXCIsICdcXHUwMTdmJzogJ3MnXG4gIH07XG5cbiAgLyoqIFVzZWQgdG8gbWFwIGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllcy4gKi9cbiAgdmFyIGh0bWxFc2NhcGVzID0ge1xuICAgICcmJzogJyZhbXA7JyxcbiAgICAnPCc6ICcmbHQ7JyxcbiAgICAnPic6ICcmZ3Q7JyxcbiAgICAnXCInOiAnJnF1b3Q7JyxcbiAgICBcIidcIjogJyYjMzk7J1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBIVE1MIGVudGl0aWVzIHRvIGNoYXJhY3RlcnMuICovXG4gIHZhciBodG1sVW5lc2NhcGVzID0ge1xuICAgICcmYW1wOyc6ICcmJyxcbiAgICAnJmx0Oyc6ICc8JyxcbiAgICAnJmd0Oyc6ICc+JyxcbiAgICAnJnF1b3Q7JzogJ1wiJyxcbiAgICAnJiMzOTsnOiBcIidcIlxuICB9O1xuXG4gIC8qKiBVc2VkIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzLiAqL1xuICB2YXIgc3RyaW5nRXNjYXBlcyA9IHtcbiAgICAnXFxcXCc6ICdcXFxcJyxcbiAgICBcIidcIjogXCInXCIsXG4gICAgJ1xcbic6ICduJyxcbiAgICAnXFxyJzogJ3InLFxuICAgICdcXHUyMDI4JzogJ3UyMDI4JyxcbiAgICAnXFx1MjAyOSc6ICd1MjAyOSdcbiAgfTtcblxuICAvKiogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgd2l0aG91dCBhIGRlcGVuZGVuY3kgb24gYHJvb3RgLiAqL1xuICB2YXIgZnJlZVBhcnNlRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgZnJlZVBhcnNlSW50ID0gcGFyc2VJbnQ7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgc2VsZmAuICovXG4gIHZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IGZyZWVHbG9iYWwgfHwgZnJlZVNlbGYgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xuICB2YXIgZnJlZUV4cG9ydHMgPSB0eXBlb2YgZXhwb3J0cyA9PSAnb2JqZWN0JyAmJiBleHBvcnRzICYmICFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IGZyZWVFeHBvcnRzICYmIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4gIC8qKiBEZXRlY3QgdGhlIHBvcHVsYXIgQ29tbW9uSlMgZXh0ZW5zaW9uIGBtb2R1bGUuZXhwb3J0c2AuICovXG4gIHZhciBtb2R1bGVFeHBvcnRzID0gZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLmV4cG9ydHMgPT09IGZyZWVFeHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgcHJvY2Vzc2AgZnJvbSBOb2RlLmpzLiAqL1xuICB2YXIgZnJlZVByb2Nlc3MgPSBtb2R1bGVFeHBvcnRzICYmIGZyZWVHbG9iYWwucHJvY2VzcztcblxuICAvKiogVXNlZCB0byBhY2Nlc3MgZmFzdGVyIE5vZGUuanMgaGVscGVycy4gKi9cbiAgdmFyIG5vZGVVdGlsID0gKGZ1bmN0aW9uKCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBVc2UgYHV0aWwudHlwZXNgIGZvciBOb2RlLmpzIDEwKy5cbiAgICAgIHZhciB0eXBlcyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5yZXF1aXJlICYmIGZyZWVNb2R1bGUucmVxdWlyZSgndXRpbCcpLnR5cGVzO1xuXG4gICAgICBpZiAodHlwZXMpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVzO1xuICAgICAgfVxuXG4gICAgICAvLyBMZWdhY3kgYHByb2Nlc3MuYmluZGluZygndXRpbCcpYCBmb3IgTm9kZS5qcyA8IDEwLlxuICAgICAgcmV0dXJuIGZyZWVQcm9jZXNzICYmIGZyZWVQcm9jZXNzLmJpbmRpbmcgJiYgZnJlZVByb2Nlc3MuYmluZGluZygndXRpbCcpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gIH0oKSk7XG5cbiAgLyogTm9kZS5qcyBoZWxwZXIgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG5vZGVJc0FycmF5QnVmZmVyID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNBcnJheUJ1ZmZlcixcbiAgICAgIG5vZGVJc0RhdGUgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc0RhdGUsXG4gICAgICBub2RlSXNNYXAgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc01hcCxcbiAgICAgIG5vZGVJc1JlZ0V4cCA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzUmVnRXhwLFxuICAgICAgbm9kZUlzU2V0ID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNTZXQsXG4gICAgICBub2RlSXNUeXBlZEFycmF5ID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNUeXBlZEFycmF5O1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBBIGZhc3RlciBhbHRlcm5hdGl2ZSB0byBgRnVuY3Rpb24jYXBwbHlgLCB0aGlzIGZ1bmN0aW9uIGludm9rZXMgYGZ1bmNgXG4gICAqIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIGB0aGlzQXJnYCBhbmQgdGhlIGFyZ3VtZW50cyBvZiBgYXJnc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGludm9rZS5cbiAgICogQHBhcmFtIHsqfSB0aGlzQXJnIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgYGZ1bmNgIHdpdGguXG4gICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXN1bHQgb2YgYGZ1bmNgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXBwbHkoZnVuYywgdGhpc0FyZywgYXJncykge1xuICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnKTtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdKTtcbiAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlQWdncmVnYXRvcmAgZm9yIGFycmF5cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBgYWNjdW11bGF0b3JgIHZhbHVlcy5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSBrZXlzLlxuICAgKiBAcGFyYW0ge09iamVjdH0gYWNjdW11bGF0b3IgVGhlIGluaXRpYWwgYWdncmVnYXRlZCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgYWNjdW11bGF0b3JgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlBZ2dyZWdhdG9yKGFycmF5LCBzZXR0ZXIsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICBzZXR0ZXIoYWNjdW11bGF0b3IsIHZhbHVlLCBpdGVyYXRlZSh2YWx1ZSksIGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5mb3JFYWNoYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RWFjaChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKGl0ZXJhdGVlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZm9yRWFjaFJpZ2h0YCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RWFjaFJpZ2h0KGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgaWYgKGl0ZXJhdGVlKGFycmF5W2xlbmd0aF0sIGxlbmd0aCwgYXJyYXkpID09PSBmYWxzZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5ldmVyeWAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlFdmVyeShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmICghcHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5maWx0ZXJgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RmlsdGVyKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uaW5jbHVkZXNgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBzcGVjaWZ5aW5nIGFuIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHRhcmdldCBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB0YXJnZXRgIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUluY2x1ZGVzKGFycmF5LCB2YWx1ZSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICByZXR1cm4gISFsZW5ndGggJiYgYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCAwKSA+IC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYXJyYXlJbmNsdWRlc2AgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhIGNvbXBhcmF0b3IuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gdGFyZ2V0IFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb21wYXJhdG9yIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdGFyZ2V0YCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlJbmNsdWRlc1dpdGgoYXJyYXksIHZhbHVlLCBjb21wYXJhdG9yKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChjb21wYXJhdG9yKHZhbHVlLCBhcnJheVtpbmRleF0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLm1hcGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAqIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlNYXAoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHJlc3VsdFtpbmRleF0gPSBpdGVyYXRlZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kcyB0aGUgZWxlbWVudHMgb2YgYHZhbHVlc2AgdG8gYGFycmF5YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gYXBwZW5kLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5UHVzaChhcnJheSwgdmFsdWVzKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgIG9mZnNldCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBhcnJheVtvZmZzZXQgKyBpbmRleF0gPSB2YWx1ZXNbaW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnJlZHVjZWAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpbml0QWNjdW1dIFNwZWNpZnkgdXNpbmcgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YCBhc1xuICAgKiAgdGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5UmVkdWNlKGFycmF5LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIGlmIChpbml0QWNjdW0gJiYgbGVuZ3RoKSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGFycmF5WysraW5kZXhdO1xuICAgIH1cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBpdGVyYXRlZShhY2N1bXVsYXRvciwgYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnJlZHVjZVJpZ2h0YCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2luaXRBY2N1bV0gU3BlY2lmeSB1c2luZyB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAgYXNcbiAgICogIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVJlZHVjZVJpZ2h0KGFycmF5LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICBpZiAoaW5pdEFjY3VtICYmIGxlbmd0aCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBhcnJheVstLWxlbmd0aF07XG4gICAgfVxuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgYWNjdW11bGF0b3IgPSBpdGVyYXRlZShhY2N1bXVsYXRvciwgYXJyYXlbbGVuZ3RoXSwgbGVuZ3RoLCBhcnJheSk7XG4gICAgfVxuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc29tZWAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAqIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICogIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5U29tZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgc2l6ZSBvZiBhbiBBU0NJSSBgc3RyaW5nYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN0cmluZyBzaXplLlxuICAgKi9cbiAgdmFyIGFzY2lpU2l6ZSA9IGJhc2VQcm9wZXJ0eSgnbGVuZ3RoJyk7XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGFuIEFTQ0lJIGBzdHJpbmdgIHRvIGFuIGFycmF5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBhc2NpaVRvQXJyYXkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG4gIH1cblxuICAvKipcbiAgICogU3BsaXRzIGFuIEFTQ0lJIGBzdHJpbmdgIGludG8gYW4gYXJyYXkgb2YgaXRzIHdvcmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXNjaWlXb3JkcyhzdHJpbmcpIHtcbiAgICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlQXNjaWlXb3JkKSB8fCBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uZmluZEtleWAgYW5kIGBfLmZpbmRMYXN0S2V5YCxcbiAgICogd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLCB3aGljaCBpdGVyYXRlcyBvdmVyIGBjb2xsZWN0aW9uYFxuICAgKiB1c2luZyBgZWFjaEZ1bmNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBgY29sbGVjdGlvbmAuXG4gICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmb3VuZCBlbGVtZW50IG9yIGl0cyBrZXksIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlRmluZEtleShjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGVhY2hGdW5jKSB7XG4gICAgdmFyIHJlc3VsdDtcbiAgICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHJlc3VsdCA9IGtleTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmluZEluZGV4YCBhbmQgYF8uZmluZExhc3RJbmRleGAgd2l0aG91dFxuICAgKiBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VGaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgZnJvbUluZGV4LCBmcm9tUmlnaHQpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICBpbmRleCA9IGZyb21JbmRleCArIChmcm9tUmlnaHQgPyAxIDogLTEpO1xuXG4gICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmluZGV4T2ZgIHdpdGhvdXQgYGZyb21JbmRleGAgYm91bmRzIGNoZWNrcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IHZhbHVlXG4gICAgICA/IHN0cmljdEluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpXG4gICAgICA6IGJhc2VGaW5kSW5kZXgoYXJyYXksIGJhc2VJc05hTiwgZnJvbUluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGJhc2VJbmRleE9mYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGEgY29tcGFyYXRvci5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb21wYXJhdG9yIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlSW5kZXhPZldpdGgoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgsIGNvbXBhcmF0b3IpIHtcbiAgICB2YXIgaW5kZXggPSBmcm9tSW5kZXggLSAxLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKGNvbXBhcmF0b3IoYXJyYXlbaW5kZXhdLCB2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNOYU5gIHdpdGhvdXQgc3VwcG9ydCBmb3IgbnVtYmVyIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgTmFOYCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUlzTmFOKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlICE9PSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tZWFuYCBhbmQgYF8ubWVhbkJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG1lYW4uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlTWVhbihhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgcmV0dXJuIGxlbmd0aCA/IChiYXNlU3VtKGFycmF5LCBpdGVyYXRlZSkgLyBsZW5ndGgpIDogTkFOO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnByb3BlcnR5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBhY2Nlc3NvciBmdW5jdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eShrZXkpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnByb3BlcnR5T2ZgIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVlcCBwYXRocy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBhY2Nlc3NvciBmdW5jdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eU9mKG9iamVjdCkge1xuICAgIHJldHVybiBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IG9iamVjdFtrZXldO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucmVkdWNlYCBhbmQgYF8ucmVkdWNlUmlnaHRgLCB3aXRob3V0IHN1cHBvcnRcbiAgICogZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMsIHdoaWNoIGl0ZXJhdGVzIG92ZXIgYGNvbGxlY3Rpb25gIHVzaW5nIGBlYWNoRnVuY2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBhY2N1bXVsYXRvciBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBpbml0QWNjdW0gU3BlY2lmeSB1c2luZyB0aGUgZmlyc3Qgb3IgbGFzdCBlbGVtZW50IG9mXG4gICAqICBgY29sbGVjdGlvbmAgYXMgdGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYGNvbGxlY3Rpb25gLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlUmVkdWNlKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBhY2N1bXVsYXRvciwgaW5pdEFjY3VtLCBlYWNoRnVuYykge1xuICAgIGVhY2hGdW5jKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgYWNjdW11bGF0b3IgPSBpbml0QWNjdW1cbiAgICAgICAgPyAoaW5pdEFjY3VtID0gZmFsc2UsIHZhbHVlKVxuICAgICAgICA6IGl0ZXJhdGVlKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgIH0pO1xuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zb3J0QnlgIHdoaWNoIHVzZXMgYGNvbXBhcmVyYCB0byBkZWZpbmUgdGhlXG4gICAqIHNvcnQgb3JkZXIgb2YgYGFycmF5YCBhbmQgcmVwbGFjZXMgY3JpdGVyaWEgb2JqZWN0cyB3aXRoIHRoZWlyIGNvcnJlc3BvbmRpbmdcbiAgICogdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc29ydC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyZXIgVGhlIGZ1bmN0aW9uIHRvIGRlZmluZSBzb3J0IG9yZGVyLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VTb3J0QnkoYXJyYXksIGNvbXBhcmVyKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIGFycmF5LnNvcnQoY29tcGFyZXIpO1xuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgYXJyYXlbbGVuZ3RoXSA9IGFycmF5W2xlbmd0aF0udmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zdW1gIGFuZCBgXy5zdW1CeWAgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdW0uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlU3VtKGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciByZXN1bHQsXG4gICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgY3VycmVudCA9IGl0ZXJhdGVlKGFycmF5W2luZGV4XSk7XG4gICAgICBpZiAoY3VycmVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gY3VycmVudCA6IChyZXN1bHQgKyBjdXJyZW50KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50aW1lc2Agd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzXG4gICAqIG9yIG1heCBhcnJheSBsZW5ndGggY2hlY2tzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIHRpbWVzIHRvIGludm9rZSBgaXRlcmF0ZWVgLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHJlc3VsdHMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVGltZXMobiwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobik7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgIHJlc3VsdFtpbmRleF0gPSBpdGVyYXRlZShpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udG9QYWlyc2AgYW5kIGBfLnRvUGFpcnNJbmAgd2hpY2ggY3JlYXRlcyBhbiBhcnJheVxuICAgKiBvZiBrZXktdmFsdWUgcGFpcnMgZm9yIGBvYmplY3RgIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3BlcnR5IG5hbWVzIG9mIGBwcm9wc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGdldCB2YWx1ZXMgZm9yLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBrZXktdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVG9QYWlycyhvYmplY3QsIHByb3BzKSB7XG4gICAgcmV0dXJuIGFycmF5TWFwKHByb3BzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBba2V5LCBvYmplY3Rba2V5XV07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udHJpbWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VUcmltKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmdcbiAgICAgID8gc3RyaW5nLnNsaWNlKDAsIHRyaW1tZWRFbmRJbmRleChzdHJpbmcpICsgMSkucmVwbGFjZShyZVRyaW1TdGFydCwgJycpXG4gICAgICA6IHN0cmluZztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bmFyeWAgd2l0aG91dCBzdXBwb3J0IGZvciBzdG9yaW5nIG1ldGFkYXRhLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY2FwcGVkIGZ1bmN0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVVuYXJ5KGZ1bmMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jKHZhbHVlKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnZhbHVlc2AgYW5kIGBfLnZhbHVlc0luYCB3aGljaCBjcmVhdGVzIGFuXG4gICAqIGFycmF5IG9mIGBvYmplY3RgIHByb3BlcnR5IHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm9wZXJ0eSBuYW1lc1xuICAgKiBvZiBgcHJvcHNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBnZXQgdmFsdWVzIGZvci5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVZhbHVlcyhvYmplY3QsIHByb3BzKSB7XG4gICAgcmV0dXJuIGFycmF5TWFwKHByb3BzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBvYmplY3Rba2V5XTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBgY2FjaGVgIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjYWNoZSBUaGUgY2FjaGUgdG8gcXVlcnkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBjYWNoZUhhcyhjYWNoZSwga2V5KSB7XG4gICAgcmV0dXJuIGNhY2hlLmhhcyhrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udHJpbWAgYW5kIGBfLnRyaW1TdGFydGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgc3RyaW5nIHN5bWJvbFxuICAgKiB0aGF0IGlzIG5vdCBmb3VuZCBpbiB0aGUgY2hhcmFjdGVyIHN5bWJvbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN0clN5bWJvbHMgVGhlIHN0cmluZyBzeW1ib2xzIHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7QXJyYXl9IGNoclN5bWJvbHMgVGhlIGNoYXJhY3RlciBzeW1ib2xzIHRvIGZpbmQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCB1bm1hdGNoZWQgc3RyaW5nIHN5bWJvbC5cbiAgICovXG4gIGZ1bmN0aW9uIGNoYXJzU3RhcnRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IHN0clN5bWJvbHMubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGggJiYgYmFzZUluZGV4T2YoY2hyU3ltYm9scywgc3RyU3ltYm9sc1tpbmRleF0sIDApID4gLTEpIHt9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udHJpbWAgYW5kIGBfLnRyaW1FbmRgIHRvIGdldCB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgc3RyaW5nIHN5bWJvbFxuICAgKiB0aGF0IGlzIG5vdCBmb3VuZCBpbiB0aGUgY2hhcmFjdGVyIHN5bWJvbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN0clN5bWJvbHMgVGhlIHN0cmluZyBzeW1ib2xzIHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7QXJyYXl9IGNoclN5bWJvbHMgVGhlIGNoYXJhY3RlciBzeW1ib2xzIHRvIGZpbmQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBsYXN0IHVubWF0Y2hlZCBzdHJpbmcgc3ltYm9sLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSB7XG4gICAgdmFyIGluZGV4ID0gc3RyU3ltYm9scy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoaW5kZXgtLSAmJiBiYXNlSW5kZXhPZihjaHJTeW1ib2xzLCBzdHJTeW1ib2xzW2luZGV4XSwgMCkgPiAtMSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGBwbGFjZWhvbGRlcmAgb2NjdXJyZW5jZXMgaW4gYGFycmF5YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHRvIHNlYXJjaCBmb3IuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHBsYWNlaG9sZGVyIGNvdW50LlxuICAgKi9cbiAgZnVuY3Rpb24gY291bnRIb2xkZXJzKGFycmF5LCBwbGFjZWhvbGRlcikge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdCA9IDA7XG5cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGlmIChhcnJheVtsZW5ndGhdID09PSBwbGFjZWhvbGRlcikge1xuICAgICAgICArK3Jlc3VsdDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLmRlYnVycmAgdG8gY29udmVydCBMYXRpbi0xIFN1cHBsZW1lbnQgYW5kIExhdGluIEV4dGVuZGVkLUFcbiAgICogbGV0dGVycyB0byBiYXNpYyBMYXRpbiBsZXR0ZXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGV0dGVyIFRoZSBtYXRjaGVkIGxldHRlciB0byBkZWJ1cnIuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGRlYnVycmVkIGxldHRlci5cbiAgICovXG4gIHZhciBkZWJ1cnJMZXR0ZXIgPSBiYXNlUHJvcGVydHlPZihkZWJ1cnJlZExldHRlcnMpO1xuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLmVzY2FwZWAgdG8gY29udmVydCBjaGFyYWN0ZXJzIHRvIEhUTUwgZW50aXRpZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIGVzY2FwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICB2YXIgZXNjYXBlSHRtbENoYXIgPSBiYXNlUHJvcGVydHlPZihodG1sRXNjYXBlcyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udGVtcGxhdGVgIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hyIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlU3RyaW5nQ2hhcihjaHIpIHtcbiAgICByZXR1cm4gJ1xcXFwnICsgc3RyaW5nRXNjYXBlc1tjaHJdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHZhbHVlIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZS5cbiAgICovXG4gIGZ1bmN0aW9uIGdldFZhbHVlKG9iamVjdCwga2V5KSB7XG4gICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGBzdHJpbmdgIGNvbnRhaW5zIFVuaWNvZGUgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhIHN5bWJvbCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaGFzVW5pY29kZShzdHJpbmcpIHtcbiAgICByZXR1cm4gcmVIYXNVbmljb2RlLnRlc3Qoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYHN0cmluZ2AgY29udGFpbnMgYSB3b3JkIGNvbXBvc2VkIG9mIFVuaWNvZGUgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhIHdvcmQgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGhhc1VuaWNvZGVXb3JkKHN0cmluZykge1xuICAgIHJldHVybiByZUhhc1VuaWNvZGVXb3JkLnRlc3Qoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgaXRlcmF0b3JgIHRvIGFuIGFycmF5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gaXRlcmF0b3IgVGhlIGl0ZXJhdG9yIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gaXRlcmF0b3JUb0FycmF5KGl0ZXJhdG9yKSB7XG4gICAgdmFyIGRhdGEsXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgd2hpbGUgKCEoZGF0YSA9IGl0ZXJhdG9yLm5leHQoKSkuZG9uZSkge1xuICAgICAgcmVzdWx0LnB1c2goZGF0YS52YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYG1hcGAgdG8gaXRzIGtleS12YWx1ZSBwYWlycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgKi9cbiAgZnVuY3Rpb24gbWFwVG9BcnJheShtYXApIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobWFwLnNpemUpO1xuXG4gICAgbWFwLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0WysraW5kZXhdID0gW2tleSwgdmFsdWVdO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHVuYXJ5IGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBpdHMgYXJndW1lbnQgdHJhbnNmb3JtZWQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHRyYW5zZm9ybSBUaGUgYXJndW1lbnQgdHJhbnNmb3JtLlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIG92ZXJBcmcoZnVuYywgdHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGFyZykge1xuICAgICAgcmV0dXJuIGZ1bmModHJhbnNmb3JtKGFyZykpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgYWxsIGBwbGFjZWhvbGRlcmAgZWxlbWVudHMgaW4gYGFycmF5YCB3aXRoIGFuIGludGVybmFsIHBsYWNlaG9sZGVyXG4gICAqIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZWlyIGluZGV4ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHRvIHJlcGxhY2UuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAqL1xuICBmdW5jdGlvbiByZXBsYWNlSG9sZGVycyhhcnJheSwgcGxhY2Vob2xkZXIpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgIGlmICh2YWx1ZSA9PT0gcGxhY2Vob2xkZXIgfHwgdmFsdWUgPT09IFBMQUNFSE9MREVSKSB7XG4gICAgICAgIGFycmF5W2luZGV4XSA9IFBMQUNFSE9MREVSO1xuICAgICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgc2V0YCB0byBhbiBhcnJheSBvZiBpdHMgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gc2V0IFRoZSBzZXQgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB2YWx1ZXMuXG4gICAqL1xuICBmdW5jdGlvbiBzZXRUb0FycmF5KHNldCkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShzZXQuc2l6ZSk7XG5cbiAgICBzZXQuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmVzdWx0WysraW5kZXhdID0gdmFsdWU7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgc2V0YCB0byBpdHMgdmFsdWUtdmFsdWUgcGFpcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHZhbHVlLXZhbHVlIHBhaXJzLlxuICAgKi9cbiAgZnVuY3Rpb24gc2V0VG9QYWlycyhzZXQpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkoc2V0LnNpemUpO1xuXG4gICAgc2V0LmZvckVhY2goZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJlc3VsdFsrK2luZGV4XSA9IFt2YWx1ZSwgdmFsdWVdO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmluZGV4T2ZgIHdoaWNoIHBlcmZvcm1zIHN0cmljdCBlcXVhbGl0eVxuICAgKiBjb21wYXJpc29ucyBvZiB2YWx1ZXMsIGkuZS4gYD09PWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmljdEluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICB2YXIgaW5kZXggPSBmcm9tSW5kZXggLSAxLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmxhc3RJbmRleE9mYCB3aGljaCBwZXJmb3JtcyBzdHJpY3QgZXF1YWxpdHlcbiAgICogY29tcGFyaXNvbnMgb2YgdmFsdWVzLCBpLmUuIGA9PT1gLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGZyb21JbmRleCBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBzdHJpY3RMYXN0SW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgIHZhciBpbmRleCA9IGZyb21JbmRleCArIDE7XG4gICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgIGlmIChhcnJheVtpbmRleF0gPT09IHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIG51bWJlciBvZiBzeW1ib2xzIGluIGBzdHJpbmdgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3RyaW5nIHNpemUuXG4gICAqL1xuICBmdW5jdGlvbiBzdHJpbmdTaXplKHN0cmluZykge1xuICAgIHJldHVybiBoYXNVbmljb2RlKHN0cmluZylcbiAgICAgID8gdW5pY29kZVNpemUoc3RyaW5nKVxuICAgICAgOiBhc2NpaVNpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBhbiBhcnJheS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gc3RyaW5nVG9BcnJheShzdHJpbmcpIHtcbiAgICByZXR1cm4gaGFzVW5pY29kZShzdHJpbmcpXG4gICAgICA/IHVuaWNvZGVUb0FycmF5KHN0cmluZylcbiAgICAgIDogYXNjaWlUb0FycmF5KHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbUVuZGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgbGFzdCBub24td2hpdGVzcGFjZVxuICAgKiBjaGFyYWN0ZXIgb2YgYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbGFzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltbWVkRW5kSW5kZXgoc3RyaW5nKSB7XG4gICAgdmFyIGluZGV4ID0gc3RyaW5nLmxlbmd0aDtcblxuICAgIHdoaWxlIChpbmRleC0tICYmIHJlV2hpdGVzcGFjZS50ZXN0KHN0cmluZy5jaGFyQXQoaW5kZXgpKSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy51bmVzY2FwZWAgdG8gY29udmVydCBIVE1MIGVudGl0aWVzIHRvIGNoYXJhY3RlcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIHVuZXNjYXBlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgdmFyIHVuZXNjYXBlSHRtbENoYXIgPSBiYXNlUHJvcGVydHlPZihodG1sVW5lc2NhcGVzKTtcblxuICAvKipcbiAgICogR2V0cyB0aGUgc2l6ZSBvZiBhIFVuaWNvZGUgYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgc2l6ZS5cbiAgICovXG4gIGZ1bmN0aW9uIHVuaWNvZGVTaXplKHN0cmluZykge1xuICAgIHZhciByZXN1bHQgPSByZVVuaWNvZGUubGFzdEluZGV4ID0gMDtcbiAgICB3aGlsZSAocmVVbmljb2RlLnRlc3Qoc3RyaW5nKSkge1xuICAgICAgKytyZXN1bHQ7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBVbmljb2RlIGBzdHJpbmdgIHRvIGFuIGFycmF5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiB1bmljb2RlVG9BcnJheShzdHJpbmcpIHtcbiAgICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlVW5pY29kZSkgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogU3BsaXRzIGEgVW5pY29kZSBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3b3JkcyBvZiBgc3RyaW5nYC5cbiAgICovXG4gIGZ1bmN0aW9uIHVuaWNvZGVXb3JkcyhzdHJpbmcpIHtcbiAgICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlVW5pY29kZVdvcmQpIHx8IFtdO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBwcmlzdGluZSBgbG9kYXNoYCBmdW5jdGlvbiB1c2luZyB0aGUgYGNvbnRleHRgIG9iamVjdC5cbiAgICpcbiAgICogQHN0YXRpY1xuICAgKiBAbWVtYmVyT2YgX1xuICAgKiBAc2luY2UgMS4xLjBcbiAgICogQGNhdGVnb3J5IFV0aWxcbiAgICogQHBhcmFtIHtPYmplY3R9IFtjb250ZXh0PXJvb3RdIFRoZSBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGEgbmV3IGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBfLm1peGluKHsgJ2Zvbyc6IF8uY29uc3RhbnQoJ2ZvbycpIH0pO1xuICAgKlxuICAgKiB2YXIgbG9kYXNoID0gXy5ydW5JbkNvbnRleHQoKTtcbiAgICogbG9kYXNoLm1peGluKHsgJ2Jhcic6IGxvZGFzaC5jb25zdGFudCgnYmFyJykgfSk7XG4gICAqXG4gICAqIF8uaXNGdW5jdGlvbihfLmZvbyk7XG4gICAqIC8vID0+IHRydWVcbiAgICogXy5pc0Z1bmN0aW9uKF8uYmFyKTtcbiAgICogLy8gPT4gZmFsc2VcbiAgICpcbiAgICogbG9kYXNoLmlzRnVuY3Rpb24obG9kYXNoLmZvbyk7XG4gICAqIC8vID0+IGZhbHNlXG4gICAqIGxvZGFzaC5pc0Z1bmN0aW9uKGxvZGFzaC5iYXIpO1xuICAgKiAvLyA9PiB0cnVlXG4gICAqXG4gICAqIC8vIENyZWF0ZSBhIHN1cGVkLXVwIGBkZWZlcmAgaW4gTm9kZS5qcy5cbiAgICogdmFyIGRlZmVyID0gXy5ydW5JbkNvbnRleHQoeyAnc2V0VGltZW91dCc6IHNldEltbWVkaWF0ZSB9KS5kZWZlcjtcbiAgICovXG4gIHZhciBydW5JbkNvbnRleHQgPSAoZnVuY3Rpb24gcnVuSW5Db250ZXh0KGNvbnRleHQpIHtcbiAgICBjb250ZXh0ID0gY29udGV4dCA9PSBudWxsID8gcm9vdCA6IF8uZGVmYXVsdHMocm9vdC5PYmplY3QoKSwgY29udGV4dCwgXy5waWNrKHJvb3QsIGNvbnRleHRQcm9wcykpO1xuXG4gICAgLyoqIEJ1aWx0LWluIGNvbnN0cnVjdG9yIHJlZmVyZW5jZXMuICovXG4gICAgdmFyIEFycmF5ID0gY29udGV4dC5BcnJheSxcbiAgICAgICAgRGF0ZSA9IGNvbnRleHQuRGF0ZSxcbiAgICAgICAgRXJyb3IgPSBjb250ZXh0LkVycm9yLFxuICAgICAgICBGdW5jdGlvbiA9IGNvbnRleHQuRnVuY3Rpb24sXG4gICAgICAgIE1hdGggPSBjb250ZXh0Lk1hdGgsXG4gICAgICAgIE9iamVjdCA9IGNvbnRleHQuT2JqZWN0LFxuICAgICAgICBSZWdFeHAgPSBjb250ZXh0LlJlZ0V4cCxcbiAgICAgICAgU3RyaW5nID0gY29udGV4dC5TdHJpbmcsXG4gICAgICAgIFR5cGVFcnJvciA9IGNvbnRleHQuVHlwZUVycm9yO1xuXG4gICAgLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBhcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlLFxuICAgICAgICBmdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGUsXG4gICAgICAgIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBvdmVycmVhY2hpbmcgY29yZS1qcyBzaGltcy4gKi9cbiAgICB2YXIgY29yZUpzRGF0YSA9IGNvbnRleHRbJ19fY29yZS1qc19zaGFyZWRfXyddO1xuXG4gICAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgZGVjb21waWxlZCBzb3VyY2Ugb2YgZnVuY3Rpb25zLiAqL1xuICAgIHZhciBmdW5jVG9TdHJpbmcgPSBmdW5jUHJvdG8udG9TdHJpbmc7XG5cbiAgICAvKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbiAgICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAgIC8qKiBVc2VkIHRvIGdlbmVyYXRlIHVuaXF1ZSBJRHMuICovXG4gICAgdmFyIGlkQ291bnRlciA9IDA7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgbWV0aG9kcyBtYXNxdWVyYWRpbmcgYXMgbmF0aXZlLiAqL1xuICAgIHZhciBtYXNrU3JjS2V5ID0gKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHVpZCA9IC9bXi5dKyQvLmV4ZWMoY29yZUpzRGF0YSAmJiBjb3JlSnNEYXRhLmtleXMgJiYgY29yZUpzRGF0YS5rZXlzLklFX1BST1RPIHx8ICcnKTtcbiAgICAgIHJldHVybiB1aWQgPyAoJ1N5bWJvbChzcmMpXzEuJyArIHVpZCkgOiAnJztcbiAgICB9KCkpO1xuXG4gICAgLyoqXG4gICAgICogVXNlZCB0byByZXNvbHZlIHRoZVxuICAgICAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICAgICAqIG9mIHZhbHVlcy5cbiAgICAgKi9cbiAgICB2YXIgbmF0aXZlT2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuICAgIC8qKiBVc2VkIHRvIGluZmVyIHRoZSBgT2JqZWN0YCBjb25zdHJ1Y3Rvci4gKi9cbiAgICB2YXIgb2JqZWN0Q3RvclN0cmluZyA9IGZ1bmNUb1N0cmluZy5jYWxsKE9iamVjdCk7XG5cbiAgICAvKiogVXNlZCB0byByZXN0b3JlIHRoZSBvcmlnaW5hbCBgX2AgcmVmZXJlbmNlIGluIGBfLm5vQ29uZmxpY3RgLiAqL1xuICAgIHZhciBvbGREYXNoID0gcm9vdC5fO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGEgbWV0aG9kIGlzIG5hdGl2ZS4gKi9cbiAgICB2YXIgcmVJc05hdGl2ZSA9IFJlZ0V4cCgnXicgK1xuICAgICAgZnVuY1RvU3RyaW5nLmNhbGwoaGFzT3duUHJvcGVydHkpLnJlcGxhY2UocmVSZWdFeHBDaGFyLCAnXFxcXCQmJylcbiAgICAgIC5yZXBsYWNlKC9oYXNPd25Qcm9wZXJ0eXwoZnVuY3Rpb24pLio/KD89XFxcXFxcKCl8IGZvciAuKz8oPz1cXFxcXFxdKS9nLCAnJDEuKj8nKSArICckJ1xuICAgICk7XG5cbiAgICAvKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbiAgICB2YXIgQnVmZmVyID0gbW9kdWxlRXhwb3J0cyA/IGNvbnRleHQuQnVmZmVyIDogdW5kZWZpbmVkLFxuICAgICAgICBTeW1ib2wgPSBjb250ZXh0LlN5bWJvbCxcbiAgICAgICAgVWludDhBcnJheSA9IGNvbnRleHQuVWludDhBcnJheSxcbiAgICAgICAgYWxsb2NVbnNhZmUgPSBCdWZmZXIgPyBCdWZmZXIuYWxsb2NVbnNhZmUgOiB1bmRlZmluZWQsXG4gICAgICAgIGdldFByb3RvdHlwZSA9IG92ZXJBcmcoT2JqZWN0LmdldFByb3RvdHlwZU9mLCBPYmplY3QpLFxuICAgICAgICBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlLFxuICAgICAgICBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3RvLnByb3BlcnR5SXNFbnVtZXJhYmxlLFxuICAgICAgICBzcGxpY2UgPSBhcnJheVByb3RvLnNwbGljZSxcbiAgICAgICAgc3ByZWFkYWJsZVN5bWJvbCA9IFN5bWJvbCA/IFN5bWJvbC5pc0NvbmNhdFNwcmVhZGFibGUgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bUl0ZXJhdG9yID0gU3ltYm9sID8gU3ltYm9sLml0ZXJhdG9yIDogdW5kZWZpbmVkLFxuICAgICAgICBzeW1Ub1N0cmluZ1RhZyA9IFN5bWJvbCA/IFN5bWJvbC50b1N0cmluZ1RhZyA6IHVuZGVmaW5lZDtcblxuICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbigpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciBmdW5jID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2RlZmluZVByb3BlcnR5Jyk7XG4gICAgICAgIGZ1bmMoe30sICcnLCB7fSk7XG4gICAgICAgIHJldHVybiBmdW5jO1xuICAgICAgfSBjYXRjaCAoZSkge31cbiAgICB9KCkpO1xuXG4gICAgLyoqIE1vY2tlZCBidWlsdC1pbnMuICovXG4gICAgdmFyIGN0eENsZWFyVGltZW91dCA9IGNvbnRleHQuY2xlYXJUaW1lb3V0ICE9PSByb290LmNsZWFyVGltZW91dCAmJiBjb250ZXh0LmNsZWFyVGltZW91dCxcbiAgICAgICAgY3R4Tm93ID0gRGF0ZSAmJiBEYXRlLm5vdyAhPT0gcm9vdC5EYXRlLm5vdyAmJiBEYXRlLm5vdyxcbiAgICAgICAgY3R4U2V0VGltZW91dCA9IGNvbnRleHQuc2V0VGltZW91dCAhPT0gcm9vdC5zZXRUaW1lb3V0ICYmIGNvbnRleHQuc2V0VGltZW91dDtcblxuICAgIC8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbiAgICB2YXIgbmF0aXZlQ2VpbCA9IE1hdGguY2VpbCxcbiAgICAgICAgbmF0aXZlRmxvb3IgPSBNYXRoLmZsb29yLFxuICAgICAgICBuYXRpdmVHZXRTeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyxcbiAgICAgICAgbmF0aXZlSXNCdWZmZXIgPSBCdWZmZXIgPyBCdWZmZXIuaXNCdWZmZXIgOiB1bmRlZmluZWQsXG4gICAgICAgIG5hdGl2ZUlzRmluaXRlID0gY29udGV4dC5pc0Zpbml0ZSxcbiAgICAgICAgbmF0aXZlSm9pbiA9IGFycmF5UHJvdG8uam9pbixcbiAgICAgICAgbmF0aXZlS2V5cyA9IG92ZXJBcmcoT2JqZWN0LmtleXMsIE9iamVjdCksXG4gICAgICAgIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgICAgICBuYXRpdmVNaW4gPSBNYXRoLm1pbixcbiAgICAgICAgbmF0aXZlTm93ID0gRGF0ZS5ub3csXG4gICAgICAgIG5hdGl2ZVBhcnNlSW50ID0gY29udGV4dC5wYXJzZUludCxcbiAgICAgICAgbmF0aXZlUmFuZG9tID0gTWF0aC5yYW5kb20sXG4gICAgICAgIG5hdGl2ZVJldmVyc2UgPSBhcnJheVByb3RvLnJldmVyc2U7XG5cbiAgICAvKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG4gICAgdmFyIERhdGFWaWV3ID0gZ2V0TmF0aXZlKGNvbnRleHQsICdEYXRhVmlldycpLFxuICAgICAgICBNYXAgPSBnZXROYXRpdmUoY29udGV4dCwgJ01hcCcpLFxuICAgICAgICBQcm9taXNlID0gZ2V0TmF0aXZlKGNvbnRleHQsICdQcm9taXNlJyksXG4gICAgICAgIFNldCA9IGdldE5hdGl2ZShjb250ZXh0LCAnU2V0JyksXG4gICAgICAgIFdlYWtNYXAgPSBnZXROYXRpdmUoY29udGV4dCwgJ1dlYWtNYXAnKSxcbiAgICAgICAgbmF0aXZlQ3JlYXRlID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2NyZWF0ZScpO1xuXG4gICAgLyoqIFVzZWQgdG8gc3RvcmUgZnVuY3Rpb24gbWV0YWRhdGEuICovXG4gICAgdmFyIG1ldGFNYXAgPSBXZWFrTWFwICYmIG5ldyBXZWFrTWFwO1xuXG4gICAgLyoqIFVzZWQgdG8gbG9va3VwIHVubWluaWZpZWQgZnVuY3Rpb24gbmFtZXMuICovXG4gICAgdmFyIHJlYWxOYW1lcyA9IHt9O1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IG1hcHMsIHNldHMsIGFuZCB3ZWFrbWFwcy4gKi9cbiAgICB2YXIgZGF0YVZpZXdDdG9yU3RyaW5nID0gdG9Tb3VyY2UoRGF0YVZpZXcpLFxuICAgICAgICBtYXBDdG9yU3RyaW5nID0gdG9Tb3VyY2UoTWFwKSxcbiAgICAgICAgcHJvbWlzZUN0b3JTdHJpbmcgPSB0b1NvdXJjZShQcm9taXNlKSxcbiAgICAgICAgc2V0Q3RvclN0cmluZyA9IHRvU291cmNlKFNldCksXG4gICAgICAgIHdlYWtNYXBDdG9yU3RyaW5nID0gdG9Tb3VyY2UoV2Vha01hcCk7XG5cbiAgICAvKiogVXNlZCB0byBjb252ZXJ0IHN5bWJvbHMgdG8gcHJpbWl0aXZlcyBhbmQgc3RyaW5ncy4gKi9cbiAgICB2YXIgc3ltYm9sUHJvdG8gPSBTeW1ib2wgPyBTeW1ib2wucHJvdG90eXBlIDogdW5kZWZpbmVkLFxuICAgICAgICBzeW1ib2xWYWx1ZU9mID0gc3ltYm9sUHJvdG8gPyBzeW1ib2xQcm90by52YWx1ZU9mIDogdW5kZWZpbmVkLFxuICAgICAgICBzeW1ib2xUb1N0cmluZyA9IHN5bWJvbFByb3RvID8gc3ltYm9sUHJvdG8udG9TdHJpbmcgOiB1bmRlZmluZWQ7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYGxvZGFzaGAgb2JqZWN0IHdoaWNoIHdyYXBzIGB2YWx1ZWAgdG8gZW5hYmxlIGltcGxpY2l0IG1ldGhvZFxuICAgICAqIGNoYWluIHNlcXVlbmNlcy4gTWV0aG9kcyB0aGF0IG9wZXJhdGUgb24gYW5kIHJldHVybiBhcnJheXMsIGNvbGxlY3Rpb25zLFxuICAgICAqIGFuZCBmdW5jdGlvbnMgY2FuIGJlIGNoYWluZWQgdG9nZXRoZXIuIE1ldGhvZHMgdGhhdCByZXRyaWV2ZSBhIHNpbmdsZSB2YWx1ZVxuICAgICAqIG9yIG1heSByZXR1cm4gYSBwcmltaXRpdmUgdmFsdWUgd2lsbCBhdXRvbWF0aWNhbGx5IGVuZCB0aGUgY2hhaW4gc2VxdWVuY2VcbiAgICAgKiBhbmQgcmV0dXJuIHRoZSB1bndyYXBwZWQgdmFsdWUuIE90aGVyd2lzZSwgdGhlIHZhbHVlIG11c3QgYmUgdW53cmFwcGVkXG4gICAgICogd2l0aCBgXyN2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBFeHBsaWNpdCBjaGFpbiBzZXF1ZW5jZXMsIHdoaWNoIG11c3QgYmUgdW53cmFwcGVkIHdpdGggYF8jdmFsdWVgLCBtYXkgYmVcbiAgICAgKiBlbmFibGVkIHVzaW5nIGBfLmNoYWluYC5cbiAgICAgKlxuICAgICAqIFRoZSBleGVjdXRpb24gb2YgY2hhaW5lZCBtZXRob2RzIGlzIGxhenksIHRoYXQgaXMsIGl0J3MgZGVmZXJyZWQgdW50aWxcbiAgICAgKiBgXyN2YWx1ZWAgaXMgaW1wbGljaXRseSBvciBleHBsaWNpdGx5IGNhbGxlZC5cbiAgICAgKlxuICAgICAqIExhenkgZXZhbHVhdGlvbiBhbGxvd3Mgc2V2ZXJhbCBtZXRob2RzIHRvIHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uLlxuICAgICAqIFNob3J0Y3V0IGZ1c2lvbiBpcyBhbiBvcHRpbWl6YXRpb24gdG8gbWVyZ2UgaXRlcmF0ZWUgY2FsbHM7IHRoaXMgYXZvaWRzXG4gICAgICogdGhlIGNyZWF0aW9uIG9mIGludGVybWVkaWF0ZSBhcnJheXMgYW5kIGNhbiBncmVhdGx5IHJlZHVjZSB0aGUgbnVtYmVyIG9mXG4gICAgICogaXRlcmF0ZWUgZXhlY3V0aW9ucy4gU2VjdGlvbnMgb2YgYSBjaGFpbiBzZXF1ZW5jZSBxdWFsaWZ5IGZvciBzaG9ydGN1dFxuICAgICAqIGZ1c2lvbiBpZiB0aGUgc2VjdGlvbiBpcyBhcHBsaWVkIHRvIGFuIGFycmF5IGFuZCBpdGVyYXRlZXMgYWNjZXB0IG9ubHlcbiAgICAgKiBvbmUgYXJndW1lbnQuIFRoZSBoZXVyaXN0aWMgZm9yIHdoZXRoZXIgYSBzZWN0aW9uIHF1YWxpZmllcyBmb3Igc2hvcnRjdXRcbiAgICAgKiBmdXNpb24gaXMgc3ViamVjdCB0byBjaGFuZ2UuXG4gICAgICpcbiAgICAgKiBDaGFpbmluZyBpcyBzdXBwb3J0ZWQgaW4gY3VzdG9tIGJ1aWxkcyBhcyBsb25nIGFzIHRoZSBgXyN2YWx1ZWAgbWV0aG9kIGlzXG4gICAgICogZGlyZWN0bHkgb3IgaW5kaXJlY3RseSBpbmNsdWRlZCBpbiB0aGUgYnVpbGQuXG4gICAgICpcbiAgICAgKiBJbiBhZGRpdGlvbiB0byBsb2Rhc2ggbWV0aG9kcywgd3JhcHBlcnMgaGF2ZSBgQXJyYXlgIGFuZCBgU3RyaW5nYCBtZXRob2RzLlxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgYEFycmF5YCBtZXRob2RzIGFyZTpcbiAgICAgKiBgY29uY2F0YCwgYGpvaW5gLCBgcG9wYCwgYHB1c2hgLCBgc2hpZnRgLCBgc29ydGAsIGBzcGxpY2VgLCBhbmQgYHVuc2hpZnRgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBgU3RyaW5nYCBtZXRob2RzIGFyZTpcbiAgICAgKiBgcmVwbGFjZWAgYW5kIGBzcGxpdGBcbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIG1ldGhvZHMgdGhhdCBzdXBwb3J0IHNob3J0Y3V0IGZ1c2lvbiBhcmU6XG4gICAgICogYGF0YCwgYGNvbXBhY3RgLCBgZHJvcGAsIGBkcm9wUmlnaHRgLCBgZHJvcFdoaWxlYCwgYGZpbHRlcmAsIGBmaW5kYCxcbiAgICAgKiBgZmluZExhc3RgLCBgaGVhZGAsIGBpbml0aWFsYCwgYGxhc3RgLCBgbWFwYCwgYHJlamVjdGAsIGByZXZlcnNlYCwgYHNsaWNlYCxcbiAgICAgKiBgdGFpbGAsIGB0YWtlYCwgYHRha2VSaWdodGAsIGB0YWtlUmlnaHRXaGlsZWAsIGB0YWtlV2hpbGVgLCBhbmQgYHRvQXJyYXlgXG4gICAgICpcbiAgICAgKiBUaGUgY2hhaW5hYmxlIHdyYXBwZXIgbWV0aG9kcyBhcmU6XG4gICAgICogYGFmdGVyYCwgYGFyeWAsIGBhc3NpZ25gLCBgYXNzaWduSW5gLCBgYXNzaWduSW5XaXRoYCwgYGFzc2lnbldpdGhgLCBgYXRgLFxuICAgICAqIGBiZWZvcmVgLCBgYmluZGAsIGBiaW5kQWxsYCwgYGJpbmRLZXlgLCBgY2FzdEFycmF5YCwgYGNoYWluYCwgYGNodW5rYCxcbiAgICAgKiBgY29tbWl0YCwgYGNvbXBhY3RgLCBgY29uY2F0YCwgYGNvbmZvcm1zYCwgYGNvbnN0YW50YCwgYGNvdW50QnlgLCBgY3JlYXRlYCxcbiAgICAgKiBgY3VycnlgLCBgZGVib3VuY2VgLCBgZGVmYXVsdHNgLCBgZGVmYXVsdHNEZWVwYCwgYGRlZmVyYCwgYGRlbGF5YCxcbiAgICAgKiBgZGlmZmVyZW5jZWAsIGBkaWZmZXJlbmNlQnlgLCBgZGlmZmVyZW5jZVdpdGhgLCBgZHJvcGAsIGBkcm9wUmlnaHRgLFxuICAgICAqIGBkcm9wUmlnaHRXaGlsZWAsIGBkcm9wV2hpbGVgLCBgZXh0ZW5kYCwgYGV4dGVuZFdpdGhgLCBgZmlsbGAsIGBmaWx0ZXJgLFxuICAgICAqIGBmbGF0TWFwYCwgYGZsYXRNYXBEZWVwYCwgYGZsYXRNYXBEZXB0aGAsIGBmbGF0dGVuYCwgYGZsYXR0ZW5EZWVwYCxcbiAgICAgKiBgZmxhdHRlbkRlcHRoYCwgYGZsaXBgLCBgZmxvd2AsIGBmbG93UmlnaHRgLCBgZnJvbVBhaXJzYCwgYGZ1bmN0aW9uc2AsXG4gICAgICogYGZ1bmN0aW9uc0luYCwgYGdyb3VwQnlgLCBgaW5pdGlhbGAsIGBpbnRlcnNlY3Rpb25gLCBgaW50ZXJzZWN0aW9uQnlgLFxuICAgICAqIGBpbnRlcnNlY3Rpb25XaXRoYCwgYGludmVydGAsIGBpbnZlcnRCeWAsIGBpbnZva2VNYXBgLCBgaXRlcmF0ZWVgLCBga2V5QnlgLFxuICAgICAqIGBrZXlzYCwgYGtleXNJbmAsIGBtYXBgLCBgbWFwS2V5c2AsIGBtYXBWYWx1ZXNgLCBgbWF0Y2hlc2AsIGBtYXRjaGVzUHJvcGVydHlgLFxuICAgICAqIGBtZW1vaXplYCwgYG1lcmdlYCwgYG1lcmdlV2l0aGAsIGBtZXRob2RgLCBgbWV0aG9kT2ZgLCBgbWl4aW5gLCBgbmVnYXRlYCxcbiAgICAgKiBgbnRoQXJnYCwgYG9taXRgLCBgb21pdEJ5YCwgYG9uY2VgLCBgb3JkZXJCeWAsIGBvdmVyYCwgYG92ZXJBcmdzYCxcbiAgICAgKiBgb3ZlckV2ZXJ5YCwgYG92ZXJTb21lYCwgYHBhcnRpYWxgLCBgcGFydGlhbFJpZ2h0YCwgYHBhcnRpdGlvbmAsIGBwaWNrYCxcbiAgICAgKiBgcGlja0J5YCwgYHBsYW50YCwgYHByb3BlcnR5YCwgYHByb3BlcnR5T2ZgLCBgcHVsbGAsIGBwdWxsQWxsYCwgYHB1bGxBbGxCeWAsXG4gICAgICogYHB1bGxBbGxXaXRoYCwgYHB1bGxBdGAsIGBwdXNoYCwgYHJhbmdlYCwgYHJhbmdlUmlnaHRgLCBgcmVhcmdgLCBgcmVqZWN0YCxcbiAgICAgKiBgcmVtb3ZlYCwgYHJlc3RgLCBgcmV2ZXJzZWAsIGBzYW1wbGVTaXplYCwgYHNldGAsIGBzZXRXaXRoYCwgYHNodWZmbGVgLFxuICAgICAqIGBzbGljZWAsIGBzb3J0YCwgYHNvcnRCeWAsIGBzcGxpY2VgLCBgc3ByZWFkYCwgYHRhaWxgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLFxuICAgICAqIGB0YWtlUmlnaHRXaGlsZWAsIGB0YWtlV2hpbGVgLCBgdGFwYCwgYHRocm90dGxlYCwgYHRocnVgLCBgdG9BcnJheWAsXG4gICAgICogYHRvUGFpcnNgLCBgdG9QYWlyc0luYCwgYHRvUGF0aGAsIGB0b1BsYWluT2JqZWN0YCwgYHRyYW5zZm9ybWAsIGB1bmFyeWAsXG4gICAgICogYHVuaW9uYCwgYHVuaW9uQnlgLCBgdW5pb25XaXRoYCwgYHVuaXFgLCBgdW5pcUJ5YCwgYHVuaXFXaXRoYCwgYHVuc2V0YCxcbiAgICAgKiBgdW5zaGlmdGAsIGB1bnppcGAsIGB1bnppcFdpdGhgLCBgdXBkYXRlYCwgYHVwZGF0ZVdpdGhgLCBgdmFsdWVzYCxcbiAgICAgKiBgdmFsdWVzSW5gLCBgd2l0aG91dGAsIGB3cmFwYCwgYHhvcmAsIGB4b3JCeWAsIGB4b3JXaXRoYCwgYHppcGAsXG4gICAgICogYHppcE9iamVjdGAsIGB6aXBPYmplY3REZWVwYCwgYW5kIGB6aXBXaXRoYFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IGFyZSAqKm5vdCoqIGNoYWluYWJsZSBieSBkZWZhdWx0IGFyZTpcbiAgICAgKiBgYWRkYCwgYGF0dGVtcHRgLCBgY2FtZWxDYXNlYCwgYGNhcGl0YWxpemVgLCBgY2VpbGAsIGBjbGFtcGAsIGBjbG9uZWAsXG4gICAgICogYGNsb25lRGVlcGAsIGBjbG9uZURlZXBXaXRoYCwgYGNsb25lV2l0aGAsIGBjb25mb3Jtc1RvYCwgYGRlYnVycmAsXG4gICAgICogYGRlZmF1bHRUb2AsIGBkaXZpZGVgLCBgZWFjaGAsIGBlYWNoUmlnaHRgLCBgZW5kc1dpdGhgLCBgZXFgLCBgZXNjYXBlYCxcbiAgICAgKiBgZXNjYXBlUmVnRXhwYCwgYGV2ZXJ5YCwgYGZpbmRgLCBgZmluZEluZGV4YCwgYGZpbmRLZXlgLCBgZmluZExhc3RgLFxuICAgICAqIGBmaW5kTGFzdEluZGV4YCwgYGZpbmRMYXN0S2V5YCwgYGZpcnN0YCwgYGZsb29yYCwgYGZvckVhY2hgLCBgZm9yRWFjaFJpZ2h0YCxcbiAgICAgKiBgZm9ySW5gLCBgZm9ySW5SaWdodGAsIGBmb3JPd25gLCBgZm9yT3duUmlnaHRgLCBgZ2V0YCwgYGd0YCwgYGd0ZWAsIGBoYXNgLFxuICAgICAqIGBoYXNJbmAsIGBoZWFkYCwgYGlkZW50aXR5YCwgYGluY2x1ZGVzYCwgYGluZGV4T2ZgLCBgaW5SYW5nZWAsIGBpbnZva2VgLFxuICAgICAqIGBpc0FyZ3VtZW50c2AsIGBpc0FycmF5YCwgYGlzQXJyYXlCdWZmZXJgLCBgaXNBcnJheUxpa2VgLCBgaXNBcnJheUxpa2VPYmplY3RgLFxuICAgICAqIGBpc0Jvb2xlYW5gLCBgaXNCdWZmZXJgLCBgaXNEYXRlYCwgYGlzRWxlbWVudGAsIGBpc0VtcHR5YCwgYGlzRXF1YWxgLFxuICAgICAqIGBpc0VxdWFsV2l0aGAsIGBpc0Vycm9yYCwgYGlzRmluaXRlYCwgYGlzRnVuY3Rpb25gLCBgaXNJbnRlZ2VyYCwgYGlzTGVuZ3RoYCxcbiAgICAgKiBgaXNNYXBgLCBgaXNNYXRjaGAsIGBpc01hdGNoV2l0aGAsIGBpc05hTmAsIGBpc05hdGl2ZWAsIGBpc05pbGAsIGBpc051bGxgLFxuICAgICAqIGBpc051bWJlcmAsIGBpc09iamVjdGAsIGBpc09iamVjdExpa2VgLCBgaXNQbGFpbk9iamVjdGAsIGBpc1JlZ0V4cGAsXG4gICAgICogYGlzU2FmZUludGVnZXJgLCBgaXNTZXRgLCBgaXNTdHJpbmdgLCBgaXNVbmRlZmluZWRgLCBgaXNUeXBlZEFycmF5YCxcbiAgICAgKiBgaXNXZWFrTWFwYCwgYGlzV2Vha1NldGAsIGBqb2luYCwgYGtlYmFiQ2FzZWAsIGBsYXN0YCwgYGxhc3RJbmRleE9mYCxcbiAgICAgKiBgbG93ZXJDYXNlYCwgYGxvd2VyRmlyc3RgLCBgbHRgLCBgbHRlYCwgYG1heGAsIGBtYXhCeWAsIGBtZWFuYCwgYG1lYW5CeWAsXG4gICAgICogYG1pbmAsIGBtaW5CeWAsIGBtdWx0aXBseWAsIGBub0NvbmZsaWN0YCwgYG5vb3BgLCBgbm93YCwgYG50aGAsIGBwYWRgLFxuICAgICAqIGBwYWRFbmRgLCBgcGFkU3RhcnRgLCBgcGFyc2VJbnRgLCBgcG9wYCwgYHJhbmRvbWAsIGByZWR1Y2VgLCBgcmVkdWNlUmlnaHRgLFxuICAgICAqIGByZXBlYXRgLCBgcmVzdWx0YCwgYHJvdW5kYCwgYHJ1bkluQ29udGV4dGAsIGBzYW1wbGVgLCBgc2hpZnRgLCBgc2l6ZWAsXG4gICAgICogYHNuYWtlQ2FzZWAsIGBzb21lYCwgYHNvcnRlZEluZGV4YCwgYHNvcnRlZEluZGV4QnlgLCBgc29ydGVkTGFzdEluZGV4YCxcbiAgICAgKiBgc29ydGVkTGFzdEluZGV4QnlgLCBgc3RhcnRDYXNlYCwgYHN0YXJ0c1dpdGhgLCBgc3R1YkFycmF5YCwgYHN0dWJGYWxzZWAsXG4gICAgICogYHN0dWJPYmplY3RgLCBgc3R1YlN0cmluZ2AsIGBzdHViVHJ1ZWAsIGBzdWJ0cmFjdGAsIGBzdW1gLCBgc3VtQnlgLFxuICAgICAqIGB0ZW1wbGF0ZWAsIGB0aW1lc2AsIGB0b0Zpbml0ZWAsIGB0b0ludGVnZXJgLCBgdG9KU09OYCwgYHRvTGVuZ3RoYCxcbiAgICAgKiBgdG9Mb3dlcmAsIGB0b051bWJlcmAsIGB0b1NhZmVJbnRlZ2VyYCwgYHRvU3RyaW5nYCwgYHRvVXBwZXJgLCBgdHJpbWAsXG4gICAgICogYHRyaW1FbmRgLCBgdHJpbVN0YXJ0YCwgYHRydW5jYXRlYCwgYHVuZXNjYXBlYCwgYHVuaXF1ZUlkYCwgYHVwcGVyQ2FzZWAsXG4gICAgICogYHVwcGVyRmlyc3RgLCBgdmFsdWVgLCBhbmQgYHdvcmRzYFxuICAgICAqXG4gICAgICogQG5hbWUgX1xuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwIGluIGEgYGxvZGFzaGAgaW5zdGFuY2UuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHNxdWFyZShuKSB7XG4gICAgICogICByZXR1cm4gbiAqIG47XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyLCAzXSk7XG4gICAgICpcbiAgICAgKiAvLyBSZXR1cm5zIGFuIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiB3cmFwcGVkLnJlZHVjZShfLmFkZCk7XG4gICAgICogLy8gPT4gNlxuICAgICAqXG4gICAgICogLy8gUmV0dXJucyBhIHdyYXBwZWQgdmFsdWUuXG4gICAgICogdmFyIHNxdWFyZXMgPSB3cmFwcGVkLm1hcChzcXVhcmUpO1xuICAgICAqXG4gICAgICogXy5pc0FycmF5KHNxdWFyZXMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcy52YWx1ZSgpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbG9kYXNoKHZhbHVlKSB7XG4gICAgICBpZiAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiAhaXNBcnJheSh2YWx1ZSkgJiYgISh2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSkge1xuICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMb2Rhc2hXcmFwcGVyKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnX193cmFwcGVkX18nKSkge1xuICAgICAgICAgIHJldHVybiB3cmFwcGVyQ2xvbmUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNyZWF0ZWAgd2l0aG91dCBzdXBwb3J0IGZvciBhc3NpZ25pbmdcbiAgICAgKiBwcm9wZXJ0aWVzIHRvIHRoZSBjcmVhdGVkIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHByb3RvIFRoZSBvYmplY3QgdG8gaW5oZXJpdCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgdmFyIGJhc2VDcmVhdGUgPSAoZnVuY3Rpb24oKSB7XG4gICAgICBmdW5jdGlvbiBvYmplY3QoKSB7fVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHByb3RvKSB7XG4gICAgICAgIGlmICghaXNPYmplY3QocHJvdG8pKSB7XG4gICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChvYmplY3RDcmVhdGUpIHtcbiAgICAgICAgICByZXR1cm4gb2JqZWN0Q3JlYXRlKHByb3RvKTtcbiAgICAgICAgfVxuICAgICAgICBvYmplY3QucHJvdG90eXBlID0gcHJvdG87XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgb2JqZWN0O1xuICAgICAgICBvYmplY3QucHJvdG90eXBlID0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KCkpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZ1bmN0aW9uIHdob3NlIHByb3RvdHlwZSBjaGFpbiBzZXF1ZW5jZSB3cmFwcGVycyBpbmhlcml0IGZyb20uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VMb2Rhc2goKSB7XG4gICAgICAvLyBObyBvcGVyYXRpb24gcGVyZm9ybWVkLlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGNvbnN0cnVjdG9yIGZvciBjcmVhdGluZyBgbG9kYXNoYCB3cmFwcGVyIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbY2hhaW5BbGxdIEVuYWJsZSBleHBsaWNpdCBtZXRob2QgY2hhaW4gc2VxdWVuY2VzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIExvZGFzaFdyYXBwZXIodmFsdWUsIGNoYWluQWxsKSB7XG4gICAgICB0aGlzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgICB0aGlzLl9fYWN0aW9uc19fID0gW107XG4gICAgICB0aGlzLl9fY2hhaW5fXyA9ICEhY2hhaW5BbGw7XG4gICAgICB0aGlzLl9faW5kZXhfXyA9IDA7XG4gICAgICB0aGlzLl9fdmFsdWVzX18gPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQnkgZGVmYXVsdCwgdGhlIHRlbXBsYXRlIGRlbGltaXRlcnMgdXNlZCBieSBsb2Rhc2ggYXJlIGxpa2UgdGhvc2UgaW5cbiAgICAgKiBlbWJlZGRlZCBSdWJ5IChFUkIpIGFzIHdlbGwgYXMgRVMyMDE1IHRlbXBsYXRlIHN0cmluZ3MuIENoYW5nZSB0aGVcbiAgICAgKiBmb2xsb3dpbmcgdGVtcGxhdGUgc2V0dGluZ3MgdG8gdXNlIGFsdGVybmF0aXZlIGRlbGltaXRlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqL1xuICAgIGxvZGFzaC50ZW1wbGF0ZVNldHRpbmdzID0ge1xuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGBkYXRhYCBwcm9wZXJ0eSB2YWx1ZXMgdG8gYmUgSFRNTC1lc2NhcGVkLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdlc2NhcGUnOiByZUVzY2FwZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIGRldGVjdCBjb2RlIHRvIGJlIGV2YWx1YXRlZC5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSB7UmVnRXhwfVxuICAgICAgICovXG4gICAgICAnZXZhbHVhdGUnOiByZUV2YWx1YXRlLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGBkYXRhYCBwcm9wZXJ0eSB2YWx1ZXMgdG8gaW5qZWN0LlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdpbnRlcnBvbGF0ZSc6IHJlSW50ZXJwb2xhdGUsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byByZWZlcmVuY2UgdGhlIGRhdGEgb2JqZWN0IGluIHRoZSB0ZW1wbGF0ZSB0ZXh0LlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICAgKi9cbiAgICAgICd2YXJpYWJsZSc6ICcnLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gaW1wb3J0IHZhcmlhYmxlcyBpbnRvIHRoZSBjb21waWxlZCB0ZW1wbGF0ZS5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAgICovXG4gICAgICAnaW1wb3J0cyc6IHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQSByZWZlcmVuY2UgdG8gdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzLmltcG9ydHNcbiAgICAgICAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgICAgICAgKi9cbiAgICAgICAgJ18nOiBsb2Rhc2hcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gRW5zdXJlIHdyYXBwZXJzIGFyZSBpbnN0YW5jZXMgb2YgYGJhc2VMb2Rhc2hgLlxuICAgIGxvZGFzaC5wcm90b3R5cGUgPSBiYXNlTG9kYXNoLnByb3RvdHlwZTtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gbG9kYXNoO1xuXG4gICAgTG9kYXNoV3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMb2Rhc2hXcmFwcGVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IExvZGFzaFdyYXBwZXI7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbGF6eSB3cmFwcGVyIG9iamVjdCB3aGljaCB3cmFwcyBgdmFsdWVgIHRvIGVuYWJsZSBsYXp5IGV2YWx1YXRpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTGF6eVdyYXBwZXIodmFsdWUpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgICAgIHRoaXMuX19kaXJfXyA9IDE7XG4gICAgICB0aGlzLl9fZmlsdGVyZWRfXyA9IGZhbHNlO1xuICAgICAgdGhpcy5fX2l0ZXJhdGVlc19fID0gW107XG4gICAgICB0aGlzLl9fdGFrZUNvdW50X18gPSBNQVhfQVJSQVlfTEVOR1RIO1xuICAgICAgdGhpcy5fX3ZpZXdzX18gPSBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGxhenkgd3JhcHBlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsb25lXG4gICAgICogQG1lbWJlck9mIExhenlXcmFwcGVyXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIGBMYXp5V3JhcHBlcmAgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhenlDbG9uZSgpIHtcbiAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF6eVdyYXBwZXIodGhpcy5fX3dyYXBwZWRfXyk7XG4gICAgICByZXN1bHQuX19hY3Rpb25zX18gPSBjb3B5QXJyYXkodGhpcy5fX2FjdGlvbnNfXyk7XG4gICAgICByZXN1bHQuX19kaXJfXyA9IHRoaXMuX19kaXJfXztcbiAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSB0aGlzLl9fZmlsdGVyZWRfXztcbiAgICAgIHJlc3VsdC5fX2l0ZXJhdGVlc19fID0gY29weUFycmF5KHRoaXMuX19pdGVyYXRlZXNfXyk7XG4gICAgICByZXN1bHQuX190YWtlQ291bnRfXyA9IHRoaXMuX190YWtlQ291bnRfXztcbiAgICAgIHJlc3VsdC5fX3ZpZXdzX18gPSBjb3B5QXJyYXkodGhpcy5fX3ZpZXdzX18pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnNlcyB0aGUgZGlyZWN0aW9uIG9mIGxhenkgaXRlcmF0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSByZXZlcnNlXG4gICAgICogQG1lbWJlck9mIExhenlXcmFwcGVyXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IHJldmVyc2VkIGBMYXp5V3JhcHBlcmAgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhenlSZXZlcnNlKCkge1xuICAgICAgaWYgKHRoaXMuX19maWx0ZXJlZF9fKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgIHJlc3VsdC5fX2Rpcl9fID0gLTE7XG4gICAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0ID0gdGhpcy5jbG9uZSgpO1xuICAgICAgICByZXN1bHQuX19kaXJfXyAqPSAtMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgdGhlIHVud3JhcHBlZCB2YWx1ZSBmcm9tIGl0cyBsYXp5IHdyYXBwZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHZhbHVlXG4gICAgICogQG1lbWJlck9mIExhenlXcmFwcGVyXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXp5VmFsdWUoKSB7XG4gICAgICB2YXIgYXJyYXkgPSB0aGlzLl9fd3JhcHBlZF9fLnZhbHVlKCksXG4gICAgICAgICAgZGlyID0gdGhpcy5fX2Rpcl9fLFxuICAgICAgICAgIGlzQXJyID0gaXNBcnJheShhcnJheSksXG4gICAgICAgICAgaXNSaWdodCA9IGRpciA8IDAsXG4gICAgICAgICAgYXJyTGVuZ3RoID0gaXNBcnIgPyBhcnJheS5sZW5ndGggOiAwLFxuICAgICAgICAgIHZpZXcgPSBnZXRWaWV3KDAsIGFyckxlbmd0aCwgdGhpcy5fX3ZpZXdzX18pLFxuICAgICAgICAgIHN0YXJ0ID0gdmlldy5zdGFydCxcbiAgICAgICAgICBlbmQgPSB2aWV3LmVuZCxcbiAgICAgICAgICBsZW5ndGggPSBlbmQgLSBzdGFydCxcbiAgICAgICAgICBpbmRleCA9IGlzUmlnaHQgPyBlbmQgOiAoc3RhcnQgLSAxKSxcbiAgICAgICAgICBpdGVyYXRlZXMgPSB0aGlzLl9faXRlcmF0ZWVzX18sXG4gICAgICAgICAgaXRlckxlbmd0aCA9IGl0ZXJhdGVlcy5sZW5ndGgsXG4gICAgICAgICAgcmVzSW5kZXggPSAwLFxuICAgICAgICAgIHRha2VDb3VudCA9IG5hdGl2ZU1pbihsZW5ndGgsIHRoaXMuX190YWtlQ291bnRfXyk7XG5cbiAgICAgIGlmICghaXNBcnIgfHwgKCFpc1JpZ2h0ICYmIGFyckxlbmd0aCA9PSBsZW5ndGggJiYgdGFrZUNvdW50ID09IGxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VXcmFwcGVyVmFsdWUoYXJyYXksIHRoaXMuX19hY3Rpb25zX18pO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuXG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlIChsZW5ndGgtLSAmJiByZXNJbmRleCA8IHRha2VDb3VudCkge1xuICAgICAgICBpbmRleCArPSBkaXI7XG5cbiAgICAgICAgdmFyIGl0ZXJJbmRleCA9IC0xLFxuICAgICAgICAgICAgdmFsdWUgPSBhcnJheVtpbmRleF07XG5cbiAgICAgICAgd2hpbGUgKCsraXRlckluZGV4IDwgaXRlckxlbmd0aCkge1xuICAgICAgICAgIHZhciBkYXRhID0gaXRlcmF0ZWVzW2l0ZXJJbmRleF0sXG4gICAgICAgICAgICAgIGl0ZXJhdGVlID0gZGF0YS5pdGVyYXRlZSxcbiAgICAgICAgICAgICAgdHlwZSA9IGRhdGEudHlwZSxcbiAgICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgICAgICBpZiAodHlwZSA9PSBMQVpZX01BUF9GTEFHKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGNvbXB1dGVkO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIWNvbXB1dGVkKSB7XG4gICAgICAgICAgICBpZiAodHlwZSA9PSBMQVpZX0ZJTFRFUl9GTEFHKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBFbnN1cmUgYExhenlXcmFwcGVyYCBpcyBhbiBpbnN0YW5jZSBvZiBgYmFzZUxvZGFzaGAuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlID0gYmFzZUNyZWF0ZShiYXNlTG9kYXNoLnByb3RvdHlwZSk7XG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTGF6eVdyYXBwZXI7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgaGFzaCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEhhc2goZW50cmllcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gZW50cmllcyA9PSBudWxsID8gMCA6IGVudHJpZXMubGVuZ3RoO1xuXG4gICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBoYXNoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBIYXNoXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaENsZWFyKCkge1xuICAgICAgdGhpcy5fX2RhdGFfXyA9IG5hdGl2ZUNyZWF0ZSA/IG5hdGl2ZUNyZWF0ZShudWxsKSA6IHt9O1xuICAgICAgdGhpcy5zaXplID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgaGFzaC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZGVsZXRlXG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gaGFzaCBUaGUgaGFzaCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc2hEZWxldGUoa2V5KSB7XG4gICAgICB2YXIgcmVzdWx0ID0gdGhpcy5oYXMoa2V5KSAmJiBkZWxldGUgdGhpcy5fX2RhdGFfX1trZXldO1xuICAgICAgdGhpcy5zaXplIC09IHJlc3VsdCA/IDEgOiAwO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBoYXNoIHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZ2V0XG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaEdldChrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIGlmIChuYXRpdmVDcmVhdGUpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGRhdGFba2V5XTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gSEFTSF9VTkRFRklORUQgPyB1bmRlZmluZWQgOiByZXN1bHQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChkYXRhLCBrZXkpID8gZGF0YVtrZXldIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIGhhc2ggdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgaGFzXG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaEhhcyhrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIHJldHVybiBuYXRpdmVDcmVhdGUgPyAoZGF0YVtrZXldICE9PSB1bmRlZmluZWQpIDogaGFzT3duUHJvcGVydHkuY2FsbChkYXRhLCBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGhhc2ggYGtleWAgdG8gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgc2V0XG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgaGFzaCBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIHRoaXMuc2l6ZSArPSB0aGlzLmhhcyhrZXkpID8gMCA6IDE7XG4gICAgICBkYXRhW2tleV0gPSAobmF0aXZlQ3JlYXRlICYmIHZhbHVlID09PSB1bmRlZmluZWQpID8gSEFTSF9VTkRFRklORUQgOiB2YWx1ZTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBIYXNoYC5cbiAgICBIYXNoLnByb3RvdHlwZS5jbGVhciA9IGhhc2hDbGVhcjtcbiAgICBIYXNoLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBoYXNoRGVsZXRlO1xuICAgIEhhc2gucHJvdG90eXBlLmdldCA9IGhhc2hHZXQ7XG4gICAgSGFzaC5wcm90b3R5cGUuaGFzID0gaGFzaEhhcztcbiAgICBIYXNoLnByb3RvdHlwZS5zZXQgPSBoYXNoU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBsaXN0IGNhY2hlIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTGlzdENhY2hlKGVudHJpZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgbGlzdCBjYWNoZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgY2xlYXJcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlQ2xlYXIoKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fID0gW107XG4gICAgICB0aGlzLnNpemUgPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxpc3RDYWNoZURlbGV0ZShrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBsYXN0SW5kZXggPSBkYXRhLmxlbmd0aCAtIDE7XG4gICAgICBpZiAoaW5kZXggPT0gbGFzdEluZGV4KSB7XG4gICAgICAgIGRhdGEucG9wKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzcGxpY2UuY2FsbChkYXRhLCBpbmRleCwgMSk7XG4gICAgICB9XG4gICAgICAtLXRoaXMuc2l6ZTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGxpc3QgY2FjaGUgdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGVudHJ5IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxpc3RDYWNoZUdldChrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gICAgICByZXR1cm4gaW5kZXggPCAwID8gdW5kZWZpbmVkIDogZGF0YVtpbmRleF1bMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxpc3RDYWNoZUhhcyhrZXkpIHtcbiAgICAgIHJldHVybiBhc3NvY0luZGV4T2YodGhpcy5fX2RhdGFfXywga2V5KSA+IC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGxpc3QgY2FjaGUgYGtleWAgdG8gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgc2V0XG4gICAgICogQG1lbWJlck9mIExpc3RDYWNoZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBsaXN0IGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxpc3RDYWNoZVNldChrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICAgICAgaW5kZXggPSBhc3NvY0luZGV4T2YoZGF0YSwga2V5KTtcblxuICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICArK3RoaXMuc2l6ZTtcbiAgICAgICAgZGF0YS5wdXNoKFtrZXksIHZhbHVlXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkYXRhW2luZGV4XVsxXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gQWRkIG1ldGhvZHMgdG8gYExpc3RDYWNoZWAuXG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5jbGVhciA9IGxpc3RDYWNoZUNsZWFyO1xuICAgIExpc3RDYWNoZS5wcm90b3R5cGVbJ2RlbGV0ZSddID0gbGlzdENhY2hlRGVsZXRlO1xuICAgIExpc3RDYWNoZS5wcm90b3R5cGUuZ2V0ID0gbGlzdENhY2hlR2V0O1xuICAgIExpc3RDYWNoZS5wcm90b3R5cGUuaGFzID0gbGlzdENhY2hlSGFzO1xuICAgIExpc3RDYWNoZS5wcm90b3R5cGUuc2V0ID0gbGlzdENhY2hlU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG1hcCBjYWNoZSBvYmplY3QgdG8gc3RvcmUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBNYXBDYWNoZShlbnRyaWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBlbnRyaWVzID09IG51bGwgPyAwIDogZW50cmllcy5sZW5ndGg7XG5cbiAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgICAgICB0aGlzLnNldChlbnRyeVswXSwgZW50cnlbMV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIG1hcC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgY2xlYXJcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBDYWNoZUNsZWFyKCkge1xuICAgICAgdGhpcy5zaXplID0gMDtcbiAgICAgIHRoaXMuX19kYXRhX18gPSB7XG4gICAgICAgICdoYXNoJzogbmV3IEhhc2gsXG4gICAgICAgICdtYXAnOiBuZXcgKE1hcCB8fCBMaXN0Q2FjaGUpLFxuICAgICAgICAnc3RyaW5nJzogbmV3IEhhc2hcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIG1hcC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZGVsZXRlXG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlRGVsZXRlKGtleSkge1xuICAgICAgdmFyIHJlc3VsdCA9IGdldE1hcERhdGEodGhpcywga2V5KVsnZGVsZXRlJ10oa2V5KTtcbiAgICAgIHRoaXMuc2l6ZSAtPSByZXN1bHQgPyAxIDogMDtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbWFwIHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZ2V0XG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGVudHJ5IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlR2V0KGtleSkge1xuICAgICAgcmV0dXJuIGdldE1hcERhdGEodGhpcywga2V5KS5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYSBtYXAgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgaGFzXG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlSGFzKGtleSkge1xuICAgICAgcmV0dXJuIGdldE1hcERhdGEodGhpcywga2V5KS5oYXMoa2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBtYXAgYGtleWAgdG8gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgc2V0XG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG1hcCBjYWNoZSBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBDYWNoZVNldChrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgZGF0YSA9IGdldE1hcERhdGEodGhpcywga2V5KSxcbiAgICAgICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gICAgICBkYXRhLnNldChrZXksIHZhbHVlKTtcbiAgICAgIHRoaXMuc2l6ZSArPSBkYXRhLnNpemUgPT0gc2l6ZSA/IDAgOiAxO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gQWRkIG1ldGhvZHMgdG8gYE1hcENhY2hlYC5cbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuY2xlYXIgPSBtYXBDYWNoZUNsZWFyO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBtYXBDYWNoZURlbGV0ZTtcbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuZ2V0ID0gbWFwQ2FjaGVHZXQ7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlLmhhcyA9IG1hcENhY2hlSGFzO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZS5zZXQgPSBtYXBDYWNoZVNldDtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBjYWNoZSBvYmplY3QgdG8gc3RvcmUgdW5pcXVlIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBTZXRDYWNoZSh2YWx1ZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHZhbHVlcyA9PSBudWxsID8gMCA6IHZhbHVlcy5sZW5ndGg7XG5cbiAgICAgIHRoaXMuX19kYXRhX18gPSBuZXcgTWFwQ2FjaGU7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB0aGlzLmFkZCh2YWx1ZXNbaW5kZXhdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGB2YWx1ZWAgdG8gdGhlIGFycmF5IGNhY2hlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBhZGRcbiAgICAgKiBAbWVtYmVyT2YgU2V0Q2FjaGVcbiAgICAgKiBAYWxpYXMgcHVzaFxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNhY2hlLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldENhY2hlQWRkKHZhbHVlKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fLnNldCh2YWx1ZSwgSEFTSF9VTkRFRklORUQpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gdGhlIGFycmF5IGNhY2hlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgU2V0Q2FjaGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRDYWNoZUhhcyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX19kYXRhX18uaGFzKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgU2V0Q2FjaGVgLlxuICAgIFNldENhY2hlLnByb3RvdHlwZS5hZGQgPSBTZXRDYWNoZS5wcm90b3R5cGUucHVzaCA9IHNldENhY2hlQWRkO1xuICAgIFNldENhY2hlLnByb3RvdHlwZS5oYXMgPSBzZXRDYWNoZUhhcztcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzdGFjayBjYWNoZSBvYmplY3QgdG8gc3RvcmUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBTdGFjayhlbnRyaWVzKSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18gPSBuZXcgTGlzdENhY2hlKGVudHJpZXMpO1xuICAgICAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIHN0YWNrLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrQ2xlYXIoKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fID0gbmV3IExpc3RDYWNoZTtcbiAgICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIHN0YWNrLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgU3RhY2tcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tEZWxldGUoa2V5KSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICAgICAgcmVzdWx0ID0gZGF0YVsnZGVsZXRlJ10oa2V5KTtcblxuICAgICAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzdGFjayB2YWx1ZSBmb3IgYGtleWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGdldFxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja0dldChrZXkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9fZGF0YV9fLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIHN0YWNrIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGhhc1xuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja0hhcyhrZXkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9fZGF0YV9fLmhhcyhrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHN0YWNrIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHNldFxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBzdGFjayBjYWNoZSBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja1NldChrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX187XG4gICAgICBpZiAoZGF0YSBpbnN0YW5jZW9mIExpc3RDYWNoZSkge1xuICAgICAgICB2YXIgcGFpcnMgPSBkYXRhLl9fZGF0YV9fO1xuICAgICAgICBpZiAoIU1hcCB8fCAocGFpcnMubGVuZ3RoIDwgTEFSR0VfQVJSQVlfU0laRSAtIDEpKSB7XG4gICAgICAgICAgcGFpcnMucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICAgIHRoaXMuc2l6ZSA9ICsrZGF0YS5zaXplO1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSB0aGlzLl9fZGF0YV9fID0gbmV3IE1hcENhY2hlKHBhaXJzKTtcbiAgICAgIH1cbiAgICAgIGRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gQWRkIG1ldGhvZHMgdG8gYFN0YWNrYC5cbiAgICBTdGFjay5wcm90b3R5cGUuY2xlYXIgPSBzdGFja0NsZWFyO1xuICAgIFN0YWNrLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBzdGFja0RlbGV0ZTtcbiAgICBTdGFjay5wcm90b3R5cGUuZ2V0ID0gc3RhY2tHZXQ7XG4gICAgU3RhY2sucHJvdG90eXBlLmhhcyA9IHN0YWNrSGFzO1xuICAgIFN0YWNrLnByb3RvdHlwZS5zZXQgPSBzdGFja1NldDtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgdGhlIGFycmF5LWxpa2UgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpbmhlcml0ZWQgU3BlY2lmeSByZXR1cm5pbmcgaW5oZXJpdGVkIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlMaWtlS2V5cyh2YWx1ZSwgaW5oZXJpdGVkKSB7XG4gICAgICB2YXIgaXNBcnIgPSBpc0FycmF5KHZhbHVlKSxcbiAgICAgICAgICBpc0FyZyA9ICFpc0FyciAmJiBpc0FyZ3VtZW50cyh2YWx1ZSksXG4gICAgICAgICAgaXNCdWZmID0gIWlzQXJyICYmICFpc0FyZyAmJiBpc0J1ZmZlcih2YWx1ZSksXG4gICAgICAgICAgaXNUeXBlID0gIWlzQXJyICYmICFpc0FyZyAmJiAhaXNCdWZmICYmIGlzVHlwZWRBcnJheSh2YWx1ZSksXG4gICAgICAgICAgc2tpcEluZGV4ZXMgPSBpc0FyciB8fCBpc0FyZyB8fCBpc0J1ZmYgfHwgaXNUeXBlLFxuICAgICAgICAgIHJlc3VsdCA9IHNraXBJbmRleGVzID8gYmFzZVRpbWVzKHZhbHVlLmxlbmd0aCwgU3RyaW5nKSA6IFtdLFxuICAgICAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGg7XG5cbiAgICAgIGZvciAodmFyIGtleSBpbiB2YWx1ZSkge1xuICAgICAgICBpZiAoKGluaGVyaXRlZCB8fCBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBrZXkpKSAmJlxuICAgICAgICAgICAgIShza2lwSW5kZXhlcyAmJiAoXG4gICAgICAgICAgICAgICAvLyBTYWZhcmkgOSBoYXMgZW51bWVyYWJsZSBgYXJndW1lbnRzLmxlbmd0aGAgaW4gc3RyaWN0IG1vZGUuXG4gICAgICAgICAgICAgICBrZXkgPT0gJ2xlbmd0aCcgfHxcbiAgICAgICAgICAgICAgIC8vIE5vZGUuanMgMC4xMCBoYXMgZW51bWVyYWJsZSBub24taW5kZXggcHJvcGVydGllcyBvbiBidWZmZXJzLlxuICAgICAgICAgICAgICAgKGlzQnVmZiAmJiAoa2V5ID09ICdvZmZzZXQnIHx8IGtleSA9PSAncGFyZW50JykpIHx8XG4gICAgICAgICAgICAgICAvLyBQaGFudG9tSlMgMiBoYXMgZW51bWVyYWJsZSBub24taW5kZXggcHJvcGVydGllcyBvbiB0eXBlZCBhcnJheXMuXG4gICAgICAgICAgICAgICAoaXNUeXBlICYmIChrZXkgPT0gJ2J1ZmZlcicgfHwga2V5ID09ICdieXRlTGVuZ3RoJyB8fCBrZXkgPT0gJ2J5dGVPZmZzZXQnKSkgfHxcbiAgICAgICAgICAgICAgIC8vIFNraXAgaW5kZXggcHJvcGVydGllcy5cbiAgICAgICAgICAgICAgIGlzSW5kZXgoa2V5LCBsZW5ndGgpXG4gICAgICAgICAgICApKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNhbXBsZWAgZm9yIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmFuZG9tIGVsZW1lbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlTYW1wbGUoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYXJyYXlbYmFzZVJhbmRvbSgwLCBsZW5ndGggLSAxKV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNhbXBsZVNpemVgIGZvciBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzYW1wbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byBzYW1wbGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJyYXlTYW1wbGVTaXplKGFycmF5LCBuKSB7XG4gICAgICByZXR1cm4gc2h1ZmZsZVNlbGYoY29weUFycmF5KGFycmF5KSwgYmFzZUNsYW1wKG4sIDAsIGFycmF5Lmxlbmd0aCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5zaHVmZmxlYCBmb3IgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2h1ZmZsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzaHVmZmxlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVNodWZmbGUoYXJyYXkpIHtcbiAgICAgIHJldHVybiBzaHVmZmxlU2VsZihjb3B5QXJyYXkoYXJyYXkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGFzc2lnblZhbHVlYCBleGNlcHQgdGhhdCBpdCBkb2Vzbid0IGFzc2lnblxuICAgICAqIGB1bmRlZmluZWRgIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGFzc2lnbi5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICAgIGlmICgodmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhZXEob2JqZWN0W2tleV0sIHZhbHVlKSkgfHxcbiAgICAgICAgICAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSkge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ25zIGB2YWx1ZWAgdG8gYGtleWAgb2YgYG9iamVjdGAgaWYgdGhlIGV4aXN0aW5nIHZhbHVlIGlzIG5vdCBlcXVpdmFsZW50XG4gICAgICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBhc3NpZ24uXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgICBpZiAoIShoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSAmJiBlcShvYmpWYWx1ZSwgdmFsdWUpKSB8fFxuICAgICAgICAgICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpKSB7XG4gICAgICAgIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBga2V5YCBpcyBmb3VuZCBpbiBgYXJyYXlgIG9mIGtleS12YWx1ZSBwYWlycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSBrZXkgVGhlIGtleSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzb2NJbmRleE9mKGFycmF5LCBrZXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgaWYgKGVxKGFycmF5W2xlbmd0aF1bMF0sIGtleSkpIHtcbiAgICAgICAgICByZXR1cm4gbGVuZ3RoO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWdncmVnYXRlcyBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmAgb24gYGFjY3VtdWxhdG9yYCB3aXRoIGtleXMgdHJhbnNmb3JtZWRcbiAgICAgKiBieSBgaXRlcmF0ZWVgIGFuZCB2YWx1ZXMgc2V0IGJ5IGBzZXR0ZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSBrZXlzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBhY2N1bXVsYXRvciBUaGUgaW5pdGlhbCBhZ2dyZWdhdGVkIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQWdncmVnYXRvcihjb2xsZWN0aW9uLCBzZXR0ZXIsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICBzZXR0ZXIoYWNjdW11bGF0b3IsIHZhbHVlLCBpdGVyYXRlZSh2YWx1ZSksIGNvbGxlY3Rpb24pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXNzaWduYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXNcbiAgICAgKiBvciBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBc3NpZ24ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgY29weU9iamVjdChzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5hc3NpZ25JbmAgd2l0aG91dCBzdXBwb3J0IGZvciBtdWx0aXBsZSBzb3VyY2VzXG4gICAgICogb3IgYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXNzaWduSW4ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgY29weU9iamVjdChzb3VyY2UsIGtleXNJbihzb3VyY2UpLCBvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBhc3NpZ25WYWx1ZWAgYW5kIGBhc3NpZ25NZXJnZVZhbHVlYCB3aXRob3V0XG4gICAgICogdmFsdWUgY2hlY2tzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gICAgICBpZiAoa2V5ID09ICdfX3Byb3RvX18nICYmIGRlZmluZVByb3BlcnR5KSB7XG4gICAgICAgIGRlZmluZVByb3BlcnR5KG9iamVjdCwga2V5LCB7XG4gICAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXG4gICAgICAgICAgJ2VudW1lcmFibGUnOiB0cnVlLFxuICAgICAgICAgICd2YWx1ZSc6IHZhbHVlLFxuICAgICAgICAgICd3cml0YWJsZSc6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmF0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGluZGl2aWR1YWwgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aHMgVGhlIHByb3BlcnR5IHBhdGhzIHRvIHBpY2suXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBwaWNrZWQgZWxlbWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUF0KG9iamVjdCwgcGF0aHMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGhzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpLFxuICAgICAgICAgIHNraXAgPSBvYmplY3QgPT0gbnVsbDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IHNraXAgPyB1bmRlZmluZWQgOiBnZXQob2JqZWN0LCBwYXRoc1tpbmRleF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jbGFtcGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gY2xhbXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsb3dlcl0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY2xhbXBlZCBudW1iZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNsYW1wKG51bWJlciwgbG93ZXIsIHVwcGVyKSB7XG4gICAgICBpZiAobnVtYmVyID09PSBudW1iZXIpIHtcbiAgICAgICAgaWYgKHVwcGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBudW1iZXIgPSBudW1iZXIgPD0gdXBwZXIgPyBudW1iZXIgOiB1cHBlcjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG93ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG51bWJlciA9IG51bWJlciA+PSBsb3dlciA/IG51bWJlciA6IGxvd2VyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVtYmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNsb25lYCBhbmQgYF8uY2xvbmVEZWVwYCB3aGljaCB0cmFja3NcbiAgICAgKiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLlxuICAgICAqICAxIC0gRGVlcCBjbG9uZVxuICAgICAqICAyIC0gRmxhdHRlbiBpbmhlcml0ZWQgcHJvcGVydGllc1xuICAgICAqICA0IC0gQ2xvbmUgc3ltYm9sc1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtrZXldIFRoZSBrZXkgb2YgYHZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIHBhcmVudCBvYmplY3Qgb2YgYHZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIG9iamVjdHMgYW5kIHRoZWlyIGNsb25lIGNvdW50ZXJwYXJ0cy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDbG9uZSh2YWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwga2V5LCBvYmplY3QsIHN0YWNrKSB7XG4gICAgICB2YXIgcmVzdWx0LFxuICAgICAgICAgIGlzRGVlcCA9IGJpdG1hc2sgJiBDTE9ORV9ERUVQX0ZMQUcsXG4gICAgICAgICAgaXNGbGF0ID0gYml0bWFzayAmIENMT05FX0ZMQVRfRkxBRyxcbiAgICAgICAgICBpc0Z1bGwgPSBiaXRtYXNrICYgQ0xPTkVfU1lNQk9MU19GTEFHO1xuXG4gICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICByZXN1bHQgPSBvYmplY3QgPyBjdXN0b21pemVyKHZhbHVlLCBrZXksIG9iamVjdCwgc3RhY2spIDogY3VzdG9taXplcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpO1xuICAgICAgaWYgKGlzQXJyKSB7XG4gICAgICAgIHJlc3VsdCA9IGluaXRDbG9uZUFycmF5KHZhbHVlKTtcbiAgICAgICAgaWYgKCFpc0RlZXApIHtcbiAgICAgICAgICByZXR1cm4gY29weUFycmF5KHZhbHVlLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdGFnID0gZ2V0VGFnKHZhbHVlKSxcbiAgICAgICAgICAgIGlzRnVuYyA9IHRhZyA9PSBmdW5jVGFnIHx8IHRhZyA9PSBnZW5UYWc7XG5cbiAgICAgICAgaWYgKGlzQnVmZmVyKHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBjbG9uZUJ1ZmZlcih2YWx1ZSwgaXNEZWVwKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFnID09IG9iamVjdFRhZyB8fCB0YWcgPT0gYXJnc1RhZyB8fCAoaXNGdW5jICYmICFvYmplY3QpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gKGlzRmxhdCB8fCBpc0Z1bmMpID8ge30gOiBpbml0Q2xvbmVPYmplY3QodmFsdWUpO1xuICAgICAgICAgIGlmICghaXNEZWVwKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNGbGF0XG4gICAgICAgICAgICAgID8gY29weVN5bWJvbHNJbih2YWx1ZSwgYmFzZUFzc2lnbkluKHJlc3VsdCwgdmFsdWUpKVxuICAgICAgICAgICAgICA6IGNvcHlTeW1ib2xzKHZhbHVlLCBiYXNlQXNzaWduKHJlc3VsdCwgdmFsdWUpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFjbG9uZWFibGVUYWdzW3RhZ10pIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QgPyB2YWx1ZSA6IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBpbml0Q2xvbmVCeVRhZyh2YWx1ZSwgdGFnLCBpc0RlZXApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBDaGVjayBmb3IgY2lyY3VsYXIgcmVmZXJlbmNlcyBhbmQgcmV0dXJuIGl0cyBjb3JyZXNwb25kaW5nIGNsb25lLlxuICAgICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICAgIHZhciBzdGFja2VkID0gc3RhY2suZ2V0KHZhbHVlKTtcbiAgICAgIGlmIChzdGFja2VkKSB7XG4gICAgICAgIHJldHVybiBzdGFja2VkO1xuICAgICAgfVxuICAgICAgc3RhY2suc2V0KHZhbHVlLCByZXN1bHQpO1xuXG4gICAgICBpZiAoaXNTZXQodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24oc3ViVmFsdWUpIHtcbiAgICAgICAgICByZXN1bHQuYWRkKGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3ViVmFsdWUsIHZhbHVlLCBzdGFjaykpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoaXNNYXAodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24oc3ViVmFsdWUsIGtleSkge1xuICAgICAgICAgIHJlc3VsdC5zZXQoa2V5LCBiYXNlQ2xvbmUoc3ViVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGtleSwgdmFsdWUsIHN0YWNrKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB2YXIga2V5c0Z1bmMgPSBpc0Z1bGxcbiAgICAgICAgPyAoaXNGbGF0ID8gZ2V0QWxsS2V5c0luIDogZ2V0QWxsS2V5cylcbiAgICAgICAgOiAoaXNGbGF0ID8ga2V5c0luIDoga2V5cyk7XG5cbiAgICAgIHZhciBwcm9wcyA9IGlzQXJyID8gdW5kZWZpbmVkIDoga2V5c0Z1bmModmFsdWUpO1xuICAgICAgYXJyYXlFYWNoKHByb3BzIHx8IHZhbHVlLCBmdW5jdGlvbihzdWJWYWx1ZSwga2V5KSB7XG4gICAgICAgIGlmIChwcm9wcykge1xuICAgICAgICAgIGtleSA9IHN1YlZhbHVlO1xuICAgICAgICAgIHN1YlZhbHVlID0gdmFsdWVba2V5XTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBwb3B1bGF0ZSBjbG9uZSAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBhc3NpZ25WYWx1ZShyZXN1bHQsIGtleSwgYmFzZUNsb25lKHN1YlZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBrZXksIHZhbHVlLCBzdGFjaykpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNvbmZvcm1zYCB3aGljaCBkb2Vzbid0IGNsb25lIGBzb3VyY2VgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgcHJlZGljYXRlcyB0byBjb25mb3JtIHRvLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNvbmZvcm1zKHNvdXJjZSkge1xuICAgICAgdmFyIHByb3BzID0ga2V5cyhzb3VyY2UpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gYmFzZUNvbmZvcm1zVG8ob2JqZWN0LCBzb3VyY2UsIHByb3BzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY29uZm9ybXNUb2Agd2hpY2ggYWNjZXB0cyBgcHJvcHNgIHRvIGNoZWNrLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgcHJlZGljYXRlcyB0byBjb25mb3JtIHRvLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBjb25mb3JtcywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDb25mb3Jtc1RvKG9iamVjdCwgc291cmNlLCBwcm9wcykge1xuICAgICAgdmFyIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gIWxlbmd0aDtcbiAgICAgIH1cbiAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tsZW5ndGhdLFxuICAgICAgICAgICAgcHJlZGljYXRlID0gc291cmNlW2tleV0sXG4gICAgICAgICAgICB2YWx1ZSA9IG9iamVjdFtrZXldO1xuXG4gICAgICAgIGlmICgodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSB8fCAhcHJlZGljYXRlKHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZGVsYXlgIGFuZCBgXy5kZWZlcmAgd2hpY2ggYWNjZXB0cyBgYXJnc2BcbiAgICAgKiB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkgaW52b2NhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gcHJvdmlkZSB0byBgZnVuY2AuXG4gICAgICogQHJldHVybnMge251bWJlcnxPYmplY3R9IFJldHVybnMgdGhlIHRpbWVyIGlkIG9yIHRpbWVvdXQgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VEZWxheShmdW5jLCB3YWl0LCBhcmdzKSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpIHsgZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpOyB9LCB3YWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uZGlmZmVyZW5jZWAgd2l0aG91dCBzdXBwb3J0XG4gICAgICogZm9yIGV4Y2x1ZGluZyBtdWx0aXBsZSBhcnJheXMgb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRGlmZmVyZW5jZShhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzLFxuICAgICAgICAgIGlzQ29tbW9uID0gdHJ1ZSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgdmFsdWVzTGVuZ3RoID0gdmFsdWVzLmxlbmd0aDtcblxuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVyYXRlZSkge1xuICAgICAgICB2YWx1ZXMgPSBhcnJheU1hcCh2YWx1ZXMsIGJhc2VVbmFyeShpdGVyYXRlZSkpO1xuICAgICAgfVxuICAgICAgaWYgKGNvbXBhcmF0b3IpIHtcbiAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzV2l0aDtcbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHZhbHVlcy5sZW5ndGggPj0gTEFSR0VfQVJSQVlfU0laRSkge1xuICAgICAgICBpbmNsdWRlcyA9IGNhY2hlSGFzO1xuICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICB2YWx1ZXMgPSBuZXcgU2V0Q2FjaGUodmFsdWVzKTtcbiAgICAgIH1cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA9PSBudWxsID8gdmFsdWUgOiBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgICAgdmFsdWUgPSAoY29tcGFyYXRvciB8fCB2YWx1ZSAhPT0gMCkgPyB2YWx1ZSA6IDA7XG4gICAgICAgIGlmIChpc0NvbW1vbiAmJiBjb21wdXRlZCA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICB2YXIgdmFsdWVzSW5kZXggPSB2YWx1ZXNMZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHZhbHVlc0luZGV4LS0pIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZXNbdmFsdWVzSW5kZXhdID09PSBjb21wdXRlZCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpbmNsdWRlcyh2YWx1ZXMsIGNvbXB1dGVkLCBjb21wYXJhdG9yKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JFYWNoYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqL1xuICAgIHZhciBiYXNlRWFjaCA9IGNyZWF0ZUJhc2VFYWNoKGJhc2VGb3JPd24pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yRWFjaFJpZ2h0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqL1xuICAgIHZhciBiYXNlRWFjaFJpZ2h0ID0gY3JlYXRlQmFzZUVhY2goYmFzZUZvck93blJpZ2h0LCB0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmV2ZXJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUV2ZXJ5KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0ID0gISFwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8ubWF4YCBhbmQgYF8ubWluYCB3aGljaCBhY2NlcHRzIGFcbiAgICAgKiBgY29tcGFyYXRvcmAgdG8gZGV0ZXJtaW5lIHRoZSBleHRyZW11bSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmF0b3IgVGhlIGNvbXBhcmF0b3IgdXNlZCB0byBjb21wYXJlIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZXh0cmVtdW0gdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUV4dHJlbXVtKGFycmF5LCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBjdXJyZW50ID0gaXRlcmF0ZWUodmFsdWUpO1xuXG4gICAgICAgIGlmIChjdXJyZW50ICE9IG51bGwgJiYgKGNvbXB1dGVkID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgPyAoY3VycmVudCA9PT0gY3VycmVudCAmJiAhaXNTeW1ib2woY3VycmVudCkpXG4gICAgICAgICAgICAgIDogY29tcGFyYXRvcihjdXJyZW50LCBjb21wdXRlZClcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICB2YXIgY29tcHV0ZWQgPSBjdXJyZW50LFxuICAgICAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5maWxsYCB3aXRob3V0IGFuIGl0ZXJhdGVlIGNhbGwgZ3VhcmQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWxsLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGZpbGwgYGFycmF5YCB3aXRoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHN0YXJ0ID0gdG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgc3RhcnQgPSAtc3RhcnQgPiBsZW5ndGggPyAwIDogKGxlbmd0aCArIHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGVuZCA9IChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiBsZW5ndGgpID8gbGVuZ3RoIDogdG9JbnRlZ2VyKGVuZCk7XG4gICAgICBpZiAoZW5kIDwgMCkge1xuICAgICAgICBlbmQgKz0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgZW5kID0gc3RhcnQgPiBlbmQgPyAwIDogdG9MZW5ndGgoZW5kKTtcbiAgICAgIHdoaWxlIChzdGFydCA8IGVuZCkge1xuICAgICAgICBhcnJheVtzdGFydCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbHRlcmAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZpbHRlcihjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mbGF0dGVuYCB3aXRoIHN1cHBvcnQgZm9yIHJlc3RyaWN0aW5nIGZsYXR0ZW5pbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkZXB0aCBUaGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGguXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbcHJlZGljYXRlPWlzRmxhdHRlbmFibGVdIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNTdHJpY3RdIFJlc3RyaWN0IHRvIHZhbHVlcyB0aGF0IHBhc3MgYHByZWRpY2F0ZWAgY2hlY2tzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHQ9W11dIFRoZSBpbml0aWFsIHJlc3VsdCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZsYXR0ZW4oYXJyYXksIGRlcHRoLCBwcmVkaWNhdGUsIGlzU3RyaWN0LCByZXN1bHQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgcHJlZGljYXRlIHx8IChwcmVkaWNhdGUgPSBpc0ZsYXR0ZW5hYmxlKTtcbiAgICAgIHJlc3VsdCB8fCAocmVzdWx0ID0gW10pO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICAgIGlmIChkZXB0aCA+IDAgJiYgcHJlZGljYXRlKHZhbHVlKSkge1xuICAgICAgICAgIGlmIChkZXB0aCA+IDEpIHtcbiAgICAgICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGZsYXR0ZW4gYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgICAgICBiYXNlRmxhdHRlbih2YWx1ZSwgZGVwdGggLSAxLCBwcmVkaWNhdGUsIGlzU3RyaWN0LCByZXN1bHQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcnJheVB1c2gocmVzdWx0LCB2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCFpc1N0cmljdCkge1xuICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBiYXNlRm9yT3duYCB3aGljaCBpdGVyYXRlcyBvdmVyIGBvYmplY3RgXG4gICAgICogcHJvcGVydGllcyByZXR1cm5lZCBieSBga2V5c0Z1bmNgIGFuZCBpbnZva2VzIGBpdGVyYXRlZWAgZm9yIGVhY2ggcHJvcGVydHkuXG4gICAgICogSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIHZhciBiYXNlRm9yID0gY3JlYXRlQmFzZUZvcigpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiYXNlRm9yYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIHByb3BlcnRpZXNcbiAgICAgKiBpbiB0aGUgb3Bwb3NpdGUgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgdmFyIGJhc2VGb3JSaWdodCA9IGNyZWF0ZUJhc2VGb3IodHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JPd25gIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZvck93bihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICYmIGJhc2VGb3Iob2JqZWN0LCBpdGVyYXRlZSwga2V5cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yT3duUmlnaHRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZvck93blJpZ2h0KG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgYmFzZUZvclJpZ2h0KG9iamVjdCwgaXRlcmF0ZWUsIGtleXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZ1bmN0aW9uc2Agd2hpY2ggY3JlYXRlcyBhbiBhcnJheSBvZlxuICAgICAqIGBvYmplY3RgIGZ1bmN0aW9uIHByb3BlcnR5IG5hbWVzIGZpbHRlcmVkIGZyb20gYHByb3BzYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGZpbHRlci5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGdW5jdGlvbnMob2JqZWN0LCBwcm9wcykge1xuICAgICAgcmV0dXJuIGFycmF5RmlsdGVyKHByb3BzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgcmV0dXJuIGlzRnVuY3Rpb24ob2JqZWN0W2tleV0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZ2V0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZmF1bHQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUdldChvYmplY3QsIHBhdGgpIHtcbiAgICAgIHBhdGggPSBjYXN0UGF0aChwYXRoLCBvYmplY3QpO1xuXG4gICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAob2JqZWN0ICE9IG51bGwgJiYgaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgb2JqZWN0ID0gb2JqZWN0W3RvS2V5KHBhdGhbaW5kZXgrK10pXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoaW5kZXggJiYgaW5kZXggPT0gbGVuZ3RoKSA/IG9iamVjdCA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgZ2V0QWxsS2V5c2AgYW5kIGBnZXRBbGxLZXlzSW5gIHdoaWNoIHVzZXNcbiAgICAgKiBga2V5c0Z1bmNgIGFuZCBgc3ltYm9sc0Z1bmNgIHRvIGdldCB0aGUgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmRcbiAgICAgKiBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzeW1ib2xzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUdldEFsbEtleXMob2JqZWN0LCBrZXlzRnVuYywgc3ltYm9sc0Z1bmMpIHtcbiAgICAgIHZhciByZXN1bHQgPSBrZXlzRnVuYyhvYmplY3QpO1xuICAgICAgcmV0dXJuIGlzQXJyYXkob2JqZWN0KSA/IHJlc3VsdCA6IGFycmF5UHVzaChyZXN1bHQsIHN5bWJvbHNGdW5jKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBnZXRUYWdgIHdpdGhvdXQgZmFsbGJhY2tzIGZvciBidWdneSBlbnZpcm9ubWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGB0b1N0cmluZ1RhZ2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUdldFRhZyh2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWRUYWcgOiBudWxsVGFnO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChzeW1Ub1N0cmluZ1RhZyAmJiBzeW1Ub1N0cmluZ1RhZyBpbiBPYmplY3QodmFsdWUpKVxuICAgICAgICA/IGdldFJhd1RhZyh2YWx1ZSlcbiAgICAgICAgOiBvYmplY3RUb1N0cmluZyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZ3RgIHdoaWNoIGRvZXNuJ3QgY29lcmNlIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBgb3RoZXJgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUd0KHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlID4gb3RoZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaGFzYCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBrZXkgVGhlIGtleSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUhhcyhvYmplY3QsIGtleSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAhPSBudWxsICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmhhc0luYCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBrZXkgVGhlIGtleSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUhhc0luKG9iamVjdCwga2V5KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICE9IG51bGwgJiYga2V5IGluIE9iamVjdChvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmluUmFuZ2VgIHdoaWNoIGRvZXNuJ3QgY29lcmNlIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBudW1iZXJgIGlzIGluIHRoZSByYW5nZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCkge1xuICAgICAgcmV0dXJuIG51bWJlciA+PSBuYXRpdmVNaW4oc3RhcnQsIGVuZCkgJiYgbnVtYmVyIDwgbmF0aXZlTWF4KHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy5pbnRlcnNlY3Rpb25gLCB3aXRob3V0IHN1cHBvcnRcbiAgICAgKiBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcywgdGhhdCBhY2NlcHRzIGFuIGFycmF5IG9mIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheXMgVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2Ygc2hhcmVkIHZhbHVlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW50ZXJzZWN0aW9uKGFycmF5cywgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBpbmNsdWRlcyA9IGNvbXBhcmF0b3IgPyBhcnJheUluY2x1ZGVzV2l0aCA6IGFycmF5SW5jbHVkZXMsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXlzWzBdLmxlbmd0aCxcbiAgICAgICAgICBvdGhMZW5ndGggPSBhcnJheXMubGVuZ3RoLFxuICAgICAgICAgIG90aEluZGV4ID0gb3RoTGVuZ3RoLFxuICAgICAgICAgIGNhY2hlcyA9IEFycmF5KG90aExlbmd0aCksXG4gICAgICAgICAgbWF4TGVuZ3RoID0gSW5maW5pdHksXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlIChvdGhJbmRleC0tKSB7XG4gICAgICAgIHZhciBhcnJheSA9IGFycmF5c1tvdGhJbmRleF07XG4gICAgICAgIGlmIChvdGhJbmRleCAmJiBpdGVyYXRlZSkge1xuICAgICAgICAgIGFycmF5ID0gYXJyYXlNYXAoYXJyYXksIGJhc2VVbmFyeShpdGVyYXRlZSkpO1xuICAgICAgICB9XG4gICAgICAgIG1heExlbmd0aCA9IG5hdGl2ZU1pbihhcnJheS5sZW5ndGgsIG1heExlbmd0aCk7XG4gICAgICAgIGNhY2hlc1tvdGhJbmRleF0gPSAhY29tcGFyYXRvciAmJiAoaXRlcmF0ZWUgfHwgKGxlbmd0aCA+PSAxMjAgJiYgYXJyYXkubGVuZ3RoID49IDEyMCkpXG4gICAgICAgICAgPyBuZXcgU2V0Q2FjaGUob3RoSW5kZXggJiYgYXJyYXkpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBhcnJheSA9IGFycmF5c1swXTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgc2VlbiA9IGNhY2hlc1swXTtcblxuICAgICAgb3V0ZXI6XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCAmJiByZXN1bHQubGVuZ3RoIDwgbWF4TGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICB2YWx1ZSA9IChjb21wYXJhdG9yIHx8IHZhbHVlICE9PSAwKSA/IHZhbHVlIDogMDtcbiAgICAgICAgaWYgKCEoc2VlblxuICAgICAgICAgICAgICA/IGNhY2hlSGFzKHNlZW4sIGNvbXB1dGVkKVxuICAgICAgICAgICAgICA6IGluY2x1ZGVzKHJlc3VsdCwgY29tcHV0ZWQsIGNvbXBhcmF0b3IpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgb3RoSW5kZXggPSBvdGhMZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKC0tb3RoSW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBjYWNoZSA9IGNhY2hlc1tvdGhJbmRleF07XG4gICAgICAgICAgICBpZiAoIShjYWNoZVxuICAgICAgICAgICAgICAgICAgPyBjYWNoZUhhcyhjYWNoZSwgY29tcHV0ZWQpXG4gICAgICAgICAgICAgICAgICA6IGluY2x1ZGVzKGFycmF5c1tvdGhJbmRleF0sIGNvbXB1dGVkLCBjb21wYXJhdG9yKSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzZWVuKSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW52ZXJ0YCBhbmQgYF8uaW52ZXJ0QnlgIHdoaWNoIGludmVydHNcbiAgICAgKiBgb2JqZWN0YCB3aXRoIHZhbHVlcyB0cmFuc2Zvcm1lZCBieSBgaXRlcmF0ZWVgIGFuZCBzZXQgYnkgYHNldHRlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW52ZXJ0ZXIob2JqZWN0LCBzZXR0ZXIsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgYmFzZUZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICBzZXR0ZXIoYWNjdW11bGF0b3IsIGl0ZXJhdGVlKHZhbHVlKSwga2V5LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW52b2tlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGluZGl2aWR1YWxcbiAgICAgKiBtZXRob2QgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpIHtcbiAgICAgIHBhdGggPSBjYXN0UGF0aChwYXRoLCBvYmplY3QpO1xuICAgICAgb2JqZWN0ID0gcGFyZW50KG9iamVjdCwgcGF0aCk7XG4gICAgICB2YXIgZnVuYyA9IG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogb2JqZWN0W3RvS2V5KGxhc3QocGF0aCkpXTtcbiAgICAgIHJldHVybiBmdW5jID09IG51bGwgPyB1bmRlZmluZWQgOiBhcHBseShmdW5jLCBvYmplY3QsIGFyZ3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzQXJndW1lbnRzYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0FyZ3VtZW50cyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gYXJnc1RhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0FycmF5QnVmZmVyYCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXkgYnVmZmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzQXJyYXlCdWZmZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IGFycmF5QnVmZmVyVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzRGF0ZWAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgZGF0ZSBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNEYXRlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBkYXRlVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzRXF1YWxgIHdoaWNoIHN1cHBvcnRzIHBhcnRpYWwgY29tcGFyaXNvbnNcbiAgICAgKiBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLlxuICAgICAqICAxIC0gVW5vcmRlcmVkIGNvbXBhcmlzb25cbiAgICAgKiAgMiAtIFBhcnRpYWwgY29tcGFyaXNvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgYHZhbHVlYCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykge1xuICAgICAgaWYgKHZhbHVlID09PSBvdGhlcikge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsIHx8IG90aGVyID09IG51bGwgfHwgKCFpc09iamVjdExpa2UodmFsdWUpICYmICFpc09iamVjdExpa2Uob3RoZXIpKSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgIT09IHZhbHVlICYmIG90aGVyICE9PSBvdGhlcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlSXNFcXVhbERlZXAodmFsdWUsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBiYXNlSXNFcXVhbCwgc3RhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxgIGZvciBhcnJheXMgYW5kIG9iamVjdHMgd2hpY2ggcGVyZm9ybXNcbiAgICAgKiBkZWVwIGNvbXBhcmlzb25zIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMgZW5hYmxpbmcgb2JqZWN0cyB3aXRoIGNpcmN1bGFyXG4gICAgICogcmVmZXJlbmNlcyB0byBiZSBjb21wYXJlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNFcXVhbERlZXAob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICAgICAgdmFyIG9iaklzQXJyID0gaXNBcnJheShvYmplY3QpLFxuICAgICAgICAgIG90aElzQXJyID0gaXNBcnJheShvdGhlciksXG4gICAgICAgICAgb2JqVGFnID0gb2JqSXNBcnIgPyBhcnJheVRhZyA6IGdldFRhZyhvYmplY3QpLFxuICAgICAgICAgIG90aFRhZyA9IG90aElzQXJyID8gYXJyYXlUYWcgOiBnZXRUYWcob3RoZXIpO1xuXG4gICAgICBvYmpUYWcgPSBvYmpUYWcgPT0gYXJnc1RhZyA/IG9iamVjdFRhZyA6IG9ialRhZztcbiAgICAgIG90aFRhZyA9IG90aFRhZyA9PSBhcmdzVGFnID8gb2JqZWN0VGFnIDogb3RoVGFnO1xuXG4gICAgICB2YXIgb2JqSXNPYmogPSBvYmpUYWcgPT0gb2JqZWN0VGFnLFxuICAgICAgICAgIG90aElzT2JqID0gb3RoVGFnID09IG9iamVjdFRhZyxcbiAgICAgICAgICBpc1NhbWVUYWcgPSBvYmpUYWcgPT0gb3RoVGFnO1xuXG4gICAgICBpZiAoaXNTYW1lVGFnICYmIGlzQnVmZmVyKG9iamVjdCkpIHtcbiAgICAgICAgaWYgKCFpc0J1ZmZlcihvdGhlcikpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgb2JqSXNBcnIgPSB0cnVlO1xuICAgICAgICBvYmpJc09iaiA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKGlzU2FtZVRhZyAmJiAhb2JqSXNPYmopIHtcbiAgICAgICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICAgICAgcmV0dXJuIChvYmpJc0FyciB8fCBpc1R5cGVkQXJyYXkob2JqZWN0KSlcbiAgICAgICAgICA/IGVxdWFsQXJyYXlzKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spXG4gICAgICAgICAgOiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIG9ialRhZywgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG4gICAgICB9XG4gICAgICBpZiAoIShiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcpKSB7XG4gICAgICAgIHZhciBvYmpJc1dyYXBwZWQgPSBvYmpJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgJ19fd3JhcHBlZF9fJyksXG4gICAgICAgICAgICBvdGhJc1dyYXBwZWQgPSBvdGhJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG90aGVyLCAnX193cmFwcGVkX18nKTtcblxuICAgICAgICBpZiAob2JqSXNXcmFwcGVkIHx8IG90aElzV3JhcHBlZCkge1xuICAgICAgICAgIHZhciBvYmpVbndyYXBwZWQgPSBvYmpJc1dyYXBwZWQgPyBvYmplY3QudmFsdWUoKSA6IG9iamVjdCxcbiAgICAgICAgICAgICAgb3RoVW53cmFwcGVkID0gb3RoSXNXcmFwcGVkID8gb3RoZXIudmFsdWUoKSA6IG90aGVyO1xuXG4gICAgICAgICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICAgICAgICByZXR1cm4gZXF1YWxGdW5jKG9ialVud3JhcHBlZCwgb3RoVW53cmFwcGVkLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghaXNTYW1lVGFnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICByZXR1cm4gZXF1YWxPYmplY3RzKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTWFwYCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBtYXAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNNYXAodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGdldFRhZyh2YWx1ZSkgPT0gbWFwVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTWF0Y2hgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBtYXRjaERhdGEgVGhlIHByb3BlcnR5IG5hbWVzLCB2YWx1ZXMsIGFuZCBjb21wYXJlIGZsYWdzIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBpcyBhIG1hdGNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIG1hdGNoRGF0YSwgY3VzdG9taXplcikge1xuICAgICAgdmFyIGluZGV4ID0gbWF0Y2hEYXRhLmxlbmd0aCxcbiAgICAgICAgICBsZW5ndGggPSBpbmRleCxcbiAgICAgICAgICBub0N1c3RvbWl6ZXIgPSAhY3VzdG9taXplcjtcblxuICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAhbGVuZ3RoO1xuICAgICAgfVxuICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICB2YXIgZGF0YSA9IG1hdGNoRGF0YVtpbmRleF07XG4gICAgICAgIGlmICgobm9DdXN0b21pemVyICYmIGRhdGFbMl0pXG4gICAgICAgICAgICAgID8gZGF0YVsxXSAhPT0gb2JqZWN0W2RhdGFbMF1dXG4gICAgICAgICAgICAgIDogIShkYXRhWzBdIGluIG9iamVjdClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgZGF0YSA9IG1hdGNoRGF0YVtpbmRleF07XG4gICAgICAgIHZhciBrZXkgPSBkYXRhWzBdLFxuICAgICAgICAgICAgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgICAgIHNyY1ZhbHVlID0gZGF0YVsxXTtcblxuICAgICAgICBpZiAobm9DdXN0b21pemVyICYmIGRhdGFbMl0pIHtcbiAgICAgICAgICBpZiAob2JqVmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBzdGFjayA9IG5ldyBTdGFjaztcbiAgICAgICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGN1c3RvbWl6ZXIob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlLCBzdGFjayk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghKHJlc3VsdCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgPyBiYXNlSXNFcXVhbChzcmNWYWx1ZSwgb2JqVmFsdWUsIENPTVBBUkVfUEFSVElBTF9GTEFHIHwgQ09NUEFSRV9VTk9SREVSRURfRkxBRywgY3VzdG9taXplciwgc3RhY2spXG4gICAgICAgICAgICAgICAgOiByZXN1bHRcbiAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNOYXRpdmVgIHdpdGhvdXQgYmFkIHNoaW0gY2hlY2tzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbixcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc05hdGl2ZSh2YWx1ZSkge1xuICAgICAgaWYgKCFpc09iamVjdCh2YWx1ZSkgfHwgaXNNYXNrZWQodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBwYXR0ZXJuID0gaXNGdW5jdGlvbih2YWx1ZSkgPyByZUlzTmF0aXZlIDogcmVJc0hvc3RDdG9yO1xuICAgICAgcmV0dXJuIHBhdHRlcm4udGVzdCh0b1NvdXJjZSh2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzUmVnRXhwYCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSByZWdleHAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNSZWdFeHAodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IHJlZ2V4cFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc1NldGAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc2V0LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzU2V0KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IHNldFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc1R5cGVkQXJyYXlgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHR5cGVkIGFycmF5LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzVHlwZWRBcnJheSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiZcbiAgICAgICAgaXNMZW5ndGgodmFsdWUubGVuZ3RoKSAmJiAhIXR5cGVkQXJyYXlUYWdzW2Jhc2VHZXRUYWcodmFsdWUpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pdGVyYXRlZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gW3ZhbHVlPV8uaWRlbnRpdHldIFRoZSB2YWx1ZSB0byBjb252ZXJ0IHRvIGFuIGl0ZXJhdGVlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgaXRlcmF0ZWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUl0ZXJhdGVlKHZhbHVlKSB7XG4gICAgICAvLyBEb24ndCBzdG9yZSB0aGUgYHR5cGVvZmAgcmVzdWx0IGluIGEgdmFyaWFibGUgdG8gYXZvaWQgYSBKSVQgYnVnIGluIFNhZmFyaSA5LlxuICAgICAgLy8gU2VlIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xNTYwMzQgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gaWRlbnRpdHk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKVxuICAgICAgICAgID8gYmFzZU1hdGNoZXNQcm9wZXJ0eSh2YWx1ZVswXSwgdmFsdWVbMV0pXG4gICAgICAgICAgOiBiYXNlTWF0Y2hlcyh2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvcGVydHkodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmtleXNgIHdoaWNoIGRvZXNuJ3QgdHJlYXQgc3BhcnNlIGFycmF5cyBhcyBkZW5zZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUtleXMob2JqZWN0KSB7XG4gICAgICBpZiAoIWlzUHJvdG90eXBlKG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZUtleXMob2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGZvciAodmFyIGtleSBpbiBPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkgJiYga2V5ICE9ICdjb25zdHJ1Y3RvcicpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmtleXNJbmAgd2hpY2ggZG9lc24ndCB0cmVhdCBzcGFyc2UgYXJyYXlzIGFzIGRlbnNlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlS2V5c0luKG9iamVjdCkge1xuICAgICAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBuYXRpdmVLZXlzSW4ob2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIHZhciBpc1Byb3RvID0gaXNQcm90b3R5cGUob2JqZWN0KSxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICBpZiAoIShrZXkgPT0gJ2NvbnN0cnVjdG9yJyAmJiAoaXNQcm90byB8fCAhaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubHRgIHdoaWNoIGRvZXNuJ3QgY29lcmNlIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBgb3RoZXJgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUx0KHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlIDwgb3RoZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWFwYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWFwKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICByZXN1bHQgPSBpc0FycmF5TGlrZShjb2xsZWN0aW9uKSA/IEFycmF5KGNvbGxlY3Rpb24ubGVuZ3RoKSA6IFtdO1xuXG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IGl0ZXJhdGVlKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1hdGNoZXNgIHdoaWNoIGRvZXNuJ3QgY2xvbmUgYHNvdXJjZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWF0Y2hlcyhzb3VyY2UpIHtcbiAgICAgIHZhciBtYXRjaERhdGEgPSBnZXRNYXRjaERhdGEoc291cmNlKTtcbiAgICAgIGlmIChtYXRjaERhdGEubGVuZ3RoID09IDEgJiYgbWF0Y2hEYXRhWzBdWzJdKSB7XG4gICAgICAgIHJldHVybiBtYXRjaGVzU3RyaWN0Q29tcGFyYWJsZShtYXRjaERhdGFbMF1bMF0sIG1hdGNoRGF0YVswXVsxXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPT09IHNvdXJjZSB8fCBiYXNlSXNNYXRjaChvYmplY3QsIHNvdXJjZSwgbWF0Y2hEYXRhKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWF0Y2hlc1Byb3BlcnR5YCB3aGljaCBkb2Vzbid0IGNsb25lIGBzcmNWYWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgdmFsdWUgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWF0Y2hlc1Byb3BlcnR5KHBhdGgsIHNyY1ZhbHVlKSB7XG4gICAgICBpZiAoaXNLZXkocGF0aCkgJiYgaXNTdHJpY3RDb21wYXJhYmxlKHNyY1ZhbHVlKSkge1xuICAgICAgICByZXR1cm4gbWF0Y2hlc1N0cmljdENvbXBhcmFibGUodG9LZXkocGF0aCksIHNyY1ZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgdmFyIG9ialZhbHVlID0gZ2V0KG9iamVjdCwgcGF0aCk7XG4gICAgICAgIHJldHVybiAob2JqVmFsdWUgPT09IHVuZGVmaW5lZCAmJiBvYmpWYWx1ZSA9PT0gc3JjVmFsdWUpXG4gICAgICAgICAgPyBoYXNJbihvYmplY3QsIHBhdGgpXG4gICAgICAgICAgOiBiYXNlSXNFcXVhbChzcmNWYWx1ZSwgb2JqVmFsdWUsIENPTVBBUkVfUEFSVElBTF9GTEFHIHwgQ09NUEFSRV9VTk9SREVSRURfRkxBRyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1lcmdlYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzcmNJbmRleCBUaGUgaW5kZXggb2YgYHNvdXJjZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgbWVyZ2VkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIHNvdXJjZSB2YWx1ZXMgYW5kIHRoZWlyIG1lcmdlZFxuICAgICAqICBjb3VudGVycGFydHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1lcmdlKG9iamVjdCwgc291cmNlLCBzcmNJbmRleCwgY3VzdG9taXplciwgc3RhY2spIHtcbiAgICAgIGlmIChvYmplY3QgPT09IHNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBiYXNlRm9yKHNvdXJjZSwgZnVuY3Rpb24oc3JjVmFsdWUsIGtleSkge1xuICAgICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgICBpZiAoaXNPYmplY3Qoc3JjVmFsdWUpKSB7XG4gICAgICAgICAgYmFzZU1lcmdlRGVlcChvYmplY3QsIHNvdXJjZSwga2V5LCBzcmNJbmRleCwgYmFzZU1lcmdlLCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIG5ld1ZhbHVlID0gY3VzdG9taXplclxuICAgICAgICAgICAgPyBjdXN0b21pemVyKHNhZmVHZXQob2JqZWN0LCBrZXkpLCBzcmNWYWx1ZSwgKGtleSArICcnKSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBzcmNWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9LCBrZXlzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZU1lcmdlYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gICAgICogZGVlcCBtZXJnZXMgYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBlbmFibGluZyBvYmplY3RzIHdpdGggY2lyY3VsYXJcbiAgICAgKiByZWZlcmVuY2VzIHRvIGJlIG1lcmdlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBtZXJnZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3JjSW5kZXggVGhlIGluZGV4IG9mIGBzb3VyY2VgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG1lcmdlRnVuYyBUaGUgZnVuY3Rpb24gdG8gbWVyZ2UgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIHNvdXJjZSB2YWx1ZXMgYW5kIHRoZWlyIG1lcmdlZFxuICAgICAqICBjb3VudGVycGFydHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1lcmdlRGVlcChvYmplY3QsIHNvdXJjZSwga2V5LCBzcmNJbmRleCwgbWVyZ2VGdW5jLCBjdXN0b21pemVyLCBzdGFjaykge1xuICAgICAgdmFyIG9ialZhbHVlID0gc2FmZUdldChvYmplY3QsIGtleSksXG4gICAgICAgICAgc3JjVmFsdWUgPSBzYWZlR2V0KHNvdXJjZSwga2V5KSxcbiAgICAgICAgICBzdGFja2VkID0gc3RhY2suZ2V0KHNyY1ZhbHVlKTtcblxuICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgc3RhY2tlZCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXJcbiAgICAgICAgPyBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSwgKGtleSArICcnKSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGlzQ29tbW9uID0gbmV3VmFsdWUgPT09IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKGlzQ29tbW9uKSB7XG4gICAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkoc3JjVmFsdWUpLFxuICAgICAgICAgICAgaXNCdWZmID0gIWlzQXJyICYmIGlzQnVmZmVyKHNyY1ZhbHVlKSxcbiAgICAgICAgICAgIGlzVHlwZWQgPSAhaXNBcnIgJiYgIWlzQnVmZiAmJiBpc1R5cGVkQXJyYXkoc3JjVmFsdWUpO1xuXG4gICAgICAgIG5ld1ZhbHVlID0gc3JjVmFsdWU7XG4gICAgICAgIGlmIChpc0FyciB8fCBpc0J1ZmYgfHwgaXNUeXBlZCkge1xuICAgICAgICAgIGlmIChpc0FycmF5KG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBvYmpWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoaXNBcnJheUxpa2VPYmplY3Qob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGNvcHlBcnJheShvYmpWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGlzQnVmZikge1xuICAgICAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gY2xvbmVCdWZmZXIoc3JjVmFsdWUsIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpc1R5cGVkKSB7XG4gICAgICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBjbG9uZVR5cGVkQXJyYXkoc3JjVmFsdWUsIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gW107XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzUGxhaW5PYmplY3Qoc3JjVmFsdWUpIHx8IGlzQXJndW1lbnRzKHNyY1ZhbHVlKSkge1xuICAgICAgICAgIG5ld1ZhbHVlID0gb2JqVmFsdWU7XG4gICAgICAgICAgaWYgKGlzQXJndW1lbnRzKG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSB0b1BsYWluT2JqZWN0KG9ialZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoIWlzT2JqZWN0KG9ialZhbHVlKSB8fCBpc0Z1bmN0aW9uKG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBpbml0Q2xvbmVPYmplY3Qoc3JjVmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXNDb21tb24pIHtcbiAgICAgICAgLy8gUmVjdXJzaXZlbHkgbWVyZ2Ugb2JqZWN0cyBhbmQgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIHN0YWNrLnNldChzcmNWYWx1ZSwgbmV3VmFsdWUpO1xuICAgICAgICBtZXJnZUZ1bmMobmV3VmFsdWUsIHNyY1ZhbHVlLCBzcmNJbmRleCwgY3VzdG9taXplciwgc3RhY2spO1xuICAgICAgICBzdGFja1snZGVsZXRlJ10oc3JjVmFsdWUpO1xuICAgICAgfVxuICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm50aGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHJldHVybi5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbnRoIGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTnRoKGFycmF5LCBuKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgbiArPSBuIDwgMCA/IGxlbmd0aCA6IDA7XG4gICAgICByZXR1cm4gaXNJbmRleChuLCBsZW5ndGgpID8gYXJyYXlbbl0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ub3JkZXJCeWAgd2l0aG91dCBwYXJhbSBndWFyZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW118T2JqZWN0W118c3RyaW5nW119IGl0ZXJhdGVlcyBUaGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gb3JkZXJzIFRoZSBzb3J0IG9yZGVycyBvZiBgaXRlcmF0ZWVzYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU9yZGVyQnkoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMpIHtcbiAgICAgIGlmIChpdGVyYXRlZXMubGVuZ3RoKSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IGFycmF5TWFwKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHtcbiAgICAgICAgICBpZiAoaXNBcnJheShpdGVyYXRlZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgICByZXR1cm4gYmFzZUdldCh2YWx1ZSwgaXRlcmF0ZWUubGVuZ3RoID09PSAxID8gaXRlcmF0ZWVbMF0gOiBpdGVyYXRlZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBpdGVyYXRlZTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpdGVyYXRlZXMgPSBbaWRlbnRpdHldO1xuICAgICAgfVxuXG4gICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgIGl0ZXJhdGVlcyA9IGFycmF5TWFwKGl0ZXJhdGVlcywgYmFzZVVuYXJ5KGdldEl0ZXJhdGVlKCkpKTtcblxuICAgICAgdmFyIHJlc3VsdCA9IGJhc2VNYXAoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICB2YXIgY3JpdGVyaWEgPSBhcnJheU1hcChpdGVyYXRlZXMsIGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgICAgcmV0dXJuIGl0ZXJhdGVlKHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7ICdjcml0ZXJpYSc6IGNyaXRlcmlhLCAnaW5kZXgnOiArK2luZGV4LCAndmFsdWUnOiB2YWx1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBiYXNlU29ydEJ5KHJlc3VsdCwgZnVuY3Rpb24ob2JqZWN0LCBvdGhlcikge1xuICAgICAgICByZXR1cm4gY29tcGFyZU11bHRpcGxlKG9iamVjdCwgb3RoZXIsIG9yZGVycyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5waWNrYCB3aXRob3V0IHN1cHBvcnQgZm9yIGluZGl2aWR1YWxcbiAgICAgKiBwcm9wZXJ0eSBpZGVudGlmaWVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQaWNrKG9iamVjdCwgcGF0aHMpIHtcbiAgICAgIHJldHVybiBiYXNlUGlja0J5KG9iamVjdCwgcGF0aHMsIGZ1bmN0aW9uKHZhbHVlLCBwYXRoKSB7XG4gICAgICAgIHJldHVybiBoYXNJbihvYmplY3QsIHBhdGgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgIGBfLnBpY2tCeWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhzIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgcHJvcGVydHkuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUGlja0J5KG9iamVjdCwgcGF0aHMsIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IHt9O1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgcGF0aCA9IHBhdGhzW2luZGV4XSxcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZUdldChvYmplY3QsIHBhdGgpO1xuXG4gICAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIHBhdGgpKSB7XG4gICAgICAgICAgYmFzZVNldChyZXN1bHQsIGNhc3RQYXRoKHBhdGgsIG9iamVjdCksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VQcm9wZXJ0eWAgd2hpY2ggc3VwcG9ydHMgZGVlcCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBhY2Nlc3NvciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUHJvcGVydHlEZWVwKHBhdGgpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VHZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucHVsbEFsbEJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAgICogc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4T2YgPSBjb21wYXJhdG9yID8gYmFzZUluZGV4T2ZXaXRoIDogYmFzZUluZGV4T2YsXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgIHNlZW4gPSBhcnJheTtcblxuICAgICAgaWYgKGFycmF5ID09PSB2YWx1ZXMpIHtcbiAgICAgICAgdmFsdWVzID0gY29weUFycmF5KHZhbHVlcyk7XG4gICAgICB9XG4gICAgICBpZiAoaXRlcmF0ZWUpIHtcbiAgICAgICAgc2VlbiA9IGFycmF5TWFwKGFycmF5LCBiYXNlVW5hcnkoaXRlcmF0ZWUpKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBmcm9tSW5kZXggPSAwLFxuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZXNbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbUluZGV4ID0gaW5kZXhPZihzZWVuLCBjb21wdXRlZCwgZnJvbUluZGV4LCBjb21wYXJhdG9yKSkgPiAtMSkge1xuICAgICAgICAgIGlmIChzZWVuICE9PSBhcnJheSkge1xuICAgICAgICAgICAgc3BsaWNlLmNhbGwoc2VlbiwgZnJvbUluZGV4LCAxKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGZyb21JbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wdWxsQXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbFxuICAgICAqIGluZGV4ZXMgb3IgY2FwdHVyaW5nIHRoZSByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyW119IGluZGV4ZXMgVGhlIGluZGV4ZXMgb2YgZWxlbWVudHMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGluZGV4ZXMubGVuZ3RoIDogMCxcbiAgICAgICAgICBsYXN0SW5kZXggPSBsZW5ndGggLSAxO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGluZGV4ID0gaW5kZXhlc1tsZW5ndGhdO1xuICAgICAgICBpZiAobGVuZ3RoID09IGxhc3RJbmRleCB8fCBpbmRleCAhPT0gcHJldmlvdXMpIHtcbiAgICAgICAgICB2YXIgcHJldmlvdXMgPSBpbmRleDtcbiAgICAgICAgICBpZiAoaXNJbmRleChpbmRleCkpIHtcbiAgICAgICAgICAgIHNwbGljZS5jYWxsKGFycmF5LCBpbmRleCwgMSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJhc2VVbnNldChhcnJheSwgaW5kZXgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJhbmRvbWAgd2l0aG91dCBzdXBwb3J0IGZvciByZXR1cm5pbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbG93ZXIgVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcmFuZG9tIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmFuZG9tKGxvd2VyLCB1cHBlcikge1xuICAgICAgcmV0dXJuIGxvd2VyICsgbmF0aXZlRmxvb3IobmF0aXZlUmFuZG9tKCkgKiAodXBwZXIgLSBsb3dlciArIDEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yYW5nZWAgYW5kIGBfLnJhbmdlUmlnaHRgIHdoaWNoIGRvZXNuJ3RcbiAgICAgKiBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZ2Ugb2YgbnVtYmVycy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmFuZ2Uoc3RhcnQsIGVuZCwgc3RlcCwgZnJvbVJpZ2h0KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgobmF0aXZlQ2VpbCgoZW5kIC0gc3RhcnQpIC8gKHN0ZXAgfHwgMSkpLCAwKSxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgcmVzdWx0W2Zyb21SaWdodCA/IGxlbmd0aCA6ICsraW5kZXhdID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ICs9IHN0ZXA7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJlcGVhdGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcmVwZWF0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmVwZWF0IHRoZSBzdHJpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmVwZWF0ZWQgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSZXBlYXQoc3RyaW5nLCBuKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gJyc7XG4gICAgICBpZiAoIXN0cmluZyB8fCBuIDwgMSB8fCBuID4gTUFYX1NBRkVfSU5URUdFUikge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgLy8gTGV2ZXJhZ2UgdGhlIGV4cG9uZW50aWF0aW9uIGJ5IHNxdWFyaW5nIGFsZ29yaXRobSBmb3IgYSBmYXN0ZXIgcmVwZWF0LlxuICAgICAgLy8gU2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V4cG9uZW50aWF0aW9uX2J5X3NxdWFyaW5nIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBkbyB7XG4gICAgICAgIGlmIChuICUgMikge1xuICAgICAgICAgIHJlc3VsdCArPSBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgbiA9IG5hdGl2ZUZsb29yKG4gLyAyKTtcbiAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICBzdHJpbmcgKz0gc3RyaW5nO1xuICAgICAgICB9XG4gICAgICB9IHdoaWxlIChuKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yZXN0YCB3aGljaCBkb2Vzbid0IHZhbGlkYXRlIG9yIGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD1mdW5jLmxlbmd0aC0xXSBUaGUgc3RhcnQgcG9zaXRpb24gb2YgdGhlIHJlc3QgcGFyYW1ldGVyLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSZXN0KGZ1bmMsIHN0YXJ0KSB7XG4gICAgICByZXR1cm4gc2V0VG9TdHJpbmcob3ZlclJlc3QoZnVuYywgc3RhcnQsIGlkZW50aXR5KSwgZnVuYyArICcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zYW1wbGVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTYW1wbGUoY29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIGFycmF5U2FtcGxlKHZhbHVlcyhjb2xsZWN0aW9uKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc2FtcGxlU2l6ZWAgd2l0aG91dCBwYXJhbSBndWFyZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2FtcGxlU2l6ZShjb2xsZWN0aW9uLCBuKSB7XG4gICAgICB2YXIgYXJyYXkgPSB2YWx1ZXMoY29sbGVjdGlvbik7XG4gICAgICByZXR1cm4gc2h1ZmZsZVNlbGYoYXJyYXksIGJhc2VDbGFtcChuLCAwLCBhcnJheS5sZW5ndGgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zZXRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIHBhdGggY3JlYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfVxuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDEsXG4gICAgICAgICAgbmVzdGVkID0gb2JqZWN0O1xuXG4gICAgICB3aGlsZSAobmVzdGVkICE9IG51bGwgJiYgKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gdG9LZXkocGF0aFtpbmRleF0pLFxuICAgICAgICAgICAgbmV3VmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICBpZiAoa2V5ID09PSAnX19wcm90b19fJyB8fCBrZXkgPT09ICdjb25zdHJ1Y3RvcicgfHwga2V5ID09PSAncHJvdG90eXBlJykge1xuICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW5kZXggIT0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgdmFyIG9ialZhbHVlID0gbmVzdGVkW2tleV07XG4gICAgICAgICAgbmV3VmFsdWUgPSBjdXN0b21pemVyID8gY3VzdG9taXplcihvYmpWYWx1ZSwga2V5LCBuZXN0ZWQpIDogdW5kZWZpbmVkO1xuICAgICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGlzT2JqZWN0KG9ialZhbHVlKVxuICAgICAgICAgICAgICA/IG9ialZhbHVlXG4gICAgICAgICAgICAgIDogKGlzSW5kZXgocGF0aFtpbmRleCArIDFdKSA/IFtdIDoge30pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhc3NpZ25WYWx1ZShuZXN0ZWQsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICBuZXN0ZWQgPSBuZXN0ZWRba2V5XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHNldERhdGFgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaG90IGxvb3Agc2hvcnRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBUaGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZVNldERhdGEgPSAhbWV0YU1hcCA/IGlkZW50aXR5IDogZnVuY3Rpb24oZnVuYywgZGF0YSkge1xuICAgICAgbWV0YU1hcC5zZXQoZnVuYywgZGF0YSk7XG4gICAgICByZXR1cm4gZnVuYztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHNldFRvU3RyaW5nYCB3aXRob3V0IHN1cHBvcnQgZm9yIGhvdCBsb29wIHNob3J0aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc3RyaW5nIFRoZSBgdG9TdHJpbmdgIHJlc3VsdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBiYXNlU2V0VG9TdHJpbmcgPSAhZGVmaW5lUHJvcGVydHkgPyBpZGVudGl0eSA6IGZ1bmN0aW9uKGZ1bmMsIHN0cmluZykge1xuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KGZ1bmMsICd0b1N0cmluZycsIHtcbiAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXG4gICAgICAgICdlbnVtZXJhYmxlJzogZmFsc2UsXG4gICAgICAgICd2YWx1ZSc6IGNvbnN0YW50KHN0cmluZyksXG4gICAgICAgICd3cml0YWJsZSc6IHRydWVcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zaHVmZmxlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2h1ZmZsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzaHVmZmxlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2h1ZmZsZShjb2xsZWN0aW9uKSB7XG4gICAgICByZXR1cm4gc2h1ZmZsZVNlbGYodmFsdWVzKGNvbGxlY3Rpb24pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zbGljZWAgd2l0aG91dCBhbiBpdGVyYXRlZSBjYWxsIGd1YXJkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2xpY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IC1zdGFydCA+IGxlbmd0aCA/IDAgOiAobGVuZ3RoICsgc3RhcnQpO1xuICAgICAgfVxuICAgICAgZW5kID0gZW5kID4gbGVuZ3RoID8gbGVuZ3RoIDogZW5kO1xuICAgICAgaWYgKGVuZCA8IDApIHtcbiAgICAgICAgZW5kICs9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGxlbmd0aCA9IHN0YXJ0ID4gZW5kID8gMCA6ICgoZW5kIC0gc3RhcnQpID4+PiAwKTtcbiAgICAgIHN0YXJ0ID4+Pj0gMDtcblxuICAgICAgdmFyIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gYXJyYXlbaW5kZXggKyBzdGFydF07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvbWVgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb21lKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdDtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJlc3VsdCA9IHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gIXJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZEluZGV4YCBhbmQgYF8uc29ydGVkTGFzdEluZGV4YCB3aGljaFxuICAgICAqIHBlcmZvcm1zIGEgYmluYXJ5IHNlYXJjaCBvZiBgYXJyYXlgIHRvIGRldGVybWluZSB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYFxuICAgICAqIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHJldEhpZ2hlc3QpIHtcbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA9PSBudWxsID8gbG93IDogYXJyYXkubGVuZ3RoO1xuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmIHZhbHVlID09PSB2YWx1ZSAmJiBoaWdoIDw9IEhBTEZfTUFYX0FSUkFZX0xFTkdUSCkge1xuICAgICAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgICAgIHZhciBtaWQgPSAobG93ICsgaGlnaCkgPj4+IDEsXG4gICAgICAgICAgICAgIGNvbXB1dGVkID0gYXJyYXlbbWlkXTtcblxuICAgICAgICAgIGlmIChjb21wdXRlZCAhPT0gbnVsbCAmJiAhaXNTeW1ib2woY29tcHV0ZWQpICYmXG4gICAgICAgICAgICAgIChyZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKSkpIHtcbiAgICAgICAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhpZ2ggPSBtaWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoaWdoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaWRlbnRpdHksIHJldEhpZ2hlc3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZEluZGV4QnlgIGFuZCBgXy5zb3J0ZWRMYXN0SW5kZXhCeWBcbiAgICAgKiB3aGljaCBpbnZva2VzIGBpdGVyYXRlZWAgZm9yIGB2YWx1ZWAgYW5kIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIHRvIGNvbXB1dGVcbiAgICAgKiB0aGVpciBzb3J0IHJhbmtpbmcuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbcmV0SGlnaGVzdF0gU3BlY2lmeSByZXR1cm5pbmcgdGhlIGhpZ2hlc3QgcXVhbGlmaWVkIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU29ydGVkSW5kZXhCeShhcnJheSwgdmFsdWUsIGl0ZXJhdGVlLCByZXRIaWdoZXN0KSB7XG4gICAgICB2YXIgbG93ID0gMCxcbiAgICAgICAgICBoaWdoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoaGlnaCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cblxuICAgICAgdmFsdWUgPSBpdGVyYXRlZSh2YWx1ZSk7XG4gICAgICB2YXIgdmFsSXNOYU4gPSB2YWx1ZSAhPT0gdmFsdWUsXG4gICAgICAgICAgdmFsSXNOdWxsID0gdmFsdWUgPT09IG51bGwsXG4gICAgICAgICAgdmFsSXNTeW1ib2wgPSBpc1N5bWJvbCh2YWx1ZSksXG4gICAgICAgICAgdmFsSXNVbmRlZmluZWQgPSB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xuXG4gICAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgICB2YXIgbWlkID0gbmF0aXZlRmxvb3IoKGxvdyArIGhpZ2gpIC8gMiksXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKGFycmF5W21pZF0pLFxuICAgICAgICAgICAgb3RoSXNEZWZpbmVkID0gY29tcHV0ZWQgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG90aElzTnVsbCA9IGNvbXB1dGVkID09PSBudWxsLFxuICAgICAgICAgICAgb3RoSXNSZWZsZXhpdmUgPSBjb21wdXRlZCA9PT0gY29tcHV0ZWQsXG4gICAgICAgICAgICBvdGhJc1N5bWJvbCA9IGlzU3ltYm9sKGNvbXB1dGVkKTtcblxuICAgICAgICBpZiAodmFsSXNOYU4pIHtcbiAgICAgICAgICB2YXIgc2V0TG93ID0gcmV0SGlnaGVzdCB8fCBvdGhJc1JlZmxleGl2ZTtcbiAgICAgICAgfSBlbHNlIGlmICh2YWxJc1VuZGVmaW5lZCkge1xuICAgICAgICAgIHNldExvdyA9IG90aElzUmVmbGV4aXZlICYmIChyZXRIaWdoZXN0IHx8IG90aElzRGVmaW5lZCk7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsSXNOdWxsKSB7XG4gICAgICAgICAgc2V0TG93ID0gb3RoSXNSZWZsZXhpdmUgJiYgb3RoSXNEZWZpbmVkICYmIChyZXRIaWdoZXN0IHx8ICFvdGhJc051bGwpO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbElzU3ltYm9sKSB7XG4gICAgICAgICAgc2V0TG93ID0gb3RoSXNSZWZsZXhpdmUgJiYgb3RoSXNEZWZpbmVkICYmICFvdGhJc051bGwgJiYgKHJldEhpZ2hlc3QgfHwgIW90aElzU3ltYm9sKTtcbiAgICAgICAgfSBlbHNlIGlmIChvdGhJc051bGwgfHwgb3RoSXNTeW1ib2wpIHtcbiAgICAgICAgICBzZXRMb3cgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRMb3cgPSByZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0TG93KSB7XG4gICAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBoaWdoID0gbWlkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbmF0aXZlTWluKGhpZ2gsIE1BWF9BUlJBWV9JTkRFWCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydGVkVW5pcWAgYW5kIGBfLnNvcnRlZFVuaXFCeWAgd2l0aG91dFxuICAgICAqIHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvcnRlZFVuaXEoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzSW5kZXggPSAwLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUpIDogdmFsdWU7XG5cbiAgICAgICAgaWYgKCFpbmRleCB8fCAhZXEoY29tcHV0ZWQsIHNlZW4pKSB7XG4gICAgICAgICAgdmFyIHNlZW4gPSBjb21wdXRlZDtcbiAgICAgICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50b051bWJlcmAgd2hpY2ggZG9lc24ndCBlbnN1cmUgY29ycmVjdFxuICAgICAqIGNvbnZlcnNpb25zIG9mIGJpbmFyeSwgaGV4YWRlY2ltYWwsIG9yIG9jdGFsIHN0cmluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgbnVtYmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VUb051bWJlcih2YWx1ZSkge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBOQU47XG4gICAgICB9XG4gICAgICByZXR1cm4gK3ZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnRvU3RyaW5nYCB3aGljaCBkb2Vzbid0IGNvbnZlcnQgbnVsbGlzaFxuICAgICAqIHZhbHVlcyB0byBlbXB0eSBzdHJpbmdzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVG9TdHJpbmcodmFsdWUpIHtcbiAgICAgIC8vIEV4aXQgZWFybHkgZm9yIHN0cmluZ3MgdG8gYXZvaWQgYSBwZXJmb3JtYW5jZSBoaXQgaW4gc29tZSBlbnZpcm9ubWVudHMuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb252ZXJ0IHZhbHVlcyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICByZXR1cm4gYXJyYXlNYXAodmFsdWUsIGJhc2VUb1N0cmluZykgKyAnJztcbiAgICAgIH1cbiAgICAgIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHN5bWJvbFRvU3RyaW5nID8gc3ltYm9sVG9TdHJpbmcuY2FsbCh2YWx1ZSkgOiAnJztcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSAodmFsdWUgKyAnJyk7XG4gICAgICByZXR1cm4gKHJlc3VsdCA9PSAnMCcgJiYgKDEgLyB2YWx1ZSkgPT0gLUlORklOSVRZKSA/ICctMCcgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udW5pcUJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVVuaXEoYXJyYXksIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmNsdWRlcyA9IGFycmF5SW5jbHVkZXMsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGlzQ29tbW9uID0gdHJ1ZSxcbiAgICAgICAgICByZXN1bHQgPSBbXSxcbiAgICAgICAgICBzZWVuID0gcmVzdWx0O1xuXG4gICAgICBpZiAoY29tcGFyYXRvcikge1xuICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICBpbmNsdWRlcyA9IGFycmF5SW5jbHVkZXNXaXRoO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAobGVuZ3RoID49IExBUkdFX0FSUkFZX1NJWkUpIHtcbiAgICAgICAgdmFyIHNldCA9IGl0ZXJhdGVlID8gbnVsbCA6IGNyZWF0ZVNldChhcnJheSk7XG4gICAgICAgIGlmIChzZXQpIHtcbiAgICAgICAgICByZXR1cm4gc2V0VG9BcnJheShzZXQpO1xuICAgICAgICB9XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIGluY2x1ZGVzID0gY2FjaGVIYXM7XG4gICAgICAgIHNlZW4gPSBuZXcgU2V0Q2FjaGU7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgc2VlbiA9IGl0ZXJhdGVlID8gW10gOiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICB2YWx1ZSA9IChjb21wYXJhdG9yIHx8IHZhbHVlICE9PSAwKSA/IHZhbHVlIDogMDtcbiAgICAgICAgaWYgKGlzQ29tbW9uICYmIGNvbXB1dGVkID09PSBjb21wdXRlZCkge1xuICAgICAgICAgIHZhciBzZWVuSW5kZXggPSBzZWVuLmxlbmd0aDtcbiAgICAgICAgICB3aGlsZSAoc2VlbkluZGV4LS0pIHtcbiAgICAgICAgICAgIGlmIChzZWVuW3NlZW5JbmRleF0gPT09IGNvbXB1dGVkKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaXRlcmF0ZWUpIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaW5jbHVkZXMoc2VlbiwgY29tcHV0ZWQsIGNvbXBhcmF0b3IpKSB7XG4gICAgICAgICAgaWYgKHNlZW4gIT09IHJlc3VsdCkge1xuICAgICAgICAgICAgc2Vlbi5wdXNoKGNvbXB1dGVkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuc2V0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcHJvcGVydHkgcGF0aCB0byB1bnNldC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IGlzIGRlbGV0ZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVW5zZXQob2JqZWN0LCBwYXRoKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcbiAgICAgIG9iamVjdCA9IHBhcmVudChvYmplY3QsIHBhdGgpO1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsIHx8IGRlbGV0ZSBvYmplY3RbdG9LZXkobGFzdChwYXRoKSldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVwZGF0ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHVwZGF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB1cGRhdGVyIFRoZSBmdW5jdGlvbiB0byBwcm9kdWNlIHRoZSB1cGRhdGVkIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIHBhdGggY3JlYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVXBkYXRlKG9iamVjdCwgcGF0aCwgdXBkYXRlciwgY3VzdG9taXplcikge1xuICAgICAgcmV0dXJuIGJhc2VTZXQob2JqZWN0LCBwYXRoLCB1cGRhdGVyKGJhc2VHZXQob2JqZWN0LCBwYXRoKSksIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy5kcm9wV2hpbGVgIGFuZCBgXy50YWtlV2hpbGVgXG4gICAgICogd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEcm9wXSBTcGVjaWZ5IGRyb3BwaW5nIGVsZW1lbnRzIGluc3RlYWQgb2YgdGFraW5nIHRoZW0uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VXaGlsZShhcnJheSwgcHJlZGljYXRlLCBpc0Ryb3AsIGZyb21SaWdodCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBpbmRleCA9IGZyb21SaWdodCA/IGxlbmd0aCA6IC0xO1xuXG4gICAgICB3aGlsZSAoKGZyb21SaWdodCA/IGluZGV4LS0gOiArK2luZGV4IDwgbGVuZ3RoKSAmJlxuICAgICAgICBwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7fVxuXG4gICAgICByZXR1cm4gaXNEcm9wXG4gICAgICAgID8gYmFzZVNsaWNlKGFycmF5LCAoZnJvbVJpZ2h0ID8gMCA6IGluZGV4KSwgKGZyb21SaWdodCA/IGluZGV4ICsgMSA6IGxlbmd0aCkpXG4gICAgICAgIDogYmFzZVNsaWNlKGFycmF5LCAoZnJvbVJpZ2h0ID8gaW5kZXggKyAxIDogMCksIChmcm9tUmlnaHQgPyBsZW5ndGggOiBpbmRleCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGB3cmFwcGVyVmFsdWVgIHdoaWNoIHJldHVybnMgdGhlIHJlc3VsdCBvZlxuICAgICAqIHBlcmZvcm1pbmcgYSBzZXF1ZW5jZSBvZiBhY3Rpb25zIG9uIHRoZSB1bndyYXBwZWQgYHZhbHVlYCwgd2hlcmUgZWFjaFxuICAgICAqIHN1Y2Nlc3NpdmUgYWN0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gYWN0aW9ucyBBY3Rpb25zIHRvIHBlcmZvcm0gdG8gcmVzb2x2ZSB0aGUgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlV3JhcHBlclZhbHVlKHZhbHVlLCBhY3Rpb25zKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gdmFsdWU7XG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpIHtcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnZhbHVlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXlSZWR1Y2UoYWN0aW9ucywgZnVuY3Rpb24ocmVzdWx0LCBhY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGFjdGlvbi5mdW5jLmFwcGx5KGFjdGlvbi50aGlzQXJnLCBhcnJheVB1c2goW3Jlc3VsdF0sIGFjdGlvbi5hcmdzKSk7XG4gICAgICB9LCByZXN1bHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy54b3JgLCB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcywgdGhhdCBhY2NlcHRzIGFuIGFycmF5IG9mIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheXMgVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgdmFsdWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VYb3IoYXJyYXlzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5cy5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZVVuaXEoYXJyYXlzWzBdKSA6IFtdO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJyYXlzW2luZGV4XSxcbiAgICAgICAgICAgIG90aEluZGV4ID0gLTE7XG5cbiAgICAgICAgd2hpbGUgKCsrb3RoSW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBpZiAob3RoSW5kZXggIT0gaW5kZXgpIHtcbiAgICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBiYXNlRGlmZmVyZW5jZShyZXN1bHRbaW5kZXhdIHx8IGFycmF5LCBhcnJheXNbb3RoSW5kZXhdLCBpdGVyYXRlZSwgY29tcGFyYXRvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVVuaXEoYmFzZUZsYXR0ZW4ocmVzdWx0LCAxKSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy56aXBPYmplY3RgIHdoaWNoIGFzc2lnbnMgdmFsdWVzIHVzaW5nIGBhc3NpZ25GdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IGlkZW50aWZpZXJzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGFzc2lnbkZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc2lnbiB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlWmlwT2JqZWN0KHByb3BzLCB2YWx1ZXMsIGFzc2lnbkZ1bmMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aCxcbiAgICAgICAgICB2YWxzTGVuZ3RoID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSB7fTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gaW5kZXggPCB2YWxzTGVuZ3RoID8gdmFsdWVzW2luZGV4XSA6IHVuZGVmaW5lZDtcbiAgICAgICAgYXNzaWduRnVuYyhyZXN1bHQsIHByb3BzW2luZGV4XSwgdmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgdmFsdWVgIHRvIGFuIGVtcHR5IGFycmF5IGlmIGl0J3Mgbm90IGFuIGFycmF5IGxpa2Ugb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgdGhlIGNhc3QgYXJyYXktbGlrZSBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FzdEFycmF5TGlrZU9iamVjdCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KHZhbHVlKSA/IHZhbHVlIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYHZhbHVlYCB0byBgaWRlbnRpdHlgIGlmIGl0J3Mgbm90IGEgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGNhc3QgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FzdEZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdmdW5jdGlvbicgPyB2YWx1ZSA6IGlkZW50aXR5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgdG8gYSBwYXRoIGFycmF5IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeSBrZXlzIG9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY2FzdCBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RQYXRoKHZhbHVlLCBvYmplY3QpIHtcbiAgICAgIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNLZXkodmFsdWUsIG9iamVjdCkgPyBbdmFsdWVdIDogc3RyaW5nVG9QYXRoKHRvU3RyaW5nKHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBgYmFzZVJlc3RgIGFsaWFzIHdoaWNoIGNhbiBiZSByZXBsYWNlZCB3aXRoIGBpZGVudGl0eWAgYnkgbW9kdWxlXG4gICAgICogcmVwbGFjZW1lbnQgcGx1Z2lucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgdmFyIGNhc3RSZXN0ID0gYmFzZVJlc3Q7XG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgYXJyYXlgIHRvIGEgc2xpY2UgaWYgaXQncyBuZWVkZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydCBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY2FzdCBzbGljZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXN0U2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbmd0aCA6IGVuZDtcbiAgICAgIHJldHVybiAoIXN0YXJ0ICYmIGVuZCA+PSBsZW5ndGgpID8gYXJyYXkgOiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIHRoZSBnbG9iYWwgW2BjbGVhclRpbWVvdXRgXShodHRwczovL21kbi5pby9jbGVhclRpbWVvdXQpLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcnxPYmplY3R9IGlkIFRoZSB0aW1lciBpZCBvciB0aW1lb3V0IG9iamVjdCBvZiB0aGUgdGltZXIgdG8gY2xlYXIuXG4gICAgICovXG4gICAgdmFyIGNsZWFyVGltZW91dCA9IGN0eENsZWFyVGltZW91dCB8fCBmdW5jdGlvbihpZCkge1xuICAgICAgcmV0dXJuIHJvb3QuY2xlYXJUaW1lb3V0KGlkKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mICBgYnVmZmVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtCdWZmZXJ9IGJ1ZmZlciBUaGUgYnVmZmVyIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge0J1ZmZlcn0gUmV0dXJucyB0aGUgY2xvbmVkIGJ1ZmZlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZUJ1ZmZlcihidWZmZXIsIGlzRGVlcCkge1xuICAgICAgaWYgKGlzRGVlcCkge1xuICAgICAgICByZXR1cm4gYnVmZmVyLnNsaWNlKCk7XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gYnVmZmVyLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBhbGxvY1Vuc2FmZSA/IGFsbG9jVW5zYWZlKGxlbmd0aCkgOiBuZXcgYnVmZmVyLmNvbnN0cnVjdG9yKGxlbmd0aCk7XG5cbiAgICAgIGJ1ZmZlci5jb3B5KHJlc3VsdCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgYXJyYXlCdWZmZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBhcnJheUJ1ZmZlciBUaGUgYXJyYXkgYnVmZmVyIHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtBcnJheUJ1ZmZlcn0gUmV0dXJucyB0aGUgY2xvbmVkIGFycmF5IGJ1ZmZlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZUFycmF5QnVmZmVyKGFycmF5QnVmZmVyKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbmV3IGFycmF5QnVmZmVyLmNvbnN0cnVjdG9yKGFycmF5QnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgbmV3IFVpbnQ4QXJyYXkocmVzdWx0KS5zZXQobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGBkYXRhVmlld2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhVmlldyBUaGUgZGF0YSB2aWV3IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIGRhdGEgdmlldy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZURhdGFWaWV3KGRhdGFWaWV3LCBpc0RlZXApIHtcbiAgICAgIHZhciBidWZmZXIgPSBpc0RlZXAgPyBjbG9uZUFycmF5QnVmZmVyKGRhdGFWaWV3LmJ1ZmZlcikgOiBkYXRhVmlldy5idWZmZXI7XG4gICAgICByZXR1cm4gbmV3IGRhdGFWaWV3LmNvbnN0cnVjdG9yKGJ1ZmZlciwgZGF0YVZpZXcuYnl0ZU9mZnNldCwgZGF0YVZpZXcuYnl0ZUxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGByZWdleHBgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcmVnZXhwIFRoZSByZWdleHAgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHJlZ2V4cC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVJlZ0V4cChyZWdleHApIHtcbiAgICAgIHZhciByZXN1bHQgPSBuZXcgcmVnZXhwLmNvbnN0cnVjdG9yKHJlZ2V4cC5zb3VyY2UsIHJlRmxhZ3MuZXhlYyhyZWdleHApKTtcbiAgICAgIHJlc3VsdC5sYXN0SW5kZXggPSByZWdleHAubGFzdEluZGV4O1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGBzeW1ib2xgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHN5bWJvbCBUaGUgc3ltYm9sIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgc3ltYm9sIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVN5bWJvbChzeW1ib2wpIHtcbiAgICAgIHJldHVybiBzeW1ib2xWYWx1ZU9mID8gT2JqZWN0KHN5bWJvbFZhbHVlT2YuY2FsbChzeW1ib2wpKSA6IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgdHlwZWRBcnJheWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0eXBlZEFycmF5IFRoZSB0eXBlZCBhcnJheSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCB0eXBlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVR5cGVkQXJyYXkodHlwZWRBcnJheSwgaXNEZWVwKSB7XG4gICAgICB2YXIgYnVmZmVyID0gaXNEZWVwID8gY2xvbmVBcnJheUJ1ZmZlcih0eXBlZEFycmF5LmJ1ZmZlcikgOiB0eXBlZEFycmF5LmJ1ZmZlcjtcbiAgICAgIHJldHVybiBuZXcgdHlwZWRBcnJheS5jb25zdHJ1Y3RvcihidWZmZXIsIHR5cGVkQXJyYXkuYnl0ZU9mZnNldCwgdHlwZWRBcnJheS5sZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXBhcmVzIHZhbHVlcyB0byBzb3J0IHRoZW0gaW4gYXNjZW5kaW5nIG9yZGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3IgZm9yIGB2YWx1ZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFyZUFzY2VuZGluZyh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIGlmICh2YWx1ZSAhPT0gb3RoZXIpIHtcbiAgICAgICAgdmFyIHZhbElzRGVmaW5lZCA9IHZhbHVlICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICB2YWxJc051bGwgPSB2YWx1ZSA9PT0gbnVsbCxcbiAgICAgICAgICAgIHZhbElzUmVmbGV4aXZlID0gdmFsdWUgPT09IHZhbHVlLFxuICAgICAgICAgICAgdmFsSXNTeW1ib2wgPSBpc1N5bWJvbCh2YWx1ZSk7XG5cbiAgICAgICAgdmFyIG90aElzRGVmaW5lZCA9IG90aGVyICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICBvdGhJc051bGwgPSBvdGhlciA9PT0gbnVsbCxcbiAgICAgICAgICAgIG90aElzUmVmbGV4aXZlID0gb3RoZXIgPT09IG90aGVyLFxuICAgICAgICAgICAgb3RoSXNTeW1ib2wgPSBpc1N5bWJvbChvdGhlcik7XG5cbiAgICAgICAgaWYgKCghb3RoSXNOdWxsICYmICFvdGhJc1N5bWJvbCAmJiAhdmFsSXNTeW1ib2wgJiYgdmFsdWUgPiBvdGhlcikgfHxcbiAgICAgICAgICAgICh2YWxJc1N5bWJvbCAmJiBvdGhJc0RlZmluZWQgJiYgb3RoSXNSZWZsZXhpdmUgJiYgIW90aElzTnVsbCAmJiAhb3RoSXNTeW1ib2wpIHx8XG4gICAgICAgICAgICAodmFsSXNOdWxsICYmIG90aElzRGVmaW5lZCAmJiBvdGhJc1JlZmxleGl2ZSkgfHxcbiAgICAgICAgICAgICghdmFsSXNEZWZpbmVkICYmIG90aElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgIXZhbElzUmVmbGV4aXZlKSB7XG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCghdmFsSXNOdWxsICYmICF2YWxJc1N5bWJvbCAmJiAhb3RoSXNTeW1ib2wgJiYgdmFsdWUgPCBvdGhlcikgfHxcbiAgICAgICAgICAgIChvdGhJc1N5bWJvbCAmJiB2YWxJc0RlZmluZWQgJiYgdmFsSXNSZWZsZXhpdmUgJiYgIXZhbElzTnVsbCAmJiAhdmFsSXNTeW1ib2wpIHx8XG4gICAgICAgICAgICAob3RoSXNOdWxsICYmIHZhbElzRGVmaW5lZCAmJiB2YWxJc1JlZmxleGl2ZSkgfHxcbiAgICAgICAgICAgICghb3RoSXNEZWZpbmVkICYmIHZhbElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgIW90aElzUmVmbGV4aXZlKSB7XG4gICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGJ5IGBfLm9yZGVyQnlgIHRvIGNvbXBhcmUgbXVsdGlwbGUgcHJvcGVydGllcyBvZiBhIHZhbHVlIHRvIGFub3RoZXJcbiAgICAgKiBhbmQgc3RhYmxlIHNvcnQgdGhlbS5cbiAgICAgKlxuICAgICAqIElmIGBvcmRlcnNgIGlzIHVuc3BlY2lmaWVkLCBhbGwgdmFsdWVzIGFyZSBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyLiBPdGhlcndpc2UsXG4gICAgICogc3BlY2lmeSBhbiBvcmRlciBvZiBcImRlc2NcIiBmb3IgZGVzY2VuZGluZyBvciBcImFzY1wiIGZvciBhc2NlbmRpbmcgc29ydCBvcmRlclxuICAgICAqIG9mIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbltdfHN0cmluZ1tdfSBvcmRlcnMgVGhlIG9yZGVyIHRvIHNvcnQgYnkgZm9yIGVhY2ggcHJvcGVydHkuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3IgZm9yIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBhcmVNdWx0aXBsZShvYmplY3QsIG90aGVyLCBvcmRlcnMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIG9iakNyaXRlcmlhID0gb2JqZWN0LmNyaXRlcmlhLFxuICAgICAgICAgIG90aENyaXRlcmlhID0gb3RoZXIuY3JpdGVyaWEsXG4gICAgICAgICAgbGVuZ3RoID0gb2JqQ3JpdGVyaWEubGVuZ3RoLFxuICAgICAgICAgIG9yZGVyc0xlbmd0aCA9IG9yZGVycy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjb21wYXJlQXNjZW5kaW5nKG9iakNyaXRlcmlhW2luZGV4XSwgb3RoQ3JpdGVyaWFbaW5kZXhdKTtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIGlmIChpbmRleCA+PSBvcmRlcnNMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBvcmRlciA9IG9yZGVyc1tpbmRleF07XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdCAqIChvcmRlciA9PSAnZGVzYycgPyAtMSA6IDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBGaXhlcyBhbiBgQXJyYXkjc29ydGAgYnVnIGluIHRoZSBKUyBlbmdpbmUgZW1iZWRkZWQgaW4gQWRvYmUgYXBwbGljYXRpb25zXG4gICAgICAvLyB0aGF0IGNhdXNlcyBpdCwgdW5kZXIgY2VydGFpbiBjaXJjdW1zdGFuY2VzLCB0byBwcm92aWRlIHRoZSBzYW1lIHZhbHVlIGZvclxuICAgICAgLy8gYG9iamVjdGAgYW5kIGBvdGhlcmAuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvcHVsbC8xMjQ3XG4gICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgLy9cbiAgICAgIC8vIFRoaXMgYWxzbyBlbnN1cmVzIGEgc3RhYmxlIHNvcnQgaW4gVjggYW5kIG90aGVyIGVuZ2luZXMuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9OTAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIHJldHVybiBvYmplY3QuaW5kZXggLSBvdGhlci5pbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IHRoYXQgaXMgdGhlIGNvbXBvc2l0aW9uIG9mIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cyxcbiAgICAgKiBwbGFjZWhvbGRlcnMsIGFuZCBwcm92aWRlZCBhcmd1bWVudHMgaW50byBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgVGhlIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXJ0aWFscyBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQuXG4gICAgICogQHBhcmFtIHtBcnJheX0gaG9sZGVycyBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbXMge2Jvb2xlYW59IFtpc0N1cnJpZWRdIFNwZWNpZnkgY29tcG9zaW5nIGZvciBhIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tcG9zZWQgYXJndW1lbnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBvc2VBcmdzKGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpIHtcbiAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gYXJncy5sZW5ndGgsXG4gICAgICAgICAgaG9sZGVyc0xlbmd0aCA9IGhvbGRlcnMubGVuZ3RoLFxuICAgICAgICAgIGxlZnRJbmRleCA9IC0xLFxuICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgcmFuZ2VMZW5ndGggPSBuYXRpdmVNYXgoYXJnc0xlbmd0aCAtIGhvbGRlcnNMZW5ndGgsIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlZnRMZW5ndGggKyByYW5nZUxlbmd0aCksXG4gICAgICAgICAgaXNVbmN1cnJpZWQgPSAhaXNDdXJyaWVkO1xuXG4gICAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2FyZ3NJbmRleCA8IGhvbGRlcnNMZW5ndGgpIHtcbiAgICAgICAgaWYgKGlzVW5jdXJyaWVkIHx8IGFyZ3NJbmRleCA8IGFyZ3NMZW5ndGgpIHtcbiAgICAgICAgICByZXN1bHRbaG9sZGVyc1thcmdzSW5kZXhdXSA9IGFyZ3NbYXJnc0luZGV4XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2hpbGUgKHJhbmdlTGVuZ3RoLS0pIHtcbiAgICAgICAgcmVzdWx0W2xlZnRJbmRleCsrXSA9IGFyZ3NbYXJnc0luZGV4KytdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGNvbXBvc2VBcmdzYCBleGNlcHQgdGhhdCB0aGUgYXJndW1lbnRzIGNvbXBvc2l0aW9uXG4gICAgICogaXMgdGFpbG9yZWQgZm9yIGBfLnBhcnRpYWxSaWdodGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgVGhlIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXJ0aWFscyBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBob2xkZXJzIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtcyB7Ym9vbGVhbn0gW2lzQ3VycmllZF0gU3BlY2lmeSBjb21wb3NpbmcgZm9yIGEgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21wb3NlZCBhcmd1bWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFscywgaG9sZGVycywgaXNDdXJyaWVkKSB7XG4gICAgICB2YXIgYXJnc0luZGV4ID0gLTEsXG4gICAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3MubGVuZ3RoLFxuICAgICAgICAgIGhvbGRlcnNJbmRleCA9IC0xLFxuICAgICAgICAgIGhvbGRlcnNMZW5ndGggPSBob2xkZXJzLmxlbmd0aCxcbiAgICAgICAgICByaWdodEluZGV4ID0gLTEsXG4gICAgICAgICAgcmlnaHRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgcmFuZ2VMZW5ndGggPSBuYXRpdmVNYXgoYXJnc0xlbmd0aCAtIGhvbGRlcnNMZW5ndGgsIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KHJhbmdlTGVuZ3RoICsgcmlnaHRMZW5ndGgpLFxuICAgICAgICAgIGlzVW5jdXJyaWVkID0gIWlzQ3VycmllZDtcblxuICAgICAgd2hpbGUgKCsrYXJnc0luZGV4IDwgcmFuZ2VMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2FyZ3NJbmRleF0gPSBhcmdzW2FyZ3NJbmRleF07XG4gICAgICB9XG4gICAgICB2YXIgb2Zmc2V0ID0gYXJnc0luZGV4O1xuICAgICAgd2hpbGUgKCsrcmlnaHRJbmRleCA8IHJpZ2h0TGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtvZmZzZXQgKyByaWdodEluZGV4XSA9IHBhcnRpYWxzW3JpZ2h0SW5kZXhdO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsraG9sZGVyc0luZGV4IDwgaG9sZGVyc0xlbmd0aCkge1xuICAgICAgICBpZiAoaXNVbmN1cnJpZWQgfHwgYXJnc0luZGV4IDwgYXJnc0xlbmd0aCkge1xuICAgICAgICAgIHJlc3VsdFtvZmZzZXQgKyBob2xkZXJzW2hvbGRlcnNJbmRleF1dID0gYXJnc1thcmdzSW5kZXgrK107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29waWVzIHRoZSB2YWx1ZXMgb2YgYHNvdXJjZWAgdG8gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gc291cmNlIFRoZSBhcnJheSB0byBjb3B5IHZhbHVlcyBmcm9tLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheT1bXV0gVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIHRvLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlBcnJheShzb3VyY2UsIGFycmF5KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBzb3VyY2UubGVuZ3RoO1xuXG4gICAgICBhcnJheSB8fCAoYXJyYXkgPSBBcnJheShsZW5ndGgpKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGFycmF5W2luZGV4XSA9IHNvdXJjZVtpbmRleF07XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29waWVzIHByb3BlcnRpZXMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgaWRlbnRpZmllcnMgdG8gY29weS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29waWVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlPYmplY3Qoc291cmNlLCBwcm9wcywgb2JqZWN0LCBjdXN0b21pemVyKSB7XG4gICAgICB2YXIgaXNOZXcgPSAhb2JqZWN0O1xuICAgICAgb2JqZWN0IHx8IChvYmplY3QgPSB7fSk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGtleSA9IHByb3BzW2luZGV4XTtcblxuICAgICAgICB2YXIgbmV3VmFsdWUgPSBjdXN0b21pemVyXG4gICAgICAgICAgPyBjdXN0b21pemVyKG9iamVjdFtrZXldLCBzb3VyY2Vba2V5XSwga2V5LCBvYmplY3QsIHNvdXJjZSlcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5ld1ZhbHVlID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTmV3KSB7XG4gICAgICAgICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXNzaWduVmFsdWUob2JqZWN0LCBrZXksIG5ld1ZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgb3duIHN5bWJvbHMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgdG8uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb3B5U3ltYm9scyhzb3VyY2UsIG9iamVjdCkge1xuICAgICAgcmV0dXJuIGNvcHlPYmplY3Qoc291cmNlLCBnZXRTeW1ib2xzKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29waWVzIG93biBhbmQgaW5oZXJpdGVkIHN5bWJvbHMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgdG8uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb3B5U3ltYm9sc0luKHNvdXJjZSwgb2JqZWN0KSB7XG4gICAgICByZXR1cm4gY29weU9iamVjdChzb3VyY2UsIGdldFN5bWJvbHNJbihzb3VyY2UpLCBvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLmdyb3VwQnlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBhY2N1bXVsYXRvciB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2luaXRpYWxpemVyXSBUaGUgYWNjdW11bGF0b3Igb2JqZWN0IGluaXRpYWxpemVyLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFnZ3JlZ2F0b3IgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQWdncmVnYXRvcihzZXR0ZXIsIGluaXRpYWxpemVyKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlBZ2dyZWdhdG9yIDogYmFzZUFnZ3JlZ2F0b3IsXG4gICAgICAgICAgICBhY2N1bXVsYXRvciA9IGluaXRpYWxpemVyID8gaW5pdGlhbGl6ZXIoKSA6IHt9O1xuXG4gICAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIHNldHRlciwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBhY2N1bXVsYXRvcik7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLmFzc2lnbmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGFzc2lnbmVyIFRoZSBmdW5jdGlvbiB0byBhc3NpZ24gdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFzc2lnbmVyIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUFzc2lnbmVyKGFzc2lnbmVyKSB7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2VzKSB7XG4gICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gc291cmNlcy5sZW5ndGgsXG4gICAgICAgICAgICBjdXN0b21pemVyID0gbGVuZ3RoID4gMSA/IHNvdXJjZXNbbGVuZ3RoIC0gMV0gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBndWFyZCA9IGxlbmd0aCA+IDIgPyBzb3VyY2VzWzJdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGN1c3RvbWl6ZXIgPSAoYXNzaWduZXIubGVuZ3RoID4gMyAmJiB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nKVxuICAgICAgICAgID8gKGxlbmd0aC0tLCBjdXN0b21pemVyKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChzb3VyY2VzWzBdLCBzb3VyY2VzWzFdLCBndWFyZCkpIHtcbiAgICAgICAgICBjdXN0b21pemVyID0gbGVuZ3RoIDwgMyA/IHVuZGVmaW5lZCA6IGN1c3RvbWl6ZXI7XG4gICAgICAgICAgbGVuZ3RoID0gMTtcbiAgICAgICAgfVxuICAgICAgICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgc291cmNlID0gc291cmNlc1tpbmRleF07XG4gICAgICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICAgICAgYXNzaWduZXIob2JqZWN0LCBzb3VyY2UsIGluZGV4LCBjdXN0b21pemVyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgYmFzZUVhY2hgIG9yIGBiYXNlRWFjaFJpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBhIGNvbGxlY3Rpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYmFzZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVCYXNlRWFjaChlYWNoRnVuYywgZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNBcnJheUxpa2UoY29sbGVjdGlvbikpIHtcbiAgICAgICAgICByZXR1cm4gZWFjaEZ1bmMoY29sbGVjdGlvbiwgaXRlcmF0ZWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aCxcbiAgICAgICAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTEsXG4gICAgICAgICAgICBpdGVyYWJsZSA9IE9iamVjdChjb2xsZWN0aW9uKTtcblxuICAgICAgICB3aGlsZSAoKGZyb21SaWdodCA/IGluZGV4LS0gOiArK2luZGV4IDwgbGVuZ3RoKSkge1xuICAgICAgICAgIGlmIChpdGVyYXRlZShpdGVyYWJsZVtpbmRleF0sIGluZGV4LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBiYXNlIGZ1bmN0aW9uIGZvciBtZXRob2RzIGxpa2UgYF8uZm9ySW5gIGFuZCBgXy5mb3JPd25gLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VGb3IoZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0LCBpdGVyYXRlZSwga2V5c0Z1bmMpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBpdGVyYWJsZSA9IE9iamVjdChvYmplY3QpLFxuICAgICAgICAgICAgcHJvcHMgPSBrZXlzRnVuYyhvYmplY3QpLFxuICAgICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICAgIHZhciBrZXkgPSBwcm9wc1tmcm9tUmlnaHQgPyBsZW5ndGggOiArK2luZGV4XTtcbiAgICAgICAgICBpZiAoaXRlcmF0ZWUoaXRlcmFibGVba2V5XSwga2V5LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIHRoZSBvcHRpb25hbCBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIGB0aGlzQXJnYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVCaW5kKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpc0JpbmQgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcsXG4gICAgICAgICAgQ3RvciA9IGNyZWF0ZUN0b3IoZnVuYyk7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IHJvb3QgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgICAgIHJldHVybiBmbi5hcHBseShpc0JpbmQgPyB0aGlzQXJnIDogdGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB3cmFwcGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLmxvd2VyRmlyc3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSBUaGUgbmFtZSBvZiB0aGUgYFN0cmluZ2AgY2FzZSBtZXRob2QgdG8gdXNlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNhc2UgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ2FzZUZpcnN0KG1ldGhvZE5hbWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcblxuICAgICAgICB2YXIgc3RyU3ltYm9scyA9IGhhc1VuaWNvZGUoc3RyaW5nKVxuICAgICAgICAgID8gc3RyaW5nVG9BcnJheShzdHJpbmcpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgdmFyIGNociA9IHN0clN5bWJvbHNcbiAgICAgICAgICA/IHN0clN5bWJvbHNbMF1cbiAgICAgICAgICA6IHN0cmluZy5jaGFyQXQoMCk7XG5cbiAgICAgICAgdmFyIHRyYWlsaW5nID0gc3RyU3ltYm9sc1xuICAgICAgICAgID8gY2FzdFNsaWNlKHN0clN5bWJvbHMsIDEpLmpvaW4oJycpXG4gICAgICAgICAgOiBzdHJpbmcuc2xpY2UoMSk7XG5cbiAgICAgICAgcmV0dXJuIGNoclttZXRob2ROYW1lXSgpICsgdHJhaWxpbmc7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLmNhbWVsQ2FzZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjb21iaW5lIGVhY2ggd29yZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb21wb3VuZGVyIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUNvbXBvdW5kZXIoY2FsbGJhY2spIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKHdvcmRzKGRlYnVycihzdHJpbmcpLnJlcGxhY2UocmVBcG9zLCAnJykpLCBjYWxsYmFjaywgJycpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhbiBpbnN0YW5jZSBvZiBgQ3RvcmAgcmVnYXJkbGVzcyBvZlxuICAgICAqIHdoZXRoZXIgaXQgd2FzIGludm9rZWQgYXMgcGFydCBvZiBhIGBuZXdgIGV4cHJlc3Npb24gb3IgYnkgYGNhbGxgIG9yIGBhcHBseWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IEN0b3IgVGhlIGNvbnN0cnVjdG9yIHRvIHdyYXAuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDdG9yKEN0b3IpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gVXNlIGEgYHN3aXRjaGAgc3RhdGVtZW50IHRvIHdvcmsgd2l0aCBjbGFzcyBjb25zdHJ1Y3RvcnMuIFNlZVxuICAgICAgICAvLyBodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWZ1bmN0aW9uLW9iamVjdHMtY2FsbC10aGlzYXJndW1lbnQtYXJndW1lbnRzbGlzdFxuICAgICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDogcmV0dXJuIG5ldyBDdG9yO1xuICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0pO1xuICAgICAgICAgIGNhc2UgMjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgICAgICAgIGNhc2UgMzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICAgIGNhc2UgNDogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pO1xuICAgICAgICAgIGNhc2UgNTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0pO1xuICAgICAgICAgIGNhc2UgNjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pO1xuICAgICAgICAgIGNhc2UgNzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0sIGFyZ3NbNl0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aGlzQmluZGluZyA9IGJhc2VDcmVhdGUoQ3Rvci5wcm90b3R5cGUpLFxuICAgICAgICAgICAgcmVzdWx0ID0gQ3Rvci5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG5cbiAgICAgICAgLy8gTWltaWMgdGhlIGNvbnN0cnVjdG9yJ3MgYHJldHVybmAgYmVoYXZpb3IuXG4gICAgICAgIC8vIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxMy4yLjIgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHJlc3VsdCkgPyByZXN1bHQgOiB0aGlzQmluZGluZztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGVuYWJsZSBjdXJyeWluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhcml0eSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ3VycnkoZnVuYywgYml0bWFzaywgYXJpdHkpIHtcbiAgICAgIHZhciBDdG9yID0gY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVuZ3RoKSxcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICAgICAgcGxhY2Vob2xkZXIgPSBnZXRIb2xkZXIod3JhcHBlcik7XG5cbiAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhvbGRlcnMgPSAobGVuZ3RoIDwgMyAmJiBhcmdzWzBdICE9PSBwbGFjZWhvbGRlciAmJiBhcmdzW2xlbmd0aCAtIDFdICE9PSBwbGFjZWhvbGRlcilcbiAgICAgICAgICA/IFtdXG4gICAgICAgICAgOiByZXBsYWNlSG9sZGVycyhhcmdzLCBwbGFjZWhvbGRlcik7XG5cbiAgICAgICAgbGVuZ3RoIC09IGhvbGRlcnMubGVuZ3RoO1xuICAgICAgICBpZiAobGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlUmVjdXJyeShcbiAgICAgICAgICAgIGZ1bmMsIGJpdG1hc2ssIGNyZWF0ZUh5YnJpZCwgd3JhcHBlci5wbGFjZWhvbGRlciwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgYXJncywgaG9sZGVycywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGFyaXR5IC0gbGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZm4gPSAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSA/IEN0b3IgOiBmdW5jO1xuICAgICAgICByZXR1cm4gYXBwbHkoZm4sIHRoaXMsIGFyZ3MpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLmZpbmRgIG9yIGBfLmZpbmRMYXN0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZmluZEluZGV4RnVuYyBUaGUgZnVuY3Rpb24gdG8gZmluZCB0aGUgY29sbGVjdGlvbiBpbmRleC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmaW5kIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUZpbmQoZmluZEluZGV4RnVuYykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZnJvbUluZGV4KSB7XG4gICAgICAgIHZhciBpdGVyYWJsZSA9IE9iamVjdChjb2xsZWN0aW9uKTtcbiAgICAgICAgaWYgKCFpc0FycmF5TGlrZShjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHZhciBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyk7XG4gICAgICAgICAgY29sbGVjdGlvbiA9IGtleXMoY29sbGVjdGlvbik7XG4gICAgICAgICAgcHJlZGljYXRlID0gZnVuY3Rpb24oa2V5KSB7IHJldHVybiBpdGVyYXRlZShpdGVyYWJsZVtrZXldLCBrZXksIGl0ZXJhYmxlKTsgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaW5kZXggPSBmaW5kSW5kZXhGdW5jKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZnJvbUluZGV4KTtcbiAgICAgICAgcmV0dXJuIGluZGV4ID4gLTEgPyBpdGVyYWJsZVtpdGVyYXRlZSA/IGNvbGxlY3Rpb25baW5kZXhdIDogaW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZmxvd2Agb3IgYF8uZmxvd1JpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZmxvdyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVGbG93KGZyb21SaWdodCkge1xuICAgICAgcmV0dXJuIGZsYXRSZXN0KGZ1bmN0aW9uKGZ1bmNzKSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBmdW5jcy5sZW5ndGgsXG4gICAgICAgICAgICBpbmRleCA9IGxlbmd0aCxcbiAgICAgICAgICAgIHByZXJlcSA9IExvZGFzaFdyYXBwZXIucHJvdG90eXBlLnRocnU7XG5cbiAgICAgICAgaWYgKGZyb21SaWdodCkge1xuICAgICAgICAgIGZ1bmNzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICAgIHZhciBmdW5jID0gZnVuY3NbaW5kZXhdO1xuICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChwcmVyZXEgJiYgIXdyYXBwZXIgJiYgZ2V0RnVuY05hbWUoZnVuYykgPT0gJ3dyYXBwZXInKSB7XG4gICAgICAgICAgICB2YXIgd3JhcHBlciA9IG5ldyBMb2Rhc2hXcmFwcGVyKFtdLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSB3cmFwcGVyID8gaW5kZXggOiBsZW5ndGg7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgZnVuYyA9IGZ1bmNzW2luZGV4XTtcblxuICAgICAgICAgIHZhciBmdW5jTmFtZSA9IGdldEZ1bmNOYW1lKGZ1bmMpLFxuICAgICAgICAgICAgICBkYXRhID0gZnVuY05hbWUgPT0gJ3dyYXBwZXInID8gZ2V0RGF0YShmdW5jKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgIGlmIChkYXRhICYmIGlzTGF6aWFibGUoZGF0YVswXSkgJiZcbiAgICAgICAgICAgICAgICBkYXRhWzFdID09IChXUkFQX0FSWV9GTEFHIHwgV1JBUF9DVVJSWV9GTEFHIHwgV1JBUF9QQVJUSUFMX0ZMQUcgfCBXUkFQX1JFQVJHX0ZMQUcpICYmXG4gICAgICAgICAgICAgICAgIWRhdGFbNF0ubGVuZ3RoICYmIGRhdGFbOV0gPT0gMVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgIHdyYXBwZXIgPSB3cmFwcGVyW2dldEZ1bmNOYW1lKGRhdGFbMF0pXS5hcHBseSh3cmFwcGVyLCBkYXRhWzNdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JhcHBlciA9IChmdW5jLmxlbmd0aCA9PSAxICYmIGlzTGF6aWFibGUoZnVuYykpXG4gICAgICAgICAgICAgID8gd3JhcHBlcltmdW5jTmFtZV0oKVxuICAgICAgICAgICAgICA6IHdyYXBwZXIudGhydShmdW5jKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAgICB2YWx1ZSA9IGFyZ3NbMF07XG5cbiAgICAgICAgICBpZiAod3JhcHBlciAmJiBhcmdzLmxlbmd0aCA9PSAxICYmIGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gd3JhcHBlci5wbGFudCh2YWx1ZSkudmFsdWUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICAgICAgcmVzdWx0ID0gbGVuZ3RoID8gZnVuY3NbaW5kZXhdLmFwcGx5KHRoaXMsIGFyZ3MpIDogdmFsdWU7XG5cbiAgICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuY3NbaW5kZXhdLmNhbGwodGhpcywgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCB0byBpbnZva2UgaXQgd2l0aCBvcHRpb25hbCBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIGB0aGlzQXJnYCwgcGFydGlhbCBhcHBsaWNhdGlvbiwgYW5kIGN1cnJ5aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAgICAgKiAgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNSaWdodF0gVGhlIGFyZ3VtZW50cyB0byBhcHBlbmQgdG8gdGhvc2UgcHJvdmlkZWRcbiAgICAgKiAgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc1JpZ2h0XSBUaGUgYHBhcnRpYWxzUmlnaHRgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ1Bvc10gVGhlIGFyZ3VtZW50IHBvc2l0aW9ucyBvZiB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJ5XSBUaGUgYXJpdHkgY2FwIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5XSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlSHlicmlkKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQXJ5ID0gYml0bWFzayAmIFdSQVBfQVJZX0ZMQUcsXG4gICAgICAgICAgaXNCaW5kID0gYml0bWFzayAmIFdSQVBfQklORF9GTEFHLFxuICAgICAgICAgIGlzQmluZEtleSA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfS0VZX0ZMQUcsXG4gICAgICAgICAgaXNDdXJyaWVkID0gYml0bWFzayAmIChXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpLFxuICAgICAgICAgIGlzRmxpcCA9IGJpdG1hc2sgJiBXUkFQX0ZMSVBfRkxBRyxcbiAgICAgICAgICBDdG9yID0gaXNCaW5kS2V5ID8gdW5kZWZpbmVkIDogY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVuZ3RoKSxcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgYXJnc1tpbmRleF0gPSBhcmd1bWVudHNbaW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0N1cnJpZWQpIHtcbiAgICAgICAgICB2YXIgcGxhY2Vob2xkZXIgPSBnZXRIb2xkZXIod3JhcHBlciksXG4gICAgICAgICAgICAgIGhvbGRlcnNDb3VudCA9IGNvdW50SG9sZGVycyhhcmdzLCBwbGFjZWhvbGRlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRpYWxzKSB7XG4gICAgICAgICAgYXJncyA9IGNvbXBvc2VBcmdzKGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJ0aWFsc1JpZ2h0KSB7XG4gICAgICAgICAgYXJncyA9IGNvbXBvc2VBcmdzUmlnaHQoYXJncywgcGFydGlhbHNSaWdodCwgaG9sZGVyc1JpZ2h0LCBpc0N1cnJpZWQpO1xuICAgICAgICB9XG4gICAgICAgIGxlbmd0aCAtPSBob2xkZXJzQ291bnQ7XG4gICAgICAgIGlmIChpc0N1cnJpZWQgJiYgbGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICB2YXIgbmV3SG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlUmVjdXJyeShcbiAgICAgICAgICAgIGZ1bmMsIGJpdG1hc2ssIGNyZWF0ZUh5YnJpZCwgd3JhcHBlci5wbGFjZWhvbGRlciwgdGhpc0FyZyxcbiAgICAgICAgICAgIGFyZ3MsIG5ld0hvbGRlcnMsIGFyZ1BvcywgYXJ5LCBhcml0eSAtIGxlbmd0aFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRoaXNCaW5kaW5nID0gaXNCaW5kID8gdGhpc0FyZyA6IHRoaXMsXG4gICAgICAgICAgICBmbiA9IGlzQmluZEtleSA/IHRoaXNCaW5kaW5nW2Z1bmNdIDogZnVuYztcblxuICAgICAgICBsZW5ndGggPSBhcmdzLmxlbmd0aDtcbiAgICAgICAgaWYgKGFyZ1Bvcykge1xuICAgICAgICAgIGFyZ3MgPSByZW9yZGVyKGFyZ3MsIGFyZ1Bvcyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNGbGlwICYmIGxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBhcmdzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNBcnkgJiYgYXJ5IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYXJncy5sZW5ndGggPSBhcnk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikge1xuICAgICAgICAgIGZuID0gQ3RvciB8fCBjcmVhdGVDdG9yKGZuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpc0JpbmRpbmcsIGFyZ3MpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uaW52ZXJ0QnlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBhY2N1bXVsYXRvciB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdG9JdGVyYXRlZSBUaGUgZnVuY3Rpb24gdG8gcmVzb2x2ZSBpdGVyYXRlZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgaW52ZXJ0ZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlSW52ZXJ0ZXIoc2V0dGVyLCB0b0l0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgICByZXR1cm4gYmFzZUludmVydGVyKG9iamVjdCwgc2V0dGVyLCB0b0l0ZXJhdGVlKGl0ZXJhdGVlKSwge30pO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBhIG1hdGhlbWF0aWNhbCBvcGVyYXRpb24gb24gdHdvIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3BlcmF0b3IgVGhlIGZ1bmN0aW9uIHRvIHBlcmZvcm0gdGhlIG9wZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2RlZmF1bHRWYWx1ZV0gVGhlIHZhbHVlIHVzZWQgZm9yIGB1bmRlZmluZWRgIGFyZ3VtZW50cy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBtYXRoZW1hdGljYWwgb3BlcmF0aW9uIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZU1hdGhPcGVyYXRpb24ob3BlcmF0b3IsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAgICB2YXIgcmVzdWx0O1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBvdGhlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvdGhlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gb3RoZXI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHwgdHlwZW9mIG90aGVyID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGJhc2VUb1N0cmluZyh2YWx1ZSk7XG4gICAgICAgICAgICBvdGhlciA9IGJhc2VUb1N0cmluZyhvdGhlcik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZVRvTnVtYmVyKHZhbHVlKTtcbiAgICAgICAgICAgIG90aGVyID0gYmFzZVRvTnVtYmVyKG90aGVyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0ID0gb3BlcmF0b3IodmFsdWUsIG90aGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5vdmVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXJyYXlGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgaXRlcmF0ZWVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG92ZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlT3ZlcihhcnJheUZ1bmMpIHtcbiAgICAgIHJldHVybiBmbGF0UmVzdChmdW5jdGlvbihpdGVyYXRlZXMpIHtcbiAgICAgICAgaXRlcmF0ZWVzID0gYXJyYXlNYXAoaXRlcmF0ZWVzLCBiYXNlVW5hcnkoZ2V0SXRlcmF0ZWUoKSkpO1xuICAgICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICAgIHZhciB0aGlzQXJnID0gdGhpcztcbiAgICAgICAgICByZXR1cm4gYXJyYXlGdW5jKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHtcbiAgICAgICAgICAgIHJldHVybiBhcHBseShpdGVyYXRlZSwgdGhpc0FyZywgYXJncyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgcGFkZGluZyBmb3IgYHN0cmluZ2AgYmFzZWQgb24gYGxlbmd0aGAuIFRoZSBgY2hhcnNgIHN0cmluZ1xuICAgICAqIGlzIHRydW5jYXRlZCBpZiB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgZXhjZWVkcyBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRpbmcgZm9yIGBzdHJpbmdgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVBhZGRpbmcobGVuZ3RoLCBjaGFycykge1xuICAgICAgY2hhcnMgPSBjaGFycyA9PT0gdW5kZWZpbmVkID8gJyAnIDogYmFzZVRvU3RyaW5nKGNoYXJzKTtcblxuICAgICAgdmFyIGNoYXJzTGVuZ3RoID0gY2hhcnMubGVuZ3RoO1xuICAgICAgaWYgKGNoYXJzTGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gY2hhcnNMZW5ndGggPyBiYXNlUmVwZWF0KGNoYXJzLCBsZW5ndGgpIDogY2hhcnM7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZVJlcGVhdChjaGFycywgbmF0aXZlQ2VpbChsZW5ndGggLyBzdHJpbmdTaXplKGNoYXJzKSkpO1xuICAgICAgcmV0dXJuIGhhc1VuaWNvZGUoY2hhcnMpXG4gICAgICAgID8gY2FzdFNsaWNlKHN0cmluZ1RvQXJyYXkocmVzdWx0KSwgMCwgbGVuZ3RoKS5qb2luKCcnKVxuICAgICAgICA6IHJlc3VsdC5zbGljZSgwLCBsZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCB0byBpbnZva2UgaXQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmdcbiAgICAgKiBvZiBgdGhpc0FyZ2AgYW5kIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgY3JlYXRlV3JhcGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXJ0aWFscyBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAgICAgKiAgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVBhcnRpYWwoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBpc0JpbmQgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcsXG4gICAgICAgICAgQ3RvciA9IGNyZWF0ZUN0b3IoZnVuYyk7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICAgIGFyZ3NMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICAgICAgbGVmdEluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZWZ0TGVuZ3RoID0gcGFydGlhbHMubGVuZ3RoLFxuICAgICAgICAgICAgYXJncyA9IEFycmF5KGxlZnRMZW5ndGggKyBhcmdzTGVuZ3RoKSxcbiAgICAgICAgICAgIGZuID0gKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcblxuICAgICAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICAgICAgYXJnc1tsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSAoYXJnc0xlbmd0aC0tKSB7XG4gICAgICAgICAgYXJnc1tsZWZ0SW5kZXgrK10gPSBhcmd1bWVudHNbKythcmdzSW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcHBseShmbiwgaXNCaW5kID8gdGhpc0FyZyA6IHRoaXMsIGFyZ3MpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLnJhbmdlYCBvciBgXy5yYW5nZVJpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmFuZ2UgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUmFuZ2UoZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oc3RhcnQsIGVuZCwgc3RlcCkge1xuICAgICAgICBpZiAoc3RlcCAmJiB0eXBlb2Ygc3RlcCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChzdGFydCwgZW5kLCBzdGVwKSkge1xuICAgICAgICAgIGVuZCA9IHN0ZXAgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW5zdXJlIHRoZSBzaWduIG9mIGAtMGAgaXMgcHJlc2VydmVkLlxuICAgICAgICBzdGFydCA9IHRvRmluaXRlKHN0YXJ0KTtcbiAgICAgICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVuZCA9IHRvRmluaXRlKGVuZCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RlcCA9IHN0ZXAgPT09IHVuZGVmaW5lZCA/IChzdGFydCA8IGVuZCA/IDEgOiAtMSkgOiB0b0Zpbml0ZShzdGVwKTtcbiAgICAgICAgcmV0dXJuIGJhc2VSYW5nZShzdGFydCwgZW5kLCBzdGVwLCBmcm9tUmlnaHQpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBhIHJlbGF0aW9uYWwgb3BlcmF0aW9uIG9uIHR3byB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wZXJhdG9yIFRoZSBmdW5jdGlvbiB0byBwZXJmb3JtIHRoZSBvcGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmVsYXRpb25hbCBvcGVyYXRpb24gZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUmVsYXRpb25hbE9wZXJhdGlvbihvcGVyYXRvcikge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAgICBpZiAoISh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgJiYgdHlwZW9mIG90aGVyID09ICdzdHJpbmcnKSkge1xuICAgICAgICAgIHZhbHVlID0gdG9OdW1iZXIodmFsdWUpO1xuICAgICAgICAgIG90aGVyID0gdG9OdW1iZXIob3RoZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvcGVyYXRvcih2YWx1ZSwgb3RoZXIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gY29udGludWUgY3VycnlpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgY3JlYXRlV3JhcGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB3cmFwRnVuYyBUaGUgZnVuY3Rpb24gdG8gY3JlYXRlIHRoZSBgZnVuY2Agd3JhcHBlci5cbiAgICAgKiBAcGFyYW0geyp9IHBsYWNlaG9sZGVyIFRoZSBwbGFjZWhvbGRlciB2YWx1ZS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBwcmVwZW5kIHRvIHRob3NlIHByb3ZpZGVkIHRvXG4gICAgICogIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2hvbGRlcnNdIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ1Bvc10gVGhlIGFyZ3VtZW50IHBvc2l0aW9ucyBvZiB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJ5XSBUaGUgYXJpdHkgY2FwIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5XSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUmVjdXJyeShmdW5jLCBiaXRtYXNrLCB3cmFwRnVuYywgcGxhY2Vob2xkZXIsIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBhcmdQb3MsIGFyeSwgYXJpdHkpIHtcbiAgICAgIHZhciBpc0N1cnJ5ID0gYml0bWFzayAmIFdSQVBfQ1VSUllfRkxBRyxcbiAgICAgICAgICBuZXdIb2xkZXJzID0gaXNDdXJyeSA/IGhvbGRlcnMgOiB1bmRlZmluZWQsXG4gICAgICAgICAgbmV3SG9sZGVyc1JpZ2h0ID0gaXNDdXJyeSA/IHVuZGVmaW5lZCA6IGhvbGRlcnMsXG4gICAgICAgICAgbmV3UGFydGlhbHMgPSBpc0N1cnJ5ID8gcGFydGlhbHMgOiB1bmRlZmluZWQsXG4gICAgICAgICAgbmV3UGFydGlhbHNSaWdodCA9IGlzQ3VycnkgPyB1bmRlZmluZWQgOiBwYXJ0aWFscztcblxuICAgICAgYml0bWFzayB8PSAoaXNDdXJyeSA/IFdSQVBfUEFSVElBTF9GTEFHIDogV1JBUF9QQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgYml0bWFzayAmPSB+KGlzQ3VycnkgPyBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyA6IFdSQVBfUEFSVElBTF9GTEFHKTtcblxuICAgICAgaWYgKCEoYml0bWFzayAmIFdSQVBfQ1VSUllfQk9VTkRfRkxBRykpIHtcbiAgICAgICAgYml0bWFzayAmPSB+KFdSQVBfQklORF9GTEFHIHwgV1JBUF9CSU5EX0tFWV9GTEFHKTtcbiAgICAgIH1cbiAgICAgIHZhciBuZXdEYXRhID0gW1xuICAgICAgICBmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBuZXdQYXJ0aWFscywgbmV3SG9sZGVycywgbmV3UGFydGlhbHNSaWdodCxcbiAgICAgICAgbmV3SG9sZGVyc1JpZ2h0LCBhcmdQb3MsIGFyeSwgYXJpdHlcbiAgICAgIF07XG5cbiAgICAgIHZhciByZXN1bHQgPSB3cmFwRnVuYy5hcHBseSh1bmRlZmluZWQsIG5ld0RhdGEpO1xuICAgICAgaWYgKGlzTGF6aWFibGUoZnVuYykpIHtcbiAgICAgICAgc2V0RGF0YShyZXN1bHQsIG5ld0RhdGEpO1xuICAgICAgfVxuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gcGxhY2Vob2xkZXI7XG4gICAgICByZXR1cm4gc2V0V3JhcFRvU3RyaW5nKHJlc3VsdCwgZnVuYywgYml0bWFzayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8ucm91bmRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSBUaGUgbmFtZSBvZiB0aGUgYE1hdGhgIG1ldGhvZCB0byB1c2Ugd2hlbiByb3VuZGluZy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByb3VuZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSb3VuZChtZXRob2ROYW1lKSB7XG4gICAgICB2YXIgZnVuYyA9IE1hdGhbbWV0aG9kTmFtZV07XG4gICAgICByZXR1cm4gZnVuY3Rpb24obnVtYmVyLCBwcmVjaXNpb24pIHtcbiAgICAgICAgbnVtYmVyID0gdG9OdW1iZXIobnVtYmVyKTtcbiAgICAgICAgcHJlY2lzaW9uID0gcHJlY2lzaW9uID09IG51bGwgPyAwIDogbmF0aXZlTWluKHRvSW50ZWdlcihwcmVjaXNpb24pLCAyOTIpO1xuICAgICAgICBpZiAocHJlY2lzaW9uICYmIG5hdGl2ZUlzRmluaXRlKG51bWJlcikpIHtcbiAgICAgICAgICAvLyBTaGlmdCB3aXRoIGV4cG9uZW50aWFsIG5vdGF0aW9uIHRvIGF2b2lkIGZsb2F0aW5nLXBvaW50IGlzc3Vlcy5cbiAgICAgICAgICAvLyBTZWUgW01ETl0oaHR0cHM6Ly9tZG4uaW8vcm91bmQjRXhhbXBsZXMpIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgICAgdmFyIHBhaXIgPSAodG9TdHJpbmcobnVtYmVyKSArICdlJykuc3BsaXQoJ2UnKSxcbiAgICAgICAgICAgICAgdmFsdWUgPSBmdW5jKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gKyBwcmVjaXNpb24pKTtcblxuICAgICAgICAgIHBhaXIgPSAodG9TdHJpbmcodmFsdWUpICsgJ2UnKS5zcGxpdCgnZScpO1xuICAgICAgICAgIHJldHVybiArKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gLSBwcmVjaXNpb24pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYyhudW1iZXIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2V0IG9iamVjdCBvZiBgdmFsdWVzYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gYWRkIHRvIHRoZSBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IHNldC5cbiAgICAgKi9cbiAgICB2YXIgY3JlYXRlU2V0ID0gIShTZXQgJiYgKDEgLyBzZXRUb0FycmF5KG5ldyBTZXQoWywtMF0pKVsxXSkgPT0gSU5GSU5JVFkpID8gbm9vcCA6IGZ1bmN0aW9uKHZhbHVlcykge1xuICAgICAgcmV0dXJuIG5ldyBTZXQodmFsdWVzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLnRvUGFpcnNgIG9yIGBfLnRvUGFpcnNJbmAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFpcnMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlVG9QYWlycyhrZXlzRnVuYykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICB2YXIgdGFnID0gZ2V0VGFnKG9iamVjdCk7XG4gICAgICAgIGlmICh0YWcgPT0gbWFwVGFnKSB7XG4gICAgICAgICAgcmV0dXJuIG1hcFRvQXJyYXkob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFnID09IHNldFRhZykge1xuICAgICAgICAgIHJldHVybiBzZXRUb1BhaXJzKG9iamVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJhc2VUb1BhaXJzKG9iamVjdCwga2V5c0Z1bmMob2JqZWN0KSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGVpdGhlciBjdXJyaWVzIG9yIGludm9rZXMgYGZ1bmNgIHdpdGggb3B0aW9uYWxcbiAgICAgKiBgdGhpc2AgYmluZGluZyBhbmQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy5cbiAgICAgKiAgICAxIC0gYF8uYmluZGBcbiAgICAgKiAgICAyIC0gYF8uYmluZEtleWBcbiAgICAgKiAgICA0IC0gYF8uY3VycnlgIG9yIGBfLmN1cnJ5UmlnaHRgIG9mIGEgYm91bmQgZnVuY3Rpb25cbiAgICAgKiAgICA4IC0gYF8uY3VycnlgXG4gICAgICogICAxNiAtIGBfLmN1cnJ5UmlnaHRgXG4gICAgICogICAzMiAtIGBfLnBhcnRpYWxgXG4gICAgICogICA2NCAtIGBfLnBhcnRpYWxSaWdodGBcbiAgICAgKiAgMTI4IC0gYF8ucmVhcmdgXG4gICAgICogIDI1NiAtIGBfLmFyeWBcbiAgICAgKiAgNTEyIC0gYF8uZmxpcGBcbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVXcmFwKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBhcmdQb3MsIGFyeSwgYXJpdHkpIHtcbiAgICAgIHZhciBpc0JpbmRLZXkgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0tFWV9GTEFHO1xuICAgICAgaWYgKCFpc0JpbmRLZXkgJiYgdHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gcGFydGlhbHMgPyBwYXJ0aWFscy5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgYml0bWFzayAmPSB+KFdSQVBfUEFSVElBTF9GTEFHIHwgV1JBUF9QQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBhcnkgPSBhcnkgPT09IHVuZGVmaW5lZCA/IGFyeSA6IG5hdGl2ZU1heCh0b0ludGVnZXIoYXJ5KSwgMCk7XG4gICAgICBhcml0eSA9IGFyaXR5ID09PSB1bmRlZmluZWQgPyBhcml0eSA6IHRvSW50ZWdlcihhcml0eSk7XG4gICAgICBsZW5ndGggLT0gaG9sZGVycyA/IGhvbGRlcnMubGVuZ3RoIDogMDtcblxuICAgICAgaWYgKGJpdG1hc2sgJiBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRykge1xuICAgICAgICB2YXIgcGFydGlhbHNSaWdodCA9IHBhcnRpYWxzLFxuICAgICAgICAgICAgaG9sZGVyc1JpZ2h0ID0gaG9sZGVycztcblxuICAgICAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB2YXIgZGF0YSA9IGlzQmluZEtleSA/IHVuZGVmaW5lZCA6IGdldERhdGEoZnVuYyk7XG5cbiAgICAgIHZhciBuZXdEYXRhID0gW1xuICAgICAgICBmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycywgcGFydGlhbHNSaWdodCwgaG9sZGVyc1JpZ2h0LFxuICAgICAgICBhcmdQb3MsIGFyeSwgYXJpdHlcbiAgICAgIF07XG5cbiAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgIG1lcmdlRGF0YShuZXdEYXRhLCBkYXRhKTtcbiAgICAgIH1cbiAgICAgIGZ1bmMgPSBuZXdEYXRhWzBdO1xuICAgICAgYml0bWFzayA9IG5ld0RhdGFbMV07XG4gICAgICB0aGlzQXJnID0gbmV3RGF0YVsyXTtcbiAgICAgIHBhcnRpYWxzID0gbmV3RGF0YVszXTtcbiAgICAgIGhvbGRlcnMgPSBuZXdEYXRhWzRdO1xuICAgICAgYXJpdHkgPSBuZXdEYXRhWzldID0gbmV3RGF0YVs5XSA9PT0gdW5kZWZpbmVkXG4gICAgICAgID8gKGlzQmluZEtleSA/IDAgOiBmdW5jLmxlbmd0aClcbiAgICAgICAgOiBuYXRpdmVNYXgobmV3RGF0YVs5XSAtIGxlbmd0aCwgMCk7XG5cbiAgICAgIGlmICghYXJpdHkgJiYgYml0bWFzayAmIChXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpKSB7XG4gICAgICAgIGJpdG1hc2sgJj0gfihXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpO1xuICAgICAgfVxuICAgICAgaWYgKCFiaXRtYXNrIHx8IGJpdG1hc2sgPT0gV1JBUF9CSU5EX0ZMQUcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZUJpbmQoZnVuYywgYml0bWFzaywgdGhpc0FyZyk7XG4gICAgICB9IGVsc2UgaWYgKGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9GTEFHIHx8IGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9SSUdIVF9GTEFHKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZUN1cnJ5KGZ1bmMsIGJpdG1hc2ssIGFyaXR5KTtcbiAgICAgIH0gZWxzZSBpZiAoKGJpdG1hc2sgPT0gV1JBUF9QQVJUSUFMX0ZMQUcgfHwgYml0bWFzayA9PSAoV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX1BBUlRJQUxfRkxBRykpICYmICFob2xkZXJzLmxlbmd0aCkge1xuICAgICAgICByZXN1bHQgPSBjcmVhdGVQYXJ0aWFsKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZUh5YnJpZC5hcHBseSh1bmRlZmluZWQsIG5ld0RhdGEpO1xuICAgICAgfVxuICAgICAgdmFyIHNldHRlciA9IGRhdGEgPyBiYXNlU2V0RGF0YSA6IHNldERhdGE7XG4gICAgICByZXR1cm4gc2V0V3JhcFRvU3RyaW5nKHNldHRlcihyZXN1bHQsIG5ld0RhdGEpLCBmdW5jLCBiaXRtYXNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGJ5IGBfLmRlZmF1bHRzYCB0byBjdXN0b21pemUgaXRzIGBfLmFzc2lnbkluYCB1c2UgdG8gYXNzaWduIHByb3BlcnRpZXNcbiAgICAgKiBvZiBzb3VyY2Ugb2JqZWN0cyB0byB0aGUgZGVzdGluYXRpb24gb2JqZWN0IGZvciBhbGwgZGVzdGluYXRpb24gcHJvcGVydGllc1xuICAgICAqIHRoYXQgcmVzb2x2ZSB0byBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBvYmpWYWx1ZSBUaGUgZGVzdGluYXRpb24gdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgc291cmNlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1c3RvbURlZmF1bHRzQXNzaWduSW4ob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgaWYgKG9ialZhbHVlID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAoZXEob2JqVmFsdWUsIG9iamVjdFByb3RvW2tleV0pICYmICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgcmV0dXJuIHNyY1ZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNEZWVwYCB0byBjdXN0b21pemUgaXRzIGBfLm1lcmdlYCB1c2UgdG8gbWVyZ2Ugc291cmNlXG4gICAgICogb2JqZWN0cyBpbnRvIGRlc3RpbmF0aW9uIG9iamVjdHMgdGhhdCBhcmUgcGFzc2VkIHRocnUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gb2JqVmFsdWUgVGhlIGRlc3RpbmF0aW9uIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHNvdXJjZSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIG1lcmdlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBwYXJlbnQgb2JqZWN0IG9mIGBzcmNWYWx1ZWAuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBzb3VyY2UgdmFsdWVzIGFuZCB0aGVpciBtZXJnZWRcbiAgICAgKiAgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3VzdG9tRGVmYXVsdHNNZXJnZShvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKSB7XG4gICAgICBpZiAoaXNPYmplY3Qob2JqVmFsdWUpICYmIGlzT2JqZWN0KHNyY1ZhbHVlKSkge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBtZXJnZSBvYmplY3RzIGFuZCBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgc3RhY2suc2V0KHNyY1ZhbHVlLCBvYmpWYWx1ZSk7XG4gICAgICAgIGJhc2VNZXJnZShvYmpWYWx1ZSwgc3JjVmFsdWUsIHVuZGVmaW5lZCwgY3VzdG9tRGVmYXVsdHNNZXJnZSwgc3RhY2spO1xuICAgICAgICBzdGFja1snZGVsZXRlJ10oc3JjVmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8ub21pdGAgdG8gY3VzdG9taXplIGl0cyBgXy5jbG9uZURlZXBgIHVzZSB0byBvbmx5IGNsb25lIHBsYWluXG4gICAgICogb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHVuY2xvbmVkIHZhbHVlIG9yIGB1bmRlZmluZWRgIHRvIGRlZmVyIGNsb25pbmcgdG8gYF8uY2xvbmVEZWVwYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXN0b21PbWl0Q2xvbmUodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc1BsYWluT2JqZWN0KHZhbHVlKSA/IHVuZGVmaW5lZCA6IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgYXJyYXlzIHdpdGggc3VwcG9ydCBmb3JcbiAgICAgKiBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG90aGVyIFRoZSBvdGhlciBhcnJheSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHN0YWNrIFRyYWNrcyB0cmF2ZXJzZWQgYGFycmF5YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYXJyYXlzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXF1YWxBcnJheXMoYXJyYXksIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gICAgICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHLFxuICAgICAgICAgIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBvdGhMZW5ndGggPSBvdGhlci5sZW5ndGg7XG5cbiAgICAgIGlmIChhcnJMZW5ndGggIT0gb3RoTGVuZ3RoICYmICEoaXNQYXJ0aWFsICYmIG90aExlbmd0aCA+IGFyckxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gQ2hlY2sgdGhhdCBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgIHZhciBhcnJTdGFja2VkID0gc3RhY2suZ2V0KGFycmF5KTtcbiAgICAgIHZhciBvdGhTdGFja2VkID0gc3RhY2suZ2V0KG90aGVyKTtcbiAgICAgIGlmIChhcnJTdGFja2VkICYmIG90aFN0YWNrZWQpIHtcbiAgICAgICAgcmV0dXJuIGFyclN0YWNrZWQgPT0gb3RoZXIgJiYgb3RoU3RhY2tlZCA9PSBhcnJheTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IHRydWUsXG4gICAgICAgICAgc2VlbiA9IChiaXRtYXNrICYgQ09NUEFSRV9VTk9SREVSRURfRkxBRykgPyBuZXcgU2V0Q2FjaGUgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHN0YWNrLnNldChhcnJheSwgb3RoZXIpO1xuICAgICAgc3RhY2suc2V0KG90aGVyLCBhcnJheSk7XG5cbiAgICAgIC8vIElnbm9yZSBub24taW5kZXggcHJvcGVydGllcy5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgYXJyTGVuZ3RoKSB7XG4gICAgICAgIHZhciBhcnJWYWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIG90aFZhbHVlID0gb3RoZXJbaW5kZXhdO1xuXG4gICAgICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICAgICAgdmFyIGNvbXBhcmVkID0gaXNQYXJ0aWFsXG4gICAgICAgICAgICA/IGN1c3RvbWl6ZXIob3RoVmFsdWUsIGFyclZhbHVlLCBpbmRleCwgb3RoZXIsIGFycmF5LCBzdGFjaylcbiAgICAgICAgICAgIDogY3VzdG9taXplcihhcnJWYWx1ZSwgb3RoVmFsdWUsIGluZGV4LCBhcnJheSwgb3RoZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29tcGFyZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGlmIChjb21wYXJlZCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIGlmIChzZWVuKSB7XG4gICAgICAgICAgaWYgKCFhcnJheVNvbWUob3RoZXIsIGZ1bmN0aW9uKG90aFZhbHVlLCBvdGhJbmRleCkge1xuICAgICAgICAgICAgICAgIGlmICghY2FjaGVIYXMoc2Vlbiwgb3RoSW5kZXgpICYmXG4gICAgICAgICAgICAgICAgICAgIChhcnJWYWx1ZSA9PT0gb3RoVmFsdWUgfHwgZXF1YWxGdW5jKGFyclZhbHVlLCBvdGhWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spKSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlZW4ucHVzaChvdGhJbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIShcbiAgICAgICAgICAgICAgYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8XG4gICAgICAgICAgICAgICAgZXF1YWxGdW5jKGFyclZhbHVlLCBvdGhWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YWNrWydkZWxldGUnXShhcnJheSk7XG4gICAgICBzdGFja1snZGVsZXRlJ10ob3RoZXIpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIGNvbXBhcmluZyBvYmplY3RzIG9mXG4gICAgICogdGhlIHNhbWUgYHRvU3RyaW5nVGFnYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY29tcGFyaW5nIHZhbHVlcyB3aXRoIHRhZ3Mgb2ZcbiAgICAgKiBgQm9vbGVhbmAsIGBEYXRlYCwgYEVycm9yYCwgYE51bWJlcmAsIGBSZWdFeHBgLCBvciBgU3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3RzIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3RhY2sgVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxdWFsQnlUYWcob2JqZWN0LCBvdGhlciwgdGFnLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gICAgICBzd2l0Y2ggKHRhZykge1xuICAgICAgICBjYXNlIGRhdGFWaWV3VGFnOlxuICAgICAgICAgIGlmICgob2JqZWN0LmJ5dGVMZW5ndGggIT0gb3RoZXIuYnl0ZUxlbmd0aCkgfHxcbiAgICAgICAgICAgICAgKG9iamVjdC5ieXRlT2Zmc2V0ICE9IG90aGVyLmJ5dGVPZmZzZXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIG9iamVjdCA9IG9iamVjdC5idWZmZXI7XG4gICAgICAgICAgb3RoZXIgPSBvdGhlci5idWZmZXI7XG5cbiAgICAgICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgICAgICBpZiAoKG9iamVjdC5ieXRlTGVuZ3RoICE9IG90aGVyLmJ5dGVMZW5ndGgpIHx8XG4gICAgICAgICAgICAgICFlcXVhbEZ1bmMobmV3IFVpbnQ4QXJyYXkob2JqZWN0KSwgbmV3IFVpbnQ4QXJyYXkob3RoZXIpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcblxuICAgICAgICBjYXNlIGJvb2xUYWc6XG4gICAgICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgICAgY2FzZSBudW1iZXJUYWc6XG4gICAgICAgICAgLy8gQ29lcmNlIGJvb2xlYW5zIHRvIGAxYCBvciBgMGAgYW5kIGRhdGVzIHRvIG1pbGxpc2Vjb25kcy5cbiAgICAgICAgICAvLyBJbnZhbGlkIGRhdGVzIGFyZSBjb2VyY2VkIHRvIGBOYU5gLlxuICAgICAgICAgIHJldHVybiBlcSgrb2JqZWN0LCArb3RoZXIpO1xuXG4gICAgICAgIGNhc2UgZXJyb3JUYWc6XG4gICAgICAgICAgcmV0dXJuIG9iamVjdC5uYW1lID09IG90aGVyLm5hbWUgJiYgb2JqZWN0Lm1lc3NhZ2UgPT0gb3RoZXIubWVzc2FnZTtcblxuICAgICAgICBjYXNlIHJlZ2V4cFRhZzpcbiAgICAgICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICAgICAgLy8gQ29lcmNlIHJlZ2V4ZXMgdG8gc3RyaW5ncyBhbmQgdHJlYXQgc3RyaW5ncywgcHJpbWl0aXZlcyBhbmQgb2JqZWN0cyxcbiAgICAgICAgICAvLyBhcyBlcXVhbC4gU2VlIGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG4gICAgICAgICAgLy8gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICByZXR1cm4gb2JqZWN0ID09IChvdGhlciArICcnKTtcblxuICAgICAgICBjYXNlIG1hcFRhZzpcbiAgICAgICAgICB2YXIgY29udmVydCA9IG1hcFRvQXJyYXk7XG5cbiAgICAgICAgY2FzZSBzZXRUYWc6XG4gICAgICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRztcbiAgICAgICAgICBjb252ZXJ0IHx8IChjb252ZXJ0ID0gc2V0VG9BcnJheSk7XG5cbiAgICAgICAgICBpZiAob2JqZWN0LnNpemUgIT0gb3RoZXIuc2l6ZSAmJiAhaXNQYXJ0aWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIEFzc3VtZSBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgICAgICB2YXIgc3RhY2tlZCA9IHN0YWNrLmdldChvYmplY3QpO1xuICAgICAgICAgIGlmIChzdGFja2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RhY2tlZCA9PSBvdGhlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgYml0bWFzayB8PSBDT01QQVJFX1VOT1JERVJFRF9GTEFHO1xuXG4gICAgICAgICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgICAgc3RhY2suc2V0KG9iamVjdCwgb3RoZXIpO1xuICAgICAgICAgIHZhciByZXN1bHQgPSBlcXVhbEFycmF5cyhjb252ZXJ0KG9iamVjdCksIGNvbnZlcnQob3RoZXIpLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKTtcbiAgICAgICAgICBzdGFja1snZGVsZXRlJ10ob2JqZWN0KTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuXG4gICAgICAgIGNhc2Ugc3ltYm9sVGFnOlxuICAgICAgICAgIGlmIChzeW1ib2xWYWx1ZU9mKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sVmFsdWVPZi5jYWxsKG9iamVjdCkgPT0gc3ltYm9sVmFsdWVPZi5jYWxsKG90aGVyKTtcbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBvYmplY3RzIHdpdGggc3VwcG9ydCBmb3JcbiAgICAgKiBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3RhY2sgVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxdWFsT2JqZWN0cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gICAgICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHLFxuICAgICAgICAgIG9ialByb3BzID0gZ2V0QWxsS2V5cyhvYmplY3QpLFxuICAgICAgICAgIG9iakxlbmd0aCA9IG9ialByb3BzLmxlbmd0aCxcbiAgICAgICAgICBvdGhQcm9wcyA9IGdldEFsbEtleXMob3RoZXIpLFxuICAgICAgICAgIG90aExlbmd0aCA9IG90aFByb3BzLmxlbmd0aDtcblxuICAgICAgaWYgKG9iakxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIWlzUGFydGlhbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBvYmpMZW5ndGg7XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICB2YXIga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgICAgICBpZiAoIShpc1BhcnRpYWwgPyBrZXkgaW4gb3RoZXIgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG90aGVyLCBrZXkpKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQ2hlY2sgdGhhdCBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgIHZhciBvYmpTdGFja2VkID0gc3RhY2suZ2V0KG9iamVjdCk7XG4gICAgICB2YXIgb3RoU3RhY2tlZCA9IHN0YWNrLmdldChvdGhlcik7XG4gICAgICBpZiAob2JqU3RhY2tlZCAmJiBvdGhTdGFja2VkKSB7XG4gICAgICAgIHJldHVybiBvYmpTdGFja2VkID09IG90aGVyICYmIG90aFN0YWNrZWQgPT0gb2JqZWN0O1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG4gICAgICBzdGFjay5zZXQob3RoZXIsIG9iamVjdCk7XG5cbiAgICAgIHZhciBza2lwQ3RvciA9IGlzUGFydGlhbDtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgb2JqTGVuZ3RoKSB7XG4gICAgICAgIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICAgICAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2tleV07XG5cbiAgICAgICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgICAgICB2YXIgY29tcGFyZWQgPSBpc1BhcnRpYWxcbiAgICAgICAgICAgID8gY3VzdG9taXplcihvdGhWYWx1ZSwgb2JqVmFsdWUsIGtleSwgb3RoZXIsIG9iamVjdCwgc3RhY2spXG4gICAgICAgICAgICA6IGN1c3RvbWl6ZXIob2JqVmFsdWUsIG90aFZhbHVlLCBrZXksIG9iamVjdCwgb3RoZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgaWYgKCEoY29tcGFyZWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICA/IChvYmpWYWx1ZSA9PT0gb3RoVmFsdWUgfHwgZXF1YWxGdW5jKG9ialZhbHVlLCBvdGhWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spKVxuICAgICAgICAgICAgICA6IGNvbXBhcmVkXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc2tpcEN0b3IgfHwgKHNraXBDdG9yID0ga2V5ID09ICdjb25zdHJ1Y3RvcicpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCAmJiAhc2tpcEN0b3IpIHtcbiAgICAgICAgdmFyIG9iakN0b3IgPSBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgICBvdGhDdG9yID0gb3RoZXIuY29uc3RydWN0b3I7XG5cbiAgICAgICAgLy8gTm9uIGBPYmplY3RgIG9iamVjdCBpbnN0YW5jZXMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1YWwuXG4gICAgICAgIGlmIChvYmpDdG9yICE9IG90aEN0b3IgJiZcbiAgICAgICAgICAgICgnY29uc3RydWN0b3InIGluIG9iamVjdCAmJiAnY29uc3RydWN0b3InIGluIG90aGVyKSAmJlxuICAgICAgICAgICAgISh0eXBlb2Ygb2JqQ3RvciA9PSAnZnVuY3Rpb24nICYmIG9iakN0b3IgaW5zdGFuY2VvZiBvYmpDdG9yICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBvdGhDdG9yID09ICdmdW5jdGlvbicgJiYgb3RoQ3RvciBpbnN0YW5jZW9mIG90aEN0b3IpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YWNrWydkZWxldGUnXShvYmplY3QpO1xuICAgICAgc3RhY2tbJ2RlbGV0ZSddKG90aGVyKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlUmVzdGAgd2hpY2ggZmxhdHRlbnMgdGhlIHJlc3QgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdFJlc3QoZnVuYykge1xuICAgICAgcmV0dXJuIHNldFRvU3RyaW5nKG92ZXJSZXN0KGZ1bmMsIHVuZGVmaW5lZCwgZmxhdHRlbiksIGZ1bmMgKyAnJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0QWxsS2V5cyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXMsIGdldFN5bWJvbHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmRcbiAgICAgKiBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRBbGxLZXlzSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gYmFzZUdldEFsbEtleXMob2JqZWN0LCBrZXlzSW4sIGdldFN5bWJvbHNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWV0YWRhdGEgZm9yIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgZ2V0RGF0YSA9ICFtZXRhTWFwID8gbm9vcCA6IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICAgIHJldHVybiBtZXRhTWFwLmdldChmdW5jKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmFtZSBvZiBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0RnVuY05hbWUoZnVuYykge1xuICAgICAgdmFyIHJlc3VsdCA9IChmdW5jLm5hbWUgKyAnJyksXG4gICAgICAgICAgYXJyYXkgPSByZWFsTmFtZXNbcmVzdWx0XSxcbiAgICAgICAgICBsZW5ndGggPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHJlYWxOYW1lcywgcmVzdWx0KSA/IGFycmF5Lmxlbmd0aCA6IDA7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgZGF0YSA9IGFycmF5W2xlbmd0aF0sXG4gICAgICAgICAgICBvdGhlckZ1bmMgPSBkYXRhLmZ1bmM7XG4gICAgICAgIGlmIChvdGhlckZ1bmMgPT0gbnVsbCB8fCBvdGhlckZ1bmMgPT0gZnVuYykge1xuICAgICAgICAgIHJldHVybiBkYXRhLm5hbWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYXJndW1lbnQgcGxhY2Vob2xkZXIgdmFsdWUgZm9yIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcGxhY2Vob2xkZXIgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SG9sZGVyKGZ1bmMpIHtcbiAgICAgIHZhciBvYmplY3QgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKGxvZGFzaCwgJ3BsYWNlaG9sZGVyJykgPyBsb2Rhc2ggOiBmdW5jO1xuICAgICAgcmV0dXJuIG9iamVjdC5wbGFjZWhvbGRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhcHByb3ByaWF0ZSBcIml0ZXJhdGVlXCIgZnVuY3Rpb24uIElmIGBfLml0ZXJhdGVlYCBpcyBjdXN0b21pemVkLFxuICAgICAqIHRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgY3VzdG9tIG1ldGhvZCwgb3RoZXJ3aXNlIGl0IHJldHVybnMgYGJhc2VJdGVyYXRlZWAuXG4gICAgICogSWYgYXJndW1lbnRzIGFyZSBwcm92aWRlZCwgdGhlIGNob3NlbiBmdW5jdGlvbiBpcyBpbnZva2VkIHdpdGggdGhlbSBhbmRcbiAgICAgKiBpdHMgcmVzdWx0IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFt2YWx1ZV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYW4gaXRlcmF0ZWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIHRoZSBjcmVhdGVkIGl0ZXJhdGVlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY2hvc2VuIGZ1bmN0aW9uIG9yIGl0cyByZXN1bHQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SXRlcmF0ZWUoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoLml0ZXJhdGVlIHx8IGl0ZXJhdGVlO1xuICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSBpdGVyYXRlZSA/IGJhc2VJdGVyYXRlZSA6IHJlc3VsdDtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gcmVzdWx0KGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdKSA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRhIGZvciBgbWFwYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHJlZmVyZW5jZSBrZXkuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hcCBkYXRhLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hcERhdGEobWFwLCBrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gbWFwLl9fZGF0YV9fO1xuICAgICAgcmV0dXJuIGlzS2V5YWJsZShrZXkpXG4gICAgICAgID8gZGF0YVt0eXBlb2Yga2V5ID09ICdzdHJpbmcnID8gJ3N0cmluZycgOiAnaGFzaCddXG4gICAgICAgIDogZGF0YS5tYXA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJvcGVydHkgbmFtZXMsIHZhbHVlcywgYW5kIGNvbXBhcmUgZmxhZ3Mgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG1hdGNoIGRhdGEgb2YgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWF0Y2hEYXRhKG9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IGtleXMob2JqZWN0KSxcbiAgICAgICAgICBsZW5ndGggPSByZXN1bHQubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGtleSA9IHJlc3VsdFtsZW5ndGhdLFxuICAgICAgICAgICAgdmFsdWUgPSBvYmplY3Rba2V5XTtcblxuICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IFtrZXksIHZhbHVlLCBpc1N0cmljdENvbXBhcmFibGUodmFsdWUpXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmF0aXZlIGZ1bmN0aW9uIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBpZiBpdCdzIG5hdGl2ZSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGdldFZhbHVlKG9iamVjdCwga2V5KTtcbiAgICAgIHJldHVybiBiYXNlSXNOYXRpdmUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlR2V0VGFnYCB3aGljaCBpZ25vcmVzIGBTeW1ib2wudG9TdHJpbmdUYWdgIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmF3IGB0b1N0cmluZ1RhZ2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UmF3VGFnKHZhbHVlKSB7XG4gICAgICB2YXIgaXNPd24gPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBzeW1Ub1N0cmluZ1RhZyksXG4gICAgICAgICAgdGFnID0gdmFsdWVbc3ltVG9TdHJpbmdUYWddO1xuXG4gICAgICB0cnkge1xuICAgICAgICB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ10gPSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciB1bm1hc2tlZCA9IHRydWU7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgICB2YXIgcmVzdWx0ID0gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICBpZiAodW5tYXNrZWQpIHtcbiAgICAgICAgaWYgKGlzT3duKSB7XG4gICAgICAgICAgdmFsdWVbc3ltVG9TdHJpbmdUYWddID0gdGFnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAgICAgKi9cbiAgICB2YXIgZ2V0U3ltYm9scyA9ICFuYXRpdmVHZXRTeW1ib2xzID8gc3R1YkFycmF5IDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICByZXR1cm4gYXJyYXlGaWx0ZXIobmF0aXZlR2V0U3ltYm9scyhvYmplY3QpLCBmdW5jdGlvbihzeW1ib2wpIHtcbiAgICAgICAgcmV0dXJuIHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqZWN0LCBzeW1ib2wpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAgICAgKi9cbiAgICB2YXIgZ2V0U3ltYm9sc0luID0gIW5hdGl2ZUdldFN5bWJvbHMgPyBzdHViQXJyYXkgOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIHdoaWxlIChvYmplY3QpIHtcbiAgICAgICAgYXJyYXlQdXNoKHJlc3VsdCwgZ2V0U3ltYm9scyhvYmplY3QpKTtcbiAgICAgICAgb2JqZWN0ID0gZ2V0UHJvdG90eXBlKG9iamVjdCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgdG9TdHJpbmdUYWdgIG9mIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGB0b1N0cmluZ1RhZ2AuXG4gICAgICovXG4gICAgdmFyIGdldFRhZyA9IGJhc2VHZXRUYWc7XG5cbiAgICAvLyBGYWxsYmFjayBmb3IgZGF0YSB2aWV3cywgbWFwcywgc2V0cywgYW5kIHdlYWsgbWFwcyBpbiBJRSAxMSBhbmQgcHJvbWlzZXMgaW4gTm9kZS5qcyA8IDYuXG4gICAgaWYgKChEYXRhVmlldyAmJiBnZXRUYWcobmV3IERhdGFWaWV3KG5ldyBBcnJheUJ1ZmZlcigxKSkpICE9IGRhdGFWaWV3VGFnKSB8fFxuICAgICAgICAoTWFwICYmIGdldFRhZyhuZXcgTWFwKSAhPSBtYXBUYWcpIHx8XG4gICAgICAgIChQcm9taXNlICYmIGdldFRhZyhQcm9taXNlLnJlc29sdmUoKSkgIT0gcHJvbWlzZVRhZykgfHxcbiAgICAgICAgKFNldCAmJiBnZXRUYWcobmV3IFNldCkgIT0gc2V0VGFnKSB8fFxuICAgICAgICAoV2Vha01hcCAmJiBnZXRUYWcobmV3IFdlYWtNYXApICE9IHdlYWtNYXBUYWcpKSB7XG4gICAgICBnZXRUYWcgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gYmFzZUdldFRhZyh2YWx1ZSksXG4gICAgICAgICAgICBDdG9yID0gcmVzdWx0ID09IG9iamVjdFRhZyA/IHZhbHVlLmNvbnN0cnVjdG9yIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3RvclN0cmluZyA9IEN0b3IgPyB0b1NvdXJjZShDdG9yKSA6ICcnO1xuXG4gICAgICAgIGlmIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgc3dpdGNoIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgICBjYXNlIGRhdGFWaWV3Q3RvclN0cmluZzogcmV0dXJuIGRhdGFWaWV3VGFnO1xuICAgICAgICAgICAgY2FzZSBtYXBDdG9yU3RyaW5nOiByZXR1cm4gbWFwVGFnO1xuICAgICAgICAgICAgY2FzZSBwcm9taXNlQ3RvclN0cmluZzogcmV0dXJuIHByb21pc2VUYWc7XG4gICAgICAgICAgICBjYXNlIHNldEN0b3JTdHJpbmc6IHJldHVybiBzZXRUYWc7XG4gICAgICAgICAgICBjYXNlIHdlYWtNYXBDdG9yU3RyaW5nOiByZXR1cm4gd2Vha01hcFRhZztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmlldywgYXBwbHlpbmcgYW55IGB0cmFuc2Zvcm1zYCB0byB0aGUgYHN0YXJ0YCBhbmQgYGVuZGAgcG9zaXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSB2aWV3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgdmlldy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB0cmFuc2Zvcm1zIFRoZSB0cmFuc2Zvcm1hdGlvbnMgdG8gYXBwbHkgdG8gdGhlIHZpZXcuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgYHN0YXJ0YCBhbmQgYGVuZGBcbiAgICAgKiAgcG9zaXRpb25zIG9mIHRoZSB2aWV3LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZpZXcoc3RhcnQsIGVuZCwgdHJhbnNmb3Jtcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdHJhbnNmb3Jtcy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBkYXRhID0gdHJhbnNmb3Jtc1tpbmRleF0sXG4gICAgICAgICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gICAgICAgIHN3aXRjaCAoZGF0YS50eXBlKSB7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6ICAgICAgc3RhcnQgKz0gc2l6ZTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcFJpZ2h0JzogZW5kIC09IHNpemU7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2UnOiAgICAgIGVuZCA9IG5hdGl2ZU1pbihlbmQsIHN0YXJ0ICsgc2l6ZSk7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2VSaWdodCc6IHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0LCBlbmQgLSBzaXplKTsgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7ICdzdGFydCc6IHN0YXJ0LCAnZW5kJzogZW5kIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgd3JhcHBlciBkZXRhaWxzIGZyb20gdGhlIGBzb3VyY2VgIGJvZHkgY29tbWVudC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSBUaGUgc291cmNlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3cmFwcGVyIGRldGFpbHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0V3JhcERldGFpbHMoc291cmNlKSB7XG4gICAgICB2YXIgbWF0Y2ggPSBzb3VyY2UubWF0Y2gocmVXcmFwRGV0YWlscyk7XG4gICAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXS5zcGxpdChyZVNwbGl0RGV0YWlscykgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHBhdGhgIGV4aXN0cyBvbiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhc0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrIHByb3BlcnRpZXMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBwYXRoYCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNQYXRoKG9iamVjdCwgcGF0aCwgaGFzRnVuYykge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gdG9LZXkocGF0aFtpbmRleF0pO1xuICAgICAgICBpZiAoIShyZXN1bHQgPSBvYmplY3QgIT0gbnVsbCAmJiBoYXNGdW5jKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBvYmplY3QgPSBvYmplY3Rba2V5XTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXN1bHQgfHwgKytpbmRleCAhPSBsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGxlbmd0aCA9IG9iamVjdCA9PSBudWxsID8gMCA6IG9iamVjdC5sZW5ndGg7XG4gICAgICByZXR1cm4gISFsZW5ndGggJiYgaXNMZW5ndGgobGVuZ3RoKSAmJiBpc0luZGV4KGtleSwgbGVuZ3RoKSAmJlxuICAgICAgICAoaXNBcnJheShvYmplY3QpIHx8IGlzQXJndW1lbnRzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGFuIGFycmF5IGNsb25lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVBcnJheShhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBuZXcgYXJyYXkuY29uc3RydWN0b3IobGVuZ3RoKTtcblxuICAgICAgLy8gQWRkIHByb3BlcnRpZXMgYXNzaWduZWQgYnkgYFJlZ0V4cCNleGVjYC5cbiAgICAgIGlmIChsZW5ndGggJiYgdHlwZW9mIGFycmF5WzBdID09ICdzdHJpbmcnICYmIGhhc093blByb3BlcnR5LmNhbGwoYXJyYXksICdpbmRleCcpKSB7XG4gICAgICAgIHJlc3VsdC5pbmRleCA9IGFycmF5LmluZGV4O1xuICAgICAgICByZXN1bHQuaW5wdXQgPSBhcnJheS5pbnB1dDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5pdENsb25lT2JqZWN0KG9iamVjdCkge1xuICAgICAgcmV0dXJuICh0eXBlb2Ygb2JqZWN0LmNvbnN0cnVjdG9yID09ICdmdW5jdGlvbicgJiYgIWlzUHJvdG90eXBlKG9iamVjdCkpXG4gICAgICAgID8gYmFzZUNyZWF0ZShnZXRQcm90b3R5cGUob2JqZWN0KSlcbiAgICAgICAgOiB7fTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhbiBvYmplY3QgY2xvbmUgYmFzZWQgb24gaXRzIGB0b1N0cmluZ1RhZ2AuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNsb25pbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICAgICAqIGBCb29sZWFuYCwgYERhdGVgLCBgRXJyb3JgLCBgTWFwYCwgYE51bWJlcmAsIGBSZWdFeHBgLCBgU2V0YCwgb3IgYFN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3QgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVCeVRhZyhvYmplY3QsIHRhZywgaXNEZWVwKSB7XG4gICAgICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgICAgIHN3aXRjaCAodGFnKSB7XG4gICAgICAgIGNhc2UgYXJyYXlCdWZmZXJUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lQXJyYXlCdWZmZXIob2JqZWN0KTtcblxuICAgICAgICBjYXNlIGJvb2xUYWc6XG4gICAgICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3IoK29iamVjdCk7XG5cbiAgICAgICAgY2FzZSBkYXRhVmlld1RhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVEYXRhVmlldyhvYmplY3QsIGlzRGVlcCk7XG5cbiAgICAgICAgY2FzZSBmbG9hdDMyVGFnOiBjYXNlIGZsb2F0NjRUYWc6XG4gICAgICAgIGNhc2UgaW50OFRhZzogY2FzZSBpbnQxNlRhZzogY2FzZSBpbnQzMlRhZzpcbiAgICAgICAgY2FzZSB1aW50OFRhZzogY2FzZSB1aW50OENsYW1wZWRUYWc6IGNhc2UgdWludDE2VGFnOiBjYXNlIHVpbnQzMlRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVUeXBlZEFycmF5KG9iamVjdCwgaXNEZWVwKTtcblxuICAgICAgICBjYXNlIG1hcFRhZzpcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3I7XG5cbiAgICAgICAgY2FzZSBudW1iZXJUYWc6XG4gICAgICAgIGNhc2Ugc3RyaW5nVGFnOlxuICAgICAgICAgIHJldHVybiBuZXcgQ3RvcihvYmplY3QpO1xuXG4gICAgICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZVJlZ0V4cChvYmplY3QpO1xuXG4gICAgICAgIGNhc2Ugc2V0VGFnOlxuICAgICAgICAgIHJldHVybiBuZXcgQ3RvcjtcblxuICAgICAgICBjYXNlIHN5bWJvbFRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVTeW1ib2wob2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnRzIHdyYXBwZXIgYGRldGFpbHNgIGluIGEgY29tbWVudCBhdCB0aGUgdG9wIG9mIHRoZSBgc291cmNlYCBib2R5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIFRoZSBzb3VyY2UgdG8gbW9kaWZ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gZGV0YWlscyBUaGUgZGV0YWlscyB0byBpbnNlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbW9kaWZpZWQgc291cmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluc2VydFdyYXBEZXRhaWxzKHNvdXJjZSwgZGV0YWlscykge1xuICAgICAgdmFyIGxlbmd0aCA9IGRldGFpbHMubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgIH1cbiAgICAgIHZhciBsYXN0SW5kZXggPSBsZW5ndGggLSAxO1xuICAgICAgZGV0YWlsc1tsYXN0SW5kZXhdID0gKGxlbmd0aCA+IDEgPyAnJiAnIDogJycpICsgZGV0YWlsc1tsYXN0SW5kZXhdO1xuICAgICAgZGV0YWlscyA9IGRldGFpbHMuam9pbihsZW5ndGggPiAyID8gJywgJyA6ICcgJyk7XG4gICAgICByZXR1cm4gc291cmNlLnJlcGxhY2UocmVXcmFwQ29tbWVudCwgJ3tcXG4vKiBbd3JhcHBlZCB3aXRoICcgKyBkZXRhaWxzICsgJ10gKi9cXG4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGZsYXR0ZW5hYmxlIGBhcmd1bWVudHNgIG9iamVjdCBvciBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZmxhdHRlbmFibGUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0ZsYXR0ZW5hYmxlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNBcnJheSh2YWx1ZSkgfHwgaXNBcmd1bWVudHModmFsdWUpIHx8XG4gICAgICAgICEhKHNwcmVhZGFibGVTeW1ib2wgJiYgdmFsdWUgJiYgdmFsdWVbc3ByZWFkYWJsZVN5bWJvbF0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgYXJyYXktbGlrZSBpbmRleC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9TUFYX1NBRkVfSU5URUdFUl0gVGhlIHVwcGVyIGJvdW5kcyBvZiBhIHZhbGlkIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgaW5kZXgsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0luZGV4KHZhbHVlLCBsZW5ndGgpIHtcbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoID09IG51bGwgPyBNQVhfU0FGRV9JTlRFR0VSIDogbGVuZ3RoO1xuXG4gICAgICByZXR1cm4gISFsZW5ndGggJiZcbiAgICAgICAgKHR5cGUgPT0gJ251bWJlcicgfHxcbiAgICAgICAgICAodHlwZSAhPSAnc3ltYm9sJyAmJiByZUlzVWludC50ZXN0KHZhbHVlKSkpICYmXG4gICAgICAgICAgICAodmFsdWUgPiAtMSAmJiB2YWx1ZSAlIDEgPT0gMCAmJiB2YWx1ZSA8IGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBhcmd1bWVudHMgYXJlIGZyb20gYW4gaXRlcmF0ZWUgY2FsbC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIHZhbHVlIGFyZ3VtZW50LlxuICAgICAqIEBwYXJhbSB7Kn0gaW5kZXggVGhlIHBvdGVudGlhbCBpdGVyYXRlZSBpbmRleCBvciBrZXkgYXJndW1lbnQuXG4gICAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIHBvdGVudGlhbCBpdGVyYXRlZSBvYmplY3QgYXJndW1lbnQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBhcmd1bWVudHMgYXJlIGZyb20gYW4gaXRlcmF0ZWUgY2FsbCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSXRlcmF0ZWVDYWxsKHZhbHVlLCBpbmRleCwgb2JqZWN0KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgaW5kZXg7XG4gICAgICBpZiAodHlwZSA9PSAnbnVtYmVyJ1xuICAgICAgICAgICAgPyAoaXNBcnJheUxpa2Uob2JqZWN0KSAmJiBpc0luZGV4KGluZGV4LCBvYmplY3QubGVuZ3RoKSlcbiAgICAgICAgICAgIDogKHR5cGUgPT0gJ3N0cmluZycgJiYgaW5kZXggaW4gb2JqZWN0KVxuICAgICAgICAgICkge1xuICAgICAgICByZXR1cm4gZXEob2JqZWN0W2luZGV4XSwgdmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgbm90IGEgcHJvcGVydHkgcGF0aC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkga2V5cyBvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHByb3BlcnR5IG5hbWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0tleSh2YWx1ZSwgb2JqZWN0KSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICBpZiAodHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICAgdmFsdWUgPT0gbnVsbCB8fCBpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVJc1BsYWluUHJvcC50ZXN0KHZhbHVlKSB8fCAhcmVJc0RlZXBQcm9wLnRlc3QodmFsdWUpIHx8XG4gICAgICAgIChvYmplY3QgIT0gbnVsbCAmJiB2YWx1ZSBpbiBPYmplY3Qob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHVzZSBhcyB1bmlxdWUgb2JqZWN0IGtleS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0tleWFibGUodmFsdWUpIHtcbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgICAgcmV0dXJuICh0eXBlID09ICdzdHJpbmcnIHx8IHR5cGUgPT0gJ251bWJlcicgfHwgdHlwZSA9PSAnc3ltYm9sJyB8fCB0eXBlID09ICdib29sZWFuJylcbiAgICAgICAgPyAodmFsdWUgIT09ICdfX3Byb3RvX18nKVxuICAgICAgICA6ICh2YWx1ZSA9PT0gbnVsbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgYSBsYXp5IGNvdW50ZXJwYXJ0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGhhcyBhIGxhenkgY291bnRlcnBhcnQsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0xhemlhYmxlKGZ1bmMpIHtcbiAgICAgIHZhciBmdW5jTmFtZSA9IGdldEZ1bmNOYW1lKGZ1bmMpLFxuICAgICAgICAgIG90aGVyID0gbG9kYXNoW2Z1bmNOYW1lXTtcblxuICAgICAgaWYgKHR5cGVvZiBvdGhlciAhPSAnZnVuY3Rpb24nIHx8ICEoZnVuY05hbWUgaW4gTGF6eVdyYXBwZXIucHJvdG90eXBlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoZnVuYyA9PT0gb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICB2YXIgZGF0YSA9IGdldERhdGEob3RoZXIpO1xuICAgICAgcmV0dXJuICEhZGF0YSAmJiBmdW5jID09PSBkYXRhWzBdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgZnVuY2AgaGFzIGl0cyBzb3VyY2UgbWFza2VkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGlzIG1hc2tlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTWFza2VkKGZ1bmMpIHtcbiAgICAgIHJldHVybiAhIW1hc2tTcmNLZXkgJiYgKG1hc2tTcmNLZXkgaW4gZnVuYyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBpcyBjYXBhYmxlIG9mIGJlaW5nIG1hc2tlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBmdW5jYCBpcyBtYXNrYWJsZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIHZhciBpc01hc2thYmxlID0gY29yZUpzRGF0YSA/IGlzRnVuY3Rpb24gOiBzdHViRmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsaWtlbHkgYSBwcm90b3R5cGUgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHByb3RvdHlwZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICB2YXIgQ3RvciA9IHZhbHVlICYmIHZhbHVlLmNvbnN0cnVjdG9yLFxuICAgICAgICAgIHByb3RvID0gKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiYgQ3Rvci5wcm90b3R5cGUpIHx8IG9iamVjdFByb3RvO1xuXG4gICAgICByZXR1cm4gdmFsdWUgPT09IHByb3RvO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHN1aXRhYmxlIGZvciBzdHJpY3QgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlmIHN1aXRhYmxlIGZvciBzdHJpY3RcbiAgICAgKiAgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1N0cmljdENvbXBhcmFibGUodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWUgJiYgIWlzT2JqZWN0KHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYG1hdGNoZXNQcm9wZXJ0eWAgZm9yIHNvdXJjZSB2YWx1ZXMgc3VpdGFibGVcbiAgICAgKiBmb3Igc3RyaWN0IGVxdWFsaXR5IGNvbXBhcmlzb25zLCBpLmUuIGA9PT1gLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSB2YWx1ZSB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzcGVjIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hdGNoZXNTdHJpY3RDb21wYXJhYmxlKGtleSwgc3JjVmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmplY3Rba2V5XSA9PT0gc3JjVmFsdWUgJiZcbiAgICAgICAgICAoc3JjVmFsdWUgIT09IHVuZGVmaW5lZCB8fCAoa2V5IGluIE9iamVjdChvYmplY3QpKSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5tZW1vaXplYCB3aGljaCBjbGVhcnMgdGhlIG1lbW9pemVkIGZ1bmN0aW9uJ3NcbiAgICAgKiBjYWNoZSB3aGVuIGl0IGV4Y2VlZHMgYE1BWF9NRU1PSVpFX1NJWkVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBoYXZlIGl0cyBvdXRwdXQgbWVtb2l6ZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVtb2l6ZUNhcHBlZChmdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbWVtb2l6ZShmdW5jLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgaWYgKGNhY2hlLnNpemUgPT09IE1BWF9NRU1PSVpFX1NJWkUpIHtcbiAgICAgICAgICBjYWNoZS5jbGVhcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBrZXk7XG4gICAgICB9KTtcblxuICAgICAgdmFyIGNhY2hlID0gcmVzdWx0LmNhY2hlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZXMgdGhlIGZ1bmN0aW9uIG1ldGFkYXRhIG9mIGBzb3VyY2VgIGludG8gYGRhdGFgLlxuICAgICAqXG4gICAgICogTWVyZ2luZyBtZXRhZGF0YSByZWR1Y2VzIHRoZSBudW1iZXIgb2Ygd3JhcHBlcnMgdXNlZCB0byBpbnZva2UgYSBmdW5jdGlvbi5cbiAgICAgKiBUaGlzIGlzIHBvc3NpYmxlIGJlY2F1c2UgbWV0aG9kcyBsaWtlIGBfLmJpbmRgLCBgXy5jdXJyeWAsIGFuZCBgXy5wYXJ0aWFsYFxuICAgICAqIG1heSBiZSBhcHBsaWVkIHJlZ2FyZGxlc3Mgb2YgZXhlY3V0aW9uIG9yZGVyLiBNZXRob2RzIGxpa2UgYF8uYXJ5YCBhbmRcbiAgICAgKiBgXy5yZWFyZ2AgbW9kaWZ5IGZ1bmN0aW9uIGFyZ3VtZW50cywgbWFraW5nIHRoZSBvcmRlciBpbiB3aGljaCB0aGV5IGFyZVxuICAgICAqIGV4ZWN1dGVkIGltcG9ydGFudCwgcHJldmVudGluZyB0aGUgbWVyZ2luZyBvZiBtZXRhZGF0YS4gSG93ZXZlciwgd2UgbWFrZVxuICAgICAqIGFuIGV4Y2VwdGlvbiBmb3IgYSBzYWZlIGNvbWJpbmVkIGNhc2Ugd2hlcmUgY3VycmllZCBmdW5jdGlvbnMgaGF2ZSBgXy5hcnlgXG4gICAgICogYW5kIG9yIGBfLnJlYXJnYCBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBkYXRhIFRoZSBkZXN0aW5hdGlvbiBtZXRhZGF0YS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIHNvdXJjZSBtZXRhZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGRhdGFgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1lcmdlRGF0YShkYXRhLCBzb3VyY2UpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gZGF0YVsxXSxcbiAgICAgICAgICBzcmNCaXRtYXNrID0gc291cmNlWzFdLFxuICAgICAgICAgIG5ld0JpdG1hc2sgPSBiaXRtYXNrIHwgc3JjQml0bWFzayxcbiAgICAgICAgICBpc0NvbW1vbiA9IG5ld0JpdG1hc2sgPCAoV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX0JJTkRfS0VZX0ZMQUcgfCBXUkFQX0FSWV9GTEFHKTtcblxuICAgICAgdmFyIGlzQ29tYm8gPVxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gV1JBUF9BUllfRkxBRykgJiYgKGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9GTEFHKSkgfHxcbiAgICAgICAgKChzcmNCaXRtYXNrID09IFdSQVBfQVJZX0ZMQUcpICYmIChiaXRtYXNrID09IFdSQVBfUkVBUkdfRkxBRykgJiYgKGRhdGFbN10ubGVuZ3RoIDw9IHNvdXJjZVs4XSkpIHx8XG4gICAgICAgICgoc3JjQml0bWFzayA9PSAoV1JBUF9BUllfRkxBRyB8IFdSQVBfUkVBUkdfRkxBRykpICYmIChzb3VyY2VbN10ubGVuZ3RoIDw9IHNvdXJjZVs4XSkgJiYgKGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9GTEFHKSk7XG5cbiAgICAgIC8vIEV4aXQgZWFybHkgaWYgbWV0YWRhdGEgY2FuJ3QgYmUgbWVyZ2VkLlxuICAgICAgaWYgKCEoaXNDb21tb24gfHwgaXNDb21ibykpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGB0aGlzQXJnYCBpZiBhdmFpbGFibGUuXG4gICAgICBpZiAoc3JjQml0bWFzayAmIFdSQVBfQklORF9GTEFHKSB7XG4gICAgICAgIGRhdGFbMl0gPSBzb3VyY2VbMl07XG4gICAgICAgIC8vIFNldCB3aGVuIGN1cnJ5aW5nIGEgYm91bmQgZnVuY3Rpb24uXG4gICAgICAgIG5ld0JpdG1hc2sgfD0gYml0bWFzayAmIFdSQVBfQklORF9GTEFHID8gMCA6IFdSQVBfQ1VSUllfQk9VTkRfRkxBRztcbiAgICAgIH1cbiAgICAgIC8vIENvbXBvc2UgcGFydGlhbCBhcmd1bWVudHMuXG4gICAgICB2YXIgdmFsdWUgPSBzb3VyY2VbM107XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgdmFyIHBhcnRpYWxzID0gZGF0YVszXTtcbiAgICAgICAgZGF0YVszXSA9IHBhcnRpYWxzID8gY29tcG9zZUFyZ3MocGFydGlhbHMsIHZhbHVlLCBzb3VyY2VbNF0pIDogdmFsdWU7XG4gICAgICAgIGRhdGFbNF0gPSBwYXJ0aWFscyA/IHJlcGxhY2VIb2xkZXJzKGRhdGFbM10sIFBMQUNFSE9MREVSKSA6IHNvdXJjZVs0XTtcbiAgICAgIH1cbiAgICAgIC8vIENvbXBvc2UgcGFydGlhbCByaWdodCBhcmd1bWVudHMuXG4gICAgICB2YWx1ZSA9IHNvdXJjZVs1XTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBwYXJ0aWFscyA9IGRhdGFbNV07XG4gICAgICAgIGRhdGFbNV0gPSBwYXJ0aWFscyA/IGNvbXBvc2VBcmdzUmlnaHQocGFydGlhbHMsIHZhbHVlLCBzb3VyY2VbNl0pIDogdmFsdWU7XG4gICAgICAgIGRhdGFbNl0gPSBwYXJ0aWFscyA/IHJlcGxhY2VIb2xkZXJzKGRhdGFbNV0sIFBMQUNFSE9MREVSKSA6IHNvdXJjZVs2XTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYGFyZ1Bvc2AgaWYgYXZhaWxhYmxlLlxuICAgICAgdmFsdWUgPSBzb3VyY2VbN107XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgZGF0YVs3XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJ5YCBpZiBpdCdzIHNtYWxsZXIuXG4gICAgICBpZiAoc3JjQml0bWFzayAmIFdSQVBfQVJZX0ZMQUcpIHtcbiAgICAgICAgZGF0YVs4XSA9IGRhdGFbOF0gPT0gbnVsbCA/IHNvdXJjZVs4XSA6IG5hdGl2ZU1pbihkYXRhWzhdLCBzb3VyY2VbOF0pO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJpdHlgIGlmIG9uZSBpcyBub3QgcHJvdmlkZWQuXG4gICAgICBpZiAoZGF0YVs5XSA9PSBudWxsKSB7XG4gICAgICAgIGRhdGFbOV0gPSBzb3VyY2VbOV07XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBmdW5jYCBhbmQgbWVyZ2UgYml0bWFza3MuXG4gICAgICBkYXRhWzBdID0gc291cmNlWzBdO1xuICAgICAgZGF0YVsxXSA9IG5ld0JpdG1hc2s7XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZVxuICAgICAqIFtgT2JqZWN0LmtleXNgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3Qua2V5cylcbiAgICAgKiBleGNlcHQgdGhhdCBpdCBpbmNsdWRlcyBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBuYXRpdmVLZXlzSW4ob2JqZWN0KSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBpZiAob2JqZWN0ICE9IG51bGwpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIE9iamVjdChvYmplY3QpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nIHVzaW5nIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKHZhbHVlKSB7XG4gICAgICByZXR1cm4gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlUmVzdGAgd2hpY2ggdHJhbnNmb3JtcyB0aGUgcmVzdCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgYSByZXN0IHBhcmFtZXRlciB0by5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PWZ1bmMubGVuZ3RoLTFdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgcmVzdCBwYXJhbWV0ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdHJhbnNmb3JtIFRoZSByZXN0IGFycmF5IHRyYW5zZm9ybS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBvdmVyUmVzdChmdW5jLCBzdGFydCwgdHJhbnNmb3JtKSB7XG4gICAgICBzdGFydCA9IG5hdGl2ZU1heChzdGFydCA9PT0gdW5kZWZpbmVkID8gKGZ1bmMubGVuZ3RoIC0gMSkgOiBzdGFydCwgMCk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChhcmdzLmxlbmd0aCAtIHN0YXJ0LCAwKSxcbiAgICAgICAgICAgIGFycmF5ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGFycmF5W2luZGV4XSA9IGFyZ3Nbc3RhcnQgKyBpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSAtMTtcbiAgICAgICAgdmFyIG90aGVyQXJncyA9IEFycmF5KHN0YXJ0ICsgMSk7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgc3RhcnQpIHtcbiAgICAgICAgICBvdGhlckFyZ3NbaW5kZXhdID0gYXJnc1tpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgb3RoZXJBcmdzW3N0YXJ0XSA9IHRyYW5zZm9ybShhcnJheSk7XG4gICAgICAgIHJldHVybiBhcHBseShmdW5jLCB0aGlzLCBvdGhlckFyZ3MpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwYXJlbnQgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0aCBUaGUgcGF0aCB0byBnZXQgdGhlIHBhcmVudCB2YWx1ZSBvZi5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcGFyZW50IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhcmVudChvYmplY3QsIHBhdGgpIHtcbiAgICAgIHJldHVybiBwYXRoLmxlbmd0aCA8IDIgPyBvYmplY3QgOiBiYXNlR2V0KG9iamVjdCwgYmFzZVNsaWNlKHBhdGgsIDAsIC0xKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVvcmRlciBgYXJyYXlgIGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWVkIGluZGV4ZXMgd2hlcmUgdGhlIGVsZW1lbnQgYXRcbiAgICAgKiB0aGUgZmlyc3QgaW5kZXggaXMgYXNzaWduZWQgYXMgdGhlIGZpcnN0IGVsZW1lbnQsIHRoZSBlbGVtZW50IGF0XG4gICAgICogdGhlIHNlY29uZCBpbmRleCBpcyBhc3NpZ25lZCBhcyB0aGUgc2Vjb25kIGVsZW1lbnQsIGFuZCBzbyBvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHJlb3JkZXIuXG4gICAgICogQHBhcmFtIHtBcnJheX0gaW5kZXhlcyBUaGUgYXJyYW5nZWQgYXJyYXkgaW5kZXhlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZW9yZGVyKGFycmF5LCBpbmRleGVzKSB7XG4gICAgICB2YXIgYXJyTGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihpbmRleGVzLmxlbmd0aCwgYXJyTGVuZ3RoKSxcbiAgICAgICAgICBvbGRBcnJheSA9IGNvcHlBcnJheShhcnJheSk7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgaW5kZXggPSBpbmRleGVzW2xlbmd0aF07XG4gICAgICAgIGFycmF5W2xlbmd0aF0gPSBpc0luZGV4KGluZGV4LCBhcnJMZW5ndGgpID8gb2xkQXJyYXlbaW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHZhbHVlIGF0IGBrZXlgLCB1bmxlc3MgYGtleWAgaXMgXCJfX3Byb3RvX19cIiBvciBcImNvbnN0cnVjdG9yXCIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FmZUdldChvYmplY3QsIGtleSkge1xuICAgICAgaWYgKGtleSA9PT0gJ2NvbnN0cnVjdG9yJyAmJiB0eXBlb2Ygb2JqZWN0W2tleV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoa2V5ID09ICdfX3Byb3RvX18nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9iamVjdFtrZXldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgbWV0YWRhdGEgZm9yIGBmdW5jYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJZiB0aGlzIGZ1bmN0aW9uIGJlY29tZXMgaG90LCBpLmUuIGlzIGludm9rZWQgYSBsb3QgaW4gYSBzaG9ydFxuICAgICAqIHBlcmlvZCBvZiB0aW1lLCBpdCB3aWxsIHRyaXAgaXRzIGJyZWFrZXIgYW5kIHRyYW5zaXRpb24gdG8gYW4gaWRlbnRpdHlcbiAgICAgKiBmdW5jdGlvbiB0byBhdm9pZCBnYXJiYWdlIGNvbGxlY3Rpb24gcGF1c2VzIGluIFY4LiBTZWVcbiAgICAgKiBbVjggaXNzdWUgMjA3MF0oaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjA3MClcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhc3NvY2lhdGUgbWV0YWRhdGEgd2l0aC5cbiAgICAgKiBAcGFyYW0geyp9IGRhdGEgVGhlIG1ldGFkYXRhLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgZnVuY2AuXG4gICAgICovXG4gICAgdmFyIHNldERhdGEgPSBzaG9ydE91dChiYXNlU2V0RGF0YSk7XG5cbiAgICAvKipcbiAgICAgKiBBIHNpbXBsZSB3cmFwcGVyIGFyb3VuZCB0aGUgZ2xvYmFsIFtgc2V0VGltZW91dGBdKGh0dHBzOi8vbWRuLmlvL3NldFRpbWVvdXQpLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheSBpbnZvY2F0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ8T2JqZWN0fSBSZXR1cm5zIHRoZSB0aW1lciBpZCBvciB0aW1lb3V0IG9iamVjdC5cbiAgICAgKi9cbiAgICB2YXIgc2V0VGltZW91dCA9IGN0eFNldFRpbWVvdXQgfHwgZnVuY3Rpb24oZnVuYywgd2FpdCkge1xuICAgICAgcmV0dXJuIHJvb3Quc2V0VGltZW91dChmdW5jLCB3YWl0KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYHRvU3RyaW5nYCBtZXRob2Qgb2YgYGZ1bmNgIHRvIHJldHVybiBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHN0cmluZyBUaGUgYHRvU3RyaW5nYCByZXN1bHQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgc2V0VG9TdHJpbmcgPSBzaG9ydE91dChiYXNlU2V0VG9TdHJpbmcpO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYHRvU3RyaW5nYCBtZXRob2Qgb2YgYHdyYXBwZXJgIHRvIG1pbWljIHRoZSBzb3VyY2Ugb2YgYHJlZmVyZW5jZWBcbiAgICAgKiB3aXRoIHdyYXBwZXIgZGV0YWlscyBpbiBhIGNvbW1lbnQgYXQgdGhlIHRvcCBvZiB0aGUgc291cmNlIGJvZHkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBwZXIgVGhlIGZ1bmN0aW9uIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSByZWZlcmVuY2UgVGhlIHJlZmVyZW5jZSBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgd3JhcHBlcmAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0V3JhcFRvU3RyaW5nKHdyYXBwZXIsIHJlZmVyZW5jZSwgYml0bWFzaykge1xuICAgICAgdmFyIHNvdXJjZSA9IChyZWZlcmVuY2UgKyAnJyk7XG4gICAgICByZXR1cm4gc2V0VG9TdHJpbmcod3JhcHBlciwgaW5zZXJ0V3JhcERldGFpbHMoc291cmNlLCB1cGRhdGVXcmFwRGV0YWlscyhnZXRXcmFwRGV0YWlscyhzb3VyY2UpLCBiaXRtYXNrKSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0J2xsIHNob3J0IG91dCBhbmQgaW52b2tlIGBpZGVudGl0eWAgaW5zdGVhZFxuICAgICAqIG9mIGBmdW5jYCB3aGVuIGl0J3MgY2FsbGVkIGBIT1RfQ09VTlRgIG9yIG1vcmUgdGltZXMgaW4gYEhPVF9TUEFOYFxuICAgICAqIG1pbGxpc2Vjb25kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVzdHJpY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc2hvcnRhYmxlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNob3J0T3V0KGZ1bmMpIHtcbiAgICAgIHZhciBjb3VudCA9IDAsXG4gICAgICAgICAgbGFzdENhbGxlZCA9IDA7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN0YW1wID0gbmF0aXZlTm93KCksXG4gICAgICAgICAgICByZW1haW5pbmcgPSBIT1RfU1BBTiAtIChzdGFtcCAtIGxhc3RDYWxsZWQpO1xuXG4gICAgICAgIGxhc3RDYWxsZWQgPSBzdGFtcDtcbiAgICAgICAgaWYgKHJlbWFpbmluZyA+IDApIHtcbiAgICAgICAgICBpZiAoKytjb3VudCA+PSBIT1RfQ09VTlQpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmd1bWVudHNbMF07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvdW50ID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5zaHVmZmxlYCB3aGljaCBtdXRhdGVzIGFuZCBzZXRzIHRoZSBzaXplIG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzaHVmZmxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc2l6ZT1hcnJheS5sZW5ndGhdIFRoZSBzaXplIG9mIGBhcnJheWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2h1ZmZsZVNlbGYoYXJyYXksIHNpemUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBsYXN0SW5kZXggPSBsZW5ndGggLSAxO1xuXG4gICAgICBzaXplID0gc2l6ZSA9PT0gdW5kZWZpbmVkID8gbGVuZ3RoIDogc2l6ZTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgc2l6ZSkge1xuICAgICAgICB2YXIgcmFuZCA9IGJhc2VSYW5kb20oaW5kZXgsIGxhc3RJbmRleCksXG4gICAgICAgICAgICB2YWx1ZSA9IGFycmF5W3JhbmRdO1xuXG4gICAgICAgIGFycmF5W3JhbmRdID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBhcnJheVtpbmRleF0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGFycmF5Lmxlbmd0aCA9IHNpemU7XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG8gYSBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHByb3BlcnR5IHBhdGggYXJyYXkuXG4gICAgICovXG4gICAgdmFyIHN0cmluZ1RvUGF0aCA9IG1lbW9pemVDYXBwZWQoZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBpZiAoc3RyaW5nLmNoYXJDb2RlQXQoMCkgPT09IDQ2IC8qIC4gKi8pIHtcbiAgICAgICAgcmVzdWx0LnB1c2goJycpO1xuICAgICAgfVxuICAgICAgc3RyaW5nLnJlcGxhY2UocmVQcm9wTmFtZSwgZnVuY3Rpb24obWF0Y2gsIG51bWJlciwgcXVvdGUsIHN1YlN0cmluZykge1xuICAgICAgICByZXN1bHQucHVzaChxdW90ZSA/IHN1YlN0cmluZy5yZXBsYWNlKHJlRXNjYXBlQ2hhciwgJyQxJykgOiAobnVtYmVyIHx8IG1hdGNoKSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nIGtleSBpZiBpdCdzIG5vdCBhIHN0cmluZyBvciBzeW1ib2wuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge3N0cmluZ3xzeW1ib2x9IFJldHVybnMgdGhlIGtleS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0tleSh2YWx1ZSkge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fCBpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9ICh2YWx1ZSArICcnKTtcbiAgICAgIHJldHVybiAocmVzdWx0ID09ICcwJyAmJiAoMSAvIHZhbHVlKSA9PSAtSU5GSU5JVFkpID8gJy0wJyA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgZnVuY2AgdG8gaXRzIHNvdXJjZSBjb2RlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHNvdXJjZSBjb2RlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU291cmNlKGZ1bmMpIHtcbiAgICAgIGlmIChmdW5jICE9IG51bGwpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gZnVuY1RvU3RyaW5nLmNhbGwoZnVuYyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIChmdW5jICsgJycpO1xuICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgfVxuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgd3JhcHBlciBgZGV0YWlsc2AgYmFzZWQgb24gYGJpdG1hc2tgIGZsYWdzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IGRldGFpbHMgVGhlIGRldGFpbHMgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBkZXRhaWxzYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGVXcmFwRGV0YWlscyhkZXRhaWxzLCBiaXRtYXNrKSB7XG4gICAgICBhcnJheUVhY2god3JhcEZsYWdzLCBmdW5jdGlvbihwYWlyKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9ICdfLicgKyBwYWlyWzBdO1xuICAgICAgICBpZiAoKGJpdG1hc2sgJiBwYWlyWzFdKSAmJiAhYXJyYXlJbmNsdWRlcyhkZXRhaWxzLCB2YWx1ZSkpIHtcbiAgICAgICAgICBkZXRhaWxzLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBkZXRhaWxzLnNvcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHdyYXBwZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gd3JhcHBlciBUaGUgd3JhcHBlciB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgd3JhcHBlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyQ2xvbmUod3JhcHBlcikge1xuICAgICAgaWYgKHdyYXBwZXIgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICByZXR1cm4gd3JhcHBlci5jbG9uZSgpO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMb2Rhc2hXcmFwcGVyKHdyYXBwZXIuX193cmFwcGVkX18sIHdyYXBwZXIuX19jaGFpbl9fKTtcbiAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXyA9IGNvcHlBcnJheSh3cmFwcGVyLl9fYWN0aW9uc19fKTtcbiAgICAgIHJlc3VsdC5fX2luZGV4X18gID0gd3JhcHBlci5fX2luZGV4X187XG4gICAgICByZXN1bHQuX192YWx1ZXNfXyA9IHdyYXBwZXIuX192YWx1ZXNfXztcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cyBzcGxpdCBpbnRvIGdyb3VwcyB0aGUgbGVuZ3RoIG9mIGBzaXplYC5cbiAgICAgKiBJZiBgYXJyYXlgIGNhbid0IGJlIHNwbGl0IGV2ZW5seSwgdGhlIGZpbmFsIGNodW5rIHdpbGwgYmUgdGhlIHJlbWFpbmluZ1xuICAgICAqIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzaXplPTFdIFRoZSBsZW5ndGggb2YgZWFjaCBjaHVua1xuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY2h1bmtzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNodW5rKFsnYScsICdiJywgJ2MnLCAnZCddLCAyKTtcbiAgICAgKiAvLyA9PiBbWydhJywgJ2InXSwgWydjJywgJ2QnXV1cbiAgICAgKlxuICAgICAqIF8uY2h1bmsoWydhJywgJ2InLCAnYycsICdkJ10sIDMpO1xuICAgICAqIC8vID0+IFtbJ2EnLCAnYicsICdjJ10sIFsnZCddXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNodW5rKGFycmF5LCBzaXplLCBndWFyZCkge1xuICAgICAgaWYgKChndWFyZCA/IGlzSXRlcmF0ZWVDYWxsKGFycmF5LCBzaXplLCBndWFyZCkgOiBzaXplID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgIHNpemUgPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2l6ZSA9IG5hdGl2ZU1heCh0b0ludGVnZXIoc2l6ZSksIDApO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGggfHwgc2l6ZSA8IDEpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobmF0aXZlQ2VpbChsZW5ndGggLyBzaXplKSk7XG5cbiAgICAgIHdoaWxlIChpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSBiYXNlU2xpY2UoYXJyYXksIGluZGV4LCAoaW5kZXggKz0gc2l6ZSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IHdpdGggYWxsIGZhbHNleSB2YWx1ZXMgcmVtb3ZlZC4gVGhlIHZhbHVlcyBgZmFsc2VgLCBgbnVsbGAsXG4gICAgICogYDBgLCBgXCJcImAsIGB1bmRlZmluZWRgLCBhbmQgYE5hTmAgYXJlIGZhbHNleS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb21wYWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jb21wYWN0KFswLCAxLCBmYWxzZSwgMiwgJycsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wYWN0KGFycmF5KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBhcnJheSBjb25jYXRlbmF0aW5nIGBhcnJheWAgd2l0aCBhbnkgYWRkaXRpb25hbCBhcnJheXNcbiAgICAgKiBhbmQvb3IgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbmNhdGVuYXRlLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjb25jYXRlbmF0ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBjb25jYXRlbmF0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxXTtcbiAgICAgKiB2YXIgb3RoZXIgPSBfLmNvbmNhdChhcnJheSwgMiwgWzNdLCBbWzRdXSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvdGhlcik7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIFs0XV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25jYXQoKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBhcmdzID0gQXJyYXkobGVuZ3RoIC0gMSksXG4gICAgICAgICAgYXJyYXkgPSBhcmd1bWVudHNbMF0sXG4gICAgICAgICAgaW5kZXggPSBsZW5ndGg7XG5cbiAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgIGFyZ3NbaW5kZXggLSAxXSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXlQdXNoKGlzQXJyYXkoYXJyYXkpID8gY29weUFycmF5KGFycmF5KSA6IFthcnJheV0sIGJhc2VGbGF0dGVuKGFyZ3MsIDEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGBhcnJheWAgdmFsdWVzIG5vdCBpbmNsdWRlZCBpbiB0aGUgb3RoZXIgZ2l2ZW4gYXJyYXlzXG4gICAgICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIFRoZSBvcmRlciBhbmQgcmVmZXJlbmNlcyBvZiByZXN1bHQgdmFsdWVzIGFyZVxuICAgICAqIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5wdWxsQWxsYCwgdGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQHNlZSBfLndpdGhvdXQsIF8ueG9yXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGlmZmVyZW5jZShbMiwgMV0sIFsyLCAzXSk7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICovXG4gICAgdmFyIGRpZmZlcmVuY2UgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5kaWZmZXJlbmNlYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCBhbmQgYHZhbHVlc2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvblxuICAgICAqIGJ5IHdoaWNoIHRoZXkncmUgY29tcGFyZWQuIFRoZSBvcmRlciBhbmQgcmVmZXJlbmNlcyBvZiByZXN1bHQgdmFsdWVzIGFyZVxuICAgICAqIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDpcbiAgICAgKiAodmFsdWUpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5wdWxsQWxsQnlgLCB0aGlzIG1ldGhvZCByZXR1cm5zIGEgbmV3IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGlmZmVyZW5jZUJ5KFsyLjEsIDEuMl0sIFsyLjMsIDMuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsxLjJdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRpZmZlcmVuY2VCeShbeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sIFt7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICB2YXIgZGlmZmVyZW5jZUJ5ID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXksIHZhbHVlcykge1xuICAgICAgdmFyIGl0ZXJhdGVlID0gbGFzdCh2YWx1ZXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGl0ZXJhdGVlKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0FycmF5TGlrZU9iamVjdChhcnJheSlcbiAgICAgICAgPyBiYXNlRGlmZmVyZW5jZShhcnJheSwgYmFzZUZsYXR0ZW4odmFsdWVzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSlcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZGlmZmVyZW5jZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5YCB0byBgdmFsdWVzYC4gVGhlIG9yZGVyIGFuZFxuICAgICAqIHJlZmVyZW5jZXMgb2YgcmVzdWx0IHZhbHVlcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuIFRoZSBjb21wYXJhdG9yXG4gICAgICogaXMgaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLnB1bGxBbGxXaXRoYCwgdGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XTtcbiAgICAgKlxuICAgICAqIF8uZGlmZmVyZW5jZVdpdGgob2JqZWN0cywgW3sgJ3gnOiAxLCAneSc6IDIgfV0sIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyLCAneSc6IDEgfV1cbiAgICAgKi9cbiAgICB2YXIgZGlmZmVyZW5jZVdpdGggPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICB2YXIgY29tcGFyYXRvciA9IGxhc3QodmFsdWVzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChjb21wYXJhdG9yKSkge1xuICAgICAgICBjb21wYXJhdG9yID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KGFycmF5KVxuICAgICAgICA/IGJhc2VEaWZmZXJlbmNlKGFycmF5LCBiYXNlRmxhdHRlbih2YWx1ZXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBiZWdpbm5pbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC41LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZHJvcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wKGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgbiA9IChndWFyZCB8fCBuID09PSB1bmRlZmluZWQpID8gMSA6IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIG4gPCAwID8gMCA6IG4sIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBlbmQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZHJvcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3BSaWdodChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICBuID0gbGVuZ3RoIC0gbjtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIDAsIG4gPCAwID8gMCA6IG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIGV4Y2x1ZGluZyBlbGVtZW50cyBkcm9wcGVkIGZyb20gdGhlIGVuZC5cbiAgICAgKiBFbGVtZW50cyBhcmUgZHJvcHBlZCB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFJpZ2h0V2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIHRydWUsIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZXhjbHVkaW5nIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqIEVsZW1lbnRzIGFyZSBkcm9wcGVkIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZHJvcFdoaWxlKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3BXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmlsbHMgZWxlbWVudHMgb2YgYGFycmF5YCB3aXRoIGB2YWx1ZWAgZnJvbSBgc3RhcnRgIHVwIHRvLCBidXQgbm90XG4gICAgICogaW5jbHVkaW5nLCBgZW5kYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmlsbC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBmaWxsIGBhcnJheWAgd2l0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8uZmlsbChhcnJheSwgJ2EnKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWydhJywgJ2EnLCAnYSddXG4gICAgICpcbiAgICAgKiBfLmZpbGwoQXJyYXkoMyksIDIpO1xuICAgICAqIC8vID0+IFsyLCAyLCAyXVxuICAgICAqXG4gICAgICogXy5maWxsKFs0LCA2LCA4LCAxMF0sICcqJywgMSwgMyk7XG4gICAgICogLy8gPT4gWzQsICcqJywgJyonLCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaWxsKGFycmF5LCB2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0ICYmIHR5cGVvZiBzdGFydCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgdmFsdWUsIHN0YXJ0KSkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIGVuZCA9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlRmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudCBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgaW5zdGVhZCBvZiB0aGUgZWxlbWVudCBpdHNlbGYuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9MF0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLnVzZXIgPT0gJ2Jhcm5leSc7IH0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIHsgJ3VzZXInOiAnZnJlZCcsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBmcm9tSW5kZXggPT0gbnVsbCA/IDAgOiB0b0ludGVnZXIoZnJvbUluZGV4KTtcbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgaW5kZXggPSBuYXRpdmVNYXgobGVuZ3RoICsgaW5kZXgsIDApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VGaW5kSW5kZXgoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIGluZGV4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRJbmRleGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50c1xuICAgICAqIG9mIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9YXJyYXkubGVuZ3RoLTFdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZm91bmQgZWxlbWVudCwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8udXNlciA9PSAncGViYmxlcyc7IH0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEluZGV4KHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZExhc3RJbmRleChhcnJheSwgcHJlZGljYXRlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IGxlbmd0aCAtIDE7XG4gICAgICBpZiAoZnJvbUluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaW5kZXggPSB0b0ludGVnZXIoZnJvbUluZGV4KTtcbiAgICAgICAgaW5kZXggPSBmcm9tSW5kZXggPCAwXG4gICAgICAgICAgPyBuYXRpdmVNYXgobGVuZ3RoICsgaW5kZXgsIDApXG4gICAgICAgICAgOiBuYXRpdmVNaW4oaW5kZXgsIGxlbmd0aCAtIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VGaW5kSW5kZXgoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIGluZGV4LCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGbGF0dGVucyBgYXJyYXlgIGEgc2luZ2xlIGxldmVsIGRlZXAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmxhdHRlbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbihbMSwgWzIsIFszLCBbNF1dLCA1XV0pO1xuICAgICAqIC8vID0+IFsxLCAyLCBbMywgWzRdXSwgNV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0dGVuKGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZUZsYXR0ZW4oYXJyYXksIDEpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgZmxhdHRlbnMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZsYXR0ZW5lZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mbGF0dGVuRGVlcChbMSwgWzIsIFszLCBbNF1dLCA1XV0pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCA0LCA1XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXR0ZW5EZWVwKGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZUZsYXR0ZW4oYXJyYXksIElORklOSVRZKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IGZsYXR0ZW4gYGFycmF5YCB1cCB0byBgZGVwdGhgIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtkZXB0aD0xXSBUaGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGguXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgWzIsIFszLCBbNF1dLCA1XV07XG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW5EZXB0aChhcnJheSwgMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIFszLCBbNF1dLCA1XVxuICAgICAqXG4gICAgICogXy5mbGF0dGVuRGVwdGgoYXJyYXksIDIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCBbNF0sIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbkRlcHRoKGFycmF5LCBkZXB0aCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgZGVwdGggPSBkZXB0aCA9PT0gdW5kZWZpbmVkID8gMSA6IHRvSW50ZWdlcihkZXB0aCk7XG4gICAgICByZXR1cm4gYmFzZUZsYXR0ZW4oYXJyYXksIGRlcHRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW52ZXJzZSBvZiBgXy50b1BhaXJzYDsgdGhpcyBtZXRob2QgcmV0dXJucyBhbiBvYmplY3QgY29tcG9zZWRcbiAgICAgKiBmcm9tIGtleS12YWx1ZSBgcGFpcnNgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFpcnMgVGhlIGtleS12YWx1ZSBwYWlycy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZyb21QYWlycyhbWydhJywgMV0sIFsnYicsIDJdXSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gZnJvbVBhaXJzKHBhaXJzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwYWlycyA9PSBudWxsID8gMCA6IHBhaXJzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSB7fTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHBhaXIgPSBwYWlyc1tpbmRleF07XG4gICAgICAgIHJlc3VsdFtwYWlyWzBdXSA9IHBhaXJbMV07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBhbGlhcyBmaXJzdFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZmlyc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmhlYWQoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiBfLmhlYWQoW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhlYWQoYXJyYXkpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSA/IGFycmF5WzBdIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGB2YWx1ZWAgaXMgZm91bmQgaW4gYGFycmF5YFxuICAgICAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLiBJZiBgZnJvbUluZGV4YCBpcyBuZWdhdGl2ZSwgaXQncyB1c2VkIGFzIHRoZVxuICAgICAqIG9mZnNldCBmcm9tIHRoZSBlbmQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9MF0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5kZXhPZihbMSwgMiwgMSwgMl0sIDIpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIFNlYXJjaCBmcm9tIHRoZSBgZnJvbUluZGV4YC5cbiAgICAgKiBfLmluZGV4T2YoWzEsIDIsIDEsIDJdLCAyLCAyKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gZnJvbUluZGV4ID09IG51bGwgPyAwIDogdG9JbnRlZ2VyKGZyb21JbmRleCk7XG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgIGluZGV4ID0gbmF0aXZlTWF4KGxlbmd0aCArIGluZGV4LCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlSW5kZXhPZihhcnJheSwgdmFsdWUsIGluZGV4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBidXQgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbml0aWFsKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5pdGlhbChhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VTbGljZShhcnJheSwgMCwgLTEpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB1bmlxdWUgdmFsdWVzIHRoYXQgYXJlIGluY2x1ZGVkIGluIGFsbCBnaXZlbiBhcnJheXNcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gVGhlIG9yZGVyIGFuZCByZWZlcmVuY2VzIG9mIHJlc3VsdCB2YWx1ZXMgYXJlXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgaW50ZXJzZWN0aW5nIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnRlcnNlY3Rpb24oWzIsIDFdLCBbMiwgM10pO1xuICAgICAqIC8vID0+IFsyXVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb24gPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBtYXBwZWQgPSBhcnJheU1hcChhcnJheXMsIGNhc3RBcnJheUxpa2VPYmplY3QpO1xuICAgICAgcmV0dXJuIChtYXBwZWQubGVuZ3RoICYmIG1hcHBlZFswXSA9PT0gYXJyYXlzWzBdKVxuICAgICAgICA/IGJhc2VJbnRlcnNlY3Rpb24obWFwcGVkKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbnRlcnNlY3Rpb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBlYWNoIGBhcnJheXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb25cbiAgICAgKiBieSB3aGljaCB0aGV5J3JlIGNvbXBhcmVkLiBUaGUgb3JkZXIgYW5kIHJlZmVyZW5jZXMgb2YgcmVzdWx0IHZhbHVlcyBhcmVcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6XG4gICAgICogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgaW50ZXJzZWN0aW5nIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnRlcnNlY3Rpb25CeShbMi4xLCAxLjJdLCBbMi4zLCAzLjRdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMi4xXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5pbnRlcnNlY3Rpb25CeShbeyAneCc6IDEgfV0sIFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEgfV1cbiAgICAgKi9cbiAgICB2YXIgaW50ZXJzZWN0aW9uQnkgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QoYXJyYXlzKSxcbiAgICAgICAgICBtYXBwZWQgPSBhcnJheU1hcChhcnJheXMsIGNhc3RBcnJheUxpa2VPYmplY3QpO1xuXG4gICAgICBpZiAoaXRlcmF0ZWUgPT09IGxhc3QobWFwcGVkKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcHBlZC5wb3AoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAobWFwcGVkLmxlbmd0aCAmJiBtYXBwZWRbMF0gPT09IGFycmF5c1swXSlcbiAgICAgICAgPyBiYXNlSW50ZXJzZWN0aW9uKG1hcHBlZCwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbnRlcnNlY3Rpb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheXNgLiBUaGUgb3JkZXIgYW5kIHJlZmVyZW5jZXNcbiAgICAgKiBvZiByZXN1bHQgdmFsdWVzIGFyZSBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS4gVGhlIGNvbXBhcmF0b3IgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBpbnRlcnNlY3RpbmcgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfV07XG4gICAgICogdmFyIG90aGVycyA9IFt7ICd4JzogMSwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLmludGVyc2VjdGlvbldpdGgob2JqZWN0cywgb3RoZXJzLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSwgJ3knOiAyIH1dXG4gICAgICovXG4gICAgdmFyIGludGVyc2VjdGlvbldpdGggPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdChhcnJheXMpLFxuICAgICAgICAgIG1hcHBlZCA9IGFycmF5TWFwKGFycmF5cywgY2FzdEFycmF5TGlrZU9iamVjdCk7XG5cbiAgICAgIGNvbXBhcmF0b3IgPSB0eXBlb2YgY29tcGFyYXRvciA9PSAnZnVuY3Rpb24nID8gY29tcGFyYXRvciA6IHVuZGVmaW5lZDtcbiAgICAgIGlmIChjb21wYXJhdG9yKSB7XG4gICAgICAgIG1hcHBlZC5wb3AoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAobWFwcGVkLmxlbmd0aCAmJiBtYXBwZWRbMF0gPT09IGFycmF5c1swXSlcbiAgICAgICAgPyBiYXNlSW50ZXJzZWN0aW9uKG1hcHBlZCwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYWxsIGVsZW1lbnRzIGluIGBhcnJheWAgaW50byBhIHN0cmluZyBzZXBhcmF0ZWQgYnkgYHNlcGFyYXRvcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29udmVydC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3NlcGFyYXRvcj0nLCddIFRoZSBlbGVtZW50IHNlcGFyYXRvci5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBqb2luZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmpvaW4oWydhJywgJ2InLCAnYyddLCAnficpO1xuICAgICAqIC8vID0+ICdhfmJ+YydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBqb2luKGFycmF5LCBzZXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiBhcnJheSA9PSBudWxsID8gJycgOiBuYXRpdmVKb2luLmNhbGwoYXJyYXksIHNlcGFyYXRvcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxhc3QoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGFzdChhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGFycmF5W2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBhcnJheWAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD1hcnJheS5sZW5ndGgtMV0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubGFzdEluZGV4T2YoWzEsIDIsIDEsIDJdLCAyKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiAvLyBTZWFyY2ggZnJvbSB0aGUgYGZyb21JbmRleGAuXG4gICAgICogXy5sYXN0SW5kZXhPZihbMSwgMiwgMSwgMl0sIDIsIDIpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXN0SW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgaWYgKGZyb21JbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGV4ID0gdG9JbnRlZ2VyKGZyb21JbmRleCk7XG4gICAgICAgIGluZGV4ID0gaW5kZXggPCAwID8gbmF0aXZlTWF4KGxlbmd0aCArIGluZGV4LCAwKSA6IG5hdGl2ZU1pbihpbmRleCwgbGVuZ3RoIC0gMSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWUgPT09IHZhbHVlXG4gICAgICAgID8gc3RyaWN0TGFzdEluZGV4T2YoYXJyYXksIHZhbHVlLCBpbmRleClcbiAgICAgICAgOiBiYXNlRmluZEluZGV4KGFycmF5LCBiYXNlSXNOYU4sIGluZGV4LCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBlbGVtZW50IGF0IGluZGV4IGBuYCBvZiBgYXJyYXlgLiBJZiBgbmAgaXMgbmVnYXRpdmUsIHRoZSBudGhcbiAgICAgKiBlbGVtZW50IGZyb20gdGhlIGVuZCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjExLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTBdIFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0byByZXR1cm4uXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG50aCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsnYScsICdiJywgJ2MnLCAnZCddO1xuICAgICAqXG4gICAgICogXy5udGgoYXJyYXksIDEpO1xuICAgICAqIC8vID0+ICdiJ1xuICAgICAqXG4gICAgICogXy5udGgoYXJyYXksIC0yKTtcbiAgICAgKiAvLyA9PiAnYyc7XG4gICAgICovXG4gICAgZnVuY3Rpb24gbnRoKGFycmF5LCBuKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkgPyBiYXNlTnRoKGFycmF5LCB0b0ludGVnZXIobikpIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGdpdmVuIHZhbHVlcyBmcm9tIGBhcnJheWAgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ud2l0aG91dGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC4gVXNlIGBfLnJlbW92ZWBcbiAgICAgKiB0byByZW1vdmUgZWxlbWVudHMgZnJvbSBhbiBhcnJheSBieSBwcmVkaWNhdGUuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsnYScsICdiJywgJ2MnLCAnYScsICdiJywgJ2MnXTtcbiAgICAgKlxuICAgICAqIF8ucHVsbChhcnJheSwgJ2EnLCAnYycpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbJ2InLCAnYiddXG4gICAgICovXG4gICAgdmFyIHB1bGwgPSBiYXNlUmVzdChwdWxsQWxsKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucHVsbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhbiBhcnJheSBvZiB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5kaWZmZXJlbmNlYCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsnYScsICdiJywgJ2MnLCAnYScsICdiJywgJ2MnXTtcbiAgICAgKlxuICAgICAqIF8ucHVsbEFsbChhcnJheSwgWydhJywgJ2MnXSk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsnYicsICdiJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwdWxsQWxsKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoICYmIHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKVxuICAgICAgICA/IGJhc2VQdWxsQWxsKGFycmF5LCB2YWx1ZXMpXG4gICAgICAgIDogYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wdWxsQWxsYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCBhbmQgYHZhbHVlc2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvblxuICAgICAqIGJ5IHdoaWNoIHRoZXkncmUgY29tcGFyZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5kaWZmZXJlbmNlQnlgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9LCB7ICd4JzogMyB9LCB7ICd4JzogMSB9XTtcbiAgICAgKlxuICAgICAqIF8ucHVsbEFsbEJ5KGFycmF5LCBbeyAneCc6IDEgfSwgeyAneCc6IDMgfV0sICd4Jyk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHB1bGxBbGxCeShhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGggJiYgdmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpXG4gICAgICAgID8gYmFzZVB1bGxBbGwoYXJyYXksIHZhbHVlcywgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKVxuICAgICAgICA6IGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucHVsbEFsbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5YCB0byBgdmFsdWVzYC4gVGhlIGNvbXBhcmF0b3IgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZGlmZmVyZW5jZVdpdGhgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDMsICd5JzogNCB9LCB7ICd4JzogNSwgJ3knOiA2IH1dO1xuICAgICAqXG4gICAgICogXy5wdWxsQWxsV2l0aChhcnJheSwgW3sgJ3gnOiAzLCAneSc6IDQgfV0sIF8uaXNFcXVhbCk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiA1LCAneSc6IDYgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwdWxsQWxsV2l0aChhcnJheSwgdmFsdWVzLCBjb21wYXJhdG9yKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCAmJiB2YWx1ZXMgJiYgdmFsdWVzLmxlbmd0aClcbiAgICAgICAgPyBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpXG4gICAgICAgIDogYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBlbGVtZW50cyBmcm9tIGBhcnJheWAgY29ycmVzcG9uZGluZyB0byBgaW5kZXhlc2AgYW5kIHJldHVybnMgYW5cbiAgICAgKiBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5hdGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHsuLi4obnVtYmVyfG51bWJlcltdKX0gW2luZGV4ZXNdIFRoZSBpbmRleGVzIG9mIGVsZW1lbnRzIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2EnLCAnYicsICdjJywgJ2QnXTtcbiAgICAgKiB2YXIgcHVsbGVkID0gXy5wdWxsQXQoYXJyYXksIFsxLCAzXSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWydhJywgJ2MnXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2cocHVsbGVkKTtcbiAgICAgKiAvLyA9PiBbJ2InLCAnZCddXG4gICAgICovXG4gICAgdmFyIHB1bGxBdCA9IGZsYXRSZXN0KGZ1bmN0aW9uKGFycmF5LCBpbmRleGVzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gYmFzZUF0KGFycmF5LCBpbmRleGVzKTtcblxuICAgICAgYmFzZVB1bGxBdChhcnJheSwgYXJyYXlNYXAoaW5kZXhlcywgZnVuY3Rpb24oaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGlzSW5kZXgoaW5kZXgsIGxlbmd0aCkgPyAraW5kZXggOiBpbmRleDtcbiAgICAgIH0pLnNvcnQoY29tcGFyZUFzY2VuZGluZykpO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSBgYXJyYXlgIHRoYXQgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yXG4gICAgICogYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgdGhlIHJlbW92ZWQgZWxlbWVudHMuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmZpbHRlcmAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC4gVXNlIGBfLnB1bGxgXG4gICAgICogdG8gcHVsbCBlbGVtZW50cyBmcm9tIGFuIGFycmF5IGJ5IHZhbHVlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDMsIDRdO1xuICAgICAqIHZhciBldmVucyA9IF8ucmVtb3ZlKGFycmF5LCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMSwgM11cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGV2ZW5zKTtcbiAgICAgKiAvLyA9PiBbMiwgNF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZW1vdmUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5kZXhlcyA9IFtdLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgcHJlZGljYXRlID0gZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgICBpbmRleGVzLnB1c2goaW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBiYXNlUHVsbEF0KGFycmF5LCBpbmRleGVzKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZXJzZXMgYGFycmF5YCBzbyB0aGF0IHRoZSBmaXJzdCBlbGVtZW50IGJlY29tZXMgdGhlIGxhc3QsIHRoZSBzZWNvbmRcbiAgICAgKiBlbGVtZW50IGJlY29tZXMgdGhlIHNlY29uZCB0byBsYXN0LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgIGFuZCBpcyBiYXNlZCBvblxuICAgICAqIFtgQXJyYXkjcmV2ZXJzZWBdKGh0dHBzOi8vbWRuLmlvL0FycmF5L3JldmVyc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXy5yZXZlcnNlKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXZlcnNlKGFycmF5KSB7XG4gICAgICByZXR1cm4gYXJyYXkgPT0gbnVsbCA/IGFycmF5IDogbmF0aXZlUmV2ZXJzZS5jYWxsKGFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBmcm9tIGBzdGFydGAgdXAgdG8sIGJ1dCBub3QgaW5jbHVkaW5nLCBgZW5kYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyB1c2VkIGluc3RlYWQgb2ZcbiAgICAgKiBbYEFycmF5I3NsaWNlYF0oaHR0cHM6Ly9tZG4uaW8vQXJyYXkvc2xpY2UpIHRvIGVuc3VyZSBkZW5zZSBhcnJheXMgYXJlXG4gICAgICogcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2xpY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzbGljZShhcnJheSwgc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGVuZCAmJiB0eXBlb2YgZW5kICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKGFycmF5LCBzdGFydCwgZW5kKSkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIGVuZCA9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBzdGFydCA9IHN0YXJ0ID09IG51bGwgPyAwIDogdG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgICAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiB0b0ludGVnZXIoZW5kKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZXMgYSBiaW5hcnkgc2VhcmNoIHRvIGRldGVybWluZSB0aGUgbG93ZXN0IGluZGV4IGF0IHdoaWNoIGB2YWx1ZWBcbiAgICAgKiBzaG91bGQgYmUgaW5zZXJ0ZWQgaW50byBgYXJyYXlgIGluIG9yZGVyIHRvIG1haW50YWluIGl0cyBzb3J0IG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleChbMzAsIDUwXSwgNDApO1xuICAgICAqIC8vID0+IDFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRJbmRleChhcnJheSwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlU29ydGVkSW5kZXgoYXJyYXksIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnNvcnRlZEluZGV4YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIGZvciBgdmFsdWVgIGFuZCBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCB0byBjb21wdXRlIHRoZWlyXG4gICAgICogc29ydCByYW5raW5nLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogNCB9LCB7ICd4JzogNSB9XTtcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXhCeShvYmplY3RzLCB7ICd4JzogNCB9LCBmdW5jdGlvbihvKSB7IHJldHVybiBvLng7IH0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29ydGVkSW5kZXhCeShvYmplY3RzLCB7ICd4JzogNCB9LCAneCcpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBiYXNlU29ydGVkSW5kZXhCeShhcnJheSwgdmFsdWUsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbmRleE9mYCBleGNlcHQgdGhhdCBpdCBwZXJmb3JtcyBhIGJpbmFyeVxuICAgICAqIHNlYXJjaCBvbiBhIHNvcnRlZCBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZEluZGV4T2YoWzQsIDUsIDUsIDUsIDZdLCA1KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkSW5kZXhPZihhcnJheSwgdmFsdWUpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGgpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSk7XG4gICAgICAgIGlmIChpbmRleCA8IGxlbmd0aCAmJiBlcShhcnJheVtpbmRleF0sIHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydGVkSW5kZXhgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGhpZ2hlc3RcbiAgICAgKiBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG9cbiAgICAgKiBtYWludGFpbiBpdHMgc29ydCBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkTGFzdEluZGV4KFs0LCA1LCA1LCA1LCA2XSwgNSk7XG4gICAgICogLy8gPT4gNFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZExhc3RJbmRleChhcnJheSwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlU29ydGVkSW5kZXgoYXJyYXksIHZhbHVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnNvcnRlZExhc3RJbmRleGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZSB0aGVpclxuICAgICAqIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDQgfSwgeyAneCc6IDUgfV07XG4gICAgICpcbiAgICAgKiBfLnNvcnRlZExhc3RJbmRleEJ5KG9iamVjdHMsIHsgJ3gnOiA0IH0sIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ueDsgfSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXhCeShvYmplY3RzLCB7ICd4JzogNCB9LCAneCcpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRMYXN0SW5kZXhCeShhcnJheSwgdmFsdWUsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMiksIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ubGFzdEluZGV4T2ZgIGV4Y2VwdCB0aGF0IGl0IHBlcmZvcm1zIGEgYmluYXJ5XG4gICAgICogc2VhcmNoIG9uIGEgc29ydGVkIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkTGFzdEluZGV4T2YoWzQsIDUsIDUsIDUsIDZdLCA1KTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkTGFzdEluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHRydWUpIC0gMTtcbiAgICAgICAgaWYgKGVxKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlxYCBleGNlcHQgdGhhdCBpdCdzIGRlc2lnbmVkIGFuZCBvcHRpbWl6ZWRcbiAgICAgKiBmb3Igc29ydGVkIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZFVuaXEoWzEsIDEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRVbmlxKGFycmF5KSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU29ydGVkVW5pcShhcnJheSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFCeWAgZXhjZXB0IHRoYXQgaXQncyBkZXNpZ25lZCBhbmQgb3B0aW1pemVkXG4gICAgICogZm9yIHNvcnRlZCBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZFVuaXFCeShbMS4xLCAxLjIsIDIuMywgMi40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzEuMSwgMi4zXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZFVuaXFCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VTb3J0ZWRVbmlxKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgYnV0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRhaWwoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWlsKGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZVNsaWNlKGFycmF5LCAxLCBsZW5ndGgpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBgbmAgZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHRha2UuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFrZShhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIGlmICghKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgbiA9IChndWFyZCB8fCBuID09PSB1bmRlZmluZWQpID8gMSA6IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIDAsIG4gPCAwID8gMCA6IG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIHRha2VuIGZyb20gdGhlIGVuZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MV0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byB0YWtlLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFszXVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFrZVJpZ2h0KGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgbiA9IChndWFyZCB8fCBuID09PSB1bmRlZmluZWQpID8gMSA6IHRvSW50ZWdlcihuKTtcbiAgICAgIG4gPSBsZW5ndGggLSBuO1xuICAgICAgcmV0dXJuIGJhc2VTbGljZShhcnJheSwgbiA8IDAgPyAwIDogbiwgbGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGVsZW1lbnRzIHRha2VuIGZyb20gdGhlIGVuZC4gRWxlbWVudHMgYXJlXG4gICAgICogdGFrZW4gdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoXG4gICAgICogdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy50YWtlUmlnaHRXaGlsZSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIGZhbHNlLCB0cnVlKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgYmVnaW5uaW5nLiBFbGVtZW50c1xuICAgICAqIGFyZSB0YWtlbiB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnRha2VXaGlsZSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VXaGlsZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2VXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMykpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB1bmlxdWUgdmFsdWVzLCBpbiBvcmRlciwgZnJvbSBhbGwgZ2l2ZW4gYXJyYXlzIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tYmluZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaW9uKFsyXSwgWzEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICB2YXIgdW5pb24gPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHJldHVybiBiYXNlVW5pcShiYXNlRmxhdHRlbihhcnJheXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaW9uYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgb2YgZWFjaCBgYXJyYXlzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5XG4gICAgICogd2hpY2ggdW5pcXVlbmVzcyBpcyBjb21wdXRlZC4gUmVzdWx0IHZhbHVlcyBhcmUgY2hvc2VuIGZyb20gdGhlIGZpcnN0XG4gICAgICogYXJyYXkgaW4gd2hpY2ggdGhlIHZhbHVlIG9jY3Vycy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6XG4gICAgICogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tYmluZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaW9uQnkoWzIuMV0sIFsxLjIsIDIuM10sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjEsIDEuMl1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udW5pb25CeShbeyAneCc6IDEgfV0sIFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEgfSwgeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICB2YXIgdW5pb25CeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGl0ZXJhdGVlID0gbGFzdChhcnJheXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGl0ZXJhdGVlKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlVW5pcShiYXNlRmxhdHRlbihhcnJheXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheXNgLiBSZXN1bHQgdmFsdWVzIGFyZSBjaG9zZW4gZnJvbVxuICAgICAqIHRoZSBmaXJzdCBhcnJheSBpbiB3aGljaCB0aGUgdmFsdWUgb2NjdXJzLiBUaGUgY29tcGFyYXRvciBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy51bmlvbldpdGgob2JqZWN0cywgb3RoZXJzLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMSB9XVxuICAgICAqL1xuICAgIHZhciB1bmlvbldpdGggPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdChhcnJheXMpO1xuICAgICAgY29tcGFyYXRvciA9IHR5cGVvZiBjb21wYXJhdG9yID09ICdmdW5jdGlvbicgPyBjb21wYXJhdG9yIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFycmF5cywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGR1cGxpY2F0ZS1mcmVlIHZlcnNpb24gb2YgYW4gYXJyYXksIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGluIHdoaWNoIG9ubHkgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgZWFjaCBlbGVtZW50XG4gICAgICogaXMga2VwdC4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXMgZGV0ZXJtaW5lZCBieSB0aGUgb3JkZXIgdGhleSBvY2N1clxuICAgICAqIGluIHRoZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXEoWzIsIDEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmlxKGFycmF5KSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkgPyBiYXNlVW5pcShhcnJheSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBpbiBgYXJyYXlgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2hcbiAgICAgKiB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpcyBkZXRlcm1pbmVkIGJ5IHRoZVxuICAgICAqIG9yZGVyIHRoZXkgb2NjdXIgaW4gdGhlIGFycmF5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDpcbiAgICAgKiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXFCeShbMi4xLCAxLjIsIDIuM10sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjEsIDEuMl1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udW5pcUJ5KFt7ICd4JzogMSB9LCB7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEgfSwgeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmlxQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkgPyBiYXNlVW5pcShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pcWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5YC4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXNcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyIGluIHRoZSBhcnJheS5UaGUgY29tcGFyYXRvciBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy51bmlxV2l0aChvYmplY3RzLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmlxV2l0aChhcnJheSwgY29tcGFyYXRvcikge1xuICAgICAgY29tcGFyYXRvciA9IHR5cGVvZiBjb21wYXJhdG9yID09ICdmdW5jdGlvbicgPyBjb21wYXJhdG9yIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpID8gYmFzZVVuaXEoYXJyYXksIHVuZGVmaW5lZCwgY29tcGFyYXRvcikgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnppcGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhbiBhcnJheSBvZiBncm91cGVkXG4gICAgICogZWxlbWVudHMgYW5kIGNyZWF0ZXMgYW4gYXJyYXkgcmVncm91cGluZyB0aGUgZWxlbWVudHMgdG8gdGhlaXIgcHJlLXppcFxuICAgICAqIGNvbmZpZ3VyYXRpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cyB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHJlZ3JvdXBlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHppcHBlZCA9IF8uemlwKFsnYScsICdiJ10sIFsxLCAyXSwgW3RydWUsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gW1snYScsIDEsIHRydWVdLCBbJ2InLCAyLCBmYWxzZV1dXG4gICAgICpcbiAgICAgKiBfLnVuemlwKHppcHBlZCk7XG4gICAgICogLy8gPT4gW1snYScsICdiJ10sIFsxLCAyXSwgW3RydWUsIGZhbHNlXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bnppcChhcnJheSkge1xuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gMDtcbiAgICAgIGFycmF5ID0gYXJyYXlGaWx0ZXIoYXJyYXksIGZ1bmN0aW9uKGdyb3VwKSB7XG4gICAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChncm91cCkpIHtcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgoZ3JvdXAubGVuZ3RoLCBsZW5ndGgpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBiYXNlVGltZXMobGVuZ3RoLCBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICByZXR1cm4gYXJyYXlNYXAoYXJyYXksIGJhc2VQcm9wZXJ0eShpbmRleCkpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bnppcGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHRvIHNwZWNpZnlcbiAgICAgKiBob3cgcmVncm91cGVkIHZhbHVlcyBzaG91bGQgYmUgY29tYmluZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhlXG4gICAgICogZWxlbWVudHMgb2YgZWFjaCBncm91cDogKC4uLmdyb3VwKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjguMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzIHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiB0byBjb21iaW5lXG4gICAgICogIHJlZ3JvdXBlZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgemlwcGVkID0gXy56aXAoWzEsIDJdLCBbMTAsIDIwXSwgWzEwMCwgMjAwXSk7XG4gICAgICogLy8gPT4gW1sxLCAxMCwgMTAwXSwgWzIsIDIwLCAyMDBdXVxuICAgICAqXG4gICAgICogXy51bnppcFdpdGgoemlwcGVkLCBfLmFkZCk7XG4gICAgICogLy8gPT4gWzMsIDMwLCAzMDBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW56aXBXaXRoKGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgaWYgKCEoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gdW56aXAoYXJyYXkpO1xuICAgICAgaWYgKGl0ZXJhdGVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheU1hcChyZXN1bHQsIGZ1bmN0aW9uKGdyb3VwKSB7XG4gICAgICAgIHJldHVybiBhcHBseShpdGVyYXRlZSwgdW5kZWZpbmVkLCBncm91cCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IGV4Y2x1ZGluZyBhbGwgZ2l2ZW4gdmFsdWVzIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLnB1bGxgLCB0aGlzIG1ldGhvZCByZXR1cm5zIGEgbmV3IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBzZWUgXy5kaWZmZXJlbmNlLCBfLnhvclxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndpdGhvdXQoWzIsIDEsIDIsIDNdLCAxLCAyKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKi9cbiAgICB2YXIgd2l0aG91dCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiBpc0FycmF5TGlrZU9iamVjdChhcnJheSlcbiAgICAgICAgPyBiYXNlRGlmZmVyZW5jZShhcnJheSwgdmFsdWVzKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB1bmlxdWUgdmFsdWVzIHRoYXQgaXMgdGhlXG4gICAgICogW3N5bW1ldHJpYyBkaWZmZXJlbmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TeW1tZXRyaWNfZGlmZmVyZW5jZSlcbiAgICAgKiBvZiB0aGUgZ2l2ZW4gYXJyYXlzLiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlclxuICAgICAqIHRoZXkgb2NjdXIgaW4gdGhlIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQHNlZSBfLmRpZmZlcmVuY2UsIF8ud2l0aG91dFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnhvcihbMiwgMV0sIFsyLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDNdXG4gICAgICovXG4gICAgdmFyIHhvciA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgcmV0dXJuIGJhc2VYb3IoYXJyYXlGaWx0ZXIoYXJyYXlzLCBpc0FycmF5TGlrZU9iamVjdCkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy54b3JgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBlYWNoIGBhcnJheXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnlcbiAgICAgKiB3aGljaCBieSB3aGljaCB0aGV5J3JlIGNvbXBhcmVkLiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpcyBkZXRlcm1pbmVkXG4gICAgICogYnkgdGhlIG9yZGVyIHRoZXkgb2NjdXIgaW4gdGhlIGFycmF5cy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmVcbiAgICAgKiBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnhvckJ5KFsyLjEsIDEuMl0sIFsyLjMsIDMuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsxLjIsIDMuNF1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ueG9yQnkoW3sgJ3gnOiAxIH1dLCBbeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgdmFyIHhvckJ5ID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgaXRlcmF0ZWUgPSBsYXN0KGFycmF5cyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoaXRlcmF0ZWUpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VYb3IoYXJyYXlGaWx0ZXIoYXJyYXlzLCBpc0FycmF5TGlrZU9iamVjdCksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnhvcmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5c2AuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgb3JkZXIgdGhleSBvY2N1ciBpbiB0aGUgYXJyYXlzLiBUaGUgY29tcGFyYXRvciBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy54b3JXaXRoKG9iamVjdHMsIG90aGVycywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAxIH1dXG4gICAgICovXG4gICAgdmFyIHhvcldpdGggPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdChhcnJheXMpO1xuICAgICAgY29tcGFyYXRvciA9IHR5cGVvZiBjb21wYXJhdG9yID09ICdmdW5jdGlvbicgPyBjb21wYXJhdG9yIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGJhc2VYb3IoYXJyYXlGaWx0ZXIoYXJyYXlzLCBpc0FycmF5TGlrZU9iamVjdCksIHVuZGVmaW5lZCwgY29tcGFyYXRvcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMsIHRoZSBmaXJzdCBvZiB3aGljaCBjb250YWlucyB0aGVcbiAgICAgKiBmaXJzdCBlbGVtZW50cyBvZiB0aGUgZ2l2ZW4gYXJyYXlzLCB0aGUgc2Vjb25kIG9mIHdoaWNoIGNvbnRhaW5zIHRoZVxuICAgICAqIHNlY29uZCBlbGVtZW50cyBvZiB0aGUgZ2l2ZW4gYXJyYXlzLCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy56aXAoWydhJywgJ2InXSwgWzEsIDJdLCBbdHJ1ZSwgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBbWydhJywgMSwgdHJ1ZV0sIFsnYicsIDIsIGZhbHNlXV1cbiAgICAgKi9cbiAgICB2YXIgemlwID0gYmFzZVJlc3QodW56aXApO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mcm9tUGFpcnNgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgdHdvIGFycmF5cyxcbiAgICAgKiBvbmUgb2YgcHJvcGVydHkgaWRlbnRpZmllcnMgYW5kIG9uZSBvZiBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjQuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwcm9wcz1bXV0gVGhlIHByb3BlcnR5IGlkZW50aWZpZXJzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXM9W11dIFRoZSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy56aXBPYmplY3QoWydhJywgJ2InXSwgWzEsIDJdKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB6aXBPYmplY3QocHJvcHMsIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGJhc2VaaXBPYmplY3QocHJvcHMgfHwgW10sIHZhbHVlcyB8fCBbXSwgYXNzaWduVmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uemlwT2JqZWN0YCBleGNlcHQgdGhhdCBpdCBzdXBwb3J0cyBwcm9wZXJ0eSBwYXRocy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwcm9wcz1bXV0gVGhlIHByb3BlcnR5IGlkZW50aWZpZXJzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXM9W11dIFRoZSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy56aXBPYmplY3REZWVwKFsnYS5iWzBdLmMnLCAnYS5iWzFdLmQnXSwgWzEsIDJdKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogeyAnYic6IFt7ICdjJzogMSB9LCB7ICdkJzogMiB9XSB9IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB6aXBPYmplY3REZWVwKHByb3BzLCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiBiYXNlWmlwT2JqZWN0KHByb3BzIHx8IFtdLCB2YWx1ZXMgfHwgW10sIGJhc2VTZXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgdG8gc3BlY2lmeVxuICAgICAqIGhvdyBncm91cGVkIHZhbHVlcyBzaG91bGQgYmUgY29tYmluZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhlXG4gICAgICogZWxlbWVudHMgb2YgZWFjaCBncm91cDogKC4uLmdyb3VwKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjguMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmVcbiAgICAgKiAgZ3JvdXBlZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy56aXBXaXRoKFsxLCAyXSwgWzEwLCAyMF0sIFsxMDAsIDIwMF0sIGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBhICsgYiArIGM7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gWzExMSwgMjIyXVxuICAgICAqL1xuICAgIHZhciB6aXBXaXRoID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXlzLmxlbmd0aCxcbiAgICAgICAgICBpdGVyYXRlZSA9IGxlbmd0aCA+IDEgPyBhcnJheXNbbGVuZ3RoIC0gMV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgIGl0ZXJhdGVlID0gdHlwZW9mIGl0ZXJhdGVlID09ICdmdW5jdGlvbicgPyAoYXJyYXlzLnBvcCgpLCBpdGVyYXRlZSkgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gdW56aXBXaXRoKGFycmF5cywgaXRlcmF0ZWUpO1xuICAgIH0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UgdGhhdCB3cmFwcyBgdmFsdWVgIHdpdGggZXhwbGljaXQgbWV0aG9kXG4gICAgICogY2hhaW4gc2VxdWVuY2VzIGVuYWJsZWQuIFRoZSByZXN1bHQgb2Ygc3VjaCBzZXF1ZW5jZXMgbXVzdCBiZSB1bndyYXBwZWRcbiAgICAgKiB3aXRoIGBfI3ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjMuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhZ2UnOiA0MCB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiB2YXIgeW91bmdlc3QgPSBfXG4gICAgICogICAuY2hhaW4odXNlcnMpXG4gICAgICogICAuc29ydEJ5KCdhZ2UnKVxuICAgICAqICAgLm1hcChmdW5jdGlvbihvKSB7XG4gICAgICogICAgIHJldHVybiBvLnVzZXIgKyAnIGlzICcgKyBvLmFnZTtcbiAgICAgKiAgIH0pXG4gICAgICogICAuaGVhZCgpXG4gICAgICogICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiAncGViYmxlcyBpcyAxJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNoYWluKHZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoKHZhbHVlKTtcbiAgICAgIHJlc3VsdC5fX2NoYWluX18gPSB0cnVlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpbnZva2VzIGBpbnRlcmNlcHRvcmAgYW5kIHJldHVybnMgYHZhbHVlYC4gVGhlIGludGVyY2VwdG9yXG4gICAgICogaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDsgKHZhbHVlKS4gVGhlIHB1cnBvc2Ugb2YgdGhpcyBtZXRob2QgaXMgdG9cbiAgICAgKiBcInRhcCBpbnRvXCIgYSBtZXRob2QgY2hhaW4gc2VxdWVuY2UgaW4gb3JkZXIgdG8gbW9kaWZ5IGludGVybWVkaWF0ZSByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb3ZpZGUgdG8gYGludGVyY2VwdG9yYC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpbnRlcmNlcHRvciBUaGUgZnVuY3Rpb24gdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGB2YWx1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDIsIDNdKVxuICAgICAqICAudGFwKGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICogICAgLy8gTXV0YXRlIGlucHV0IGFycmF5LlxuICAgICAqICAgIGFycmF5LnBvcCgpO1xuICAgICAqICB9KVxuICAgICAqICAucmV2ZXJzZSgpXG4gICAgICogIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRhcCh2YWx1ZSwgaW50ZXJjZXB0b3IpIHtcbiAgICAgIGludGVyY2VwdG9yKHZhbHVlKTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnRhcGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgcmVzdWx0IG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICogVGhlIHB1cnBvc2Ugb2YgdGhpcyBtZXRob2QgaXMgdG8gXCJwYXNzIHRocnVcIiB2YWx1ZXMgcmVwbGFjaW5nIGludGVybWVkaWF0ZVxuICAgICAqIHJlc3VsdHMgaW4gYSBtZXRob2QgY2hhaW4gc2VxdWVuY2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvdmlkZSB0byBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGludGVyY2VwdG9yIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKCcgIGFiYyAgJylcbiAgICAgKiAgLmNoYWluKClcbiAgICAgKiAgLnRyaW0oKVxuICAgICAqICAudGhydShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgIHJldHVybiBbdmFsdWVdO1xuICAgICAqICB9KVxuICAgICAqICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbJ2FiYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGhydSh2YWx1ZSwgaW50ZXJjZXB0b3IpIHtcbiAgICAgIHJldHVybiBpbnRlcmNlcHRvcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgdGhlIHdyYXBwZXIgdmVyc2lvbiBvZiBgXy5hdGAuXG4gICAgICpcbiAgICAgKiBAbmFtZSBhdFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMC4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Li4uKHN0cmluZ3xzdHJpbmdbXSl9IFtwYXRoc10gVGhlIHByb3BlcnR5IHBhdGhzIHRvIHBpY2suXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogMyB9IH0sIDRdIH07XG4gICAgICpcbiAgICAgKiBfKG9iamVjdCkuYXQoWydhWzBdLmIuYycsICdhWzFdJ10pLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzMsIDRdXG4gICAgICovXG4gICAgdmFyIHdyYXBwZXJBdCA9IGZsYXRSZXN0KGZ1bmN0aW9uKHBhdGhzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHN0YXJ0ID0gbGVuZ3RoID8gcGF0aHNbMF0gOiAwLFxuICAgICAgICAgIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICBpbnRlcmNlcHRvciA9IGZ1bmN0aW9uKG9iamVjdCkgeyByZXR1cm4gYmFzZUF0KG9iamVjdCwgcGF0aHMpOyB9O1xuXG4gICAgICBpZiAobGVuZ3RoID4gMSB8fCB0aGlzLl9fYWN0aW9uc19fLmxlbmd0aCB8fFxuICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikgfHwgIWlzSW5kZXgoc3RhcnQpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRocnUoaW50ZXJjZXB0b3IpO1xuICAgICAgfVxuICAgICAgdmFsdWUgPSB2YWx1ZS5zbGljZShzdGFydCwgK3N0YXJ0ICsgKGxlbmd0aCA/IDEgOiAwKSk7XG4gICAgICB2YWx1ZS5fX2FjdGlvbnNfXy5wdXNoKHtcbiAgICAgICAgJ2Z1bmMnOiB0aHJ1LFxuICAgICAgICAnYXJncyc6IFtpbnRlcmNlcHRvcl0sXG4gICAgICAgICd0aGlzQXJnJzogdW5kZWZpbmVkXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih2YWx1ZSwgdGhpcy5fX2NoYWluX18pLnRocnUoZnVuY3Rpb24oYXJyYXkpIHtcbiAgICAgICAgaWYgKGxlbmd0aCAmJiAhYXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgYXJyYXkucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2Ugd2l0aCBleHBsaWNpdCBtZXRob2QgY2hhaW4gc2VxdWVuY2VzIGVuYWJsZWQuXG4gICAgICpcbiAgICAgKiBAbmFtZSBjaGFpblxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBBIHNlcXVlbmNlIHdpdGhvdXQgZXhwbGljaXQgY2hhaW5pbmcuXG4gICAgICogXyh1c2VycykuaGVhZCgpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKlxuICAgICAqIC8vIEEgc2VxdWVuY2Ugd2l0aCBleHBsaWNpdCBjaGFpbmluZy5cbiAgICAgKiBfKHVzZXJzKVxuICAgICAqICAgLmNoYWluKClcbiAgICAgKiAgIC5oZWFkKClcbiAgICAgKiAgIC5waWNrKCd1c2VyJylcbiAgICAgKiAgIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnYmFybmV5JyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlckNoYWluKCkge1xuICAgICAgcmV0dXJuIGNoYWluKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVzIHRoZSBjaGFpbiBzZXF1ZW5jZSBhbmQgcmV0dXJucyB0aGUgd3JhcHBlZCByZXN1bHQuXG4gICAgICpcbiAgICAgKiBAbmFtZSBjb21taXRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjIuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDJdO1xuICAgICAqIHZhciB3cmFwcGVkID0gXyhhcnJheSkucHVzaCgzKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIHdyYXBwZWQgPSB3cmFwcGVkLmNvbW1pdCgpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIHdyYXBwZWQubGFzdCgpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyQ29tbWl0KCkge1xuICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHRoaXMudmFsdWUoKSwgdGhpcy5fX2NoYWluX18pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG5leHQgdmFsdWUgb24gYSB3cmFwcGVkIG9iamVjdCBmb2xsb3dpbmcgdGhlXG4gICAgICogW2l0ZXJhdG9yIHByb3RvY29sXShodHRwczovL21kbi5pby9pdGVyYXRpb25fcHJvdG9jb2xzI2l0ZXJhdG9yKS5cbiAgICAgKlxuICAgICAqIEBuYW1lIG5leHRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXh0IGl0ZXJhdG9yIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDJdKTtcbiAgICAgKlxuICAgICAqIHdyYXBwZWQubmV4dCgpO1xuICAgICAqIC8vID0+IHsgJ2RvbmUnOiBmYWxzZSwgJ3ZhbHVlJzogMSB9XG4gICAgICpcbiAgICAgKiB3cmFwcGVkLm5leHQoKTtcbiAgICAgKiAvLyA9PiB7ICdkb25lJzogZmFsc2UsICd2YWx1ZSc6IDIgfVxuICAgICAqXG4gICAgICogd3JhcHBlZC5uZXh0KCk7XG4gICAgICogLy8gPT4geyAnZG9uZSc6IHRydWUsICd2YWx1ZSc6IHVuZGVmaW5lZCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlck5leHQoKSB7XG4gICAgICBpZiAodGhpcy5fX3ZhbHVlc19fID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fX3ZhbHVlc19fID0gdG9BcnJheSh0aGlzLnZhbHVlKCkpO1xuICAgICAgfVxuICAgICAgdmFyIGRvbmUgPSB0aGlzLl9faW5kZXhfXyA+PSB0aGlzLl9fdmFsdWVzX18ubGVuZ3RoLFxuICAgICAgICAgIHZhbHVlID0gZG9uZSA/IHVuZGVmaW5lZCA6IHRoaXMuX192YWx1ZXNfX1t0aGlzLl9faW5kZXhfXysrXTtcblxuICAgICAgcmV0dXJuIHsgJ2RvbmUnOiBkb25lLCAndmFsdWUnOiB2YWx1ZSB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMgdGhlIHdyYXBwZXIgdG8gYmUgaXRlcmFibGUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBTeW1ib2wuaXRlcmF0b3JcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyXSk7XG4gICAgICpcbiAgICAgKiB3cmFwcGVkW1N5bWJvbC5pdGVyYXRvcl0oKSA9PT0gd3JhcHBlZDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBBcnJheS5mcm9tKHdyYXBwZWQpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJUb0l0ZXJhdG9yKCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBjaGFpbiBzZXF1ZW5jZSBwbGFudGluZyBgdmFsdWVgIGFzIHRoZSB3cmFwcGVkIHZhbHVlLlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhbnRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjIuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwbGFudC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDJdKS5tYXAoc3F1YXJlKTtcbiAgICAgKiB2YXIgb3RoZXIgPSB3cmFwcGVkLnBsYW50KFszLCA0XSk7XG4gICAgICpcbiAgICAgKiBvdGhlci52YWx1ZSgpO1xuICAgICAqIC8vID0+IFs5LCAxNl1cbiAgICAgKlxuICAgICAqIHdyYXBwZWQudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMSwgNF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyUGxhbnQodmFsdWUpIHtcbiAgICAgIHZhciByZXN1bHQsXG4gICAgICAgICAgcGFyZW50ID0gdGhpcztcblxuICAgICAgd2hpbGUgKHBhcmVudCBpbnN0YW5jZW9mIGJhc2VMb2Rhc2gpIHtcbiAgICAgICAgdmFyIGNsb25lID0gd3JhcHBlckNsb25lKHBhcmVudCk7XG4gICAgICAgIGNsb25lLl9faW5kZXhfXyA9IDA7XG4gICAgICAgIGNsb25lLl9fdmFsdWVzX18gPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICBwcmV2aW91cy5fX3dyYXBwZWRfXyA9IGNsb25lO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc3VsdCA9IGNsb25lO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmV2aW91cyA9IGNsb25lO1xuICAgICAgICBwYXJlbnQgPSBwYXJlbnQuX193cmFwcGVkX187XG4gICAgICB9XG4gICAgICBwcmV2aW91cy5fX3dyYXBwZWRfXyA9IHZhbHVlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyB0aGUgd3JhcHBlciB2ZXJzaW9uIG9mIGBfLnJldmVyc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgdGhlIHdyYXBwZWQgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAbmFtZSByZXZlcnNlXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8oYXJyYXkpLnJldmVyc2UoKS52YWx1ZSgpXG4gICAgICogLy8gPT4gWzMsIDIsIDFdXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzMsIDIsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlclJldmVyc2UoKSB7XG4gICAgICB2YXIgdmFsdWUgPSB0aGlzLl9fd3JhcHBlZF9fO1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpIHtcbiAgICAgICAgdmFyIHdyYXBwZWQgPSB2YWx1ZTtcbiAgICAgICAgaWYgKHRoaXMuX19hY3Rpb25zX18ubGVuZ3RoKSB7XG4gICAgICAgICAgd3JhcHBlZCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICB3cmFwcGVkID0gd3JhcHBlZC5yZXZlcnNlKCk7XG4gICAgICAgIHdyYXBwZWQuX19hY3Rpb25zX18ucHVzaCh7XG4gICAgICAgICAgJ2Z1bmMnOiB0aHJ1LFxuICAgICAgICAgICdhcmdzJzogW3JldmVyc2VdLFxuICAgICAgICAgICd0aGlzQXJnJzogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIod3JhcHBlZCwgdGhpcy5fX2NoYWluX18pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMudGhydShyZXZlcnNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyB0aGUgY2hhaW4gc2VxdWVuY2UgdG8gcmVzb2x2ZSB0aGUgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqXG4gICAgICogQG5hbWUgdmFsdWVcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBhbGlhcyB0b0pTT04sIHZhbHVlT2ZcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlclZhbHVlKCkge1xuICAgICAgcmV0dXJuIGJhc2VXcmFwcGVyVmFsdWUodGhpcy5fX3dyYXBwZWRfXywgdGhpcy5fX2FjdGlvbnNfXyk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJ1IGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIG9mXG4gICAgICogZWFjaCBrZXkgaXMgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUga2V5IHdhcyByZXR1cm5lZCBieSBgaXRlcmF0ZWVgLiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNvdW50QnkoWzYuMSwgNC4yLCA2LjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiB7ICc0JzogMSwgJzYnOiAyIH1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uY291bnRCeShbJ29uZScsICd0d28nLCAndGhyZWUnXSwgJ2xlbmd0aCcpO1xuICAgICAqIC8vID0+IHsgJzMnOiAyLCAnNSc6IDEgfVxuICAgICAqL1xuICAgIHZhciBjb3VudEJ5ID0gY3JlYXRlQWdncmVnYXRvcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdCwga2V5KSkge1xuICAgICAgICArK3Jlc3VsdFtrZXldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCAxKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgKiphbGwqKiBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmAuXG4gICAgICogSXRlcmF0aW9uIGlzIHN0b3BwZWQgb25jZSBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCByZXR1cm5zIGB0cnVlYCBmb3JcbiAgICAgKiBbZW1wdHkgY29sbGVjdGlvbnNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0VtcHR5X3NldCkgYmVjYXVzZVxuICAgICAqIFtldmVyeXRoaW5nIGlzIHRydWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1ZhY3VvdXNfdHJ1dGgpIG9mXG4gICAgICogZWxlbWVudHMgb2YgZW1wdHkgY29sbGVjdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmV2ZXJ5KFt0cnVlLCAxLCBudWxsLCAneWVzJ10sIEJvb2xlYW4pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmV2ZXJ5KHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZXZlcnkodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmV2ZXJ5KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBldmVyeShjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUV2ZXJ5IDogYmFzZUV2ZXJ5O1xuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZ3VhcmQpKSB7XG4gICAgICAgIHByZWRpY2F0ZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLCByZXR1cm5pbmcgYW4gYXJyYXkgb2YgYWxsIGVsZW1lbnRzXG4gICAgICogYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5yZW1vdmVgLCB0aGlzIG1ldGhvZCByZXR1cm5zIGEgbmV3IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICAgICAqIEBzZWUgXy5yZWplY3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maWx0ZXIodXNlcnMsIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maWx0ZXIodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maWx0ZXIodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBDb21iaW5pbmcgc2V2ZXJhbCBwcmVkaWNhdGVzIHVzaW5nIGBfLm92ZXJFdmVyeWAgb3IgYF8ub3ZlclNvbWVgLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLm92ZXJTb21lKFt7ICdhZ2UnOiAzNiB9LCBbJ2FnZScsIDQwXV0pKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAnYmFybmV5J11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaWx0ZXIoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUZpbHRlciA6IGJhc2VGaWx0ZXI7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCwgcmV0dXJuaW5nIHRoZSBmaXJzdCBlbGVtZW50XG4gICAgICogYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmQodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlIDwgNDA7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kKHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3QgZm9yICdwZWJibGVzJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2ZyZWQnXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmQodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3QgZm9yICdiYXJuZXknXG4gICAgICovXG4gICAgdmFyIGZpbmQgPSBjcmVhdGVGaW5kKGZpbmRJbmRleCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD1jb2xsZWN0aW9uLmxlbmd0aC0xXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5maW5kTGFzdChbMSwgMiwgMywgNF0sIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAxO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICB2YXIgZmluZExhc3QgPSBjcmVhdGVGaW5kKGZpbmRMYXN0SW5kZXgpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZsYXR0ZW5lZCBhcnJheSBvZiB2YWx1ZXMgYnkgcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gXG4gICAgICogdGhydSBgaXRlcmF0ZWVgIGFuZCBmbGF0dGVuaW5nIHRoZSBtYXBwZWQgcmVzdWx0cy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkdXBsaWNhdGUobikge1xuICAgICAqICAgcmV0dXJuIFtuLCBuXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXAoWzEsIDJdLCBkdXBsaWNhdGUpO1xuICAgICAqIC8vID0+IFsxLCAxLCAyLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXRNYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBiYXNlRmxhdHRlbihtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZsYXRNYXBgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGZsYXR0ZW5zIHRoZVxuICAgICAqIG1hcHBlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNy4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkdXBsaWNhdGUobikge1xuICAgICAqICAgcmV0dXJuIFtbW24sIG5dXV07XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5mbGF0TWFwRGVlcChbMSwgMl0sIGR1cGxpY2F0ZSk7XG4gICAgICogLy8gPT4gWzEsIDEsIDIsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdE1hcERlZXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBiYXNlRmxhdHRlbihtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpLCBJTkZJTklUWSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mbGF0TWFwYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBmbGF0dGVucyB0aGVcbiAgICAgKiBtYXBwZWQgcmVzdWx0cyB1cCB0byBgZGVwdGhgIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNy4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtkZXB0aD0xXSBUaGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGguXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkdXBsaWNhdGUobikge1xuICAgICAqICAgcmV0dXJuIFtbW24sIG5dXV07XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5mbGF0TWFwRGVwdGgoWzEsIDJdLCBkdXBsaWNhdGUsIDIpO1xuICAgICAqIC8vID0+IFtbMSwgMV0sIFsyLCAyXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0TWFwRGVwdGgoY29sbGVjdGlvbiwgaXRlcmF0ZWUsIGRlcHRoKSB7XG4gICAgICBkZXB0aCA9IGRlcHRoID09PSB1bmRlZmluZWQgPyAxIDogdG9JbnRlZ2VyKGRlcHRoKTtcbiAgICAgIHJldHVybiBiYXNlRmxhdHRlbihtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpLCBkZXB0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmAgYW5kIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgZWFjaCBlbGVtZW50LlxuICAgICAqIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICogSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIEFzIHdpdGggb3RoZXIgXCJDb2xsZWN0aW9uc1wiIG1ldGhvZHMsIG9iamVjdHMgd2l0aCBhIFwibGVuZ3RoXCJcbiAgICAgKiBwcm9wZXJ0eSBhcmUgaXRlcmF0ZWQgbGlrZSBhcnJheXMuIFRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgdXNlIGBfLmZvckluYFxuICAgICAqIG9yIGBfLmZvck93bmAgZm9yIG9iamVjdCBpdGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAYWxpYXMgZWFjaFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqIEBzZWUgXy5mb3JFYWNoUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mb3JFYWNoKFsxLCAyXSwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKHZhbHVlKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzIGAxYCB0aGVuIGAyYC5cbiAgICAgKlxuICAgICAqIF8uZm9yRWFjaCh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYScgdGhlbiAnYicgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yRWFjaChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlFYWNoIDogYmFzZUVhY2g7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9yRWFjaGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAYWxpYXMgZWFjaFJpZ2h0XG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQHNlZSBfLmZvckVhY2hcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mb3JFYWNoUmlnaHQoWzEsIDJdLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgY29uc29sZS5sb2codmFsdWUpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgYDJgIHRoZW4gYDFgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZvckVhY2hSaWdodChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlFYWNoUmlnaHQgOiBiYXNlRWFjaFJpZ2h0O1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiBrZXlzIGdlbmVyYXRlZCBmcm9tIHRoZSByZXN1bHRzIG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIHRocnUgYGl0ZXJhdGVlYC4gVGhlIG9yZGVyIG9mIGdyb3VwZWQgdmFsdWVzXG4gICAgICogaXMgZGV0ZXJtaW5lZCBieSB0aGUgb3JkZXIgdGhleSBvY2N1ciBpbiBgY29sbGVjdGlvbmAuIFRoZSBjb3JyZXNwb25kaW5nXG4gICAgICogdmFsdWUgb2YgZWFjaCBrZXkgaXMgYW4gYXJyYXkgb2YgZWxlbWVudHMgcmVzcG9uc2libGUgZm9yIGdlbmVyYXRpbmcgdGhlXG4gICAgICoga2V5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIGtleXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29tcG9zZWQgYWdncmVnYXRlIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ncm91cEJ5KFs2LjEsIDQuMiwgNi4zXSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4geyAnNCc6IFs0LjJdLCAnNic6IFs2LjEsIDYuM10gfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ncm91cEJ5KFsnb25lJywgJ3R3bycsICd0aHJlZSddLCAnbGVuZ3RoJyk7XG4gICAgICogLy8gPT4geyAnMyc6IFsnb25lJywgJ3R3byddLCAnNSc6IFsndGhyZWUnXSB9XG4gICAgICovXG4gICAgdmFyIGdyb3VwQnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCBrZXkpKSB7XG4gICAgICAgIHJlc3VsdFtrZXldLnB1c2godmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCBbdmFsdWVdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGluIGBjb2xsZWN0aW9uYC4gSWYgYGNvbGxlY3Rpb25gIGlzIGEgc3RyaW5nLCBpdCdzXG4gICAgICogY2hlY2tlZCBmb3IgYSBzdWJzdHJpbmcgb2YgYHZhbHVlYCwgb3RoZXJ3aXNlXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBpcyB1c2VkIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gSWYgYGZyb21JbmRleGAgaXMgbmVnYXRpdmUsIGl0J3MgdXNlZCBhc1xuICAgICAqIHRoZSBvZmZzZXQgZnJvbSB0aGUgZW5kIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKFsxLCAyLCAzXSwgMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pbmNsdWRlcyhbMSwgMiwgM10sIDEsIDIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKHsgJ2EnOiAxLCAnYic6IDIgfSwgMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pbmNsdWRlcygnYWJjZCcsICdiYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmNsdWRlcyhjb2xsZWN0aW9uLCB2YWx1ZSwgZnJvbUluZGV4LCBndWFyZCkge1xuICAgICAgY29sbGVjdGlvbiA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gY29sbGVjdGlvbiA6IHZhbHVlcyhjb2xsZWN0aW9uKTtcbiAgICAgIGZyb21JbmRleCA9IChmcm9tSW5kZXggJiYgIWd1YXJkKSA/IHRvSW50ZWdlcihmcm9tSW5kZXgpIDogMDtcblxuICAgICAgdmFyIGxlbmd0aCA9IGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgICAgaWYgKGZyb21JbmRleCA8IDApIHtcbiAgICAgICAgZnJvbUluZGV4ID0gbmF0aXZlTWF4KGxlbmd0aCArIGZyb21JbmRleCwgMCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNTdHJpbmcoY29sbGVjdGlvbilcbiAgICAgICAgPyAoZnJvbUluZGV4IDw9IGxlbmd0aCAmJiBjb2xsZWN0aW9uLmluZGV4T2YodmFsdWUsIGZyb21JbmRleCkgPiAtMSlcbiAgICAgICAgOiAoISFsZW5ndGggJiYgYmFzZUluZGV4T2YoY29sbGVjdGlvbiwgdmFsdWUsIGZyb21JbmRleCkgPiAtMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gLCByZXR1cm5pbmdcbiAgICAgKiBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZiBlYWNoIGludm9rZWQgbWV0aG9kLiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICAgKiBhcmUgcHJvdmlkZWQgdG8gZWFjaCBpbnZva2VkIG1ldGhvZC4gSWYgYHBhdGhgIGlzIGEgZnVuY3Rpb24sIGl0J3MgaW52b2tlZFxuICAgICAqIGZvciwgYW5kIGB0aGlzYCBib3VuZCB0bywgZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7QXJyYXl8RnVuY3Rpb258c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBtZXRob2QgdG8gaW52b2tlIG9yXG4gICAgICogIHRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgZWFjaCBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHJlc3VsdHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW52b2tlTWFwKFtbNSwgMSwgN10sIFszLCAyLCAxXV0sICdzb3J0Jyk7XG4gICAgICogLy8gPT4gW1sxLCA1LCA3XSwgWzEsIDIsIDNdXVxuICAgICAqXG4gICAgICogXy5pbnZva2VNYXAoWzEyMywgNDU2XSwgU3RyaW5nLnByb3RvdHlwZS5zcGxpdCwgJycpO1xuICAgICAqIC8vID0+IFtbJzEnLCAnMicsICczJ10sIFsnNCcsICc1JywgJzYnXV1cbiAgICAgKi9cbiAgICB2YXIgaW52b2tlTWFwID0gYmFzZVJlc3QoZnVuY3Rpb24oY29sbGVjdGlvbiwgcGF0aCwgYXJncykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaXNGdW5jID0gdHlwZW9mIHBhdGggPT0gJ2Z1bmN0aW9uJyxcbiAgICAgICAgICByZXN1bHQgPSBpc0FycmF5TGlrZShjb2xsZWN0aW9uKSA/IEFycmF5KGNvbGxlY3Rpb24ubGVuZ3RoKSA6IFtdO1xuXG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICByZXN1bHRbKytpbmRleF0gPSBpc0Z1bmMgPyBhcHBseShwYXRoLCB2YWx1ZSwgYXJncykgOiBiYXNlSW52b2tlKHZhbHVlLCBwYXRoLCBhcmdzKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgY29sbGVjdGlvbmAgdGhydSBgaXRlcmF0ZWVgLiBUaGUgY29ycmVzcG9uZGluZyB2YWx1ZSBvZlxuICAgICAqIGVhY2gga2V5IGlzIHRoZSBsYXN0IGVsZW1lbnQgcmVzcG9uc2libGUgZm9yIGdlbmVyYXRpbmcgdGhlIGtleS4gVGhlXG4gICAgICogaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIGtleXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29tcG9zZWQgYWdncmVnYXRlIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW1xuICAgICAqICAgeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sXG4gICAgICogICB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ua2V5QnkoYXJyYXksIGZ1bmN0aW9uKG8pIHtcbiAgICAgKiAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKG8uY29kZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnYSc6IHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LCAnZCc6IHsgJ2Rpcic6ICdyaWdodCcsICdjb2RlJzogMTAwIH0gfVxuICAgICAqXG4gICAgICogXy5rZXlCeShhcnJheSwgJ2RpcicpO1xuICAgICAqIC8vID0+IHsgJ2xlZnQnOiB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSwgJ3JpZ2h0JzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICovXG4gICAgdmFyIGtleUJ5ID0gY3JlYXRlQWdncmVnYXRvcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIGJhc2VBc3NpZ25WYWx1ZShyZXN1bHQsIGtleSwgdmFsdWUpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgYnkgcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gIHRocnVcbiAgICAgKiBgaXRlcmF0ZWVgLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBNYW55IGxvZGFzaCBtZXRob2RzIGFyZSBndWFyZGVkIHRvIHdvcmsgYXMgaXRlcmF0ZWVzIGZvciBtZXRob2RzIGxpa2VcbiAgICAgKiBgXy5ldmVyeWAsIGBfLmZpbHRlcmAsIGBfLm1hcGAsIGBfLm1hcFZhbHVlc2AsIGBfLnJlamVjdGAsIGFuZCBgXy5zb21lYC5cbiAgICAgKlxuICAgICAqIFRoZSBndWFyZGVkIG1ldGhvZHMgYXJlOlxuICAgICAqIGBhcnlgLCBgY2h1bmtgLCBgY3VycnlgLCBgY3VycnlSaWdodGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBldmVyeWAsXG4gICAgICogYGZpbGxgLCBgaW52ZXJ0YCwgYHBhcnNlSW50YCwgYHJhbmRvbWAsIGByYW5nZWAsIGByYW5nZVJpZ2h0YCwgYHJlcGVhdGAsXG4gICAgICogYHNhbXBsZVNpemVgLCBgc2xpY2VgLCBgc29tZWAsIGBzb3J0QnlgLCBgc3BsaXRgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLFxuICAgICAqIGB0ZW1wbGF0ZWAsIGB0cmltYCwgYHRyaW1FbmRgLCBgdHJpbVN0YXJ0YCwgYW5kIGB3b3Jkc2BcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLm1hcChbNCwgOF0sIHNxdWFyZSk7XG4gICAgICogLy8gPT4gWzE2LCA2NF1cbiAgICAgKlxuICAgICAqIF8ubWFwKHsgJ2EnOiA0LCAnYic6IDggfSwgc3F1YXJlKTtcbiAgICAgKiAvLyA9PiBbMTYsIDY0XSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXAodXNlcnMsICd1c2VyJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheU1hcCA6IGJhc2VNYXA7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydEJ5YCBleGNlcHQgdGhhdCBpdCBhbGxvd3Mgc3BlY2lmeWluZyB0aGUgc29ydFxuICAgICAqIG9yZGVycyBvZiB0aGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuIElmIGBvcmRlcnNgIGlzIHVuc3BlY2lmaWVkLCBhbGwgdmFsdWVzXG4gICAgICogYXJlIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXIuIE90aGVyd2lzZSwgc3BlY2lmeSBhbiBvcmRlciBvZiBcImRlc2NcIiBmb3JcbiAgICAgKiBkZXNjZW5kaW5nIG9yIFwiYXNjXCIgZm9yIGFzY2VuZGluZyBzb3J0IG9yZGVyIG9mIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtBcnJheVtdfEZ1bmN0aW9uW118T2JqZWN0W118c3RyaW5nW119IFtpdGVyYXRlZXM9W18uaWRlbnRpdHldXVxuICAgICAqICBUaGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gW29yZGVyc10gVGhlIHNvcnQgb3JkZXJzIG9mIGBpdGVyYXRlZXNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLnJlZHVjZWAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgc29ydGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0OCB9LFxuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzQgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIFNvcnQgYnkgYHVzZXJgIGluIGFzY2VuZGluZyBvcmRlciBhbmQgYnkgYGFnZWAgaW4gZGVzY2VuZGluZyBvcmRlci5cbiAgICAgKiBfLm9yZGVyQnkodXNlcnMsIFsndXNlcicsICdhZ2UnXSwgWydhc2MnLCAnZGVzYyddKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydiYXJuZXknLCAzNl0sIFsnYmFybmV5JywgMzRdLCBbJ2ZyZWQnLCA0OF0sIFsnZnJlZCcsIDQwXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBvcmRlckJ5KGNvbGxlY3Rpb24sIGl0ZXJhdGVlcywgb3JkZXJzLCBndWFyZCkge1xuICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBpZiAoIWlzQXJyYXkoaXRlcmF0ZWVzKSkge1xuICAgICAgICBpdGVyYXRlZXMgPSBpdGVyYXRlZXMgPT0gbnVsbCA/IFtdIDogW2l0ZXJhdGVlc107XG4gICAgICB9XG4gICAgICBvcmRlcnMgPSBndWFyZCA/IHVuZGVmaW5lZCA6IG9yZGVycztcbiAgICAgIGlmICghaXNBcnJheShvcmRlcnMpKSB7XG4gICAgICAgIG9yZGVycyA9IG9yZGVycyA9PSBudWxsID8gW10gOiBbb3JkZXJzXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlT3JkZXJCeShjb2xsZWN0aW9uLCBpdGVyYXRlZXMsIG9yZGVycyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cyBzcGxpdCBpbnRvIHR3byBncm91cHMsIHRoZSBmaXJzdCBvZiB3aGljaFxuICAgICAqIGNvbnRhaW5zIGVsZW1lbnRzIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciwgdGhlIHNlY29uZCBvZiB3aGljaFxuICAgICAqIGNvbnRhaW5zIGVsZW1lbnRzIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5IGZvci4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWdlJzogMzYsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEsICAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnBhcnRpdGlvbih1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2ZyZWQnXSwgWydiYXJuZXknLCAncGViYmxlcyddXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnBhcnRpdGlvbih1c2VycywgeyAnYWdlJzogMSwgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ3BlYmJsZXMnXSwgWydiYXJuZXknLCAnZnJlZCddXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snYmFybmV5JywgJ3BlYmJsZXMnXSwgWydmcmVkJ11dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnBhcnRpdGlvbih1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2ZyZWQnXSwgWydiYXJuZXknLCAncGViYmxlcyddXVxuICAgICAqL1xuICAgIHZhciBwYXJ0aXRpb24gPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0W2tleSA/IDAgOiAxXS5wdXNoKHZhbHVlKTtcbiAgICB9LCBmdW5jdGlvbigpIHsgcmV0dXJuIFtbXSwgW11dOyB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlZHVjZXMgYGNvbGxlY3Rpb25gIHRvIGEgdmFsdWUgd2hpY2ggaXMgdGhlIGFjY3VtdWxhdGVkIHJlc3VsdCBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYCB0aHJ1IGBpdGVyYXRlZWAsIHdoZXJlIGVhY2ggc3VjY2Vzc2l2ZVxuICAgICAqIGludm9jYXRpb24gaXMgc3VwcGxpZWQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcHJldmlvdXMuIElmIGBhY2N1bXVsYXRvcmBcbiAgICAgKiBpcyBub3QgZ2l2ZW4sIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCBpcyB1c2VkIGFzIHRoZSBpbml0aWFsXG4gICAgICogdmFsdWUuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6XG4gICAgICogKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIE1hbnkgbG9kYXNoIG1ldGhvZHMgYXJlIGd1YXJkZWQgdG8gd29yayBhcyBpdGVyYXRlZXMgZm9yIG1ldGhvZHMgbGlrZVxuICAgICAqIGBfLnJlZHVjZWAsIGBfLnJlZHVjZVJpZ2h0YCwgYW5kIGBfLnRyYW5zZm9ybWAuXG4gICAgICpcbiAgICAgKiBUaGUgZ3VhcmRlZCBtZXRob2RzIGFyZTpcbiAgICAgKiBgYXNzaWduYCwgYGRlZmF1bHRzYCwgYGRlZmF1bHRzRGVlcGAsIGBpbmNsdWRlc2AsIGBtZXJnZWAsIGBvcmRlckJ5YCxcbiAgICAgKiBhbmQgYHNvcnRCeWBcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQHNlZSBfLnJlZHVjZVJpZ2h0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlKFsxLCAyXSwgZnVuY3Rpb24oc3VtLCBuKSB7XG4gICAgICogICByZXR1cm4gc3VtICsgbjtcbiAgICAgKiB9LCAwKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnJlZHVjZSh7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfSwgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICogICAocmVzdWx0W3ZhbHVlXSB8fCAocmVzdWx0W3ZhbHVlXSA9IFtdKSkucHVzaChrZXkpO1xuICAgICAqICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgKiB9LCB7fSk7XG4gICAgICogLy8gPT4geyAnMSc6IFsnYScsICdjJ10sICcyJzogWydiJ10gfSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlZHVjZShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5UmVkdWNlIDogYmFzZVJlZHVjZSxcbiAgICAgICAgICBpbml0QWNjdW0gPSBhcmd1bWVudHMubGVuZ3RoIDwgMztcblxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDQpLCBhY2N1bXVsYXRvciwgaW5pdEFjY3VtLCBiYXNlRWFjaCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5yZWR1Y2VgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8ucmVkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFtbMCwgMV0sIFsyLCAzXSwgWzQsIDVdXTtcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlUmlnaHQoYXJyYXksIGZ1bmN0aW9uKGZsYXR0ZW5lZCwgb3RoZXIpIHtcbiAgICAgKiAgIHJldHVybiBmbGF0dGVuZWQuY29uY2F0KG90aGVyKTtcbiAgICAgKiB9LCBbXSk7XG4gICAgICogLy8gPT4gWzQsIDUsIDIsIDMsIDAsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVkdWNlUmlnaHQoY29sbGVjdGlvbiwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheVJlZHVjZVJpZ2h0IDogYmFzZVJlZHVjZSxcbiAgICAgICAgICBpbml0QWNjdW0gPSBhcmd1bWVudHMubGVuZ3RoIDwgMztcblxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDQpLCBhY2N1bXVsYXRvciwgaW5pdEFjY3VtLCBiYXNlRWFjaFJpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8uZmlsdGVyYDsgdGhpcyBtZXRob2QgcmV0dXJucyB0aGUgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gXG4gICAgICogdGhhdCBgcHJlZGljYXRlYCBkb2VzICoqbm90KiogcmV0dXJuIHRydXRoeSBmb3IuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAgICogQHNlZSBfLmZpbHRlclxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnJlamVjdCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgeyAnYWdlJzogNDAsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWplY3QoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUZpbHRlciA6IGJhc2VGaWx0ZXI7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBuZWdhdGUoZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYSByYW5kb20gZWxlbWVudCBmcm9tIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2FtcGxlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zYW1wbGUoWzEsIDIsIDMsIDRdKTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FtcGxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5U2FtcGxlIDogYmFzZVNhbXBsZTtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYG5gIHJhbmRvbSBlbGVtZW50cyBhdCB1bmlxdWUga2V5cyBmcm9tIGBjb2xsZWN0aW9uYCB1cCB0byB0aGVcbiAgICAgKiBzaXplIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZG9tIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNhbXBsZVNpemUoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMywgMV1cbiAgICAgKlxuICAgICAqIF8uc2FtcGxlU2l6ZShbMSwgMiwgM10sIDQpO1xuICAgICAqIC8vID0+IFsyLCAzLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNhbXBsZVNpemUoY29sbGVjdGlvbiwgbiwgZ3VhcmQpIHtcbiAgICAgIGlmICgoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBuLCBndWFyZCkgOiBuID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgIG4gPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIH1cbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5U2FtcGxlU2l6ZSA6IGJhc2VTYW1wbGVTaXplO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBzaHVmZmxlZCB2YWx1ZXMsIHVzaW5nIGEgdmVyc2lvbiBvZiB0aGVcbiAgICAgKiBbRmlzaGVyLVlhdGVzIHNodWZmbGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlci1ZYXRlc19zaHVmZmxlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2h1ZmZsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzaHVmZmxlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zaHVmZmxlKFsxLCAyLCAzLCA0XSk7XG4gICAgICogLy8gPT4gWzQsIDEsIDMsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2h1ZmZsZShjb2xsZWN0aW9uKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheVNodWZmbGUgOiBiYXNlU2h1ZmZsZTtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNpemUgb2YgYGNvbGxlY3Rpb25gIGJ5IHJldHVybmluZyBpdHMgbGVuZ3RoIGZvciBhcnJheS1saWtlXG4gICAgICogdmFsdWVzIG9yIHRoZSBudW1iZXIgb2Ygb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgZm9yIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbGxlY3Rpb24gc2l6ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zaXplKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5zaXplKHsgJ2EnOiAxLCAnYic6IDIgfSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5zaXplKCdwZWJibGVzJyk7XG4gICAgICogLy8gPT4gN1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNpemUoY29sbGVjdGlvbikge1xuICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICAgIGlmIChpc0FycmF5TGlrZShjb2xsZWN0aW9uKSkge1xuICAgICAgICByZXR1cm4gaXNTdHJpbmcoY29sbGVjdGlvbikgPyBzdHJpbmdTaXplKGNvbGxlY3Rpb24pIDogY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgICB9XG4gICAgICB2YXIgdGFnID0gZ2V0VGFnKGNvbGxlY3Rpb24pO1xuICAgICAgaWYgKHRhZyA9PSBtYXBUYWcgfHwgdGFnID09IHNldFRhZykge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbi5zaXplO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VLZXlzKGNvbGxlY3Rpb24pLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yICoqYW55KiogZWxlbWVudCBvZiBgY29sbGVjdGlvbmAuXG4gICAgICogSXRlcmF0aW9uIGlzIHN0b3BwZWQgb25jZSBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeS4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvbWUoW251bGwsIDAsICd5ZXMnLCBmYWxzZV0sIEJvb2xlYW4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvbWUodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zb21lKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zb21lKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvbWUoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBndWFyZCkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlTb21lIDogYmFzZVNvbWU7XG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBndWFyZCkpIHtcbiAgICAgICAgcHJlZGljYXRlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cywgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlciBieSB0aGUgcmVzdWx0cyBvZlxuICAgICAqIHJ1bm5pbmcgZWFjaCBlbGVtZW50IGluIGEgY29sbGVjdGlvbiB0aHJ1IGVhY2ggaXRlcmF0ZWUuIFRoaXMgbWV0aG9kXG4gICAgICogcGVyZm9ybXMgYSBzdGFibGUgc29ydCwgdGhhdCBpcywgaXQgcHJlc2VydmVzIHRoZSBvcmlnaW5hbCBzb3J0IG9yZGVyIG9mXG4gICAgICogZXF1YWwgZWxlbWVudHMuIFRoZSBpdGVyYXRlZXMgYXJlIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2l0ZXJhdGVlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQ4IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogMzAgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM0IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5zb3J0QnkodXNlcnMsIFtmdW5jdGlvbihvKSB7IHJldHVybiBvLnVzZXI7IH1dKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydiYXJuZXknLCAzNl0sIFsnYmFybmV5JywgMzRdLCBbJ2ZyZWQnLCA0OF0sIFsnZnJlZCcsIDMwXV1cbiAgICAgKlxuICAgICAqIF8uc29ydEJ5KHVzZXJzLCBbJ3VzZXInLCAnYWdlJ10pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM0XSwgWydiYXJuZXknLCAzNl0sIFsnZnJlZCcsIDMwXSwgWydmcmVkJywgNDhdXVxuICAgICAqL1xuICAgIHZhciBzb3J0QnkgPSBiYXNlUmVzdChmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZXMpIHtcbiAgICAgIGlmIChjb2xsZWN0aW9uID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IGl0ZXJhdGVlcy5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoID4gMSAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBpdGVyYXRlZXNbMF0sIGl0ZXJhdGVlc1sxXSkpIHtcbiAgICAgICAgaXRlcmF0ZWVzID0gW107XG4gICAgICB9IGVsc2UgaWYgKGxlbmd0aCA+IDIgJiYgaXNJdGVyYXRlZUNhbGwoaXRlcmF0ZWVzWzBdLCBpdGVyYXRlZXNbMV0sIGl0ZXJhdGVlc1syXSkpIHtcbiAgICAgICAgaXRlcmF0ZWVzID0gW2l0ZXJhdGVlc1swXV07XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZU9yZGVyQnkoY29sbGVjdGlvbiwgYmFzZUZsYXR0ZW4oaXRlcmF0ZWVzLCAxKSwgW10pO1xuICAgIH0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gICAgICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgRGF0ZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVzdGFtcC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZlcihmdW5jdGlvbihzdGFtcCkge1xuICAgICAqICAgY29uc29sZS5sb2coXy5ub3coKSAtIHN0YW1wKTtcbiAgICAgKiB9LCBfLm5vdygpKTtcbiAgICAgKiAvLyA9PiBMb2dzIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGl0IHRvb2sgZm9yIHRoZSBkZWZlcnJlZCBpbnZvY2F0aW9uLlxuICAgICAqL1xuICAgIHZhciBub3cgPSBjdHhOb3cgfHwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcm9vdC5EYXRlLm5vdygpO1xuICAgIH07XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8uYmVmb3JlYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlc1xuICAgICAqIGBmdW5jYCBvbmNlIGl0J3MgY2FsbGVkIGBuYCBvciBtb3JlIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiBjYWxscyBiZWZvcmUgYGZ1bmNgIGlzIGludm9rZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVzdHJpY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmVzdHJpY3RlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHNhdmVzID0gWydwcm9maWxlJywgJ3NldHRpbmdzJ107XG4gICAgICpcbiAgICAgKiB2YXIgZG9uZSA9IF8uYWZ0ZXIoc2F2ZXMubGVuZ3RoLCBmdW5jdGlvbigpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKCdkb25lIHNhdmluZyEnKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIF8uZm9yRWFjaChzYXZlcywgZnVuY3Rpb24odHlwZSkge1xuICAgICAqICAgYXN5bmNTYXZlKHsgJ3R5cGUnOiB0eXBlLCAnY29tcGxldGUnOiBkb25lIH0pO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgJ2RvbmUgc2F2aW5nIScgYWZ0ZXIgdGhlIHR3byBhc3luYyBzYXZlcyBoYXZlIGNvbXBsZXRlZC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZnRlcihuLCBmdW5jKSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoLS1uIDwgMSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2AsIHdpdGggdXAgdG8gYG5gIGFyZ3VtZW50cyxcbiAgICAgKiBpZ25vcmluZyBhbnkgYWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249ZnVuYy5sZW5ndGhdIFRoZSBhcml0eSBjYXAuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjYXBwZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnNicsICc4JywgJzEwJ10sIF8uYXJ5KHBhcnNlSW50LCAxKSk7XG4gICAgICogLy8gPT4gWzYsIDgsIDEwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFyeShmdW5jLCBuLCBndWFyZCkge1xuICAgICAgbiA9IGd1YXJkID8gdW5kZWZpbmVkIDogbjtcbiAgICAgIG4gPSAoZnVuYyAmJiBuID09IG51bGwpID8gZnVuYy5sZW5ndGggOiBuO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9BUllfRkxBRywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCwgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50c1xuICAgICAqIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLCB3aGlsZSBpdCdzIGNhbGxlZCBsZXNzIHRoYW4gYG5gIHRpbWVzLiBTdWJzZXF1ZW50XG4gICAgICogY2FsbHMgdG8gdGhlIGNyZWF0ZWQgZnVuY3Rpb24gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGludm9jYXRpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGNhbGxzIGF0IHdoaWNoIGBmdW5jYCBpcyBubyBsb25nZXIgaW52b2tlZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5iZWZvcmUoNSwgYWRkQ29udGFjdFRvTGlzdCkpO1xuICAgICAqIC8vID0+IEFsbG93cyBhZGRpbmcgdXAgdG8gNCBjb250YWN0cyB0byB0aGUgbGlzdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiZWZvcmUobiwgZnVuYykge1xuICAgICAgdmFyIHJlc3VsdDtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICgtLW4gPiAwKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuIDw9IDEpIHtcbiAgICAgICAgICBmdW5jID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIGB0aGlzQXJnYFxuICAgICAqIGFuZCBgcGFydGlhbHNgIHByZXBlbmRlZCB0byB0aGUgYXJndW1lbnRzIGl0IHJlY2VpdmVzLlxuICAgICAqXG4gICAgICogVGhlIGBfLmJpbmQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpYyBidWlsZHMsXG4gICAgICogbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBuYXRpdmUgYEZ1bmN0aW9uI2JpbmRgLCB0aGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIlxuICAgICAqIHByb3BlcnR5IG9mIGJvdW5kIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGJpbmQuXG4gICAgICogQHBhcmFtIHsqfSB0aGlzQXJnIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGdyZWV0KGdyZWV0aW5nLCBwdW5jdHVhdGlvbikge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZChncmVldCwgb2JqZWN0LCAnaGknKTtcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkISdcbiAgICAgKlxuICAgICAqIC8vIEJvdW5kIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZChncmVldCwgb2JqZWN0LCBfLCAnIScpO1xuICAgICAqIGJvdW5kKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkISdcbiAgICAgKi9cbiAgICB2YXIgYmluZCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIHRoaXNBcmcsIHBhcnRpYWxzKSB7XG4gICAgICB2YXIgYml0bWFzayA9IFdSQVBfQklORF9GTEFHO1xuICAgICAgaWYgKHBhcnRpYWxzLmxlbmd0aCkge1xuICAgICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBnZXRIb2xkZXIoYmluZCkpO1xuICAgICAgICBiaXRtYXNrIHw9IFdSQVBfUEFSVElBTF9GTEFHO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBvYmplY3Rba2V5XWAgd2l0aCBgcGFydGlhbHNgXG4gICAgICogcHJlcGVuZGVkIHRvIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBkaWZmZXJzIGZyb20gYF8uYmluZGAgYnkgYWxsb3dpbmcgYm91bmQgZnVuY3Rpb25zIHRvIHJlZmVyZW5jZVxuICAgICAqIG1ldGhvZHMgdGhhdCBtYXkgYmUgcmVkZWZpbmVkIG9yIGRvbid0IHlldCBleGlzdC4gU2VlXG4gICAgICogW1BldGVyIE1pY2hhdXgncyBhcnRpY2xlXShodHRwOi8vcGV0ZXIubWljaGF1eC5jYS9hcnRpY2xlcy9sYXp5LWZ1bmN0aW9uLWRlZmluaXRpb24tcGF0dGVybilcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogVGhlIGBfLmJpbmRLZXkucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpY1xuICAgICAqIGJ1aWxkcywgbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnZva2UgdGhlIG1ldGhvZCBvbi5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIG1ldGhvZC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHtcbiAgICAgKiAgICd1c2VyJzogJ2ZyZWQnLFxuICAgICAqICAgJ2dyZWV0JzogZnVuY3Rpb24oZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICAgIHJldHVybiBncmVldGluZyArICcgJyArIHRoaXMudXNlciArIHB1bmN0dWF0aW9uO1xuICAgICAqICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgYm91bmQgPSBfLmJpbmRLZXkob2JqZWN0LCAnZ3JlZXQnLCAnaGknKTtcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkISdcbiAgICAgKlxuICAgICAqIG9iamVjdC5ncmVldCA9IGZ1bmN0aW9uKGdyZWV0aW5nLCBwdW5jdHVhdGlvbikge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJ3lhICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogYm91bmQoJyEnKTtcbiAgICAgKiAvLyA9PiAnaGl5YSBmcmVkISdcbiAgICAgKlxuICAgICAqIC8vIEJvdW5kIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZEtleShvYmplY3QsICdncmVldCcsIF8sICchJyk7XG4gICAgICogYm91bmQoJ2hpJyk7XG4gICAgICogLy8gPT4gJ2hpeWEgZnJlZCEnXG4gICAgICovXG4gICAgdmFyIGJpbmRLZXkgPSBiYXNlUmVzdChmdW5jdGlvbihvYmplY3QsIGtleSwgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX0JJTkRfS0VZX0ZMQUc7XG4gICAgICBpZiAocGFydGlhbHMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBob2xkZXJzID0gcmVwbGFjZUhvbGRlcnMocGFydGlhbHMsIGdldEhvbGRlcihiaW5kS2V5KSk7XG4gICAgICAgIGJpdG1hc2sgfD0gV1JBUF9QQVJUSUFMX0ZMQUc7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChrZXksIGJpdG1hc2ssIG9iamVjdCwgcGFydGlhbHMsIGhvbGRlcnMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBhcmd1bWVudHMgb2YgYGZ1bmNgIGFuZCBlaXRoZXIgaW52b2tlc1xuICAgICAqIGBmdW5jYCByZXR1cm5pbmcgaXRzIHJlc3VsdCwgaWYgYXQgbGVhc3QgYGFyaXR5YCBudW1iZXIgb2YgYXJndW1lbnRzIGhhdmVcbiAgICAgKiBiZWVuIHByb3ZpZGVkLCBvciByZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHRoZSByZW1haW5pbmcgYGZ1bmNgXG4gICAgICogYXJndW1lbnRzLCBhbmQgc28gb24uIFRoZSBhcml0eSBvZiBgZnVuY2AgbWF5IGJlIHNwZWNpZmllZCBpZiBgZnVuYy5sZW5ndGhgXG4gICAgICogaXMgbm90IHN1ZmZpY2llbnQuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uY3VycnkucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpYyBidWlsZHMsXG4gICAgICogbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIGN1cnJpZWQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY3VycnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eT1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhYmMgPSBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICogICByZXR1cm4gW2EsIGIsIGNdO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgY3VycmllZCA9IF8uY3VycnkoYWJjKTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSkoMikoMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIpKDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyLCAzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIC8vIEN1cnJpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogY3VycmllZCgxKShfLCAzKSgyKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXJyeShmdW5jLCBhcml0eSwgZ3VhcmQpIHtcbiAgICAgIGFyaXR5ID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBhcml0eTtcbiAgICAgIHZhciByZXN1bHQgPSBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfQ1VSUllfRkxBRywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGFyaXR5KTtcbiAgICAgIHJlc3VsdC5wbGFjZWhvbGRlciA9IGN1cnJ5LnBsYWNlaG9sZGVyO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmN1cnJ5YCBleGNlcHQgdGhhdCBhcmd1bWVudHMgYXJlIGFwcGxpZWQgdG8gYGZ1bmNgXG4gICAgICogaW4gdGhlIG1hbm5lciBvZiBgXy5wYXJ0aWFsUmlnaHRgIGluc3RlYWQgb2YgYF8ucGFydGlhbGAuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uY3VycnlSaWdodC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgY3VycmllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5PWZ1bmMubGVuZ3RoXSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFiYyA9IGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBbYSwgYiwgY107XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBjdXJyaWVkID0gXy5jdXJyeVJpZ2h0KGFiYyk7XG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDMpKDIpKDEpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgyLCAzKSgxKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSwgMiwgMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiAvLyBDdXJyaWVkIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIGN1cnJpZWQoMykoMSwgXykoMik7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3VycnlSaWdodChmdW5jLCBhcml0eSwgZ3VhcmQpIHtcbiAgICAgIGFyaXR5ID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBhcml0eTtcbiAgICAgIHZhciByZXN1bHQgPSBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfQ1VSUllfUklHSFRfRkxBRywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGFyaXR5KTtcbiAgICAgIHJlc3VsdC5wbGFjZWhvbGRlciA9IGN1cnJ5UmlnaHQucGxhY2Vob2xkZXI7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gdGhhdCBkZWxheXMgaW52b2tpbmcgYGZ1bmNgIHVudGlsIGFmdGVyIGB3YWl0YFxuICAgICAqIG1pbGxpc2Vjb25kcyBoYXZlIGVsYXBzZWQgc2luY2UgdGhlIGxhc3QgdGltZSB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHdhc1xuICAgICAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAgICAgKiBkZWxheWVkIGBmdW5jYCBpbnZvY2F0aW9ucyBhbmQgYSBgZmx1c2hgIG1ldGhvZCB0byBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS5cbiAgICAgKiBQcm92aWRlIGBvcHRpb25zYCB0byBpbmRpY2F0ZSB3aGV0aGVyIGBmdW5jYCBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGVcbiAgICAgKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbi4gU3Vic2VxdWVudFxuICAgICAqIGNhbGxzIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgXG4gICAgICogaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXNcbiAgICAgKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICAgICAqIGlzIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAgICAgKlxuICAgICAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICAgICAqIHVudGlsIHRvIHRoZSBuZXh0IHRpY2ssIHNpbWlsYXIgdG8gYHNldFRpbWVvdXRgIHdpdGggYSB0aW1lb3V0IG9mIGAwYC5cbiAgICAgKlxuICAgICAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICAgICAqIGZvciBkZXRhaWxzIG92ZXIgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYF8uZGVib3VuY2VgIGFuZCBgXy50aHJvdHRsZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3dhaXQ9MF0gVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICAgICAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm1heFdhaXRdXG4gICAgICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAgICAgKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBkZWJvdW5jZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIEF2b2lkIGNvc3RseSBjYWxjdWxhdGlvbnMgd2hpbGUgdGhlIHdpbmRvdyBzaXplIGlzIGluIGZsdXguXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3Jlc2l6ZScsIF8uZGVib3VuY2UoY2FsY3VsYXRlTGF5b3V0LCAxNTApKTtcbiAgICAgKlxuICAgICAqIC8vIEludm9rZSBgc2VuZE1haWxgIHdoZW4gY2xpY2tlZCwgZGVib3VuY2luZyBzdWJzZXF1ZW50IGNhbGxzLlxuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmRlYm91bmNlKHNlbmRNYWlsLCAzMDAsIHtcbiAgICAgKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAgICAgKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gICAgICogfSkpO1xuICAgICAqXG4gICAgICogLy8gRW5zdXJlIGBiYXRjaExvZ2AgaXMgaW52b2tlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxscy5cbiAgICAgKiB2YXIgZGVib3VuY2VkID0gXy5kZWJvdW5jZShiYXRjaExvZywgMjUwLCB7ICdtYXhXYWl0JzogMTAwMCB9KTtcbiAgICAgKiB2YXIgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJyk7XG4gICAgICogalF1ZXJ5KHNvdXJjZSkub24oJ21lc3NhZ2UnLCBkZWJvdW5jZWQpO1xuICAgICAqXG4gICAgICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyBkZWJvdW5jZWQgaW52b2NhdGlvbi5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgICB2YXIgbGFzdEFyZ3MsXG4gICAgICAgICAgbGFzdFRoaXMsXG4gICAgICAgICAgbWF4V2FpdCxcbiAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgdGltZXJJZCxcbiAgICAgICAgICBsYXN0Q2FsbFRpbWUsXG4gICAgICAgICAgbGFzdEludm9rZVRpbWUgPSAwLFxuICAgICAgICAgIGxlYWRpbmcgPSBmYWxzZSxcbiAgICAgICAgICBtYXhpbmcgPSBmYWxzZSxcbiAgICAgICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHdhaXQgPSB0b051bWJlcih3YWl0KSB8fCAwO1xuICAgICAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICAgICAgbWF4aW5nID0gJ21heFdhaXQnIGluIG9wdGlvbnM7XG4gICAgICAgIG1heFdhaXQgPSBtYXhpbmcgPyBuYXRpdmVNYXgodG9OdW1iZXIob3B0aW9ucy5tYXhXYWl0KSB8fCAwLCB3YWl0KSA6IG1heFdhaXQ7XG4gICAgICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGludm9rZUZ1bmModGltZSkge1xuICAgICAgICB2YXIgYXJncyA9IGxhc3RBcmdzLFxuICAgICAgICAgICAgdGhpc0FyZyA9IGxhc3RUaGlzO1xuXG4gICAgICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gbGVhZGluZ0VkZ2UodGltZSkge1xuICAgICAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgICAgICBsYXN0SW52b2tlVGltZSA9IHRpbWU7XG4gICAgICAgIC8vIFN0YXJ0IHRoZSB0aW1lciBmb3IgdGhlIHRyYWlsaW5nIGVkZ2UuXG4gICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgICAgICByZXR1cm4gbGVhZGluZyA/IGludm9rZUZ1bmModGltZSkgOiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHJlbWFpbmluZ1dhaXQodGltZSkge1xuICAgICAgICB2YXIgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lLFxuICAgICAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZSxcbiAgICAgICAgICAgIHRpbWVXYWl0aW5nID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgICAgIHJldHVybiBtYXhpbmdcbiAgICAgICAgICA/IG5hdGl2ZU1pbih0aW1lV2FpdGluZywgbWF4V2FpdCAtIHRpbWVTaW5jZUxhc3RJbnZva2UpXG4gICAgICAgICAgOiB0aW1lV2FpdGluZztcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gc2hvdWxkSW52b2tlKHRpbWUpIHtcbiAgICAgICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgICAgIHRpbWVTaW5jZUxhc3RJbnZva2UgPSB0aW1lIC0gbGFzdEludm9rZVRpbWU7XG5cbiAgICAgICAgLy8gRWl0aGVyIHRoaXMgaXMgdGhlIGZpcnN0IGNhbGwsIGFjdGl2aXR5IGhhcyBzdG9wcGVkIGFuZCB3ZSdyZSBhdCB0aGVcbiAgICAgICAgLy8gdHJhaWxpbmcgZWRnZSwgdGhlIHN5c3RlbSB0aW1lIGhhcyBnb25lIGJhY2t3YXJkcyBhbmQgd2UncmUgdHJlYXRpbmdcbiAgICAgICAgLy8gaXQgYXMgdGhlIHRyYWlsaW5nIGVkZ2UsIG9yIHdlJ3ZlIGhpdCB0aGUgYG1heFdhaXRgIGxpbWl0LlxuICAgICAgICByZXR1cm4gKGxhc3RDYWxsVGltZSA9PT0gdW5kZWZpbmVkIHx8ICh0aW1lU2luY2VMYXN0Q2FsbCA+PSB3YWl0KSB8fFxuICAgICAgICAgICh0aW1lU2luY2VMYXN0Q2FsbCA8IDApIHx8IChtYXhpbmcgJiYgdGltZVNpbmNlTGFzdEludm9rZSA+PSBtYXhXYWl0KSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVyRXhwaXJlZCgpIHtcbiAgICAgICAgdmFyIHRpbWUgPSBub3coKTtcbiAgICAgICAgaWYgKHNob3VsZEludm9rZSh0aW1lKSkge1xuICAgICAgICAgIHJldHVybiB0cmFpbGluZ0VkZ2UodGltZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgcmVtYWluaW5nV2FpdCh0aW1lKSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHRyYWlsaW5nRWRnZSh0aW1lKSB7XG4gICAgICAgIHRpbWVySWQgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gT25seSBpbnZva2UgaWYgd2UgaGF2ZSBgbGFzdEFyZ3NgIHdoaWNoIG1lYW5zIGBmdW5jYCBoYXMgYmVlblxuICAgICAgICAvLyBkZWJvdW5jZWQgYXQgbGVhc3Qgb25jZS5cbiAgICAgICAgaWYgKHRyYWlsaW5nICYmIGxhc3RBcmdzKSB7XG4gICAgICAgICAgcmV0dXJuIGludm9rZUZ1bmModGltZSk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgICAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgICAgICB9XG4gICAgICAgIGxhc3RJbnZva2VUaW1lID0gMDtcbiAgICAgICAgbGFzdEFyZ3MgPSBsYXN0Q2FsbFRpbWUgPSBsYXN0VGhpcyA9IHRpbWVySWQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgICAgICByZXR1cm4gdGltZXJJZCA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKG5vdygpKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuICAgICAgICB2YXIgdGltZSA9IG5vdygpLFxuICAgICAgICAgICAgaXNJbnZva2luZyA9IHNob3VsZEludm9rZSh0aW1lKTtcblxuICAgICAgICBsYXN0QXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgbGFzdFRoaXMgPSB0aGlzO1xuICAgICAgICBsYXN0Q2FsbFRpbWUgPSB0aW1lO1xuXG4gICAgICAgIGlmIChpc0ludm9raW5nKSB7XG4gICAgICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGxlYWRpbmdFZGdlKGxhc3RDYWxsVGltZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChtYXhpbmcpIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBpbnZvY2F0aW9ucyBpbiBhIHRpZ2h0IGxvb3AuXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICAgICAgcmV0dXJuIGludm9rZUZ1bmMobGFzdENhbGxUaW1lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRpbWVySWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gICAgICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgICAgIHJldHVybiBkZWJvdW5jZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVmZXJzIGludm9raW5nIHRoZSBgZnVuY2AgdW50aWwgdGhlIGN1cnJlbnQgY2FsbCBzdGFjayBoYXMgY2xlYXJlZC4gQW55XG4gICAgICogYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0J3MgaW52b2tlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlZmVyLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmVyKGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKHRleHQpO1xuICAgICAqIH0sICdkZWZlcnJlZCcpO1xuICAgICAqIC8vID0+IExvZ3MgJ2RlZmVycmVkJyBhZnRlciBvbmUgbWlsbGlzZWNvbmQuXG4gICAgICovXG4gICAgdmFyIGRlZmVyID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgYXJncykge1xuICAgICAgcmV0dXJuIGJhc2VEZWxheShmdW5jLCAxLCBhcmdzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEludm9rZXMgYGZ1bmNgIGFmdGVyIGB3YWl0YCBtaWxsaXNlY29uZHMuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmVcbiAgICAgKiBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCdzIGludm9rZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheSBpbnZvY2F0aW9uLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlbGF5KGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKHRleHQpO1xuICAgICAqIH0sIDEwMDAsICdsYXRlcicpO1xuICAgICAqIC8vID0+IExvZ3MgJ2xhdGVyJyBhZnRlciBvbmUgc2Vjb25kLlxuICAgICAqL1xuICAgIHZhciBkZWxheSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGFyZ3MpIHtcbiAgICAgIHJldHVybiBiYXNlRGVsYXkoZnVuYywgdG9OdW1iZXIod2FpdCkgfHwgMCwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGFyZ3VtZW50cyByZXZlcnNlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGZsaXAgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmbGlwcGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZmxpcHBlZCA9IF8uZmxpcChmdW5jdGlvbigpIHtcbiAgICAgKiAgIHJldHVybiBfLnRvQXJyYXkoYXJndW1lbnRzKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGZsaXBwZWQoJ2EnLCAnYicsICdjJywgJ2QnKTtcbiAgICAgKiAvLyA9PiBbJ2QnLCAnYycsICdiJywgJ2EnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsaXAoZnVuYykge1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9GTElQX0ZMQUcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IG1lbW9pemVzIHRoZSByZXN1bHQgb2YgYGZ1bmNgLiBJZiBgcmVzb2x2ZXJgIGlzXG4gICAgICogcHJvdmlkZWQsIGl0IGRldGVybWluZXMgdGhlIGNhY2hlIGtleSBmb3Igc3RvcmluZyB0aGUgcmVzdWx0IGJhc2VkIG9uIHRoZVxuICAgICAqIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24uIEJ5IGRlZmF1bHQsIHRoZSBmaXJzdCBhcmd1bWVudFxuICAgICAqIHByb3ZpZGVkIHRvIHRoZSBtZW1vaXplZCBmdW5jdGlvbiBpcyB1c2VkIGFzIHRoZSBtYXAgY2FjaGUga2V5LiBUaGUgYGZ1bmNgXG4gICAgICogaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhlIGNhY2hlIGlzIGV4cG9zZWQgYXMgdGhlIGBjYWNoZWAgcHJvcGVydHkgb24gdGhlIG1lbW9pemVkXG4gICAgICogZnVuY3Rpb24uIEl0cyBjcmVhdGlvbiBtYXkgYmUgY3VzdG9taXplZCBieSByZXBsYWNpbmcgdGhlIGBfLm1lbW9pemUuQ2FjaGVgXG4gICAgICogY29uc3RydWN0b3Igd2l0aCBvbmUgd2hvc2UgaW5zdGFuY2VzIGltcGxlbWVudCB0aGVcbiAgICAgKiBbYE1hcGBdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXByb3BlcnRpZXMtb2YtdGhlLW1hcC1wcm90b3R5cGUtb2JqZWN0KVxuICAgICAqIG1ldGhvZCBpbnRlcmZhY2Ugb2YgYGNsZWFyYCwgYGRlbGV0ZWAsIGBnZXRgLCBgaGFzYCwgYW5kIGBzZXRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaGF2ZSBpdHMgb3V0cHV0IG1lbW9pemVkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtyZXNvbHZlcl0gVGhlIGZ1bmN0aW9uIHRvIHJlc29sdmUgdGhlIGNhY2hlIGtleS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBtZW1vaXplZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIgfTtcbiAgICAgKiB2YXIgb3RoZXIgPSB7ICdjJzogMywgJ2QnOiA0IH07XG4gICAgICpcbiAgICAgKiB2YXIgdmFsdWVzID0gXy5tZW1vaXplKF8udmFsdWVzKTtcbiAgICAgKiB2YWx1ZXMob2JqZWN0KTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIHZhbHVlcyhvdGhlcik7XG4gICAgICogLy8gPT4gWzMsIDRdXG4gICAgICpcbiAgICAgKiBvYmplY3QuYSA9IDI7XG4gICAgICogdmFsdWVzKG9iamVjdCk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiAvLyBNb2RpZnkgdGhlIHJlc3VsdCBjYWNoZS5cbiAgICAgKiB2YWx1ZXMuY2FjaGUuc2V0KG9iamVjdCwgWydhJywgJ2InXSk7XG4gICAgICogdmFsdWVzKG9iamVjdCk7XG4gICAgICogLy8gPT4gWydhJywgJ2InXVxuICAgICAqXG4gICAgICogLy8gUmVwbGFjZSBgXy5tZW1vaXplLkNhY2hlYC5cbiAgICAgKiBfLm1lbW9pemUuQ2FjaGUgPSBXZWFrTWFwO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1lbW9pemUoZnVuYywgcmVzb2x2ZXIpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nIHx8IChyZXNvbHZlciAhPSBudWxsICYmIHR5cGVvZiByZXNvbHZlciAhPSAnZnVuY3Rpb24nKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICB2YXIgbWVtb2l6ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICBrZXkgPSByZXNvbHZlciA/IHJlc29sdmVyLmFwcGx5KHRoaXMsIGFyZ3MpIDogYXJnc1swXSxcbiAgICAgICAgICAgIGNhY2hlID0gbWVtb2l6ZWQuY2FjaGU7XG5cbiAgICAgICAgaWYgKGNhY2hlLmhhcyhrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGNhY2hlLmdldChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICBtZW1vaXplZC5jYWNoZSA9IGNhY2hlLnNldChrZXksIHJlc3VsdCkgfHwgY2FjaGU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgICAgbWVtb2l6ZWQuY2FjaGUgPSBuZXcgKG1lbW9pemUuQ2FjaGUgfHwgTWFwQ2FjaGUpO1xuICAgICAgcmV0dXJuIG1lbW9pemVkO1xuICAgIH1cblxuICAgIC8vIEV4cG9zZSBgTWFwQ2FjaGVgLlxuICAgIG1lbW9pemUuQ2FjaGUgPSBNYXBDYWNoZTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IG5lZ2F0ZXMgdGhlIHJlc3VsdCBvZiB0aGUgcHJlZGljYXRlIGBmdW5jYC4gVGhlXG4gICAgICogYGZ1bmNgIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHMgb2YgdGhlXG4gICAgICogY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgcHJlZGljYXRlIHRvIG5lZ2F0ZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBuZWdhdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBpc0V2ZW4obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5maWx0ZXIoWzEsIDIsIDMsIDQsIDUsIDZdLCBfLm5lZ2F0ZShpc0V2ZW4pKTtcbiAgICAgKiAvLyA9PiBbMSwgMywgNV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBuZWdhdGUocHJlZGljYXRlKSB7XG4gICAgICBpZiAodHlwZW9mIHByZWRpY2F0ZSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICBjYXNlIDA6IHJldHVybiAhcHJlZGljYXRlLmNhbGwodGhpcyk7XG4gICAgICAgICAgY2FzZSAxOiByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKHRoaXMsIGFyZ3NbMF0pO1xuICAgICAgICAgIGNhc2UgMjogcmV0dXJuICFwcmVkaWNhdGUuY2FsbCh0aGlzLCBhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgICAgICBjYXNlIDM6IHJldHVybiAhcHJlZGljYXRlLmNhbGwodGhpcywgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICFwcmVkaWNhdGUuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGlzIHJlc3RyaWN0ZWQgdG8gaW52b2tpbmcgYGZ1bmNgIG9uY2UuIFJlcGVhdCBjYWxsc1xuICAgICAqIHRvIHRoZSBmdW5jdGlvbiByZXR1cm4gdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBpbnZvY2F0aW9uLiBUaGUgYGZ1bmNgIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVzdHJpY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmVzdHJpY3RlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGluaXRpYWxpemUgPSBfLm9uY2UoY3JlYXRlQXBwbGljYXRpb24pO1xuICAgICAqIGluaXRpYWxpemUoKTtcbiAgICAgKiBpbml0aWFsaXplKCk7XG4gICAgICogLy8gPT4gYGNyZWF0ZUFwcGxpY2F0aW9uYCBpcyBpbnZva2VkIG9uY2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBvbmNlKGZ1bmMpIHtcbiAgICAgIHJldHVybiBiZWZvcmUoMiwgZnVuYyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBpdHMgYXJndW1lbnRzIHRyYW5zZm9ybWVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW3RyYW5zZm9ybXM9W18uaWRlbnRpdHldXVxuICAgICAqICBUaGUgYXJndW1lbnQgdHJhbnNmb3Jtcy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZG91YmxlZChuKSB7XG4gICAgICogICByZXR1cm4gbiAqIDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlckFyZ3MoZnVuY3Rpb24oeCwgeSkge1xuICAgICAqICAgcmV0dXJuIFt4LCB5XTtcbiAgICAgKiB9LCBbc3F1YXJlLCBkb3VibGVkXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKDksIDMpO1xuICAgICAqIC8vID0+IFs4MSwgNl1cbiAgICAgKlxuICAgICAqIGZ1bmMoMTAsIDUpO1xuICAgICAqIC8vID0+IFsxMDAsIDEwXVxuICAgICAqL1xuICAgIHZhciBvdmVyQXJncyA9IGNhc3RSZXN0KGZ1bmN0aW9uKGZ1bmMsIHRyYW5zZm9ybXMpIHtcbiAgICAgIHRyYW5zZm9ybXMgPSAodHJhbnNmb3Jtcy5sZW5ndGggPT0gMSAmJiBpc0FycmF5KHRyYW5zZm9ybXNbMF0pKVxuICAgICAgICA/IGFycmF5TWFwKHRyYW5zZm9ybXNbMF0sIGJhc2VVbmFyeShnZXRJdGVyYXRlZSgpKSlcbiAgICAgICAgOiBhcnJheU1hcChiYXNlRmxhdHRlbih0cmFuc2Zvcm1zLCAxKSwgYmFzZVVuYXJ5KGdldEl0ZXJhdGVlKCkpKTtcblxuICAgICAgdmFyIGZ1bmNzTGVuZ3RoID0gdHJhbnNmb3Jtcy5sZW5ndGg7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihhcmdzLmxlbmd0aCwgZnVuY3NMZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYXJnc1tpbmRleF0gPSB0cmFuc2Zvcm1zW2luZGV4XS5jYWxsKHRoaXMsIGFyZ3NbaW5kZXhdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXBwbHkoZnVuYywgdGhpcywgYXJncyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggYHBhcnRpYWxzYCBwcmVwZW5kZWQgdG8gdGhlXG4gICAgICogYXJndW1lbnRzIGl0IHJlY2VpdmVzLiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmJpbmRgIGV4Y2VwdCBpdCBkb2VzICoqbm90KipcbiAgICAgKiBhbHRlciB0aGUgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBUaGUgYF8ucGFydGlhbC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgcGFydGlhbGx5XG4gICAgICogYXBwbGllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkgYXJndW1lbnRzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhcnRpYWxseSBhcHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBncmVldChncmVldGluZywgbmFtZSkge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgbmFtZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgc2F5SGVsbG9UbyA9IF8ucGFydGlhbChncmVldCwgJ2hlbGxvJyk7XG4gICAgICogc2F5SGVsbG9UbygnZnJlZCcpO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkJ1xuICAgICAqXG4gICAgICogLy8gUGFydGlhbGx5IGFwcGxpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIGdyZWV0RnJlZCA9IF8ucGFydGlhbChncmVldCwgXywgJ2ZyZWQnKTtcbiAgICAgKiBncmVldEZyZWQoJ2hpJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQnXG4gICAgICovXG4gICAgdmFyIHBhcnRpYWwgPSBiYXNlUmVzdChmdW5jdGlvbihmdW5jLCBwYXJ0aWFscykge1xuICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0SG9sZGVyKHBhcnRpYWwpKTtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfUEFSVElBTF9GTEFHLCB1bmRlZmluZWQsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucGFydGlhbGAgZXhjZXB0IHRoYXQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzXG4gICAgICogYXJlIGFwcGVuZGVkIHRvIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8ucGFydGlhbFJpZ2h0LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBwYXJ0aWFsbHlcbiAgICAgKiBhcHBsaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHBhcnRpYWxseSBhcHBseSBhcmd1bWVudHMgdG8uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFydGlhbGx5IGFwcGxpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGdyZWV0KGdyZWV0aW5nLCBuYW1lKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyBuYW1lO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBncmVldEZyZWQgPSBfLnBhcnRpYWxSaWdodChncmVldCwgJ2ZyZWQnKTtcbiAgICAgKiBncmVldEZyZWQoJ2hpJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQnXG4gICAgICpcbiAgICAgKiAvLyBQYXJ0aWFsbHkgYXBwbGllZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiB2YXIgc2F5SGVsbG9UbyA9IF8ucGFydGlhbFJpZ2h0KGdyZWV0LCAnaGVsbG8nLCBfKTtcbiAgICAgKiBzYXlIZWxsb1RvKCdmcmVkJyk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQnXG4gICAgICovXG4gICAgdmFyIHBhcnRpYWxSaWdodCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIHBhcnRpYWxzKSB7XG4gICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBnZXRIb2xkZXIocGFydGlhbFJpZ2h0KSk7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRywgdW5kZWZpbmVkLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGFyZ3VtZW50cyBhcnJhbmdlZCBhY2NvcmRpbmdcbiAgICAgKiB0byB0aGUgc3BlY2lmaWVkIGBpbmRleGVzYCB3aGVyZSB0aGUgYXJndW1lbnQgdmFsdWUgYXQgdGhlIGZpcnN0IGluZGV4IGlzXG4gICAgICogcHJvdmlkZWQgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LCB0aGUgYXJndW1lbnQgdmFsdWUgYXQgdGhlIHNlY29uZCBpbmRleCBpc1xuICAgICAqIHByb3ZpZGVkIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQsIGFuZCBzbyBvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlYXJyYW5nZSBhcmd1bWVudHMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKG51bWJlcnxudW1iZXJbXSl9IGluZGV4ZXMgVGhlIGFycmFuZ2VkIGFyZ3VtZW50IGluZGV4ZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciByZWFyZ2VkID0gXy5yZWFyZyhmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICogICByZXR1cm4gW2EsIGIsIGNdO1xuICAgICAqIH0sIFsyLCAwLCAxXSk7XG4gICAgICpcbiAgICAgKiByZWFyZ2VkKCdiJywgJ2MnLCAnYScpXG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgdmFyIHJlYXJnID0gZmxhdFJlc3QoZnVuY3Rpb24oZnVuYywgaW5kZXhlcykge1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9SRUFSR19GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBpbmRleGVzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZVxuICAgICAqIGNyZWF0ZWQgZnVuY3Rpb24gYW5kIGFyZ3VtZW50cyBmcm9tIGBzdGFydGAgYW5kIGJleW9uZCBwcm92aWRlZCBhc1xuICAgICAqIGFuIGFycmF5LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uIHRoZVxuICAgICAqIFtyZXN0IHBhcmFtZXRlcl0oaHR0cHM6Ly9tZG4uaW8vcmVzdF9wYXJhbWV0ZXJzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD1mdW5jLmxlbmd0aC0xXSBUaGUgc3RhcnQgcG9zaXRpb24gb2YgdGhlIHJlc3QgcGFyYW1ldGVyLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F5ID0gXy5yZXN0KGZ1bmN0aW9uKHdoYXQsIG5hbWVzKSB7XG4gICAgICogICByZXR1cm4gd2hhdCArICcgJyArIF8uaW5pdGlhbChuYW1lcykuam9pbignLCAnKSArXG4gICAgICogICAgIChfLnNpemUobmFtZXMpID4gMSA/ICcsICYgJyA6ICcnKSArIF8ubGFzdChuYW1lcyk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBzYXkoJ2hlbGxvJywgJ2ZyZWQnLCAnYmFybmV5JywgJ3BlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzdChmdW5jLCBzdGFydCkge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSBzdGFydCA9PT0gdW5kZWZpbmVkID8gc3RhcnQgOiB0b0ludGVnZXIoc3RhcnQpO1xuICAgICAgcmV0dXJuIGJhc2VSZXN0KGZ1bmMsIHN0YXJ0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGVcbiAgICAgKiBjcmVhdGUgZnVuY3Rpb24gYW5kIGFuIGFycmF5IG9mIGFyZ3VtZW50cyBtdWNoIGxpa2VcbiAgICAgKiBbYEZ1bmN0aW9uI2FwcGx5YF0oaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gdGhlXG4gICAgICogW3NwcmVhZCBvcGVyYXRvcl0oaHR0cHM6Ly9tZG4uaW8vc3ByZWFkX29wZXJhdG9yKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjIuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHNwcmVhZCBhcmd1bWVudHMgb3Zlci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgc3ByZWFkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F5ID0gXy5zcHJlYWQoZnVuY3Rpb24od2hvLCB3aGF0KSB7XG4gICAgICogICByZXR1cm4gd2hvICsgJyBzYXlzICcgKyB3aGF0O1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogc2F5KFsnZnJlZCcsICdoZWxsbyddKTtcbiAgICAgKiAvLyA9PiAnZnJlZCBzYXlzIGhlbGxvJ1xuICAgICAqXG4gICAgICogdmFyIG51bWJlcnMgPSBQcm9taXNlLmFsbChbXG4gICAgICogICBQcm9taXNlLnJlc29sdmUoNDApLFxuICAgICAqICAgUHJvbWlzZS5yZXNvbHZlKDM2KVxuICAgICAqIF0pO1xuICAgICAqXG4gICAgICogbnVtYmVycy50aGVuKF8uc3ByZWFkKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHJldHVybiB4ICsgeTtcbiAgICAgKiB9KSk7XG4gICAgICogLy8gPT4gYSBQcm9taXNlIG9mIDc2XG4gICAgICovXG4gICAgZnVuY3Rpb24gc3ByZWFkKGZ1bmMsIHN0YXJ0KSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBzdGFydCA9IHN0YXJ0ID09IG51bGwgPyAwIDogbmF0aXZlTWF4KHRvSW50ZWdlcihzdGFydCksIDApO1xuICAgICAgcmV0dXJuIGJhc2VSZXN0KGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJnc1tzdGFydF0sXG4gICAgICAgICAgICBvdGhlckFyZ3MgPSBjYXN0U2xpY2UoYXJncywgMCwgc3RhcnQpO1xuXG4gICAgICAgIGlmIChhcnJheSkge1xuICAgICAgICAgIGFycmF5UHVzaChvdGhlckFyZ3MsIGFycmF5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXBwbHkoZnVuYywgdGhpcywgb3RoZXJBcmdzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAgICAgKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICAgICAqIG1ldGhvZCB0byBjYW5jZWwgZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG9cbiAgICAgKiBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS4gUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2BcbiAgICAgKiBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgXG4gICAgICogdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZVxuICAgICAqIHRocm90dGxlZCBmdW5jdGlvbi4gU3Vic2VxdWVudCBjYWxscyB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHJldHVybiB0aGVcbiAgICAgKiByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGludm9jYXRpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gICAgICogaW52b2tlZCBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dCBvbmx5IGlmIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb25cbiAgICAgKiBpcyBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gICAgICpcbiAgICAgKiBJZiBgd2FpdGAgaXMgYDBgIGFuZCBgbGVhZGluZ2AgaXMgYGZhbHNlYCwgYGZ1bmNgIGludm9jYXRpb24gaXMgZGVmZXJyZWRcbiAgICAgKiB1bnRpbCB0byB0aGUgbmV4dCB0aWNrLCBzaW1pbGFyIHRvIGBzZXRUaW1lb3V0YCB3aXRoIGEgdGltZW91dCBvZiBgMGAuXG4gICAgICpcbiAgICAgKiBTZWUgW0RhdmlkIENvcmJhY2hvJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9jc3MtdHJpY2tzLmNvbS9kZWJvdW5jaW5nLXRocm90dGxpbmctZXhwbGFpbmVkLWV4YW1wbGVzLylcbiAgICAgKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLnRocm90dGxlYCBhbmQgYF8uZGVib3VuY2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gdGhyb3R0bGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHRocm90dGxlIGludm9jYXRpb25zIHRvLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz10cnVlXVxuICAgICAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSBsZWFkaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICAgICAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHRocm90dGxlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gQXZvaWQgZXhjZXNzaXZlbHkgdXBkYXRpbmcgdGhlIHBvc2l0aW9uIHdoaWxlIHNjcm9sbGluZy5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbignc2Nyb2xsJywgXy50aHJvdHRsZSh1cGRhdGVQb3NpdGlvbiwgMTAwKSk7XG4gICAgICpcbiAgICAgKiAvLyBJbnZva2UgYHJlbmV3VG9rZW5gIHdoZW4gdGhlIGNsaWNrIGV2ZW50IGlzIGZpcmVkLCBidXQgbm90IG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IDUgbWludXRlcy5cbiAgICAgKiB2YXIgdGhyb3R0bGVkID0gXy50aHJvdHRsZShyZW5ld1Rva2VuLCAzMDAwMDAsIHsgJ3RyYWlsaW5nJzogZmFsc2UgfSk7XG4gICAgICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIHRocm90dGxlZCk7XG4gICAgICpcbiAgICAgKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIHRocm90dGxlZCBpbnZvY2F0aW9uLlxuICAgICAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIHRocm90dGxlZC5jYW5jZWwpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRocm90dGxlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsZWFkaW5nID0gdHJ1ZSxcbiAgICAgICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgICBsZWFkaW5nID0gJ2xlYWRpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMubGVhZGluZyA6IGxlYWRpbmc7XG4gICAgICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLnRyYWlsaW5nIDogdHJhaWxpbmc7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGVib3VuY2UoZnVuYywgd2FpdCwge1xuICAgICAgICAnbGVhZGluZyc6IGxlYWRpbmcsXG4gICAgICAgICdtYXhXYWl0Jzogd2FpdCxcbiAgICAgICAgJ3RyYWlsaW5nJzogdHJhaWxpbmdcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdXAgdG8gb25lIGFyZ3VtZW50LCBpZ25vcmluZyBhbnlcbiAgICAgKiBhZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNhcHBlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzgnLCAnMTAnXSwgXy51bmFyeShwYXJzZUludCkpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmFyeShmdW5jKSB7XG4gICAgICByZXR1cm4gYXJ5KGZ1bmMsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb3ZpZGVzIGB2YWx1ZWAgdG8gYHdyYXBwZXJgIGFzIGl0cyBmaXJzdFxuICAgICAqIGFyZ3VtZW50LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIGZ1bmN0aW9uIGFyZSBhcHBlbmRlZFxuICAgICAqIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBgd3JhcHBlcmAuIFRoZSB3cmFwcGVyIGlzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgXG4gICAgICogYmluZGluZyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3dyYXBwZXI9aWRlbnRpdHldIFRoZSB3cmFwcGVyIGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgcCA9IF8ud3JhcChfLmVzY2FwZSwgZnVuY3Rpb24oZnVuYywgdGV4dCkge1xuICAgICAqICAgcmV0dXJuICc8cD4nICsgZnVuYyh0ZXh0KSArICc8L3A+JztcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHAoJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJzxwPmZyZWQsIGJhcm5leSwgJmFtcDsgcGViYmxlczwvcD4nXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcCh2YWx1ZSwgd3JhcHBlcikge1xuICAgICAgcmV0dXJuIHBhcnRpYWwoY2FzdEZ1bmN0aW9uKHdyYXBwZXIpLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYHZhbHVlYCBhcyBhbiBhcnJheSBpZiBpdCdzIG5vdCBvbmUuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC40LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjYXN0IGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSgxKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KHsgJ2EnOiAxIH0pO1xuICAgICAqIC8vID0+IFt7ICdhJzogMSB9XVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkoJ2FiYycpO1xuICAgICAqIC8vID0+IFsnYWJjJ11cbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KG51bGwpO1xuICAgICAqIC8vID0+IFtudWxsXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkodW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiBbdW5kZWZpbmVkXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkoKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqIGNvbnNvbGUubG9nKF8uY2FzdEFycmF5KGFycmF5KSA9PT0gYXJyYXkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXN0QXJyYXkoKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIHZhbHVlID0gYXJndW1lbnRzWzBdO1xuICAgICAgcmV0dXJuIGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzaGFsbG93IGNsb25lIG9mIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgbG9vc2VseSBiYXNlZCBvbiB0aGVcbiAgICAgKiBbc3RydWN0dXJlZCBjbG9uZSBhbGdvcml0aG1dKGh0dHBzOi8vbWRuLmlvL1N0cnVjdHVyZWRfY2xvbmVfYWxnb3JpdGhtKVxuICAgICAqIGFuZCBzdXBwb3J0cyBjbG9uaW5nIGFycmF5cywgYXJyYXkgYnVmZmVycywgYm9vbGVhbnMsIGRhdGUgb2JqZWN0cywgbWFwcyxcbiAgICAgKiBudW1iZXJzLCBgT2JqZWN0YCBvYmplY3RzLCByZWdleGVzLCBzZXRzLCBzdHJpbmdzLCBzeW1ib2xzLCBhbmQgdHlwZWRcbiAgICAgKiBhcnJheXMuIFRoZSBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGBhcmd1bWVudHNgIG9iamVjdHMgYXJlIGNsb25lZFxuICAgICAqIGFzIHBsYWluIG9iamVjdHMuIEFuIGVtcHR5IG9iamVjdCBpcyByZXR1cm5lZCBmb3IgdW5jbG9uZWFibGUgdmFsdWVzIHN1Y2hcbiAgICAgKiBhcyBlcnJvciBvYmplY3RzLCBmdW5jdGlvbnMsIERPTSBub2RlcywgYW5kIFdlYWtNYXBzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5jbG9uZURlZXBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnYSc6IDEgfSwgeyAnYic6IDIgfV07XG4gICAgICpcbiAgICAgKiB2YXIgc2hhbGxvdyA9IF8uY2xvbmUob2JqZWN0cyk7XG4gICAgICogY29uc29sZS5sb2coc2hhbGxvd1swXSA9PT0gb2JqZWN0c1swXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lKHZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCBDTE9ORV9TWU1CT0xTX0ZMQUcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY2xvbmVgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBwcm9kdWNlIHRoZSBjbG9uZWQgdmFsdWUuIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgLFxuICAgICAqIGNsb25pbmcgaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZCB3aXRoXG4gICAgICogdXAgdG8gZm91ciBhcmd1bWVudHM7ICh2YWx1ZSBbLCBpbmRleHxrZXksIG9iamVjdCwgc3RhY2tdKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5jbG9uZURlZXBXaXRoXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIodmFsdWUpIHtcbiAgICAgKiAgIGlmIChfLmlzRWxlbWVudCh2YWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIHZhbHVlLmNsb25lTm9kZShmYWxzZSk7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGVsID0gXy5jbG9uZVdpdGgoZG9jdW1lbnQuYm9keSwgY3VzdG9taXplcik7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhlbCA9PT0gZG9jdW1lbnQuYm9keSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5ub2RlTmFtZSk7XG4gICAgICogLy8gPT4gJ0JPRFknXG4gICAgICogY29uc29sZS5sb2coZWwuY2hpbGROb2Rlcy5sZW5ndGgpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVdpdGgodmFsdWUsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gY3VzdG9taXplciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIENMT05FX1NZTUJPTFNfRkxBRywgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZWAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgY2xvbmVzIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJlY3Vyc2l2ZWx5IGNsb25lLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBkZWVwIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8uY2xvbmVcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnYSc6IDEgfSwgeyAnYic6IDIgfV07XG4gICAgICpcbiAgICAgKiB2YXIgZGVlcCA9IF8uY2xvbmVEZWVwKG9iamVjdHMpO1xuICAgICAqIGNvbnNvbGUubG9nKGRlZXBbMF0gPT09IG9iamVjdHNbMF0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVEZWVwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCBDTE9ORV9ERUVQX0ZMQUcgfCBDTE9ORV9TWU1CT0xTX0ZMQUcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY2xvbmVXaXRoYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBjbG9uZXMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmVjdXJzaXZlbHkgY2xvbmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZGVlcCBjbG9uZWQgdmFsdWUuXG4gICAgICogQHNlZSBfLmNsb25lV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKHZhbHVlKSB7XG4gICAgICogICBpZiAoXy5pc0VsZW1lbnQodmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiB2YWx1ZS5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGVsID0gXy5jbG9uZURlZXBXaXRoKGRvY3VtZW50LmJvZHksIGN1c3RvbWl6ZXIpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coZWwgPT09IGRvY3VtZW50LmJvZHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICogY29uc29sZS5sb2coZWwubm9kZU5hbWUpO1xuICAgICAqIC8vID0+ICdCT0RZJ1xuICAgICAqIGNvbnNvbGUubG9nKGVsLmNoaWxkTm9kZXMubGVuZ3RoKTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGVlcFdpdGgodmFsdWUsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gY3VzdG9taXplciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIENMT05FX0RFRVBfRkxBRyB8IENMT05FX1NZTUJPTFNfRkxBRywgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBvYmplY3RgIGNvbmZvcm1zIHRvIGBzb3VyY2VgIGJ5IGludm9raW5nIHRoZSBwcmVkaWNhdGVcbiAgICAgKiBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkgdmFsdWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGVxdWl2YWxlbnQgdG8gYF8uY29uZm9ybXNgIHdoZW4gYHNvdXJjZWAgaXNcbiAgICAgKiBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjE0LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGNvbmZvcm1zLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyIH07XG4gICAgICpcbiAgICAgKiBfLmNvbmZvcm1zVG8ob2JqZWN0LCB7ICdiJzogZnVuY3Rpb24obikgeyByZXR1cm4gbiA+IDE7IH0gfSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5jb25mb3Jtc1RvKG9iamVjdCwgeyAnYic6IGZ1bmN0aW9uKG4pIHsgcmV0dXJuIG4gPiAyOyB9IH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uZm9ybXNUbyhvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIHNvdXJjZSA9PSBudWxsIHx8IGJhc2VDb25mb3Jtc1RvKG9iamVjdCwgc291cmNlLCBrZXlzKHNvdXJjZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGFcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGNvbXBhcmlzb24gYmV0d2VlbiB0d28gdmFsdWVzIHRvIGRldGVybWluZSBpZiB0aGV5IGFyZSBlcXVpdmFsZW50LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gICAgICogdmFyIG90aGVyID0geyAnYSc6IDEgfTtcbiAgICAgKlxuICAgICAqIF8uZXEob2JqZWN0LCBvYmplY3QpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZXEob2JqZWN0LCBvdGhlcik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZXEoJ2EnLCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZXEoJ2EnLCBPYmplY3QoJ2EnKSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZXEoTmFOLCBOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcSh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gb3RoZXIgfHwgKHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIGBvdGhlcmAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8ubHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ndCgzLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmd0KDMsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmd0KDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGd0ID0gY3JlYXRlUmVsYXRpb25hbE9wZXJhdGlvbihiYXNlR3QpO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGBvdGhlcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy45LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG9cbiAgICAgKiAgYG90aGVyYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBzZWUgXy5sdGVcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ndGUoMywgMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5ndGUoMywgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5ndGUoMSwgMyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgZ3RlID0gY3JlYXRlUmVsYXRpb25hbE9wZXJhdGlvbihmdW5jdGlvbih2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA+PSBvdGhlcjtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhbiBgYXJndW1lbnRzYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcmd1bWVudHMoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0FyZ3VtZW50cyA9IGJhc2VJc0FyZ3VtZW50cyhmdW5jdGlvbigpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA/IGJhc2VJc0FyZ3VtZW50cyA6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnY2FsbGVlJykgJiZcbiAgICAgICAgIXByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwodmFsdWUsICdjYWxsZWUnKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhbiBgQXJyYXlgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoJ2FiYycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYEFycmF5QnVmZmVyYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGFycmF5IGJ1ZmZlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlCdWZmZXIobmV3IEFycmF5QnVmZmVyKDIpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlCdWZmZXIobmV3IEFycmF5KDIpKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0FycmF5QnVmZmVyID0gbm9kZUlzQXJyYXlCdWZmZXIgPyBiYXNlVW5hcnkobm9kZUlzQXJyYXlCdWZmZXIpIDogYmFzZUlzQXJyYXlCdWZmZXI7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLiBBIHZhbHVlIGlzIGNvbnNpZGVyZWQgYXJyYXktbGlrZSBpZiBpdCdzXG4gICAgICogbm90IGEgZnVuY3Rpb24gYW5kIGhhcyBhIGB2YWx1ZS5sZW5ndGhgIHRoYXQncyBhbiBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiBvclxuICAgICAqIGVxdWFsIHRvIGAwYCBhbmQgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoZG9jdW1lbnQuYm9keS5jaGlsZHJlbik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZSgnYWJjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZShfLm5vb3ApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcnJheUxpa2UodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgIWlzRnVuY3Rpb24odmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaXNBcnJheUxpa2VgIGV4Y2VwdCB0aGF0IGl0IGFsc28gY2hlY2tzIGlmIGB2YWx1ZWBcbiAgICAgKiBpcyBhbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGFycmF5LWxpa2Ugb2JqZWN0LFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2VPYmplY3QoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2VPYmplY3QoJ2FiYycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KF8ubm9vcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0FycmF5TGlrZU9iamVjdCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaXNBcnJheUxpa2UodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBib29sZWFuIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgYm9vbGVhbiwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQm9vbGVhbihmYWxzZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Jvb2xlYW4obnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdHJ1ZSB8fCB2YWx1ZSA9PT0gZmFsc2UgfHxcbiAgICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gYm9vbFRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBidWZmZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgYnVmZmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNCdWZmZXIobmV3IEJ1ZmZlcigyKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0J1ZmZlcihuZXcgVWludDhBcnJheSgyKSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNCdWZmZXIgPSBuYXRpdmVJc0J1ZmZlciB8fCBzdHViRmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYERhdGVgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBkYXRlIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRGF0ZShuZXcgRGF0ZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0RhdGUoJ01vbiBBcHJpbCAyMyAyMDEyJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNEYXRlID0gbm9kZUlzRGF0ZSA/IGJhc2VVbmFyeShub2RlSXNEYXRlKSA6IGJhc2VJc0RhdGU7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsaWtlbHkgYSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBET00gZWxlbWVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRWxlbWVudChkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRWxlbWVudCgnPGJvZHk+Jyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIHZhbHVlLm5vZGVUeXBlID09PSAxICYmICFpc1BsYWluT2JqZWN0KHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhbiBlbXB0eSBvYmplY3QsIGNvbGxlY3Rpb24sIG1hcCwgb3Igc2V0LlxuICAgICAqXG4gICAgICogT2JqZWN0cyBhcmUgY29uc2lkZXJlZCBlbXB0eSBpZiB0aGV5IGhhdmUgbm8gb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkXG4gICAgICogcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEFycmF5LWxpa2UgdmFsdWVzIHN1Y2ggYXMgYGFyZ3VtZW50c2Agb2JqZWN0cywgYXJyYXlzLCBidWZmZXJzLCBzdHJpbmdzLCBvclxuICAgICAqIGpRdWVyeS1saWtlIGNvbGxlY3Rpb25zIGFyZSBjb25zaWRlcmVkIGVtcHR5IGlmIHRoZXkgaGF2ZSBhIGBsZW5ndGhgIG9mIGAwYC5cbiAgICAgKiBTaW1pbGFybHksIG1hcHMgYW5kIHNldHMgYXJlIGNvbnNpZGVyZWQgZW1wdHkgaWYgdGhleSBoYXZlIGEgYHNpemVgIG9mIGAwYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZW1wdHksIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KG51bGwpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSh0cnVlKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSh7ICdhJzogMSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRW1wdHkodmFsdWUpIHtcbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSAmJlxuICAgICAgICAgIChpc0FycmF5KHZhbHVlKSB8fCB0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlLnNwbGljZSA9PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgICBpc0J1ZmZlcih2YWx1ZSkgfHwgaXNUeXBlZEFycmF5KHZhbHVlKSB8fCBpc0FyZ3VtZW50cyh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiAhdmFsdWUubGVuZ3RoO1xuICAgICAgfVxuICAgICAgdmFyIHRhZyA9IGdldFRhZyh2YWx1ZSk7XG4gICAgICBpZiAodGFnID09IG1hcFRhZyB8fCB0YWcgPT0gc2V0VGFnKSB7XG4gICAgICAgIHJldHVybiAhdmFsdWUuc2l6ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1Byb3RvdHlwZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuICFiYXNlS2V5cyh2YWx1ZSkubGVuZ3RoO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIga2V5IGluIHZhbHVlKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlXG4gICAgICogZXF1aXZhbGVudC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBzdXBwb3J0cyBjb21wYXJpbmcgYXJyYXlzLCBhcnJheSBidWZmZXJzLCBib29sZWFucyxcbiAgICAgKiBkYXRlIG9iamVjdHMsIGVycm9yIG9iamVjdHMsIG1hcHMsIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsXG4gICAgICogc2V0cywgc3RyaW5ncywgc3ltYm9scywgYW5kIHR5cGVkIGFycmF5cy4gYE9iamVjdGAgb2JqZWN0cyBhcmUgY29tcGFyZWRcbiAgICAgKiBieSB0aGVpciBvd24sIG5vdCBpbmhlcml0ZWQsIGVudW1lcmFibGUgcHJvcGVydGllcy4gRnVuY3Rpb25zIGFuZCBET01cbiAgICAgKiBub2RlcyBhcmUgY29tcGFyZWQgYnkgc3RyaWN0IGVxdWFsaXR5LCBpLmUuIGA9PT1gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gICAgICogdmFyIG90aGVyID0geyAnYSc6IDEgfTtcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbChvYmplY3QsIG90aGVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBvYmplY3QgPT09IG90aGVyO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcXVhbCh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiBiYXNlSXNFcXVhbCh2YWx1ZSwgb3RoZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaXNFcXVhbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCwgY29tcGFyaXNvbnNcbiAgICAgKiBhcmUgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZCB3aXRoIHVwIHRvXG4gICAgICogc2l4IGFyZ3VtZW50czogKG9ialZhbHVlLCBvdGhWYWx1ZSBbLCBpbmRleHxrZXksIG9iamVjdCwgb3RoZXIsIHN0YWNrXSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBpc0dyZWV0aW5nKHZhbHVlKSB7XG4gICAgICogICByZXR1cm4gL15oKD86aXxlbGxvKSQvLnRlc3QodmFsdWUpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIob2JqVmFsdWUsIG90aFZhbHVlKSB7XG4gICAgICogICBpZiAoaXNHcmVldGluZyhvYmpWYWx1ZSkgJiYgaXNHcmVldGluZyhvdGhWYWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIHRydWU7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWydoZWxsbycsICdnb29kYnllJ107XG4gICAgICogdmFyIG90aGVyID0gWydoaScsICdnb29kYnllJ107XG4gICAgICpcbiAgICAgKiBfLmlzRXF1YWxXaXRoKGFycmF5LCBvdGhlciwgY3VzdG9taXplcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRXF1YWxXaXRoKHZhbHVlLCBvdGhlciwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgdmFyIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKHZhbHVlLCBvdGhlcikgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyBiYXNlSXNFcXVhbCh2YWx1ZSwgb3RoZXIsIHVuZGVmaW5lZCwgY3VzdG9taXplcikgOiAhIXJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhbiBgRXJyb3JgLCBgRXZhbEVycm9yYCwgYFJhbmdlRXJyb3JgLCBgUmVmZXJlbmNlRXJyb3JgLFxuICAgICAqIGBTeW50YXhFcnJvcmAsIGBUeXBlRXJyb3JgLCBvciBgVVJJRXJyb3JgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gZXJyb3Igb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFcnJvcihuZXcgRXJyb3IpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFcnJvcihFcnJvcik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Vycm9yKHZhbHVlKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIHRhZyA9IGJhc2VHZXRUYWcodmFsdWUpO1xuICAgICAgcmV0dXJuIHRhZyA9PSBlcnJvclRhZyB8fCB0YWcgPT0gZG9tRXhjVGFnIHx8XG4gICAgICAgICh0eXBlb2YgdmFsdWUubWVzc2FnZSA9PSAnc3RyaW5nJyAmJiB0eXBlb2YgdmFsdWUubmFtZSA9PSAnc3RyaW5nJyAmJiAhaXNQbGFpbk9iamVjdCh2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgZmluaXRlIHByaW1pdGl2ZSBudW1iZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYE51bWJlci5pc0Zpbml0ZWBdKGh0dHBzOi8vbWRuLmlvL051bWJlci9pc0Zpbml0ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgZmluaXRlIG51bWJlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZShJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRmluaXRlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmIG5hdGl2ZUlzRmluaXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYEZ1bmN0aW9uYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgZnVuY3Rpb24sIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Z1bmN0aW9uKF8pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGdW5jdGlvbigvYWJjLyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBUaGUgdXNlIG9mIGBPYmplY3QjdG9TdHJpbmdgIGF2b2lkcyBpc3N1ZXMgd2l0aCB0aGUgYHR5cGVvZmAgb3BlcmF0b3JcbiAgICAgIC8vIGluIFNhZmFyaSA5IHdoaWNoIHJldHVybnMgJ29iamVjdCcgZm9yIHR5cGVkIGFycmF5cyBhbmQgb3RoZXIgY29uc3RydWN0b3JzLlxuICAgICAgdmFyIHRhZyA9IGJhc2VHZXRUYWcodmFsdWUpO1xuICAgICAgcmV0dXJuIHRhZyA9PSBmdW5jVGFnIHx8IHRhZyA9PSBnZW5UYWcgfHwgdGFnID09IGFzeW5jVGFnIHx8IHRhZyA9PSBwcm94eVRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhbiBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uXG4gICAgICogW2BOdW1iZXIuaXNJbnRlZ2VyYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzSW50ZWdlcikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGludGVnZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNJbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSW50ZWdlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA9PSB0b0ludGVnZXIodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgYXJyYXktbGlrZSBsZW5ndGguXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgbG9vc2VseSBiYXNlZCBvblxuICAgICAqIFtgVG9MZW5ndGhgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy10b2xlbmd0aCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgbGVuZ3RoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aChOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aChJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTGVuZ3RoKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmXG4gICAgICAgIHZhbHVlID4gLTEgJiYgdmFsdWUgJSAxID09IDAgJiYgdmFsdWUgPD0gTUFYX1NBRkVfSU5URUdFUjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAgICAgKiBbbGFuZ3VhZ2UgdHlwZV0oaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWVjbWFzY3JpcHQtbGFuZ3VhZ2UtdHlwZXMpXG4gICAgICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdCh7fSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0KG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAgICAgKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKHt9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0TGlrZShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKF8ubm9vcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNPYmplY3RMaWtlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBNYXBgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBtYXAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc01hcChuZXcgTWFwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTWFwKG5ldyBXZWFrTWFwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc01hcCA9IG5vZGVJc01hcCA/IGJhc2VVbmFyeShub2RlSXNNYXApIDogYmFzZUlzTWFwO1xuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgYSBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIGBvYmplY3RgIGFuZCBgc291cmNlYCB0b1xuICAgICAqIGRldGVybWluZSBpZiBgb2JqZWN0YCBjb250YWlucyBlcXVpdmFsZW50IHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBlcXVpdmFsZW50IHRvIGBfLm1hdGNoZXNgIHdoZW4gYHNvdXJjZWAgaXNcbiAgICAgKiBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKlxuICAgICAqIFBhcnRpYWwgY29tcGFyaXNvbnMgd2lsbCBtYXRjaCBlbXB0eSBhcnJheSBhbmQgZW1wdHkgb2JqZWN0IGBzb3VyY2VgXG4gICAgICogdmFsdWVzIGFnYWluc3QgYW55IGFycmF5IG9yIG9iamVjdCB2YWx1ZSwgcmVzcGVjdGl2ZWx5LiBTZWUgYF8uaXNFcXVhbGBcbiAgICAgKiBmb3IgYSBsaXN0IG9mIHN1cHBvcnRlZCB2YWx1ZSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiB9O1xuICAgICAqXG4gICAgICogXy5pc01hdGNoKG9iamVjdCwgeyAnYic6IDIgfSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc01hdGNoKG9iamVjdCwgeyAnYic6IDEgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc01hdGNoKG9iamVjdCwgc291cmNlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09PSBzb3VyY2UgfHwgYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIGdldE1hdGNoRGF0YShzb3VyY2UpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmlzTWF0Y2hgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIHZhbHVlcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAsIGNvbXBhcmlzb25zXG4gICAgICogYXJlIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aCBmaXZlXG4gICAgICogYXJndW1lbnRzOiAob2JqVmFsdWUsIHNyY1ZhbHVlLCBpbmRleHxrZXksIG9iamVjdCwgc291cmNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBpc0dyZWV0aW5nKHZhbHVlKSB7XG4gICAgICogICByZXR1cm4gL15oKD86aXxlbGxvKSQvLnRlc3QodmFsdWUpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIob2JqVmFsdWUsIHNyY1ZhbHVlKSB7XG4gICAgICogICBpZiAoaXNHcmVldGluZyhvYmpWYWx1ZSkgJiYgaXNHcmVldGluZyhzcmNWYWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIHRydWU7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2dyZWV0aW5nJzogJ2hlbGxvJyB9O1xuICAgICAqIHZhciBzb3VyY2UgPSB7ICdncmVldGluZyc6ICdoaScgfTtcbiAgICAgKlxuICAgICAqIF8uaXNNYXRjaFdpdGgob2JqZWN0LCBzb3VyY2UsIGN1c3RvbWl6ZXIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc01hdGNoV2l0aChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBnZXRNYXRjaERhdGEoc291cmNlKSwgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYE5hTmAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYE51bWJlci5pc05hTmBdKGh0dHBzOi8vbWRuLmlvL051bWJlci9pc05hTikgYW5kIGlzIG5vdCB0aGUgc2FtZSBhc1xuICAgICAqIGdsb2JhbCBbYGlzTmFOYF0oaHR0cHM6Ly9tZG4uaW8vaXNOYU4pIHdoaWNoIHJldHVybnMgYHRydWVgIGZvclxuICAgICAqIGB1bmRlZmluZWRgIGFuZCBvdGhlciBub24tbnVtYmVyIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYE5hTmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc05hTihOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4obmV3IE51bWJlcihOYU4pKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBpc05hTih1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4odW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmFOKHZhbHVlKSB7XG4gICAgICAvLyBBbiBgTmFOYCBwcmltaXRpdmUgaXMgdGhlIG9ubHkgdmFsdWUgdGhhdCBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLlxuICAgICAgLy8gUGVyZm9ybSB0aGUgYHRvU3RyaW5nVGFnYCBjaGVjayBmaXJzdCB0byBhdm9pZCBlcnJvcnMgd2l0aCBzb21lXG4gICAgICAvLyBBY3RpdmVYIG9iamVjdHMgaW4gSUUuXG4gICAgICByZXR1cm4gaXNOdW1iZXIodmFsdWUpICYmIHZhbHVlICE9ICt2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHByaXN0aW5lIG5hdGl2ZSBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBjYW4ndCByZWxpYWJseSBkZXRlY3QgbmF0aXZlIGZ1bmN0aW9ucyBpbiB0aGUgcHJlc2VuY2VcbiAgICAgKiBvZiB0aGUgY29yZS1qcyBwYWNrYWdlIGJlY2F1c2UgY29yZS1qcyBjaXJjdW12ZW50cyB0aGlzIGtpbmQgb2YgZGV0ZWN0aW9uLlxuICAgICAqIERlc3BpdGUgbXVsdGlwbGUgcmVxdWVzdHMsIHRoZSBjb3JlLWpzIG1haW50YWluZXIgaGFzIG1hZGUgaXQgY2xlYXI6IGFueVxuICAgICAqIGF0dGVtcHQgdG8gZml4IHRoZSBkZXRlY3Rpb24gd2lsbCBiZSBvYnN0cnVjdGVkLiBBcyBhIHJlc3VsdCwgd2UncmUgbGVmdFxuICAgICAqIHdpdGggbGl0dGxlIGNob2ljZSBidXQgdG8gdGhyb3cgYW4gZXJyb3IuIFVuZm9ydHVuYXRlbHksIHRoaXMgYWxzbyBhZmZlY3RzXG4gICAgICogcGFja2FnZXMsIGxpa2UgW2JhYmVsLXBvbHlmaWxsXShodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9iYWJlbC1wb2x5ZmlsbCksXG4gICAgICogd2hpY2ggcmVseSBvbiBjb3JlLWpzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbixcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmF0aXZlKEFycmF5LnByb3RvdHlwZS5wdXNoKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmF0aXZlKF8pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOYXRpdmUodmFsdWUpIHtcbiAgICAgIGlmIChpc01hc2thYmxlKHZhbHVlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoQ09SRV9FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlSXNOYXRpdmUodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBudWxsYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYG51bGxgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOdWxsKG51bGwpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdWxsKHZvaWQgMCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc051bGwodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG51bGxpc2gsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc05pbChudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmlsKHZvaWQgMCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05pbChOYU4pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOaWwodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgTnVtYmVyYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRvIGV4Y2x1ZGUgYEluZmluaXR5YCwgYC1JbmZpbml0eWAsIGFuZCBgTmFOYCwgd2hpY2ggYXJlXG4gICAgICogY2xhc3NpZmllZCBhcyBudW1iZXJzLCB1c2UgdGhlIGBfLmlzRmluaXRlYCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbnVtYmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKCczJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc051bWJlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyB8fFxuICAgICAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBudW1iZXJUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcGxhaW4gb2JqZWN0LCB0aGF0IGlzLCBhbiBvYmplY3QgY3JlYXRlZCBieSB0aGVcbiAgICAgKiBgT2JqZWN0YCBjb25zdHJ1Y3RvciBvciBvbmUgd2l0aCBhIGBbW1Byb3RvdHlwZV1dYCBvZiBgbnVsbGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC44LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcGxhaW4gb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5pc1BsYWluT2JqZWN0KG5ldyBGb28pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc1BsYWluT2JqZWN0KHsgJ3gnOiAwLCAneSc6IDAgfSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1BsYWluT2JqZWN0KE9iamVjdC5jcmVhdGUobnVsbCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1BsYWluT2JqZWN0KHZhbHVlKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0TGlrZSh2YWx1ZSkgfHwgYmFzZUdldFRhZyh2YWx1ZSkgIT0gb2JqZWN0VGFnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBwcm90byA9IGdldFByb3RvdHlwZSh2YWx1ZSk7XG4gICAgICBpZiAocHJvdG8gPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICB2YXIgQ3RvciA9IGhhc093blByb3BlcnR5LmNhbGwocHJvdG8sICdjb25zdHJ1Y3RvcicpICYmIHByb3RvLmNvbnN0cnVjdG9yO1xuICAgICAgcmV0dXJuIHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiYgQ3RvciBpbnN0YW5jZW9mIEN0b3IgJiZcbiAgICAgICAgZnVuY1RvU3RyaW5nLmNhbGwoQ3RvcikgPT0gb2JqZWN0Q3RvclN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFJlZ0V4cGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHJlZ2V4cCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzUmVnRXhwKC9hYmMvKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzUmVnRXhwKCcvYWJjLycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzUmVnRXhwID0gbm9kZUlzUmVnRXhwID8gYmFzZVVuYXJ5KG5vZGVJc1JlZ0V4cCkgOiBiYXNlSXNSZWdFeHA7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHNhZmUgaW50ZWdlci4gQW4gaW50ZWdlciBpcyBzYWZlIGlmIGl0J3MgYW4gSUVFRS03NTRcbiAgICAgKiBkb3VibGUgcHJlY2lzaW9uIG51bWJlciB3aGljaCBpc24ndCB0aGUgcmVzdWx0IG9mIGEgcm91bmRlZCB1bnNhZmUgaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgTnVtYmVyLmlzU2FmZUludGVnZXJgXShodHRwczovL21kbi5pby9OdW1iZXIvaXNTYWZlSW50ZWdlcikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc2FmZSBpbnRlZ2VyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNTYWZlSW50ZWdlcigzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNTYWZlSW50ZWdlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNTYWZlSW50ZWdlcignMycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNTYWZlSW50ZWdlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzSW50ZWdlcih2YWx1ZSkgJiYgdmFsdWUgPj0gLU1BWF9TQUZFX0lOVEVHRVIgJiYgdmFsdWUgPD0gTUFYX1NBRkVfSU5URUdFUjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFNldGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNldCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU2V0KG5ldyBTZXQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNTZXQobmV3IFdlYWtTZXQpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzU2V0ID0gbm9kZUlzU2V0ID8gYmFzZVVuYXJ5KG5vZGVJc1NldCkgOiBiYXNlSXNTZXQ7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN0cmluZ2AgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzdHJpbmcsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1N0cmluZygnYWJjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1N0cmluZygxKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8XG4gICAgICAgICghaXNBcnJheSh2YWx1ZSkgJiYgaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBzdHJpbmdUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHN5bWJvbCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU3ltYm9sKFN5bWJvbC5pdGVyYXRvcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1N5bWJvbCgnYWJjJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1N5bWJvbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgICAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSB0eXBlZCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB0eXBlZCBhcnJheSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzVHlwZWRBcnJheShuZXcgVWludDhBcnJheSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1R5cGVkQXJyYXkoW10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzVHlwZWRBcnJheSA9IG5vZGVJc1R5cGVkQXJyYXkgPyBiYXNlVW5hcnkobm9kZUlzVHlwZWRBcnJheSkgOiBiYXNlSXNUeXBlZEFycmF5O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGB1bmRlZmluZWRgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNVbmRlZmluZWQodm9pZCAwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzVW5kZWZpbmVkKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgV2Vha01hcGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHdlYWsgbWFwLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNXZWFrTWFwKG5ldyBXZWFrTWFwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha01hcChuZXcgTWFwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzV2Vha01hcCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSB3ZWFrTWFwVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgV2Vha1NldGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHdlYWsgc2V0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNXZWFrU2V0KG5ldyBXZWFrU2V0KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha1NldChuZXcgU2V0KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzV2Vha1NldCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gd2Vha1NldFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBgb3RoZXJgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQHNlZSBfLmd0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubHQoMSwgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5sdCgzLCAzKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5sdCgzLCAxKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBsdCA9IGNyZWF0ZVJlbGF0aW9uYWxPcGVyYXRpb24oYmFzZUx0KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvXG4gICAgICogIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8uZ3RlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubHRlKDEsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHRlKDMsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHRlKDMsIDEpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGx0ZSA9IGNyZWF0ZVJlbGF0aW9uYWxPcGVyYXRpb24oZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPD0gb3RoZXI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGFuIGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8udG9BcnJheSgnYWJjJyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkoMSk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKlxuICAgICAqIF8udG9BcnJheShudWxsKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvQXJyYXkodmFsdWUpIHtcbiAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gaXNTdHJpbmcodmFsdWUpID8gc3RyaW5nVG9BcnJheSh2YWx1ZSkgOiBjb3B5QXJyYXkodmFsdWUpO1xuICAgICAgfVxuICAgICAgaWYgKHN5bUl0ZXJhdG9yICYmIHZhbHVlW3N5bUl0ZXJhdG9yXSkge1xuICAgICAgICByZXR1cm4gaXRlcmF0b3JUb0FycmF5KHZhbHVlW3N5bUl0ZXJhdG9yXSgpKTtcbiAgICAgIH1cbiAgICAgIHZhciB0YWcgPSBnZXRUYWcodmFsdWUpLFxuICAgICAgICAgIGZ1bmMgPSB0YWcgPT0gbWFwVGFnID8gbWFwVG9BcnJheSA6ICh0YWcgPT0gc2V0VGFnID8gc2V0VG9BcnJheSA6IHZhbHVlcyk7XG5cbiAgICAgIHJldHVybiBmdW5jKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgZmluaXRlIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjEyLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0Zpbml0ZSgzLjIpO1xuICAgICAqIC8vID0+IDMuMlxuICAgICAqXG4gICAgICogXy50b0Zpbml0ZShOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiA1ZS0zMjRcbiAgICAgKlxuICAgICAqIF8udG9GaW5pdGUoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IDEuNzk3NjkzMTM0ODYyMzE1N2UrMzA4XG4gICAgICpcbiAgICAgKiBfLnRvRmluaXRlKCczLjInKTtcbiAgICAgKiAvLyA9PiAzLjJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0Zpbml0ZSh2YWx1ZSkge1xuICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6IDA7XG4gICAgICB9XG4gICAgICB2YWx1ZSA9IHRvTnVtYmVyKHZhbHVlKTtcbiAgICAgIGlmICh2YWx1ZSA9PT0gSU5GSU5JVFkgfHwgdmFsdWUgPT09IC1JTkZJTklUWSkge1xuICAgICAgICB2YXIgc2lnbiA9ICh2YWx1ZSA8IDAgPyAtMSA6IDEpO1xuICAgICAgICByZXR1cm4gc2lnbiAqIE1BWF9JTlRFR0VSO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSA/IHZhbHVlIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGFuIGludGVnZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgbG9vc2VseSBiYXNlZCBvblxuICAgICAqIFtgVG9JbnRlZ2VyYF0oaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXRvaW50ZWdlcikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9JbnRlZ2VyKDMuMik7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy50b0ludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogXy50b0ludGVnZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IDEuNzk3NjkzMTM0ODYyMzE1N2UrMzA4XG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcignMy4yJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvSW50ZWdlcih2YWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHRvRmluaXRlKHZhbHVlKSxcbiAgICAgICAgICByZW1haW5kZXIgPSByZXN1bHQgJSAxO1xuXG4gICAgICByZXR1cm4gcmVzdWx0ID09PSByZXN1bHQgPyAocmVtYWluZGVyID8gcmVzdWx0IC0gcmVtYWluZGVyIDogcmVzdWx0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBpbnRlZ2VyIHN1aXRhYmxlIGZvciB1c2UgYXMgdGhlIGxlbmd0aCBvZiBhblxuICAgICAqIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uXG4gICAgICogW2BUb0xlbmd0aGBdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXRvbGVuZ3RoKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgaW50ZWdlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0xlbmd0aCgzLjIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8udG9MZW5ndGgoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogXy50b0xlbmd0aChJbmZpbml0eSk7XG4gICAgICogLy8gPT4gNDI5NDk2NzI5NVxuICAgICAqXG4gICAgICogXy50b0xlbmd0aCgnMy4yJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvTGVuZ3RoKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPyBiYXNlQ2xhbXAodG9JbnRlZ2VyKHZhbHVlKSwgMCwgTUFYX0FSUkFZX0xFTkdUSCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvTnVtYmVyKDMuMik7XG4gICAgICogLy8gPT4gMy4yXG4gICAgICpcbiAgICAgKiBfLnRvTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDVlLTMyNFxuICAgICAqXG4gICAgICogXy50b051bWJlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gSW5maW5pdHlcbiAgICAgKlxuICAgICAqIF8udG9OdW1iZXIoJzMuMicpO1xuICAgICAqIC8vID0+IDMuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvTnVtYmVyKHZhbHVlKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIE5BTjtcbiAgICAgIH1cbiAgICAgIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgdmFyIG90aGVyID0gdHlwZW9mIHZhbHVlLnZhbHVlT2YgPT0gJ2Z1bmN0aW9uJyA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgICAgICB2YWx1ZSA9IGlzT2JqZWN0KG90aGVyKSA/IChvdGhlciArICcnKSA6IG90aGVyO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6ICt2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHZhbHVlID0gYmFzZVRyaW0odmFsdWUpO1xuICAgICAgdmFyIGlzQmluYXJ5ID0gcmVJc0JpbmFyeS50ZXN0KHZhbHVlKTtcbiAgICAgIHJldHVybiAoaXNCaW5hcnkgfHwgcmVJc09jdGFsLnRlc3QodmFsdWUpKVxuICAgICAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICAgICAgOiAocmVJc0JhZEhleC50ZXN0KHZhbHVlKSA/IE5BTiA6ICt2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIHBsYWluIG9iamVjdCBmbGF0dGVuaW5nIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZ1xuICAgICAqIGtleWVkIHByb3BlcnRpZXMgb2YgYHZhbHVlYCB0byBvd24gcHJvcGVydGllcyBvZiB0aGUgcGxhaW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBwbGFpbiBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ2EnOiAxIH0sIG5ldyBGb28pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqXG4gICAgICogXy5hc3NpZ24oeyAnYSc6IDEgfSwgXy50b1BsYWluT2JqZWN0KG5ldyBGb28pKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0KHZhbHVlLCBrZXlzSW4odmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc2FmZSBpbnRlZ2VyLiBBIHNhZmUgaW50ZWdlciBjYW4gYmUgY29tcGFyZWQgYW5kXG4gICAgICogcmVwcmVzZW50ZWQgY29ycmVjdGx5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoMy4yKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogXy50b1NhZmVJbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiA5MDA3MTk5MjU0NzQwOTkxXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoJzMuMicpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1NhZmVJbnRlZ2VyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgPyBiYXNlQ2xhbXAodG9JbnRlZ2VyKHZhbHVlKSwgLU1BWF9TQUZFX0lOVEVHRVIsIE1BWF9TQUZFX0lOVEVHRVIpXG4gICAgICAgIDogKHZhbHVlID09PSAwID8gdmFsdWUgOiAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nLiBBbiBlbXB0eSBzdHJpbmcgaXMgcmV0dXJuZWQgZm9yIGBudWxsYFxuICAgICAqIGFuZCBgdW5kZWZpbmVkYCB2YWx1ZXMuIFRoZSBzaWduIG9mIGAtMGAgaXMgcHJlc2VydmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcobnVsbCk7XG4gICAgICogLy8gPT4gJydcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcoLTApO1xuICAgICAqIC8vID0+ICctMCdcbiAgICAgKlxuICAgICAqIF8udG9TdHJpbmcoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAnMSwyLDMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PSBudWxsID8gJycgOiBiYXNlVG9TdHJpbmcodmFsdWUpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2Ygc291cmNlIG9iamVjdHMgdG8gdGhlXG4gICAgICogZGVzdGluYXRpb24gb2JqZWN0LiBTb3VyY2Ugb2JqZWN0cyBhcmUgYXBwbGllZCBmcm9tIGxlZnQgdG8gcmlnaHQuXG4gICAgICogU3Vic2VxdWVudCBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyBzb3VyY2VzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAgYW5kIGlzIGxvb3NlbHkgYmFzZWQgb25cbiAgICAgKiBbYE9iamVjdC5hc3NpZ25gXShodHRwczovL21kbi5pby9PYmplY3QvYXNzaWduKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmFzc2lnbkluXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQmFyKCkge1xuICAgICAqICAgdGhpcy5jID0gMztcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmIgPSAyO1xuICAgICAqIEJhci5wcm90b3R5cGUuZCA9IDQ7XG4gICAgICpcbiAgICAgKiBfLmFzc2lnbih7ICdhJzogMCB9LCBuZXcgRm9vLCBuZXcgQmFyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzIH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIGlmIChpc1Byb3RvdHlwZShzb3VyY2UpIHx8IGlzQXJyYXlMaWtlKHNvdXJjZSkpIHtcbiAgICAgICAgY29weU9iamVjdChzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHtcbiAgICAgICAgICBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgc291cmNlW2tleV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBvd24gYW5kXG4gICAgICogaW5oZXJpdGVkIHNvdXJjZSBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAYWxpYXMgZXh0ZW5kXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5hc3NpZ25cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBCYXIoKSB7XG4gICAgICogICB0aGlzLmMgPSAzO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYiA9IDI7XG4gICAgICogQmFyLnByb3RvdHlwZS5kID0gNDtcbiAgICAgKlxuICAgICAqIF8uYXNzaWduSW4oeyAnYSc6IDAgfSwgbmV3IEZvbywgbmV3IEJhcik7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzLCAnZCc6IDQgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25JbiA9IGNyZWF0ZUFzc2lnbmVyKGZ1bmN0aW9uKG9iamVjdCwgc291cmNlKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbkluYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgYXNzaWduZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJuc1xuICAgICAqIGB1bmRlZmluZWRgLCBhc3NpZ25tZW50IGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgXG4gICAgICogaXMgaW52b2tlZCB3aXRoIGZpdmUgYXJndW1lbnRzOiAob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGFsaWFzIGV4dGVuZFdpdGhcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBzb3VyY2VzIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uYXNzaWduV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQob2JqVmFsdWUpID8gc3JjVmFsdWUgOiBvYmpWYWx1ZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZGVmYXVsdHMgPSBfLnBhcnRpYWxSaWdodChfLmFzc2lnbkluV2l0aCwgY3VzdG9taXplcik7XG4gICAgICpcbiAgICAgKiBkZWZhdWx0cyh7ICdhJzogMSB9LCB7ICdiJzogMiB9LCB7ICdhJzogMyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduSW5XaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCwgY3VzdG9taXplcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIGFzc2lnbmVkIHZhbHVlcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnNcbiAgICAgKiBgdW5kZWZpbmVkYCwgYXNzaWdubWVudCBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYFxuICAgICAqIGlzIGludm9rZWQgd2l0aCBmaXZlIGFyZ3VtZW50czogKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5hc3NpZ25JbldpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiBfLmlzVW5kZWZpbmVkKG9ialZhbHVlKSA/IHNyY1ZhbHVlIDogb2JqVmFsdWU7XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGRlZmF1bHRzID0gXy5wYXJ0aWFsUmlnaHQoXy5hc3NpZ25XaXRoLCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGRlZmF1bHRzKHsgJ2EnOiAxIH0sIHsgJ2InOiAyIH0sIHsgJ2EnOiAzIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25XaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QsIGN1c3RvbWl6ZXIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBgcGF0aHNgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHBpY2tlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogMyB9IH0sIDRdIH07XG4gICAgICpcbiAgICAgKiBfLmF0KG9iamVjdCwgWydhWzBdLmIuYycsICdhWzFdJ10pO1xuICAgICAqIC8vID0+IFszLCA0XVxuICAgICAqL1xuICAgIHZhciBhdCA9IGZsYXRSZXN0KGJhc2VBdCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gdGhlIGBwcm90b3R5cGVgIG9iamVjdC4gSWYgYVxuICAgICAqIGBwcm9wZXJ0aWVzYCBvYmplY3QgaXMgZ2l2ZW4sIGl0cyBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllc1xuICAgICAqIGFyZSBhc3NpZ25lZCB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHByb3RvdHlwZSBUaGUgb2JqZWN0IHRvIGluaGVyaXQgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3Byb3BlcnRpZXNdIFRoZSBwcm9wZXJ0aWVzIHRvIGFzc2lnbiB0byB0aGUgb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIFNoYXBlKCkge1xuICAgICAqICAgdGhpcy54ID0gMDtcbiAgICAgKiAgIHRoaXMueSA9IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQ2lyY2xlKCkge1xuICAgICAqICAgU2hhcGUuY2FsbCh0aGlzKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBDaXJjbGUucHJvdG90eXBlID0gXy5jcmVhdGUoU2hhcGUucHJvdG90eXBlLCB7XG4gICAgICogICAnY29uc3RydWN0b3InOiBDaXJjbGVcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHZhciBjaXJjbGUgPSBuZXcgQ2lyY2xlO1xuICAgICAqIGNpcmNsZSBpbnN0YW5jZW9mIENpcmNsZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjaXJjbGUgaW5zdGFuY2VvZiBTaGFwZTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlKHByb3RvdHlwZSwgcHJvcGVydGllcykge1xuICAgICAgdmFyIHJlc3VsdCA9IGJhc2VDcmVhdGUocHJvdG90eXBlKTtcbiAgICAgIHJldHVybiBwcm9wZXJ0aWVzID09IG51bGwgPyByZXN1bHQgOiBiYXNlQXNzaWduKHJlc3VsdCwgcHJvcGVydGllcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzIG9mIHNvdXJjZVxuICAgICAqIG9iamVjdHMgdG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdCBmb3IgYWxsIGRlc3RpbmF0aW9uIHByb3BlcnRpZXMgdGhhdFxuICAgICAqIHJlc29sdmUgdG8gYHVuZGVmaW5lZGAuIFNvdXJjZSBvYmplY3RzIGFyZSBhcHBsaWVkIGZyb20gbGVmdCB0byByaWdodC5cbiAgICAgKiBPbmNlIGEgcHJvcGVydHkgaXMgc2V0LCBhZGRpdGlvbmFsIHZhbHVlcyBvZiB0aGUgc2FtZSBwcm9wZXJ0eSBhcmUgaWdub3JlZC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5kZWZhdWx0c0RlZXBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0cyh7ICdhJzogMSB9LCB7ICdiJzogMiB9LCB7ICdhJzogMyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgZGVmYXVsdHMgPSBiYXNlUmVzdChmdW5jdGlvbihvYmplY3QsIHNvdXJjZXMpIHtcbiAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgIHZhciBsZW5ndGggPSBzb3VyY2VzLmxlbmd0aDtcbiAgICAgIHZhciBndWFyZCA9IGxlbmd0aCA+IDIgPyBzb3VyY2VzWzJdIDogdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoZ3VhcmQgJiYgaXNJdGVyYXRlZUNhbGwoc291cmNlc1swXSwgc291cmNlc1sxXSwgZ3VhcmQpKSB7XG4gICAgICAgIGxlbmd0aCA9IDE7XG4gICAgICB9XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2luZGV4XTtcbiAgICAgICAgdmFyIHByb3BzID0ga2V5c0luKHNvdXJjZSk7XG4gICAgICAgIHZhciBwcm9wc0luZGV4ID0gLTE7XG4gICAgICAgIHZhciBwcm9wc0xlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgICB3aGlsZSAoKytwcm9wc0luZGV4IDwgcHJvcHNMZW5ndGgpIHtcbiAgICAgICAgICB2YXIga2V5ID0gcHJvcHNbcHJvcHNJbmRleF07XG4gICAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W2tleV07XG5cbiAgICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgICAoZXEodmFsdWUsIG9iamVjdFByb3RvW2tleV0pICYmICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgICAgIG9iamVjdFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRlZmF1bHRzYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBhc3NpZ25zXG4gICAgICogZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4xMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5kZWZhdWx0c1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRzRGVlcCh7ICdhJzogeyAnYic6IDIgfSB9LCB7ICdhJzogeyAnYic6IDEsICdjJzogMyB9IH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdiJzogMiwgJ2MnOiAzIH0gfVxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0c0RlZXAgPSBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICBhcmdzLnB1c2godW5kZWZpbmVkLCBjdXN0b21EZWZhdWx0c01lcmdlKTtcbiAgICAgIHJldHVybiBhcHBseShtZXJnZVdpdGgsIHVuZGVmaW5lZCwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGtleSBvZiB0aGUgZmlyc3RcbiAgICAgKiBlbGVtZW50IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjEuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFJldHVybnMgdGhlIGtleSBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50LFxuICAgICAqICBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSB7XG4gICAgICogICAnYmFybmV5JzogIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgJ2ZyZWQnOiAgICB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZEtleSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2UgPCA0MDsgfSk7XG4gICAgICogLy8gPT4gJ2Jhcm5leScgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiAncGViYmxlcydcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZEtleShvYmplY3QsIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIGJhc2VGaW5kS2V5KG9iamVjdCwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgYmFzZUZvck93bik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kS2V5YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYSBjb2xsZWN0aW9uIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFJldHVybnMgdGhlIGtleSBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50LFxuICAgICAqICBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSB7XG4gICAgICogICAnYmFybmV5JzogIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgJ2ZyZWQnOiAgICB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3RLZXkodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlIDwgNDA7IH0pO1xuICAgICAqIC8vID0+IHJldHVybnMgJ3BlYmJsZXMnIGFzc3VtaW5nIGBfLmZpbmRLZXlgIHJldHVybnMgJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRMYXN0S2V5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gYmFzZUZpbmRLZXkob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBiYXNlRm9yT3duUmlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBhblxuICAgICAqIG9iamVjdCBhbmQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIHByb3BlcnR5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGtleSwgb2JqZWN0KS4gSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0XG4gICAgICogaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5mb3JJblJpZ2h0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvckluKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYScsICdiJywgdGhlbiAnYycgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9ySW4ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsXG4gICAgICAgID8gb2JqZWN0XG4gICAgICAgIDogYmFzZUZvcihvYmplY3QsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSwga2V5c0luKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvckluYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIHByb3BlcnRpZXMgb2ZcbiAgICAgKiBgb2JqZWN0YCBpbiB0aGUgb3Bwb3NpdGUgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5mb3JJblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JJblJpZ2h0KG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYycsICdiJywgdGhlbiAnYScgYXNzdW1pbmcgYF8uZm9ySW5gIGxvZ3MgJ2EnLCAnYicsIHRoZW4gJ2MnLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZvckluUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsXG4gICAgICAgID8gb2JqZWN0XG4gICAgICAgIDogYmFzZUZvclJpZ2h0KG9iamVjdCwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpLCBrZXlzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0IGFuZFxuICAgICAqIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgZWFjaCBwcm9wZXJ0eS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBrZXksIG9iamVjdCkuIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb25cbiAgICAgKiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMy4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uZm9yT3duUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9yT3duKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYScgdGhlbiAnYicgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgYmFzZUZvck93bihvYmplY3QsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mb3JPd25gIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllcyBvZlxuICAgICAqIGBvYmplY3RgIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmZvck93blxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JPd25SaWdodChuZXcgRm9vLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgJ2InIHRoZW4gJ2EnIGFzc3VtaW5nIGBfLmZvck93bmAgbG9ncyAnYScgdGhlbiAnYicuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yT3duUmlnaHQob2JqZWN0LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZnJvbSBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzXG4gICAgICogb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBuYW1lcy5cbiAgICAgKiBAc2VlIF8uZnVuY3Rpb25zSW5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmdW5jdGlvbnMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZnJvbSBvd24gYW5kIGluaGVyaXRlZFxuICAgICAqIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWVzLlxuICAgICAqIEBzZWUgXy5mdW5jdGlvbnNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZnVuY3Rpb25zSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzSW4ob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiB0aGUgcmVzb2x2ZWQgdmFsdWUgaXNcbiAgICAgKiBgdW5kZWZpbmVkYCwgdGhlIGBkZWZhdWx0VmFsdWVgIGlzIHJldHVybmVkIGluIGl0cyBwbGFjZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IFtkZWZhdWx0VmFsdWVdIFRoZSB2YWx1ZSByZXR1cm5lZCBmb3IgYHVuZGVmaW5lZGAgcmVzb2x2ZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uZ2V0KG9iamVjdCwgJ2FbMF0uYi5jJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCBbJ2EnLCAnMCcsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCAnYS5iLmMnLCAnZGVmYXVsdCcpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gZGVmYXVsdFZhbHVlIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3QgcHJvcGVydHkgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgcGF0aGAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogeyAnYic6IDIgfSB9O1xuICAgICAqIHZhciBvdGhlciA9IF8uY3JlYXRlKHsgJ2EnOiBfLmNyZWF0ZSh7ICdiJzogMiB9KSB9KTtcbiAgICAgKlxuICAgICAqIF8uaGFzKG9iamVjdCwgJ2EnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsICdhLmInKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsIFsnYScsICdiJ10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzKG90aGVyLCAnYScpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzKG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIG9iamVjdCAhPSBudWxsICYmIGhhc1BhdGgob2JqZWN0LCBwYXRoLCBiYXNlSGFzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHBhdGhgIGlzIGEgZGlyZWN0IG9yIGluaGVyaXRlZCBwcm9wZXJ0eSBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBwYXRoYCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IF8uY3JlYXRlKHsgJ2EnOiBfLmNyZWF0ZSh7ICdiJzogMiB9KSB9KTtcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYS5iJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXNJbihvYmplY3QsIFsnYScsICdiJ10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzSW4ob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICE9IG51bGwgJiYgaGFzUGF0aChvYmplY3QsIHBhdGgsIGJhc2VIYXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIGludmVydGVkIGtleXMgYW5kIHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKiBJZiBgb2JqZWN0YCBjb250YWlucyBkdXBsaWNhdGUgdmFsdWVzLCBzdWJzZXF1ZW50IHZhbHVlcyBvdmVyd3JpdGVcbiAgICAgKiBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgaW52ZXJ0ZWQgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiwgJ2MnOiAxIH07XG4gICAgICpcbiAgICAgKiBfLmludmVydChvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzEnOiAnYycsICcyJzogJ2InIH1cbiAgICAgKi9cbiAgICB2YXIgaW52ZXJ0ID0gY3JlYXRlSW52ZXJ0ZXIoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICBpZiAodmFsdWUgIT0gbnVsbCAmJlxuICAgICAgICAgIHR5cGVvZiB2YWx1ZS50b1N0cmluZyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHZhbHVlID0gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHJlc3VsdFt2YWx1ZV0gPSBrZXk7XG4gICAgfSwgY29uc3RhbnQoaWRlbnRpdHkpKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW52ZXJ0YCBleGNlcHQgdGhhdCB0aGUgaW52ZXJ0ZWQgb2JqZWN0IGlzIGdlbmVyYXRlZFxuICAgICAqIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZyBlYWNoIGVsZW1lbnQgb2YgYG9iamVjdGAgdGhydSBgaXRlcmF0ZWVgLiBUaGVcbiAgICAgKiBjb3JyZXNwb25kaW5nIGludmVydGVkIHZhbHVlIG9mIGVhY2ggaW52ZXJ0ZWQga2V5IGlzIGFuIGFycmF5IG9mIGtleXNcbiAgICAgKiByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUgaW52ZXJ0ZWQgdmFsdWUuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9O1xuICAgICAqXG4gICAgICogXy5pbnZlcnRCeShvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzEnOiBbJ2EnLCAnYyddLCAnMic6IFsnYiddIH1cbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0Qnkob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgcmV0dXJuICdncm91cCcgKyB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdncm91cDEnOiBbJ2EnLCAnYyddLCAnZ3JvdXAyJzogWydiJ10gfVxuICAgICAqL1xuICAgIHZhciBpbnZlcnRCeSA9IGNyZWF0ZUludmVydGVyKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiZcbiAgICAgICAgICB0eXBlb2YgdmFsdWUudG9TdHJpbmcgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB2YWx1ZSA9IG5hdGl2ZU9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIHZhbHVlKSkge1xuICAgICAgICByZXN1bHRbdmFsdWVdLnB1c2goa2V5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFt2YWx1ZV0gPSBba2V5XTtcbiAgICAgIH1cbiAgICB9LCBnZXRJdGVyYXRlZSk7XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogWzEsIDIsIDMsIDRdIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uaW52b2tlKG9iamVjdCwgJ2FbMF0uYi5jLnNsaWNlJywgMSwgMyk7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICovXG4gICAgdmFyIGludm9rZSA9IGJhc2VSZXN0KGJhc2VJbnZva2UpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy4gU2VlIHRoZVxuICAgICAqIFtFUyBzcGVjXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3Qua2V5cylcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5rZXlzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIF8ua2V5cygnaGknKTtcbiAgICAgKiAvLyA9PiBbJzAnLCAnMSddXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBpc0FycmF5TGlrZShvYmplY3QpID8gYXJyYXlMaWtlS2V5cyhvYmplY3QpIDogYmFzZUtleXMob2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmtleXNJbihuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBrZXlzSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2Uob2JqZWN0KSA/IGFycmF5TGlrZUtleXMob2JqZWN0LCB0cnVlKSA6IGJhc2VLZXlzSW4ob2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ubWFwVmFsdWVzYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3Qgd2l0aCB0aGVcbiAgICAgKiBzYW1lIHZhbHVlcyBhcyBgb2JqZWN0YCBhbmQga2V5cyBnZW5lcmF0ZWQgYnkgcnVubmluZyBlYWNoIG93biBlbnVtZXJhYmxlXG4gICAgICogc3RyaW5nIGtleWVkIHByb3BlcnR5IG9mIGBvYmplY3RgIHRocnUgYGl0ZXJhdGVlYC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBrZXksIG9iamVjdCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy44LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIG9iamVjdC5cbiAgICAgKiBAc2VlIF8ubWFwVmFsdWVzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwS2V5cyh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIHJldHVybiBrZXkgKyB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdhMSc6IDEsICdiMic6IDIgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcEtleXMob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyk7XG5cbiAgICAgIGJhc2VGb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwgaXRlcmF0ZWUodmFsdWUsIGtleSwgb2JqZWN0KSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyBgb2JqZWN0YCBhbmQgdmFsdWVzIGdlbmVyYXRlZFxuICAgICAqIGJ5IHJ1bm5pbmcgZWFjaCBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydHkgb2YgYG9iamVjdGAgdGhydVxuICAgICAqIGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuNC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBvYmplY3QuXG4gICAgICogQHNlZSBfLm1hcEtleXNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2ZyZWQnOiAgICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1hcFZhbHVlcyh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2U7IH0pO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiA0MCwgJ3BlYmJsZXMnOiAxIH0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ubWFwVmFsdWVzKHVzZXJzLCAnYWdlJyk7XG4gICAgICogLy8gPT4geyAnZnJlZCc6IDQwLCAncGViYmxlcyc6IDEgfSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcFZhbHVlcyhvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKTtcblxuICAgICAgYmFzZUZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUocmVzdWx0LCBrZXksIGl0ZXJhdGVlKHZhbHVlLCBrZXksIG9iamVjdCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBtZXJnZXMgb3duIGFuZFxuICAgICAqIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzIG9mIHNvdXJjZSBvYmplY3RzIGludG8gdGhlXG4gICAgICogZGVzdGluYXRpb24gb2JqZWN0LiBTb3VyY2UgcHJvcGVydGllcyB0aGF0IHJlc29sdmUgdG8gYHVuZGVmaW5lZGAgYXJlXG4gICAgICogc2tpcHBlZCBpZiBhIGRlc3RpbmF0aW9uIHZhbHVlIGV4aXN0cy4gQXJyYXkgYW5kIHBsYWluIG9iamVjdCBwcm9wZXJ0aWVzXG4gICAgICogYXJlIG1lcmdlZCByZWN1cnNpdmVseS4gT3RoZXIgb2JqZWN0cyBhbmQgdmFsdWUgdHlwZXMgYXJlIG92ZXJyaWRkZW4gYnlcbiAgICAgKiBhc3NpZ25tZW50LiBTb3VyY2Ugb2JqZWN0cyBhcmUgYXBwbGllZCBmcm9tIGxlZnQgdG8gcmlnaHQuIFN1YnNlcXVlbnRcbiAgICAgKiBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91cyBzb3VyY2VzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC41LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7XG4gICAgICogICAnYSc6IFt7ICdiJzogMiB9LCB7ICdkJzogNCB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgb3RoZXIgPSB7XG4gICAgICogICAnYSc6IFt7ICdjJzogMyB9LCB7ICdlJzogNSB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1lcmdlKG9iamVjdCwgb3RoZXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbeyAnYic6IDIsICdjJzogMyB9LCB7ICdkJzogNCwgJ2UnOiA1IH1dIH1cbiAgICAgKi9cbiAgICB2YXIgbWVyZ2UgPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgpIHtcbiAgICAgIGJhc2VNZXJnZShvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5tZXJnZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIG1lcmdlZCB2YWx1ZXMgb2YgdGhlIGRlc3RpbmF0aW9uIGFuZCBzb3VyY2VcbiAgICAgKiBwcm9wZXJ0aWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCwgbWVyZ2luZyBpcyBoYW5kbGVkIGJ5IHRoZVxuICAgICAqIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aCBzaXggYXJndW1lbnRzOlxuICAgICAqIChvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNBcnJheShvYmpWYWx1ZSkpIHtcbiAgICAgKiAgICAgcmV0dXJuIG9ialZhbHVlLmNvbmNhdChzcmNWYWx1ZSk7XG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbMV0sICdiJzogWzJdIH07XG4gICAgICogdmFyIG90aGVyID0geyAnYSc6IFszXSwgJ2InOiBbNF0gfTtcbiAgICAgKlxuICAgICAqIF8ubWVyZ2VXaXRoKG9iamVjdCwgb3RoZXIsIGN1c3RvbWl6ZXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbMSwgM10sICdiJzogWzIsIDRdIH1cbiAgICAgKi9cbiAgICB2YXIgbWVyZ2VXaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5waWNrYDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlXG4gICAgICogb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBwYXRocyBvZiBgb2JqZWN0YCB0aGF0IGFyZSBub3Qgb21pdHRlZC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBjb25zaWRlcmFibHkgc2xvd2VyIHRoYW4gYF8ucGlja2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBvbWl0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5vbWl0KG9iamVjdCwgWydhJywgJ2MnXSk7XG4gICAgICogLy8gPT4geyAnYic6ICcyJyB9XG4gICAgICovXG4gICAgdmFyIG9taXQgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIHBhdGhzKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHZhciBpc0RlZXAgPSBmYWxzZTtcbiAgICAgIHBhdGhzID0gYXJyYXlNYXAocGF0aHMsIGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG4gICAgICAgIGlzRGVlcCB8fCAoaXNEZWVwID0gcGF0aC5sZW5ndGggPiAxKTtcbiAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICB9KTtcbiAgICAgIGNvcHlPYmplY3Qob2JqZWN0LCBnZXRBbGxLZXlzSW4ob2JqZWN0KSwgcmVzdWx0KTtcbiAgICAgIGlmIChpc0RlZXApIHtcbiAgICAgICAgcmVzdWx0ID0gYmFzZUNsb25lKHJlc3VsdCwgQ0xPTkVfREVFUF9GTEFHIHwgQ0xPTkVfRkxBVF9GTEFHIHwgQ0xPTkVfU1lNQk9MU19GTEFHLCBjdXN0b21PbWl0Q2xvbmUpO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IHBhdGhzLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBiYXNlVW5zZXQocmVzdWx0LCBwYXRoc1tsZW5ndGhdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucGlja0J5YDsgdGhpcyBtZXRob2QgY3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2ZcbiAgICAgKiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBgb2JqZWN0YCB0aGF0XG4gICAgICogYHByZWRpY2F0ZWAgZG9lc24ndCByZXR1cm4gdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdHdvXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGtleSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdEJ5KG9iamVjdCwgXy5pc051bWJlcik7XG4gICAgICogLy8gPT4geyAnYic6ICcyJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gb21pdEJ5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gcGlja0J5KG9iamVjdCwgbmVnYXRlKGdldEl0ZXJhdGVlKHByZWRpY2F0ZSkpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgcGlja2VkIGBvYmplY3RgIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5waWNrKG9iamVjdCwgWydhJywgJ2MnXSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdjJzogMyB9XG4gICAgICovXG4gICAgdmFyIHBpY2sgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIHBhdGhzKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB7fSA6IGJhc2VQaWNrKG9iamVjdCwgcGF0aHMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIGBvYmplY3RgIHByb3BlcnRpZXMgYHByZWRpY2F0ZWAgcmV0dXJuc1xuICAgICAqIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6ICh2YWx1ZSwga2V5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIHByb3BlcnR5LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAnMicsICdjJzogMyB9O1xuICAgICAqXG4gICAgICogXy5waWNrQnkob2JqZWN0LCBfLmlzTnVtYmVyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwaWNrQnkob2JqZWN0LCBwcmVkaWNhdGUpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgICB9XG4gICAgICB2YXIgcHJvcHMgPSBhcnJheU1hcChnZXRBbGxLZXlzSW4ob2JqZWN0KSwgZnVuY3Rpb24ocHJvcCkge1xuICAgICAgICByZXR1cm4gW3Byb3BdO1xuICAgICAgfSk7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUpO1xuICAgICAgcmV0dXJuIGJhc2VQaWNrQnkob2JqZWN0LCBwcm9wcywgZnVuY3Rpb24odmFsdWUsIHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIHByZWRpY2F0ZSh2YWx1ZSwgcGF0aFswXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmdldGAgZXhjZXB0IHRoYXQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGFcbiAgICAgKiBmdW5jdGlvbiBpdCdzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgaXRzIHBhcmVudCBvYmplY3QgYW5kXG4gICAgICogaXRzIHJlc3VsdCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHJlc29sdmUuXG4gICAgICogQHBhcmFtIHsqfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgcmV0dXJuZWQgZm9yIGB1bmRlZmluZWRgIHJlc29sdmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjMSc6IDMsICdjMic6IF8uY29uc3RhbnQoNCkgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMxJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMyJyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMzJywgJ2RlZmF1bHQnKTtcbiAgICAgKiAvLyA9PiAnZGVmYXVsdCdcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KG9iamVjdCwgJ2FbMF0uYi5jMycsIF8uY29uc3RhbnQoJ2RlZmF1bHQnKSk7XG4gICAgICogLy8gPT4gJ2RlZmF1bHQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzdWx0KG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGg7XG5cbiAgICAgIC8vIEVuc3VyZSB0aGUgbG9vcCBpcyBlbnRlcmVkIHdoZW4gcGF0aCBpcyBlbXB0eS5cbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIGxlbmd0aCA9IDE7XG4gICAgICAgIG9iamVjdCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W3RvS2V5KHBhdGhbaW5kZXhdKV07XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaW5kZXggPSBsZW5ndGg7XG4gICAgICAgICAgdmFsdWUgPSBkZWZhdWx0VmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0ID0gaXNGdW5jdGlvbih2YWx1ZSkgPyB2YWx1ZS5jYWxsKG9iamVjdCkgOiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiBhIHBvcnRpb24gb2YgYHBhdGhgIGRvZXNuJ3QgZXhpc3QsXG4gICAgICogaXQncyBjcmVhdGVkLiBBcnJheXMgYXJlIGNyZWF0ZWQgZm9yIG1pc3NpbmcgaW5kZXggcHJvcGVydGllcyB3aGlsZSBvYmplY3RzXG4gICAgICogYXJlIGNyZWF0ZWQgZm9yIGFsbCBvdGhlciBtaXNzaW5nIHByb3BlcnRpZXMuIFVzZSBgXy5zZXRXaXRoYCB0byBjdXN0b21pemVcbiAgICAgKiBgcGF0aGAgY3JlYXRpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogMyB9IH1dIH07XG4gICAgICpcbiAgICAgKiBfLnNldChvYmplY3QsICdhWzBdLmIuYycsIDQpO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC5hWzBdLmIuYyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5zZXQob2JqZWN0LCBbJ3gnLCAnMCcsICd5JywgJ3onXSwgNSk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LnhbMF0ueS56KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0KG9iamVjdCwgcGF0aCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IGJhc2VTZXQob2JqZWN0LCBwYXRoLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zZXRgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCB0byBwcm9kdWNlIHRoZSBvYmplY3RzIG9mIGBwYXRoYC4gIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgXG4gICAgICogcGF0aCBjcmVhdGlvbiBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6IChuc1ZhbHVlLCBrZXksIG5zT2JqZWN0KS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7fTtcbiAgICAgKlxuICAgICAqIF8uc2V0V2l0aChvYmplY3QsICdbMF1bMV0nLCAnYScsIE9iamVjdCk7XG4gICAgICogLy8gPT4geyAnMCc6IHsgJzEnOiAnYScgfSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0V2l0aChvYmplY3QsIHBhdGgsIHZhbHVlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUsIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkLXZhbHVlIHBhaXJzIGZvciBgb2JqZWN0YFxuICAgICAqIHdoaWNoIGNhbiBiZSBjb25zdW1lZCBieSBgXy5mcm9tUGFpcnNgLiBJZiBgb2JqZWN0YCBpcyBhIG1hcCBvciBzZXQsIGl0c1xuICAgICAqIGVudHJpZXMgYXJlIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGFsaWFzIGVudHJpZXNcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxXSwgWydiJywgMl1dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgdmFyIHRvUGFpcnMgPSBjcmVhdGVUb1BhaXJzKGtleXMpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZC12YWx1ZSBwYWlyc1xuICAgICAqIGZvciBgb2JqZWN0YCB3aGljaCBjYW4gYmUgY29uc3VtZWQgYnkgYF8uZnJvbVBhaXJzYC4gSWYgYG9iamVjdGAgaXMgYSBtYXBcbiAgICAgKiBvciBzZXQsIGl0cyBlbnRyaWVzIGFyZSByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBhbGlhcyBlbnRyaWVzSW5cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gW1snYScsIDFdLCBbJ2InLCAyXSwgWydjJywgM11dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgdmFyIHRvUGFpcnNJbiA9IGNyZWF0ZVRvUGFpcnMoa2V5c0luKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGFsdGVybmF0aXZlIHRvIGBfLnJlZHVjZWA7IHRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYG9iamVjdGAgdG8gYSBuZXdcbiAgICAgKiBgYWNjdW11bGF0b3JgIG9iamVjdCB3aGljaCBpcyB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgZWFjaCBvZiBpdHMgb3duXG4gICAgICogZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyB0aHJ1IGBpdGVyYXRlZWAsIHdpdGggZWFjaCBpbnZvY2F0aW9uXG4gICAgICogcG90ZW50aWFsbHkgbXV0YXRpbmcgdGhlIGBhY2N1bXVsYXRvcmAgb2JqZWN0LiBJZiBgYWNjdW11bGF0b3JgIGlzIG5vdFxuICAgICAqIHByb3ZpZGVkLCBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgc2FtZSBgW1tQcm90b3R5cGVdXWAgd2lsbCBiZSB1c2VkLiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6IChhY2N1bXVsYXRvciwgdmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGN1c3RvbSBhY2N1bXVsYXRvciB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJhbnNmb3JtKFsyLCAzLCA0XSwgZnVuY3Rpb24ocmVzdWx0LCBuKSB7XG4gICAgICogICByZXN1bHQucHVzaChuICo9IG4pO1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDA7XG4gICAgICogfSwgW10pO1xuICAgICAqIC8vID0+IFs0LCA5XVxuICAgICAqXG4gICAgICogXy50cmFuc2Zvcm0oeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAxIH0sIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAqICAgKHJlc3VsdFt2YWx1ZV0gfHwgKHJlc3VsdFt2YWx1ZV0gPSBbXSkpLnB1c2goa2V5KTtcbiAgICAgKiB9LCB7fSk7XG4gICAgICogLy8gPT4geyAnMSc6IFsnYScsICdjJ10sICcyJzogWydiJ10gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybShvYmplY3QsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgdmFyIGlzQXJyID0gaXNBcnJheShvYmplY3QpLFxuICAgICAgICAgIGlzQXJyTGlrZSA9IGlzQXJyIHx8IGlzQnVmZmVyKG9iamVjdCkgfHwgaXNUeXBlZEFycmF5KG9iamVjdCk7XG5cbiAgICAgIGl0ZXJhdGVlID0gZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDQpO1xuICAgICAgaWYgKGFjY3VtdWxhdG9yID09IG51bGwpIHtcbiAgICAgICAgdmFyIEN0b3IgPSBvYmplY3QgJiYgb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgICBpZiAoaXNBcnJMaWtlKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSBpc0FyciA/IG5ldyBDdG9yIDogW107XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yID0gaXNGdW5jdGlvbihDdG9yKSA/IGJhc2VDcmVhdGUoZ2V0UHJvdG90eXBlKG9iamVjdCkpIDoge307XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgKGlzQXJyTGlrZSA/IGFycmF5RWFjaCA6IGJhc2VGb3JPd24pKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdGVlKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBwcm9wZXJ0eSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byB1bnNldC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHByb3BlcnR5IGlzIGRlbGV0ZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiA3IH0gfV0gfTtcbiAgICAgKiBfLnVuc2V0KG9iamVjdCwgJ2FbMF0uYi5jJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogW3sgJ2InOiB7fSB9XSB9O1xuICAgICAqXG4gICAgICogXy51bnNldChvYmplY3QsIFsnYScsICcwJywgJ2InLCAnYyddKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbeyAnYic6IHt9IH1dIH07XG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5zZXQob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB0cnVlIDogYmFzZVVuc2V0KG9iamVjdCwgcGF0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zZXRgIGV4Y2VwdCB0aGF0IGFjY2VwdHMgYHVwZGF0ZXJgIHRvIHByb2R1Y2UgdGhlXG4gICAgICogdmFsdWUgdG8gc2V0LiBVc2UgYF8udXBkYXRlV2l0aGAgdG8gY3VzdG9taXplIGBwYXRoYCBjcmVhdGlvbi4gVGhlIGB1cGRhdGVyYFxuICAgICAqIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjYuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlciBUaGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy51cGRhdGUob2JqZWN0LCAnYVswXS5iLmMnLCBmdW5jdGlvbihuKSB7IHJldHVybiBuICogbjsgfSk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LmFbMF0uYi5jKTtcbiAgICAgKiAvLyA9PiA5XG4gICAgICpcbiAgICAgKiBfLnVwZGF0ZShvYmplY3QsICd4WzBdLnkueicsIGZ1bmN0aW9uKG4pIHsgcmV0dXJuIG4gPyBuICsgMSA6IDA7IH0pO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC54WzBdLnkueik7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVwZGF0ZShvYmplY3QsIHBhdGgsIHVwZGF0ZXIpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IGJhc2VVcGRhdGUob2JqZWN0LCBwYXRoLCBjYXN0RnVuY3Rpb24odXBkYXRlcikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udXBkYXRlYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgb2JqZWN0cyBvZiBgcGF0aGAuICBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIHBhdGggY3JlYXRpb24gaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAobnNWYWx1ZSwga2V5LCBuc09iamVjdCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjYuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlciBUaGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHt9O1xuICAgICAqXG4gICAgICogXy51cGRhdGVXaXRoKG9iamVjdCwgJ1swXVsxXScsIF8uY29uc3RhbnQoJ2EnKSwgT2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICcwJzogeyAnMSc6ICdhJyB9IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGVXaXRoKG9iamVjdCwgcGF0aCwgdXBkYXRlciwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogYmFzZVVwZGF0ZShvYmplY3QsIHBhdGgsIGNhc3RGdW5jdGlvbih1cGRhdGVyKSwgY3VzdG9taXplcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBOb24tb2JqZWN0IHZhbHVlcyBhcmUgY29lcmNlZCB0byBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8udmFsdWVzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogXy52YWx1ZXMoJ2hpJyk7XG4gICAgICogLy8gPT4gWydoJywgJ2knXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IFtdIDogYmFzZVZhbHVlcyhvYmplY3QsIGtleXMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydHlcbiAgICAgKiB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLnZhbHVlc0luKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlc0luKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gW10gOiBiYXNlVmFsdWVzKG9iamVjdCwga2V5c0luKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyBgbnVtYmVyYCB3aXRoaW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gY2xhbXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsb3dlcl0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY2xhbXBlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoLTEwLCAtNSwgNSk7XG4gICAgICogLy8gPT4gLTVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoMTAsIC01LCA1KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmICh1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHVwcGVyID0gbG93ZXI7XG4gICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKHVwcGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdXBwZXIgPSB0b051bWJlcih1cHBlcik7XG4gICAgICAgIHVwcGVyID0gdXBwZXIgPT09IHVwcGVyID8gdXBwZXIgOiAwO1xuICAgICAgfVxuICAgICAgaWYgKGxvd2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbG93ZXIgPSB0b051bWJlcihsb3dlcik7XG4gICAgICAgIGxvd2VyID0gbG93ZXIgPT09IGxvd2VyID8gbG93ZXIgOiAwO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VDbGFtcCh0b051bWJlcihudW1iZXIpLCBsb3dlciwgdXBwZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgbmAgaXMgYmV0d2VlbiBgc3RhcnRgIGFuZCB1cCB0bywgYnV0IG5vdCBpbmNsdWRpbmcsIGBlbmRgLiBJZlxuICAgICAqIGBlbmRgIGlzIG5vdCBzcGVjaWZpZWQsIGl0J3Mgc2V0IHRvIGBzdGFydGAgd2l0aCBgc3RhcnRgIHRoZW4gc2V0IHRvIGAwYC5cbiAgICAgKiBJZiBgc3RhcnRgIGlzIGdyZWF0ZXIgdGhhbiBgZW5kYCB0aGUgcGFyYW1zIGFyZSBzd2FwcGVkIHRvIHN1cHBvcnRcbiAgICAgKiBuZWdhdGl2ZSByYW5nZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgbnVtYmVyYCBpcyBpbiB0aGUgcmFuZ2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8ucmFuZ2UsIF8ucmFuZ2VSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoMywgMiwgNCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDQsIDgpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSg0LCAyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDIsIDIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoMS4yLCAyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoNS4yLCA0KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKC0zLCAtMiwgLTYpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCkge1xuICAgICAgc3RhcnQgPSB0b0Zpbml0ZShzdGFydCk7XG4gICAgICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVuZCA9IHRvRmluaXRlKGVuZCk7XG4gICAgICB9XG4gICAgICBudW1iZXIgPSB0b051bWJlcihudW1iZXIpO1xuICAgICAgcmV0dXJuIGJhc2VJblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvZHVjZXMgYSByYW5kb20gbnVtYmVyIGJldHdlZW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKiBJZiBvbmx5IG9uZSBhcmd1bWVudCBpcyBwcm92aWRlZCBhIG51bWJlciBiZXR3ZWVuIGAwYCBhbmQgdGhlIGdpdmVuIG51bWJlclxuICAgICAqIGlzIHJldHVybmVkLiBJZiBgZmxvYXRpbmdgIGlzIGB0cnVlYCwgb3IgZWl0aGVyIGBsb3dlcmAgb3IgYHVwcGVyYCBhcmVcbiAgICAgKiBmbG9hdHMsIGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyIGlzIHJldHVybmVkIGluc3RlYWQgb2YgYW4gaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNy4wXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbG93ZXI9MF0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdXBwZXI9MV0gVGhlIHVwcGVyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zsb2F0aW5nXSBTcGVjaWZ5IHJldHVybmluZyBhIGZsb2F0aW5nLXBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgwLCA1KTtcbiAgICAgKiAvLyA9PiBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSk7XG4gICAgICogLy8gPT4gYWxzbyBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSwgdHJ1ZSk7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAwIGFuZCA1XG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgxLjIsIDUuMik7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAxLjIgYW5kIDUuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJhbmRvbShsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSB7XG4gICAgICBpZiAoZmxvYXRpbmcgJiYgdHlwZW9mIGZsb2F0aW5nICE9ICdib29sZWFuJyAmJiBpc0l0ZXJhdGVlQ2FsbChsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSkge1xuICAgICAgICB1cHBlciA9IGZsb2F0aW5nID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1cHBlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IHVwcGVyO1xuICAgICAgICAgIHVwcGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBsb3dlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IGxvd2VyO1xuICAgICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG93ZXIgPT09IHVuZGVmaW5lZCAmJiB1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxvd2VyID0gMDtcbiAgICAgICAgdXBwZXIgPSAxO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGxvd2VyID0gdG9GaW5pdGUobG93ZXIpO1xuICAgICAgICBpZiAodXBwZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHVwcGVyID0gbG93ZXI7XG4gICAgICAgICAgbG93ZXIgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVwcGVyID0gdG9GaW5pdGUodXBwZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG93ZXIgPiB1cHBlcikge1xuICAgICAgICB2YXIgdGVtcCA9IGxvd2VyO1xuICAgICAgICBsb3dlciA9IHVwcGVyO1xuICAgICAgICB1cHBlciA9IHRlbXA7XG4gICAgICB9XG4gICAgICBpZiAoZmxvYXRpbmcgfHwgbG93ZXIgJSAxIHx8IHVwcGVyICUgMSkge1xuICAgICAgICB2YXIgcmFuZCA9IG5hdGl2ZVJhbmRvbSgpO1xuICAgICAgICByZXR1cm4gbmF0aXZlTWluKGxvd2VyICsgKHJhbmQgKiAodXBwZXIgLSBsb3dlciArIGZyZWVQYXJzZUZsb2F0KCcxZS0nICsgKChyYW5kICsgJycpLmxlbmd0aCAtIDEpKSkpLCB1cHBlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVJhbmRvbShsb3dlciwgdXBwZXIpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIFtjYW1lbCBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DYW1lbENhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY2FtZWwgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNhbWVsQ2FzZSgnRm9vIEJhcicpO1xuICAgICAqIC8vID0+ICdmb29CYXInXG4gICAgICpcbiAgICAgKiBfLmNhbWVsQ2FzZSgnLS1mb28tYmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJ19fRk9PX0JBUl9fJyk7XG4gICAgICogLy8gPT4gJ2Zvb0JhcidcbiAgICAgKi9cbiAgICB2YXIgY2FtZWxDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICB3b3JkID0gd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/IGNhcGl0YWxpemUod29yZCkgOiB3b3JkKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgYHN0cmluZ2AgdG8gdXBwZXIgY2FzZSBhbmQgdGhlIHJlbWFpbmluZ1xuICAgICAqIHRvIGxvd2VyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FwaXRhbGl6ZSgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdGcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgICByZXR1cm4gdXBwZXJGaXJzdCh0b1N0cmluZyhzdHJpbmcpLnRvTG93ZXJDYXNlKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlYnVycnMgYHN0cmluZ2AgYnkgY29udmVydGluZ1xuICAgICAqIFtMYXRpbi0xIFN1cHBsZW1lbnRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhdGluLTFfU3VwcGxlbWVudF8oVW5pY29kZV9ibG9jaykjQ2hhcmFjdGVyX3RhYmxlKVxuICAgICAqIGFuZCBbTGF0aW4gRXh0ZW5kZWQtQV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW5fRXh0ZW5kZWQtQSlcbiAgICAgKiBsZXR0ZXJzIHRvIGJhc2ljIExhdGluIGxldHRlcnMgYW5kIHJlbW92aW5nXG4gICAgICogW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBkZWJ1cnIuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlYnVycignZMOpasOgIHZ1Jyk7XG4gICAgICogLy8gPT4gJ2RlamEgdnUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVidXJyKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcgJiYgc3RyaW5nLnJlcGxhY2UocmVMYXRpbiwgZGVidXJyTGV0dGVyKS5yZXBsYWNlKHJlQ29tYm9NYXJrLCAnJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBzdHJpbmdgIGVuZHMgd2l0aCB0aGUgZ2l2ZW4gdGFyZ2V0IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSBUaGUgc3RyaW5nIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwb3NpdGlvbj1zdHJpbmcubGVuZ3RoXSBUaGUgcG9zaXRpb24gdG8gc2VhcmNoIHVwIHRvLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgc3RyaW5nYCBlbmRzIHdpdGggYHRhcmdldGAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lbmRzV2l0aCgnYWJjJywgJ2MnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYicsIDIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlbmRzV2l0aChzdHJpbmcsIHRhcmdldCwgcG9zaXRpb24pIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICB0YXJnZXQgPSBiYXNlVG9TdHJpbmcodGFyZ2V0KTtcblxuICAgICAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBsZW5ndGhcbiAgICAgICAgOiBiYXNlQ2xhbXAodG9JbnRlZ2VyKHBvc2l0aW9uKSwgMCwgbGVuZ3RoKTtcblxuICAgICAgdmFyIGVuZCA9IHBvc2l0aW9uO1xuICAgICAgcG9zaXRpb24gLT0gdGFyZ2V0Lmxlbmd0aDtcbiAgICAgIHJldHVybiBwb3NpdGlvbiA+PSAwICYmIHN0cmluZy5zbGljZShwb3NpdGlvbiwgZW5kKSA9PSB0YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGNoYXJhY3RlcnMgXCImXCIsIFwiPFwiLCBcIj5cIiwgJ1wiJywgYW5kIFwiJ1wiIGluIGBzdHJpbmdgIHRvIHRoZWlyXG4gICAgICogY29ycmVzcG9uZGluZyBIVE1MIGVudGl0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vIG90aGVyIGNoYXJhY3RlcnMgYXJlIGVzY2FwZWQuIFRvIGVzY2FwZSBhZGRpdGlvbmFsXG4gICAgICogY2hhcmFjdGVycyB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBUaG91Z2ggdGhlIFwiPlwiIGNoYXJhY3RlciBpcyBlc2NhcGVkIGZvciBzeW1tZXRyeSwgY2hhcmFjdGVycyBsaWtlXG4gICAgICogXCI+XCIgYW5kIFwiL1wiIGRvbid0IG5lZWQgZXNjYXBpbmcgaW4gSFRNTCBhbmQgaGF2ZSBubyBzcGVjaWFsIG1lYW5pbmdcbiAgICAgKiB1bmxlc3MgdGhleSdyZSBwYXJ0IG9mIGEgdGFnIG9yIHVucXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZS4gU2VlXG4gICAgICogW01hdGhpYXMgQnluZW5zJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2FtYmlndW91cy1hbXBlcnNhbmRzKVxuICAgICAqICh1bmRlciBcInNlbWktcmVsYXRlZCBmdW4gZmFjdFwiKSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogV2hlbiB3b3JraW5nIHdpdGggSFRNTCB5b3Ugc2hvdWxkIGFsd2F5c1xuICAgICAqIFtxdW90ZSBhdHRyaWJ1dGUgdmFsdWVzXShodHRwOi8vd29ua28uY29tL3Bvc3QvaHRtbC1lc2NhcGluZykgdG8gcmVkdWNlXG4gICAgICogWFNTIHZlY3RvcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gZXNjYXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmVzY2FwZSgnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVzY2FwZShzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gKHN0cmluZyAmJiByZUhhc1VuZXNjYXBlZEh0bWwudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlVW5lc2NhcGVkSHRtbCwgZXNjYXBlSHRtbENoYXIpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZXMgdGhlIGBSZWdFeHBgIHNwZWNpYWwgY2hhcmFjdGVycyBcIl5cIiwgXCIkXCIsIFwiXFxcIiwgXCIuXCIsIFwiKlwiLCBcIitcIixcbiAgICAgKiBcIj9cIiwgXCIoXCIsIFwiKVwiLCBcIltcIiwgXCJdXCIsIFwie1wiLCBcIn1cIiwgYW5kIFwifFwiIGluIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlc2NhcGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lc2NhcGVSZWdFeHAoJ1tsb2Rhc2hdKGh0dHBzOi8vbG9kYXNoLmNvbS8pJyk7XG4gICAgICogLy8gPT4gJ1xcW2xvZGFzaFxcXVxcKGh0dHBzOi8vbG9kYXNoXFwuY29tL1xcKSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlc2NhcGVSZWdFeHAoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgcmV0dXJuIChzdHJpbmcgJiYgcmVIYXNSZWdFeHBDaGFyLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZVJlZ0V4cENoYXIsICdcXFxcJCYnKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0b1xuICAgICAqIFtrZWJhYiBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTcGVjaWFsX2Nhc2Vfc3R5bGVzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGtlYmFiIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5rZWJhYkNhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdmb28tYmFyJ1xuICAgICAqL1xuICAgIHZhciBrZWJhYkNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnLScgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCwgYXMgc3BhY2Ugc2VwYXJhdGVkIHdvcmRzLCB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbG93ZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnLS1Gb28tQmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKlxuICAgICAqIF8ubG93ZXJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKlxuICAgICAqIF8ubG93ZXJDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdmb28gYmFyJ1xuICAgICAqL1xuICAgIHZhciBsb3dlckNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGBzdHJpbmdgIHRvIGxvd2VyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxvd2VyRmlyc3QoJ0ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIF8ubG93ZXJGaXJzdCgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdmUkVEJ1xuICAgICAqL1xuICAgIHZhciBsb3dlckZpcnN0ID0gY3JlYXRlQ2FzZUZpcnN0KCd0b0xvd2VyQ2FzZScpO1xuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgc2lkZXMgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuXG4gICAgICogUGFkZGluZyBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBjYW4ndCBiZSBldmVubHkgZGl2aWRlZCBieSBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZCgnYWJjJywgOCk7XG4gICAgICogLy8gPT4gJyAgYWJjICAgJ1xuICAgICAqXG4gICAgICogXy5wYWQoJ2FiYycsIDgsICdfLScpO1xuICAgICAqIC8vID0+ICdfLWFiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkKCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBsZW5ndGggPSB0b0ludGVnZXIobGVuZ3RoKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IGxlbmd0aCA/IHN0cmluZ1NpemUoc3RyaW5nKSA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCB8fCBzdHJMZW5ndGggPj0gbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgbWlkID0gKGxlbmd0aCAtIHN0ckxlbmd0aCkgLyAyO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgY3JlYXRlUGFkZGluZyhuYXRpdmVGbG9vcihtaWQpLCBjaGFycykgK1xuICAgICAgICBzdHJpbmcgK1xuICAgICAgICBjcmVhdGVQYWRkaW5nKG5hdGl2ZUNlaWwobWlkKSwgY2hhcnMpXG4gICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhZHMgYHN0cmluZ2Agb24gdGhlIHJpZ2h0IHNpZGUgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuIFBhZGRpbmdcbiAgICAgKiBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBleGNlZWQgYGxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gcGFkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoPTBdIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5wYWRFbmQoJ2FiYycsIDYpO1xuICAgICAqIC8vID0+ICdhYmMgICAnXG4gICAgICpcbiAgICAgKiBfLnBhZEVuZCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiY18tXydcbiAgICAgKlxuICAgICAqIF8ucGFkRW5kKCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZEVuZChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBsZW5ndGggPSB0b0ludGVnZXIobGVuZ3RoKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IGxlbmd0aCA/IHN0cmluZ1NpemUoc3RyaW5nKSA6IDA7XG4gICAgICByZXR1cm4gKGxlbmd0aCAmJiBzdHJMZW5ndGggPCBsZW5ndGgpXG4gICAgICAgID8gKHN0cmluZyArIGNyZWF0ZVBhZGRpbmcobGVuZ3RoIC0gc3RyTGVuZ3RoLCBjaGFycykpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhZHMgYHN0cmluZ2Agb24gdGhlIGxlZnQgc2lkZSBpZiBpdCdzIHNob3J0ZXIgdGhhbiBgbGVuZ3RoYC4gUGFkZGluZ1xuICAgICAqIGNoYXJhY3RlcnMgYXJlIHRydW5jYXRlZCBpZiB0aGV5IGV4Y2VlZCBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZFN0YXJ0KCdhYmMnLCA2KTtcbiAgICAgKiAvLyA9PiAnICAgYWJjJ1xuICAgICAqXG4gICAgICogXy5wYWRTdGFydCgnYWJjJywgNiwgJ18tJyk7XG4gICAgICogLy8gPT4gJ18tX2FiYydcbiAgICAgKlxuICAgICAqIF8ucGFkU3RhcnQoJ2FiYycsIDMpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFkU3RhcnQoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgbGVuZ3RoID0gdG9JbnRlZ2VyKGxlbmd0aCk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBsZW5ndGggPyBzdHJpbmdTaXplKHN0cmluZykgOiAwO1xuICAgICAgcmV0dXJuIChsZW5ndGggJiYgc3RyTGVuZ3RoIDwgbGVuZ3RoKVxuICAgICAgICA/IChjcmVhdGVQYWRkaW5nKGxlbmd0aCAtIHN0ckxlbmd0aCwgY2hhcnMpICsgc3RyaW5nKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBhbiBpbnRlZ2VyIG9mIHRoZSBzcGVjaWZpZWQgcmFkaXguIElmIGByYWRpeGAgaXNcbiAgICAgKiBgdW5kZWZpbmVkYCBvciBgMGAsIGEgYHJhZGl4YCBvZiBgMTBgIGlzIHVzZWQgdW5sZXNzIGB2YWx1ZWAgaXMgYVxuICAgICAqIGhleGFkZWNpbWFsLCBpbiB3aGljaCBjYXNlIGEgYHJhZGl4YCBvZiBgMTZgIGlzIHVzZWQuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgYWxpZ25zIHdpdGggdGhlXG4gICAgICogW0VTNSBpbXBsZW1lbnRhdGlvbl0oaHR0cHM6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMS4yLjIpIG9mIGBwYXJzZUludGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtyYWRpeD0xMF0gVGhlIHJhZGl4IHRvIGludGVycHJldCBgdmFsdWVgIGJ5LlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFyc2VJbnQoJzA4Jyk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzA4JywgJzEwJ10sIF8ucGFyc2VJbnQpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJzZUludChzdHJpbmcsIHJhZGl4LCBndWFyZCkge1xuICAgICAgaWYgKGd1YXJkIHx8IHJhZGl4ID09IG51bGwpIHtcbiAgICAgICAgcmFkaXggPSAwO1xuICAgICAgfSBlbHNlIGlmIChyYWRpeCkge1xuICAgICAgICByYWRpeCA9ICtyYWRpeDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVQYXJzZUludCh0b1N0cmluZyhzdHJpbmcpLnJlcGxhY2UocmVUcmltU3RhcnQsICcnKSwgcmFkaXggfHwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwZWF0cyB0aGUgZ2l2ZW4gc3RyaW5nIGBuYCB0aW1lcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byByZXBlYXQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmVwZWF0IHRoZSBzdHJpbmcuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByZXBlYXRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCcqJywgMyk7XG4gICAgICogLy8gPT4gJyoqKidcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCdhYmMnLCAyKTtcbiAgICAgKiAvLyA9PiAnYWJjYWJjJ1xuICAgICAqXG4gICAgICogXy5yZXBlYXQoJ2FiYycsIDApO1xuICAgICAqIC8vID0+ICcnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVwZWF0KHN0cmluZywgbiwgZ3VhcmQpIHtcbiAgICAgIGlmICgoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIG4sIGd1YXJkKSA6IG4gPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgbiA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VSZXBlYXQodG9TdHJpbmcoc3RyaW5nKSwgbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgbWF0Y2hlcyBmb3IgYHBhdHRlcm5gIGluIGBzdHJpbmdgIHdpdGggYHJlcGxhY2VtZW50YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgU3RyaW5nI3JlcGxhY2VgXShodHRwczovL21kbi5pby9TdHJpbmcvcmVwbGFjZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gcGF0dGVybiBUaGUgcGF0dGVybiB0byByZXBsYWNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSByZXBsYWNlbWVudCBUaGUgbWF0Y2ggcmVwbGFjZW1lbnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbW9kaWZpZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJlcGxhY2UoJ0hpIEZyZWQnLCAnRnJlZCcsICdCYXJuZXknKTtcbiAgICAgKiAvLyA9PiAnSGkgQmFybmV5J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlcGxhY2UoKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICBzdHJpbmcgPSB0b1N0cmluZyhhcmdzWzBdKTtcblxuICAgICAgcmV0dXJuIGFyZ3MubGVuZ3RoIDwgMyA/IHN0cmluZyA6IHN0cmluZy5yZXBsYWNlKGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvXG4gICAgICogW3NuYWtlIGNhc2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NuYWtlX2Nhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc25ha2UgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnRm9vIEJhcicpO1xuICAgICAqIC8vID0+ICdmb29fYmFyJ1xuICAgICAqXG4gICAgICogXy5zbmFrZUNhc2UoJ2Zvb0JhcicpO1xuICAgICAqIC8vID0+ICdmb29fYmFyJ1xuICAgICAqXG4gICAgICogXy5zbmFrZUNhc2UoJy0tRk9PLUJBUi0tJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICovXG4gICAgdmFyIHNuYWtlQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICdfJyA6ICcnKSArIHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBieSBgc2VwYXJhdG9yYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgU3RyaW5nI3NwbGl0YF0oaHR0cHM6Ly9tZG4uaW8vU3RyaW5nL3NwbGl0KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBzcGxpdC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cHxzdHJpbmd9IHNlcGFyYXRvciBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gc3BsaXQgYnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsaW1pdF0gVGhlIGxlbmd0aCB0byB0cnVuY2F0ZSByZXN1bHRzIHRvLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc3RyaW5nIHNlZ21lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNwbGl0KCdhLWItYycsICctJywgMik7XG4gICAgICogLy8gPT4gWydhJywgJ2InXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNwbGl0KHN0cmluZywgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgaWYgKGxpbWl0ICYmIHR5cGVvZiBsaW1pdCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIHNlcGFyYXRvciwgbGltaXQpKSB7XG4gICAgICAgIHNlcGFyYXRvciA9IGxpbWl0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWZpbmVkID8gTUFYX0FSUkFZX0xFTkdUSCA6IGxpbWl0ID4+PiAwO1xuICAgICAgaWYgKCFsaW1pdCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKHN0cmluZyAmJiAoXG4gICAgICAgICAgICB0eXBlb2Ygc2VwYXJhdG9yID09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICAoc2VwYXJhdG9yICE9IG51bGwgJiYgIWlzUmVnRXhwKHNlcGFyYXRvcikpXG4gICAgICAgICAgKSkge1xuICAgICAgICBzZXBhcmF0b3IgPSBiYXNlVG9TdHJpbmcoc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKCFzZXBhcmF0b3IgJiYgaGFzVW5pY29kZShzdHJpbmcpKSB7XG4gICAgICAgICAgcmV0dXJuIGNhc3RTbGljZShzdHJpbmdUb0FycmF5KHN0cmluZyksIDAsIGxpbWl0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZy5zcGxpdChzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0b1xuICAgICAqIFtzdGFydCBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTdHlsaXN0aWNfb3Jfc3BlY2lhbGlzZWRfdXNhZ2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMS4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RhcnQgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnLS1mb28tYmFyLS0nKTtcbiAgICAgKiAvLyA9PiAnRm9vIEJhcidcbiAgICAgKlxuICAgICAqIF8uc3RhcnRDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnRm9vIEJhcidcbiAgICAgKlxuICAgICAqIF8uc3RhcnRDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqL1xuICAgIHZhciBzdGFydENhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB1cHBlckZpcnN0KHdvcmQpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBzdHJpbmdgIHN0YXJ0cyB3aXRoIHRoZSBnaXZlbiB0YXJnZXQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFt0YXJnZXRdIFRoZSBzdHJpbmcgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3Bvc2l0aW9uPTBdIFRoZSBwb3NpdGlvbiB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHN0cmluZ2Agc3RhcnRzIHdpdGggYHRhcmdldGAsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2InKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5zdGFydHNXaXRoKCdhYmMnLCAnYicsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFydHNXaXRoKHN0cmluZywgdGFyZ2V0LCBwb3NpdGlvbikge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb24gPT0gbnVsbFxuICAgICAgICA/IDBcbiAgICAgICAgOiBiYXNlQ2xhbXAodG9JbnRlZ2VyKHBvc2l0aW9uKSwgMCwgc3RyaW5nLmxlbmd0aCk7XG5cbiAgICAgIHRhcmdldCA9IGJhc2VUb1N0cmluZyh0YXJnZXQpO1xuICAgICAgcmV0dXJuIHN0cmluZy5zbGljZShwb3NpdGlvbiwgcG9zaXRpb24gKyB0YXJnZXQubGVuZ3RoKSA9PSB0YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNvbXBpbGVkIHRlbXBsYXRlIGZ1bmN0aW9uIHRoYXQgY2FuIGludGVycG9sYXRlIGRhdGEgcHJvcGVydGllc1xuICAgICAqIGluIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXJzLCBIVE1MLWVzY2FwZSBpbnRlcnBvbGF0ZWQgZGF0YSBwcm9wZXJ0aWVzIGluXG4gICAgICogXCJlc2NhcGVcIiBkZWxpbWl0ZXJzLCBhbmQgZXhlY3V0ZSBKYXZhU2NyaXB0IGluIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXJzLiBEYXRhXG4gICAgICogcHJvcGVydGllcyBtYXkgYmUgYWNjZXNzZWQgYXMgZnJlZSB2YXJpYWJsZXMgaW4gdGhlIHRlbXBsYXRlLiBJZiBhIHNldHRpbmdcbiAgICAgKiBvYmplY3QgaXMgZ2l2ZW4sIGl0IHRha2VzIHByZWNlZGVuY2Ugb3ZlciBgXy50ZW1wbGF0ZVNldHRpbmdzYCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSW4gdGhlIGRldmVsb3BtZW50IGJ1aWxkIGBfLnRlbXBsYXRlYCB1dGlsaXplc1xuICAgICAqIFtzb3VyY2VVUkxzXShodHRwOi8vd3d3Lmh0bWw1cm9ja3MuY29tL2VuL3R1dG9yaWFscy9kZXZlbG9wZXJ0b29scy9zb3VyY2VtYXBzLyN0b2Mtc291cmNldXJsKVxuICAgICAqIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAqXG4gICAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gcHJlY29tcGlsaW5nIHRlbXBsYXRlcyBzZWVcbiAgICAgKiBbbG9kYXNoJ3MgY3VzdG9tIGJ1aWxkcyBkb2N1bWVudGF0aW9uXShodHRwczovL2xvZGFzaC5jb20vY3VzdG9tLWJ1aWxkcykuXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBDaHJvbWUgZXh0ZW5zaW9uIHNhbmRib3hlcyBzZWVcbiAgICAgKiBbQ2hyb21lJ3MgZXh0ZW5zaW9ucyBkb2N1bWVudGF0aW9uXShodHRwczovL2RldmVsb3Blci5jaHJvbWUuY29tL2V4dGVuc2lvbnMvc2FuZGJveGluZ0V2YWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgdGVtcGxhdGUgc3RyaW5nLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBbb3B0aW9ucy5lc2NhcGU9Xy50ZW1wbGF0ZVNldHRpbmdzLmVzY2FwZV1cbiAgICAgKiAgVGhlIEhUTUwgXCJlc2NhcGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmV2YWx1YXRlPV8udGVtcGxhdGVTZXR0aW5ncy5ldmFsdWF0ZV1cbiAgICAgKiAgVGhlIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmltcG9ydHM9Xy50ZW1wbGF0ZVNldHRpbmdzLmltcG9ydHNdXG4gICAgICogIEFuIG9iamVjdCB0byBpbXBvcnQgaW50byB0aGUgdGVtcGxhdGUgYXMgZnJlZSB2YXJpYWJsZXMuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmludGVycG9sYXRlPV8udGVtcGxhdGVTZXR0aW5ncy5pbnRlcnBvbGF0ZV1cbiAgICAgKiAgVGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnNvdXJjZVVSTD0nbG9kYXNoLnRlbXBsYXRlU291cmNlc1tuXSddXG4gICAgICogIFRoZSBzb3VyY2VVUkwgb2YgdGhlIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy52YXJpYWJsZT0nb2JqJ11cbiAgICAgKiAgVGhlIGRhdGEgb2JqZWN0IHZhcmlhYmxlIG5hbWUuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNvbXBpbGVkIHRlbXBsYXRlIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIgdG8gY3JlYXRlIGEgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdmcmVkJyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIEhUTUwgXCJlc2NhcGVcIiBkZWxpbWl0ZXIgdG8gZXNjYXBlIGRhdGEgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzxiPjwlLSB2YWx1ZSAlPjwvYj4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd2YWx1ZSc6ICc8c2NyaXB0PicgfSk7XG4gICAgICogLy8gPT4gJzxiPiZsdDtzY3JpcHQmZ3Q7PC9iPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlciB0byBleGVjdXRlIEphdmFTY3JpcHQgYW5kIGdlbmVyYXRlIEhUTUwuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPCUgXy5mb3JFYWNoKHVzZXJzLCBmdW5jdGlvbih1c2VyKSB7ICU+PGxpPjwlLSB1c2VyICU+PC9saT48JSB9KTsgJT4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2Vycyc6IFsnZnJlZCcsICdiYXJuZXknXSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgaW50ZXJuYWwgYHByaW50YCBmdW5jdGlvbiBpbiBcImV2YWx1YXRlXCIgZGVsaW1pdGVycy5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JSBwcmludChcImhlbGxvIFwiICsgdXNlcik7ICU+IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnYmFybmV5JyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gYmFybmV5ISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgRVMgdGVtcGxhdGUgbGl0ZXJhbCBkZWxpbWl0ZXIgYXMgYW4gXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiAvLyBEaXNhYmxlIHN1cHBvcnQgYnkgcmVwbGFjaW5nIHRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvICR7IHVzZXIgfSEnKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2VyJzogJ3BlYmJsZXMnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBwZWJibGVzISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSBiYWNrc2xhc2hlcyB0byB0cmVhdCBkZWxpbWl0ZXJzIGFzIHBsYWluIHRleHQuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPCU9IFwiXFxcXDwlLSB2YWx1ZSAlXFxcXD5cIiAlPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3ZhbHVlJzogJ2lnbm9yZWQnIH0pO1xuICAgICAqIC8vID0+ICc8JS0gdmFsdWUgJT4nXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIGBpbXBvcnRzYCBvcHRpb24gdG8gaW1wb3J0IGBqUXVlcnlgIGFzIGBqcWAuXG4gICAgICogdmFyIHRleHQgPSAnPCUganEuZWFjaCh1c2VycywgZnVuY3Rpb24odXNlcikgeyAlPjxsaT48JS0gdXNlciAlPjwvbGk+PCUgfSk7ICU+JztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKHRleHQsIHsgJ2ltcG9ydHMnOiB7ICdqcSc6IGpRdWVyeSB9IH0pO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXJzJzogWydmcmVkJywgJ2Jhcm5leSddIH0pO1xuICAgICAqIC8vID0+ICc8bGk+ZnJlZDwvbGk+PGxpPmJhcm5leTwvbGk+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBgc291cmNlVVJMYCBvcHRpb24gdG8gc3BlY2lmeSBhIGN1c3RvbSBzb3VyY2VVUkwgZm9yIHRoZSB0ZW1wbGF0ZS5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyA8JT0gdXNlciAlPiEnLCB7ICdzb3VyY2VVUkwnOiAnL2Jhc2ljL2dyZWV0aW5nLmpzdCcgfSk7XG4gICAgICogY29tcGlsZWQoZGF0YSk7XG4gICAgICogLy8gPT4gRmluZCB0aGUgc291cmNlIG9mIFwiZ3JlZXRpbmcuanN0XCIgdW5kZXIgdGhlIFNvdXJjZXMgdGFiIG9yIFJlc291cmNlcyBwYW5lbCBvZiB0aGUgd2ViIGluc3BlY3Rvci5cbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHZhcmlhYmxlYCBvcHRpb24gdG8gZW5zdXJlIGEgd2l0aC1zdGF0ZW1lbnQgaXNuJ3QgdXNlZCBpbiB0aGUgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGkgPCU9IGRhdGEudXNlciAlPiEnLCB7ICd2YXJpYWJsZSc6ICdkYXRhJyB9KTtcbiAgICAgKiBjb21waWxlZC5zb3VyY2U7XG4gICAgICogLy8gPT4gZnVuY3Rpb24oZGF0YSkge1xuICAgICAqIC8vICAgdmFyIF9fdCwgX19wID0gJyc7XG4gICAgICogLy8gICBfX3AgKz0gJ2hpICcgKyAoKF9fdCA9ICggZGF0YS51c2VyICkpID09IG51bGwgPyAnJyA6IF9fdCkgKyAnISc7XG4gICAgICogLy8gICByZXR1cm4gX19wO1xuICAgICAqIC8vIH1cbiAgICAgKlxuICAgICAqIC8vIFVzZSBjdXN0b20gdGVtcGxhdGUgZGVsaW1pdGVycy5cbiAgICAgKiBfLnRlbXBsYXRlU2V0dGluZ3MuaW50ZXJwb2xhdGUgPSAve3soW1xcc1xcU10rPyl9fS9nO1xuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvIHt7IHVzZXIgfX0hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdtdXN0YWNoZScgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIG11c3RhY2hlISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHNvdXJjZWAgcHJvcGVydHkgdG8gaW5saW5lIGNvbXBpbGVkIHRlbXBsYXRlcyBmb3IgbWVhbmluZ2Z1bFxuICAgICAqIC8vIGxpbmUgbnVtYmVycyBpbiBlcnJvciBtZXNzYWdlcyBhbmQgc3RhY2sgdHJhY2VzLlxuICAgICAqIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICdqc3QuanMnKSwgJ1xcXG4gICAgICogICB2YXIgSlNUID0ge1xcXG4gICAgICogICAgIFwibWFpblwiOiAnICsgXy50ZW1wbGF0ZShtYWluVGV4dCkuc291cmNlICsgJ1xcXG4gICAgICogICB9O1xcXG4gICAgICogJyk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gdGVtcGxhdGUoc3RyaW5nLCBvcHRpb25zLCBndWFyZCkge1xuICAgICAgLy8gQmFzZWQgb24gSm9obiBSZXNpZydzIGB0bXBsYCBpbXBsZW1lbnRhdGlvblxuICAgICAgLy8gKGh0dHA6Ly9lam9obi5vcmcvYmxvZy9qYXZhc2NyaXB0LW1pY3JvLXRlbXBsYXRpbmcvKVxuICAgICAgLy8gYW5kIExhdXJhIERva3Rvcm92YSdzIGRvVC5qcyAoaHR0cHM6Ly9naXRodWIuY29tL29sYWRvL2RvVCkuXG4gICAgICB2YXIgc2V0dGluZ3MgPSBsb2Rhc2gudGVtcGxhdGVTZXR0aW5ncztcblxuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHN0cmluZywgb3B0aW9ucywgZ3VhcmQpKSB7XG4gICAgICAgIG9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgb3B0aW9ucyA9IGFzc2lnbkluV2l0aCh7fSwgb3B0aW9ucywgc2V0dGluZ3MsIGN1c3RvbURlZmF1bHRzQXNzaWduSW4pO1xuXG4gICAgICB2YXIgaW1wb3J0cyA9IGFzc2lnbkluV2l0aCh7fSwgb3B0aW9ucy5pbXBvcnRzLCBzZXR0aW5ncy5pbXBvcnRzLCBjdXN0b21EZWZhdWx0c0Fzc2lnbkluKSxcbiAgICAgICAgICBpbXBvcnRzS2V5cyA9IGtleXMoaW1wb3J0cyksXG4gICAgICAgICAgaW1wb3J0c1ZhbHVlcyA9IGJhc2VWYWx1ZXMoaW1wb3J0cywgaW1wb3J0c0tleXMpO1xuXG4gICAgICB2YXIgaXNFc2NhcGluZyxcbiAgICAgICAgICBpc0V2YWx1YXRpbmcsXG4gICAgICAgICAgaW5kZXggPSAwLFxuICAgICAgICAgIGludGVycG9sYXRlID0gb3B0aW9ucy5pbnRlcnBvbGF0ZSB8fCByZU5vTWF0Y2gsXG4gICAgICAgICAgc291cmNlID0gXCJfX3AgKz0gJ1wiO1xuXG4gICAgICAvLyBDb21waWxlIHRoZSByZWdleHAgdG8gbWF0Y2ggZWFjaCBkZWxpbWl0ZXIuXG4gICAgICB2YXIgcmVEZWxpbWl0ZXJzID0gUmVnRXhwKFxuICAgICAgICAob3B0aW9ucy5lc2NhcGUgfHwgcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICBpbnRlcnBvbGF0ZS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAoaW50ZXJwb2xhdGUgPT09IHJlSW50ZXJwb2xhdGUgPyByZUVzVGVtcGxhdGUgOiByZU5vTWF0Y2gpLnNvdXJjZSArICd8JyArXG4gICAgICAgIChvcHRpb25zLmV2YWx1YXRlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wkJ1xuICAgICAgLCAnZycpO1xuXG4gICAgICAvLyBVc2UgYSBzb3VyY2VVUkwgZm9yIGVhc2llciBkZWJ1Z2dpbmcuXG4gICAgICAvLyBUaGUgc291cmNlVVJMIGdldHMgaW5qZWN0ZWQgaW50byB0aGUgc291cmNlIHRoYXQncyBldmFsLWVkLCBzbyBiZSBjYXJlZnVsXG4gICAgICAvLyB0byBub3JtYWxpemUgYWxsIGtpbmRzIG9mIHdoaXRlc3BhY2UsIHNvIGUuZy4gbmV3bGluZXMgKGFuZCB1bmljb2RlIHZlcnNpb25zIG9mIGl0KSBjYW4ndCBzbmVhayBpblxuICAgICAgLy8gYW5kIGVzY2FwZSB0aGUgY29tbWVudCwgdGh1cyBpbmplY3RpbmcgY29kZSB0aGF0IGdldHMgZXZhbGVkLlxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICcvLyMgc291cmNlVVJMPScgK1xuICAgICAgICAoaGFzT3duUHJvcGVydHkuY2FsbChvcHRpb25zLCAnc291cmNlVVJMJylcbiAgICAgICAgICA/IChvcHRpb25zLnNvdXJjZVVSTCArICcnKS5yZXBsYWNlKC9cXHMvZywgJyAnKVxuICAgICAgICAgIDogKCdsb2Rhc2gudGVtcGxhdGVTb3VyY2VzWycgKyAoKyt0ZW1wbGF0ZUNvdW50ZXIpICsgJ10nKVxuICAgICAgICApICsgJ1xcbic7XG5cbiAgICAgIHN0cmluZy5yZXBsYWNlKHJlRGVsaW1pdGVycywgZnVuY3Rpb24obWF0Y2gsIGVzY2FwZVZhbHVlLCBpbnRlcnBvbGF0ZVZhbHVlLCBlc1RlbXBsYXRlVmFsdWUsIGV2YWx1YXRlVmFsdWUsIG9mZnNldCkge1xuICAgICAgICBpbnRlcnBvbGF0ZVZhbHVlIHx8IChpbnRlcnBvbGF0ZVZhbHVlID0gZXNUZW1wbGF0ZVZhbHVlKTtcblxuICAgICAgICAvLyBFc2NhcGUgY2hhcmFjdGVycyB0aGF0IGNhbid0IGJlIGluY2x1ZGVkIGluIHN0cmluZyBsaXRlcmFscy5cbiAgICAgICAgc291cmNlICs9IHN0cmluZy5zbGljZShpbmRleCwgb2Zmc2V0KS5yZXBsYWNlKHJlVW5lc2NhcGVkU3RyaW5nLCBlc2NhcGVTdHJpbmdDaGFyKTtcblxuICAgICAgICAvLyBSZXBsYWNlIGRlbGltaXRlcnMgd2l0aCBzbmlwcGV0cy5cbiAgICAgICAgaWYgKGVzY2FwZVZhbHVlKSB7XG4gICAgICAgICAgaXNFc2NhcGluZyA9IHRydWU7XG4gICAgICAgICAgc291cmNlICs9IFwiJyArXFxuX19lKFwiICsgZXNjYXBlVmFsdWUgKyBcIikgK1xcbidcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZhbHVhdGVWYWx1ZSkge1xuICAgICAgICAgIGlzRXZhbHVhdGluZyA9IHRydWU7XG4gICAgICAgICAgc291cmNlICs9IFwiJztcXG5cIiArIGV2YWx1YXRlVmFsdWUgKyBcIjtcXG5fX3AgKz0gJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbnRlcnBvbGF0ZVZhbHVlKSB7XG4gICAgICAgICAgc291cmNlICs9IFwiJyArXFxuKChfX3QgPSAoXCIgKyBpbnRlcnBvbGF0ZVZhbHVlICsgXCIpKSA9PSBudWxsID8gJycgOiBfX3QpICtcXG4nXCI7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSBvZmZzZXQgKyBtYXRjaC5sZW5ndGg7XG5cbiAgICAgICAgLy8gVGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBwcm9kdWN0cyBuZWVkcyBgbWF0Y2hgIHJldHVybmVkIGluXG4gICAgICAgIC8vIG9yZGVyIHRvIHByb2R1Y2UgdGhlIGNvcnJlY3QgYG9mZnNldGAgdmFsdWUuXG4gICAgICAgIHJldHVybiBtYXRjaDtcbiAgICAgIH0pO1xuXG4gICAgICBzb3VyY2UgKz0gXCInO1xcblwiO1xuXG4gICAgICAvLyBJZiBgdmFyaWFibGVgIGlzIG5vdCBzcGVjaWZpZWQgd3JhcCBhIHdpdGgtc3RhdGVtZW50IGFyb3VuZCB0aGUgZ2VuZXJhdGVkXG4gICAgICAvLyBjb2RlIHRvIGFkZCB0aGUgZGF0YSBvYmplY3QgdG8gdGhlIHRvcCBvZiB0aGUgc2NvcGUgY2hhaW4uXG4gICAgICB2YXIgdmFyaWFibGUgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsICd2YXJpYWJsZScpICYmIG9wdGlvbnMudmFyaWFibGU7XG4gICAgICBpZiAoIXZhcmlhYmxlKSB7XG4gICAgICAgIHNvdXJjZSA9ICd3aXRoIChvYmopIHtcXG4nICsgc291cmNlICsgJ1xcbn1cXG4nO1xuICAgICAgfVxuICAgICAgLy8gVGhyb3cgYW4gZXJyb3IgaWYgYSBmb3JiaWRkZW4gY2hhcmFjdGVyIHdhcyBmb3VuZCBpbiBgdmFyaWFibGVgLCB0byBwcmV2ZW50XG4gICAgICAvLyBwb3RlbnRpYWwgY29tbWFuZCBpbmplY3Rpb24gYXR0YWNrcy5cbiAgICAgIGVsc2UgaWYgKHJlRm9yYmlkZGVuSWRlbnRpZmllckNoYXJzLnRlc3QodmFyaWFibGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihJTlZBTElEX1RFTVBMX1ZBUl9FUlJPUl9URVhUKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2xlYW51cCBjb2RlIGJ5IHN0cmlwcGluZyBlbXB0eSBzdHJpbmdzLlxuICAgICAgc291cmNlID0gKGlzRXZhbHVhdGluZyA/IHNvdXJjZS5yZXBsYWNlKHJlRW1wdHlTdHJpbmdMZWFkaW5nLCAnJykgOiBzb3VyY2UpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdNaWRkbGUsICckMScpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdUcmFpbGluZywgJyQxOycpO1xuXG4gICAgICAvLyBGcmFtZSBjb2RlIGFzIHRoZSBmdW5jdGlvbiBib2R5LlxuICAgICAgc291cmNlID0gJ2Z1bmN0aW9uKCcgKyAodmFyaWFibGUgfHwgJ29iaicpICsgJykge1xcbicgK1xuICAgICAgICAodmFyaWFibGVcbiAgICAgICAgICA/ICcnXG4gICAgICAgICAgOiAnb2JqIHx8IChvYmogPSB7fSk7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgXCJ2YXIgX190LCBfX3AgPSAnJ1wiICtcbiAgICAgICAgKGlzRXNjYXBpbmdcbiAgICAgICAgICAgPyAnLCBfX2UgPSBfLmVzY2FwZSdcbiAgICAgICAgICAgOiAnJ1xuICAgICAgICApICtcbiAgICAgICAgKGlzRXZhbHVhdGluZ1xuICAgICAgICAgID8gJywgX19qID0gQXJyYXkucHJvdG90eXBlLmpvaW47XFxuJyArXG4gICAgICAgICAgICBcImZ1bmN0aW9uIHByaW50KCkgeyBfX3AgKz0gX19qLmNhbGwoYXJndW1lbnRzLCAnJykgfVxcblwiXG4gICAgICAgICAgOiAnO1xcbidcbiAgICAgICAgKSArXG4gICAgICAgIHNvdXJjZSArXG4gICAgICAgICdyZXR1cm4gX19wXFxufSc7XG5cbiAgICAgIHZhciByZXN1bHQgPSBhdHRlbXB0KGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gRnVuY3Rpb24oaW1wb3J0c0tleXMsIHNvdXJjZVVSTCArICdyZXR1cm4gJyArIHNvdXJjZSlcbiAgICAgICAgICAuYXBwbHkodW5kZWZpbmVkLCBpbXBvcnRzVmFsdWVzKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBQcm92aWRlIHRoZSBjb21waWxlZCBmdW5jdGlvbidzIHNvdXJjZSBieSBpdHMgYHRvU3RyaW5nYCBtZXRob2Qgb3JcbiAgICAgIC8vIHRoZSBgc291cmNlYCBwcm9wZXJ0eSBhcyBhIGNvbnZlbmllbmNlIGZvciBpbmxpbmluZyBjb21waWxlZCB0ZW1wbGF0ZXMuXG4gICAgICByZXN1bHQuc291cmNlID0gc291cmNlO1xuICAgICAgaWYgKGlzRXJyb3IocmVzdWx0KSkge1xuICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBhIHdob2xlLCB0byBsb3dlciBjYXNlIGp1c3QgbGlrZVxuICAgICAqIFtTdHJpbmcjdG9Mb3dlckNhc2VdKGh0dHBzOi8vbWRuLmlvL3RvTG93ZXJDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGxvd2VyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0xvd2VyKCctLUZvby1CYXItLScpO1xuICAgICAqIC8vID0+ICctLWZvby1iYXItLSdcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb2JhcidcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnX19mb29fYmFyX18nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9Mb3dlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBhIHdob2xlLCB0byB1cHBlciBjYXNlIGp1c3QgbGlrZVxuICAgICAqIFtTdHJpbmcjdG9VcHBlckNhc2VdKGh0dHBzOi8vbWRuLmlvL3RvVXBwZXJDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVwcGVyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b1VwcGVyKCctLWZvby1iYXItLScpO1xuICAgICAqIC8vID0+ICctLUZPTy1CQVItLSdcbiAgICAgKlxuICAgICAqIF8udG9VcHBlcignZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ0ZPT0JBUidcbiAgICAgKlxuICAgICAqIF8udG9VcHBlcignX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnX19GT09fQkFSX18nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9VcHBlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS50b1VwcGVyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBvciBzcGVjaWZpZWQgY2hhcmFjdGVycyBmcm9tIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRyaW0uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz13aGl0ZXNwYWNlXSBUaGUgY2hhcmFjdGVycyB0byB0cmltLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbSgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLnRyaW0oJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLm1hcChbJyAgZm9vICAnLCAnICBiYXIgICddLCBfLnRyaW0pO1xuICAgICAqIC8vID0+IFsnZm9vJywgJ2JhciddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbShzdHJpbmcsIGNoYXJzLCBndWFyZCkge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGlmIChzdHJpbmcgJiYgKGd1YXJkIHx8IGNoYXJzID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgIHJldHVybiBiYXNlVHJpbShzdHJpbmcpO1xuICAgICAgfVxuICAgICAgaWYgKCFzdHJpbmcgfHwgIShjaGFycyA9IGJhc2VUb1N0cmluZyhjaGFycykpKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKSxcbiAgICAgICAgICBjaHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShjaGFycyksXG4gICAgICAgICAgc3RhcnQgPSBjaGFyc1N0YXJ0SW5kZXgoc3RyU3ltYm9scywgY2hyU3ltYm9scyksXG4gICAgICAgICAgZW5kID0gY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSArIDE7XG5cbiAgICAgIHJldHVybiBjYXN0U2xpY2Uoc3RyU3ltYm9scywgc3RhcnQsIGVuZCkuam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0cmFpbGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmltRW5kKCcgIGFiYyAgJyk7XG4gICAgICogLy8gPT4gJyAgYWJjJ1xuICAgICAqXG4gICAgICogXy50cmltRW5kKCctXy1hYmMtXy0nLCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnLV8tYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyaW1FbmQoc3RyaW5nLCBjaGFycywgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoc3RyaW5nICYmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIHRyaW1tZWRFbmRJbmRleChzdHJpbmcpICsgMSk7XG4gICAgICB9XG4gICAgICBpZiAoIXN0cmluZyB8fCAhKGNoYXJzID0gYmFzZVRvU3RyaW5nKGNoYXJzKSkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHZhciBzdHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShzdHJpbmcpLFxuICAgICAgICAgIGVuZCA9IGNoYXJzRW5kSW5kZXgoc3RyU3ltYm9scywgc3RyaW5nVG9BcnJheShjaGFycykpICsgMTtcblxuICAgICAgcmV0dXJuIGNhc3RTbGljZShzdHJTeW1ib2xzLCAwLCBlbmQpLmpvaW4oJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGVhZGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmltU3RhcnQoJyAgYWJjICAnKTtcbiAgICAgKiAvLyA9PiAnYWJjICAnXG4gICAgICpcbiAgICAgKiBfLnRyaW1TdGFydCgnLV8tYWJjLV8tJywgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiYy1fLSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmltU3RhcnQoc3RyaW5nLCBjaGFycywgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoc3RyaW5nICYmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UocmVUcmltU3RhcnQsICcnKTtcbiAgICAgIH1cbiAgICAgIGlmICghc3RyaW5nIHx8ICEoY2hhcnMgPSBiYXNlVG9TdHJpbmcoY2hhcnMpKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIHN0clN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KHN0cmluZyksXG4gICAgICAgICAgc3RhcnQgPSBjaGFyc1N0YXJ0SW5kZXgoc3RyU3ltYm9scywgc3RyaW5nVG9BcnJheShjaGFycykpO1xuXG4gICAgICByZXR1cm4gY2FzdFNsaWNlKHN0clN5bWJvbHMsIHN0YXJ0KS5qb2luKCcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVuY2F0ZXMgYHN0cmluZ2AgaWYgaXQncyBsb25nZXIgdGhhbiB0aGUgZ2l2ZW4gbWF4aW11bSBzdHJpbmcgbGVuZ3RoLlxuICAgICAqIFRoZSBsYXN0IGNoYXJhY3RlcnMgb2YgdGhlIHRydW5jYXRlZCBzdHJpbmcgYXJlIHJlcGxhY2VkIHdpdGggdGhlIG9taXNzaW9uXG4gICAgICogc3RyaW5nIHdoaWNoIGRlZmF1bHRzIHRvIFwiLi4uXCIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJ1bmNhdGUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmxlbmd0aD0zMF0gVGhlIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMub21pc3Npb249Jy4uLiddIFRoZSBzdHJpbmcgdG8gaW5kaWNhdGUgdGV4dCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW29wdGlvbnMuc2VwYXJhdG9yXSBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gdHJ1bmNhdGUgdG8uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJ1bmNhdGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycpO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm8uLi4nXG4gICAgICpcbiAgICAgKiBfLnRydW5jYXRlKCdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm9yaW5vJywge1xuICAgICAqICAgJ2xlbmd0aCc6IDI0LFxuICAgICAqICAgJ3NlcGFyYXRvcic6ICcgJ1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdsZW5ndGgnOiAyNCxcbiAgICAgKiAgICdzZXBhcmF0b3InOiAvLD8gKy9cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdvbWlzc2lvbic6ICcgWy4uLl0nXG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZyBbLi4uXSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cnVuY2F0ZShzdHJpbmcsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBERUZBVUxUX1RSVU5DX0xFTkdUSCxcbiAgICAgICAgICBvbWlzc2lvbiA9IERFRkFVTFRfVFJVTkNfT01JU1NJT047XG5cbiAgICAgIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gJ3NlcGFyYXRvcicgaW4gb3B0aW9ucyA/IG9wdGlvbnMuc2VwYXJhdG9yIDogc2VwYXJhdG9yO1xuICAgICAgICBsZW5ndGggPSAnbGVuZ3RoJyBpbiBvcHRpb25zID8gdG9JbnRlZ2VyKG9wdGlvbnMubGVuZ3RoKSA6IGxlbmd0aDtcbiAgICAgICAgb21pc3Npb24gPSAnb21pc3Npb24nIGluIG9wdGlvbnMgPyBiYXNlVG9TdHJpbmcob3B0aW9ucy5vbWlzc2lvbikgOiBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgaWYgKGhhc1VuaWNvZGUoc3RyaW5nKSkge1xuICAgICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKTtcbiAgICAgICAgc3RyTGVuZ3RoID0gc3RyU3ltYm9scy5sZW5ndGg7XG4gICAgICB9XG4gICAgICBpZiAobGVuZ3RoID49IHN0ckxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIGVuZCA9IGxlbmd0aCAtIHN0cmluZ1NpemUob21pc3Npb24pO1xuICAgICAgaWYgKGVuZCA8IDEpIHtcbiAgICAgICAgcmV0dXJuIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHN0clN5bWJvbHNcbiAgICAgICAgPyBjYXN0U2xpY2Uoc3RyU3ltYm9scywgMCwgZW5kKS5qb2luKCcnKVxuICAgICAgICA6IHN0cmluZy5zbGljZSgwLCBlbmQpO1xuXG4gICAgICBpZiAoc2VwYXJhdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCArIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgaWYgKHN0clN5bWJvbHMpIHtcbiAgICAgICAgZW5kICs9IChyZXN1bHQubGVuZ3RoIC0gZW5kKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1JlZ0V4cChzZXBhcmF0b3IpKSB7XG4gICAgICAgIGlmIChzdHJpbmcuc2xpY2UoZW5kKS5zZWFyY2goc2VwYXJhdG9yKSkge1xuICAgICAgICAgIHZhciBtYXRjaCxcbiAgICAgICAgICAgICAgc3Vic3RyaW5nID0gcmVzdWx0O1xuXG4gICAgICAgICAgaWYgKCFzZXBhcmF0b3IuZ2xvYmFsKSB7XG4gICAgICAgICAgICBzZXBhcmF0b3IgPSBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgdG9TdHJpbmcocmVGbGFncy5leGVjKHNlcGFyYXRvcikpICsgJ2cnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgd2hpbGUgKChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN1YnN0cmluZykpKSB7XG4gICAgICAgICAgICB2YXIgbmV3RW5kID0gbWF0Y2guaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCBuZXdFbmQgPT09IHVuZGVmaW5lZCA/IGVuZCA6IG5ld0VuZCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nLmluZGV4T2YoYmFzZVRvU3RyaW5nKHNlcGFyYXRvciksIGVuZCkgIT0gZW5kKSB7XG4gICAgICAgIHZhciBpbmRleCA9IHJlc3VsdC5sYXN0SW5kZXhPZihzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCBpbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQgKyBvbWlzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW52ZXJzZSBvZiBgXy5lc2NhcGVgOyB0aGlzIG1ldGhvZCBjb252ZXJ0cyB0aGUgSFRNTCBlbnRpdGllc1xuICAgICAqIGAmYW1wO2AsIGAmbHQ7YCwgYCZndDtgLCBgJnF1b3Q7YCwgYW5kIGAmIzM5O2AgaW4gYHN0cmluZ2AgdG9cbiAgICAgKiB0aGVpciBjb3JyZXNwb25kaW5nIGNoYXJhY3RlcnMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm8gb3RoZXIgSFRNTCBlbnRpdGllcyBhcmUgdW5lc2NhcGVkLiBUbyB1bmVzY2FwZSBhZGRpdGlvbmFsXG4gICAgICogSFRNTCBlbnRpdGllcyB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdW5lc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdW5lc2NhcGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmVzY2FwZSgnZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuZXNjYXBlKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiAoc3RyaW5nICYmIHJlSGFzRXNjYXBlZEh0bWwudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlRXNjYXBlZEh0bWwsIHVuZXNjYXBlSHRtbENoYXIpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBzcGFjZSBzZXBhcmF0ZWQgd29yZHMsIHRvIHVwcGVyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1cHBlciBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCctLWZvby1iYXInKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCdfX2Zvb19iYXJfXycpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqL1xuICAgIHZhciB1cHBlckNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB3b3JkLnRvVXBwZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGBzdHJpbmdgIHRvIHVwcGVyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVwcGVyRmlyc3QoJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnRnJlZCdcbiAgICAgKlxuICAgICAqIF8udXBwZXJGaXJzdCgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdGUkVEJ1xuICAgICAqL1xuICAgIHZhciB1cHBlckZpcnN0ID0gY3JlYXRlQ2FzZUZpcnN0KCd0b1VwcGVyQ2FzZScpO1xuXG4gICAgLyoqXG4gICAgICogU3BsaXRzIGBzdHJpbmdgIGludG8gYW4gYXJyYXkgb2YgaXRzIHdvcmRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtSZWdFeHB8c3RyaW5nfSBbcGF0dGVybl0gVGhlIHBhdHRlcm4gdG8gbWF0Y2ggd29yZHMuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+IFsnZnJlZCcsICdiYXJuZXknLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycsIC9bXiwgXSsvZyk7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ2Jhcm5leScsICcmJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdvcmRzKHN0cmluZywgcGF0dGVybiwgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwYXR0ZXJuID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBwYXR0ZXJuO1xuXG4gICAgICBpZiAocGF0dGVybiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBoYXNVbmljb2RlV29yZChzdHJpbmcpID8gdW5pY29kZVdvcmRzKHN0cmluZykgOiBhc2NpaVdvcmRzKHN0cmluZyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RyaW5nLm1hdGNoKHBhdHRlcm4pIHx8IFtdO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIEF0dGVtcHRzIHRvIGludm9rZSBgZnVuY2AsIHJldHVybmluZyBlaXRoZXIgdGhlIHJlc3VsdCBvciB0aGUgY2F1Z2h0IGVycm9yXG4gICAgICogb2JqZWN0LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0J3MgaW52b2tlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXR0ZW1wdC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBgZnVuY2Agd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYGZ1bmNgIHJlc3VsdCBvciBlcnJvciBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIEF2b2lkIHRocm93aW5nIGVycm9ycyBmb3IgaW52YWxpZCBzZWxlY3RvcnMuXG4gICAgICogdmFyIGVsZW1lbnRzID0gXy5hdHRlbXB0KGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgICogICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgICogfSwgJz5fPicpO1xuICAgICAqXG4gICAgICogaWYgKF8uaXNFcnJvcihlbGVtZW50cykpIHtcbiAgICAgKiAgIGVsZW1lbnRzID0gW107XG4gICAgICogfVxuICAgICAqL1xuICAgIHZhciBhdHRlbXB0ID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgYXJncykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHVuZGVmaW5lZCwgYXJncyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBpc0Vycm9yKGUpID8gZSA6IG5ldyBFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEJpbmRzIG1ldGhvZHMgb2YgYW4gb2JqZWN0IHRvIHRoZSBvYmplY3QgaXRzZWxmLCBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmdcbiAgICAgKiBtZXRob2QuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gYmluZCBhbmQgYXNzaWduIHRoZSBib3VuZCBtZXRob2RzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKHN0cmluZ3xzdHJpbmdbXSl9IG1ldGhvZE5hbWVzIFRoZSBvYmplY3QgbWV0aG9kIG5hbWVzIHRvIGJpbmQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHZpZXcgPSB7XG4gICAgICogICAnbGFiZWwnOiAnZG9jcycsXG4gICAgICogICAnY2xpY2snOiBmdW5jdGlvbigpIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ2NsaWNrZWQgJyArIHRoaXMubGFiZWwpO1xuICAgICAqICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmJpbmRBbGwodmlldywgWydjbGljayddKTtcbiAgICAgKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdmlldy5jbGljayk7XG4gICAgICogLy8gPT4gTG9ncyAnY2xpY2tlZCBkb2NzJyB3aGVuIGNsaWNrZWQuXG4gICAgICovXG4gICAgdmFyIGJpbmRBbGwgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIG1ldGhvZE5hbWVzKSB7XG4gICAgICBhcnJheUVhY2gobWV0aG9kTmFtZXMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBrZXkgPSB0b0tleShrZXkpO1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIGJpbmQob2JqZWN0W2tleV0sIG9iamVjdCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXRlcmF0ZXMgb3ZlciBgcGFpcnNgIGFuZCBpbnZva2VzIHRoZSBjb3JyZXNwb25kaW5nXG4gICAgICogZnVuY3Rpb24gb2YgdGhlIGZpcnN0IHByZWRpY2F0ZSB0byByZXR1cm4gdHJ1dGh5LiBUaGUgcHJlZGljYXRlLWZ1bmN0aW9uXG4gICAgICogcGFpcnMgYXJlIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGUgY3JlYXRlZFxuICAgICAqIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYWlycyBUaGUgcHJlZGljYXRlLWZ1bmN0aW9uIHBhaXJzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvc2l0ZSBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLmNvbmQoW1xuICAgICAqICAgW18ubWF0Y2hlcyh7ICdhJzogMSB9KSwgICAgICAgICAgIF8uY29uc3RhbnQoJ21hdGNoZXMgQScpXSxcbiAgICAgKiAgIFtfLmNvbmZvcm1zKHsgJ2InOiBfLmlzTnVtYmVyIH0pLCBfLmNvbnN0YW50KCdtYXRjaGVzIEInKV0sXG4gICAgICogICBbXy5zdHViVHJ1ZSwgICAgICAgICAgICAgICAgICAgICAgXy5jb25zdGFudCgnbm8gbWF0Y2gnKV1cbiAgICAgKiBdKTtcbiAgICAgKlxuICAgICAqIGZ1bmMoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAnbWF0Y2hlcyBBJ1xuICAgICAqXG4gICAgICogZnVuYyh7ICdhJzogMCwgJ2InOiAxIH0pO1xuICAgICAqIC8vID0+ICdtYXRjaGVzIEInXG4gICAgICpcbiAgICAgKiBmdW5jKHsgJ2EnOiAnMScsICdiJzogJzInIH0pO1xuICAgICAqIC8vID0+ICdubyBtYXRjaCdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25kKHBhaXJzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gcGFpcnMgPT0gbnVsbCA/IDAgOiBwYWlycy5sZW5ndGgsXG4gICAgICAgICAgdG9JdGVyYXRlZSA9IGdldEl0ZXJhdGVlKCk7XG5cbiAgICAgIHBhaXJzID0gIWxlbmd0aCA/IFtdIDogYXJyYXlNYXAocGFpcnMsIGZ1bmN0aW9uKHBhaXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwYWlyWzFdICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFt0b0l0ZXJhdGVlKHBhaXJbMF0pLCBwYWlyWzFdXTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgcGFpciA9IHBhaXJzW2luZGV4XTtcbiAgICAgICAgICBpZiAoYXBwbHkocGFpclswXSwgdGhpcywgYXJncykpIHtcbiAgICAgICAgICAgIHJldHVybiBhcHBseShwYWlyWzFdLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgdGhlIHByZWRpY2F0ZSBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHdpdGhcbiAgICAgKiB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eSB2YWx1ZXMgb2YgYSBnaXZlbiBvYmplY3QsIHJldHVybmluZyBgdHJ1ZWAgaWZcbiAgICAgKiBhbGwgcHJlZGljYXRlcyByZXR1cm4gdHJ1dGh5LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhlIGNyZWF0ZWQgZnVuY3Rpb24gaXMgZXF1aXZhbGVudCB0byBgXy5jb25mb3Jtc1RvYCB3aXRoXG4gICAgICogYHNvdXJjZWAgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbXG4gICAgICogICB7ICdhJzogMiwgJ2InOiAxIH0sXG4gICAgICogICB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIob2JqZWN0cywgXy5jb25mb3Jtcyh7ICdiJzogZnVuY3Rpb24obikgeyByZXR1cm4gbiA+IDE7IH0gfSkpO1xuICAgICAqIC8vID0+IFt7ICdhJzogMSwgJ2InOiAyIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uZm9ybXMoc291cmNlKSB7XG4gICAgICByZXR1cm4gYmFzZUNvbmZvcm1zKGJhc2VDbG9uZShzb3VyY2UsIENMT05FX0RFRVBfRkxBRykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmV0dXJuIGZyb20gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb25zdGFudCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBfLnRpbWVzKDIsIF8uY29uc3RhbnQoeyAnYSc6IDEgfSkpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0cyk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxIH0sIHsgJ2EnOiAxIH1dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3RzWzBdID09PSBvYmplY3RzWzFdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uc3RhbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgYHZhbHVlYCB0byBkZXRlcm1pbmUgd2hldGhlciBhIGRlZmF1bHQgdmFsdWUgc2hvdWxkIGJlIHJldHVybmVkIGluXG4gICAgICogaXRzIHBsYWNlLiBUaGUgYGRlZmF1bHRWYWx1ZWAgaXMgcmV0dXJuZWQgaWYgYHZhbHVlYCBpcyBgTmFOYCwgYG51bGxgLFxuICAgICAqIG9yIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHsqfSBkZWZhdWx0VmFsdWUgVGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRUbygxLCAxMCk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0VG8odW5kZWZpbmVkLCAxMCk7XG4gICAgICogLy8gPT4gMTBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkZWZhdWx0VG8odmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgcmV0dXJuICh2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSkgPyBkZWZhdWx0VmFsdWUgOiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSByZXN1bHQgb2YgaW52b2tpbmcgdGhlIGdpdmVuIGZ1bmN0aW9uc1xuICAgICAqIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLCB3aGVyZSBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgKiBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2Z1bmNzXSBUaGUgZnVuY3Rpb25zIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb21wb3NpdGUgZnVuY3Rpb24uXG4gICAgICogQHNlZSBfLmZsb3dSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3coW18uYWRkLCBzcXVhcmVdKTtcbiAgICAgKiBhZGRTcXVhcmUoMSwgMik7XG4gICAgICogLy8gPT4gOVxuICAgICAqL1xuICAgIHZhciBmbG93ID0gY3JlYXRlRmxvdygpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mbG93YCBleGNlcHQgdGhhdCBpdCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdFxuICAgICAqIGludm9rZXMgdGhlIGdpdmVuIGZ1bmN0aW9ucyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbZnVuY3NdIFRoZSBmdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvc2l0ZSBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIF8uZmxvd1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3dSaWdodChbc3F1YXJlLCBfLmFkZF0pO1xuICAgICAqIGFkZFNxdWFyZSgxLCAyKTtcbiAgICAgKiAvLyA9PiA5XG4gICAgICovXG4gICAgdmFyIGZsb3dSaWdodCA9IGNyZWF0ZUZsb3codHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBmaXJzdCBhcmd1bWVudCBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBBbnkgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgYHZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhfLmlkZW50aXR5KG9iamVjdCkgPT09IG9iamVjdCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlkZW50aXR5KHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYXJndW1lbnRzIG9mIHRoZSBjcmVhdGVkXG4gICAgICogZnVuY3Rpb24uIElmIGBmdW5jYCBpcyBhIHByb3BlcnR5IG5hbWUsIHRoZSBjcmVhdGVkIGZ1bmN0aW9uIHJldHVybnMgdGhlXG4gICAgICogcHJvcGVydHkgdmFsdWUgZm9yIGEgZ2l2ZW4gZWxlbWVudC4gSWYgYGZ1bmNgIGlzIGFuIGFycmF5IG9yIG9iamVjdCwgdGhlXG4gICAgICogY3JlYXRlZCBmdW5jdGlvbiByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBjb250YWluIHRoZSBlcXVpdmFsZW50XG4gICAgICogc291cmNlIHByb3BlcnRpZXMsIG90aGVyd2lzZSBpdCByZXR1cm5zIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gW2Z1bmM9Xy5pZGVudGl0eV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYSBjYWxsYmFjay5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLml0ZXJhdGVlKHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IHRydWUgfSkpO1xuICAgICAqIC8vID0+IFt7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgXy5pdGVyYXRlZShbJ3VzZXInLCAnZnJlZCddKSk7XG4gICAgICogLy8gPT4gW3sgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCB9XVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXAodXNlcnMsIF8uaXRlcmF0ZWUoJ3VzZXInKSk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBDcmVhdGUgY3VzdG9tIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICogXy5pdGVyYXRlZSA9IF8ud3JhcChfLml0ZXJhdGVlLCBmdW5jdGlvbihpdGVyYXRlZSwgZnVuYykge1xuICAgICAqICAgcmV0dXJuICFfLmlzUmVnRXhwKGZ1bmMpID8gaXRlcmF0ZWUoZnVuYykgOiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgKiAgICAgcmV0dXJuIGZ1bmMudGVzdChzdHJpbmcpO1xuICAgICAqICAgfTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKFsnYWJjJywgJ2RlZiddLCAvZWYvKTtcbiAgICAgKiAvLyA9PiBbJ2RlZiddXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXRlcmF0ZWUoZnVuYykge1xuICAgICAgcmV0dXJuIGJhc2VJdGVyYXRlZSh0eXBlb2YgZnVuYyA9PSAnZnVuY3Rpb24nID8gZnVuYyA6IGJhc2VDbG9uZShmdW5jLCBDTE9ORV9ERUVQX0ZMQUcpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBhIHBhcnRpYWwgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYSBnaXZlblxuICAgICAqIG9iamVjdCBhbmQgYHNvdXJjZWAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIG9iamVjdCBoYXMgZXF1aXZhbGVudFxuICAgICAqIHByb3BlcnR5IHZhbHVlcywgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoZSBjcmVhdGVkIGZ1bmN0aW9uIGlzIGVxdWl2YWxlbnQgdG8gYF8uaXNNYXRjaGAgd2l0aCBgc291cmNlYFxuICAgICAqIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogUGFydGlhbCBjb21wYXJpc29ucyB3aWxsIG1hdGNoIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBvYmplY3QgYHNvdXJjZWBcbiAgICAgKiB2YWx1ZXMgYWdhaW5zdCBhbnkgYXJyYXkgb3Igb2JqZWN0IHZhbHVlLCByZXNwZWN0aXZlbHkuIFNlZSBgXy5pc0VxdWFsYFxuICAgICAqIGZvciBhIGxpc3Qgb2Ygc3VwcG9ydGVkIHZhbHVlIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE11bHRpcGxlIHZhbHVlcyBjYW4gYmUgY2hlY2tlZCBieSBjb21iaW5pbmcgc2V2ZXJhbCBtYXRjaGVyc1xuICAgICAqIHVzaW5nIGBfLm92ZXJTb21lYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzIH0sXG4gICAgICogICB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcihvYmplY3RzLCBfLm1hdGNoZXMoeyAnYSc6IDQsICdjJzogNiB9KSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiA0LCAnYic6IDUsICdjJzogNiB9XVxuICAgICAqXG4gICAgICogLy8gQ2hlY2tpbmcgZm9yIHNldmVyYWwgcG9zc2libGUgdmFsdWVzXG4gICAgICogXy5maWx0ZXIob2JqZWN0cywgXy5vdmVyU29tZShbXy5tYXRjaGVzKHsgJ2EnOiAxIH0pLCBfLm1hdGNoZXMoeyAnYSc6IDQgfSldKSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LCB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXRjaGVzKHNvdXJjZSkge1xuICAgICAgcmV0dXJuIGJhc2VNYXRjaGVzKGJhc2VDbG9uZShzb3VyY2UsIENMT05FX0RFRVBfRkxBRykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgcGFydGlhbCBkZWVwIGNvbXBhcmlzb24gYmV0d2VlbiB0aGVcbiAgICAgKiB2YWx1ZSBhdCBgcGF0aGAgb2YgYSBnaXZlbiBvYmplY3QgdG8gYHNyY1ZhbHVlYCwgcmV0dXJuaW5nIGB0cnVlYCBpZiB0aGVcbiAgICAgKiBvYmplY3QgdmFsdWUgaXMgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFBhcnRpYWwgY29tcGFyaXNvbnMgd2lsbCBtYXRjaCBlbXB0eSBhcnJheSBhbmQgZW1wdHkgb2JqZWN0XG4gICAgICogYHNyY1ZhbHVlYCB2YWx1ZXMgYWdhaW5zdCBhbnkgYXJyYXkgb3Igb2JqZWN0IHZhbHVlLCByZXNwZWN0aXZlbHkuIFNlZVxuICAgICAqIGBfLmlzRXF1YWxgIGZvciBhIGxpc3Qgb2Ygc3VwcG9ydGVkIHZhbHVlIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE11bHRpcGxlIHZhbHVlcyBjYW4gYmUgY2hlY2tlZCBieSBjb21iaW5pbmcgc2V2ZXJhbCBtYXRjaGVyc1xuICAgICAqIHVzaW5nIGBfLm92ZXJTb21lYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMi4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzIH0sXG4gICAgICogICB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmQob2JqZWN0cywgXy5tYXRjaGVzUHJvcGVydHkoJ2EnLCA0KSk7XG4gICAgICogLy8gPT4geyAnYSc6IDQsICdiJzogNSwgJ2MnOiA2IH1cbiAgICAgKlxuICAgICAqIC8vIENoZWNraW5nIGZvciBzZXZlcmFsIHBvc3NpYmxlIHZhbHVlc1xuICAgICAqIF8uZmlsdGVyKG9iamVjdHMsIF8ub3ZlclNvbWUoW18ubWF0Y2hlc1Byb3BlcnR5KCdhJywgMSksIF8ubWF0Y2hlc1Byb3BlcnR5KCdhJywgNCldKSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LCB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXRjaGVzUHJvcGVydHkocGF0aCwgc3JjVmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlTWF0Y2hlc1Byb3BlcnR5KHBhdGgsIGJhc2VDbG9uZShzcmNWYWx1ZSwgQ0xPTkVfREVFUF9GTEFHKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdC5cbiAgICAgKiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGludm9rZXIgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiBfLmNvbnN0YW50KDIpIH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogXy5jb25zdGFudCgxKSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5tZXRob2QoJ2EuYicpKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKlxuICAgICAqIF8ubWFwKG9iamVjdHMsIF8ubWV0aG9kKFsnYScsICdiJ10pKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICB2YXIgbWV0aG9kID0gYmFzZVJlc3QoZnVuY3Rpb24ocGF0aCwgYXJncykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5tZXRob2RgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogdGhlIG1ldGhvZCBhdCBhIGdpdmVuIHBhdGggb2YgYG9iamVjdGAuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmVcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy43LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgaW52b2tlciBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gXy50aW1lcygzLCBfLmNvbnN0YW50KSxcbiAgICAgKiAgICAgb2JqZWN0ID0geyAnYSc6IGFycmF5LCAnYic6IGFycmF5LCAnYyc6IGFycmF5IH07XG4gICAgICpcbiAgICAgKiBfLm1hcChbJ2FbMl0nLCAnY1swXSddLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqL1xuICAgIHZhciBtZXRob2RPZiA9IGJhc2VSZXN0KGZ1bmN0aW9uKG9iamVjdCwgYXJncykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2Uob2JqZWN0LCBwYXRoLCBhcmdzKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGFsbCBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgZnVuY3Rpb24gcHJvcGVydGllcyBvZiBhIHNvdXJjZVxuICAgICAqIG9iamVjdCB0byB0aGUgZGVzdGluYXRpb24gb2JqZWN0LiBJZiBgb2JqZWN0YCBpcyBhIGZ1bmN0aW9uLCB0aGVuIG1ldGhvZHNcbiAgICAgKiBhcmUgYWRkZWQgdG8gaXRzIHByb3RvdHlwZSBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVzZSBgXy5ydW5JbkNvbnRleHRgIHRvIGNyZWF0ZSBhIHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHRvXG4gICAgICogYXZvaWQgY29uZmxpY3RzIGNhdXNlZCBieSBtb2RpZnlpbmcgdGhlIG9yaWdpbmFsLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdH0gW29iamVjdD1sb2Rhc2hdIFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5jaGFpbj10cnVlXSBTcGVjaWZ5IHdoZXRoZXIgbWl4aW5zIGFyZSBjaGFpbmFibGUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufE9iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gdm93ZWxzKHN0cmluZykge1xuICAgICAqICAgcmV0dXJuIF8uZmlsdGVyKHN0cmluZywgZnVuY3Rpb24odikge1xuICAgICAqICAgICByZXR1cm4gL1thZWlvdV0vaS50ZXN0KHYpO1xuICAgICAqICAgfSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5taXhpbih7ICd2b3dlbHMnOiB2b3dlbHMgfSk7XG4gICAgICogXy52b3dlbHMoJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiBbJ2UnXVxuICAgICAqXG4gICAgICogXygnZnJlZCcpLnZvd2VscygpLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWydlJ11cbiAgICAgKlxuICAgICAqIF8ubWl4aW4oeyAndm93ZWxzJzogdm93ZWxzIH0sIHsgJ2NoYWluJzogZmFsc2UgfSk7XG4gICAgICogXygnZnJlZCcpLnZvd2VscygpO1xuICAgICAqIC8vID0+IFsnZSddXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWl4aW4ob2JqZWN0LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBwcm9wcyA9IGtleXMoc291cmNlKSxcbiAgICAgICAgICBtZXRob2ROYW1lcyA9IGJhc2VGdW5jdGlvbnMoc291cmNlLCBwcm9wcyk7XG5cbiAgICAgIGlmIChvcHRpb25zID09IG51bGwgJiZcbiAgICAgICAgICAhKGlzT2JqZWN0KHNvdXJjZSkgJiYgKG1ldGhvZE5hbWVzLmxlbmd0aCB8fCAhcHJvcHMubGVuZ3RoKSkpIHtcbiAgICAgICAgb3B0aW9ucyA9IHNvdXJjZTtcbiAgICAgICAgc291cmNlID0gb2JqZWN0O1xuICAgICAgICBvYmplY3QgPSB0aGlzO1xuICAgICAgICBtZXRob2ROYW1lcyA9IGJhc2VGdW5jdGlvbnMoc291cmNlLCBrZXlzKHNvdXJjZSkpO1xuICAgICAgfVxuICAgICAgdmFyIGNoYWluID0gIShpc09iamVjdChvcHRpb25zKSAmJiAnY2hhaW4nIGluIG9wdGlvbnMpIHx8ICEhb3B0aW9ucy5jaGFpbixcbiAgICAgICAgICBpc0Z1bmMgPSBpc0Z1bmN0aW9uKG9iamVjdCk7XG5cbiAgICAgIGFycmF5RWFjaChtZXRob2ROYW1lcywgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgICB2YXIgZnVuYyA9IHNvdXJjZVttZXRob2ROYW1lXTtcbiAgICAgICAgb2JqZWN0W21ldGhvZE5hbWVdID0gZnVuYztcbiAgICAgICAgaWYgKGlzRnVuYykge1xuICAgICAgICAgIG9iamVjdC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fO1xuICAgICAgICAgICAgaWYgKGNoYWluIHx8IGNoYWluQWxsKSB7XG4gICAgICAgICAgICAgIHZhciByZXN1bHQgPSBvYmplY3QodGhpcy5fX3dyYXBwZWRfXyksXG4gICAgICAgICAgICAgICAgICBhY3Rpb25zID0gcmVzdWx0Ll9fYWN0aW9uc19fID0gY29weUFycmF5KHRoaXMuX19hY3Rpb25zX18pO1xuXG4gICAgICAgICAgICAgIGFjdGlvbnMucHVzaCh7ICdmdW5jJzogZnVuYywgJ2FyZ3MnOiBhcmd1bWVudHMsICd0aGlzQXJnJzogb2JqZWN0IH0pO1xuICAgICAgICAgICAgICByZXN1bHQuX19jaGFpbl9fID0gY2hhaW5BbGw7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseShvYmplY3QsIGFycmF5UHVzaChbdGhpcy52YWx1ZSgpXSwgYXJndW1lbnRzKSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgYF9gIHZhcmlhYmxlIHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0b1xuICAgICAqIHRoZSBgbG9kYXNoYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBgbG9kYXNoYCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGxvZGFzaCA9IF8ubm9Db25mbGljdCgpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICBpZiAocm9vdC5fID09PSB0aGlzKSB7XG4gICAgICAgIHJvb3QuXyA9IG9sZERhc2g7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygyLCBfLm5vb3ApO1xuICAgICAqIC8vID0+IFt1bmRlZmluZWQsIHVuZGVmaW5lZF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBub29wKCkge1xuICAgICAgLy8gTm8gb3BlcmF0aW9uIHBlcmZvcm1lZC5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBnZXRzIHRoZSBhcmd1bWVudCBhdCBpbmRleCBgbmAuIElmIGBuYCBpcyBuZWdhdGl2ZSxcbiAgICAgKiB0aGUgbnRoIGFyZ3VtZW50IGZyb20gdGhlIGVuZCBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTBdIFRoZSBpbmRleCBvZiB0aGUgYXJndW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhc3MtdGhydSBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm50aEFyZygxKTtcbiAgICAgKiBmdW5jKCdhJywgJ2InLCAnYycsICdkJyk7XG4gICAgICogLy8gPT4gJ2InXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ubnRoQXJnKC0yKTtcbiAgICAgKiBmdW5jKCdhJywgJ2InLCAnYycsICdkJyk7XG4gICAgICogLy8gPT4gJ2MnXG4gICAgICovXG4gICAgZnVuY3Rpb24gbnRoQXJnKG4pIHtcbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICByZXR1cm4gYmFzZU50aChhcmdzLCBuKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGl0ZXJhdGVlc2Agd2l0aCB0aGUgYXJndW1lbnRzIGl0IHJlY2VpdmVzXG4gICAgICogYW5kIHJldHVybnMgdGhlaXIgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IFtpdGVyYXRlZXM9W18uaWRlbnRpdHldXVxuICAgICAqICBUaGUgaXRlcmF0ZWVzIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm92ZXIoW01hdGgubWF4LCBNYXRoLm1pbl0pO1xuICAgICAqXG4gICAgICogZnVuYygxLCAyLCAzLCA0KTtcbiAgICAgKiAvLyA9PiBbNCwgMV1cbiAgICAgKi9cbiAgICB2YXIgb3ZlciA9IGNyZWF0ZU92ZXIoYXJyYXlNYXApO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYWxsKiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEZvbGxvd2luZyBzaG9ydGhhbmRzIGFyZSBwb3NzaWJsZSBmb3IgcHJvdmlkaW5nIHByZWRpY2F0ZXMuXG4gICAgICogUGFzcyBhbiBgT2JqZWN0YCBhbmQgaXQgd2lsbCBiZSB1c2VkIGFzIGFuIHBhcmFtZXRlciBmb3IgYF8ubWF0Y2hlc2AgdG8gY3JlYXRlIHRoZSBwcmVkaWNhdGUuXG4gICAgICogUGFzcyBhbiBgQXJyYXlgIG9mIHBhcmFtZXRlcnMgZm9yIGBfLm1hdGNoZXNQcm9wZXJ0eWAgYW5kIHRoZSBwcmVkaWNhdGUgd2lsbCBiZSBjcmVhdGVkIHVzaW5nIHRoZW0uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbcHJlZGljYXRlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBwcmVkaWNhdGVzIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlckV2ZXJ5KFtCb29sZWFuLCBpc0Zpbml0ZV0pO1xuICAgICAqXG4gICAgICogZnVuYygnMScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGZ1bmMobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIGZ1bmMoTmFOKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBvdmVyRXZlcnkgPSBjcmVhdGVPdmVyKGFycmF5RXZlcnkpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYW55Kiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEZvbGxvd2luZyBzaG9ydGhhbmRzIGFyZSBwb3NzaWJsZSBmb3IgcHJvdmlkaW5nIHByZWRpY2F0ZXMuXG4gICAgICogUGFzcyBhbiBgT2JqZWN0YCBhbmQgaXQgd2lsbCBiZSB1c2VkIGFzIGFuIHBhcmFtZXRlciBmb3IgYF8ubWF0Y2hlc2AgdG8gY3JlYXRlIHRoZSBwcmVkaWNhdGUuXG4gICAgICogUGFzcyBhbiBgQXJyYXlgIG9mIHBhcmFtZXRlcnMgZm9yIGBfLm1hdGNoZXNQcm9wZXJ0eWAgYW5kIHRoZSBwcmVkaWNhdGUgd2lsbCBiZSBjcmVhdGVkIHVzaW5nIHRoZW0uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbcHJlZGljYXRlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBwcmVkaWNhdGVzIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlclNvbWUoW0Jvb2xlYW4sIGlzRmluaXRlXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKCcxJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogZnVuYyhudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBmdW5jKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIHZhciBtYXRjaGVzRnVuYyA9IF8ub3ZlclNvbWUoW3sgJ2EnOiAxIH0sIHsgJ2EnOiAyIH1dKVxuICAgICAqIHZhciBtYXRjaGVzUHJvcGVydHlGdW5jID0gXy5vdmVyU29tZShbWydhJywgMV0sIFsnYScsIDJdXSlcbiAgICAgKi9cbiAgICB2YXIgb3ZlclNvbWUgPSBjcmVhdGVPdmVyKGFycmF5U29tZSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSB2YWx1ZSBhdCBgcGF0aGAgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiAyIH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogMSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5wcm9wZXJ0eSgnYS5iJykpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqXG4gICAgICogXy5tYXAoXy5zb3J0Qnkob2JqZWN0cywgXy5wcm9wZXJ0eShbJ2EnLCAnYiddKSksICdhLmInKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eShwYXRoKSB7XG4gICAgICByZXR1cm4gaXNLZXkocGF0aCkgPyBiYXNlUHJvcGVydHkodG9LZXkocGF0aCkpIDogYmFzZVByb3BlcnR5RGVlcChwYXRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucHJvcGVydHlgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zXG4gICAgICogdGhlIHZhbHVlIGF0IGEgZ2l2ZW4gcGF0aCBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFjY2Vzc29yIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMCwgMSwgMl0sXG4gICAgICogICAgIG9iamVjdCA9IHsgJ2EnOiBhcnJheSwgJ2InOiBhcnJheSwgJ2MnOiBhcnJheSB9O1xuICAgICAqXG4gICAgICogXy5tYXAoWydhWzJdJywgJ2NbMF0nXSwgXy5wcm9wZXJ0eU9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLnByb3BlcnR5T2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHJvcGVydHlPZihvYmplY3QpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihwYXRoKSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IGJhc2VHZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBudW1iZXJzIChwb3NpdGl2ZSBhbmQvb3IgbmVnYXRpdmUpIHByb2dyZXNzaW5nIGZyb21cbiAgICAgKiBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIEEgc3RlcCBvZiBgLTFgIGlzIHVzZWQgaWYgYSBuZWdhdGl2ZVxuICAgICAqIGBzdGFydGAgaXMgc3BlY2lmaWVkIHdpdGhvdXQgYW4gYGVuZGAgb3IgYHN0ZXBgLiBJZiBgZW5kYCBpcyBub3Qgc3BlY2lmaWVkLFxuICAgICAqIGl0J3Mgc2V0IHRvIGBzdGFydGAgd2l0aCBgc3RhcnRgIHRoZW4gc2V0IHRvIGAwYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0ZXA9MV0gVGhlIHZhbHVlIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5nZSBvZiBudW1iZXJzLlxuICAgICAqIEBzZWUgXy5pblJhbmdlLCBfLnJhbmdlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5nZSg0KTtcbiAgICAgKiAvLyA9PiBbMCwgMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoLTQpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA1KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgNF1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCwgMjAsIDUpO1xuICAgICAqIC8vID0+IFswLCA1LCAxMCwgMTVdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWzAsIC0xLCAtMiwgLTNdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDEsIDQsIDApO1xuICAgICAqIC8vID0+IFsxLCAxLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIHZhciByYW5nZSA9IGNyZWF0ZVJhbmdlKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJhbmdlYCBleGNlcHQgdGhhdCBpdCBwb3B1bGF0ZXMgdmFsdWVzIGluXG4gICAgICogZGVzY2VuZGluZyBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGVwPTFdIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZ2Ugb2YgbnVtYmVycy5cbiAgICAgKiBAc2VlIF8uaW5SYW5nZSwgXy5yYW5nZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoNCk7XG4gICAgICogLy8gPT4gWzMsIDIsIDEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoLTQpO1xuICAgICAqIC8vID0+IFstMywgLTIsIC0xLCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDEsIDUpO1xuICAgICAqIC8vID0+IFs0LCAzLCAyLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTUsIDEwLCA1LCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWy0zLCAtMiwgLTEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMSwgNCwgMCk7XG4gICAgICogLy8gPT4gWzEsIDEsIDFdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICB2YXIgcmFuZ2VSaWdodCA9IGNyZWF0ZVJhbmdlKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjEzLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGVtcHR5IGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXlzID0gXy50aW1lcygyLCBfLnN0dWJBcnJheSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXMpO1xuICAgICAqIC8vID0+IFtbXSwgW11dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXNbMF0gPT09IGFycmF5c1sxXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViQXJyYXkoKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTMuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygyLCBfLnN0dWJGYWxzZSk7XG4gICAgICogLy8gPT4gW2ZhbHNlLCBmYWxzZV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViRmFsc2UoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgZW1wdHkgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IF8udGltZXMoMiwgXy5zdHViT2JqZWN0KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdHMpO1xuICAgICAqIC8vID0+IFt7fSwge31dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3RzWzBdID09PSBvYmplY3RzWzFdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJPYmplY3QoKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlbXB0eSBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViU3RyaW5nKTtcbiAgICAgKiAvLyA9PiBbJycsICcnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJTdHJpbmcoKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViVHJ1ZSk7XG4gICAgICogLy8gPT4gW3RydWUsIHRydWVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3R1YlRydWUoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBpdGVyYXRlZSBgbmAgdGltZXMsIHJldHVybmluZyBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZlxuICAgICAqIGVhY2ggaW52b2NhdGlvbi4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7IChpbmRleCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gaW52b2tlIGBpdGVyYXRlZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRpbWVzKDMsIFN0cmluZyk7XG4gICAgICogLy8gPT4gWycwJywgJzEnLCAnMiddXG4gICAgICpcbiAgICAgKiAgXy50aW1lcyg0LCBfLmNvbnN0YW50KDApKTtcbiAgICAgKiAvLyA9PiBbMCwgMCwgMCwgMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aW1lcyhuLCBpdGVyYXRlZSkge1xuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIGlmIChuIDwgMSB8fCBuID4gTUFYX1NBRkVfSU5URUdFUikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBNQVhfQVJSQVlfTEVOR1RILFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihuLCBNQVhfQVJSQVlfTEVOR1RIKTtcblxuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSk7XG4gICAgICBuIC09IE1BWF9BUlJBWV9MRU5HVEg7XG5cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlVGltZXMobGVuZ3RoLCBpdGVyYXRlZSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgaXRlcmF0ZWUoaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvUGF0aCgnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIF8udG9QYXRoKCdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IFsnYScsICcwJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYXRoKHZhbHVlKSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5TWFwKHZhbHVlLCB0b0tleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNTeW1ib2wodmFsdWUpID8gW3ZhbHVlXSA6IGNvcHlBcnJheShzdHJpbmdUb1BhdGgodG9TdHJpbmcodmFsdWUpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGEgdW5pcXVlIElELiBJZiBgcHJlZml4YCBpcyBnaXZlbiwgdGhlIElEIGlzIGFwcGVuZGVkIHRvIGl0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD0nJ10gVGhlIHZhbHVlIHRvIHByZWZpeCB0aGUgSUQgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmlxdWUgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoJ2NvbnRhY3RfJyk7XG4gICAgICogLy8gPT4gJ2NvbnRhY3RfMTA0J1xuICAgICAqXG4gICAgICogXy51bmlxdWVJZCgpO1xuICAgICAqIC8vID0+ICcxMDUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcXVlSWQocHJlZml4KSB7XG4gICAgICB2YXIgaWQgPSArK2lkQ291bnRlcjtcbiAgICAgIHJldHVybiB0b1N0cmluZyhwcmVmaXgpICsgaWQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyB0d28gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjQuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGF1Z2VuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGFuIGFkZGl0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYW4gYWRkaXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdG90YWwuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYWRkKDYsIDQpO1xuICAgICAqIC8vID0+IDEwXG4gICAgICovXG4gICAgdmFyIGFkZCA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oYXVnZW5kLCBhZGRlbmQpIHtcbiAgICAgIHJldHVybiBhdWdlbmQgKyBhZGRlbmQ7XG4gICAgfSwgMCk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHVwIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kIHVwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdXAgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCB1cCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2VpbCg0LjAwNik7XG4gICAgICogLy8gPT4gNVxuICAgICAqXG4gICAgICogXy5jZWlsKDYuMDA0LCAyKTtcbiAgICAgKiAvLyA9PiA2LjAxXG4gICAgICpcbiAgICAgKiBfLmNlaWwoNjA0MCwgLTIpO1xuICAgICAqIC8vID0+IDYxMDBcbiAgICAgKi9cbiAgICB2YXIgY2VpbCA9IGNyZWF0ZVJvdW5kKCdjZWlsJyk7XG5cbiAgICAvKipcbiAgICAgKiBEaXZpZGUgdHdvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXZpZGVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgZGl2aXNpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRpdmlzb3IgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBkaXZpc2lvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBxdW90aWVudC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kaXZpZGUoNiwgNCk7XG4gICAgICogLy8gPT4gMS41XG4gICAgICovXG4gICAgdmFyIGRpdmlkZSA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgIHJldHVybiBkaXZpZGVuZCAvIGRpdmlzb3I7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIGRvd24gdG8gYHByZWNpc2lvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4xMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gcm91bmQgZG93bi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3ByZWNpc2lvbj0wXSBUaGUgcHJlY2lzaW9uIHRvIHJvdW5kIGRvd24gdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBkb3duIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mbG9vcig0LjAwNik7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5mbG9vcigwLjA0NiwgMik7XG4gICAgICogLy8gPT4gMC4wNFxuICAgICAqXG4gICAgICogXy5mbG9vcig0MDYwLCAtMik7XG4gICAgICogLy8gPT4gNDAwMFxuICAgICAqL1xuICAgIHZhciBmbG9vciA9IGNyZWF0ZVJvdW5kKCdmbG9vcicpO1xuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1heGltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXgoW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1heChhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUd0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1heGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF4aW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1heEJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDIgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXhCeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXhCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlR3QpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBtZWFuIG9mIHRoZSB2YWx1ZXMgaW4gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1lYW4oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVhbihhcnJheSkge1xuICAgICAgcmV0dXJuIGJhc2VNZWFuKGFycmF5LCBpZGVudGl0eSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5tZWFuYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgaW4gYGFycmF5YCB0byBnZW5lcmF0ZSB0aGUgdmFsdWUgdG8gYmUgYXZlcmFnZWQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG1lYW4uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ24nOiA0IH0sIHsgJ24nOiAyIH0sIHsgJ24nOiA4IH0sIHsgJ24nOiA2IH1dO1xuICAgICAqXG4gICAgICogXy5tZWFuQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1lYW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZWFuQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZU1lYW4oYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1pbmltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1pbmltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWluKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5taW4oW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1pbihhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUx0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1pbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWluaW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1pbkJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDEgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5taW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAxIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaW5CeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlTHQpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE11bHRpcGx5IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNy4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbXVsdGlwbGllciBUaGUgZmlyc3QgbnVtYmVyIGluIGEgbXVsdGlwbGljYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG11bHRpcGxpY2FuZCBUaGUgc2Vjb25kIG51bWJlciBpbiBhIG11bHRpcGxpY2F0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHByb2R1Y3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubXVsdGlwbHkoNiwgNCk7XG4gICAgICogLy8gPT4gMjRcbiAgICAgKi9cbiAgICB2YXIgbXVsdGlwbHkgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG11bHRpcGxpZXIsIG11bHRpcGxpY2FuZCkge1xuICAgICAgcmV0dXJuIG11bHRpcGxpZXIgKiBtdWx0aXBsaWNhbmQ7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYsIDIpO1xuICAgICAqIC8vID0+IDQuMDFcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNDA2MCwgLTIpO1xuICAgICAqIC8vID0+IDQxMDBcbiAgICAgKi9cbiAgICB2YXIgcm91bmQgPSBjcmVhdGVSb3VuZCgncm91bmQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRyYWN0IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWludWVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgc3VidHJhY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN1YnRyYWhlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBzdWJ0cmFjdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBkaWZmZXJlbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN1YnRyYWN0KDYsIDQpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICB2YXIgc3VidHJhY3QgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG1pbnVlbmQsIHN1YnRyYWhlbmQpIHtcbiAgICAgIHJldHVybiBtaW51ZW5kIC0gc3VidHJhaGVuZDtcbiAgICB9LCAwKTtcblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuNC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdW0oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN1bShhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVN1bShhcnJheSwgaWRlbnRpdHkpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnN1bWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIHZhbHVlIHRvIGJlIHN1bW1lZC5cbiAgICAgKiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICduJzogNCB9LCB7ICduJzogMiB9LCB7ICduJzogOCB9LCB7ICduJzogNiB9XTtcbiAgICAgKlxuICAgICAqIF8uc3VtQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zdW1CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDIwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3VtQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU3VtKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0aGF0IHJldHVybiB3cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFmdGVyID0gYWZ0ZXI7XG4gICAgbG9kYXNoLmFyeSA9IGFyeTtcbiAgICBsb2Rhc2guYXNzaWduID0gYXNzaWduO1xuICAgIGxvZGFzaC5hc3NpZ25JbiA9IGFzc2lnbkluO1xuICAgIGxvZGFzaC5hc3NpZ25JbldpdGggPSBhc3NpZ25JbldpdGg7XG4gICAgbG9kYXNoLmFzc2lnbldpdGggPSBhc3NpZ25XaXRoO1xuICAgIGxvZGFzaC5hdCA9IGF0O1xuICAgIGxvZGFzaC5iZWZvcmUgPSBiZWZvcmU7XG4gICAgbG9kYXNoLmJpbmQgPSBiaW5kO1xuICAgIGxvZGFzaC5iaW5kQWxsID0gYmluZEFsbDtcbiAgICBsb2Rhc2guYmluZEtleSA9IGJpbmRLZXk7XG4gICAgbG9kYXNoLmNhc3RBcnJheSA9IGNhc3RBcnJheTtcbiAgICBsb2Rhc2guY2hhaW4gPSBjaGFpbjtcbiAgICBsb2Rhc2guY2h1bmsgPSBjaHVuaztcbiAgICBsb2Rhc2guY29tcGFjdCA9IGNvbXBhY3Q7XG4gICAgbG9kYXNoLmNvbmNhdCA9IGNvbmNhdDtcbiAgICBsb2Rhc2guY29uZCA9IGNvbmQ7XG4gICAgbG9kYXNoLmNvbmZvcm1zID0gY29uZm9ybXM7XG4gICAgbG9kYXNoLmNvbnN0YW50ID0gY29uc3RhbnQ7XG4gICAgbG9kYXNoLmNvdW50QnkgPSBjb3VudEJ5O1xuICAgIGxvZGFzaC5jcmVhdGUgPSBjcmVhdGU7XG4gICAgbG9kYXNoLmN1cnJ5ID0gY3Vycnk7XG4gICAgbG9kYXNoLmN1cnJ5UmlnaHQgPSBjdXJyeVJpZ2h0O1xuICAgIGxvZGFzaC5kZWJvdW5jZSA9IGRlYm91bmNlO1xuICAgIGxvZGFzaC5kZWZhdWx0cyA9IGRlZmF1bHRzO1xuICAgIGxvZGFzaC5kZWZhdWx0c0RlZXAgPSBkZWZhdWx0c0RlZXA7XG4gICAgbG9kYXNoLmRlZmVyID0gZGVmZXI7XG4gICAgbG9kYXNoLmRlbGF5ID0gZGVsYXk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2UgPSBkaWZmZXJlbmNlO1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlQnkgPSBkaWZmZXJlbmNlQnk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2VXaXRoID0gZGlmZmVyZW5jZVdpdGg7XG4gICAgbG9kYXNoLmRyb3AgPSBkcm9wO1xuICAgIGxvZGFzaC5kcm9wUmlnaHQgPSBkcm9wUmlnaHQ7XG4gICAgbG9kYXNoLmRyb3BSaWdodFdoaWxlID0gZHJvcFJpZ2h0V2hpbGU7XG4gICAgbG9kYXNoLmRyb3BXaGlsZSA9IGRyb3BXaGlsZTtcbiAgICBsb2Rhc2guZmlsbCA9IGZpbGw7XG4gICAgbG9kYXNoLmZpbHRlciA9IGZpbHRlcjtcbiAgICBsb2Rhc2guZmxhdE1hcCA9IGZsYXRNYXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZWVwID0gZmxhdE1hcERlZXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZXB0aCA9IGZsYXRNYXBEZXB0aDtcbiAgICBsb2Rhc2guZmxhdHRlbiA9IGZsYXR0ZW47XG4gICAgbG9kYXNoLmZsYXR0ZW5EZWVwID0gZmxhdHRlbkRlZXA7XG4gICAgbG9kYXNoLmZsYXR0ZW5EZXB0aCA9IGZsYXR0ZW5EZXB0aDtcbiAgICBsb2Rhc2guZmxpcCA9IGZsaXA7XG4gICAgbG9kYXNoLmZsb3cgPSBmbG93O1xuICAgIGxvZGFzaC5mbG93UmlnaHQgPSBmbG93UmlnaHQ7XG4gICAgbG9kYXNoLmZyb21QYWlycyA9IGZyb21QYWlycztcbiAgICBsb2Rhc2guZnVuY3Rpb25zID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5mdW5jdGlvbnNJbiA9IGZ1bmN0aW9uc0luO1xuICAgIGxvZGFzaC5ncm91cEJ5ID0gZ3JvdXBCeTtcbiAgICBsb2Rhc2guaW5pdGlhbCA9IGluaXRpYWw7XG4gICAgbG9kYXNoLmludGVyc2VjdGlvbiA9IGludGVyc2VjdGlvbjtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uQnkgPSBpbnRlcnNlY3Rpb25CeTtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uV2l0aCA9IGludGVyc2VjdGlvbldpdGg7XG4gICAgbG9kYXNoLmludmVydCA9IGludmVydDtcbiAgICBsb2Rhc2guaW52ZXJ0QnkgPSBpbnZlcnRCeTtcbiAgICBsb2Rhc2guaW52b2tlTWFwID0gaW52b2tlTWFwO1xuICAgIGxvZGFzaC5pdGVyYXRlZSA9IGl0ZXJhdGVlO1xuICAgIGxvZGFzaC5rZXlCeSA9IGtleUJ5O1xuICAgIGxvZGFzaC5rZXlzID0ga2V5cztcbiAgICBsb2Rhc2gua2V5c0luID0ga2V5c0luO1xuICAgIGxvZGFzaC5tYXAgPSBtYXA7XG4gICAgbG9kYXNoLm1hcEtleXMgPSBtYXBLZXlzO1xuICAgIGxvZGFzaC5tYXBWYWx1ZXMgPSBtYXBWYWx1ZXM7XG4gICAgbG9kYXNoLm1hdGNoZXMgPSBtYXRjaGVzO1xuICAgIGxvZGFzaC5tYXRjaGVzUHJvcGVydHkgPSBtYXRjaGVzUHJvcGVydHk7XG4gICAgbG9kYXNoLm1lbW9pemUgPSBtZW1vaXplO1xuICAgIGxvZGFzaC5tZXJnZSA9IG1lcmdlO1xuICAgIGxvZGFzaC5tZXJnZVdpdGggPSBtZXJnZVdpdGg7XG4gICAgbG9kYXNoLm1ldGhvZCA9IG1ldGhvZDtcbiAgICBsb2Rhc2gubWV0aG9kT2YgPSBtZXRob2RPZjtcbiAgICBsb2Rhc2gubWl4aW4gPSBtaXhpbjtcbiAgICBsb2Rhc2gubmVnYXRlID0gbmVnYXRlO1xuICAgIGxvZGFzaC5udGhBcmcgPSBudGhBcmc7XG4gICAgbG9kYXNoLm9taXQgPSBvbWl0O1xuICAgIGxvZGFzaC5vbWl0QnkgPSBvbWl0Qnk7XG4gICAgbG9kYXNoLm9uY2UgPSBvbmNlO1xuICAgIGxvZGFzaC5vcmRlckJ5ID0gb3JkZXJCeTtcbiAgICBsb2Rhc2gub3ZlciA9IG92ZXI7XG4gICAgbG9kYXNoLm92ZXJBcmdzID0gb3ZlckFyZ3M7XG4gICAgbG9kYXNoLm92ZXJFdmVyeSA9IG92ZXJFdmVyeTtcbiAgICBsb2Rhc2gub3ZlclNvbWUgPSBvdmVyU29tZTtcbiAgICBsb2Rhc2gucGFydGlhbCA9IHBhcnRpYWw7XG4gICAgbG9kYXNoLnBhcnRpYWxSaWdodCA9IHBhcnRpYWxSaWdodDtcbiAgICBsb2Rhc2gucGFydGl0aW9uID0gcGFydGl0aW9uO1xuICAgIGxvZGFzaC5waWNrID0gcGljaztcbiAgICBsb2Rhc2gucGlja0J5ID0gcGlja0J5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eSA9IHByb3BlcnR5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eU9mID0gcHJvcGVydHlPZjtcbiAgICBsb2Rhc2gucHVsbCA9IHB1bGw7XG4gICAgbG9kYXNoLnB1bGxBbGwgPSBwdWxsQWxsO1xuICAgIGxvZGFzaC5wdWxsQWxsQnkgPSBwdWxsQWxsQnk7XG4gICAgbG9kYXNoLnB1bGxBbGxXaXRoID0gcHVsbEFsbFdpdGg7XG4gICAgbG9kYXNoLnB1bGxBdCA9IHB1bGxBdDtcbiAgICBsb2Rhc2gucmFuZ2UgPSByYW5nZTtcbiAgICBsb2Rhc2gucmFuZ2VSaWdodCA9IHJhbmdlUmlnaHQ7XG4gICAgbG9kYXNoLnJlYXJnID0gcmVhcmc7XG4gICAgbG9kYXNoLnJlamVjdCA9IHJlamVjdDtcbiAgICBsb2Rhc2gucmVtb3ZlID0gcmVtb3ZlO1xuICAgIGxvZGFzaC5yZXN0ID0gcmVzdDtcbiAgICBsb2Rhc2gucmV2ZXJzZSA9IHJldmVyc2U7XG4gICAgbG9kYXNoLnNhbXBsZVNpemUgPSBzYW1wbGVTaXplO1xuICAgIGxvZGFzaC5zZXQgPSBzZXQ7XG4gICAgbG9kYXNoLnNldFdpdGggPSBzZXRXaXRoO1xuICAgIGxvZGFzaC5zaHVmZmxlID0gc2h1ZmZsZTtcbiAgICBsb2Rhc2guc2xpY2UgPSBzbGljZTtcbiAgICBsb2Rhc2guc29ydEJ5ID0gc29ydEJ5O1xuICAgIGxvZGFzaC5zb3J0ZWRVbmlxID0gc29ydGVkVW5pcTtcbiAgICBsb2Rhc2guc29ydGVkVW5pcUJ5ID0gc29ydGVkVW5pcUJ5O1xuICAgIGxvZGFzaC5zcGxpdCA9IHNwbGl0O1xuICAgIGxvZGFzaC5zcHJlYWQgPSBzcHJlYWQ7XG4gICAgbG9kYXNoLnRhaWwgPSB0YWlsO1xuICAgIGxvZGFzaC50YWtlID0gdGFrZTtcbiAgICBsb2Rhc2gudGFrZVJpZ2h0ID0gdGFrZVJpZ2h0O1xuICAgIGxvZGFzaC50YWtlUmlnaHRXaGlsZSA9IHRha2VSaWdodFdoaWxlO1xuICAgIGxvZGFzaC50YWtlV2hpbGUgPSB0YWtlV2hpbGU7XG4gICAgbG9kYXNoLnRhcCA9IHRhcDtcbiAgICBsb2Rhc2gudGhyb3R0bGUgPSB0aHJvdHRsZTtcbiAgICBsb2Rhc2gudGhydSA9IHRocnU7XG4gICAgbG9kYXNoLnRvQXJyYXkgPSB0b0FycmF5O1xuICAgIGxvZGFzaC50b1BhaXJzID0gdG9QYWlycztcbiAgICBsb2Rhc2gudG9QYWlyc0luID0gdG9QYWlyc0luO1xuICAgIGxvZGFzaC50b1BhdGggPSB0b1BhdGg7XG4gICAgbG9kYXNoLnRvUGxhaW5PYmplY3QgPSB0b1BsYWluT2JqZWN0O1xuICAgIGxvZGFzaC50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG4gICAgbG9kYXNoLnVuYXJ5ID0gdW5hcnk7XG4gICAgbG9kYXNoLnVuaW9uID0gdW5pb247XG4gICAgbG9kYXNoLnVuaW9uQnkgPSB1bmlvbkJ5O1xuICAgIGxvZGFzaC51bmlvbldpdGggPSB1bmlvbldpdGg7XG4gICAgbG9kYXNoLnVuaXEgPSB1bmlxO1xuICAgIGxvZGFzaC51bmlxQnkgPSB1bmlxQnk7XG4gICAgbG9kYXNoLnVuaXFXaXRoID0gdW5pcVdpdGg7XG4gICAgbG9kYXNoLnVuc2V0ID0gdW5zZXQ7XG4gICAgbG9kYXNoLnVuemlwID0gdW56aXA7XG4gICAgbG9kYXNoLnVuemlwV2l0aCA9IHVuemlwV2l0aDtcbiAgICBsb2Rhc2gudXBkYXRlID0gdXBkYXRlO1xuICAgIGxvZGFzaC51cGRhdGVXaXRoID0gdXBkYXRlV2l0aDtcbiAgICBsb2Rhc2gudmFsdWVzID0gdmFsdWVzO1xuICAgIGxvZGFzaC52YWx1ZXNJbiA9IHZhbHVlc0luO1xuICAgIGxvZGFzaC53aXRob3V0ID0gd2l0aG91dDtcbiAgICBsb2Rhc2gud29yZHMgPSB3b3JkcztcbiAgICBsb2Rhc2gud3JhcCA9IHdyYXA7XG4gICAgbG9kYXNoLnhvciA9IHhvcjtcbiAgICBsb2Rhc2gueG9yQnkgPSB4b3JCeTtcbiAgICBsb2Rhc2gueG9yV2l0aCA9IHhvcldpdGg7XG4gICAgbG9kYXNoLnppcCA9IHppcDtcbiAgICBsb2Rhc2guemlwT2JqZWN0ID0gemlwT2JqZWN0O1xuICAgIGxvZGFzaC56aXBPYmplY3REZWVwID0gemlwT2JqZWN0RGVlcDtcbiAgICBsb2Rhc2guemlwV2l0aCA9IHppcFdpdGg7XG5cbiAgICAvLyBBZGQgYWxpYXNlcy5cbiAgICBsb2Rhc2guZW50cmllcyA9IHRvUGFpcnM7XG4gICAgbG9kYXNoLmVudHJpZXNJbiA9IHRvUGFpcnNJbjtcbiAgICBsb2Rhc2guZXh0ZW5kID0gYXNzaWduSW47XG4gICAgbG9kYXNoLmV4dGVuZFdpdGggPSBhc3NpZ25JbldpdGg7XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgbWl4aW4obG9kYXNoLCBsb2Rhc2gpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQWRkIG1ldGhvZHMgdGhhdCByZXR1cm4gdW53cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFkZCA9IGFkZDtcbiAgICBsb2Rhc2guYXR0ZW1wdCA9IGF0dGVtcHQ7XG4gICAgbG9kYXNoLmNhbWVsQ2FzZSA9IGNhbWVsQ2FzZTtcbiAgICBsb2Rhc2guY2FwaXRhbGl6ZSA9IGNhcGl0YWxpemU7XG4gICAgbG9kYXNoLmNlaWwgPSBjZWlsO1xuICAgIGxvZGFzaC5jbGFtcCA9IGNsYW1wO1xuICAgIGxvZGFzaC5jbG9uZSA9IGNsb25lO1xuICAgIGxvZGFzaC5jbG9uZURlZXAgPSBjbG9uZURlZXA7XG4gICAgbG9kYXNoLmNsb25lRGVlcFdpdGggPSBjbG9uZURlZXBXaXRoO1xuICAgIGxvZGFzaC5jbG9uZVdpdGggPSBjbG9uZVdpdGg7XG4gICAgbG9kYXNoLmNvbmZvcm1zVG8gPSBjb25mb3Jtc1RvO1xuICAgIGxvZGFzaC5kZWJ1cnIgPSBkZWJ1cnI7XG4gICAgbG9kYXNoLmRlZmF1bHRUbyA9IGRlZmF1bHRUbztcbiAgICBsb2Rhc2guZGl2aWRlID0gZGl2aWRlO1xuICAgIGxvZGFzaC5lbmRzV2l0aCA9IGVuZHNXaXRoO1xuICAgIGxvZGFzaC5lcSA9IGVxO1xuICAgIGxvZGFzaC5lc2NhcGUgPSBlc2NhcGU7XG4gICAgbG9kYXNoLmVzY2FwZVJlZ0V4cCA9IGVzY2FwZVJlZ0V4cDtcbiAgICBsb2Rhc2guZXZlcnkgPSBldmVyeTtcbiAgICBsb2Rhc2guZmluZCA9IGZpbmQ7XG4gICAgbG9kYXNoLmZpbmRJbmRleCA9IGZpbmRJbmRleDtcbiAgICBsb2Rhc2guZmluZEtleSA9IGZpbmRLZXk7XG4gICAgbG9kYXNoLmZpbmRMYXN0ID0gZmluZExhc3Q7XG4gICAgbG9kYXNoLmZpbmRMYXN0SW5kZXggPSBmaW5kTGFzdEluZGV4O1xuICAgIGxvZGFzaC5maW5kTGFzdEtleSA9IGZpbmRMYXN0S2V5O1xuICAgIGxvZGFzaC5mbG9vciA9IGZsb29yO1xuICAgIGxvZGFzaC5mb3JFYWNoID0gZm9yRWFjaDtcbiAgICBsb2Rhc2guZm9yRWFjaFJpZ2h0ID0gZm9yRWFjaFJpZ2h0O1xuICAgIGxvZGFzaC5mb3JJbiA9IGZvckluO1xuICAgIGxvZGFzaC5mb3JJblJpZ2h0ID0gZm9ySW5SaWdodDtcbiAgICBsb2Rhc2guZm9yT3duID0gZm9yT3duO1xuICAgIGxvZGFzaC5mb3JPd25SaWdodCA9IGZvck93blJpZ2h0O1xuICAgIGxvZGFzaC5nZXQgPSBnZXQ7XG4gICAgbG9kYXNoLmd0ID0gZ3Q7XG4gICAgbG9kYXNoLmd0ZSA9IGd0ZTtcbiAgICBsb2Rhc2guaGFzID0gaGFzO1xuICAgIGxvZGFzaC5oYXNJbiA9IGhhc0luO1xuICAgIGxvZGFzaC5oZWFkID0gaGVhZDtcbiAgICBsb2Rhc2guaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICBsb2Rhc2guaW5jbHVkZXMgPSBpbmNsdWRlcztcbiAgICBsb2Rhc2guaW5kZXhPZiA9IGluZGV4T2Y7XG4gICAgbG9kYXNoLmluUmFuZ2UgPSBpblJhbmdlO1xuICAgIGxvZGFzaC5pbnZva2UgPSBpbnZva2U7XG4gICAgbG9kYXNoLmlzQXJndW1lbnRzID0gaXNBcmd1bWVudHM7XG4gICAgbG9kYXNoLmlzQXJyYXkgPSBpc0FycmF5O1xuICAgIGxvZGFzaC5pc0FycmF5QnVmZmVyID0gaXNBcnJheUJ1ZmZlcjtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2UgPSBpc0FycmF5TGlrZTtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2VPYmplY3QgPSBpc0FycmF5TGlrZU9iamVjdDtcbiAgICBsb2Rhc2guaXNCb29sZWFuID0gaXNCb29sZWFuO1xuICAgIGxvZGFzaC5pc0J1ZmZlciA9IGlzQnVmZmVyO1xuICAgIGxvZGFzaC5pc0RhdGUgPSBpc0RhdGU7XG4gICAgbG9kYXNoLmlzRWxlbWVudCA9IGlzRWxlbWVudDtcbiAgICBsb2Rhc2guaXNFbXB0eSA9IGlzRW1wdHk7XG4gICAgbG9kYXNoLmlzRXF1YWwgPSBpc0VxdWFsO1xuICAgIGxvZGFzaC5pc0VxdWFsV2l0aCA9IGlzRXF1YWxXaXRoO1xuICAgIGxvZGFzaC5pc0Vycm9yID0gaXNFcnJvcjtcbiAgICBsb2Rhc2guaXNGaW5pdGUgPSBpc0Zpbml0ZTtcbiAgICBsb2Rhc2guaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG4gICAgbG9kYXNoLmlzSW50ZWdlciA9IGlzSW50ZWdlcjtcbiAgICBsb2Rhc2guaXNMZW5ndGggPSBpc0xlbmd0aDtcbiAgICBsb2Rhc2guaXNNYXAgPSBpc01hcDtcbiAgICBsb2Rhc2guaXNNYXRjaCA9IGlzTWF0Y2g7XG4gICAgbG9kYXNoLmlzTWF0Y2hXaXRoID0gaXNNYXRjaFdpdGg7XG4gICAgbG9kYXNoLmlzTmFOID0gaXNOYU47XG4gICAgbG9kYXNoLmlzTmF0aXZlID0gaXNOYXRpdmU7XG4gICAgbG9kYXNoLmlzTmlsID0gaXNOaWw7XG4gICAgbG9kYXNoLmlzTnVsbCA9IGlzTnVsbDtcbiAgICBsb2Rhc2guaXNOdW1iZXIgPSBpc051bWJlcjtcbiAgICBsb2Rhc2guaXNPYmplY3QgPSBpc09iamVjdDtcbiAgICBsb2Rhc2guaXNPYmplY3RMaWtlID0gaXNPYmplY3RMaWtlO1xuICAgIGxvZGFzaC5pc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdDtcbiAgICBsb2Rhc2guaXNSZWdFeHAgPSBpc1JlZ0V4cDtcbiAgICBsb2Rhc2guaXNTYWZlSW50ZWdlciA9IGlzU2FmZUludGVnZXI7XG4gICAgbG9kYXNoLmlzU2V0ID0gaXNTZXQ7XG4gICAgbG9kYXNoLmlzU3RyaW5nID0gaXNTdHJpbmc7XG4gICAgbG9kYXNoLmlzU3ltYm9sID0gaXNTeW1ib2w7XG4gICAgbG9kYXNoLmlzVHlwZWRBcnJheSA9IGlzVHlwZWRBcnJheTtcbiAgICBsb2Rhc2guaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcbiAgICBsb2Rhc2guaXNXZWFrTWFwID0gaXNXZWFrTWFwO1xuICAgIGxvZGFzaC5pc1dlYWtTZXQgPSBpc1dlYWtTZXQ7XG4gICAgbG9kYXNoLmpvaW4gPSBqb2luO1xuICAgIGxvZGFzaC5rZWJhYkNhc2UgPSBrZWJhYkNhc2U7XG4gICAgbG9kYXNoLmxhc3QgPSBsYXN0O1xuICAgIGxvZGFzaC5sYXN0SW5kZXhPZiA9IGxhc3RJbmRleE9mO1xuICAgIGxvZGFzaC5sb3dlckNhc2UgPSBsb3dlckNhc2U7XG4gICAgbG9kYXNoLmxvd2VyRmlyc3QgPSBsb3dlckZpcnN0O1xuICAgIGxvZGFzaC5sdCA9IGx0O1xuICAgIGxvZGFzaC5sdGUgPSBsdGU7XG4gICAgbG9kYXNoLm1heCA9IG1heDtcbiAgICBsb2Rhc2gubWF4QnkgPSBtYXhCeTtcbiAgICBsb2Rhc2gubWVhbiA9IG1lYW47XG4gICAgbG9kYXNoLm1lYW5CeSA9IG1lYW5CeTtcbiAgICBsb2Rhc2gubWluID0gbWluO1xuICAgIGxvZGFzaC5taW5CeSA9IG1pbkJ5O1xuICAgIGxvZGFzaC5zdHViQXJyYXkgPSBzdHViQXJyYXk7XG4gICAgbG9kYXNoLnN0dWJGYWxzZSA9IHN0dWJGYWxzZTtcbiAgICBsb2Rhc2guc3R1Yk9iamVjdCA9IHN0dWJPYmplY3Q7XG4gICAgbG9kYXNoLnN0dWJTdHJpbmcgPSBzdHViU3RyaW5nO1xuICAgIGxvZGFzaC5zdHViVHJ1ZSA9IHN0dWJUcnVlO1xuICAgIGxvZGFzaC5tdWx0aXBseSA9IG11bHRpcGx5O1xuICAgIGxvZGFzaC5udGggPSBudGg7XG4gICAgbG9kYXNoLm5vQ29uZmxpY3QgPSBub0NvbmZsaWN0O1xuICAgIGxvZGFzaC5ub29wID0gbm9vcDtcbiAgICBsb2Rhc2gubm93ID0gbm93O1xuICAgIGxvZGFzaC5wYWQgPSBwYWQ7XG4gICAgbG9kYXNoLnBhZEVuZCA9IHBhZEVuZDtcbiAgICBsb2Rhc2gucGFkU3RhcnQgPSBwYWRTdGFydDtcbiAgICBsb2Rhc2gucGFyc2VJbnQgPSBwYXJzZUludDtcbiAgICBsb2Rhc2gucmFuZG9tID0gcmFuZG9tO1xuICAgIGxvZGFzaC5yZWR1Y2UgPSByZWR1Y2U7XG4gICAgbG9kYXNoLnJlZHVjZVJpZ2h0ID0gcmVkdWNlUmlnaHQ7XG4gICAgbG9kYXNoLnJlcGVhdCA9IHJlcGVhdDtcbiAgICBsb2Rhc2gucmVwbGFjZSA9IHJlcGxhY2U7XG4gICAgbG9kYXNoLnJlc3VsdCA9IHJlc3VsdDtcbiAgICBsb2Rhc2gucm91bmQgPSByb3VuZDtcbiAgICBsb2Rhc2gucnVuSW5Db250ZXh0ID0gcnVuSW5Db250ZXh0O1xuICAgIGxvZGFzaC5zYW1wbGUgPSBzYW1wbGU7XG4gICAgbG9kYXNoLnNpemUgPSBzaXplO1xuICAgIGxvZGFzaC5zbmFrZUNhc2UgPSBzbmFrZUNhc2U7XG4gICAgbG9kYXNoLnNvbWUgPSBzb21lO1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleCA9IHNvcnRlZEluZGV4O1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleEJ5ID0gc29ydGVkSW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXhPZiA9IHNvcnRlZEluZGV4T2Y7XG4gICAgbG9kYXNoLnNvcnRlZExhc3RJbmRleCA9IHNvcnRlZExhc3RJbmRleDtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4QnkgPSBzb3J0ZWRMYXN0SW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4T2YgPSBzb3J0ZWRMYXN0SW5kZXhPZjtcbiAgICBsb2Rhc2guc3RhcnRDYXNlID0gc3RhcnRDYXNlO1xuICAgIGxvZGFzaC5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcbiAgICBsb2Rhc2guc3VidHJhY3QgPSBzdWJ0cmFjdDtcbiAgICBsb2Rhc2guc3VtID0gc3VtO1xuICAgIGxvZGFzaC5zdW1CeSA9IHN1bUJ5O1xuICAgIGxvZGFzaC50ZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIGxvZGFzaC50aW1lcyA9IHRpbWVzO1xuICAgIGxvZGFzaC50b0Zpbml0ZSA9IHRvRmluaXRlO1xuICAgIGxvZGFzaC50b0ludGVnZXIgPSB0b0ludGVnZXI7XG4gICAgbG9kYXNoLnRvTGVuZ3RoID0gdG9MZW5ndGg7XG4gICAgbG9kYXNoLnRvTG93ZXIgPSB0b0xvd2VyO1xuICAgIGxvZGFzaC50b051bWJlciA9IHRvTnVtYmVyO1xuICAgIGxvZGFzaC50b1NhZmVJbnRlZ2VyID0gdG9TYWZlSW50ZWdlcjtcbiAgICBsb2Rhc2gudG9TdHJpbmcgPSB0b1N0cmluZztcbiAgICBsb2Rhc2gudG9VcHBlciA9IHRvVXBwZXI7XG4gICAgbG9kYXNoLnRyaW0gPSB0cmltO1xuICAgIGxvZGFzaC50cmltRW5kID0gdHJpbUVuZDtcbiAgICBsb2Rhc2gudHJpbVN0YXJ0ID0gdHJpbVN0YXJ0O1xuICAgIGxvZGFzaC50cnVuY2F0ZSA9IHRydW5jYXRlO1xuICAgIGxvZGFzaC51bmVzY2FwZSA9IHVuZXNjYXBlO1xuICAgIGxvZGFzaC51bmlxdWVJZCA9IHVuaXF1ZUlkO1xuICAgIGxvZGFzaC51cHBlckNhc2UgPSB1cHBlckNhc2U7XG4gICAgbG9kYXNoLnVwcGVyRmlyc3QgPSB1cHBlckZpcnN0O1xuXG4gICAgLy8gQWRkIGFsaWFzZXMuXG4gICAgbG9kYXNoLmVhY2ggPSBmb3JFYWNoO1xuICAgIGxvZGFzaC5lYWNoUmlnaHQgPSBmb3JFYWNoUmlnaHQ7XG4gICAgbG9kYXNoLmZpcnN0ID0gaGVhZDtcblxuICAgIG1peGluKGxvZGFzaCwgKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHNvdXJjZSA9IHt9O1xuICAgICAgYmFzZUZvck93bihsb2Rhc2gsIGZ1bmN0aW9uKGZ1bmMsIG1ldGhvZE5hbWUpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKGxvZGFzaC5wcm90b3R5cGUsIG1ldGhvZE5hbWUpKSB7XG4gICAgICAgICAgc291cmNlW21ldGhvZE5hbWVdID0gZnVuYztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gc291cmNlO1xuICAgIH0oKSksIHsgJ2NoYWluJzogZmFsc2UgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIGxvZGFzaC5WRVJTSU9OID0gVkVSU0lPTjtcblxuICAgIC8vIEFzc2lnbiBkZWZhdWx0IHBsYWNlaG9sZGVycy5cbiAgICBhcnJheUVhY2goWydiaW5kJywgJ2JpbmRLZXknLCAnY3VycnknLCAnY3VycnlSaWdodCcsICdwYXJ0aWFsJywgJ3BhcnRpYWxSaWdodCddLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICBsb2Rhc2hbbWV0aG9kTmFtZV0ucGxhY2Vob2xkZXIgPSBsb2Rhc2g7XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5kcm9wYCBhbmQgYF8udGFrZWAgdmFyaWFudHMuXG4gICAgYXJyYXlFYWNoKFsnZHJvcCcsICd0YWtlJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihuKSB7XG4gICAgICAgIG4gPSBuID09PSB1bmRlZmluZWQgPyAxIDogbmF0aXZlTWF4KHRvSW50ZWdlcihuKSwgMCk7XG5cbiAgICAgICAgdmFyIHJlc3VsdCA9ICh0aGlzLl9fZmlsdGVyZWRfXyAmJiAhaW5kZXgpXG4gICAgICAgICAgPyBuZXcgTGF6eVdyYXBwZXIodGhpcylcbiAgICAgICAgICA6IHRoaXMuY2xvbmUoKTtcblxuICAgICAgICBpZiAocmVzdWx0Ll9fZmlsdGVyZWRfXykge1xuICAgICAgICAgIHJlc3VsdC5fX3Rha2VDb3VudF9fID0gbmF0aXZlTWluKG4sIHJlc3VsdC5fX3Rha2VDb3VudF9fKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQuX192aWV3c19fLnB1c2goe1xuICAgICAgICAgICAgJ3NpemUnOiBuYXRpdmVNaW4obiwgTUFYX0FSUkFZX0xFTkdUSCksXG4gICAgICAgICAgICAndHlwZSc6IG1ldGhvZE5hbWUgKyAocmVzdWx0Ll9fZGlyX18gPCAwID8gJ1JpZ2h0JyA6ICcnKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZSArICdSaWdodCddID0gZnVuY3Rpb24obikge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlKClbbWV0aG9kTmFtZV0obikucmV2ZXJzZSgpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgdGhhdCBhY2NlcHQgYW4gYGl0ZXJhdGVlYCB2YWx1ZS5cbiAgICBhcnJheUVhY2goWydmaWx0ZXInLCAnbWFwJywgJ3Rha2VXaGlsZSddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIHR5cGUgPSBpbmRleCArIDEsXG4gICAgICAgICAgaXNGaWx0ZXIgPSB0eXBlID09IExBWllfRklMVEVSX0ZMQUcgfHwgdHlwZSA9PSBMQVpZX1dISUxFX0ZMQUc7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgIHJlc3VsdC5fX2l0ZXJhdGVlc19fLnB1c2goe1xuICAgICAgICAgICdpdGVyYXRlZSc6IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSxcbiAgICAgICAgICAndHlwZSc6IHR5cGVcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSByZXN1bHQuX19maWx0ZXJlZF9fIHx8IGlzRmlsdGVyO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgZm9yIGBfLmhlYWRgIGFuZCBgXy5sYXN0YC5cbiAgICBhcnJheUVhY2goWydoZWFkJywgJ2xhc3QnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciB0YWtlTmFtZSA9ICd0YWtlJyArIChpbmRleCA/ICdSaWdodCcgOiAnJyk7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpc1t0YWtlTmFtZV0oMSkudmFsdWUoKVswXTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5pbml0aWFsYCBhbmQgYF8udGFpbGAuXG4gICAgYXJyYXlFYWNoKFsnaW5pdGlhbCcsICd0YWlsJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICB2YXIgZHJvcE5hbWUgPSAnZHJvcCcgKyAoaW5kZXggPyAnJyA6ICdSaWdodCcpO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX19maWx0ZXJlZF9fID8gbmV3IExhenlXcmFwcGVyKHRoaXMpIDogdGhpc1tkcm9wTmFtZV0oMSk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNvbXBhY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpbHRlcihpZGVudGl0eSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIocHJlZGljYXRlKS5oZWFkKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kTGFzdCA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpLmZpbmQocHJlZGljYXRlKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmludm9rZU1hcCA9IGJhc2VSZXN0KGZ1bmN0aW9uKHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUucmVqZWN0ID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIobmVnYXRlKGdldEl0ZXJhdGVlKHByZWRpY2F0ZSkpKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgc3RhcnQgPSB0b0ludGVnZXIoc3RhcnQpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gdGhpcztcbiAgICAgIGlmIChyZXN1bHQuX19maWx0ZXJlZF9fICYmIChzdGFydCA+IDAgfHwgZW5kIDwgMCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXp5V3JhcHBlcihyZXN1bHQpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudGFrZVJpZ2h0KC1zdGFydCk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXJ0KSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC5kcm9wKHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbmQgPSB0b0ludGVnZXIoZW5kKTtcbiAgICAgICAgcmVzdWx0ID0gZW5kIDwgMCA/IHJlc3VsdC5kcm9wUmlnaHQoLWVuZCkgOiByZXN1bHQudGFrZShlbmQgLSBzdGFydCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUudGFrZVJpZ2h0V2hpbGUgPSBmdW5jdGlvbihwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJldmVyc2UoKS50YWtlV2hpbGUocHJlZGljYXRlKS5yZXZlcnNlKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy50YWtlKE1BWF9BUlJBWV9MRU5HVEgpO1xuICAgIH07XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIHRvIGBsb2Rhc2gucHJvdG90eXBlYC5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGNoZWNrSXRlcmF0ZWUgPSAvXig/OmZpbHRlcnxmaW5kfG1hcHxyZWplY3QpfFdoaWxlJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBpc1Rha2VyID0gL14oPzpoZWFkfGxhc3QpJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBsb2Rhc2hGdW5jID0gbG9kYXNoW2lzVGFrZXIgPyAoJ3Rha2UnICsgKG1ldGhvZE5hbWUgPT0gJ2xhc3QnID8gJ1JpZ2h0JyA6ICcnKSkgOiBtZXRob2ROYW1lXSxcbiAgICAgICAgICByZXRVbndyYXBwZWQgPSBpc1Rha2VyIHx8IC9eZmluZC8udGVzdChtZXRob2ROYW1lKTtcblxuICAgICAgaWYgKCFsb2Rhc2hGdW5jKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICAgIGFyZ3MgPSBpc1Rha2VyID8gWzFdIDogYXJndW1lbnRzLFxuICAgICAgICAgICAgaXNMYXp5ID0gdmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcixcbiAgICAgICAgICAgIGl0ZXJhdGVlID0gYXJnc1swXSxcbiAgICAgICAgICAgIHVzZUxhenkgPSBpc0xhenkgfHwgaXNBcnJheSh2YWx1ZSk7XG5cbiAgICAgICAgdmFyIGludGVyY2VwdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoRnVuYy5hcHBseShsb2Rhc2gsIGFycmF5UHVzaChbdmFsdWVdLCBhcmdzKSk7XG4gICAgICAgICAgcmV0dXJuIChpc1Rha2VyICYmIGNoYWluQWxsKSA/IHJlc3VsdFswXSA6IHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodXNlTGF6eSAmJiBjaGVja0l0ZXJhdGVlICYmIHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nICYmIGl0ZXJhdGVlLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgLy8gQXZvaWQgbGF6eSB1c2UgaWYgdGhlIGl0ZXJhdGVlIGhhcyBhIFwibGVuZ3RoXCIgdmFsdWUgb3RoZXIgdGhhbiBgMWAuXG4gICAgICAgICAgaXNMYXp5ID0gdXNlTGF6eSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fLFxuICAgICAgICAgICAgaXNIeWJyaWQgPSAhIXRoaXMuX19hY3Rpb25zX18ubGVuZ3RoLFxuICAgICAgICAgICAgaXNVbndyYXBwZWQgPSByZXRVbndyYXBwZWQgJiYgIWNoYWluQWxsLFxuICAgICAgICAgICAgb25seUxhenkgPSBpc0xhenkgJiYgIWlzSHlicmlkO1xuXG4gICAgICAgIGlmICghcmV0VW53cmFwcGVkICYmIHVzZUxhenkpIHtcbiAgICAgICAgICB2YWx1ZSA9IG9ubHlMYXp5ID8gdmFsdWUgOiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgICAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXy5wdXNoKHsgJ2Z1bmMnOiB0aHJ1LCAnYXJncyc6IFtpbnRlcmNlcHRvcl0sICd0aGlzQXJnJzogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNVbndyYXBwZWQgJiYgb25seUxhenkpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSB0aGlzLnRocnUoaW50ZXJjZXB0b3IpO1xuICAgICAgICByZXR1cm4gaXNVbndyYXBwZWQgPyAoaXNUYWtlciA/IHJlc3VsdC52YWx1ZSgpWzBdIDogcmVzdWx0LnZhbHVlKCkpIDogcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgQXJyYXlgIG1ldGhvZHMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIGFycmF5RWFjaChbJ3BvcCcsICdwdXNoJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBhcnJheVByb3RvW21ldGhvZE5hbWVdLFxuICAgICAgICAgIGNoYWluTmFtZSA9IC9eKD86cHVzaHxzb3J0fHVuc2hpZnQpJC8udGVzdChtZXRob2ROYW1lKSA/ICd0YXAnIDogJ3RocnUnLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86cG9wfHNoaWZ0KSQvLnRlc3QobWV0aG9kTmFtZSk7XG5cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmIChyZXRVbndyYXBwZWQgJiYgIXRoaXMuX19jaGFpbl9fKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gdGhpcy52YWx1ZSgpO1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXNbY2hhaW5OYW1lXShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIE1hcCBtaW5pZmllZCBtZXRob2QgbmFtZXMgdG8gdGhlaXIgcmVhbCBuYW1lcy5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbbWV0aG9kTmFtZV07XG4gICAgICBpZiAobG9kYXNoRnVuYykge1xuICAgICAgICB2YXIga2V5ID0gbG9kYXNoRnVuYy5uYW1lICsgJyc7XG4gICAgICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChyZWFsTmFtZXMsIGtleSkpIHtcbiAgICAgICAgICByZWFsTmFtZXNba2V5XSA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHJlYWxOYW1lc1trZXldLnB1c2goeyAnbmFtZSc6IG1ldGhvZE5hbWUsICdmdW5jJzogbG9kYXNoRnVuYyB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlYWxOYW1lc1tjcmVhdGVIeWJyaWQodW5kZWZpbmVkLCBXUkFQX0JJTkRfS0VZX0ZMQUcpLm5hbWVdID0gW3tcbiAgICAgICduYW1lJzogJ3dyYXBwZXInLFxuICAgICAgJ2Z1bmMnOiB1bmRlZmluZWRcbiAgICB9XTtcblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBMYXp5V3JhcHBlcmAuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNsb25lID0gbGF6eUNsb25lO1xuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5yZXZlcnNlID0gbGF6eVJldmVyc2U7XG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnZhbHVlID0gbGF6eVZhbHVlO1xuXG4gICAgLy8gQWRkIGNoYWluIHNlcXVlbmNlIG1ldGhvZHMgdG8gdGhlIGBsb2Rhc2hgIHdyYXBwZXIuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5hdCA9IHdyYXBwZXJBdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29tbWl0ID0gd3JhcHBlckNvbW1pdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLm5leHQgPSB3cmFwcGVyTmV4dDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnBsYW50ID0gd3JhcHBlclBsYW50O1xuICAgIGxvZGFzaC5wcm90b3R5cGUucmV2ZXJzZSA9IHdyYXBwZXJSZXZlcnNlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudG9KU09OID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZU9mID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZSA9IHdyYXBwZXJWYWx1ZTtcblxuICAgIC8vIEFkZCBsYXp5IGFsaWFzZXMuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5maXJzdCA9IGxvZGFzaC5wcm90b3R5cGUuaGVhZDtcblxuICAgIGlmIChzeW1JdGVyYXRvcikge1xuICAgICAgbG9kYXNoLnByb3RvdHlwZVtzeW1JdGVyYXRvcl0gPSB3cmFwcGVyVG9JdGVyYXRvcjtcbiAgICB9XG4gICAgcmV0dXJuIGxvZGFzaDtcbiAgfSk7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IGxvZGFzaC5cbiAgdmFyIF8gPSBydW5JbkNvbnRleHQoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZTpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIExvZGFzaCBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIExvZGFzaCBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICAvLyBVc2UgYF8ubm9Db25mbGljdGAgdG8gcmVtb3ZlIExvZGFzaCBmcm9tIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QuXyA9IF87XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbywgdGhyb3VnaCBwYXRoIG1hcHBpbmcsIGl0IGNhbiBiZVxuICAgIC8vIHJlZmVyZW5jZWQgYXMgdGhlIFwidW5kZXJzY29yZVwiIG1vZHVsZS5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXztcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBpdC5cbiAgZWxzZSBpZiAoZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgTm9kZS5qcy5cbiAgICAoZnJlZU1vZHVsZS5leHBvcnRzID0gXykuXyA9IF87XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIGhhc01hcCA9IHR5cGVvZiBNYXAgPT09ICdmdW5jdGlvbicgJiYgTWFwLnByb3RvdHlwZTtcbnZhciBtYXBTaXplRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiYgaGFzTWFwID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihNYXAucHJvdG90eXBlLCAnc2l6ZScpIDogbnVsbDtcbnZhciBtYXBTaXplID0gaGFzTWFwICYmIG1hcFNpemVEZXNjcmlwdG9yICYmIHR5cGVvZiBtYXBTaXplRGVzY3JpcHRvci5nZXQgPT09ICdmdW5jdGlvbicgPyBtYXBTaXplRGVzY3JpcHRvci5nZXQgOiBudWxsO1xudmFyIG1hcEZvckVhY2ggPSBoYXNNYXAgJiYgTWFwLnByb3RvdHlwZS5mb3JFYWNoO1xudmFyIGhhc1NldCA9IHR5cGVvZiBTZXQgPT09ICdmdW5jdGlvbicgJiYgU2V0LnByb3RvdHlwZTtcbnZhciBzZXRTaXplRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiYgaGFzU2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihTZXQucHJvdG90eXBlLCAnc2l6ZScpIDogbnVsbDtcbnZhciBzZXRTaXplID0gaGFzU2V0ICYmIHNldFNpemVEZXNjcmlwdG9yICYmIHR5cGVvZiBzZXRTaXplRGVzY3JpcHRvci5nZXQgPT09ICdmdW5jdGlvbicgPyBzZXRTaXplRGVzY3JpcHRvci5nZXQgOiBudWxsO1xudmFyIHNldEZvckVhY2ggPSBoYXNTZXQgJiYgU2V0LnByb3RvdHlwZS5mb3JFYWNoO1xudmFyIGhhc1dlYWtNYXAgPSB0eXBlb2YgV2Vha01hcCA9PT0gJ2Z1bmN0aW9uJyAmJiBXZWFrTWFwLnByb3RvdHlwZTtcbnZhciB3ZWFrTWFwSGFzID0gaGFzV2Vha01hcCA/IFdlYWtNYXAucHJvdG90eXBlLmhhcyA6IG51bGw7XG52YXIgaGFzV2Vha1NldCA9IHR5cGVvZiBXZWFrU2V0ID09PSAnZnVuY3Rpb24nICYmIFdlYWtTZXQucHJvdG90eXBlO1xudmFyIHdlYWtTZXRIYXMgPSBoYXNXZWFrU2V0ID8gV2Vha1NldC5wcm90b3R5cGUuaGFzIDogbnVsbDtcbnZhciBoYXNXZWFrUmVmID0gdHlwZW9mIFdlYWtSZWYgPT09ICdmdW5jdGlvbicgJiYgV2Vha1JlZi5wcm90b3R5cGU7XG52YXIgd2Vha1JlZkRlcmVmID0gaGFzV2Vha1JlZiA/IFdlYWtSZWYucHJvdG90eXBlLmRlcmVmIDogbnVsbDtcbnZhciBib29sZWFuVmFsdWVPZiA9IEJvb2xlYW4ucHJvdG90eXBlLnZhbHVlT2Y7XG52YXIgb2JqZWN0VG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xudmFyIGZ1bmN0aW9uVG9TdHJpbmcgPSBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG52YXIgbWF0Y2ggPSBTdHJpbmcucHJvdG90eXBlLm1hdGNoO1xudmFyIGJpZ0ludFZhbHVlT2YgPSB0eXBlb2YgQmlnSW50ID09PSAnZnVuY3Rpb24nID8gQmlnSW50LnByb3RvdHlwZS52YWx1ZU9mIDogbnVsbDtcbnZhciBnT1BTID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcbnZhciBzeW1Ub1N0cmluZyA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gJ3N5bWJvbCcgPyBTeW1ib2wucHJvdG90eXBlLnRvU3RyaW5nIDogbnVsbDtcbnZhciBoYXNTaGFtbWVkU3ltYm9scyA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gJ29iamVjdCc7XG52YXIgaXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxudmFyIGdQTyA9ICh0eXBlb2YgUmVmbGVjdCA9PT0gJ2Z1bmN0aW9uJyA/IFJlZmxlY3QuZ2V0UHJvdG90eXBlT2YgOiBPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHx8IChcbiAgICBbXS5fX3Byb3RvX18gPT09IEFycmF5LnByb3RvdHlwZSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXByb3RvXG4gICAgICAgID8gZnVuY3Rpb24gKE8pIHtcbiAgICAgICAgICAgIHJldHVybiBPLl9fcHJvdG9fXzsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1wcm90b1xuICAgICAgICB9XG4gICAgICAgIDogbnVsbFxuKTtcblxudmFyIGluc3BlY3RDdXN0b20gPSByZXF1aXJlKCcuL3V0aWwuaW5zcGVjdCcpLmN1c3RvbTtcbnZhciBpbnNwZWN0U3ltYm9sID0gaW5zcGVjdEN1c3RvbSAmJiBpc1N5bWJvbChpbnNwZWN0Q3VzdG9tKSA/IGluc3BlY3RDdXN0b20gOiBudWxsO1xudmFyIHRvU3RyaW5nVGFnID0gdHlwZW9mIFN5bWJvbCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgU3ltYm9sLnRvU3RyaW5nVGFnICE9PSAndW5kZWZpbmVkJyA/IFN5bWJvbC50b1N0cmluZ1RhZyA6IG51bGw7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5zcGVjdF8ob2JqLCBvcHRpb25zLCBkZXB0aCwgc2Vlbikge1xuICAgIHZhciBvcHRzID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIGlmIChoYXMob3B0cywgJ3F1b3RlU3R5bGUnKSAmJiAob3B0cy5xdW90ZVN0eWxlICE9PSAnc2luZ2xlJyAmJiBvcHRzLnF1b3RlU3R5bGUgIT09ICdkb3VibGUnKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb24gXCJxdW90ZVN0eWxlXCIgbXVzdCBiZSBcInNpbmdsZVwiIG9yIFwiZG91YmxlXCInKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgICBoYXMob3B0cywgJ21heFN0cmluZ0xlbmd0aCcpICYmICh0eXBlb2Ygb3B0cy5tYXhTdHJpbmdMZW5ndGggPT09ICdudW1iZXInXG4gICAgICAgICAgICA/IG9wdHMubWF4U3RyaW5nTGVuZ3RoIDwgMCAmJiBvcHRzLm1heFN0cmluZ0xlbmd0aCAhPT0gSW5maW5pdHlcbiAgICAgICAgICAgIDogb3B0cy5tYXhTdHJpbmdMZW5ndGggIT09IG51bGxcbiAgICAgICAgKVxuICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb24gXCJtYXhTdHJpbmdMZW5ndGhcIiwgaWYgcHJvdmlkZWQsIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyLCBJbmZpbml0eSwgb3IgYG51bGxgJyk7XG4gICAgfVxuICAgIHZhciBjdXN0b21JbnNwZWN0ID0gaGFzKG9wdHMsICdjdXN0b21JbnNwZWN0JykgPyBvcHRzLmN1c3RvbUluc3BlY3QgOiB0cnVlO1xuICAgIGlmICh0eXBlb2YgY3VzdG9tSW5zcGVjdCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbiBcImN1c3RvbUluc3BlY3RcIiwgaWYgcHJvdmlkZWQsIG11c3QgYmUgYHRydWVgIG9yIGBmYWxzZWAnKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICAgIGhhcyhvcHRzLCAnaW5kZW50JylcbiAgICAgICAgJiYgb3B0cy5pbmRlbnQgIT09IG51bGxcbiAgICAgICAgJiYgb3B0cy5pbmRlbnQgIT09ICdcXHQnXG4gICAgICAgICYmICEocGFyc2VJbnQob3B0cy5pbmRlbnQsIDEwKSA9PT0gb3B0cy5pbmRlbnQgJiYgb3B0cy5pbmRlbnQgPiAwKVxuICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zIFwiaW5kZW50XCIgbXVzdCBiZSBcIlxcXFx0XCIsIGFuIGludGVnZXIgPiAwLCBvciBgbnVsbGAnKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuICd1bmRlZmluZWQnO1xuICAgIH1cbiAgICBpZiAob2JqID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAnbnVsbCc7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgcmV0dXJuIG9iaiA/ICd0cnVlJyA6ICdmYWxzZSc7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBpbnNwZWN0U3RyaW5nKG9iaiwgb3B0cyk7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAob2JqID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gSW5maW5pdHkgLyBvYmogPiAwID8gJzAnIDogJy0wJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnYmlnaW50Jykge1xuICAgICAgICByZXR1cm4gU3RyaW5nKG9iaikgKyAnbic7XG4gICAgfVxuXG4gICAgdmFyIG1heERlcHRoID0gdHlwZW9mIG9wdHMuZGVwdGggPT09ICd1bmRlZmluZWQnID8gNSA6IG9wdHMuZGVwdGg7XG4gICAgaWYgKHR5cGVvZiBkZXB0aCA9PT0gJ3VuZGVmaW5lZCcpIHsgZGVwdGggPSAwOyB9XG4gICAgaWYgKGRlcHRoID49IG1heERlcHRoICYmIG1heERlcHRoID4gMCAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gaXNBcnJheShvYmopID8gJ1tBcnJheV0nIDogJ1tPYmplY3RdJztcbiAgICB9XG5cbiAgICB2YXIgaW5kZW50ID0gZ2V0SW5kZW50KG9wdHMsIGRlcHRoKTtcblxuICAgIGlmICh0eXBlb2Ygc2VlbiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgc2VlbiA9IFtdO1xuICAgIH0gZWxzZSBpZiAoaW5kZXhPZihzZWVuLCBvYmopID49IDApIHtcbiAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnNwZWN0KHZhbHVlLCBmcm9tLCBub0luZGVudCkge1xuICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgc2VlbiA9IHNlZW4uc2xpY2UoKTtcbiAgICAgICAgICAgIHNlZW4ucHVzaChmcm9tKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9JbmRlbnQpIHtcbiAgICAgICAgICAgIHZhciBuZXdPcHRzID0ge1xuICAgICAgICAgICAgICAgIGRlcHRoOiBvcHRzLmRlcHRoXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGhhcyhvcHRzLCAncXVvdGVTdHlsZScpKSB7XG4gICAgICAgICAgICAgICAgbmV3T3B0cy5xdW90ZVN0eWxlID0gb3B0cy5xdW90ZVN0eWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGluc3BlY3RfKHZhbHVlLCBuZXdPcHRzLCBkZXB0aCArIDEsIHNlZW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnNwZWN0Xyh2YWx1ZSwgb3B0cywgZGVwdGggKyAxLCBzZWVuKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB2YXIgbmFtZSA9IG5hbWVPZihvYmopO1xuICAgICAgICB2YXIga2V5cyA9IGFyck9iaktleXMob2JqLCBpbnNwZWN0KTtcbiAgICAgICAgcmV0dXJuICdbRnVuY3Rpb24nICsgKG5hbWUgPyAnOiAnICsgbmFtZSA6ICcgKGFub255bW91cyknKSArICddJyArIChrZXlzLmxlbmd0aCA+IDAgPyAnIHsgJyArIGtleXMuam9pbignLCAnKSArICcgfScgOiAnJyk7XG4gICAgfVxuICAgIGlmIChpc1N5bWJvbChvYmopKSB7XG4gICAgICAgIHZhciBzeW1TdHJpbmcgPSBoYXNTaGFtbWVkU3ltYm9scyA/IFN0cmluZyhvYmopLnJlcGxhY2UoL14oU3ltYm9sXFwoLipcXCkpX1teKV0qJC8sICckMScpIDogc3ltVG9TdHJpbmcuY2FsbChvYmopO1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgIWhhc1NoYW1tZWRTeW1ib2xzID8gbWFya0JveGVkKHN5bVN0cmluZykgOiBzeW1TdHJpbmc7XG4gICAgfVxuICAgIGlmIChpc0VsZW1lbnQob2JqKSkge1xuICAgICAgICB2YXIgcyA9ICc8JyArIFN0cmluZyhvYmoubm9kZU5hbWUpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHZhciBhdHRycyA9IG9iai5hdHRyaWJ1dGVzIHx8IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzICs9ICcgJyArIGF0dHJzW2ldLm5hbWUgKyAnPScgKyB3cmFwUXVvdGVzKHF1b3RlKGF0dHJzW2ldLnZhbHVlKSwgJ2RvdWJsZScsIG9wdHMpO1xuICAgICAgICB9XG4gICAgICAgIHMgKz0gJz4nO1xuICAgICAgICBpZiAob2JqLmNoaWxkTm9kZXMgJiYgb2JqLmNoaWxkTm9kZXMubGVuZ3RoKSB7IHMgKz0gJy4uLic7IH1cbiAgICAgICAgcyArPSAnPC8nICsgU3RyaW5nKG9iai5ub2RlTmFtZSkudG9Mb3dlckNhc2UoKSArICc+JztcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuICAgIGlmIChpc0FycmF5KG9iaikpIHtcbiAgICAgICAgaWYgKG9iai5sZW5ndGggPT09IDApIHsgcmV0dXJuICdbXSc7IH1cbiAgICAgICAgdmFyIHhzID0gYXJyT2JqS2V5cyhvYmosIGluc3BlY3QpO1xuICAgICAgICBpZiAoaW5kZW50ICYmICFzaW5nbGVMaW5lVmFsdWVzKHhzKSkge1xuICAgICAgICAgICAgcmV0dXJuICdbJyArIGluZGVudGVkSm9pbih4cywgaW5kZW50KSArICddJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ1sgJyArIHhzLmpvaW4oJywgJykgKyAnIF0nO1xuICAgIH1cbiAgICBpZiAoaXNFcnJvcihvYmopKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGFyck9iaktleXMob2JqLCBpbnNwZWN0KTtcbiAgICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gJ1snICsgU3RyaW5nKG9iaikgKyAnXSc7IH1cbiAgICAgICAgcmV0dXJuICd7IFsnICsgU3RyaW5nKG9iaikgKyAnXSAnICsgcGFydHMuam9pbignLCAnKSArICcgfSc7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBjdXN0b21JbnNwZWN0KSB7XG4gICAgICAgIGlmIChpbnNwZWN0U3ltYm9sICYmIHR5cGVvZiBvYmpbaW5zcGVjdFN5bWJvbF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmpbaW5zcGVjdFN5bWJvbF0oKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqLmluc3BlY3QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmouaW5zcGVjdCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChpc01hcChvYmopKSB7XG4gICAgICAgIHZhciBtYXBQYXJ0cyA9IFtdO1xuICAgICAgICBtYXBGb3JFYWNoLmNhbGwob2JqLCBmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgbWFwUGFydHMucHVzaChpbnNwZWN0KGtleSwgb2JqLCB0cnVlKSArICcgPT4gJyArIGluc3BlY3QodmFsdWUsIG9iaikpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25PZignTWFwJywgbWFwU2l6ZS5jYWxsKG9iaiksIG1hcFBhcnRzLCBpbmRlbnQpO1xuICAgIH1cbiAgICBpZiAoaXNTZXQob2JqKSkge1xuICAgICAgICB2YXIgc2V0UGFydHMgPSBbXTtcbiAgICAgICAgc2V0Rm9yRWFjaC5jYWxsKG9iaiwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBzZXRQYXJ0cy5wdXNoKGluc3BlY3QodmFsdWUsIG9iaikpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25PZignU2V0Jywgc2V0U2l6ZS5jYWxsKG9iaiksIHNldFBhcnRzLCBpbmRlbnQpO1xuICAgIH1cbiAgICBpZiAoaXNXZWFrTWFwKG9iaikpIHtcbiAgICAgICAgcmV0dXJuIHdlYWtDb2xsZWN0aW9uT2YoJ1dlYWtNYXAnKTtcbiAgICB9XG4gICAgaWYgKGlzV2Vha1NldChvYmopKSB7XG4gICAgICAgIHJldHVybiB3ZWFrQ29sbGVjdGlvbk9mKCdXZWFrU2V0Jyk7XG4gICAgfVxuICAgIGlmIChpc1dlYWtSZWYob2JqKSkge1xuICAgICAgICByZXR1cm4gd2Vha0NvbGxlY3Rpb25PZignV2Vha1JlZicpO1xuICAgIH1cbiAgICBpZiAoaXNOdW1iZXIob2JqKSkge1xuICAgICAgICByZXR1cm4gbWFya0JveGVkKGluc3BlY3QoTnVtYmVyKG9iaikpKTtcbiAgICB9XG4gICAgaWYgKGlzQmlnSW50KG9iaikpIHtcbiAgICAgICAgcmV0dXJuIG1hcmtCb3hlZChpbnNwZWN0KGJpZ0ludFZhbHVlT2YuY2FsbChvYmopKSk7XG4gICAgfVxuICAgIGlmIChpc0Jvb2xlYW4ob2JqKSkge1xuICAgICAgICByZXR1cm4gbWFya0JveGVkKGJvb2xlYW5WYWx1ZU9mLmNhbGwob2JqKSk7XG4gICAgfVxuICAgIGlmIChpc1N0cmluZyhvYmopKSB7XG4gICAgICAgIHJldHVybiBtYXJrQm94ZWQoaW5zcGVjdChTdHJpbmcob2JqKSkpO1xuICAgIH1cbiAgICBpZiAoIWlzRGF0ZShvYmopICYmICFpc1JlZ0V4cChvYmopKSB7XG4gICAgICAgIHZhciB5cyA9IGFyck9iaktleXMob2JqLCBpbnNwZWN0KTtcbiAgICAgICAgdmFyIGlzUGxhaW5PYmplY3QgPSBnUE8gPyBnUE8ob2JqKSA9PT0gT2JqZWN0LnByb3RvdHlwZSA6IG9iaiBpbnN0YW5jZW9mIE9iamVjdCB8fCBvYmouY29uc3RydWN0b3IgPT09IE9iamVjdDtcbiAgICAgICAgdmFyIHByb3RvVGFnID0gb2JqIGluc3RhbmNlb2YgT2JqZWN0ID8gJycgOiAnbnVsbCBwcm90b3R5cGUnO1xuICAgICAgICB2YXIgc3RyaW5nVGFnID0gIWlzUGxhaW5PYmplY3QgJiYgdG9TdHJpbmdUYWcgJiYgT2JqZWN0KG9iaikgPT09IG9iaiAmJiB0b1N0cmluZ1RhZyBpbiBvYmogPyB0b1N0cihvYmopLnNsaWNlKDgsIC0xKSA6IHByb3RvVGFnID8gJ09iamVjdCcgOiAnJztcbiAgICAgICAgdmFyIGNvbnN0cnVjdG9yVGFnID0gaXNQbGFpbk9iamVjdCB8fCB0eXBlb2Ygb2JqLmNvbnN0cnVjdG9yICE9PSAnZnVuY3Rpb24nID8gJycgOiBvYmouY29uc3RydWN0b3IubmFtZSA/IG9iai5jb25zdHJ1Y3Rvci5uYW1lICsgJyAnIDogJyc7XG4gICAgICAgIHZhciB0YWcgPSBjb25zdHJ1Y3RvclRhZyArIChzdHJpbmdUYWcgfHwgcHJvdG9UYWcgPyAnWycgKyBbXS5jb25jYXQoc3RyaW5nVGFnIHx8IFtdLCBwcm90b1RhZyB8fCBbXSkuam9pbignOiAnKSArICddICcgOiAnJyk7XG4gICAgICAgIGlmICh5cy5sZW5ndGggPT09IDApIHsgcmV0dXJuIHRhZyArICd7fSc7IH1cbiAgICAgICAgaWYgKGluZGVudCkge1xuICAgICAgICAgICAgcmV0dXJuIHRhZyArICd7JyArIGluZGVudGVkSm9pbih5cywgaW5kZW50KSArICd9JztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGFnICsgJ3sgJyArIHlzLmpvaW4oJywgJykgKyAnIH0nO1xuICAgIH1cbiAgICByZXR1cm4gU3RyaW5nKG9iaik7XG59O1xuXG5mdW5jdGlvbiB3cmFwUXVvdGVzKHMsIGRlZmF1bHRTdHlsZSwgb3B0cykge1xuICAgIHZhciBxdW90ZUNoYXIgPSAob3B0cy5xdW90ZVN0eWxlIHx8IGRlZmF1bHRTdHlsZSkgPT09ICdkb3VibGUnID8gJ1wiJyA6IFwiJ1wiO1xuICAgIHJldHVybiBxdW90ZUNoYXIgKyBzICsgcXVvdGVDaGFyO1xufVxuXG5mdW5jdGlvbiBxdW90ZShzKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzKS5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7Jyk7XG59XG5cbmZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7IHJldHVybiB0b1N0cihvYmopID09PSAnW29iamVjdCBBcnJheV0nICYmICghdG9TdHJpbmdUYWcgfHwgISh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiB0b1N0cmluZ1RhZyBpbiBvYmopKTsgfVxuZnVuY3Rpb24gaXNEYXRlKG9iaikgeyByZXR1cm4gdG9TdHIob2JqKSA9PT0gJ1tvYmplY3QgRGF0ZV0nICYmICghdG9TdHJpbmdUYWcgfHwgISh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiB0b1N0cmluZ1RhZyBpbiBvYmopKTsgfVxuZnVuY3Rpb24gaXNSZWdFeHAob2JqKSB7IHJldHVybiB0b1N0cihvYmopID09PSAnW29iamVjdCBSZWdFeHBdJyAmJiAoIXRvU3RyaW5nVGFnIHx8ICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgdG9TdHJpbmdUYWcgaW4gb2JqKSk7IH1cbmZ1bmN0aW9uIGlzRXJyb3Iob2JqKSB7IHJldHVybiB0b1N0cihvYmopID09PSAnW29iamVjdCBFcnJvcl0nICYmICghdG9TdHJpbmdUYWcgfHwgISh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiB0b1N0cmluZ1RhZyBpbiBvYmopKTsgfVxuZnVuY3Rpb24gaXNTdHJpbmcob2JqKSB7IHJldHVybiB0b1N0cihvYmopID09PSAnW29iamVjdCBTdHJpbmddJyAmJiAoIXRvU3RyaW5nVGFnIHx8ICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgdG9TdHJpbmdUYWcgaW4gb2JqKSk7IH1cbmZ1bmN0aW9uIGlzTnVtYmVyKG9iaikgeyByZXR1cm4gdG9TdHIob2JqKSA9PT0gJ1tvYmplY3QgTnVtYmVyXScgJiYgKCF0b1N0cmluZ1RhZyB8fCAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIHRvU3RyaW5nVGFnIGluIG9iaikpOyB9XG5mdW5jdGlvbiBpc0Jvb2xlYW4ob2JqKSB7IHJldHVybiB0b1N0cihvYmopID09PSAnW29iamVjdCBCb29sZWFuXScgJiYgKCF0b1N0cmluZ1RhZyB8fCAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIHRvU3RyaW5nVGFnIGluIG9iaikpOyB9XG5cbi8vIFN5bWJvbCBhbmQgQmlnSW50IGRvIGhhdmUgU3ltYm9sLnRvU3RyaW5nVGFnIGJ5IHNwZWMsIHNvIHRoYXQgY2FuJ3QgYmUgdXNlZCB0byBlbGltaW5hdGUgZmFsc2UgcG9zaXRpdmVzXG5mdW5jdGlvbiBpc1N5bWJvbChvYmopIHtcbiAgICBpZiAoaGFzU2hhbW1lZFN5bWJvbHMpIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBvYmogaW5zdGFuY2VvZiBTeW1ib2w7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAnc3ltYm9sJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCFvYmogfHwgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgIXN5bVRvU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgc3ltVG9TdHJpbmcuY2FsbChvYmopO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7fVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNCaWdJbnQob2JqKSB7XG4gICAgaWYgKCFvYmogfHwgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgIWJpZ0ludFZhbHVlT2YpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBiaWdJbnRWYWx1ZU9mLmNhbGwob2JqKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge31cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbnZhciBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5IHx8IGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIGtleSBpbiB0aGlzOyB9O1xuZnVuY3Rpb24gaGFzKG9iaiwga2V5KSB7XG4gICAgcmV0dXJuIGhhc093bi5jYWxsKG9iaiwga2V5KTtcbn1cblxuZnVuY3Rpb24gdG9TdHIob2JqKSB7XG4gICAgcmV0dXJuIG9iamVjdFRvU3RyaW5nLmNhbGwob2JqKTtcbn1cblxuZnVuY3Rpb24gbmFtZU9mKGYpIHtcbiAgICBpZiAoZi5uYW1lKSB7IHJldHVybiBmLm5hbWU7IH1cbiAgICB2YXIgbSA9IG1hdGNoLmNhbGwoZnVuY3Rpb25Ub1N0cmluZy5jYWxsKGYpLCAvXmZ1bmN0aW9uXFxzKihbXFx3JF0rKS8pO1xuICAgIGlmIChtKSB7IHJldHVybiBtWzFdOyB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIGluZGV4T2YoeHMsIHgpIHtcbiAgICBpZiAoeHMuaW5kZXhPZikgeyByZXR1cm4geHMuaW5kZXhPZih4KTsgfVxuICAgIGZvciAodmFyIGkgPSAwLCBsID0geHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIGlmICh4c1tpXSA9PT0geCkgeyByZXR1cm4gaTsgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG59XG5cbmZ1bmN0aW9uIGlzTWFwKHgpIHtcbiAgICBpZiAoIW1hcFNpemUgfHwgIXggfHwgdHlwZW9mIHggIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgbWFwU2l6ZS5jYWxsKHgpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2V0U2l6ZS5jYWxsKHgpO1xuICAgICAgICB9IGNhdGNoIChzKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geCBpbnN0YW5jZW9mIE1hcDsgLy8gY29yZS1qcyB3b3JrYXJvdW5kLCBwcmUtdjIuNS4wXG4gICAgfSBjYXRjaCAoZSkge31cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzV2Vha01hcCh4KSB7XG4gICAgaWYgKCF3ZWFrTWFwSGFzIHx8ICF4IHx8IHR5cGVvZiB4ICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIHdlYWtNYXBIYXMuY2FsbCh4LCB3ZWFrTWFwSGFzKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdlYWtTZXRIYXMuY2FsbCh4LCB3ZWFrU2V0SGFzKTtcbiAgICAgICAgfSBjYXRjaCAocykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHggaW5zdGFuY2VvZiBXZWFrTWFwOyAvLyBjb3JlLWpzIHdvcmthcm91bmQsIHByZS12Mi41LjBcbiAgICB9IGNhdGNoIChlKSB7fVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNXZWFrUmVmKHgpIHtcbiAgICBpZiAoIXdlYWtSZWZEZXJlZiB8fCAheCB8fCB0eXBlb2YgeCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICB3ZWFrUmVmRGVyZWYuY2FsbCh4KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge31cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzU2V0KHgpIHtcbiAgICBpZiAoIXNldFNpemUgfHwgIXggfHwgdHlwZW9mIHggIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgc2V0U2l6ZS5jYWxsKHgpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbWFwU2l6ZS5jYWxsKHgpO1xuICAgICAgICB9IGNhdGNoIChtKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geCBpbnN0YW5jZW9mIFNldDsgLy8gY29yZS1qcyB3b3JrYXJvdW5kLCBwcmUtdjIuNS4wXG4gICAgfSBjYXRjaCAoZSkge31cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzV2Vha1NldCh4KSB7XG4gICAgaWYgKCF3ZWFrU2V0SGFzIHx8ICF4IHx8IHR5cGVvZiB4ICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIHdlYWtTZXRIYXMuY2FsbCh4LCB3ZWFrU2V0SGFzKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdlYWtNYXBIYXMuY2FsbCh4LCB3ZWFrTWFwSGFzKTtcbiAgICAgICAgfSBjYXRjaCAocykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHggaW5zdGFuY2VvZiBXZWFrU2V0OyAvLyBjb3JlLWpzIHdvcmthcm91bmQsIHByZS12Mi41LjBcbiAgICB9IGNhdGNoIChlKSB7fVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNFbGVtZW50KHgpIHtcbiAgICBpZiAoIXggfHwgdHlwZW9mIHggIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgIT09ICd1bmRlZmluZWQnICYmIHggaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiB4Lm5vZGVOYW1lID09PSAnc3RyaW5nJyAmJiB0eXBlb2YgeC5nZXRBdHRyaWJ1dGUgPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGluc3BlY3RTdHJpbmcoc3RyLCBvcHRzKSB7XG4gICAgaWYgKHN0ci5sZW5ndGggPiBvcHRzLm1heFN0cmluZ0xlbmd0aCkge1xuICAgICAgICB2YXIgcmVtYWluaW5nID0gc3RyLmxlbmd0aCAtIG9wdHMubWF4U3RyaW5nTGVuZ3RoO1xuICAgICAgICB2YXIgdHJhaWxlciA9ICcuLi4gJyArIHJlbWFpbmluZyArICcgbW9yZSBjaGFyYWN0ZXInICsgKHJlbWFpbmluZyA+IDEgPyAncycgOiAnJyk7XG4gICAgICAgIHJldHVybiBpbnNwZWN0U3RyaW5nKHN0ci5zbGljZSgwLCBvcHRzLm1heFN0cmluZ0xlbmd0aCksIG9wdHMpICsgdHJhaWxlcjtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnRyb2wtcmVnZXhcbiAgICB2YXIgcyA9IHN0ci5yZXBsYWNlKC8oWydcXFxcXSkvZywgJ1xcXFwkMScpLnJlcGxhY2UoL1tcXHgwMC1cXHgxZl0vZywgbG93Ynl0ZSk7XG4gICAgcmV0dXJuIHdyYXBRdW90ZXMocywgJ3NpbmdsZScsIG9wdHMpO1xufVxuXG5mdW5jdGlvbiBsb3dieXRlKGMpIHtcbiAgICB2YXIgbiA9IGMuY2hhckNvZGVBdCgwKTtcbiAgICB2YXIgeCA9IHtcbiAgICAgICAgODogJ2InLFxuICAgICAgICA5OiAndCcsXG4gICAgICAgIDEwOiAnbicsXG4gICAgICAgIDEyOiAnZicsXG4gICAgICAgIDEzOiAncidcbiAgICB9W25dO1xuICAgIGlmICh4KSB7IHJldHVybiAnXFxcXCcgKyB4OyB9XG4gICAgcmV0dXJuICdcXFxceCcgKyAobiA8IDB4MTAgPyAnMCcgOiAnJykgKyBuLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBtYXJrQm94ZWQoc3RyKSB7XG4gICAgcmV0dXJuICdPYmplY3QoJyArIHN0ciArICcpJztcbn1cblxuZnVuY3Rpb24gd2Vha0NvbGxlY3Rpb25PZih0eXBlKSB7XG4gICAgcmV0dXJuIHR5cGUgKyAnIHsgPyB9Jztcbn1cblxuZnVuY3Rpb24gY29sbGVjdGlvbk9mKHR5cGUsIHNpemUsIGVudHJpZXMsIGluZGVudCkge1xuICAgIHZhciBqb2luZWRFbnRyaWVzID0gaW5kZW50ID8gaW5kZW50ZWRKb2luKGVudHJpZXMsIGluZGVudCkgOiBlbnRyaWVzLmpvaW4oJywgJyk7XG4gICAgcmV0dXJuIHR5cGUgKyAnICgnICsgc2l6ZSArICcpIHsnICsgam9pbmVkRW50cmllcyArICd9Jztcbn1cblxuZnVuY3Rpb24gc2luZ2xlTGluZVZhbHVlcyh4cykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgeHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGluZGV4T2YoeHNbaV0sICdcXG4nKSA+PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGdldEluZGVudChvcHRzLCBkZXB0aCkge1xuICAgIHZhciBiYXNlSW5kZW50O1xuICAgIGlmIChvcHRzLmluZGVudCA9PT0gJ1xcdCcpIHtcbiAgICAgICAgYmFzZUluZGVudCA9ICdcXHQnO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdHMuaW5kZW50ID09PSAnbnVtYmVyJyAmJiBvcHRzLmluZGVudCA+IDApIHtcbiAgICAgICAgYmFzZUluZGVudCA9IEFycmF5KG9wdHMuaW5kZW50ICsgMSkuam9pbignICcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBiYXNlOiBiYXNlSW5kZW50LFxuICAgICAgICBwcmV2OiBBcnJheShkZXB0aCArIDEpLmpvaW4oYmFzZUluZGVudClcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBpbmRlbnRlZEpvaW4oeHMsIGluZGVudCkge1xuICAgIGlmICh4cy5sZW5ndGggPT09IDApIHsgcmV0dXJuICcnOyB9XG4gICAgdmFyIGxpbmVKb2luZXIgPSAnXFxuJyArIGluZGVudC5wcmV2ICsgaW5kZW50LmJhc2U7XG4gICAgcmV0dXJuIGxpbmVKb2luZXIgKyB4cy5qb2luKCcsJyArIGxpbmVKb2luZXIpICsgJ1xcbicgKyBpbmRlbnQucHJldjtcbn1cblxuZnVuY3Rpb24gYXJyT2JqS2V5cyhvYmosIGluc3BlY3QpIHtcbiAgICB2YXIgaXNBcnIgPSBpc0FycmF5KG9iaik7XG4gICAgdmFyIHhzID0gW107XG4gICAgaWYgKGlzQXJyKSB7XG4gICAgICAgIHhzLmxlbmd0aCA9IG9iai5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB4c1tpXSA9IGhhcyhvYmosIGkpID8gaW5zcGVjdChvYmpbaV0sIG9iaikgOiAnJztcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgc3ltcyA9IHR5cGVvZiBnT1BTID09PSAnZnVuY3Rpb24nID8gZ09QUyhvYmopIDogW107XG4gICAgdmFyIHN5bU1hcDtcbiAgICBpZiAoaGFzU2hhbW1lZFN5bWJvbHMpIHtcbiAgICAgICAgc3ltTWFwID0ge307XG4gICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgc3ltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgc3ltTWFwWyckJyArIHN5bXNba11dID0gc3ltc1trXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1yZXN0cmljdGVkLXN5bnRheFxuICAgICAgICBpZiAoIWhhcyhvYmosIGtleSkpIHsgY29udGludWU7IH0gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1yZXN0cmljdGVkLXN5bnRheCwgbm8tY29udGludWVcbiAgICAgICAgaWYgKGlzQXJyICYmIFN0cmluZyhOdW1iZXIoa2V5KSkgPT09IGtleSAmJiBrZXkgPCBvYmoubGVuZ3RoKSB7IGNvbnRpbnVlOyB9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tcmVzdHJpY3RlZC1zeW50YXgsIG5vLWNvbnRpbnVlXG4gICAgICAgIGlmIChoYXNTaGFtbWVkU3ltYm9scyAmJiBzeW1NYXBbJyQnICsga2V5XSBpbnN0YW5jZW9mIFN5bWJvbCkge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyB0byBwcmV2ZW50IHNoYW1tZWQgU3ltYm9scywgd2hpY2ggYXJlIHN0b3JlZCBhcyBzdHJpbmdzLCBmcm9tIGJlaW5nIGluY2x1ZGVkIGluIHRoZSBzdHJpbmcga2V5IHNlY3Rpb25cbiAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXJlc3RyaWN0ZWQtc3ludGF4LCBuby1jb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKCgvW15cXHckXS8pLnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgeHMucHVzaChpbnNwZWN0KGtleSwgb2JqKSArICc6ICcgKyBpbnNwZWN0KG9ialtrZXldLCBvYmopKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHhzLnB1c2goa2V5ICsgJzogJyArIGluc3BlY3Qob2JqW2tleV0sIG9iaikpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZ09QUyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN5bXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmIChpc0VudW1lcmFibGUuY2FsbChvYmosIHN5bXNbal0pKSB7XG4gICAgICAgICAgICAgICAgeHMucHVzaCgnWycgKyBpbnNwZWN0KHN5bXNbal0pICsgJ106ICcgKyBpbnNwZWN0KG9ialtzeW1zW2pdXSwgb2JqKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHhzO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGliJylcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGFzYXAgPSByZXF1aXJlKCdhc2FwL3JhdycpO1xuXG5mdW5jdGlvbiBub29wKCkge31cblxuLy8gU3RhdGVzOlxuLy9cbi8vIDAgLSBwZW5kaW5nXG4vLyAxIC0gZnVsZmlsbGVkIHdpdGggX3ZhbHVlXG4vLyAyIC0gcmVqZWN0ZWQgd2l0aCBfdmFsdWVcbi8vIDMgLSBhZG9wdGVkIHRoZSBzdGF0ZSBvZiBhbm90aGVyIHByb21pc2UsIF92YWx1ZVxuLy9cbi8vIG9uY2UgdGhlIHN0YXRlIGlzIG5vIGxvbmdlciBwZW5kaW5nICgwKSBpdCBpcyBpbW11dGFibGVcblxuLy8gQWxsIGBfYCBwcmVmaXhlZCBwcm9wZXJ0aWVzIHdpbGwgYmUgcmVkdWNlZCB0byBgX3tyYW5kb20gbnVtYmVyfWBcbi8vIGF0IGJ1aWxkIHRpbWUgdG8gb2JmdXNjYXRlIHRoZW0gYW5kIGRpc2NvdXJhZ2UgdGhlaXIgdXNlLlxuLy8gV2UgZG9uJ3QgdXNlIHN5bWJvbHMgb3IgT2JqZWN0LmRlZmluZVByb3BlcnR5IHRvIGZ1bGx5IGhpZGUgdGhlbVxuLy8gYmVjYXVzZSB0aGUgcGVyZm9ybWFuY2UgaXNuJ3QgZ29vZCBlbm91Z2guXG5cblxuLy8gdG8gYXZvaWQgdXNpbmcgdHJ5L2NhdGNoIGluc2lkZSBjcml0aWNhbCBmdW5jdGlvbnMsIHdlXG4vLyBleHRyYWN0IHRoZW0gdG8gaGVyZS5cbnZhciBMQVNUX0VSUk9SID0gbnVsbDtcbnZhciBJU19FUlJPUiA9IHt9O1xuZnVuY3Rpb24gZ2V0VGhlbihvYmopIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gb2JqLnRoZW47XG4gIH0gY2F0Y2ggKGV4KSB7XG4gICAgTEFTVF9FUlJPUiA9IGV4O1xuICAgIHJldHVybiBJU19FUlJPUjtcbiAgfVxufVxuXG5mdW5jdGlvbiB0cnlDYWxsT25lKGZuLCBhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGZuKGEpO1xuICB9IGNhdGNoIChleCkge1xuICAgIExBU1RfRVJST1IgPSBleDtcbiAgICByZXR1cm4gSVNfRVJST1I7XG4gIH1cbn1cbmZ1bmN0aW9uIHRyeUNhbGxUd28oZm4sIGEsIGIpIHtcbiAgdHJ5IHtcbiAgICBmbihhLCBiKTtcbiAgfSBjYXRjaCAoZXgpIHtcbiAgICBMQVNUX0VSUk9SID0gZXg7XG4gICAgcmV0dXJuIElTX0VSUk9SO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gUHJvbWlzZTtcblxuZnVuY3Rpb24gUHJvbWlzZShmbikge1xuICBpZiAodHlwZW9mIHRoaXMgIT09ICdvYmplY3QnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignUHJvbWlzZXMgbXVzdCBiZSBjb25zdHJ1Y3RlZCB2aWEgbmV3Jyk7XG4gIH1cbiAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Byb21pc2UgY29uc3RydWN0b3JcXCdzIGFyZ3VtZW50IGlzIG5vdCBhIGZ1bmN0aW9uJyk7XG4gIH1cbiAgdGhpcy5fVSA9IDA7XG4gIHRoaXMuX1YgPSAwO1xuICB0aGlzLl9XID0gbnVsbDtcbiAgdGhpcy5fWCA9IG51bGw7XG4gIGlmIChmbiA9PT0gbm9vcCkgcmV0dXJuO1xuICBkb1Jlc29sdmUoZm4sIHRoaXMpO1xufVxuUHJvbWlzZS5fWSA9IG51bGw7XG5Qcm9taXNlLl9aID0gbnVsbDtcblByb21pc2UuXzAgPSBub29wO1xuXG5Qcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpIHtcbiAgaWYgKHRoaXMuY29uc3RydWN0b3IgIT09IFByb21pc2UpIHtcbiAgICByZXR1cm4gc2FmZVRoZW4odGhpcywgb25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpO1xuICB9XG4gIHZhciByZXMgPSBuZXcgUHJvbWlzZShub29wKTtcbiAgaGFuZGxlKHRoaXMsIG5ldyBIYW5kbGVyKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCByZXMpKTtcbiAgcmV0dXJuIHJlcztcbn07XG5cbmZ1bmN0aW9uIHNhZmVUaGVuKHNlbGYsIG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gIHJldHVybiBuZXcgc2VsZi5jb25zdHJ1Y3RvcihmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHJlcyA9IG5ldyBQcm9taXNlKG5vb3ApO1xuICAgIHJlcy50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgaGFuZGxlKHNlbGYsIG5ldyBIYW5kbGVyKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCByZXMpKTtcbiAgfSk7XG59XG5mdW5jdGlvbiBoYW5kbGUoc2VsZiwgZGVmZXJyZWQpIHtcbiAgd2hpbGUgKHNlbGYuX1YgPT09IDMpIHtcbiAgICBzZWxmID0gc2VsZi5fVztcbiAgfVxuICBpZiAoUHJvbWlzZS5fWSkge1xuICAgIFByb21pc2UuX1koc2VsZik7XG4gIH1cbiAgaWYgKHNlbGYuX1YgPT09IDApIHtcbiAgICBpZiAoc2VsZi5fVSA9PT0gMCkge1xuICAgICAgc2VsZi5fVSA9IDE7XG4gICAgICBzZWxmLl9YID0gZGVmZXJyZWQ7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzZWxmLl9VID09PSAxKSB7XG4gICAgICBzZWxmLl9VID0gMjtcbiAgICAgIHNlbGYuX1ggPSBbc2VsZi5fWCwgZGVmZXJyZWRdO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzZWxmLl9YLnB1c2goZGVmZXJyZWQpO1xuICAgIHJldHVybjtcbiAgfVxuICBoYW5kbGVSZXNvbHZlZChzZWxmLCBkZWZlcnJlZCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVJlc29sdmVkKHNlbGYsIGRlZmVycmVkKSB7XG4gIGFzYXAoZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNiID0gc2VsZi5fViA9PT0gMSA/IGRlZmVycmVkLm9uRnVsZmlsbGVkIDogZGVmZXJyZWQub25SZWplY3RlZDtcbiAgICBpZiAoY2IgPT09IG51bGwpIHtcbiAgICAgIGlmIChzZWxmLl9WID09PSAxKSB7XG4gICAgICAgIHJlc29sdmUoZGVmZXJyZWQucHJvbWlzZSwgc2VsZi5fVyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QoZGVmZXJyZWQucHJvbWlzZSwgc2VsZi5fVyk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciByZXQgPSB0cnlDYWxsT25lKGNiLCBzZWxmLl9XKTtcbiAgICBpZiAocmV0ID09PSBJU19FUlJPUikge1xuICAgICAgcmVqZWN0KGRlZmVycmVkLnByb21pc2UsIExBU1RfRVJST1IpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXNvbHZlKGRlZmVycmVkLnByb21pc2UsIHJldCk7XG4gICAgfVxuICB9KTtcbn1cbmZ1bmN0aW9uIHJlc29sdmUoc2VsZiwgbmV3VmFsdWUpIHtcbiAgLy8gUHJvbWlzZSBSZXNvbHV0aW9uIFByb2NlZHVyZTogaHR0cHM6Ly9naXRodWIuY29tL3Byb21pc2VzLWFwbHVzL3Byb21pc2VzLXNwZWMjdGhlLXByb21pc2UtcmVzb2x1dGlvbi1wcm9jZWR1cmVcbiAgaWYgKG5ld1ZhbHVlID09PSBzZWxmKSB7XG4gICAgcmV0dXJuIHJlamVjdChcbiAgICAgIHNlbGYsXG4gICAgICBuZXcgVHlwZUVycm9yKCdBIHByb21pc2UgY2Fubm90IGJlIHJlc29sdmVkIHdpdGggaXRzZWxmLicpXG4gICAgKTtcbiAgfVxuICBpZiAoXG4gICAgbmV3VmFsdWUgJiZcbiAgICAodHlwZW9mIG5ld1ZhbHVlID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgbmV3VmFsdWUgPT09ICdmdW5jdGlvbicpXG4gICkge1xuICAgIHZhciB0aGVuID0gZ2V0VGhlbihuZXdWYWx1ZSk7XG4gICAgaWYgKHRoZW4gPT09IElTX0VSUk9SKSB7XG4gICAgICByZXR1cm4gcmVqZWN0KHNlbGYsIExBU1RfRVJST1IpO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0aGVuID09PSBzZWxmLnRoZW4gJiZcbiAgICAgIG5ld1ZhbHVlIGluc3RhbmNlb2YgUHJvbWlzZVxuICAgICkge1xuICAgICAgc2VsZi5fViA9IDM7XG4gICAgICBzZWxmLl9XID0gbmV3VmFsdWU7XG4gICAgICBmaW5hbGUoc2VsZik7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZG9SZXNvbHZlKHRoZW4uYmluZChuZXdWYWx1ZSksIHNlbGYpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuICBzZWxmLl9WID0gMTtcbiAgc2VsZi5fVyA9IG5ld1ZhbHVlO1xuICBmaW5hbGUoc2VsZik7XG59XG5cbmZ1bmN0aW9uIHJlamVjdChzZWxmLCBuZXdWYWx1ZSkge1xuICBzZWxmLl9WID0gMjtcbiAgc2VsZi5fVyA9IG5ld1ZhbHVlO1xuICBpZiAoUHJvbWlzZS5fWikge1xuICAgIFByb21pc2UuX1ooc2VsZiwgbmV3VmFsdWUpO1xuICB9XG4gIGZpbmFsZShzZWxmKTtcbn1cbmZ1bmN0aW9uIGZpbmFsZShzZWxmKSB7XG4gIGlmIChzZWxmLl9VID09PSAxKSB7XG4gICAgaGFuZGxlKHNlbGYsIHNlbGYuX1gpO1xuICAgIHNlbGYuX1ggPSBudWxsO1xuICB9XG4gIGlmIChzZWxmLl9VID09PSAyKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxmLl9YLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGUoc2VsZiwgc2VsZi5fWFtpXSk7XG4gICAgfVxuICAgIHNlbGYuX1ggPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIEhhbmRsZXIob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQsIHByb21pc2Upe1xuICB0aGlzLm9uRnVsZmlsbGVkID0gdHlwZW9mIG9uRnVsZmlsbGVkID09PSAnZnVuY3Rpb24nID8gb25GdWxmaWxsZWQgOiBudWxsO1xuICB0aGlzLm9uUmVqZWN0ZWQgPSB0eXBlb2Ygb25SZWplY3RlZCA9PT0gJ2Z1bmN0aW9uJyA/IG9uUmVqZWN0ZWQgOiBudWxsO1xuICB0aGlzLnByb21pc2UgPSBwcm9taXNlO1xufVxuXG4vKipcbiAqIFRha2UgYSBwb3RlbnRpYWxseSBtaXNiZWhhdmluZyByZXNvbHZlciBmdW5jdGlvbiBhbmQgbWFrZSBzdXJlXG4gKiBvbkZ1bGZpbGxlZCBhbmQgb25SZWplY3RlZCBhcmUgb25seSBjYWxsZWQgb25jZS5cbiAqXG4gKiBNYWtlcyBubyBndWFyYW50ZWVzIGFib3V0IGFzeW5jaHJvbnkuXG4gKi9cbmZ1bmN0aW9uIGRvUmVzb2x2ZShmbiwgcHJvbWlzZSkge1xuICB2YXIgZG9uZSA9IGZhbHNlO1xuICB2YXIgcmVzID0gdHJ5Q2FsbFR3byhmbiwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgaWYgKGRvbmUpIHJldHVybjtcbiAgICBkb25lID0gdHJ1ZTtcbiAgICByZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgIGlmIChkb25lKSByZXR1cm47XG4gICAgZG9uZSA9IHRydWU7XG4gICAgcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gIH0pO1xuICBpZiAoIWRvbmUgJiYgcmVzID09PSBJU19FUlJPUikge1xuICAgIGRvbmUgPSB0cnVlO1xuICAgIHJlamVjdChwcm9taXNlLCBMQVNUX0VSUk9SKTtcbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUHJvbWlzZSA9IHJlcXVpcmUoJy4vY29yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG5Qcm9taXNlLnByb3RvdHlwZS5kb25lID0gZnVuY3Rpb24gKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gIHZhciBzZWxmID0gYXJndW1lbnRzLmxlbmd0aCA/IHRoaXMudGhlbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogdGhpcztcbiAgc2VsZi50aGVuKG51bGwsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9LCAwKTtcbiAgfSk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vL1RoaXMgZmlsZSBjb250YWlucyB0aGUgRVM2IGV4dGVuc2lvbnMgdG8gdGhlIGNvcmUgUHJvbWlzZXMvQSsgQVBJXG5cbnZhciBQcm9taXNlID0gcmVxdWlyZSgnLi9jb3JlLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gUHJvbWlzZTtcblxuLyogU3RhdGljIEZ1bmN0aW9ucyAqL1xuXG52YXIgVFJVRSA9IHZhbHVlUHJvbWlzZSh0cnVlKTtcbnZhciBGQUxTRSA9IHZhbHVlUHJvbWlzZShmYWxzZSk7XG52YXIgTlVMTCA9IHZhbHVlUHJvbWlzZShudWxsKTtcbnZhciBVTkRFRklORUQgPSB2YWx1ZVByb21pc2UodW5kZWZpbmVkKTtcbnZhciBaRVJPID0gdmFsdWVQcm9taXNlKDApO1xudmFyIEVNUFRZU1RSSU5HID0gdmFsdWVQcm9taXNlKCcnKTtcblxuZnVuY3Rpb24gdmFsdWVQcm9taXNlKHZhbHVlKSB7XG4gIHZhciBwID0gbmV3IFByb21pc2UoUHJvbWlzZS5fMCk7XG4gIHAuX1YgPSAxO1xuICBwLl9XID0gdmFsdWU7XG4gIHJldHVybiBwO1xufVxuUHJvbWlzZS5yZXNvbHZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFByb21pc2UpIHJldHVybiB2YWx1ZTtcblxuICBpZiAodmFsdWUgPT09IG51bGwpIHJldHVybiBOVUxMO1xuICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFVOREVGSU5FRDtcbiAgaWYgKHZhbHVlID09PSB0cnVlKSByZXR1cm4gVFJVRTtcbiAgaWYgKHZhbHVlID09PSBmYWxzZSkgcmV0dXJuIEZBTFNFO1xuICBpZiAodmFsdWUgPT09IDApIHJldHVybiBaRVJPO1xuICBpZiAodmFsdWUgPT09ICcnKSByZXR1cm4gRU1QVFlTVFJJTkc7XG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciB0aGVuID0gdmFsdWUudGhlbjtcbiAgICAgIGlmICh0eXBlb2YgdGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UodGhlbi5iaW5kKHZhbHVlKSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIHJlamVjdChleCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHZhbHVlUHJvbWlzZSh2YWx1ZSk7XG59O1xuXG52YXIgaXRlcmFibGVUb0FycmF5ID0gZnVuY3Rpb24gKGl0ZXJhYmxlKSB7XG4gIGlmICh0eXBlb2YgQXJyYXkuZnJvbSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIEVTMjAxNSssIGl0ZXJhYmxlcyBleGlzdFxuICAgIGl0ZXJhYmxlVG9BcnJheSA9IEFycmF5LmZyb207XG4gICAgcmV0dXJuIEFycmF5LmZyb20oaXRlcmFibGUpO1xuICB9XG5cbiAgLy8gRVM1LCBvbmx5IGFycmF5cyBhbmQgYXJyYXktbGlrZXMgZXhpc3RcbiAgaXRlcmFibGVUb0FycmF5ID0gZnVuY3Rpb24gKHgpIHsgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHgpOyB9O1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoaXRlcmFibGUpO1xufVxuXG5Qcm9taXNlLmFsbCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgdmFyIGFyZ3MgPSBpdGVyYWJsZVRvQXJyYXkoYXJyKTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHJlc29sdmUoW10pO1xuICAgIHZhciByZW1haW5pbmcgPSBhcmdzLmxlbmd0aDtcbiAgICBmdW5jdGlvbiByZXMoaSwgdmFsKSB7XG4gICAgICBpZiAodmFsICYmICh0eXBlb2YgdmFsID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgUHJvbWlzZSAmJiB2YWwudGhlbiA9PT0gUHJvbWlzZS5wcm90b3R5cGUudGhlbikge1xuICAgICAgICAgIHdoaWxlICh2YWwuX1YgPT09IDMpIHtcbiAgICAgICAgICAgIHZhbCA9IHZhbC5fVztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHZhbC5fViA9PT0gMSkgcmV0dXJuIHJlcyhpLCB2YWwuX1cpO1xuICAgICAgICAgIGlmICh2YWwuX1YgPT09IDIpIHJlamVjdCh2YWwuX1cpO1xuICAgICAgICAgIHZhbC50aGVuKGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgICAgIHJlcyhpLCB2YWwpO1xuICAgICAgICAgIH0sIHJlamVjdCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB0aGVuID0gdmFsLnRoZW47XG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB2YXIgcCA9IG5ldyBQcm9taXNlKHRoZW4uYmluZCh2YWwpKTtcbiAgICAgICAgICAgIHAudGhlbihmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgICAgICAgIHJlcyhpLCB2YWwpO1xuICAgICAgICAgICAgfSwgcmVqZWN0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFyZ3NbaV0gPSB2YWw7XG4gICAgICBpZiAoLS1yZW1haW5pbmcgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZShhcmdzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXMoaSwgYXJnc1tpXSk7XG4gICAgfVxuICB9KTtcbn07XG5cblByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgcmVqZWN0KHZhbHVlKTtcbiAgfSk7XG59O1xuXG5Qcm9taXNlLnJhY2UgPSBmdW5jdGlvbiAodmFsdWVzKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaXRlcmFibGVUb0FycmF5KHZhbHVlcykuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSl7XG4gICAgICBQcm9taXNlLnJlc29sdmUodmFsdWUpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG4vKiBQcm90b3R5cGUgTWV0aG9kcyAqL1xuXG5Qcm9taXNlLnByb3RvdHlwZVsnY2F0Y2gnXSA9IGZ1bmN0aW9uIChvblJlamVjdGVkKSB7XG4gIHJldHVybiB0aGlzLnRoZW4obnVsbCwgb25SZWplY3RlZCk7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgUHJvbWlzZSA9IHJlcXVpcmUoJy4vY29yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG5Qcm9taXNlLnByb3RvdHlwZS5maW5hbGx5ID0gZnVuY3Rpb24gKGYpIHtcbiAgcmV0dXJuIHRoaXMudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGYoKSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSk7XG4gIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGYoKSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG4gIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2NvcmUuanMnKTtcbnJlcXVpcmUoJy4vZG9uZS5qcycpO1xucmVxdWlyZSgnLi9maW5hbGx5LmpzJyk7XG5yZXF1aXJlKCcuL2VzNi1leHRlbnNpb25zLmpzJyk7XG5yZXF1aXJlKCcuL25vZGUtZXh0ZW5zaW9ucy5qcycpO1xucmVxdWlyZSgnLi9zeW5jaHJvbm91cy5qcycpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBUaGlzIGZpbGUgY29udGFpbnMgdGhlbi9wcm9taXNlIHNwZWNpZmljIGV4dGVuc2lvbnMgdGhhdCBhcmUgb25seSB1c2VmdWxcbi8vIGZvciBub2RlLmpzIGludGVyb3BcblxudmFyIFByb21pc2UgPSByZXF1aXJlKCcuL2NvcmUuanMnKTtcbnZhciBhc2FwID0gcmVxdWlyZSgnYXNhcCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG5cbi8qIFN0YXRpYyBGdW5jdGlvbnMgKi9cblxuUHJvbWlzZS5kZW5vZGVpZnkgPSBmdW5jdGlvbiAoZm4sIGFyZ3VtZW50Q291bnQpIHtcbiAgaWYgKFxuICAgIHR5cGVvZiBhcmd1bWVudENvdW50ID09PSAnbnVtYmVyJyAmJiBhcmd1bWVudENvdW50ICE9PSBJbmZpbml0eVxuICApIHtcbiAgICByZXR1cm4gZGVub2RlaWZ5V2l0aENvdW50KGZuLCBhcmd1bWVudENvdW50KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGVub2RlaWZ5V2l0aG91dENvdW50KGZuKTtcbiAgfVxufTtcblxudmFyIGNhbGxiYWNrRm4gPSAoXG4gICdmdW5jdGlvbiAoZXJyLCByZXMpIHsnICtcbiAgJ2lmIChlcnIpIHsgcmooZXJyKTsgfSBlbHNlIHsgcnMocmVzKTsgfScgK1xuICAnfSdcbik7XG5mdW5jdGlvbiBkZW5vZGVpZnlXaXRoQ291bnQoZm4sIGFyZ3VtZW50Q291bnQpIHtcbiAgdmFyIGFyZ3MgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudENvdW50OyBpKyspIHtcbiAgICBhcmdzLnB1c2goJ2EnICsgaSk7XG4gIH1cbiAgdmFyIGJvZHkgPSBbXG4gICAgJ3JldHVybiBmdW5jdGlvbiAoJyArIGFyZ3Muam9pbignLCcpICsgJykgeycsXG4gICAgJ3ZhciBzZWxmID0gdGhpczsnLFxuICAgICdyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJzLCByaikgeycsXG4gICAgJ3ZhciByZXMgPSBmbi5jYWxsKCcsXG4gICAgWydzZWxmJ10uY29uY2F0KGFyZ3MpLmNvbmNhdChbY2FsbGJhY2tGbl0pLmpvaW4oJywnKSxcbiAgICAnKTsnLFxuICAgICdpZiAocmVzICYmJyxcbiAgICAnKHR5cGVvZiByZXMgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIHJlcyA9PT0gXCJmdW5jdGlvblwiKSAmJicsXG4gICAgJ3R5cGVvZiByZXMudGhlbiA9PT0gXCJmdW5jdGlvblwiJyxcbiAgICAnKSB7cnMocmVzKTt9JyxcbiAgICAnfSk7JyxcbiAgICAnfTsnXG4gIF0uam9pbignJyk7XG4gIHJldHVybiBGdW5jdGlvbihbJ1Byb21pc2UnLCAnZm4nXSwgYm9keSkoUHJvbWlzZSwgZm4pO1xufVxuZnVuY3Rpb24gZGVub2RlaWZ5V2l0aG91dENvdW50KGZuKSB7XG4gIHZhciBmbkxlbmd0aCA9IE1hdGgubWF4KGZuLmxlbmd0aCAtIDEsIDMpO1xuICB2YXIgYXJncyA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGZuTGVuZ3RoOyBpKyspIHtcbiAgICBhcmdzLnB1c2goJ2EnICsgaSk7XG4gIH1cbiAgdmFyIGJvZHkgPSBbXG4gICAgJ3JldHVybiBmdW5jdGlvbiAoJyArIGFyZ3Muam9pbignLCcpICsgJykgeycsXG4gICAgJ3ZhciBzZWxmID0gdGhpczsnLFxuICAgICd2YXIgYXJnczsnLFxuICAgICd2YXIgYXJnTGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDsnLFxuICAgICdpZiAoYXJndW1lbnRzLmxlbmd0aCA+ICcgKyBmbkxlbmd0aCArICcpIHsnLFxuICAgICdhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggKyAxKTsnLFxuICAgICdmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeycsXG4gICAgJ2FyZ3NbaV0gPSBhcmd1bWVudHNbaV07JyxcbiAgICAnfScsXG4gICAgJ30nLFxuICAgICdyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJzLCByaikgeycsXG4gICAgJ3ZhciBjYiA9ICcgKyBjYWxsYmFja0ZuICsgJzsnLFxuICAgICd2YXIgcmVzOycsXG4gICAgJ3N3aXRjaCAoYXJnTGVuZ3RoKSB7JyxcbiAgICBhcmdzLmNvbmNhdChbJ2V4dHJhJ10pLm1hcChmdW5jdGlvbiAoXywgaW5kZXgpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgICdjYXNlICcgKyAoaW5kZXgpICsgJzonICtcbiAgICAgICAgJ3JlcyA9IGZuLmNhbGwoJyArIFsnc2VsZiddLmNvbmNhdChhcmdzLnNsaWNlKDAsIGluZGV4KSkuY29uY2F0KCdjYicpLmpvaW4oJywnKSArICcpOycgK1xuICAgICAgICAnYnJlYWs7J1xuICAgICAgKTtcbiAgICB9KS5qb2luKCcnKSxcbiAgICAnZGVmYXVsdDonLFxuICAgICdhcmdzW2FyZ0xlbmd0aF0gPSBjYjsnLFxuICAgICdyZXMgPSBmbi5hcHBseShzZWxmLCBhcmdzKTsnLFxuICAgICd9JyxcbiAgICBcbiAgICAnaWYgKHJlcyAmJicsXG4gICAgJyh0eXBlb2YgcmVzID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiByZXMgPT09IFwiZnVuY3Rpb25cIikgJiYnLFxuICAgICd0eXBlb2YgcmVzLnRoZW4gPT09IFwiZnVuY3Rpb25cIicsXG4gICAgJykge3JzKHJlcyk7fScsXG4gICAgJ30pOycsXG4gICAgJ307J1xuICBdLmpvaW4oJycpO1xuXG4gIHJldHVybiBGdW5jdGlvbihcbiAgICBbJ1Byb21pc2UnLCAnZm4nXSxcbiAgICBib2R5XG4gICkoUHJvbWlzZSwgZm4pO1xufVxuXG5Qcm9taXNlLm5vZGVpZnkgPSBmdW5jdGlvbiAoZm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgdmFyIGNhbGxiYWNrID1cbiAgICAgIHR5cGVvZiBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gPT09ICdmdW5jdGlvbicgPyBhcmdzLnBvcCgpIDogbnVsbDtcbiAgICB2YXIgY3R4ID0gdGhpcztcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykubm9kZWlmeShjYWxsYmFjaywgY3R4KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGNhbGxiYWNrID09PSBudWxsIHx8IHR5cGVvZiBjYWxsYmFjayA9PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgIHJlamVjdChleCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXNhcChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY2FsbGJhY2suY2FsbChjdHgsIGV4KTtcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cblByb21pc2UucHJvdG90eXBlLm5vZGVpZnkgPSBmdW5jdGlvbiAoY2FsbGJhY2ssIGN0eCkge1xuICBpZiAodHlwZW9mIGNhbGxiYWNrICE9ICdmdW5jdGlvbicpIHJldHVybiB0aGlzO1xuXG4gIHRoaXMudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICBhc2FwKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxiYWNrLmNhbGwoY3R4LCBudWxsLCB2YWx1ZSk7XG4gICAgfSk7XG4gIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICBhc2FwKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxiYWNrLmNhbGwoY3R4LCBlcnIpO1xuICAgIH0pO1xuICB9KTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBQcm9taXNlID0gcmVxdWlyZSgnLi9jb3JlLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gUHJvbWlzZTtcblByb21pc2UuZW5hYmxlU3luY2hyb25vdXMgPSBmdW5jdGlvbiAoKSB7XG4gIFByb21pc2UucHJvdG90eXBlLmlzUGVuZGluZyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmdldFN0YXRlKCkgPT0gMDtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS5pc0Z1bGZpbGxlZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmdldFN0YXRlKCkgPT0gMTtcbiAgfTtcblxuICBQcm9taXNlLnByb3RvdHlwZS5pc1JlamVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0U3RhdGUoKSA9PSAyO1xuICB9O1xuXG4gIFByb21pc2UucHJvdG90eXBlLmdldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLl9WID09PSAzKSB7XG4gICAgICByZXR1cm4gdGhpcy5fVy5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0Z1bGZpbGxlZCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBnZXQgYSB2YWx1ZSBvZiBhbiB1bmZ1bGZpbGxlZCBwcm9taXNlLicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9XO1xuICB9O1xuXG4gIFByb21pc2UucHJvdG90eXBlLmdldFJlYXNvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fViA9PT0gMykge1xuICAgICAgcmV0dXJuIHRoaXMuX1cuZ2V0UmVhc29uKCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzUmVqZWN0ZWQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IGEgcmVqZWN0aW9uIHJlYXNvbiBvZiBhIG5vbi1yZWplY3RlZCBwcm9taXNlLicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9XO1xuICB9O1xuXG4gIFByb21pc2UucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLl9WID09PSAzKSB7XG4gICAgICByZXR1cm4gdGhpcy5fVy5nZXRTdGF0ZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fViA9PT0gLTEgfHwgdGhpcy5fViA9PT0gLTIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9WO1xuICB9O1xufTtcblxuUHJvbWlzZS5kaXNhYmxlU3luY2hyb25vdXMgPSBmdW5jdGlvbigpIHtcbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNQZW5kaW5nID0gdW5kZWZpbmVkO1xuICBQcm9taXNlLnByb3RvdHlwZS5pc0Z1bGZpbGxlZCA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuaXNSZWplY3RlZCA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuZ2V0VmFsdWUgPSB1bmRlZmluZWQ7XG4gIFByb21pc2UucHJvdG90eXBlLmdldFJlYXNvbiA9IHVuZGVmaW5lZDtcbiAgUHJvbWlzZS5wcm90b3R5cGUuZ2V0U3RhdGUgPSB1bmRlZmluZWQ7XG59O1xuIiwiLyohIGh0dHBzOi8vbXRocy5iZS9wdW55Y29kZSB2MS4zLjIgYnkgQG1hdGhpYXMgKi9cbjsoZnVuY3Rpb24ocm9vdCkge1xuXG5cdC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZXMgKi9cblx0dmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJlxuXHRcdCFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cdHZhciBmcmVlTW9kdWxlID0gdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiZcblx0XHQhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblx0dmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcblx0aWYgKFxuXHRcdGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8XG5cdFx0ZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHxcblx0XHRmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWxcblx0KSB7XG5cdFx0cm9vdCA9IGZyZWVHbG9iYWw7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGBwdW55Y29kZWAgb2JqZWN0LlxuXHQgKiBAbmFtZSBwdW55Y29kZVxuXHQgKiBAdHlwZSBPYmplY3Rcblx0ICovXG5cdHZhciBwdW55Y29kZSxcblxuXHQvKiogSGlnaGVzdCBwb3NpdGl2ZSBzaWduZWQgMzItYml0IGZsb2F0IHZhbHVlICovXG5cdG1heEludCA9IDIxNDc0ODM2NDcsIC8vIGFrYS4gMHg3RkZGRkZGRiBvciAyXjMxLTFcblxuXHQvKiogQm9vdHN0cmluZyBwYXJhbWV0ZXJzICovXG5cdGJhc2UgPSAzNixcblx0dE1pbiA9IDEsXG5cdHRNYXggPSAyNixcblx0c2tldyA9IDM4LFxuXHRkYW1wID0gNzAwLFxuXHRpbml0aWFsQmlhcyA9IDcyLFxuXHRpbml0aWFsTiA9IDEyOCwgLy8gMHg4MFxuXHRkZWxpbWl0ZXIgPSAnLScsIC8vICdcXHgyRCdcblxuXHQvKiogUmVndWxhciBleHByZXNzaW9ucyAqL1xuXHRyZWdleFB1bnljb2RlID0gL154bi0tLyxcblx0cmVnZXhOb25BU0NJSSA9IC9bXlxceDIwLVxceDdFXS8sIC8vIHVucHJpbnRhYmxlIEFTQ0lJIGNoYXJzICsgbm9uLUFTQ0lJIGNoYXJzXG5cdHJlZ2V4U2VwYXJhdG9ycyA9IC9bXFx4MkVcXHUzMDAyXFx1RkYwRVxcdUZGNjFdL2csIC8vIFJGQyAzNDkwIHNlcGFyYXRvcnNcblxuXHQvKiogRXJyb3IgbWVzc2FnZXMgKi9cblx0ZXJyb3JzID0ge1xuXHRcdCdvdmVyZmxvdyc6ICdPdmVyZmxvdzogaW5wdXQgbmVlZHMgd2lkZXIgaW50ZWdlcnMgdG8gcHJvY2VzcycsXG5cdFx0J25vdC1iYXNpYyc6ICdJbGxlZ2FsIGlucHV0ID49IDB4ODAgKG5vdCBhIGJhc2ljIGNvZGUgcG9pbnQpJyxcblx0XHQnaW52YWxpZC1pbnB1dCc6ICdJbnZhbGlkIGlucHV0J1xuXHR9LFxuXG5cdC8qKiBDb252ZW5pZW5jZSBzaG9ydGN1dHMgKi9cblx0YmFzZU1pbnVzVE1pbiA9IGJhc2UgLSB0TWluLFxuXHRmbG9vciA9IE1hdGguZmxvb3IsXG5cdHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGUsXG5cblx0LyoqIFRlbXBvcmFyeSB2YXJpYWJsZSAqL1xuXHRrZXk7XG5cblx0LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cblx0LyoqXG5cdCAqIEEgZ2VuZXJpYyBlcnJvciB1dGlsaXR5IGZ1bmN0aW9uLlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXJyb3IgdHlwZS5cblx0ICogQHJldHVybnMge0Vycm9yfSBUaHJvd3MgYSBgUmFuZ2VFcnJvcmAgd2l0aCB0aGUgYXBwbGljYWJsZSBlcnJvciBtZXNzYWdlLlxuXHQgKi9cblx0ZnVuY3Rpb24gZXJyb3IodHlwZSkge1xuXHRcdHRocm93IFJhbmdlRXJyb3IoZXJyb3JzW3R5cGVdKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBIGdlbmVyaWMgYEFycmF5I21hcGAgdXRpbGl0eSBmdW5jdGlvbi5cblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgZm9yIGV2ZXJ5IGFycmF5XG5cdCAqIGl0ZW0uXG5cdCAqIEByZXR1cm5zIHtBcnJheX0gQSBuZXcgYXJyYXkgb2YgdmFsdWVzIHJldHVybmVkIGJ5IHRoZSBjYWxsYmFjayBmdW5jdGlvbi5cblx0ICovXG5cdGZ1bmN0aW9uIG1hcChhcnJheSwgZm4pIHtcblx0XHR2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXHRcdHZhciByZXN1bHQgPSBbXTtcblx0XHR3aGlsZSAobGVuZ3RoLS0pIHtcblx0XHRcdHJlc3VsdFtsZW5ndGhdID0gZm4oYXJyYXlbbGVuZ3RoXSk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHQvKipcblx0ICogQSBzaW1wbGUgYEFycmF5I21hcGAtbGlrZSB3cmFwcGVyIHRvIHdvcmsgd2l0aCBkb21haW4gbmFtZSBzdHJpbmdzIG9yIGVtYWlsXG5cdCAqIGFkZHJlc3Nlcy5cblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRvbWFpbiBUaGUgZG9tYWluIG5hbWUgb3IgZW1haWwgYWRkcmVzcy5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgZm9yIGV2ZXJ5XG5cdCAqIGNoYXJhY3Rlci5cblx0ICogQHJldHVybnMge0FycmF5fSBBIG5ldyBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXR1cm5lZCBieSB0aGUgY2FsbGJhY2tcblx0ICogZnVuY3Rpb24uXG5cdCAqL1xuXHRmdW5jdGlvbiBtYXBEb21haW4oc3RyaW5nLCBmbikge1xuXHRcdHZhciBwYXJ0cyA9IHN0cmluZy5zcGxpdCgnQCcpO1xuXHRcdHZhciByZXN1bHQgPSAnJztcblx0XHRpZiAocGFydHMubGVuZ3RoID4gMSkge1xuXHRcdFx0Ly8gSW4gZW1haWwgYWRkcmVzc2VzLCBvbmx5IHRoZSBkb21haW4gbmFtZSBzaG91bGQgYmUgcHVueWNvZGVkLiBMZWF2ZVxuXHRcdFx0Ly8gdGhlIGxvY2FsIHBhcnQgKGkuZS4gZXZlcnl0aGluZyB1cCB0byBgQGApIGludGFjdC5cblx0XHRcdHJlc3VsdCA9IHBhcnRzWzBdICsgJ0AnO1xuXHRcdFx0c3RyaW5nID0gcGFydHNbMV07XG5cdFx0fVxuXHRcdC8vIEF2b2lkIGBzcGxpdChyZWdleClgIGZvciBJRTggY29tcGF0aWJpbGl0eS4gU2VlICMxNy5cblx0XHRzdHJpbmcgPSBzdHJpbmcucmVwbGFjZShyZWdleFNlcGFyYXRvcnMsICdcXHgyRScpO1xuXHRcdHZhciBsYWJlbHMgPSBzdHJpbmcuc3BsaXQoJy4nKTtcblx0XHR2YXIgZW5jb2RlZCA9IG1hcChsYWJlbHMsIGZuKS5qb2luKCcuJyk7XG5cdFx0cmV0dXJuIHJlc3VsdCArIGVuY29kZWQ7XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBhbiBhcnJheSBjb250YWluaW5nIHRoZSBudW1lcmljIGNvZGUgcG9pbnRzIG9mIGVhY2ggVW5pY29kZVxuXHQgKiBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZy4gV2hpbGUgSmF2YVNjcmlwdCB1c2VzIFVDUy0yIGludGVybmFsbHksXG5cdCAqIHRoaXMgZnVuY3Rpb24gd2lsbCBjb252ZXJ0IGEgcGFpciBvZiBzdXJyb2dhdGUgaGFsdmVzIChlYWNoIG9mIHdoaWNoXG5cdCAqIFVDUy0yIGV4cG9zZXMgYXMgc2VwYXJhdGUgY2hhcmFjdGVycykgaW50byBhIHNpbmdsZSBjb2RlIHBvaW50LFxuXHQgKiBtYXRjaGluZyBVVEYtMTYuXG5cdCAqIEBzZWUgYHB1bnljb2RlLnVjczIuZW5jb2RlYFxuXHQgKiBAc2VlIDxodHRwczovL21hdGhpYXNieW5lbnMuYmUvbm90ZXMvamF2YXNjcmlwdC1lbmNvZGluZz5cblx0ICogQG1lbWJlck9mIHB1bnljb2RlLnVjczJcblx0ICogQG5hbWUgZGVjb2RlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBzdHJpbmcgVGhlIFVuaWNvZGUgaW5wdXQgc3RyaW5nIChVQ1MtMikuXG5cdCAqIEByZXR1cm5zIHtBcnJheX0gVGhlIG5ldyBhcnJheSBvZiBjb2RlIHBvaW50cy5cblx0ICovXG5cdGZ1bmN0aW9uIHVjczJkZWNvZGUoc3RyaW5nKSB7XG5cdFx0dmFyIG91dHB1dCA9IFtdLFxuXHRcdCAgICBjb3VudGVyID0gMCxcblx0XHQgICAgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aCxcblx0XHQgICAgdmFsdWUsXG5cdFx0ICAgIGV4dHJhO1xuXHRcdHdoaWxlIChjb3VudGVyIDwgbGVuZ3RoKSB7XG5cdFx0XHR2YWx1ZSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XG5cdFx0XHRpZiAodmFsdWUgPj0gMHhEODAwICYmIHZhbHVlIDw9IDB4REJGRiAmJiBjb3VudGVyIDwgbGVuZ3RoKSB7XG5cdFx0XHRcdC8vIGhpZ2ggc3Vycm9nYXRlLCBhbmQgdGhlcmUgaXMgYSBuZXh0IGNoYXJhY3RlclxuXHRcdFx0XHRleHRyYSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XG5cdFx0XHRcdGlmICgoZXh0cmEgJiAweEZDMDApID09IDB4REMwMCkgeyAvLyBsb3cgc3Vycm9nYXRlXG5cdFx0XHRcdFx0b3V0cHV0LnB1c2goKCh2YWx1ZSAmIDB4M0ZGKSA8PCAxMCkgKyAoZXh0cmEgJiAweDNGRikgKyAweDEwMDAwKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyB1bm1hdGNoZWQgc3Vycm9nYXRlOyBvbmx5IGFwcGVuZCB0aGlzIGNvZGUgdW5pdCwgaW4gY2FzZSB0aGUgbmV4dFxuXHRcdFx0XHRcdC8vIGNvZGUgdW5pdCBpcyB0aGUgaGlnaCBzdXJyb2dhdGUgb2YgYSBzdXJyb2dhdGUgcGFpclxuXHRcdFx0XHRcdG91dHB1dC5wdXNoKHZhbHVlKTtcblx0XHRcdFx0XHRjb3VudGVyLS07XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG91dHB1dC5wdXNoKHZhbHVlKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG91dHB1dDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgc3RyaW5nIGJhc2VkIG9uIGFuIGFycmF5IG9mIG51bWVyaWMgY29kZSBwb2ludHMuXG5cdCAqIEBzZWUgYHB1bnljb2RlLnVjczIuZGVjb2RlYFxuXHQgKiBAbWVtYmVyT2YgcHVueWNvZGUudWNzMlxuXHQgKiBAbmFtZSBlbmNvZGVcblx0ICogQHBhcmFtIHtBcnJheX0gY29kZVBvaW50cyBUaGUgYXJyYXkgb2YgbnVtZXJpYyBjb2RlIHBvaW50cy5cblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIG5ldyBVbmljb2RlIHN0cmluZyAoVUNTLTIpLlxuXHQgKi9cblx0ZnVuY3Rpb24gdWNzMmVuY29kZShhcnJheSkge1xuXHRcdHJldHVybiBtYXAoYXJyYXksIGZ1bmN0aW9uKHZhbHVlKSB7XG5cdFx0XHR2YXIgb3V0cHV0ID0gJyc7XG5cdFx0XHRpZiAodmFsdWUgPiAweEZGRkYpIHtcblx0XHRcdFx0dmFsdWUgLT0gMHgxMDAwMDtcblx0XHRcdFx0b3V0cHV0ICs9IHN0cmluZ0Zyb21DaGFyQ29kZSh2YWx1ZSA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMCk7XG5cdFx0XHRcdHZhbHVlID0gMHhEQzAwIHwgdmFsdWUgJiAweDNGRjtcblx0XHRcdH1cblx0XHRcdG91dHB1dCArPSBzdHJpbmdGcm9tQ2hhckNvZGUodmFsdWUpO1xuXHRcdFx0cmV0dXJuIG91dHB1dDtcblx0XHR9KS5qb2luKCcnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIGJhc2ljIGNvZGUgcG9pbnQgaW50byBhIGRpZ2l0L2ludGVnZXIuXG5cdCAqIEBzZWUgYGRpZ2l0VG9CYXNpYygpYFxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0gY29kZVBvaW50IFRoZSBiYXNpYyBudW1lcmljIGNvZGUgcG9pbnQgdmFsdWUuXG5cdCAqIEByZXR1cm5zIHtOdW1iZXJ9IFRoZSBudW1lcmljIHZhbHVlIG9mIGEgYmFzaWMgY29kZSBwb2ludCAoZm9yIHVzZSBpblxuXHQgKiByZXByZXNlbnRpbmcgaW50ZWdlcnMpIGluIHRoZSByYW5nZSBgMGAgdG8gYGJhc2UgLSAxYCwgb3IgYGJhc2VgIGlmXG5cdCAqIHRoZSBjb2RlIHBvaW50IGRvZXMgbm90IHJlcHJlc2VudCBhIHZhbHVlLlxuXHQgKi9cblx0ZnVuY3Rpb24gYmFzaWNUb0RpZ2l0KGNvZGVQb2ludCkge1xuXHRcdGlmIChjb2RlUG9pbnQgLSA0OCA8IDEwKSB7XG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gMjI7XG5cdFx0fVxuXHRcdGlmIChjb2RlUG9pbnQgLSA2NSA8IDI2KSB7XG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gNjU7XG5cdFx0fVxuXHRcdGlmIChjb2RlUG9pbnQgLSA5NyA8IDI2KSB7XG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gOTc7XG5cdFx0fVxuXHRcdHJldHVybiBiYXNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgZGlnaXQvaW50ZWdlciBpbnRvIGEgYmFzaWMgY29kZSBwb2ludC5cblx0ICogQHNlZSBgYmFzaWNUb0RpZ2l0KClgXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBkaWdpdCBUaGUgbnVtZXJpYyB2YWx1ZSBvZiBhIGJhc2ljIGNvZGUgcG9pbnQuXG5cdCAqIEByZXR1cm5zIHtOdW1iZXJ9IFRoZSBiYXNpYyBjb2RlIHBvaW50IHdob3NlIHZhbHVlICh3aGVuIHVzZWQgZm9yXG5cdCAqIHJlcHJlc2VudGluZyBpbnRlZ2VycykgaXMgYGRpZ2l0YCwgd2hpY2ggbmVlZHMgdG8gYmUgaW4gdGhlIHJhbmdlXG5cdCAqIGAwYCB0byBgYmFzZSAtIDFgLiBJZiBgZmxhZ2AgaXMgbm9uLXplcm8sIHRoZSB1cHBlcmNhc2UgZm9ybSBpc1xuXHQgKiB1c2VkOyBlbHNlLCB0aGUgbG93ZXJjYXNlIGZvcm0gaXMgdXNlZC4gVGhlIGJlaGF2aW9yIGlzIHVuZGVmaW5lZFxuXHQgKiBpZiBgZmxhZ2AgaXMgbm9uLXplcm8gYW5kIGBkaWdpdGAgaGFzIG5vIHVwcGVyY2FzZSBmb3JtLlxuXHQgKi9cblx0ZnVuY3Rpb24gZGlnaXRUb0Jhc2ljKGRpZ2l0LCBmbGFnKSB7XG5cdFx0Ly8gIDAuLjI1IG1hcCB0byBBU0NJSSBhLi56IG9yIEEuLlpcblx0XHQvLyAyNi4uMzUgbWFwIHRvIEFTQ0lJIDAuLjlcblx0XHRyZXR1cm4gZGlnaXQgKyAyMiArIDc1ICogKGRpZ2l0IDwgMjYpIC0gKChmbGFnICE9IDApIDw8IDUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJpYXMgYWRhcHRhdGlvbiBmdW5jdGlvbiBhcyBwZXIgc2VjdGlvbiAzLjQgb2YgUkZDIDM0OTIuXG5cdCAqIGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzM0OTIjc2VjdGlvbi0zLjRcblx0ICogQHByaXZhdGVcblx0ICovXG5cdGZ1bmN0aW9uIGFkYXB0KGRlbHRhLCBudW1Qb2ludHMsIGZpcnN0VGltZSkge1xuXHRcdHZhciBrID0gMDtcblx0XHRkZWx0YSA9IGZpcnN0VGltZSA/IGZsb29yKGRlbHRhIC8gZGFtcCkgOiBkZWx0YSA+PiAxO1xuXHRcdGRlbHRhICs9IGZsb29yKGRlbHRhIC8gbnVtUG9pbnRzKTtcblx0XHRmb3IgKC8qIG5vIGluaXRpYWxpemF0aW9uICovOyBkZWx0YSA+IGJhc2VNaW51c1RNaW4gKiB0TWF4ID4+IDE7IGsgKz0gYmFzZSkge1xuXHRcdFx0ZGVsdGEgPSBmbG9vcihkZWx0YSAvIGJhc2VNaW51c1RNaW4pO1xuXHRcdH1cblx0XHRyZXR1cm4gZmxvb3IoayArIChiYXNlTWludXNUTWluICsgMSkgKiBkZWx0YSAvIChkZWx0YSArIHNrZXcpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMgdG8gYSBzdHJpbmcgb2YgVW5pY29kZVxuXHQgKiBzeW1ib2xzLlxuXHQgKiBAbWVtYmVyT2YgcHVueWNvZGVcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFRoZSBQdW55Y29kZSBzdHJpbmcgb2YgQVNDSUktb25seSBzeW1ib2xzLlxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcmVzdWx0aW5nIHN0cmluZyBvZiBVbmljb2RlIHN5bWJvbHMuXG5cdCAqL1xuXHRmdW5jdGlvbiBkZWNvZGUoaW5wdXQpIHtcblx0XHQvLyBEb24ndCB1c2UgVUNTLTJcblx0XHR2YXIgb3V0cHV0ID0gW10sXG5cdFx0ICAgIGlucHV0TGVuZ3RoID0gaW5wdXQubGVuZ3RoLFxuXHRcdCAgICBvdXQsXG5cdFx0ICAgIGkgPSAwLFxuXHRcdCAgICBuID0gaW5pdGlhbE4sXG5cdFx0ICAgIGJpYXMgPSBpbml0aWFsQmlhcyxcblx0XHQgICAgYmFzaWMsXG5cdFx0ICAgIGosXG5cdFx0ICAgIGluZGV4LFxuXHRcdCAgICBvbGRpLFxuXHRcdCAgICB3LFxuXHRcdCAgICBrLFxuXHRcdCAgICBkaWdpdCxcblx0XHQgICAgdCxcblx0XHQgICAgLyoqIENhY2hlZCBjYWxjdWxhdGlvbiByZXN1bHRzICovXG5cdFx0ICAgIGJhc2VNaW51c1Q7XG5cblx0XHQvLyBIYW5kbGUgdGhlIGJhc2ljIGNvZGUgcG9pbnRzOiBsZXQgYGJhc2ljYCBiZSB0aGUgbnVtYmVyIG9mIGlucHV0IGNvZGVcblx0XHQvLyBwb2ludHMgYmVmb3JlIHRoZSBsYXN0IGRlbGltaXRlciwgb3IgYDBgIGlmIHRoZXJlIGlzIG5vbmUsIHRoZW4gY29weVxuXHRcdC8vIHRoZSBmaXJzdCBiYXNpYyBjb2RlIHBvaW50cyB0byB0aGUgb3V0cHV0LlxuXG5cdFx0YmFzaWMgPSBpbnB1dC5sYXN0SW5kZXhPZihkZWxpbWl0ZXIpO1xuXHRcdGlmIChiYXNpYyA8IDApIHtcblx0XHRcdGJhc2ljID0gMDtcblx0XHR9XG5cblx0XHRmb3IgKGogPSAwOyBqIDwgYmFzaWM7ICsraikge1xuXHRcdFx0Ly8gaWYgaXQncyBub3QgYSBiYXNpYyBjb2RlIHBvaW50XG5cdFx0XHRpZiAoaW5wdXQuY2hhckNvZGVBdChqKSA+PSAweDgwKSB7XG5cdFx0XHRcdGVycm9yKCdub3QtYmFzaWMnKTtcblx0XHRcdH1cblx0XHRcdG91dHB1dC5wdXNoKGlucHV0LmNoYXJDb2RlQXQoaikpO1xuXHRcdH1cblxuXHRcdC8vIE1haW4gZGVjb2RpbmcgbG9vcDogc3RhcnQganVzdCBhZnRlciB0aGUgbGFzdCBkZWxpbWl0ZXIgaWYgYW55IGJhc2ljIGNvZGVcblx0XHQvLyBwb2ludHMgd2VyZSBjb3BpZWQ7IHN0YXJ0IGF0IHRoZSBiZWdpbm5pbmcgb3RoZXJ3aXNlLlxuXG5cdFx0Zm9yIChpbmRleCA9IGJhc2ljID4gMCA/IGJhc2ljICsgMSA6IDA7IGluZGV4IDwgaW5wdXRMZW5ndGg7IC8qIG5vIGZpbmFsIGV4cHJlc3Npb24gKi8pIHtcblxuXHRcdFx0Ly8gYGluZGV4YCBpcyB0aGUgaW5kZXggb2YgdGhlIG5leHQgY2hhcmFjdGVyIHRvIGJlIGNvbnN1bWVkLlxuXHRcdFx0Ly8gRGVjb2RlIGEgZ2VuZXJhbGl6ZWQgdmFyaWFibGUtbGVuZ3RoIGludGVnZXIgaW50byBgZGVsdGFgLFxuXHRcdFx0Ly8gd2hpY2ggZ2V0cyBhZGRlZCB0byBgaWAuIFRoZSBvdmVyZmxvdyBjaGVja2luZyBpcyBlYXNpZXJcblx0XHRcdC8vIGlmIHdlIGluY3JlYXNlIGBpYCBhcyB3ZSBnbywgdGhlbiBzdWJ0cmFjdCBvZmYgaXRzIHN0YXJ0aW5nXG5cdFx0XHQvLyB2YWx1ZSBhdCB0aGUgZW5kIHRvIG9idGFpbiBgZGVsdGFgLlxuXHRcdFx0Zm9yIChvbGRpID0gaSwgdyA9IDEsIGsgPSBiYXNlOyAvKiBubyBjb25kaXRpb24gKi87IGsgKz0gYmFzZSkge1xuXG5cdFx0XHRcdGlmIChpbmRleCA+PSBpbnB1dExlbmd0aCkge1xuXHRcdFx0XHRcdGVycm9yKCdpbnZhbGlkLWlucHV0Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkaWdpdCA9IGJhc2ljVG9EaWdpdChpbnB1dC5jaGFyQ29kZUF0KGluZGV4KyspKTtcblxuXHRcdFx0XHRpZiAoZGlnaXQgPj0gYmFzZSB8fCBkaWdpdCA+IGZsb29yKChtYXhJbnQgLSBpKSAvIHcpKSB7XG5cdFx0XHRcdFx0ZXJyb3IoJ292ZXJmbG93Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpICs9IGRpZ2l0ICogdztcblx0XHRcdFx0dCA9IGsgPD0gYmlhcyA/IHRNaW4gOiAoayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhcyk7XG5cblx0XHRcdFx0aWYgKGRpZ2l0IDwgdCkge1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YmFzZU1pbnVzVCA9IGJhc2UgLSB0O1xuXHRcdFx0XHRpZiAodyA+IGZsb29yKG1heEludCAvIGJhc2VNaW51c1QpKSB7XG5cdFx0XHRcdFx0ZXJyb3IoJ292ZXJmbG93Jyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR3ICo9IGJhc2VNaW51c1Q7XG5cblx0XHRcdH1cblxuXHRcdFx0b3V0ID0gb3V0cHV0Lmxlbmd0aCArIDE7XG5cdFx0XHRiaWFzID0gYWRhcHQoaSAtIG9sZGksIG91dCwgb2xkaSA9PSAwKTtcblxuXHRcdFx0Ly8gYGlgIHdhcyBzdXBwb3NlZCB0byB3cmFwIGFyb3VuZCBmcm9tIGBvdXRgIHRvIGAwYCxcblx0XHRcdC8vIGluY3JlbWVudGluZyBgbmAgZWFjaCB0aW1lLCBzbyB3ZSdsbCBmaXggdGhhdCBub3c6XG5cdFx0XHRpZiAoZmxvb3IoaSAvIG91dCkgPiBtYXhJbnQgLSBuKSB7XG5cdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xuXHRcdFx0fVxuXG5cdFx0XHRuICs9IGZsb29yKGkgLyBvdXQpO1xuXHRcdFx0aSAlPSBvdXQ7XG5cblx0XHRcdC8vIEluc2VydCBgbmAgYXQgcG9zaXRpb24gYGlgIG9mIHRoZSBvdXRwdXRcblx0XHRcdG91dHB1dC5zcGxpY2UoaSsrLCAwLCBuKTtcblxuXHRcdH1cblxuXHRcdHJldHVybiB1Y3MyZW5jb2RlKG91dHB1dCk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBzdHJpbmcgb2YgVW5pY29kZSBzeW1ib2xzIChlLmcuIGEgZG9tYWluIG5hbWUgbGFiZWwpIHRvIGFcblx0ICogUHVueWNvZGUgc3RyaW5nIG9mIEFTQ0lJLW9ubHkgc3ltYm9scy5cblx0ICogQG1lbWJlck9mIHB1bnljb2RlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBUaGUgc3RyaW5nIG9mIFVuaWNvZGUgc3ltYm9scy5cblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIHJlc3VsdGluZyBQdW55Y29kZSBzdHJpbmcgb2YgQVNDSUktb25seSBzeW1ib2xzLlxuXHQgKi9cblx0ZnVuY3Rpb24gZW5jb2RlKGlucHV0KSB7XG5cdFx0dmFyIG4sXG5cdFx0ICAgIGRlbHRhLFxuXHRcdCAgICBoYW5kbGVkQ1BDb3VudCxcblx0XHQgICAgYmFzaWNMZW5ndGgsXG5cdFx0ICAgIGJpYXMsXG5cdFx0ICAgIGosXG5cdFx0ICAgIG0sXG5cdFx0ICAgIHEsXG5cdFx0ICAgIGssXG5cdFx0ICAgIHQsXG5cdFx0ICAgIGN1cnJlbnRWYWx1ZSxcblx0XHQgICAgb3V0cHV0ID0gW10sXG5cdFx0ICAgIC8qKiBgaW5wdXRMZW5ndGhgIHdpbGwgaG9sZCB0aGUgbnVtYmVyIG9mIGNvZGUgcG9pbnRzIGluIGBpbnB1dGAuICovXG5cdFx0ICAgIGlucHV0TGVuZ3RoLFxuXHRcdCAgICAvKiogQ2FjaGVkIGNhbGN1bGF0aW9uIHJlc3VsdHMgKi9cblx0XHQgICAgaGFuZGxlZENQQ291bnRQbHVzT25lLFxuXHRcdCAgICBiYXNlTWludXNULFxuXHRcdCAgICBxTWludXNUO1xuXG5cdFx0Ly8gQ29udmVydCB0aGUgaW5wdXQgaW4gVUNTLTIgdG8gVW5pY29kZVxuXHRcdGlucHV0ID0gdWNzMmRlY29kZShpbnB1dCk7XG5cblx0XHQvLyBDYWNoZSB0aGUgbGVuZ3RoXG5cdFx0aW5wdXRMZW5ndGggPSBpbnB1dC5sZW5ndGg7XG5cblx0XHQvLyBJbml0aWFsaXplIHRoZSBzdGF0ZVxuXHRcdG4gPSBpbml0aWFsTjtcblx0XHRkZWx0YSA9IDA7XG5cdFx0YmlhcyA9IGluaXRpYWxCaWFzO1xuXG5cdFx0Ly8gSGFuZGxlIHRoZSBiYXNpYyBjb2RlIHBvaW50c1xuXHRcdGZvciAoaiA9IDA7IGogPCBpbnB1dExlbmd0aDsgKytqKSB7XG5cdFx0XHRjdXJyZW50VmFsdWUgPSBpbnB1dFtqXTtcblx0XHRcdGlmIChjdXJyZW50VmFsdWUgPCAweDgwKSB7XG5cdFx0XHRcdG91dHB1dC5wdXNoKHN0cmluZ0Zyb21DaGFyQ29kZShjdXJyZW50VmFsdWUpKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRoYW5kbGVkQ1BDb3VudCA9IGJhc2ljTGVuZ3RoID0gb3V0cHV0Lmxlbmd0aDtcblxuXHRcdC8vIGBoYW5kbGVkQ1BDb3VudGAgaXMgdGhlIG51bWJlciBvZiBjb2RlIHBvaW50cyB0aGF0IGhhdmUgYmVlbiBoYW5kbGVkO1xuXHRcdC8vIGBiYXNpY0xlbmd0aGAgaXMgdGhlIG51bWJlciBvZiBiYXNpYyBjb2RlIHBvaW50cy5cblxuXHRcdC8vIEZpbmlzaCB0aGUgYmFzaWMgc3RyaW5nIC0gaWYgaXQgaXMgbm90IGVtcHR5IC0gd2l0aCBhIGRlbGltaXRlclxuXHRcdGlmIChiYXNpY0xlbmd0aCkge1xuXHRcdFx0b3V0cHV0LnB1c2goZGVsaW1pdGVyKTtcblx0XHR9XG5cblx0XHQvLyBNYWluIGVuY29kaW5nIGxvb3A6XG5cdFx0d2hpbGUgKGhhbmRsZWRDUENvdW50IDwgaW5wdXRMZW5ndGgpIHtcblxuXHRcdFx0Ly8gQWxsIG5vbi1iYXNpYyBjb2RlIHBvaW50cyA8IG4gaGF2ZSBiZWVuIGhhbmRsZWQgYWxyZWFkeS4gRmluZCB0aGUgbmV4dFxuXHRcdFx0Ly8gbGFyZ2VyIG9uZTpcblx0XHRcdGZvciAobSA9IG1heEludCwgaiA9IDA7IGogPCBpbnB1dExlbmd0aDsgKytqKSB7XG5cdFx0XHRcdGN1cnJlbnRWYWx1ZSA9IGlucHV0W2pdO1xuXHRcdFx0XHRpZiAoY3VycmVudFZhbHVlID49IG4gJiYgY3VycmVudFZhbHVlIDwgbSkge1xuXHRcdFx0XHRcdG0gPSBjdXJyZW50VmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gSW5jcmVhc2UgYGRlbHRhYCBlbm91Z2ggdG8gYWR2YW5jZSB0aGUgZGVjb2RlcidzIDxuLGk+IHN0YXRlIHRvIDxtLDA+LFxuXHRcdFx0Ly8gYnV0IGd1YXJkIGFnYWluc3Qgb3ZlcmZsb3dcblx0XHRcdGhhbmRsZWRDUENvdW50UGx1c09uZSA9IGhhbmRsZWRDUENvdW50ICsgMTtcblx0XHRcdGlmIChtIC0gbiA+IGZsb29yKChtYXhJbnQgLSBkZWx0YSkgLyBoYW5kbGVkQ1BDb3VudFBsdXNPbmUpKSB7XG5cdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xuXHRcdFx0fVxuXG5cdFx0XHRkZWx0YSArPSAobSAtIG4pICogaGFuZGxlZENQQ291bnRQbHVzT25lO1xuXHRcdFx0biA9IG07XG5cblx0XHRcdGZvciAoaiA9IDA7IGogPCBpbnB1dExlbmd0aDsgKytqKSB7XG5cdFx0XHRcdGN1cnJlbnRWYWx1ZSA9IGlucHV0W2pdO1xuXG5cdFx0XHRcdGlmIChjdXJyZW50VmFsdWUgPCBuICYmICsrZGVsdGEgPiBtYXhJbnQpIHtcblx0XHRcdFx0XHRlcnJvcignb3ZlcmZsb3cnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChjdXJyZW50VmFsdWUgPT0gbikge1xuXHRcdFx0XHRcdC8vIFJlcHJlc2VudCBkZWx0YSBhcyBhIGdlbmVyYWxpemVkIHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyXG5cdFx0XHRcdFx0Zm9yIChxID0gZGVsdGEsIGsgPSBiYXNlOyAvKiBubyBjb25kaXRpb24gKi87IGsgKz0gYmFzZSkge1xuXHRcdFx0XHRcdFx0dCA9IGsgPD0gYmlhcyA/IHRNaW4gOiAoayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhcyk7XG5cdFx0XHRcdFx0XHRpZiAocSA8IHQpIHtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRxTWludXNUID0gcSAtIHQ7XG5cdFx0XHRcdFx0XHRiYXNlTWludXNUID0gYmFzZSAtIHQ7XG5cdFx0XHRcdFx0XHRvdXRwdXQucHVzaChcblx0XHRcdFx0XHRcdFx0c3RyaW5nRnJvbUNoYXJDb2RlKGRpZ2l0VG9CYXNpYyh0ICsgcU1pbnVzVCAlIGJhc2VNaW51c1QsIDApKVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdHEgPSBmbG9vcihxTWludXNUIC8gYmFzZU1pbnVzVCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0b3V0cHV0LnB1c2goc3RyaW5nRnJvbUNoYXJDb2RlKGRpZ2l0VG9CYXNpYyhxLCAwKSkpO1xuXHRcdFx0XHRcdGJpYXMgPSBhZGFwdChkZWx0YSwgaGFuZGxlZENQQ291bnRQbHVzT25lLCBoYW5kbGVkQ1BDb3VudCA9PSBiYXNpY0xlbmd0aCk7XG5cdFx0XHRcdFx0ZGVsdGEgPSAwO1xuXHRcdFx0XHRcdCsraGFuZGxlZENQQ291bnQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0KytkZWx0YTtcblx0XHRcdCsrbjtcblxuXHRcdH1cblx0XHRyZXR1cm4gb3V0cHV0LmpvaW4oJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgUHVueWNvZGUgc3RyaW5nIHJlcHJlc2VudGluZyBhIGRvbWFpbiBuYW1lIG9yIGFuIGVtYWlsIGFkZHJlc3Ncblx0ICogdG8gVW5pY29kZS4gT25seSB0aGUgUHVueWNvZGVkIHBhcnRzIG9mIHRoZSBpbnB1dCB3aWxsIGJlIGNvbnZlcnRlZCwgaS5lLlxuXHQgKiBpdCBkb2Vzbid0IG1hdHRlciBpZiB5b3UgY2FsbCBpdCBvbiBhIHN0cmluZyB0aGF0IGhhcyBhbHJlYWR5IGJlZW5cblx0ICogY29udmVydGVkIHRvIFVuaWNvZGUuXG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIFB1bnljb2RlZCBkb21haW4gbmFtZSBvciBlbWFpbCBhZGRyZXNzIHRvXG5cdCAqIGNvbnZlcnQgdG8gVW5pY29kZS5cblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIFVuaWNvZGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIFB1bnljb2RlXG5cdCAqIHN0cmluZy5cblx0ICovXG5cdGZ1bmN0aW9uIHRvVW5pY29kZShpbnB1dCkge1xuXHRcdHJldHVybiBtYXBEb21haW4oaW5wdXQsIGZ1bmN0aW9uKHN0cmluZykge1xuXHRcdFx0cmV0dXJuIHJlZ2V4UHVueWNvZGUudGVzdChzdHJpbmcpXG5cdFx0XHRcdD8gZGVjb2RlKHN0cmluZy5zbGljZSg0KS50b0xvd2VyQ2FzZSgpKVxuXHRcdFx0XHQ6IHN0cmluZztcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIFVuaWNvZGUgc3RyaW5nIHJlcHJlc2VudGluZyBhIGRvbWFpbiBuYW1lIG9yIGFuIGVtYWlsIGFkZHJlc3MgdG9cblx0ICogUHVueWNvZGUuIE9ubHkgdGhlIG5vbi1BU0NJSSBwYXJ0cyBvZiB0aGUgZG9tYWluIG5hbWUgd2lsbCBiZSBjb252ZXJ0ZWQsXG5cdCAqIGkuZS4gaXQgZG9lc24ndCBtYXR0ZXIgaWYgeW91IGNhbGwgaXQgd2l0aCBhIGRvbWFpbiB0aGF0J3MgYWxyZWFkeSBpblxuXHQgKiBBU0NJSS5cblx0ICogQG1lbWJlck9mIHB1bnljb2RlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBUaGUgZG9tYWluIG5hbWUgb3IgZW1haWwgYWRkcmVzcyB0byBjb252ZXJ0LCBhcyBhXG5cdCAqIFVuaWNvZGUgc3RyaW5nLlxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgUHVueWNvZGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIGRvbWFpbiBuYW1lIG9yXG5cdCAqIGVtYWlsIGFkZHJlc3MuXG5cdCAqL1xuXHRmdW5jdGlvbiB0b0FTQ0lJKGlucHV0KSB7XG5cdFx0cmV0dXJuIG1hcERvbWFpbihpbnB1dCwgZnVuY3Rpb24oc3RyaW5nKSB7XG5cdFx0XHRyZXR1cm4gcmVnZXhOb25BU0NJSS50ZXN0KHN0cmluZylcblx0XHRcdFx0PyAneG4tLScgKyBlbmNvZGUoc3RyaW5nKVxuXHRcdFx0XHQ6IHN0cmluZztcblx0XHR9KTtcblx0fVxuXG5cdC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5cdC8qKiBEZWZpbmUgdGhlIHB1YmxpYyBBUEkgKi9cblx0cHVueWNvZGUgPSB7XG5cdFx0LyoqXG5cdFx0ICogQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBjdXJyZW50IFB1bnljb2RlLmpzIHZlcnNpb24gbnVtYmVyLlxuXHRcdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxuXHRcdCAqIEB0eXBlIFN0cmluZ1xuXHRcdCAqL1xuXHRcdCd2ZXJzaW9uJzogJzEuMy4yJyxcblx0XHQvKipcblx0XHQgKiBBbiBvYmplY3Qgb2YgbWV0aG9kcyB0byBjb252ZXJ0IGZyb20gSmF2YVNjcmlwdCdzIGludGVybmFsIGNoYXJhY3RlclxuXHRcdCAqIHJlcHJlc2VudGF0aW9uIChVQ1MtMikgdG8gVW5pY29kZSBjb2RlIHBvaW50cywgYW5kIGJhY2suXG5cdFx0ICogQHNlZSA8aHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtZW5jb2Rpbmc+XG5cdFx0ICogQG1lbWJlck9mIHB1bnljb2RlXG5cdFx0ICogQHR5cGUgT2JqZWN0XG5cdFx0ICovXG5cdFx0J3VjczInOiB7XG5cdFx0XHQnZGVjb2RlJzogdWNzMmRlY29kZSxcblx0XHRcdCdlbmNvZGUnOiB1Y3MyZW5jb2RlXG5cdFx0fSxcblx0XHQnZGVjb2RlJzogZGVjb2RlLFxuXHRcdCdlbmNvZGUnOiBlbmNvZGUsXG5cdFx0J3RvQVNDSUknOiB0b0FTQ0lJLFxuXHRcdCd0b1VuaWNvZGUnOiB0b1VuaWNvZGVcblx0fTtcblxuXHQvKiogRXhwb3NlIGBwdW55Y29kZWAgKi9cblx0Ly8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycywgbGlrZSByLmpzLCBjaGVjayBmb3Igc3BlY2lmaWMgY29uZGl0aW9uIHBhdHRlcm5zXG5cdC8vIGxpa2UgdGhlIGZvbGxvd2luZzpcblx0aWYgKFxuXHRcdHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJlxuXHRcdHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmXG5cdFx0ZGVmaW5lLmFtZFxuXHQpIHtcblx0XHRkZWZpbmUoJ3B1bnljb2RlJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gcHVueWNvZGU7XG5cdFx0fSk7XG5cdH0gZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuXHRcdGlmIChtb2R1bGUuZXhwb3J0cyA9PSBmcmVlRXhwb3J0cykgeyAvLyBpbiBOb2RlLmpzIG9yIFJpbmdvSlMgdjAuOC4wK1xuXHRcdFx0ZnJlZU1vZHVsZS5leHBvcnRzID0gcHVueWNvZGU7XG5cdFx0fSBlbHNlIHsgLy8gaW4gTmFyd2hhbCBvciBSaW5nb0pTIHYwLjcuMC1cblx0XHRcdGZvciAoa2V5IGluIHB1bnljb2RlKSB7XG5cdFx0XHRcdHB1bnljb2RlLmhhc093blByb3BlcnR5KGtleSkgJiYgKGZyZWVFeHBvcnRzW2tleV0gPSBwdW55Y29kZVtrZXldKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSB7IC8vIGluIFJoaW5vIG9yIGEgd2ViIGJyb3dzZXJcblx0XHRyb290LnB1bnljb2RlID0gcHVueWNvZGU7XG5cdH1cblxufSh0aGlzKSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciByZXBsYWNlID0gU3RyaW5nLnByb3RvdHlwZS5yZXBsYWNlO1xudmFyIHBlcmNlbnRUd2VudGllcyA9IC8lMjAvZztcblxudmFyIEZvcm1hdCA9IHtcbiAgICBSRkMxNzM4OiAnUkZDMTczOCcsXG4gICAgUkZDMzk4NjogJ1JGQzM5ODYnXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAnZGVmYXVsdCc6IEZvcm1hdC5SRkMzOTg2LFxuICAgIGZvcm1hdHRlcnM6IHtcbiAgICAgICAgUkZDMTczODogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVwbGFjZS5jYWxsKHZhbHVlLCBwZXJjZW50VHdlbnRpZXMsICcrJyk7XG4gICAgICAgIH0sXG4gICAgICAgIFJGQzM5ODY6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIFJGQzE3Mzg6IEZvcm1hdC5SRkMxNzM4LFxuICAgIFJGQzM5ODY6IEZvcm1hdC5SRkMzOTg2XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3RyaW5naWZ5ID0gcmVxdWlyZSgnLi9zdHJpbmdpZnknKTtcbnZhciBwYXJzZSA9IHJlcXVpcmUoJy4vcGFyc2UnKTtcbnZhciBmb3JtYXRzID0gcmVxdWlyZSgnLi9mb3JtYXRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGZvcm1hdHM6IGZvcm1hdHMsXG4gICAgcGFyc2U6IHBhcnNlLFxuICAgIHN0cmluZ2lmeTogc3RyaW5naWZ5XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG5cbnZhciBoYXMgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG52YXIgZGVmYXVsdHMgPSB7XG4gICAgYWxsb3dEb3RzOiBmYWxzZSxcbiAgICBhbGxvd1Byb3RvdHlwZXM6IGZhbHNlLFxuICAgIGFsbG93U3BhcnNlOiBmYWxzZSxcbiAgICBhcnJheUxpbWl0OiAyMCxcbiAgICBjaGFyc2V0OiAndXRmLTgnLFxuICAgIGNoYXJzZXRTZW50aW5lbDogZmFsc2UsXG4gICAgY29tbWE6IGZhbHNlLFxuICAgIGRlY29kZXI6IHV0aWxzLmRlY29kZSxcbiAgICBkZWxpbWl0ZXI6ICcmJyxcbiAgICBkZXB0aDogNSxcbiAgICBpZ25vcmVRdWVyeVByZWZpeDogZmFsc2UsXG4gICAgaW50ZXJwcmV0TnVtZXJpY0VudGl0aWVzOiBmYWxzZSxcbiAgICBwYXJhbWV0ZXJMaW1pdDogMTAwMCxcbiAgICBwYXJzZUFycmF5czogdHJ1ZSxcbiAgICBwbGFpbk9iamVjdHM6IGZhbHNlLFxuICAgIHN0cmljdE51bGxIYW5kbGluZzogZmFsc2Vcbn07XG5cbnZhciBpbnRlcnByZXROdW1lcmljRW50aXRpZXMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8mIyhcXGQrKTsvZywgZnVuY3Rpb24gKCQwLCBudW1iZXJTdHIpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUocGFyc2VJbnQobnVtYmVyU3RyLCAxMCkpO1xuICAgIH0pO1xufTtcblxudmFyIHBhcnNlQXJyYXlWYWx1ZSA9IGZ1bmN0aW9uICh2YWwsIG9wdGlvbnMpIHtcbiAgICBpZiAodmFsICYmIHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnICYmIG9wdGlvbnMuY29tbWEgJiYgdmFsLmluZGV4T2YoJywnKSA+IC0xKSB7XG4gICAgICAgIHJldHVybiB2YWwuc3BsaXQoJywnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsO1xufTtcblxuLy8gVGhpcyBpcyB3aGF0IGJyb3dzZXJzIHdpbGwgc3VibWl0IHdoZW4gdGhlIOKckyBjaGFyYWN0ZXIgb2NjdXJzIGluIGFuXG4vLyBhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQgYm9keSBhbmQgdGhlIGVuY29kaW5nIG9mIHRoZSBwYWdlIGNvbnRhaW5pbmdcbi8vIHRoZSBmb3JtIGlzIGlzby04ODU5LTEsIG9yIHdoZW4gdGhlIHN1Ym1pdHRlZCBmb3JtIGhhcyBhbiBhY2NlcHQtY2hhcnNldFxuLy8gYXR0cmlidXRlIG9mIGlzby04ODU5LTEuIFByZXN1bWFibHkgYWxzbyB3aXRoIG90aGVyIGNoYXJzZXRzIHRoYXQgZG8gbm90IGNvbnRhaW5cbi8vIHRoZSDinJMgY2hhcmFjdGVyLCBzdWNoIGFzIHVzLWFzY2lpLlxudmFyIGlzb1NlbnRpbmVsID0gJ3V0Zjg9JTI2JTIzMTAwMDMlM0InOyAvLyBlbmNvZGVVUklDb21wb25lbnQoJyYjMTAwMDM7JylcblxuLy8gVGhlc2UgYXJlIHRoZSBwZXJjZW50LWVuY29kZWQgdXRmLTggb2N0ZXRzIHJlcHJlc2VudGluZyBhIGNoZWNrbWFyaywgaW5kaWNhdGluZyB0aGF0IHRoZSByZXF1ZXN0IGFjdHVhbGx5IGlzIHV0Zi04IGVuY29kZWQuXG52YXIgY2hhcnNldFNlbnRpbmVsID0gJ3V0Zjg9JUUyJTlDJTkzJzsgLy8gZW5jb2RlVVJJQ29tcG9uZW50KCfinJMnKVxuXG52YXIgcGFyc2VWYWx1ZXMgPSBmdW5jdGlvbiBwYXJzZVF1ZXJ5U3RyaW5nVmFsdWVzKHN0ciwgb3B0aW9ucykge1xuICAgIHZhciBvYmogPSB7fTtcbiAgICB2YXIgY2xlYW5TdHIgPSBvcHRpb25zLmlnbm9yZVF1ZXJ5UHJlZml4ID8gc3RyLnJlcGxhY2UoL15cXD8vLCAnJykgOiBzdHI7XG4gICAgdmFyIGxpbWl0ID0gb3B0aW9ucy5wYXJhbWV0ZXJMaW1pdCA9PT0gSW5maW5pdHkgPyB1bmRlZmluZWQgOiBvcHRpb25zLnBhcmFtZXRlckxpbWl0O1xuICAgIHZhciBwYXJ0cyA9IGNsZWFuU3RyLnNwbGl0KG9wdGlvbnMuZGVsaW1pdGVyLCBsaW1pdCk7XG4gICAgdmFyIHNraXBJbmRleCA9IC0xOyAvLyBLZWVwIHRyYWNrIG9mIHdoZXJlIHRoZSB1dGY4IHNlbnRpbmVsIHdhcyBmb3VuZFxuICAgIHZhciBpO1xuXG4gICAgdmFyIGNoYXJzZXQgPSBvcHRpb25zLmNoYXJzZXQ7XG4gICAgaWYgKG9wdGlvbnMuY2hhcnNldFNlbnRpbmVsKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKHBhcnRzW2ldLmluZGV4T2YoJ3V0Zjg9JykgPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAocGFydHNbaV0gPT09IGNoYXJzZXRTZW50aW5lbCkge1xuICAgICAgICAgICAgICAgICAgICBjaGFyc2V0ID0gJ3V0Zi04JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcnRzW2ldID09PSBpc29TZW50aW5lbCkge1xuICAgICAgICAgICAgICAgICAgICBjaGFyc2V0ID0gJ2lzby04ODU5LTEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBza2lwSW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIGkgPSBwYXJ0cy5sZW5ndGg7IC8vIFRoZSBlc2xpbnQgc2V0dGluZ3MgZG8gbm90IGFsbG93IGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChpID09PSBza2lwSW5kZXgpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJ0ID0gcGFydHNbaV07XG5cbiAgICAgICAgdmFyIGJyYWNrZXRFcXVhbHNQb3MgPSBwYXJ0LmluZGV4T2YoJ109Jyk7XG4gICAgICAgIHZhciBwb3MgPSBicmFja2V0RXF1YWxzUG9zID09PSAtMSA/IHBhcnQuaW5kZXhPZignPScpIDogYnJhY2tldEVxdWFsc1BvcyArIDE7XG5cbiAgICAgICAgdmFyIGtleSwgdmFsO1xuICAgICAgICBpZiAocG9zID09PSAtMSkge1xuICAgICAgICAgICAga2V5ID0gb3B0aW9ucy5kZWNvZGVyKHBhcnQsIGRlZmF1bHRzLmRlY29kZXIsIGNoYXJzZXQsICdrZXknKTtcbiAgICAgICAgICAgIHZhbCA9IG9wdGlvbnMuc3RyaWN0TnVsbEhhbmRsaW5nID8gbnVsbCA6ICcnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAga2V5ID0gb3B0aW9ucy5kZWNvZGVyKHBhcnQuc2xpY2UoMCwgcG9zKSwgZGVmYXVsdHMuZGVjb2RlciwgY2hhcnNldCwgJ2tleScpO1xuICAgICAgICAgICAgdmFsID0gdXRpbHMubWF5YmVNYXAoXG4gICAgICAgICAgICAgICAgcGFyc2VBcnJheVZhbHVlKHBhcnQuc2xpY2UocG9zICsgMSksIG9wdGlvbnMpLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChlbmNvZGVkVmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmRlY29kZXIoZW5jb2RlZFZhbCwgZGVmYXVsdHMuZGVjb2RlciwgY2hhcnNldCwgJ3ZhbHVlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwgJiYgb3B0aW9ucy5pbnRlcnByZXROdW1lcmljRW50aXRpZXMgJiYgY2hhcnNldCA9PT0gJ2lzby04ODU5LTEnKSB7XG4gICAgICAgICAgICB2YWwgPSBpbnRlcnByZXROdW1lcmljRW50aXRpZXModmFsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJ0LmluZGV4T2YoJ1tdPScpID4gLTEpIHtcbiAgICAgICAgICAgIHZhbCA9IGlzQXJyYXkodmFsKSA/IFt2YWxdIDogdmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGhhcy5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICAgICAgb2JqW2tleV0gPSB1dGlscy5jb21iaW5lKG9ialtrZXldLCB2YWwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2JqW2tleV0gPSB2YWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb2JqO1xufTtcblxudmFyIHBhcnNlT2JqZWN0ID0gZnVuY3Rpb24gKGNoYWluLCB2YWwsIG9wdGlvbnMsIHZhbHVlc1BhcnNlZCkge1xuICAgIHZhciBsZWFmID0gdmFsdWVzUGFyc2VkID8gdmFsIDogcGFyc2VBcnJheVZhbHVlKHZhbCwgb3B0aW9ucyk7XG5cbiAgICBmb3IgKHZhciBpID0gY2hhaW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgdmFyIG9iajtcbiAgICAgICAgdmFyIHJvb3QgPSBjaGFpbltpXTtcblxuICAgICAgICBpZiAocm9vdCA9PT0gJ1tdJyAmJiBvcHRpb25zLnBhcnNlQXJyYXlzKSB7XG4gICAgICAgICAgICBvYmogPSBbXS5jb25jYXQobGVhZik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvYmogPSBvcHRpb25zLnBsYWluT2JqZWN0cyA/IE9iamVjdC5jcmVhdGUobnVsbCkgOiB7fTtcbiAgICAgICAgICAgIHZhciBjbGVhblJvb3QgPSByb290LmNoYXJBdCgwKSA9PT0gJ1snICYmIHJvb3QuY2hhckF0KHJvb3QubGVuZ3RoIC0gMSkgPT09ICddJyA/IHJvb3Quc2xpY2UoMSwgLTEpIDogcm9vdDtcbiAgICAgICAgICAgIHZhciBpbmRleCA9IHBhcnNlSW50KGNsZWFuUm9vdCwgMTApO1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zLnBhcnNlQXJyYXlzICYmIGNsZWFuUm9vdCA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICBvYmogPSB7IDA6IGxlYWYgfTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgIWlzTmFOKGluZGV4KVxuICAgICAgICAgICAgICAgICYmIHJvb3QgIT09IGNsZWFuUm9vdFxuICAgICAgICAgICAgICAgICYmIFN0cmluZyhpbmRleCkgPT09IGNsZWFuUm9vdFxuICAgICAgICAgICAgICAgICYmIGluZGV4ID49IDBcbiAgICAgICAgICAgICAgICAmJiAob3B0aW9ucy5wYXJzZUFycmF5cyAmJiBpbmRleCA8PSBvcHRpb25zLmFycmF5TGltaXQpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBvYmogPSBbXTtcbiAgICAgICAgICAgICAgICBvYmpbaW5kZXhdID0gbGVhZjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb2JqW2NsZWFuUm9vdF0gPSBsZWFmO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGVhZiA9IG9iajtcbiAgICB9XG5cbiAgICByZXR1cm4gbGVhZjtcbn07XG5cbnZhciBwYXJzZUtleXMgPSBmdW5jdGlvbiBwYXJzZVF1ZXJ5U3RyaW5nS2V5cyhnaXZlbktleSwgdmFsLCBvcHRpb25zLCB2YWx1ZXNQYXJzZWQpIHtcbiAgICBpZiAoIWdpdmVuS2V5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBUcmFuc2Zvcm0gZG90IG5vdGF0aW9uIHRvIGJyYWNrZXQgbm90YXRpb25cbiAgICB2YXIga2V5ID0gb3B0aW9ucy5hbGxvd0RvdHMgPyBnaXZlbktleS5yZXBsYWNlKC9cXC4oW14uW10rKS9nLCAnWyQxXScpIDogZ2l2ZW5LZXk7XG5cbiAgICAvLyBUaGUgcmVnZXggY2h1bmtzXG5cbiAgICB2YXIgYnJhY2tldHMgPSAvKFxcW1teW1xcXV0qXSkvO1xuICAgIHZhciBjaGlsZCA9IC8oXFxbW15bXFxdXSpdKS9nO1xuXG4gICAgLy8gR2V0IHRoZSBwYXJlbnRcblxuICAgIHZhciBzZWdtZW50ID0gb3B0aW9ucy5kZXB0aCA+IDAgJiYgYnJhY2tldHMuZXhlYyhrZXkpO1xuICAgIHZhciBwYXJlbnQgPSBzZWdtZW50ID8ga2V5LnNsaWNlKDAsIHNlZ21lbnQuaW5kZXgpIDoga2V5O1xuXG4gICAgLy8gU3Rhc2ggdGhlIHBhcmVudCBpZiBpdCBleGlzdHNcblxuICAgIHZhciBrZXlzID0gW107XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgICAvLyBJZiB3ZSBhcmVuJ3QgdXNpbmcgcGxhaW4gb2JqZWN0cywgb3B0aW9uYWxseSBwcmVmaXgga2V5cyB0aGF0IHdvdWxkIG92ZXJ3cml0ZSBvYmplY3QgcHJvdG90eXBlIHByb3BlcnRpZXNcbiAgICAgICAgaWYgKCFvcHRpb25zLnBsYWluT2JqZWN0cyAmJiBoYXMuY2FsbChPYmplY3QucHJvdG90eXBlLCBwYXJlbnQpKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMuYWxsb3dQcm90b3R5cGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAga2V5cy5wdXNoKHBhcmVudCk7XG4gICAgfVxuXG4gICAgLy8gTG9vcCB0aHJvdWdoIGNoaWxkcmVuIGFwcGVuZGluZyB0byB0aGUgYXJyYXkgdW50aWwgd2UgaGl0IGRlcHRoXG5cbiAgICB2YXIgaSA9IDA7XG4gICAgd2hpbGUgKG9wdGlvbnMuZGVwdGggPiAwICYmIChzZWdtZW50ID0gY2hpbGQuZXhlYyhrZXkpKSAhPT0gbnVsbCAmJiBpIDwgb3B0aW9ucy5kZXB0aCkge1xuICAgICAgICBpICs9IDE7XG4gICAgICAgIGlmICghb3B0aW9ucy5wbGFpbk9iamVjdHMgJiYgaGFzLmNhbGwoT2JqZWN0LnByb3RvdHlwZSwgc2VnbWVudFsxXS5zbGljZSgxLCAtMSkpKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMuYWxsb3dQcm90b3R5cGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGtleXMucHVzaChzZWdtZW50WzFdKTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGVyZSdzIGEgcmVtYWluZGVyLCBqdXN0IGFkZCB3aGF0ZXZlciBpcyBsZWZ0XG5cbiAgICBpZiAoc2VnbWVudCkge1xuICAgICAgICBrZXlzLnB1c2goJ1snICsga2V5LnNsaWNlKHNlZ21lbnQuaW5kZXgpICsgJ10nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFyc2VPYmplY3Qoa2V5cywgdmFsLCBvcHRpb25zLCB2YWx1ZXNQYXJzZWQpO1xufTtcblxudmFyIG5vcm1hbGl6ZVBhcnNlT3B0aW9ucyA9IGZ1bmN0aW9uIG5vcm1hbGl6ZVBhcnNlT3B0aW9ucyhvcHRzKSB7XG4gICAgaWYgKCFvcHRzKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0cztcbiAgICB9XG5cbiAgICBpZiAob3B0cy5kZWNvZGVyICE9PSBudWxsICYmIG9wdHMuZGVjb2RlciAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvcHRzLmRlY29kZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRGVjb2RlciBoYXMgdG8gYmUgYSBmdW5jdGlvbi4nKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdHMuY2hhcnNldCAhPT0gJ3VuZGVmaW5lZCcgJiYgb3B0cy5jaGFyc2V0ICE9PSAndXRmLTgnICYmIG9wdHMuY2hhcnNldCAhPT0gJ2lzby04ODU5LTEnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBjaGFyc2V0IG9wdGlvbiBtdXN0IGJlIGVpdGhlciB1dGYtOCwgaXNvLTg4NTktMSwgb3IgdW5kZWZpbmVkJyk7XG4gICAgfVxuICAgIHZhciBjaGFyc2V0ID0gdHlwZW9mIG9wdHMuY2hhcnNldCA9PT0gJ3VuZGVmaW5lZCcgPyBkZWZhdWx0cy5jaGFyc2V0IDogb3B0cy5jaGFyc2V0O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWxsb3dEb3RzOiB0eXBlb2Ygb3B0cy5hbGxvd0RvdHMgPT09ICd1bmRlZmluZWQnID8gZGVmYXVsdHMuYWxsb3dEb3RzIDogISFvcHRzLmFsbG93RG90cyxcbiAgICAgICAgYWxsb3dQcm90b3R5cGVzOiB0eXBlb2Ygb3B0cy5hbGxvd1Byb3RvdHlwZXMgPT09ICdib29sZWFuJyA/IG9wdHMuYWxsb3dQcm90b3R5cGVzIDogZGVmYXVsdHMuYWxsb3dQcm90b3R5cGVzLFxuICAgICAgICBhbGxvd1NwYXJzZTogdHlwZW9mIG9wdHMuYWxsb3dTcGFyc2UgPT09ICdib29sZWFuJyA/IG9wdHMuYWxsb3dTcGFyc2UgOiBkZWZhdWx0cy5hbGxvd1NwYXJzZSxcbiAgICAgICAgYXJyYXlMaW1pdDogdHlwZW9mIG9wdHMuYXJyYXlMaW1pdCA9PT0gJ251bWJlcicgPyBvcHRzLmFycmF5TGltaXQgOiBkZWZhdWx0cy5hcnJheUxpbWl0LFxuICAgICAgICBjaGFyc2V0OiBjaGFyc2V0LFxuICAgICAgICBjaGFyc2V0U2VudGluZWw6IHR5cGVvZiBvcHRzLmNoYXJzZXRTZW50aW5lbCA9PT0gJ2Jvb2xlYW4nID8gb3B0cy5jaGFyc2V0U2VudGluZWwgOiBkZWZhdWx0cy5jaGFyc2V0U2VudGluZWwsXG4gICAgICAgIGNvbW1hOiB0eXBlb2Ygb3B0cy5jb21tYSA9PT0gJ2Jvb2xlYW4nID8gb3B0cy5jb21tYSA6IGRlZmF1bHRzLmNvbW1hLFxuICAgICAgICBkZWNvZGVyOiB0eXBlb2Ygb3B0cy5kZWNvZGVyID09PSAnZnVuY3Rpb24nID8gb3B0cy5kZWNvZGVyIDogZGVmYXVsdHMuZGVjb2RlcixcbiAgICAgICAgZGVsaW1pdGVyOiB0eXBlb2Ygb3B0cy5kZWxpbWl0ZXIgPT09ICdzdHJpbmcnIHx8IHV0aWxzLmlzUmVnRXhwKG9wdHMuZGVsaW1pdGVyKSA/IG9wdHMuZGVsaW1pdGVyIDogZGVmYXVsdHMuZGVsaW1pdGVyLFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8taW1wbGljaXQtY29lcmNpb24sIG5vLWV4dHJhLXBhcmVuc1xuICAgICAgICBkZXB0aDogKHR5cGVvZiBvcHRzLmRlcHRoID09PSAnbnVtYmVyJyB8fCBvcHRzLmRlcHRoID09PSBmYWxzZSkgPyArb3B0cy5kZXB0aCA6IGRlZmF1bHRzLmRlcHRoLFxuICAgICAgICBpZ25vcmVRdWVyeVByZWZpeDogb3B0cy5pZ25vcmVRdWVyeVByZWZpeCA9PT0gdHJ1ZSxcbiAgICAgICAgaW50ZXJwcmV0TnVtZXJpY0VudGl0aWVzOiB0eXBlb2Ygb3B0cy5pbnRlcnByZXROdW1lcmljRW50aXRpZXMgPT09ICdib29sZWFuJyA/IG9wdHMuaW50ZXJwcmV0TnVtZXJpY0VudGl0aWVzIDogZGVmYXVsdHMuaW50ZXJwcmV0TnVtZXJpY0VudGl0aWVzLFxuICAgICAgICBwYXJhbWV0ZXJMaW1pdDogdHlwZW9mIG9wdHMucGFyYW1ldGVyTGltaXQgPT09ICdudW1iZXInID8gb3B0cy5wYXJhbWV0ZXJMaW1pdCA6IGRlZmF1bHRzLnBhcmFtZXRlckxpbWl0LFxuICAgICAgICBwYXJzZUFycmF5czogb3B0cy5wYXJzZUFycmF5cyAhPT0gZmFsc2UsXG4gICAgICAgIHBsYWluT2JqZWN0czogdHlwZW9mIG9wdHMucGxhaW5PYmplY3RzID09PSAnYm9vbGVhbicgPyBvcHRzLnBsYWluT2JqZWN0cyA6IGRlZmF1bHRzLnBsYWluT2JqZWN0cyxcbiAgICAgICAgc3RyaWN0TnVsbEhhbmRsaW5nOiB0eXBlb2Ygb3B0cy5zdHJpY3ROdWxsSGFuZGxpbmcgPT09ICdib29sZWFuJyA/IG9wdHMuc3RyaWN0TnVsbEhhbmRsaW5nIDogZGVmYXVsdHMuc3RyaWN0TnVsbEhhbmRsaW5nXG4gICAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0ciwgb3B0cykge1xuICAgIHZhciBvcHRpb25zID0gbm9ybWFsaXplUGFyc2VPcHRpb25zKG9wdHMpO1xuXG4gICAgaWYgKHN0ciA9PT0gJycgfHwgc3RyID09PSBudWxsIHx8IHR5cGVvZiBzdHIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLnBsYWluT2JqZWN0cyA/IE9iamVjdC5jcmVhdGUobnVsbCkgOiB7fTtcbiAgICB9XG5cbiAgICB2YXIgdGVtcE9iaiA9IHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnID8gcGFyc2VWYWx1ZXMoc3RyLCBvcHRpb25zKSA6IHN0cjtcbiAgICB2YXIgb2JqID0gb3B0aW9ucy5wbGFpbk9iamVjdHMgPyBPYmplY3QuY3JlYXRlKG51bGwpIDoge307XG5cbiAgICAvLyBJdGVyYXRlIG92ZXIgdGhlIGtleXMgYW5kIHNldHVwIHRoZSBuZXcgb2JqZWN0XG5cbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRlbXBPYmopO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgdmFyIG5ld09iaiA9IHBhcnNlS2V5cyhrZXksIHRlbXBPYmpba2V5XSwgb3B0aW9ucywgdHlwZW9mIHN0ciA9PT0gJ3N0cmluZycpO1xuICAgICAgICBvYmogPSB1dGlscy5tZXJnZShvYmosIG5ld09iaiwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuYWxsb3dTcGFyc2UgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG5cbiAgICByZXR1cm4gdXRpbHMuY29tcGFjdChvYmopO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGdldFNpZGVDaGFubmVsID0gcmVxdWlyZSgnc2lkZS1jaGFubmVsJyk7XG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG52YXIgZm9ybWF0cyA9IHJlcXVpcmUoJy4vZm9ybWF0cycpO1xudmFyIGhhcyA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbnZhciBhcnJheVByZWZpeEdlbmVyYXRvcnMgPSB7XG4gICAgYnJhY2tldHM6IGZ1bmN0aW9uIGJyYWNrZXRzKHByZWZpeCkge1xuICAgICAgICByZXR1cm4gcHJlZml4ICsgJ1tdJztcbiAgICB9LFxuICAgIGNvbW1hOiAnY29tbWEnLFxuICAgIGluZGljZXM6IGZ1bmN0aW9uIGluZGljZXMocHJlZml4LCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIHByZWZpeCArICdbJyArIGtleSArICddJztcbiAgICB9LFxuICAgIHJlcGVhdDogZnVuY3Rpb24gcmVwZWF0KHByZWZpeCkge1xuICAgICAgICByZXR1cm4gcHJlZml4O1xuICAgIH1cbn07XG5cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbnZhciBwdXNoID0gQXJyYXkucHJvdG90eXBlLnB1c2g7XG52YXIgcHVzaFRvQXJyYXkgPSBmdW5jdGlvbiAoYXJyLCB2YWx1ZU9yQXJyYXkpIHtcbiAgICBwdXNoLmFwcGx5KGFyciwgaXNBcnJheSh2YWx1ZU9yQXJyYXkpID8gdmFsdWVPckFycmF5IDogW3ZhbHVlT3JBcnJheV0pO1xufTtcblxudmFyIHRvSVNPID0gRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmc7XG5cbnZhciBkZWZhdWx0Rm9ybWF0ID0gZm9ybWF0c1snZGVmYXVsdCddO1xudmFyIGRlZmF1bHRzID0ge1xuICAgIGFkZFF1ZXJ5UHJlZml4OiBmYWxzZSxcbiAgICBhbGxvd0RvdHM6IGZhbHNlLFxuICAgIGNoYXJzZXQ6ICd1dGYtOCcsXG4gICAgY2hhcnNldFNlbnRpbmVsOiBmYWxzZSxcbiAgICBkZWxpbWl0ZXI6ICcmJyxcbiAgICBlbmNvZGU6IHRydWUsXG4gICAgZW5jb2RlcjogdXRpbHMuZW5jb2RlLFxuICAgIGVuY29kZVZhbHVlc09ubHk6IGZhbHNlLFxuICAgIGZvcm1hdDogZGVmYXVsdEZvcm1hdCxcbiAgICBmb3JtYXR0ZXI6IGZvcm1hdHMuZm9ybWF0dGVyc1tkZWZhdWx0Rm9ybWF0XSxcbiAgICAvLyBkZXByZWNhdGVkXG4gICAgaW5kaWNlczogZmFsc2UsXG4gICAgc2VyaWFsaXplRGF0ZTogZnVuY3Rpb24gc2VyaWFsaXplRGF0ZShkYXRlKSB7XG4gICAgICAgIHJldHVybiB0b0lTTy5jYWxsKGRhdGUpO1xuICAgIH0sXG4gICAgc2tpcE51bGxzOiBmYWxzZSxcbiAgICBzdHJpY3ROdWxsSGFuZGxpbmc6IGZhbHNlXG59O1xuXG52YXIgaXNOb25OdWxsaXNoUHJpbWl0aXZlID0gZnVuY3Rpb24gaXNOb25OdWxsaXNoUHJpbWl0aXZlKHYpIHtcbiAgICByZXR1cm4gdHlwZW9mIHYgPT09ICdzdHJpbmcnXG4gICAgICAgIHx8IHR5cGVvZiB2ID09PSAnbnVtYmVyJ1xuICAgICAgICB8fCB0eXBlb2YgdiA9PT0gJ2Jvb2xlYW4nXG4gICAgICAgIHx8IHR5cGVvZiB2ID09PSAnc3ltYm9sJ1xuICAgICAgICB8fCB0eXBlb2YgdiA9PT0gJ2JpZ2ludCc7XG59O1xuXG52YXIgc3RyaW5naWZ5ID0gZnVuY3Rpb24gc3RyaW5naWZ5KFxuICAgIG9iamVjdCxcbiAgICBwcmVmaXgsXG4gICAgZ2VuZXJhdGVBcnJheVByZWZpeCxcbiAgICBzdHJpY3ROdWxsSGFuZGxpbmcsXG4gICAgc2tpcE51bGxzLFxuICAgIGVuY29kZXIsXG4gICAgZmlsdGVyLFxuICAgIHNvcnQsXG4gICAgYWxsb3dEb3RzLFxuICAgIHNlcmlhbGl6ZURhdGUsXG4gICAgZm9ybWF0LFxuICAgIGZvcm1hdHRlcixcbiAgICBlbmNvZGVWYWx1ZXNPbmx5LFxuICAgIGNoYXJzZXQsXG4gICAgc2lkZUNoYW5uZWxcbikge1xuICAgIHZhciBvYmogPSBvYmplY3Q7XG5cbiAgICBpZiAoc2lkZUNoYW5uZWwuaGFzKG9iamVjdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0N5Y2xpYyBvYmplY3QgdmFsdWUnKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGZpbHRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBvYmogPSBmaWx0ZXIocHJlZml4LCBvYmopO1xuICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBvYmogPSBzZXJpYWxpemVEYXRlKG9iaik7XG4gICAgfSBlbHNlIGlmIChnZW5lcmF0ZUFycmF5UHJlZml4ID09PSAnY29tbWEnICYmIGlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmogPSB1dGlscy5tYXliZU1hcChvYmosIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZXJpYWxpemVEYXRlKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgICAgICBpZiAoc3RyaWN0TnVsbEhhbmRsaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlciAmJiAhZW5jb2RlVmFsdWVzT25seSA/IGVuY29kZXIocHJlZml4LCBkZWZhdWx0cy5lbmNvZGVyLCBjaGFyc2V0LCAna2V5JywgZm9ybWF0KSA6IHByZWZpeDtcbiAgICAgICAgfVxuXG4gICAgICAgIG9iaiA9ICcnO1xuICAgIH1cblxuICAgIGlmIChpc05vbk51bGxpc2hQcmltaXRpdmUob2JqKSB8fCB1dGlscy5pc0J1ZmZlcihvYmopKSB7XG4gICAgICAgIGlmIChlbmNvZGVyKSB7XG4gICAgICAgICAgICB2YXIga2V5VmFsdWUgPSBlbmNvZGVWYWx1ZXNPbmx5ID8gcHJlZml4IDogZW5jb2RlcihwcmVmaXgsIGRlZmF1bHRzLmVuY29kZXIsIGNoYXJzZXQsICdrZXknLCBmb3JtYXQpO1xuICAgICAgICAgICAgcmV0dXJuIFtmb3JtYXR0ZXIoa2V5VmFsdWUpICsgJz0nICsgZm9ybWF0dGVyKGVuY29kZXIob2JqLCBkZWZhdWx0cy5lbmNvZGVyLCBjaGFyc2V0LCAndmFsdWUnLCBmb3JtYXQpKV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtmb3JtYXR0ZXIocHJlZml4KSArICc9JyArIGZvcm1hdHRlcihTdHJpbmcob2JqKSldO1xuICAgIH1cblxuICAgIHZhciB2YWx1ZXMgPSBbXTtcblxuICAgIGlmICh0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH1cblxuICAgIHZhciBvYmpLZXlzO1xuICAgIGlmIChnZW5lcmF0ZUFycmF5UHJlZml4ID09PSAnY29tbWEnICYmIGlzQXJyYXkob2JqKSkge1xuICAgICAgICAvLyB3ZSBuZWVkIHRvIGpvaW4gZWxlbWVudHMgaW5cbiAgICAgICAgb2JqS2V5cyA9IFt7IHZhbHVlOiBvYmoubGVuZ3RoID4gMCA/IG9iai5qb2luKCcsJykgfHwgbnVsbCA6IHVuZGVmaW5lZCB9XTtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoZmlsdGVyKSkge1xuICAgICAgICBvYmpLZXlzID0gZmlsdGVyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcbiAgICAgICAgb2JqS2V5cyA9IHNvcnQgPyBrZXlzLnNvcnQoc29ydCkgOiBrZXlzO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqS2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIga2V5ID0gb2JqS2V5c1tpXTtcbiAgICAgICAgdmFyIHZhbHVlID0gdHlwZW9mIGtleSA9PT0gJ29iamVjdCcgJiYga2V5LnZhbHVlICE9PSB1bmRlZmluZWQgPyBrZXkudmFsdWUgOiBvYmpba2V5XTtcblxuICAgICAgICBpZiAoc2tpcE51bGxzICYmIHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBrZXlQcmVmaXggPSBpc0FycmF5KG9iailcbiAgICAgICAgICAgID8gdHlwZW9mIGdlbmVyYXRlQXJyYXlQcmVmaXggPT09ICdmdW5jdGlvbicgPyBnZW5lcmF0ZUFycmF5UHJlZml4KHByZWZpeCwga2V5KSA6IHByZWZpeFxuICAgICAgICAgICAgOiBwcmVmaXggKyAoYWxsb3dEb3RzID8gJy4nICsga2V5IDogJ1snICsga2V5ICsgJ10nKTtcblxuICAgICAgICBzaWRlQ2hhbm5lbC5zZXQob2JqZWN0LCB0cnVlKTtcbiAgICAgICAgdmFyIHZhbHVlU2lkZUNoYW5uZWwgPSBnZXRTaWRlQ2hhbm5lbCgpO1xuICAgICAgICBwdXNoVG9BcnJheSh2YWx1ZXMsIHN0cmluZ2lmeShcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAga2V5UHJlZml4LFxuICAgICAgICAgICAgZ2VuZXJhdGVBcnJheVByZWZpeCxcbiAgICAgICAgICAgIHN0cmljdE51bGxIYW5kbGluZyxcbiAgICAgICAgICAgIHNraXBOdWxscyxcbiAgICAgICAgICAgIGVuY29kZXIsXG4gICAgICAgICAgICBmaWx0ZXIsXG4gICAgICAgICAgICBzb3J0LFxuICAgICAgICAgICAgYWxsb3dEb3RzLFxuICAgICAgICAgICAgc2VyaWFsaXplRGF0ZSxcbiAgICAgICAgICAgIGZvcm1hdCxcbiAgICAgICAgICAgIGZvcm1hdHRlcixcbiAgICAgICAgICAgIGVuY29kZVZhbHVlc09ubHksXG4gICAgICAgICAgICBjaGFyc2V0LFxuICAgICAgICAgICAgdmFsdWVTaWRlQ2hhbm5lbFxuICAgICAgICApKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWVzO1xufTtcblxudmFyIG5vcm1hbGl6ZVN0cmluZ2lmeU9wdGlvbnMgPSBmdW5jdGlvbiBub3JtYWxpemVTdHJpbmdpZnlPcHRpb25zKG9wdHMpIHtcbiAgICBpZiAoIW9wdHMpIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRzO1xuICAgIH1cblxuICAgIGlmIChvcHRzLmVuY29kZXIgIT09IG51bGwgJiYgb3B0cy5lbmNvZGVyICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9wdHMuZW5jb2RlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFbmNvZGVyIGhhcyB0byBiZSBhIGZ1bmN0aW9uLicpO1xuICAgIH1cblxuICAgIHZhciBjaGFyc2V0ID0gb3B0cy5jaGFyc2V0IHx8IGRlZmF1bHRzLmNoYXJzZXQ7XG4gICAgaWYgKHR5cGVvZiBvcHRzLmNoYXJzZXQgIT09ICd1bmRlZmluZWQnICYmIG9wdHMuY2hhcnNldCAhPT0gJ3V0Zi04JyAmJiBvcHRzLmNoYXJzZXQgIT09ICdpc28tODg1OS0xJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgY2hhcnNldCBvcHRpb24gbXVzdCBiZSBlaXRoZXIgdXRmLTgsIGlzby04ODU5LTEsIG9yIHVuZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHZhciBmb3JtYXQgPSBmb3JtYXRzWydkZWZhdWx0J107XG4gICAgaWYgKHR5cGVvZiBvcHRzLmZvcm1hdCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKCFoYXMuY2FsbChmb3JtYXRzLmZvcm1hdHRlcnMsIG9wdHMuZm9ybWF0KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBmb3JtYXQgb3B0aW9uIHByb3ZpZGVkLicpO1xuICAgICAgICB9XG4gICAgICAgIGZvcm1hdCA9IG9wdHMuZm9ybWF0O1xuICAgIH1cbiAgICB2YXIgZm9ybWF0dGVyID0gZm9ybWF0cy5mb3JtYXR0ZXJzW2Zvcm1hdF07XG5cbiAgICB2YXIgZmlsdGVyID0gZGVmYXVsdHMuZmlsdGVyO1xuICAgIGlmICh0eXBlb2Ygb3B0cy5maWx0ZXIgPT09ICdmdW5jdGlvbicgfHwgaXNBcnJheShvcHRzLmZpbHRlcikpIHtcbiAgICAgICAgZmlsdGVyID0gb3B0cy5maWx0ZXI7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWRkUXVlcnlQcmVmaXg6IHR5cGVvZiBvcHRzLmFkZFF1ZXJ5UHJlZml4ID09PSAnYm9vbGVhbicgPyBvcHRzLmFkZFF1ZXJ5UHJlZml4IDogZGVmYXVsdHMuYWRkUXVlcnlQcmVmaXgsXG4gICAgICAgIGFsbG93RG90czogdHlwZW9mIG9wdHMuYWxsb3dEb3RzID09PSAndW5kZWZpbmVkJyA/IGRlZmF1bHRzLmFsbG93RG90cyA6ICEhb3B0cy5hbGxvd0RvdHMsXG4gICAgICAgIGNoYXJzZXQ6IGNoYXJzZXQsXG4gICAgICAgIGNoYXJzZXRTZW50aW5lbDogdHlwZW9mIG9wdHMuY2hhcnNldFNlbnRpbmVsID09PSAnYm9vbGVhbicgPyBvcHRzLmNoYXJzZXRTZW50aW5lbCA6IGRlZmF1bHRzLmNoYXJzZXRTZW50aW5lbCxcbiAgICAgICAgZGVsaW1pdGVyOiB0eXBlb2Ygb3B0cy5kZWxpbWl0ZXIgPT09ICd1bmRlZmluZWQnID8gZGVmYXVsdHMuZGVsaW1pdGVyIDogb3B0cy5kZWxpbWl0ZXIsXG4gICAgICAgIGVuY29kZTogdHlwZW9mIG9wdHMuZW5jb2RlID09PSAnYm9vbGVhbicgPyBvcHRzLmVuY29kZSA6IGRlZmF1bHRzLmVuY29kZSxcbiAgICAgICAgZW5jb2RlcjogdHlwZW9mIG9wdHMuZW5jb2RlciA9PT0gJ2Z1bmN0aW9uJyA/IG9wdHMuZW5jb2RlciA6IGRlZmF1bHRzLmVuY29kZXIsXG4gICAgICAgIGVuY29kZVZhbHVlc09ubHk6IHR5cGVvZiBvcHRzLmVuY29kZVZhbHVlc09ubHkgPT09ICdib29sZWFuJyA/IG9wdHMuZW5jb2RlVmFsdWVzT25seSA6IGRlZmF1bHRzLmVuY29kZVZhbHVlc09ubHksXG4gICAgICAgIGZpbHRlcjogZmlsdGVyLFxuICAgICAgICBmb3JtYXQ6IGZvcm1hdCxcbiAgICAgICAgZm9ybWF0dGVyOiBmb3JtYXR0ZXIsXG4gICAgICAgIHNlcmlhbGl6ZURhdGU6IHR5cGVvZiBvcHRzLnNlcmlhbGl6ZURhdGUgPT09ICdmdW5jdGlvbicgPyBvcHRzLnNlcmlhbGl6ZURhdGUgOiBkZWZhdWx0cy5zZXJpYWxpemVEYXRlLFxuICAgICAgICBza2lwTnVsbHM6IHR5cGVvZiBvcHRzLnNraXBOdWxscyA9PT0gJ2Jvb2xlYW4nID8gb3B0cy5za2lwTnVsbHMgOiBkZWZhdWx0cy5za2lwTnVsbHMsXG4gICAgICAgIHNvcnQ6IHR5cGVvZiBvcHRzLnNvcnQgPT09ICdmdW5jdGlvbicgPyBvcHRzLnNvcnQgOiBudWxsLFxuICAgICAgICBzdHJpY3ROdWxsSGFuZGxpbmc6IHR5cGVvZiBvcHRzLnN0cmljdE51bGxIYW5kbGluZyA9PT0gJ2Jvb2xlYW4nID8gb3B0cy5zdHJpY3ROdWxsSGFuZGxpbmcgOiBkZWZhdWx0cy5zdHJpY3ROdWxsSGFuZGxpbmdcbiAgICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBvcHRzKSB7XG4gICAgdmFyIG9iaiA9IG9iamVjdDtcbiAgICB2YXIgb3B0aW9ucyA9IG5vcm1hbGl6ZVN0cmluZ2lmeU9wdGlvbnMob3B0cyk7XG5cbiAgICB2YXIgb2JqS2V5cztcbiAgICB2YXIgZmlsdGVyO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmZpbHRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBmaWx0ZXIgPSBvcHRpb25zLmZpbHRlcjtcbiAgICAgICAgb2JqID0gZmlsdGVyKCcnLCBvYmopO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheShvcHRpb25zLmZpbHRlcikpIHtcbiAgICAgICAgZmlsdGVyID0gb3B0aW9ucy5maWx0ZXI7XG4gICAgICAgIG9iaktleXMgPSBmaWx0ZXI7XG4gICAgfVxuXG4gICAgdmFyIGtleXMgPSBbXTtcblxuICAgIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JyB8fCBvYmogPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIHZhciBhcnJheUZvcm1hdDtcbiAgICBpZiAob3B0cyAmJiBvcHRzLmFycmF5Rm9ybWF0IGluIGFycmF5UHJlZml4R2VuZXJhdG9ycykge1xuICAgICAgICBhcnJheUZvcm1hdCA9IG9wdHMuYXJyYXlGb3JtYXQ7XG4gICAgfSBlbHNlIGlmIChvcHRzICYmICdpbmRpY2VzJyBpbiBvcHRzKSB7XG4gICAgICAgIGFycmF5Rm9ybWF0ID0gb3B0cy5pbmRpY2VzID8gJ2luZGljZXMnIDogJ3JlcGVhdCc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXJyYXlGb3JtYXQgPSAnaW5kaWNlcyc7XG4gICAgfVxuXG4gICAgdmFyIGdlbmVyYXRlQXJyYXlQcmVmaXggPSBhcnJheVByZWZpeEdlbmVyYXRvcnNbYXJyYXlGb3JtYXRdO1xuXG4gICAgaWYgKCFvYmpLZXlzKSB7XG4gICAgICAgIG9iaktleXMgPSBPYmplY3Qua2V5cyhvYmopO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnNvcnQpIHtcbiAgICAgICAgb2JqS2V5cy5zb3J0KG9wdGlvbnMuc29ydCk7XG4gICAgfVxuXG4gICAgdmFyIHNpZGVDaGFubmVsID0gZ2V0U2lkZUNoYW5uZWwoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iaktleXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGtleSA9IG9iaktleXNbaV07XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc2tpcE51bGxzICYmIG9ialtrZXldID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBwdXNoVG9BcnJheShrZXlzLCBzdHJpbmdpZnkoXG4gICAgICAgICAgICBvYmpba2V5XSxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIGdlbmVyYXRlQXJyYXlQcmVmaXgsXG4gICAgICAgICAgICBvcHRpb25zLnN0cmljdE51bGxIYW5kbGluZyxcbiAgICAgICAgICAgIG9wdGlvbnMuc2tpcE51bGxzLFxuICAgICAgICAgICAgb3B0aW9ucy5lbmNvZGUgPyBvcHRpb25zLmVuY29kZXIgOiBudWxsLFxuICAgICAgICAgICAgb3B0aW9ucy5maWx0ZXIsXG4gICAgICAgICAgICBvcHRpb25zLnNvcnQsXG4gICAgICAgICAgICBvcHRpb25zLmFsbG93RG90cyxcbiAgICAgICAgICAgIG9wdGlvbnMuc2VyaWFsaXplRGF0ZSxcbiAgICAgICAgICAgIG9wdGlvbnMuZm9ybWF0LFxuICAgICAgICAgICAgb3B0aW9ucy5mb3JtYXR0ZXIsXG4gICAgICAgICAgICBvcHRpb25zLmVuY29kZVZhbHVlc09ubHksXG4gICAgICAgICAgICBvcHRpb25zLmNoYXJzZXQsXG4gICAgICAgICAgICBzaWRlQ2hhbm5lbFxuICAgICAgICApKTtcbiAgICB9XG5cbiAgICB2YXIgam9pbmVkID0ga2V5cy5qb2luKG9wdGlvbnMuZGVsaW1pdGVyKTtcbiAgICB2YXIgcHJlZml4ID0gb3B0aW9ucy5hZGRRdWVyeVByZWZpeCA9PT0gdHJ1ZSA/ICc/JyA6ICcnO1xuXG4gICAgaWYgKG9wdGlvbnMuY2hhcnNldFNlbnRpbmVsKSB7XG4gICAgICAgIGlmIChvcHRpb25zLmNoYXJzZXQgPT09ICdpc28tODg1OS0xJykge1xuICAgICAgICAgICAgLy8gZW5jb2RlVVJJQ29tcG9uZW50KCcmIzEwMDAzOycpLCB0aGUgXCJudW1lcmljIGVudGl0eVwiIHJlcHJlc2VudGF0aW9uIG9mIGEgY2hlY2ttYXJrXG4gICAgICAgICAgICBwcmVmaXggKz0gJ3V0Zjg9JTI2JTIzMTAwMDMlM0ImJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGVuY29kZVVSSUNvbXBvbmVudCgn4pyTJylcbiAgICAgICAgICAgIHByZWZpeCArPSAndXRmOD0lRTIlOUMlOTMmJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBqb2luZWQubGVuZ3RoID4gMCA/IHByZWZpeCArIGpvaW5lZCA6ICcnO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGZvcm1hdHMgPSByZXF1aXJlKCcuL2Zvcm1hdHMnKTtcblxudmFyIGhhcyA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG5cbnZhciBoZXhUYWJsZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFycmF5ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICAgICAgICBhcnJheS5wdXNoKCclJyArICgoaSA8IDE2ID8gJzAnIDogJycpICsgaS50b1N0cmluZygxNikpLnRvVXBwZXJDYXNlKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBhcnJheTtcbn0oKSk7XG5cbnZhciBjb21wYWN0UXVldWUgPSBmdW5jdGlvbiBjb21wYWN0UXVldWUocXVldWUpIHtcbiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMSkge1xuICAgICAgICB2YXIgaXRlbSA9IHF1ZXVlLnBvcCgpO1xuICAgICAgICB2YXIgb2JqID0gaXRlbS5vYmpbaXRlbS5wcm9wXTtcblxuICAgICAgICBpZiAoaXNBcnJheShvYmopKSB7XG4gICAgICAgICAgICB2YXIgY29tcGFjdGVkID0gW107XG5cbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgb2JqLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmpbal0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBhY3RlZC5wdXNoKG9ialtqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpdGVtLm9ialtpdGVtLnByb3BdID0gY29tcGFjdGVkO1xuICAgICAgICB9XG4gICAgfVxufTtcblxudmFyIGFycmF5VG9PYmplY3QgPSBmdW5jdGlvbiBhcnJheVRvT2JqZWN0KHNvdXJjZSwgb3B0aW9ucykge1xuICAgIHZhciBvYmogPSBvcHRpb25zICYmIG9wdGlvbnMucGxhaW5PYmplY3RzID8gT2JqZWN0LmNyZWF0ZShudWxsKSA6IHt9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc291cmNlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlW2ldICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgb2JqW2ldID0gc291cmNlW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iajtcbn07XG5cbnZhciBtZXJnZSA9IGZ1bmN0aW9uIG1lcmdlKHRhcmdldCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgLyogZXNsaW50IG5vLXBhcmFtLXJlYXNzaWduOiAwICovXG4gICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHNvdXJjZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgaWYgKGlzQXJyYXkodGFyZ2V0KSkge1xuICAgICAgICAgICAgdGFyZ2V0LnB1c2goc291cmNlKTtcbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXQgJiYgdHlwZW9mIHRhcmdldCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICgob3B0aW9ucyAmJiAob3B0aW9ucy5wbGFpbk9iamVjdHMgfHwgb3B0aW9ucy5hbGxvd1Byb3RvdHlwZXMpKSB8fCAhaGFzLmNhbGwoT2JqZWN0LnByb3RvdHlwZSwgc291cmNlKSkge1xuICAgICAgICAgICAgICAgIHRhcmdldFtzb3VyY2VdID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbdGFyZ2V0LCBzb3VyY2VdO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9XG5cbiAgICBpZiAoIXRhcmdldCB8fCB0eXBlb2YgdGFyZ2V0ICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gW3RhcmdldF0uY29uY2F0KHNvdXJjZSk7XG4gICAgfVxuXG4gICAgdmFyIG1lcmdlVGFyZ2V0ID0gdGFyZ2V0O1xuICAgIGlmIChpc0FycmF5KHRhcmdldCkgJiYgIWlzQXJyYXkoc291cmNlKSkge1xuICAgICAgICBtZXJnZVRhcmdldCA9IGFycmF5VG9PYmplY3QodGFyZ2V0LCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBcnJheSh0YXJnZXQpICYmIGlzQXJyYXkoc291cmNlKSkge1xuICAgICAgICBzb3VyY2UuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgICAgICAgICAgaWYgKGhhcy5jYWxsKHRhcmdldCwgaSkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0SXRlbSA9IHRhcmdldFtpXTtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SXRlbSAmJiB0eXBlb2YgdGFyZ2V0SXRlbSA9PT0gJ29iamVjdCcgJiYgaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W2ldID0gbWVyZ2UodGFyZ2V0SXRlbSwgaXRlbSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnB1c2goaXRlbSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRbaV0gPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMoc291cmNlKS5yZWR1Y2UoZnVuY3Rpb24gKGFjYywga2V5KSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHNvdXJjZVtrZXldO1xuXG4gICAgICAgIGlmIChoYXMuY2FsbChhY2MsIGtleSkpIHtcbiAgICAgICAgICAgIGFjY1trZXldID0gbWVyZ2UoYWNjW2tleV0sIHZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFjY1trZXldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCBtZXJnZVRhcmdldCk7XG59O1xuXG52YXIgYXNzaWduID0gZnVuY3Rpb24gYXNzaWduU2luZ2xlU291cmNlKHRhcmdldCwgc291cmNlKSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHNvdXJjZSkucmVkdWNlKGZ1bmN0aW9uIChhY2MsIGtleSkge1xuICAgICAgICBhY2Nba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgIH0sIHRhcmdldCk7XG59O1xuXG52YXIgZGVjb2RlID0gZnVuY3Rpb24gKHN0ciwgZGVjb2RlciwgY2hhcnNldCkge1xuICAgIHZhciBzdHJXaXRob3V0UGx1cyA9IHN0ci5yZXBsYWNlKC9cXCsvZywgJyAnKTtcbiAgICBpZiAoY2hhcnNldCA9PT0gJ2lzby04ODU5LTEnKSB7XG4gICAgICAgIC8vIHVuZXNjYXBlIG5ldmVyIHRocm93cywgbm8gdHJ5Li4uY2F0Y2ggbmVlZGVkOlxuICAgICAgICByZXR1cm4gc3RyV2l0aG91dFBsdXMucmVwbGFjZSgvJVswLTlhLWZdezJ9L2dpLCB1bmVzY2FwZSk7XG4gICAgfVxuICAgIC8vIHV0Zi04XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHJXaXRob3V0UGx1cyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gc3RyV2l0aG91dFBsdXM7XG4gICAgfVxufTtcblxudmFyIGVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShzdHIsIGRlZmF1bHRFbmNvZGVyLCBjaGFyc2V0LCBraW5kLCBmb3JtYXQpIHtcbiAgICAvLyBUaGlzIGNvZGUgd2FzIG9yaWdpbmFsbHkgd3JpdHRlbiBieSBCcmlhbiBXaGl0ZSAobXNjZGV4KSBmb3IgdGhlIGlvLmpzIGNvcmUgcXVlcnlzdHJpbmcgbGlicmFyeS5cbiAgICAvLyBJdCBoYXMgYmVlbiBhZGFwdGVkIGhlcmUgZm9yIHN0cmljdGVyIGFkaGVyZW5jZSB0byBSRkMgMzk4NlxuICAgIGlmIChzdHIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuXG4gICAgdmFyIHN0cmluZyA9IHN0cjtcbiAgICBpZiAodHlwZW9mIHN0ciA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgc3RyaW5nID0gU3ltYm9sLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHN0cik7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgICAgICBzdHJpbmcgPSBTdHJpbmcoc3RyKTtcbiAgICB9XG5cbiAgICBpZiAoY2hhcnNldCA9PT0gJ2lzby04ODU5LTEnKSB7XG4gICAgICAgIHJldHVybiBlc2NhcGUoc3RyaW5nKS5yZXBsYWNlKC8ldVswLTlhLWZdezR9L2dpLCBmdW5jdGlvbiAoJDApIHtcbiAgICAgICAgICAgIHJldHVybiAnJTI2JTIzJyArIHBhcnNlSW50KCQwLnNsaWNlKDIpLCAxNikgKyAnJTNCJztcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIG91dCA9ICcnO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBjID0gc3RyaW5nLmNoYXJDb2RlQXQoaSk7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgYyA9PT0gMHgyRCAvLyAtXG4gICAgICAgICAgICB8fCBjID09PSAweDJFIC8vIC5cbiAgICAgICAgICAgIHx8IGMgPT09IDB4NUYgLy8gX1xuICAgICAgICAgICAgfHwgYyA9PT0gMHg3RSAvLyB+XG4gICAgICAgICAgICB8fCAoYyA+PSAweDMwICYmIGMgPD0gMHgzOSkgLy8gMC05XG4gICAgICAgICAgICB8fCAoYyA+PSAweDQxICYmIGMgPD0gMHg1QSkgLy8gYS16XG4gICAgICAgICAgICB8fCAoYyA+PSAweDYxICYmIGMgPD0gMHg3QSkgLy8gQS1aXG4gICAgICAgICAgICB8fCAoZm9ybWF0ID09PSBmb3JtYXRzLlJGQzE3MzggJiYgKGMgPT09IDB4MjggfHwgYyA9PT0gMHgyOSkpIC8vICggKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIG91dCArPSBzdHJpbmcuY2hhckF0KGkpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODApIHtcbiAgICAgICAgICAgIG91dCA9IG91dCArIGhleFRhYmxlW2NdO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYyA8IDB4ODAwKSB7XG4gICAgICAgICAgICBvdXQgPSBvdXQgKyAoaGV4VGFibGVbMHhDMCB8IChjID4+IDYpXSArIGhleFRhYmxlWzB4ODAgfCAoYyAmIDB4M0YpXSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjIDwgMHhEODAwIHx8IGMgPj0gMHhFMDAwKSB7XG4gICAgICAgICAgICBvdXQgPSBvdXQgKyAoaGV4VGFibGVbMHhFMCB8IChjID4+IDEyKV0gKyBoZXhUYWJsZVsweDgwIHwgKChjID4+IDYpICYgMHgzRildICsgaGV4VGFibGVbMHg4MCB8IChjICYgMHgzRildKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaSArPSAxO1xuICAgICAgICBjID0gMHgxMDAwMCArICgoKGMgJiAweDNGRikgPDwgMTApIHwgKHN0cmluZy5jaGFyQ29kZUF0KGkpICYgMHgzRkYpKTtcbiAgICAgICAgb3V0ICs9IGhleFRhYmxlWzB4RjAgfCAoYyA+PiAxOCldXG4gICAgICAgICAgICArIGhleFRhYmxlWzB4ODAgfCAoKGMgPj4gMTIpICYgMHgzRildXG4gICAgICAgICAgICArIGhleFRhYmxlWzB4ODAgfCAoKGMgPj4gNikgJiAweDNGKV1cbiAgICAgICAgICAgICsgaGV4VGFibGVbMHg4MCB8IChjICYgMHgzRildO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG52YXIgY29tcGFjdCA9IGZ1bmN0aW9uIGNvbXBhY3QodmFsdWUpIHtcbiAgICB2YXIgcXVldWUgPSBbeyBvYmo6IHsgbzogdmFsdWUgfSwgcHJvcDogJ28nIH1dO1xuICAgIHZhciByZWZzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBpdGVtID0gcXVldWVbaV07XG4gICAgICAgIHZhciBvYmogPSBpdGVtLm9ialtpdGVtLnByb3BdO1xuXG4gICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBrZXlzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0ga2V5c1tqXTtcbiAgICAgICAgICAgIHZhciB2YWwgPSBvYmpba2V5XTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGwgJiYgcmVmcy5pbmRleE9mKHZhbCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcXVldWUucHVzaCh7IG9iajogb2JqLCBwcm9wOiBrZXkgfSk7XG4gICAgICAgICAgICAgICAgcmVmcy5wdXNoKHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb21wYWN0UXVldWUocXVldWUpO1xuXG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxudmFyIGlzUmVnRXhwID0gZnVuY3Rpb24gaXNSZWdFeHAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBSZWdFeHBdJztcbn07XG5cbnZhciBpc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyKG9iaikge1xuICAgIGlmICghb2JqIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gISEob2JqLmNvbnN0cnVjdG9yICYmIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlciAmJiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKSk7XG59O1xuXG52YXIgY29tYmluZSA9IGZ1bmN0aW9uIGNvbWJpbmUoYSwgYikge1xuICAgIHJldHVybiBbXS5jb25jYXQoYSwgYik7XG59O1xuXG52YXIgbWF5YmVNYXAgPSBmdW5jdGlvbiBtYXliZU1hcCh2YWwsIGZuKSB7XG4gICAgaWYgKGlzQXJyYXkodmFsKSkge1xuICAgICAgICB2YXIgbWFwcGVkID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBtYXBwZWQucHVzaChmbih2YWxbaV0pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWFwcGVkO1xuICAgIH1cbiAgICByZXR1cm4gZm4odmFsKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGFycmF5VG9PYmplY3Q6IGFycmF5VG9PYmplY3QsXG4gICAgYXNzaWduOiBhc3NpZ24sXG4gICAgY29tYmluZTogY29tYmluZSxcbiAgICBjb21wYWN0OiBjb21wYWN0LFxuICAgIGRlY29kZTogZGVjb2RlLFxuICAgIGVuY29kZTogZW5jb2RlLFxuICAgIGlzQnVmZmVyOiBpc0J1ZmZlcixcbiAgICBpc1JlZ0V4cDogaXNSZWdFeHAsXG4gICAgbWF5YmVNYXA6IG1heWJlTWFwLFxuICAgIG1lcmdlOiBtZXJnZVxufTtcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbi8vIElmIG9iai5oYXNPd25Qcm9wZXJ0eSBoYXMgYmVlbiBvdmVycmlkZGVuLCB0aGVuIGNhbGxpbmdcbi8vIG9iai5oYXNPd25Qcm9wZXJ0eShwcm9wKSB3aWxsIGJyZWFrLlxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vam95ZW50L25vZGUvaXNzdWVzLzE3MDdcbmZ1bmN0aW9uIGhhc093blByb3BlcnR5KG9iaiwgcHJvcCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ocXMsIHNlcCwgZXEsIG9wdGlvbnMpIHtcbiAgc2VwID0gc2VwIHx8ICcmJztcbiAgZXEgPSBlcSB8fCAnPSc7XG4gIHZhciBvYmogPSB7fTtcblxuICBpZiAodHlwZW9mIHFzICE9PSAnc3RyaW5nJyB8fCBxcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gb2JqO1xuICB9XG5cbiAgdmFyIHJlZ2V4cCA9IC9cXCsvZztcbiAgcXMgPSBxcy5zcGxpdChzZXApO1xuXG4gIHZhciBtYXhLZXlzID0gMTAwMDtcbiAgaWYgKG9wdGlvbnMgJiYgdHlwZW9mIG9wdGlvbnMubWF4S2V5cyA9PT0gJ251bWJlcicpIHtcbiAgICBtYXhLZXlzID0gb3B0aW9ucy5tYXhLZXlzO1xuICB9XG5cbiAgdmFyIGxlbiA9IHFzLmxlbmd0aDtcbiAgLy8gbWF4S2V5cyA8PSAwIG1lYW5zIHRoYXQgd2Ugc2hvdWxkIG5vdCBsaW1pdCBrZXlzIGNvdW50XG4gIGlmIChtYXhLZXlzID4gMCAmJiBsZW4gPiBtYXhLZXlzKSB7XG4gICAgbGVuID0gbWF4S2V5cztcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICB2YXIgeCA9IHFzW2ldLnJlcGxhY2UocmVnZXhwLCAnJTIwJyksXG4gICAgICAgIGlkeCA9IHguaW5kZXhPZihlcSksXG4gICAgICAgIGtzdHIsIHZzdHIsIGssIHY7XG5cbiAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgIGtzdHIgPSB4LnN1YnN0cigwLCBpZHgpO1xuICAgICAgdnN0ciA9IHguc3Vic3RyKGlkeCArIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICBrc3RyID0geDtcbiAgICAgIHZzdHIgPSAnJztcbiAgICB9XG5cbiAgICBrID0gZGVjb2RlVVJJQ29tcG9uZW50KGtzdHIpO1xuICAgIHYgPSBkZWNvZGVVUklDb21wb25lbnQodnN0cik7XG5cbiAgICBpZiAoIWhhc093blByb3BlcnR5KG9iaiwgaykpIHtcbiAgICAgIG9ialtrXSA9IHY7XG4gICAgfSBlbHNlIGlmIChpc0FycmF5KG9ialtrXSkpIHtcbiAgICAgIG9ialtrXS5wdXNoKHYpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba10gPSBbb2JqW2tdLCB2XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gb2JqO1xufTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uICh4cykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHhzKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3RyaW5naWZ5UHJpbWl0aXZlID0gZnVuY3Rpb24odikge1xuICBzd2l0Y2ggKHR5cGVvZiB2KSB7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiB2O1xuXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gdiA/ICd0cnVlJyA6ICdmYWxzZSc7XG5cbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIGlzRmluaXRlKHYpID8gdiA6ICcnO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAnJztcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvYmosIHNlcCwgZXEsIG5hbWUpIHtcbiAgc2VwID0gc2VwIHx8ICcmJztcbiAgZXEgPSBlcSB8fCAnPSc7XG4gIGlmIChvYmogPT09IG51bGwpIHtcbiAgICBvYmogPSB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbWFwKG9iamVjdEtleXMob2JqKSwgZnVuY3Rpb24oaykge1xuICAgICAgdmFyIGtzID0gZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShrKSkgKyBlcTtcbiAgICAgIGlmIChpc0FycmF5KG9ialtrXSkpIHtcbiAgICAgICAgcmV0dXJuIG1hcChvYmpba10sIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICByZXR1cm4ga3MgKyBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKHYpKTtcbiAgICAgICAgfSkuam9pbihzZXApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGtzICsgZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShvYmpba10pKTtcbiAgICAgIH1cbiAgICB9KS5qb2luKHNlcCk7XG5cbiAgfVxuXG4gIGlmICghbmFtZSkgcmV0dXJuICcnO1xuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShuYW1lKSkgKyBlcSArXG4gICAgICAgICBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKG9iaikpO1xufTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uICh4cykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHhzKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG5cbmZ1bmN0aW9uIG1hcCAoeHMsIGYpIHtcbiAgaWYgKHhzLm1hcCkgcmV0dXJuIHhzLm1hcChmKTtcbiAgdmFyIHJlcyA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgcmVzLnB1c2goZih4c1tpXSwgaSkpO1xuICB9XG4gIHJldHVybiByZXM7XG59XG5cbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgZnVuY3Rpb24gKG9iaikge1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkgcmVzLnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5kZWNvZGUgPSBleHBvcnRzLnBhcnNlID0gcmVxdWlyZSgnLi9kZWNvZGUnKTtcbmV4cG9ydHMuZW5jb2RlID0gZXhwb3J0cy5zdHJpbmdpZnkgPSByZXF1aXJlKCcuL2VuY29kZScpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgR2V0SW50cmluc2ljID0gcmVxdWlyZSgnZ2V0LWludHJpbnNpYycpO1xudmFyIGNhbGxCb3VuZCA9IHJlcXVpcmUoJ2NhbGwtYmluZC9jYWxsQm91bmQnKTtcbnZhciBpbnNwZWN0ID0gcmVxdWlyZSgnb2JqZWN0LWluc3BlY3QnKTtcblxudmFyICRUeXBlRXJyb3IgPSBHZXRJbnRyaW5zaWMoJyVUeXBlRXJyb3IlJyk7XG52YXIgJFdlYWtNYXAgPSBHZXRJbnRyaW5zaWMoJyVXZWFrTWFwJScsIHRydWUpO1xudmFyICRNYXAgPSBHZXRJbnRyaW5zaWMoJyVNYXAlJywgdHJ1ZSk7XG5cbnZhciAkd2Vha01hcEdldCA9IGNhbGxCb3VuZCgnV2Vha01hcC5wcm90b3R5cGUuZ2V0JywgdHJ1ZSk7XG52YXIgJHdlYWtNYXBTZXQgPSBjYWxsQm91bmQoJ1dlYWtNYXAucHJvdG90eXBlLnNldCcsIHRydWUpO1xudmFyICR3ZWFrTWFwSGFzID0gY2FsbEJvdW5kKCdXZWFrTWFwLnByb3RvdHlwZS5oYXMnLCB0cnVlKTtcbnZhciAkbWFwR2V0ID0gY2FsbEJvdW5kKCdNYXAucHJvdG90eXBlLmdldCcsIHRydWUpO1xudmFyICRtYXBTZXQgPSBjYWxsQm91bmQoJ01hcC5wcm90b3R5cGUuc2V0JywgdHJ1ZSk7XG52YXIgJG1hcEhhcyA9IGNhbGxCb3VuZCgnTWFwLnByb3RvdHlwZS5oYXMnLCB0cnVlKTtcblxuLypcbiAqIFRoaXMgZnVuY3Rpb24gdHJhdmVyc2VzIHRoZSBsaXN0IHJldHVybmluZyB0aGUgbm9kZSBjb3JyZXNwb25kaW5nIHRvIHRoZVxuICogZ2l2ZW4ga2V5LlxuICpcbiAqIFRoYXQgbm9kZSBpcyBhbHNvIG1vdmVkIHRvIHRoZSBoZWFkIG9mIHRoZSBsaXN0LCBzbyB0aGF0IGlmIGl0J3MgYWNjZXNzZWRcbiAqIGFnYWluIHdlIGRvbid0IG5lZWQgdG8gdHJhdmVyc2UgdGhlIHdob2xlIGxpc3QuIEJ5IGRvaW5nIHNvLCBhbGwgdGhlIHJlY2VudGx5XG4gKiB1c2VkIG5vZGVzIGNhbiBiZSBhY2Nlc3NlZCByZWxhdGl2ZWx5IHF1aWNrbHkuXG4gKi9cbnZhciBsaXN0R2V0Tm9kZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXkpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuXHRmb3IgKHZhciBwcmV2ID0gbGlzdCwgY3VycjsgKGN1cnIgPSBwcmV2Lm5leHQpICE9PSBudWxsOyBwcmV2ID0gY3Vycikge1xuXHRcdGlmIChjdXJyLmtleSA9PT0ga2V5KSB7XG5cdFx0XHRwcmV2Lm5leHQgPSBjdXJyLm5leHQ7XG5cdFx0XHRjdXJyLm5leHQgPSBsaXN0Lm5leHQ7XG5cdFx0XHRsaXN0Lm5leHQgPSBjdXJyOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG5cdFx0XHRyZXR1cm4gY3Vycjtcblx0XHR9XG5cdH1cbn07XG5cbnZhciBsaXN0R2V0ID0gZnVuY3Rpb24gKG9iamVjdHMsIGtleSkge1xuXHR2YXIgbm9kZSA9IGxpc3RHZXROb2RlKG9iamVjdHMsIGtleSk7XG5cdHJldHVybiBub2RlICYmIG5vZGUudmFsdWU7XG59O1xudmFyIGxpc3RTZXQgPSBmdW5jdGlvbiAob2JqZWN0cywga2V5LCB2YWx1ZSkge1xuXHR2YXIgbm9kZSA9IGxpc3RHZXROb2RlKG9iamVjdHMsIGtleSk7XG5cdGlmIChub2RlKSB7XG5cdFx0bm9kZS52YWx1ZSA9IHZhbHVlO1xuXHR9IGVsc2Uge1xuXHRcdC8vIFByZXBlbmQgdGhlIG5ldyBub2RlIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpc3Rcblx0XHRvYmplY3RzLm5leHQgPSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cblx0XHRcdGtleToga2V5LFxuXHRcdFx0bmV4dDogb2JqZWN0cy5uZXh0LFxuXHRcdFx0dmFsdWU6IHZhbHVlXG5cdFx0fTtcblx0fVxufTtcbnZhciBsaXN0SGFzID0gZnVuY3Rpb24gKG9iamVjdHMsIGtleSkge1xuXHRyZXR1cm4gISFsaXN0R2V0Tm9kZShvYmplY3RzLCBrZXkpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRTaWRlQ2hhbm5lbCgpIHtcblx0dmFyICR3bTtcblx0dmFyICRtO1xuXHR2YXIgJG87XG5cdHZhciBjaGFubmVsID0ge1xuXHRcdGFzc2VydDogZnVuY3Rpb24gKGtleSkge1xuXHRcdFx0aWYgKCFjaGFubmVsLmhhcyhrZXkpKSB7XG5cdFx0XHRcdHRocm93IG5ldyAkVHlwZUVycm9yKCdTaWRlIGNoYW5uZWwgZG9lcyBub3QgY29udGFpbiAnICsgaW5zcGVjdChrZXkpKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGdldDogZnVuY3Rpb24gKGtleSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGNvbnNpc3RlbnQtcmV0dXJuXG5cdFx0XHRpZiAoJFdlYWtNYXAgJiYga2V5ICYmICh0eXBlb2Yga2V5ID09PSAnb2JqZWN0JyB8fCB0eXBlb2Yga2V5ID09PSAnZnVuY3Rpb24nKSkge1xuXHRcdFx0XHRpZiAoJHdtKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR3ZWFrTWFwR2V0KCR3bSwga2V5KTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICgkTWFwKSB7XG5cdFx0XHRcdGlmICgkbSkge1xuXHRcdFx0XHRcdHJldHVybiAkbWFwR2V0KCRtLCBrZXkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoJG8pIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1sb25lbHktaWZcblx0XHRcdFx0XHRyZXR1cm4gbGlzdEdldCgkbywga2V5KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0aGFzOiBmdW5jdGlvbiAoa2V5KSB7XG5cdFx0XHRpZiAoJFdlYWtNYXAgJiYga2V5ICYmICh0eXBlb2Yga2V5ID09PSAnb2JqZWN0JyB8fCB0eXBlb2Yga2V5ID09PSAnZnVuY3Rpb24nKSkge1xuXHRcdFx0XHRpZiAoJHdtKSB7XG5cdFx0XHRcdFx0cmV0dXJuICR3ZWFrTWFwSGFzKCR3bSwga2V5KTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICgkTWFwKSB7XG5cdFx0XHRcdGlmICgkbSkge1xuXHRcdFx0XHRcdHJldHVybiAkbWFwSGFzKCRtLCBrZXkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoJG8pIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1sb25lbHktaWZcblx0XHRcdFx0XHRyZXR1cm4gbGlzdEhhcygkbywga2V5KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0sXG5cdFx0c2V0OiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuXHRcdFx0aWYgKCRXZWFrTWFwICYmIGtleSAmJiAodHlwZW9mIGtleSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGtleSA9PT0gJ2Z1bmN0aW9uJykpIHtcblx0XHRcdFx0aWYgKCEkd20pIHtcblx0XHRcdFx0XHQkd20gPSBuZXcgJFdlYWtNYXAoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQkd2Vha01hcFNldCgkd20sIGtleSwgdmFsdWUpO1xuXHRcdFx0fSBlbHNlIGlmICgkTWFwKSB7XG5cdFx0XHRcdGlmICghJG0pIHtcblx0XHRcdFx0XHQkbSA9IG5ldyAkTWFwKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0JG1hcFNldCgkbSwga2V5LCB2YWx1ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoISRvKSB7XG5cdFx0XHRcdFx0Lypcblx0XHRcdFx0XHQgKiBJbml0aWFsaXplIHRoZSBsaW5rZWQgbGlzdCBhcyBhbiBlbXB0eSBub2RlLCBzbyB0aGF0IHdlIGRvbid0IGhhdmVcblx0XHRcdFx0XHQgKiB0byBzcGVjaWFsLWNhc2UgaGFuZGxpbmcgb2YgdGhlIGZpcnN0IG5vZGU6IHdlIGNhbiBhbHdheXMgcmVmZXIgdG9cblx0XHRcdFx0XHQgKiBpdCBhcyAocHJldmlvdXMgbm9kZSkubmV4dCwgaW5zdGVhZCBvZiBzb21ldGhpbmcgbGlrZSAobGlzdCkuaGVhZFxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdCRvID0geyBrZXk6IHt9LCBuZXh0OiBudWxsIH07XG5cdFx0XHRcdH1cblx0XHRcdFx0bGlzdFNldCgkbywga2V5LCB2YWx1ZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXHRyZXR1cm4gY2hhbm5lbDtcbn07XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcHVueWNvZGUgPSByZXF1aXJlKCdwdW55Y29kZScpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuZXhwb3J0cy5wYXJzZSA9IHVybFBhcnNlO1xuZXhwb3J0cy5yZXNvbHZlID0gdXJsUmVzb2x2ZTtcbmV4cG9ydHMucmVzb2x2ZU9iamVjdCA9IHVybFJlc29sdmVPYmplY3Q7XG5leHBvcnRzLmZvcm1hdCA9IHVybEZvcm1hdDtcblxuZXhwb3J0cy5VcmwgPSBVcmw7XG5cbmZ1bmN0aW9uIFVybCgpIHtcbiAgdGhpcy5wcm90b2NvbCA9IG51bGw7XG4gIHRoaXMuc2xhc2hlcyA9IG51bGw7XG4gIHRoaXMuYXV0aCA9IG51bGw7XG4gIHRoaXMuaG9zdCA9IG51bGw7XG4gIHRoaXMucG9ydCA9IG51bGw7XG4gIHRoaXMuaG9zdG5hbWUgPSBudWxsO1xuICB0aGlzLmhhc2ggPSBudWxsO1xuICB0aGlzLnNlYXJjaCA9IG51bGw7XG4gIHRoaXMucXVlcnkgPSBudWxsO1xuICB0aGlzLnBhdGhuYW1lID0gbnVsbDtcbiAgdGhpcy5wYXRoID0gbnVsbDtcbiAgdGhpcy5ocmVmID0gbnVsbDtcbn1cblxuLy8gUmVmZXJlbmNlOiBSRkMgMzk4NiwgUkZDIDE4MDgsIFJGQyAyMzk2XG5cbi8vIGRlZmluZSB0aGVzZSBoZXJlIHNvIGF0IGxlYXN0IHRoZXkgb25seSBoYXZlIHRvIGJlXG4vLyBjb21waWxlZCBvbmNlIG9uIHRoZSBmaXJzdCBtb2R1bGUgbG9hZC5cbnZhciBwcm90b2NvbFBhdHRlcm4gPSAvXihbYS16MC05ListXSs6KS9pLFxuICAgIHBvcnRQYXR0ZXJuID0gLzpbMC05XSokLyxcblxuICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgYSBzaW1wbGUgcGF0aCBVUkxcbiAgICBzaW1wbGVQYXRoUGF0dGVybiA9IC9eKFxcL1xcLz8oPyFcXC8pW15cXD9cXHNdKikoXFw/W15cXHNdKik/JC8sXG5cbiAgICAvLyBSRkMgMjM5NjogY2hhcmFjdGVycyByZXNlcnZlZCBmb3IgZGVsaW1pdGluZyBVUkxzLlxuICAgIC8vIFdlIGFjdHVhbGx5IGp1c3QgYXV0by1lc2NhcGUgdGhlc2UuXG4gICAgZGVsaW1zID0gWyc8JywgJz4nLCAnXCInLCAnYCcsICcgJywgJ1xccicsICdcXG4nLCAnXFx0J10sXG5cbiAgICAvLyBSRkMgMjM5NjogY2hhcmFjdGVycyBub3QgYWxsb3dlZCBmb3IgdmFyaW91cyByZWFzb25zLlxuICAgIHVud2lzZSA9IFsneycsICd9JywgJ3wnLCAnXFxcXCcsICdeJywgJ2AnXS5jb25jYXQoZGVsaW1zKSxcblxuICAgIC8vIEFsbG93ZWQgYnkgUkZDcywgYnV0IGNhdXNlIG9mIFhTUyBhdHRhY2tzLiAgQWx3YXlzIGVzY2FwZSB0aGVzZS5cbiAgICBhdXRvRXNjYXBlID0gWydcXCcnXS5jb25jYXQodW53aXNlKSxcbiAgICAvLyBDaGFyYWN0ZXJzIHRoYXQgYXJlIG5ldmVyIGV2ZXIgYWxsb3dlZCBpbiBhIGhvc3RuYW1lLlxuICAgIC8vIE5vdGUgdGhhdCBhbnkgaW52YWxpZCBjaGFycyBhcmUgYWxzbyBoYW5kbGVkLCBidXQgdGhlc2VcbiAgICAvLyBhcmUgdGhlIG9uZXMgdGhhdCBhcmUgKmV4cGVjdGVkKiB0byBiZSBzZWVuLCBzbyB3ZSBmYXN0LXBhdGhcbiAgICAvLyB0aGVtLlxuICAgIG5vbkhvc3RDaGFycyA9IFsnJScsICcvJywgJz8nLCAnOycsICcjJ10uY29uY2F0KGF1dG9Fc2NhcGUpLFxuICAgIGhvc3RFbmRpbmdDaGFycyA9IFsnLycsICc/JywgJyMnXSxcbiAgICBob3N0bmFtZU1heExlbiA9IDI1NSxcbiAgICBob3N0bmFtZVBhcnRQYXR0ZXJuID0gL15bK2EtejAtOUEtWl8tXXswLDYzfSQvLFxuICAgIGhvc3RuYW1lUGFydFN0YXJ0ID0gL14oWythLXowLTlBLVpfLV17MCw2M30pKC4qKSQvLFxuICAgIC8vIHByb3RvY29scyB0aGF0IGNhbiBhbGxvdyBcInVuc2FmZVwiIGFuZCBcInVud2lzZVwiIGNoYXJzLlxuICAgIHVuc2FmZVByb3RvY29sID0ge1xuICAgICAgJ2phdmFzY3JpcHQnOiB0cnVlLFxuICAgICAgJ2phdmFzY3JpcHQ6JzogdHJ1ZVxuICAgIH0sXG4gICAgLy8gcHJvdG9jb2xzIHRoYXQgbmV2ZXIgaGF2ZSBhIGhvc3RuYW1lLlxuICAgIGhvc3RsZXNzUHJvdG9jb2wgPSB7XG4gICAgICAnamF2YXNjcmlwdCc6IHRydWUsXG4gICAgICAnamF2YXNjcmlwdDonOiB0cnVlXG4gICAgfSxcbiAgICAvLyBwcm90b2NvbHMgdGhhdCBhbHdheXMgY29udGFpbiBhIC8vIGJpdC5cbiAgICBzbGFzaGVkUHJvdG9jb2wgPSB7XG4gICAgICAnaHR0cCc6IHRydWUsXG4gICAgICAnaHR0cHMnOiB0cnVlLFxuICAgICAgJ2Z0cCc6IHRydWUsXG4gICAgICAnZ29waGVyJzogdHJ1ZSxcbiAgICAgICdmaWxlJzogdHJ1ZSxcbiAgICAgICdodHRwOic6IHRydWUsXG4gICAgICAnaHR0cHM6JzogdHJ1ZSxcbiAgICAgICdmdHA6JzogdHJ1ZSxcbiAgICAgICdnb3BoZXI6JzogdHJ1ZSxcbiAgICAgICdmaWxlOic6IHRydWVcbiAgICB9LFxuICAgIHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcblxuZnVuY3Rpb24gdXJsUGFyc2UodXJsLCBwYXJzZVF1ZXJ5U3RyaW5nLCBzbGFzaGVzRGVub3RlSG9zdCkge1xuICBpZiAodXJsICYmIHV0aWwuaXNPYmplY3QodXJsKSAmJiB1cmwgaW5zdGFuY2VvZiBVcmwpIHJldHVybiB1cmw7XG5cbiAgdmFyIHUgPSBuZXcgVXJsO1xuICB1LnBhcnNlKHVybCwgcGFyc2VRdWVyeVN0cmluZywgc2xhc2hlc0Rlbm90ZUhvc3QpO1xuICByZXR1cm4gdTtcbn1cblxuVXJsLnByb3RvdHlwZS5wYXJzZSA9IGZ1bmN0aW9uKHVybCwgcGFyc2VRdWVyeVN0cmluZywgc2xhc2hlc0Rlbm90ZUhvc3QpIHtcbiAgaWYgKCF1dGlsLmlzU3RyaW5nKHVybCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUGFyYW1ldGVyICd1cmwnIG11c3QgYmUgYSBzdHJpbmcsIG5vdCBcIiArIHR5cGVvZiB1cmwpO1xuICB9XG5cbiAgLy8gQ29weSBjaHJvbWUsIElFLCBvcGVyYSBiYWNrc2xhc2gtaGFuZGxpbmcgYmVoYXZpb3IuXG4gIC8vIEJhY2sgc2xhc2hlcyBiZWZvcmUgdGhlIHF1ZXJ5IHN0cmluZyBnZXQgY29udmVydGVkIHRvIGZvcndhcmQgc2xhc2hlc1xuICAvLyBTZWU6IGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD0yNTkxNlxuICB2YXIgcXVlcnlJbmRleCA9IHVybC5pbmRleE9mKCc/JyksXG4gICAgICBzcGxpdHRlciA9XG4gICAgICAgICAgKHF1ZXJ5SW5kZXggIT09IC0xICYmIHF1ZXJ5SW5kZXggPCB1cmwuaW5kZXhPZignIycpKSA/ICc/JyA6ICcjJyxcbiAgICAgIHVTcGxpdCA9IHVybC5zcGxpdChzcGxpdHRlciksXG4gICAgICBzbGFzaFJlZ2V4ID0gL1xcXFwvZztcbiAgdVNwbGl0WzBdID0gdVNwbGl0WzBdLnJlcGxhY2Uoc2xhc2hSZWdleCwgJy8nKTtcbiAgdXJsID0gdVNwbGl0LmpvaW4oc3BsaXR0ZXIpO1xuXG4gIHZhciByZXN0ID0gdXJsO1xuXG4gIC8vIHRyaW0gYmVmb3JlIHByb2NlZWRpbmcuXG4gIC8vIFRoaXMgaXMgdG8gc3VwcG9ydCBwYXJzZSBzdHVmZiBsaWtlIFwiICBodHRwOi8vZm9vLmNvbSAgXFxuXCJcbiAgcmVzdCA9IHJlc3QudHJpbSgpO1xuXG4gIGlmICghc2xhc2hlc0Rlbm90ZUhvc3QgJiYgdXJsLnNwbGl0KCcjJykubGVuZ3RoID09PSAxKSB7XG4gICAgLy8gVHJ5IGZhc3QgcGF0aCByZWdleHBcbiAgICB2YXIgc2ltcGxlUGF0aCA9IHNpbXBsZVBhdGhQYXR0ZXJuLmV4ZWMocmVzdCk7XG4gICAgaWYgKHNpbXBsZVBhdGgpIHtcbiAgICAgIHRoaXMucGF0aCA9IHJlc3Q7XG4gICAgICB0aGlzLmhyZWYgPSByZXN0O1xuICAgICAgdGhpcy5wYXRobmFtZSA9IHNpbXBsZVBhdGhbMV07XG4gICAgICBpZiAoc2ltcGxlUGF0aFsyXSkge1xuICAgICAgICB0aGlzLnNlYXJjaCA9IHNpbXBsZVBhdGhbMl07XG4gICAgICAgIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgICAgdGhpcy5xdWVyeSA9IHF1ZXJ5c3RyaW5nLnBhcnNlKHRoaXMuc2VhcmNoLnN1YnN0cigxKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5xdWVyeSA9IHRoaXMuc2VhcmNoLnN1YnN0cigxKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoID0gJyc7XG4gICAgICAgIHRoaXMucXVlcnkgPSB7fTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIHZhciBwcm90byA9IHByb3RvY29sUGF0dGVybi5leGVjKHJlc3QpO1xuICBpZiAocHJvdG8pIHtcbiAgICBwcm90byA9IHByb3RvWzBdO1xuICAgIHZhciBsb3dlclByb3RvID0gcHJvdG8udG9Mb3dlckNhc2UoKTtcbiAgICB0aGlzLnByb3RvY29sID0gbG93ZXJQcm90bztcbiAgICByZXN0ID0gcmVzdC5zdWJzdHIocHJvdG8ubGVuZ3RoKTtcbiAgfVxuXG4gIC8vIGZpZ3VyZSBvdXQgaWYgaXQncyBnb3QgYSBob3N0XG4gIC8vIHVzZXJAc2VydmVyIGlzICphbHdheXMqIGludGVycHJldGVkIGFzIGEgaG9zdG5hbWUsIGFuZCB1cmxcbiAgLy8gcmVzb2x1dGlvbiB3aWxsIHRyZWF0IC8vZm9vL2JhciBhcyBob3N0PWZvbyxwYXRoPWJhciBiZWNhdXNlIHRoYXQnc1xuICAvLyBob3cgdGhlIGJyb3dzZXIgcmVzb2x2ZXMgcmVsYXRpdmUgVVJMcy5cbiAgaWYgKHNsYXNoZXNEZW5vdGVIb3N0IHx8IHByb3RvIHx8IHJlc3QubWF0Y2goL15cXC9cXC9bXkBcXC9dK0BbXkBcXC9dKy8pKSB7XG4gICAgdmFyIHNsYXNoZXMgPSByZXN0LnN1YnN0cigwLCAyKSA9PT0gJy8vJztcbiAgICBpZiAoc2xhc2hlcyAmJiAhKHByb3RvICYmIGhvc3RsZXNzUHJvdG9jb2xbcHJvdG9dKSkge1xuICAgICAgcmVzdCA9IHJlc3Quc3Vic3RyKDIpO1xuICAgICAgdGhpcy5zbGFzaGVzID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIWhvc3RsZXNzUHJvdG9jb2xbcHJvdG9dICYmXG4gICAgICAoc2xhc2hlcyB8fCAocHJvdG8gJiYgIXNsYXNoZWRQcm90b2NvbFtwcm90b10pKSkge1xuXG4gICAgLy8gdGhlcmUncyBhIGhvc3RuYW1lLlxuICAgIC8vIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiAvLCA/LCA7LCBvciAjIGVuZHMgdGhlIGhvc3QuXG4gICAgLy9cbiAgICAvLyBJZiB0aGVyZSBpcyBhbiBAIGluIHRoZSBob3N0bmFtZSwgdGhlbiBub24taG9zdCBjaGFycyAqYXJlKiBhbGxvd2VkXG4gICAgLy8gdG8gdGhlIGxlZnQgb2YgdGhlIGxhc3QgQCBzaWduLCB1bmxlc3Mgc29tZSBob3N0LWVuZGluZyBjaGFyYWN0ZXJcbiAgICAvLyBjb21lcyAqYmVmb3JlKiB0aGUgQC1zaWduLlxuICAgIC8vIFVSTHMgYXJlIG9ibm94aW91cy5cbiAgICAvL1xuICAgIC8vIGV4OlxuICAgIC8vIGh0dHA6Ly9hQGJAYy8gPT4gdXNlcjphQGIgaG9zdDpjXG4gICAgLy8gaHR0cDovL2FAYj9AYyA9PiB1c2VyOmEgaG9zdDpjIHBhdGg6Lz9AY1xuXG4gICAgLy8gdjAuMTIgVE9ETyhpc2FhY3MpOiBUaGlzIGlzIG5vdCBxdWl0ZSBob3cgQ2hyb21lIGRvZXMgdGhpbmdzLlxuICAgIC8vIFJldmlldyBvdXIgdGVzdCBjYXNlIGFnYWluc3QgYnJvd3NlcnMgbW9yZSBjb21wcmVoZW5zaXZlbHkuXG5cbiAgICAvLyBmaW5kIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBhbnkgaG9zdEVuZGluZ0NoYXJzXG4gICAgdmFyIGhvc3RFbmQgPSAtMTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhvc3RFbmRpbmdDaGFycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGhlYyA9IHJlc3QuaW5kZXhPZihob3N0RW5kaW5nQ2hhcnNbaV0pO1xuICAgICAgaWYgKGhlYyAhPT0gLTEgJiYgKGhvc3RFbmQgPT09IC0xIHx8IGhlYyA8IGhvc3RFbmQpKVxuICAgICAgICBob3N0RW5kID0gaGVjO1xuICAgIH1cblxuICAgIC8vIGF0IHRoaXMgcG9pbnQsIGVpdGhlciB3ZSBoYXZlIGFuIGV4cGxpY2l0IHBvaW50IHdoZXJlIHRoZVxuICAgIC8vIGF1dGggcG9ydGlvbiBjYW5ub3QgZ28gcGFzdCwgb3IgdGhlIGxhc3QgQCBjaGFyIGlzIHRoZSBkZWNpZGVyLlxuICAgIHZhciBhdXRoLCBhdFNpZ247XG4gICAgaWYgKGhvc3RFbmQgPT09IC0xKSB7XG4gICAgICAvLyBhdFNpZ24gY2FuIGJlIGFueXdoZXJlLlxuICAgICAgYXRTaWduID0gcmVzdC5sYXN0SW5kZXhPZignQCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBhdFNpZ24gbXVzdCBiZSBpbiBhdXRoIHBvcnRpb24uXG4gICAgICAvLyBodHRwOi8vYUBiL2NAZCA9PiBob3N0OmIgYXV0aDphIHBhdGg6L2NAZFxuICAgICAgYXRTaWduID0gcmVzdC5sYXN0SW5kZXhPZignQCcsIGhvc3RFbmQpO1xuICAgIH1cblxuICAgIC8vIE5vdyB3ZSBoYXZlIGEgcG9ydGlvbiB3aGljaCBpcyBkZWZpbml0ZWx5IHRoZSBhdXRoLlxuICAgIC8vIFB1bGwgdGhhdCBvZmYuXG4gICAgaWYgKGF0U2lnbiAhPT0gLTEpIHtcbiAgICAgIGF1dGggPSByZXN0LnNsaWNlKDAsIGF0U2lnbik7XG4gICAgICByZXN0ID0gcmVzdC5zbGljZShhdFNpZ24gKyAxKTtcbiAgICAgIHRoaXMuYXV0aCA9IGRlY29kZVVSSUNvbXBvbmVudChhdXRoKTtcbiAgICB9XG5cbiAgICAvLyB0aGUgaG9zdCBpcyB0aGUgcmVtYWluaW5nIHRvIHRoZSBsZWZ0IG9mIHRoZSBmaXJzdCBub24taG9zdCBjaGFyXG4gICAgaG9zdEVuZCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9uSG9zdENoYXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaGVjID0gcmVzdC5pbmRleE9mKG5vbkhvc3RDaGFyc1tpXSk7XG4gICAgICBpZiAoaGVjICE9PSAtMSAmJiAoaG9zdEVuZCA9PT0gLTEgfHwgaGVjIDwgaG9zdEVuZCkpXG4gICAgICAgIGhvc3RFbmQgPSBoZWM7XG4gICAgfVxuICAgIC8vIGlmIHdlIHN0aWxsIGhhdmUgbm90IGhpdCBpdCwgdGhlbiB0aGUgZW50aXJlIHRoaW5nIGlzIGEgaG9zdC5cbiAgICBpZiAoaG9zdEVuZCA9PT0gLTEpXG4gICAgICBob3N0RW5kID0gcmVzdC5sZW5ndGg7XG5cbiAgICB0aGlzLmhvc3QgPSByZXN0LnNsaWNlKDAsIGhvc3RFbmQpO1xuICAgIHJlc3QgPSByZXN0LnNsaWNlKGhvc3RFbmQpO1xuXG4gICAgLy8gcHVsbCBvdXQgcG9ydC5cbiAgICB0aGlzLnBhcnNlSG9zdCgpO1xuXG4gICAgLy8gd2UndmUgaW5kaWNhdGVkIHRoYXQgdGhlcmUgaXMgYSBob3N0bmFtZSxcbiAgICAvLyBzbyBldmVuIGlmIGl0J3MgZW1wdHksIGl0IGhhcyB0byBiZSBwcmVzZW50LlxuICAgIHRoaXMuaG9zdG5hbWUgPSB0aGlzLmhvc3RuYW1lIHx8ICcnO1xuXG4gICAgLy8gaWYgaG9zdG5hbWUgYmVnaW5zIHdpdGggWyBhbmQgZW5kcyB3aXRoIF1cbiAgICAvLyBhc3N1bWUgdGhhdCBpdCdzIGFuIElQdjYgYWRkcmVzcy5cbiAgICB2YXIgaXB2Nkhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZVswXSA9PT0gJ1snICYmXG4gICAgICAgIHRoaXMuaG9zdG5hbWVbdGhpcy5ob3N0bmFtZS5sZW5ndGggLSAxXSA9PT0gJ10nO1xuXG4gICAgLy8gdmFsaWRhdGUgYSBsaXR0bGUuXG4gICAgaWYgKCFpcHY2SG9zdG5hbWUpIHtcbiAgICAgIHZhciBob3N0cGFydHMgPSB0aGlzLmhvc3RuYW1lLnNwbGl0KC9cXC4vKTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gaG9zdHBhcnRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIgcGFydCA9IGhvc3RwYXJ0c1tpXTtcbiAgICAgICAgaWYgKCFwYXJ0KSBjb250aW51ZTtcbiAgICAgICAgaWYgKCFwYXJ0Lm1hdGNoKGhvc3RuYW1lUGFydFBhdHRlcm4pKSB7XG4gICAgICAgICAgdmFyIG5ld3BhcnQgPSAnJztcbiAgICAgICAgICBmb3IgKHZhciBqID0gMCwgayA9IHBhcnQubGVuZ3RoOyBqIDwgazsgaisrKSB7XG4gICAgICAgICAgICBpZiAocGFydC5jaGFyQ29kZUF0KGopID4gMTI3KSB7XG4gICAgICAgICAgICAgIC8vIHdlIHJlcGxhY2Ugbm9uLUFTQ0lJIGNoYXIgd2l0aCBhIHRlbXBvcmFyeSBwbGFjZWhvbGRlclxuICAgICAgICAgICAgICAvLyB3ZSBuZWVkIHRoaXMgdG8gbWFrZSBzdXJlIHNpemUgb2YgaG9zdG5hbWUgaXMgbm90XG4gICAgICAgICAgICAgIC8vIGJyb2tlbiBieSByZXBsYWNpbmcgbm9uLUFTQ0lJIGJ5IG5vdGhpbmdcbiAgICAgICAgICAgICAgbmV3cGFydCArPSAneCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBuZXdwYXJ0ICs9IHBhcnRbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHdlIHRlc3QgYWdhaW4gd2l0aCBBU0NJSSBjaGFyIG9ubHlcbiAgICAgICAgICBpZiAoIW5ld3BhcnQubWF0Y2goaG9zdG5hbWVQYXJ0UGF0dGVybikpIHtcbiAgICAgICAgICAgIHZhciB2YWxpZFBhcnRzID0gaG9zdHBhcnRzLnNsaWNlKDAsIGkpO1xuICAgICAgICAgICAgdmFyIG5vdEhvc3QgPSBob3N0cGFydHMuc2xpY2UoaSArIDEpO1xuICAgICAgICAgICAgdmFyIGJpdCA9IHBhcnQubWF0Y2goaG9zdG5hbWVQYXJ0U3RhcnQpO1xuICAgICAgICAgICAgaWYgKGJpdCkge1xuICAgICAgICAgICAgICB2YWxpZFBhcnRzLnB1c2goYml0WzFdKTtcbiAgICAgICAgICAgICAgbm90SG9zdC51bnNoaWZ0KGJpdFsyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobm90SG9zdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgcmVzdCA9ICcvJyArIG5vdEhvc3Quam9pbignLicpICsgcmVzdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaG9zdG5hbWUgPSB2YWxpZFBhcnRzLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmhvc3RuYW1lLmxlbmd0aCA+IGhvc3RuYW1lTWF4TGVuKSB7XG4gICAgICB0aGlzLmhvc3RuYW1lID0gJyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGhvc3RuYW1lcyBhcmUgYWx3YXlzIGxvd2VyIGNhc2UuXG4gICAgICB0aGlzLmhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIGlmICghaXB2Nkhvc3RuYW1lKSB7XG4gICAgICAvLyBJRE5BIFN1cHBvcnQ6IFJldHVybnMgYSBwdW55Y29kZWQgcmVwcmVzZW50YXRpb24gb2YgXCJkb21haW5cIi5cbiAgICAgIC8vIEl0IG9ubHkgY29udmVydHMgcGFydHMgb2YgdGhlIGRvbWFpbiBuYW1lIHRoYXRcbiAgICAgIC8vIGhhdmUgbm9uLUFTQ0lJIGNoYXJhY3RlcnMsIGkuZS4gaXQgZG9lc24ndCBtYXR0ZXIgaWZcbiAgICAgIC8vIHlvdSBjYWxsIGl0IHdpdGggYSBkb21haW4gdGhhdCBhbHJlYWR5IGlzIEFTQ0lJLW9ubHkuXG4gICAgICB0aGlzLmhvc3RuYW1lID0gcHVueWNvZGUudG9BU0NJSSh0aGlzLmhvc3RuYW1lKTtcbiAgICB9XG5cbiAgICB2YXIgcCA9IHRoaXMucG9ydCA/ICc6JyArIHRoaXMucG9ydCA6ICcnO1xuICAgIHZhciBoID0gdGhpcy5ob3N0bmFtZSB8fCAnJztcbiAgICB0aGlzLmhvc3QgPSBoICsgcDtcbiAgICB0aGlzLmhyZWYgKz0gdGhpcy5ob3N0O1xuXG4gICAgLy8gc3RyaXAgWyBhbmQgXSBmcm9tIHRoZSBob3N0bmFtZVxuICAgIC8vIHRoZSBob3N0IGZpZWxkIHN0aWxsIHJldGFpbnMgdGhlbSwgdGhvdWdoXG4gICAgaWYgKGlwdjZIb3N0bmFtZSkge1xuICAgICAgdGhpcy5ob3N0bmFtZSA9IHRoaXMuaG9zdG5hbWUuc3Vic3RyKDEsIHRoaXMuaG9zdG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBpZiAocmVzdFswXSAhPT0gJy8nKSB7XG4gICAgICAgIHJlc3QgPSAnLycgKyByZXN0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIG5vdyByZXN0IGlzIHNldCB0byB0aGUgcG9zdC1ob3N0IHN0dWZmLlxuICAvLyBjaG9wIG9mZiBhbnkgZGVsaW0gY2hhcnMuXG4gIGlmICghdW5zYWZlUHJvdG9jb2xbbG93ZXJQcm90b10pIHtcblxuICAgIC8vIEZpcnN0LCBtYWtlIDEwMCUgc3VyZSB0aGF0IGFueSBcImF1dG9Fc2NhcGVcIiBjaGFycyBnZXRcbiAgICAvLyBlc2NhcGVkLCBldmVuIGlmIGVuY29kZVVSSUNvbXBvbmVudCBkb2Vzbid0IHRoaW5rIHRoZXlcbiAgICAvLyBuZWVkIHRvIGJlLlxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXV0b0VzY2FwZS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHZhciBhZSA9IGF1dG9Fc2NhcGVbaV07XG4gICAgICBpZiAocmVzdC5pbmRleE9mKGFlKSA9PT0gLTEpXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgdmFyIGVzYyA9IGVuY29kZVVSSUNvbXBvbmVudChhZSk7XG4gICAgICBpZiAoZXNjID09PSBhZSkge1xuICAgICAgICBlc2MgPSBlc2NhcGUoYWUpO1xuICAgICAgfVxuICAgICAgcmVzdCA9IHJlc3Quc3BsaXQoYWUpLmpvaW4oZXNjKTtcbiAgICB9XG4gIH1cblxuXG4gIC8vIGNob3Agb2ZmIGZyb20gdGhlIHRhaWwgZmlyc3QuXG4gIHZhciBoYXNoID0gcmVzdC5pbmRleE9mKCcjJyk7XG4gIGlmIChoYXNoICE9PSAtMSkge1xuICAgIC8vIGdvdCBhIGZyYWdtZW50IHN0cmluZy5cbiAgICB0aGlzLmhhc2ggPSByZXN0LnN1YnN0cihoYXNoKTtcbiAgICByZXN0ID0gcmVzdC5zbGljZSgwLCBoYXNoKTtcbiAgfVxuICB2YXIgcW0gPSByZXN0LmluZGV4T2YoJz8nKTtcbiAgaWYgKHFtICE9PSAtMSkge1xuICAgIHRoaXMuc2VhcmNoID0gcmVzdC5zdWJzdHIocW0pO1xuICAgIHRoaXMucXVlcnkgPSByZXN0LnN1YnN0cihxbSArIDEpO1xuICAgIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgICB0aGlzLnF1ZXJ5ID0gcXVlcnlzdHJpbmcucGFyc2UodGhpcy5xdWVyeSk7XG4gICAgfVxuICAgIHJlc3QgPSByZXN0LnNsaWNlKDAsIHFtKTtcbiAgfSBlbHNlIGlmIChwYXJzZVF1ZXJ5U3RyaW5nKSB7XG4gICAgLy8gbm8gcXVlcnkgc3RyaW5nLCBidXQgcGFyc2VRdWVyeVN0cmluZyBzdGlsbCByZXF1ZXN0ZWRcbiAgICB0aGlzLnNlYXJjaCA9ICcnO1xuICAgIHRoaXMucXVlcnkgPSB7fTtcbiAgfVxuICBpZiAocmVzdCkgdGhpcy5wYXRobmFtZSA9IHJlc3Q7XG4gIGlmIChzbGFzaGVkUHJvdG9jb2xbbG93ZXJQcm90b10gJiZcbiAgICAgIHRoaXMuaG9zdG5hbWUgJiYgIXRoaXMucGF0aG5hbWUpIHtcbiAgICB0aGlzLnBhdGhuYW1lID0gJy8nO1xuICB9XG5cbiAgLy90byBzdXBwb3J0IGh0dHAucmVxdWVzdFxuICBpZiAodGhpcy5wYXRobmFtZSB8fCB0aGlzLnNlYXJjaCkge1xuICAgIHZhciBwID0gdGhpcy5wYXRobmFtZSB8fCAnJztcbiAgICB2YXIgcyA9IHRoaXMuc2VhcmNoIHx8ICcnO1xuICAgIHRoaXMucGF0aCA9IHAgKyBzO1xuICB9XG5cbiAgLy8gZmluYWxseSwgcmVjb25zdHJ1Y3QgdGhlIGhyZWYgYmFzZWQgb24gd2hhdCBoYXMgYmVlbiB2YWxpZGF0ZWQuXG4gIHRoaXMuaHJlZiA9IHRoaXMuZm9ybWF0KCk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLy8gZm9ybWF0IGEgcGFyc2VkIG9iamVjdCBpbnRvIGEgdXJsIHN0cmluZ1xuZnVuY3Rpb24gdXJsRm9ybWF0KG9iaikge1xuICAvLyBlbnN1cmUgaXQncyBhbiBvYmplY3QsIGFuZCBub3QgYSBzdHJpbmcgdXJsLlxuICAvLyBJZiBpdCdzIGFuIG9iaiwgdGhpcyBpcyBhIG5vLW9wLlxuICAvLyB0aGlzIHdheSwgeW91IGNhbiBjYWxsIHVybF9mb3JtYXQoKSBvbiBzdHJpbmdzXG4gIC8vIHRvIGNsZWFuIHVwIHBvdGVudGlhbGx5IHdvbmt5IHVybHMuXG4gIGlmICh1dGlsLmlzU3RyaW5nKG9iaikpIG9iaiA9IHVybFBhcnNlKG9iaik7XG4gIGlmICghKG9iaiBpbnN0YW5jZW9mIFVybCkpIHJldHVybiBVcmwucHJvdG90eXBlLmZvcm1hdC5jYWxsKG9iaik7XG4gIHJldHVybiBvYmouZm9ybWF0KCk7XG59XG5cblVybC5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBhdXRoID0gdGhpcy5hdXRoIHx8ICcnO1xuICBpZiAoYXV0aCkge1xuICAgIGF1dGggPSBlbmNvZGVVUklDb21wb25lbnQoYXV0aCk7XG4gICAgYXV0aCA9IGF1dGgucmVwbGFjZSgvJTNBL2ksICc6Jyk7XG4gICAgYXV0aCArPSAnQCc7XG4gIH1cblxuICB2YXIgcHJvdG9jb2wgPSB0aGlzLnByb3RvY29sIHx8ICcnLFxuICAgICAgcGF0aG5hbWUgPSB0aGlzLnBhdGhuYW1lIHx8ICcnLFxuICAgICAgaGFzaCA9IHRoaXMuaGFzaCB8fCAnJyxcbiAgICAgIGhvc3QgPSBmYWxzZSxcbiAgICAgIHF1ZXJ5ID0gJyc7XG5cbiAgaWYgKHRoaXMuaG9zdCkge1xuICAgIGhvc3QgPSBhdXRoICsgdGhpcy5ob3N0O1xuICB9IGVsc2UgaWYgKHRoaXMuaG9zdG5hbWUpIHtcbiAgICBob3N0ID0gYXV0aCArICh0aGlzLmhvc3RuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEgP1xuICAgICAgICB0aGlzLmhvc3RuYW1lIDpcbiAgICAgICAgJ1snICsgdGhpcy5ob3N0bmFtZSArICddJyk7XG4gICAgaWYgKHRoaXMucG9ydCkge1xuICAgICAgaG9zdCArPSAnOicgKyB0aGlzLnBvcnQ7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRoaXMucXVlcnkgJiZcbiAgICAgIHV0aWwuaXNPYmplY3QodGhpcy5xdWVyeSkgJiZcbiAgICAgIE9iamVjdC5rZXlzKHRoaXMucXVlcnkpLmxlbmd0aCkge1xuICAgIHF1ZXJ5ID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHRoaXMucXVlcnkpO1xuICB9XG5cbiAgdmFyIHNlYXJjaCA9IHRoaXMuc2VhcmNoIHx8IChxdWVyeSAmJiAoJz8nICsgcXVlcnkpKSB8fCAnJztcblxuICBpZiAocHJvdG9jb2wgJiYgcHJvdG9jb2wuc3Vic3RyKC0xKSAhPT0gJzonKSBwcm90b2NvbCArPSAnOic7XG5cbiAgLy8gb25seSB0aGUgc2xhc2hlZFByb3RvY29scyBnZXQgdGhlIC8vLiAgTm90IG1haWx0bzosIHhtcHA6LCBldGMuXG4gIC8vIHVubGVzcyB0aGV5IGhhZCB0aGVtIHRvIGJlZ2luIHdpdGguXG4gIGlmICh0aGlzLnNsYXNoZXMgfHxcbiAgICAgICghcHJvdG9jb2wgfHwgc2xhc2hlZFByb3RvY29sW3Byb3RvY29sXSkgJiYgaG9zdCAhPT0gZmFsc2UpIHtcbiAgICBob3N0ID0gJy8vJyArIChob3N0IHx8ICcnKTtcbiAgICBpZiAocGF0aG5hbWUgJiYgcGF0aG5hbWUuY2hhckF0KDApICE9PSAnLycpIHBhdGhuYW1lID0gJy8nICsgcGF0aG5hbWU7XG4gIH0gZWxzZSBpZiAoIWhvc3QpIHtcbiAgICBob3N0ID0gJyc7XG4gIH1cblxuICBpZiAoaGFzaCAmJiBoYXNoLmNoYXJBdCgwKSAhPT0gJyMnKSBoYXNoID0gJyMnICsgaGFzaDtcbiAgaWYgKHNlYXJjaCAmJiBzZWFyY2guY2hhckF0KDApICE9PSAnPycpIHNlYXJjaCA9ICc/JyArIHNlYXJjaDtcblxuICBwYXRobmFtZSA9IHBhdGhuYW1lLnJlcGxhY2UoL1s/I10vZywgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KG1hdGNoKTtcbiAgfSk7XG4gIHNlYXJjaCA9IHNlYXJjaC5yZXBsYWNlKCcjJywgJyUyMycpO1xuXG4gIHJldHVybiBwcm90b2NvbCArIGhvc3QgKyBwYXRobmFtZSArIHNlYXJjaCArIGhhc2g7XG59O1xuXG5mdW5jdGlvbiB1cmxSZXNvbHZlKHNvdXJjZSwgcmVsYXRpdmUpIHtcbiAgcmV0dXJuIHVybFBhcnNlKHNvdXJjZSwgZmFsc2UsIHRydWUpLnJlc29sdmUocmVsYXRpdmUpO1xufVxuXG5VcmwucHJvdG90eXBlLnJlc29sdmUgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICByZXR1cm4gdGhpcy5yZXNvbHZlT2JqZWN0KHVybFBhcnNlKHJlbGF0aXZlLCBmYWxzZSwgdHJ1ZSkpLmZvcm1hdCgpO1xufTtcblxuZnVuY3Rpb24gdXJsUmVzb2x2ZU9iamVjdChzb3VyY2UsIHJlbGF0aXZlKSB7XG4gIGlmICghc291cmNlKSByZXR1cm4gcmVsYXRpdmU7XG4gIHJldHVybiB1cmxQYXJzZShzb3VyY2UsIGZhbHNlLCB0cnVlKS5yZXNvbHZlT2JqZWN0KHJlbGF0aXZlKTtcbn1cblxuVXJsLnByb3RvdHlwZS5yZXNvbHZlT2JqZWN0ID0gZnVuY3Rpb24ocmVsYXRpdmUpIHtcbiAgaWYgKHV0aWwuaXNTdHJpbmcocmVsYXRpdmUpKSB7XG4gICAgdmFyIHJlbCA9IG5ldyBVcmwoKTtcbiAgICByZWwucGFyc2UocmVsYXRpdmUsIGZhbHNlLCB0cnVlKTtcbiAgICByZWxhdGl2ZSA9IHJlbDtcbiAgfVxuXG4gIHZhciByZXN1bHQgPSBuZXcgVXJsKCk7XG4gIHZhciB0a2V5cyA9IE9iamVjdC5rZXlzKHRoaXMpO1xuICBmb3IgKHZhciB0ayA9IDA7IHRrIDwgdGtleXMubGVuZ3RoOyB0aysrKSB7XG4gICAgdmFyIHRrZXkgPSB0a2V5c1t0a107XG4gICAgcmVzdWx0W3RrZXldID0gdGhpc1t0a2V5XTtcbiAgfVxuXG4gIC8vIGhhc2ggaXMgYWx3YXlzIG92ZXJyaWRkZW4sIG5vIG1hdHRlciB3aGF0LlxuICAvLyBldmVuIGhyZWY9XCJcIiB3aWxsIHJlbW92ZSBpdC5cbiAgcmVzdWx0Lmhhc2ggPSByZWxhdGl2ZS5oYXNoO1xuXG4gIC8vIGlmIHRoZSByZWxhdGl2ZSB1cmwgaXMgZW1wdHksIHRoZW4gdGhlcmUncyBub3RoaW5nIGxlZnQgdG8gZG8gaGVyZS5cbiAgaWYgKHJlbGF0aXZlLmhyZWYgPT09ICcnKSB7XG4gICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIGhyZWZzIGxpa2UgLy9mb28vYmFyIGFsd2F5cyBjdXQgdG8gdGhlIHByb3RvY29sLlxuICBpZiAocmVsYXRpdmUuc2xhc2hlcyAmJiAhcmVsYXRpdmUucHJvdG9jb2wpIHtcbiAgICAvLyB0YWtlIGV2ZXJ5dGhpbmcgZXhjZXB0IHRoZSBwcm90b2NvbCBmcm9tIHJlbGF0aXZlXG4gICAgdmFyIHJrZXlzID0gT2JqZWN0LmtleXMocmVsYXRpdmUpO1xuICAgIGZvciAodmFyIHJrID0gMDsgcmsgPCBya2V5cy5sZW5ndGg7IHJrKyspIHtcbiAgICAgIHZhciBya2V5ID0gcmtleXNbcmtdO1xuICAgICAgaWYgKHJrZXkgIT09ICdwcm90b2NvbCcpXG4gICAgICAgIHJlc3VsdFtya2V5XSA9IHJlbGF0aXZlW3JrZXldO1xuICAgIH1cblxuICAgIC8vdXJsUGFyc2UgYXBwZW5kcyB0cmFpbGluZyAvIHRvIHVybHMgbGlrZSBodHRwOi8vd3d3LmV4YW1wbGUuY29tXG4gICAgaWYgKHNsYXNoZWRQcm90b2NvbFtyZXN1bHQucHJvdG9jb2xdICYmXG4gICAgICAgIHJlc3VsdC5ob3N0bmFtZSAmJiAhcmVzdWx0LnBhdGhuYW1lKSB7XG4gICAgICByZXN1bHQucGF0aCA9IHJlc3VsdC5wYXRobmFtZSA9ICcvJztcbiAgICB9XG5cbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgaWYgKHJlbGF0aXZlLnByb3RvY29sICYmIHJlbGF0aXZlLnByb3RvY29sICE9PSByZXN1bHQucHJvdG9jb2wpIHtcbiAgICAvLyBpZiBpdCdzIGEga25vd24gdXJsIHByb3RvY29sLCB0aGVuIGNoYW5naW5nXG4gICAgLy8gdGhlIHByb3RvY29sIGRvZXMgd2VpcmQgdGhpbmdzXG4gICAgLy8gZmlyc3QsIGlmIGl0J3Mgbm90IGZpbGU6LCB0aGVuIHdlIE1VU1QgaGF2ZSBhIGhvc3QsXG4gICAgLy8gYW5kIGlmIHRoZXJlIHdhcyBhIHBhdGhcbiAgICAvLyB0byBiZWdpbiB3aXRoLCB0aGVuIHdlIE1VU1QgaGF2ZSBhIHBhdGguXG4gICAgLy8gaWYgaXQgaXMgZmlsZTosIHRoZW4gdGhlIGhvc3QgaXMgZHJvcHBlZCxcbiAgICAvLyBiZWNhdXNlIHRoYXQncyBrbm93biB0byBiZSBob3N0bGVzcy5cbiAgICAvLyBhbnl0aGluZyBlbHNlIGlzIGFzc3VtZWQgdG8gYmUgYWJzb2x1dGUuXG4gICAgaWYgKCFzbGFzaGVkUHJvdG9jb2xbcmVsYXRpdmUucHJvdG9jb2xdKSB7XG4gICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHJlbGF0aXZlKTtcbiAgICAgIGZvciAodmFyIHYgPSAwOyB2IDwga2V5cy5sZW5ndGg7IHYrKykge1xuICAgICAgICB2YXIgayA9IGtleXNbdl07XG4gICAgICAgIHJlc3VsdFtrXSA9IHJlbGF0aXZlW2tdO1xuICAgICAgfVxuICAgICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJlc3VsdC5wcm90b2NvbCA9IHJlbGF0aXZlLnByb3RvY29sO1xuICAgIGlmICghcmVsYXRpdmUuaG9zdCAmJiAhaG9zdGxlc3NQcm90b2NvbFtyZWxhdGl2ZS5wcm90b2NvbF0pIHtcbiAgICAgIHZhciByZWxQYXRoID0gKHJlbGF0aXZlLnBhdGhuYW1lIHx8ICcnKS5zcGxpdCgnLycpO1xuICAgICAgd2hpbGUgKHJlbFBhdGgubGVuZ3RoICYmICEocmVsYXRpdmUuaG9zdCA9IHJlbFBhdGguc2hpZnQoKSkpO1xuICAgICAgaWYgKCFyZWxhdGl2ZS5ob3N0KSByZWxhdGl2ZS5ob3N0ID0gJyc7XG4gICAgICBpZiAoIXJlbGF0aXZlLmhvc3RuYW1lKSByZWxhdGl2ZS5ob3N0bmFtZSA9ICcnO1xuICAgICAgaWYgKHJlbFBhdGhbMF0gIT09ICcnKSByZWxQYXRoLnVuc2hpZnQoJycpO1xuICAgICAgaWYgKHJlbFBhdGgubGVuZ3RoIDwgMikgcmVsUGF0aC51bnNoaWZ0KCcnKTtcbiAgICAgIHJlc3VsdC5wYXRobmFtZSA9IHJlbFBhdGguam9pbignLycpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQucGF0aG5hbWUgPSByZWxhdGl2ZS5wYXRobmFtZTtcbiAgICB9XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICByZXN1bHQuaG9zdCA9IHJlbGF0aXZlLmhvc3QgfHwgJyc7XG4gICAgcmVzdWx0LmF1dGggPSByZWxhdGl2ZS5hdXRoO1xuICAgIHJlc3VsdC5ob3N0bmFtZSA9IHJlbGF0aXZlLmhvc3RuYW1lIHx8IHJlbGF0aXZlLmhvc3Q7XG4gICAgcmVzdWx0LnBvcnQgPSByZWxhdGl2ZS5wb3J0O1xuICAgIC8vIHRvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gICAgaWYgKHJlc3VsdC5wYXRobmFtZSB8fCByZXN1bHQuc2VhcmNoKSB7XG4gICAgICB2YXIgcCA9IHJlc3VsdC5wYXRobmFtZSB8fCAnJztcbiAgICAgIHZhciBzID0gcmVzdWx0LnNlYXJjaCB8fCAnJztcbiAgICAgIHJlc3VsdC5wYXRoID0gcCArIHM7XG4gICAgfVxuICAgIHJlc3VsdC5zbGFzaGVzID0gcmVzdWx0LnNsYXNoZXMgfHwgcmVsYXRpdmUuc2xhc2hlcztcbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdmFyIGlzU291cmNlQWJzID0gKHJlc3VsdC5wYXRobmFtZSAmJiByZXN1bHQucGF0aG5hbWUuY2hhckF0KDApID09PSAnLycpLFxuICAgICAgaXNSZWxBYnMgPSAoXG4gICAgICAgICAgcmVsYXRpdmUuaG9zdCB8fFxuICAgICAgICAgIHJlbGF0aXZlLnBhdGhuYW1lICYmIHJlbGF0aXZlLnBhdGhuYW1lLmNoYXJBdCgwKSA9PT0gJy8nXG4gICAgICApLFxuICAgICAgbXVzdEVuZEFicyA9IChpc1JlbEFicyB8fCBpc1NvdXJjZUFicyB8fFxuICAgICAgICAgICAgICAgICAgICAocmVzdWx0Lmhvc3QgJiYgcmVsYXRpdmUucGF0aG5hbWUpKSxcbiAgICAgIHJlbW92ZUFsbERvdHMgPSBtdXN0RW5kQWJzLFxuICAgICAgc3JjUGF0aCA9IHJlc3VsdC5wYXRobmFtZSAmJiByZXN1bHQucGF0aG5hbWUuc3BsaXQoJy8nKSB8fCBbXSxcbiAgICAgIHJlbFBhdGggPSByZWxhdGl2ZS5wYXRobmFtZSAmJiByZWxhdGl2ZS5wYXRobmFtZS5zcGxpdCgnLycpIHx8IFtdLFxuICAgICAgcHN5Y2hvdGljID0gcmVzdWx0LnByb3RvY29sICYmICFzbGFzaGVkUHJvdG9jb2xbcmVzdWx0LnByb3RvY29sXTtcblxuICAvLyBpZiB0aGUgdXJsIGlzIGEgbm9uLXNsYXNoZWQgdXJsLCB0aGVuIHJlbGF0aXZlXG4gIC8vIGxpbmtzIGxpa2UgLi4vLi4gc2hvdWxkIGJlIGFibGVcbiAgLy8gdG8gY3Jhd2wgdXAgdG8gdGhlIGhvc3RuYW1lLCBhcyB3ZWxsLiAgVGhpcyBpcyBzdHJhbmdlLlxuICAvLyByZXN1bHQucHJvdG9jb2wgaGFzIGFscmVhZHkgYmVlbiBzZXQgYnkgbm93LlxuICAvLyBMYXRlciBvbiwgcHV0IHRoZSBmaXJzdCBwYXRoIHBhcnQgaW50byB0aGUgaG9zdCBmaWVsZC5cbiAgaWYgKHBzeWNob3RpYykge1xuICAgIHJlc3VsdC5ob3N0bmFtZSA9ICcnO1xuICAgIHJlc3VsdC5wb3J0ID0gbnVsbDtcbiAgICBpZiAocmVzdWx0Lmhvc3QpIHtcbiAgICAgIGlmIChzcmNQYXRoWzBdID09PSAnJykgc3JjUGF0aFswXSA9IHJlc3VsdC5ob3N0O1xuICAgICAgZWxzZSBzcmNQYXRoLnVuc2hpZnQocmVzdWx0Lmhvc3QpO1xuICAgIH1cbiAgICByZXN1bHQuaG9zdCA9ICcnO1xuICAgIGlmIChyZWxhdGl2ZS5wcm90b2NvbCkge1xuICAgICAgcmVsYXRpdmUuaG9zdG5hbWUgPSBudWxsO1xuICAgICAgcmVsYXRpdmUucG9ydCA9IG51bGw7XG4gICAgICBpZiAocmVsYXRpdmUuaG9zdCkge1xuICAgICAgICBpZiAocmVsUGF0aFswXSA9PT0gJycpIHJlbFBhdGhbMF0gPSByZWxhdGl2ZS5ob3N0O1xuICAgICAgICBlbHNlIHJlbFBhdGgudW5zaGlmdChyZWxhdGl2ZS5ob3N0KTtcbiAgICAgIH1cbiAgICAgIHJlbGF0aXZlLmhvc3QgPSBudWxsO1xuICAgIH1cbiAgICBtdXN0RW5kQWJzID0gbXVzdEVuZEFicyAmJiAocmVsUGF0aFswXSA9PT0gJycgfHwgc3JjUGF0aFswXSA9PT0gJycpO1xuICB9XG5cbiAgaWYgKGlzUmVsQWJzKSB7XG4gICAgLy8gaXQncyBhYnNvbHV0ZS5cbiAgICByZXN1bHQuaG9zdCA9IChyZWxhdGl2ZS5ob3N0IHx8IHJlbGF0aXZlLmhvc3QgPT09ICcnKSA/XG4gICAgICAgICAgICAgICAgICByZWxhdGl2ZS5ob3N0IDogcmVzdWx0Lmhvc3Q7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gKHJlbGF0aXZlLmhvc3RuYW1lIHx8IHJlbGF0aXZlLmhvc3RuYW1lID09PSAnJykgP1xuICAgICAgICAgICAgICAgICAgICAgIHJlbGF0aXZlLmhvc3RuYW1lIDogcmVzdWx0Lmhvc3RuYW1lO1xuICAgIHJlc3VsdC5zZWFyY2ggPSByZWxhdGl2ZS5zZWFyY2g7XG4gICAgcmVzdWx0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgc3JjUGF0aCA9IHJlbFBhdGg7XG4gICAgLy8gZmFsbCB0aHJvdWdoIHRvIHRoZSBkb3QtaGFuZGxpbmcgYmVsb3cuXG4gIH0gZWxzZSBpZiAocmVsUGF0aC5sZW5ndGgpIHtcbiAgICAvLyBpdCdzIHJlbGF0aXZlXG4gICAgLy8gdGhyb3cgYXdheSB0aGUgZXhpc3RpbmcgZmlsZSwgYW5kIHRha2UgdGhlIG5ldyBwYXRoIGluc3RlYWQuXG4gICAgaWYgKCFzcmNQYXRoKSBzcmNQYXRoID0gW107XG4gICAgc3JjUGF0aC5wb3AoKTtcbiAgICBzcmNQYXRoID0gc3JjUGF0aC5jb25jYXQocmVsUGF0aCk7XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgfSBlbHNlIGlmICghdXRpbC5pc051bGxPclVuZGVmaW5lZChyZWxhdGl2ZS5zZWFyY2gpKSB7XG4gICAgLy8ganVzdCBwdWxsIG91dCB0aGUgc2VhcmNoLlxuICAgIC8vIGxpa2UgaHJlZj0nP2ZvbycuXG4gICAgLy8gUHV0IHRoaXMgYWZ0ZXIgdGhlIG90aGVyIHR3byBjYXNlcyBiZWNhdXNlIGl0IHNpbXBsaWZpZXMgdGhlIGJvb2xlYW5zXG4gICAgaWYgKHBzeWNob3RpYykge1xuICAgICAgcmVzdWx0Lmhvc3RuYW1lID0gcmVzdWx0Lmhvc3QgPSBzcmNQYXRoLnNoaWZ0KCk7XG4gICAgICAvL29jY2F0aW9uYWx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgICAvL3RoaXMgZXNwZWNpYWxseSBoYXBwZW5zIGluIGNhc2VzIGxpa2VcbiAgICAgIC8vdXJsLnJlc29sdmVPYmplY3QoJ21haWx0bzpsb2NhbDFAZG9tYWluMScsICdsb2NhbDJAZG9tYWluMicpXG4gICAgICB2YXIgYXV0aEluSG9zdCA9IHJlc3VsdC5ob3N0ICYmIHJlc3VsdC5ob3N0LmluZGV4T2YoJ0AnKSA+IDAgP1xuICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuaG9zdC5zcGxpdCgnQCcpIDogZmFsc2U7XG4gICAgICBpZiAoYXV0aEluSG9zdCkge1xuICAgICAgICByZXN1bHQuYXV0aCA9IGF1dGhJbkhvc3Quc2hpZnQoKTtcbiAgICAgICAgcmVzdWx0Lmhvc3QgPSByZXN1bHQuaG9zdG5hbWUgPSBhdXRoSW5Ib3N0LnNoaWZ0KCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc3VsdC5zZWFyY2ggPSByZWxhdGl2ZS5zZWFyY2g7XG4gICAgcmVzdWx0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgLy90byBzdXBwb3J0IGh0dHAucmVxdWVzdFxuICAgIGlmICghdXRpbC5pc051bGwocmVzdWx0LnBhdGhuYW1lKSB8fCAhdXRpbC5pc051bGwocmVzdWx0LnNlYXJjaCkpIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gKHJlc3VsdC5wYXRobmFtZSA/IHJlc3VsdC5wYXRobmFtZSA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgIChyZXN1bHQuc2VhcmNoID8gcmVzdWx0LnNlYXJjaCA6ICcnKTtcbiAgICB9XG4gICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGlmICghc3JjUGF0aC5sZW5ndGgpIHtcbiAgICAvLyBubyBwYXRoIGF0IGFsbC4gIGVhc3kuXG4gICAgLy8gd2UndmUgYWxyZWFkeSBoYW5kbGVkIHRoZSBvdGhlciBzdHVmZiBhYm92ZS5cbiAgICByZXN1bHQucGF0aG5hbWUgPSBudWxsO1xuICAgIC8vdG8gc3VwcG9ydCBodHRwLnJlcXVlc3RcbiAgICBpZiAocmVzdWx0LnNlYXJjaCkge1xuICAgICAgcmVzdWx0LnBhdGggPSAnLycgKyByZXN1bHQuc2VhcmNoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQucGF0aCA9IG51bGw7XG4gICAgfVxuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBpZiBhIHVybCBFTkRzIGluIC4gb3IgLi4sIHRoZW4gaXQgbXVzdCBnZXQgYSB0cmFpbGluZyBzbGFzaC5cbiAgLy8gaG93ZXZlciwgaWYgaXQgZW5kcyBpbiBhbnl0aGluZyBlbHNlIG5vbi1zbGFzaHksXG4gIC8vIHRoZW4gaXQgbXVzdCBOT1QgZ2V0IGEgdHJhaWxpbmcgc2xhc2guXG4gIHZhciBsYXN0ID0gc3JjUGF0aC5zbGljZSgtMSlbMF07XG4gIHZhciBoYXNUcmFpbGluZ1NsYXNoID0gKFxuICAgICAgKHJlc3VsdC5ob3N0IHx8IHJlbGF0aXZlLmhvc3QgfHwgc3JjUGF0aC5sZW5ndGggPiAxKSAmJlxuICAgICAgKGxhc3QgPT09ICcuJyB8fCBsYXN0ID09PSAnLi4nKSB8fCBsYXN0ID09PSAnJyk7XG5cbiAgLy8gc3RyaXAgc2luZ2xlIGRvdHMsIHJlc29sdmUgZG91YmxlIGRvdHMgdG8gcGFyZW50IGRpclxuICAvLyBpZiB0aGUgcGF0aCB0cmllcyB0byBnbyBhYm92ZSB0aGUgcm9vdCwgYHVwYCBlbmRzIHVwID4gMFxuICB2YXIgdXAgPSAwO1xuICBmb3IgKHZhciBpID0gc3JjUGF0aC5sZW5ndGg7IGkgPj0gMDsgaS0tKSB7XG4gICAgbGFzdCA9IHNyY1BhdGhbaV07XG4gICAgaWYgKGxhc3QgPT09ICcuJykge1xuICAgICAgc3JjUGF0aC5zcGxpY2UoaSwgMSk7XG4gICAgfSBlbHNlIGlmIChsYXN0ID09PSAnLi4nKSB7XG4gICAgICBzcmNQYXRoLnNwbGljZShpLCAxKTtcbiAgICAgIHVwKys7XG4gICAgfSBlbHNlIGlmICh1cCkge1xuICAgICAgc3JjUGF0aC5zcGxpY2UoaSwgMSk7XG4gICAgICB1cC0tO1xuICAgIH1cbiAgfVxuXG4gIC8vIGlmIHRoZSBwYXRoIGlzIGFsbG93ZWQgdG8gZ28gYWJvdmUgdGhlIHJvb3QsIHJlc3RvcmUgbGVhZGluZyAuLnNcbiAgaWYgKCFtdXN0RW5kQWJzICYmICFyZW1vdmVBbGxEb3RzKSB7XG4gICAgZm9yICg7IHVwLS07IHVwKSB7XG4gICAgICBzcmNQYXRoLnVuc2hpZnQoJy4uJyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG11c3RFbmRBYnMgJiYgc3JjUGF0aFswXSAhPT0gJycgJiZcbiAgICAgICghc3JjUGF0aFswXSB8fCBzcmNQYXRoWzBdLmNoYXJBdCgwKSAhPT0gJy8nKSkge1xuICAgIHNyY1BhdGgudW5zaGlmdCgnJyk7XG4gIH1cblxuICBpZiAoaGFzVHJhaWxpbmdTbGFzaCAmJiAoc3JjUGF0aC5qb2luKCcvJykuc3Vic3RyKC0xKSAhPT0gJy8nKSkge1xuICAgIHNyY1BhdGgucHVzaCgnJyk7XG4gIH1cblxuICB2YXIgaXNBYnNvbHV0ZSA9IHNyY1BhdGhbMF0gPT09ICcnIHx8XG4gICAgICAoc3JjUGF0aFswXSAmJiBzcmNQYXRoWzBdLmNoYXJBdCgwKSA9PT0gJy8nKTtcblxuICAvLyBwdXQgdGhlIGhvc3QgYmFja1xuICBpZiAocHN5Y2hvdGljKSB7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gcmVzdWx0Lmhvc3QgPSBpc0Fic29sdXRlID8gJycgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjUGF0aC5sZW5ndGggPyBzcmNQYXRoLnNoaWZ0KCkgOiAnJztcbiAgICAvL29jY2F0aW9uYWx5IHRoZSBhdXRoIGNhbiBnZXQgc3R1Y2sgb25seSBpbiBob3N0XG4gICAgLy90aGlzIGVzcGVjaWFsbHkgaGFwcGVucyBpbiBjYXNlcyBsaWtlXG4gICAgLy91cmwucmVzb2x2ZU9iamVjdCgnbWFpbHRvOmxvY2FsMUBkb21haW4xJywgJ2xvY2FsMkBkb21haW4yJylcbiAgICB2YXIgYXV0aEluSG9zdCA9IHJlc3VsdC5ob3N0ICYmIHJlc3VsdC5ob3N0LmluZGV4T2YoJ0AnKSA+IDAgP1xuICAgICAgICAgICAgICAgICAgICAgcmVzdWx0Lmhvc3Quc3BsaXQoJ0AnKSA6IGZhbHNlO1xuICAgIGlmIChhdXRoSW5Ib3N0KSB7XG4gICAgICByZXN1bHQuYXV0aCA9IGF1dGhJbkhvc3Quc2hpZnQoKTtcbiAgICAgIHJlc3VsdC5ob3N0ID0gcmVzdWx0Lmhvc3RuYW1lID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgIH1cbiAgfVxuXG4gIG11c3RFbmRBYnMgPSBtdXN0RW5kQWJzIHx8IChyZXN1bHQuaG9zdCAmJiBzcmNQYXRoLmxlbmd0aCk7XG5cbiAgaWYgKG11c3RFbmRBYnMgJiYgIWlzQWJzb2x1dGUpIHtcbiAgICBzcmNQYXRoLnVuc2hpZnQoJycpO1xuICB9XG5cbiAgaWYgKCFzcmNQYXRoLmxlbmd0aCkge1xuICAgIHJlc3VsdC5wYXRobmFtZSA9IG51bGw7XG4gICAgcmVzdWx0LnBhdGggPSBudWxsO1xuICB9IGVsc2Uge1xuICAgIHJlc3VsdC5wYXRobmFtZSA9IHNyY1BhdGguam9pbignLycpO1xuICB9XG5cbiAgLy90byBzdXBwb3J0IHJlcXVlc3QuaHR0cFxuICBpZiAoIXV0aWwuaXNOdWxsKHJlc3VsdC5wYXRobmFtZSkgfHwgIXV0aWwuaXNOdWxsKHJlc3VsdC5zZWFyY2gpKSB7XG4gICAgcmVzdWx0LnBhdGggPSAocmVzdWx0LnBhdGhuYW1lID8gcmVzdWx0LnBhdGhuYW1lIDogJycpICtcbiAgICAgICAgICAgICAgICAgIChyZXN1bHQuc2VhcmNoID8gcmVzdWx0LnNlYXJjaCA6ICcnKTtcbiAgfVxuICByZXN1bHQuYXV0aCA9IHJlbGF0aXZlLmF1dGggfHwgcmVzdWx0LmF1dGg7XG4gIHJlc3VsdC5zbGFzaGVzID0gcmVzdWx0LnNsYXNoZXMgfHwgcmVsYXRpdmUuc2xhc2hlcztcbiAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5VcmwucHJvdG90eXBlLnBhcnNlSG9zdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaG9zdCA9IHRoaXMuaG9zdDtcbiAgdmFyIHBvcnQgPSBwb3J0UGF0dGVybi5leGVjKGhvc3QpO1xuICBpZiAocG9ydCkge1xuICAgIHBvcnQgPSBwb3J0WzBdO1xuICAgIGlmIChwb3J0ICE9PSAnOicpIHtcbiAgICAgIHRoaXMucG9ydCA9IHBvcnQuc3Vic3RyKDEpO1xuICAgIH1cbiAgICBob3N0ID0gaG9zdC5zdWJzdHIoMCwgaG9zdC5sZW5ndGggLSBwb3J0Lmxlbmd0aCk7XG4gIH1cbiAgaWYgKGhvc3QpIHRoaXMuaG9zdG5hbWUgPSBob3N0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGlzU3RyaW5nOiBmdW5jdGlvbihhcmcpIHtcbiAgICByZXR1cm4gdHlwZW9mKGFyZykgPT09ICdzdHJpbmcnO1xuICB9LFxuICBpc09iamVjdDogZnVuY3Rpb24oYXJnKSB7XG4gICAgcmV0dXJuIHR5cGVvZihhcmcpID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG4gIH0sXG4gIGlzTnVsbDogZnVuY3Rpb24oYXJnKSB7XG4gICAgcmV0dXJuIGFyZyA9PT0gbnVsbDtcbiAgfSxcbiAgaXNOdWxsT3JVbmRlZmluZWQ6IGZ1bmN0aW9uKGFyZykge1xuICAgIHJldHVybiBhcmcgPT0gbnVsbDtcbiAgfVxufTtcbiJdfQ=="}